From: Jan Kiszka Date: Sat, 5 Mar 2016 19:43:28 +0000 (+0100) Subject: x86: Factor out iommu_select_fault_reporting_cpu X-Git-Url: https://rtime.felk.cvut.cz/gitweb/jailhouse.git/commitdiff_plain/4127cb50604f7adb38a23dcbf7d0d634215c8aa0 x86: Factor out iommu_select_fault_reporting_cpu The logic to pick a root cell CPU for IOMMU fault reporting will be reused for AMD. Factor it out. Signed-off-by: Jan Kiszka --- diff --git a/hypervisor/arch/x86/include/asm/iommu.h b/hypervisor/arch/x86/include/asm/iommu.h index 9cc4f73..b667576 100644 --- a/hypervisor/arch/x86/include/asm/iommu.h +++ b/hypervisor/arch/x86/include/asm/iommu.h @@ -21,6 +21,8 @@ #include #include +extern unsigned int fault_reporting_cpu_id; + unsigned int iommu_count_units(void); unsigned int iommu_mmio_count_regions(struct cell *cell); @@ -49,6 +51,7 @@ void iommu_config_commit(struct cell *cell_added_removed); void iommu_shutdown(void); +struct per_cpu *iommu_select_fault_reporting_cpu(void); void iommu_check_pending_faults(void); bool iommu_cell_emulates_ir(struct cell *cell); diff --git a/hypervisor/arch/x86/iommu.c b/hypervisor/arch/x86/iommu.c index 11f35bc..d86d8f9 100644 --- a/hypervisor/arch/x86/iommu.c +++ b/hypervisor/arch/x86/iommu.c @@ -13,6 +13,8 @@ #include #include +unsigned int fault_reporting_cpu_id; + unsigned int iommu_count_units(void) { unsigned int units = 0; @@ -22,3 +24,21 @@ unsigned int iommu_count_units(void) units++; return units; } + +struct per_cpu *iommu_select_fault_reporting_cpu(void) +{ + struct per_cpu *cpu_data; + unsigned int n; + + /* This assumes that at least one bit is set somewhere because we + * don't support configurations where Linux is left with no CPUs. */ + for (n = 0; root_cell.cpu_set->bitmap[n] == 0; n++) + /* Empty loop */; + cpu_data = per_cpu(ffsl(root_cell.cpu_set->bitmap[n])); + + /* Save this value globally to avoid multiple reports of the same + * case from different CPUs */ + fault_reporting_cpu_id = cpu_data->cpu_id; + + return cpu_data; +} diff --git a/hypervisor/arch/x86/vtd.c b/hypervisor/arch/x86/vtd.c index f65dac9..d9b9644 100644 --- a/hypervisor/arch/x86/vtd.c +++ b/hypervisor/arch/x86/vtd.c @@ -199,7 +199,6 @@ static void *unit_inv_queue; static unsigned int dmar_units; static unsigned int dmar_pt_levels; static unsigned int dmar_num_did = ~0U; -static unsigned int fault_reporting_cpu_id; static DEFINE_SPINLOCK(inv_queue_lock); static struct vtd_emulation root_cell_units[JAILHOUSE_MAX_IOMMU_UNITS]; static bool dmar_units_initialized; @@ -298,19 +297,12 @@ static void vtd_init_fault_nmi(void) struct per_cpu *cpu_data; unsigned int n; - /* This assumes that at least one bit is set somewhere because we - * don't support configurations where Linux is left with no CPUs. */ - for (n = 0; root_cell.cpu_set->bitmap[n] == 0; n++) - /* Empty loop */; - cpu_data = per_cpu(ffsl(root_cell.cpu_set->bitmap[n])); + /* Pick a suitable root cell CPU to report faults. */ + cpu_data = iommu_select_fault_reporting_cpu(); /* We only support 8-bit APIC IDs. */ msi.native.destination = (u8)cpu_data->apic_id; - /* Save this value globally to avoid multiple reports of the same - * case from different CPUs */ - fault_reporting_cpu_id = cpu_data->cpu_id; - for (n = 0; n < dmar_units; n++, reg_base += DMAR_MMIO_SIZE) { /* Mask events */ mmio_write32_field(reg_base + VTD_FECTL_REG, VTD_FECTL_IM, 1);