mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-11 03:24:58 -06:00
qtest/xive: Add group-interrupt test
Add XIVE2 tests for group interrupts and group interrupts that have been backlogged. Signed-off-by: Frederic Barrat <fbarrat@linux.ibm.com> Signed-off-by: Michael Kowal <kowal@linux.ibm.com> Reviewed-by: Nicholas Piggin <npiggin@gmail.com> Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
This commit is contained in:
parent
26c55b9941
commit
c2b7fade9f
1 changed files with 160 additions and 0 deletions
|
@ -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);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue