hv: vtd: remove dynamic allocation for dmar_drhd_rt

Predefine a dmar_drhd_rt table for all possible dmar unit

Tracked-On: #861
Signed-off-by: Tw <wei.tan@intel.com>
Reviewed-by: Binbin Wu <binbin.wu@intel.com>
Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
Tw 2018-10-24 13:55:46 +08:00 committed by lijinxia
parent f05bfeb961
commit dda08957d7
4 changed files with 53 additions and 42 deletions

View File

@ -479,7 +479,9 @@ static void bsp_boot_post(void)
/* Initialize interrupts */ /* Initialize interrupts */
interrupt_init(BOOT_CPU_ID); interrupt_init(BOOT_CPU_ID);
init_iommu(); if (init_iommu() != 0) {
panic("failed to initialize iommu!");
}
timer_init(); timer_init();
profiling_setup(); profiling_setup();

View File

@ -95,7 +95,6 @@ enum dmar_iirg_type {
/* dmar unit runtime data */ /* dmar unit runtime data */
struct dmar_drhd_rt { struct dmar_drhd_rt {
uint32_t index; uint32_t index;
struct list_head list;
spinlock_t lock; spinlock_t lock;
struct dmar_drhd *drhd; struct dmar_drhd *drhd;
@ -157,8 +156,7 @@ get_ctx_table(uint32_t dmar_index, uint8_t bus_no)
return ctx_tables[dmar_index].buses[bus_no].contents; return ctx_tables[dmar_index].buses[bus_no].contents;
} }
static struct list_head dmar_drhd_units; static struct dmar_drhd_rt dmar_drhd_units[CONFIG_MAX_IOMMU_NUM];
static uint32_t dmar_hdrh_unit_count;
/* Use to record the domain ids that are used, /* Use to record the domain ids that are used,
* support 64 domains (should be enough?) * support 64 domains (should be enough?)
@ -175,20 +173,32 @@ static struct list_head iommu_domains;
static void dmar_register_hrhd(struct dmar_drhd_rt *dmar_uint); static void dmar_register_hrhd(struct dmar_drhd_rt *dmar_uint);
static struct dmar_drhd_rt *device_to_dmaru(uint16_t segment, uint8_t bus, static struct dmar_drhd_rt *device_to_dmaru(uint16_t segment, uint8_t bus,
uint8_t devfun); uint8_t devfun);
static void register_hrhd_units(void) static int register_hrhd_units(void)
{ {
struct dmar_info *info = get_dmar_info(); struct dmar_info *info = get_dmar_info();
struct dmar_drhd_rt *drhd_rt; struct dmar_drhd_rt *drhd_rt;
uint32_t i; uint32_t i;
if (info == NULL || info->drhd_count == 0U) {
pr_fatal("%s: can't find dmar info\n", __func__);
return -ENODEV;
}
if (info->drhd_count > CONFIG_MAX_IOMMU_NUM) {
pr_fatal("%s: dmar count(%d) beyond the limitation(%d)\n",
__func__, info->drhd_count, CONFIG_MAX_IOMMU_NUM);
return -EINVAL;
}
for (i = 0U; i < info->drhd_count; i++) { for (i = 0U; i < info->drhd_count; i++) {
drhd_rt = calloc(1U, sizeof(struct dmar_drhd_rt)); drhd_rt = &dmar_drhd_units[i];
ASSERT(drhd_rt != NULL, "");
drhd_rt->index = i; drhd_rt->index = i;
drhd_rt->drhd = &info->drhd_units[i]; drhd_rt->drhd = &info->drhd_units[i];
drhd_rt->dmar_irq = IRQ_INVALID; drhd_rt->dmar_irq = IRQ_INVALID;
dmar_register_hrhd(drhd_rt); dmar_register_hrhd(drhd_rt);
} }
return 0;
} }
static uint32_t iommu_read32(const struct dmar_drhd_rt *dmar_uint, uint32_t offset) static uint32_t iommu_read32(const struct dmar_drhd_rt *dmar_uint, uint32_t offset)
@ -417,7 +427,7 @@ static void dmar_disable_translation(struct dmar_drhd_rt *dmar_uint)
static void dmar_register_hrhd(struct dmar_drhd_rt *dmar_uint) static void dmar_register_hrhd(struct dmar_drhd_rt *dmar_uint)
{ {
dev_dbg(ACRN_DBG_IOMMU, "Register dmar uint [%d] @0x%llx", dev_dbg(ACRN_DBG_IOMMU, "Register dmar uint [%d] @0x%llx",
dmar_hdrh_unit_count, dmar_uint->index,
dmar_uint->drhd->reg_base_addr); dmar_uint->drhd->reg_base_addr);
spinlock_init(&dmar_uint->lock); spinlock_init(&dmar_uint->lock);
@ -477,16 +487,6 @@ static void dmar_register_hrhd(struct dmar_drhd_rt *dmar_uint)
max_domain_id = dmar_uint->max_domain_id; max_domain_id = dmar_uint->max_domain_id;
} }
/* register operation is considered serial, no lock here */
if ((dmar_uint->drhd->flags & DRHD_FLAG_INCLUDE_PCI_ALL_MASK) != 0U) {
list_add_tail(&dmar_uint->list, &dmar_drhd_units);
}
else {
list_add(&dmar_uint->list, &dmar_drhd_units);
}
dmar_hdrh_unit_count++;
if ((dmar_uint->gcmd & DMA_GCMD_TE) != 0U) { if ((dmar_uint->gcmd & DMA_GCMD_TE) != 0U) {
dmar_disable_translation(dmar_uint); dmar_disable_translation(dmar_uint);
} }
@ -495,12 +495,12 @@ static void dmar_register_hrhd(struct dmar_drhd_rt *dmar_uint)
static struct dmar_drhd_rt *device_to_dmaru(uint16_t segment, uint8_t bus, static struct dmar_drhd_rt *device_to_dmaru(uint16_t segment, uint8_t bus,
uint8_t devfun) uint8_t devfun)
{ {
struct dmar_info *info = get_dmar_info();
struct dmar_drhd_rt *dmar_uint; struct dmar_drhd_rt *dmar_uint;
struct list_head *pos; uint32_t i, j;
uint32_t i;
list_for_each(pos, &dmar_drhd_units) { for (j = 0U; j < info->drhd_count; j++) {
dmar_uint = list_entry(pos, struct dmar_drhd_rt, list); dmar_uint = &dmar_drhd_units[j];
if (dmar_uint->drhd->segment != segment) { if (dmar_uint->drhd->segment != segment) {
continue; continue;
@ -1195,11 +1195,12 @@ int unassign_iommu_device(const struct iommu_domain *domain, uint8_t bus,
void enable_iommu(void) void enable_iommu(void)
{ {
struct dmar_info *info = get_dmar_info();
struct dmar_drhd_rt *dmar_uint; struct dmar_drhd_rt *dmar_uint;
struct list_head *pos; uint32_t j;
list_for_each(pos, &dmar_drhd_units) { for (j = 0U; j < info->drhd_count; j++) {
dmar_uint = list_entry(pos, struct dmar_drhd_rt, list); dmar_uint = &dmar_drhd_units[j];
if (!dmar_uint->drhd->ignore) { if (!dmar_uint->drhd->ignore) {
dmar_enable(dmar_uint); dmar_enable(dmar_uint);
} }
@ -1212,23 +1213,24 @@ void enable_iommu(void)
void disable_iommu(void) void disable_iommu(void)
{ {
struct dmar_info *info = get_dmar_info();
struct dmar_drhd_rt *dmar_uint; struct dmar_drhd_rt *dmar_uint;
struct list_head *pos; uint32_t j;
list_for_each(pos, &dmar_drhd_units) { for (j = 0U; j < info->drhd_count; j++) {
dmar_uint = list_entry(pos, struct dmar_drhd_rt, list); dmar_uint = &dmar_drhd_units[j];
dmar_disable(dmar_uint); dmar_disable(dmar_uint);
} }
} }
void suspend_iommu(void) void suspend_iommu(void)
{ {
struct dmar_info *info = get_dmar_info();
struct dmar_drhd_rt *dmar_unit; struct dmar_drhd_rt *dmar_unit;
struct list_head *pos; uint32_t i, j;
uint32_t i;
list_for_each(pos, &dmar_drhd_units) { for (j = 0U; j < info->drhd_count; j++) {
dmar_unit = list_entry(pos, struct dmar_drhd_rt, list); dmar_unit = &dmar_drhd_units[j];
if (dmar_unit->drhd->ignore) { if (dmar_unit->drhd->ignore) {
continue; continue;
@ -1253,12 +1255,12 @@ void suspend_iommu(void)
void resume_iommu(void) void resume_iommu(void)
{ {
struct dmar_drhd_rt *dmar_unit; struct dmar_drhd_rt *dmar_unit;
struct list_head *pos; struct dmar_info *info = get_dmar_info();
uint32_t i; uint32_t i, j;
/* restore IOMMU fault register state */ /* restore IOMMU fault register state */
list_for_each(pos, &dmar_drhd_units) { for (j = 0U; j < info->drhd_count; j++) {
dmar_unit = list_entry(pos, struct dmar_drhd_rt, list); dmar_unit = &dmar_drhd_units[j];
if (dmar_unit->drhd->ignore) { if (dmar_unit->drhd->ignore) {
continue; continue;
@ -1283,18 +1285,24 @@ void resume_iommu(void)
} }
} }
void init_iommu(void) int init_iommu(void)
{ {
INIT_LIST_HEAD(&dmar_drhd_units); int ret = 0;
INIT_LIST_HEAD(&iommu_domains); INIT_LIST_HEAD(&iommu_domains);
spinlock_init(&domain_lock); spinlock_init(&domain_lock);
register_hrhd_units(); ret = register_hrhd_units();
if (ret != 0) {
return ret;
}
enable_iommu(); enable_iommu();
cache_flush_invalidate_all(); cache_flush_invalidate_all();
return ret;
} }
void init_iommu_vm0_domain(struct vm *vm0) void init_iommu_vm0_domain(struct vm *vm0)

View File

@ -324,8 +324,9 @@ int parse_dmar_table(void)
*/ */
struct dmar_info *get_dmar_info(void) struct dmar_info *get_dmar_info(void)
{ {
parse_dmar_table(); if (dmar_info_parsed.drhd_count == 0) {
parse_dmar_table();
}
return &dmar_info_parsed; return &dmar_info_parsed;
} }
#endif #endif

View File

@ -495,7 +495,7 @@ void suspend_iommu(void);
void resume_iommu(void); void resume_iommu(void);
/* iommu initialization */ /* iommu initialization */
void init_iommu(void); int init_iommu(void);
void init_iommu_vm0_domain(struct vm *vm0); void init_iommu_vm0_domain(struct vm *vm0);
#endif #endif