mirror of
https://github.com/rdmsr/zag.git
synced 2026-10-27 13:58:20 +00:00
feat(amd64): basic hypervisor detection
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user