svn commit: r261457 - in projects/bhyve_svm/sys/amd64/vmm: . intel io
Peter Grehan
grehan at FreeBSD.org
Tue Feb 4 05:03:17 UTC 2014
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(®ion_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, ®ion_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(®ion_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(®ion_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 ***
More information about the svn-src-projects
mailing list