summaryrefslogtreecommitdiffstats
path: root/sys/amd64
diff options
context:
space:
mode:
authorneel <neel@FreeBSD.org>2012-10-24 02:54:21 +0000
committerneel <neel@FreeBSD.org>2012-10-24 02:54:21 +0000
commit583a9ef76d9ec8f3bb8e7927281cfe79fc0c0584 (patch)
treeebe1a9d2777b5f416d302581cf79fa0ff4d66b9f /sys/amd64
parenta74007510aa98cb51b2d7cc4056a994e3bf64763 (diff)
downloadFreeBSD-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.h4
-rw-r--r--sys/amd64/vmm/amd/amdv.c9
-rw-r--r--sys/amd64/vmm/intel/vmx.c16
-rw-r--r--sys/amd64/vmm/intel/vmx.h1
-rw-r--r--sys/amd64/vmm/vmm.c49
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
OpenPOWER on IntegriCloud