Changeset View
Changeset View
Standalone View
Standalone View
head/sys/amd64/vmm/x86.c
Show First 20 Lines • Show All 54 Lines • ▼ Show 20 Lines | |||||
#define CPUID_VM_HIGH 0x40000000 | #define CPUID_VM_HIGH 0x40000000 | ||||
static const char bhyve_id[12] = "bhyve bhyve "; | static const char bhyve_id[12] = "bhyve bhyve "; | ||||
static uint64_t bhyve_xcpuids; | static uint64_t bhyve_xcpuids; | ||||
SYSCTL_ULONG(_hw_vmm, OID_AUTO, bhyve_xcpuids, CTLFLAG_RW, &bhyve_xcpuids, 0, | SYSCTL_ULONG(_hw_vmm, OID_AUTO, bhyve_xcpuids, CTLFLAG_RW, &bhyve_xcpuids, 0, | ||||
"Number of times an unknown cpuid leaf was accessed"); | "Number of times an unknown cpuid leaf was accessed"); | ||||
/* | #if __FreeBSD_version < 1200060 /* Remove after 11 EOL helps MFCing */ | ||||
* The default CPU topology is a single thread per package. | extern u_int threads_per_core; | ||||
*/ | |||||
static u_int threads_per_core = 1; | |||||
SYSCTL_UINT(_hw_vmm_topology, OID_AUTO, threads_per_core, CTLFLAG_RDTUN, | SYSCTL_UINT(_hw_vmm_topology, OID_AUTO, threads_per_core, CTLFLAG_RDTUN, | ||||
&threads_per_core, 0, NULL); | &threads_per_core, 0, NULL); | ||||
static u_int cores_per_package = 1; | extern u_int cores_per_package; | ||||
SYSCTL_UINT(_hw_vmm_topology, OID_AUTO, cores_per_package, CTLFLAG_RDTUN, | SYSCTL_UINT(_hw_vmm_topology, OID_AUTO, cores_per_package, CTLFLAG_RDTUN, | ||||
&cores_per_package, 0, NULL); | &cores_per_package, 0, NULL); | ||||
#endif | |||||
static int cpuid_leaf_b = 1; | static int cpuid_leaf_b = 1; | ||||
SYSCTL_INT(_hw_vmm_topology, OID_AUTO, cpuid_leaf_b, CTLFLAG_RDTUN, | SYSCTL_INT(_hw_vmm_topology, OID_AUTO, cpuid_leaf_b, CTLFLAG_RDTUN, | ||||
&cpuid_leaf_b, 0, NULL); | &cpuid_leaf_b, 0, NULL); | ||||
/* | /* | ||||
* Round up to the next power of two, if necessary, and then take log2. | * Round up to the next power of two, if necessary, and then take log2. | ||||
* Returns -1 if argument is zero. | * Returns -1 if argument is zero. | ||||
Show All 9 Lines | |||||
x86_emulate_cpuid(struct vm *vm, int vcpu_id, | x86_emulate_cpuid(struct vm *vm, int vcpu_id, | ||||
uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx) | uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx) | ||||
{ | { | ||||
const struct xsave_limits *limits; | const struct xsave_limits *limits; | ||||
uint64_t cr4; | uint64_t cr4; | ||||
int error, enable_invpcid, level, width, x2apic_id; | int error, enable_invpcid, level, width, x2apic_id; | ||||
unsigned int func, regs[4], logical_cpus; | unsigned int func, regs[4], logical_cpus; | ||||
enum x2apic_state x2apic_state; | enum x2apic_state x2apic_state; | ||||
uint16_t cores, maxcpus, sockets, threads; | |||||
VCPU_CTR2(vm, vcpu_id, "cpuid %#x,%#x", *eax, *ecx); | VCPU_CTR2(vm, vcpu_id, "cpuid %#x,%#x", *eax, *ecx); | ||||
/* | /* | ||||
* Requests for invalid CPUID levels should map to the highest | * Requests for invalid CPUID levels should map to the highest | ||||
* available level instead. | * available level instead. | ||||
*/ | */ | ||||
if (cpu_exthigh != 0 && *eax >= 0x80000000) { | if (cpu_exthigh != 0 && *eax >= 0x80000000) { | ||||
Show All 31 Lines | case CPUID_8000_0008: | ||||
cpuid_count(*eax, *ecx, regs); | cpuid_count(*eax, *ecx, regs); | ||||
if (vmm_is_amd()) { | if (vmm_is_amd()) { | ||||
/* | /* | ||||
* XXX this might appear silly because AMD | * XXX this might appear silly because AMD | ||||
* cpus don't have threads. | * cpus don't have threads. | ||||
* | * | ||||
* However this matches the logical cpus as | * However this matches the logical cpus as | ||||
* advertised by leaf 0x1 and will work even | * advertised by leaf 0x1 and will work even | ||||
* if the 'threads_per_core' tunable is set | * if threads is set incorrectly on an AMD host. | ||||
* incorrectly on an AMD host. | |||||
*/ | */ | ||||
logical_cpus = threads_per_core * | vm_get_topology(vm, &sockets, &cores, &threads, | ||||
cores_per_package; | &maxcpus); | ||||
logical_cpus = threads * cores; | |||||
regs[2] = logical_cpus - 1; | regs[2] = logical_cpus - 1; | ||||
} | } | ||||
break; | break; | ||||
case CPUID_8000_0001: | case CPUID_8000_0001: | ||||
cpuid_count(*eax, *ecx, regs); | cpuid_count(*eax, *ecx, regs); | ||||
/* | /* | ||||
▲ Show 20 Lines • Show All 142 Lines • ▼ Show 20 Lines | case CPUID_0000_0001: | ||||
/* | /* | ||||
* Advertise the Machine Check and MTRR capability. | * Advertise the Machine Check and MTRR capability. | ||||
* | * | ||||
* Some guest OSes (e.g. Windows) will not boot if | * Some guest OSes (e.g. Windows) will not boot if | ||||
* these features are absent. | * these features are absent. | ||||
*/ | */ | ||||
regs[3] |= (CPUID_MCA | CPUID_MCE | CPUID_MTRR); | regs[3] |= (CPUID_MCA | CPUID_MCE | CPUID_MTRR); | ||||
logical_cpus = threads_per_core * cores_per_package; | vm_get_topology(vm, &sockets, &cores, &threads, | ||||
&maxcpus); | |||||
logical_cpus = threads * cores; | |||||
regs[1] &= ~CPUID_HTT_CORES; | regs[1] &= ~CPUID_HTT_CORES; | ||||
regs[1] |= (logical_cpus & 0xff) << 16; | regs[1] |= (logical_cpus & 0xff) << 16; | ||||
regs[3] |= CPUID_HTT; | regs[3] |= CPUID_HTT; | ||||
break; | break; | ||||
case CPUID_0000_0004: | case CPUID_0000_0004: | ||||
cpuid_count(*eax, *ecx, regs); | cpuid_count(*eax, *ecx, regs); | ||||
if (regs[0] || regs[1] || regs[2] || regs[3]) { | if (regs[0] || regs[1] || regs[2] || regs[3]) { | ||||
vm_get_topology(vm, &sockets, &cores, &threads, | |||||
&maxcpus); | |||||
regs[0] &= 0x3ff; | regs[0] &= 0x3ff; | ||||
regs[0] |= (cores_per_package - 1) << 26; | regs[0] |= (cores - 1) << 26; | ||||
/* | /* | ||||
* Cache topology: | * Cache topology: | ||||
* - L1 and L2 are shared only by the logical | * - L1 and L2 are shared only by the logical | ||||
* processors in a single core. | * processors in a single core. | ||||
* - L3 and above are shared by all logical | * - L3 and above are shared by all logical | ||||
* processors in the package. | * processors in the package. | ||||
*/ | */ | ||||
logical_cpus = threads_per_core; | logical_cpus = threads; | ||||
level = (regs[0] >> 5) & 0x7; | level = (regs[0] >> 5) & 0x7; | ||||
if (level >= 3) | if (level >= 3) | ||||
logical_cpus *= cores_per_package; | logical_cpus *= cores; | ||||
regs[0] |= (logical_cpus - 1) << 14; | regs[0] |= (logical_cpus - 1) << 14; | ||||
} | } | ||||
break; | break; | ||||
case CPUID_0000_0007: | case CPUID_0000_0007: | ||||
regs[0] = 0; | regs[0] = 0; | ||||
regs[1] = 0; | regs[1] = 0; | ||||
regs[2] = 0; | regs[2] = 0; | ||||
▲ Show 20 Lines • Show All 45 Lines • ▼ Show 20 Lines | case CPUID_0000_000A: | ||||
regs[2] = 0; | regs[2] = 0; | ||||
regs[3] = 0; | regs[3] = 0; | ||||
break; | break; | ||||
case CPUID_0000_000B: | case CPUID_0000_000B: | ||||
/* | /* | ||||
* Processor topology enumeration | * Processor topology enumeration | ||||
*/ | */ | ||||
vm_get_topology(vm, &sockets, &cores, &threads, | |||||
&maxcpus); | |||||
if (*ecx == 0) { | if (*ecx == 0) { | ||||
logical_cpus = threads_per_core; | logical_cpus = threads; | ||||
width = log2(logical_cpus); | width = log2(logical_cpus); | ||||
level = CPUID_TYPE_SMT; | level = CPUID_TYPE_SMT; | ||||
x2apic_id = vcpu_id; | x2apic_id = vcpu_id; | ||||
} | } | ||||
if (*ecx == 1) { | if (*ecx == 1) { | ||||
logical_cpus = threads_per_core * | logical_cpus = threads * cores; | ||||
cores_per_package; | |||||
width = log2(logical_cpus); | width = log2(logical_cpus); | ||||
level = CPUID_TYPE_CORE; | level = CPUID_TYPE_CORE; | ||||
x2apic_id = vcpu_id; | x2apic_id = vcpu_id; | ||||
} | } | ||||
if (!cpuid_leaf_b || *ecx >= 2) { | if (!cpuid_leaf_b || *ecx >= 2) { | ||||
width = 0; | width = 0; | ||||
logical_cpus = 0; | logical_cpus = 0; | ||||
▲ Show 20 Lines • Show All 117 Lines • Show Last 20 Lines |