mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-06-20 12:42:54 +00:00
HV: ioapic: unify the access pattern to RTEs
There are two different ways the current implementation adopts to access ioapic RTEs: 1. As two 32-bit registers (typically named ''low'' and ''high''), or 2. As one 64-bit register (typically named ''rte''). Two issues arise due to the mixed use of these two patterns. 1. Additional conversions are introduced. As an example, ioapic_get_rte() merges two RTE fragments into a uint64_t, while some callers break it back to ''low'' and ''high'' again. 2. It is tricky to choose the proper width of IOAPIC_RTE_xxx constants. SOS boot failure is seen when they are 32-bit due to the following code: /* reg is uint64_t */ vioapic->rtbl[pin].reg &= ~IOAPIC_RTE_REM_IRR; while making them 64-bit leads to implicit narrowing when the RTEs are accessed in the low & high pattern. This patch defines a union ''ioapic_rte'' and unifies the access pattern to IOAPIC and vIOAPIC RTEs. v1 -> v2: * Instead of two 32-bit ''low'' and ''high'', define a union that allows either 32-bit or 64-bit accesses to RTEs. Signed-off-by: Junjie Mao <junjie.mao@intel.com> Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
parent
9878543356
commit
a1069a5117
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -31,6 +31,9 @@
|
||||
#ifndef _VIOAPIC_H_
|
||||
#define _VIOAPIC_H_
|
||||
|
||||
#include <apicreg.h>
|
||||
#include <vm.h>
|
||||
|
||||
#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);
|
||||
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user