aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGlenn Miles <milesg@linux.vnet.ibm.com>2024-09-13 11:16:56 -0500
committerNicholas Piggin <npiggin@gmail.com>2024-11-04 09:14:45 +1000
commita9bb09678a7487609769f1965a04d3a774810bda (patch)
tree105ce076e03fc589b5887222f2b1cdf6749c94f9
parent81939a9211dc42479fe5fd84166a714e682c1314 (diff)
pnv/xive: Add special handling for pool targets
Hypervisor "pool" targets do not get their own interrupt line and instead must share an interrupt line with the hypervisor "physical" targets. This also means that the pool ring must use some of the registers from the physical ring in the TIMA. Specifically, the NSR, PIPR and CPPR registers: NSR = Notification Source Register PIPR = Post Interrupt Priority Register CPPR = Current Processor Priority Register The NSR specifies that there is an active interrupt. The CPPR specifies the priority of the context and the PIPR specifies the priority of the interrupt. For an interrupt to be presented to a context, the priority of the interrupt must be higher than the priority of the context it is interrupting (value must be lower). The existing code was not aware of the sharing of these registers. This commit adds that support. Signed-off-by: Glenn Miles <milesg@linux.vnet.ibm.com> Signed-off-by: Michael Kowal <kowal@linux.ibm.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
-rw-r--r--hw/intc/xive.c36
1 files changed, 26 insertions, 10 deletions
diff --git a/hw/intc/xive.c b/hw/intc/xive.c
index 951aaf5279..baad7129ca 100644
--- a/hw/intc/xive.c
+++ b/hw/intc/xive.c
@@ -74,33 +74,49 @@ static uint64_t xive_tctx_accept(XiveTCTX *tctx, uint8_t ring)
if (regs[TM_NSR] & mask) {
uint8_t cppr = regs[TM_PIPR];
+ uint8_t alt_ring;
+ uint8_t *alt_regs;
+
+ /* POOL interrupt uses IPB in QW2, POOL ring */
+ if ((ring == TM_QW3_HV_PHYS) && (nsr & (TM_QW3_NSR_HE_POOL << 6))) {
+ alt_ring = TM_QW2_HV_POOL;
+ } else {
+ alt_ring = ring;
+ }
+ alt_regs = &tctx->regs[alt_ring];
regs[TM_CPPR] = cppr;
/* Reset the pending buffer bit */
- regs[TM_IPB] &= ~xive_priority_to_ipb(cppr);
- regs[TM_PIPR] = ipb_to_pipr(regs[TM_IPB]);
+ alt_regs[TM_IPB] &= ~xive_priority_to_ipb(cppr);
+ regs[TM_PIPR] = ipb_to_pipr(alt_regs[TM_IPB]);
/* Drop Exception bit */
regs[TM_NSR] &= ~mask;
- trace_xive_tctx_accept(tctx->cs->cpu_index, ring,
- regs[TM_IPB], regs[TM_PIPR],
+ trace_xive_tctx_accept(tctx->cs->cpu_index, alt_ring,
+ alt_regs[TM_IPB], regs[TM_PIPR],
regs[TM_CPPR], regs[TM_NSR]);
}
- return (nsr << 8) | regs[TM_CPPR];
+ return ((uint64_t)nsr << 8) | regs[TM_CPPR];
}
static void xive_tctx_notify(XiveTCTX *tctx, uint8_t ring)
{
+ /* HV_POOL ring uses HV_PHYS NSR, CPPR and PIPR registers */
+ uint8_t alt_ring = (ring == TM_QW2_HV_POOL) ? TM_QW3_HV_PHYS : ring;
+ uint8_t *alt_regs = &tctx->regs[alt_ring];
uint8_t *regs = &tctx->regs[ring];
- if (regs[TM_PIPR] < regs[TM_CPPR]) {
+ if (alt_regs[TM_PIPR] < alt_regs[TM_CPPR]) {
switch (ring) {
case TM_QW1_OS:
regs[TM_NSR] |= TM_QW1_NSR_EO;
break;
+ case TM_QW2_HV_POOL:
+ alt_regs[TM_NSR] = (TM_QW3_NSR_HE_POOL << 6);
+ break;
case TM_QW3_HV_PHYS:
regs[TM_NSR] |= (TM_QW3_NSR_HE_PHYS << 6);
break;
@@ -108,8 +124,8 @@ static void xive_tctx_notify(XiveTCTX *tctx, uint8_t ring)
g_assert_not_reached();
}
trace_xive_tctx_notify(tctx->cs->cpu_index, ring,
- regs[TM_IPB], regs[TM_PIPR],
- regs[TM_CPPR], regs[TM_NSR]);
+ regs[TM_IPB], alt_regs[TM_PIPR],
+ alt_regs[TM_CPPR], alt_regs[TM_NSR]);
qemu_irq_raise(xive_tctx_output(tctx, ring));
}
}
@@ -217,14 +233,14 @@ static uint64_t xive_tm_vt_poll(XivePresenter *xptr, XiveTCTX *tctx,
static const uint8_t xive_tm_hw_view[] = {
3, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, 0, 0, 0, /* QW-0 User */
3, 3, 3, 3, 3, 3, 0, 2, 3, 3, 3, 3, 0, 0, 0, 0, /* QW-1 OS */
- 0, 0, 3, 3, 0, 0, 0, 0, 3, 3, 3, 3, 0, 0, 0, 0, /* QW-2 POOL */
+ 0, 0, 3, 3, 0, 3, 3, 0, 3, 3, 3, 3, 0, 0, 0, 0, /* QW-2 POOL */
3, 3, 3, 3, 0, 3, 0, 2, 3, 0, 0, 3, 3, 3, 3, 0, /* QW-3 PHYS */
};
static const uint8_t xive_tm_hv_view[] = {
3, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, 0, 0, 0, /* QW-0 User */
3, 3, 3, 3, 3, 3, 0, 2, 3, 3, 3, 3, 0, 0, 0, 0, /* QW-1 OS */
- 0, 0, 3, 3, 0, 0, 0, 0, 0, 3, 3, 3, 0, 0, 0, 0, /* QW-2 POOL */
+ 0, 0, 3, 3, 0, 3, 3, 0, 0, 3, 3, 3, 0, 0, 0, 0, /* QW-2 POOL */
3, 3, 3, 3, 0, 3, 0, 2, 3, 0, 0, 3, 0, 0, 0, 0, /* QW-3 PHYS */
};