diff --git a/src/arch/amd64/root.zig b/src/arch/amd64/root.zig index d653bcf..98009f4 100644 --- a/src/arch/amd64/root.zig +++ b/src/arch/amd64/root.zig @@ -18,6 +18,8 @@ pub const Msr = enum(u32) { Star = 0xC000_0081, /// IA32_LSTAR LStar = 0xC000_0082, + /// MSR_KVM_SYSTEM_TIME_NEW + KvmSystemTimeNew = 0x4B564D01, }; pub const IrqFrame = extern struct { @@ -263,6 +265,7 @@ pub const CpuidRequest = union(enum) { extended_features: ExtendedFeaturesSubLeaf, brand_string: BrandStringPart, power_management_info, + hypervisor_id, pub const ExtendedFeaturesSubLeaf = enum(u32) { first = 0, @@ -285,6 +288,7 @@ pub const CpuidRequest = union(enum) { .power_management_info => .{ 0x80000007, 0 }, .extended_features => |s| .{ 0x7, @intFromEnum(s) }, .brand_string => |p| .{ @intFromEnum(p), 0 }, + .hypervisor_id => .{ 0x40000000, 0 }, }; return cpuid(leaf, subleaf); } @@ -425,8 +429,50 @@ pub const CpuFeatures = struct { brand_string: [48]u8, }; +pub const HypervisorVendor = enum(u32) { + Unknown = 0, + KVM = 1, +}; + +pub const HypervisorInfo = struct { + brand_string: [12]u8, + vendor: HypervisorVendor, + highest_function: u32, +}; + +pub var hypervisor_info: ?HypervisorInfo = null; pub var cpu_features: CpuFeatures = undefined; +const known_hypervisors = [_]struct { + vendor_string: *const [12:0]u8, + vendor: HypervisorVendor, +}{ + .{ .vendor_string = "KVMKVMKVM\x00\x00\x00", .vendor = HypervisorVendor.KVM }, +}; + +fn detect_hypervisor() void { + const r = CpuidRequest.execute(.hypervisor_id); + var hypervisor_brand: [12]u8 = undefined; + std.mem.writeInt(u32, hypervisor_brand[0..4], r.ebx, .little); + std.mem.writeInt(u32, hypervisor_brand[4..8], r.ecx, .little); + std.mem.writeInt(u32, hypervisor_brand[8..12], r.edx, .little); + + var vendor = HypervisorVendor.Unknown; + + for (known_hypervisors) |h| { + if (std.mem.eql(u8, hypervisor_brand[0..], h.vendor_string[0..])) { + vendor = h.vendor; + break; + } + } + + hypervisor_info = HypervisorInfo{ + .brand_string = hypervisor_brand, + .vendor = vendor, + .highest_function = r.eax, + }; +} + pub fn detect_cpu_features() void { const vendor_info = CpuidRequest.execute(.vendor_info); const max_ext = CpuidRequest.execute(.highest_extended_function).eax; @@ -445,6 +491,7 @@ pub fn detect_cpu_features() void { var smap = false; var smep = false; var pge = false; + var hypervisor = false; var vendor_string: [12]u8 = undefined; var brand_string: [48]u8 = undefined; @@ -464,6 +511,7 @@ pub fn detect_cpu_features() void { pcid = ecx.pcid; fxsave = edx.fxsave; pge = edx.pge; + hypervisor = ecx.hypervisor; } if (max_basic >= 0x7) { @@ -505,6 +553,10 @@ pub fn detect_cpu_features() void { invtsc = edx.invtsc; } + if (hypervisor) { + detect_hypervisor(); + } + cpu_features = .{ .x2apic = x2apic, .five_level_paging = five_level_paging, diff --git a/src/platform/pc/impl.zig b/src/platform/pc/impl.zig index 81a8bba..fda0dbd 100644 --- a/src/platform/pc/impl.zig +++ b/src/platform/pc/impl.zig @@ -34,7 +34,7 @@ pub fn early_init(boot_info: *pl.BootInfo) linksection(b.init) void { const f = amd64.cpu_features; std.log.info("amd64/cpu: {s}", .{&f.brand_string}); - std.log.info("amd64/cpu: vendor={s} x2apic={} la57={} nx={} pcid={} pge={} smap={} smep={} pdpe1g={} invtsc={} xsave={} fxsave={} tsc-deadline={}", .{ + std.log.info("amd64/cpu: vendor={s} features={}{}{}{}{}{}{}{}{}{}{}{}", .{ &f.vendor_string, @intFromBool(f.x2apic), @intFromBool(f.five_level_paging), @@ -49,6 +49,10 @@ pub fn early_init(boot_info: *pl.BootInfo) linksection(b.init) void { @intFromBool(f.fxsave), @intFromBool(f.tsc_deadline), }); + + if (amd64.hypervisor_info) |h| { + std.log.info("amd64/cpu: running on hypervisor {s}", .{@tagName(h.vendor)}); + } _ = boot_info; }