aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBobby <[email protected]>2026-02-25 10:13:24 +0530
committerBobby <[email protected]>2026-02-25 10:13:24 +0530
commita51c50b236f4480bc5eed76a7c78ebb14f8710ef (patch)
treeed429b05d3f076107b74131493cec9e6c69d1862
parent15f9ee5984f97bdca1b75a4f732c4a503ee504dc (diff)
downloadakiba-a51c50b236f4480bc5eed76a7c78ebb14f8710ef.tar.xz
akiba-a51c50b236f4480bc5eed76a7c78ebb14f8710ef.zip
Add Global Descriptor Table (GDT) and Task State Segment (TSS) implementation
- Introduced GDT constants, including selectors, access rights, and flags. - Created GDT entry structures for kernel and user segments, along with TSS descriptors. - Implemented GDT initialization and loading functions. - Developed boot sequence phases for CPU and memory initialization. - Added boot information structure to manage memory regions and kernel details. - Implemented TSS management, including core-specific TSS setup and stack allocation. - Established state management for boot sequence phases and TSS.
-rw-r--r--mirai/asm/asm.zig1
-rw-r--r--mirai/asm/gdt/gdt.zig19
-rw-r--r--mirai/asm/gdt/lgdt.zig24
-rw-r--r--mirai/asm/gdt/segments.zig83
-rw-r--r--mirai/boot/boot.zig5
-rw-r--r--mirai/boot/gdt/constants/access.zig19
-rw-r--r--mirai/boot/gdt/constants/constants.zig5
-rw-r--r--mirai/boot/gdt/constants/flags.zig15
-rw-r--r--mirai/boot/gdt/constants/selectors.zig21
-rw-r--r--mirai/boot/gdt/entries/entries.zig13
-rw-r--r--mirai/boot/gdt/entries/kernel.zig26
-rw-r--r--mirai/boot/gdt/entries/tss.zig23
-rw-r--r--mirai/boot/gdt/entries/user.zig26
-rw-r--r--mirai/boot/gdt/gdt.zig39
-rw-r--r--mirai/boot/gdt/load/load.zig23
-rw-r--r--mirai/boot/gdt/state.zig41
-rw-r--r--mirai/boot/gdt/types/entry.zig55
-rw-r--r--mirai/boot/gdt/types/gdtr.zig16
-rw-r--r--mirai/boot/gdt/types/table.zig36
-rw-r--r--mirai/boot/gdt/types/tss_descriptor.zig43
-rw-r--r--mirai/boot/gdt/types/types.zig11
-rw-r--r--mirai/boot/sequence/constants/constants.zig7
-rw-r--r--mirai/boot/sequence/constants/phases.zig33
-rw-r--r--mirai/boot/sequence/message/message.zig12
-rw-r--r--mirai/boot/sequence/message/print.zig15
-rw-r--r--mirai/boot/sequence/phases/cpu.zig17
-rw-r--r--mirai/boot/sequence/phases/memory.zig60
-rw-r--r--mirai/boot/sequence/phases/phases.zig7
-rw-r--r--mirai/boot/sequence/sequence.zig64
-rw-r--r--mirai/boot/sequence/state.zig58
-rw-r--r--mirai/boot/sequence/types/boot_info.zig44
-rw-r--r--mirai/boot/sequence/types/types.zig5
-rw-r--r--mirai/boot/tss/constants/constants.zig13
-rw-r--r--mirai/boot/tss/constants/limits.zig15
-rw-r--r--mirai/boot/tss/init/init.zig6
-rw-r--r--mirai/boot/tss/init/setup.zig32
-rw-r--r--mirai/boot/tss/stacks/allocate.zig38
-rw-r--r--mirai/boot/tss/stacks/stacks.zig7
-rw-r--r--mirai/boot/tss/state.zig51
-rw-r--r--mirai/boot/tss/tss.zig60
-rw-r--r--mirai/boot/tss/types/core_tss.zig53
-rw-r--r--mirai/boot/tss/types/tss.zig71
-rw-r--r--mirai/boot/tss/types/types.zig8
-rw-r--r--mirai/drivers/serial/serial.zig5
-rw-r--r--mirai/drivers/serial/write.zig121
-rw-r--r--mirai/kagami/types/kagami.zig4
46 files changed, 1301 insertions, 49 deletions
diff --git a/mirai/asm/asm.zig b/mirai/asm/asm.zig
index e6d1f24..520ea9e 100644
--- a/mirai/asm/asm.zig
+++ b/mirai/asm/asm.zig
@@ -2,3 +2,4 @@
pub const cpu = @import("cpu/cpu.zig");
pub const io = @import("io/io.zig");
+pub const gdt = @import("gdt/gdt.zig");
diff --git a/mirai/asm/gdt/gdt.zig b/mirai/asm/gdt/gdt.zig
new file mode 100644
index 0000000..e7a1639
--- /dev/null
+++ b/mirai/asm/gdt/gdt.zig
@@ -0,0 +1,19 @@
+//! GDT Assembly Operations
+
+pub const lgdt_ops = @import("lgdt.zig");
+pub const segments = @import("segments.zig");
+
+pub const Gdtr = lgdt_ops.Gdtr;
+pub const lgdt = lgdt_ops.lgdt;
+pub const sgdt = lgdt_ops.sgdt;
+
+pub const reload_code_segment = segments.reload_code_segment;
+pub const reload_data_segments = segments.reload_data_segments;
+pub const load_tss = segments.load_tss;
+
+pub const get_cs = segments.get_cs;
+pub const get_ds = segments.get_ds;
+pub const get_ss = segments.get_ss;
+pub const get_es = segments.get_es;
+pub const get_fs = segments.get_fs;
+pub const get_gs = segments.get_gs;
diff --git a/mirai/asm/gdt/lgdt.zig b/mirai/asm/gdt/lgdt.zig
new file mode 100644
index 0000000..457a8aa
--- /dev/null
+++ b/mirai/asm/gdt/lgdt.zig
@@ -0,0 +1,24 @@
+//! GDT Load Instructions
+
+pub const Gdtr = packed struct {
+ limit: u16,
+ base: u64,
+};
+
+pub fn lgdt(gdtr: *const Gdtr) void {
+ asm volatile ("lgdt (%[gdtr])"
+ :
+ : [gdtr] "r" (gdtr),
+ : .{ .memory = true }
+ );
+}
+
+pub fn sgdt() Gdtr {
+ var gdtr: Gdtr = undefined;
+ asm volatile ("sgdt (%[gdtr])"
+ :
+ : [gdtr] "r" (&gdtr),
+ : .{ .memory = true }
+ );
+ return gdtr;
+}
diff --git a/mirai/asm/gdt/segments.zig b/mirai/asm/gdt/segments.zig
new file mode 100644
index 0000000..ab2a26a
--- /dev/null
+++ b/mirai/asm/gdt/segments.zig
@@ -0,0 +1,83 @@
+//! Segment Register Operations
+
+pub fn reload_code_segment(code_selector: u16) void {
+ asm volatile (
+ \\push %[code_sel]
+ \\lea 1f(%%rip), %%rax
+ \\push %%rax
+ \\lretq
+ \\1:
+ :
+ : [code_sel] "r" (@as(u64, code_selector)),
+ : .{ .rax = true, .memory = true }
+ );
+}
+
+pub fn reload_data_segments(data_selector: u16) void {
+ asm volatile (
+ \\mov %[data_sel], %%ax
+ \\mov %%ax, %%ds
+ \\mov %%ax, %%es
+ \\mov %%ax, %%fs
+ \\mov %%ax, %%gs
+ \\mov %%ax, %%ss
+ :
+ : [data_sel] "r" (data_selector),
+ : .{ .rax = true, .memory = true }
+ );
+}
+
+pub fn load_tss(tss_selector: u16) void {
+ asm volatile ("ltr %[sel]"
+ :
+ : [sel] "r" (tss_selector),
+ );
+}
+
+pub fn get_cs() u16 {
+ var cs: u16 = undefined;
+ asm volatile ("mov %%cs, %[cs]"
+ : [cs] "=r" (cs),
+ );
+ return cs;
+}
+
+pub fn get_ds() u16 {
+ var ds: u16 = undefined;
+ asm volatile ("mov %%ds, %[ds]"
+ : [ds] "=r" (ds),
+ );
+ return ds;
+}
+
+pub fn get_ss() u16 {
+ var ss: u16 = undefined;
+ asm volatile ("mov %%ss, %[ss]"
+ : [ss] "=r" (ss),
+ );
+ return ss;
+}
+
+pub fn get_es() u16 {
+ var es: u16 = undefined;
+ asm volatile ("mov %%es, %[es]"
+ : [es] "=r" (es),
+ );
+ return es;
+}
+
+pub fn get_fs() u16 {
+ var fs: u16 = undefined;
+ asm volatile ("mov %%fs, %[fs]"
+ : [fs] "=r" (fs),
+ );
+ return fs;
+}
+
+pub fn get_gs() u16 {
+ var gs: u16 = undefined;
+ asm volatile ("mov %%gs, %[gs]"
+ : [gs] "=r" (gs),
+ );
+ return gs;
+}
diff --git a/mirai/boot/boot.zig b/mirai/boot/boot.zig
new file mode 100644
index 0000000..0fc6a0f
--- /dev/null
+++ b/mirai/boot/boot.zig
@@ -0,0 +1,5 @@
+//! Boot Module
+
+pub const gdt = @import("gdt/gdt.zig");
+pub const tss = @import("tss/tss.zig");
+pub const sequence = @import("sequence/sequence.zig");
diff --git a/mirai/boot/gdt/constants/access.zig b/mirai/boot/gdt/constants/access.zig
new file mode 100644
index 0000000..c5ad670
--- /dev/null
+++ b/mirai/boot/gdt/constants/access.zig
@@ -0,0 +1,19 @@
+//! GDT Access Flag Constants
+
+pub const accessed: u8 = 1 << 0;
+pub const read_write: u8 = 1 << 1;
+pub const direction_conforming: u8 = 1 << 2;
+pub const executable: u8 = 1 << 3;
+pub const descriptor_type: u8 = 1 << 4;
+pub const dpl_ring_1: u8 = 1 << 5;
+pub const dpl_ring_2: u8 = 2 << 5;
+pub const dpl_ring_3: u8 = 3 << 5;
+pub const present: u8 = 1 << 7;
+
+pub const kernel_code_access: u8 = present | descriptor_type | executable | read_write;
+pub const kernel_data_access: u8 = present | descriptor_type | read_write;
+pub const user_code_access: u8 = present | dpl_ring_3 | descriptor_type | executable | read_write;
+pub const user_data_access: u8 = present | dpl_ring_3 | descriptor_type | read_write;
+
+pub const tss_access: u8 = present | 0x09;
+pub const tss_access_busy: u8 = present | 0x0B;
diff --git a/mirai/boot/gdt/constants/constants.zig b/mirai/boot/gdt/constants/constants.zig
new file mode 100644
index 0000000..87723ed
--- /dev/null
+++ b/mirai/boot/gdt/constants/constants.zig
@@ -0,0 +1,5 @@
+//! GDT Constants
+
+pub const selectors = @import("selectors.zig");
+pub const access = @import("access.zig");
+pub const flags = @import("flags.zig");
diff --git a/mirai/boot/gdt/constants/flags.zig b/mirai/boot/gdt/constants/flags.zig
new file mode 100644
index 0000000..4a8f9de
--- /dev/null
+++ b/mirai/boot/gdt/constants/flags.zig
@@ -0,0 +1,15 @@
+//! GDT Flags Constants
+
+pub const granularity_byte: u4 = 0;
+pub const granularity_page: u4 = 1 << 3;
+
+pub const size_16bit: u4 = 0;
+pub const size_32bit: u4 = 1 << 2;
+
+pub const long_mode_code: u4 = 1 << 1;
+
+pub const kernel_code_flags: u4 = granularity_page | long_mode_code;
+pub const kernel_data_flags: u4 = granularity_page | size_32bit;
+pub const user_code_flags: u4 = granularity_page | long_mode_code;
+pub const user_data_flags: u4 = granularity_page | size_32bit;
+pub const tss_flags: u4 = 0;
diff --git a/mirai/boot/gdt/constants/selectors.zig b/mirai/boot/gdt/constants/selectors.zig
new file mode 100644
index 0000000..5163e93
--- /dev/null
+++ b/mirai/boot/gdt/constants/selectors.zig
@@ -0,0 +1,21 @@
+//! GDT Selector Constants
+
+pub const null_selector: u16 = 0x00;
+pub const kernel_code_selector: u16 = 0x08;
+pub const kernel_data_selector: u16 = 0x10;
+pub const user_code_selector: u16 = 0x18;
+pub const user_data_selector: u16 = 0x20;
+pub const tss_selector: u16 = 0x28;
+
+pub const kernel_code_index: u16 = 1;
+pub const kernel_data_index: u16 = 2;
+pub const user_code_index: u16 = 3;
+pub const user_data_index: u16 = 4;
+pub const tss_index: u16 = 5;
+
+pub const ring_0: u8 = 0;
+pub const ring_3: u8 = 3;
+
+pub fn selector_with_rpl(selector: u16, rpl: u8) u16 {
+ return (selector & 0xFFF8) | @as(u16, rpl & 0x03);
+}
diff --git a/mirai/boot/gdt/entries/entries.zig b/mirai/boot/gdt/entries/entries.zig
new file mode 100644
index 0000000..8fd7cf6
--- /dev/null
+++ b/mirai/boot/gdt/entries/entries.zig
@@ -0,0 +1,13 @@
+//! GDT Entries
+
+pub const kernel = @import("kernel.zig");
+pub const user = @import("user.zig");
+pub const tss = @import("tss.zig");
+
+pub const create_kernel_code = kernel.create_kernel_code;
+pub const create_kernel_data = kernel.create_kernel_data;
+pub const create_user_code = user.create_user_code;
+pub const create_user_data = user.create_user_data;
+pub const create_tss_descriptor = tss.create_tss_descriptor;
+pub const mark_tss_busy = tss.mark_tss_busy;
+pub const mark_tss_available = tss.mark_tss_available;
diff --git a/mirai/boot/gdt/entries/kernel.zig b/mirai/boot/gdt/entries/kernel.zig
new file mode 100644
index 0000000..92b61d8
--- /dev/null
+++ b/mirai/boot/gdt/entries/kernel.zig
@@ -0,0 +1,26 @@
+//! Kernel GDT Entries
+
+const types = @import("../types/types.zig");
+const constants = @import("../constants/constants.zig");
+
+const Entry = types.Entry;
+const access = constants.access;
+const flags = constants.flags;
+
+pub fn create_kernel_code() Entry {
+ return Entry.init(
+ 0,
+ 0xFFFFF,
+ access.kernel_code_access,
+ flags.kernel_code_flags,
+ );
+}
+
+pub fn create_kernel_data() Entry {
+ return Entry.init(
+ 0,
+ 0xFFFFF,
+ access.kernel_data_access,
+ flags.kernel_data_flags,
+ );
+}
diff --git a/mirai/boot/gdt/entries/tss.zig b/mirai/boot/gdt/entries/tss.zig
new file mode 100644
index 0000000..ac4eba6
--- /dev/null
+++ b/mirai/boot/gdt/entries/tss.zig
@@ -0,0 +1,23 @@
+//! TSS GDT Entry
+
+const types = @import("../types/types.zig");
+const constants = @import("../constants/constants.zig");
+
+const TssDescriptor = types.TssDescriptor;
+const access = constants.access;
+
+pub fn create_tss_descriptor(tss_address: u64, tss_size: u20) TssDescriptor {
+ return TssDescriptor.init(
+ tss_address,
+ tss_size,
+ access.tss_access,
+ );
+}
+
+pub fn mark_tss_busy(descriptor: *TssDescriptor) void {
+ descriptor.access = access.tss_access_busy;
+}
+
+pub fn mark_tss_available(descriptor: *TssDescriptor) void {
+ descriptor.access = access.tss_access;
+}
diff --git a/mirai/boot/gdt/entries/user.zig b/mirai/boot/gdt/entries/user.zig
new file mode 100644
index 0000000..4dea6cf
--- /dev/null
+++ b/mirai/boot/gdt/entries/user.zig
@@ -0,0 +1,26 @@
+//! User GDT Entries
+
+const types = @import("../types/types.zig");
+const constants = @import("../constants/constants.zig");
+
+const Entry = types.Entry;
+const access = constants.access;
+const flags = constants.flags;
+
+pub fn create_user_code() Entry {
+ return Entry.init(
+ 0,
+ 0xFFFFF,
+ access.user_code_access,
+ flags.user_code_flags,
+ );
+}
+
+pub fn create_user_data() Entry {
+ return Entry.init(
+ 0,
+ 0xFFFFF,
+ access.user_data_access,
+ flags.user_data_flags,
+ );
+}
diff --git a/mirai/boot/gdt/gdt.zig b/mirai/boot/gdt/gdt.zig
new file mode 100644
index 0000000..6adb9c2
--- /dev/null
+++ b/mirai/boot/gdt/gdt.zig
@@ -0,0 +1,39 @@
+//! Global Descriptor Table
+
+pub const constants = @import("constants/constants.zig");
+pub const types = @import("types/types.zig");
+pub const entries = @import("entries/entries.zig");
+pub const load = @import("load/load.zig");
+pub const state = @import("state.zig");
+
+pub const Entry = types.Entry;
+pub const TssDescriptor = types.TssDescriptor;
+pub const Gdtr = types.Gdtr;
+pub const Table = types.Table;
+
+pub const selectors = constants.selectors;
+
+pub fn initialize(tss_address: u64, tss_size: u20) void {
+ state.setup_entries(tss_address, tss_size);
+
+ const gdtr = state.get_gdtr();
+ load.lgdt(&gdtr);
+
+ load.reload_segments();
+
+ load.load_tss(selectors.tss_selector);
+
+ state.set_initialized();
+}
+
+pub fn is_initialized() bool {
+ return state.is_initialized();
+}
+
+pub fn get_table() *Table {
+ return state.get_table();
+}
+
+pub fn update_tss(tss_address: u64, tss_size: u20) void {
+ state.update_tss(tss_address, tss_size);
+}
diff --git a/mirai/boot/gdt/load/load.zig b/mirai/boot/gdt/load/load.zig
new file mode 100644
index 0000000..dfcfe00
--- /dev/null
+++ b/mirai/boot/gdt/load/load.zig
@@ -0,0 +1,23 @@
+//! GDT Load Operations
+
+const asm_gdt = @import("../../../asm/gdt/gdt.zig");
+const constants = @import("../constants/constants.zig");
+
+const selectors = constants.selectors;
+
+pub const Gdtr = asm_gdt.Gdtr;
+pub const lgdt = asm_gdt.lgdt;
+pub const sgdt = asm_gdt.sgdt;
+
+pub fn reload_segments() void {
+ asm_gdt.reload_code_segment(selectors.kernel_code_selector);
+ asm_gdt.reload_data_segments(selectors.kernel_data_selector);
+}
+
+pub const reload_code_segment = asm_gdt.reload_code_segment;
+pub const reload_data_segments = asm_gdt.reload_data_segments;
+pub const load_tss = asm_gdt.load_tss;
+
+pub const get_cs = asm_gdt.get_cs;
+pub const get_ds = asm_gdt.get_ds;
+pub const get_ss = asm_gdt.get_ss;
diff --git a/mirai/boot/gdt/state.zig b/mirai/boot/gdt/state.zig
new file mode 100644
index 0000000..92219d8
--- /dev/null
+++ b/mirai/boot/gdt/state.zig
@@ -0,0 +1,41 @@
+//! GDT State
+
+const types = @import("types/types.zig");
+const entries = @import("entries/entries.zig");
+
+const Table = types.Table;
+const Entry = types.Entry;
+const TssDescriptor = types.TssDescriptor;
+const Gdtr = types.Gdtr;
+
+var global_gdt: Table = undefined;
+var initialized: bool = false;
+
+pub fn get_table() *Table {
+ return &global_gdt;
+}
+
+pub fn get_gdtr() Gdtr {
+ return global_gdt.get_gdtr();
+}
+
+pub fn is_initialized() bool {
+ return initialized;
+}
+
+pub fn set_initialized() void {
+ initialized = true;
+}
+
+pub fn setup_entries(tss_address: u64, tss_size: u20) void {
+ global_gdt.null = Entry.null_entry();
+ global_gdt.kernel_code = entries.create_kernel_code();
+ global_gdt.kernel_data = entries.create_kernel_data();
+ global_gdt.user_code = entries.create_user_code();
+ global_gdt.user_data = entries.create_user_data();
+ global_gdt.tss = entries.create_tss_descriptor(tss_address, tss_size);
+}
+
+pub fn update_tss(tss_address: u64, tss_size: u20) void {
+ global_gdt.tss = entries.create_tss_descriptor(tss_address, tss_size);
+}
diff --git a/mirai/boot/gdt/types/entry.zig b/mirai/boot/gdt/types/entry.zig
new file mode 100644
index 0000000..c8e1798
--- /dev/null
+++ b/mirai/boot/gdt/types/entry.zig
@@ -0,0 +1,55 @@
+//! GDT Entry Type
+
+pub const Entry = packed struct {
+ limit_low: u16,
+ base_low: u16,
+ base_middle: u8,
+ access: u8,
+ limit_high_and_flags: u8,
+ base_high: u8,
+
+ pub fn init(base: u32, limit: u20, access_byte: u8, flags_nibble: u4) Entry {
+ return Entry{
+ .limit_low = @truncate(limit),
+ .base_low = @truncate(base),
+ .base_middle = @truncate(base >> 16),
+ .access = access_byte,
+ .limit_high_and_flags = @as(u8, flags_nibble) << 4 | @as(u8, @truncate(limit >> 16)),
+ .base_high = @truncate(base >> 24),
+ };
+ }
+
+ pub fn null_entry() Entry {
+ return Entry{
+ .limit_low = 0,
+ .base_low = 0,
+ .base_middle = 0,
+ .access = 0,
+ .limit_high_and_flags = 0,
+ .base_high = 0,
+ };
+ }
+
+ pub fn get_base(self: Entry) u32 {
+ return @as(u32, self.base_high) << 24 |
+ @as(u32, self.base_middle) << 16 |
+ @as(u32, self.base_low);
+ }
+
+ pub fn get_limit(self: Entry) u20 {
+ return @as(u20, @truncate(self.limit_high_and_flags & 0x0F)) << 16 |
+ @as(u20, self.limit_low);
+ }
+
+ pub fn get_flags(self: Entry) u4 {
+ return @truncate(self.limit_high_and_flags >> 4);
+ }
+
+ pub fn is_present(self: Entry) bool {
+ return (self.access & 0x80) != 0;
+ }
+
+ pub fn get_dpl(self: Entry) u2 {
+ return @truncate((self.access >> 5) & 0x03);
+ }
+};
diff --git a/mirai/boot/gdt/types/gdtr.zig b/mirai/boot/gdt/types/gdtr.zig
new file mode 100644
index 0000000..ab23a75
--- /dev/null
+++ b/mirai/boot/gdt/types/gdtr.zig
@@ -0,0 +1,16 @@
+//! GDT Register Type
+
+const asm_gdt = @import("../../../asm/gdt/gdt.zig");
+
+pub const Gdtr = asm_gdt.Gdtr;
+
+pub fn create(base_address: u64, num_entries: u16) Gdtr {
+ return Gdtr{
+ .limit = (num_entries * 8) - 1,
+ .base = base_address,
+ };
+}
+
+pub fn get_entry_count(gdtr: Gdtr) u16 {
+ return (gdtr.limit + 1) / 8;
+}
diff --git a/mirai/boot/gdt/types/table.zig b/mirai/boot/gdt/types/table.zig
new file mode 100644
index 0000000..5b6cc99
--- /dev/null
+++ b/mirai/boot/gdt/types/table.zig
@@ -0,0 +1,36 @@
+//! GDT Table Type
+
+const Entry = @import("entry.zig").Entry;
+const TssDescriptor = @import("tss_descriptor.zig").TssDescriptor;
+const Gdtr = @import("gdtr.zig").Gdtr;
+
+pub const Table = extern struct {
+ null: Entry,
+ kernel_code: Entry,
+ kernel_data: Entry,
+ user_code: Entry,
+ user_data: Entry,
+ tss: TssDescriptor,
+
+ pub fn get_gdtr(self: *Table) Gdtr {
+ const base = @intFromPtr(self);
+ const size = @sizeOf(Table);
+ return Gdtr{
+ .limit = size - 1,
+ .base = base,
+ };
+ }
+
+ pub fn get_entry(self: *Table, index: u16) ?*Entry {
+ const entries: [*]Entry = @ptrCast(self);
+ const max_entries = @sizeOf(Table) / @sizeOf(Entry);
+ if (index >= max_entries) {
+ return null;
+ }
+ return &entries[index];
+ }
+
+ pub fn get_tss_descriptor(self: *Table) *TssDescriptor {
+ return &self.tss;
+ }
+};
diff --git a/mirai/boot/gdt/types/tss_descriptor.zig b/mirai/boot/gdt/types/tss_descriptor.zig
new file mode 100644
index 0000000..960446c
--- /dev/null
+++ b/mirai/boot/gdt/types/tss_descriptor.zig
@@ -0,0 +1,43 @@
+//! TSS Descriptor Type (16 bytes in Long Mode)
+
+const Entry = @import("entry.zig").Entry;
+
+pub const TssDescriptor = packed struct {
+ limit_low: u16,
+ base_low: u16,
+ base_middle_low: u8,
+ access: u8,
+ limit_high_and_flags: u8,
+ base_middle_high: u8,
+ base_high: u32,
+ reserved: u32,
+
+ pub fn init(base: u64, limit: u20, access_byte: u8) TssDescriptor {
+ return TssDescriptor{
+ .limit_low = @truncate(limit),
+ .base_low = @truncate(base),
+ .base_middle_low = @truncate(base >> 16),
+ .access = access_byte,
+ .limit_high_and_flags = @truncate(limit >> 16),
+ .base_middle_high = @truncate(base >> 24),
+ .base_high = @truncate(base >> 32),
+ .reserved = 0,
+ };
+ }
+
+ pub fn get_base(self: TssDescriptor) u64 {
+ return @as(u64, self.base_high) << 32 |
+ @as(u64, self.base_middle_high) << 24 |
+ @as(u64, self.base_middle_low) << 16 |
+ @as(u64, self.base_low);
+ }
+
+ pub fn get_limit(self: TssDescriptor) u20 {
+ return @as(u20, @truncate(self.limit_high_and_flags & 0x0F)) << 16 |
+ @as(u20, self.limit_low);
+ }
+
+ pub fn as_entries(self: *TssDescriptor) *[2]Entry {
+ return @ptrCast(self);
+ }
+};
diff --git a/mirai/boot/gdt/types/types.zig b/mirai/boot/gdt/types/types.zig
new file mode 100644
index 0000000..b4e583b
--- /dev/null
+++ b/mirai/boot/gdt/types/types.zig
@@ -0,0 +1,11 @@
+//! GDT Types
+
+pub const entry = @import("entry.zig");
+pub const tss_descriptor = @import("tss_descriptor.zig");
+pub const gdtr = @import("gdtr.zig");
+pub const table = @import("table.zig");
+
+pub const Entry = entry.Entry;
+pub const TssDescriptor = tss_descriptor.TssDescriptor;
+pub const Gdtr = gdtr.Gdtr;
+pub const Table = table.Table;
diff --git a/mirai/boot/sequence/constants/constants.zig b/mirai/boot/sequence/constants/constants.zig
new file mode 100644
index 0000000..dc19129
--- /dev/null
+++ b/mirai/boot/sequence/constants/constants.zig
@@ -0,0 +1,7 @@
+//! Boot Sequence Constants
+
+pub const phases = @import("phases.zig");
+
+pub const Phase = phases.Phase;
+pub const phase_names = phases.phase_names;
+pub const get_phase_name = phases.get_phase_name;
diff --git a/mirai/boot/sequence/constants/phases.zig b/mirai/boot/sequence/constants/phases.zig
new file mode 100644
index 0000000..cce1129
--- /dev/null
+++ b/mirai/boot/sequence/constants/phases.zig
@@ -0,0 +1,33 @@
+//! Boot Phase Constants
+
+pub const Phase = enum(u8) {
+ cpu = 0,
+ memory = 1,
+ interrupts = 2,
+ multicore = 3,
+ world = 4,
+ drivers = 5,
+ filesystem = 6,
+ pulse = 7,
+ complete = 8,
+};
+
+pub const phase_names = [_][]const u8{
+ "CPU",
+ "Memory",
+ "Interrupts",
+ "Multicore",
+ "World",
+ "Drivers",
+ "Filesystem",
+ "Pulse",
+ "Complete",
+};
+
+pub fn get_phase_name(phase: Phase) []const u8 {
+ const index = @intFromEnum(phase);
+ if (index < phase_names.len) {
+ return phase_names[index];
+ }
+ return "Unknown";
+}
diff --git a/mirai/boot/sequence/message/message.zig b/mirai/boot/sequence/message/message.zig
new file mode 100644
index 0000000..a9c29c5
--- /dev/null
+++ b/mirai/boot/sequence/message/message.zig
@@ -0,0 +1,12 @@
+//! Boot Messages
+
+pub const print = @import("print.zig");
+
+pub const print_phase_start = print.print_phase_start;
+pub const print_phase_complete = print.print_phase_complete;
+pub const print_phase_error = print.print_phase_error;
+pub const print_status = print.print_status;
+pub const print_status_value = print.print_status_value;
+pub const print_status_hex = print.print_status_hex;
+pub const print_banner = print.print_banner;
+pub const print_boot_complete = print.print_boot_complete;
diff --git a/mirai/boot/sequence/message/print.zig b/mirai/boot/sequence/message/print.zig
new file mode 100644
index 0000000..9071557
--- /dev/null
+++ b/mirai/boot/sequence/message/print.zig
@@ -0,0 +1,15 @@
+//! Boot Messages
+
+const serial = @import("../../../drivers/serial/serial.zig");
+
+pub fn log(comptime fmt: []const u8, args: anytype) void {
+ serial.printf(fmt, args);
+}
+
+pub fn print_banner() void {
+ serial.printf("\n", .{});
+ serial.printf("+-----------------------+\n", .{});
+ serial.printf("| A K I B A |\n", .{});
+ serial.printf("+-----------------------+\n", .{});
+ serial.printf("\n", .{});
+}
diff --git a/mirai/boot/sequence/phases/cpu.zig b/mirai/boot/sequence/phases/cpu.zig
new file mode 100644
index 0000000..addf1fe
--- /dev/null
+++ b/mirai/boot/sequence/phases/cpu.zig
@@ -0,0 +1,17 @@
+//! CPU Phase
+
+const gdt = @import("../../gdt/gdt.zig");
+const tss = @import("../../tss/tss.zig");
+const tss_constants = @import("../../tss/constants/constants.zig");
+const serial = @import("../../../drivers/serial/serial.zig");
+
+pub fn execute() bool {
+ serial.printf("Setting up Task State Segment for CPU exceptions\n", .{});
+ tss.initialize_boot();
+
+ serial.printf("Setting up Global Descriptor Table with kernel and user segments\n", .{});
+ const tss_address = tss.get_boot_tss_address();
+ gdt.initialize(tss_address, tss_constants.tss_size);
+
+ return true;
+}
diff --git a/mirai/boot/sequence/phases/memory.zig b/mirai/boot/sequence/phases/memory.zig
new file mode 100644
index 0000000..3cd4152
--- /dev/null
+++ b/mirai/boot/sequence/phases/memory.zig
@@ -0,0 +1,60 @@
+//! Memory Phase
+
+const pmm = @import("../../../pmm/pmm.zig");
+const kagami = @import("../../../kagami/kagami.zig");
+const serial = @import("../../../drivers/serial/serial.zig");
+const types = @import("../types/types.zig");
+
+const BootInfo = types.BootInfo;
+
+pub fn execute(boot_info: *const BootInfo) bool {
+ serial.printf("Detecting physical memory from Hikari bootloader\n", .{});
+
+ const bitmap_location = find_bitmap_location(boot_info);
+ if (bitmap_location == 0) {
+ serial.printf(" Could not find suitable location for page bitmap\n", .{});
+ return false;
+ }
+
+ pmm.initialize(boot_info.memory_map, boot_info.memory_map_count, bitmap_location);
+
+ const stats = pmm.get_statistics();
+ const total_mb = (stats.total_pages * 4096) / (1024 * 1024);
+ const free_mb = (stats.free_pages * 4096) / (1024 * 1024);
+
+ serial.printf(" Found %d pages (%d MB total)\n", .{ stats.total_pages, total_mb });
+ serial.printf(" Available: %d pages (%d MB)\n", .{ stats.free_pages, free_mb });
+
+ serial.printf("Setting up Kagami page table abstraction\n", .{});
+ kagami.initialize(boot_info.pml4_physical);
+ serial.printf(" Using PML4 at physical address %x\n", .{boot_info.pml4_physical});
+
+ return true;
+}
+
+fn find_bitmap_location(boot_info: *const BootInfo) u64 {
+ const bitmap_size = pmm.constants.bitmap_size_bytes;
+ const required_pages = (bitmap_size + 4095) / 4096;
+
+ var index: u64 = 0;
+ while (index < boot_info.memory_map_count) : (index += 1) {
+ const region = boot_info.memory_map[index];
+
+ if (!region.is_usable()) continue;
+
+ if (region.base_address < 0x100000) continue;
+
+ if (region.base_address >= boot_info.kernel_physical_base and
+ region.base_address < boot_info.kernel_physical_end)
+ {
+ continue;
+ }
+
+ const region_pages = region.page_count();
+ if (region_pages >= required_pages) {
+ return region.base_address;
+ }
+ }
+
+ return 0;
+}
diff --git a/mirai/boot/sequence/phases/phases.zig b/mirai/boot/sequence/phases/phases.zig
new file mode 100644
index 0000000..2a09ed3
--- /dev/null
+++ b/mirai/boot/sequence/phases/phases.zig
@@ -0,0 +1,7 @@
+//! Boot Phases
+
+pub const cpu = @import("cpu.zig");
+pub const memory = @import("memory.zig");
+
+pub const execute_cpu = cpu.execute;
+pub const execute_memory = memory.execute;
diff --git a/mirai/boot/sequence/sequence.zig b/mirai/boot/sequence/sequence.zig
new file mode 100644
index 0000000..2500455
--- /dev/null
+++ b/mirai/boot/sequence/sequence.zig
@@ -0,0 +1,64 @@
+//! Boot Sequence
+
+const asm_cpu = @import("../../asm/cpu/cpu.zig");
+const serial = @import("../../drivers/serial/serial.zig");
+
+pub const constants = @import("constants/constants.zig");
+pub const types = @import("types/types.zig");
+pub const phases = @import("phases/phases.zig");
+pub const message = @import("message/message.zig");
+pub const state = @import("state.zig");
+
+pub const Phase = constants.Phase;
+pub const BootInfo = types.BootInfo;
+
+pub fn execute(boot_info: *const BootInfo) bool {
+ state.set_boot_info(boot_info);
+
+ if (!serial.initialize_default()) {
+ return false;
+ }
+
+ message.print_banner();
+
+ serial.printf("Starting Akiba boot sequence\n", .{});
+ serial.printf("Powered by the Mirai kernel\n\n", .{});
+
+ state.set_current_phase(Phase.cpu);
+ if (!phases.execute_cpu()) {
+ serial.printf("\nCPU initialization failed, cannot continue\n", .{});
+ return false;
+ }
+ state.advance_phase();
+
+ serial.printf("\n", .{});
+
+ state.set_current_phase(Phase.memory);
+ if (!phases.execute_memory(boot_info)) {
+ serial.printf("\nMemory initialization failed, cannot continue\n", .{});
+ return false;
+ }
+ state.advance_phase();
+
+ serial.printf("\nBoot sequence complete, Akiba is ready\n", .{});
+ state.set_current_phase(Phase.complete);
+
+ return true;
+}
+
+pub fn halt_on_failure() noreturn {
+ serial.printf("\nSystem halted due to unrecoverable error\n", .{});
+ asm_cpu.halt_loop();
+}
+
+pub fn get_current_phase() Phase {
+ return state.get_current_phase();
+}
+
+pub fn get_boot_info() ?*const BootInfo {
+ return state.get_boot_info();
+}
+
+pub fn is_complete() bool {
+ return state.is_complete();
+}
diff --git a/mirai/boot/sequence/state.zig b/mirai/boot/sequence/state.zig
new file mode 100644
index 0000000..5ea7c8a
--- /dev/null
+++ b/mirai/boot/sequence/state.zig
@@ -0,0 +1,58 @@
+//! Boot Sequence State
+
+const constants = @import("constants/constants.zig");
+const types = @import("types/types.zig");
+
+const Phase = constants.Phase;
+const BootInfo = types.BootInfo;
+
+var current_phase: Phase = Phase.cpu;
+var boot_info_ptr: ?*const BootInfo = null;
+var boot_failed: bool = false;
+var failure_phase: Phase = Phase.cpu;
+var failure_message: []const u8 = "";
+
+pub fn get_current_phase() Phase {
+ return current_phase;
+}
+
+pub fn set_current_phase(phase: Phase) void {
+ current_phase = phase;
+}
+
+pub fn advance_phase() void {
+ const next = @intFromEnum(current_phase) + 1;
+ if (next <= @intFromEnum(Phase.complete)) {
+ current_phase = @enumFromInt(next);
+ }
+}
+
+pub fn set_boot_info(info: *const BootInfo) void {
+ boot_info_ptr = info;
+}
+
+pub fn get_boot_info() ?*const BootInfo {
+ return boot_info_ptr;
+}
+
+pub fn set_failure(phase: Phase, message: []const u8) void {
+ boot_failed = true;
+ failure_phase = phase;
+ failure_message = message;
+}
+
+pub fn has_failed() bool {
+ return boot_failed;
+}
+
+pub fn get_failure_phase() Phase {
+ return failure_phase;
+}
+
+pub fn get_failure_message() []const u8 {
+ return failure_message;
+}
+
+pub fn is_complete() bool {
+ return current_phase == Phase.complete;
+}
diff --git a/mirai/boot/sequence/types/boot_info.zig b/mirai/boot/sequence/types/boot_info.zig
new file mode 100644
index 0000000..8d0c802
--- /dev/null
+++ b/mirai/boot/sequence/types/boot_info.zig
@@ -0,0 +1,44 @@
+//! Boot Information Type
+
+const pmm_types = @import("../../../pmm/types/types.zig");
+const MemoryRegion = pmm_types.MemoryRegion;
+
+pub const BootInfo = struct {
+ memory_map: [*]const MemoryRegion,
+ memory_map_count: u64,
+ framebuffer_address: u64,
+ framebuffer_width: u32,
+ framebuffer_height: u32,
+ framebuffer_pitch: u32,
+ framebuffer_bpp: u8,
+ kernel_physical_base: u64,
+ kernel_physical_end: u64,
+ kernel_virtual_base: u64,
+ pml4_physical: u64,
+ rsdp_address: u64,
+ boot_stack_top: u64,
+
+ pub fn total_memory(self: BootInfo) u64 {
+ var total: u64 = 0;
+ var index: u64 = 0;
+ while (index < self.memory_map_count) : (index += 1) {
+ total += self.memory_map[index].length;
+ }
+ return total;
+ }
+
+ pub fn usable_memory(self: BootInfo) u64 {
+ var usable: u64 = 0;
+ var index: u64 = 0;
+ while (index < self.memory_map_count) : (index += 1) {
+ if (self.memory_map[index].is_usable()) {
+ usable += self.memory_map[index].length;
+ }
+ }
+ return usable;
+ }
+
+ pub fn kernel_size(self: BootInfo) u64 {
+ return self.kernel_physical_end - self.kernel_physical_base;
+ }
+};
diff --git a/mirai/boot/sequence/types/types.zig b/mirai/boot/sequence/types/types.zig
new file mode 100644
index 0000000..1883cb8
--- /dev/null
+++ b/mirai/boot/sequence/types/types.zig
@@ -0,0 +1,5 @@
+//! Boot Sequence Types
+
+pub const boot_info = @import("boot_info.zig");
+
+pub const BootInfo = boot_info.BootInfo;
diff --git a/mirai/boot/tss/constants/constants.zig b/mirai/boot/tss/constants/constants.zig
new file mode 100644
index 0000000..2155572
--- /dev/null
+++ b/mirai/boot/tss/constants/constants.zig
@@ -0,0 +1,13 @@
+//! TSS Constants
+
+pub const limits = @import("limits.zig");
+
+pub const tss_size = limits.tss_size;
+pub const ist_count = limits.ist_count;
+pub const ist_double_fault = limits.ist_double_fault;
+pub const ist_nmi = limits.ist_nmi;
+pub const ist_machine_check = limits.ist_machine_check;
+pub const ist_debug = limits.ist_debug;
+pub const default_stack_size = limits.default_stack_size;
+pub const interrupt_stack_size = limits.interrupt_stack_size;
+pub const max_cores = limits.max_cores;
diff --git a/mirai/boot/tss/constants/limits.zig b/mirai/boot/tss/constants/limits.zig
new file mode 100644
index 0000000..d29884b
--- /dev/null
+++ b/mirai/boot/tss/constants/limits.zig
@@ -0,0 +1,15 @@
+//! TSS Constants
+
+pub const tss_size: u20 = 104;
+
+pub const ist_count: u8 = 7;
+
+pub const ist_double_fault: u8 = 1;
+pub const ist_nmi: u8 = 2;
+pub const ist_machine_check: u8 = 3;
+pub const ist_debug: u8 = 4;
+
+pub const default_stack_size: u64 = 16 * 1024;
+pub const interrupt_stack_size: u64 = 8 * 1024;
+
+pub const max_cores: u16 = 256;
diff --git a/mirai/boot/tss/init/init.zig b/mirai/boot/tss/init/init.zig
new file mode 100644
index 0000000..4080560
--- /dev/null
+++ b/mirai/boot/tss/init/init.zig
@@ -0,0 +1,6 @@
+//! TSS Initialization
+
+pub const setup = @import("setup.zig");
+
+pub const setup_core_tss = setup.setup_core_tss;
+pub const setup_minimal_tss = setup.setup_minimal_tss;
diff --git a/mirai/boot/tss/init/setup.zig b/mirai/boot/tss/init/setup.zig
new file mode 100644
index 0000000..95dbb53
--- /dev/null
+++ b/mirai/boot/tss/init/setup.zig
@@ -0,0 +1,32 @@
+//! TSS Setup
+
+const types = @import("../types/types.zig");
+const constants = @import("../constants/constants.zig");
+const stacks = @import("../stacks/stacks.zig");
+const common = @import("../../../../common/common.zig");
+
+const CoreTss = types.CoreTss;
+const Tss = types.Tss;
+const AllocationError = common.errors.memory.AllocationError;
+
+pub fn setup_core_tss(core_tss: *CoreTss) AllocationError!void {
+ const kernel_stack = try stacks.allocate_kernel_stack();
+ core_tss.set_kernel_stack(kernel_stack.base, constants.default_stack_size);
+
+ const ist1_stack = try stacks.allocate_ist_stack();
+ core_tss.set_ist_stack(constants.ist_double_fault, ist1_stack.base, constants.interrupt_stack_size);
+
+ const ist2_stack = try stacks.allocate_ist_stack();
+ core_tss.set_ist_stack(constants.ist_nmi, ist2_stack.base, constants.interrupt_stack_size);
+
+ const ist3_stack = try stacks.allocate_ist_stack();
+ core_tss.set_ist_stack(constants.ist_machine_check, ist3_stack.base, constants.interrupt_stack_size);
+
+ const ist4_stack = try stacks.allocate_ist_stack();
+ core_tss.set_ist_stack(constants.ist_debug, ist4_stack.base, constants.interrupt_stack_size);
+}
+
+pub fn setup_minimal_tss(tss: *Tss, kernel_stack_top: u64) void {
+ tss.clear();
+ tss.set_rsp0(kernel_stack_top);
+}
diff --git a/mirai/boot/tss/stacks/allocate.zig b/mirai/boot/tss/stacks/allocate.zig
new file mode 100644
index 0000000..11f8598
--- /dev/null
+++ b/mirai/boot/tss/stacks/allocate.zig
@@ -0,0 +1,38 @@
+//! TSS Stack Allocation
+
+const pmm = @import("../../../pmm/pmm.zig");
+const common = @import("../../../../common/common.zig");
+const constants = @import("../constants/constants.zig");
+
+const memory_layout = common.constants.memory.layout;
+const AllocationError = common.errors.memory.AllocationError;
+
+pub fn allocate_kernel_stack() AllocationError!struct { base: u64, top: u64 } {
+ const page_count = constants.default_stack_size / 4096;
+ const physical_base = try pmm.allocate_contiguous(page_count);
+ const virtual_base = physical_base + memory_layout.physmap_base;
+ const stack_top = virtual_base + constants.default_stack_size;
+
+ return .{
+ .base = virtual_base,
+ .top = stack_top,
+ };
+}
+
+pub fn allocate_ist_stack() AllocationError!struct { base: u64, top: u64 } {
+ const page_count = constants.interrupt_stack_size / 4096;
+ const physical_base = try pmm.allocate_contiguous(page_count);
+ const virtual_base = physical_base + memory_layout.physmap_base;
+ const stack_top = virtual_base + constants.interrupt_stack_size;
+
+ return .{
+ .base = virtual_base,
+ .top = stack_top,
+ };
+}
+
+pub fn free_stack(base: u64, size: u64) void {
+ const physical_base = base - memory_layout.physmap_base;
+ const page_count = size / 4096;
+ pmm.free_range(physical_base, page_count);
+}
diff --git a/mirai/boot/tss/stacks/stacks.zig b/mirai/boot/tss/stacks/stacks.zig
new file mode 100644
index 0000000..06682f1
--- /dev/null
+++ b/mirai/boot/tss/stacks/stacks.zig
@@ -0,0 +1,7 @@
+//! TSS Stack Operations
+
+pub const allocate = @import("allocate.zig");
+
+pub const allocate_kernel_stack = allocate.allocate_kernel_stack;
+pub const allocate_ist_stack = allocate.allocate_ist_stack;
+pub const free_stack = allocate.free_stack;
diff --git a/mirai/boot/tss/state.zig b/mirai/boot/tss/state.zig
new file mode 100644
index 0000000..55b2bee
--- /dev/null
+++ b/mirai/boot/tss/state.zig
@@ -0,0 +1,51 @@
+//! TSS State
+
+const types = @import("types/types.zig");
+const constants = @import("constants/constants.zig");
+
+const CoreTss = types.CoreTss;
+const Tss = types.Tss;
+
+var boot_tss: Tss = Tss{};
+
+var core_tss_array: [constants.max_cores]CoreTss = undefined;
+var core_count: u16 = 0;
+var initialized: bool = false;
+
+pub fn get_boot_tss() *Tss {
+ return &boot_tss;
+}
+
+pub fn get_boot_tss_address() u64 {
+ return @intFromPtr(&boot_tss);
+}
+
+pub fn get_core_tss(core_id: u16) ?*CoreTss {
+ if (core_id >= core_count) {
+ return null;
+ }
+ return &core_tss_array[core_id];
+}
+
+pub fn register_core(core_id: u16) ?*CoreTss {
+ if (core_id >= constants.max_cores) {
+ return null;
+ }
+ if (core_id >= core_count) {
+ core_count = core_id + 1;
+ }
+ core_tss_array[core_id] = CoreTss.init(core_id);
+ return &core_tss_array[core_id];
+}
+
+pub fn get_core_count() u16 {
+ return core_count;
+}
+
+pub fn is_initialized() bool {
+ return initialized;
+}
+
+pub fn set_initialized() void {
+ initialized = true;
+}
diff --git a/mirai/boot/tss/tss.zig b/mirai/boot/tss/tss.zig
new file mode 100644
index 0000000..923684d
--- /dev/null
+++ b/mirai/boot/tss/tss.zig
@@ -0,0 +1,60 @@
+//! Task State Segment
+
+const gdt = @import("../gdt/gdt.zig");
+
+pub const constants = @import("constants/constants.zig");
+pub const types = @import("types/types.zig");
+pub const stacks = @import("stacks/stacks.zig");
+pub const init = @import("init/init.zig");
+pub const state = @import("state.zig");
+
+pub const Tss = types.Tss;
+pub const CoreTss = types.CoreTss;
+
+pub fn initialize_boot() void {
+ const tss = state.get_boot_tss();
+ tss.clear();
+ state.set_initialized();
+}
+
+pub fn initialize_core(core_id: u16, kernel_stack_top: u64) !*CoreTss {
+ const core_tss = state.register_core(core_id) orelse return error.TooManyCores;
+
+ core_tss.tss.clear();
+ core_tss.tss.set_rsp0(kernel_stack_top);
+
+ try init.setup_core_tss(core_tss);
+
+ return core_tss;
+}
+
+pub fn get_boot_tss() *Tss {
+ return state.get_boot_tss();
+}
+
+pub fn get_boot_tss_address() u64 {
+ return state.get_boot_tss_address();
+}
+
+pub fn get_core_tss(core_id: u16) ?*CoreTss {
+ return state.get_core_tss(core_id);
+}
+
+pub fn get_current_rsp0(core_id: u16) u64 {
+ if (state.get_core_tss(core_id)) |core_tss| {
+ return core_tss.tss.rsp0;
+ }
+ return state.get_boot_tss().rsp0;
+}
+
+pub fn set_current_rsp0(core_id: u16, stack_top: u64) void {
+ if (state.get_core_tss(core_id)) |core_tss| {
+ core_tss.tss.set_rsp0(stack_top);
+ } else {
+ state.get_boot_tss().set_rsp0(stack_top);
+ }
+}
+
+pub fn is_initialized() bool {
+ return state.is_initialized();
+}
diff --git a/mirai/boot/tss/types/core_tss.zig b/mirai/boot/tss/types/core_tss.zig
new file mode 100644
index 0000000..9a63109
--- /dev/null
+++ b/mirai/boot/tss/types/core_tss.zig
@@ -0,0 +1,53 @@
+//! Per-Core TSS
+
+const Tss = @import("tss.zig").Tss;
+const constants = @import("../constants/constants.zig");
+
+pub const CoreTss = struct {
+ tss: Tss,
+ core_id: u16,
+ kernel_stack_base: u64,
+ kernel_stack_top: u64,
+ ist_stacks: [7]IstStack,
+
+ pub const IstStack = struct {
+ base: u64,
+ top: u64,
+ size: u64,
+ };
+
+ pub fn init(core_id: u16) CoreTss {
+ return CoreTss{
+ .tss = Tss{},
+ .core_id = core_id,
+ .kernel_stack_base = 0,
+ .kernel_stack_top = 0,
+ .ist_stacks = [_]IstStack{.{ .base = 0, .top = 0, .size = 0 }} ** 7,
+ };
+ }
+
+ pub fn set_kernel_stack(self: *CoreTss, base: u64, size: u64) void {
+ self.kernel_stack_base = base;
+ self.kernel_stack_top = base + size;
+ self.tss.set_rsp0(self.kernel_stack_top);
+ }
+
+ pub fn set_ist_stack(self: *CoreTss, index: u8, base: u64, size: u64) void {
+ if (index < 1 or index > 7) return;
+ const ist_index = index - 1;
+ self.ist_stacks[ist_index] = .{
+ .base = base,
+ .top = base + size,
+ .size = size,
+ };
+ self.tss.set_ist(index, base + size);
+ }
+
+ pub fn get_tss(self: *CoreTss) *Tss {
+ return &self.tss;
+ }
+
+ pub fn get_tss_address(self: *const CoreTss) u64 {
+ return @intFromPtr(&self.tss);
+ }
+};
diff --git a/mirai/boot/tss/types/tss.zig b/mirai/boot/tss/types/tss.zig
new file mode 100644
index 0000000..7c4896c
--- /dev/null
+++ b/mirai/boot/tss/types/tss.zig
@@ -0,0 +1,71 @@
+//! TSS Structure Type
+
+pub const Tss = extern struct {
+ reserved_0: u32 = 0,
+ rsp0: u64 = 0,
+ rsp1: u64 = 0,
+ rsp2: u64 = 0,
+ reserved_1: u64 = 0,
+ ist1: u64 = 0,
+ ist2: u64 = 0,
+ ist3: u64 = 0,
+ ist4: u64 = 0,
+ ist5: u64 = 0,
+ ist6: u64 = 0,
+ ist7: u64 = 0,
+ reserved_2: u64 = 0,
+ reserved_3: u16 = 0,
+ iopb_offset: u16 = @sizeOf(Tss),
+
+ pub fn set_rsp0(self: *Tss, stack_top: u64) void {
+ self.rsp0 = stack_top;
+ }
+
+ pub fn set_rsp1(self: *Tss, stack_top: u64) void {
+ self.rsp1 = stack_top;
+ }
+
+ pub fn set_rsp2(self: *Tss, stack_top: u64) void {
+ self.rsp2 = stack_top;
+ }
+
+ pub fn set_ist(self: *Tss, index: u8, stack_top: u64) void {
+ switch (index) {
+ 1 => self.ist1 = stack_top,
+ 2 => self.ist2 = stack_top,
+ 3 => self.ist3 = stack_top,
+ 4 => self.ist4 = stack_top,
+ 5 => self.ist5 = stack_top,
+ 6 => self.ist6 = stack_top,
+ 7 => self.ist7 = stack_top,
+ else => {},
+ }
+ }
+
+ pub fn get_ist(self: *const Tss, index: u8) u64 {
+ return switch (index) {
+ 1 => self.ist1,
+ 2 => self.ist2,
+ 3 => self.ist3,
+ 4 => self.ist4,
+ 5 => self.ist5,
+ 6 => self.ist6,
+ 7 => self.ist7,
+ else => 0,
+ };
+ }
+
+ pub fn get_address(self: *const Tss) u64 {
+ return @intFromPtr(self);
+ }
+
+ pub fn clear(self: *Tss) void {
+ self.* = Tss{};
+ }
+};
+
+comptime {
+ if (@sizeOf(Tss) != 104) {
+ @compileError("TSS size must be 104 bytes");
+ }
+}
diff --git a/mirai/boot/tss/types/types.zig b/mirai/boot/tss/types/types.zig
new file mode 100644
index 0000000..aafeb73
--- /dev/null
+++ b/mirai/boot/tss/types/types.zig
@@ -0,0 +1,8 @@
+//! TSS Types
+
+pub const tss = @import("tss.zig");
+pub const core_tss = @import("core_tss.zig");
+
+pub const Tss = tss.Tss;
+pub const CoreTss = core_tss.CoreTss;
+pub const IstStack = core_tss.CoreTss.IstStack;
diff --git a/mirai/drivers/serial/serial.zig b/mirai/drivers/serial/serial.zig
index 8f5d191..7fd374e 100644
--- a/mirai/drivers/serial/serial.zig
+++ b/mirai/drivers/serial/serial.zig
@@ -7,7 +7,4 @@ pub const initialize = init.initialize;
pub const initialize_default = init.initialize_default;
pub const set_port = write.set_port;
-pub const print = write.print;
-pub const print_character = write.print_character;
-pub const print_hex = write.print_hex;
-pub const print_decimal = write.print_decimal;
+pub const printf = write.printf;
diff --git a/mirai/drivers/serial/write.zig b/mirai/drivers/serial/write.zig
index 447ac17..0921d40 100644
--- a/mirai/drivers/serial/write.zig
+++ b/mirai/drivers/serial/write.zig
@@ -13,68 +13,101 @@ pub fn set_port(port: u16) void {
current_port = port;
}
-pub fn is_transmit_empty(port: u16) bool {
+fn is_transmit_empty(port: u16) bool {
return (asm_io.read_byte(port + registers.line_status_register) & registers.line_status_transmit_empty) != 0;
}
-pub fn write_character(port: u16, character: u8) void {
+fn write_char(port: u16, char: u8) void {
while (!is_transmit_empty(port)) {
asm_io.io_wait();
}
- asm_io.write_byte(port + registers.data_register, character);
+ asm_io.write_byte(port + registers.data_register, char);
}
-pub fn write_string(port: u16, string: []const u8) void {
- for (string) |character| {
- if (character == '\n') {
- write_character(port, '\r');
+pub fn printf(comptime fmt: []const u8, args: anytype) void {
+ const ArgsType = @TypeOf(args);
+ const fields = @typeInfo(ArgsType).@"struct".fields;
+
+ comptime var i: usize = 0;
+ comptime var arg_index: usize = 0;
+
+ inline while (i < fmt.len) {
+ if (fmt[i] == '%' and i + 1 < fmt.len) {
+ switch (fmt[i + 1]) {
+ 's' => {
+ const str = @field(args, fields[arg_index].name);
+ for (str) |c| {
+ if (c == '\n') write_char(current_port, '\r');
+ write_char(current_port, c);
+ }
+ arg_index += 1;
+ i += 2;
+ },
+ 'd' => {
+ const val = @field(args, fields[arg_index].name);
+ print_decimal_value(@intCast(val));
+ arg_index += 1;
+ i += 2;
+ },
+ 'x' => {
+ const val = @field(args, fields[arg_index].name);
+ print_hex_value(@intCast(val));
+ arg_index += 1;
+ i += 2;
+ },
+ '%' => {
+ write_char(current_port, '%');
+ i += 2;
+ },
+ else => {
+ write_char(current_port, fmt[i]);
+ i += 1;
+ },
+ }
+ } else {
+ if (fmt[i] == '\n') write_char(current_port, '\r');
+ write_char(current_port, fmt[i]);
+ i += 1;
}
- write_character(port, character);
}
}
-pub fn print(string: []const u8) void {
- write_string(current_port, string);
-}
-
-pub fn print_character(character: u8) void {
- if (character == '\n') {
- write_character(current_port, '\r');
- }
- write_character(current_port, character);
-}
-
-pub fn print_hex(value: u64) void {
- const hex_chars = "0123456789ABCDEF";
- var buffer: [18]u8 = undefined;
- buffer[0] = '0';
- buffer[1] = 'x';
-
- var temp_value = value;
- var index: usize = 17;
- while (index > 1) : (index -= 1) {
- buffer[index] = hex_chars[@truncate(temp_value & 0xF)];
- temp_value >>= 4;
- }
-
- print(&buffer);
-}
-
-pub fn print_decimal(value: u64) void {
+fn print_decimal_value(value: u64) void {
if (value == 0) {
- print_character('0');
+ write_char(current_port, '0');
return;
}
var buffer: [20]u8 = undefined;
- var temp_value = value;
- var index: usize = 20;
+ var temp = value;
+ var len: usize = 0;
- while (temp_value > 0) {
- index -= 1;
- buffer[index] = @truncate((temp_value % 10) + '0');
- temp_value /= 10;
+ while (temp > 0) {
+ buffer[len] = @truncate((temp % 10) + '0');
+ temp /= 10;
+ len += 1;
}
- print(buffer[index..]);
+ while (len > 0) {
+ len -= 1;
+ write_char(current_port, buffer[len]);
+ }
+}
+
+fn print_hex_value(value: u64) void {
+ const hex = "0123456789abcdef";
+ write_char(current_port, '0');
+ write_char(current_port, 'x');
+
+ var started = false;
+ var shift: u6 = 60;
+ while (true) {
+ const nibble: u4 = @truncate((value >> shift) & 0xF);
+ if (nibble != 0 or started or shift == 0) {
+ write_char(current_port, hex[nibble]);
+ started = true;
+ }
+ if (shift == 0) break;
+ shift -= 4;
+ }
}
diff --git a/mirai/kagami/types/kagami.zig b/mirai/kagami/types/kagami.zig
index f89863f..8979e5d 100644
--- a/mirai/kagami/types/kagami.zig
+++ b/mirai/kagami/types/kagami.zig
@@ -1,5 +1,7 @@
//! Kagami Structure
+const state = @import("../state.zig");
+
pub const Kagami = struct {
pml4_physical: u64,
reference_count: u32,
@@ -9,7 +11,7 @@ pub const Kagami = struct {
lock: bool,
pub fn is_kernel(self: *const Kagami) bool {
- const kernel_kagami = @import("../state.zig").get_kernel_kagami();
+ const kernel_kagami = state.get_kernel_kagami();
return self.pml4_physical == kernel_kagami.pml4_physical;
}