svn commit: r254548 - head/sys/amd64/vmm/intel

Neel Natu neel at FreeBSD.org
Tue Aug 20 06:20:05 UTC 2013


Author: neel
Date: Tue Aug 20 06:20:05 2013
New Revision: 254548
URL: http://svnweb.freebsd.org/changeset/base/254548

Log:
  Extract the location of the remapping hardware units from the ACPI DMAR table.
  
  Submitted by:	Gopakumar T (gopakumar_thekkedath at yahoo.co.in)

Modified:
  head/sys/amd64/vmm/intel/vtd.c

Modified: head/sys/amd64/vmm/intel/vtd.c
==============================================================================
--- head/sys/amd64/vmm/intel/vtd.c	Tue Aug 20 02:09:26 2013	(r254547)
+++ head/sys/amd64/vmm/intel/vtd.c	Tue Aug 20 06:20:05 2013	(r254548)
@@ -41,7 +41,7 @@ __FBSDID("$FreeBSD$");
 
 #include <machine/pmap.h>
 #include <machine/vmparam.h>
-#include <machine/pci_cfgreg.h>
+#include <contrib/dev/acpica/include/acpi.h>
 
 #include "io/iommu.h"
 
@@ -123,60 +123,6 @@ static uint64_t ctx_tables[256][PAGE_SIZ
 
 static MALLOC_DEFINE(M_VTD, "vtd", "vtd");
 
-/*
- * Config space register definitions from the "Intel 5520 and 5500" datasheet.
- */
-static int
-tylersburg_vtd_ident(void)
-{
-	int units, nlbus;
-	uint16_t did, vid;
-	uint32_t miscsts, vtbar;
-
-	const int bus = 0;
-	const int slot = 20;
-	const int func = 0;
-
-	units = 0;
-
-	vid = pci_cfgregread(bus, slot, func, PCIR_VENDOR, 2);
-	did = pci_cfgregread(bus, slot, func, PCIR_DEVICE, 2);
-	if (vid != 0x8086 || did != 0x342E)
-		goto done;
-
-	/*
-	 * Check if this is a dual IOH configuration.
-	 */
-	miscsts = pci_cfgregread(bus, slot, func, 0x9C, 4);
-	if (miscsts & (1 << 25))
-		nlbus = pci_cfgregread(bus, slot, func, 0x160, 1);
-	else	
-		nlbus = -1;
-
-	vtbar = pci_cfgregread(bus, slot, func, 0x180, 4);
-	if (vtbar & 0x1) {
-		vtdmaps[units++] = (struct vtdmap *)
-					PHYS_TO_DMAP(vtbar & 0xffffe000);
-	} else if (bootverbose)
-		printf("VT-d unit in legacy IOH is disabled!\n");
-
-	if (nlbus != -1) {
-		vtbar = pci_cfgregread(nlbus, slot, func, 0x180, 4);
-		if (vtbar & 0x1) {
-			vtdmaps[units++] = (struct vtdmap *)
-					   PHYS_TO_DMAP(vtbar & 0xffffe000);
-		} else if (bootverbose)
-			printf("VT-d unit in non-legacy IOH is disabled!\n");
-	}
-done:
-	return (units);
-}
-
-static drhd_ident_func_t drhd_ident_funcs[] = {
-	tylersburg_vtd_ident,
-	NULL
-};
-
 static int
 vtd_max_domains(struct vtdmap *vtdmap)
 {
@@ -291,19 +237,67 @@ vtd_translation_disable(struct vtdmap *v
 static int
 vtd_init(void)
 {
-	int i, units;
+	int i, units, remaining;
 	struct vtdmap *vtdmap;
 	vm_paddr_t ctx_paddr;
-	
-	for (i = 0; drhd_ident_funcs[i] != NULL; i++) {
-		units = (*drhd_ident_funcs[i])();
-		if (units > 0)
+	char *end, envname[32];
+	unsigned long mapaddr;
+	ACPI_STATUS status;
+	ACPI_TABLE_DMAR *dmar;
+	ACPI_DMAR_HEADER *hdr;
+	ACPI_DMAR_HARDWARE_UNIT *drhd;
+
+	/*
+	 * Allow the user to override the ACPI DMAR table by specifying the
+	 * physical address of each remapping unit.
+	 *
+	 * The following example specifies two remapping units at
+	 * physical addresses 0xfed90000 and 0xfeda0000 respectively.
+	 * set vtd.regmap.0.addr=0xfed90000
+	 * set vtd.regmap.1.addr=0xfeda0000
+	 */
+	for (units = 0; units < DRHD_MAX_UNITS; units++) {
+		snprintf(envname, sizeof(envname), "vtd.regmap.%d.addr", units);
+		if (getenv_ulong(envname, &mapaddr) == 0)
+			break;
+		vtdmaps[units] = (struct vtdmap *)PHYS_TO_DMAP(mapaddr);
+	}
+
+	if (units > 0)
+		goto skip_dmar;
+
+	/* Search for DMAR table. */
+	status = AcpiGetTable(ACPI_SIG_DMAR, 0, (ACPI_TABLE_HEADER **)&dmar);
+	if (ACPI_FAILURE(status))
+		return (ENXIO);
+
+	end = (char *)dmar + dmar->Header.Length;
+	remaining = dmar->Header.Length - sizeof(ACPI_TABLE_DMAR);
+	while (remaining > sizeof(ACPI_DMAR_HEADER)) {
+		hdr = (ACPI_DMAR_HEADER *)(end - remaining);
+		if (hdr->Length > remaining)
+			break;
+		/*
+		 * From Intel VT-d arch spec, version 1.3:
+		 * BIOS implementations must report mapping structures
+		 * in numerical order, i.e. All remapping structures of
+		 * type 0 (DRHD) enumerated before remapping structures of
+		 * type 1 (RMRR) and so forth.
+		 */
+		if (hdr->Type != ACPI_DMAR_TYPE_HARDWARE_UNIT)
+			break;
+
+		drhd = (ACPI_DMAR_HARDWARE_UNIT *)hdr;
+		vtdmaps[units++] = (struct vtdmap *)PHYS_TO_DMAP(drhd->Address);
+		if (units >= DRHD_MAX_UNITS)
 			break;
+		remaining -= hdr->Length;
 	}
 
 	if (units <= 0)
 		return (ENXIO);
 
+skip_dmar:
 	drhd_num = units;
 	vtdmap = vtdmaps[0];
 


More information about the svn-src-all mailing list