From 29f89dc1b3e8c32203f66da2ebc0949e647319d9 Mon Sep 17 00:00:00 2001 From: Ratakor Date: Thu, 5 Oct 2023 13:56:04 +0200 Subject: [PATCH] Add some stuff to cpu.zig, qemu -> 2 cpu --- build.zig | 2 +- kernel/arch/x86_64.zig | 16 +++++++++++ kernel/cpu.zig | 60 +++++++++++++++++++++++++++++++++++------- kernel/gdt.zig | 18 ++++++------- kernel/main.zig | 9 +++---- 5 files changed, 79 insertions(+), 26 deletions(-) diff --git a/build.zig b/build.zig index e2810b7..6c2cdf6 100644 --- a/build.zig +++ b/build.zig @@ -87,7 +87,7 @@ pub fn build(b: *std.Build) void { "-serial", "mon:stdio", "-M", "q35", "-m", "1G", - "-smp", "1", + "-smp", "2", "-boot", "d", "-cdrom", image_name }; diff --git a/kernel/arch/x86_64.zig b/kernel/arch/x86_64.zig index a557e9f..527b841 100644 --- a/kernel/arch/x86_64.zig +++ b/kernel/arch/x86_64.zig @@ -60,3 +60,19 @@ pub inline fn in(comptime T: type, port: u16) T { else => @compileError("No port in instruction available for type " ++ @typeName(T)), }; } + +pub inline fn readRegister(comptime reg: []const u8) u64 { + return asm volatile ("mov %%" ++ reg ++ ", %[res]" + : [res] "=r" (-> u64), + : + : "memory" + ); +} + +pub inline fn writeRegister(comptime reg: []const u8, value: u64) void { + asm volatile ("mov %[val], %%" ++ reg + : + : [val] "r" (value), + : "memory" + ); +} diff --git a/kernel/cpu.zig b/kernel/cpu.zig index 981a083..8928803 100644 --- a/kernel/cpu.zig +++ b/kernel/cpu.zig @@ -1,5 +1,9 @@ const std = @import("std"); +const limine = @import("limine"); const root = @import("root"); +const arch = @import("arch.zig"); +const gdt = @import("gdt.zig"); +const idt = @import("idt.zig"); const SpinLock = @import("lock.zig").SpinLock; const log = std.log.scoped(.cpu); @@ -45,7 +49,7 @@ pub const TSS = extern struct { }; pub const CpuLocal = struct { - cpu_number: u32, + cpu_number: usize, bsp: bool, active: bool, last_run_queue_index: u32, @@ -55,26 +59,64 @@ pub const CpuLocal = struct { idle_thread: *Thread, tlb_shootdown_lock: SpinLock, tlb_shootdown_done: SpinLock, - tlb_shootdown_cr3: usize, + tlb_shootdown_cr3: usize, // TODO: volatile }; +const CPU_STACK_SIZE = 0x10000; + pub var sysenter: bool = false; pub var bsp_lapic_id: u32 = undefined; // TODO: x86 specific pub var smp_started: bool = undefined; pub var cpus: []CpuLocal = undefined; -pub var fpu_storage_size: usize = 0; -// extern void (*fpu_save)(void *ctx); -// extern void (*fpu_restore)(void *ctx); +var cpus_started_i: usize = 0; -pub var cpu_count: usize = undefined; +pub var fpu_storage_size: usize = 0; +pub var fpu_save: *const fn (*Context) void = undefined; +pub var fpu_restore: *const fn (*Context) void = undefined; pub fn init() void { + // TODO: is_amd... + const smp = root.smp_request.response.?; bsp_lapic_id = smp.bsp_lapic_id; - cpu_count = smp.cpu_count; - log.info("{} processors detected", .{cpu_count}); + cpus = root.allocator.alloc(CpuLocal, smp.cpu_count) catch unreachable; + log.info("{} processors detected", .{cpus.len}); + + for (smp.cpus(), cpus, 0..) |cpu, *cpu_local, i| { + cpu.extra_argument = @intFromPtr(cpu_local); + cpu_local.cpu_number = i; + + if (cpu.lapic_id != bsp_lapic_id) { + // cpu.goto_address = singleCpuInit; + } else { + cpu_local.bsp = true; + // singleCpuInit(cpu); + } + + // while (cpus_started_i != cpus.len) { + // std.atomic.spinLoopHint(); + // } + } + + smp_started = true; } -// TODO: a lot of functions with inline assembly +pub fn this() *CpuLocal {} + +fn singleCpuInit(smp_info: *limine.SmpInfo) callconv(.C) noreturn { + const cpu_local: *CpuLocal = @ptrFromInt(smp_info.extra_argument); + const cpu_number = cpu_local.cpu_number; + _ = cpu_number; + + cpu_local.lapic_id = smp_info.lapic_id; + + gdt.reloadGDT(); + idt.reloadIDT(); + gdt.loadTSS(&cpu_local.tss); + + // TODO + + arch.halt(); +} diff --git a/kernel/gdt.zig b/kernel/gdt.zig index f7c70d9..7351465 100644 --- a/kernel/gdt.zig +++ b/kernel/gdt.zig @@ -58,12 +58,9 @@ var gdt: GDT = .{ .access = 0b1111_0010, .flags = 0b1100, }, - .tss = .{ - .access = 0b1000_1001, - .flags = 0, - }, + .tss = .{}, }; -var lock: SpinLock = .{}; +var tss_lock: SpinLock = .{}; pub fn init() void { gdtr.base = @intFromPtr(&gdt); @@ -94,19 +91,20 @@ pub fn reloadGDT() void { } pub fn loadTSS(tss: *TSS) void { - lock.lock(); - defer lock.unlock(); + tss_lock.lock(); + defer tss_lock.unlock(); const tss_int = @intFromPtr(tss); - gdt.tss.base_low = tss_int; + gdt.tss.base_low = @truncate(tss_int); gdt.tss.base_mid = @truncate(tss_int >> 16); gdt.tss.base_high = @truncate(tss_int >> 24); gdt.tss.base_upper = @truncate(tss_int >> 32); - asm volatile ("ltr %[tss]" + asm volatile ( + \\ltr %[tss] : - : [tss] "r" (0x28), + : [tss] "r" (0x28), // 0x28 = address of tss descriptor in gdt : "memory" ); } diff --git a/kernel/main.zig b/kernel/main.zig index d32d290..e8f6970 100644 --- a/kernel/main.zig +++ b/kernel/main.zig @@ -41,8 +41,8 @@ pub export var kernel_file_request: limine.KernelFileRequest = .{}; pub export var kernel_address_request: limine.KernelAddressRequest = .{}; pub export var rsdp_request: limine.RsdpRequest = .{}; pub export var smp_request: limine.SmpRequest = .{}; -// pub export var module_request: limine.ModuleRequest = .{}; -// pub export var boot_time_request: limine.BootTimeRequest = .{}; +pub export var boot_time_request: limine.BootTimeRequest = .{}; +pub export var module_request: limine.ModuleRequest = .{}; pub fn panic(msg: []const u8, _: ?*std.builtin.StackTrace, _: ?usize) noreturn { @setCold(true); @@ -73,13 +73,10 @@ fn main() !void { arch.disableInterrupts(); defer arch.enableInterrupts(); - const boot_info = boot_info_request.response.?; - // const module = module_request.response.?; - // const boot_time = boot_time_request.?; - serial.init(); tty.init() catch unreachable; + const boot_info = boot_info_request.response.?; tty.print("Booting Ubik with {s} {s}\n", .{ boot_info.name, boot_info.version }); debug.init() catch |err| {