mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-06-22 13:37:10 +00:00
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:
parent
f05bfeb961
commit
dda08957d7
@ -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();
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user