refactor: move directories around a bit

This commit is contained in:
Loïc Grégoire
2026-03-30 20:05:45 -04:00
parent faf76ca485
commit 827e8bf0ca
11 changed files with 34 additions and 11 deletions
-447
View File
@@ -1,447 +0,0 @@
//! Wrappers over amd64 CPU instructions and CPUID feature detection.
const std = @import("std");
pub const Msr = enum(u32) {
/// IA32_APIC_BASE
LapicBase = 0x1B,
/// IA32_FS_BASE
FsBase = 0xC000_0100,
/// IA32_GS_BASE
GsBase = 0xC000_0101,
/// IA32_KERNEL_GS_BASE
KernelGsBase = 0xC000_0102,
/// IA32_EFER
Efer = 0xC000_0080,
/// IA32_STAR
Star = 0xC000_0081,
/// IA32_LSTAR
LStar = 0xC000_0082,
};
pub const InterruptFrame = packed struct {
r15: u64,
r14: u64,
r13: u64,
r12: u64,
r11: u64,
r10: u64,
r9: u64,
r8: u64,
rsi: u64,
rdi: u64,
rbp: u64,
rdx: u64,
rcx: u64,
rbx: u64,
rax: u64,
intno: u64,
errcode: u64,
rip: u64,
cs: u64,
rflags: u64,
rsp: u64,
ss: u64,
};
pub inline fn outb(port: u16, value: u8) void {
asm volatile ("outb %[value], %[port]"
:
: [value] "{al}" (value),
[port] "{dx}" (port),
);
}
pub inline fn outw(port: u16, value: u16) void {
asm volatile ("outw %[value], %[port]"
:
: [value] "{ax}" (value),
[port] "{dx}" (port),
);
}
pub inline fn outl(port: u16, value: u32) void {
asm volatile ("outl %[value], %[port]"
:
: [value] "{eax}" (value),
[port] "{dx}" (port),
);
}
pub inline fn inb(port: u16) u8 {
return asm volatile ("inb %[port], %[ret]"
: [ret] "={al}" (-> u8),
: [port] "{dx}" (port),
);
}
pub inline fn inw(port: u16) u16 {
return asm volatile ("inw %[port], %[ret]"
: [ret] "={ax}" (-> u16),
: [port] "{dx}" (port),
);
}
pub inline fn inl(port: u16) u32 {
return asm volatile ("inl %[port], %[ret]"
: [ret] "={eax}" (-> u32),
: [port] "{dx}" (port),
);
}
pub inline fn rdmsr(msr: Msr) u64 {
var low: u32 = undefined;
var high: u32 = undefined;
asm volatile ("rdmsr"
: [low] "={eax}" (low),
[high] "={edx}" (high),
: [msr] "{ecx}" (@intFromEnum(msr)),
);
return @as(u64, high) << 32 | low;
}
pub inline fn wrmsr(msr: Msr, value: u64) void {
asm volatile ("wrmsr"
:
: [low] "{eax}" (@as(u32, @truncate(value))),
[high] "{edx}" (@as(u32, @truncate(value >> 32))),
[msr] "{ecx}" (@intFromEnum(msr)),
);
}
pub inline fn invlpg(addr: u64) void {
asm volatile ("invlpg (%[addr])"
:
: [addr] "r" (addr),
: .{ .memory = true });
}
pub inline fn sti() void {
asm volatile ("sti");
}
pub inline fn cli() void {
asm volatile ("cli");
}
pub inline fn hlt() void {
asm volatile ("hlt");
}
pub inline fn rflags() u64 {
var flags: u64 = undefined;
asm volatile ("pushfq; pop %[flags]"
: [flags] "=r" (flags),
);
return flags;
}
pub inline fn rdtsc() u64 {
var low: u32 = undefined;
var high: u32 = undefined;
asm volatile ("rdtsc"
: [low] "={eax}" (low),
[high] "={edx}" (high),
);
return @as(u64, high) << 32 | low;
}
pub inline fn read_cr(comptime n: u2) u64 {
comptime std.debug.assert(n != 1);
return asm volatile (std.fmt.comptimePrint("mov %%cr{}, %[ret]", .{n})
: [ret] "=r" (-> u64),
);
}
pub inline fn write_cr(comptime n: u2, value: u64) void {
comptime std.debug.assert(n != 1);
asm volatile (std.fmt.comptimePrint("mov %[value], %%cr{}", .{n})
:
: [value] "r" (value),
);
}
pub const CpuidResult = struct { eax: u32, ebx: u32, ecx: u32, edx: u32 };
pub inline fn cpuid(leaf: u32, subleaf: u32) CpuidResult {
var eax: u32 = undefined;
var ebx: u32 = undefined;
var ecx: u32 = undefined;
var edx: u32 = undefined;
asm volatile ("cpuid"
: [eax] "={eax}" (eax),
[ebx] "={ebx}" (ebx),
[ecx] "={ecx}" (ecx),
[edx] "={edx}" (edx),
: [leaf] "{eax}" (leaf),
[subleaf] "{ecx}" (subleaf),
);
return .{ .eax = eax, .ebx = ebx, .ecx = ecx, .edx = edx };
}
pub const CpuidRequest = union(enum) {
vendor_info,
feature_info,
extended_info,
highest_extended_function,
extended_features: ExtendedFeaturesSubLeaf,
brand_string: BrandStringPart,
power_management_info,
pub const ExtendedFeaturesSubLeaf = enum(u32) {
first = 0,
second = 1,
third = 3,
};
pub const BrandStringPart = enum(u32) {
part0 = 0x80000002,
part1 = 0x80000003,
part2 = 0x80000004,
};
pub fn execute(self: CpuidRequest) CpuidResult {
const leaf, const subleaf = switch (self) {
.vendor_info => .{ 0x0, 0 },
.feature_info => .{ 0x1, 0 },
.highest_extended_function => .{ 0x80000000, 0 },
.extended_info => .{ 0x80000001, 0 },
.power_management_info => .{ 0x80000007, 0 },
.extended_features => |s| .{ 0x7, @intFromEnum(s) },
.brand_string => |p| .{ @intFromEnum(p), 0 },
};
return cpuid(leaf, subleaf);
}
};
const FeatureInfoEcx = packed struct(u32) {
sse3: bool,
pclmul: bool,
dtes64: bool,
monitor: bool,
ds_cpl: bool,
vmx: bool,
smx: bool,
est: bool,
tm2: bool,
ssse3: bool,
cnxt_id: bool,
sdbg: bool,
fma: bool,
cx16: bool,
xtpr: bool,
pdcm: bool,
_reserved: u1,
pcid: bool,
dca: bool,
sse4_1: bool,
sse4_2: bool,
x2apic: bool,
movbe: bool,
popcnt: bool,
tsc_deadline: bool,
aes: bool,
xsave: bool,
osxsave: bool,
avx: bool,
f16c: bool,
rdrand: bool,
hypervisor: bool,
};
const FeatureInfoEdx = packed struct(u32) {
fpu: bool,
vme: bool,
de: bool,
pse: bool,
tsc: bool,
msr: bool,
pae: bool,
mce: bool,
cx8: bool,
apic: bool,
_reserved0: u1,
sep: bool,
mtrr: bool,
pge: bool,
mca: bool,
cmov: bool,
pat: bool,
pse36: bool,
psn: bool,
clfsh: bool,
_reserved1: u1,
ds: bool,
acpi: bool,
mmx: bool,
fxsave: bool,
sse: bool,
sse2: bool,
ignore: u5,
};
const ExtendedFeaturesEcx = packed struct(u32) {
_reserved0: u16,
la57: bool,
_reserved1: u5,
rdpid: bool,
_reserved2: u9,
};
const ExtendedFeaturesEbx = packed struct(u32) {
ignore: u7,
smep: bool,
ignore2: u12,
smap: bool,
ignore3: u11,
};
const ExtendedProcessorInfoEdx = packed struct(u32) {
ignore: u20,
nx: bool,
ignore2: u5,
pdpe1gb: bool,
ignore3: u5,
};
const PowerManagementInfoEdx = packed struct(u32) {
ignore: u8,
invtsc: bool,
ignore2: u23,
};
fn assert_bit(comptime T: type, comptime field_name: []const u8, comptime expected_bit: u5) void {
var v: T = @bitCast(@as(u32, 0));
@field(v, field_name) = true;
const raw: u32 = @bitCast(v);
const want = (@as(u32, 1) << expected_bit);
if (raw != want) @compileError("bit mismatch for field " ++ field_name);
}
comptime {
assert_bit(FeatureInfoEcx, "pcid", 17);
assert_bit(FeatureInfoEcx, "x2apic", 21);
assert_bit(FeatureInfoEcx, "tsc_deadline", 24);
assert_bit(FeatureInfoEcx, "xsave", 26);
assert_bit(ExtendedFeaturesEcx, "la57", 16);
assert_bit(ExtendedProcessorInfoEdx, "nx", 20);
assert_bit(ExtendedProcessorInfoEdx, "pdpe1gb", 26);
assert_bit(PowerManagementInfoEdx, "invtsc", 8);
assert_bit(FeatureInfoEdx, "fxsave", 24);
assert_bit(ExtendedFeaturesEbx, "smap", 20);
assert_bit(ExtendedFeaturesEbx, "smep", 7);
}
pub const CpuFeatures = struct {
x2apic: bool,
five_level_paging: bool,
gib_pages: bool,
tsc_deadline: bool,
fxsave: bool,
xsave: bool,
invariant_tsc: bool,
nx: bool,
pcid: bool,
smap: bool,
smep: bool,
pge: bool,
vendor_string: [12]u8,
brand_string: [48]u8,
};
pub var cpu_features: CpuFeatures = undefined;
pub fn detect_cpu_features() void {
const vendor_info = CpuidRequest.execute(.vendor_info);
const max_ext = CpuidRequest.execute(.highest_extended_function).eax;
const max_basic = vendor_info.eax;
var x2apic = false;
var five_level_paging = false;
var gib_pages = false;
var tsc_deadline = false;
var xsave = false;
var fxsave = false;
var invtsc = false;
var nx = false;
var pcid = false;
var smap = false;
var smep = false;
var pge = false;
var vendor_string: [12]u8 = undefined;
var brand_string: [48]u8 = undefined;
std.mem.writeInt(u32, vendor_string[0..4], vendor_info.ebx, .little);
std.mem.writeInt(u32, vendor_string[4..8], vendor_info.edx, .little);
std.mem.writeInt(u32, vendor_string[8..12], vendor_info.ecx, .little);
if (max_basic >= 0x1) {
const r = CpuidRequest.execute(.feature_info);
const ecx: FeatureInfoEcx = @bitCast(r.ecx);
const edx: FeatureInfoEdx = @bitCast(r.edx);
x2apic = ecx.x2apic;
tsc_deadline = ecx.tsc_deadline;
xsave = ecx.xsave;
pcid = ecx.pcid;
fxsave = edx.fxsave;
pge = edx.pge;
}
if (max_basic >= 0x7) {
const r = CpuidRequest.execute(.{ .extended_features = .first });
const ecx: ExtendedFeaturesEcx = @bitCast(r.ecx);
const ebx: ExtendedFeaturesEbx = @bitCast(r.ebx);
smap = ebx.smap;
smep = ebx.smep;
five_level_paging = ecx.la57;
}
if (max_ext >= 0x80000001) {
const r = CpuidRequest.execute(.extended_info);
const edx: ExtendedProcessorInfoEdx = @bitCast(r.edx);
gib_pages = edx.pdpe1gb;
nx = edx.nx;
}
if (max_ext >= 0x80000004) {
const parts = [_]CpuidResult{
CpuidRequest.execute(.{ .brand_string = .part0 }),
CpuidRequest.execute(.{ .brand_string = .part1 }),
CpuidRequest.execute(.{ .brand_string = .part2 }),
};
var off: usize = 0;
for (parts) |p| {
for ([_]u32{ p.eax, p.ebx, p.ecx, p.edx }) |reg| {
const dst: *[4]u8 = @ptrCast(brand_string[off..].ptr);
std.mem.writeInt(u32, dst, reg, .little);
off += 4;
}
}
}
if (max_ext >= 0x80000007) {
const r = CpuidRequest.execute(.power_management_info);
const edx: PowerManagementInfoEdx = @bitCast(r.edx);
invtsc = edx.invtsc;
}
cpu_features = .{
.x2apic = x2apic,
.five_level_paging = five_level_paging,
.gib_pages = gib_pages,
.tsc_deadline = tsc_deadline,
.fxsave = fxsave,
.xsave = xsave,
.invariant_tsc = invtsc,
.nx = nx,
.pcid = pcid,
.smap = smap,
.smep = smep,
.vendor_string = vendor_string,
.brand_string = brand_string,
.pge = pge,
};
}
-93
View File
@@ -1,93 +0,0 @@
const b = @import("base");
const ksyms = @import("ksyms");
const limine = @import("limine.zig");
const pl = b.pl;
const ke = b.ke;
const ki = ke.private;
pub const std_options = b.std_options;
pub const panic = b.panic;
const std = @import("std");
var boot_info: pl.BootInfo = undefined;
pub export var limine_base_revision: [3]u64 linksection(".limine_requests") = limine.base_revision(6);
pub export var framebuffer_request: limine.FramebufferRequest linksection(".limine_requests") = .{
.id = limine.framebuffer_request_id,
.revision = 0,
.response = null,
};
pub export var limine_requests_start_marker: [4]u64 linksection(".limine_requests_start") = limine.requests_start_marker;
pub export var limine_requests_end_marker: [2]u64 linksection(".limine_requests_end") = limine.requests_end_marker;
pub export var memmap_request: limine.MemmapRequest linksection(".limine_requests") = .{
.id = limine.memmap_request_id,
.revision = 0,
.response = null,
};
pub export var rsdp_request: limine.RsdpRequest linksection(".limine_requests") = .{
.id = limine.rsdp_request_id,
.revision = 0,
.response = null,
};
pub export var cmdline_request: limine.CmdlineRequest linksection(".limine_requests") = .{
.id = limine.cmdline_request_id,
.revision = 0,
.response = null,
};
pub export var kernel_address_request: limine.ExecutableAddressRequest linksection(".limine_requests") = .{
.id = limine.executable_address_request_id,
.revision = 0,
.response = null,
};
fn build_memory_map() void {
const memmap_response = memmap_request.response orelse {
@panic("Limine memmap request failed");
};
boot_info.memory_map.entry_count = memmap_response.entry_count;
const entries = memmap_response.entries orelse {
@panic("Limine memmap response has no entries");
};
for (0..memmap_response.entry_count) |i| {
const entry = entries[i];
boot_info.memory_map.entries[i] = .{
.base = entry.base,
.size = entry.length,
.type = switch (entry.type) {
.Usable => pl.BootInfo.MemMap.Entry.Type.Free,
.AcpiReclaimable => pl.BootInfo.MemMap.Entry.Type.AcpiReclaimable,
.AcpiNvs => pl.BootInfo.MemMap.Entry.Type.AcpiNvs,
.BootloaderReclaimable => pl.BootInfo.MemMap.Entry.Type.LoaderReclaimable,
.KernelAndModules => pl.BootInfo.MemMap.Entry.Type.Kernel,
else => pl.BootInfo.MemMap.Entry.Type.Reserved,
},
};
}
}
export fn kmain() callconv(.c) void {
boot_info.cmdline = if (cmdline_request.response) |cmdline_response| std.mem.span(cmdline_response.cmdline) else null;
boot_info.rsdp = if (rsdp_request.response) |rsdp_response| @intFromPtr(rsdp_response.rsdp) else null;
boot_info.kernel_address = if (kernel_address_request.response) |ka_response| .{
.physical_base = ka_response.physical_base,
.virtual_base = ka_response.virtual_base,
} else .{ .physical_base = 0, .virtual_base = 0 };
build_memory_map();
ke.ncpus = 1;
ki.init(&boot_info);
}
-157
View File
@@ -1,157 +0,0 @@
pub const common_magic: [2]u64 = .{
0xc7b1dd30df4c8b88,
0x0a82e883a194f07b,
};
pub const requests_start_marker: [4]u64 = .{
0xf6b8f4b39de7d1ae,
0xfab91a6940fcb9cf,
0x785c6ed015d3e316,
0x181e920a7852b9d9,
};
pub const requests_end_marker: [2]u64 = .{
0xadc0e0531bb10d03,
0x9572709f31764c62,
};
pub fn base_revision(rev: u64) [3]u64 {
return .{
0xf9562b2d5c95a6c8,
0x6a7b384944536bdc,
rev,
};
}
pub fn base_revision_supported(base_rev: *const [3]u64) bool {
return base_rev[2] == 0;
}
pub const memmap_request_id: [4]u64 = .{
common_magic[0],
common_magic[1],
0x67cf3d9d378a806f,
0xe304acdfc50c3c62,
};
pub const MemmapRequest = extern struct {
id: [4]u64,
revision: u64,
response: ?*MemmapResponse,
};
pub const MemmapResponse = extern struct {
revision: u64,
entry_count: u64,
entries: ?[*]*MemmapEntry,
};
pub const MemmapEntryType = enum(u64) {
Usable = 0,
Reserved = 1,
AcpiReclaimable = 2,
AcpiNvs = 3,
BadMemory = 4,
BootloaderReclaimable = 5,
KernelAndModules = 6,
Framebuffer = 7,
ReservedMapped = 8,
};
pub const MemmapEntry = extern struct {
base: u64,
length: u64,
type: MemmapEntryType,
};
pub const rsdp_request_id: [4]u64 = .{
common_magic[0],
common_magic[1],
0xc5e77b6b397e7b43,
0x27637845accdcf3c,
};
pub const RsdpRequest = extern struct {
id: [4]u64,
revision: u64,
response: ?*RsdpResponse,
};
pub const RsdpResponse = extern struct {
revision: u64,
rsdp: ?*anyopaque,
};
pub const cmdline_request_id: [4]u64 = .{
common_magic[0],
common_magic[1],
0x4b161536e598651e,
0xb390ad4a2f1f303a,
};
pub const CmdlineRequest = extern struct {
id: [4]u64,
revision: u64,
response: ?*CmdlineResponse,
};
pub const CmdlineResponse = extern struct {
revision: u64,
cmdline: ?[*:0]u8,
};
pub const executable_address_request_id: [4]u64 = .{
common_magic[0],
common_magic[1],
0x71ba76863cc55f63,
0xb2644a48c516a487,
};
pub const ExecutableAddressRequest = extern struct {
id: [4]u64,
revision: u64,
response: ?*ExecutableAddressResponse,
};
pub const ExecutableAddressResponse = extern struct {
revision: u64,
physical_base: u64,
virtual_base: u64,
};
pub const framebuffer_request_id: [4]u64 = .{
common_magic[0],
common_magic[1],
0x9d5827dcd881dd75,
0xa3148604f6fab11b,
};
pub const FramebufferRequest = extern struct {
id: [4]u64,
revision: u64,
response: ?*FramebufferResponse,
};
pub const FramebufferResponse = extern struct {
revision: u64,
framebuffer_count: u64,
framebuffers: ?[*]*Framebuffer,
};
pub const Framebuffer = extern struct {
address: ?*anyopaque,
width: u64,
height: u64,
pitch: u64,
bpp: u16,
memory_model: u8,
red_mask_size: u8,
red_mask_shift: u8,
green_mask_size: u8,
green_mask_shift: u8,
blue_mask_size: u8,
blue_mask_shift: u8,
unused: [7]u8,
edid_size: u64,
edid: ?*anyopaque,
};
@@ -1,9 +1,11 @@
const b = @import("base");
pub const cpu = @import("cpu.zig");
const ki = b.ke.private;
const amd64 = b.arch;
const std = @import("std");
pub const name = "amd64";
const ki = b.ke.private;
const cpu = amd64.cpu;
pub const name = "PC";
const com1 = 0x3F8;
+1 -1
View File
@@ -4,7 +4,7 @@
const config = @import("config");
pub const impl = if (@hasDecl(config, "CONFIG_ARCH_AMD64"))
@import("amd64/impl.zig")
@import("pc/impl.zig")
else if (@hasDecl(config, "CONFIG_ARCH_UM"))
@import("um/impl.zig")
else