On Tue Dec 10, 2024 at 10:05 AM AEST, Michael Kowal wrote: > From: Frederic Barrat <fbar...@linux.ibm.com> > > Add XIVE2 tests for group interrupts and group interrupts that have > been backlogged. > > Signed-off-by: Frederic Barrat <fbar...@linux.ibm.com> > Signed-off-by: Michael Kowal <ko...@linux.ibm.com>
Reviewed-by: Nicholas Piggin <npig...@gmail.com> > --- > tests/qtest/pnv-xive2-test.c | 160 +++++++++++++++++++++++++++++++++++ > 1 file changed, 160 insertions(+) > > diff --git a/tests/qtest/pnv-xive2-test.c b/tests/qtest/pnv-xive2-test.c > index dd19e88861..a4d06550ee 100644 > --- a/tests/qtest/pnv-xive2-test.c > +++ b/tests/qtest/pnv-xive2-test.c > @@ -2,6 +2,8 @@ > * QTest testcase for PowerNV 10 interrupt controller (xive2) > * - Test irq to hardware thread > * - Test 'Pull Thread Context to Odd Thread Reporting Line' > + * - Test irq to hardware group > + * - Test irq to hardware group going through backlog > * > * Copyright (c) 2024, IBM Corporation. > * > @@ -315,6 +317,158 @@ static void > test_pull_thread_ctx_to_odd_thread_cl(QTestState *qts) > word2 = get_tima32(qts, target_pir, TM_QW3_HV_PHYS + TM_WORD2); > g_assert_cmphex(xive_get_field32(TM_QW3W2_VT, word2), ==, 0); > } > + > +static void test_hw_group_irq(QTestState *qts) > +{ > + uint32_t irq = 100; > + uint32_t irq_data = 0xdeadbeef; > + uint32_t end_index = 23; > + uint32_t chosen_one; > + uint32_t target_nvp = 0x81; /* group size = 4 */ > + uint8_t priority = 6; > + uint32_t reg32; > + uint16_t reg16; > + uint8_t pq, nsr, cppr; > + > + printf("# > ============================================================\n"); > + printf("# Testing irq %d to hardware group of size 4\n", irq); > + > + /* irq config */ > + set_eas(qts, irq, end_index, irq_data); > + set_end(qts, end_index, target_nvp, priority, true /* group */); > + > + /* enable and trigger irq */ > + get_esb(qts, irq, XIVE_EOI_PAGE, XIVE_ESB_SET_PQ_00); > + set_esb(qts, irq, XIVE_TRIGGER_PAGE, 0, 0); > + > + /* check irq is raised on cpu */ > + pq = get_esb(qts, irq, XIVE_EOI_PAGE, XIVE_ESB_GET); > + g_assert_cmpuint(pq, ==, XIVE_ESB_PENDING); > + > + /* find the targeted vCPU */ > + for (chosen_one = 0; chosen_one < SMT; chosen_one++) { > + reg32 = get_tima32(qts, chosen_one, TM_QW3_HV_PHYS + TM_WORD0); > + nsr = reg32 >> 24; > + if (nsr == 0x82) { > + break; > + } > + } > + g_assert_cmphex(chosen_one, <, SMT); > + cppr = (reg32 >> 16) & 0xFF; > + g_assert_cmphex(nsr, ==, 0x82); > + g_assert_cmphex(cppr, ==, 0xFF); > + > + /* ack the irq */ > + reg16 = get_tima16(qts, chosen_one, TM_SPC_ACK_HV_REG); > + nsr = reg16 >> 8; > + cppr = reg16 & 0xFF; > + g_assert_cmphex(nsr, ==, 0x82); > + g_assert_cmphex(cppr, ==, priority); > + > + /* check irq data is what was configured */ > + reg32 = qtest_readl(qts, xive_get_queue_addr(end_index)); > + g_assert_cmphex((reg32 & 0x7fffffff), ==, (irq_data & 0x7fffffff)); > + > + /* End Of Interrupt */ > + set_esb(qts, irq, XIVE_EOI_PAGE, XIVE_ESB_STORE_EOI, 0); > + pq = get_esb(qts, irq, XIVE_EOI_PAGE, XIVE_ESB_GET); > + g_assert_cmpuint(pq, ==, XIVE_ESB_RESET); > + > + /* reset CPPR */ > + set_tima8(qts, chosen_one, TM_QW3_HV_PHYS + TM_CPPR, 0xFF); > + reg32 = get_tima32(qts, chosen_one, TM_QW3_HV_PHYS + TM_WORD0); > + nsr = reg32 >> 24; > + cppr = (reg32 >> 16) & 0xFF; > + g_assert_cmphex(nsr, ==, 0x00); > + g_assert_cmphex(cppr, ==, 0xFF); > +} > + > +static void test_hw_group_irq_backlog(QTestState *qts) > +{ > + uint32_t irq = 31; > + uint32_t irq_data = 0x01234567; > + uint32_t end_index = 129; > + uint32_t target_nvp = 0x81; /* group size = 4 */ > + uint32_t chosen_one = 3; > + uint8_t blocking_priority, priority = 3; > + uint32_t reg32; > + uint16_t reg16; > + uint8_t pq, nsr, cppr, lsmfb, i; > + > + printf("# > ============================================================\n"); > + printf("# Testing irq %d to hardware group of size 4 going through " \ > + "backlog\n", > + irq); > + > + /* > + * set current priority of all threads in the group to something > + * higher than what we're about to trigger > + */ > + blocking_priority = priority - 1; > + for (i = 0; i < SMT; i++) { > + set_tima8(qts, i, TM_QW3_HV_PHYS + TM_CPPR, blocking_priority); > + } > + > + /* irq config */ > + set_eas(qts, irq, end_index, irq_data); > + set_end(qts, end_index, target_nvp, priority, true /* group */); > + > + /* enable and trigger irq */ > + get_esb(qts, irq, XIVE_EOI_PAGE, XIVE_ESB_SET_PQ_00); > + set_esb(qts, irq, XIVE_TRIGGER_PAGE, 0, 0); > + > + /* check irq is raised on cpu */ > + pq = get_esb(qts, irq, XIVE_EOI_PAGE, XIVE_ESB_GET); > + g_assert_cmpuint(pq, ==, XIVE_ESB_PENDING); > + > + /* check no interrupt is pending on the 2 possible targets */ > + for (i = 0; i < SMT; i++) { > + reg32 = get_tima32(qts, i, TM_QW3_HV_PHYS + TM_WORD0); > + nsr = reg32 >> 24; > + cppr = (reg32 >> 16) & 0xFF; > + lsmfb = reg32 & 0xFF; > + g_assert_cmphex(nsr, ==, 0x0); > + g_assert_cmphex(cppr, ==, blocking_priority); > + g_assert_cmphex(lsmfb, ==, priority); > + } > + > + /* lower priority of one thread */ > + set_tima8(qts, chosen_one, TM_QW3_HV_PHYS + TM_CPPR, priority + 1); > + > + /* check backlogged interrupt is presented */ > + reg32 = get_tima32(qts, chosen_one, TM_QW3_HV_PHYS + TM_WORD0); > + nsr = reg32 >> 24; > + cppr = (reg32 >> 16) & 0xFF; > + g_assert_cmphex(nsr, ==, 0x82); > + g_assert_cmphex(cppr, ==, priority + 1); > + > + /* ack the irq */ > + reg16 = get_tima16(qts, chosen_one, TM_SPC_ACK_HV_REG); > + nsr = reg16 >> 8; > + cppr = reg16 & 0xFF; > + g_assert_cmphex(nsr, ==, 0x82); > + g_assert_cmphex(cppr, ==, priority); > + > + /* check irq data is what was configured */ > + reg32 = qtest_readl(qts, xive_get_queue_addr(end_index)); > + g_assert_cmphex((reg32 & 0x7fffffff), ==, (irq_data & 0x7fffffff)); > + > + /* End Of Interrupt */ > + set_esb(qts, irq, XIVE_EOI_PAGE, XIVE_ESB_STORE_EOI, 0); > + pq = get_esb(qts, irq, XIVE_EOI_PAGE, XIVE_ESB_GET); > + g_assert_cmpuint(pq, ==, XIVE_ESB_RESET); > + > + /* reset CPPR */ > + set_tima8(qts, chosen_one, TM_QW3_HV_PHYS + TM_CPPR, 0xFF); > + reg32 = get_tima32(qts, chosen_one, TM_QW3_HV_PHYS + TM_WORD0); > + nsr = reg32 >> 24; > + cppr = (reg32 >> 16) & 0xFF; > + lsmfb = reg32 & 0xFF; > + g_assert_cmphex(nsr, ==, 0x00); > + g_assert_cmphex(cppr, ==, 0xFF); > + g_assert_cmphex(lsmfb, ==, 0xFF); > +} > + > static void test_xive(void) > { > QTestState *qts; > @@ -330,6 +484,12 @@ static void test_xive(void) > /* omit reset_state here and use settings from test_hw_irq */ > test_pull_thread_ctx_to_odd_thread_cl(qts); > > + reset_state(qts); > + test_hw_group_irq(qts); > + > + reset_state(qts); > + test_hw_group_irq_backlog(qts); > + > reset_state(qts); > test_flush_sync_inject(qts); >