mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-07-29 22:47:21 +00:00
hv: Bit Representation for IOAPIC RTE
As we enable Interrupt Remapping, bit positions in IOAPIC RTEs have a different syntax for programming. ACRN should handle original format for vIOAPIC as well IR representation for physical IOAPIC. This patch adds bit granularity IOAPIC RTE. Tracked-On: #2407 Signed-off-by: Sainath Grandhi <sainath.grandhi@intel.com>
This commit is contained in:
parent
7d57eb056e
commit
6d5456a0df
@ -54,9 +54,9 @@ ptirq_lookup_entry_by_vpin(const struct acrn_vm *vm, uint32_t virt_pin, bool pic
|
||||
return entry;
|
||||
}
|
||||
|
||||
static uint64_t calculate_logical_dest_mask(uint64_t pdmask)
|
||||
static uint32_t calculate_logical_dest_mask(uint64_t pdmask)
|
||||
{
|
||||
uint64_t dest_mask = 0UL;
|
||||
uint32_t dest_mask = 0UL;
|
||||
uint64_t pcpu_mask = pdmask;
|
||||
uint16_t pcpu_id;
|
||||
|
||||
@ -72,8 +72,8 @@ static uint64_t calculate_logical_dest_mask(uint64_t pdmask)
|
||||
static void ptirq_build_physical_msi(struct acrn_vm *vm, struct ptirq_msi_info *info,
|
||||
uint32_t vector)
|
||||
{
|
||||
uint64_t vdmask, pdmask, dest_mask;
|
||||
uint32_t dest, delmode;
|
||||
uint64_t vdmask, pdmask;
|
||||
uint32_t dest, delmode, dest_mask;
|
||||
bool phys;
|
||||
|
||||
/* get physical destination cpu mask */
|
||||
@ -114,8 +114,8 @@ ptirq_build_physical_rte(struct acrn_vm *vm, struct ptirq_remapping_info *entry)
|
||||
union source_id *virt_sid = &entry->virt_sid;
|
||||
|
||||
if (virt_sid->intx_id.src == PTDEV_VPIN_IOAPIC) {
|
||||
uint64_t vdmask, pdmask, delmode, dest_mask, vector;
|
||||
uint32_t dest;
|
||||
uint64_t vdmask, pdmask;
|
||||
uint32_t dest, delmode, dest_mask, vector;
|
||||
union ioapic_rte virt_rte;
|
||||
bool phys;
|
||||
|
||||
@ -123,7 +123,7 @@ ptirq_build_physical_rte(struct acrn_vm *vm, struct ptirq_remapping_info *entry)
|
||||
rte = virt_rte;
|
||||
|
||||
/* init polarity & pin state */
|
||||
if ((rte.full & IOAPIC_RTE_INTPOL) != 0UL) {
|
||||
if (rte.bits.intr_polarity == IOAPIC_RTE_INTPOL_ALO) {
|
||||
if (entry->polarity == 0U) {
|
||||
vioapic_set_irqline_nolock(vm, virt_sid->intx_id.pin, GSI_SET_HIGH);
|
||||
}
|
||||
@ -136,27 +136,27 @@ ptirq_build_physical_rte(struct acrn_vm *vm, struct ptirq_remapping_info *entry)
|
||||
}
|
||||
|
||||
/* physical destination cpu mask */
|
||||
phys = ((virt_rte.full & IOAPIC_RTE_DESTMOD) == IOAPIC_RTE_DESTPHY);
|
||||
dest = (uint32_t)(virt_rte.full >> IOAPIC_RTE_DEST_SHIFT);
|
||||
phys = (virt_rte.bits.dest_mode == IOAPIC_RTE_DESTMODE_PHY);
|
||||
dest = (uint32_t)virt_rte.bits.dest_field;
|
||||
vlapic_calcdest(vm, &vdmask, dest, phys, false);
|
||||
pdmask = vcpumask2pcpumask(vm, vdmask);
|
||||
|
||||
/* physical delivery mode */
|
||||
delmode = virt_rte.full & IOAPIC_RTE_DELMOD;
|
||||
if ((delmode != IOAPIC_RTE_DELFIXED) &&
|
||||
(delmode != IOAPIC_RTE_DELLOPRI)) {
|
||||
delmode = IOAPIC_RTE_DELLOPRI;
|
||||
delmode = virt_rte.bits.delivery_mode;
|
||||
if ((delmode != IOAPIC_RTE_DELMODE_FIXED) &&
|
||||
(delmode != IOAPIC_RTE_DELMODE_LOPRI)) {
|
||||
delmode = IOAPIC_RTE_DELMODE_LOPRI;
|
||||
}
|
||||
|
||||
/* update physical delivery mode, dest mode(logical) & vector */
|
||||
vector = (uint64_t)irq_to_vector(phys_irq);
|
||||
rte.full &= ~(IOAPIC_RTE_DESTMOD | IOAPIC_RTE_DELMOD | IOAPIC_RTE_INTVEC);
|
||||
rte.full |= IOAPIC_RTE_DESTLOG | delmode | vector;
|
||||
vector = irq_to_vector(phys_irq);
|
||||
rte.bits.dest_mode = IOAPIC_RTE_DESTMODE_LOGICAL;
|
||||
rte.bits.delivery_mode = delmode;
|
||||
rte.bits.vector = vector;
|
||||
|
||||
dest_mask = calculate_logical_dest_mask(pdmask);
|
||||
/* update physical dest field */
|
||||
rte.full &= ~IOAPIC_RTE_DEST_MASK;
|
||||
rte.full |= dest_mask << IOAPIC_RTE_DEST_SHIFT;
|
||||
rte.bits.dest_field = dest_mask;
|
||||
|
||||
dev_dbg(ACRN_DBG_IRQ, "IOAPIC RTE = 0x%x:%x(V) -> 0x%x:%x(P)",
|
||||
virt_rte.u.hi_32, virt_rte.u.lo_32,
|
||||
@ -167,10 +167,11 @@ ptirq_build_physical_rte(struct acrn_vm *vm, struct ptirq_remapping_info *entry)
|
||||
|
||||
/* just update trigger mode */
|
||||
ioapic_get_rte(phys_irq, &phys_rte);
|
||||
rte.full = phys_rte.full & (~IOAPIC_RTE_TRGRMOD);
|
||||
vpic_get_irqline_trigger_mode(vm, virt_sid->intx_id.pin, &trigger);
|
||||
rte = phys_rte;
|
||||
rte.bits.trigger_mode = IOAPIC_RTE_TRGRMODE_EDGE;
|
||||
vpic_get_irqline_trigger_mode(vm, (uint32_t)virt_sid->intx_id.pin, &trigger);
|
||||
if (trigger == LEVEL_TRIGGER) {
|
||||
rte.full |= IOAPIC_RTE_TRGRLVL;
|
||||
rte.bits.trigger_mode = IOAPIC_RTE_TRGRMODE_LEVEL;
|
||||
}
|
||||
|
||||
dev_dbg(ACRN_DBG_IRQ, "IOAPIC RTE = 0x%x:%x(P) -> 0x%x:%x(P)",
|
||||
@ -367,8 +368,8 @@ static void ptirq_handle_intx(struct acrn_vm *vm,
|
||||
bool trigger_lvl = false;
|
||||
|
||||
/* VPIN_IOAPIC src means we have vioapic enabled */
|
||||
vioapic_get_rte(vm, virt_sid->intx_id.pin, &rte);
|
||||
if ((rte.full & IOAPIC_RTE_TRGRMOD) == IOAPIC_RTE_TRGRLVL) {
|
||||
vioapic_get_rte(vm, (uint32_t)virt_sid->intx_id.pin, &rte);
|
||||
if (rte.bits.trigger_mode == IOAPIC_RTE_TRGRMODE_LEVEL) {
|
||||
trigger_lvl = true;
|
||||
}
|
||||
|
||||
@ -557,7 +558,7 @@ static void activate_physical_ioapic(struct acrn_vm *vm,
|
||||
{
|
||||
union ioapic_rte rte;
|
||||
uint32_t phys_irq = entry->allocated_pirq;
|
||||
uint32_t intr_mask;
|
||||
uint64_t intr_mask;
|
||||
bool is_lvl_trigger = false;
|
||||
|
||||
/* disable interrupt */
|
||||
@ -565,19 +566,19 @@ static void activate_physical_ioapic(struct acrn_vm *vm,
|
||||
|
||||
/* build physical IOAPIC RTE */
|
||||
rte = ptirq_build_physical_rte(vm, entry);
|
||||
intr_mask = (uint32_t)(rte.full & IOAPIC_RTE_INTMASK);
|
||||
intr_mask = rte.bits.intr_mask;
|
||||
|
||||
/* update irq trigger mode according to info in guest */
|
||||
if ((rte.full & IOAPIC_RTE_TRGRMOD) == IOAPIC_RTE_TRGRLVL) {
|
||||
if (rte.bits.trigger_mode == IOAPIC_RTE_TRGRMODE_LEVEL) {
|
||||
is_lvl_trigger = true;
|
||||
}
|
||||
set_irq_trigger_mode(phys_irq, is_lvl_trigger);
|
||||
|
||||
/* set rte entry when masked */
|
||||
rte.full |= IOAPIC_RTE_INTMSET;
|
||||
rte.bits.intr_mask = IOAPIC_RTE_MASK_SET;
|
||||
ioapic_set_rte(phys_irq, rte);
|
||||
|
||||
if (intr_mask == IOAPIC_RTE_INTMCLR) {
|
||||
if (intr_mask == IOAPIC_RTE_MASK_CLR) {
|
||||
ioapic_gsi_unmask_irq(phys_irq);
|
||||
}
|
||||
}
|
||||
|
@ -1806,13 +1806,13 @@ vlapic_deliver_intr(struct acrn_vm *vm, bool level, uint32_t dest, bool phys,
|
||||
uint64_t dmask;
|
||||
struct acrn_vcpu *target_vcpu;
|
||||
|
||||
if ((delmode != IOAPIC_RTE_DELFIXED) &&
|
||||
(delmode != IOAPIC_RTE_DELLOPRI) &&
|
||||
(delmode != IOAPIC_RTE_DELEXINT)) {
|
||||
if ((delmode != IOAPIC_RTE_DELMODE_FIXED) &&
|
||||
(delmode != IOAPIC_RTE_DELMODE_LOPRI) &&
|
||||
(delmode != IOAPIC_RTE_DELMODE_EXINT)) {
|
||||
dev_dbg(ACRN_DBG_LAPIC,
|
||||
"vlapic intr invalid delmode %#x", delmode);
|
||||
} else {
|
||||
lowprio = (delmode == IOAPIC_RTE_DELLOPRI) || rh;
|
||||
lowprio = (delmode == IOAPIC_RTE_DELMODE_LOPRI) || rh;
|
||||
|
||||
/*
|
||||
* We don't provide any virtual interrupt redirection hardware so
|
||||
@ -1829,7 +1829,7 @@ vlapic_deliver_intr(struct acrn_vm *vm, bool level, uint32_t dest, bool phys,
|
||||
/* only make request when vlapic enabled */
|
||||
vlapic = vcpu_vlapic(target_vcpu);
|
||||
if (vlapic_enabled(vlapic)) {
|
||||
if (delmode == IOAPIC_RTE_DELEXINT) {
|
||||
if (delmode == IOAPIC_RTE_DELMODE_EXINT) {
|
||||
vcpu_inject_extint(target_vcpu);
|
||||
} else {
|
||||
vlapic_set_intr(target_vcpu, vec, level);
|
||||
|
@ -45,23 +45,23 @@ static const uint32_t legacy_irq_to_pin[NR_LEGACY_IRQ] = {
|
||||
15U, /* IRQ15*/
|
||||
};
|
||||
|
||||
static const uint64_t legacy_irq_trigger_mode[NR_LEGACY_IRQ] = {
|
||||
IOAPIC_RTE_TRGREDG, /* IRQ0*/
|
||||
IOAPIC_RTE_TRGREDG, /* IRQ1*/
|
||||
IOAPIC_RTE_TRGREDG, /* IRQ2*/
|
||||
IOAPIC_RTE_TRGREDG, /* IRQ3*/
|
||||
IOAPIC_RTE_TRGREDG, /* IRQ4*/
|
||||
IOAPIC_RTE_TRGREDG, /* IRQ5*/
|
||||
IOAPIC_RTE_TRGREDG, /* IRQ6*/
|
||||
IOAPIC_RTE_TRGREDG, /* IRQ7*/
|
||||
IOAPIC_RTE_TRGREDG, /* IRQ8*/
|
||||
IOAPIC_RTE_TRGRLVL, /* IRQ9*/
|
||||
IOAPIC_RTE_TRGREDG, /* IRQ10*/
|
||||
IOAPIC_RTE_TRGREDG, /* IRQ11*/
|
||||
IOAPIC_RTE_TRGREDG, /* IRQ12*/
|
||||
IOAPIC_RTE_TRGREDG, /* IRQ13*/
|
||||
IOAPIC_RTE_TRGREDG, /* IRQ14*/
|
||||
IOAPIC_RTE_TRGREDG, /* IRQ15*/
|
||||
static const uint32_t legacy_irq_trigger_mode[NR_LEGACY_IRQ] = {
|
||||
IOAPIC_RTE_TRGRMODE_EDGE, /* IRQ0*/
|
||||
IOAPIC_RTE_TRGRMODE_EDGE, /* IRQ1*/
|
||||
IOAPIC_RTE_TRGRMODE_EDGE, /* IRQ2*/
|
||||
IOAPIC_RTE_TRGRMODE_EDGE, /* IRQ3*/
|
||||
IOAPIC_RTE_TRGRMODE_EDGE, /* IRQ4*/
|
||||
IOAPIC_RTE_TRGRMODE_EDGE, /* IRQ5*/
|
||||
IOAPIC_RTE_TRGRMODE_EDGE, /* IRQ6*/
|
||||
IOAPIC_RTE_TRGRMODE_EDGE, /* IRQ7*/
|
||||
IOAPIC_RTE_TRGRMODE_EDGE, /* IRQ8*/
|
||||
IOAPIC_RTE_TRGRMODE_LEVEL, /* IRQ9*/
|
||||
IOAPIC_RTE_TRGRMODE_EDGE, /* IRQ10*/
|
||||
IOAPIC_RTE_TRGRMODE_EDGE, /* IRQ11*/
|
||||
IOAPIC_RTE_TRGRMODE_EDGE, /* IRQ12*/
|
||||
IOAPIC_RTE_TRGRMODE_EDGE, /* IRQ13*/
|
||||
IOAPIC_RTE_TRGRMODE_EDGE, /* IRQ14*/
|
||||
IOAPIC_RTE_TRGRMODE_EDGE, /* IRQ15*/
|
||||
};
|
||||
|
||||
static const uint32_t pic_ioapic_pin_map[NR_LEGACY_PIN] = {
|
||||
@ -184,17 +184,18 @@ create_rte_for_legacy_irq(uint32_t irq, uint32_t vr)
|
||||
* before we have ACPI table parsing in HV we use common hardcode
|
||||
*/
|
||||
|
||||
rte.full = IOAPIC_RTE_INTMSET;
|
||||
rte.full |= legacy_irq_trigger_mode[irq];
|
||||
rte.full |= DEFAULT_DEST_MODE;
|
||||
rte.full |= DEFAULT_DELIVERY_MODE;
|
||||
rte.full |= (IOAPIC_RTE_INTVEC & (uint64_t)vr);
|
||||
rte.full = 0UL;
|
||||
rte.bits.intr_mask = IOAPIC_RTE_MASK_SET;
|
||||
rte.bits.trigger_mode = legacy_irq_trigger_mode[irq];
|
||||
rte.bits.dest_mode = DEFAULT_DEST_MODE;
|
||||
rte.bits.delivery_mode = DEFAULT_DELIVERY_MODE;
|
||||
rte.bits.vector = vr;
|
||||
|
||||
/* Fixed to active high */
|
||||
rte.full |= IOAPIC_RTE_INTAHI;
|
||||
rte.bits.intr_polarity = IOAPIC_RTE_INTPOL_AHI;
|
||||
|
||||
/* Dest field: legacy irq fixed to CPU0 */
|
||||
rte.full |= (1UL << IOAPIC_RTE_DEST_SHIFT);
|
||||
rte.bits.dest_field = 1U;
|
||||
|
||||
return rte;
|
||||
}
|
||||
@ -204,21 +205,23 @@ create_rte_for_gsi_irq(uint32_t irq, uint32_t vr)
|
||||
{
|
||||
union ioapic_rte rte;
|
||||
|
||||
rte.full = 0UL;
|
||||
|
||||
if (irq < NR_LEGACY_IRQ) {
|
||||
rte = create_rte_for_legacy_irq(irq, vr);
|
||||
} else {
|
||||
/* irq default masked, level trig */
|
||||
rte.full = IOAPIC_RTE_INTMSET;
|
||||
rte.full |= IOAPIC_RTE_TRGRLVL;
|
||||
rte.full |= DEFAULT_DEST_MODE;
|
||||
rte.full |= DEFAULT_DELIVERY_MODE;
|
||||
rte.full |= (IOAPIC_RTE_INTVEC & (uint64_t)vr);
|
||||
rte.bits.intr_mask = IOAPIC_RTE_MASK_SET;
|
||||
rte.bits.trigger_mode = IOAPIC_RTE_TRGRMODE_LEVEL;
|
||||
rte.bits.dest_mode = DEFAULT_DEST_MODE;
|
||||
rte.bits.delivery_mode = DEFAULT_DELIVERY_MODE;
|
||||
rte.bits.vector = vr;
|
||||
|
||||
/* Fixed to active high */
|
||||
rte.full |= IOAPIC_RTE_INTAHI;
|
||||
rte.bits.intr_polarity = IOAPIC_RTE_INTPOL_AHI;
|
||||
|
||||
/* Dest field */
|
||||
rte.full |= (ALL_CPUS_MASK << IOAPIC_RTE_DEST_SHIFT);
|
||||
rte.bits.dest_field = ALL_CPUS_MASK;
|
||||
}
|
||||
|
||||
return rte;
|
||||
@ -233,7 +236,7 @@ static void ioapic_set_routing(uint32_t gsi, uint32_t vr)
|
||||
rte = create_rte_for_gsi_irq(gsi, vr);
|
||||
ioapic_set_rte_entry(addr, gsi_table_data[gsi].pin, rte);
|
||||
|
||||
if ((rte.full & IOAPIC_RTE_TRGRMOD) != 0UL) {
|
||||
if (rte.bits.trigger_mode == IOAPIC_RTE_TRGRMODE_LEVEL) {
|
||||
set_irq_trigger_mode(gsi, true);
|
||||
} else {
|
||||
set_irq_trigger_mode(gsi, false);
|
||||
@ -322,9 +325,9 @@ ioapic_irq_gsi_mask_unmask(uint32_t irq, bool mask)
|
||||
if (addr != NULL) {
|
||||
ioapic_get_rte_entry(addr, pin, &rte);
|
||||
if (mask) {
|
||||
rte.full |= IOAPIC_RTE_INTMSET;
|
||||
rte.bits.intr_mask = IOAPIC_RTE_MASK_SET;
|
||||
} else {
|
||||
rte.full &= ~IOAPIC_RTE_INTMASK;
|
||||
rte.bits.intr_mask = IOAPIC_RTE_MASK_CLR;
|
||||
}
|
||||
ioapic_set_rte_entry(addr, pin, rte);
|
||||
dev_dbg(ACRN_DBG_PTIRQ, "update: irq:%d pin:%hhu rte:%lx",
|
||||
|
@ -927,8 +927,8 @@ static void get_entry_info(const struct ptirq_remapping_info *entry, char *type,
|
||||
(void)strncpy_s(type, 16U, "PIC", 16U);
|
||||
}
|
||||
ioapic_get_rte(phys_irq, &rte);
|
||||
*dest = rte.full >> IOAPIC_RTE_DEST_SHIFT;
|
||||
if ((rte.full & IOAPIC_RTE_TRGRLVL) != 0UL) {
|
||||
*dest = rte.bits.dest_field;
|
||||
if (rte.bits.trigger_mode == IOAPIC_RTE_TRGRMODE_LEVEL) {
|
||||
*lvl_tm = true;
|
||||
} else {
|
||||
*lvl_tm = false;
|
||||
@ -1047,13 +1047,13 @@ static void get_vioapic_info(char *str_arg, size_t str_max, uint16_t vmid)
|
||||
rte.full = 0UL;
|
||||
for (pin = 0U; pin < pincount; pin++) {
|
||||
vioapic_get_rte(vm, pin, &rte);
|
||||
mask = ((rte.full & IOAPIC_RTE_INTMASK) == IOAPIC_RTE_INTMSET);
|
||||
remote_irr = ((rte.full & IOAPIC_RTE_REM_IRR) == IOAPIC_RTE_REM_IRR);
|
||||
phys = ((rte.full & IOAPIC_RTE_DESTMOD) == IOAPIC_RTE_DESTPHY);
|
||||
delmode = (uint32_t)(rte.full & IOAPIC_RTE_DELMOD);
|
||||
level = ((rte.full & IOAPIC_RTE_TRGRLVL) != 0UL);
|
||||
vector = rte.u.lo_32 & IOAPIC_RTE_LOW_INTVEC;
|
||||
dest = (uint32_t)(rte.full >> IOAPIC_RTE_DEST_SHIFT);
|
||||
mask = (rte.bits.intr_mask == IOAPIC_RTE_MASK_SET);
|
||||
remote_irr = (rte.bits.remote_irr == IOAPIC_RTE_REM_IRR);
|
||||
phys = (rte.bits.dest_mode == IOAPIC_RTE_DESTMODE_PHY);
|
||||
delmode = rte.bits.delivery_mode;
|
||||
level = (rte.bits.trigger_mode == IOAPIC_RTE_TRGRMODE_LEVEL);
|
||||
vector = rte.bits.vector;
|
||||
dest = rte.bits.dest_field;
|
||||
|
||||
len = snprintf(str, size, "\r\n%hhu\t0x%X\t%s\t0x%X\t%s\t%u\t%d\t%d",
|
||||
pin, vector, phys ? "phys" : "logic", dest, level ? "level" : "edge",
|
||||
@ -1092,18 +1092,6 @@ static int32_t shell_show_vioapic_info(int32_t argc, char **argv)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static void get_rte_info(union ioapic_rte rte, bool *mask, bool *irr,
|
||||
bool *phys, uint32_t *delmode, bool *level, uint32_t *vector, uint32_t *dest)
|
||||
{
|
||||
*mask = ((rte.full & IOAPIC_RTE_INTMASK) == IOAPIC_RTE_INTMSET);
|
||||
*irr = ((rte.full & IOAPIC_RTE_REM_IRR) == IOAPIC_RTE_REM_IRR);
|
||||
*phys = ((rte.full & IOAPIC_RTE_DESTMOD) == IOAPIC_RTE_DESTPHY);
|
||||
*delmode = (uint32_t)(rte.full & IOAPIC_RTE_DELMOD);
|
||||
*level = ((rte.full & IOAPIC_RTE_TRGRLVL) != 0UL);
|
||||
*vector = (uint32_t)(rte.full & IOAPIC_RTE_INTVEC);
|
||||
*dest = (uint32_t)(rte.full >> APIC_ID_SHIFT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get information of ioapic
|
||||
*
|
||||
@ -1133,9 +1121,6 @@ static int32_t get_ioapic_info(char *str_arg, size_t str_max_len)
|
||||
uint32_t pin = ioapic_irq_to_pin(irq);
|
||||
union ioapic_rte rte;
|
||||
|
||||
bool irr, phys, level, mask;
|
||||
uint32_t delmode, vector, dest;
|
||||
|
||||
/* Add NULL check for addr, INVALID_PIN check for pin */
|
||||
if ((addr == NULL) || (!ioapic_is_pin_valid(pin))) {
|
||||
goto overflow;
|
||||
@ -1143,8 +1128,6 @@ static int32_t get_ioapic_info(char *str_arg, size_t str_max_len)
|
||||
|
||||
ioapic_get_rte_entry(addr, pin, &rte);
|
||||
|
||||
get_rte_info(rte, &mask, &irr, &phys, &delmode, &level, &vector, &dest);
|
||||
|
||||
len = snprintf(str, size, "\r\n%03d\t%03hhu\t0x%08X\t0x%08X\t", irq, pin, rte.u.hi_32, rte.u.lo_32);
|
||||
if (len >= size) {
|
||||
goto overflow;
|
||||
@ -1153,7 +1136,9 @@ static int32_t get_ioapic_info(char *str_arg, size_t str_max_len)
|
||||
str += len;
|
||||
|
||||
len = snprintf(str, size, "0x%02X\t0x%02X\t%s\t%s\t%u\t%d\t%d",
|
||||
vector, dest, phys ? "phys" : "logic", level ? "level" : "edge", delmode >> 8, irr, mask);
|
||||
rte.bits.vector, rte.bits.dest_field, rte.bits.dest_mode ? "logic" : "phys",
|
||||
rte.bits.trigger_mode ? "level" : "edge", rte.bits.delivery_mode, rte.bits.remote_irr,
|
||||
rte.bits.intr_mask);
|
||||
if (len >= size) {
|
||||
goto overflow;
|
||||
}
|
||||
|
@ -143,7 +143,7 @@ static void vuart_toggle_intr(const struct acrn_vuart *vu)
|
||||
* modify the vioapic setting, as it's only for debug uart,
|
||||
* we want to make it as an known issue.
|
||||
*/
|
||||
if ((rte.full & IOAPIC_RTE_INTPOL) != 0UL) {
|
||||
if (rte.bits.intr_polarity == IOAPIC_RTE_INTPOL_ALO) {
|
||||
operation = (intr_reason != IIR_NOPEND) ? GSI_SET_LOW : GSI_SET_HIGH;
|
||||
} else {
|
||||
operation = (intr_reason != IIR_NOPEND) ? GSI_SET_HIGH : GSI_SET_LOW;
|
||||
|
@ -32,8 +32,7 @@
|
||||
|
||||
#include <hypervisor.h>
|
||||
|
||||
#define RTBL_RO_BITS (uint32_t)(IOAPIC_RTE_REM_IRR | IOAPIC_RTE_DELIVS)
|
||||
#define NEED_EOI_EXIT_UPDATE (IOAPIC_RTE_TRGRMOD | IOAPIC_RTE_DELMOD | IOAPIC_RTE_DEST_MASK | IOAPIC_RTE_INTVEC)
|
||||
#define RTBL_RO_BITS ((uint32_t)0x00004000U | (uint32_t)0x00001000U) /*Remote IRR and Delivery Status bits*/
|
||||
|
||||
#define ACRN_DBG_IOAPIC 6U
|
||||
#define ACRN_IOAPIC_VERSION 0x11U
|
||||
@ -53,22 +52,22 @@ vioapic_generate_intr(struct acrn_vioapic *vioapic, uint32_t pin)
|
||||
|
||||
rte = vioapic->rtbl[pin];
|
||||
|
||||
if ((rte.full & IOAPIC_RTE_INTMASK) == IOAPIC_RTE_INTMSET) {
|
||||
if (rte.bits.intr_mask == IOAPIC_RTE_MASK_SET) {
|
||||
dev_dbg(ACRN_DBG_IOAPIC, "ioapic pin%hhu: masked", pin);
|
||||
} else {
|
||||
phys = ((rte.full & IOAPIC_RTE_DESTMOD) == IOAPIC_RTE_DESTPHY);
|
||||
delmode = (uint32_t)(rte.full & IOAPIC_RTE_DELMOD);
|
||||
level = ((rte.full & IOAPIC_RTE_TRGRLVL) != 0UL);
|
||||
phys = (rte.bits.dest_mode == IOAPIC_RTE_DESTMODE_PHY);
|
||||
delmode = rte.bits.delivery_mode;
|
||||
level = (rte.bits.trigger_mode == IOAPIC_RTE_TRGRMODE_LEVEL);
|
||||
|
||||
/* For level trigger irq, avoid send intr if
|
||||
* previous one hasn't received EOI
|
||||
*/
|
||||
if (!level || ((vioapic->rtbl[pin].full & IOAPIC_RTE_REM_IRR) == 0UL)) {
|
||||
if (!level || (vioapic->rtbl[pin].bits.remote_irr == 0UL)) {
|
||||
if (level) {
|
||||
vioapic->rtbl[pin].full |= IOAPIC_RTE_REM_IRR;
|
||||
vioapic->rtbl[pin].bits.remote_irr = IOAPIC_RTE_REM_IRR;
|
||||
}
|
||||
vector = rte.u.lo_32 & IOAPIC_RTE_LOW_INTVEC;
|
||||
dest = (uint32_t)(rte.full >> IOAPIC_RTE_DEST_SHIFT);
|
||||
vector = rte.bits.vector;
|
||||
dest = rte.bits.dest_field;
|
||||
vlapic_deliver_intr(vioapic->vm, level, dest, phys, delmode, vector, false);
|
||||
}
|
||||
}
|
||||
@ -89,14 +88,14 @@ vioapic_set_pinstate(struct acrn_vioapic *vioapic, uint32_t pin, uint32_t level)
|
||||
if (level == 0U) {
|
||||
/* clear pin_state and deliver interrupt according to polarity */
|
||||
bitmap_clear_nolock((uint16_t)(pin & 0x3FU), &vioapic->pin_state[pin >> 6U]);
|
||||
if (((rte.full & IOAPIC_RTE_INTPOL) != 0UL)
|
||||
if ((rte.bits.intr_polarity == IOAPIC_RTE_INTPOL_ALO)
|
||||
&& old_lvl != level) {
|
||||
vioapic_generate_intr(vioapic, pin);
|
||||
}
|
||||
} else {
|
||||
/* set pin_state and deliver intrrupt according to polarity */
|
||||
bitmap_set_nolock((uint16_t)(pin & 0x3FU), &vioapic->pin_state[pin >> 6U]);
|
||||
if (((rte.full & IOAPIC_RTE_INTPOL) == 0UL)
|
||||
if ((rte.bits.intr_polarity == IOAPIC_RTE_INTPOL_AHI)
|
||||
&& old_lvl != level) {
|
||||
vioapic_generate_intr(vioapic, pin);
|
||||
}
|
||||
@ -200,19 +199,19 @@ vioapic_update_eoi_exit(const struct acrn_vioapic *vioapic)
|
||||
for (pin = 0U; pin < pincount; pin++) {
|
||||
rte = vioapic->rtbl[pin];
|
||||
|
||||
level = ((rte.full & IOAPIC_RTE_TRGRLVL) != 0UL);
|
||||
vector = rte.u.lo_32 & IOAPIC_RTE_LOW_INTVEC;
|
||||
level = (rte.bits.trigger_mode == IOAPIC_RTE_TRGRMODE_LEVEL);
|
||||
vector = rte.bits.vector;
|
||||
|
||||
if (level && ((vector >= 0x20U) && (vector < NR_MAX_VECTOR))) {
|
||||
/* if level-trigger and vector is valid */
|
||||
delmode = (uint32_t)(rte.full & IOAPIC_RTE_DELMOD);
|
||||
delmode = (uint32_t)rte.bits.delivery_mode;
|
||||
|
||||
if ((delmode != APIC_DELMODE_FIXED) && (delmode != APIC_DELMODE_LOWPRIO)) {
|
||||
if ((delmode != IOAPIC_RTE_DELMODE_FIXED) && (delmode != IOAPIC_RTE_DELMODE_LOPRI)) {
|
||||
dev_dbg(ACRN_DBG_IOAPIC,
|
||||
"Ignoring level trigger-mode for delivery-mode 0x%x", delmode);
|
||||
} else {
|
||||
dest = (uint32_t)((rte.full) >> IOAPIC_RTE_DEST_SHIFT);
|
||||
phys = ((rte.full & IOAPIC_RTE_DESTLOG) == 0UL);
|
||||
dest = (uint32_t)rte.bits.dest_field;
|
||||
phys = (rte.bits.dest_mode == IOAPIC_RTE_DESTMODE_PHY);
|
||||
vlapic_calcdest(vioapic->vm, &mask, dest, phys, false);
|
||||
|
||||
for (vcpu_id = ffs64(mask); vcpu_id != INVALID_BIT_INDEX; vcpu_id = ffs64(mask)) {
|
||||
@ -285,8 +284,8 @@ static inline bool vioapic_need_intr(const struct acrn_vioapic *vioapic, uint16_
|
||||
} else {
|
||||
rte = vioapic->rtbl[pin];
|
||||
lvl = (uint32_t)bitmap_test(pin & 0x3FU, &vioapic->pin_state[pin >> 6U]);
|
||||
ret = !!((((rte.full & IOAPIC_RTE_INTPOL) != 0UL) && lvl == 0U) ||
|
||||
(((rte.full & IOAPIC_RTE_INTPOL) == 0UL) && lvl != 0U));
|
||||
ret = !!(((rte.bits.intr_polarity == IOAPIC_RTE_INTPOL_ALO) && lvl == 0U) ||
|
||||
((rte.bits.intr_polarity == IOAPIC_RTE_INTPOL_AHI) && lvl != 0U));
|
||||
}
|
||||
|
||||
return ret;
|
||||
@ -298,8 +297,7 @@ static inline bool vioapic_need_intr(const struct acrn_vioapic *vioapic, uint16_
|
||||
*/
|
||||
static void vioapic_indirect_write(struct acrn_vioapic *vioapic, uint32_t addr, uint32_t data)
|
||||
{
|
||||
union ioapic_rte last, new;
|
||||
uint64_t changed;
|
||||
union ioapic_rte last, new, changed;
|
||||
uint32_t regnum;
|
||||
uint32_t pin, pincount = vioapic_pincount(vioapic->vm);
|
||||
|
||||
@ -344,15 +342,15 @@ static void vioapic_indirect_write(struct acrn_vioapic *vioapic, uint32_t addr,
|
||||
* 0x20 version IOAPIC, otherwise use switch Trigger Mode to
|
||||
* Edge Sensitive to clear it.
|
||||
*/
|
||||
if ((new.full & IOAPIC_RTE_TRGRLVL) == 0U) {
|
||||
new.full &= ~IOAPIC_RTE_REM_IRR;
|
||||
if (new.bits.trigger_mode == IOAPIC_RTE_TRGRMODE_EDGE) {
|
||||
new.bits.remote_irr = 0U;
|
||||
}
|
||||
|
||||
changed = last.full ^ new.full;
|
||||
changed.full = last.full ^ new.full;
|
||||
/* pin0 from vpic mask/unmask */
|
||||
if ((pin == 0U) && ((changed & IOAPIC_RTE_INTMASK) != 0UL)) {
|
||||
if ((pin == 0U) && (changed.bits.intr_mask != 0UL)) {
|
||||
/* mask -> umask */
|
||||
if ((last.full & IOAPIC_RTE_INTMASK) != 0UL) {
|
||||
if (last.bits.intr_mask == IOAPIC_RTE_MASK_SET) {
|
||||
if ((vioapic->vm->wire_mode == VPIC_WIRE_NULL) ||
|
||||
(vioapic->vm->wire_mode == VPIC_WIRE_INTR)) {
|
||||
vioapic->vm->wire_mode = VPIC_WIRE_IOAPIC;
|
||||
@ -380,7 +378,8 @@ static void vioapic_indirect_write(struct acrn_vioapic *vioapic, uint32_t addr,
|
||||
* rendezvous all the vcpus to update their vlapic
|
||||
* trigger-mode registers.
|
||||
*/
|
||||
if ((changed & NEED_EOI_EXIT_UPDATE) != 0UL) {
|
||||
if ((changed.bits.vector != 0UL) || (changed.bits.delivery_mode != 0UL)
|
||||
|| (changed.bits.trigger_mode != 0UL) || (changed.bits.dest_field != 0UL)) {
|
||||
dev_dbg(ACRN_DBG_IOAPIC, "ioapic pin%hhu: recalculate vlapic trigger-mode reg", pin);
|
||||
vioapic_update_eoi_exit(vioapic);
|
||||
}
|
||||
@ -391,15 +390,15 @@ static void vioapic_indirect_write(struct acrn_vioapic *vioapic, uint32_t addr,
|
||||
* - previous interrupt has been EOIed
|
||||
* - pin level is asserted
|
||||
*/
|
||||
if (((vioapic->rtbl[pin].full & IOAPIC_RTE_INTMASK) == IOAPIC_RTE_INTMCLR) &&
|
||||
((vioapic->rtbl[pin].full & IOAPIC_RTE_REM_IRR) == 0UL) &&
|
||||
if ((vioapic->rtbl[pin].bits.intr_mask == IOAPIC_RTE_MASK_CLR) &&
|
||||
(vioapic->rtbl[pin].bits.remote_irr == 0UL) &&
|
||||
vioapic_need_intr(vioapic, (uint16_t)pin)) {
|
||||
dev_dbg(ACRN_DBG_IOAPIC, "ioapic pin%hhu: asserted at rtbl write", pin);
|
||||
vioapic_generate_intr(vioapic, pin);
|
||||
}
|
||||
|
||||
/* remap for ptdev */
|
||||
if (((new.full & IOAPIC_RTE_INTMASK) == 0UL) || ((last.full & IOAPIC_RTE_INTMASK) == 0UL)) {
|
||||
if ((new.bits.intr_mask == IOAPIC_RTE_MASK_CLR) || (last.bits.intr_mask == IOAPIC_RTE_MASK_CLR)) {
|
||||
/* VM enable intr */
|
||||
/* NOTE: only support max 256 pin */
|
||||
(void)ptirq_intx_pin_remap(vioapic->vm, pin, PTDEV_VPIN_IOAPIC);
|
||||
@ -465,8 +464,8 @@ vioapic_process_eoi(struct acrn_vm *vm, uint32_t vector)
|
||||
/* notify device to ack if assigned pin */
|
||||
for (pin = 0U; pin < pincount; pin++) {
|
||||
rte = vioapic->rtbl[pin];
|
||||
if (((rte.u.lo_32 & IOAPIC_RTE_LOW_INTVEC) != vector) ||
|
||||
((rte.full & IOAPIC_RTE_REM_IRR) == 0UL)) {
|
||||
if ((rte.bits.vector != vector) ||
|
||||
(rte.bits.remote_irr == 0U)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -480,12 +479,12 @@ vioapic_process_eoi(struct acrn_vm *vm, uint32_t vector)
|
||||
spinlock_obtain(&(vioapic->mtx));
|
||||
for (pin = 0U; pin < pincount; pin++) {
|
||||
rte = vioapic->rtbl[pin];
|
||||
if (((rte.u.lo_32 & IOAPIC_RTE_LOW_INTVEC) != vector) ||
|
||||
((rte.full & IOAPIC_RTE_REM_IRR) == 0UL)) {
|
||||
if ((rte.bits.vector != vector) ||
|
||||
(rte.bits.remote_irr == 0U)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
vioapic->rtbl[pin].full &= (~IOAPIC_RTE_REM_IRR);
|
||||
vioapic->rtbl[pin].bits.remote_irr = 0U;
|
||||
if (vioapic_need_intr(vioapic, (uint16_t)pin)) {
|
||||
dev_dbg(ACRN_DBG_IOAPIC,
|
||||
"ioapic pin%hhu: asserted at eoi", pin);
|
||||
|
@ -166,6 +166,30 @@ struct ioapic {
|
||||
uint32_t rsv1[3];
|
||||
};
|
||||
|
||||
/*
|
||||
* Macros for bits in union ioapic_rte
|
||||
*/
|
||||
#define IOAPIC_RTE_MASK_CLR 0x0U /* Interrupt Mask: Clear */
|
||||
#define IOAPIC_RTE_MASK_SET 0x1U /* Interrupt Mask: Set */
|
||||
|
||||
#define IOAPIC_RTE_TRGRMODE_EDGE 0x0U /* Trigger Mode: Edge */
|
||||
#define IOAPIC_RTE_TRGRMODE_LEVEL 0x1U /* Trigger Mode: Level */
|
||||
|
||||
#define IOAPIC_RTE_REM_IRR 0x1U /* Remote IRR: Read-Only */
|
||||
|
||||
#define IOAPIC_RTE_INTPOL_AHI 0x0U /* Interrupt Polarity: active high */
|
||||
#define IOAPIC_RTE_INTPOL_ALO 0x1U /* Interrupt Polarity: active low */
|
||||
|
||||
#define IOAPIC_RTE_DELIVS 0x1U /* Delivery Status: Read-Only */
|
||||
|
||||
#define IOAPIC_RTE_DESTMODE_PHY 0x0U /* Destination Mode: Physical */
|
||||
#define IOAPIC_RTE_DESTMODE_LOGICAL 0x1U /* Destination Mode: Logical */
|
||||
|
||||
#define IOAPIC_RTE_DELMODE_FIXED 0x0U /* Delivery Mode: Fixed */
|
||||
#define IOAPIC_RTE_DELMODE_LOPRI 0x1U /* Delivery Mode: Lowest priority */
|
||||
#define IOAPIC_RTE_DELMODE_INIT 0x5U /* Delivery Mode: INIT signal */
|
||||
#define IOAPIC_RTE_DELMODE_EXINT 0x7U /* Delivery Mode: External INTerrupt */
|
||||
|
||||
/* IOAPIC Redirection Table (RTE) Entry structure */
|
||||
union ioapic_rte {
|
||||
uint64_t full;
|
||||
@ -173,6 +197,18 @@ union ioapic_rte {
|
||||
uint32_t lo_32;
|
||||
uint32_t hi_32;
|
||||
} u;
|
||||
struct {
|
||||
uint64_t vector:8;
|
||||
uint64_t delivery_mode:3;
|
||||
uint64_t dest_mode:1;
|
||||
uint64_t delivery_status:1;
|
||||
uint64_t intr_polarity:1;
|
||||
uint64_t remote_irr:1;
|
||||
uint64_t trigger_mode:1;
|
||||
uint64_t intr_mask:1;
|
||||
uint64_t rsvd_1:39;
|
||||
uint64_t dest_field:8;
|
||||
} bits __packed;
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
@ -390,45 +426,4 @@ union ioapic_rte {
|
||||
#define IOAPIC_MAX_RTE_MASK 0x00ff0000U
|
||||
#define MAX_RTE_SHIFT 16U
|
||||
|
||||
/*
|
||||
* fields in the IO APIC's redirection table entries
|
||||
*/
|
||||
#define IOAPIC_RTE_DEST_SHIFT 56U
|
||||
/* broadcast addr: all APICs */
|
||||
#define IOAPIC_RTE_DEST_MASK 0xff00000000000000UL
|
||||
|
||||
#define IOAPIC_RTE_RESV 0x00fe0000UL /* reserved */
|
||||
|
||||
#define IOAPIC_RTE_INTMASK 0x00010000UL /* R/W: INTerrupt mask */
|
||||
#define IOAPIC_RTE_INTMCLR 0x00000000UL /* clear, allow INTs */
|
||||
#define IOAPIC_RTE_INTMSET 0x00010000UL /* set, inhibit INTs */
|
||||
|
||||
#define IOAPIC_RTE_TRGRMOD 0x00008000UL /* R/W: trigger mode */
|
||||
#define IOAPIC_RTE_TRGREDG 0x00000000UL /* edge */
|
||||
#define IOAPIC_RTE_TRGRLVL 0x00008000UL /* level */
|
||||
|
||||
#define IOAPIC_RTE_REM_IRR 0x00004000UL /* RO: remote IRR */
|
||||
|
||||
#define IOAPIC_RTE_INTPOL 0x00002000UL /*R/W:INT input pin polarity*/
|
||||
#define IOAPIC_RTE_INTAHI 0x00000000UL /* active high */
|
||||
#define IOAPIC_RTE_INTALO 0x00002000UL /* active low */
|
||||
|
||||
#define IOAPIC_RTE_DELIVS 0x00001000UL /* RO: delivery status */
|
||||
|
||||
#define IOAPIC_RTE_DESTMOD 0x00000800UL /*R/W:destination mode*/
|
||||
#define IOAPIC_RTE_DESTPHY 0x00000000UL /* physical */
|
||||
#define IOAPIC_RTE_DESTLOG 0x00000800UL /* logical */
|
||||
|
||||
#define IOAPIC_RTE_DELMOD 0x00000700UL /* R/W: delivery mode */
|
||||
#define IOAPIC_RTE_DELFIXED 0x00000000UL /* fixed */
|
||||
#define IOAPIC_RTE_DELLOPRI 0x00000100UL /* lowest priority */
|
||||
#define IOAPIC_RTE_DELSMI 0x00000200UL /*System Management INT*/
|
||||
#define IOAPIC_RTE_DELRSV1 0x00000300UL /* reserved */
|
||||
#define IOAPIC_RTE_DELNMI 0x00000400UL /* NMI signal */
|
||||
#define IOAPIC_RTE_DELINIT 0x00000500UL /* INIT signal */
|
||||
#define IOAPIC_RTE_DELRSV2 0x00000600UL /* reserved */
|
||||
#define IOAPIC_RTE_DELEXINT 0x00000700UL /* External INTerrupt */
|
||||
|
||||
#define IOAPIC_RTE_INTVEC 0x000000ffUL /*R/W: INT vector field*/
|
||||
|
||||
#endif /* APICREG_H */
|
||||
|
@ -48,9 +48,9 @@
|
||||
#define POSTED_INTR_NOTIFY_IRQ (NR_IRQS - 3U)
|
||||
#define PMI_IRQ (NR_IRQS - 4U)
|
||||
|
||||
#define DEFAULT_DEST_MODE IOAPIC_RTE_DESTLOG
|
||||
#define DEFAULT_DELIVERY_MODE IOAPIC_RTE_DELLOPRI
|
||||
#define ALL_CPUS_MASK ((1UL << (uint64_t)get_pcpu_nums()) - 1UL)
|
||||
#define DEFAULT_DEST_MODE IOAPIC_RTE_DESTMODE_LOGICAL
|
||||
#define DEFAULT_DELIVERY_MODE IOAPIC_RTE_DELMODE_LOPRI
|
||||
#define ALL_CPUS_MASK (uint32_t) (((uint32_t)1U << (uint32_t) get_pcpu_nums()) - (uint32_t)1U)
|
||||
|
||||
#define IRQ_ALLOC_BITMAP_SIZE INT_DIV_ROUNDUP(NR_IRQS, 64U)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user