diff --git a/hypervisor/arch/x86/assign.c b/hypervisor/arch/x86/assign.c index a168a8bfe..3d1206d2d 100644 --- a/hypervisor/arch/x86/assign.c +++ b/hypervisor/arch/x86/assign.c @@ -150,12 +150,12 @@ ptdev_update_irq_handler(struct vm *vm, struct ptdev_remapping_info *entry) if ((entry->type == PTDEV_INTR_INTX) && (entry->ptdev_intr_info.intx.vpin_src == PTDEV_VPIN_IOAPIC)) { - uint64_t rte; + union ioapic_rte rte; bool trigger_lvl = false; /* VPIN_IOAPIC src means we have vioapic enabled */ vioapic_get_rte(vm, entry->ptdev_intr_info.intx.virt_pin, &rte); - if ((rte & IOAPIC_RTE_TRGRMOD) == IOAPIC_RTE_TRGRLVL) { + if ((rte.full & IOAPIC_RTE_TRGRMOD) == IOAPIC_RTE_TRGRLVL) { trigger_lvl = true; } @@ -228,66 +228,65 @@ static void ptdev_build_physical_msi(struct vm *vm, struct ptdev_msi_info *info, info->pmsi_addr, info->pmsi_data); } -static uint64_t ptdev_build_physical_rte(struct vm *vm, +static union ioapic_rte +ptdev_build_physical_rte(struct vm *vm, struct ptdev_remapping_info *entry) { - uint64_t rte; + union ioapic_rte rte; uint32_t phys_irq = dev_to_irq(entry->node); uint32_t vector = dev_to_vector(entry->node); if (entry->ptdev_intr_info.intx.vpin_src == PTDEV_VPIN_IOAPIC) { - uint64_t vdmask, pdmask; - uint32_t dest, low, high, delmode; + uint64_t vdmask, pdmask, delmode; + uint32_t dest; + union ioapic_rte virt_rte; bool phys; - vioapic_get_rte(vm, entry->ptdev_intr_info.intx.virt_pin, &rte); - low = rte; - high = rte >> 32; + vioapic_get_rte(vm, entry->ptdev_intr_info.intx.virt_pin, + &virt_rte); + rte = virt_rte; /* physical destination cpu mask */ - phys = ((low & IOAPIC_RTE_DESTMOD) == IOAPIC_RTE_DESTPHY); - dest = high >> APIC_ID_SHIFT; + phys = ((virt_rte.full & IOAPIC_RTE_DESTMOD) == IOAPIC_RTE_DESTPHY); + dest = (uint32_t)(virt_rte.full >> IOAPIC_RTE_DEST_SHIFT); calcvdest(vm, &vdmask, dest, phys); pdmask = vcpumask2pcpumask(vm, vdmask); /* physical delivery mode */ - delmode = low & IOAPIC_RTE_DELMOD; + delmode = virt_rte.full & IOAPIC_RTE_DELMOD; if ((delmode != IOAPIC_RTE_DELFIXED) && (delmode != IOAPIC_RTE_DELLOPRI)) { delmode = IOAPIC_RTE_DELLOPRI; } /* update physical delivery mode, dest mode(logical) & vector */ - low &= ~(IOAPIC_RTE_DESTMOD | + rte.full &= ~(IOAPIC_RTE_DESTMOD | IOAPIC_RTE_DELMOD | IOAPIC_RTE_INTVEC); - low |= IOAPIC_RTE_DESTLOG | delmode | vector; + rte.full |= IOAPIC_RTE_DESTLOG | delmode | (uint64_t)vector; /* update physical dest field */ - high &= ~IOAPIC_RTE_DEST; - high |= pdmask << 24; + rte.full &= ~IOAPIC_RTE_DEST_MASK; + rte.full |= pdmask << IOAPIC_RTE_DEST_SHIFT; dev_dbg(ACRN_DBG_IRQ, "IOAPIC RTE = 0x%x:%x(V) -> 0x%x:%x(P)", - rte >> 32, (uint32_t)rte, high, low); - - rte = high; - rte = rte << 32 | low; + virt_rte.u.hi_32, virt_rte.u.lo_32, + rte.u.hi_32, rte.u.lo_32); } else { enum vpic_trigger trigger; - uint64_t physical_rte; + union ioapic_rte phys_rte; /* just update trigger mode */ - ioapic_get_rte(phys_irq, &physical_rte); - rte = physical_rte; - rte &= ~IOAPIC_RTE_TRGRMOD; + ioapic_get_rte(phys_irq, &phys_rte); + rte.full = phys_rte.full & (~IOAPIC_RTE_TRGRMOD); vpic_get_irq_trigger(vm, entry->ptdev_intr_info.intx.virt_pin, &trigger); if (trigger == LEVEL_TRIGGER) { - rte |= IOAPIC_RTE_TRGRLVL; + rte.full |= IOAPIC_RTE_TRGRLVL; } dev_dbg(ACRN_DBG_IRQ, "IOAPIC RTE = 0x%x:%x(P) -> 0x%x:%x(P)", - physical_rte >> 32, (uint32_t)physical_rte, - rte >> 32, (uint32_t)rte); + phys_rte.u.hi_32, phys_rte.u.lo_32, + rte.u.hi_32, rte.u.lo_32); } return rte; @@ -469,12 +468,13 @@ static void ptdev_intr_handle_irq(struct vm *vm, switch (entry->ptdev_intr_info.intx.vpin_src) { case PTDEV_VPIN_IOAPIC: { - uint64_t rte; + union ioapic_rte rte; bool trigger_lvl = false; /* VPIN_IOAPIC src means we have vioapic enabled */ - vioapic_get_rte(vm, entry->ptdev_intr_info.intx.virt_pin, &rte); - if ((rte & IOAPIC_RTE_TRGRMOD) == IOAPIC_RTE_TRGRLVL) { + vioapic_get_rte(vm, entry->ptdev_intr_info.intx.virt_pin, + &rte); + if ((rte.full & IOAPIC_RTE_TRGRMOD) == IOAPIC_RTE_TRGRLVL) { trigger_lvl = true; } @@ -487,9 +487,10 @@ static void ptdev_intr_handle_irq(struct vm *vm, } dev_dbg(ACRN_DBG_PTIRQ, - "dev-assign: irq=0x%x assert vr: 0x%x vRTE=0x%x", + "dev-assign: irq=0x%x assert vr: 0x%x vRTE=0x%lx", dev_to_irq(entry->node), - irq_to_vector(dev_to_irq(entry->node)), rte); + irq_to_vector(dev_to_irq(entry->node)), + rte.full); break; } case PTDEV_VPIN_PIC: @@ -669,14 +670,10 @@ static bool vpin_masked(struct vm *vm, uint8_t virt_pin, enum ptdev_vpin_source vpin_src) { if (vpin_src == PTDEV_VPIN_IOAPIC) { - uint64_t rte; + union ioapic_rte rte; vioapic_get_rte(vm, virt_pin, &rte); - if ((rte & IOAPIC_RTE_INTMASK) == IOAPIC_RTE_INTMSET) { - return true; - } else { - return false; - } + return ((rte.full & IOAPIC_RTE_INTMASK) == IOAPIC_RTE_INTMSET); } else { return vpic_is_pin_mask(vm->vpic, virt_pin); } @@ -685,7 +682,7 @@ static bool vpin_masked(struct vm *vm, uint8_t virt_pin, static void activate_physical_ioapic(struct vm *vm, struct ptdev_remapping_info *entry) { - uint64_t rte; + union ioapic_rte rte; uint32_t phys_irq = dev_to_irq(entry->node); /* disable interrupt */ @@ -695,7 +692,8 @@ static void activate_physical_ioapic(struct vm *vm, rte = ptdev_build_physical_rte(vm, entry); /* set rte entry */ - GSI_SET_RTE(phys_irq, rte | IOAPIC_RTE_INTMSET); + rte.full |= IOAPIC_RTE_INTMSET; + ioapic_set_rte(phys_irq, rte); /* update irq handler according to info in guest */ ptdev_update_irq_handler(vm, entry); @@ -710,7 +708,7 @@ static void activate_physical_ioapic(struct vm *vm, int ptdev_intx_pin_remap(struct vm *vm, struct ptdev_intx_info *info) { struct ptdev_remapping_info *entry; - uint64_t rte; + union ioapic_rte rte; uint32_t phys_irq; uint8_t phys_pin; bool lowpri = !is_vm0(vm); @@ -824,7 +822,7 @@ int ptdev_intx_pin_remap(struct vm *vm, struct ptdev_intx_info *info) && (entry->ptdev_intr_info.intx.vpin_src == PTDEV_VPIN_IOAPIC)) { vioapic_get_rte(vm, entry->ptdev_intr_info.intx.virt_pin, &rte); - if (((uint32_t)rte) == 0x10000) { + if (rte.u.lo_32 == 0x10000U) { /* disable interrupt */ GSI_MASK_IRQ(phys_irq); ptdev_deactivate_entry(entry); @@ -957,7 +955,7 @@ static void get_entry_info(struct ptdev_remapping_info *entry, char *type, } else { uint32_t phys_irq = pin_to_irq( entry->ptdev_intr_info.intx.phys_pin); - uint64_t rte = 0; + union ioapic_rte rte; if (entry->ptdev_intr_info.intx.vpin_src == PTDEV_VPIN_IOAPIC) { @@ -966,8 +964,8 @@ static void get_entry_info(struct ptdev_remapping_info *entry, char *type, (void)strcpy_s(type, 16, "PIC"); } ioapic_get_rte(phys_irq, &rte); - *dest = ((rte >> 32) & IOAPIC_RTE_DEST) >> 24; - if ((rte & IOAPIC_RTE_TRGRLVL) != 0U) { + *dest = rte.full >> IOAPIC_RTE_DEST_SHIFT; + if ((rte.full & IOAPIC_RTE_TRGRLVL) != 0UL) { *lvl_tm = true; } else { *lvl_tm = false; diff --git a/hypervisor/arch/x86/guest/vioapic.c b/hypervisor/arch/x86/guest/vioapic.c index b88084fd7..474d43149 100644 --- a/hypervisor/arch/x86/guest/vioapic.c +++ b/hypervisor/arch/x86/guest/vioapic.c @@ -37,7 +37,8 @@ #define IOEOI 0x40 #define REDIR_ENTRIES_HW 120U /* SOS align with native ioapic */ -#define RTBL_RO_BITS ((uint64_t)(IOAPIC_RTE_REM_IRR | IOAPIC_RTE_DELIVS)) +#define RTBL_RO_BITS (uint32_t)(IOAPIC_RTE_REM_IRR | IOAPIC_RTE_DELIVS) +#define NEED_TMR_UPDATE (~(IOAPIC_RTE_INTMASK | IOAPIC_RTE_INTPOL)) #define ACRN_DBG_IOAPIC 6 @@ -46,16 +47,16 @@ struct vioapic { spinlock_t mtx; uint32_t id; uint32_t ioregsel; - struct { - uint64_t reg; - int acnt; /* sum of pin asserts (+1) and deasserts (-1) */ - } rtbl[REDIR_ENTRIES_HW]; + union ioapic_rte rtbl[REDIR_ENTRIES_HW]; + /* sum of pin asserts (+1) and deasserts (-1) */ + int32_t acnt[REDIR_ENTRIES_HW]; }; #define VIOAPIC_LOCK(vioapic) spinlock_obtain(&((vioapic)->mtx)) #define VIOAPIC_UNLOCK(vioapic) spinlock_release(&((vioapic)->mtx)) #define MASK_ALL_INTERRUPTS 0x0001000000010000UL +#define IOAPIC_RTE_LOW_INTVEC ((uint32_t)IOAPIC_RTE_INTVEC) static inline const char *pinstate_str(bool asserted) { @@ -71,8 +72,8 @@ vm_ioapic(struct vm *vm) static void vioapic_send_intr(struct vioapic *vioapic, uint8_t pin) { - int delmode; - uint32_t vector, low, high, dest; + uint32_t vector, dest, delmode; + union ioapic_rte rte; bool level, phys; uint8_t pincount = vioapic_pincount(vioapic->vm); @@ -80,23 +81,22 @@ vioapic_send_intr(struct vioapic *vioapic, uint8_t pin) pr_err("vioapic_send_intr: invalid pin number %hhu", pin); } - low = vioapic->rtbl[pin].reg; - high = vioapic->rtbl[pin].reg >> 32; + rte = vioapic->rtbl[pin]; - if ((low & IOAPIC_RTE_INTMASK) == IOAPIC_RTE_INTMSET) { + if ((rte.full & IOAPIC_RTE_INTMASK) == IOAPIC_RTE_INTMSET) { dev_dbg(ACRN_DBG_IOAPIC, "ioapic pin%hhu: masked", pin); return; } - phys = ((low & IOAPIC_RTE_DESTMOD) == IOAPIC_RTE_DESTPHY); - delmode = low & IOAPIC_RTE_DELMOD; - level = (low & IOAPIC_RTE_TRGRLVL) != 0U ? true : false; + phys = ((rte.full & IOAPIC_RTE_DESTMOD) == IOAPIC_RTE_DESTPHY); + delmode = (uint32_t)(rte.full & IOAPIC_RTE_DELMOD); + level = ((rte.full & IOAPIC_RTE_TRGRLVL) != 0UL); if (level) { - vioapic->rtbl[pin].reg |= IOAPIC_RTE_REM_IRR; + vioapic->rtbl[pin].full |= IOAPIC_RTE_REM_IRR; } - vector = low & IOAPIC_RTE_INTVEC; - dest = high >> APIC_ID_SHIFT; + vector = rte.u.lo_32 & IOAPIC_RTE_LOW_INTVEC; + dest = (uint32_t)(rte.full >> IOAPIC_RTE_DEST_SHIFT); vlapic_deliver_intr(vioapic->vm, level, dest, phys, delmode, vector); } @@ -111,13 +111,13 @@ vioapic_set_pinstate(struct vioapic *vioapic, uint8_t pin, bool newstate) pr_err("vioapic_set_pinstate: invalid pin number %hhu", pin); } - oldcnt = vioapic->rtbl[pin].acnt; + oldcnt = vioapic->acnt[pin]; if (newstate) { - vioapic->rtbl[pin].acnt++; + vioapic->acnt[pin]++; } else { - vioapic->rtbl[pin].acnt--; + vioapic->acnt[pin]--; } - newcnt = vioapic->rtbl[pin].acnt; + newcnt = vioapic->acnt[pin]; if (newcnt < 0) { pr_err("ioapic pin%hhu: bad acnt %d", pin, newcnt); @@ -204,8 +204,8 @@ vioapic_update_tmr(struct vcpu *vcpu) { struct vioapic *vioapic; struct vlapic *vlapic; - uint32_t low, vector; - int delmode; + union ioapic_rte rte; + uint32_t vector, delmode; bool level; uint8_t pin, pincount; @@ -215,9 +215,9 @@ vioapic_update_tmr(struct vcpu *vcpu) VIOAPIC_LOCK(vioapic); pincount = vioapic_pincount(vcpu->vm); for (pin = 0U; pin < pincount; pin++) { - low = vioapic->rtbl[pin].reg; + rte = vioapic->rtbl[pin]; - level = (low & IOAPIC_RTE_TRGRLVL) != 0U ? true : false; + level = ((rte.full & IOAPIC_RTE_TRGRLVL) != 0UL); /* * For a level-triggered 'pin' let the vlapic figure out if @@ -225,8 +225,8 @@ vioapic_update_tmr(struct vcpu *vcpu) * being delivered to it. If yes, then it will modify the * TMR bit associated with this vector to level-triggered. */ - delmode = low & IOAPIC_RTE_DELMOD; - vector = low & IOAPIC_RTE_INTVEC; + delmode = (uint32_t)(rte.full & IOAPIC_RTE_DELMOD); + vector = rte.u.lo_32 & IOAPIC_RTE_LOW_INTVEC; vlapic_set_tmr_one_vec(vlapic, delmode, vector, level); } vlapic_apicv_batch_set_tmr(vlapic); @@ -236,7 +236,7 @@ vioapic_update_tmr(struct vcpu *vcpu) static uint32_t vioapic_read(struct vioapic *vioapic, uint32_t addr) { - uint32_t regnum, rshift; + uint32_t regnum; uint8_t pin, pincount = vioapic_pincount(vioapic->vm); regnum = addr & 0xffU; @@ -258,12 +258,10 @@ vioapic_read(struct vioapic *vioapic, uint32_t addr) uint32_t rte_offset = addr_offset / 2U; pin = (uint8_t)rte_offset; if ((addr_offset % 2U) != 0U) { - rshift = 32U; + return vioapic->rtbl[pin].u.hi_32; } else { - rshift = 0U; + return vioapic->rtbl[pin].u.lo_32; } - - return vioapic->rtbl[pin].reg >> rshift; } return 0; @@ -277,6 +275,7 @@ static void vioapic_write_eoi(struct vioapic *vioapic, uint32_t vector) { struct vm *vm = vioapic->vm; + union ioapic_rte rte; uint8_t pin, pincount; if (vector < VECTOR_FOR_INTR_START || vector > NR_MAX_VECTOR) { @@ -286,19 +285,20 @@ vioapic_write_eoi(struct vioapic *vioapic, uint32_t vector) VIOAPIC_LOCK(vioapic); pincount = vioapic_pincount(vm); for (pin = 0U; pin < pincount; pin++) { - if ((vioapic->rtbl[pin].reg & IOAPIC_RTE_REM_IRR) == 0) { + rte = vioapic->rtbl[pin]; + + if ((rte.full & IOAPIC_RTE_REM_IRR) == 0UL) { continue; } - if ((vioapic->rtbl[pin].reg & IOAPIC_RTE_INTVEC) != - (uint64_t)vector) { + if ((rte.u.lo_32 & IOAPIC_RTE_LOW_INTVEC) != vector) { continue; } - vioapic->rtbl[pin].reg &= ~IOAPIC_RTE_REM_IRR; - if (vioapic->rtbl[pin].acnt > 0) { + vioapic->rtbl[pin].full &= ~IOAPIC_RTE_REM_IRR; + if (vioapic->acnt[pin] > 0) { dev_dbg(ACRN_DBG_IOAPIC, "ioapic pin%hhu: asserted at eoi, acnt %d", - pin, vioapic->rtbl[pin].acnt); + pin, vioapic->acnt[pin]); vioapic_send_intr(vioapic, pin); } } @@ -308,9 +308,9 @@ vioapic_write_eoi(struct vioapic *vioapic, uint32_t vector) static void vioapic_write(struct vioapic *vioapic, uint32_t addr, uint32_t data) { - uint64_t data64, mask64; - uint64_t last, new, changed; - uint32_t regnum, lshift; + union ioapic_rte last, new; + uint64_t changed; + uint32_t regnum; uint8_t pin, pincount = vioapic_pincount(vioapic->vm); regnum = addr & 0xffUL; @@ -332,25 +332,22 @@ vioapic_write(struct vioapic *vioapic, uint32_t addr, uint32_t data) uint32_t addr_offset = regnum - IOAPIC_REDTBL; uint32_t rte_offset = addr_offset / 2U; pin = (uint8_t)rte_offset; + + last = vioapic->rtbl[pin]; + new = last; if ((addr_offset % 2U) != 0U) { - lshift = 32; + new.u.hi_32 = data; } else { - lshift = 0; + new.u.lo_32 &= RTBL_RO_BITS; + new.u.lo_32 |= (data & ~RTBL_RO_BITS); } - last = vioapic->rtbl[pin].reg; - - data64 = (uint64_t)data << lshift; - mask64 = 0xffffffffUL << lshift; - new = last & (~mask64 | RTBL_RO_BITS); - new |= data64 & ~RTBL_RO_BITS; - - changed = last ^ new; + changed = last.full ^ new.full; /* pin0 from vpic mask/unmask */ - if (pin == 0U && (changed & IOAPIC_RTE_INTMASK) != 0U) { + if (pin == 0U && (changed & IOAPIC_RTE_INTMASK) != 0UL) { /* mask -> umask */ - if ((last & IOAPIC_RTE_INTMASK) != 0U && - ((new & IOAPIC_RTE_INTMASK) == 0)) { + if ((last.full & IOAPIC_RTE_INTMASK) != 0UL && + ((new.full & IOAPIC_RTE_INTMASK) == 0UL)) { if ((vioapic->vm->vpic_wire_mode == VPIC_WIRE_NULL) || (vioapic->vm->vpic_wire_mode == @@ -364,8 +361,8 @@ vioapic_write(struct vioapic *vioapic, uint32_t addr, uint32_t data) return; } /* unmask -> mask */ - } else if (((last & IOAPIC_RTE_INTMASK) == 0) && - (new & IOAPIC_RTE_INTMASK) != 0U) { + } else if (((last.full & IOAPIC_RTE_INTMASK) == 0UL) && + (new.full & IOAPIC_RTE_INTMASK) != 0UL) { if (vioapic->vm->vpic_wire_mode == VPIC_WIRE_IOAPIC) { vioapic->vm->vpic_wire_mode = @@ -375,15 +372,15 @@ vioapic_write(struct vioapic *vioapic, uint32_t addr, uint32_t data) } } } - vioapic->rtbl[pin].reg = new; + vioapic->rtbl[pin] = new; dev_dbg(ACRN_DBG_IOAPIC, "ioapic pin%hhu: redir table entry %#lx", - pin, vioapic->rtbl[pin].reg); + pin, vioapic->rtbl[pin].full); /* * If any fields in the redirection table entry (except mask * or polarity) have changed then rendezvous all the vcpus * to update their vlapic trigger-mode registers. */ - if ((changed & ~(IOAPIC_RTE_INTMASK | IOAPIC_RTE_INTPOL)) != 0U) { + if ((changed & NEED_TMR_UPDATE) != 0UL) { uint16_t i; struct vcpu *vcpu; @@ -405,13 +402,13 @@ vioapic_write(struct vioapic *vioapic, uint32_t addr, uint32_t data) * - previous interrupt has been EOIed * - pin level is asserted */ - if ((vioapic->rtbl[pin].reg & IOAPIC_RTE_INTMASK) == + if ((vioapic->rtbl[pin].full & IOAPIC_RTE_INTMASK) == IOAPIC_RTE_INTMCLR && - (vioapic->rtbl[pin].reg & IOAPIC_RTE_REM_IRR) == 0 && - (vioapic->rtbl[pin].acnt > 0)) { + (vioapic->rtbl[pin].full & IOAPIC_RTE_REM_IRR) == 0UL && + (vioapic->acnt[pin] > 0)) { dev_dbg(ACRN_DBG_IOAPIC, "ioapic pin%hhu: asserted at rtbl write, acnt %d", - pin, vioapic->rtbl[pin].acnt); + pin, vioapic->acnt[pin]); vioapic_send_intr(vioapic, pin); } @@ -509,6 +506,7 @@ vioapic_process_eoi(struct vm *vm, uint32_t vector) { struct vioapic *vioapic; uint8_t pin, pincount = vioapic_pincount(vm); + union ioapic_rte rte; if (vector < VECTOR_FOR_INTR_START || vector > NR_MAX_VECTOR) { pr_err("vioapic_process_eoi: invalid vector %u", vector); @@ -519,11 +517,11 @@ vioapic_process_eoi(struct vm *vm, uint32_t vector) /* notify device to ack if assigned pin */ for (pin = 0U; pin < pincount; pin++) { - if ((vioapic->rtbl[pin].reg & IOAPIC_RTE_REM_IRR) == 0) { + rte = vioapic->rtbl[pin]; + if ((rte.full & IOAPIC_RTE_REM_IRR) == 0UL) { continue; } - if ((vioapic->rtbl[pin].reg & IOAPIC_RTE_INTVEC) != - (uint64_t)vector) { + if ((rte.u.lo_32 & IOAPIC_RTE_LOW_INTVEC) != vector) { continue; } ptdev_intx_ack(vm, pin, PTDEV_VPIN_IOAPIC); @@ -535,19 +533,19 @@ vioapic_process_eoi(struct vm *vm, uint32_t vector) */ VIOAPIC_LOCK(vioapic); for (pin = 0U; pin < pincount; pin++) { - if ((vioapic->rtbl[pin].reg & IOAPIC_RTE_REM_IRR) == 0) { + rte = vioapic->rtbl[pin]; + if ((rte.full & IOAPIC_RTE_REM_IRR) == 0UL) { continue; } - if ((vioapic->rtbl[pin].reg & IOAPIC_RTE_INTVEC) != - (uint64_t)vector) { + if ((rte.u.lo_32 & IOAPIC_RTE_LOW_INTVEC) != vector) { continue; } - vioapic->rtbl[pin].reg &= ~IOAPIC_RTE_REM_IRR; - if (vioapic->rtbl[pin].acnt > 0) { + vioapic->rtbl[pin].full &= (~IOAPIC_RTE_REM_IRR); + if (vioapic->acnt[pin] > 0) { dev_dbg(ACRN_DBG_IOAPIC, "ioapic pin%hhu: asserted at eoi, acnt %d", - pin, vioapic->rtbl[pin].acnt); + pin, vioapic->acnt[pin]); vioapic_send_intr(vioapic, pin); } } @@ -562,7 +560,7 @@ vioapic_reset(struct vioapic *vioapic) /* Initialize all redirection entries to mask all interrupts */ pincount = vioapic_pincount(vioapic->vm); for (pin = 0U; pin < pincount; pin++) { - vioapic->rtbl[pin].reg = MASK_ALL_INTERRUPTS; + vioapic->rtbl[pin].full = MASK_ALL_INTERRUPTS; } } @@ -637,13 +635,13 @@ int vioapic_mmio_access_handler(struct vcpu *vcpu, struct mem_io *mmio, return ret; } -bool vioapic_get_rte(struct vm *vm, uint8_t pin, void *rte) +bool vioapic_get_rte(struct vm *vm, uint8_t pin, union ioapic_rte *rte) { struct vioapic *vioapic; vioapic = vm_ioapic(vm); if ((vioapic != NULL) && (rte != NULL)) { - *(uint64_t *)rte = vioapic->rtbl[pin].reg; + *rte = vioapic->rtbl[pin]; return true; } else { return false; @@ -653,9 +651,9 @@ bool vioapic_get_rte(struct vm *vm, uint8_t pin, void *rte) #ifdef HV_DEBUG void get_vioapic_info(char *str, int str_max, uint16_t vmid) { - int len, size = str_max, delmode; - uint64_t rte; - uint32_t low, high, vector, dest; + int len, size = str_max; + union ioapic_rte rte; + uint32_t delmode, vector, dest; bool level, phys, remote_irr, mask; struct vm *vm = get_vm_from_vmid(vmid); uint8_t pin, pincount; @@ -674,24 +672,22 @@ void get_vioapic_info(char *str, int str_max, uint16_t vmid) str += len; pincount = vioapic_pincount(vm); - rte = 0UL; + rte.full = 0UL; for (pin = 0U; pin < pincount; pin++) { - vioapic_get_rte(vm, pin, (void *)&rte); - low = rte; - high = rte >> 32; - mask = ((low & IOAPIC_RTE_INTMASK) == IOAPIC_RTE_INTMSET); - remote_irr = ((low & IOAPIC_RTE_REM_IRR) == IOAPIC_RTE_REM_IRR); - phys = ((low & IOAPIC_RTE_DESTMOD) == IOAPIC_RTE_DESTPHY); - delmode = low & IOAPIC_RTE_DELMOD; - level = ((low & IOAPIC_RTE_TRGRLVL) != 0U) ? true : false; - vector = low & IOAPIC_RTE_INTVEC; - dest = high >> APIC_ID_SHIFT; + 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); len = snprintf(str, size, - "\r\n%hhu\t0x%X\t%s\t0x%X\t%s\t%d\t%d\t%d", + "\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", - delmode >> 8, remote_irr, mask); + delmode >> 8U, remote_irr, mask); size -= len; str += len; } diff --git a/hypervisor/arch/x86/ioapic.c b/hypervisor/arch/x86/ioapic.c index a758b458b..a525641b7 100644 --- a/hypervisor/arch/x86/ioapic.c +++ b/hypervisor/arch/x86/ioapic.c @@ -10,15 +10,9 @@ #define IOAPIC_REGSEL_OFFSET 0 #define IOAPIC_WINSWL_OFFSET 0x10 -#define IOAPIC_MAX_PIN 240U +#define IOAPIC_MAX_PIN 240U #define IOAPIC_INVALID_PIN 0xffU -/* IOAPIC Redirection Table (RTE) Entry structure */ -struct ioapic_rte { - uint32_t lo_32; - uint32_t hi_32; -} ioapic_rte; - struct gsi_table { uint8_t ioapic_id; uint8_t pin; @@ -28,7 +22,7 @@ static struct gsi_table gsi_table[NR_MAX_GSI]; static uint32_t nr_gsi; static spinlock_t ioapic_lock; -static struct ioapic_rte saved_rte[CONFIG_NR_IOAPICS][IOAPIC_MAX_PIN]; +static union ioapic_rte saved_rte[CONFIG_NR_IOAPICS][IOAPIC_MAX_PIN]; /* * the irq to ioapic pin mapping should extract from ACPI MADT table @@ -53,7 +47,7 @@ uint8_t legacy_irq_to_pin[NR_LEGACY_IRQ] = { 15U, /* IRQ15*/ }; -uint32_t legacy_irq_trigger_mode[NR_LEGACY_IRQ] = { +uint64_t legacy_irq_trigger_mode[NR_LEGACY_IRQ] = { IOAPIC_RTE_TRGREDG, /* IRQ0*/ IOAPIC_RTE_TRGREDG, /* IRQ1*/ IOAPIC_RTE_TRGREDG, /* IRQ2*/ @@ -154,69 +148,68 @@ get_ioapic_base(uint8_t apic_id) static inline void ioapic_get_rte_entry(void *ioapic_addr, - uint8_t pin, struct ioapic_rte *rte) + uint8_t pin, union ioapic_rte *rte) { uint32_t rte_addr = (uint32_t)pin * 2U + 0x10U; - rte->lo_32 = ioapic_read_reg32(ioapic_addr, rte_addr); - rte->hi_32 = ioapic_read_reg32(ioapic_addr, rte_addr + 1U); + rte->u.lo_32 = ioapic_read_reg32(ioapic_addr, rte_addr); + rte->u.hi_32 = ioapic_read_reg32(ioapic_addr, rte_addr + 1U); } static inline void ioapic_set_rte_entry(void *ioapic_addr, - uint8_t pin, struct ioapic_rte *rte) + uint8_t pin, union ioapic_rte rte) { uint32_t rte_addr = (uint32_t)pin * 2U + 0x10U; - ioapic_write_reg32(ioapic_addr, rte_addr, rte->lo_32); - ioapic_write_reg32(ioapic_addr, rte_addr + 1U, rte->hi_32); + ioapic_write_reg32(ioapic_addr, rte_addr, rte.u.lo_32); + ioapic_write_reg32(ioapic_addr, rte_addr + 1U, rte.u.hi_32); } -static inline struct ioapic_rte +static inline union ioapic_rte create_rte_for_legacy_irq(uint32_t irq, uint32_t vr) { - struct ioapic_rte rte = {0U, 0U}; + union ioapic_rte rte; /* Legacy IRQ 0-15 setup, default masked * are actually defined in either MPTable or ACPI MADT table * before we have ACPI table parsing in HV we use common hardcode */ - rte.lo_32 |= IOAPIC_RTE_INTMSET; - - rte.lo_32 |= legacy_irq_trigger_mode[irq]; - rte.lo_32 |= DEFAULT_DEST_MODE; - rte.lo_32 |= DEFAULT_DELIVERY_MODE; - rte.lo_32 |= (IOAPIC_RTE_INTVEC & vr); + 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); /* FIXME: Fixed to active Low? */ - rte.lo_32 |= IOAPIC_RTE_INTALO; + rte.full |= IOAPIC_RTE_INTALO; /* Dest field: legacy irq fixed to CPU0 */ - rte.hi_32 |= 1U << 24; + rte.full |= (1UL << IOAPIC_RTE_DEST_SHIFT); return rte; } -static inline struct ioapic_rte +static inline union ioapic_rte create_rte_for_gsi_irq(uint32_t irq, uint32_t vr) { - struct ioapic_rte rte = {0, 0}; + union ioapic_rte rte; if (irq < NR_LEGACY_IRQ) { return create_rte_for_legacy_irq(irq, vr); } /* irq default masked, level trig */ - rte.lo_32 |= IOAPIC_RTE_INTMSET; - rte.lo_32 |= IOAPIC_RTE_TRGRLVL; - rte.lo_32 |= DEFAULT_DEST_MODE; - rte.lo_32 |= DEFAULT_DELIVERY_MODE; - rte.lo_32 |= (IOAPIC_RTE_INTVEC & vr); + 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); /* FIXME: Fixed to active Low? */ - rte.lo_32 |= IOAPIC_RTE_INTALO; + rte.full |= IOAPIC_RTE_INTALO; /* Dest field */ - rte.hi_32 |= ALL_CPUS_MASK << 24U; + rte.full |= ((uint64_t)ALL_CPUS_MASK << IOAPIC_RTE_DEST_SHIFT); return rte; } @@ -224,56 +217,52 @@ create_rte_for_gsi_irq(uint32_t irq, uint32_t vr) static void ioapic_set_routing(uint32_t gsi, uint32_t vr) { void *addr; - struct ioapic_rte rte; + union ioapic_rte rte; addr = gsi_table[gsi].addr; rte = create_rte_for_gsi_irq(gsi, vr); - ioapic_set_rte_entry(addr, gsi_table[gsi].pin, &rte); + ioapic_set_rte_entry(addr, gsi_table[gsi].pin, rte); - if ((rte.lo_32 & IOAPIC_RTE_TRGRMOD) != 0U) { + if ((rte.full & IOAPIC_RTE_TRGRMOD) != 0UL) { update_irq_handler(gsi, handle_level_interrupt_common); } else { update_irq_handler(gsi, common_handler_edge); } - dev_dbg(ACRN_DBG_IRQ, "GSI: irq:%d pin:%hhu rte:%x", + dev_dbg(ACRN_DBG_IRQ, "GSI: irq:%d pin:%hhu rte:%lx", gsi, gsi_table[gsi].pin, - rte.lo_32); + rte.full); } -void ioapic_get_rte(uint32_t irq, uint64_t *rte) +/** + * @pre rte != NULL + */ +void ioapic_get_rte(uint32_t irq, union ioapic_rte *rte) { void *addr; - struct ioapic_rte _rte; if (!irq_is_gsi(irq)) { return; } addr = gsi_table[irq].addr; - ioapic_get_rte_entry(addr, gsi_table[irq].pin, &_rte); - - *rte = _rte.hi_32; - *rte = *rte << 32 | _rte.lo_32; + ioapic_get_rte_entry(addr, gsi_table[irq].pin, rte); } -void ioapic_set_rte(uint32_t irq, uint64_t raw_rte) +void ioapic_set_rte(uint32_t irq, union ioapic_rte rte) { void *addr; - struct ioapic_rte rte; if (!irq_is_gsi(irq)) { return; } addr = gsi_table[irq].addr; - rte.lo_32 = (uint32_t)raw_rte; - rte.hi_32 = (uint32_t)(raw_rte >> 32); - ioapic_set_rte_entry(addr, gsi_table[irq].pin, &rte); + ioapic_set_rte_entry(addr, gsi_table[irq].pin, rte); - dev_dbg(ACRN_DBG_IRQ, "GSI: irq:%d pin:%hhu rte:%x", + dev_dbg(ACRN_DBG_IRQ, "GSI: irq:%d pin:%hhu rte:%lx", irq, gsi_table[irq].pin, - rte.lo_32); + rte.full); } uint32_t irq_gsi_num(void) @@ -312,7 +301,7 @@ irq_gsi_mask_unmask(uint32_t irq, bool mask) { void *addr = gsi_table[irq].addr; uint8_t pin = gsi_table[irq].pin; - struct ioapic_rte rte; + union ioapic_rte rte; if (!irq_is_gsi(irq)) { return; @@ -320,13 +309,13 @@ irq_gsi_mask_unmask(uint32_t irq, bool mask) ioapic_get_rte_entry(addr, pin, &rte); if (mask) { - rte.lo_32 |= IOAPIC_RTE_INTMSET; + rte.full |= IOAPIC_RTE_INTMSET; } else { - rte.lo_32 &= ~IOAPIC_RTE_INTMASK; + rte.full &= ~IOAPIC_RTE_INTMASK; } - ioapic_set_rte_entry(addr, pin, &rte); - dev_dbg(ACRN_DBG_PTIRQ, "update: irq:%d pin:%hhu rte:%x", - irq, pin, rte.lo_32); + ioapic_set_rte_entry(addr, pin, rte); + dev_dbg(ACRN_DBG_PTIRQ, "update: irq:%d pin:%hhu rte:%lx", + irq, pin, rte.full); } static uint8_t @@ -414,11 +403,11 @@ static void dump_ioapic(void) for (irq = 0U; irq < nr_gsi; irq++) { void *addr = gsi_table[irq].addr; uint8_t pin = gsi_table[irq].pin; - struct ioapic_rte rte; + union ioapic_rte rte; ioapic_get_rte_entry(addr, pin, &rte); - dev_dbg(ACRN_DBG_IRQ, "DUMP: irq:%d pin:%hhu rte:%x", - irq, pin, rte.lo_32); + dev_dbg(ACRN_DBG_IRQ, "DUMP: irq:%d pin:%hhu rte:%lx", + irq, pin, rte.full); } } @@ -451,22 +440,22 @@ void resume_ioapic(void) nr_pins = ioapic_nr_pins(addr); for (ioapic_pin = 0U; ioapic_pin < nr_pins; ioapic_pin++) { ioapic_set_rte_entry(addr, ioapic_pin, - &saved_rte[ioapic_id][ioapic_pin]); + saved_rte[ioapic_id][ioapic_pin]); } } } #ifdef HV_DEBUG -static void get_rte_info(struct ioapic_rte *rte, bool *mask, bool *irr, +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->lo_32 & IOAPIC_RTE_INTMASK) == IOAPIC_RTE_INTMSET); - *irr = ((rte->lo_32 & IOAPIC_RTE_REM_IRR) == IOAPIC_RTE_REM_IRR); - *phys = ((rte->lo_32 & IOAPIC_RTE_DESTMOD) == IOAPIC_RTE_DESTPHY); - *delmode = rte->lo_32 & IOAPIC_RTE_DELMOD; - *level = ((rte->lo_32 & IOAPIC_RTE_TRGRLVL) != 0U) ? true : false; - *vector = rte->lo_32 & IOAPIC_RTE_INTVEC; - *dest = rte->hi_32 >> APIC_ID_SHIFT; + *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 = rte.full & IOAPIC_RTE_DELMOD; + *level = ((rte.full & IOAPIC_RTE_TRGRLVL) != 0UL); + *vector = rte.full & IOAPIC_RTE_INTVEC; + *dest = (uint32_t)(rte.full >> APIC_ID_SHIFT); } int get_ioapic_info(char *str, int str_max_len) @@ -482,18 +471,18 @@ int get_ioapic_info(char *str, int str_max_len) for (irq = 0U; irq < nr_gsi; irq++) { void *addr = gsi_table[irq].addr; uint8_t pin = gsi_table[irq].pin; - struct ioapic_rte rte; + union ioapic_rte rte; bool irr, phys, level, mask; uint32_t delmode, vector, dest; ioapic_get_rte_entry(addr, pin, &rte); - get_rte_info(&rte, &mask, &irr, &phys, &delmode, &level, + 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.hi_32, rte.lo_32); + irq, pin, rte.u.hi_32, rte.u.lo_32); size -= len; str += len; diff --git a/hypervisor/include/arch/x86/apicreg.h b/hypervisor/include/arch/x86/apicreg.h index fdf35dd57..69e4915d9 100644 --- a/hypervisor/include/arch/x86/apicreg.h +++ b/hypervisor/include/arch/x86/apicreg.h @@ -253,6 +253,15 @@ struct ioapic { uint32_t iowin; PAD3; }; +/* IOAPIC Redirection Table (RTE) Entry structure */ +union ioapic_rte { + uint64_t full; + struct { + uint32_t lo_32; + uint32_t hi_32; + } u; +}; + #undef PAD4 #undef PAD3 @@ -480,7 +489,9 @@ struct ioapic { /* * fields in the IO APIC's redirection table entries */ -#define IOAPIC_RTE_DEST APIC_ID_MASK /* broadcast addr: all APICs */ +#define IOAPIC_RTE_DEST_SHIFT 56U +/* broadcast addr: all APICs */ +#define IOAPIC_RTE_DEST_MASK 0xff00000000000000UL #define IOAPIC_RTE_RESV 0x00fe0000UL /* reserved */ diff --git a/hypervisor/include/arch/x86/guest/vioapic.h b/hypervisor/include/arch/x86/guest/vioapic.h index 53556cad9..b8c568f0d 100644 --- a/hypervisor/include/arch/x86/guest/vioapic.h +++ b/hypervisor/include/arch/x86/guest/vioapic.h @@ -31,6 +31,9 @@ #ifndef _VIOAPIC_H_ #define _VIOAPIC_H_ +#include +#include + #define VIOAPIC_BASE 0xFEC00000UL #define VIOAPIC_SIZE 4096UL @@ -50,7 +53,7 @@ int vioapic_mmio_read(void *vm, uint64_t gpa, uint8_t vioapic_pincount(struct vm *vm); void vioapic_process_eoi(struct vm *vm, uint32_t vector); -bool vioapic_get_rte(struct vm *vm, uint8_t pin, void *rte); +bool vioapic_get_rte(struct vm *vm, uint8_t pin, union ioapic_rte *rte); int vioapic_mmio_access_handler(struct vcpu *vcpu, struct mem_io *mmio, void *handler_private_data); diff --git a/hypervisor/include/arch/x86/ioapic.h b/hypervisor/include/arch/x86/ioapic.h index 0bebdd31d..feef8e005 100644 --- a/hypervisor/include/arch/x86/ioapic.h +++ b/hypervisor/include/arch/x86/ioapic.h @@ -17,7 +17,6 @@ #define GSI_MASK_IRQ(irq) irq_gsi_mask_unmask((irq), true) #define GSI_UNMASK_IRQ(irq) irq_gsi_mask_unmask((irq), false) -#define GSI_SET_RTE(irq, rte) ioapic_set_rte((irq), (rte)) void setup_ioapic_irq(void); @@ -26,8 +25,8 @@ uint32_t irq_gsi_num(void); uint8_t irq_to_pin(uint32_t irq); uint32_t pin_to_irq(uint8_t pin); void irq_gsi_mask_unmask(uint32_t irq, bool mask); -void ioapic_set_rte(uint32_t irq, uint64_t rte); -void ioapic_get_rte(uint32_t irq, uint64_t *rte); +void ioapic_set_rte(uint32_t irq, union ioapic_rte rte); +void ioapic_get_rte(uint32_t irq, union ioapic_rte *rte); void suspend_ioapic(void);