diff --git a/hypervisor/arch/x86/vtd.c b/hypervisor/arch/x86/vtd.c index da03675aa..db480d483 100644 --- a/hypervisor/arch/x86/vtd.c +++ b/hypervisor/arch/x86/vtd.c @@ -128,8 +128,8 @@ struct dmar_drhd_rt { uint64_t root_table_addr; uint64_t ir_table_addr; - uint64_t irte_alloc_bitmap[CONFIG_MAX_IR_ENTRIES / 64U]; - uint64_t irte_reserved_bitmap[CONFIG_MAX_IR_ENTRIES / 64U]; + uint64_t irte_alloc_bitmap[MAX_IR_ENTRIES / 64U]; + uint64_t irte_reserved_bitmap[MAX_IR_ENTRIES / 64U]; uint64_t qi_queue; uint16_t qi_tail; @@ -152,7 +152,7 @@ struct context_table { }; struct intr_remap_table { - struct page tables[CONFIG_MAX_IR_ENTRIES/DMAR_NUM_IR_ENTRIES_PER_PAGE]; + struct page tables[MAX_IR_ENTRIES/DMAR_NUM_IR_ENTRIES_PER_PAGE]; }; static inline uint8_t *get_root_table(uint32_t dmar_index) @@ -672,7 +672,7 @@ static void dmar_set_intr_remap_table(struct dmar_drhd_rt *dmar_unit) spinlock_obtain(&(dmar_unit->lock)); /* Set number of bits needed to represent the entries minus 1 */ - size = (uint8_t) fls32(CONFIG_MAX_IR_ENTRIES) - 1U; + size = (uint8_t) fls32(MAX_IR_ENTRIES) - 1U; address = dmar_unit->ir_table_addr | DMAR_IR_ENABLE_EIM | size; iommu_write64(dmar_unit, DMAR_IRTA_REG, address); @@ -1276,7 +1276,7 @@ static uint16_t alloc_irtes(struct dmar_drhd_rt *dmar_unit, const uint16_t num) ASSERT((bitmap_weight(num) == 1U) && (num <= 32U)); spinlock_obtain(&dmar_unit->lock); - for (irte_idx = 0U; irte_idx < CONFIG_MAX_IR_ENTRIES; irte_idx += num) { + for (irte_idx = 0U; irte_idx < MAX_IR_ENTRIES; irte_idx += num) { test_mask = mask << (irte_idx & 0x3FU); if ((dmar_unit->irte_alloc_bitmap[irte_idx >> 6U] & test_mask) == 0UL) { dmar_unit->irte_alloc_bitmap[irte_idx >> 6U] |= test_mask; @@ -1285,7 +1285,7 @@ static uint16_t alloc_irtes(struct dmar_drhd_rt *dmar_unit, const uint16_t num) } spinlock_release(&dmar_unit->lock); - return (irte_idx < CONFIG_MAX_IR_ENTRIES) ? irte_idx: INVALID_IRTE_ID; + return (irte_idx < MAX_IR_ENTRIES) ? irte_idx: INVALID_IRTE_ID; } static bool is_irte_reserved(const struct dmar_drhd_rt *dmar_unit, uint16_t index) @@ -1309,7 +1309,7 @@ int32_t dmar_reserve_irte(const struct intr_source *intr_src, uint16_t num, uint if (is_dmar_unit_valid(dmar_unit, sid)) { *start_id = alloc_irtes(dmar_unit, num); - if (*start_id < CONFIG_MAX_IR_ENTRIES) { + if (*start_id < MAX_IR_ENTRIES) { dmar_unit->irte_reserved_bitmap[*start_id >> 6U] |= mask << (*start_id & 0x3FU); } ret = 0; @@ -1346,7 +1346,7 @@ int32_t dmar_assign_irte(const struct intr_source *intr_src, union dmar_ir_entry if (idx_in == INVALID_IRTE_ID) { *idx_out = alloc_irtes(dmar_unit, 1U); } - if (*idx_out < CONFIG_MAX_IR_ENTRIES) { + if (*idx_out < MAX_IR_ENTRIES) { ir_entry = ir_table + *idx_out; if (intr_src->pid_paddr != 0UL) { @@ -1397,7 +1397,7 @@ void dmar_free_irte(const struct intr_source *intr_src, uint16_t index) dmar_unit = ioapic_to_dmaru(intr_src->src.ioapic_id, &sid); } - if (is_dmar_unit_valid(dmar_unit, sid) && (index < CONFIG_MAX_IR_ENTRIES)) { + if (is_dmar_unit_valid(dmar_unit, sid) && (index < MAX_IR_ENTRIES)) { ir_table = (union dmar_ir_entry *)hpa2hva(dmar_unit->ir_table_addr); ir_entry = ir_table + index; ir_entry->bits.remap.present = 0x0UL; diff --git a/hypervisor/include/arch/x86/asm/vtd.h b/hypervisor/include/arch/x86/asm/vtd.h index 7e1257d0a..10b0beb11 100644 --- a/hypervisor/include/arch/x86/asm/vtd.h +++ b/hypervisor/include/arch/x86/asm/vtd.h @@ -42,6 +42,13 @@ #define DMAR_ICS_REG 0x9cU /* Invalidation complete status register */ #define DMAR_IRTA_REG 0xb8U /* Interrupt remapping table addr register */ +/* Make sure all PT IRQs work w/ interrupt remapping or post interrupt */ +#if (CONFIG_MAX_PT_IRQ_ENTRIES <= 256) +#define MAX_IR_ENTRIES 256 +#else +#define MAX_IR_ENTRIES powerof2_roundup(CONFIG_MAX_PT_IRQ_ENTRIES) +#endif + /* Values for entry_type in ACPI_DMAR_DEVICE_SCOPE - device types */ enum acpi_dmar_scope_type { ACPI_DMAR_SCOPE_TYPE_NOT_USED = 0, diff --git a/hypervisor/include/lib/util.h b/hypervisor/include/lib/util.h index eff71cd3a..36dc7d20a 100644 --- a/hypervisor/include/lib/util.h +++ b/hypervisor/include/lib/util.h @@ -25,6 +25,27 @@ /** Replaces 'x' by the string "x". */ #define STRINGIFY(x) #x +/* + * This algorithm get the round up 2^n + * + * n = input - 1; 0x1002 ----> 0x1001 + * n |= n >> 1; 0x1001 | 0x800 + * n |= n >> 2; 0x1801 | 0x600 + * n |= n >> 4; 0x1e01 | 0x1e0 + * n |= n >> 8; 0x1fe1 | 0x1f + * n |= n >> 16; 0x1fff + * n |= n >> 32; 0x1fff + * n += 1; 0x2000 + */ +#define ROUND0(x) ((x)-1) +#define ROUND1(x) (ROUND0(x) |(ROUND0(x)>>1)) +#define ROUND2(x) (ROUND1(x) |(ROUND1(x)>>2)) +#define ROUND4(x) (ROUND2(x) |(ROUND2(x)>>4)) +#define ROUND8(x) (ROUND4(x) |(ROUND4(x)>>8)) +#define ROUND16(x) (ROUND8(x) |(ROUND8(x)>>16)) +#define ROUND32(x) (ROUND16(x) |(ROUND16(x)>>32)) +#define powerof2_roundup(x) ((ROUND32(x) == (~0UL)) ? ~0UL : (ROUND32(x) +1)) + /* Macro used to check if a value is aligned to the required boundary. * Returns TRUE if aligned; FALSE if not aligned * NOTE: The required alignment must be a power of 2 (2, 4, 8, 16, 32, etc) diff --git a/misc/hv_prebuild/static_checks.c b/misc/hv_prebuild/static_checks.c index 1fb081dd2..36eb01ee0 100644 --- a/misc/hv_prebuild/static_checks.c +++ b/misc/hv_prebuild/static_checks.c @@ -9,6 +9,7 @@ #include #include #include +#include #define CAT__(A,B) A ## B #define CAT_(A,B) CAT__(A,B) @@ -28,8 +29,8 @@ typedef int32_t CAT_(CTA_DummyType,__LINE__)[(expr) ? 1 : -1] #error "CONFIG_HV_RAM_SIZE must be integral multiple of 2MB" #endif -#if ((CONFIG_MAX_IR_ENTRIES < 256U) || (CONFIG_MAX_IR_ENTRIES & (CONFIG_MAX_IR_ENTRIES -1)) != 0U) -#error "CONFIG_MAX_IR_ENTRIES must >=256 and be 2^n" +#if ((MAX_IR_ENTRIES < 256U) || (MAX_IR_ENTRIES > 0x10000U) || (MAX_IR_ENTRIES & (MAX_IR_ENTRIES -1)) != 0U) +#error "MAX_IR_ENTRIES must in the region of [256,0x10000] and be 2^n" #endif /* Build time sanity checks to make sure hard-coded offset