mirror of
https://github.com/rdmsr/zag.git
synced 2026-10-27 13:58:20 +00:00
125 lines
2.9 KiB
Zig
125 lines
2.9 KiB
Zig
//! amd64-specific kernel initialization code.
|
|
|
|
const amd64 = @import("arch");
|
|
const int = @import("int.zig");
|
|
const r = @import("root");
|
|
const std = @import("std");
|
|
const impl = @import("impl.zig");
|
|
const ke = r.ke;
|
|
const kep = r.ke.private;
|
|
const pl = r.pl;
|
|
|
|
var gdt = extern struct {
|
|
entries: [9]u64 align(1),
|
|
tss: amd64.TssDescriptor align(1),
|
|
}{
|
|
.entries = .{
|
|
0, // null
|
|
0x00009a000000ffff, // code16
|
|
0x000093000000ffff, // data16
|
|
0x00cf9a000000ffff, // code32
|
|
0x00cf93000000ffff, // data32
|
|
0x00af9b000000ffff, // kernel code64
|
|
0x00af93000000ffff, // kernel data64
|
|
0x00aff3000000ffff, // user code64
|
|
0x00affb000000ffff, // user data64
|
|
},
|
|
|
|
.tss = undefined,
|
|
};
|
|
|
|
extern fn gdt_load(gdtr: *const amd64.Gdtr) callconv(.c) void;
|
|
|
|
fn early_cpu_init() linksection(r.init) void {
|
|
const gdtr: amd64.Gdtr = .{
|
|
.limit = @sizeOf(@TypeOf(gdt)) - 1,
|
|
.base = @intFromPtr(&gdt),
|
|
};
|
|
|
|
gdt_load(&gdtr);
|
|
|
|
var cr0: amd64.Cr0 = @bitCast(amd64.read_cr(0));
|
|
|
|
// Disable x87 emulation.
|
|
cr0.em = false;
|
|
// Monitor co-processor.
|
|
cr0.mp = true;
|
|
// Numeric error.
|
|
cr0.ne = true;
|
|
// Write-protection (cannot write to read-only pages).
|
|
cr0.wp = true;
|
|
|
|
amd64.write_cr(0, @bitCast(cr0));
|
|
|
|
// Enable CPU features we might want through cr4.
|
|
const f = amd64.cpu_features;
|
|
var cr4: amd64.Cr4 = @bitCast(amd64.read_cr(4));
|
|
|
|
// Allow userspace to read TSC.
|
|
cr4.tsd = false;
|
|
// Enable global pages.
|
|
cr4.pge = f.pge;
|
|
|
|
if (f.fxsave == true) {
|
|
// Enable FXSAVE/FXRSTOR and SSE.
|
|
cr4.osfxsr = true;
|
|
cr4.osxmmexcpt = true;
|
|
}
|
|
|
|
// Enable XSAVE.
|
|
cr4.osxsave = f.xsave;
|
|
|
|
// Enable UMIP.
|
|
cr4.umip = f.umip;
|
|
|
|
amd64.write_cr(4, @bitCast(cr4));
|
|
|
|
// Configure the EFER MSR.
|
|
var efer: amd64.Efer = @bitCast(amd64.read_msr(.Efer));
|
|
|
|
// Enable syscall if supported.
|
|
efer.sce = f.syscall;
|
|
|
|
// Enable NX.
|
|
efer.nxe = true;
|
|
|
|
amd64.write_msr(.Efer, @bitCast(efer));
|
|
}
|
|
|
|
pub fn ap_entry(cpu_id: u32, booted: *std.atomic.Value(usize)) noreturn {
|
|
amd64.write_msr(.GsBase, kep.impl.cpu_offsets[cpu_id]);
|
|
|
|
early_cpu_init();
|
|
kep.cpu.init_cpu(cpu_id);
|
|
pl.impl.init_ap();
|
|
|
|
const sched = kep.sched.percpu.local();
|
|
|
|
sched.current_thread = pl.impl.smp.start_thread.local().*;
|
|
sched.idle_thread = sched.current_thread;
|
|
|
|
amd64.sti();
|
|
|
|
_ = booted.fetchAdd(1, .monotonic);
|
|
ke.ipl.lower(.Passive);
|
|
|
|
kep.sched.idle(null);
|
|
}
|
|
|
|
var initial_offsets: [1]usize = .{0};
|
|
extern var __percpu_start: u8;
|
|
|
|
pub fn early_init() linksection(r.init) void {
|
|
amd64.cpu_features = r.boot_info.arch_info.cpu_features;
|
|
amd64.hypervisor.info = r.boot_info.arch_info.hypervisor_info;
|
|
early_cpu_init();
|
|
|
|
impl.cpu_offsets = &initial_offsets;
|
|
|
|
// Enable Per-CPU data for this CPU
|
|
amd64.write_msr(.GsBase, 0);
|
|
|
|
int.init();
|
|
amd64.sti();
|
|
}
|