paging almost done, endianess problem for now
This commit is contained in:
parent
e619364f71
commit
e832dede16
19 changed files with 270 additions and 137 deletions
|
|
@ -24,6 +24,8 @@ slowly porting from rust.
|
|||
`./qemu.sh monitor`
|
||||
`./qemu.sh gdb`
|
||||
|
||||
### todo
|
||||
# Notes
|
||||
|
||||
- recycling allocator that wraps the bump allocator
|
||||
## interrupts
|
||||
|
||||
`interrupt` -> `idt[n]` -> `isrN` -> `isrDispatch` -> `handlers[n]` (default `unhandled()`)
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ const Builder = @import("std").build.Builder;
|
|||
const builtin = @import("builtin");
|
||||
|
||||
pub fn build(b: *Builder) void {
|
||||
const kernel = b.addExecutable("bzImage", "src/arch/x86/main.zig");
|
||||
const kernel = b.addExecutable("kernel", "src/arch/x86/main.zig");
|
||||
kernel.addPackagePath("kernel", "src/index.zig");
|
||||
kernel.addPackagePath("arch", "src/arch/x86/lib/index.zig");
|
||||
kernel.setOutputDir("build");
|
||||
|
|
@ -10,6 +10,7 @@ pub fn build(b: *Builder) void {
|
|||
kernel.addAssemblyFile("src/arch/x86/_start.s");
|
||||
kernel.addAssemblyFile("src/arch/x86/gdt.s");
|
||||
kernel.addAssemblyFile("src/arch/x86/isr.s");
|
||||
kernel.addAssemblyFile("src/arch/x86/paging.s");
|
||||
|
||||
kernel.setBuildMode(b.standardReleaseOptions());
|
||||
kernel.setTarget(builtin.Arch.i386, builtin.Os.freestanding, builtin.Abi.none);
|
||||
|
|
|
|||
6
qemu.sh
6
qemu.sh
|
|
@ -1,7 +1,7 @@
|
|||
QEMU_SOCKET=/tmp/qemu.sock
|
||||
QEMU_MONITOR="socat - UNIX-CONNECT:${QEMU_SOCKET}"
|
||||
QEMU_GDB_PORT=4242
|
||||
KERNEL=build/bzImage
|
||||
KERNEL=build/kernel
|
||||
|
||||
start() {
|
||||
sudo pkill -9 qemu
|
||||
|
|
@ -10,11 +10,11 @@ start() {
|
|||
-monitor unix:${QEMU_SOCKET},server,nowait \
|
||||
-enable-kvm \
|
||||
-m 1337M \
|
||||
-display curses \
|
||||
-curses \
|
||||
-serial mon:stdio \
|
||||
-append "Hello" \
|
||||
-device virtio-net,netdev=network0 -netdev tap,id=network0,ifname=tap0,script=no,downscript=no \
|
||||
-kernel ${KERNEL}
|
||||
# -device virtio-net,netdev=network0 -netdev tap,id=network0,ifname=tap0,script=no,downscript=no \
|
||||
# build/kernel.iso
|
||||
"$@"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ fn makeEntry(base: usize, limit: usize, access: u8, flags: u4) GDTEntry {
|
|||
}
|
||||
|
||||
// Fill in the GDT.
|
||||
var gdt align(4) = []GDTEntry{
|
||||
var gdt align(4) = [_]GDTEntry{
|
||||
makeEntry(0, 0, 0, 0),
|
||||
makeEntry(0, 0xFFFFF, KERNEL | CODE, PROTECTED | BLOCKS_4K),
|
||||
makeEntry(0, 0xFFFFF, KERNEL | DATA, PROTECTED | BLOCKS_4K),
|
||||
|
|
@ -92,7 +92,7 @@ var tss = TSS{
|
|||
.unused1 = 0,
|
||||
.esp0 = undefined,
|
||||
.ss0 = KERNEL_DATA,
|
||||
.unused2 = []u32{0} ** 22,
|
||||
.unused2 = [_]u32{0} ** 22,
|
||||
.unused3 = 0,
|
||||
.iomap_base = @sizeOf(TSS),
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
// https://wiki.osdev.org/IDT
|
||||
usingnamespace @import("../../vga.zig");
|
||||
const x86 = @import("lib/index.zig");
|
||||
const interrupt = @import("interrupt.zig");
|
||||
const gdt = @import("gdt.zig");
|
||||
|
|
@ -47,12 +48,18 @@ pub fn setGate(n: u8, flags: u8, offset: extern fn () void) void {
|
|||
idt[n].flags = flags;
|
||||
idt[n].zero = 0;
|
||||
idt[n].selector = gdt.KERNEL_CODE;
|
||||
println("offset: 0x{x}", @ptrToInt(offset));
|
||||
println("low : 0x{x}", idt[n].offset_low);
|
||||
println("high : 0x{x}", idt[n].offset_high);
|
||||
}
|
||||
|
||||
////
|
||||
// Initialize the Interrupt Descriptor Table.
|
||||
//
|
||||
pub fn initialize() void {
|
||||
// configure PIC and set ISRs
|
||||
interrupt.initialize();
|
||||
|
||||
// load IDT
|
||||
x86.lidt(@ptrToInt(&idtr));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
const x86 = @import("lib/index.zig");
|
||||
const isr = @import("isr.zig");
|
||||
const println = @import("../../vga.zig").println;
|
||||
|
||||
// PIC ports.
|
||||
const PIC1_CMD = 0x20;
|
||||
|
|
@ -31,11 +32,11 @@ var handlers = [_]fn () void{unhandled} ** 48;
|
|||
|
||||
fn unhandled() noreturn {
|
||||
const n = isr.context.interrupt_n;
|
||||
// if (n >= IRQ_0) {
|
||||
// tty.panic("unhandled IRQ number {d}", n - IRQ_0);
|
||||
// } else {
|
||||
// tty.panic("unhandled exception number {d}", n);
|
||||
// }
|
||||
if (n < IRQ_0) {
|
||||
println("unhandled exception number {d}", n);
|
||||
} else {
|
||||
println("unhandled IRQ number {d} (intr {d})", n - IRQ_0, n);
|
||||
}
|
||||
x86.hang();
|
||||
}
|
||||
|
||||
|
|
@ -177,6 +178,7 @@ pub fn maskIRQ(irq: u8, mask: bool) void {
|
|||
} else {
|
||||
x86.outb(port, old & ~(u8(1) << shift));
|
||||
}
|
||||
const new = x86.inb(port); // Retrieve the current mask.
|
||||
}
|
||||
|
||||
////
|
||||
|
|
|
|||
|
|
@ -135,24 +135,24 @@ pub fn install() void {
|
|||
idt.setGate(30, idt.INTERRUPT_GATE, isr30);
|
||||
idt.setGate(31, idt.INTERRUPT_GATE, isr31);
|
||||
|
||||
// // IRQs.
|
||||
// IRQs.
|
||||
idt.setGate(32, idt.INTERRUPT_GATE, isr32);
|
||||
idt.setGate(33, idt.INTERRUPT_GATE, isr33);
|
||||
// idt.setGate(34, idt.INTERRUPT_GATE, isr34);
|
||||
// idt.setGate(35, idt.INTERRUPT_GATE, isr35);
|
||||
// idt.setGate(36, idt.INTERRUPT_GATE, isr36);
|
||||
// idt.setGate(37, idt.INTERRUPT_GATE, isr37);
|
||||
// idt.setGate(38, idt.INTERRUPT_GATE, isr38);
|
||||
// idt.setGate(39, idt.INTERRUPT_GATE, isr39);
|
||||
// idt.setGate(40, idt.INTERRUPT_GATE, isr40);
|
||||
// idt.setGate(41, idt.INTERRUPT_GATE, isr41);
|
||||
// idt.setGate(42, idt.INTERRUPT_GATE, isr42);
|
||||
// idt.setGate(43, idt.INTERRUPT_GATE, isr43);
|
||||
// idt.setGate(44, idt.INTERRUPT_GATE, isr44);
|
||||
// idt.setGate(45, idt.INTERRUPT_GATE, isr45);
|
||||
// idt.setGate(46, idt.INTERRUPT_GATE, isr46);
|
||||
// idt.setGate(47, idt.INTERRUPT_GATE, isr47);
|
||||
idt.setGate(34, idt.INTERRUPT_GATE, isr34);
|
||||
idt.setGate(35, idt.INTERRUPT_GATE, isr35);
|
||||
idt.setGate(36, idt.INTERRUPT_GATE, isr36);
|
||||
idt.setGate(37, idt.INTERRUPT_GATE, isr37);
|
||||
idt.setGate(38, idt.INTERRUPT_GATE, isr38);
|
||||
idt.setGate(39, idt.INTERRUPT_GATE, isr39);
|
||||
idt.setGate(40, idt.INTERRUPT_GATE, isr40);
|
||||
idt.setGate(41, idt.INTERRUPT_GATE, isr41);
|
||||
idt.setGate(42, idt.INTERRUPT_GATE, isr42);
|
||||
idt.setGate(43, idt.INTERRUPT_GATE, isr43);
|
||||
idt.setGate(44, idt.INTERRUPT_GATE, isr44);
|
||||
idt.setGate(45, idt.INTERRUPT_GATE, isr45);
|
||||
idt.setGate(46, idt.INTERRUPT_GATE, isr46);
|
||||
idt.setGate(47, idt.INTERRUPT_GATE, isr47);
|
||||
|
||||
// // Syscalls.
|
||||
// idt.setGate(128, idt.SYSCALL_GATE, isr128);
|
||||
// Syscalls.
|
||||
idt.setGate(128, idt.SYSCALL_GATE, isr128);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,9 @@ pub inline fn hang() noreturn {
|
|||
pub inline fn sti() void {
|
||||
asm volatile ("sti");
|
||||
}
|
||||
pub inline fn int3() void {
|
||||
asm volatile ("int3");
|
||||
}
|
||||
|
||||
////
|
||||
// Load a new Interrupt Descriptor Table.
|
||||
|
|
|
|||
|
|
@ -8,7 +8,8 @@ SECTIONS {
|
|||
. = 0xb8000;
|
||||
. += 80 * 25 * 2;
|
||||
|
||||
. = 0x100000;
|
||||
/* lower half kernel */
|
||||
. = 0x10000;
|
||||
|
||||
/* ensure that the multiboot header is at the beginning */
|
||||
.multiboot :
|
||||
|
|
@ -67,16 +68,4 @@ SECTIONS {
|
|||
*(.bss .bss.*)
|
||||
. = ALIGN(4K);
|
||||
}
|
||||
|
||||
/* .stab : */
|
||||
/* { */
|
||||
/* KEEP(*(.stab)) */
|
||||
/* . = ALIGN(4K); */
|
||||
/* } */
|
||||
|
||||
/* .stabstr : */
|
||||
/* { */
|
||||
/* KEEP(*(.stabstr)) */
|
||||
/* . = ALIGN(4K); */
|
||||
/* } */
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,18 +1,37 @@
|
|||
usingnamespace @import("kernel").main;
|
||||
usingnamespace @import("kernel").multiboot;
|
||||
const console = @import("../console.zig");
|
||||
const println = @import("../../vga.zig").println;
|
||||
|
||||
const idt = @import("idt.zig");
|
||||
const mem = @import("mem.zig");
|
||||
const memory = @import("memory.zig");
|
||||
const paging = @import("paging.zig");
|
||||
const gdt = @import("gdt.zig");
|
||||
const x86 = @import("lib/index.zig");
|
||||
const console = @import("../console.zig");
|
||||
const printf = @import("../../vga.zig").printf;
|
||||
|
||||
/// x86 specific intialization
|
||||
/// first entry point (see linker.ld)
|
||||
pub fn x86_main(info: *const MultibootInfo) void {
|
||||
var allocator = mem.initialize(info);
|
||||
// set up the physical frame allocator
|
||||
memory.initialize(info);
|
||||
|
||||
// gdt.initialize();
|
||||
println("{}", memory.allocator.allocate(1));
|
||||
// println("{}", memory.allocator.allocate(1));
|
||||
// println("{}", memory.allocator.allocate(1));
|
||||
// println("{}", memory.allocator.allocate(1));
|
||||
|
||||
// setup memory segmentation
|
||||
gdt.initialize();
|
||||
|
||||
// setup interrupts
|
||||
idt.initialize();
|
||||
|
||||
// enable interrupts
|
||||
x86.sti();
|
||||
|
||||
// set up the virtual page mapper
|
||||
paging.initialize();
|
||||
|
||||
// test breakpoint
|
||||
// x86.int3();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,41 +1,43 @@
|
|||
usingnamespace @import("kernel").multiboot;
|
||||
usingnamespace @import("../../vga.zig");
|
||||
const assert = @import("std").debug.assert;
|
||||
const vga = @import("../../vga.zig");
|
||||
const std = @import("std");
|
||||
const printf = @import("../../vga.zig").printf;
|
||||
|
||||
pub fn initialize(info: *const MultibootInfo) bumpAllocator {
|
||||
pub var allocator: bumpAllocator = undefined;
|
||||
|
||||
pub fn initialize(info: *const MultibootInfo) void {
|
||||
assert((info.flags & MULTIBOOT_INFO_MEMORY) != 0);
|
||||
assert((info.flags & MULTIBOOT_INFO_MEM_MAP) != 0);
|
||||
|
||||
format_multibootinfo(info);
|
||||
return bumpAllocator.new(info);
|
||||
allocator = bumpAllocator.new(info);
|
||||
}
|
||||
|
||||
pub fn format_multibootentry(entry: *MultibootMMapEntry) void {
|
||||
fn format_multibootentry(entry: *MultibootMMapEntry) void {
|
||||
if (entry.type == MULTIBOOT_MEMORY_AVAILABLE) {
|
||||
vga.printf("AVAILABLE: ");
|
||||
print(" AVAILABLE: ");
|
||||
} else {
|
||||
vga.printf("NOT AVAILABLE: ");
|
||||
print("NOT AVAILABLE: ");
|
||||
}
|
||||
vga.printf("{x} ", entry.addr);
|
||||
print("{x} ", entry.addr);
|
||||
if (entry.len / (1024 * 1024) > 0) {
|
||||
vga.printf("({} MB)\n", entry.len / (1024 * 1024));
|
||||
println("({} MB)", entry.len / (1024 * 1024));
|
||||
} else {
|
||||
vga.printf("({} kB)\n", entry.len / (1024));
|
||||
println("({} kB)", entry.len / (1024));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn format_multibootinfo(info: *const MultibootInfo) void {
|
||||
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);
|
||||
println("flags: {b}", info.flags);
|
||||
println("lower: {x}", info.mem_lower);
|
||||
println("upper: {x}", info.mem_upper);
|
||||
println("mmap_l: {}", info.mmap_length);
|
||||
println("mmap_a: {x}", info.mmap_addr);
|
||||
println("cmdline: {x}", cmdline_ptr);
|
||||
println("cmdline: {}", cmdline);
|
||||
|
||||
var map: usize = info.mmap_addr;
|
||||
while (map < info.mmap_addr + info.mmap_length) {
|
||||
|
|
@ -47,22 +49,21 @@ pub fn format_multibootinfo(info: *const MultibootInfo) void {
|
|||
|
||||
// returns each available physical frame one by one in order
|
||||
pub const bumpAllocator = struct {
|
||||
next_free_frame: physFrame,
|
||||
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{
|
||||
var allocato = bumpAllocator{
|
||||
.current_area = first_area,
|
||||
.next_free_frame = physFrame.from_addr(first_area.addr),
|
||||
.next_free_frame = PhysFrame.from_addr(@intCast(u32, first_area.addr)),
|
||||
.info = info,
|
||||
};
|
||||
// allocator.choose_next_area();
|
||||
return allocator;
|
||||
return allocato;
|
||||
}
|
||||
|
||||
pub fn allocate(self: var, count: u64) ?physFrame {
|
||||
pub fn allocate(self: var, count: u32) ?PhysFrame {
|
||||
if (count == 0) {
|
||||
return null;
|
||||
}
|
||||
|
|
@ -73,10 +74,15 @@ pub const bumpAllocator = struct {
|
|||
self.choose_next_area();
|
||||
return self.allocate(count);
|
||||
}
|
||||
// <4MB identity mapped kernel, lazy trick
|
||||
if (PhysFrame.start_addr(self.next_free_frame) < 0x400000) {
|
||||
self.next_free_frame.number += 1;
|
||||
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);
|
||||
const current_area_last_frame = PhysFrame.from_addr(@intCast(u32, 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);
|
||||
|
|
@ -86,72 +92,33 @@ pub const bumpAllocator = struct {
|
|||
}
|
||||
|
||||
pub fn choose_next_area(self: var) void {
|
||||
printf("choosing next area\n");
|
||||
println("choosing next area");
|
||||
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);
|
||||
self.next_free_frame = PhysFrame.from_addr(@intCast(u32, self.current_area.?.addr));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
pub const PAGE_SIZE = 4096;
|
||||
|
||||
pub const physFrame = struct {
|
||||
number: u64,
|
||||
pub const PhysFrame = struct {
|
||||
number: u32,
|
||||
|
||||
pub fn from_addr(addr: u64) physFrame {
|
||||
return physFrame{ .number = @divTrunc(addr, PAGE_SIZE) };
|
||||
pub fn from_addr(addr: u32) PhysFrame {
|
||||
return PhysFrame{ .number = @divTrunc(addr, PAGE_SIZE) };
|
||||
}
|
||||
|
||||
pub fn add(self: physFrame, count: u64) physFrame {
|
||||
return physFrame{ .number = self.number + count };
|
||||
pub fn add(self: PhysFrame, count: u32) PhysFrame {
|
||||
return PhysFrame{ .number = self.number + count };
|
||||
}
|
||||
|
||||
pub fn start_addr(self: physFrame) u64 {
|
||||
pub fn start_addr(self: PhysFrame) u32 {
|
||||
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);
|
||||
24
src/arch/x86/paging.s
Normal file
24
src/arch/x86/paging.s
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
.type setupPaging, @function
|
||||
.global setupPaging
|
||||
|
||||
////
|
||||
// Enable the paging system.
|
||||
//
|
||||
// Arguments:
|
||||
// phys_pd: Physical pointer to the page directory.
|
||||
//
|
||||
setupPaging:
|
||||
mov +4(%esp), %eax // Fetch the phys_pd parameter.
|
||||
mov %eax, %cr3 // Point CR3 to the page directory.
|
||||
|
||||
// Enable Page Size Extension and Page Global.
|
||||
mov %cr4, %eax
|
||||
or $0b00010000, %eax
|
||||
mov %eax, %cr4
|
||||
|
||||
// Enable Paging.
|
||||
mov %cr0, %eax
|
||||
or $(1 << 31), %eax
|
||||
mov %eax, %cr0
|
||||
|
||||
ret
|
||||
89
src/arch/x86/paging.zig
Normal file
89
src/arch/x86/paging.zig
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
const x86 = @import("lib/index.zig");
|
||||
const allocator = @import("memory.zig").allocator;
|
||||
const assert = @import("std").debug.assert;
|
||||
const println = @import("../../vga.zig").println;
|
||||
|
||||
extern fn setupPaging(phys_pd: usize) void;
|
||||
|
||||
pub var mapper: Mapper = undefined;
|
||||
pub const PAGE_SIZE = 4096;
|
||||
|
||||
pub fn initialize() void {
|
||||
const empty_page = PageDirectoryEntry{};
|
||||
// var p2 = allocator.allocate(1);
|
||||
var p2 = [_]PageDirectoryEntry{empty_page} ** 1024;
|
||||
// var p2 = [_]u32{0} ** 1024;
|
||||
|
||||
// identity map 0 -> 4MB
|
||||
p2[0].pageTable = 0x0;
|
||||
p2[0].present = true;
|
||||
p2[0].read_write = true;
|
||||
p2[0].huge = true;
|
||||
// p2[0] = @bitReverse(u32, 0b10000011);
|
||||
|
||||
println("p2[0] {b}", p2[0]);
|
||||
println("p2[0] {b}", @bitCast(u32, p2[0]));
|
||||
// x86.hang();
|
||||
// paging.s
|
||||
// setupPaging(@ptrToInt(&p2));
|
||||
|
||||
// mapper = Mapper{
|
||||
// .p2 = p2,
|
||||
// };
|
||||
const addr = mapper.translate(0xfffff000);
|
||||
}
|
||||
|
||||
const builtin = @import("builtin");
|
||||
const Mapper = struct {
|
||||
p2: PageDirectory,
|
||||
|
||||
// virt to phys
|
||||
pub fn translate(self: Mapper, virt: u32) ?u32 {
|
||||
const map = @bitCast(VirtAddr, virt);
|
||||
println("{}", builtin.endian);
|
||||
println("virt {x} -> {}-{}-{x}", virt, map.page_directory, map.page_table, map.offset);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
pub const VirtAddr = packed struct {
|
||||
page_directory: u10,
|
||||
page_table: u10,
|
||||
offset: u12,
|
||||
};
|
||||
|
||||
pub const PageDirectoryEntry = packed struct {
|
||||
pageTable: u20 = 0,
|
||||
available: u3 = 0,
|
||||
ignored: bool = false,
|
||||
huge: bool = false,
|
||||
zero: bool = false,
|
||||
accessed: bool = false,
|
||||
cache_disabled: bool = false,
|
||||
write_thru: bool = false,
|
||||
supervisor: bool = false,
|
||||
read_write: bool = false,
|
||||
present: bool = false,
|
||||
};
|
||||
|
||||
pub const PageTableEntry = packed struct {
|
||||
addr: u20 = 0,
|
||||
available: u3 = 0,
|
||||
global: bool = false,
|
||||
zero: bool = false,
|
||||
dirty: bool = false,
|
||||
accessed: bool = false,
|
||||
cache_disabled: bool = false,
|
||||
write_thru: bool = false,
|
||||
supervisor: bool = false,
|
||||
read_write: bool = false,
|
||||
present: bool = false,
|
||||
};
|
||||
|
||||
pub const PageTable = [1024]PageTableEntry;
|
||||
pub const PageDirectory = [1024]PageDirectoryEntry;
|
||||
|
||||
comptime {
|
||||
assert(@sizeOf(PageDirectoryEntry) == 4); //32 bits
|
||||
assert(@sizeOf(PageTableEntry) == 4); //32 bits
|
||||
}
|
||||
|
|
@ -33,7 +33,7 @@ pub fn keypress(char: u8) void {
|
|||
}
|
||||
|
||||
pub fn initialize() void {
|
||||
vga.clear();
|
||||
// vga.writeString("> ");
|
||||
// vga.clear();
|
||||
interrupt.registerIRQ(1, ps2.keyboard_handler);
|
||||
vga.writeString("> ");
|
||||
}
|
||||
|
|
|
|||
11
src/main.zig
11
src/main.zig
|
|
@ -9,17 +9,18 @@ const assert = @import("std").debug.assert;
|
|||
// arch independant initialization
|
||||
export fn kmain(magic: u32, info: *const MultibootInfo) noreturn {
|
||||
assert(magic == MULTIBOOT_BOOTLOADER_MAGIC);
|
||||
console.initialize();
|
||||
|
||||
printf("--- hello x86_main ---\n");
|
||||
|
||||
println("--- x86 initialization ---");
|
||||
x86.x86_main(info);
|
||||
|
||||
// pagefault_test(0xfeffc000);
|
||||
|
||||
printf("\n--- arch indepent boot ---\n");
|
||||
println("--- core initialization ---");
|
||||
console.initialize();
|
||||
|
||||
while (true) {}
|
||||
while (true) {
|
||||
asm volatile ("hlt");
|
||||
}
|
||||
}
|
||||
|
||||
fn pagefault_test(addr: u32) void {
|
||||
|
|
|
|||
|
|
@ -13,29 +13,46 @@ pub const MULTIBOOT_BOOTLOADER_MAGIC = 0x2BADB002;
|
|||
pub const MULTIBOOT_INFO_MEMORY = 0x00000001;
|
||||
// Is there a full memory map?
|
||||
pub const MULTIBOOT_INFO_MEM_MAP = 0x00000040;
|
||||
|
||||
// System information structure passed by the bootloader.
|
||||
pub const MultibootInfo = packed struct {
|
||||
// Multiboot info version number.
|
||||
flags: u32,
|
||||
|
||||
// Available memory from BIOS.
|
||||
// present if flags[0]
|
||||
mem_lower: u32,
|
||||
mem_upper: u32,
|
||||
|
||||
// "root" partition.
|
||||
// present if flags[1]
|
||||
boot_device: u32,
|
||||
|
||||
// Kernel command line.
|
||||
// present if flags[2]
|
||||
cmdline: u32,
|
||||
|
||||
// Boot-Module list.
|
||||
mods_count: u32,
|
||||
mods_addr: u32,
|
||||
|
||||
// TODO: use the real types here.
|
||||
u: u128,
|
||||
syms: extern union {
|
||||
// present if flags[4]
|
||||
nlist: extern struct {
|
||||
tabsize: u32,
|
||||
strsize: u32,
|
||||
addr: u32,
|
||||
_reserved: u32,
|
||||
},
|
||||
// present if flags[5]
|
||||
shdr: extern struct {
|
||||
num: u32,
|
||||
size: u32,
|
||||
addr: u32,
|
||||
shndx: u32,
|
||||
},
|
||||
},
|
||||
|
||||
// Memory Mapping buffer.
|
||||
// present if flags[6]
|
||||
mmap_length: u32,
|
||||
mmap_addr: u32,
|
||||
|
||||
|
|
@ -112,16 +129,22 @@ const MultibootHeader = packed struct {
|
|||
magic: u32, // Must be equal to header magic number.
|
||||
flags: u32, // Feature flags.
|
||||
checksum: u32, // Above fields plus this one must equal 0 mod 2^32.
|
||||
// following fields are used if flag bit 16 is specified
|
||||
header_addr: u32 = 0,
|
||||
load_addr: u32 = 0,
|
||||
load_end_addr: u32 = 0,
|
||||
bss_end_addr: u32 = 0,
|
||||
entry_addr: u32 = 0,
|
||||
};
|
||||
// NOTE: this structure is incomplete.
|
||||
|
||||
// Place the header at the very beginning of the binary.
|
||||
export const multiboot_header align(4) linksection(".multiboot") = multiboot: {
|
||||
const MAGIC = u32(0x1BADB002); // multiboot magic
|
||||
const ALIGN = u32(1 << 0); // Align loaded modules.
|
||||
const ALIGN = u32(1 << 0); // Align loaded modules at 4k
|
||||
const MEMINFO = u32(1 << 1); // Receive a memory map from the bootloader.
|
||||
const CMDLINE = u32(1 << 2); // Receive a cmdline from the bootloader
|
||||
const FLAGS = ALIGN | MEMINFO | CMDLINE; // Combine the flags.
|
||||
const ADDR = u32(1 << 16); // Load specific addr
|
||||
const FLAGS = ALIGN | MEMINFO; // Combine the flags.
|
||||
|
||||
break :multiboot MultibootHeader {
|
||||
.magic = MAGIC,
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ const arch = @import("arch/x86/lib/index.zig");
|
|||
|
||||
const PCI_CONFIG_ADDRESS = 0xCF8;
|
||||
const PCI_CONFIG_DATA = 0xCFC;
|
||||
const vga = @import("vga.zig");
|
||||
usingnamespace @import("vga.zig");
|
||||
|
||||
pub const PciAddress = packed struct {
|
||||
offset: u8,
|
||||
|
|
@ -57,7 +57,7 @@ pub const PciDevice = struct {
|
|||
}
|
||||
|
||||
pub fn format(self: PciDevice) void {
|
||||
vga.printf("{}:{}.{} {x},{x}: {x} {x}\n", self.bus, self.slot, self.function, self.class, self.subclass, self.vendor, self.device);
|
||||
println("{}:{}.{} {x},{x}: {x} {x}", self.bus, self.slot, self.function, self.class, self.subclass, self.vendor, self.device);
|
||||
}
|
||||
|
||||
pub fn access(self: PciDevice, offset: u8) void {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
usingnamespace @import("vga.zig");
|
||||
const x86 = @import("arch/x86/lib/index.zig");
|
||||
const console = @import("console.zig");
|
||||
|
||||
|
|
@ -84,6 +85,7 @@ fn key_isrelease(scancode: u8) bool {
|
|||
pub fn keyboard_handler() void {
|
||||
const scancode = ps2_scancode();
|
||||
const isrelease = key_isrelease(scancode);
|
||||
println("keyboard scancode 0b{b}", scancode);
|
||||
if (isrelease) {
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,10 +56,14 @@ pub fn disableCursor() void {
|
|||
}
|
||||
|
||||
const Errors = error{};
|
||||
pub fn printf(comptime format: []const u8, args: ...) void {
|
||||
pub fn print(comptime format: []const u8, args: ...) void {
|
||||
var a = std.fmt.format({}, Errors, printCallback, format, args);
|
||||
}
|
||||
|
||||
pub fn println(comptime format: []const u8, args: ...) void {
|
||||
var a = std.fmt.format({}, Errors, printCallback, format ++ "\n", args);
|
||||
}
|
||||
|
||||
fn printCallback(context: void, string: []const u8) Errors!void {
|
||||
vga.writeString(string);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue