summaryrefslogtreecommitdiff
path: root/usr/src/uts/i86pc
diff options
context:
space:
mode:
authorPatrick Mooney <pmooney@pfmooney.com>2019-06-04 21:27:31 +0000
committerPatrick Mooney <pmooney@pfmooney.com>2019-06-14 16:28:50 +0000
commitc3cbf49c8d881ba57710e7e8b70aa6275bc5fc44 (patch)
tree549f85b42dcc7444792f88104bc0fd374f0b15ef /usr/src/uts/i86pc
parentde37b27aa9332f8b33b7b4041b3bdaa6894dcde9 (diff)
downloadillumos-joyent-c3cbf49c8d881ba57710e7e8b70aa6275bc5fc44.tar.gz
OS-7819 bhyve upstream sync 2019 June
Reviewed by: Hans Rosenfeld <hans.rosenfeld@joyent.com> Reviewed by: Mike Gerdts <mike.gerdts@joyent.com> Approved by: John Levon <john.levon@joyent.com>
Diffstat (limited to 'usr/src/uts/i86pc')
-rw-r--r--usr/src/uts/i86pc/io/vmm/README.sync17
-rw-r--r--usr/src/uts/i86pc/io/vmm/amd/svm.c4
-rw-r--r--usr/src/uts/i86pc/io/vmm/intel/vmx.c20
-rw-r--r--usr/src/uts/i86pc/io/vmm/io/iommu.c4
-rw-r--r--usr/src/uts/i86pc/io/vmm/io/vlapic.c11
-rw-r--r--usr/src/uts/i86pc/io/vmm/vmm.c92
-rw-r--r--usr/src/uts/i86pc/io/vmm/vmm_instruction_emul.c100
-rw-r--r--usr/src/uts/i86pc/io/vmm/vmm_lapic.c4
-rw-r--r--usr/src/uts/i86pc/io/vmm/vmm_sol_dev.c20
-rw-r--r--usr/src/uts/i86pc/io/vmm/vmm_stat.c2
-rw-r--r--usr/src/uts/i86pc/io/vmm/x86.c1
-rw-r--r--usr/src/uts/i86pc/sys/vmm.h1
12 files changed, 203 insertions, 73 deletions
diff --git a/usr/src/uts/i86pc/io/vmm/README.sync b/usr/src/uts/i86pc/io/vmm/README.sync
index 676fdd3a9d..1cddfd829e 100644
--- a/usr/src/uts/i86pc/io/vmm/README.sync
+++ b/usr/src/uts/i86pc/io/vmm/README.sync
@@ -2,12 +2,17 @@ The bhyve kernel module and its associated userland consumers have been updated
to the latest upstream FreeBSD sources as of:
-commit 6b1bb0edb4792cc3d4e6b71c4a80e99438081d5d
-Author: imp <imp@FreeBSD.org>
-Date: Tue Feb 12 19:05:09 2019 +0000
+commit 3b9cb80b242682690203709aaff4eafae41c138f
+Author: jhb <jhb@FreeBSD.org>
+Date: Mon Jun 3 23:17:35 2019 +0000
- Revert r343077 until the license issues surrounding it can be resolved.
+ Emulate the AMD MSR_LS_CFG MSR used for various Ryzen errata.
- Approved by: core@
+ Writes are ignored and reads always return zero.
-Which corresponds to SVN revision: 344057
+ Submitted by: José Albornoz <jojo@eljojo.net> (write-only version)
+ Reviewed by: Patrick Mooney, cem
+ MFC after: 2 weeks
+ Differential Revision: https://reviews.freebsd.org/D19506
+
+Which corresponds to SVN revision: 348592
diff --git a/usr/src/uts/i86pc/io/vmm/amd/svm.c b/usr/src/uts/i86pc/io/vmm/amd/svm.c
index ca9ed9e4e1..114eec365a 100644
--- a/usr/src/uts/i86pc/io/vmm/amd/svm.c
+++ b/usr/src/uts/i86pc/io/vmm/amd/svm.c
@@ -574,6 +574,7 @@ svm_vminit(struct vm *vm, pmap_t pmap)
struct svm_vcpu *vcpu;
vm_paddr_t msrpm_pa, iopm_pa, pml4_pa;
int i;
+ uint16_t maxcpus;
svm_sc = malloc(sizeof (*svm_sc), M_SVM, M_WAITOK | M_ZERO);
if (((uintptr_t)svm_sc & PAGE_MASK) != 0)
@@ -627,7 +628,8 @@ svm_vminit(struct vm *vm, pmap_t pmap)
iopm_pa = vtophys(svm_sc->iopm_bitmap);
msrpm_pa = vtophys(svm_sc->msr_bitmap);
pml4_pa = svm_sc->nptp;
- for (i = 0; i < VM_MAXCPU; i++) {
+ maxcpus = vm_get_maxcpus(svm_sc->vm);
+ for (i = 0; i < maxcpus; i++) {
vcpu = svm_get_vcpu(svm_sc, i);
vcpu->nextrip = ~0;
vcpu->lastcpu = NOCPU;
diff --git a/usr/src/uts/i86pc/io/vmm/intel/vmx.c b/usr/src/uts/i86pc/io/vmm/intel/vmx.c
index 4a636dcea0..cf6b0e69c3 100644
--- a/usr/src/uts/i86pc/io/vmm/intel/vmx.c
+++ b/usr/src/uts/i86pc/io/vmm/intel/vmx.c
@@ -3,6 +3,7 @@
*
* Copyright (c) 2011 NetApp, Inc.
* All rights reserved.
+ * Copyright (c) 2018 Joyent, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -1044,6 +1045,7 @@ vmx_vminit(struct vm *vm, pmap_t pmap)
struct vmx *vmx;
struct vmcs *vmcs;
uint32_t exc_bitmap;
+ uint16_t maxcpus;
vmx = malloc(sizeof(struct vmx), M_VMX, M_WAITOK | M_ZERO);
if ((uintptr_t)vmx & PAGE_MASK) {
@@ -1105,7 +1107,8 @@ vmx_vminit(struct vm *vm, pmap_t pmap)
KASSERT(error == 0, ("vm_map_mmio(apicbase) error %d", error));
}
- for (i = 0; i < VM_MAXCPU; i++) {
+ maxcpus = vm_get_maxcpus(vm);
+ for (i = 0; i < maxcpus; i++) {
#ifndef __FreeBSD__
/*
* Cache physical address lookups for various components which
@@ -3472,11 +3475,13 @@ vmx_vmcleanup(void *arg)
{
int i;
struct vmx *vmx = arg;
+ uint16_t maxcpus;
if (apic_access_virtualization(vmx, 0))
vm_unmap_mmio(vmx->vm, DEFAULT_APIC_BASE, PAGE_SIZE);
- for (i = 0; i < VM_MAXCPU; i++)
+ maxcpus = vm_get_maxcpus(vmx->vm);
+ for (i = 0; i < maxcpus; i++)
vpid_free(vmx->state[i].vpid);
free(vmx, M_VMX);
@@ -3873,7 +3878,7 @@ struct vlapic_vtx {
struct vlapic vlapic;
struct pir_desc *pir_desc;
struct vmx *vmx;
- uint_t pending_prio;
+ u_int pending_prio;
};
#define VPR_PRIO_BIT(vpr) (1 << ((vpr) >> 4))
@@ -3935,8 +3940,8 @@ vmx_set_intr_ready(struct vlapic *vlapic, int vector, bool level)
notify = 1;
vlapic_vtx->pending_prio = 0;
} else {
- const uint_t old_prio = vlapic_vtx->pending_prio;
- const uint_t prio_bit = VPR_PRIO_BIT(vector & APIC_TPR_INT);
+ const u_int old_prio = vlapic_vtx->pending_prio;
+ const u_int prio_bit = VPR_PRIO_BIT(vector & APIC_TPR_INT);
if ((old_prio & prio_bit) == 0 && prio_bit > old_prio) {
atomic_set_int(&vlapic_vtx->pending_prio, prio_bit);
@@ -4014,6 +4019,7 @@ vmx_pending_intr(struct vlapic *vlapic, int *vecptr)
break;
}
}
+
/*
* If the highest-priority pending interrupt falls short of the
* processor priority of this vCPU, ensure that 'pending_prio' does not
@@ -4021,8 +4027,8 @@ vmx_pending_intr(struct vlapic *vlapic, int *vecptr)
* from incurring a notification later.
*/
if (vpr <= ppr) {
- const uint_t prio_bit = VPR_PRIO_BIT(vpr);
- const uint_t old = vlapic_vtx->pending_prio;
+ const u_int prio_bit = VPR_PRIO_BIT(vpr);
+ const u_int old = vlapic_vtx->pending_prio;
if (old > prio_bit && (old & prio_bit) == 0) {
vlapic_vtx->pending_prio = prio_bit;
diff --git a/usr/src/uts/i86pc/io/vmm/io/iommu.c b/usr/src/uts/i86pc/io/vmm/io/iommu.c
index 5f686d3c62..b949573fe2 100644
--- a/usr/src/uts/i86pc/io/vmm/io/iommu.c
+++ b/usr/src/uts/i86pc/io/vmm/io/iommu.c
@@ -32,10 +32,10 @@
__FBSDID("$FreeBSD$");
#include <sys/param.h>
-#include <sys/types.h>
-#include <sys/systm.h>
#include <sys/bus.h>
+#include <sys/eventhandler.h>
#include <sys/sysctl.h>
+#include <sys/systm.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
diff --git a/usr/src/uts/i86pc/io/vmm/io/vlapic.c b/usr/src/uts/i86pc/io/vmm/io/vlapic.c
index 6a5fcc5d4c..98dfc6ee56 100644
--- a/usr/src/uts/i86pc/io/vmm/io/vlapic.c
+++ b/usr/src/uts/i86pc/io/vmm/io/vlapic.c
@@ -853,7 +853,7 @@ vlapic_calcdest(struct vm *vm, cpuset_t *dmask, uint32_t dest, bool phys,
*/
CPU_ZERO(dmask);
vcpuid = vm_apicid2vcpuid(vm, dest);
- if (vcpuid < VM_MAXCPU)
+ if (vcpuid < vm_get_maxcpus(vm))
CPU_SET(vcpuid, dmask);
} else {
/*
@@ -980,6 +980,7 @@ vlapic_icrlo_write_handler(struct vlapic *vlapic, bool *retu)
struct vlapic *vlapic2;
struct vm_exit *vmexit;
struct LAPIC *lapic;
+ uint16_t maxcpus;
lapic = vlapic->apic_page;
lapic->icr_lo &= ~APIC_DELSTAT_PEND;
@@ -1041,11 +1042,12 @@ vlapic_icrlo_write_handler(struct vlapic *vlapic, bool *retu)
return (0); /* handled completely in the kernel */
}
+ maxcpus = vm_get_maxcpus(vlapic->vm);
if (mode == APIC_DELMODE_INIT) {
if ((icrval & APIC_LEVEL_MASK) == APIC_LEVEL_DEASSERT)
return (0);
- if (vlapic->vcpuid == 0 && dest != 0 && dest < VM_MAXCPU) {
+ if (vlapic->vcpuid == 0 && dest != 0 && dest < maxcpus) {
vlapic2 = vm_lapic(vlapic->vm, dest);
/* move from INIT to waiting-for-SIPI state */
@@ -1058,7 +1060,7 @@ vlapic_icrlo_write_handler(struct vlapic *vlapic, bool *retu)
}
if (mode == APIC_DELMODE_STARTUP) {
- if (vlapic->vcpuid == 0 && dest != 0 && dest < VM_MAXCPU) {
+ if (vlapic->vcpuid == 0 && dest != 0 && dest < maxcpus) {
vlapic2 = vm_lapic(vlapic->vm, dest);
/*
@@ -1467,7 +1469,8 @@ void
vlapic_init(struct vlapic *vlapic)
{
KASSERT(vlapic->vm != NULL, ("vlapic_init: vm is not initialized"));
- KASSERT(vlapic->vcpuid >= 0 && vlapic->vcpuid < VM_MAXCPU,
+ KASSERT(vlapic->vcpuid >= 0 &&
+ vlapic->vcpuid < vm_get_maxcpus(vlapic->vm),
("vlapic_init: vcpuid is not initialized"));
KASSERT(vlapic->apic_page != NULL, ("vlapic_init: apic_page is not "
"initialized"));
diff --git a/usr/src/uts/i86pc/io/vmm/vmm.c b/usr/src/uts/i86pc/io/vmm/vmm.c
index 14e2fc4e60..11915220d2 100644
--- a/usr/src/uts/i86pc/io/vmm/vmm.c
+++ b/usr/src/uts/i86pc/io/vmm/vmm.c
@@ -334,7 +334,7 @@ vcpu_init(struct vm *vm, int vcpu_id, bool create)
{
struct vcpu *vcpu;
- KASSERT(vcpu_id >= 0 && vcpu_id < VM_MAXCPU,
+ KASSERT(vcpu_id >= 0 && vcpu_id < vm->maxcpus,
("vcpu_init: invalid vcpu %d", vcpu_id));
vcpu = &vm->vcpu[vcpu_id];
@@ -378,7 +378,7 @@ vm_exitinfo(struct vm *vm, int cpuid)
{
struct vcpu *vcpu;
- if (cpuid < 0 || cpuid >= VM_MAXCPU)
+ if (cpuid < 0 || cpuid >= vm->maxcpus)
panic("vm_exitinfo: invalid cpuid %d", cpuid);
vcpu = &vm->vcpu[cpuid];
@@ -546,12 +546,12 @@ vm_init(struct vm *vm, bool create)
vm->suspend = 0;
CPU_ZERO(&vm->suspended_cpus);
- for (i = 0; i < VM_MAXCPU; i++)
+ for (i = 0; i < vm->maxcpus; i++)
vcpu_init(vm, i, create);
#ifndef __FreeBSD__
tsc_off = (uint64_t)(-(int64_t)rdtsc());
- for (i = 0; i < VM_MAXCPU; i++) {
+ for (i = 0; i < vm->maxcpus; i++) {
vm->vcpu[i].tsc_offset = tsc_off;
}
#endif /* __FreeBSD__ */
@@ -591,7 +591,7 @@ vm_create(const char *name, struct vm **retvm)
vm->sockets = 1;
vm->cores = cores_per_package; /* XXX backwards compatibility */
vm->threads = threads_per_core; /* XXX backwards compatibility */
- vm->maxcpus = 0; /* XXX not implemented */
+ vm->maxcpus = VM_MAXCPU; /* XXX temp to keep code working */
vm_init(vm, true);
@@ -609,19 +609,25 @@ vm_get_topology(struct vm *vm, uint16_t *sockets, uint16_t *cores,
*maxcpus = vm->maxcpus;
}
+uint16_t
+vm_get_maxcpus(struct vm *vm)
+{
+ return (vm->maxcpus);
+}
+
int
vm_set_topology(struct vm *vm, uint16_t sockets, uint16_t cores,
uint16_t threads, uint16_t maxcpus)
{
if (maxcpus != 0)
return (EINVAL); /* XXX remove when supported */
- if ((sockets * cores * threads) > VM_MAXCPU)
+ if ((sockets * cores * threads) > vm->maxcpus)
return (EINVAL);
/* XXX need to check sockets * cores * threads == vCPU, how? */
vm->sockets = sockets;
vm->cores = cores;
vm->threads = threads;
- vm->maxcpus = maxcpus;
+ vm->maxcpus = VM_MAXCPU; /* XXX temp to keep code working */
return(0);
}
@@ -646,7 +652,7 @@ vm_cleanup(struct vm *vm, bool destroy)
vatpic_cleanup(vm->vatpic);
vioapic_cleanup(vm->vioapic);
- for (i = 0; i < VM_MAXCPU; i++)
+ for (i = 0; i < vm->maxcpus; i++)
vcpu_cleanup(vm, i, destroy);
VMCLEANUP(vm->cookie);
@@ -918,7 +924,8 @@ vm_mmap_memseg(struct vm *vm, vm_paddr_t gpa, int segid, vm_ooffset_t first,
VM_MAP_WIRE_USER | VM_MAP_WIRE_NOHOLES);
if (error != KERN_SUCCESS) {
vm_map_remove(&vm->vmspace->vm_map, gpa, gpa + len);
- return (EFAULT);
+ return (error == KERN_RESOURCE_SHORTAGE ? ENOMEM :
+ EFAULT);
}
}
@@ -1156,9 +1163,9 @@ vm_gpa_hold(struct vm *vm, int vcpuid, vm_paddr_t gpa, size_t len, int reqprot,
* guaranteed if at least one vcpu is in the VCPU_FROZEN state.
*/
int state;
- KASSERT(vcpuid >= -1 && vcpuid < VM_MAXCPU, ("%s: invalid vcpuid %d",
+ KASSERT(vcpuid >= -1 && vcpuid < vm->maxcpus, ("%s: invalid vcpuid %d",
__func__, vcpuid));
- for (i = 0; i < VM_MAXCPU; i++) {
+ for (i = 0; i < vm->maxcpus; i++) {
if (vcpuid != -1 && vcpuid != i)
continue;
state = vcpu_get_state(vm, i, NULL);
@@ -1204,7 +1211,7 @@ int
vm_get_register(struct vm *vm, int vcpu, int reg, uint64_t *retval)
{
- if (vcpu < 0 || vcpu >= VM_MAXCPU)
+ if (vcpu < 0 || vcpu >= vm->maxcpus)
return (EINVAL);
if (reg >= VM_REG_LAST)
@@ -1219,7 +1226,7 @@ vm_set_register(struct vm *vm, int vcpuid, int reg, uint64_t val)
struct vcpu *vcpu;
int error;
- if (vcpuid < 0 || vcpuid >= VM_MAXCPU)
+ if (vcpuid < 0 || vcpuid >= vm->maxcpus)
return (EINVAL);
if (reg >= VM_REG_LAST)
@@ -1273,7 +1280,7 @@ vm_get_seg_desc(struct vm *vm, int vcpu, int reg,
struct seg_desc *desc)
{
- if (vcpu < 0 || vcpu >= VM_MAXCPU)
+ if (vcpu < 0 || vcpu >= vm->maxcpus)
return (EINVAL);
if (!is_segment_register(reg) && !is_descriptor_table(reg))
@@ -1286,7 +1293,7 @@ int
vm_set_seg_desc(struct vm *vm, int vcpu, int reg,
struct seg_desc *desc)
{
- if (vcpu < 0 || vcpu >= VM_MAXCPU)
+ if (vcpu < 0 || vcpu >= vm->maxcpus)
return (EINVAL);
if (!is_segment_register(reg) && !is_descriptor_table(reg))
@@ -1478,7 +1485,7 @@ static void
vm_handle_rendezvous(struct vm *vm, int vcpuid)
{
- KASSERT(vcpuid == -1 || (vcpuid >= 0 && vcpuid < VM_MAXCPU),
+ KASSERT(vcpuid == -1 || (vcpuid >= 0 && vcpuid < vm->maxcpus),
("vm_handle_rendezvous: invalid vcpuid %d", vcpuid));
mtx_lock(&vm->rendezvous_mtx);
@@ -1813,7 +1820,7 @@ vm_handle_suspend(struct vm *vm, int vcpuid, bool *retu)
/*
* Wakeup the other sleeping vcpus and return to userspace.
*/
- for (i = 0; i < VM_MAXCPU; i++) {
+ for (i = 0; i < vm->maxcpus; i++) {
if (CPU_ISSET(i, &vm->suspended_cpus)) {
vcpu_notify_event(vm, i, false);
}
@@ -1873,7 +1880,7 @@ vm_suspend(struct vm *vm, enum vm_suspend_how how)
/*
* Notify all active vcpus that they are now suspended.
*/
- for (i = 0; i < VM_MAXCPU; i++) {
+ for (i = 0; i < vm->maxcpus; i++) {
if (CPU_ISSET(i, &vm->active_cpus))
vcpu_notify_event(vm, i, false);
}
@@ -2068,7 +2075,7 @@ vm_run(struct vm *vm, struct vm_run *vmrun)
vcpuid = vmrun->cpuid;
- if (vcpuid < 0 || vcpuid >= VM_MAXCPU)
+ if (vcpuid < 0 || vcpuid >= vm->maxcpus)
return (EINVAL);
if (!CPU_ISSET(vcpuid, &vm->active_cpus))
@@ -2241,7 +2248,7 @@ vm_restart_instruction(void *arg, int vcpuid)
int error;
vm = arg;
- if (vcpuid < 0 || vcpuid >= VM_MAXCPU)
+ if (vcpuid < 0 || vcpuid >= vm->maxcpus)
return (EINVAL);
vcpu = &vm->vcpu[vcpuid];
@@ -2280,7 +2287,7 @@ vm_exit_intinfo(struct vm *vm, int vcpuid, uint64_t info)
struct vcpu *vcpu;
int type, vector;
- if (vcpuid < 0 || vcpuid >= VM_MAXCPU)
+ if (vcpuid < 0 || vcpuid >= vm->maxcpus)
return (EINVAL);
vcpu = &vm->vcpu[vcpuid];
@@ -2430,7 +2437,8 @@ vm_entry_intinfo(struct vm *vm, int vcpuid, uint64_t *retinfo)
uint64_t info1, info2;
int valid;
- KASSERT(vcpuid >= 0 && vcpuid < VM_MAXCPU, ("invalid vcpu %d", vcpuid));
+ KASSERT(vcpuid >= 0 &&
+ vcpuid < vm->maxcpus, ("invalid vcpu %d", vcpuid));
vcpu = &vm->vcpu[vcpuid];
@@ -2470,7 +2478,7 @@ vm_get_intinfo(struct vm *vm, int vcpuid, uint64_t *info1, uint64_t *info2)
{
struct vcpu *vcpu;
- if (vcpuid < 0 || vcpuid >= VM_MAXCPU)
+ if (vcpuid < 0 || vcpuid >= vm->maxcpus)
return (EINVAL);
vcpu = &vm->vcpu[vcpuid];
@@ -2487,7 +2495,7 @@ vm_inject_exception(struct vm *vm, int vcpuid, int vector, int errcode_valid,
uint64_t regval;
int error;
- if (vcpuid < 0 || vcpuid >= VM_MAXCPU)
+ if (vcpuid < 0 || vcpuid >= vm->maxcpus)
return (EINVAL);
if (vector < 0 || vector >= 32)
@@ -2578,7 +2586,7 @@ vm_inject_nmi(struct vm *vm, int vcpuid)
{
struct vcpu *vcpu;
- if (vcpuid < 0 || vcpuid >= VM_MAXCPU)
+ if (vcpuid < 0 || vcpuid >= vm->maxcpus)
return (EINVAL);
vcpu = &vm->vcpu[vcpuid];
@@ -2593,7 +2601,7 @@ vm_nmi_pending(struct vm *vm, int vcpuid)
{
struct vcpu *vcpu;
- if (vcpuid < 0 || vcpuid >= VM_MAXCPU)
+ if (vcpuid < 0 || vcpuid >= vm->maxcpus)
panic("vm_nmi_pending: invalid vcpuid %d", vcpuid);
vcpu = &vm->vcpu[vcpuid];
@@ -2606,7 +2614,7 @@ vm_nmi_clear(struct vm *vm, int vcpuid)
{
struct vcpu *vcpu;
- if (vcpuid < 0 || vcpuid >= VM_MAXCPU)
+ if (vcpuid < 0 || vcpuid >= vm->maxcpus)
panic("vm_nmi_pending: invalid vcpuid %d", vcpuid);
vcpu = &vm->vcpu[vcpuid];
@@ -2625,7 +2633,7 @@ vm_inject_extint(struct vm *vm, int vcpuid)
{
struct vcpu *vcpu;
- if (vcpuid < 0 || vcpuid >= VM_MAXCPU)
+ if (vcpuid < 0 || vcpuid >= vm->maxcpus)
return (EINVAL);
vcpu = &vm->vcpu[vcpuid];
@@ -2640,7 +2648,7 @@ vm_extint_pending(struct vm *vm, int vcpuid)
{
struct vcpu *vcpu;
- if (vcpuid < 0 || vcpuid >= VM_MAXCPU)
+ if (vcpuid < 0 || vcpuid >= vm->maxcpus)
panic("vm_extint_pending: invalid vcpuid %d", vcpuid);
vcpu = &vm->vcpu[vcpuid];
@@ -2653,7 +2661,7 @@ vm_extint_clear(struct vm *vm, int vcpuid)
{
struct vcpu *vcpu;
- if (vcpuid < 0 || vcpuid >= VM_MAXCPU)
+ if (vcpuid < 0 || vcpuid >= vm->maxcpus)
panic("vm_extint_pending: invalid vcpuid %d", vcpuid);
vcpu = &vm->vcpu[vcpuid];
@@ -2668,7 +2676,7 @@ vm_extint_clear(struct vm *vm, int vcpuid)
int
vm_get_capability(struct vm *vm, int vcpu, int type, int *retval)
{
- if (vcpu < 0 || vcpu >= VM_MAXCPU)
+ if (vcpu < 0 || vcpu >= vm->maxcpus)
return (EINVAL);
if (type < 0 || type >= VM_CAP_MAX)
@@ -2680,7 +2688,7 @@ vm_get_capability(struct vm *vm, int vcpu, int type, int *retval)
int
vm_set_capability(struct vm *vm, int vcpu, int type, int val)
{
- if (vcpu < 0 || vcpu >= VM_MAXCPU)
+ if (vcpu < 0 || vcpu >= vm->maxcpus)
return (EINVAL);
if (type < 0 || type >= VM_CAP_MAX)
@@ -2767,7 +2775,7 @@ vcpu_set_state(struct vm *vm, int vcpuid, enum vcpu_state newstate,
int error;
struct vcpu *vcpu;
- if (vcpuid < 0 || vcpuid >= VM_MAXCPU)
+ if (vcpuid < 0 || vcpuid >= vm->maxcpus)
panic("vm_set_run_state: invalid vcpuid %d", vcpuid);
vcpu = &vm->vcpu[vcpuid];
@@ -2785,7 +2793,7 @@ vcpu_get_state(struct vm *vm, int vcpuid, int *hostcpu)
struct vcpu *vcpu;
enum vcpu_state state;
- if (vcpuid < 0 || vcpuid >= VM_MAXCPU)
+ if (vcpuid < 0 || vcpuid >= vm->maxcpus)
panic("vm_get_run_state: invalid vcpuid %d", vcpuid);
vcpu = &vm->vcpu[vcpuid];
@@ -2811,7 +2819,7 @@ int
vm_activate_cpu(struct vm *vm, int vcpuid)
{
- if (vcpuid < 0 || vcpuid >= VM_MAXCPU)
+ if (vcpuid < 0 || vcpuid >= vm->maxcpus)
return (EINVAL);
if (CPU_ISSET(vcpuid, &vm->active_cpus))
@@ -2827,12 +2835,12 @@ vm_suspend_cpu(struct vm *vm, int vcpuid)
{
int i;
- if (vcpuid < -1 || vcpuid >= VM_MAXCPU)
+ if (vcpuid < -1 || vcpuid >= vm->maxcpus)
return (EINVAL);
if (vcpuid == -1) {
vm->debug_cpus = vm->active_cpus;
- for (i = 0; i < VM_MAXCPU; i++) {
+ for (i = 0; i < vm->maxcpus; i++) {
if (CPU_ISSET(i, &vm->active_cpus))
vcpu_notify_event(vm, i, false);
}
@@ -2850,7 +2858,7 @@ int
vm_resume_cpu(struct vm *vm, int vcpuid)
{
- if (vcpuid < -1 || vcpuid >= VM_MAXCPU)
+ if (vcpuid < -1 || vcpuid >= vm->maxcpus)
return (EINVAL);
if (vcpuid == -1) {
@@ -2902,7 +2910,7 @@ vcpu_stats(struct vm *vm, int vcpuid)
int
vm_get_x2apic_state(struct vm *vm, int vcpuid, enum x2apic_state *state)
{
- if (vcpuid < 0 || vcpuid >= VM_MAXCPU)
+ if (vcpuid < 0 || vcpuid >= vm->maxcpus)
return (EINVAL);
*state = vm->vcpu[vcpuid].x2apic_state;
@@ -2913,7 +2921,7 @@ vm_get_x2apic_state(struct vm *vm, int vcpuid, enum x2apic_state *state)
int
vm_set_x2apic_state(struct vm *vm, int vcpuid, enum x2apic_state state)
{
- if (vcpuid < 0 || vcpuid >= VM_MAXCPU)
+ if (vcpuid < 0 || vcpuid >= vm->maxcpus)
return (EINVAL);
if (state >= X2APIC_STATE_LAST)
@@ -3005,7 +3013,7 @@ vm_smp_rendezvous(struct vm *vm, int vcpuid, cpuset_t dest,
* Enforce that this function is called without any locks
*/
WITNESS_WARN(WARN_PANIC, NULL, "vm_smp_rendezvous");
- KASSERT(vcpuid == -1 || (vcpuid >= 0 && vcpuid < VM_MAXCPU),
+ KASSERT(vcpuid == -1 || (vcpuid >= 0 && vcpuid < vm->maxcpus),
("vm_smp_rendezvous: invalid vcpuid %d", vcpuid));
restart:
@@ -3035,7 +3043,7 @@ restart:
* Wake up any sleeping vcpus and trigger a VM-exit in any running
* vcpus so they handle the rendezvous as soon as possible.
*/
- for (i = 0; i < VM_MAXCPU; i++) {
+ for (i = 0; i < vm->maxcpus; i++) {
if (CPU_ISSET(i, &dest))
vcpu_notify_event(vm, i, false);
}
diff --git a/usr/src/uts/i86pc/io/vmm/vmm_instruction_emul.c b/usr/src/uts/i86pc/io/vmm/vmm_instruction_emul.c
index d276944800..ea96cd8db0 100644
--- a/usr/src/uts/i86pc/io/vmm/vmm_instruction_emul.c
+++ b/usr/src/uts/i86pc/io/vmm/vmm_instruction_emul.c
@@ -90,6 +90,7 @@ enum {
VIE_OP_TYPE_STOS,
VIE_OP_TYPE_BITTEST,
VIE_OP_TYPE_TWOB_GRP15,
+ VIE_OP_TYPE_ADD,
VIE_OP_TYPE_LAST
};
@@ -126,6 +127,10 @@ static const struct vie_op two_byte_opcodes[256] = {
};
static const struct vie_op one_byte_opcodes[256] = {
+ [0x03] = {
+ .op_byte = 0x03,
+ .op_type = VIE_OP_TYPE_ADD,
+ },
[0x0F] = {
.op_byte = 0x0F,
.op_type = VIE_OP_TYPE_TWO_BYTE
@@ -425,6 +430,41 @@ getcc(int opsize, uint64_t x, uint64_t y)
return (getcc64(x, y));
}
+/*
+ * Macro creation of functions getaddflags{8,16,32,64}
+ */
+#define GETADDFLAGS(sz) \
+static u_long \
+getaddflags##sz(uint##sz##_t x, uint##sz##_t y) \
+{ \
+ u_long rflags; \
+ \
+ __asm __volatile("add %2,%1; pushfq; popq %0" : \
+ "=r" (rflags), "+r" (x) : "m" (y)); \
+ return (rflags); \
+} struct __hack
+
+GETADDFLAGS(8);
+GETADDFLAGS(16);
+GETADDFLAGS(32);
+GETADDFLAGS(64);
+
+static u_long
+getaddflags(int opsize, uint64_t x, uint64_t y)
+{
+ KASSERT(opsize == 1 || opsize == 2 || opsize == 4 || opsize == 8,
+ ("getaddflags: invalid operand size %d", opsize));
+
+ if (opsize == 1)
+ return (getaddflags8(x, y));
+ else if (opsize == 2)
+ return (getaddflags16(x, y));
+ else if (opsize == 4)
+ return (getaddflags32(x, y));
+ else
+ return (getaddflags64(x, y));
+}
+
static int
emulate_mov(void *vm, int vcpuid, uint64_t gpa, struct vie *vie,
mem_region_read_t memread, mem_region_write_t memwrite, void *arg)
@@ -1194,6 +1234,62 @@ emulate_cmp(void *vm, int vcpuid, uint64_t gpa, struct vie *vie,
}
static int
+emulate_add(void *vm, int vcpuid, uint64_t gpa, struct vie *vie,
+ mem_region_read_t memread, mem_region_write_t memwrite, void *arg)
+{
+ int error, size;
+ uint64_t nval, rflags, rflags2, val1, val2;
+ enum vm_reg_name reg;
+
+ size = vie->opsize;
+ error = EINVAL;
+
+ switch (vie->op.op_byte) {
+ case 0x03:
+ /*
+ * ADD r/m to r and store the result in r
+ *
+ * 03/r ADD r16, r/m16
+ * 03/r ADD r32, r/m32
+ * REX.W + 03/r ADD r64, r/m64
+ */
+
+ /* get the first operand */
+ reg = gpr_map[vie->reg];
+ error = vie_read_register(vm, vcpuid, reg, &val1);
+ if (error)
+ break;
+
+ /* get the second operand */
+ error = memread(vm, vcpuid, gpa, &val2, size, arg);
+ if (error)
+ break;
+
+ /* perform the operation and write the result */
+ nval = val1 + val2;
+ error = vie_update_register(vm, vcpuid, reg, nval, size);
+ break;
+ default:
+ break;
+ }
+
+ if (!error) {
+ rflags2 = getaddflags(size, val1, val2);
+ error = vie_read_register(vm, vcpuid, VM_REG_GUEST_RFLAGS,
+ &rflags);
+ if (error)
+ return (error);
+
+ rflags &= ~RFLAGS_STATUS_BITS;
+ rflags |= rflags2 & RFLAGS_STATUS_BITS;
+ error = vie_update_register(vm, vcpuid, VM_REG_GUEST_RFLAGS,
+ rflags, 8);
+ }
+
+ return (error);
+}
+
+static int
emulate_sub(void *vm, int vcpuid, uint64_t gpa, struct vie *vie,
mem_region_read_t memread, mem_region_write_t memwrite, void *arg)
{
@@ -1558,6 +1654,10 @@ vmm_emulate_instruction(void *vm, int vcpuid, uint64_t gpa, struct vie *vie,
error = emulate_twob_group15(vm, vcpuid, gpa, vie,
memread, memwrite, memarg);
break;
+ case VIE_OP_TYPE_ADD:
+ error = emulate_add(vm, vcpuid, gpa, vie, memread,
+ memwrite, memarg);
+ break;
default:
error = EINVAL;
break;
diff --git a/usr/src/uts/i86pc/io/vmm/vmm_lapic.c b/usr/src/uts/i86pc/io/vmm/vmm_lapic.c
index 7cafc0755e..43b2bebe97 100644
--- a/usr/src/uts/i86pc/io/vmm/vmm_lapic.c
+++ b/usr/src/uts/i86pc/io/vmm/vmm_lapic.c
@@ -68,7 +68,7 @@ lapic_set_intr(struct vm *vm, int cpu, int vector, bool level)
{
struct vlapic *vlapic;
- if (cpu < 0 || cpu >= VM_MAXCPU)
+ if (cpu < 0 || cpu >= vm_get_maxcpus(vm))
return (EINVAL);
/*
@@ -91,7 +91,7 @@ lapic_set_local_intr(struct vm *vm, int cpu, int vector)
cpuset_t dmask;
int error;
- if (cpu < -1 || cpu >= VM_MAXCPU)
+ if (cpu < -1 || cpu >= vm_get_maxcpus(vm))
return (EINVAL);
if (cpu == -1)
diff --git a/usr/src/uts/i86pc/io/vmm/vmm_sol_dev.c b/usr/src/uts/i86pc/io/vmm/vmm_sol_dev.c
index af775d4d7b..d20732ee1e 100644
--- a/usr/src/uts/i86pc/io/vmm/vmm_sol_dev.c
+++ b/usr/src/uts/i86pc/io/vmm/vmm_sol_dev.c
@@ -230,7 +230,7 @@ vcpu_lock_one(vmm_softc_t *sc, int vcpu)
{
int error;
- if (vcpu < 0 || vcpu >= VM_MAXCPU)
+ if (vcpu < 0 || vcpu >= vm_get_maxcpus(sc->vmm_vm))
return (EINVAL);
error = vcpu_set_state(sc->vmm_vm, vcpu, VCPU_FROZEN, true);
@@ -254,9 +254,11 @@ vcpu_unlock_one(vmm_softc_t *sc, int vcpu)
static int
vcpu_lock_all(vmm_softc_t *sc)
{
- int error, vcpu;
+ int error = 0, vcpu;
+ uint16_t maxcpus;
- for (vcpu = 0; vcpu < VM_MAXCPU; vcpu++) {
+ maxcpus = vm_get_maxcpus(sc->vmm_vm);
+ for (vcpu = 0; vcpu < maxcpus; vcpu++) {
error = vcpu_lock_one(sc, vcpu);
if (error)
break;
@@ -274,8 +276,10 @@ static void
vcpu_unlock_all(vmm_softc_t *sc)
{
int vcpu;
+ uint16_t maxcpus;
- for (vcpu = 0; vcpu < VM_MAXCPU; vcpu++)
+ maxcpus = vm_get_maxcpus(sc->vmm_vm);
+ for (vcpu = 0; vcpu < maxcpus; vcpu++)
vcpu_unlock_one(sc, vcpu);
}
@@ -320,7 +324,7 @@ vmmdev_do_ioctl(vmm_softc_t *sc, int cmd, intptr_t arg, int md,
if (ddi_copyin(datap, &vcpu, sizeof (vcpu), md)) {
return (EFAULT);
}
- if (vcpu < 0 || vcpu >= VM_MAXCPU) {
+ if (vcpu < 0 || vcpu >= vm_get_maxcpus(sc->vmm_vm)) {
error = EINVAL;
goto done;
}
@@ -356,7 +360,7 @@ vmmdev_do_ioctl(vmm_softc_t *sc, int cmd, intptr_t arg, int md,
* Lock a vcpu to make sure that the memory map cannot be
* modified while it is being inspected.
*/
- vcpu = VM_MAXCPU - 1;
+ vcpu = vm_get_maxcpus(sc->vmm_vm) - 1;
error = vcpu_lock_one(sc, vcpu);
if (error)
goto done;
@@ -976,7 +980,7 @@ vmmdev_do_ioctl(vmm_softc_t *sc, int cmd, intptr_t arg, int md,
error = EFAULT;
break;
}
- if (vcpu < -1 || vcpu >= VM_MAXCPU) {
+ if (vcpu < -1 || vcpu >= vm_get_maxcpus(sc->vmm_vm)) {
error = EINVAL;
break;
}
@@ -989,7 +993,7 @@ vmmdev_do_ioctl(vmm_softc_t *sc, int cmd, intptr_t arg, int md,
error = EFAULT;
break;
}
- if (vcpu < -1 || vcpu >= VM_MAXCPU) {
+ if (vcpu < -1 || vcpu >= vm_get_maxcpus(sc->vmm_vm)) {
error = EINVAL;
break;
}
diff --git a/usr/src/uts/i86pc/io/vmm/vmm_stat.c b/usr/src/uts/i86pc/io/vmm/vmm_stat.c
index c2c2cfe77c..f61272c49c 100644
--- a/usr/src/uts/i86pc/io/vmm/vmm_stat.c
+++ b/usr/src/uts/i86pc/io/vmm/vmm_stat.c
@@ -88,7 +88,7 @@ vmm_stat_copy(struct vm *vm, int vcpu, int *num_stats, uint64_t *buf)
uint64_t *stats;
int i;
- if (vcpu < 0 || vcpu >= VM_MAXCPU)
+ if (vcpu < 0 || vcpu >= vm_get_maxcpus(vm))
return (EINVAL);
/* Let stats functions update their counters */
diff --git a/usr/src/uts/i86pc/io/vmm/x86.c b/usr/src/uts/i86pc/io/vmm/x86.c
index 2ffa80b335..d74f866013 100644
--- a/usr/src/uts/i86pc/io/vmm/x86.c
+++ b/usr/src/uts/i86pc/io/vmm/x86.c
@@ -451,6 +451,7 @@ x86_emulate_cpuid(struct vm *vm, int vcpu_id,
CPUID_STDEXT_AVX2 | CPUID_STDEXT_BMI2 |
CPUID_STDEXT_ERMS | CPUID_STDEXT_RTM |
CPUID_STDEXT_AVX512F |
+ CPUID_STDEXT_RDSEED |
CPUID_STDEXT_AVX512PF |
CPUID_STDEXT_AVX512ER |
CPUID_STDEXT_AVX512CD | CPUID_STDEXT_SHA);
diff --git a/usr/src/uts/i86pc/sys/vmm.h b/usr/src/uts/i86pc/sys/vmm.h
index e5e5460211..d6313469a5 100644
--- a/usr/src/uts/i86pc/sys/vmm.h
+++ b/usr/src/uts/i86pc/sys/vmm.h
@@ -209,6 +209,7 @@ int vm_create(const char *name, struct vm **retvm);
void vm_destroy(struct vm *vm);
int vm_reinit(struct vm *vm);
const char *vm_name(struct vm *vm);
+uint16_t vm_get_maxcpus(struct vm *vm);
void vm_get_topology(struct vm *vm, uint16_t *sockets, uint16_t *cores,
uint16_t *threads, uint16_t *maxcpus);
int vm_set_topology(struct vm *vm, uint16_t sockets, uint16_t cores,