diff options
author | neel <neel@FreeBSD.org> | 2012-10-24 02:54:21 +0000 |
---|---|---|
committer | neel <neel@FreeBSD.org> | 2012-10-24 02:54:21 +0000 |
commit | 583a9ef76d9ec8f3bb8e7927281cfe79fc0c0584 (patch) | |
tree | ebe1a9d2777b5f416d302581cf79fa0ff4d66b9f /sys/amd64 | |
parent | a74007510aa98cb51b2d7cc4056a994e3bf64763 (diff) | |
download | FreeBSD-src-583a9ef76d9ec8f3bb8e7927281cfe79fc0c0584.zip FreeBSD-src-583a9ef76d9ec8f3bb8e7927281cfe79fc0c0584.tar.gz |
Maintain state regarding NMI delivery to guest vcpu in VT-x independent manner.
Also add a stats counter to count the number of NMIs delivered per vcpu.
Obtained from: NetApp
Diffstat (limited to 'sys/amd64')
-rw-r--r-- | sys/amd64/include/vmm.h | 4 | ||||
-rw-r--r-- | sys/amd64/vmm/amd/amdv.c | 9 | ||||
-rw-r--r-- | sys/amd64/vmm/intel/vmx.c | 16 | ||||
-rw-r--r-- | sys/amd64/vmm/intel/vmx.h | 1 | ||||
-rw-r--r-- | sys/amd64/vmm/vmm.c | 49 |
5 files changed, 45 insertions, 34 deletions
diff --git a/sys/amd64/include/vmm.h b/sys/amd64/include/vmm.h index d0dfb04..8f78b8f 100644 --- a/sys/amd64/include/vmm.h +++ b/sys/amd64/include/vmm.h @@ -63,7 +63,6 @@ typedef int (*vmi_set_desc_t)(void *vmi, int vcpu, int num, typedef int (*vmi_inject_event_t)(void *vmi, int vcpu, int type, int vector, uint32_t code, int code_valid); -typedef int (*vmi_inject_nmi_t)(void *vmi, int vcpu); typedef int (*vmi_get_cap_t)(void *vmi, int vcpu, int num, int *retval); typedef int (*vmi_set_cap_t)(void *vmi, int vcpu, int num, int val); @@ -81,7 +80,6 @@ struct vmm_ops { vmi_get_desc_t vmgetdesc; vmi_set_desc_t vmsetdesc; vmi_inject_event_t vminject; - vmi_inject_nmi_t vmnmi; vmi_get_cap_t vmgetcap; vmi_set_cap_t vmsetcap; }; @@ -110,6 +108,8 @@ int vm_run(struct vm *vm, struct vm_run *vmrun); int vm_inject_event(struct vm *vm, int vcpu, int type, int vector, uint32_t error_code, int error_code_valid); int vm_inject_nmi(struct vm *vm, int vcpu); +int vm_nmi_pending(struct vm *vm, int vcpuid); +void vm_nmi_clear(struct vm *vm, int vcpuid); uint64_t *vm_guest_msrs(struct vm *vm, int cpu); struct vlapic *vm_lapic(struct vm *vm, int cpu); int vm_get_capability(struct vm *vm, int vcpu, int type, int *val); diff --git a/sys/amd64/vmm/amd/amdv.c b/sys/amd64/vmm/amd/amdv.c index 020743f..dc071d3 100644 --- a/sys/amd64/vmm/amd/amdv.c +++ b/sys/amd64/vmm/amd/amdv.c @@ -136,14 +136,6 @@ amdv_inject_event(void *vmi, int vcpu, int type, int vector, } static int -amdv_nmi(void *arg, int vcpu) -{ - - printf("amdv_nmi: not implemented\n"); - return (EINVAL); -} - -static int amdv_getcap(void *arg, int vcpu, int type, int *retval) { @@ -172,7 +164,6 @@ struct vmm_ops vmm_ops_amd = { amdv_getdesc, amdv_setdesc, amdv_inject_event, - amdv_nmi, amdv_getcap, amdv_setcap }; diff --git a/sys/amd64/vmm/intel/vmx.c b/sys/amd64/vmm/intel/vmx.c index 11b8c9f..16acfff 100644 --- a/sys/amd64/vmm/intel/vmx.c +++ b/sys/amd64/vmm/intel/vmx.c @@ -751,7 +751,6 @@ vmx_vminit(struct vm *vm) vmx->cap[i].set = 0; vmx->cap[i].proc_ctls = procbased_ctls; - vmx->state[i].request_nmi = 0; vmx->state[i].lastcpu = -1; vmx->state[i].vpid = vpid; @@ -940,7 +939,7 @@ vmx_inject_nmi(struct vmx *vmx, int vcpu) uint64_t info, interruptibility; /* Bail out if no NMI requested */ - if (vmx->state[vcpu].request_nmi == 0) + if (!vm_nmi_pending(vmx->vm, vcpu)) return (0); error = vmread(VMCS_GUEST_INTERRUPTIBILITY, &interruptibility); @@ -965,7 +964,7 @@ vmx_inject_nmi(struct vmx *vmx, int vcpu) VMM_CTR0(vmx->vm, vcpu, "Injecting vNMI"); /* Clear the request */ - vmx->state[vcpu].request_nmi = 0; + vm_nmi_clear(vmx->vm, vcpu); return (1); nmiblocked: @@ -1696,16 +1695,6 @@ vmx_inject(void *arg, int vcpu, int type, int vector, uint32_t code, } static int -vmx_nmi(void *arg, int vcpu) -{ - struct vmx *vmx = arg; - - atomic_set_int(&vmx->state[vcpu].request_nmi, 1); - - return (0); -} - -static int vmx_getcap(void *arg, int vcpu, int type, int *retval) { struct vmx *vmx = arg; @@ -1843,7 +1832,6 @@ struct vmm_ops vmm_ops_intel = { vmx_getdesc, vmx_setdesc, vmx_inject, - vmx_nmi, vmx_getcap, vmx_setcap }; diff --git a/sys/amd64/vmm/intel/vmx.h b/sys/amd64/vmm/intel/vmx.h index d4c90fa..c7cd567 100644 --- a/sys/amd64/vmm/intel/vmx.h +++ b/sys/amd64/vmm/intel/vmx.h @@ -76,7 +76,6 @@ struct vmxcap { }; struct vmxstate { - int request_nmi; int lastcpu; /* host cpu that this 'vcpu' last ran on */ uint16_t vpid; }; diff --git a/sys/amd64/vmm/vmm.c b/sys/amd64/vmm/vmm.c index 8d8f143..6c6df21 100644 --- a/sys/amd64/vmm/vmm.c +++ b/sys/amd64/vmm/vmm.c @@ -77,6 +77,7 @@ struct vcpu { void *stats; struct vm_exit exitinfo; enum x2apic_state x2apic_state; + int nmi_pending; }; #define VCPU_F_PINNED 0x0001 @@ -137,8 +138,6 @@ static struct vmm_ops *ops; (ops != NULL ? (*ops->vmsetdesc)(vmi, vcpu, num, desc) : ENXIO) #define VMINJECT(vmi, vcpu, type, vec, ec, ecv) \ (ops != NULL ? (*ops->vminject)(vmi, vcpu, type, vec, ec, ecv) : ENXIO) -#define VMNMI(vmi, vcpu) \ - (ops != NULL ? (*ops->vmnmi)(vmi, vcpu) : ENXIO) #define VMGETCAP(vmi, vcpu, num, retval) \ (ops != NULL ? (*ops->vmgetcap)(vmi, vcpu, num, retval) : ENXIO) #define VMSETCAP(vmi, vcpu, num, val) \ @@ -710,17 +709,51 @@ vm_inject_event(struct vm *vm, int vcpuid, int type, return (VMINJECT(vm->cookie, vcpuid, type, vector, code, code_valid)); } +VMM_STAT_DEFINE(VCPU_NMI_COUNT, "number of NMIs delivered to vcpu"); + int -vm_inject_nmi(struct vm *vm, int vcpu) +vm_inject_nmi(struct vm *vm, int vcpuid) { - int error; + struct vcpu *vcpu; - if (vcpu < 0 || vcpu >= VM_MAXCPU) + if (vcpuid < 0 || vcpuid >= VM_MAXCPU) return (EINVAL); - error = VMNMI(vm->cookie, vcpu); - vm_interrupt_hostcpu(vm, vcpu); - return (error); + vcpu = &vm->vcpu[vcpuid]; + + vcpu->nmi_pending = 1; + vm_interrupt_hostcpu(vm, vcpuid); + return (0); +} + +int +vm_nmi_pending(struct vm *vm, int vcpuid) +{ + struct vcpu *vcpu; + + if (vcpuid < 0 || vcpuid >= VM_MAXCPU) + panic("vm_nmi_pending: invalid vcpuid %d", vcpuid); + + vcpu = &vm->vcpu[vcpuid]; + + return (vcpu->nmi_pending); +} + +void +vm_nmi_clear(struct vm *vm, int vcpuid) +{ + struct vcpu *vcpu; + + if (vcpuid < 0 || vcpuid >= VM_MAXCPU) + panic("vm_nmi_pending: invalid vcpuid %d", vcpuid); + + vcpu = &vm->vcpu[vcpuid]; + + if (vcpu->nmi_pending == 0) + panic("vm_nmi_clear: inconsistent nmi_pending state"); + + vcpu->nmi_pending = 0; + vmm_stat_incr(vm, vcpuid, VCPU_NMI_COUNT, 1); } int |