Extract the location of the remapping hardware units from the ACPI DMAR table.
Submitted by: Gopakumar T (gopakumar_thekkedath@yahoo.co.in)
This commit is contained in:
parent
15e683837c
commit
f77e982952
@ -41,7 +41,7 @@ __FBSDID("$FreeBSD$");
|
|||||||
|
|
||||||
#include <machine/pmap.h>
|
#include <machine/pmap.h>
|
||||||
#include <machine/vmparam.h>
|
#include <machine/vmparam.h>
|
||||||
#include <machine/pci_cfgreg.h>
|
#include <contrib/dev/acpica/include/acpi.h>
|
||||||
|
|
||||||
#include "io/iommu.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");
|
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
|
static int
|
||||||
vtd_max_domains(struct vtdmap *vtdmap)
|
vtd_max_domains(struct vtdmap *vtdmap)
|
||||||
{
|
{
|
||||||
@ -291,19 +237,67 @@ vtd_translation_disable(struct vtdmap *vtdmap)
|
|||||||
static int
|
static int
|
||||||
vtd_init(void)
|
vtd_init(void)
|
||||||
{
|
{
|
||||||
int i, units;
|
int i, units, remaining;
|
||||||
struct vtdmap *vtdmap;
|
struct vtdmap *vtdmap;
|
||||||
vm_paddr_t ctx_paddr;
|
vm_paddr_t ctx_paddr;
|
||||||
|
char *end, envname[32];
|
||||||
for (i = 0; drhd_ident_funcs[i] != NULL; i++) {
|
unsigned long mapaddr;
|
||||||
units = (*drhd_ident_funcs[i])();
|
ACPI_STATUS status;
|
||||||
if (units > 0)
|
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;
|
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)
|
if (units <= 0)
|
||||||
return (ENXIO);
|
return (ENXIO);
|
||||||
|
|
||||||
|
skip_dmar:
|
||||||
drhd_num = units;
|
drhd_num = units;
|
||||||
vtdmap = vtdmaps[0];
|
vtdmap = vtdmaps[0];
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user