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