hv: Remove redundant get_dmar_info API calls

get_dmar_info API is called from multiple functions in vtd.c. This patch
calls get_dmar_info once during init and uses the cached info during
runtime.

Tracked-On: #2657
Signed-off-by: Sainath Grandhi <sainath.grandhi@intel.com>
Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
Sainath Grandhi 2019-02-26 17:41:03 -08:00 committed by Xie, Nanlin
parent 308d4e8c4e
commit b49df10a23
3 changed files with 65 additions and 74 deletions

View File

@ -208,6 +208,7 @@ static struct dmar_drhd_rt dmar_drhd_units[CONFIG_MAX_IOMMU_NUM];
static bool iommu_page_walk_coherent = true; static bool iommu_page_walk_coherent = true;
static struct iommu_domain *fallback_iommu_domain; static struct iommu_domain *fallback_iommu_domain;
static uint32_t qi_status = 0U; static uint32_t qi_status = 0U;
static struct dmar_info *platform_dmar_info = NULL;
/* Domain id 0 is reserved in some cases per VT-d */ /* Domain id 0 is reserved in some cases per VT-d */
#define MAX_DOMAIN_NUM (CONFIG_MAX_VM_NUM + 1) #define MAX_DOMAIN_NUM (CONFIG_MAX_VM_NUM + 1)
@ -221,30 +222,20 @@ static int32_t dmar_register_hrhd(struct dmar_drhd_rt *dmar_unit);
static struct dmar_drhd_rt *device_to_dmaru(uint16_t segment, uint8_t bus, uint8_t devfun); static struct dmar_drhd_rt *device_to_dmaru(uint16_t segment, uint8_t bus, uint8_t devfun);
static int32_t register_hrhd_units(void) static int32_t register_hrhd_units(void)
{ {
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;
int32_t ret = 0; int32_t ret = 0;
if ((info == NULL) || (info->drhd_count == 0U)) { for (i = 0U; i < platform_dmar_info->drhd_count; i++) {
pr_fatal("%s: can't find dmar info\n", __func__);
ret = -ENODEV;
} else 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);
ret = -EINVAL;
} else {
for (i = 0U; i < info->drhd_count; i++) {
drhd_rt = &dmar_drhd_units[i]; drhd_rt = &dmar_drhd_units[i];
drhd_rt->index = i; drhd_rt->index = i;
drhd_rt->drhd = &info->drhd_units[i]; drhd_rt->drhd = &platform_dmar_info->drhd_units[i];
drhd_rt->dmar_irq = IRQ_INVALID; drhd_rt->dmar_irq = IRQ_INVALID;
ret = dmar_register_hrhd(drhd_rt); ret = dmar_register_hrhd(drhd_rt);
if (ret != 0) { if (ret != 0) {
break; break;
} }
} }
}
return ret; return ret;
} }
@ -544,15 +535,11 @@ static int32_t dmar_register_hrhd(struct dmar_drhd_rt *dmar_unit)
static struct dmar_drhd_rt *ioapic_to_dmaru(uint16_t ioapic_id, union pci_bdf *sid) static struct dmar_drhd_rt *ioapic_to_dmaru(uint16_t ioapic_id, union pci_bdf *sid)
{ {
struct dmar_info *info = get_dmar_info();
struct dmar_drhd_rt *dmar_unit = NULL; struct dmar_drhd_rt *dmar_unit = NULL;
uint32_t i, j; uint32_t i, j;
bool found = false; bool found = false;
if (info == NULL) { for (j = 0U; j < platform_dmar_info->drhd_count; j++) {
pr_fatal("%s: can't find dmar info\n", __func__);
} else {
for (j = 0U; j < info->drhd_count; j++) {
dmar_unit = &dmar_drhd_units[j]; dmar_unit = &dmar_drhd_units[j];
for (i = 0U; i < dmar_unit->drhd->dev_cnt; i++) { for (i = 0U; i < dmar_unit->drhd->dev_cnt; i++) {
if ((dmar_unit->drhd->devices[i].type == ACPI_DMAR_SCOPE_TYPE_IOAPIC) && if ((dmar_unit->drhd->devices[i].type == ACPI_DMAR_SCOPE_TYPE_IOAPIC) &&
@ -569,24 +556,19 @@ static struct dmar_drhd_rt *ioapic_to_dmaru(uint16_t ioapic_id, union pci_bdf *s
} }
} }
if (j == info->drhd_count) { if (j == platform_dmar_info->drhd_count) {
dmar_unit = NULL; dmar_unit = NULL;
} }
}
return dmar_unit; return dmar_unit;
} }
static struct dmar_drhd_rt *device_to_dmaru(uint16_t segment, uint8_t bus, uint8_t devfun) static struct dmar_drhd_rt *device_to_dmaru(uint16_t segment, uint8_t bus, uint8_t devfun)
{ {
struct dmar_info *info = get_dmar_info();
struct dmar_drhd_rt *dmar_unit = NULL; struct dmar_drhd_rt *dmar_unit = NULL;
uint32_t i, j; uint32_t i, j;
if (info == NULL) { for (j = 0U; j < platform_dmar_info->drhd_count; j++) {
pr_fatal("%s: can't find dmar info\n", __func__);
} else {
for (j = 0U; j < info->drhd_count; j++) {
dmar_unit = &dmar_drhd_units[j]; dmar_unit = &dmar_drhd_units[j];
if (dmar_unit->drhd->segment != segment) { if (dmar_unit->drhd->segment != segment) {
@ -607,10 +589,9 @@ static struct dmar_drhd_rt *device_to_dmaru(uint16_t segment, uint8_t bus, uint8
} }
/* not found */ /* not found */
if (j == info->drhd_count) { if (j == platform_dmar_info->drhd_count) {
dmar_unit = NULL; dmar_unit = NULL;
} }
}
return dmar_unit; return dmar_unit;
} }
@ -1229,12 +1210,10 @@ static int32_t remove_iommu_device(const struct iommu_domain *domain, uint16_t s
*/ */
static void do_action_for_iommus(void (*action)(struct dmar_drhd_rt *)) static void do_action_for_iommus(void (*action)(struct dmar_drhd_rt *))
{ {
struct dmar_info *info = get_dmar_info();
struct dmar_drhd_rt *dmar_unit; struct dmar_drhd_rt *dmar_unit;
uint32_t i; uint32_t i;
if (info != NULL) { for (i = 0U; i < platform_dmar_info->drhd_count; i++) {
for (i = 0U; i < info->drhd_count; i++) {
dmar_unit = &dmar_drhd_units[i]; dmar_unit = &dmar_drhd_units[i];
if (!dmar_unit->drhd->ignore) { if (!dmar_unit->drhd->ignore) {
action(dmar_unit); action(dmar_unit);
@ -1242,9 +1221,6 @@ static void do_action_for_iommus(void (*action)(struct dmar_drhd_rt *))
dev_dbg(ACRN_DBG_IOMMU, "ignore dmar_unit @0x%x", dmar_unit->drhd->reg_base_addr); dev_dbg(ACRN_DBG_IOMMU, "ignore dmar_unit @0x%x", dmar_unit->drhd->reg_base_addr);
} }
} }
} else {
pr_fatal("%s: can't find dmar info\n", __func__);
}
} }
struct iommu_domain *create_iommu_domain(uint16_t vm_id, uint64_t translation_table, uint32_t addr_width) struct iommu_domain *create_iommu_domain(uint16_t vm_id, uint64_t translation_table, uint32_t addr_width)
@ -1351,11 +1327,21 @@ int32_t init_iommu(void)
{ {
int32_t ret = 0; int32_t ret = 0;
platform_dmar_info = get_dmar_info();
if ((platform_dmar_info == NULL) || (platform_dmar_info->drhd_count == 0U)) {
pr_fatal("%s: can't find dmar info\n", __func__);
ret = -ENODEV;
} else if (platform_dmar_info->drhd_count > CONFIG_MAX_IOMMU_NUM) {
pr_fatal("%s: dmar count(%d) beyond the limitation(%d)\n",
__func__, platform_dmar_info->drhd_count, CONFIG_MAX_IOMMU_NUM);
ret = -EINVAL;
} else {
ret = register_hrhd_units(); ret = register_hrhd_units();
if (ret == 0) { if (ret == 0) {
do_action_for_iommus(dmar_prepare); do_action_for_iommus(dmar_prepare);
} }
}
return ret; return ret;
} }

View File

@ -306,6 +306,7 @@ static int32_t parse_dmar_table(void)
/** /**
* @post return != NULL * @post return != NULL
* @post return->drhd_count > 0U
*/ */
struct dmar_info *get_dmar_info(void) struct dmar_info *get_dmar_info(void)
{ {

View File

@ -130,6 +130,10 @@ static struct dmar_info sbl_dmar_info = {
.drhd_units = drhd_info_array, .drhd_units = drhd_info_array,
}; };
/**
* @post return != NULL
* @post return->drhd_count > 0U
*/
struct dmar_info *get_dmar_info(void) struct dmar_info *get_dmar_info(void)
{ {
return &sbl_dmar_info; return &sbl_dmar_info;