diff --git a/build.zig b/build.zig index 5cc7d1a..2ec1a56 100644 --- a/build.zig +++ b/build.zig @@ -1,4 +1,7 @@ const Builder = @import("std").build.Builder; +const Target = @import("std").Target; +const CrossTarget = @import("std").zig.CrossTarget; +const Feature = @import("std").Target.Cpu.Feature; const builtin = @import("builtin"); const std = @import("std"); @@ -6,6 +9,7 @@ pub fn build(b: *Builder) void { const kernel = b.addExecutable("kernel", "src/main.zig"); kernel.addPackagePath("kernel", "src/index.zig"); kernel.addPackagePath("x86", "src/arch/x86/index.zig"); + kernel.setOutputDir("build"); kernel.addAssemblyFile("src/arch/x86/start.s"); @@ -14,18 +18,28 @@ pub fn build(b: *Builder) void { kernel.addAssemblyFile("src/arch/x86/paging.s"); kernel.addAssemblyFile("src/arch/x86/switch_tasks.s"); + // const features = Target.x86.Feature; + + // var disabled_features = Feature.Set.empty; + // var enabled_features = Feature.Set.empty; + + // disabled_features.addFeature(@enumToInt(features.mmx)); + // disabled_features.addFeature(@enumToInt(features.sse)); + // disabled_features.addFeature(@enumToInt(features.sse2)); + // disabled_features.addFeature(@enumToInt(features.avx)); + // disabled_features.addFeature(@enumToInt(features.avx2)); + // enabled_features.addFeature(@enumToInt(features.soft_float)); + + const target = CrossTarget{ + .cpu_arch = Target.Cpu.Arch.i386, + .os_tag = Target.Os.Tag.freestanding, + .abi = Target.Abi.none, + // .cpu_features_sub = disabled_features, + // .cpu_features_add = enabled_features + }; + + kernel.setTarget(target); kernel.setBuildMode(b.standardReleaseOptions()); - kernel.setTheTarget(std.Target{ - .Cross = std.Target.Cross{ - .arch = std.Target.Arch.i386, - .os = std.Target.Os.freestanding, - .abi = std.Target.Abi.none, - .cpu_features = std.Target.CpuFeatures.initFromCpu( - builtin.Arch.i386, - &builtin.Target.x86.cpu._i686, - ), - }, - }); - kernel.setLinkerScriptPath("src/arch/x86/linker.ld"); + kernel.setLinkerScriptPath(.{ .path = "src/arch/x86/linker.ld" }); b.default_step.dependOn(&kernel.step); } diff --git a/src/arch/x86/idt.zig b/src/arch/x86/idt.zig index e644040..c3229d2 100644 --- a/src/arch/x86/idt.zig +++ b/src/arch/x86/idt.zig @@ -1,7 +1,7 @@ // https://wiki.osdev.org/IDT -// usingnamespace @import("kernel"); -// usingnamespace @import("x86"); -usingnamespace @import("index.zig"); + +const kernel = @import("kernel"); +const x86 = @import("x86"); // Types of gates. pub const INTERRUPT_GATE = 0x8E; @@ -38,51 +38,52 @@ const IDTRegister = packed struct { // flags: Type and attributes. // offset: Address of the ISR. // -pub fn setGate(n: u8, flags: u8, offset: extern fn () void) void { - const intOffset = @ptrToInt(offset); +pub fn setGate(n: u8, flags: u8, offset: anytype) void { + const intOffset = @ptrToInt(&offset); + // const intOffset = offset; idt_table[n].offset_low = @truncate(u16, intOffset); idt_table[n].offset_high = @truncate(u16, intOffset >> 16); idt_table[n].flags = flags; idt_table[n].zero = 0; - idt_table[n].selector = gdt.KERNEL_CODE; + idt_table[n].selector = x86.gdt.KERNEL_CODE; } // Initialize the Interrupt Descriptor Table. pub fn initialize() void { // configure PIC - interrupt.remapPIC(); - interrupt.configPIT(); + x86.interrupt.remapPIC(); + x86.interrupt.configPIT(); // install ISRs - isr.install_exceptions(); - isr.install_irqs(); - isr.install_syscalls(); - interrupt.registerIRQ(0, kernel.time.increment); - interrupt.registerIRQ(1, kernel.ps2.keyboard_handler); - interrupt.register(1, debug_trap); - interrupt.register(13, general_protection_fault); - interrupt.register(14, page_fault); + x86.isr.install_exceptions(); + x86.isr.install_irqs(); + x86.isr.install_syscalls(); + x86.interrupt.registerIRQ(0, kernel.time.increment); + x86.interrupt.registerIRQ(1, kernel.ps2.keyboard_handler); + x86.interrupt.register(1, debug_trap); + x86.interrupt.register(13, general_protection_fault); + x86.interrupt.register(14, page_fault); // load IDT - lidt(@ptrToInt(&idtr)); + x86.instr.lidt(@ptrToInt(&idtr)); } fn general_protection_fault() void { kernel.println("general protection fault", .{}); - hang(); + x86.instr.hang(); } fn debug_trap() void { kernel.println("debug fault/trap", .{}); - kernel.println("dr7: 0b{b}", .{dr7()}); + kernel.println("dr7: 0b{b}", .{x86.instr.dr7()}); } fn page_fault() void { - const vaddr = cr2(); + const vaddr = x86.instr.cr2(); kernel.println("cr2: 0x{x}", .{vaddr}); - kernel.println("phy: 0x{x}", .{paging.translate(vaddr)}); - kernel.println("pde: 0x{x} ({})", .{ paging.pde(vaddr), vaddr >> 22 }); - kernel.println("pte: 0x{x} ({})", .{ paging.pte(vaddr), vaddr >> 12 }); + kernel.println("phy: 0x{x}", .{kernel.paging.translate(vaddr)}); + kernel.println("pde: 0x{x} ({})", .{ kernel.paging.pde(vaddr), vaddr >> 22 }); + kernel.println("pte: 0x{x} ({})", .{ kernel.paging.pte(vaddr), vaddr >> 12 }); // paging.format(); - hang(); + x86.instr.hang(); } diff --git a/src/arch/x86/index.zig b/src/arch/x86/index.zig index 73048a5..df9cbf5 100644 --- a/src/arch/x86/index.zig +++ b/src/arch/x86/index.zig @@ -5,8 +5,8 @@ pub const kernel = @import("../../index.zig"); // x86 namespace pub const PAGE_SIZE: usize = 4096; -pub usingnamespace @import("lib/io.zig"); -pub usingnamespace @import("lib/instructions.zig"); +pub const io = @import("lib/io.zig"); +pub const instr = @import("lib/instructions.zig"); pub usingnamespace @import("main.zig"); pub const pmem = @import("pmem.zig"); pub const paging = @import("paging.zig"); diff --git a/src/arch/x86/interrupt.zig b/src/arch/x86/interrupt.zig index 2515970..680a002 100644 --- a/src/arch/x86/interrupt.zig +++ b/src/arch/x86/interrupt.zig @@ -1,4 +1,6 @@ -usingnamespace @import("index.zig"); +const std = @import("std"); +const kernel = @import("kernel"); +const x86 = @import("x86"); // PIC ports. const PIC1_CMD = 0x20; @@ -28,37 +30,37 @@ const IRQ_15 = IRQ_0 + 15; // Interrupt Vector offsets of syscalls. const SYSCALL = 128; -// Registered interrupt handlers. (see isr.s) +// Registered interrupt handlers. (see x86.isr.s) var handlers = [_]fn () void{unhandled} ** 48; -// Registered IRQ subscribers. (see isr.s) +// Registered IRQ subscribers. (see x86.isr.s) // var irq_subscribers = []MailboxId{MailboxId.Kernel} ** 16; fn unhandled() noreturn { - const n = isr.context.interrupt_n; - kernel.print("unhandled interrupt number {d}", .{n}); - if (n < IRQ_0) kernel.println(" (exception)", .{}); - if (n >= IRQ_0) kernel.println(" (IRQ number {d})", .{n - IRQ_0}); - hang(); + const n = x86.isr.context.interrupt_n; + kernel.vga.print("unhandled interrupt number {d}", .{n}); + if (n < IRQ_0) kernel.vga.println(" (exception)", .{}); + if (n >= IRQ_0) kernel.vga.println(" (IRQ number {d})", .{n - IRQ_0}); + x86.instr.hang(); } inline fn picwait() void { - outb(WAIT_PORT, 0); + x86.io.outb(WAIT_PORT, 0); } //// // Call the correct handler based on the interrupt number. // export fn interruptDispatch() void { - const n = @intCast(u8, isr.context.interrupt_n); + const n = @intCast(u8, x86.isr.context.interrupt_n); switch (n) { // Exceptions. EXCEPTION_0...EXCEPTION_31 => { - kernel.println("", .{}); - kernel.println("num: {}", .{n}); - kernel.println("err: {}", .{@truncate(u8, isr.context.error_code)}); - kernel.println("ip: 0x{x}", .{@truncate(u16, isr.context.eip)}); - kernel.println("ip: 0x{x}", .{@truncate(u16, isr.context.eip >> 16)}); + kernel.vga.println("", .{}); + kernel.vga.println("num: {}", .{n}); + kernel.vga.println("err: {}", .{@truncate(u8, x86.isr.context.error_code)}); + kernel.vga.println("ip: 0x{x}", .{@truncate(u16, x86.isr.context.eip)}); + kernel.vga.println("ip: 0x{x}", .{@truncate(u16, x86.isr.context.eip >> 16)}); return handlers[n](); }, @@ -74,7 +76,7 @@ export fn interruptDispatch() void { // Syscalls. // SYSCALL => { - // const syscall_n = isr.context.registers.eax; + // const syscall_n = x86.isr.context.registers.eax; // if (syscall_n < syscall.handlers.len) { // syscall.handlers[syscall_n](); // } else { @@ -98,8 +100,8 @@ inline fn spuriousIRQ(irq: u8) bool { // TODO: handle spurious IRQ15. // Read the value of the In-Service Register. - outb(PIC1_CMD, ISR_READ); - const in_service = inb(PIC1_CMD); + x86.io.outb(PIC1_CMD, ISR_READ); + const in_service = x86.io.inb(PIC1_CMD); // Verify whether IRQ7 is set in the ISR. return (in_service & (1 << 7)) == 0; @@ -109,11 +111,11 @@ inline fn startOfInterrupt(irq: u8) void { // mask the irq and then ACK if (irq >= 8) { maskIRQ(irq, true); - outb(PIC1_CMD, ACK); - outb(PIC2_CMD, ACK); + x86.io.outb(PIC1_CMD, ACK); + x86.io.outb(PIC2_CMD, ACK); } else { maskIRQ(irq, true); - outb(PIC1_CMD, ACK); + x86.io.outb(PIC1_CMD, ACK); } } @@ -121,10 +123,10 @@ inline fn endOfInterrupt(irq: u8) void { // unmask the irq and then ACK if (irq >= 8) { maskIRQ(irq, false); - outb(PIC2_CMD, ACK); + x86.io.outb(PIC2_CMD, ACK); } else { maskIRQ(irq, false); - outb(PIC1_CMD, ACK); + x86.io.outb(PIC1_CMD, ACK); } } @@ -139,33 +141,33 @@ pub fn registerIRQ(irq: u8, handler: fn () void) void { pub fn remapPIC() void { // ICW1: start initialization sequence. - outb(PIC1_CMD, ICW1_INIT | ICW1_ICW4); + x86.io.outb(PIC1_CMD, ICW1_INIT | ICW1_ICW4); picwait(); - outb(PIC2_CMD, ICW1_INIT | ICW1_ICW4); + x86.io.outb(PIC2_CMD, ICW1_INIT | ICW1_ICW4); picwait(); // ICW2: Interrupt Vector offsets of IRQs. - outb(PIC1_DATA, IRQ_0); // IRQ 0..7 -> Interrupt 32..39 + x86.io.outb(PIC1_DATA, IRQ_0); // IRQ 0..7 -> Interrupt 32..39 picwait(); - outb(PIC2_DATA, IRQ_0 + 8); // IRQ 8..15 -> Interrupt 40..47 + x86.io.outb(PIC2_DATA, IRQ_0 + 8); // IRQ 8..15 -> Interrupt 40..47 picwait(); // ICW3: IRQ line 2 to connect master to slave PIC. - outb(PIC1_DATA, 1 << 2); + x86.io.outb(PIC1_DATA, 1 << 2); picwait(); - outb(PIC2_DATA, 2); + x86.io.outb(PIC2_DATA, 2); picwait(); // ICW4: 80x86 mode. - outb(PIC1_DATA, ICW4_8086); + x86.io.outb(PIC1_DATA, ICW4_8086); picwait(); - outb(PIC2_DATA, ICW4_8086); + x86.io.outb(PIC2_DATA, ICW4_8086); picwait(); // Mask all IRQs. - outb(PIC1_DATA, 0xFF); + x86.io.outb(PIC1_DATA, 0xFF); picwait(); - outb(PIC2_DATA, 0xFF); + x86.io.outb(PIC2_DATA, 0xFF); picwait(); } @@ -173,15 +175,16 @@ pub fn maskIRQ(irq: u8, comptime mask: bool) void { if (irq > 15) return; // Figure out if master or slave PIC owns the IRQ. const port = @as(u16, if (irq < 8) PIC1_DATA else PIC2_DATA); - const old = inb(port); // Retrieve the current mask. + const old = x86.io.inb(port); // Retrieve the current mask. // Mask or unmask the interrupt. const shift = @truncate(u3, irq % 8); // const shift = @truncate(u3, if (irq < 8) irq else irq - 8); const bit = @as(u8, 1) << shift; - if (mask) outb(port, old | bit); - if (!mask) outb(port, old & ~bit); - const new = inb(port); // Retrieve the current mask. + if (mask) x86.io.outb(port, old | bit); + if (!mask) x86.io.outb(port, old & ~bit); + // TODO uncomment + // const new = x86.io.inb(port); // Retrieve the current mask. } // configures the chan0 with a rate generator, which will trigger irq0 @@ -189,10 +192,11 @@ pub const divisor = 2685; pub const tick = 2251; // f = 1.193182 MHz, TODO: turn into a function pub fn configPIT() void { const chanNum = 0; - const chan = PIT_CHAN0; + // const chan = PIT_CHAN0; const LOHI = 0b11; // bit4 | bit5 const PITMODE_RATE_GEN = 0x2; - outb(PIT_CMD, chanNum << 6 | LOHI << 4 | PITMODE_RATE_GEN << 1); - outb(PIT_CHAN0, divisor & 0xff); - outb(PIT_CHAN0, divisor >> 8); + + x86.io.outb(PIT_CMD, chanNum << 6 | LOHI << 4 | PITMODE_RATE_GEN << 1); + x86.io.outb(PIT_CHAN0, divisor & 0xff); + x86.io.outb(PIT_CHAN0, divisor >> 8); } diff --git a/src/arch/x86/isr.zig b/src/arch/x86/isr.zig index d2df8b6..1036dd2 100644 --- a/src/arch/x86/isr.zig +++ b/src/arch/x86/isr.zig @@ -1,4 +1,4 @@ -usingnamespace @import("index.zig"); +const idt = @import("idt.zig"); // Interrupt Service Routines defined externally in assembly. extern fn isr0() void; @@ -65,9 +65,9 @@ pub const Context = packed struct { esp: u32, ss: u32, - pub inline fn setReturnValue(self: *volatile Context, value: var) void { - self.registers.eax = if (@TypeOf(value) == bool) @boolToInt(value) else @intCast(u32, value); - } + // pub inline fn setReturnValue(self: *volatile Context, value: var) void { + // self.registers.eax = if (@TypeOf(value) == bool) @boolToInt(value) else @intCast(u32, value); + // } }; // Structure holding general purpose registers as saved by PUSHA. diff --git a/src/arch/x86/lib/instructions.zig b/src/arch/x86/lib/instructions.zig index 1a638f5..97cc125 100644 --- a/src/arch/x86/lib/instructions.zig +++ b/src/arch/x86/lib/instructions.zig @@ -1,7 +1,7 @@ pub inline fn ltr(desc: u16) void { asm volatile ("ltr %[desc]" : - : [desc] "r" (desc) + : [desc] "r" (desc), ); } @@ -30,18 +30,18 @@ pub inline fn int3() void { pub inline fn lidt(idtr: usize) void { asm volatile ("lidt (%[idtr])" : - : [idtr] "r" (idtr) + : [idtr] "r" (idtr), ); } pub fn cr2() usize { return asm volatile ("movl %%cr2, %[result]" - : [result] "=r" (-> usize) + : [result] "=r" (-> usize), ); } pub fn dr7() usize { return asm volatile ("movl %%dr7, %[result]" - : [result] "=r" (-> usize) + : [result] "=r" (-> usize), ); } diff --git a/src/arch/x86/lib/io.zig b/src/arch/x86/lib/io.zig index a6283b4..45de365 100644 --- a/src/arch/x86/lib/io.zig +++ b/src/arch/x86/lib/io.zig @@ -2,32 +2,32 @@ usingnamespace @import("../index.zig"); pub inline fn inb(port: u16) u8 { return asm volatile ("inb %[port], %[result]" - : [result] "={al}" (-> u8) - : [port] "N{dx}" (port) + : [result] "={al}" (-> u8), + : [port] "N{dx}" (port), ); } pub inline fn inw(port: u16) u16 { return asm volatile ("inw %[port], %[result]" - : [result] "={ax}" (-> u16) - : [port] "N{dx}" (port) + : [result] "={ax}" (-> u16), + : [port] "N{dx}" (port), ); } pub inline fn inl(port: u16) u32 { return asm volatile ("inl %[port], %[result]" - : [result] "={eax}" (-> u32) - : [port] "N{dx}" (port) + : [result] "={eax}" (-> u32), + : [port] "N{dx}" (port), ); } -pub inline fn insl(port: u16, addr: var, cnt: usize) void { +pub inline fn insl(port: u16, addr: anytype, cnt: usize) void { asm volatile ("cld; repne; insl;" : [addr] "={edi}" (addr), - [cnt] "={ecx}" (cnt) + [cnt] "={ecx}" (cnt), : [port] "{dx}" (port), [addr] "0" (addr), - [cnt] "1" (cnt) + [cnt] "1" (cnt), : "memory", "cc" ); } @@ -36,7 +36,7 @@ pub inline fn outb(port: u16, value: u8) void { asm volatile ("outb %[value], %[port]" : : [value] "{al}" (value), - [port] "N{dx}" (port) + [port] "N{dx}" (port), ); } @@ -44,7 +44,7 @@ pub inline fn outw(port: u16, value: u16) void { asm volatile ("outw %[value], %[port]" : : [value] "{ax}" (value), - [port] "N{dx}" (port) + [port] "N{dx}" (port), ); } @@ -52,6 +52,6 @@ pub inline fn outl(port: u16, value: u32) void { asm volatile ("outl %[value], %[port]" : : [value] "{eax}" (value), - [port] "N{dx}" (port) + [port] "N{dx}" (port), ); } diff --git a/src/arch/x86/main.zig b/src/arch/x86/main.zig index 09b1fb4..d72461d 100644 --- a/src/arch/x86/main.zig +++ b/src/arch/x86/main.zig @@ -1,10 +1,12 @@ -usingnamespace @import("index.zig"); +const std = @import("std"); +const kernel = @import("kernel"); +const x86 = @import("x86"); /// x86 specific intialization pub fn x86_main(info: *const kernel.multiboot.MultibootInfo) void { - gdt.initialize(); - idt.initialize(); - pmem.initialize(info); - paging.initialize(); - sti(); + x86.gdt.initialize(); + x86.idt.initialize(); + x86.pmem.initialize(info); + x86.paging.initialize(); + x86.instr.sti(); } diff --git a/src/arch/x86/paging.zig b/src/arch/x86/paging.zig index aefc4fc..2a5e5d2 100644 --- a/src/arch/x86/paging.zig +++ b/src/arch/x86/paging.zig @@ -1,4 +1,6 @@ -usingnamespace @import("index.zig"); +const std = @import("std"); +const kernel = @import("kernel"); +const x86 = @import("x86"); extern fn setupPaging(phys_pd: usize) void; @@ -17,7 +19,7 @@ pub var pageDirectory: [1024]PageEntry align(4096) linksection(".bss") = [_]Page // TODO: inline these fn pageBase(virt: usize) usize { - return virt & (~PAGE_SIZE +% 1); + return virt & (~x86.PAGE_SIZE +% 1); } pub fn pde(virt: usize) *PageEntry { return &PD[virt >> 22]; //relies on recursive mapping @@ -34,18 +36,18 @@ pub fn translate(virt: usize) ?usize { pub fn unmap(virt: usize) void { if (translate(virt)) |phys| { - pmem.free(phys); + x86.pmem.free(phys); } else { - kernel.println("can't unmap 0x{x} because it is not mapped.", .{virt}); + kernel.vga.println("can't unmap 0x{x} because it is not mapped.", .{virt}); } } pub fn mmap(virt: usize, phys: ?usize) !void { //TODO: support hugepages // allocate a page directory if there is none - if (pde(virt).* == 0) pde(virt).* = (try pmem.allocate()) | WRITE | PRESENT; + if (pde(virt).* == 0) pde(virt).* = (try x86.pmem.allocate()) | WRITE | PRESENT; // allocate a frame if phys isn't specified - pte(virt).* = (if (phys) |p| p else try pmem.allocate()) | PRESENT; + pte(virt).* = (if (phys) |p| p else try x86.pmem.allocate()) | PRESENT; } pub fn initialize() void { @@ -57,7 +59,7 @@ pub fn initialize() void { p2[1023] = @ptrToInt(&p2[0]) | PRESENT | WRITE; // TODO: verify is this a hack? - assert(pmem.stack_end < kernel.layout.IDENTITY); + std.debug.assert(x86.pmem.stack_end < kernel.layout.IDENTITY); setupPaging(@ptrToInt(&pageDirectory[0])); //asm routine } @@ -67,12 +69,12 @@ pub fn format() void { i = 0; while (i < 1024) : (i += 1) { if (PD[i] == 0) continue; - kernel.println("p2[{}] -> 0x{x}", .{ i, PD[i] }); + kernel.vga.println("p2[{}] -> 0x{x}", .{ i, PD[i] }); if (PD[i] & HUGE != 0) continue; var j: usize = 0; while (j < 1024) : (j += 1) { var entry: PageEntry = PT[i * 1024 + j]; - if (entry != 0) kernel.println("p2[{}]p1[{}] -> 0x{x}", .{ i, j, entry }); + if (entry != 0) kernel.vga.println("p2[{}]p1[{}] -> 0x{x}", .{ i, j, entry }); } } } diff --git a/src/arch/x86/pmem.zig b/src/arch/x86/pmem.zig index 40f46e7..29eba2c 100644 --- a/src/arch/x86/pmem.zig +++ b/src/arch/x86/pmem.zig @@ -1,4 +1,6 @@ -usingnamespace @import("index.zig"); +const std = @import("std"); +const kernel = @import("kernel"); +const x86 = @import("x86"); var stack: [*]usize = undefined; // Stack of free physical page. var stack_index: usize = 0; // Index into the stack. @@ -11,13 +13,13 @@ pub inline fn pageAlign(address: u32) u32 { // 4095 -> 4096 // 4096 -> 4096 // 4097 -> 8192 - return (address + PAGE_SIZE - 1) & (~PAGE_SIZE +% 1); + return (address + x86.PAGE_SIZE - 1) & (~x86.PAGE_SIZE +% 1); } // Return the amount of variable elements (in bytes). // pub fn available() usize { - return stack_index * PAGE_SIZE; + return stack_index * x86.PAGE_SIZE; } pub inline fn available_MiB() usize { @@ -52,8 +54,8 @@ pub fn free(address: usize) void { // pub fn initialize(info: *const kernel.multiboot.MultibootInfo) void { // Ensure the bootloader has given us the memory map. - assert((info.flags & kernel.multiboot.MULTIBOOT_INFO_MEMORY) != 0); - assert((info.flags & kernel.multiboot.MULTIBOOT_INFO_MEM_MAP) != 0); + std.debug.assert((info.flags & kernel.multiboot.MULTIBOOT_INFO_MEMORY) != 0); + std.debug.assert((info.flags & kernel.multiboot.MULTIBOOT_INFO_MEM_MAP) != 0); // TODO: WHAT WHY WHAAAAT, must check back here later // Place stack at 0x200000 so that in the future I trigger a @@ -64,7 +66,7 @@ pub fn initialize(info: *const kernel.multiboot.MultibootInfo) void { // stack = @intToPtr([*]usize, pageAlign(info.mods_addr)); // Calculate the approximate size of the stack based on the amount of total upper memory. - stack_size = ((info.mem_upper * 1024) / PAGE_SIZE) * @sizeOf(usize); + stack_size = ((info.mem_upper * 1024) / x86.PAGE_SIZE) * @sizeOf(usize); stack_end = pageAlign(@ptrToInt(stack) + stack_size); var map: usize = info.mmap_addr; @@ -78,17 +80,16 @@ pub fn initialize(info: *const kernel.multiboot.MultibootInfo) void { start = if (start >= stack_end) start else stack_end; // Flag all the pages in this memory area as free. - if (entry.type == kernel.multiboot.MULTIBOOT_MEMORY_AVAILABLE) while (start < end) : (start += PAGE_SIZE) + if (entry.type == kernel.multiboot.MULTIBOOT_MEMORY_AVAILABLE) while (start < end) : (start += x86.PAGE_SIZE) free(start); // Go to the next entry in the memory map. map += entry.size + @sizeOf(@TypeOf(entry.size)); } - const a = available(); - kernel.println("available memory: {d} MiB ", .{available() / 1024 / 1024}); + kernel.vga.println("available memory: {d} MiB ", .{available() / 1024 / 1024}); } pub fn format() void { - kernel.println("physframes left: {d} ({d} MiB)", .{ stack_index, available_MiB() }); + kernel.vga.println("physframes left: {d} ({d} MiB)", .{ stack_index, available_MiB() }); } diff --git a/src/delta_queue.zig b/src/delta_queue.zig index f19a924..763b409 100644 --- a/src/delta_queue.zig +++ b/src/delta_queue.zig @@ -1,4 +1,5 @@ const std = @import("std"); +const Allocator = std.mem.Allocator; /// DeltaQueue is a singly-linked list where each /// node has a counter. Each counter is relative diff --git a/src/index.zig b/src/index.zig index 9430853..c9bf802 100644 --- a/src/index.zig +++ b/src/index.zig @@ -1,24 +1,25 @@ -pub usingnamespace @import("common.zig"); -pub usingnamespace @import("delta_queue.zig"); -pub usingnamespace @import("ring_buffer.zig"); -pub usingnamespace @import("vga.zig"); +// pub usingnamespace @import("common.zig"); +// pub usingnamespace @import("delta_queue.zig"); +// pub usingnamespace @import("ring_buffer.zig"); -///drivers -pub const driver = @import("driver/index.zig"); +pub const vga = @import("vga.zig"); -///arch +//drivers +// pub const driver = @import("driver/index.zig"); + +//arch pub const x86 = @import("arch/x86/index.zig"); -///core +//core pub const constants = @import("constants.zig"); pub const layout = @import("layout.zig"); pub const multiboot = @import("multiboot.zig"); pub const vmem = @import("vmem.zig"); -pub const task = @import("task.zig"); +// pub const task = @import("task.zig"); pub const time = @import("time.zig"); -///extra -pub const console = @import("console.zig"); -pub const bio = @import("bio.zig"); -pub const pci = @import("pci/pci.zig"); -pub const ps2 = @import("ps2.zig"); +//extra +// pub const console = @import("console.zig"); +// pub const bio = @import("bio.zig"); +// pub const pci = @import("pci/pci.zig"); +// pub const ps2 = @import("ps2.zig"); diff --git a/src/main.zig b/src/main.zig index 4e0bf91..c155009 100644 --- a/src/main.zig +++ b/src/main.zig @@ -1,14 +1,16 @@ -usingnamespace @import("kernel"); +const std = @import("std"); +const builtin = std.builtin; +const kernel = @import("index.zig"); // Place the header at the very beginning of the binary. export const multiboot_header align(4) linksection(".multiboot") = multiboot: { const MAGIC = @as(u32, 0x1BADB002); // multiboot magic const ALIGN = @as(u32, 1 << 0); // Align loaded modules at 4k const MEMINFO = @as(u32, 1 << 1); // Receive a memory map from the bootloader. - const ADDR = @as(u32, 1 << 16); // Load specific addr + // const ADDR = @as(u32, 1 << 16); // Load specific addr const FLAGS = ALIGN | MEMINFO; // Combine the flags. - break :multiboot multiboot.MultibootHeader{ + break :multiboot kernel.multiboot.MultibootHeader{ .magic = MAGIC, .flags = FLAGS, .checksum = ~(MAGIC +% FLAGS) +% 1, @@ -16,32 +18,32 @@ export const multiboot_header align(4) linksection(".multiboot") = multiboot: { }; // arch independant initialization -export fn kmain(magic: u32, info: *const multiboot.MultibootInfo) noreturn { - assert(magic == multiboot.MULTIBOOT_BOOTLOADER_MAGIC); - clear(); - println("--- x86 initialization ---", .{}); - x86.x86_main(info); - println("--- core initialization ---", .{}); - vmem.init(); - pci.scan(); - println("--- finished booting --- ", .{}); +export fn kmain(magic: u32, info: *const kernel.multiboot.MultibootInfo) noreturn { + std.debug.assert(magic == kernel.multiboot.MULTIBOOT_BOOTLOADER_MAGIC); + kernel.vga.clear(); + kernel.vga.println("--- x86 initialization ---", .{}); + kernel.x86.x86_main(info); + kernel.vga.println("--- core initialization ---", .{}); + kernel.vmem.init(); + kernel.pci.scan(); + kernel.vga.println("--- finished booting --- ", .{}); - task.cleaner_task = task.new(@ptrToInt(task.cleaner_loop)) catch unreachable; - _ = task.new(@ptrToInt(topbar)) catch unreachable; - _ = task.new(@ptrToInt(console.loop)) catch unreachable; + // kernel.task.cleaner_task = kernel.task.new(@ptrToInt(kernel.task.cleaner_loop)) catch unreachable; + // _ = kernel.task.new(@ptrToInt(kernel.vga.topbar)) catch unreachable; + // _ = kernel.task.new(@ptrToInt(kernel.console.loop)) catch unreachable; - var buf = vmem.allocator.create([512]u8) catch unreachable; - println("buf at 0x{x}", .{@ptrToInt(buf)}); - driver.ide.first_ide_drive.read(2, buf); + // var buf = kernel.vmem.allocator.create([512]u8) catch unreachable; + // kernel.vga.println("buf at 0x{x}", .{@ptrToInt(buf)}); + // kernel.driver.ide.first_ide_drive.read(2, buf); - const sig = buf[56..58]; - println("sig: {x}", .{sig}); + // const sig = buf[56..58]; + // kernel.vga.println("sig: {x}", .{sig}); - task.terminate(); + // kernel.task.terminate(); } -pub fn panic(a: []const u8, b: ?*builtin.StackTrace) noreturn { - println("{}", .{a}); - println("{}", .{b}); - while (true) asm volatile ("hlt"); -} +// pub fn panic(a: []const u8, b: ?*builtin.StackTrace) noreturn { +// kernel.vga.println("{}", .{a}); +// kernel.vga.println("{}", .{b}); +// while (true) asm volatile ("hlt"); +// } diff --git a/src/multiboot.zig b/src/multiboot.zig index cdb38d1..e8fea23 100644 --- a/src/multiboot.zig +++ b/src/multiboot.zig @@ -29,16 +29,16 @@ pub const MultibootInfo = packed struct { mods_count: u32, mods_addr: u32, - syms: extern union { + syms: packed union { // present if flags[4] - nlist: extern struct { + nlist: packed struct { tabsize: u32, strsize: u32, addr: u32, _reserved: u32, }, // present if flags[5] - shdr: extern struct { + shdr: packed struct { num: u32, size: u32, addr: u32, @@ -124,7 +124,7 @@ pub const MultibootModule = packed struct { }; // Multiboot structure to be read by the bootloader. -pub const MultibootHeader = packed struct { +pub const MultibootHeader = extern 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. diff --git a/src/time.zig b/src/time.zig index 546bf20..464a66e 100644 --- a/src/time.zig +++ b/src/time.zig @@ -1,4 +1,5 @@ -usingnamespace @import("index.zig"); +const kernel = @import("index.zig"); +const x86 = @import("x86"); pub var offset_us: u64 = 0; pub var task_slice_remaining: u64 = 0; @@ -8,14 +9,14 @@ pub fn increment() void { offset_us += tick; //global time counter - var should_preempt = task.wakeup_tick(tick); + var should_preempt = kernel.task.wakeup_tick(tick); if (task_slice_remaining != 0) { // There is a time slice length if (task_slice_remaining <= tick) should_preempt = true; if (task_slice_remaining > tick) task_slice_remaining -= tick; } - if (should_preempt) task.preempt(); + if (should_preempt) kernel.task.preempt(); } pub fn uptime() void { @@ -23,9 +24,9 @@ pub fn uptime() void { const offset_s: u64 = offset_ms / 1000; offset_ms = @mod(offset_ms / 100, 10); - print("{}.{:.3}", .{ offset_s, offset_ms }); + kernel.vga.print("{}.{:.3}", .{ offset_s, offset_ms }); } pub fn utilisation() void { - print("{}%", .{100 * (offset_us - task.CPU_idle_time) / offset_us}); + kernel.vga.print("{}%", .{100 * (offset_us - kernel.task.CPU_idle_time) / offset_us}); } diff --git a/src/vga.zig b/src/vga.zig index 7e17dd0..c80d8f1 100644 --- a/src/vga.zig +++ b/src/vga.zig @@ -1,7 +1,6 @@ -usingnamespace @import("index.zig"); -// const time = @import("time.zig"); -// const x86 = @import("arch/x86/index.zig"); -// const std = @import("std"); +const std = @import("std"); +const kernel = @import("index.zig"); + // Screen size. pub const VGA_WIDTH = 80; pub const VGA_HEIGHT = 25; @@ -42,23 +41,26 @@ pub const VGAEntry = packed struct { // Enable hardware cursor. pub fn enableCursor() void { - outb(0x3D4, 0x0A); - outb(0x3D5, 0x00); + kernel.x86.io.outb(0x3D4, 0x0A); + kernel.x86.io.outb(0x3D5, 0x00); } // Disable hardware cursor. pub fn disableCursor() void { - outb(0x3D4, 0x0A); - outb(0x3D5, 1 << 5); + kernel.x86.io.outb(0x3D4, 0x0A); + kernel.x86.io.outb(0x3D5, 1 << 5); } const Errors = error{}; -pub fn print(comptime format: []const u8, args: var) void { - var a = std.fmt.format({}, Errors, printCallback, format, args); +pub fn print(comptime format: []const u8, args: anytype) void { + try std.fmt.format(.{ .writeAll = printCallback }, format, args); } -pub fn println(comptime format: []const u8, args: var) void { - var a = print(format ++ "\n", args); + +pub fn println(comptime format: []const u8, args: anytype) void { + print(format ++ "\n", args); } + +// const time = @import("time.zig"); pub fn clear() void { vga.clear(); } @@ -73,11 +75,11 @@ pub fn topbar() void { vga.cursor = 0; vga.cursor_enabled = false; - time.uptime(); + kernel.time.uptime(); print(" | ", .{}); - time.utilisation(); + kernel.time.utilisation(); print(" | ", .{}); - task.format_short(); + kernel.task.format_short(); println("", .{}); vga.cursor_enabled = true; @@ -85,11 +87,11 @@ pub fn topbar() void { vga.background = bg; vga.foreground = fg; - task.usleep(50 * 1000) catch unreachable; // 60ms + kernel.task.usleep(50 * 1000) catch unreachable; // 60ms } } -fn printCallback(context: void, string: []const u8) Errors!void { +fn printCallback(string: []const u8) Errors!void { vga.writeString(string); } @@ -182,10 +184,10 @@ const VGA = struct { // Use the software cursor as the source of truth. // pub fn updateCursor(self: *const VGA) void { - x86.outb(0x3D4, 0x0F); - x86.outb(0x3D5, @truncate(u8, self.cursor)); - x86.outb(0x3D4, 0x0E); - x86.outb(0x3D5, @truncate(u8, self.cursor >> 8)); + kernel.x86.io.outb(0x3D4, 0x0F); + kernel.x86.io.outb(0x3D5, @truncate(u8, self.cursor)); + kernel.x86.io.outb(0x3D4, 0x0E); + kernel.x86.io.outb(0x3D5, @truncate(u8, self.cursor >> 8)); } //// @@ -195,11 +197,11 @@ const VGA = struct { pub fn fetchCursor(self: *VGA) void { var cursor: usize = 0; - x86.outb(0x3D4, 0x0E); - cursor |= usize(x86.inb(0x3D5)) << 8; + kernel.x86.io.outb(0x3D4, 0x0E); + cursor |= usize(kernel.x86.io.inb(0x3D5)) << 8; - x86.outb(0x3D4, 0x0F); - cursor |= x86.inb(0x3D5); + kernel.x86.outb(0x3D4, 0x0F); + cursor |= kernel.x86.io.inb(0x3D5); self.cursor = cursor; } diff --git a/src/vmem.zig b/src/vmem.zig index 7c88612..c5a30ca 100644 --- a/src/vmem.zig +++ b/src/vmem.zig @@ -1,4 +1,7 @@ -pub usingnamespace @import("index.zig"); +const std = @import("std"); +const kernel = @import("kernel"); +const x86 = @import("x86"); + pub var allocator: std.mem.Allocator = undefined; // TODO: make a better memory allocator @@ -7,7 +10,7 @@ pub var allocator: std.mem.Allocator = undefined; // - no defragmentation // - no allocation bigger than a page -const stack_size: usize = (layout.HEAP_END - layout.HEAP) / x86.PAGE_SIZE; +const stack_size: usize = (kernel.layout.HEAP_END - kernel.layout.HEAP) / kernel.x86.PAGE_SIZE; var stack_index: usize = 0; // Index into the stack. var stack: [stack_size]usize = undefined; // Stack of free virtual addresses @@ -32,7 +35,7 @@ fn realloc( ) ![]u8 { if (old_mem.len == 0) { // new allocation - assert(new_byte_count < x86.PAGE_SIZE); // this allocator only support 1:1 mapping + std.debug.assert(new_byte_count < x86.PAGE_SIZE); // this allocator only support 1:1 mapping if (available() == 0) return error.OutOfMemory; stack_index -= 1; var vaddr: usize = stack[stack_index]; @@ -44,7 +47,7 @@ fn realloc( dealloc(@ptrToInt(&old_mem[0])); return &[_]u8{}; } - println("vmem: unsupported allocator operation", .{}); + kernel.vga.println("vmem: unsupported allocator operation", .{}); x86.hang(); // return undefined; } @@ -62,7 +65,7 @@ fn shrink( return &[_]u8{}; } - println("vmem doesn't support shrinking, {}, {}, {}, {}", .{ + kernel.vga.println("vmem doesn't support shrinking, {}, {}, {}, {}", .{ old_mem, old_alignment, new_byte_count, @@ -77,8 +80,8 @@ pub fn init() void { .reallocFn = realloc, .shrinkFn = shrink, }; - var addr: usize = layout.HEAP; - while (addr < layout.HEAP_END) : (addr += x86.PAGE_SIZE) { + var addr: usize = kernel.layout.HEAP; + while (addr < kernel.layout.HEAP_END) : (addr += x86.PAGE_SIZE) { stack[stack_index] = addr; stack_index += 1; }