towards 0.10.1

This commit is contained in:
Jack Halford 2023-08-06 15:38:23 +02:00
parent e392799b91
commit 08d447115d
No known key found for this signature in database
GPG key ID: A427D956E8E67679
17 changed files with 239 additions and 205 deletions

View file

@ -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);
}

View file

@ -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();
}

View file

@ -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");

View file

@ -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);
}

View file

@ -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.

View file

@ -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),
);
}

View file

@ -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),
);
}

View file

@ -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();
}

View file

@ -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 });
}
}
}

View file

@ -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() });
}

View file

@ -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

View file

@ -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");

View file

@ -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");
// }

View file

@ -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.

View file

@ -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});
}

View file

@ -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;
}

View file

@ -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;
}