bump allocator implemented
This commit is contained in:
parent
33a6b9d323
commit
e619364f71
6 changed files with 175 additions and 27 deletions
17
README.md
17
README.md
|
|
@ -9,20 +9,21 @@ slowly porting from rust.
|
||||||
- interrupts
|
- interrupts
|
||||||
- terminal console
|
- terminal console
|
||||||
- lspci
|
- lspci
|
||||||
- todo: memory mapping
|
|
||||||
- todo: cfs scheduler
|
|
||||||
- todo: smp
|
|
||||||
|
|
||||||
### dependencies
|
### dependencies
|
||||||
|
|
||||||
`ziglang` compiler
|
`zig` compiler
|
||||||
|
|
||||||
### compile
|
### compile
|
||||||
|
|
||||||
`zig build` compile and links a multiboot kernel, without a bootloader.
|
`zig build` compiles and links the multiboot kernel, without a bootloader.
|
||||||
|
|
||||||
### test
|
### test
|
||||||
|
|
||||||
`./run.sh qemu start`
|
`./qemu.sh start`
|
||||||
`./run.sh qemu monitor`
|
`./qemu.sh monitor`
|
||||||
`./run.sh gdb`
|
`./qemu.sh gdb`
|
||||||
|
|
||||||
|
### todo
|
||||||
|
|
||||||
|
- recycling allocator that wraps the bump allocator
|
||||||
|
|
|
||||||
4
qemu.sh
4
qemu.sh
|
|
@ -9,8 +9,10 @@ start() {
|
||||||
-gdb tcp::${QEMU_GDB_PORT} \
|
-gdb tcp::${QEMU_GDB_PORT} \
|
||||||
-monitor unix:${QEMU_SOCKET},server,nowait \
|
-monitor unix:${QEMU_SOCKET},server,nowait \
|
||||||
-enable-kvm \
|
-enable-kvm \
|
||||||
-m 547M \
|
-m 1337M \
|
||||||
-display curses \
|
-display curses \
|
||||||
|
-serial mon:stdio \
|
||||||
|
-append "Hello" \
|
||||||
-device virtio-net,netdev=network0 -netdev tap,id=network0,ifname=tap0,script=no,downscript=no \
|
-device virtio-net,netdev=network0 -netdev tap,id=network0,ifname=tap0,script=no,downscript=no \
|
||||||
-kernel ${KERNEL}
|
-kernel ${KERNEL}
|
||||||
# build/kernel.iso
|
# build/kernel.iso
|
||||||
|
|
|
||||||
|
|
@ -5,12 +5,14 @@ const mem = @import("mem.zig");
|
||||||
const gdt = @import("gdt.zig");
|
const gdt = @import("gdt.zig");
|
||||||
const x86 = @import("lib/index.zig");
|
const x86 = @import("lib/index.zig");
|
||||||
const console = @import("../console.zig");
|
const console = @import("../console.zig");
|
||||||
|
const printf = @import("../../vga.zig").printf;
|
||||||
|
|
||||||
/// x86 specific intialization
|
/// x86 specific intialization
|
||||||
/// first entry point (see linker.ld)
|
/// first entry point (see linker.ld)
|
||||||
pub fn x86_main(info: *const MultibootInfo) void {
|
pub fn x86_main(info: *const MultibootInfo) void {
|
||||||
mem.initialize(info);
|
var allocator = mem.initialize(info);
|
||||||
|
|
||||||
// gdt.initialize();
|
// gdt.initialize();
|
||||||
idt.initialize();
|
idt.initialize();
|
||||||
// x86.sti();
|
x86.sti();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,18 @@
|
||||||
usingnamespace @import("kernel").multiboot;
|
usingnamespace @import("kernel").multiboot;
|
||||||
const assert = @import("std").debug.assert;
|
const assert = @import("std").debug.assert;
|
||||||
const vga = @import("../../vga.zig");
|
const vga = @import("../../vga.zig");
|
||||||
|
const std = @import("std");
|
||||||
|
const printf = @import("../../vga.zig").printf;
|
||||||
|
|
||||||
pub fn initialize(info: *const MultibootInfo) void {
|
pub fn initialize(info: *const MultibootInfo) bumpAllocator {
|
||||||
assert((info.flags & MULTIBOOT_INFO_MEMORY) != 0);
|
assert((info.flags & MULTIBOOT_INFO_MEMORY) != 0);
|
||||||
assert((info.flags & MULTIBOOT_INFO_MEM_MAP) != 0);
|
assert((info.flags & MULTIBOOT_INFO_MEM_MAP) != 0);
|
||||||
|
|
||||||
vga.printf("lower: {x}\n", info.mem_lower);
|
format_multibootinfo(info);
|
||||||
vga.printf("upper: {x}\n", info.mem_upper);
|
return bumpAllocator.new(info);
|
||||||
vga.printf("mmap_l: {}\n", info.mmap_length);
|
}
|
||||||
vga.printf("mmap_a: {x}\n", info.mmap_addr);
|
|
||||||
|
|
||||||
var map: usize = info.mmap_addr;
|
pub fn format_multibootentry(entry: *MultibootMMapEntry) void {
|
||||||
while (map < info.mmap_addr + info.mmap_length) {
|
|
||||||
var entry = @intToPtr(*MultibootMMapEntry, map);
|
|
||||||
if (entry.type == MULTIBOOT_MEMORY_AVAILABLE) {
|
if (entry.type == MULTIBOOT_MEMORY_AVAILABLE) {
|
||||||
vga.printf("AVAILABLE: ");
|
vga.printf("AVAILABLE: ");
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -25,6 +24,134 @@ pub fn initialize(info: *const MultibootInfo) void {
|
||||||
} else {
|
} else {
|
||||||
vga.printf("({} kB)\n", entry.len / (1024));
|
vga.printf("({} kB)\n", entry.len / (1024));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn format_multibootinfo(info: *const MultibootInfo) void {
|
||||||
|
var cmdline_ptr = @intToPtr([*c]const u8, info.cmdline);
|
||||||
|
var cmdline = @ptrCast([*c]const u8, cmdline_ptr);
|
||||||
|
// var cmdline = std.cstr.toSliceConst(info.cmdline);
|
||||||
|
vga.printf("lower: {x}\n", info.mem_lower);
|
||||||
|
vga.printf("upper: {x}\n", info.mem_upper);
|
||||||
|
vga.printf("mmap_l: {}\n", info.mmap_length);
|
||||||
|
vga.printf("mmap_a: {x}\n", info.mmap_addr);
|
||||||
|
vga.printf("cmdline: {x}\n", cmdline_ptr);
|
||||||
|
vga.printf("cmdline: {}\n", cmdline);
|
||||||
|
|
||||||
|
var map: usize = info.mmap_addr;
|
||||||
|
while (map < info.mmap_addr + info.mmap_length) {
|
||||||
|
var entry = @intToPtr(*MultibootMMapEntry, map);
|
||||||
|
format_multibootentry(entry);
|
||||||
map += entry.size + @sizeOf(@typeOf(entry.size));
|
map += entry.size + @sizeOf(@typeOf(entry.size));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// returns each available physical frame one by one in order
|
||||||
|
pub const bumpAllocator = struct {
|
||||||
|
next_free_frame: physFrame,
|
||||||
|
current_area: ?*MultibootMMapEntry,
|
||||||
|
info: *const MultibootInfo,
|
||||||
|
|
||||||
|
pub fn new(info: *const MultibootInfo) bumpAllocator {
|
||||||
|
const first_area = @intToPtr(*MultibootMMapEntry, info.mmap_addr);
|
||||||
|
var allocator = bumpAllocator{
|
||||||
|
.current_area = first_area,
|
||||||
|
.next_free_frame = physFrame.from_addr(first_area.addr),
|
||||||
|
.info = info,
|
||||||
|
};
|
||||||
|
// allocator.choose_next_area();
|
||||||
|
return allocator;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn allocate(self: var, count: u64) ?physFrame {
|
||||||
|
if (count == 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (self.current_area == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (self.current_area.?.type != MULTIBOOT_MEMORY_AVAILABLE) {
|
||||||
|
self.choose_next_area();
|
||||||
|
return self.allocate(count);
|
||||||
|
}
|
||||||
|
|
||||||
|
const start_frame = self.next_free_frame;
|
||||||
|
const end_frame = self.next_free_frame.add(count - 1);
|
||||||
|
const current_area_last_frame = physFrame.from_addr(self.current_area.?.addr + self.current_area.?.len);
|
||||||
|
if (end_frame.number > current_area_last_frame.number) {
|
||||||
|
self.choose_next_area();
|
||||||
|
return self.allocate(count);
|
||||||
|
}
|
||||||
|
self.next_free_frame.number += count;
|
||||||
|
return start_frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn choose_next_area(self: var) void {
|
||||||
|
printf("choosing next area\n");
|
||||||
|
const current = self.current_area.?;
|
||||||
|
var next_area = @ptrToInt(current) + current.size + @sizeOf(@typeOf(current));
|
||||||
|
if (next_area >= self.info.mmap_addr + self.info.mmap_length) {
|
||||||
|
self.current_area = null;
|
||||||
|
} else {
|
||||||
|
format_multibootentry(self.current_area.?);
|
||||||
|
self.current_area = @intToPtr(*MultibootMMapEntry, next_area);
|
||||||
|
format_multibootentry(self.current_area.?);
|
||||||
|
self.next_free_frame = physFrame.from_addr(self.current_area.?.addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const PAGE_SIZE = 4096;
|
||||||
|
|
||||||
|
pub const physFrame = struct {
|
||||||
|
number: u64,
|
||||||
|
|
||||||
|
pub fn from_addr(addr: u64) physFrame {
|
||||||
|
return physFrame{ .number = @divTrunc(addr, PAGE_SIZE) };
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add(self: physFrame, count: u64) physFrame {
|
||||||
|
return physFrame{ .number = self.number + count };
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn start_addr(self: physFrame) u64 {
|
||||||
|
return (self.number * PAGE_SIZE);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const PageDirectory = packed struct {
|
||||||
|
entries: [1024]PageDirectoryEntry,
|
||||||
|
};
|
||||||
|
|
||||||
|
const PageDirectoryEntry = packed struct {
|
||||||
|
address: u21,
|
||||||
|
available: u2,
|
||||||
|
ignored: u1,
|
||||||
|
size: u1,
|
||||||
|
zero: u1,
|
||||||
|
accessed: u1,
|
||||||
|
cache_disabled: u1,
|
||||||
|
write_through: u1,
|
||||||
|
user: u1,
|
||||||
|
writeable: u1,
|
||||||
|
present: u1,
|
||||||
|
};
|
||||||
|
|
||||||
|
const PageTable = packed struct {
|
||||||
|
entries: [1024]PageTableEntry,
|
||||||
|
};
|
||||||
|
|
||||||
|
const PageTableEntry = packed struct {
|
||||||
|
address: u21,
|
||||||
|
available: u2,
|
||||||
|
global: u1,
|
||||||
|
zero: u1,
|
||||||
|
dirty: u1,
|
||||||
|
accessed: u1,
|
||||||
|
cache_disabled: u1,
|
||||||
|
write_through: u1,
|
||||||
|
user: u1,
|
||||||
|
writeable: u1,
|
||||||
|
present: u1,
|
||||||
|
};
|
||||||
|
|
||||||
|
// assert(@sizeOf(PageTableEntry) == 32);
|
||||||
|
|
|
||||||
18
src/main.zig
18
src/main.zig
|
|
@ -1,8 +1,8 @@
|
||||||
usingnamespace @import("multiboot.zig");
|
usingnamespace @import("multiboot.zig");
|
||||||
|
usingnamespace @import("vga.zig");
|
||||||
const pci = @import("pci.zig");
|
const pci = @import("pci.zig");
|
||||||
const arch = @import("arch/x86/lib/index.zig");
|
const arch = @import("arch/x86/lib/index.zig");
|
||||||
const console = @import("console.zig");
|
const console = @import("console.zig");
|
||||||
const vga = @import("vga.zig");
|
|
||||||
const x86 = @import("arch/x86/main.zig");
|
const x86 = @import("arch/x86/main.zig");
|
||||||
const assert = @import("std").debug.assert;
|
const assert = @import("std").debug.assert;
|
||||||
|
|
||||||
|
|
@ -11,11 +11,23 @@ export fn kmain(magic: u32, info: *const MultibootInfo) noreturn {
|
||||||
assert(magic == MULTIBOOT_BOOTLOADER_MAGIC);
|
assert(magic == MULTIBOOT_BOOTLOADER_MAGIC);
|
||||||
console.initialize();
|
console.initialize();
|
||||||
|
|
||||||
vga.printf("--- x86_main ---\n");
|
printf("--- hello x86_main ---\n");
|
||||||
|
|
||||||
x86.x86_main(info);
|
x86.x86_main(info);
|
||||||
|
|
||||||
vga.printf("--- arch indepent boot ---\n");
|
// pagefault_test(0xfeffc000);
|
||||||
|
|
||||||
|
printf("\n--- arch indepent boot ---\n");
|
||||||
|
|
||||||
while (true) {}
|
while (true) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn pagefault_test(addr: u32) void {
|
||||||
|
const ptr = @intToPtr(*volatile u8, addr);
|
||||||
|
var a: u8 = ptr.*;
|
||||||
|
printf("a = {}\n", a);
|
||||||
|
|
||||||
|
ptr.* += 1;
|
||||||
|
|
||||||
|
printf("a = {}\n", ptr.*);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,6 @@
|
||||||
|
// MULTIBOOT1
|
||||||
|
// https://www.gnu.org/software/grub/manual/multiboot/multiboot.html
|
||||||
|
|
||||||
// zig fmt: off
|
// zig fmt: off
|
||||||
const tty = @import("tty.zig");
|
const tty = @import("tty.zig");
|
||||||
const cstr = @import("std").cstr;
|
const cstr = @import("std").cstr;
|
||||||
|
|
@ -117,7 +120,8 @@ export const multiboot_header align(4) linksection(".multiboot") = multiboot: {
|
||||||
const MAGIC = u32(0x1BADB002); // multiboot magic
|
const MAGIC = u32(0x1BADB002); // multiboot magic
|
||||||
const ALIGN = u32(1 << 0); // Align loaded modules.
|
const ALIGN = u32(1 << 0); // Align loaded modules.
|
||||||
const MEMINFO = u32(1 << 1); // Receive a memory map from the bootloader.
|
const MEMINFO = u32(1 << 1); // Receive a memory map from the bootloader.
|
||||||
const FLAGS = ALIGN | MEMINFO; // Combine the flags.
|
const CMDLINE = u32(1 << 2); // Receive a cmdline from the bootloader
|
||||||
|
const FLAGS = ALIGN | MEMINFO | CMDLINE; // Combine the flags.
|
||||||
|
|
||||||
break :multiboot MultibootHeader {
|
break :multiboot MultibootHeader {
|
||||||
.magic = MAGIC,
|
.magic = MAGIC,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue