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,28 +222,18 @@ 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__); drhd_rt = &dmar_drhd_units[i];
ret = -ENODEV; drhd_rt->index = i;
} else if (info->drhd_count > CONFIG_MAX_IOMMU_NUM) { drhd_rt->drhd = &platform_dmar_info->drhd_units[i];
pr_fatal("%s: dmar count(%d) beyond the limitation(%d)\n", drhd_rt->dmar_irq = IRQ_INVALID;
__func__, info->drhd_count, CONFIG_MAX_IOMMU_NUM); ret = dmar_register_hrhd(drhd_rt);
ret = -EINVAL; if (ret != 0) {
} else { break;
for (i = 0U; i < info->drhd_count; i++) {
drhd_rt = &dmar_drhd_units[i];
drhd_rt->index = i;
drhd_rt->drhd = &info->drhd_units[i];
drhd_rt->dmar_irq = IRQ_INVALID;
ret = dmar_register_hrhd(drhd_rt);
if (ret != 0) {
break;
}
} }
} }
@ -544,74 +535,64 @@ 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__); dmar_unit = &dmar_drhd_units[j];
} else { for (i = 0U; i < dmar_unit->drhd->dev_cnt; i++) {
for (j = 0U; j < info->drhd_count; j++) { if ((dmar_unit->drhd->devices[i].type == ACPI_DMAR_SCOPE_TYPE_IOAPIC) &&
dmar_unit = &dmar_drhd_units[j]; (dmar_unit->drhd->devices[i].id == ioapic_id)) {
for (i = 0U; i < dmar_unit->drhd->dev_cnt; i++) { sid->bits.f = pci_func((uint8_t)dmar_unit->drhd->devices[i].devfun);
if ((dmar_unit->drhd->devices[i].type == ACPI_DMAR_SCOPE_TYPE_IOAPIC) && sid->bits.d = pci_slot((uint8_t)dmar_unit->drhd->devices[i].devfun);
(dmar_unit->drhd->devices[i].id == ioapic_id)) { sid->bits.b = dmar_unit->drhd->devices[i].bus;
sid->bits.f = pci_func((uint8_t)dmar_unit->drhd->devices[i].devfun); found = true;
sid->bits.d = pci_slot((uint8_t)dmar_unit->drhd->devices[i].devfun);
sid->bits.b = dmar_unit->drhd->devices[i].bus;
found = true;
break;
}
}
if (found) {
break; break;
} }
} }
if (found) {
if (j == info->drhd_count) { break;
dmar_unit = NULL;
} }
} }
if (j == platform_dmar_info->drhd_count) {
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__); dmar_unit = &dmar_drhd_units[j];
} else {
for (j = 0U; j < info->drhd_count; j++) {
dmar_unit = &dmar_drhd_units[j];
if (dmar_unit->drhd->segment != segment) { if (dmar_unit->drhd->segment != segment) {
continue; continue;
} }
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].bus == bus) && if ((dmar_unit->drhd->devices[i].bus == bus) &&
(dmar_unit->drhd->devices[i].devfun == devfun)) { (dmar_unit->drhd->devices[i].devfun == devfun)) {
break;
}
}
/* found exact one or the one which has the same segment number with INCLUDE_PCI_ALL set */
if ((i != dmar_unit->drhd->dev_cnt) || ((dmar_unit->drhd->flags & DRHD_FLAG_INCLUDE_PCI_ALL_MASK) != 0U)) {
break; break;
} }
} }
/* not found */ /* found exact one or the one which has the same segment number with INCLUDE_PCI_ALL set */
if (j == info->drhd_count) { if ((i != dmar_unit->drhd->dev_cnt) || ((dmar_unit->drhd->flags & DRHD_FLAG_INCLUDE_PCI_ALL_MASK) != 0U)) {
dmar_unit = NULL; break;
} }
} }
/* not found */
if (j == platform_dmar_info->drhd_count) {
dmar_unit = NULL;
}
return dmar_unit; return dmar_unit;
} }
@ -1229,21 +1210,16 @@ 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); } else {
} else { 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__);
} }
} }
@ -1351,11 +1327,21 @@ int32_t init_iommu(void)
{ {
int32_t ret = 0; int32_t ret = 0;
ret = register_hrhd_units(); platform_dmar_info = get_dmar_info();
if (ret == 0) {
do_action_for_iommus(dmar_prepare);
}
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();
if (ret == 0) {
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;