#include <asm/apic.h>
#include <asm/percpu.h>
+extern unsigned int fault_reporting_cpu_id;
+
unsigned int iommu_count_units(void);
unsigned int iommu_mmio_count_regions(struct cell *cell);
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);
#include <jailhouse/control.h>
#include <asm/iommu.h>
+unsigned int fault_reporting_cpu_id;
+
unsigned int iommu_count_units(void)
{
unsigned int units = 0;
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;
+}
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;
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);