Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 4 Feb 2014 05:03:14 +0000 (UTC)
From:      Peter Grehan <grehan@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r261457 - in projects/bhyve_svm/sys/amd64/vmm: . intel io
Message-ID:  <201402040503.s1453Ee5073979@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: grehan
Date: Tue Feb  4 05:03:14 2014
New Revision: 261457
URL: http://svnweb.freebsd.org/changeset/base/261457

Log:
  Roll back botched partial MFC :(

Added:
  projects/bhyve_svm/sys/amd64/vmm/io/vdev.c
     - copied unchanged from r261451, projects/bhyve_svm/sys/amd64/vmm/io/vdev.c
  projects/bhyve_svm/sys/amd64/vmm/io/vdev.h
     - copied unchanged from r261451, projects/bhyve_svm/sys/amd64/vmm/io/vdev.h
Deleted:
  projects/bhyve_svm/sys/amd64/vmm/io/vhpet.c
  projects/bhyve_svm/sys/amd64/vmm/io/vhpet.h
  projects/bhyve_svm/sys/amd64/vmm/io/vioapic.c
  projects/bhyve_svm/sys/amd64/vmm/io/vioapic.h
Modified:
  projects/bhyve_svm/sys/amd64/vmm/intel/vmcs.c
  projects/bhyve_svm/sys/amd64/vmm/intel/vmcs.h
  projects/bhyve_svm/sys/amd64/vmm/intel/vmx.c
  projects/bhyve_svm/sys/amd64/vmm/intel/vmx.h
  projects/bhyve_svm/sys/amd64/vmm/intel/vmx_controls.h
  projects/bhyve_svm/sys/amd64/vmm/intel/vmx_genassym.c
  projects/bhyve_svm/sys/amd64/vmm/intel/vtd.c
  projects/bhyve_svm/sys/amd64/vmm/io/ppt.c
  projects/bhyve_svm/sys/amd64/vmm/io/vlapic.c
  projects/bhyve_svm/sys/amd64/vmm/io/vlapic.h
  projects/bhyve_svm/sys/amd64/vmm/vmm.c
  projects/bhyve_svm/sys/amd64/vmm/vmm_dev.c
  projects/bhyve_svm/sys/amd64/vmm/vmm_instruction_emul.c
  projects/bhyve_svm/sys/amd64/vmm/vmm_ktr.h
  projects/bhyve_svm/sys/amd64/vmm/vmm_lapic.c
  projects/bhyve_svm/sys/amd64/vmm/vmm_lapic.h
  projects/bhyve_svm/sys/amd64/vmm/vmm_msr.c
  projects/bhyve_svm/sys/amd64/vmm/vmm_msr.h
  projects/bhyve_svm/sys/amd64/vmm/x86.c
Directory Properties:
  projects/bhyve_svm/sys/amd64/vmm/   (props changed)

Modified: projects/bhyve_svm/sys/amd64/vmm/intel/vmcs.c
==============================================================================
--- projects/bhyve_svm/sys/amd64/vmm/intel/vmcs.c	Tue Feb  4 03:59:35 2014	(r261456)
+++ projects/bhyve_svm/sys/amd64/vmm/intel/vmcs.c	Tue Feb  4 05:03:14 2014	(r261457)
@@ -39,6 +39,8 @@ __FBSDID("$FreeBSD$");
 #include <vm/pmap.h>
 
 #include <machine/segments.h>
+#include <machine/pmap.h>
+
 #include <machine/vmm.h>
 #include "vmm_host.h"
 #include "vmcs.h"

Modified: projects/bhyve_svm/sys/amd64/vmm/intel/vmcs.h
==============================================================================
--- projects/bhyve_svm/sys/amd64/vmm/intel/vmcs.h	Tue Feb  4 03:59:35 2014	(r261456)
+++ projects/bhyve_svm/sys/amd64/vmm/intel/vmcs.h	Tue Feb  4 05:03:14 2014	(r261457)
@@ -318,7 +318,7 @@ uint64_t vmcs_read(uint32_t encoding);
 /*
  * VMCS IDT-Vectoring information fields
  */
-#define	VMCS_IDT_VEC_VALID		(1U << 31)
+#define	VMCS_IDT_VEC_VALID		(1 << 31)
 #define	VMCS_IDT_VEC_ERRCODE_VALID	(1 << 11)
 
 /*

Modified: projects/bhyve_svm/sys/amd64/vmm/intel/vmx.c
==============================================================================
--- projects/bhyve_svm/sys/amd64/vmm/intel/vmx.c	Tue Feb  4 03:59:35 2014	(r261456)
+++ projects/bhyve_svm/sys/amd64/vmm/intel/vmx.c	Tue Feb  4 05:03:14 2014	(r261457)
@@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$");
 #include <machine/psl.h>
 #include <machine/cpufunc.h>
 #include <machine/md_var.h>
+#include <machine/pmap.h>
 #include <machine/segments.h>
 #include <machine/specialreg.h>
 #include <machine/vmparam.h>
@@ -163,7 +164,6 @@ static int cap_halt_exit;
 static int cap_pause_exit;
 static int cap_unrestricted_guest;
 static int cap_monitor_trap;
-static int cap_invpcid;
  
 static struct unrhdr *vpid_unr;
 static u_int vpid_alloc_failed;
@@ -307,8 +307,8 @@ vmx_setjmp_rc2str(int rc)
 	}
 }
 
-#define	SETJMP_TRACE(vmx, vcpu, vmxctx, regname)			    \
-	VCPU_CTR1((vmx)->vm, (vcpu), "setjmp trace " #regname " 0x%016lx",  \
+#define	SETJMP_TRACE(vmx, vcpu, vmxctx, regname)			  \
+	VMM_CTR1((vmx)->vm, (vcpu), "setjmp trace " #regname " 0x%016lx", \
 		 (vmxctx)->regname)
 
 static void
@@ -320,14 +320,14 @@ vmx_setjmp_trace(struct vmx *vmx, int vc
 		panic("vmx_setjmp_trace: invalid vmxctx %p; should be %p",
 			vmxctx, &vmx->ctx[vcpu]);
 
-	VCPU_CTR1((vmx)->vm, (vcpu), "vmxctx = %p", vmxctx);
-	VCPU_CTR2((vmx)->vm, (vcpu), "setjmp return code %s(%d)",
+	VMM_CTR1((vmx)->vm, (vcpu), "vmxctx = %p", vmxctx);
+	VMM_CTR2((vmx)->vm, (vcpu), "setjmp return code %s(%d)",
 		 vmx_setjmp_rc2str(rc), rc);
 
 	host_rsp = host_rip = ~0;
 	vmread(VMCS_HOST_RIP, &host_rip);
 	vmread(VMCS_HOST_RSP, &host_rsp);
-	VCPU_CTR2((vmx)->vm, (vcpu), "vmcs host_rip 0x%016lx, host_rsp %#lx",
+	VMM_CTR2((vmx)->vm, (vcpu), "vmcs host_rip 0x%016lx, host_rsp 0x%016lx",
 		 host_rip, host_rsp);
 
 	SETJMP_TRACE(vmx, vcpu, vmxctx, host_r15);
@@ -660,11 +660,6 @@ vmx_init(void)
 					PROCBASED2_UNRESTRICTED_GUEST, 0,
 				        &tmp) == 0);
 
-	cap_invpcid = (vmx_set_ctlreg(MSR_VMX_PROCBASED_CTLS2,
-	    MSR_VMX_PROCBASED_CTLS2, PROCBASED2_ENABLE_INVPCID, 0,
-	    &tmp) == 0);
-
-
 	/* Initialize EPT */
 	error = ept_init();
 	if (error) {
@@ -833,7 +828,6 @@ vmx_vminit(struct vm *vm, pmap_t pmap)
 
 		vmx->cap[i].set = 0;
 		vmx->cap[i].proc_ctls = procbased_ctls;
-		vmx->cap[i].proc_ctls2 = procbased_ctls2;
 
 		vmx->state[i].lastcpu = -1;
 		vmx->state[i].vpid = vpid[i];
@@ -886,7 +880,7 @@ static __inline void
 vmx_run_trace(struct vmx *vmx, int vcpu)
 {
 #ifdef KTR
-	VCPU_CTR1(vmx->vm, vcpu, "Resume execution at %#lx", vmcs_guest_rip());
+	VMM_CTR1(vmx->vm, vcpu, "Resume execution at 0x%0lx", vmcs_guest_rip());
 #endif
 }
 
@@ -895,7 +889,7 @@ vmx_exit_trace(struct vmx *vmx, int vcpu
 	       int handled)
 {
 #ifdef KTR
-	VCPU_CTR3(vmx->vm, vcpu, "%s %s vmexit at 0x%0lx",
+	VMM_CTR3(vmx->vm, vcpu, "%s %s vmexit at 0x%0lx",
 		 handled ? "handled" : "unhandled",
 		 exit_reason_to_str(exit_reason), rip);
 #endif
@@ -905,7 +899,7 @@ static __inline void
 vmx_astpending_trace(struct vmx *vmx, int vcpu, uint64_t rip)
 {
 #ifdef KTR
-	VCPU_CTR1(vmx->vm, vcpu, "astpending vmexit at 0x%0lx", rip);
+	VMM_CTR1(vmx->vm, vcpu, "astpending vmexit at 0x%0lx", rip);
 #endif
 }
 
@@ -1054,7 +1048,7 @@ vmx_inject_nmi(struct vmx *vmx, int vcpu
 	if (error)
 		panic("vmx_inject_nmi: vmwrite(intrinfo) %d", error);
 
-	VCPU_CTR0(vmx->vm, vcpu, "Injecting vNMI");
+	VMM_CTR0(vmx->vm, vcpu, "Injecting vNMI");
 
 	/* Clear the request */
 	vm_nmi_clear(vmx->vm, vcpu);
@@ -1067,7 +1061,7 @@ nmiblocked:
 	 */
 	vmx_set_nmi_window_exiting(vmx, vcpu);
 
-	VCPU_CTR0(vmx->vm, vcpu, "Enabling NMI window exiting");
+	VMM_CTR0(vmx->vm, vcpu, "Enabling NMI window exiting");
 	return (1);
 }
 
@@ -1133,7 +1127,7 @@ vmx_inject_interrupts(struct vmx *vmx, i
 	/* Update the Local APIC ISR */
 	lapic_intr_accepted(vmx->vm, vcpu, vector);
 
-	VCPU_CTR1(vmx->vm, vcpu, "Injecting hwintr at vector %d", vector);
+	VMM_CTR1(vmx->vm, vcpu, "Injecting hwintr at vector %d", vector);
 
 	return;
 
@@ -1144,7 +1138,7 @@ cantinject:
 	 */
 	vmx_set_int_window_exiting(vmx, vcpu);
 
-	VCPU_CTR0(vmx->vm, vcpu, "Enabling interrupt window exiting");
+	VMM_CTR0(vmx->vm, vcpu, "Enabling interrupt window exiting");
 }
 
 static int
@@ -1301,6 +1295,21 @@ ept_fault_type(uint64_t ept_qual)
 	return (fault_type);
 }
 
+static int
+ept_protection(uint64_t ept_qual)
+{
+	int prot = 0;
+
+	if (ept_qual & EPT_VIOLATION_GPA_READABLE)
+		prot |= VM_PROT_READ;
+	if (ept_qual & EPT_VIOLATION_GPA_WRITEABLE)
+		prot |= VM_PROT_WRITE;
+	if (ept_qual & EPT_VIOLATION_GPA_EXECUTABLE)
+		prot |= VM_PROT_EXECUTE;
+
+	return (prot);
+}
+
 static boolean_t
 ept_emulation_fault(uint64_t ept_qual)
 {
@@ -1336,8 +1345,7 @@ vmx_exit_process(struct vmx *vmx, int vc
 	struct vmcs *vmcs;
 	struct vmxctx *vmxctx;
 	uint32_t eax, ecx, edx, idtvec_info, idtvec_err, reason;
-	uint64_t qual, gpa, rflags;
-	bool retu;
+	uint64_t qual, gpa;
 
 	handled = 0;
 	vmcs = &vmx->vmcs[vcpu];
@@ -1383,46 +1391,31 @@ vmx_exit_process(struct vmx *vmx, int vc
 		break;
 	case EXIT_REASON_RDMSR:
 		vmm_stat_incr(vmx->vm, vcpu, VMEXIT_RDMSR, 1);
-		retu = false;
 		ecx = vmxctx->guest_rcx;
-		error = emulate_rdmsr(vmx->vm, vcpu, ecx, &retu);
+		error = emulate_rdmsr(vmx->vm, vcpu, ecx);
 		if (error) {
 			vmexit->exitcode = VM_EXITCODE_RDMSR;
 			vmexit->u.msr.code = ecx;
-		} else if (!retu) {
+		} else
 			handled = 1;
-		} else {
-			/* Return to userspace with a valid exitcode */
-			KASSERT(vmexit->exitcode != VM_EXITCODE_BOGUS,
-			    ("emulate_wrmsr retu with bogus exitcode"));
-		}
 		break;
 	case EXIT_REASON_WRMSR:
 		vmm_stat_incr(vmx->vm, vcpu, VMEXIT_WRMSR, 1);
-		retu = false;
 		eax = vmxctx->guest_rax;
 		ecx = vmxctx->guest_rcx;
 		edx = vmxctx->guest_rdx;
 		error = emulate_wrmsr(vmx->vm, vcpu, ecx,
-		    (uint64_t)edx << 32 | eax, &retu);
+					(uint64_t)edx << 32 | eax);
 		if (error) {
 			vmexit->exitcode = VM_EXITCODE_WRMSR;
 			vmexit->u.msr.code = ecx;
 			vmexit->u.msr.wval = (uint64_t)edx << 32 | eax;
-		} else if (!retu) {
+		} else
 			handled = 1;
-		} else {
-			/* Return to userspace with a valid exitcode */
-			KASSERT(vmexit->exitcode != VM_EXITCODE_BOGUS,
-			    ("emulate_wrmsr retu with bogus exitcode"));
-		}
 		break;
 	case EXIT_REASON_HLT:
 		vmm_stat_incr(vmx->vm, vcpu, VMEXIT_HLT, 1);
-		if ((error = vmread(VMCS_GUEST_RFLAGS, &rflags)) != 0)
-			panic("vmx_exit_process: vmread(rflags) %d", error);
 		vmexit->exitcode = VM_EXITCODE_HLT;
-		vmexit->u.hlt.rflags = rflags;
 		break;
 	case EXIT_REASON_MTF:
 		vmm_stat_incr(vmx->vm, vcpu, VMEXIT_MTRAP, 1);
@@ -1435,7 +1428,7 @@ vmx_exit_process(struct vmx *vmx, int vc
 	case EXIT_REASON_INTR_WINDOW:
 		vmm_stat_incr(vmx->vm, vcpu, VMEXIT_INTR_WINDOW, 1);
 		vmx_clear_int_window_exiting(vmx, vcpu);
-		VCPU_CTR0(vmx->vm, vcpu, "Disabling interrupt window exiting");
+		VMM_CTR0(vmx->vm, vcpu, "Disabling interrupt window exiting");
 		return (1);
 	case EXIT_REASON_EXT_INTR:
 		/*
@@ -1458,7 +1451,7 @@ vmx_exit_process(struct vmx *vmx, int vc
 		/* Exit to allow the pending virtual NMI to be injected */
 		vmm_stat_incr(vmx->vm, vcpu, VMEXIT_NMI_WINDOW, 1);
 		vmx_clear_nmi_window_exiting(vmx, vcpu);
-		VCPU_CTR0(vmx->vm, vcpu, "Disabling NMI window exiting");
+		VMM_CTR0(vmx->vm, vcpu, "Disabling NMI window exiting");
 		return (1);
 	case EXIT_REASON_INOUT:
 		vmm_stat_incr(vmx->vm, vcpu, VMEXIT_INOUT, 1);
@@ -1486,6 +1479,7 @@ vmx_exit_process(struct vmx *vmx, int vc
 			vmexit->exitcode = VM_EXITCODE_PAGING;
 			vmexit->u.paging.gpa = gpa;
 			vmexit->u.paging.fault_type = ept_fault_type(qual);
+			vmexit->u.paging.protection = ept_protection(qual);
 		} else if (ept_emulation_fault(qual)) {
 			vmexit->exitcode = VM_EXITCODE_INST_EMUL;
 			vmexit->u.inst_emul.gpa = gpa;
@@ -1576,6 +1570,7 @@ vmx_run(void *arg, int vcpu, register_t 
 		panic("vmx_run: error %d setting up pcpu defaults", error);
 
 	do {
+		lapic_timer_tick(vmx->vm, vcpu);
 		vmx_inject_interrupts(vmx, vcpu);
 		vmx_run_trace(vmx, vcpu);
 		rc = vmx_setjmp(vmxctx);
@@ -1657,7 +1652,7 @@ vmx_run(void *arg, int vcpu, register_t 
 	if (!handled)
 		vmm_stat_incr(vmx->vm, vcpu, VMEXIT_USERSPACE, 1);
 
-	VCPU_CTR1(vmx->vm, vcpu, "goto userland: exitcode %d",vmexit->exitcode);
+	VMM_CTR1(vmx->vm, vcpu, "goto userland: exitcode %d",vmexit->exitcode);
 
 	/*
 	 * XXX
@@ -1937,10 +1932,6 @@ vmx_getcap(void *arg, int vcpu, int type
 		if (cap_unrestricted_guest)
 			ret = 0;
 		break;
-	case VM_CAP_ENABLE_INVPCID:
-		if (cap_invpcid)
-			ret = 0;
-		break;
 	default:
 		break;
 	}
@@ -1997,21 +1988,11 @@ vmx_setcap(void *arg, int vcpu, int type
 	case VM_CAP_UNRESTRICTED_GUEST:
 		if (cap_unrestricted_guest) {
 			retval = 0;
-			pptr = &vmx->cap[vcpu].proc_ctls2;
-			baseval = *pptr;
+			baseval = procbased_ctls2;
 			flag = PROCBASED2_UNRESTRICTED_GUEST;
 			reg = VMCS_SEC_PROC_BASED_CTLS;
 		}
 		break;
-	case VM_CAP_ENABLE_INVPCID:
-		if (cap_invpcid) {
-			retval = 0;
-			pptr = &vmx->cap[vcpu].proc_ctls2;
-			baseval = *pptr;
-			flag = PROCBASED2_ENABLE_INVPCID;
-			reg = VMCS_SEC_PROC_BASED_CTLS;
-		}
-		break;
 	default:
 		break;
 	}

Modified: projects/bhyve_svm/sys/amd64/vmm/intel/vmx.h
==============================================================================
--- projects/bhyve_svm/sys/amd64/vmm/intel/vmx.h	Tue Feb  4 03:59:35 2014	(r261456)
+++ projects/bhyve_svm/sys/amd64/vmm/intel/vmx.h	Tue Feb  4 05:03:14 2014	(r261457)
@@ -84,7 +84,6 @@ struct vmxctx {
 struct vmxcap {
 	int	set;
 	uint32_t proc_ctls;
-	uint32_t proc_ctls2;
 };
 
 struct vmxstate {

Modified: projects/bhyve_svm/sys/amd64/vmm/intel/vmx_controls.h
==============================================================================
--- projects/bhyve_svm/sys/amd64/vmm/intel/vmx_controls.h	Tue Feb  4 03:59:35 2014	(r261456)
+++ projects/bhyve_svm/sys/amd64/vmm/intel/vmx_controls.h	Tue Feb  4 05:03:14 2014	(r261457)
@@ -56,7 +56,7 @@
 #define	PROCBASED_MSR_BITMAPS		(1 << 28)
 #define	PROCBASED_MONITOR_EXITING	(1 << 29)
 #define	PROCBASED_PAUSE_EXITING		(1 << 30)
-#define	PROCBASED_SECONDARY_CONTROLS	(1U << 31)
+#define	PROCBASED_SECONDARY_CONTROLS	(1 << 31)
 
 /* Secondary Processor-Based VM-Execution Controls */
 #define	PROCBASED2_VIRTUALIZE_APIC	(1 << 0)
@@ -68,7 +68,6 @@
 #define	PROCBASED2_WBINVD_EXITING	(1 << 6)
 #define	PROCBASED2_UNRESTRICTED_GUEST	(1 << 7)
 #define	PROCBASED2_PAUSE_LOOP_EXITING	(1 << 10)
-#define	PROCBASED2_ENABLE_INVPCID	(1 << 12)
 
 /* VM Exit Controls */
 #define	VM_EXIT_SAVE_DEBUG_CONTROLS	(1 << 2)

Modified: projects/bhyve_svm/sys/amd64/vmm/intel/vmx_genassym.c
==============================================================================
--- projects/bhyve_svm/sys/amd64/vmm/intel/vmx_genassym.c	Tue Feb  4 03:59:35 2014	(r261456)
+++ projects/bhyve_svm/sys/amd64/vmm/intel/vmx_genassym.c	Tue Feb  4 05:03:14 2014	(r261457)
@@ -38,6 +38,8 @@ __FBSDID("$FreeBSD$");
 #include <vm/vm.h>
 #include <vm/pmap.h>
 
+#include <machine/pmap.h>
+
 #include <machine/vmm.h>
 #include "vmx.h"
 #include "vmx_cpufunc.h"

Modified: projects/bhyve_svm/sys/amd64/vmm/intel/vtd.c
==============================================================================
--- projects/bhyve_svm/sys/amd64/vmm/intel/vtd.c	Tue Feb  4 03:59:35 2014	(r261456)
+++ projects/bhyve_svm/sys/amd64/vmm/intel/vtd.c	Tue Feb  4 05:03:14 2014	(r261457)
@@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$");
 
 #include <dev/pci/pcireg.h>
 
+#include <machine/pmap.h>
 #include <machine/vmparam.h>
 #include <contrib/dev/acpica/include/acpi.h>
 
@@ -73,11 +74,11 @@ struct vtdmap {
 
 #define	VTD_GCR_WBF		(1 << 27)
 #define	VTD_GCR_SRTP		(1 << 30)
-#define	VTD_GCR_TE		(1U << 31)
+#define	VTD_GCR_TE		(1 << 31)
 
 #define	VTD_GSR_WBFS		(1 << 27)
 #define	VTD_GSR_RTPS		(1 << 30)
-#define	VTD_GSR_TES		(1U << 31)
+#define	VTD_GSR_TES		(1 << 31)
 
 #define	VTD_CCR_ICC		(1UL << 63)	/* invalidate context cache */
 #define	VTD_CCR_CIRG_GLOBAL	(1UL << 61)	/* global invalidation */

Modified: projects/bhyve_svm/sys/amd64/vmm/io/ppt.c
==============================================================================
--- projects/bhyve_svm/sys/amd64/vmm/io/ppt.c	Tue Feb  4 03:59:35 2014	(r261456)
+++ projects/bhyve_svm/sys/amd64/vmm/io/ppt.c	Tue Feb  4 05:03:14 2014	(r261457)
@@ -421,7 +421,7 @@ pptintr(void *arg)
 	vec = pptarg->vec;
 
 	if (ppt->vm != NULL)
-		lapic_intr_edge(ppt->vm, pptarg->vcpu, vec);
+		(void) lapic_set_intr(ppt->vm, pptarg->vcpu, vec);
 	else {
 		/*
 		 * XXX

Copied: projects/bhyve_svm/sys/amd64/vmm/io/vdev.c (from r261451, projects/bhyve_svm/sys/amd64/vmm/io/vdev.c)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ projects/bhyve_svm/sys/amd64/vmm/io/vdev.c	Tue Feb  4 05:03:14 2014	(r261457, copy of r261451, projects/bhyve_svm/sys/amd64/vmm/io/vdev.c)
@@ -0,0 +1,270 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+
+#include "vdev.h"
+
+struct vdev {
+	SLIST_ENTRY(vdev) 	 entry;
+	struct vdev_ops 	*ops;
+	void			*dev;
+};
+static SLIST_HEAD(, vdev)	vdev_head;
+static int 		  	vdev_count;
+
+struct vdev_region {
+	SLIST_ENTRY(vdev_region) 	 entry;
+	struct vdev_ops 		*ops;
+	void				*dev;
+	struct io_region		*io;
+};
+static SLIST_HEAD(, vdev_region)	 region_head;
+static int 		  		 region_count;
+
+static MALLOC_DEFINE(M_VDEV, "vdev", "vdev");
+
+#define VDEV_INIT 	(0)
+#define VDEV_RESET	(1)
+#define VDEV_HALT	(2)
+
+// static const char* vdev_event_str[] = {"VDEV_INIT", "VDEV_RESET", "VDEV_HALT"};
+
+static int
+vdev_system_event(int event)
+{
+	struct vdev 	*vd;
+	int		 rc;
+
+	// TODO: locking
+	SLIST_FOREACH(vd, &vdev_head, entry) {
+		// printf("%s : %s Device %s\n", __func__, vdev_event_str[event], vd->ops->name);
+		switch (event) {
+			case VDEV_INIT:
+				rc = vd->ops->init(vd->dev);
+				break;
+			case VDEV_RESET:
+				rc = vd->ops->reset(vd->dev);
+				break;
+			case VDEV_HALT:
+				rc = vd->ops->halt(vd->dev);
+				break;
+			default:
+				break;
+		}
+		if (rc) {
+			printf("vdev %s init failed rc=%d\n",
+			    vd->ops->name, rc);
+			return rc;
+		}
+	}
+	return 0;
+}
+
+int
+vdev_init(void)
+{
+	return vdev_system_event(VDEV_INIT);
+}
+
+int
+vdev_reset(void)
+{
+	return vdev_system_event(VDEV_RESET);
+}
+
+int
+vdev_halt(void)
+{
+	return vdev_system_event(VDEV_HALT);
+}
+
+void
+vdev_vm_init(void)
+{
+	SLIST_INIT(&vdev_head);
+	vdev_count = 0;
+
+	SLIST_INIT(&region_head);
+	region_count = 0;
+}
+void
+vdev_vm_cleanup(void)
+{
+	struct vdev *vd;
+     
+	// TODO: locking
+	while (!SLIST_EMPTY(&vdev_head)) {
+		vd = SLIST_FIRST(&vdev_head);
+		SLIST_REMOVE_HEAD(&vdev_head, entry);
+		free(vd, M_VDEV);
+		vdev_count--;
+	}
+}
+
+int
+vdev_register(struct vdev_ops *ops, void *dev)
+{
+	struct vdev *vd;
+	vd = malloc(sizeof(*vd), M_VDEV, M_WAITOK | M_ZERO); 
+	vd->ops = ops;
+	vd->dev = dev;
+	
+	// TODO: locking
+	SLIST_INSERT_HEAD(&vdev_head, vd, entry); 
+	vdev_count++;
+	return 0;
+}
+
+void
+vdev_unregister(void *dev)
+{
+	struct vdev 	*vd, *found;
+
+	found = NULL;
+	// TODO: locking
+	SLIST_FOREACH(vd, &vdev_head, entry) {
+		if (vd->dev == dev) {
+			found = vd;
+		}
+	}
+
+	if (found) {
+		SLIST_REMOVE(&vdev_head, found, vdev, entry);
+		free(found, M_VDEV);
+	}
+}
+
+#define IN_RANGE(val, start, end)	\
+    (((val) >= (start)) && ((val) < (end)))
+
+static struct vdev_region*
+vdev_find_region(struct io_region *io, void *dev) 
+{
+	struct 		vdev_region *region, *found;
+	uint64_t	region_base;
+	uint64_t	region_end;
+
+	found = NULL;
+
+	// TODO: locking
+	// FIXME: we should verify we are in the context the current
+	// 	  vcpu here as well.
+	SLIST_FOREACH(region, &region_head, entry) {
+		region_base = region->io->base;
+		region_end = region_base + region->io->len;
+		if (IN_RANGE(io->base, region_base, region_end) &&
+		    IN_RANGE(io->base+io->len, region_base, region_end+1) &&
+		    (dev && dev == region->dev)) {
+			found = region;
+			break;
+		}
+	}
+	return found;
+}
+
+int
+vdev_register_region(struct vdev_ops *ops, void *dev, struct io_region *io)
+{
+	struct vdev_region *region;
+
+	region = vdev_find_region(io, dev);
+	if (region) {
+		return -EEXIST;
+	}
+
+	region = malloc(sizeof(*region), M_VDEV, M_WAITOK | M_ZERO);
+	region->io = io;
+	region->ops = ops;
+	region->dev = dev;
+
+	// TODO: locking
+	SLIST_INSERT_HEAD(&region_head, region, entry); 
+	region_count++;
+
+	return 0;
+}
+
+void
+vdev_unregister_region(void *dev, struct io_region *io)
+{
+	struct vdev_region *region;
+
+	region = vdev_find_region(io, dev);
+	
+	if (region) {
+		SLIST_REMOVE(&region_head, region, vdev_region, entry);
+		free(region, M_VDEV);
+		region_count--;
+	}
+}
+
+static int
+vdev_memrw(uint64_t gpa, opsize_t size, uint64_t *data, int read)
+{
+	struct vdev_region 	*region;
+	struct io_region	 io;
+	region_attr_t		 attr;
+	int			 rc;
+
+	io.base = gpa;
+	io.len = size;
+
+	region = vdev_find_region(&io, NULL);
+	if (!region)
+		return -EINVAL;
+	
+	attr = (read) ? MMIO_READ : MMIO_WRITE;
+	if (!(region->io->attr & attr))
+		return -EPERM;
+
+	if (read)
+		rc = region->ops->memread(region->dev, gpa, size, data);
+	else 
+		rc = region->ops->memwrite(region->dev, gpa, size, *data);
+
+	return rc;
+}
+
+int
+vdev_memread(uint64_t gpa, opsize_t size, uint64_t *data)
+{
+	return vdev_memrw(gpa, size, data, 1);
+}
+
+int
+vdev_memwrite(uint64_t gpa, opsize_t size, uint64_t data)
+{
+	return vdev_memrw(gpa, size, &data, 0);
+}

Copied: projects/bhyve_svm/sys/amd64/vmm/io/vdev.h (from r261451, projects/bhyve_svm/sys/amd64/vmm/io/vdev.h)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ projects/bhyve_svm/sys/amd64/vmm/io/vdev.h	Tue Feb  4 05:03:14 2014	(r261457, copy of r261451, projects/bhyve_svm/sys/amd64/vmm/io/vdev.h)
@@ -0,0 +1,84 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _VDEV_H_
+#define	_VDEV_H_
+
+typedef enum {
+	BYTE	= 1,
+	WORD	= 2,
+	DWORD	= 4,
+	QWORD	= 8,
+} opsize_t;
+
+typedef enum {
+	MMIO_READ = 1,
+	MMIO_WRITE = 2,
+} region_attr_t;
+
+struct io_region {
+	uint64_t	base;
+	uint64_t	len;
+	region_attr_t	attr;
+	int		vcpu;
+};
+
+typedef int (*vdev_init_t)(void* dev);
+typedef int (*vdev_reset_t)(void* dev);
+typedef int (*vdev_halt_t)(void* dev);
+typedef int (*vdev_memread_t)(void* dev, uint64_t gpa, opsize_t size, uint64_t *data);
+typedef int (*vdev_memwrite_t)(void* dev, uint64_t gpa, opsize_t size, uint64_t data);
+
+
+struct vdev_ops {
+	const char	*name;
+	vdev_init_t	init;
+	vdev_reset_t	reset;
+	vdev_halt_t	halt;
+	vdev_memread_t	memread;
+	vdev_memwrite_t	memwrite;
+};
+
+
+void vdev_vm_init(void);
+void vdev_vm_cleanup(void);
+
+int  vdev_register(struct vdev_ops *ops, void *dev);
+void vdev_unregister(void *dev);
+
+int  vdev_register_region(struct vdev_ops *ops, void *dev, struct io_region *io);
+void vdev_unregister_region(void *dev, struct io_region *io);
+
+int vdev_init(void);
+int vdev_reset(void);
+int vdev_halt(void);
+int vdev_memread(uint64_t gpa, opsize_t size, uint64_t *data);
+int vdev_memwrite(uint64_t gpa, opsize_t size, uint64_t data);
+
+#endif	/* _VDEV_H_ */
+

Modified: projects/bhyve_svm/sys/amd64/vmm/io/vlapic.c
==============================================================================
--- projects/bhyve_svm/sys/amd64/vmm/io/vlapic.c	Tue Feb  4 03:59:35 2014	(r261456)
+++ projects/bhyve_svm/sys/amd64/vmm/io/vlapic.c	Tue Feb  4 05:03:14 2014	(r261457)
@@ -30,10 +30,8 @@
 __FBSDID("$FreeBSD$");
 
 #include <sys/param.h>
-#include <sys/lock.h>
 #include <sys/kernel.h>
 #include <sys/malloc.h>
-#include <sys/mutex.h>
 #include <sys/systm.h>
 #include <sys/smp.h>
 
@@ -46,17 +44,14 @@ __FBSDID("$FreeBSD$");
 #include "vmm_stat.h"
 #include "vmm_lapic.h"
 #include "vmm_ktr.h"
+#include "vdev.h"
 #include "vlapic.h"
-#include "vioapic.h"
 
 #define	VLAPIC_CTR0(vlapic, format)					\
-	VCPU_CTR0((vlapic)->vm, (vlapic)->vcpuid, format)
+	VMM_CTR0((vlapic)->vm, (vlapic)->vcpuid, format)
 
 #define	VLAPIC_CTR1(vlapic, format, p1)					\
-	VCPU_CTR1((vlapic)->vm, (vlapic)->vcpuid, format, p1)
-
-#define	VLAPIC_CTR2(vlapic, format, p1, p2)				\
-	VCPU_CTR2((vlapic)->vm, (vlapic)->vcpuid, format, p1, p2)
+	VMM_CTR1((vlapic)->vm, (vlapic)->vcpuid, format, p1)
 
 #define	VLAPIC_CTR_IRR(vlapic, msg)					\
 do {									\
@@ -105,15 +100,14 @@ struct vlapic {
 	struct vm		*vm;
 	int			vcpuid;
 
-	struct LAPIC		apic;
+	struct io_region	*mmio;
+	struct vdev_ops		*ops;
+	struct LAPIC		 apic;
 
 	int			 esr_update;
 
-	struct callout	callout;	/* vlapic timer */
-	struct bintime	timer_fire_bt;	/* callout expiry time */
-	struct bintime	timer_freq_bt;	/* timer frequency */
-	struct bintime	timer_period_bt; /* timer period */
-	struct mtx	timer_mtx;
+	int			 divisor;
+	int			 ccr_ticks;
 
 	/*
 	 * The 'isrvec_stk' is a stack of vectors injected by the local apic.
@@ -128,21 +122,6 @@ struct vlapic {
 	enum boot_state		boot_state;
 };
 
-/*
- * The 'vlapic->timer_mtx' is used to provide mutual exclusion between the
- * vlapic_callout_handler() and vcpu accesses to the following registers:
- * - initial count register aka icr_timer
- * - current count register aka ccr_timer
- * - divide config register aka dcr_timer
- * - timer LVT register
- *
- * Note that the vlapic_callout_handler() does not write to any of these
- * registers so they can be safely read from the vcpu context without locking.
- */
-#define	VLAPIC_TIMER_LOCK(vlapic)	mtx_lock_spin(&((vlapic)->timer_mtx))
-#define	VLAPIC_TIMER_UNLOCK(vlapic)	mtx_unlock_spin(&((vlapic)->timer_mtx))
-#define	VLAPIC_TIMER_LOCKED(vlapic)	mtx_owned(&((vlapic)->timer_mtx))
-
 #define VLAPIC_BUS_FREQ	tsc_freq
 
 static int
@@ -190,62 +169,11 @@ vlapic_dump_lvt(uint32_t offset, uint32_
 }
 #endif
 
-static uint32_t
+static uint64_t
 vlapic_get_ccr(struct vlapic *vlapic)
 {
-	struct bintime bt_now, bt_rem;
-	struct LAPIC *lapic;
-	uint32_t ccr;
-	
-	ccr = 0;
-	lapic = &vlapic->apic;
-
-	VLAPIC_TIMER_LOCK(vlapic);
-	if (callout_active(&vlapic->callout)) {
-		/*
-		 * If the timer is scheduled to expire in the future then
-		 * compute the value of 'ccr' based on the remaining time.
-		 */
-		binuptime(&bt_now);
-		if (bintime_cmp(&vlapic->timer_fire_bt, &bt_now, >)) {
-			bt_rem = vlapic->timer_fire_bt;
-			bintime_sub(&bt_rem, &bt_now);
-			ccr += bt_rem.sec * BT2FREQ(&vlapic->timer_freq_bt);
-			ccr += bt_rem.frac / vlapic->timer_freq_bt.frac;
-		}
-	}
-	KASSERT(ccr <= lapic->icr_timer, ("vlapic_get_ccr: invalid ccr %#x, "
-	    "icr_timer is %#x", ccr, lapic->icr_timer));
-	VLAPIC_CTR2(vlapic, "vlapic ccr_timer = %#x, icr_timer = %#x",
-	    ccr, lapic->icr_timer);
-	VLAPIC_TIMER_UNLOCK(vlapic);
-	return (ccr);
-}
-
-static void
-vlapic_set_dcr(struct vlapic *vlapic, uint32_t dcr)
-{
-	struct LAPIC *lapic;
-	int divisor;
-	
-	lapic = &vlapic->apic;
-	VLAPIC_TIMER_LOCK(vlapic);
-
-	lapic->dcr_timer = dcr;
-	divisor = vlapic_timer_divisor(dcr);
-	VLAPIC_CTR2(vlapic, "vlapic dcr_timer=%#x, divisor=%d", dcr, divisor);
-
-	/*
-	 * Update the timer frequency and the timer period.
-	 *
-	 * XXX changes to the frequency divider will not take effect until
-	 * the timer is reloaded.
-	 */
-	FREQ2BT(VLAPIC_BUS_FREQ / divisor, &vlapic->timer_freq_bt);
-	vlapic->timer_period_bt = vlapic->timer_freq_bt;
-	bintime_mul(&vlapic->timer_period_bt, lapic->icr_timer);
-
-	VLAPIC_TIMER_UNLOCK(vlapic);
+	struct LAPIC    *lapic = &vlapic->apic;
+	return lapic->ccr_timer;
 }
 
 static void
@@ -267,14 +195,15 @@ vlapic_init_ipi(struct vlapic *vlapic)
 }
 
 static int
-vlapic_reset(struct vlapic *vlapic)
+vlapic_op_reset(void* dev)
 {
+	struct vlapic 	*vlapic = (struct vlapic*)dev;
 	struct LAPIC	*lapic = &vlapic->apic;
 
 	memset(lapic, 0, sizeof(*lapic));
 	lapic->apr = vlapic->vcpuid;
 	vlapic_init_ipi(vlapic);
-	vlapic_set_dcr(vlapic, 0);
+	vlapic->divisor = vlapic_timer_divisor(lapic->dcr_timer);
 
 	if (vlapic->vcpuid == 0)
 		vlapic->boot_state = BS_RUNNING;	/* BSP */
@@ -285,44 +214,63 @@ vlapic_reset(struct vlapic *vlapic)
 
 }
 
+static int
+vlapic_op_init(void* dev)
+{
+	struct vlapic *vlapic = (struct vlapic*)dev;
+	vdev_register_region(vlapic->ops, vlapic, vlapic->mmio);
+	return vlapic_op_reset(dev);
+}
+
+static int
+vlapic_op_halt(void* dev)
+{
+	struct vlapic *vlapic = (struct vlapic*)dev;
+	vdev_unregister_region(vlapic, vlapic->mmio);
+	return 0;
+
+}
+
 void
-vlapic_set_intr_ready(struct vlapic *vlapic, int vector, bool level)
+vlapic_set_intr_ready(struct vlapic *vlapic, int vector)
 {
 	struct LAPIC	*lapic = &vlapic->apic;
-	uint32_t	*irrptr, *tmrptr, mask;
+	uint32_t	*irrptr;
 	int		idx;
 
 	if (vector < 0 || vector >= 256)
 		panic("vlapic_set_intr_ready: invalid vector %d\n", vector);
 
-	if (!(lapic->svr & APIC_SVR_ENABLE)) {
-		VLAPIC_CTR1(vlapic, "vlapic is software disabled, ignoring "
-		    "interrupt %d", vector);
-		return;
-	}
-
 	idx = (vector / 32) * 4;
-	mask = 1 << (vector % 32);
-
 	irrptr = &lapic->irr0;
-	atomic_set_int(&irrptr[idx], mask);
+	atomic_set_int(&irrptr[idx], 1 << (vector % 32));
+	VLAPIC_CTR_IRR(vlapic, "vlapic_set_intr_ready");
+}
 
-	/*
-	 * Upon acceptance of an interrupt into the IRR the corresponding
-	 * TMR bit is cleared for edge-triggered interrupts and set for
-	 * level-triggered interrupts.
-	 */
-	tmrptr = &lapic->tmr0;
-	if (level)
-		atomic_set_int(&tmrptr[idx], mask);
-	else
-		atomic_clear_int(&tmrptr[idx], mask);
+static void
+vlapic_start_timer(struct vlapic *vlapic, uint32_t elapsed)
+{
+	uint32_t icr_timer;
 
-	VLAPIC_CTR_IRR(vlapic, "vlapic_set_intr_ready");
+	icr_timer = vlapic->apic.icr_timer;
+
+	vlapic->ccr_ticks = ticks;
+	if (elapsed < icr_timer)
+		vlapic->apic.ccr_timer = icr_timer - elapsed;
+	else {
+		/*
+		 * This can happen when the guest is trying to run its local
+		 * apic timer higher that the setting of 'hz' in the host.
+		 *
+		 * We deal with this by running the guest local apic timer
+		 * at the rate of the host's 'hz' setting.
+		 */
+		vlapic->apic.ccr_timer = 0;
+	}
 }
 
 static __inline uint32_t *
-vlapic_get_lvtptr(struct vlapic *vlapic, uint32_t offset)
+vlapic_get_lvt(struct vlapic *vlapic, uint32_t offset)
 {
 	struct LAPIC	*lapic = &vlapic->apic;
 	int 		 i;
@@ -334,33 +282,6 @@ vlapic_get_lvtptr(struct vlapic *vlapic,
 	return ((&lapic->lvt_timer) + i);;
 }
 
-static __inline uint32_t

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



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