Skip to content

Commit

Permalink
Move apic to arch folder and cpu init to arch.cpu
Browse files Browse the repository at this point in the history
  • Loading branch information
Ratakor committed Oct 24, 2023
1 parent 21336e7 commit 9da0050
Show file tree
Hide file tree
Showing 11 changed files with 96 additions and 110 deletions.
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Copyright © 2023, Ratakor <[email protected]>
Copyright (c) Ratakor

Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
Expand Down
2 changes: 1 addition & 1 deletion kernel/acpi.zig
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
const std = @import("std");
const root = @import("root");
const arch = @import("arch.zig");
const apic = arch.apic;
const vmm = @import("vmm.zig");
const apic = @import("apic.zig");
const log = std.log.scoped(.acpi);
const readIntNative = std.mem.readIntNative;

Expand Down
1 change: 1 addition & 0 deletions kernel/arch/x86_64.zig
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
pub usingnamespace @import("x86_64/x86_64.zig");
pub const gdt = @import("x86_64/gdt.zig");
pub const idt = @import("x86_64/idt.zig");
pub const apic = @import("x86_64/apic.zig");
pub const cpu = @import("x86_64/cpu.zig");

pub const Context = idt.Context;
Expand Down
15 changes: 8 additions & 7 deletions kernel/apic.zig → kernel/arch/x86_64/apic.zig
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
const std = @import("std");
const arch = @import("arch.zig");
const vmm = @import("vmm.zig");
const smp = @import("smp.zig");
const pit = @import("time.zig");
const SpinLock = @import("SpinLock.zig");
const root = @import("root");
const x86 = @import("x86_64.zig");
const vmm = root.vmm;
const smp = root.smp;
const pit = root.time;
const SpinLock = root.SpinLock;

const Register = enum(u64) {
lapic_id = 0x020,
Expand Down Expand Up @@ -74,8 +75,8 @@ pub inline fn eoi() void {
}

pub fn timerOneShot(microseconds: u64, vector: u8) void {
const old_state = arch.toggleInterrupts(false);
defer _ = arch.toggleInterrupts(old_state);
const old_state = x86.toggleInterrupts(false);
defer _ = x86.toggleInterrupts(old_state);

timerStop();

Expand Down
62 changes: 57 additions & 5 deletions kernel/arch/x86_64/cpu.zig
Original file line number Diff line number Diff line change
@@ -1,10 +1,62 @@
const std = @import("std");
const limine = @import("limine");
const root = @import("root");
const pmm = root.pmm;
const vmm = root.vmm;
const sched = root.sched;
const x86 = @import("x86_64.zig");
const gdt = @import("idt.zig");
const gdt = @import("gdt.zig");
const idt = @import("idt.zig");
const apic = @import("apic.zig");
const log = std.log.scoped(.cpu);
const page_size = std.mem.page_size;

pub const CpuLocal = struct {
id: usize,
active: bool,
idle_thread: *sched.Thread,
current_thread: *sched.Thread, // TODO

lapic_id: u32,
lapic_freq: u64,
tss: gdt.TSS,

pub const stack_size = 0x10000; // 64KiB

pub fn initCpu(self: *CpuLocal, is_bsp: bool) void {
gdt.reload();
idt.reload();
gdt.loadTSS(&self.tss);

vmm.switchPageTable(vmm.kaddr_space.cr3());

// TODO: use null for idle?
const idle_thread = root.allocator.create(sched.Thread) catch unreachable;
idle_thread.self = idle_thread;
idle_thread.cpu = self;
idle_thread.process = sched.kernel_process;
self.idle_thread = idle_thread;
x86.setGsBase(@intFromPtr(idle_thread));

const common_int_stack_phys = pmm.alloc(stack_size / page_size, true) orelse unreachable;
const common_int_stack = common_int_stack_phys + stack_size + vmm.hhdm_offset;
self.tss.rsp0 = common_int_stack;

const sched_stack_phys = pmm.alloc(stack_size / page_size, true) orelse unreachable;
const sched_stack = sched_stack_phys + stack_size + vmm.hhdm_offset;
self.tss.ist1 = sched_stack;

initFeatures(is_bsp);

if (is_bsp) {
// disable PIC
x86.out(u8, 0xa1, 0xff);
x86.out(u8, 0x21, 0xff);
}

apic.init(); // smp safe
}
};

const PAT = packed struct {
// zig fmt: off
Expand Down Expand Up @@ -164,7 +216,7 @@ inline fn hasFeature(features: u64, feat: Feature) bool {
return features & @intFromEnum(feat) != 0;
}

pub fn initFeatures(bsp: bool) void {
fn initFeatures(is_bsp: bool) void {
const regs = x86.cpuid(1, 0);
const features: u64 = @as(u64, regs.edx) << 32 | regs.ecx;

Expand All @@ -186,7 +238,7 @@ pub fn initFeatures(bsp: bool) void {
x86.wrmsr(0x277, @bitCast(pat));

if (hasFeature(features, .xsave)) {
if (bsp) log.info("xsave is supported", .{});
if (is_bsp) log.info("xsave is supported", .{});
use_xsave = true;

cr4 = x86.readRegister("cr4");
Expand All @@ -198,12 +250,12 @@ pub fn initFeatures(bsp: bool) void {
xcr0 |= @intFromEnum(XCR0.sse);

if (hasFeature(features, .avx)) {
if (bsp) log.info("saving avx state using xsave", .{});
if (is_bsp) log.info("saving avx state using xsave", .{});
xcr0 |= @intFromEnum(XCR0.avx);
}

if (x86.cpuid(7, 0).ebx & @as(u64, 1 << 16) != 0) {
if (bsp) log.info("saving avx512 state using xsave", .{});
if (is_bsp) log.info("saving avx512 state using xsave", .{});
xcr0 |= @intFromEnum(XCR0.opmask);
xcr0 |= @intFromEnum(XCR0.zmm_hi256);
xcr0 |= @intFromEnum(XCR0.hi16_zmm);
Expand Down
8 changes: 4 additions & 4 deletions kernel/main.zig
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ const arch = @import("arch.zig");
const debug = @import("debug.zig");
const serial = @import("serial.zig");
const event = @import("event.zig");
const pmm = @import("pmm.zig");
pub const pmm = @import("pmm.zig");
pub const vmm = @import("vmm.zig");
const acpi = @import("acpi.zig");
const sched = @import("sched.zig");
const smp = @import("smp.zig");
const time = @import("time.zig");
pub const sched = @import("sched.zig");
pub const smp = @import("smp.zig");
pub const time = @import("time.zig");
const vfs = @import("vfs.zig");
const ps2 = @import("ps2.zig");
const TTY = @import("TTY.zig");
Expand Down
2 changes: 1 addition & 1 deletion kernel/ps2.zig
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ const std = @import("std");
const root = @import("root");
const arch = @import("arch.zig");
const idt = arch.idt;
const apic = arch.apic;
const smp = @import("smp.zig");
const apic = @import("apic.zig");

pub fn init() void {
// disable primary and secondary PS/2 ports
Expand Down
14 changes: 7 additions & 7 deletions kernel/sched.zig
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const root = @import("root");
const arch = @import("arch.zig");
const gdt = arch.gdt;
const idt = arch.idt;
const apic = @import("apic.zig");
const apic = arch.apic;
const ev = @import("event.zig");
const rand = @import("rand.zig");
const smp = @import("smp.zig");
Expand Down Expand Up @@ -76,7 +76,7 @@ pub const Thread = struct {

tid: usize,
lock: SpinLock = .{},
cpu: ?*smp.CpuLocal,
cpu: ?*arch.cpu.CpuLocal,
process: *Process,
ctx: arch.Context,

Expand Down Expand Up @@ -281,7 +281,7 @@ fn schedHandler(ctx: *arch.Context) callconv(.SysV) void {
cpu.active = true;
const next_thread = nextThread();

if (current_thread != cpu.idle) {
if (current_thread != cpu.idle_thread) {
current_thread.yield_await.unlock();

if (next_thread == null and current_thread.enqueued) {
Expand All @@ -306,8 +306,8 @@ fn schedHandler(ctx: *arch.Context) callconv(.SysV) void {
if (next_thread == null) {
apic.eoi();
if (arch.arch == .x86_64) {
arch.setGsBase(@intFromPtr(cpu.idle));
arch.setKernelGsBase(@intFromPtr(cpu.idle));
arch.setGsBase(@intFromPtr(cpu.idle_thread));
arch.setKernelGsBase(@intFromPtr(cpu.idle_thread));
}
cpu.active = false;
vmm.switchPageTable(vmm.kaddr_space.cr3());
Expand Down Expand Up @@ -366,8 +366,8 @@ pub fn yield(save_ctx: bool) void {
if (save_ctx) {
thread.yield_await.lock();
} else {
arch.setGsBase(@intFromPtr(cpu.idle));
arch.setKernelGsBase(@intFromPtr(cpu.idle));
arch.setGsBase(@intFromPtr(cpu.idle_thread));
arch.setKernelGsBase(@intFromPtr(cpu.idle_thread));
}

apic.sendIPI(cpu.lapic_id, sched_vector);
Expand Down
93 changes: 12 additions & 81 deletions kernel/smp.zig
Original file line number Diff line number Diff line change
Expand Up @@ -2,83 +2,38 @@ const std = @import("std");
const limine = @import("limine");
const root = @import("root");
const arch = @import("arch.zig");
const gdt = arch.gdt;
const idt = arch.idt;
const pmm = @import("pmm.zig");
const vmm = @import("vmm.zig");
const apic = @import("apic.zig");
const apic = arch.apic;
const sched = @import("sched.zig");
const SpinLock = @import("SpinLock.zig");
const CpuLocal = arch.cpu.CpuLocal;
const log = std.log.scoped(.smp);

// TODO: use SYSENTER/SYSEXIT?
// TODO: use FSGSBASE?

pub const CpuLocal = struct {
id: usize,
active: bool,
idle: *sched.Thread,
current: *sched.Thread,

lapic_id: u32,
lapic_freq: u64,
tss: gdt.TSS,
};

const page_size = std.mem.page_size;
const stack_size = 0x10000; // 64KiB

pub var bsp_lapic_id: u32 = undefined; // bootstrap processor lapic id
pub var cpus: []CpuLocal = undefined;
var cpus_started: usize = 0;

// TODO
// pub var sysenter = false;

pub fn init() void {
const smp = root.smp_request.response.?;
bsp_lapic_id = smp.bsp_lapic_id;
cpus = root.allocator.alloc(CpuLocal, smp.cpu_count) catch unreachable;
@memset(std.mem.sliceAsBytes(cpus), 0);
log.info("{} processors detected", .{cpus.len});

for (smp.cpus(), cpus, 0..) |cpu, *cpu_local, i| {
for (smp.cpus(), cpus, 0..) |cpu, *cpu_local, id| {
cpu.extra_argument = @intFromPtr(cpu_local);
cpu_local.id = i;
cpu_local.id = id;
cpu_local.lapic_id = cpu.lapic_id;

if (cpu.lapic_id == bsp_lapic_id) {
// TODO: use trampoline

gdt.loadTSS(&cpu_local.tss);

// TODO: use null for idle?
const idle_thread = root.allocator.create(sched.Thread) catch unreachable;
idle_thread.self = idle_thread;
idle_thread.cpu = cpu_local;
idle_thread.process = sched.kernel_process;
cpu_local.idle = idle_thread;
arch.setGsBase(@intFromPtr(idle_thread));

const common_int_stack_phys = pmm.alloc(stack_size / page_size, true) orelse unreachable;
const common_int_stack = common_int_stack_phys + stack_size + vmm.hhdm_offset;
cpu_local.tss.rsp0 = common_int_stack;

const sched_stack_phys = pmm.alloc(stack_size / page_size, true) orelse unreachable;
const sched_stack = sched_stack_phys + stack_size + vmm.hhdm_offset;
cpu_local.tss.ist1 = sched_stack;

arch.cpu.initFeatures(true);

// disable PIC
arch.out(u8, 0xa1, 0xff);
arch.out(u8, 0x21, 0xff);
apic.init(); // smp safe
if (cpu.lapic_id != bsp_lapic_id) {
cpu.goto_address = apInit;
} else {
cpu_local.initCpu(true);

log.info("bootstrap processor is online with id: {}", .{cpu_local.id});
_ = @atomicRmw(usize, &cpus_started, .Add, 1, .AcqRel);
} else {
cpu.goto_address = trampoline;
_ = @atomicRmw(usize, &cpus_started, .Add, 1, .Release);
}
}

Expand All @@ -104,37 +59,13 @@ pub fn thisCpu() *CpuLocal {
return thread.cpu.?;
}

fn trampoline(smp_info: *limine.SmpInfo) callconv(.C) noreturn {
fn apInit(smp_info: *limine.SmpInfo) callconv(.C) noreturn {
const cpu_local: *CpuLocal = @ptrFromInt(smp_info.extra_argument);

gdt.reload();
idt.reload();
gdt.loadTSS(&cpu_local.tss);

vmm.switchPageTable(vmm.kaddr_space.cr3());

// TODO: use null for idle?
const idle_thread = root.allocator.create(sched.Thread) catch unreachable;
idle_thread.self = idle_thread;
idle_thread.cpu = cpu_local;
idle_thread.process = sched.kernel_process;
cpu_local.idle = idle_thread;
arch.setGsBase(@intFromPtr(idle_thread));

const common_int_stack_phys = pmm.alloc(stack_size / page_size, true) orelse unreachable;
const common_int_stack = common_int_stack_phys + stack_size + vmm.hhdm_offset;
cpu_local.tss.rsp0 = common_int_stack;

const sched_stack_phys = pmm.alloc(stack_size / page_size, true) orelse unreachable;
const sched_stack = sched_stack_phys + stack_size + vmm.hhdm_offset;
cpu_local.tss.ist1 = sched_stack;

arch.cpu.initFeatures(false);

apic.init(); // smp safe
cpu_local.initCpu(false);

log.info("processor {} is online", .{cpu_local.id});
_ = @atomicRmw(usize, &cpus_started, .Add, 1, .AcqRel);
_ = @atomicRmw(usize, &cpus_started, .Add, 1, .Release);

sched.wait();
}
2 changes: 1 addition & 1 deletion kernel/time.zig
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const root = @import("root");
const arch = @import("arch.zig");
const smp = @import("smp.zig");
const idt = arch.idt;
const apic = @import("apic.zig");
const apic = arch.apic;
const ev = @import("event.zig");
const SpinLock = @import("SpinLock.zig");

Expand Down
5 changes: 3 additions & 2 deletions kernel/vmm.zig
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const std = @import("std");
const root = @import("root");
const arch = @import("arch.zig");
const idt = arch.idt;
const apic = @import("apic.zig");
const apic = arch.apic;
const pmm = @import("pmm.zig");
const smp = @import("smp.zig");
const sched = @import("sched.zig");
Expand Down Expand Up @@ -426,7 +426,8 @@ pub fn init() void {
// map the rest of the memory map
const memory_map = root.memory_map_request.response.?;
for (memory_map.entries()) |entry| {
if (entry.kind == .reserved) continue; // TODO
if (entry.kind == .reserved) continue;

const base = alignBackward(u64, entry.base, page_size);
const top = alignForward(u64, entry.base + entry.length, page_size);
if (top <= 0x100000000) continue;
Expand Down

0 comments on commit 9da0050

Please sign in to comment.