diff options
author | Glenn Miles <milesg@linux.vnet.ibm.com> | 2024-09-13 11:16:55 -0500 |
---|---|---|
committer | Nicholas Piggin <npiggin@gmail.com> | 2024-11-04 09:14:43 +1000 |
commit | 81939a9211dc42479fe5fd84166a714e682c1314 (patch) | |
tree | f661418b4f116003ec9183de75f9659b7ab0b0ec /hw/intc/xive2.c | |
parent | 00a7a7a548ea537f888f2f90d66155f14ff93727 (diff) |
ppc/xive2: Support "Pull Thread Context to Odd Thread Reporting Line"
Adds support for single byte writes to offset 0xC38 of the TIMA address
space. When this offset is written to, the hardware disables the thread
context and copies the current state information to the odd cache line of
the pair specified by the NVT structure indexed by the THREAD CAM entry.
Note that this operation is almost identical to what we are already doing
for the "Pull OS Context to Odd Thread Reporting Line" operation except
that it also invalidates the Pool and Thread Contexts.
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@kaod.org>
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Diffstat (limited to 'hw/intc/xive2.c')
-rw-r--r-- | hw/intc/xive2.c | 73 |
1 files changed, 52 insertions, 21 deletions
diff --git a/hw/intc/xive2.c b/hw/intc/xive2.c index c5aa784fe8..2e41bd9edb 100644 --- a/hw/intc/xive2.c +++ b/hw/intc/xive2.c @@ -323,12 +323,12 @@ static void xive2_tctx_save_ctx(Xive2Router *xrtr, XiveTCTX *tctx, } static void xive2_cam_decode(uint32_t cam, uint8_t *nvp_blk, - uint32_t *nvp_idx, bool *vo, bool *ho) + uint32_t *nvp_idx, bool *valid, bool *hw) { *nvp_blk = xive2_nvp_blk(cam); *nvp_idx = xive2_nvp_idx(cam); - *vo = !!(cam & TM2_QW1W2_VO); - *ho = !!(cam & TM2_QW1W2_HO); + *valid = !!(cam & TM2_W2_VALID); + *hw = !!(cam & TM2_W2_HW); } /* @@ -351,35 +351,52 @@ static uint32_t xive2_tctx_hw_cam_line(XivePresenter *xptr, XiveTCTX *tctx) return xive2_nvp_cam_line(blk, 1 << tid_shift | (pir & tid_mask)); } -uint64_t xive2_tm_pull_os_ctx(XivePresenter *xptr, XiveTCTX *tctx, - hwaddr offset, unsigned size) +static uint64_t xive2_tm_pull_ctx(XivePresenter *xptr, XiveTCTX *tctx, + hwaddr offset, unsigned size, uint8_t ring) { Xive2Router *xrtr = XIVE2_ROUTER(xptr); - uint32_t qw1w2 = xive_tctx_word2(&tctx->regs[TM_QW1_OS]); - uint32_t qw1w2_new; - uint32_t cam = be32_to_cpu(qw1w2); + uint32_t target_ringw2 = xive_tctx_word2(&tctx->regs[ring]); + uint32_t cam = be32_to_cpu(target_ringw2); uint8_t nvp_blk; uint32_t nvp_idx; - bool vo; + uint8_t cur_ring; + bool valid; bool do_save; - xive2_cam_decode(cam, &nvp_blk, &nvp_idx, &vo, &do_save); + xive2_cam_decode(cam, &nvp_blk, &nvp_idx, &valid, &do_save); - if (!vo) { + if (!valid) { qemu_log_mask(LOG_GUEST_ERROR, "XIVE: pulling invalid NVP %x/%x !?\n", nvp_blk, nvp_idx); } - /* Invalidate CAM line */ - qw1w2_new = xive_set_field32(TM2_QW1W2_VO, qw1w2, 0); - memcpy(&tctx->regs[TM_QW1_OS + TM_WORD2], &qw1w2_new, 4); + /* Invalidate CAM line of requested ring and all lower rings */ + for (cur_ring = TM_QW0_USER; cur_ring <= ring; + cur_ring += XIVE_TM_RING_SIZE) { + uint32_t ringw2 = xive_tctx_word2(&tctx->regs[cur_ring]); + uint32_t ringw2_new = xive_set_field32(TM2_QW1W2_VO, ringw2, 0); + memcpy(&tctx->regs[cur_ring + TM_WORD2], &ringw2_new, 4); + } if (xive2_router_get_config(xrtr) & XIVE2_VP_SAVE_RESTORE && do_save) { - xive2_tctx_save_ctx(xrtr, tctx, nvp_blk, nvp_idx, TM_QW1_OS); + xive2_tctx_save_ctx(xrtr, tctx, nvp_blk, nvp_idx, ring); + } + + /* + * Lower external interrupt line of requested ring and below except for + * USER, which doesn't exist. + */ + for (cur_ring = TM_QW1_OS; cur_ring <= ring; + cur_ring += XIVE_TM_RING_SIZE) { + xive_tctx_reset_signal(tctx, cur_ring); } + return target_ringw2; +} - xive_tctx_reset_signal(tctx, TM_QW1_OS); - return qw1w2; +uint64_t xive2_tm_pull_os_ctx(XivePresenter *xptr, XiveTCTX *tctx, + hwaddr offset, unsigned size) +{ + return xive2_tm_pull_ctx(xptr, tctx, offset, size, TM_QW1_OS); } #define REPORT_LINE_GEN1_SIZE 16 @@ -424,8 +441,9 @@ static void xive2_tm_report_line_gen1(XiveTCTX *tctx, uint8_t *data, } } -void xive2_tm_pull_os_ctx_ol(XivePresenter *xptr, XiveTCTX *tctx, - hwaddr offset, uint64_t value, unsigned size) +static void xive2_tm_pull_ctx_ol(XivePresenter *xptr, XiveTCTX *tctx, + hwaddr offset, uint64_t value, + unsigned size, uint8_t ring) { Xive2Router *xrtr = XIVE2_ROUTER(xptr); uint32_t hw_cam, nvp_idx, xive2_cfg, reserved; @@ -473,8 +491,21 @@ void xive2_tm_pull_os_ctx_ol(XivePresenter *xptr, XiveTCTX *tctx, assert(result == MEMTX_OK); } - /* the rest is similar to pull OS context to registers */ - xive2_tm_pull_os_ctx(xptr, tctx, offset, size); + /* the rest is similar to pull context to registers */ + xive2_tm_pull_ctx(xptr, tctx, offset, size, ring); +} + +void xive2_tm_pull_os_ctx_ol(XivePresenter *xptr, XiveTCTX *tctx, + hwaddr offset, uint64_t value, unsigned size) +{ + xive2_tm_pull_ctx_ol(xptr, tctx, offset, value, size, TM_QW1_OS); +} + + +void xive2_tm_pull_phys_ctx_ol(XivePresenter *xptr, XiveTCTX *tctx, + hwaddr offset, uint64_t value, unsigned size) +{ + xive2_tm_pull_ctx_ol(xptr, tctx, offset, value, size, TM_QW3_HV_PHYS); } static uint8_t xive2_tctx_restore_os_ctx(Xive2Router *xrtr, XiveTCTX *tctx, |