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 monitor`
|
||||||
`./qemu.sh gdb`
|
`./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");
|
const builtin = @import("builtin");
|
||||||
|
|
||||||
pub fn build(b: *Builder) void {
|
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("kernel", "src/index.zig");
|
||||||
kernel.addPackagePath("arch", "src/arch/x86/lib/index.zig");
|
kernel.addPackagePath("arch", "src/arch/x86/lib/index.zig");
|
||||||
kernel.setOutputDir("build");
|
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/_start.s");
|
||||||
kernel.addAssemblyFile("src/arch/x86/gdt.s");
|
kernel.addAssemblyFile("src/arch/x86/gdt.s");
|
||||||
kernel.addAssemblyFile("src/arch/x86/isr.s");
|
kernel.addAssemblyFile("src/arch/x86/isr.s");
|
||||||
|
kernel.addAssemblyFile("src/arch/x86/paging.s");
|
||||||
|
|
||||||
kernel.setBuildMode(b.standardReleaseOptions());
|
kernel.setBuildMode(b.standardReleaseOptions());
|
||||||
kernel.setTarget(builtin.Arch.i386, builtin.Os.freestanding, builtin.Abi.none);
|
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_SOCKET=/tmp/qemu.sock
|
||||||
QEMU_MONITOR="socat - UNIX-CONNECT:${QEMU_SOCKET}"
|
QEMU_MONITOR="socat - UNIX-CONNECT:${QEMU_SOCKET}"
|
||||||
QEMU_GDB_PORT=4242
|
QEMU_GDB_PORT=4242
|
||||||
KERNEL=build/bzImage
|
KERNEL=build/kernel
|
||||||
|
|
||||||
start() {
|
start() {
|
||||||
sudo pkill -9 qemu
|
sudo pkill -9 qemu
|
||||||
|
|
@ -10,11 +10,11 @@ start() {
|
||||||
-monitor unix:${QEMU_SOCKET},server,nowait \
|
-monitor unix:${QEMU_SOCKET},server,nowait \
|
||||||
-enable-kvm \
|
-enable-kvm \
|
||||||
-m 1337M \
|
-m 1337M \
|
||||||
-display curses \
|
-curses \
|
||||||
-serial mon:stdio \
|
-serial mon:stdio \
|
||||||
-append "Hello" \
|
-append "Hello" \
|
||||||
-device virtio-net,netdev=network0 -netdev tap,id=network0,ifname=tap0,script=no,downscript=no \
|
|
||||||
-kernel ${KERNEL}
|
-kernel ${KERNEL}
|
||||||
|
# -device virtio-net,netdev=network0 -netdev tap,id=network0,ifname=tap0,script=no,downscript=no \
|
||||||
# build/kernel.iso
|
# build/kernel.iso
|
||||||
"$@"
|
"$@"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,7 @@ fn makeEntry(base: usize, limit: usize, access: u8, flags: u4) GDTEntry {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fill in the GDT.
|
// Fill in the GDT.
|
||||||
var gdt align(4) = []GDTEntry{
|
var gdt align(4) = [_]GDTEntry{
|
||||||
makeEntry(0, 0, 0, 0),
|
makeEntry(0, 0, 0, 0),
|
||||||
makeEntry(0, 0xFFFFF, KERNEL | CODE, PROTECTED | BLOCKS_4K),
|
makeEntry(0, 0xFFFFF, KERNEL | CODE, PROTECTED | BLOCKS_4K),
|
||||||
makeEntry(0, 0xFFFFF, KERNEL | DATA, PROTECTED | BLOCKS_4K),
|
makeEntry(0, 0xFFFFF, KERNEL | DATA, PROTECTED | BLOCKS_4K),
|
||||||
|
|
@ -92,7 +92,7 @@ var tss = TSS{
|
||||||
.unused1 = 0,
|
.unused1 = 0,
|
||||||
.esp0 = undefined,
|
.esp0 = undefined,
|
||||||
.ss0 = KERNEL_DATA,
|
.ss0 = KERNEL_DATA,
|
||||||
.unused2 = []u32{0} ** 22,
|
.unused2 = [_]u32{0} ** 22,
|
||||||
.unused3 = 0,
|
.unused3 = 0,
|
||||||
.iomap_base = @sizeOf(TSS),
|
.iomap_base = @sizeOf(TSS),
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
// https://wiki.osdev.org/IDT
|
// https://wiki.osdev.org/IDT
|
||||||
|
usingnamespace @import("../../vga.zig");
|
||||||
const x86 = @import("lib/index.zig");
|
const x86 = @import("lib/index.zig");
|
||||||
const interrupt = @import("interrupt.zig");
|
const interrupt = @import("interrupt.zig");
|
||||||
const gdt = @import("gdt.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].flags = flags;
|
||||||
idt[n].zero = 0;
|
idt[n].zero = 0;
|
||||||
idt[n].selector = gdt.KERNEL_CODE;
|
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.
|
// Initialize the Interrupt Descriptor Table.
|
||||||
//
|
//
|
||||||
pub fn initialize() void {
|
pub fn initialize() void {
|
||||||
|
// configure PIC and set ISRs
|
||||||
interrupt.initialize();
|
interrupt.initialize();
|
||||||
|
|
||||||
|
// load IDT
|
||||||
x86.lidt(@ptrToInt(&idtr));
|
x86.lidt(@ptrToInt(&idtr));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
const x86 = @import("lib/index.zig");
|
const x86 = @import("lib/index.zig");
|
||||||
const isr = @import("isr.zig");
|
const isr = @import("isr.zig");
|
||||||
|
const println = @import("../../vga.zig").println;
|
||||||
|
|
||||||
// PIC ports.
|
// PIC ports.
|
||||||
const PIC1_CMD = 0x20;
|
const PIC1_CMD = 0x20;
|
||||||
|
|
@ -31,11 +32,11 @@ var handlers = [_]fn () void{unhandled} ** 48;
|
||||||
|
|
||||||
fn unhandled() noreturn {
|
fn unhandled() noreturn {
|
||||||
const n = isr.context.interrupt_n;
|
const n = isr.context.interrupt_n;
|
||||||
// if (n >= IRQ_0) {
|
if (n < IRQ_0) {
|
||||||
// tty.panic("unhandled IRQ number {d}", n - IRQ_0);
|
println("unhandled exception number {d}", n);
|
||||||
// } else {
|
} else {
|
||||||
// tty.panic("unhandled exception number {d}", n);
|
println("unhandled IRQ number {d} (intr {d})", n - IRQ_0, n);
|
||||||
// }
|
}
|
||||||
x86.hang();
|
x86.hang();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -177,6 +178,7 @@ pub fn maskIRQ(irq: u8, mask: bool) void {
|
||||||
} else {
|
} else {
|
||||||
x86.outb(port, old & ~(u8(1) << shift));
|
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(30, idt.INTERRUPT_GATE, isr30);
|
||||||
idt.setGate(31, idt.INTERRUPT_GATE, isr31);
|
idt.setGate(31, idt.INTERRUPT_GATE, isr31);
|
||||||
|
|
||||||
// // IRQs.
|
// IRQs.
|
||||||
idt.setGate(32, idt.INTERRUPT_GATE, isr32);
|
idt.setGate(32, idt.INTERRUPT_GATE, isr32);
|
||||||
idt.setGate(33, idt.INTERRUPT_GATE, isr33);
|
idt.setGate(33, idt.INTERRUPT_GATE, isr33);
|
||||||
// idt.setGate(34, idt.INTERRUPT_GATE, isr34);
|
idt.setGate(34, idt.INTERRUPT_GATE, isr34);
|
||||||
// idt.setGate(35, idt.INTERRUPT_GATE, isr35);
|
idt.setGate(35, idt.INTERRUPT_GATE, isr35);
|
||||||
// idt.setGate(36, idt.INTERRUPT_GATE, isr36);
|
idt.setGate(36, idt.INTERRUPT_GATE, isr36);
|
||||||
// idt.setGate(37, idt.INTERRUPT_GATE, isr37);
|
idt.setGate(37, idt.INTERRUPT_GATE, isr37);
|
||||||
// idt.setGate(38, idt.INTERRUPT_GATE, isr38);
|
idt.setGate(38, idt.INTERRUPT_GATE, isr38);
|
||||||
// idt.setGate(39, idt.INTERRUPT_GATE, isr39);
|
idt.setGate(39, idt.INTERRUPT_GATE, isr39);
|
||||||
// idt.setGate(40, idt.INTERRUPT_GATE, isr40);
|
idt.setGate(40, idt.INTERRUPT_GATE, isr40);
|
||||||
// idt.setGate(41, idt.INTERRUPT_GATE, isr41);
|
idt.setGate(41, idt.INTERRUPT_GATE, isr41);
|
||||||
// idt.setGate(42, idt.INTERRUPT_GATE, isr42);
|
idt.setGate(42, idt.INTERRUPT_GATE, isr42);
|
||||||
// idt.setGate(43, idt.INTERRUPT_GATE, isr43);
|
idt.setGate(43, idt.INTERRUPT_GATE, isr43);
|
||||||
// idt.setGate(44, idt.INTERRUPT_GATE, isr44);
|
idt.setGate(44, idt.INTERRUPT_GATE, isr44);
|
||||||
// idt.setGate(45, idt.INTERRUPT_GATE, isr45);
|
idt.setGate(45, idt.INTERRUPT_GATE, isr45);
|
||||||
// idt.setGate(46, idt.INTERRUPT_GATE, isr46);
|
idt.setGate(46, idt.INTERRUPT_GATE, isr46);
|
||||||
// idt.setGate(47, idt.INTERRUPT_GATE, isr47);
|
idt.setGate(47, idt.INTERRUPT_GATE, isr47);
|
||||||
|
|
||||||
// // Syscalls.
|
// Syscalls.
|
||||||
// idt.setGate(128, idt.SYSCALL_GATE, isr128);
|
idt.setGate(128, idt.SYSCALL_GATE, isr128);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,9 @@ pub inline fn hang() noreturn {
|
||||||
pub inline fn sti() void {
|
pub inline fn sti() void {
|
||||||
asm volatile ("sti");
|
asm volatile ("sti");
|
||||||
}
|
}
|
||||||
|
pub inline fn int3() void {
|
||||||
|
asm volatile ("int3");
|
||||||
|
}
|
||||||
|
|
||||||
////
|
////
|
||||||
// Load a new Interrupt Descriptor Table.
|
// Load a new Interrupt Descriptor Table.
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,8 @@ SECTIONS {
|
||||||
. = 0xb8000;
|
. = 0xb8000;
|
||||||
. += 80 * 25 * 2;
|
. += 80 * 25 * 2;
|
||||||
|
|
||||||
. = 0x100000;
|
/* lower half kernel */
|
||||||
|
. = 0x10000;
|
||||||
|
|
||||||
/* ensure that the multiboot header is at the beginning */
|
/* ensure that the multiboot header is at the beginning */
|
||||||
.multiboot :
|
.multiboot :
|
||||||
|
|
@ -67,16 +68,4 @@ SECTIONS {
|
||||||
*(.bss .bss.*)
|
*(.bss .bss.*)
|
||||||
. = ALIGN(4K);
|
. = ALIGN(4K);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* .stab : */
|
|
||||||
/* { */
|
|
||||||
/* KEEP(*(.stab)) */
|
|
||||||
/* . = ALIGN(4K); */
|
|
||||||
/* } */
|
|
||||||
|
|
||||||
/* .stabstr : */
|
|
||||||
/* { */
|
|
||||||
/* KEEP(*(.stabstr)) */
|
|
||||||
/* . = ALIGN(4K); */
|
|
||||||
/* } */
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,37 @@
|
||||||
usingnamespace @import("kernel").main;
|
usingnamespace @import("kernel").main;
|
||||||
usingnamespace @import("kernel").multiboot;
|
usingnamespace @import("kernel").multiboot;
|
||||||
|
const console = @import("../console.zig");
|
||||||
|
const println = @import("../../vga.zig").println;
|
||||||
|
|
||||||
const idt = @import("idt.zig");
|
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 gdt = @import("gdt.zig");
|
||||||
const x86 = @import("lib/index.zig");
|
const x86 = @import("lib/index.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 {
|
||||||
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();
|
idt.initialize();
|
||||||
|
|
||||||
|
// enable interrupts
|
||||||
x86.sti();
|
x86.sti();
|
||||||
|
|
||||||
|
// set up the virtual page mapper
|
||||||
|
paging.initialize();
|
||||||
|
|
||||||
|
// test breakpoint
|
||||||
|
// x86.int3();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,41 +1,43 @@
|
||||||
usingnamespace @import("kernel").multiboot;
|
usingnamespace @import("kernel").multiboot;
|
||||||
|
usingnamespace @import("../../vga.zig");
|
||||||
const assert = @import("std").debug.assert;
|
const assert = @import("std").debug.assert;
|
||||||
const vga = @import("../../vga.zig");
|
|
||||||
const std = @import("std");
|
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_MEMORY) != 0);
|
||||||
assert((info.flags & MULTIBOOT_INFO_MEM_MAP) != 0);
|
assert((info.flags & MULTIBOOT_INFO_MEM_MAP) != 0);
|
||||||
|
|
||||||
format_multibootinfo(info);
|
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) {
|
if (entry.type == MULTIBOOT_MEMORY_AVAILABLE) {
|
||||||
vga.printf("AVAILABLE: ");
|
print(" AVAILABLE: ");
|
||||||
} else {
|
} else {
|
||||||
vga.printf("NOT AVAILABLE: ");
|
print("NOT AVAILABLE: ");
|
||||||
}
|
}
|
||||||
vga.printf("{x} ", entry.addr);
|
print("{x} ", entry.addr);
|
||||||
if (entry.len / (1024 * 1024) > 0) {
|
if (entry.len / (1024 * 1024) > 0) {
|
||||||
vga.printf("({} MB)\n", entry.len / (1024 * 1024));
|
println("({} MB)", entry.len / (1024 * 1024));
|
||||||
} else {
|
} 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_ptr = @intToPtr([*c]const u8, info.cmdline);
|
||||||
var cmdline = @ptrCast([*c]const u8, cmdline_ptr);
|
var cmdline = @ptrCast([*c]const u8, cmdline_ptr);
|
||||||
// var cmdline = std.cstr.toSliceConst(info.cmdline);
|
// var cmdline = std.cstr.toSliceConst(info.cmdline);
|
||||||
vga.printf("lower: {x}\n", info.mem_lower);
|
println("flags: {b}", info.flags);
|
||||||
vga.printf("upper: {x}\n", info.mem_upper);
|
println("lower: {x}", info.mem_lower);
|
||||||
vga.printf("mmap_l: {}\n", info.mmap_length);
|
println("upper: {x}", info.mem_upper);
|
||||||
vga.printf("mmap_a: {x}\n", info.mmap_addr);
|
println("mmap_l: {}", info.mmap_length);
|
||||||
vga.printf("cmdline: {x}\n", cmdline_ptr);
|
println("mmap_a: {x}", info.mmap_addr);
|
||||||
vga.printf("cmdline: {}\n", cmdline);
|
println("cmdline: {x}", cmdline_ptr);
|
||||||
|
println("cmdline: {}", cmdline);
|
||||||
|
|
||||||
var map: usize = info.mmap_addr;
|
var map: usize = info.mmap_addr;
|
||||||
while (map < info.mmap_addr + info.mmap_length) {
|
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
|
// returns each available physical frame one by one in order
|
||||||
pub const bumpAllocator = struct {
|
pub const bumpAllocator = struct {
|
||||||
next_free_frame: physFrame,
|
next_free_frame: PhysFrame,
|
||||||
current_area: ?*MultibootMMapEntry,
|
current_area: ?*MultibootMMapEntry,
|
||||||
info: *const MultibootInfo,
|
info: *const MultibootInfo,
|
||||||
|
|
||||||
pub fn new(info: *const MultibootInfo) bumpAllocator {
|
pub fn new(info: *const MultibootInfo) bumpAllocator {
|
||||||
const first_area = @intToPtr(*MultibootMMapEntry, info.mmap_addr);
|
const first_area = @intToPtr(*MultibootMMapEntry, info.mmap_addr);
|
||||||
var allocator = bumpAllocator{
|
var allocato = bumpAllocator{
|
||||||
.current_area = first_area,
|
.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,
|
.info = info,
|
||||||
};
|
};
|
||||||
// allocator.choose_next_area();
|
return allocato;
|
||||||
return allocator;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn allocate(self: var, count: u64) ?physFrame {
|
pub fn allocate(self: var, count: u32) ?PhysFrame {
|
||||||
if (count == 0) {
|
if (count == 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
@ -73,10 +74,15 @@ pub const bumpAllocator = struct {
|
||||||
self.choose_next_area();
|
self.choose_next_area();
|
||||||
return self.allocate(count);
|
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 start_frame = self.next_free_frame;
|
||||||
const end_frame = self.next_free_frame.add(count - 1);
|
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) {
|
if (end_frame.number > current_area_last_frame.number) {
|
||||||
self.choose_next_area();
|
self.choose_next_area();
|
||||||
return self.allocate(count);
|
return self.allocate(count);
|
||||||
|
|
@ -86,72 +92,33 @@ pub const bumpAllocator = struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn choose_next_area(self: var) void {
|
pub fn choose_next_area(self: var) void {
|
||||||
printf("choosing next area\n");
|
println("choosing next area");
|
||||||
const current = self.current_area.?;
|
const current = self.current_area.?;
|
||||||
var next_area = @ptrToInt(current) + current.size + @sizeOf(@typeOf(current));
|
var next_area = @ptrToInt(current) + current.size + @sizeOf(@typeOf(current));
|
||||||
if (next_area >= self.info.mmap_addr + self.info.mmap_length) {
|
if (next_area >= self.info.mmap_addr + self.info.mmap_length) {
|
||||||
self.current_area = null;
|
self.current_area = null;
|
||||||
} else {
|
} else {
|
||||||
format_multibootentry(self.current_area.?);
|
|
||||||
self.current_area = @intToPtr(*MultibootMMapEntry, next_area);
|
self.current_area = @intToPtr(*MultibootMMapEntry, next_area);
|
||||||
format_multibootentry(self.current_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 PAGE_SIZE = 4096;
|
||||||
|
|
||||||
pub const physFrame = struct {
|
pub const PhysFrame = struct {
|
||||||
number: u64,
|
number: u32,
|
||||||
|
|
||||||
pub fn from_addr(addr: u64) physFrame {
|
pub fn from_addr(addr: u32) PhysFrame {
|
||||||
return physFrame{ .number = @divTrunc(addr, PAGE_SIZE) };
|
return PhysFrame{ .number = @divTrunc(addr, PAGE_SIZE) };
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add(self: physFrame, count: u64) physFrame {
|
pub fn add(self: PhysFrame, count: u32) PhysFrame {
|
||||||
return physFrame{ .number = self.number + count };
|
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);
|
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 {
|
pub fn initialize() void {
|
||||||
vga.clear();
|
// vga.clear();
|
||||||
// vga.writeString("> ");
|
|
||||||
interrupt.registerIRQ(1, ps2.keyboard_handler);
|
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
|
// arch independant initialization
|
||||||
export fn kmain(magic: u32, info: *const MultibootInfo) noreturn {
|
export fn kmain(magic: u32, info: *const MultibootInfo) noreturn {
|
||||||
assert(magic == MULTIBOOT_BOOTLOADER_MAGIC);
|
assert(magic == MULTIBOOT_BOOTLOADER_MAGIC);
|
||||||
console.initialize();
|
|
||||||
|
|
||||||
printf("--- hello x86_main ---\n");
|
|
||||||
|
|
||||||
|
println("--- x86 initialization ---");
|
||||||
x86.x86_main(info);
|
x86.x86_main(info);
|
||||||
|
|
||||||
// pagefault_test(0xfeffc000);
|
// 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 {
|
fn pagefault_test(addr: u32) void {
|
||||||
|
|
|
||||||
|
|
@ -13,29 +13,46 @@ pub const MULTIBOOT_BOOTLOADER_MAGIC = 0x2BADB002;
|
||||||
pub const MULTIBOOT_INFO_MEMORY = 0x00000001;
|
pub const MULTIBOOT_INFO_MEMORY = 0x00000001;
|
||||||
// Is there a full memory map?
|
// Is there a full memory map?
|
||||||
pub const MULTIBOOT_INFO_MEM_MAP = 0x00000040;
|
pub const MULTIBOOT_INFO_MEM_MAP = 0x00000040;
|
||||||
|
|
||||||
// System information structure passed by the bootloader.
|
// System information structure passed by the bootloader.
|
||||||
pub const MultibootInfo = packed struct {
|
pub const MultibootInfo = packed struct {
|
||||||
// Multiboot info version number.
|
// Multiboot info version number.
|
||||||
flags: u32,
|
flags: u32,
|
||||||
|
|
||||||
// Available memory from BIOS.
|
// Available memory from BIOS.
|
||||||
|
// present if flags[0]
|
||||||
mem_lower: u32,
|
mem_lower: u32,
|
||||||
mem_upper: u32,
|
mem_upper: u32,
|
||||||
|
|
||||||
// "root" partition.
|
// present if flags[1]
|
||||||
boot_device: u32,
|
boot_device: u32,
|
||||||
|
|
||||||
// Kernel command line.
|
// present if flags[2]
|
||||||
cmdline: u32,
|
cmdline: u32,
|
||||||
|
|
||||||
// Boot-Module list.
|
// Boot-Module list.
|
||||||
mods_count: u32,
|
mods_count: u32,
|
||||||
mods_addr: u32,
|
mods_addr: u32,
|
||||||
|
|
||||||
// TODO: use the real types here.
|
syms: extern union {
|
||||||
u: u128,
|
// 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.
|
// Memory Mapping buffer.
|
||||||
|
// present if flags[6]
|
||||||
mmap_length: u32,
|
mmap_length: u32,
|
||||||
mmap_addr: u32,
|
mmap_addr: u32,
|
||||||
|
|
||||||
|
|
@ -112,16 +129,22 @@ const MultibootHeader = packed struct {
|
||||||
magic: u32, // Must be equal to header magic number.
|
magic: u32, // Must be equal to header magic number.
|
||||||
flags: u32, // Feature flags.
|
flags: u32, // Feature flags.
|
||||||
checksum: u32, // Above fields plus this one must equal 0 mod 2^32.
|
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.
|
// NOTE: this structure is incomplete.
|
||||||
|
|
||||||
// Place the header at the very beginning of the binary.
|
// Place the header at the very beginning of the binary.
|
||||||
export const multiboot_header align(4) linksection(".multiboot") = multiboot: {
|
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 at 4k
|
||||||
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 CMDLINE = u32(1 << 2); // Receive a cmdline from the bootloader
|
const ADDR = u32(1 << 16); // Load specific addr
|
||||||
const FLAGS = ALIGN | MEMINFO | CMDLINE; // Combine the flags.
|
const FLAGS = ALIGN | MEMINFO; // Combine the flags.
|
||||||
|
|
||||||
break :multiboot MultibootHeader {
|
break :multiboot MultibootHeader {
|
||||||
.magic = MAGIC,
|
.magic = MAGIC,
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ const arch = @import("arch/x86/lib/index.zig");
|
||||||
|
|
||||||
const PCI_CONFIG_ADDRESS = 0xCF8;
|
const PCI_CONFIG_ADDRESS = 0xCF8;
|
||||||
const PCI_CONFIG_DATA = 0xCFC;
|
const PCI_CONFIG_DATA = 0xCFC;
|
||||||
const vga = @import("vga.zig");
|
usingnamespace @import("vga.zig");
|
||||||
|
|
||||||
pub const PciAddress = packed struct {
|
pub const PciAddress = packed struct {
|
||||||
offset: u8,
|
offset: u8,
|
||||||
|
|
@ -57,7 +57,7 @@ pub const PciDevice = struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn format(self: PciDevice) void {
|
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 {
|
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 x86 = @import("arch/x86/lib/index.zig");
|
||||||
const console = @import("console.zig");
|
const console = @import("console.zig");
|
||||||
|
|
||||||
|
|
@ -84,6 +85,7 @@ fn key_isrelease(scancode: u8) bool {
|
||||||
pub fn keyboard_handler() void {
|
pub fn keyboard_handler() void {
|
||||||
const scancode = ps2_scancode();
|
const scancode = ps2_scancode();
|
||||||
const isrelease = key_isrelease(scancode);
|
const isrelease = key_isrelease(scancode);
|
||||||
|
println("keyboard scancode 0b{b}", scancode);
|
||||||
if (isrelease) {
|
if (isrelease) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -56,10 +56,14 @@ pub fn disableCursor() void {
|
||||||
}
|
}
|
||||||
|
|
||||||
const Errors = error{};
|
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);
|
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 {
|
fn printCallback(context: void, string: []const u8) Errors!void {
|
||||||
vga.writeString(string);
|
vga.writeString(string);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue