diff options
author | Patrick Mooney <pmooney@pfmooney.com> | 2019-06-04 21:27:31 +0000 |
---|---|---|
committer | Patrick Mooney <pmooney@pfmooney.com> | 2019-06-14 16:28:50 +0000 |
commit | c3cbf49c8d881ba57710e7e8b70aa6275bc5fc44 (patch) | |
tree | 549f85b42dcc7444792f88104bc0fd374f0b15ef /usr/src/uts/i86pc | |
parent | de37b27aa9332f8b33b7b4041b3bdaa6894dcde9 (diff) | |
download | illumos-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.sync | 17 | ||||
-rw-r--r-- | usr/src/uts/i86pc/io/vmm/amd/svm.c | 4 | ||||
-rw-r--r-- | usr/src/uts/i86pc/io/vmm/intel/vmx.c | 20 | ||||
-rw-r--r-- | usr/src/uts/i86pc/io/vmm/io/iommu.c | 4 | ||||
-rw-r--r-- | usr/src/uts/i86pc/io/vmm/io/vlapic.c | 11 | ||||
-rw-r--r-- | usr/src/uts/i86pc/io/vmm/vmm.c | 92 | ||||
-rw-r--r-- | usr/src/uts/i86pc/io/vmm/vmm_instruction_emul.c | 100 | ||||
-rw-r--r-- | usr/src/uts/i86pc/io/vmm/vmm_lapic.c | 4 | ||||
-rw-r--r-- | usr/src/uts/i86pc/io/vmm/vmm_sol_dev.c | 20 | ||||
-rw-r--r-- | usr/src/uts/i86pc/io/vmm/vmm_stat.c | 2 | ||||
-rw-r--r-- | usr/src/uts/i86pc/io/vmm/x86.c | 1 | ||||
-rw-r--r-- | usr/src/uts/i86pc/sys/vmm.h | 1 |
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, |