Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 13 May 2011 04:54:02 +0000 (UTC)
From:      Peter Grehan <grehan@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r221828 - in projects/bhyve_ref: lib lib/libvmmapi share/mk sys/amd64/include sys/amd64/vmm sys/amd64/vmm/amd sys/amd64/vmm/intel sys/amd64/vmm/io sys/modules sys/modules/vmm usr.sbin u...
Message-ID:  <201105130454.p4D4s24C060136@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: grehan
Date: Fri May 13 04:54:01 2011
New Revision: 221828
URL: http://svn.freebsd.org/changeset/base/221828

Log:
  Import of bhyve hypervisor and utilities, part 1.
    vmm.ko - kernel module for VT-x, VT-d and hypervisor control
    bhyve  - user-space sequencer and i/o emulation
    vmmctl - dump of hypervisor register state
    libvmm - front-end to vmm.ko chardev interface
  
  bhyve was designed and implemented by Neel Natu.
  
  Thanks to the following folk from NetApp who helped to make this available:
  	Joe CaraDonna
  	Peter Snyder
  	Jeff Heller
  	Sandeep Mann
  	Steve Miller
  	Brian Pawlowski

Added:
  projects/bhyve_ref/lib/libvmmapi/
  projects/bhyve_ref/lib/libvmmapi/Makefile
  projects/bhyve_ref/lib/libvmmapi/mptable.c
  projects/bhyve_ref/lib/libvmmapi/mptable.h
  projects/bhyve_ref/lib/libvmmapi/vmmapi.c
  projects/bhyve_ref/lib/libvmmapi/vmmapi.h
  projects/bhyve_ref/lib/libvmmapi/vmmapi_freebsd.c
  projects/bhyve_ref/sys/amd64/include/vmm.h
  projects/bhyve_ref/sys/amd64/include/vmm_dev.h
  projects/bhyve_ref/sys/amd64/vmm/
  projects/bhyve_ref/sys/amd64/vmm/amd/
  projects/bhyve_ref/sys/amd64/vmm/amd/amdv.c
  projects/bhyve_ref/sys/amd64/vmm/intel/
  projects/bhyve_ref/sys/amd64/vmm/intel/ept.c
  projects/bhyve_ref/sys/amd64/vmm/intel/ept.h
  projects/bhyve_ref/sys/amd64/vmm/intel/vmcs.c
  projects/bhyve_ref/sys/amd64/vmm/intel/vmcs.h
  projects/bhyve_ref/sys/amd64/vmm/intel/vmx.c
  projects/bhyve_ref/sys/amd64/vmm/intel/vmx.h
  projects/bhyve_ref/sys/amd64/vmm/intel/vmx_controls.h
  projects/bhyve_ref/sys/amd64/vmm/intel/vmx_cpufunc.h
  projects/bhyve_ref/sys/amd64/vmm/intel/vmx_genassym.c
  projects/bhyve_ref/sys/amd64/vmm/intel/vmx_msr.c
  projects/bhyve_ref/sys/amd64/vmm/intel/vmx_msr.h
  projects/bhyve_ref/sys/amd64/vmm/intel/vmx_support.S
  projects/bhyve_ref/sys/amd64/vmm/intel/vtd.c
  projects/bhyve_ref/sys/amd64/vmm/io/
  projects/bhyve_ref/sys/amd64/vmm/io/iommu.c
  projects/bhyve_ref/sys/amd64/vmm/io/iommu.h
  projects/bhyve_ref/sys/amd64/vmm/io/ppt.c
  projects/bhyve_ref/sys/amd64/vmm/io/ppt.h
  projects/bhyve_ref/sys/amd64/vmm/io/vdev.c
  projects/bhyve_ref/sys/amd64/vmm/io/vdev.h
  projects/bhyve_ref/sys/amd64/vmm/io/vlapic.c
  projects/bhyve_ref/sys/amd64/vmm/io/vlapic.h
  projects/bhyve_ref/sys/amd64/vmm/vmm.c
  projects/bhyve_ref/sys/amd64/vmm/vmm_dev.c
  projects/bhyve_ref/sys/amd64/vmm/vmm_ipi.c
  projects/bhyve_ref/sys/amd64/vmm/vmm_ipi.h
  projects/bhyve_ref/sys/amd64/vmm/vmm_ktr.h
  projects/bhyve_ref/sys/amd64/vmm/vmm_lapic.c
  projects/bhyve_ref/sys/amd64/vmm/vmm_lapic.h
  projects/bhyve_ref/sys/amd64/vmm/vmm_mem.c
  projects/bhyve_ref/sys/amd64/vmm/vmm_mem.h
  projects/bhyve_ref/sys/amd64/vmm/vmm_msr.c
  projects/bhyve_ref/sys/amd64/vmm/vmm_msr.h
  projects/bhyve_ref/sys/amd64/vmm/vmm_stat.c
  projects/bhyve_ref/sys/amd64/vmm/vmm_stat.h
  projects/bhyve_ref/sys/amd64/vmm/vmm_support.S
  projects/bhyve_ref/sys/amd64/vmm/vmm_util.c
  projects/bhyve_ref/sys/amd64/vmm/vmm_util.h
  projects/bhyve_ref/sys/amd64/vmm/x86.c
  projects/bhyve_ref/sys/amd64/vmm/x86.h
  projects/bhyve_ref/sys/modules/vmm/
  projects/bhyve_ref/sys/modules/vmm/Makefile
  projects/bhyve_ref/usr.sbin/bhyve/
  projects/bhyve_ref/usr.sbin/bhyve/Makefile
  projects/bhyve_ref/usr.sbin/bhyve/atpic.c
  projects/bhyve_ref/usr.sbin/bhyve/consport.c
  projects/bhyve_ref/usr.sbin/bhyve/dbgport.c
  projects/bhyve_ref/usr.sbin/bhyve/dbgport.h
  projects/bhyve_ref/usr.sbin/bhyve/elcr.c
  projects/bhyve_ref/usr.sbin/bhyve/fbsdrun.c
  projects/bhyve_ref/usr.sbin/bhyve/fbsdrun.h
  projects/bhyve_ref/usr.sbin/bhyve/inout.c
  projects/bhyve_ref/usr.sbin/bhyve/inout.h
  projects/bhyve_ref/usr.sbin/bhyve/mevent.c
  projects/bhyve_ref/usr.sbin/bhyve/mevent.h
  projects/bhyve_ref/usr.sbin/bhyve/mevent_test.c
  projects/bhyve_ref/usr.sbin/bhyve/pci_emul.c
  projects/bhyve_ref/usr.sbin/bhyve/pci_emul.h
  projects/bhyve_ref/usr.sbin/bhyve/pci_hostbridge.c
  projects/bhyve_ref/usr.sbin/bhyve/pci_passthru.c
  projects/bhyve_ref/usr.sbin/bhyve/pci_virtio_block.c
  projects/bhyve_ref/usr.sbin/bhyve/pci_virtio_net.c
  projects/bhyve_ref/usr.sbin/bhyve/pit_8254.c
  projects/bhyve_ref/usr.sbin/bhyve/pit_8254.h
  projects/bhyve_ref/usr.sbin/bhyve/post.c
  projects/bhyve_ref/usr.sbin/bhyve/rtc.c
  projects/bhyve_ref/usr.sbin/bhyve/uart.c
  projects/bhyve_ref/usr.sbin/bhyve/virtio.h
  projects/bhyve_ref/usr.sbin/bhyve/xmsr.c
  projects/bhyve_ref/usr.sbin/bhyve/xmsr.h
  projects/bhyve_ref/usr.sbin/vmmctl/
  projects/bhyve_ref/usr.sbin/vmmctl/Makefile
  projects/bhyve_ref/usr.sbin/vmmctl/sample.sh   (contents, props changed)
  projects/bhyve_ref/usr.sbin/vmmctl/vmmctl.c
Modified:
  projects/bhyve_ref/lib/Makefile
  projects/bhyve_ref/share/mk/bsd.libnames.mk
  projects/bhyve_ref/sys/amd64/include/specialreg.h
  projects/bhyve_ref/sys/modules/Makefile
  projects/bhyve_ref/usr.sbin/Makefile

Modified: projects/bhyve_ref/lib/Makefile
==============================================================================
--- projects/bhyve_ref/lib/Makefile	Fri May 13 03:40:16 2011	(r221827)
+++ projects/bhyve_ref/lib/Makefile	Fri May 13 04:54:01 2011	(r221828)
@@ -102,6 +102,7 @@ SUBDIR= ${SUBDIR_ORDERED} \
 	${_libusbhid} \
 	${_libusb} \
 	${_libvgl} \
+	${_libvmmapi} \
 	libwrap \
 	liby \
 	libz \
@@ -177,6 +178,7 @@ _libncp=	libncp
 .endif
 _libsmb=	libsmb
 _libvgl=	libvgl
+_libvmmapi=	libvmmapi
 .endif
 
 .if ${MACHINE_ARCH} == "powerpc"

Added: projects/bhyve_ref/lib/libvmmapi/Makefile
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ projects/bhyve_ref/lib/libvmmapi/Makefile	Fri May 13 04:54:01 2011	(r221828)
@@ -0,0 +1,9 @@
+# $FreeBSD$
+
+LIB=	vmmapi
+SRCS=	vmmapi.c vmmapi_freebsd.c mptable.c
+INCS=	vmmapi.h
+
+CFLAGS+= -I${.CURDIR}
+
+.include <bsd.lib.mk>

Added: projects/bhyve_ref/lib/libvmmapi/mptable.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ projects/bhyve_ref/lib/libvmmapi/mptable.c	Fri May 13 04:54:01 2011	(r221828)
@@ -0,0 +1,336 @@
+/*-
+ * 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/types.h>
+#include <sys/mman.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <machine/vmm.h>
+#include <machine/vmm_dev.h>
+
+#include "vmmapi.h"
+#include "mptable.h"
+
+#define LAPIC_PADDR		(0xFEE00000)
+#define LAPIC_VERSION 		(16)
+
+#define IOAPIC_PADDR		(0xFEC00000)
+#define IOAPIC_VERSION		(0x11)
+
+extern int errno;
+
+static uint8_t
+mp_compute_checksum(void *base, size_t len)
+{
+	uint8_t	*bytes = base;
+	uint8_t	 sum = 0;
+	for(; len > 0; len--) {
+		sum += *bytes++;
+	}
+	return 256 - sum;
+}
+
+static void
+mp_build_mpfp(struct mp_floating_pointer *mpfp, vm_paddr_t mpfp_gpa)
+{
+	memset(mpfp, 0, sizeof(*mpfp));
+	memcpy(mpfp->signature, MPFP_SIGNATURE, MPFP_SIGNATURE_LEN);
+	mpfp->mptable_paddr = mpfp_gpa + sizeof(*mpfp);
+	mpfp->specrev = MP_SPECREV;
+	mpfp->feature2 = 0;
+	mpfp->checksum = mp_compute_checksum(mpfp, sizeof(*mpfp));
+}
+
+static void
+mp_build_mpch(struct mp_config_hdr *mpch)
+{
+	memset(mpch, 0, sizeof(*mpch));
+	mpch->specrev = MP_SPECREV;
+	memcpy(mpch->signature, MPCH_SIGNATURE, MPCH_SIGNATURE_LEN);
+	memcpy(mpch->oemid, MPCH_OEMID, MPCH_OEMID_LEN);
+	memcpy(mpch->prodid, MPCH_PRODID, MPCH_PRODID_LEN);
+	mpch->lapic_paddr = LAPIC_PADDR;
+
+
+}
+
+static void
+mp_build_proc_entries(struct mpe_proc *mpep, int num_proc)
+{
+	int i;
+
+	for (i = 0; i < num_proc; i++) {
+		memset(mpep, 0, sizeof(*mpep));
+		mpep->entry_type = MP_ENTRY_PROC;
+		mpep->lapic_id = i; // XXX
+		mpep->lapic_version = LAPIC_VERSION;
+		mpep->proc_flags = (i == 0)?MPEP_FLAGS_BSP:0;
+		mpep->proc_flags |= MPEP_FLAGS_EN;
+		mpep->proc_signature = MPEP_SIGNATURE;
+		mpep->feature_flags = MPEP_FEATURES;
+		mpep++;
+	}
+	
+}
+
+static void
+mp_build_bus_entries(struct mpe_bus *mpeb)
+{
+	memset(mpeb, 0, sizeof(*mpeb));
+	mpeb->entry_type = MP_ENTRY_BUS;
+	mpeb->busid = MPE_BUSID_ISA;
+	memcpy(mpeb->busname, MPE_BUSNAME_ISA, MPE_BUSNAME_LEN);
+	mpeb++;
+
+	memset(mpeb, 0, sizeof(*mpeb));
+	mpeb->entry_type = MP_ENTRY_BUS;
+	mpeb->busid = MPE_BUSID_PCI;
+	memcpy(mpeb->busname, MPE_BUSNAME_PCI, MPE_BUSNAME_LEN);
+
+}
+
+static void
+mp_build_ioapic_entries(struct mpe_ioapic *mpei)
+{
+	memset(mpei, 0, sizeof(*mpei));
+	mpei->entry_type = MP_ENTRY_IOAPIC;
+	mpei->ioapic_id = MPE_IOAPIC_ID;
+	mpei->ioapic_version = IOAPIC_VERSION;
+	mpei->ioapic_flags = MPE_IOAPIC_FLAG_EN;
+	mpei->ioapic_paddr = IOAPIC_PADDR;
+}
+
+static void
+mp_build_ioint_entries(struct mpe_ioint *mpeii, int num_pins)
+{
+	int pin;
+
+	/*
+	 * The following config is taken from kernel mptable.c
+	 * mptable_parse_default_config_ints(...), for now 
+	 * just use the default config, tweek later if needed.
+	 */
+
+
+	/* Run through all 16 pins. */
+	for (pin = 0; pin < num_pins; pin++) {
+		memset(mpeii, 0, sizeof(*mpeii));
+		mpeii->entry_type = MP_ENTRY_IOINT;
+		mpeii->src_bus_id = MPE_BUSID_ISA;
+		mpeii->dst_apic_id = MPE_IOAPIC_ID;
+
+		/*
+		 * All default configs route IRQs from bus 0 to the first 16 pins
+		 * of the first I/O APIC with an APIC ID of 2.
+		 */
+		mpeii->dst_apic_intin = pin;
+		switch (pin) {
+		case 0:
+			/* Pin 0 is an ExtINT pin. */
+			mpeii->intr_type = MPEII_INTR_EXTINT;
+			break;
+		case 2:
+			/* IRQ 0 is routed to pin 2. */
+			mpeii->intr_type = MPEII_INTR_INT;
+			mpeii->src_bus_irq = 0;
+			break;
+		case 5:
+		case 10:
+		case 11:
+			/*
+			 * PCI Irqs set to level triggered.
+			 */
+			mpeii->intr_flags = MPEII_FLAGS_TRIGMODE_LEVEL;
+			mpeii->src_bus_id = MPE_BUSID_PCI;
+		default:
+			/* All other pins are identity mapped. */
+			mpeii->intr_type = MPEII_INTR_INT;
+			mpeii->src_bus_irq = pin;
+			break;
+		}
+		mpeii++;
+	}
+
+}
+
+#define COPYSTR(dest, src, bytes)		\
+	memcpy(dest, src, bytes); 		\
+	str[bytes] = 0;
+
+
+static void
+mptable_dump(struct mp_floating_pointer *mpfp, struct mp_config_hdr *mpch)
+{
+	static char 	 str[16];
+	int 		 i;
+	char 		*cur;
+
+	union mpe {
+		struct mpe_proc 	*proc;
+		struct mpe_bus  	*bus;
+		struct mpe_ioapic 	*ioapic;
+		struct mpe_ioint 	*ioint;
+		struct mpe_lint 	*lnit;
+		char   			*p;
+	};
+
+	union mpe mpe;
+
+	printf(" MP Floating Pointer :\n");
+	COPYSTR(str, mpfp->signature, 4);
+	printf("    signature: 	%s\n", str);
+	printf("    mpch paddr: %x\n", mpfp->mptable_paddr);
+	printf("    length: 	%x\n", mpfp->length);
+	printf("    specrec: 	%x\n", mpfp->specrev);
+	printf("    checksum: 	%x\n", mpfp->checksum);
+	printf("    feature1: 	%x\n", mpfp->feature1);
+	printf("    feature2: 	%x\n", mpfp->feature2);
+	printf("    feature3: 	%x\n", mpfp->feature3);
+	printf("    feature4: 	%x\n", mpfp->feature4);
+
+	printf(" MP Configuration Header :\n");
+	COPYSTR(str, mpch->signature, 4);
+	printf("    signature: 		%s\n", str);
+	printf("    length: 		%x\n", mpch->length);
+	printf("    specrec: 		%x\n", mpch->specrev);
+	printf("    checksum: 		%x\n", mpch->checksum);
+	COPYSTR(str, mpch->oemid, MPCH_OEMID_LEN);
+	printf("    oemid: 		%s\n", str);
+	COPYSTR(str, mpch->prodid, MPCH_PRODID_LEN);
+	printf("    prodid: 		%s\n", str);
+	printf("    oem_ptr: 		%x\n", mpch->oem_ptr);
+	printf("    oem_sz: 		%x\n", mpch->oem_sz);
+	printf("    nr_entries: 	%x\n", mpch->nr_entries);
+	printf("    apic paddr: 	%x\n", mpch->lapic_paddr);
+	printf("    ext_length: 	%x\n", mpch->ext_length);
+	printf("    ext_checksum: 	%x\n", mpch->ext_checksum);
+
+	cur = (char *)mpch + sizeof(*mpch);
+	for (i = 0; i < mpch->nr_entries; i++) {
+		mpe.p = cur;
+		switch(*mpe.p) {		
+			case MP_ENTRY_PROC:
+				printf(" MP Processor Entry :\n");
+				printf("	lapic_id: 	%x\n", mpe.proc->lapic_id);
+				printf("	lapic_version:	%x\n", mpe.proc->lapic_version);
+				printf("	proc_flags: 	%x\n", mpe.proc->proc_flags);
+				printf("	proc_signature: %x\n", mpe.proc->proc_signature);
+				printf("	feature_flags: 	%x\n", mpe.proc->feature_flags);
+				cur += sizeof(struct mpe_proc);
+				break;
+			case MP_ENTRY_BUS:
+				printf(" MP Bus Entry :\n");
+				printf("	busid: 		%x\n", mpe.bus->busid);
+				COPYSTR(str, mpe.bus->busname, MPE_BUSNAME_LEN);
+				printf("	busname: 	%s\n", str);
+				cur += sizeof(struct mpe_bus);
+				break;
+			case MP_ENTRY_IOAPIC:
+				printf(" MP IOAPIC Entry :\n");
+				printf("	ioapi_id: 		%x\n", mpe.ioapic->ioapic_id);
+				printf("	ioapi_version: 		%x\n", mpe.ioapic->ioapic_version);
+				printf("	ioapi_flags: 		%x\n", mpe.ioapic->ioapic_flags);
+				printf("	ioapi_paddr: 		%x\n", mpe.ioapic->ioapic_paddr);
+				cur += sizeof(struct mpe_ioapic);
+				break;
+			case MP_ENTRY_IOINT:
+				printf(" MP IO Interrupt Entry :\n");
+				printf("	intr_type: 		%x\n", mpe.ioint->intr_type);
+				printf("	intr_flags: 		%x\n", mpe.ioint->intr_flags);
+				printf("	src_bus_id: 		%x\n", mpe.ioint->src_bus_id);
+				printf("	src_bus_irq: 		%x\n", mpe.ioint->src_bus_irq);
+				printf("	dst_apic_id: 		%x\n", mpe.ioint->dst_apic_id);
+				printf("	dst_apic_intin:		%x\n", mpe.ioint->dst_apic_intin);
+				cur += sizeof(struct mpe_ioint);
+				break;
+			case MP_ENTRY_LINT:
+				printf(" MP Local Interrupt Entry :\n");
+				cur += sizeof(struct mpe_lint);
+				break;
+		}
+
+	}
+}
+
+int
+vm_build_mptable(struct vmctx *ctx, vm_paddr_t gpa, int len, int ncpu,
+		 void *oemp, int oemsz)
+{
+	struct mp_config_hdr	*mpch;
+	char 			*mapaddr;
+	char 			*startaddr;
+	int 	 		 error;
+
+	mapaddr = vm_map_memory(ctx, gpa, len);
+	if (mapaddr == MAP_FAILED) {
+		printf("%s\n", strerror(errno));
+		goto err;
+	}
+	startaddr = mapaddr;
+
+	mp_build_mpfp((struct mp_floating_pointer*) mapaddr, gpa);
+	mapaddr += sizeof(struct mp_floating_pointer);
+
+	mpch = (struct mp_config_hdr*)mapaddr;
+	mp_build_mpch(mpch);
+	mapaddr += sizeof(struct mp_config_hdr);
+
+	mp_build_proc_entries((struct mpe_proc*) mapaddr, ncpu);
+	mapaddr += (sizeof(struct mpe_proc)*ncpu);
+	mpch->nr_entries += ncpu;
+
+	mp_build_bus_entries((struct mpe_bus*)mapaddr);
+	mapaddr += (sizeof(struct mpe_bus)*MPE_NUM_BUSES);
+	mpch->nr_entries += MPE_NUM_BUSES;
+#if 0
+	mp_build_ioapic_entries((struct mpe_ioapic*)mapaddr);
+	mapaddr += sizeof(struct mpe_ioapic);
+	mpch->nr_entries++;
+
+	mp_build_ioint_entries((struct mpe_ioint*)mapaddr, MPEII_MAX_IRQ);
+	mapaddr += sizeof(struct mpe_ioint)*MPEII_MAX_IRQ;
+	mpch->nr_entries += MPEII_MAX_IRQ;
+
+#endif
+	if (oemp) {
+		mpch->oem_ptr = mapaddr - startaddr + gpa;
+		mpch->oem_sz = oemsz;
+		memcpy(mapaddr, oemp, oemsz);
+	}
+	mpch->length = (mapaddr) - ((char*) mpch);
+	mpch->checksum = mp_compute_checksum(mpch, sizeof(*mpch));
+
+
+	// mptable_dump((struct mp_floating_pointer*)startaddr, mpch);
+err:
+	return (error);
+}

Added: projects/bhyve_ref/lib/libvmmapi/mptable.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ projects/bhyve_ref/lib/libvmmapi/mptable.h	Fri May 13 04:54:01 2011	(r221828)
@@ -0,0 +1,171 @@
+/*-
+ * 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 _MPTABLE_h_
+#define	_MPTABLE_h_
+
+#define MP_SPECREV		(4)		// MP spec revision 1.1
+
+/*
+ * MP Floating Pointer Structure
+ */ 
+#define MPFP_SIGNATURE		"_MP_"
+#define MPFP_SIGNATURE_LEN	(4)
+#define MPFP_FEATURE2		(0x80)	// IMCR is present
+struct mp_floating_pointer {
+	uint8_t 	signature[MPFP_SIGNATURE_LEN];
+	uint32_t 	mptable_paddr;
+	uint8_t 	length;
+	uint8_t 	specrev;
+	uint8_t 	checksum;
+	uint8_t 	feature1;
+	uint8_t 	feature2;
+	uint8_t 	feature3;
+	uint8_t 	feature4;
+	uint8_t 	feature5;
+};
+
+
+/*
+ * MP Configuration Table Header
+ */
+#define MPCH_SIGNATURE		"PCMP"
+#define MPCH_SIGNATURE_LEN	(4)
+
+#define MPCH_OEMID		"NETAPP  "
+#define MPCH_OEMID_LEN		(8)
+#define MPCH_PRODID		"vFiler      "
+#define MPCH_PRODID_LEN		(12)
+
+struct mp_config_hdr {
+	uint8_t 	signature[MPCH_SIGNATURE_LEN];
+	uint16_t 	length;
+	uint8_t 	specrev;
+	uint8_t 	checksum;
+	uint8_t 	oemid[MPCH_OEMID_LEN];
+	uint8_t 	prodid[MPCH_PRODID_LEN];
+	uint32_t 	oem_ptr;
+	uint16_t 	oem_sz;
+	uint16_t 	nr_entries;
+	uint32_t 	lapic_paddr;
+	uint16_t 	ext_length;
+	uint8_t 	ext_checksum;
+	uint8_t 	reserved;
+};
+
+#define MP_ENTRY_PROC	(0)
+#define MP_ENTRY_BUS	(1)
+#define MP_ENTRY_IOAPIC	(2)
+#define MP_ENTRY_IOINT	(3)
+#define MP_ENTRY_LINT	(4)
+
+/*
+ * MP Processor Entry
+ */
+
+#define MPEP_FLAGS_EN		(0x1)
+#define MPEP_FLAGS_BSP		(0x2)
+
+#define MPEP_SIG_FAMILY         (6)
+#define MPEP_SIG_MODEL          (26)
+#define MPEP_SIG_STEPPING       (5)
+#define MPEP_SIGNATURE  	((MPEP_SIG_FAMILY << 8) | (MPEP_SIG_MODEL << 4)  \
+				| (MPEP_SIG_STEPPING))
+
+#define MPEP_FEATURES		(0xBFEBFBFF) // Value from Intel i7 CPUID
+
+struct mpe_proc {
+	uint8_t 	entry_type;
+	uint8_t 	lapic_id;
+	uint8_t 	lapic_version;
+	uint8_t 	proc_flags;
+	uint32_t 	proc_signature;
+	uint32_t 	feature_flags;
+	uint8_t 	reserved[8];
+};
+
+/*
+ * MP Bus Entry
+ */
+
+#define MPE_NUM_BUSES	(2)
+#define MPE_BUSNAME_LEN	(6)
+#define MPE_BUSID_ISA	(0)
+#define MPE_BUSID_PCI	(1)
+#define MPE_BUSNAME_ISA	"ISA   "
+#define MPE_BUSNAME_PCI	"PCI   "
+struct mpe_bus {
+	uint8_t 	entry_type;
+	uint8_t		busid;
+	uint8_t		busname[MPE_BUSNAME_LEN];
+};
+
+/*
+ * MP IO APIC Entry
+ */
+#define MPE_IOAPIC_ID		(2)
+#define MPE_IOAPIC_FLAG_EN	(1)
+struct mpe_ioapic {
+	uint8_t 	entry_type;
+	uint8_t		ioapic_id;
+	uint8_t		ioapic_version;
+	uint8_t		ioapic_flags;
+	uint32_t	ioapic_paddr;
+
+};
+
+/*
+ * MP IO Interrupt Assignment Entry
+ */
+#define MPEII_INTR_INT		(0)
+#define MPEII_INTR_NMI		(1)
+#define MPEII_INTR_SMI		(2)
+#define MPEII_INTR_EXTINT	(3)
+#define MPEII_PCI_IRQ_MASK    	(0x0c20U) /* IRQ 5,10,11 are PCI connected */
+#define MPEII_MAX_IRQ		(16)
+#define MPEII_FLAGS_TRIGMODE_LEVEL	(0x3)
+struct mpe_ioint {
+	uint8_t 	entry_type;
+	uint8_t		intr_type;
+	uint16_t	intr_flags;
+	uint8_t		src_bus_id;
+	uint8_t		src_bus_irq;
+	uint8_t		dst_apic_id;
+	uint8_t		dst_apic_intin;
+};
+
+/*
+ * MP Local Interrupt Assignment Entry
+ */
+struct mpe_lint {
+	uint8_t 	entry_type;
+};
+
+int	vm_build_mptable(struct vmctx *ctxt, vm_paddr_t gpa, int len,
+			 int ncpu, void *oemp, int oemsz);
+#endif	/* _MPTABLE_h_ */

Added: projects/bhyve_ref/lib/libvmmapi/vmmapi.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ projects/bhyve_ref/lib/libvmmapi/vmmapi.c	Fri May 13 04:54:01 2011	(r221828)
@@ -0,0 +1,647 @@
+/*-
+ * 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/types.h>
+#include <sys/sysctl.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+
+#include <machine/specialreg.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <machine/vmm.h>
+#include <machine/vmm_dev.h>
+
+#include "vmmapi.h"
+#include "mptable.h"
+
+#ifndef	CR4_VMXE
+#define	CR4_VMXE	(1UL << 13)
+#endif
+
+#define BIOS_ROM_BASE		(0xf0000)
+#define BIOS_ROM_SIZE		(0x10000)
+
+struct vmctx {
+	int	fd;
+	char	*name;
+};
+
+#define	CREATE(x)  sysctlbyname("hw.vmm.create", NULL, NULL, (x), strlen((x)))
+#define	DESTROY(x) sysctlbyname("hw.vmm.destroy", NULL, NULL, (x), strlen((x)))
+
+static int
+vm_device_open(const char *name)
+{
+        int fd, len;
+        char *vmfile;
+
+	len = strlen("/dev/vmm/") + strlen(name) + 1;
+	vmfile = malloc(len);
+	assert(vmfile != NULL);
+	snprintf(vmfile, len, "/dev/vmm/%s", name);
+
+        /* Open the device file */
+        fd = open(vmfile, O_RDWR, 0);
+
+	free(vmfile);
+        return (fd);
+}
+
+int
+vm_create(const char *name)
+{
+
+	return (CREATE((char *)name));
+}
+
+struct vmctx *
+vm_open(const char *name)
+{
+	struct vmctx *vm;
+
+	vm = malloc(sizeof(struct vmctx) + strlen(name) + 1);
+	assert(vm != NULL);
+
+	vm->fd = -1;
+	vm->name = (char *)(vm + 1);
+	strcpy(vm->name, name);
+
+	if ((vm->fd = vm_device_open(vm->name)) < 0)
+		goto err;
+
+	return (vm);
+err:
+	vm_destroy(vm);
+	return (NULL);
+}
+
+void
+vm_destroy(struct vmctx *vm)
+{
+	assert(vm != NULL);
+
+	DESTROY(vm->name);
+	if (vm->fd >= 0)
+		close(vm->fd);
+	free(vm);
+}
+
+int
+vm_get_memory_seg(struct vmctx *ctx, vm_paddr_t gpa,
+		  vm_paddr_t *ret_hpa, size_t *ret_len)
+{
+	int error;
+	struct vm_memory_segment seg;
+
+	bzero(&seg, sizeof(seg));
+	seg.gpa = gpa;
+	error = ioctl(ctx->fd, VM_GET_MEMORY_SEG, &seg);
+	*ret_hpa = seg.hpa;
+	*ret_len = seg.len;
+	return (error);
+}
+
+int
+vm_setup_memory(struct vmctx *ctx, vm_paddr_t gpa, size_t len, char **mapaddr)
+{
+	int error;
+	struct vm_memory_segment seg;
+
+	/*
+	 * Create and optionally map 'len' bytes of memory at guest
+	 * physical address 'gpa'
+	 */
+	bzero(&seg, sizeof(seg));
+	seg.gpa = gpa;
+	seg.len = len;
+	error = ioctl(ctx->fd, VM_MAP_MEMORY, &seg);
+	if (error == 0 && mapaddr != NULL) {
+		*mapaddr = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED,
+				ctx->fd, gpa);
+	}
+	return (error);
+}
+
+char *
+vm_map_memory(struct vmctx *ctx, vm_paddr_t gpa, size_t len)
+{
+
+	/* Map 'len' bytes of memory at guest physical address 'gpa' */
+	return ((char *)mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED,
+		     ctx->fd, gpa));
+}
+
+int
+vm_set_desc(struct vmctx *ctx, int vcpu, int reg,
+	    uint64_t base, uint32_t limit, uint32_t access)
+{
+	int error;
+	struct vm_seg_desc vmsegdesc;
+
+	bzero(&vmsegdesc, sizeof(vmsegdesc));
+	vmsegdesc.cpuid = vcpu;
+	vmsegdesc.regnum = reg;
+	vmsegdesc.desc.base = base;
+	vmsegdesc.desc.limit = limit;
+	vmsegdesc.desc.access = access;
+
+	error = ioctl(ctx->fd, VM_SET_SEGMENT_DESCRIPTOR, &vmsegdesc);
+	return (error);
+}
+
+int
+vm_get_desc(struct vmctx *ctx, int vcpu, int reg,
+	    uint64_t *base, uint32_t *limit, uint32_t *access)
+{
+	int error;
+	struct vm_seg_desc vmsegdesc;
+
+	bzero(&vmsegdesc, sizeof(vmsegdesc));
+	vmsegdesc.cpuid = vcpu;
+	vmsegdesc.regnum = reg;
+
+	error = ioctl(ctx->fd, VM_GET_SEGMENT_DESCRIPTOR, &vmsegdesc);
+	if (error == 0) {
+		*base = vmsegdesc.desc.base;
+		*limit = vmsegdesc.desc.limit;
+		*access = vmsegdesc.desc.access;
+	}
+	return (error);
+}
+
+int
+vm_set_register(struct vmctx *ctx, int vcpu, int reg, uint64_t val)
+{
+	int error;
+	struct vm_register vmreg;
+
+	bzero(&vmreg, sizeof(vmreg));
+	vmreg.cpuid = vcpu;
+	vmreg.regnum = reg;
+	vmreg.regval = val;
+
+	error = ioctl(ctx->fd, VM_SET_REGISTER, &vmreg);
+	return (error);
+}
+
+int
+vm_get_register(struct vmctx *ctx, int vcpu, int reg, uint64_t *ret_val)
+{
+	int error;
+	struct vm_register vmreg;
+
+	bzero(&vmreg, sizeof(vmreg));
+	vmreg.cpuid = vcpu;
+	vmreg.regnum = reg;
+
+	error = ioctl(ctx->fd, VM_GET_REGISTER, &vmreg);
+	*ret_val = vmreg.regval;
+	return (error);
+}
+
+int
+vm_get_pinning(struct vmctx *ctx, int vcpu, int *host_cpuid)
+{
+	int error;
+	struct vm_pin vmpin;
+
+	bzero(&vmpin, sizeof(vmpin));
+	vmpin.vm_cpuid = vcpu;
+
+	error = ioctl(ctx->fd, VM_GET_PINNING, &vmpin);
+	*host_cpuid = vmpin.host_cpuid;
+	return (error);
+}
+
+int
+vm_set_pinning(struct vmctx *ctx, int vcpu, int host_cpuid)
+{
+	int error;
+	struct vm_pin vmpin;
+
+	bzero(&vmpin, sizeof(vmpin));
+	vmpin.vm_cpuid = vcpu;
+	vmpin.host_cpuid = host_cpuid;
+
+	error = ioctl(ctx->fd, VM_SET_PINNING, &vmpin);
+	return (error);
+}
+
+int
+vm_run(struct vmctx *ctx, int vcpu, uint64_t rip, struct vm_exit *vmexit)
+{
+	int error;
+	struct vm_run vmrun;
+
+	bzero(&vmrun, sizeof(vmrun));
+	vmrun.cpuid = vcpu;
+	vmrun.rip = rip;
+
+	error = ioctl(ctx->fd, VM_RUN, &vmrun);
+	bcopy(&vmrun.vm_exit, vmexit, sizeof(struct vm_exit));
+	return (error);
+}
+
+static int
+vm_inject_event_real(struct vmctx *ctx, int vcpu, enum vm_event_type type,
+		     int vector, int error_code, int error_code_valid)
+{
+	struct vm_event ev;
+
+	bzero(&ev, sizeof(ev));
+	ev.cpuid = vcpu;
+	ev.type = type;
+	ev.vector = vector;
+	ev.error_code = error_code;
+	ev.error_code_valid = error_code_valid;
+
+	return (ioctl(ctx->fd, VM_INJECT_EVENT, &ev));
+}
+
+int
+vm_inject_event(struct vmctx *ctx, int vcpu, enum vm_event_type type,
+		int vector)
+{
+
+	return (vm_inject_event_real(ctx, vcpu, type, vector, 0, 0));
+}
+
+int
+vm_inject_event2(struct vmctx *ctx, int vcpu, enum vm_event_type type,
+		 int vector, int error_code)
+{
+
+	return (vm_inject_event_real(ctx, vcpu, type, vector, error_code, 1));
+}
+
+int
+vm_build_tables(struct vmctx *ctxt, int ncpu, void *oemtbl, int oemtblsz)
+{
+
+	return (vm_build_mptable(ctxt, BIOS_ROM_BASE, BIOS_ROM_SIZE, ncpu,
+				 oemtbl, oemtblsz));
+}
+
+int
+vm_lapic_irq(struct vmctx *ctx, int vcpu, int vector)
+{
+	struct vm_lapic_irq vmirq;
+
+	bzero(&vmirq, sizeof(vmirq));
+	vmirq.cpuid = vcpu;
+	vmirq.vector = vector;
+
+	return (ioctl(ctx->fd, VM_LAPIC_IRQ, &vmirq));
+}
+
+int
+vm_inject_nmi(struct vmctx *ctx, int vcpu)
+{
+	struct vm_nmi vmnmi;
+
+	bzero(&vmnmi, sizeof(vmnmi));
+	vmnmi.cpuid = vcpu;
+
+	return (ioctl(ctx->fd, VM_INJECT_NMI, &vmnmi));
+}
+
+int
+vm_capability_name2type(const char *capname)
+{
+	int i;
+
+	static struct {
+		const char	*name;
+		int		type;
+	} capstrmap[] = {
+		{ "hlt_exit",		VM_CAP_HALT_EXIT },
+		{ "mtrap_exit",		VM_CAP_MTRAP_EXIT },
+		{ "pause_exit",		VM_CAP_PAUSE_EXIT },
+		{ "unrestricted_guest",	VM_CAP_UNRESTRICTED_GUEST },
+		{ 0 }
+	};
+
+	for (i = 0; capstrmap[i].name != NULL && capname != NULL; i++) {
+		if (strcmp(capstrmap[i].name, capname) == 0)
+			return (capstrmap[i].type);
+	}
+
+	return (-1);
+}
+
+int
+vm_get_capability(struct vmctx *ctx, int vcpu, enum vm_cap_type cap,
+		  int *retval)
+{
+	int error;
+	struct vm_capability vmcap;
+
+	bzero(&vmcap, sizeof(vmcap));
+	vmcap.cpuid = vcpu;
+	vmcap.captype = cap;
+
+	error = ioctl(ctx->fd, VM_GET_CAPABILITY, &vmcap);
+	*retval = vmcap.capval;
+	return (error);
+}
+
+int
+vm_set_capability(struct vmctx *ctx, int vcpu, enum vm_cap_type cap, int val)
+{
+	struct vm_capability vmcap;
+
+	bzero(&vmcap, sizeof(vmcap));
+	vmcap.cpuid = vcpu;
+	vmcap.captype = cap;
+	vmcap.capval = val;
+	
+	return (ioctl(ctx->fd, VM_SET_CAPABILITY, &vmcap));
+}
+
+int
+vm_assign_pptdev(struct vmctx *ctx, int bus, int slot, int func)
+{
+	struct vm_pptdev pptdev;
+
+	bzero(&pptdev, sizeof(pptdev));
+	pptdev.bus = bus;
+	pptdev.slot = slot;
+	pptdev.func = func;
+
+	return (ioctl(ctx->fd, VM_BIND_PPTDEV, &pptdev));
+}
+
+int
+vm_unassign_pptdev(struct vmctx *ctx, int bus, int slot, int func)
+{
+	struct vm_pptdev pptdev;
+
+	bzero(&pptdev, sizeof(pptdev));
+	pptdev.bus = bus;
+	pptdev.slot = slot;
+	pptdev.func = func;
+
+	return (ioctl(ctx->fd, VM_UNBIND_PPTDEV, &pptdev));
+}
+
+int
+vm_map_pptdev_mmio(struct vmctx *ctx, int bus, int slot, int func,
+		   vm_paddr_t gpa, size_t len, vm_paddr_t hpa)
+{
+	struct vm_pptdev_mmio pptmmio;
+
+	bzero(&pptmmio, sizeof(pptmmio));
+	pptmmio.bus = bus;
+	pptmmio.slot = slot;
+	pptmmio.func = func;
+	pptmmio.gpa = gpa;
+	pptmmio.len = len;
+	pptmmio.hpa = hpa;
+
+	return (ioctl(ctx->fd, VM_MAP_PPTDEV_MMIO, &pptmmio));
+}
+
+int
+vm_setup_msi(struct vmctx *ctx, int vcpu, int bus, int slot, int func,
+	     int destcpu, int vector, int numvec)
+{
+	struct vm_pptdev_msi pptmsi;
+
+	bzero(&pptmsi, sizeof(pptmsi));
+	pptmsi.vcpu = vcpu;
+	pptmsi.bus = bus;
+	pptmsi.slot = slot;
+	pptmsi.func = func;
+	pptmsi.destcpu = destcpu;
+	pptmsi.vector = vector;
+	pptmsi.numvec = numvec;
+
+	return (ioctl(ctx->fd, VM_PPTDEV_MSI, &pptmsi));

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



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