Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 24 Oct 2012 02:54:21 +0000 (UTC)
From:      Neel Natu <neel@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r241982 - in projects/bhyve/sys/amd64: include vmm vmm/amd vmm/intel
Message-ID:  <201210240254.q9O2sLl9022839@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: neel
Date: Wed Oct 24 02:54:21 2012
New Revision: 241982
URL: http://svn.freebsd.org/changeset/base/241982

Log:
  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

Modified:
  projects/bhyve/sys/amd64/include/vmm.h
  projects/bhyve/sys/amd64/vmm/amd/amdv.c
  projects/bhyve/sys/amd64/vmm/intel/vmx.c
  projects/bhyve/sys/amd64/vmm/intel/vmx.h
  projects/bhyve/sys/amd64/vmm/vmm.c

Modified: projects/bhyve/sys/amd64/include/vmm.h
==============================================================================
--- projects/bhyve/sys/amd64/include/vmm.h	Wed Oct 24 02:32:06 2012	(r241981)
+++ projects/bhyve/sys/amd64/include/vmm.h	Wed Oct 24 02:54:21 2012	(r241982)
@@ -63,7 +63,6 @@ typedef int	(*vmi_set_desc_t)(void *vmi,
 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 
 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);

Modified: projects/bhyve/sys/amd64/vmm/amd/amdv.c
==============================================================================
--- projects/bhyve/sys/amd64/vmm/amd/amdv.c	Wed Oct 24 02:32:06 2012	(r241981)
+++ projects/bhyve/sys/amd64/vmm/amd/amdv.c	Wed Oct 24 02:54:21 2012	(r241982)
@@ -136,14 +136,6 @@ amdv_inject_event(void *vmi, int vcpu, i
 }
 
 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
 };

Modified: projects/bhyve/sys/amd64/vmm/intel/vmx.c
==============================================================================
--- projects/bhyve/sys/amd64/vmm/intel/vmx.c	Wed Oct 24 02:32:06 2012	(r241981)
+++ projects/bhyve/sys/amd64/vmm/intel/vmx.c	Wed Oct 24 02:54:21 2012	(r241982)
@@ -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
 }
 
 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
 };

Modified: projects/bhyve/sys/amd64/vmm/intel/vmx.h
==============================================================================
--- projects/bhyve/sys/amd64/vmm/intel/vmx.h	Wed Oct 24 02:32:06 2012	(r241981)
+++ projects/bhyve/sys/amd64/vmm/intel/vmx.h	Wed Oct 24 02:54:21 2012	(r241982)
@@ -76,7 +76,6 @@ struct vmxcap {
 };
 
 struct vmxstate {
-	int	request_nmi;	
 	int	lastcpu;	/* host cpu that this 'vcpu' last ran on */
 	uint16_t vpid;
 };

Modified: projects/bhyve/sys/amd64/vmm/vmm.c
==============================================================================
--- projects/bhyve/sys/amd64/vmm/vmm.c	Wed Oct 24 02:32:06 2012	(r241981)
+++ projects/bhyve/sys/amd64/vmm/vmm.c	Wed Oct 24 02:54:21 2012	(r241982)
@@ -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 vcpui
 	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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201210240254.q9O2sLl9022839>