summaryrefslogtreecommitdiffstats
path: root/sys/amd64
diff options
context:
space:
mode:
authorneel <neel@FreeBSD.org>2013-08-20 06:20:05 +0000
committerneel <neel@FreeBSD.org>2013-08-20 06:20:05 +0000
commit15659a9ddf36ff14d1f8eb8329675e1f1251301d (patch)
tree8175c94c0a1b996fca713d1955b153f5443f2447 /sys/amd64
parentbea80a701c438014ad3a85212547369e82c77201 (diff)
downloadFreeBSD-src-15659a9ddf36ff14d1f8eb8329675e1f1251301d.zip
FreeBSD-src-15659a9ddf36ff14d1f8eb8329675e1f1251301d.tar.gz
Extract the location of the remapping hardware units from the ACPI DMAR table.
Submitted by: Gopakumar T (gopakumar_thekkedath@yahoo.co.in)
Diffstat (limited to 'sys/amd64')
-rw-r--r--sys/amd64/vmm/intel/vtd.c114
1 files changed, 54 insertions, 60 deletions
diff --git a/sys/amd64/vmm/intel/vtd.c b/sys/amd64/vmm/intel/vtd.c
index ef0e9bc..a8ed265 100644
--- a/sys/amd64/vmm/intel/vtd.c
+++ b/sys/amd64/vmm/intel/vtd.c
@@ -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_SIZE / sizeof(uint64_t)] __aligned(4096);
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 *vtdmap)
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];
OpenPOWER on IntegriCloud