Changeset View
Changeset View
Standalone View
Standalone View
sys/x86/iommu/intel_drv.c
Show First 20 Lines • Show All 246 Lines • ▼ Show 20 Lines | dmar_release_intr(device_t dev, struct dmar_unit *unit, int idx) | ||||
dmd->irq = -1; | dmd->irq = -1; | ||||
} | } | ||||
static void | static void | ||||
dmar_release_resources(device_t dev, struct dmar_unit *unit) | dmar_release_resources(device_t dev, struct dmar_unit *unit) | ||||
{ | { | ||||
int i; | int i; | ||||
dmar_fini_busdma(unit); | iommu_fini_busdma(&unit->iommu); | ||||
dmar_fini_irt(unit); | dmar_fini_irt(unit); | ||||
dmar_fini_qi(unit); | dmar_fini_qi(unit); | ||||
dmar_fini_fault_log(unit); | dmar_fini_fault_log(unit); | ||||
for (i = 0; i < DMAR_INTR_TOTAL; i++) | for (i = 0; i < DMAR_INTR_TOTAL; i++) | ||||
dmar_release_intr(dev, unit, i); | dmar_release_intr(dev, unit, i); | ||||
if (unit->regs != NULL) { | if (unit->regs != NULL) { | ||||
bus_deactivate_resource(dev, SYS_RES_MEMORY, unit->reg_rid, | bus_deactivate_resource(dev, SYS_RES_MEMORY, unit->reg_rid, | ||||
unit->regs); | unit->regs); | ||||
▲ Show 20 Lines • Show All 144 Lines • ▼ Show 20 Lines | |||||
{ | { | ||||
struct dmar_unit *unit; | struct dmar_unit *unit; | ||||
ACPI_DMAR_HARDWARE_UNIT *dmaru; | ACPI_DMAR_HARDWARE_UNIT *dmaru; | ||||
uint64_t timeout; | uint64_t timeout; | ||||
int i, error; | int i, error; | ||||
unit = device_get_softc(dev); | unit = device_get_softc(dev); | ||||
unit->dev = dev; | unit->dev = dev; | ||||
unit->unit = device_get_unit(dev); | unit->iommu.unit = device_get_unit(dev); | ||||
dmaru = dmar_find_by_index(unit->unit); | dmaru = dmar_find_by_index(unit->iommu.unit); | ||||
if (dmaru == NULL) | if (dmaru == NULL) | ||||
return (EINVAL); | return (EINVAL); | ||||
unit->segment = dmaru->Segment; | unit->segment = dmaru->Segment; | ||||
unit->base = dmaru->Address; | unit->base = dmaru->Address; | ||||
unit->reg_rid = DMAR_REG_RID; | unit->reg_rid = DMAR_REG_RID; | ||||
unit->regs = bus_alloc_resource_any(dev, SYS_RES_MEMORY, | unit->regs = bus_alloc_resource_any(dev, SYS_RES_MEMORY, | ||||
&unit->reg_rid, RF_ACTIVE); | &unit->reg_rid, RF_ACTIVE); | ||||
if (unit->regs == NULL) { | if (unit->regs == NULL) { | ||||
Show All 38 Lines | if (DMAR_HAS_QI(unit)) { | ||||
unit->intrs[DMAR_INTR_QI].disable_intr = dmar_disable_qi_intr; | unit->intrs[DMAR_INTR_QI].disable_intr = dmar_disable_qi_intr; | ||||
error = dmar_alloc_irq(dev, unit, DMAR_INTR_QI); | error = dmar_alloc_irq(dev, unit, DMAR_INTR_QI); | ||||
if (error != 0) { | if (error != 0) { | ||||
dmar_release_resources(dev, unit); | dmar_release_resources(dev, unit); | ||||
return (error); | return (error); | ||||
} | } | ||||
} | } | ||||
mtx_init(&unit->lock, "dmarhw", NULL, MTX_DEF); | mtx_init(&unit->iommu.lock, "dmarhw", NULL, MTX_DEF); | ||||
unit->domids = new_unrhdr(0, dmar_nd2mask(DMAR_CAP_ND(unit->hw_cap)), | unit->domids = new_unrhdr(0, dmar_nd2mask(DMAR_CAP_ND(unit->hw_cap)), | ||||
&unit->lock); | &unit->iommu.lock); | ||||
LIST_INIT(&unit->domains); | LIST_INIT(&unit->domains); | ||||
/* | /* | ||||
* 9.2 "Context Entry": | * 9.2 "Context Entry": | ||||
* When Caching Mode (CM) field is reported as Set, the | * When Caching Mode (CM) field is reported as Set, the | ||||
* domain-id value of zero is architecturally reserved. | * domain-id value of zero is architecturally reserved. | ||||
* Software must not use domain-id value of zero | * Software must not use domain-id value of zero | ||||
* when CM is Set. | * when CM is Set. | ||||
▲ Show 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | if (error != 0) { | ||||
dmar_release_resources(dev, unit); | dmar_release_resources(dev, unit); | ||||
return (error); | return (error); | ||||
} | } | ||||
error = dmar_init_irt(unit); | error = dmar_init_irt(unit); | ||||
if (error != 0) { | if (error != 0) { | ||||
dmar_release_resources(dev, unit); | dmar_release_resources(dev, unit); | ||||
return (error); | return (error); | ||||
} | } | ||||
error = dmar_init_busdma(unit); | error = iommu_init_busdma(&unit->iommu); | ||||
if (error != 0) { | if (error != 0) { | ||||
dmar_release_resources(dev, unit); | dmar_release_resources(dev, unit); | ||||
return (error); | return (error); | ||||
} | } | ||||
#ifdef NOTYET | #ifdef NOTYET | ||||
DMAR_LOCK(unit); | DMAR_LOCK(unit); | ||||
error = dmar_enable_translation(unit); | error = dmar_enable_translation(unit); | ||||
▲ Show 20 Lines • Show All 48 Lines • ▼ Show 20 Lines | static driver_t dmar_driver = { | ||||
dmar_methods, | dmar_methods, | ||||
sizeof(struct dmar_unit), | sizeof(struct dmar_unit), | ||||
}; | }; | ||||
DRIVER_MODULE(dmar, acpi, dmar_driver, dmar_devclass, 0, 0); | DRIVER_MODULE(dmar, acpi, dmar_driver, dmar_devclass, 0, 0); | ||||
MODULE_DEPEND(dmar, acpi, 1, 1, 1); | MODULE_DEPEND(dmar, acpi, 1, 1, 1); | ||||
void | void | ||||
dmar_set_buswide_ctx(struct dmar_unit *unit, u_int busno) | dmar_set_buswide_ctx(struct iommu_unit *unit, u_int busno) | ||||
{ | { | ||||
struct dmar_unit *dmar; | |||||
dmar = (struct dmar_unit *)unit; | |||||
MPASS(busno <= PCI_BUSMAX); | MPASS(busno <= PCI_BUSMAX); | ||||
DMAR_LOCK(unit); | DMAR_LOCK(dmar); | ||||
unit->buswide_ctxs[busno / NBBY / sizeof(uint32_t)] |= | dmar->buswide_ctxs[busno / NBBY / sizeof(uint32_t)] |= | ||||
1 << (busno % (NBBY * sizeof(uint32_t))); | 1 << (busno % (NBBY * sizeof(uint32_t))); | ||||
DMAR_UNLOCK(unit); | DMAR_UNLOCK(dmar); | ||||
} | } | ||||
bool | bool | ||||
dmar_is_buswide_ctx(struct dmar_unit *unit, u_int busno) | dmar_is_buswide_ctx(struct dmar_unit *unit, u_int busno) | ||||
{ | { | ||||
MPASS(busno <= PCI_BUSMAX); | MPASS(busno <= PCI_BUSMAX); | ||||
return ((unit->buswide_ctxs[busno / NBBY / sizeof(uint32_t)] & | return ((unit->buswide_ctxs[busno / NBBY / sizeof(uint32_t)] & | ||||
▲ Show 20 Lines • Show All 116 Lines • ▼ Show 20 Lines | |||||
dmar_match_by_path(struct dmar_unit *unit, int dev_domain, int dev_busno, | dmar_match_by_path(struct dmar_unit *unit, int dev_domain, int dev_busno, | ||||
const ACPI_DMAR_PCI_PATH *dev_path, int dev_path_len, const char **banner) | const ACPI_DMAR_PCI_PATH *dev_path, int dev_path_len, const char **banner) | ||||
{ | { | ||||
ACPI_DMAR_HARDWARE_UNIT *dmarh; | ACPI_DMAR_HARDWARE_UNIT *dmarh; | ||||
ACPI_DMAR_DEVICE_SCOPE *devscope; | ACPI_DMAR_DEVICE_SCOPE *devscope; | ||||
char *ptr, *ptrend; | char *ptr, *ptrend; | ||||
int match; | int match; | ||||
dmarh = dmar_find_by_index(unit->unit); | dmarh = dmar_find_by_index(unit->iommu.unit); | ||||
if (dmarh == NULL) | if (dmarh == NULL) | ||||
return (false); | return (false); | ||||
if (dmarh->Segment != dev_domain) | if (dmarh->Segment != dev_domain) | ||||
return (false); | return (false); | ||||
if ((dmarh->Flags & ACPI_DMAR_INCLUDE_ALL) != 0) { | if ((dmarh->Flags & ACPI_DMAR_INCLUDE_ALL) != 0) { | ||||
if (banner != NULL) | if (banner != NULL) | ||||
*banner = "INCLUDE_ALL"; | *banner = "INCLUDE_ALL"; | ||||
return (true); | return (true); | ||||
▲ Show 20 Lines • Show All 65 Lines • ▼ Show 20 Lines | if (dmar_match_by_path(unit, dev_domain, dev_busno, | ||||
break; | break; | ||||
} | } | ||||
if (i == dmar_devcnt) | if (i == dmar_devcnt) | ||||
return (NULL); | return (NULL); | ||||
if (verbose) { | if (verbose) { | ||||
device_printf(dev, "pci%d:%d:%d:%d matched dmar%d by %s", | device_printf(dev, "pci%d:%d:%d:%d matched dmar%d by %s", | ||||
dev_domain, pci_get_bus(dev), pci_get_slot(dev), | dev_domain, pci_get_bus(dev), pci_get_slot(dev), | ||||
pci_get_function(dev), unit->unit, banner); | pci_get_function(dev), unit->iommu.unit, banner); | ||||
printf(" scope path "); | printf(" scope path "); | ||||
dmar_print_path(dev_busno, dev_path_len, dev_path); | dmar_print_path(dev_busno, dev_path_len, dev_path); | ||||
printf("\n"); | printf("\n"); | ||||
} | } | ||||
return (unit); | return (unit); | ||||
} | } | ||||
static struct dmar_unit * | static struct dmar_unit * | ||||
▲ Show 20 Lines • Show All 76 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
struct rmrr_iter_args { | struct rmrr_iter_args { | ||||
struct dmar_domain *domain; | struct dmar_domain *domain; | ||||
int dev_domain; | int dev_domain; | ||||
int dev_busno; | int dev_busno; | ||||
const ACPI_DMAR_PCI_PATH *dev_path; | const ACPI_DMAR_PCI_PATH *dev_path; | ||||
int dev_path_len; | int dev_path_len; | ||||
struct dmar_map_entries_tailq *rmrr_entries; | struct iommu_map_entries_tailq *rmrr_entries; | ||||
}; | }; | ||||
static int | static int | ||||
dmar_rmrr_iter(ACPI_DMAR_HEADER *dmarh, void *arg) | dmar_rmrr_iter(ACPI_DMAR_HEADER *dmarh, void *arg) | ||||
{ | { | ||||
struct rmrr_iter_args *ria; | struct rmrr_iter_args *ria; | ||||
ACPI_DMAR_RESERVED_MEMORY *resmem; | ACPI_DMAR_RESERVED_MEMORY *resmem; | ||||
ACPI_DMAR_DEVICE_SCOPE *devscope; | ACPI_DMAR_DEVICE_SCOPE *devscope; | ||||
struct dmar_map_entry *entry; | struct iommu_map_entry *entry; | ||||
char *ptr, *ptrend; | char *ptr, *ptrend; | ||||
int match; | int match; | ||||
if (dmarh->Type != ACPI_DMAR_TYPE_RESERVED_MEMORY) | if (dmarh->Type != ACPI_DMAR_TYPE_RESERVED_MEMORY) | ||||
return (1); | return (1); | ||||
ria = arg; | ria = arg; | ||||
resmem = (ACPI_DMAR_RESERVED_MEMORY *)dmarh; | resmem = (ACPI_DMAR_RESERVED_MEMORY *)dmarh; | ||||
if (resmem->Segment != ria->dev_domain) | if (resmem->Segment != ria->dev_domain) | ||||
return (1); | return (1); | ||||
ptr = (char *)resmem + sizeof(*resmem); | ptr = (char *)resmem + sizeof(*resmem); | ||||
ptrend = (char *)resmem + resmem->Header.Length; | ptrend = (char *)resmem + resmem->Header.Length; | ||||
for (;;) { | for (;;) { | ||||
if (ptr >= ptrend) | if (ptr >= ptrend) | ||||
break; | break; | ||||
devscope = (ACPI_DMAR_DEVICE_SCOPE *)ptr; | devscope = (ACPI_DMAR_DEVICE_SCOPE *)ptr; | ||||
ptr += devscope->Length; | ptr += devscope->Length; | ||||
match = dmar_match_devscope(devscope, ria->dev_busno, | match = dmar_match_devscope(devscope, ria->dev_busno, | ||||
ria->dev_path, ria->dev_path_len); | ria->dev_path, ria->dev_path_len); | ||||
if (match == 1) { | if (match == 1) { | ||||
entry = dmar_gas_alloc_entry(ria->domain, | entry = dmar_gas_alloc_entry(&ria->domain->iodom, | ||||
DMAR_PGF_WAITOK); | DMAR_PGF_WAITOK); | ||||
entry->start = resmem->BaseAddress; | entry->start = resmem->BaseAddress; | ||||
/* The RMRR entry end address is inclusive. */ | /* The RMRR entry end address is inclusive. */ | ||||
entry->end = resmem->EndAddress; | entry->end = resmem->EndAddress; | ||||
TAILQ_INSERT_TAIL(ria->rmrr_entries, entry, | TAILQ_INSERT_TAIL(ria->rmrr_entries, entry, | ||||
unroll_link); | unroll_link); | ||||
} | } | ||||
} | } | ||||
return (1); | return (1); | ||||
} | } | ||||
void | void | ||||
dmar_dev_parse_rmrr(struct dmar_domain *domain, int dev_domain, int dev_busno, | dmar_dev_parse_rmrr(struct dmar_domain *domain, int dev_domain, int dev_busno, | ||||
const void *dev_path, int dev_path_len, | const void *dev_path, int dev_path_len, | ||||
struct dmar_map_entries_tailq *rmrr_entries) | struct iommu_map_entries_tailq *rmrr_entries) | ||||
{ | { | ||||
struct rmrr_iter_args ria; | struct rmrr_iter_args ria; | ||||
ria.domain = domain; | ria.domain = domain; | ||||
ria.dev_domain = dev_domain; | ria.dev_domain = dev_domain; | ||||
ria.dev_busno = dev_busno; | ria.dev_busno = dev_busno; | ||||
ria.dev_path = (const ACPI_DMAR_PCI_PATH *)dev_path; | ria.dev_path = (const ACPI_DMAR_PCI_PATH *)dev_path; | ||||
ria.dev_path_len = dev_path_len; | ria.dev_path_len = dev_path_len; | ||||
Show All 29 Lines | |||||
static int | static int | ||||
dmar_inst_rmrr_iter(ACPI_DMAR_HEADER *dmarh, void *arg) | dmar_inst_rmrr_iter(ACPI_DMAR_HEADER *dmarh, void *arg) | ||||
{ | { | ||||
const ACPI_DMAR_RESERVED_MEMORY *resmem; | const ACPI_DMAR_RESERVED_MEMORY *resmem; | ||||
const ACPI_DMAR_DEVICE_SCOPE *devscope; | const ACPI_DMAR_DEVICE_SCOPE *devscope; | ||||
struct inst_rmrr_iter_args *iria; | struct inst_rmrr_iter_args *iria; | ||||
const char *ptr, *ptrend; | const char *ptr, *ptrend; | ||||
device_t dev; | device_t dev; | ||||
struct dmar_unit *unit; | struct iommu_unit *unit; | ||||
struct dmar_unit *dmar; | |||||
int dev_path_len; | int dev_path_len; | ||||
uint16_t rid; | uint16_t rid; | ||||
iria = arg; | iria = arg; | ||||
if (dmarh->Type != ACPI_DMAR_TYPE_RESERVED_MEMORY) | if (dmarh->Type != ACPI_DMAR_TYPE_RESERVED_MEMORY) | ||||
return (1); | return (1); | ||||
Show All 16 Lines | dev_path_len = (devscope->Length - | ||||
sizeof(ACPI_DMAR_DEVICE_SCOPE)) / 2; | sizeof(ACPI_DMAR_DEVICE_SCOPE)) / 2; | ||||
dev = dmar_path_dev(resmem->Segment, dev_path_len, | dev = dmar_path_dev(resmem->Segment, dev_path_len, | ||||
devscope->Bus, | devscope->Bus, | ||||
(const ACPI_DMAR_PCI_PATH *)(devscope + 1), &rid); | (const ACPI_DMAR_PCI_PATH *)(devscope + 1), &rid); | ||||
if (dev == NULL) { | if (dev == NULL) { | ||||
if (bootverbose) { | if (bootverbose) { | ||||
printf("dmar%d no dev found for RMRR " | printf("dmar%d no dev found for RMRR " | ||||
"[%#jx, %#jx] rid %#x scope path ", | "[%#jx, %#jx] rid %#x scope path ", | ||||
iria->dmar->unit, | iria->dmar->iommu.unit, | ||||
(uintmax_t)resmem->BaseAddress, | (uintmax_t)resmem->BaseAddress, | ||||
(uintmax_t)resmem->EndAddress, | (uintmax_t)resmem->EndAddress, | ||||
rid); | rid); | ||||
dmar_print_path(devscope->Bus, dev_path_len, | dmar_print_path(devscope->Bus, dev_path_len, | ||||
(const ACPI_DMAR_PCI_PATH *)(devscope + 1)); | (const ACPI_DMAR_PCI_PATH *)(devscope + 1)); | ||||
printf("\n"); | printf("\n"); | ||||
} | } | ||||
unit = dmar_find_by_scope(resmem->Segment, | dmar = dmar_find_by_scope(resmem->Segment, | ||||
devscope->Bus, | devscope->Bus, | ||||
(const ACPI_DMAR_PCI_PATH *)(devscope + 1), | (const ACPI_DMAR_PCI_PATH *)(devscope + 1), | ||||
dev_path_len); | dev_path_len); | ||||
if (iria->dmar != unit) | if (iria->dmar != dmar) | ||||
continue; | continue; | ||||
dmar_get_ctx_for_devpath(iria->dmar, rid, | dmar_get_ctx_for_devpath(iria->dmar, rid, | ||||
resmem->Segment, devscope->Bus, | resmem->Segment, devscope->Bus, | ||||
(const ACPI_DMAR_PCI_PATH *)(devscope + 1), | (const ACPI_DMAR_PCI_PATH *)(devscope + 1), | ||||
dev_path_len, false, true); | dev_path_len, false, true); | ||||
} else { | } else { | ||||
unit = dmar_find(dev, false); | unit = iommu_find(dev, false); | ||||
if (iria->dmar != unit) | dmar = (struct dmar_unit *)unit; | ||||
if (iria->dmar != dmar) | |||||
continue; | continue; | ||||
dmar_instantiate_ctx(iria->dmar, dev, true); | iommu_instantiate_device(&(iria)->dmar->iommu, | ||||
dev, true); | |||||
} | } | ||||
} | } | ||||
return (1); | return (1); | ||||
} | } | ||||
/* | /* | ||||
* Pre-create all contexts for the DMAR which have RMRR entries. | * Pre-create all contexts for the DMAR which have RMRR entries. | ||||
*/ | */ | ||||
int | int | ||||
dmar_instantiate_rmrr_ctxs(struct dmar_unit *dmar) | dmar_instantiate_rmrr_ctxs(struct iommu_unit *unit) | ||||
{ | { | ||||
struct dmar_unit *dmar; | |||||
struct inst_rmrr_iter_args iria; | struct inst_rmrr_iter_args iria; | ||||
int error; | int error; | ||||
dmar = (struct dmar_unit *)unit; | |||||
if (!dmar_barrier_enter(dmar, DMAR_BARRIER_RMRR)) | if (!dmar_barrier_enter(dmar, DMAR_BARRIER_RMRR)) | ||||
return (0); | return (0); | ||||
error = 0; | error = 0; | ||||
iria.dmar = dmar; | iria.dmar = dmar; | ||||
dmar_iterate_tbl(dmar_inst_rmrr_iter, &iria); | dmar_iterate_tbl(dmar_inst_rmrr_iter, &iria); | ||||
DMAR_LOCK(dmar); | DMAR_LOCK(dmar); | ||||
if (!LIST_EMPTY(&dmar->domains)) { | if (!LIST_EMPTY(&dmar->domains)) { | ||||
KASSERT((dmar->hw_gcmd & DMAR_GCMD_TE) == 0, | KASSERT((dmar->hw_gcmd & DMAR_GCMD_TE) == 0, | ||||
("dmar%d: RMRR not handled but translation is already enabled", | ("dmar%d: RMRR not handled but translation is already enabled", | ||||
dmar->unit)); | dmar->iommu.unit)); | ||||
error = dmar_enable_translation(dmar); | error = dmar_enable_translation(dmar); | ||||
if (bootverbose) { | if (bootverbose) { | ||||
if (error == 0) { | if (error == 0) { | ||||
printf("dmar%d: enabled translation\n", | printf("dmar%d: enabled translation\n", | ||||
dmar->unit); | dmar->iommu.unit); | ||||
} else { | } else { | ||||
printf("dmar%d: enabling translation failed, " | printf("dmar%d: enabling translation failed, " | ||||
"error %d\n", dmar->unit, error); | "error %d\n", dmar->iommu.unit, error); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
dmar_barrier_exit(dmar, DMAR_BARRIER_RMRR); | dmar_barrier_exit(dmar, DMAR_BARRIER_RMRR); | ||||
return (error); | return (error); | ||||
} | } | ||||
#ifdef DDB | #ifdef DDB | ||||
#include <ddb/ddb.h> | #include <ddb/ddb.h> | ||||
#include <ddb/db_lex.h> | #include <ddb/db_lex.h> | ||||
static void | static void | ||||
dmar_print_domain_entry(const struct dmar_map_entry *entry) | dmar_print_domain_entry(const struct iommu_map_entry *entry) | ||||
{ | { | ||||
struct dmar_map_entry *l, *r; | struct iommu_map_entry *l, *r; | ||||
db_printf( | db_printf( | ||||
" start %jx end %jx first %jx last %jx free_down %jx flags %x ", | " start %jx end %jx first %jx last %jx free_down %jx flags %x ", | ||||
entry->start, entry->end, entry->first, entry->last, | entry->start, entry->end, entry->first, entry->last, | ||||
entry->free_down, entry->flags); | entry->free_down, entry->flags); | ||||
db_printf("left "); | db_printf("left "); | ||||
l = RB_LEFT(entry, rb_entry); | l = RB_LEFT(entry, rb_entry); | ||||
if (l == NULL) | if (l == NULL) | ||||
Show All 10 Lines | |||||
} | } | ||||
static void | static void | ||||
dmar_print_ctx(struct dmar_ctx *ctx) | dmar_print_ctx(struct dmar_ctx *ctx) | ||||
{ | { | ||||
db_printf( | db_printf( | ||||
" @%p pci%d:%d:%d refs %d flags %x loads %lu unloads %lu\n", | " @%p pci%d:%d:%d refs %d flags %x loads %lu unloads %lu\n", | ||||
ctx, pci_get_bus(ctx->ctx_tag.owner), | ctx, pci_get_bus(ctx->device.tag.owner), | ||||
pci_get_slot(ctx->ctx_tag.owner), | pci_get_slot(ctx->device.tag.owner), | ||||
pci_get_function(ctx->ctx_tag.owner), ctx->refs, ctx->flags, | pci_get_function(ctx->device.tag.owner), ctx->refs, | ||||
ctx->loads, ctx->unloads); | ctx->device.flags, ctx->device.loads, ctx->device.unloads); | ||||
} | } | ||||
static void | static void | ||||
dmar_print_domain(struct dmar_domain *domain, bool show_mappings) | dmar_print_domain(struct dmar_domain *domain, bool show_mappings) | ||||
{ | { | ||||
struct dmar_map_entry *entry; | struct iommu_map_entry *entry; | ||||
struct dmar_ctx *ctx; | struct dmar_ctx *ctx; | ||||
db_printf( | db_printf( | ||||
" @%p dom %d mgaw %d agaw %d pglvl %d end %jx refs %d\n" | " @%p dom %d mgaw %d agaw %d pglvl %d end %jx refs %d\n" | ||||
" ctx_cnt %d flags %x pgobj %p map_ents %u\n", | " ctx_cnt %d flags %x pgobj %p map_ents %u\n", | ||||
domain, domain->domain, domain->mgaw, domain->agaw, domain->pglvl, | domain, domain->domain, domain->mgaw, domain->agaw, domain->pglvl, | ||||
(uintmax_t)domain->end, domain->refs, domain->ctx_cnt, | (uintmax_t)domain->end, domain->refs, domain->ctx_cnt, | ||||
domain->flags, domain->pgtbl_obj, domain->entries_cnt); | domain->flags, domain->pgtbl_obj, domain->entries_cnt); | ||||
if (!LIST_EMPTY(&domain->contexts)) { | if (!LIST_EMPTY(&domain->contexts)) { | ||||
db_printf(" Contexts:\n"); | db_printf(" Contexts:\n"); | ||||
LIST_FOREACH(ctx, &domain->contexts, link) | LIST_FOREACH(ctx, &domain->contexts, link) | ||||
dmar_print_ctx(ctx); | dmar_print_ctx(ctx); | ||||
} | } | ||||
if (!show_mappings) | if (!show_mappings) | ||||
return; | return; | ||||
db_printf(" mapped:\n"); | db_printf(" mapped:\n"); | ||||
RB_FOREACH(entry, dmar_gas_entries_tree, &domain->rb_root) { | RB_FOREACH(entry, dmar_gas_entries_tree, &domain->rb_root) { | ||||
dmar_print_domain_entry(entry); | dmar_print_domain_entry(entry); | ||||
if (db_pager_quit) | if (db_pager_quit) | ||||
break; | break; | ||||
} | } | ||||
if (db_pager_quit) | if (db_pager_quit) | ||||
return; | return; | ||||
db_printf(" unloading:\n"); | db_printf(" unloading:\n"); | ||||
TAILQ_FOREACH(entry, &domain->unload_entries, dmamap_link) { | TAILQ_FOREACH(entry, &domain->iodom.unload_entries, dmamap_link) { | ||||
dmar_print_domain_entry(entry); | dmar_print_domain_entry(entry); | ||||
if (db_pager_quit) | if (db_pager_quit) | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
DB_FUNC(dmar_domain, db_dmar_print_domain, db_show_table, CS_OWN, NULL) | DB_FUNC(dmar_domain, db_dmar_print_domain, db_show_table, CS_OWN, NULL) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | db_printf("usage: show dmar_domain [/m] " | ||||
"<domain> <bus> <device> <func>\n"); | "<domain> <bus> <device> <func>\n"); | ||||
return; | return; | ||||
} | } | ||||
for (i = 0; i < dmar_devcnt; i++) { | for (i = 0; i < dmar_devcnt; i++) { | ||||
unit = device_get_softc(dmar_devs[i]); | unit = device_get_softc(dmar_devs[i]); | ||||
LIST_FOREACH(domain, &unit->domains, link) { | LIST_FOREACH(domain, &unit->domains, link) { | ||||
LIST_FOREACH(ctx, &domain->contexts, link) { | LIST_FOREACH(ctx, &domain->contexts, link) { | ||||
if (pci_domain == unit->segment && | if (pci_domain == unit->segment && | ||||
bus == pci_get_bus(ctx->ctx_tag.owner) && | bus == pci_get_bus(ctx->device.tag.owner) && | ||||
device == | device == | ||||
pci_get_slot(ctx->ctx_tag.owner) && | pci_get_slot(ctx->device.tag.owner) && | ||||
function == | function == | ||||
pci_get_function(ctx->ctx_tag.owner)) { | pci_get_function(ctx->device.tag.owner)) { | ||||
dmar_print_domain(domain, | dmar_print_domain(domain, | ||||
show_mappings); | show_mappings); | ||||
goto out; | goto out; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
} | } | ||||
out:; | out:; | ||||
} | } | ||||
static void | static void | ||||
dmar_print_one(int idx, bool show_domains, bool show_mappings) | dmar_print_one(int idx, bool show_domains, bool show_mappings) | ||||
{ | { | ||||
struct dmar_unit *unit; | struct dmar_unit *unit; | ||||
struct dmar_domain *domain; | struct dmar_domain *domain; | ||||
int i, frir; | int i, frir; | ||||
unit = device_get_softc(dmar_devs[idx]); | unit = device_get_softc(dmar_devs[idx]); | ||||
db_printf("dmar%d at %p, root at 0x%jx, ver 0x%x\n", unit->unit, unit, | db_printf("dmar%d at %p, root at 0x%jx, ver 0x%x\n", unit->iommu.unit, | ||||
dmar_read8(unit, DMAR_RTADDR_REG), dmar_read4(unit, DMAR_VER_REG)); | unit, dmar_read8(unit, DMAR_RTADDR_REG), | ||||
dmar_read4(unit, DMAR_VER_REG)); | |||||
db_printf("cap 0x%jx ecap 0x%jx gsts 0x%x fsts 0x%x fectl 0x%x\n", | db_printf("cap 0x%jx ecap 0x%jx gsts 0x%x fsts 0x%x fectl 0x%x\n", | ||||
(uintmax_t)dmar_read8(unit, DMAR_CAP_REG), | (uintmax_t)dmar_read8(unit, DMAR_CAP_REG), | ||||
(uintmax_t)dmar_read8(unit, DMAR_ECAP_REG), | (uintmax_t)dmar_read8(unit, DMAR_ECAP_REG), | ||||
dmar_read4(unit, DMAR_GSTS_REG), | dmar_read4(unit, DMAR_GSTS_REG), | ||||
dmar_read4(unit, DMAR_FSTS_REG), | dmar_read4(unit, DMAR_FSTS_REG), | ||||
dmar_read4(unit, DMAR_FECTL_REG)); | dmar_read4(unit, DMAR_FECTL_REG)); | ||||
if (unit->ir_enabled) { | if (unit->ir_enabled) { | ||||
db_printf("ir is enabled; IRT @%p phys 0x%jx maxcnt %d\n", | db_printf("ir is enabled; IRT @%p phys 0x%jx maxcnt %d\n", | ||||
▲ Show 20 Lines • Show All 70 Lines • ▼ Show 20 Lines | DB_SHOW_ALL_COMMAND(dmars, db_show_all_dmars) | ||||
for (i = 0; i < dmar_devcnt; i++) { | for (i = 0; i < dmar_devcnt; i++) { | ||||
dmar_print_one(i, show_domains, show_mappings); | dmar_print_one(i, show_domains, show_mappings); | ||||
if (db_pager_quit) | if (db_pager_quit) | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
#endif | #endif | ||||
struct iommu_unit * | |||||
iommu_find(device_t dev, bool verbose) | |||||
{ | |||||
struct dmar_unit *dmar; | |||||
dmar = dmar_find(dev, verbose); | |||||
return (&dmar->iommu); | |||||
} |