PERFORCE change 1190142 for review
John Baldwin
jhb at FreeBSD.org
Sat Jan 18 21:23:12 UTC 2014
http://p4web.freebsd.org/@@1190142?ac=10
Change 1190142 by jhb at jhb_pippin on 2014/01/18 21:22:36
IFC @1190140
Affected files ...
.. //depot/projects/pci/sys/amd64/amd64/identcpu.c#9 integrate
.. //depot/projects/pci/sys/amd64/conf/NOTES#12 integrate
.. //depot/projects/pci/sys/amd64/include/vmm.h#8 integrate
.. //depot/projects/pci/sys/amd64/vmm/amd/amdv.c#5 integrate
.. //depot/projects/pci/sys/amd64/vmm/intel/vmcs.c#7 integrate
.. //depot/projects/pci/sys/amd64/vmm/intel/vmcs.h#7 integrate
.. //depot/projects/pci/sys/amd64/vmm/intel/vmx.c#9 integrate
.. //depot/projects/pci/sys/amd64/vmm/intel/vmx.h#6 integrate
.. //depot/projects/pci/sys/amd64/vmm/intel/vmx_genassym.c#6 integrate
.. //depot/projects/pci/sys/amd64/vmm/intel/vmx_support.S#4 integrate
.. //depot/projects/pci/sys/amd64/vmm/io/vioapic.c#3 integrate
.. //depot/projects/pci/sys/amd64/vmm/io/vlapic.c#6 integrate
.. //depot/projects/pci/sys/amd64/vmm/io/vlapic.h#5 integrate
.. //depot/projects/pci/sys/amd64/vmm/vmm.c#8 integrate
.. //depot/projects/pci/sys/amd64/vmm/vmm_stat.c#3 integrate
.. //depot/projects/pci/sys/amd64/vmm/vmm_stat.h#3 integrate
.. //depot/projects/pci/sys/arm/at91/at91_gpio.h#1 branch
.. //depot/projects/pci/sys/arm/at91/at91rm9200.c#4 integrate
.. //depot/projects/pci/sys/arm/at91/at91sam9260.c#3 integrate
.. //depot/projects/pci/sys/arm/at91/at91sam9g20.c#3 integrate
.. //depot/projects/pci/sys/arm/at91/at91sam9g45.c#2 integrate
.. //depot/projects/pci/sys/arm/at91/at91sam9x5.c#2 integrate
.. //depot/projects/pci/sys/arm/at91/at91var.h#3 integrate
.. //depot/projects/pci/sys/arm/freescale/imx/imx51_ipuv3_fbd.c#2 integrate
.. //depot/projects/pci/sys/cam/cam_periph.c#13 integrate
.. //depot/projects/pci/sys/cam/cam_periph.h#8 integrate
.. //depot/projects/pci/sys/cam/cam_xpt.c#15 integrate
.. //depot/projects/pci/sys/cam/scsi/scsi_xpt.c#10 integrate
.. //depot/projects/pci/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c#9 integrate
.. //depot/projects/pci/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_traverse.c#6 integrate
.. //depot/projects/pci/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_mirror.c#6 integrate
.. //depot/projects/pci/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_dir.c#7 integrate
.. //depot/projects/pci/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c#12 integrate
.. //depot/projects/pci/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c#9 integrate
.. //depot/projects/pci/sys/compat/freebsd32/freebsd32_misc.c#14 integrate
.. //depot/projects/pci/sys/conf/files.amd64#13 integrate
.. //depot/projects/pci/sys/conf/files.i386#15 integrate
.. //depot/projects/pci/sys/contrib/dev/iwn/iwlwifi-105-6-18.168.6.1.fw.uu#1 branch
.. //depot/projects/pci/sys/contrib/ipfilter/netinet/ip_compat.h#6 integrate
.. //depot/projects/pci/sys/contrib/ipfilter/netinet/ip_fil_freebsd.c#4 integrate
.. //depot/projects/pci/sys/dev/ahci/ahci.c#16 integrate
.. //depot/projects/pci/sys/dev/altera/atse/if_atse.c#2 integrate
.. //depot/projects/pci/sys/dev/bxe/bxe.c#6 integrate
.. //depot/projects/pci/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c#4 integrate
.. //depot/projects/pci/sys/dev/netmap/netmap.c#7 integrate
.. //depot/projects/pci/sys/dev/netmap/netmap_generic.c#3 integrate
.. //depot/projects/pci/sys/dev/netmap/netmap_vale.c#3 integrate
.. //depot/projects/pci/sys/dev/qlxge/qls_os.c#2 integrate
.. //depot/projects/pci/sys/dev/usb/controller/ehci.c#9 integrate
.. //depot/projects/pci/sys/dev/usb/controller/uhci.c#6 integrate
.. //depot/projects/pci/sys/dev/usb/controller/xhci.c#11 integrate
.. //depot/projects/pci/sys/dev/usb/input/ukbd.c#11 integrate
.. //depot/projects/pci/sys/dev/usb/net/uhso.c#9 integrate
.. //depot/projects/pci/sys/dev/usb/serial/u3g.c#9 integrate
.. //depot/projects/pci/sys/dev/usb/serial/umcs.c#5 integrate
.. //depot/projects/pci/sys/dev/usb/usb_dev.c#6 integrate
.. //depot/projects/pci/sys/dev/usb/usb_device.c#8 integrate
.. //depot/projects/pci/sys/dev/usb/usb_device.h#8 integrate
.. //depot/projects/pci/sys/dev/usb/usb_hub.c#11 integrate
.. //depot/projects/pci/sys/dev/usb/usb_hub.h#4 integrate
.. //depot/projects/pci/sys/dev/usb/usb_request.c#8 integrate
.. //depot/projects/pci/sys/dev/usb/usb_transfer.c#8 integrate
.. //depot/projects/pci/sys/dev/usb/wlan/if_run.c#12 integrate
.. //depot/projects/pci/sys/dev/virtio/block/virtio_blk.c#5 integrate
.. //depot/projects/pci/sys/dev/virtio/random/virtio_random.c#1 branch
.. //depot/projects/pci/sys/dev/virtio/scsi/virtio_scsi.c#4 integrate
.. //depot/projects/pci/sys/dev/vt/hw/xboxfb/xboxfb.c#3 integrate
.. //depot/projects/pci/sys/fs/ext2fs/ext2_inode_cnv.c#7 integrate
.. //depot/projects/pci/sys/fs/nfs/nfs_var.h#12 integrate
.. //depot/projects/pci/sys/fs/nfsserver/nfs_nfsdcache.c#9 integrate
.. //depot/projects/pci/sys/fs/nfsserver/nfs_nfsdkrpc.c#8 integrate
.. //depot/projects/pci/sys/geom/uncompress/g_uncompress.c#3 integrate
.. //depot/projects/pci/sys/i386/conf/NOTES#11 integrate
.. //depot/projects/pci/sys/i386/i386/identcpu.c#8 integrate
.. //depot/projects/pci/sys/ia64/ia64/exception.S#7 integrate
.. //depot/projects/pci/sys/kern/kern_event.c#11 integrate
.. //depot/projects/pci/sys/kern/subr_sglist.c#3 integrate
.. //depot/projects/pci/sys/kern/uipc_mbuf.c#9 integrate
.. //depot/projects/pci/sys/kern/uipc_sockbuf.c#7 integrate
.. //depot/projects/pci/sys/kern/uipc_socket.c#9 integrate
.. //depot/projects/pci/sys/kern/uipc_syscalls.c#14 integrate
.. //depot/projects/pci/sys/mips/cavium/ciu.c#4 integrate
.. //depot/projects/pci/sys/modules/geom/Makefile#4 integrate
.. //depot/projects/pci/sys/modules/geom/geom_uncompress/Makefile#3 integrate
.. //depot/projects/pci/sys/modules/iwnfw/Makefile#7 integrate
.. //depot/projects/pci/sys/modules/iwnfw/iwn105/Makefile#1 branch
.. //depot/projects/pci/sys/modules/sound/driver/ai2s/Makefile#3 integrate
.. //depot/projects/pci/sys/modules/virtio/Makefile#3 integrate
.. //depot/projects/pci/sys/modules/virtio/random/Makefile#1 branch
.. //depot/projects/pci/sys/net/netmap_user.h#6 integrate
.. //depot/projects/pci/sys/net80211/ieee80211_mesh.c#11 integrate
.. //depot/projects/pci/sys/netinet/in.c#12 integrate
.. //depot/projects/pci/sys/netinet/in_mcast.c#8 integrate
.. //depot/projects/pci/sys/netinet/ip_output.c#13 integrate
.. //depot/projects/pci/sys/netinet6/in6.c#14 integrate
.. //depot/projects/pci/sys/netinet6/in6_ifattach.c#10 integrate
.. //depot/projects/pci/sys/netinet6/in6_var.h#8 integrate
.. //depot/projects/pci/sys/netinet6/nd6_rtr.c#9 integrate
.. //depot/projects/pci/sys/netpfil/ipfw/ip_fw_nat.c#4 integrate
.. //depot/projects/pci/sys/powerpc/include/atomic.h#4 integrate
.. //depot/projects/pci/sys/powerpc/powermac/macgpio.c#3 integrate
.. //depot/projects/pci/sys/powerpc/powermac/macgpiovar.h#3 integrate
.. //depot/projects/pci/sys/sys/mbuf.h#10 integrate
.. //depot/projects/pci/sys/sys/random.h#6 integrate
.. //depot/projects/pci/sys/sys/sf_base.h#2 integrate
.. //depot/projects/pci/sys/sys/sf_sync.h#2 integrate
.. //depot/projects/pci/sys/sys/sglist.h#3 integrate
.. //depot/projects/pci/sys/sys/socket.h#8 integrate
.. //depot/projects/pci/sys/vm/vm_pageout.c#11 integrate
Differences ...
==== //depot/projects/pci/sys/amd64/amd64/identcpu.c#9 (text+ko) ====
@@ -39,7 +39,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/amd64/amd64/identcpu.c 257856 2013-11-08 16:32:30Z kib $");
+__FBSDID("$FreeBSD: head/sys/amd64/amd64/identcpu.c 260557 2014-01-11 22:41:10Z gavin $");
#include "opt_cpu.h"
@@ -206,16 +206,16 @@
}
printf("-class CPU)\n");
if (*cpu_vendor)
- printf(" Origin = \"%s\"", cpu_vendor);
+ printf(" Origin=\"%s\"", cpu_vendor);
if (cpu_id)
- printf(" Id = 0x%x", cpu_id);
+ printf(" Id=0x%x", cpu_id);
if (cpu_vendor_id == CPU_VENDOR_INTEL ||
cpu_vendor_id == CPU_VENDOR_AMD ||
cpu_vendor_id == CPU_VENDOR_CENTAUR) {
- printf(" Family = 0x%x", CPUID_TO_FAMILY(cpu_id));
- printf(" Model = 0x%x", CPUID_TO_MODEL(cpu_id));
- printf(" Stepping = %u", cpu_id & CPUID_STEPPING);
+ printf(" Family=0x%x", CPUID_TO_FAMILY(cpu_id));
+ printf(" Model=0x%x", CPUID_TO_MODEL(cpu_id));
+ printf(" Stepping=%u", cpu_id & CPUID_STEPPING);
/*
* AMD CPUID Specification
==== //depot/projects/pci/sys/amd64/conf/NOTES#12 (text+ko) ====
@@ -4,7 +4,7 @@
# This file contains machine dependent kernel configuration notes. For
# machine independent notes, look in /sys/conf/NOTES.
#
-# $FreeBSD: head/sys/amd64/conf/NOTES 260376 2014-01-06 17:23:22Z schweikh $
+# $FreeBSD: head/sys/amd64/conf/NOTES 260847 2014-01-18 06:14:38Z bryanv $
#
#
@@ -472,6 +472,7 @@
device virtio_blk # VirtIO Block device
device virtio_scsi # VirtIO SCSI device
device virtio_balloon # VirtIO Memory Balloon device
+device virtio_random # VirtIO Entropy device
device hyperv # HyperV drivers
==== //depot/projects/pci/sys/amd64/include/vmm.h#8 (text+ko) ====
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: head/sys/amd64/include/vmm.h 260466 2014-01-09 03:25:54Z neel $
+ * $FreeBSD: head/sys/amd64/include/vmm.h 260619 2014-01-14 01:55:58Z neel $
*/
#ifndef _VMM_H_
@@ -52,7 +52,7 @@
typedef void (*vmm_resume_func_t)(void);
typedef void * (*vmi_init_func_t)(struct vm *vm, struct pmap *pmap);
typedef int (*vmi_run_func_t)(void *vmi, int vcpu, register_t rip,
- struct pmap *pmap);
+ struct pmap *pmap, void *rendezvous_cookie);
typedef void (*vmi_cleanup_func_t)(void *vmi);
typedef int (*vmi_get_register_t)(void *vmi, int vcpu, int num,
uint64_t *retval);
@@ -136,6 +136,31 @@
struct vm_exit *vm_exitinfo(struct vm *vm, int vcpuid);
/*
+ * Rendezvous all vcpus specified in 'dest' and execute 'func(arg)'.
+ * The rendezvous 'func(arg)' is not allowed to do anything that will
+ * cause the thread to be put to sleep.
+ *
+ * If the rendezvous is being initiated from a vcpu context then the
+ * 'vcpuid' must refer to that vcpu, otherwise it should be set to -1.
+ *
+ * The caller cannot hold any locks when initiating the rendezvous.
+ *
+ * The implementation of this API may cause vcpus other than those specified
+ * by 'dest' to be stalled. The caller should not rely on any vcpus making
+ * forward progress when the rendezvous is in progress.
+ */
+typedef void (*vm_rendezvous_func_t)(struct vm *vm, int vcpuid, void *arg);
+void vm_smp_rendezvous(struct vm *vm, int vcpuid, cpuset_t dest,
+ vm_rendezvous_func_t func, void *arg);
+
+static __inline int
+vcpu_rendezvous_pending(void *rendezvous_cookie)
+{
+
+ return (*(uintptr_t *)rendezvous_cookie != 0);
+}
+
+/*
* Return 1 if device indicated by bus/slot/func is supposed to be a
* pci passthrough device.
*
@@ -272,6 +297,7 @@
VM_EXITCODE_INST_EMUL,
VM_EXITCODE_SPINUP_AP,
VM_EXITCODE_SPINDOWN_CPU,
+ VM_EXITCODE_RENDEZVOUS,
VM_EXITCODE_MAX
};
==== //depot/projects/pci/sys/amd64/vmm/amd/amdv.c#5 (text+ko) ====
@@ -23,11 +23,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: head/sys/amd64/vmm/amd/amdv.c 260466 2014-01-09 03:25:54Z neel $
+ * $FreeBSD: head/sys/amd64/vmm/amd/amdv.c 260619 2014-01-14 01:55:58Z neel $
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/amd64/vmm/amd/amdv.c 260466 2014-01-09 03:25:54Z neel $");
+__FBSDID("$FreeBSD: head/sys/amd64/vmm/amd/amdv.c 260619 2014-01-14 01:55:58Z neel $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -67,7 +67,7 @@
}
static int
-amdv_vmrun(void *arg, int vcpu, register_t rip, struct pmap *pmap)
+amdv_vmrun(void *arg, int vcpu, register_t rip, struct pmap *pmap, void *cookie)
{
printf("amdv_vmrun: not implemented\n");
==== //depot/projects/pci/sys/amd64/vmm/intel/vmcs.c#7 (text+ko) ====
@@ -23,13 +23,13 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: head/sys/amd64/vmm/intel/vmcs.c 260380 2014-01-06 23:16:39Z neel $
+ * $FreeBSD: head/sys/amd64/vmm/intel/vmcs.c 260531 2014-01-11 03:14:05Z neel $
*/
#include "opt_ddb.h"
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/amd64/vmm/intel/vmcs.c 260380 2014-01-06 23:16:39Z neel $");
+__FBSDID("$FreeBSD: head/sys/amd64/vmm/intel/vmcs.c 260531 2014-01-11 03:14:05Z neel $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -473,7 +473,7 @@
switch (exit & 0x8000ffff) {
case EXIT_REASON_EXCEPTION:
case EXIT_REASON_EXT_INTR:
- val = vmcs_read(VMCS_EXIT_INTERRUPTION_INFO);
+ val = vmcs_read(VMCS_EXIT_INTR_INFO);
db_printf("Interrupt Type: ");
switch (val >> 8 & 0x7) {
case 0:
@@ -495,7 +495,7 @@
db_printf(" Vector: %lu", val & 0xff);
if (val & 0x800)
db_printf(" Error Code: %lx",
- vmcs_read(VMCS_EXIT_INTERRUPTION_ERROR));
+ vmcs_read(VMCS_EXIT_INTR_ERRCODE));
db_printf("\n");
break;
case EXIT_REASON_EPT_FAULT:
==== //depot/projects/pci/sys/amd64/vmm/intel/vmcs.h#7 (text+ko) ====
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: head/sys/amd64/vmm/intel/vmcs.h 260410 2014-01-07 21:04:49Z neel $
+ * $FreeBSD: head/sys/amd64/vmm/intel/vmcs.h 260836 2014-01-18 02:20:10Z neel $
*/
#ifndef _VMCS_H_
@@ -97,6 +97,7 @@
/* 16-bit control fields */
#define VMCS_VPID 0x00000000
+#define VMCS_PIR_VECTOR 0x00000002
/* 16-bit guest-state fields */
#define VMCS_GUEST_ES_SELECTOR 0x00000800
@@ -129,6 +130,7 @@
#define VMCS_TSC_OFFSET 0x00002010
#define VMCS_VIRTUAL_APIC 0x00002012
#define VMCS_APIC_ACCESS 0x00002014
+#define VMCS_PIR_DESC 0x00002016
#define VMCS_EPTP 0x0000201A
#define VMCS_EOI_EXIT0 0x0000201C
#define VMCS_EOI_EXIT1 0x0000201E
@@ -177,8 +179,8 @@
/* 32-bit read-only data fields */
#define VMCS_INSTRUCTION_ERROR 0x00004400
#define VMCS_EXIT_REASON 0x00004402
-#define VMCS_EXIT_INTERRUPTION_INFO 0x00004404
-#define VMCS_EXIT_INTERRUPTION_ERROR 0x00004406
+#define VMCS_EXIT_INTR_INFO 0x00004404
+#define VMCS_EXIT_INTR_ERRCODE 0x00004406
#define VMCS_IDT_VECTORING_INFO 0x00004408
#define VMCS_IDT_VECTORING_ERROR 0x0000440A
#define VMCS_EXIT_INSTRUCTION_LENGTH 0x0000440C
@@ -329,11 +331,18 @@
#define EXIT_REASON_APIC_WRITE 56
/*
+ * NMI unblocking due to IRET.
+ *
+ * Applies to VM-exits due to hardware exception or EPT fault.
+ */
+#define EXIT_QUAL_NMIUDTI (1 << 12)
+/*
* VMCS interrupt information fields
*/
-#define VMCS_INTERRUPTION_INFO_VALID (1U << 31)
-#define VMCS_INTERRUPTION_INFO_HW_INTR (0 << 8)
-#define VMCS_INTERRUPTION_INFO_NMI (2 << 8)
+#define VMCS_INTR_VALID (1U << 31)
+#define VMCS_INTR_T_MASK 0x700 /* Interruption-info type */
+#define VMCS_INTR_T_HWINTR (0 << 8)
+#define VMCS_INTR_T_NMI (2 << 8)
/*
* VMCS IDT-Vectoring information fields
==== //depot/projects/pci/sys/amd64/vmm/intel/vmx.c#9 (text+ko) ====
@@ -23,11 +23,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: head/sys/amd64/vmm/intel/vmx.c 260466 2014-01-09 03:25:54Z neel $
+ * $FreeBSD: head/sys/amd64/vmm/intel/vmx.c 260836 2014-01-18 02:20:10Z neel $
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/amd64/vmm/intel/vmx.c 260466 2014-01-09 03:25:54Z neel $");
+__FBSDID("$FreeBSD: head/sys/amd64/vmm/intel/vmx.c 260836 2014-01-18 02:20:10Z neel $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -45,11 +45,13 @@
#include <machine/cpufunc.h>
#include <machine/md_var.h>
#include <machine/segments.h>
+#include <machine/smp.h>
#include <machine/specialreg.h>
#include <machine/vmparam.h>
#include <machine/vmm.h>
#include "vmm_host.h"
+#include "vmm_ipi.h"
#include "vmm_msr.h"
#include "vmm_ktr.h"
#include "vmm_stat.h"
@@ -93,6 +95,7 @@
#define VM_EXIT_CTLS_ONE_SETTING \
(VM_EXIT_CTLS_ONE_SETTING_NO_PAT | \
+ VM_EXIT_ACKNOWLEDGE_INTERRUPT | \
VM_EXIT_SAVE_PAT | \
VM_EXIT_LOAD_PAT)
#define VM_EXIT_CTLS_ZERO_SETTING VM_EXIT_SAVE_DEBUG_CONTROLS
@@ -171,6 +174,14 @@
SYSCTL_INT(_hw_vmm_vmx, OID_AUTO, virtual_interrupt_delivery, CTLFLAG_RD,
&virtual_interrupt_delivery, 0, "APICv virtual interrupt delivery support");
+static int posted_interrupts;
+SYSCTL_INT(_hw_vmm_vmx, OID_AUTO, posted_interrupts, CTLFLAG_RD,
+ &posted_interrupts, 0, "APICv posted interrupt support");
+
+static int pirvec;
+SYSCTL_INT(_hw_vmm_vmx, OID_AUTO, posted_interrupt_vector, CTLFLAG_RD,
+ &pirvec, 0, "APICv posted interrupt vector");
+
static struct unrhdr *vpid_unr;
static u_int vpid_alloc_failed;
SYSCTL_UINT(_hw_vmm_vmx, OID_AUTO, vpid_alloc_failed, CTLFLAG_RD,
@@ -441,6 +452,9 @@
static int
vmx_cleanup(void)
{
+
+ if (pirvec != 0)
+ vmm_ipi_free(pirvec);
if (vpid_unr != NULL) {
delete_unrhdr(vpid_unr);
@@ -636,8 +650,32 @@
procbased_ctls |= PROCBASED_USE_TPR_SHADOW;
procbased_ctls2 |= procbased2_vid_bits;
procbased_ctls2 &= ~PROCBASED2_VIRTUALIZE_X2APIC_MODE;
+
+ /*
+ * Check for Posted Interrupts only if Virtual Interrupt
+ * Delivery is enabled.
+ */
+ error = vmx_set_ctlreg(MSR_VMX_PINBASED_CTLS,
+ MSR_VMX_TRUE_PINBASED_CTLS, PINBASED_POSTED_INTERRUPT, 0,
+ &tmp);
+ if (error == 0) {
+ pirvec = vmm_ipi_alloc();
+ if (pirvec == 0) {
+ if (bootverbose) {
+ printf("vmx_init: unable to allocate "
+ "posted interrupt vector\n");
+ }
+ } else {
+ posted_interrupts = 1;
+ TUNABLE_INT_FETCH("hw.vmm.vmx.use_apic_pir",
+ &posted_interrupts);
+ }
+ }
}
+ if (posted_interrupts)
+ pinbased_ctls |= PINBASED_POSTED_INTERRUPT;
+
/* Initialize EPT */
error = ept_init(ipinum);
if (error) {
@@ -680,6 +718,31 @@
return (0);
}
+static void
+vmx_trigger_hostintr(int vector)
+{
+ uintptr_t func;
+ struct gate_descriptor *gd;
+
+ gd = &idt[vector];
+
+ KASSERT(vector >= 32 && vector <= 255, ("vmx_trigger_hostintr: "
+ "invalid vector %d", vector));
+ KASSERT(gd->gd_p == 1, ("gate descriptor for vector %d not present",
+ vector));
+ KASSERT(gd->gd_type == SDT_SYSIGT, ("gate descriptor for vector %d "
+ "has invalid type %d", vector, gd->gd_type));
+ KASSERT(gd->gd_dpl == SEL_KPL, ("gate descriptor for vector %d "
+ "has invalid dpl %d", vector, gd->gd_dpl));
+ KASSERT(gd->gd_selector == GSEL(GCODE_SEL, SEL_KPL), ("gate descriptor "
+ "for vector %d has invalid selector %d", vector, gd->gd_selector));
+ KASSERT(gd->gd_ist == 0, ("gate descriptor for vector %d has invalid "
+ "IST %d", vector, gd->gd_ist));
+
+ func = ((long)gd->gd_hioffset << 16 | gd->gd_looffset);
+ vmx_call_isr(func);
+}
+
static int
vmx_setup_cr_shadow(int which, struct vmcs *vmcs, uint32_t initial)
{
@@ -822,6 +885,11 @@
error += vmwrite(VMCS_EOI_EXIT2, 0);
error += vmwrite(VMCS_EOI_EXIT3, 0);
}
+ if (posted_interrupts) {
+ error += vmwrite(VMCS_PIR_VECTOR, pirvec);
+ error += vmwrite(VMCS_PIR_DESC,
+ vtophys(&vmx->pir_desc[i]));
+ }
VMCLEAR(vmcs);
KASSERT(error == 0, ("vmx_vminit: error customizing the vmcs"));
@@ -997,7 +1065,7 @@
* Inject the virtual NMI. The vector must be the NMI IDT entry
* or the VMCS entry check will fail.
*/
- info = VMCS_INTERRUPTION_INFO_NMI | VMCS_INTERRUPTION_INFO_VALID;
+ info = VMCS_INTR_T_NMI | VMCS_INTR_VALID;
info |= IDT_NMI;
vmcs_write(VMCS_ENTRY_INTR_INFO, info);
@@ -1035,7 +1103,7 @@
* because of a pending AST.
*/
info = vmcs_read(VMCS_ENTRY_INTR_INFO);
- if (info & VMCS_INTERRUPTION_INFO_VALID)
+ if (info & VMCS_INTR_VALID)
return;
/*
@@ -1066,7 +1134,7 @@
goto cantinject;
/* Inject the interrupt */
- info = VMCS_INTERRUPTION_INFO_HW_INTR | VMCS_INTERRUPTION_INFO_VALID;
+ info = VMCS_INTR_T_HWINTR | VMCS_INTR_VALID;
info |= vector;
vmcs_write(VMCS_ENTRY_INTR_INFO, info);
@@ -1087,6 +1155,37 @@
VCPU_CTR0(vmx->vm, vcpu, "Enabling interrupt window exiting");
}
+/*
+ * If the Virtual NMIs execution control is '1' then the logical processor
+ * tracks virtual-NMI blocking in the Guest Interruptibility-state field of
+ * the VMCS. An IRET instruction in VMX non-root operation will remove any
+ * virtual-NMI blocking.
+ *
+ * This unblocking occurs even if the IRET causes a fault. In this case the
+ * hypervisor needs to restore virtual-NMI blocking before resuming the guest.
+ */
+static void
+vmx_restore_nmi_blocking(struct vmx *vmx, int vcpuid)
+{
+ uint32_t gi;
+
+ VCPU_CTR0(vmx->vm, vcpuid, "Restore Virtual-NMI blocking");
+ gi = vmcs_read(VMCS_GUEST_INTERRUPTIBILITY);
+ gi |= VMCS_INTERRUPTIBILITY_NMI_BLOCKING;
+ vmcs_write(VMCS_GUEST_INTERRUPTIBILITY, gi);
+}
+
+static void
+vmx_clear_nmi_blocking(struct vmx *vmx, int vcpuid)
+{
+ uint32_t gi;
+
+ VCPU_CTR0(vmx->vm, vcpuid, "Clear Virtual-NMI blocking");
+ gi = vmcs_read(VMCS_GUEST_INTERRUPTIBILITY);
+ gi &= ~VMCS_INTERRUPTIBILITY_NMI_BLOCKING;
+ vmcs_write(VMCS_GUEST_INTERRUPTIBILITY, gi);
+}
+
static int
vmx_emulate_cr_access(struct vmx *vmx, int vcpu, uint64_t exitqual)
{
@@ -1376,10 +1475,12 @@
int error, handled;
struct vmxctx *vmxctx;
struct vlapic *vlapic;
- uint32_t eax, ecx, edx, idtvec_info, idtvec_err, reason;
+ uint32_t eax, ecx, edx, idtvec_info, idtvec_err, intr_info, reason;
uint64_t qual, gpa;
bool retu;
+ CTASSERT((PINBASED_CTLS_ONE_SETTING & PINBASED_VIRTUAL_NMI) != 0);
+
handled = 0;
vmxctx = &vmx->ctx[vcpu];
@@ -1412,9 +1513,20 @@
vmcs_write(VMCS_ENTRY_EXCEPTION_ERROR,
idtvec_err);
}
+ /*
+ * If 'virtual NMIs' are being used and the VM-exit
+ * happened while injecting an NMI during the previous
+ * VM-entry, then clear "blocking by NMI" in the Guest
+ * Interruptibility-state.
+ */
+ if ((idtvec_info & VMCS_INTR_T_MASK) ==
+ VMCS_INTR_T_NMI) {
+ vmx_clear_nmi_blocking(vmx, vcpu);
+ }
vmcs_write(VMCS_ENTRY_INST_LENGTH, vmexit->inst_length);
}
default:
+ idtvec_info = 0;
break;
}
@@ -1487,6 +1599,11 @@
* host interrupt handler in the VM's softc. We will inject
* this virtual interrupt during the subsequent VM enter.
*/
+ intr_info = vmcs_read(VMCS_EXIT_INTR_INFO);
+ KASSERT((intr_info & VMCS_INTR_VALID) != 0 &&
+ (intr_info & VMCS_INTR_T_MASK) == VMCS_INTR_T_HWINTR,
+ ("VM exit interruption info invalid: %#x", intr_info));
+ vmx_trigger_hostintr(intr_info & 0xff);
/*
* This is special. We want to treat this as an 'handled'
@@ -1514,6 +1631,23 @@
vmm_stat_incr(vmx->vm, vcpu, VMEXIT_CPUID, 1);
handled = vmx_handle_cpuid(vmx->vm, vcpu, vmxctx);
break;
+ case EXIT_REASON_EXCEPTION:
+ intr_info = vmcs_read(VMCS_EXIT_INTR_INFO);
+ KASSERT((intr_info & VMCS_INTR_VALID) != 0,
+ ("VM exit interruption info invalid: %#x", intr_info));
+ /*
+ * If Virtual NMIs control is 1 and the VM-exit is due to a
+ * fault encountered during the execution of IRET then we must
+ * restore the state of "virtual-NMI blocking" before resuming
+ * the guest.
+ *
+ * See "Resuming Guest Software after Handling an Exception".
+ */
+ if ((idtvec_info & VMCS_IDT_VEC_VALID) == 0 &&
+ (intr_info & 0xff) != IDT_DF &&
+ (intr_info & EXIT_QUAL_NMIUDTI) != 0)
+ vmx_restore_nmi_blocking(vmx, vcpu);
+ break;
case EXIT_REASON_EPT_FAULT:
vmm_stat_incr(vmx->vm, vcpu, VMEXIT_EPT_FAULT, 1);
/*
@@ -1532,6 +1666,17 @@
vmexit->u.inst_emul.gla = vmcs_gla();
vmexit->u.inst_emul.cr3 = vmcs_guest_cr3();
}
+ /*
+ * If Virtual NMIs control is 1 and the VM-exit is due to an
+ * EPT fault during the execution of IRET then we must restore
+ * the state of "virtual-NMI blocking" before resuming.
+ *
+ * See description of "NMI unblocking due to IRET" in
+ * "Exit Qualification for EPT Violations".
+ */
+ if ((idtvec_info & VMCS_IDT_VEC_VALID) == 0 &&
+ (qual & EXIT_QUAL_NMIUDTI) != 0)
+ vmx_restore_nmi_blocking(vmx, vcpu);
break;
case EXIT_REASON_APIC_ACCESS:
handled = vmx_handle_apic_access(vmx, vcpu, vmexit);
@@ -1596,6 +1741,18 @@
}
static __inline int
+vmx_exit_rendezvous(struct vmx *vmx, int vcpu, struct vm_exit *vmexit)
+{
+
+ vmexit->rip = vmcs_guest_rip();
+ vmexit->inst_length = 0;
+ vmexit->exitcode = VM_EXITCODE_RENDEZVOUS;
+ vmm_stat_incr(vmx->vm, vcpu, VMEXIT_RENDEZVOUS, 1);
+
+ return (UNHANDLED);
+}
+
+static __inline int
vmx_exit_inst_error(struct vmxctx *vmxctx, int rc, struct vm_exit *vmexit)
{
@@ -1624,10 +1781,12 @@
}
static int
-vmx_run(void *arg, int vcpu, register_t startrip, pmap_t pmap)
+vmx_run(void *arg, int vcpu, register_t startrip, pmap_t pmap,
+ void *rendezvous_cookie)
{
int rc, handled, launched;
struct vmx *vmx;
+ struct vm *vm;
struct vmxctx *vmxctx;
struct vmcs *vmcs;
struct vm_exit *vmexit;
@@ -1636,10 +1795,11 @@
uint32_t exit_reason;
vmx = arg;
+ vm = vmx->vm;
vmcs = &vmx->vmcs[vcpu];
vmxctx = &vmx->ctx[vcpu];
- vlapic = vm_lapic(vmx->vm, vcpu);
- vmexit = vm_exitinfo(vmx->vm, vcpu);
+ vlapic = vm_lapic(vm, vcpu);
+ vmexit = vm_exitinfo(vm, vcpu);
launched = 0;
KASSERT(vmxctx->pmap == pmap,
@@ -1687,6 +1847,12 @@
break;
}
+ if (vcpu_rendezvous_pending(rendezvous_cookie)) {
+ enable_intr();
+ handled = vmx_exit_rendezvous(vmx, vcpu, vmexit);
+ break;
+ }
+
vmx_inject_interrupts(vmx, vcpu, vlapic);
vmx_run_trace(vmx, vcpu);
rc = vmx_enter_guest(vmxctx, launched);
@@ -1720,9 +1886,9 @@
}
if (!handled)
- vmm_stat_incr(vmx->vm, vcpu, VMEXIT_USERSPACE, 1);
+ vmm_stat_incr(vm, vcpu, VMEXIT_USERSPACE, 1);
- VCPU_CTR1(vmx->vm, vcpu, "returning from vmx_run: exitcode %d",
+ VCPU_CTR1(vm, vcpu, "returning from vmx_run: exitcode %d",
vmexit->exitcode);
VMCLEAR(vmcs);
@@ -1945,11 +2111,11 @@
if (error)
return (error);
- if (info & VMCS_INTERRUPTION_INFO_VALID)
+ if (info & VMCS_INTR_VALID)
return (EAGAIN);
info = vector | (type_map[type] << 8) | (code_valid ? 1 << 11 : 0);
- info |= VMCS_INTERRUPTION_INFO_VALID;
+ info |= VMCS_INTR_VALID;
error = vmcs_setreg(vmcs, 0, VMCS_IDENT(VMCS_ENTRY_INTR_INFO), info);
if (error != 0)
return (error);
@@ -2101,19 +2267,9 @@
return (retval);
}
-/*
- * Posted Interrupt Descriptor (described in section 29.6 of the Intel SDM).
- */
-struct pir_desc {
- uint64_t pir[4];
- uint64_t pending;
- uint64_t unused[3];
-} __aligned(64);
-CTASSERT(sizeof(struct pir_desc) == 64);
-
struct vlapic_vtx {
struct vlapic vlapic;
- struct pir_desc pir_desc;
+ struct pir_desc *pir_desc;
};
#define VMX_CTR_PIR(vm, vcpuid, pir_desc, notify, vector, level, msg) \
@@ -2143,7 +2299,7 @@
* XXX need to deal with level triggered interrupts
*/
vlapic_vtx = (struct vlapic_vtx *)vlapic;
- pir_desc = &vlapic_vtx->pir_desc;
+ pir_desc = vlapic_vtx->pir_desc;
/*
* Keep track of interrupt requests in the PIR descriptor. This is
@@ -2177,7 +2333,7 @@
KASSERT(vecptr == NULL, ("vmx_pending_intr: vecptr must be NULL"));
vlapic_vtx = (struct vlapic_vtx *)vlapic;
- pir_desc = &vlapic_vtx->pir_desc;
+ pir_desc = vlapic_vtx->pir_desc;
pending = atomic_load_acq_long(&pir_desc->pending);
if (!pending)
@@ -2215,6 +2371,13 @@
panic("vmx_intr_accepted: not expected to be called");
}
+static void
+vmx_post_intr(struct vlapic *vlapic, int hostcpu)
+{
+
+ ipi_cpu(hostcpu, pirvec);
+}
+
/*
* Transfer the pending interrupts in the PIR descriptor to the IRR
* in the virtual APIC page.
@@ -2230,7 +2393,7 @@
uint16_t intr_status_old, intr_status_new;
vlapic_vtx = (struct vlapic_vtx *)vlapic;
- pir_desc = &vlapic_vtx->pir_desc;
+ pir_desc = vlapic_vtx->pir_desc;
if (atomic_cmpset_long(&pir_desc->pending, 1, 0) == 0) {
VCPU_CTR0(vlapic->vm, vlapic->vcpuid, "vmx_inject_pir: "
"no posted interrupt pending");
@@ -2295,6 +2458,7 @@
{
struct vmx *vmx;
struct vlapic *vlapic;
+ struct vlapic_vtx *vlapic_vtx;
vmx = arg;
@@ -2303,12 +2467,18 @@
vlapic->vcpuid = vcpuid;
vlapic->apic_page = (struct LAPIC *)&vmx->apic_page[vcpuid];
+ vlapic_vtx = (struct vlapic_vtx *)vlapic;
+ vlapic_vtx->pir_desc = &vmx->pir_desc[vcpuid];
+
if (virtual_interrupt_delivery) {
vlapic->ops.set_intr_ready = vmx_set_intr_ready;
vlapic->ops.pending_intr = vmx_pending_intr;
vlapic->ops.intr_accepted = vmx_intr_accepted;
}
+ if (posted_interrupts)
+ vlapic->ops.post_intr = vmx_post_intr;
+
vlapic_init(vlapic);
return (vlapic);
==== //depot/projects/pci/sys/amd64/vmm/intel/vmx.h#6 (text+ko) ====
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: head/sys/amd64/vmm/intel/vmx.h 260167 2014-01-01 21:17:08Z neel $
+ * $FreeBSD: head/sys/amd64/vmm/intel/vmx.h 260532 2014-01-11 04:22:00Z neel $
*/
#ifndef _VMX_H_
@@ -93,11 +93,20 @@
};
CTASSERT(sizeof(struct apic_page) == PAGE_SIZE);
+/* Posted Interrupt Descriptor (described in section 29.6 of the Intel SDM) */
+struct pir_desc {
+ uint64_t pir[4];
+ uint64_t pending;
+ uint64_t unused[3];
+} __aligned(64);
+CTASSERT(sizeof(struct pir_desc) == 64);
+
/* virtual machine softc */
struct vmx {
struct vmcs vmcs[VM_MAXCPU]; /* one vmcs per virtual cpu */
struct apic_page apic_page[VM_MAXCPU]; /* one apic page per vcpu */
char msr_bitmap[PAGE_SIZE];
+ struct pir_desc pir_desc[VM_MAXCPU];
struct msr_entry guest_msrs[VM_MAXCPU][GUEST_MSR_MAX_ENTRIES];
struct vmxctx ctx[VM_MAXCPU];
struct vmxcap cap[VM_MAXCPU];
@@ -108,6 +117,7 @@
CTASSERT((offsetof(struct vmx, vmcs) & PAGE_MASK) == 0);
CTASSERT((offsetof(struct vmx, msr_bitmap) & PAGE_MASK) == 0);
CTASSERT((offsetof(struct vmx, guest_msrs) & 15) == 0);
+CTASSERT((offsetof(struct vmx, pir_desc[0]) & 63) == 0);
#define VMX_GUEST_VMEXIT 0
#define VMX_VMRESUME_ERROR 1
@@ -115,6 +125,7 @@
#define VMX_INVEPT_ERROR 3
int vmx_enter_guest(struct vmxctx *ctx, int launched);
void vmx_exit_guest(void);
+void vmx_call_isr(uintptr_t entry);
u_long vmx_fix_cr0(u_long cr0);
u_long vmx_fix_cr4(u_long cr4);
==== //depot/projects/pci/sys/amd64/vmm/intel/vmx_genassym.c#6 (text+ko) ====
@@ -23,11 +23,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: head/sys/amd64/vmm/intel/vmx_genassym.c 260167 2014-01-01 21:17:08Z neel $
+ * $FreeBSD: head/sys/amd64/vmm/intel/vmx_genassym.c 260531 2014-01-11 03:14:05Z neel $
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/amd64/vmm/intel/vmx_genassym.c 260167 2014-01-01 21:17:08Z neel $");
+__FBSDID("$FreeBSD: head/sys/amd64/vmm/intel/vmx_genassym.c 260531 2014-01-11 03:14:05Z neel $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -84,3 +84,6 @@
ASSYM(PM_ACTIVE, offsetof(struct pmap, pm_active));
ASSYM(PM_EPTGEN, offsetof(struct pmap, pm_eptgen));
+
+ASSYM(KERNEL_SS, GSEL(GDATA_SEL, SEL_KPL));
+ASSYM(KERNEL_CS, GSEL(GCODE_SEL, SEL_KPL));
==== //depot/projects/pci/sys/amd64/vmm/intel/vmx_support.S#4 (text+ko) ====
@@ -24,7 +24,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: head/sys/amd64/vmm/intel/vmx_support.S 260238 2014-01-03 19:29:33Z neel $
+ * $FreeBSD: head/sys/amd64/vmm/intel/vmx_support.S 260531 2014-01-11 03:14:05Z neel $
*/
#include <machine/asmacros.h>
@@ -234,3 +234,21 @@
movl $VMX_GUEST_VMEXIT, %eax
ret
END(vmx_exit_guest)
+
+/*
+ * %rdi = interrupt handler entry point
+ *
+ * Calling sequence described in the "Instruction Set Reference" for the "INT"
+ * instruction in Intel SDM, Vol 2.
+ */
+ENTRY(vmx_call_isr)
+ mov %rsp, %r11 /* save %rsp */
+ and $~0xf, %rsp /* align on 16-byte boundary */
+ pushq $KERNEL_SS /* %ss */
+ pushq %r11 /* %rsp */
+ pushfq /* %rflags */
+ pushq $KERNEL_CS /* %cs */
+ cli /* disable interrupts */
+ callq *%rdi /* push %rip and call isr */
+ ret
+END(vmx_call_isr)
==== //depot/projects/pci/sys/amd64/vmm/io/vioapic.c#3 (text+ko) ====
@@ -24,11 +24,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: head/sys/amd64/vmm/io/vioapic.c 259482 2013-12-16 19:59:31Z neel $
+ * $FreeBSD: head/sys/amd64/vmm/io/vioapic.c 260619 2014-01-14 01:55:58Z neel $
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/amd64/vmm/io/vioapic.c 259482 2013-12-16 19:59:31Z neel $");
+__FBSDID("$FreeBSD: head/sys/amd64/vmm/io/vioapic.c 260619 2014-01-14 01:55:58Z neel $");
#include <sys/param.h>
#include <sys/queue.h>
@@ -222,8 +222,52 @@
return (vioapic_set_irqstate(vm, irq, IRQSTATE_PULSE));
}
+/*
+ * Reset the vlapic's trigger-mode register to reflect the ioapic pin
+ * configuration.
+ */
+static void
+vioapic_update_tmr(struct vm *vm, int vcpuid, void *arg)
+{
+ struct vioapic *vioapic;
+ struct vlapic *vlapic;
+ uint32_t low, high, dest;
+ int delmode, pin, vector;
+ bool level, phys;
+
+ vlapic = vm_lapic(vm, vcpuid);
+ vioapic = vm_ioapic(vm);
+
+ VIOAPIC_LOCK(vioapic);
+ /*
+ * Reset all vectors to be edge-triggered.
+ */
+ vlapic_reset_tmr(vlapic);
+ for (pin = 0; pin < REDIR_ENTRIES; pin++) {
+ low = vioapic->rtbl[pin].reg;
+ high = vioapic->rtbl[pin].reg >> 32;
+
+ level = low & IOART_TRGRLVL ? true : false;
+ if (!level)
+ continue;
+
+ /*
+ * For a level-triggered 'pin' let the vlapic figure out if
+ * an assertion on this 'pin' would result in an interrupt
+ * being delivered to it. If yes, then it will modify the
+ * TMR bit associated with this vector to level-triggered.
+ */
+ phys = ((low & IOART_DESTMOD) == IOART_DESTPHY);
+ delmode = low & IOART_DELMOD;
+ vector = low & IOART_INTVEC;
+ dest = high >> APIC_ID_SHIFT;
+ vlapic_set_tmr_level(vlapic, dest, phys, delmode, vector);
+ }
+ VIOAPIC_UNLOCK(vioapic);
+}
+
static uint32_t
-vioapic_read(struct vioapic *vioapic, uint32_t addr)
>>> TRUNCATED FOR MAIL (1000 lines) <<<
More information about the p4-projects
mailing list