Skip to content

Commit

Permalink
Add Hypervisor Vendor (#147)
Browse files Browse the repository at this point in the history
* fix: vendor id mapping for KVM

Last few bytes are ascii null characters: "KVMKVMKVM\0\0\0". When parsed by `valAsString` this shows up as just "KVMKVMKVM".

Tested manually in a QEMU VM with KVM using https://github.com/numtide/nixos-facter.

* feat: hypervisor vendor

Read hypervisor vendor as per https://lwn.net/Articles/301888/.
  • Loading branch information
brianmcgee authored Aug 5, 2024
1 parent d25825d commit 92d5326
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 21 deletions.
60 changes: 43 additions & 17 deletions cpuid.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,12 @@ const (
Qualcomm
Marvell

QEMU
QNX
ACRN
SRE
Apple

lastVendor
)

Expand Down Expand Up @@ -296,20 +302,22 @@ const (

// CPUInfo contains information about the detected system CPU.
type CPUInfo struct {
BrandName string // Brand name reported by the CPU
VendorID Vendor // Comparable CPU vendor ID
VendorString string // Raw vendor string.
featureSet flagSet // Features of the CPU
PhysicalCores int // Number of physical processor cores in your CPU. Will be 0 if undetectable.
ThreadsPerCore int // Number of threads per physical core. Will be 1 if undetectable.
LogicalCores int // Number of physical cores times threads that can run on each core through the use of hyperthreading. Will be 0 if undetectable.
Family int // CPU family number
Model int // CPU model number
Stepping int // CPU stepping info
CacheLine int // Cache line size in bytes. Will be 0 if undetectable.
Hz int64 // Clock speed, if known, 0 otherwise. Will attempt to contain base clock speed.
BoostFreq int64 // Max clock speed, if known, 0 otherwise
Cache struct {
BrandName string // Brand name reported by the CPU
VendorID Vendor // Comparable CPU vendor ID
VendorString string // Raw vendor string.
HypervisorVendorID Vendor // Hypervisor vendor
HypervisorVendorString string // Raw hypervisor vendor string
featureSet flagSet // Features of the CPU
PhysicalCores int // Number of physical processor cores in your CPU. Will be 0 if undetectable.
ThreadsPerCore int // Number of threads per physical core. Will be 1 if undetectable.
LogicalCores int // Number of physical cores times threads that can run on each core through the use of hyperthreading. Will be 0 if undetectable.
Family int // CPU family number
Model int // CPU model number
Stepping int // CPU stepping info
CacheLine int // Cache line size in bytes. Will be 0 if undetectable.
Hz int64 // Clock speed, if known, 0 otherwise. Will attempt to contain base clock speed.
BoostFreq int64 // Max clock speed, if known, 0 otherwise
Cache struct {
L1I int // L1 Instruction Cache (per core or shared). Will be -1 if undetected
L1D int // L1 Data Cache (per core or shared). Will be -1 if undetected
L2 int // L2 Cache (per core or shared). Will be -1 if undetected
Expand All @@ -318,8 +326,9 @@ type CPUInfo struct {
SGX SGXSupport
AMDMemEncryption AMDMemEncryptionSupport
AVX10Level uint8
maxFunc uint32
maxExFunc uint32

maxFunc uint32
maxExFunc uint32
}

var cpuid func(op uint32) (eax, ebx, ecx, edx uint32)
Expand Down Expand Up @@ -886,7 +895,9 @@ var vendorMapping = map[string]Vendor{
"GenuineTMx86": Transmeta,
"Geode by NSC": NSC,
"VIA VIA VIA ": VIA,
"KVMKVMKVMKVM": KVM,
"KVMKVMKVM": KVM,
"Linux KVM Hv": KVM,
"TCGTCGTCGTCG": QEMU,
"Microsoft Hv": MSVM,
"VMwareVMware": VMware,
"XenVMMXenVMM": XenHVM,
Expand All @@ -896,6 +907,10 @@ var vendorMapping = map[string]Vendor{
"SiS SiS SiS ": SiS,
"RiseRiseRise": SiS,
"Genuine RDC": RDC,
"QNXQVMBSQG": QNX,
"ACRNACRNACRN": ACRN,
"SRESRESRESRE": SRE,
"Apple VZ": Apple,
}

func vendorID() (Vendor, string) {
Expand All @@ -908,6 +923,17 @@ func vendorID() (Vendor, string) {
return vend, v
}

func hypervisorVendorID() (Vendor, string) {
// https://lwn.net/Articles/301888/
_, b, c, d := cpuid(0x40000000)
v := string(valAsString(b, c, d))
vend, ok := vendorMapping[v]
if !ok {
return VendorUnknown, v
}
return vend, v
}

func cacheLine() int {
if maxFunctionID() < 0x1 {
return 0
Expand Down
1 change: 1 addition & 0 deletions detect_x86.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ func addInfo(c *CPUInfo, safe bool) {
c.LogicalCores = logicalCores()
c.PhysicalCores = physicalCores()
c.VendorID, c.VendorString = vendorID()
c.HypervisorVendorID, c.HypervisorVendorString = hypervisorVendorID()
c.AVX10Level = c.supportAVX10()
c.cacheSize()
c.frequencies()
Expand Down
11 changes: 8 additions & 3 deletions featureid_string.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion mockcpu_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ func mockCPU(def []byte) func() {
}(idfuncs{cpuid: cpuid, cpuidex: cpuidex, xgetbv: xgetbv})

cpuid = func(op uint32) (eax, ebx, ecx, edx uint32) {
if op == 0x80000000 || op == 0 || op == 0x4000000c {
if op == 0x80000000 || op == 0 || op == 0x4000000c || op == 0x40000000 {
var ok bool
_, ok = fakeID[op]
if !ok {
Expand Down

0 comments on commit 92d5326

Please sign in to comment.