github.com/iDigitalFlame/xmt@v0.5.4/device/cpu.go (about) 1 //go:build amd64 || 386 2 // +build amd64 386 3 4 // Copyright (C) 2020 - 2023 iDigitalFlame 5 // 6 // This program is free software: you can redistribute it and/or modify 7 // it under the terms of the GNU General Public License as published by 8 // the Free Software Foundation, either version 3 of the License, or 9 // any later version. 10 // 11 // This program is distributed in the hope that it will be useful, 12 // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 // GNU General Public License for more details. 15 // 16 // You should have received a copy of the GNU General Public License 17 // along with this program. If not, see <https://www.gnu.org/licenses/>. 18 // 19 20 package device 21 22 // IsVirtual attempts to determine if the underlying device is inside a container 23 // or is running in a virtual machine. 24 // 25 // If this returns true, it is suspected that a non-physical device is present. 26 // 27 // Different versions of this function are used depending on CPU type. 28 // - For x86/x64/amd64 this function uses the CPUID instruction. 29 // See https://en.wikipedia.org/wiki/CPUID for more info. 30 func IsVirtual() bool { 31 _, _, c, d := cpuid(0x1, 0) // CPU Features 32 if c&(1<<31) != 0 { // Hypervisor flag 33 return true 34 } 35 t := d&(1<<29) == 0 // Thermal monitor 36 // Save this one for later, most VMs /don't/ have thermal monitoring but we 37 // will check all other options first. 38 _, b, c, d := cpuid(0x40000000, 0) // Hypervisor CPUID 39 if d == 0 || b == 0 || c == 0 { 40 if !t { 41 // Fall back to thermal if CPUID returns '0' as this can be overridden 42 // in some hypervisors. 43 a, b, c, _ := cpuid(0x6, 0) // Thermal and power management 44 if t = a <= 4 && (b == 0 || c == 0); !t { 45 return false 46 } 47 } 48 } 49 // We don't need to check the name /but/ we're just making sure that the 50 // name is not all zero's first. 51 n := [16]byte{ 52 byte((b >> 0)), byte((b >> 8)), byte((b >> 16)), byte((b >> 24)), 53 byte((c >> 0)), byte((c >> 8)), byte((c >> 16)), byte((c >> 24)), 54 byte((d >> 0)), byte((d >> 8)), byte((d >> 16)), byte((d >> 24)), 55 } 56 var z int 57 for i := range n { 58 if n[i] > 0 { 59 continue 60 } 61 z++ 62 } 63 // Less than 10 chars are zeros. 64 if z < 10 { 65 return true 66 } 67 // Fallback to temp. 68 return t 69 } 70 71 // cpuid is implemented in ASM file "cpu.s" 72 func cpuid(arg1 uint32, arg2 uint32) (uint32, uint32, uint32, uint32)