aboutsummaryrefslogtreecommitdiff
path: root/hw/intc
diff options
context:
space:
mode:
authorCédric Le Goater <clg@kaod.org>2019-03-06 09:50:14 +0100
committerDavid Gibson <david@gibson.dropbear.id.au>2019-03-12 14:33:04 +1100
commit4836b45510aa84da52a29bf5a23794f71a29d98b (patch)
tree83f68cd4e861d20407de9389c742de1e0416db68 /hw/intc
parentd8e4aad533573b6237b5da6ceb06027fc4eac9c7 (diff)
downloadqemu-4836b45510aa84da52a29bf5a23794f71a29d98b.zip
qemu-4836b45510aa84da52a29bf5a23794f71a29d98b.tar.gz
qemu-4836b45510aa84da52a29bf5a23794f71a29d98b.tar.bz2
ppc/xive: activate HV support
The NSR register of the HV ring has a different, although similar, bit layout. TM_QW3_NSR_HE_PHYS bit should now be raised when the Hypervisor interrupt line is signaled. Other bits TM_QW3_NSR_HE_POOL and TM_QW3_NSR_HE_LSI are not modeled. LSI are for special interrupts reserved for HW bringup and the POOL bit is used when signaling a group of VPs. This is not currently implemented in Linux but it is in pHyp. The most important special commands on the HV TIMA page are added to let the core manage interrupts : acking and changing the CPU priority. Signed-off-by: Cédric Le Goater <clg@kaod.org> Message-Id: <20190306085032.15744-10-clg@kaod.org> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Diffstat (limited to 'hw/intc')
-rw-r--r--hw/intc/xive.c57
1 files changed, 54 insertions, 3 deletions
diff --git a/hw/intc/xive.c b/hw/intc/xive.c
index 7d7992c..a0b8700 100644
--- a/hw/intc/xive.c
+++ b/hw/intc/xive.c
@@ -54,6 +54,8 @@ static uint8_t exception_mask(uint8_t ring)
switch (ring) {
case TM_QW1_OS:
return TM_QW1_NSR_EO;
+ case TM_QW3_HV_PHYS:
+ return TM_QW3_NSR_HE;
default:
g_assert_not_reached();
}
@@ -88,7 +90,16 @@ static void xive_tctx_notify(XiveTCTX *tctx, uint8_t ring)
uint8_t *regs = &tctx->regs[ring];
if (regs[TM_PIPR] < regs[TM_CPPR]) {
- regs[TM_NSR] |= exception_mask(ring);
+ switch (ring) {
+ case TM_QW1_OS:
+ regs[TM_NSR] |= TM_QW1_NSR_EO;
+ break;
+ case TM_QW3_HV_PHYS:
+ regs[TM_NSR] |= (TM_QW3_NSR_HE_PHYS << 6);
+ break;
+ default:
+ g_assert_not_reached();
+ }
qemu_irq_raise(tctx->output);
}
}
@@ -109,6 +120,38 @@ static void xive_tctx_set_cppr(XiveTCTX *tctx, uint8_t ring, uint8_t cppr)
* XIVE Thread Interrupt Management Area (TIMA)
*/
+static void xive_tm_set_hv_cppr(XiveTCTX *tctx, hwaddr offset,
+ uint64_t value, unsigned size)
+{
+ xive_tctx_set_cppr(tctx, TM_QW3_HV_PHYS, value & 0xff);
+}
+
+static uint64_t xive_tm_ack_hv_reg(XiveTCTX *tctx, hwaddr offset, unsigned size)
+{
+ return xive_tctx_accept(tctx, TM_QW3_HV_PHYS);
+}
+
+static uint64_t xive_tm_pull_pool_ctx(XiveTCTX *tctx, hwaddr offset,
+ unsigned size)
+{
+ uint64_t ret;
+
+ ret = tctx->regs[TM_QW2_HV_POOL + TM_WORD2] & TM_QW2W2_POOL_CAM;
+ tctx->regs[TM_QW2_HV_POOL + TM_WORD2] &= ~TM_QW2W2_POOL_CAM;
+ return ret;
+}
+
+static void xive_tm_vt_push(XiveTCTX *tctx, hwaddr offset,
+ uint64_t value, unsigned size)
+{
+ tctx->regs[TM_QW3_HV_PHYS + TM_WORD2] = value & 0xff;
+}
+
+static uint64_t xive_tm_vt_poll(XiveTCTX *tctx, hwaddr offset, unsigned size)
+{
+ return tctx->regs[TM_QW3_HV_PHYS + TM_WORD2] & 0xff;
+}
+
/*
* Define an access map for each page of the TIMA that we will use in
* the memory region ops to filter values when doing loads and stores
@@ -288,10 +331,16 @@ static const XiveTmOp xive_tm_operations[] = {
* effects
*/
{ XIVE_TM_OS_PAGE, TM_QW1_OS + TM_CPPR, 1, xive_tm_set_os_cppr, NULL },
+ { XIVE_TM_HV_PAGE, TM_QW3_HV_PHYS + TM_CPPR, 1, xive_tm_set_hv_cppr, NULL },
+ { XIVE_TM_HV_PAGE, TM_QW3_HV_PHYS + TM_WORD2, 1, xive_tm_vt_push, NULL },
+ { XIVE_TM_HV_PAGE, TM_QW3_HV_PHYS + TM_WORD2, 1, NULL, xive_tm_vt_poll },
/* MMIOs above 2K : special operations with side effects */
{ XIVE_TM_OS_PAGE, TM_SPC_ACK_OS_REG, 2, NULL, xive_tm_ack_os_reg },
{ XIVE_TM_OS_PAGE, TM_SPC_SET_OS_PENDING, 1, xive_tm_set_os_pending, NULL },
+ { XIVE_TM_HV_PAGE, TM_SPC_ACK_HV_REG, 2, NULL, xive_tm_ack_hv_reg },
+ { XIVE_TM_HV_PAGE, TM_SPC_PULL_POOL_CTX, 4, NULL, xive_tm_pull_pool_ctx },
+ { XIVE_TM_HV_PAGE, TM_SPC_PULL_POOL_CTX, 8, NULL, xive_tm_pull_pool_ctx },
};
static const XiveTmOp *xive_tm_find_op(hwaddr offset, unsigned size, bool write)
@@ -323,7 +372,7 @@ void xive_tctx_tm_write(XiveTCTX *tctx, hwaddr offset, uint64_t value,
const XiveTmOp *xto;
/*
- * TODO: check V bit in Q[0-3]W2, check PTER bit associated with CPU
+ * TODO: check V bit in Q[0-3]W2
*/
/*
@@ -360,7 +409,7 @@ uint64_t xive_tctx_tm_read(XiveTCTX *tctx, hwaddr offset, unsigned size)
const XiveTmOp *xto;
/*
- * TODO: check V bit in Q[0-3]W2, check PTER bit associated with CPU
+ * TODO: check V bit in Q[0-3]W2
*/
/*
@@ -472,6 +521,8 @@ static void xive_tctx_reset(void *dev)
*/
tctx->regs[TM_QW1_OS + TM_PIPR] =
ipb_to_pipr(tctx->regs[TM_QW1_OS + TM_IPB]);
+ tctx->regs[TM_QW3_HV_PHYS + TM_PIPR] =
+ ipb_to_pipr(tctx->regs[TM_QW3_HV_PHYS + TM_IPB]);
}
static void xive_tctx_realize(DeviceState *dev, Error **errp)