summaryrefslogtreecommitdiff
path: root/usr/src/uts
diff options
context:
space:
mode:
authorPatrick Mooney <pmooney@pfmooney.com>2020-05-05 15:31:34 -0500
committerPatrick Mooney <pmooney@pfmooney.com>2020-05-22 02:56:09 +0000
commit3c5f2a9de9c6554ce899ad4ebf7978ea7293994a (patch)
tree93b2f9726b921d07911adaccd4df1de79c49e8c9 /usr/src/uts
parent537911b676ea740315ce9055d857ea1d626e6fe7 (diff)
downloadillumos-gate-3c5f2a9de9c6554ce899ad4ebf7978ea7293994a.tar.gz
12746 x86_emulate_cpuid() should clear upper 32 bits
Reviewed by: John Levon <john.levon@joyent.com> Reviewed by: Mike Zeller <mike.zeller@joyent.com> Reviewed by: Toomas Soome <tsoome@me.com> Approved by: Dan McDonald <danmcd@joyent.com>
Diffstat (limited to 'usr/src/uts')
-rw-r--r--usr/src/uts/i86pc/io/vmm/amd/svm.c8
-rw-r--r--usr/src/uts/i86pc/io/vmm/intel/vmx.c9
-rw-r--r--usr/src/uts/i86pc/io/vmm/x86.c75
-rw-r--r--usr/src/uts/i86pc/io/vmm/x86.h4
4 files changed, 51 insertions, 45 deletions
diff --git a/usr/src/uts/i86pc/io/vmm/amd/svm.c b/usr/src/uts/i86pc/io/vmm/amd/svm.c
index 25dc3a63fa..80d76ab640 100644
--- a/usr/src/uts/i86pc/io/vmm/amd/svm.c
+++ b/usr/src/uts/i86pc/io/vmm/amd/svm.c
@@ -28,6 +28,7 @@
/*
* Copyright 2018 Joyent, Inc.
+ * Copyright 2020 Oxide Computer Company
*/
#include <sys/cdefs.h>
@@ -1518,11 +1519,8 @@ svm_vmexit(struct svm_softc *svm_sc, int vcpu, struct vm_exit *vmexit)
break;
case VMCB_EXIT_CPUID:
vmm_stat_incr(svm_sc->vm, vcpu, VMEXIT_CPUID, 1);
- handled = x86_emulate_cpuid(svm_sc->vm, vcpu,
- (uint32_t *)&state->rax,
- (uint32_t *)&ctx->sctx_rbx,
- (uint32_t *)&ctx->sctx_rcx,
- (uint32_t *)&ctx->sctx_rdx);
+ handled = x86_emulate_cpuid(svm_sc->vm, vcpu, &state->rax,
+ &ctx->sctx_rbx, &ctx->sctx_rcx, &ctx->sctx_rdx);
break;
case VMCB_EXIT_HLT:
vmm_stat_incr(svm_sc->vm, vcpu, VMEXIT_HLT, 1);
diff --git a/usr/src/uts/i86pc/io/vmm/intel/vmx.c b/usr/src/uts/i86pc/io/vmm/intel/vmx.c
index ce42ff8c9c..eea036b253 100644
--- a/usr/src/uts/i86pc/io/vmm/intel/vmx.c
+++ b/usr/src/uts/i86pc/io/vmm/intel/vmx.c
@@ -40,6 +40,7 @@
*
* Copyright 2015 Pluribus Networks Inc.
* Copyright 2018 Joyent, Inc.
+ * Copyright 2020 Oxide Computer Company
*/
#include <sys/cdefs.h>
@@ -1244,11 +1245,9 @@ vmx_handle_cpuid(struct vm *vm, int vcpu, struct vmxctx *vmxctx)
int handled;
#endif
- handled = x86_emulate_cpuid(vm, vcpu,
- (uint32_t*)(&vmxctx->guest_rax),
- (uint32_t*)(&vmxctx->guest_rbx),
- (uint32_t*)(&vmxctx->guest_rcx),
- (uint32_t*)(&vmxctx->guest_rdx));
+ handled = x86_emulate_cpuid(vm, vcpu, (uint64_t *)&vmxctx->guest_rax,
+ (uint64_t *)&vmxctx->guest_rbx, (uint64_t *)&vmxctx->guest_rcx,
+ (uint64_t *)&vmxctx->guest_rdx);
return (handled);
}
diff --git a/usr/src/uts/i86pc/io/vmm/x86.c b/usr/src/uts/i86pc/io/vmm/x86.c
index d74f866013..6213173587 100644
--- a/usr/src/uts/i86pc/io/vmm/x86.c
+++ b/usr/src/uts/i86pc/io/vmm/x86.c
@@ -39,6 +39,7 @@
*
* Copyright 2014 Pluribus Networks Inc.
* Copyright 2018 Joyent, Inc.
+ * Copyright 2020 Oxide Computer Company
*/
#include <sys/cdefs.h>
@@ -90,34 +91,39 @@ log2(u_int x)
}
int
-x86_emulate_cpuid(struct vm *vm, int vcpu_id,
- uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
+x86_emulate_cpuid(struct vm *vm, int vcpu_id, uint64_t *rax, uint64_t *rbx,
+ uint64_t *rcx, uint64_t *rdx)
{
const struct xsave_limits *limits;
uint64_t cr4;
int error, enable_invpcid, level, width = 0, x2apic_id = 0;
- unsigned int func, regs[4], logical_cpus = 0;
+ unsigned int func, regs[4], logical_cpus = 0, param;
enum x2apic_state x2apic_state;
uint16_t cores, maxcpus, sockets, threads;
- VCPU_CTR2(vm, vcpu_id, "cpuid %#x,%#x", *eax, *ecx);
+ /*
+ * The function of CPUID is controlled through the provided value of
+ * %eax (and secondarily %ecx, for certain leaf data).
+ */
+ func = (uint32_t)*rax;
+ param = (uint32_t)*rcx;
+
+ VCPU_CTR2(vm, vcpu_id, "cpuid %#x,%#x", func, param);
/*
* Requests for invalid CPUID levels should map to the highest
* available level instead.
*/
- if (cpu_exthigh != 0 && *eax >= 0x80000000) {
- if (*eax > cpu_exthigh)
- *eax = cpu_exthigh;
- } else if (*eax >= 0x40000000) {
- if (*eax > CPUID_VM_HIGH)
- *eax = CPUID_VM_HIGH;
- } else if (*eax > cpu_high) {
- *eax = cpu_high;
+ if (cpu_exthigh != 0 && func >= 0x80000000) {
+ if (func > cpu_exthigh)
+ func = cpu_exthigh;
+ } else if (func >= 0x40000000) {
+ if (func > CPUID_VM_HIGH)
+ func = CPUID_VM_HIGH;
+ } else if (func > cpu_high) {
+ func = cpu_high;
}
- func = *eax;
-
/*
* In general the approach used for CPU topology is to
* advertise a flat topology where all CPUs are packages with
@@ -135,10 +141,10 @@ x86_emulate_cpuid(struct vm *vm, int vcpu_id,
case CPUID_8000_0003:
case CPUID_8000_0004:
case CPUID_8000_0006:
- cpuid_count(*eax, *ecx, regs);
+ cpuid_count(func, param, regs);
break;
case CPUID_8000_0008:
- cpuid_count(*eax, *ecx, regs);
+ cpuid_count(func, param, regs);
if (vmm_is_amd()) {
/*
* As on Intel (0000_0007:0, EDX), mask out
@@ -169,7 +175,7 @@ x86_emulate_cpuid(struct vm *vm, int vcpu_id,
break;
case CPUID_8000_0001:
- cpuid_count(*eax, *ecx, regs);
+ cpuid_count(func, param, regs);
/*
* Hide SVM from guest.
@@ -263,7 +269,7 @@ x86_emulate_cpuid(struct vm *vm, int vcpu_id,
*/
vm_get_topology(vm, &sockets, &cores, &threads,
&maxcpus);
- switch (*ecx) {
+ switch (param) {
case 0:
logical_cpus = threads;
level = 1;
@@ -408,7 +414,7 @@ x86_emulate_cpuid(struct vm *vm, int vcpu_id,
break;
case CPUID_0000_0004:
- cpuid_count(*eax, *ecx, regs);
+ cpuid_count(func, param, regs);
if (regs[0] || regs[1] || regs[2] || regs[3]) {
vm_get_topology(vm, &sockets, &cores, &threads,
@@ -437,8 +443,8 @@ x86_emulate_cpuid(struct vm *vm, int vcpu_id,
regs[3] = 0;
/* leaf 0 */
- if (*ecx == 0) {
- cpuid_count(*eax, *ecx, regs);
+ if (param == 0) {
+ cpuid_count(func, param, regs);
/* Only leaf 0 is supported */
regs[0] = 0;
@@ -491,21 +497,21 @@ x86_emulate_cpuid(struct vm *vm, int vcpu_id,
if (vmm_is_intel()) {
vm_get_topology(vm, &sockets, &cores, &threads,
&maxcpus);
- if (*ecx == 0) {
+ if (param == 0) {
logical_cpus = threads;
width = log2(logical_cpus);
level = CPUID_TYPE_SMT;
x2apic_id = vcpu_id;
}
- if (*ecx == 1) {
+ if (param == 1) {
logical_cpus = threads * cores;
width = log2(logical_cpus);
level = CPUID_TYPE_CORE;
x2apic_id = vcpu_id;
}
- if (!cpuid_leaf_b || *ecx >= 2) {
+ if (!cpuid_leaf_b || param >= 2) {
width = 0;
logical_cpus = 0;
level = 0;
@@ -514,7 +520,7 @@ x86_emulate_cpuid(struct vm *vm, int vcpu_id,
regs[0] = width & 0x1f;
regs[1] = logical_cpus & 0xffff;
- regs[2] = (level << 8) | (*ecx & 0xff);
+ regs[2] = (level << 8) | (param & 0xff);
regs[3] = x2apic_id;
} else {
regs[0] = 0;
@@ -534,8 +540,8 @@ x86_emulate_cpuid(struct vm *vm, int vcpu_id,
break;
}
- cpuid_count(*eax, *ecx, regs);
- switch (*ecx) {
+ cpuid_count(func, param, regs);
+ switch (param) {
case 0:
/*
* Only permit the guest to use bits
@@ -565,7 +571,7 @@ x86_emulate_cpuid(struct vm *vm, int vcpu_id,
* pass through as-is, otherwise return
* all zeroes.
*/
- if (!(limits->xcr0_allowed & (1ul << *ecx))) {
+ if (!(limits->xcr0_allowed & (1ul << param))) {
regs[0] = 0;
regs[1] = 0;
regs[2] = 0;
@@ -590,14 +596,17 @@ default_leaf:
* how many unhandled leaf values have been seen.
*/
atomic_add_long(&bhyve_xcpuids, 1);
- cpuid_count(*eax, *ecx, regs);
+ cpuid_count(func, param, regs);
break;
}
- *eax = regs[0];
- *ebx = regs[1];
- *ecx = regs[2];
- *edx = regs[3];
+ /*
+ * CPUID clears the upper 32-bits of the long-mode registers.
+ */
+ *rax = regs[0];
+ *rbx = regs[1];
+ *rcx = regs[2];
+ *rdx = regs[3];
return (1);
}
diff --git a/usr/src/uts/i86pc/io/vmm/x86.h b/usr/src/uts/i86pc/io/vmm/x86.h
index 0d70c04fd8..cb8e12fcd2 100644
--- a/usr/src/uts/i86pc/io/vmm/x86.h
+++ b/usr/src/uts/i86pc/io/vmm/x86.h
@@ -63,8 +63,8 @@
*/
#define CPUID_0000_0001_FEAT0_VMX (1<<5)
-int x86_emulate_cpuid(struct vm *vm, int vcpu_id, uint32_t *eax, uint32_t *ebx,
- uint32_t *ecx, uint32_t *edx);
+int x86_emulate_cpuid(struct vm *vm, int vcpu_id, uint64_t *rax, uint64_t *rbx,
+ uint64_t *rcx, uint64_t *rdx);
enum vm_cpuid_capability {
VCC_NONE,