Skip to content

Commit 92d5326

Browse files
authored
Add Hypervisor Vendor (#147)
* 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/.
1 parent d25825d commit 92d5326

File tree

4 files changed

+53
-21
lines changed

4 files changed

+53
-21
lines changed

cpuid.go

Lines changed: 43 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,12 @@ const (
5555
Qualcomm
5656
Marvell
5757

58+
QEMU
59+
QNX
60+
ACRN
61+
SRE
62+
Apple
63+
5864
lastVendor
5965
)
6066

@@ -296,20 +302,22 @@ const (
296302

297303
// CPUInfo contains information about the detected system CPU.
298304
type CPUInfo struct {
299-
BrandName string // Brand name reported by the CPU
300-
VendorID Vendor // Comparable CPU vendor ID
301-
VendorString string // Raw vendor string.
302-
featureSet flagSet // Features of the CPU
303-
PhysicalCores int // Number of physical processor cores in your CPU. Will be 0 if undetectable.
304-
ThreadsPerCore int // Number of threads per physical core. Will be 1 if undetectable.
305-
LogicalCores int // Number of physical cores times threads that can run on each core through the use of hyperthreading. Will be 0 if undetectable.
306-
Family int // CPU family number
307-
Model int // CPU model number
308-
Stepping int // CPU stepping info
309-
CacheLine int // Cache line size in bytes. Will be 0 if undetectable.
310-
Hz int64 // Clock speed, if known, 0 otherwise. Will attempt to contain base clock speed.
311-
BoostFreq int64 // Max clock speed, if known, 0 otherwise
312-
Cache struct {
305+
BrandName string // Brand name reported by the CPU
306+
VendorID Vendor // Comparable CPU vendor ID
307+
VendorString string // Raw vendor string.
308+
HypervisorVendorID Vendor // Hypervisor vendor
309+
HypervisorVendorString string // Raw hypervisor vendor string
310+
featureSet flagSet // Features of the CPU
311+
PhysicalCores int // Number of physical processor cores in your CPU. Will be 0 if undetectable.
312+
ThreadsPerCore int // Number of threads per physical core. Will be 1 if undetectable.
313+
LogicalCores int // Number of physical cores times threads that can run on each core through the use of hyperthreading. Will be 0 if undetectable.
314+
Family int // CPU family number
315+
Model int // CPU model number
316+
Stepping int // CPU stepping info
317+
CacheLine int // Cache line size in bytes. Will be 0 if undetectable.
318+
Hz int64 // Clock speed, if known, 0 otherwise. Will attempt to contain base clock speed.
319+
BoostFreq int64 // Max clock speed, if known, 0 otherwise
320+
Cache struct {
313321
L1I int // L1 Instruction Cache (per core or shared). Will be -1 if undetected
314322
L1D int // L1 Data Cache (per core or shared). Will be -1 if undetected
315323
L2 int // L2 Cache (per core or shared). Will be -1 if undetected
@@ -318,8 +326,9 @@ type CPUInfo struct {
318326
SGX SGXSupport
319327
AMDMemEncryption AMDMemEncryptionSupport
320328
AVX10Level uint8
321-
maxFunc uint32
322-
maxExFunc uint32
329+
330+
maxFunc uint32
331+
maxExFunc uint32
323332
}
324333

325334
var cpuid func(op uint32) (eax, ebx, ecx, edx uint32)
@@ -886,7 +895,9 @@ var vendorMapping = map[string]Vendor{
886895
"GenuineTMx86": Transmeta,
887896
"Geode by NSC": NSC,
888897
"VIA VIA VIA ": VIA,
889-
"KVMKVMKVMKVM": KVM,
898+
"KVMKVMKVM": KVM,
899+
"Linux KVM Hv": KVM,
900+
"TCGTCGTCGTCG": QEMU,
890901
"Microsoft Hv": MSVM,
891902
"VMwareVMware": VMware,
892903
"XenVMMXenVMM": XenHVM,
@@ -896,6 +907,10 @@ var vendorMapping = map[string]Vendor{
896907
"SiS SiS SiS ": SiS,
897908
"RiseRiseRise": SiS,
898909
"Genuine RDC": RDC,
910+
"QNXQVMBSQG": QNX,
911+
"ACRNACRNACRN": ACRN,
912+
"SRESRESRESRE": SRE,
913+
"Apple VZ": Apple,
899914
}
900915

901916
func vendorID() (Vendor, string) {
@@ -908,6 +923,17 @@ func vendorID() (Vendor, string) {
908923
return vend, v
909924
}
910925

926+
func hypervisorVendorID() (Vendor, string) {
927+
// https://lwn.net/Articles/301888/
928+
_, b, c, d := cpuid(0x40000000)
929+
v := string(valAsString(b, c, d))
930+
vend, ok := vendorMapping[v]
931+
if !ok {
932+
return VendorUnknown, v
933+
}
934+
return vend, v
935+
}
936+
911937
func cacheLine() int {
912938
if maxFunctionID() < 0x1 {
913939
return 0

detect_x86.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ func addInfo(c *CPUInfo, safe bool) {
3232
c.LogicalCores = logicalCores()
3333
c.PhysicalCores = physicalCores()
3434
c.VendorID, c.VendorString = vendorID()
35+
c.HypervisorVendorID, c.HypervisorVendorString = hypervisorVendorID()
3536
c.AVX10Level = c.supportAVX10()
3637
c.cacheSize()
3738
c.frequencies()

featureid_string.go

Lines changed: 8 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

mockcpu_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ func mockCPU(def []byte) func() {
9898
}(idfuncs{cpuid: cpuid, cpuidex: cpuidex, xgetbv: xgetbv})
9999

100100
cpuid = func(op uint32) (eax, ebx, ecx, edx uint32) {
101-
if op == 0x80000000 || op == 0 || op == 0x4000000c {
101+
if op == 0x80000000 || op == 0 || op == 0x4000000c || op == 0x40000000 {
102102
var ok bool
103103
_, ok = fakeID[op]
104104
if !ok {

0 commit comments

Comments
 (0)