mirror of https://gitlab.com/qemu-project/qemu
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
153 lines
5.0 KiB
C
153 lines
5.0 KiB
C
/*
|
|
* QTest testcase for PowerNV 10 interrupt controller (xive2)
|
|
* - Test NVPG BAR MMIO operations
|
|
*
|
|
* Copyright (c) 2024, IBM Corporation.
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
|
*/
|
|
#include "qemu/osdep.h"
|
|
#include "libqtest.h"
|
|
|
|
#include "pnv-xive2-common.h"
|
|
|
|
#define NVPG_BACKLOG_OP_SHIFT 10
|
|
#define NVPG_BACKLOG_PRIO_SHIFT 4
|
|
|
|
#define XIVE_PRIORITY_MAX 7
|
|
|
|
enum NVx {
|
|
NVP,
|
|
NVG,
|
|
NVC
|
|
};
|
|
|
|
typedef enum {
|
|
INCR_STORE = 0b100,
|
|
INCR_LOAD = 0b000,
|
|
DECR_STORE = 0b101,
|
|
DECR_LOAD = 0b001,
|
|
READ_x = 0b010,
|
|
READ_y = 0b011,
|
|
} backlog_op;
|
|
|
|
static uint32_t nvpg_backlog_op(QTestState *qts, backlog_op op,
|
|
enum NVx type, uint64_t index,
|
|
uint8_t priority, uint8_t delta)
|
|
{
|
|
uint64_t addr, offset;
|
|
uint32_t count = 0;
|
|
|
|
switch (type) {
|
|
case NVP:
|
|
addr = XIVE_NVPG_ADDR + (index << (XIVE_PAGE_SHIFT + 1));
|
|
break;
|
|
case NVG:
|
|
addr = XIVE_NVPG_ADDR + (index << (XIVE_PAGE_SHIFT + 1)) +
|
|
(1 << XIVE_PAGE_SHIFT);
|
|
break;
|
|
case NVC:
|
|
addr = XIVE_NVC_ADDR + (index << XIVE_PAGE_SHIFT);
|
|
break;
|
|
default:
|
|
g_assert_not_reached();
|
|
}
|
|
|
|
offset = (op & 0b11) << NVPG_BACKLOG_OP_SHIFT;
|
|
offset |= priority << NVPG_BACKLOG_PRIO_SHIFT;
|
|
if (op >> 2) {
|
|
qtest_writeb(qts, addr + offset, delta);
|
|
} else {
|
|
count = qtest_readw(qts, addr + offset);
|
|
}
|
|
return count;
|
|
}
|
|
|
|
void test_nvpg_bar(QTestState *qts)
|
|
{
|
|
uint32_t nvp_target = 0x11;
|
|
uint32_t group_target = 0x17; /* size 16 */
|
|
uint32_t vp_irq = 33, group_irq = 47;
|
|
uint32_t vp_end = 3, group_end = 97;
|
|
uint32_t vp_irq_data = 0x33333333;
|
|
uint32_t group_irq_data = 0x66666666;
|
|
uint8_t vp_priority = 0, group_priority = 5;
|
|
uint32_t vp_count[XIVE_PRIORITY_MAX + 1] = { 0 };
|
|
uint32_t group_count[XIVE_PRIORITY_MAX + 1] = { 0 };
|
|
uint32_t count, delta;
|
|
uint8_t i;
|
|
|
|
g_test_message("=========================================================");
|
|
g_test_message("Testing NVPG BAR operations");
|
|
|
|
set_nvg(qts, group_target, 0);
|
|
set_nvp(qts, nvp_target, 0x04);
|
|
set_nvp(qts, group_target, 0x04);
|
|
|
|
/*
|
|
* Setup: trigger a VP-specific interrupt and a group interrupt
|
|
* so that the backlog counters are initialized to something else
|
|
* than 0 for at least one priority level
|
|
*/
|
|
set_eas(qts, vp_irq, vp_end, vp_irq_data);
|
|
set_end(qts, vp_end, nvp_target, vp_priority, false /* group */);
|
|
|
|
set_eas(qts, group_irq, group_end, group_irq_data);
|
|
set_end(qts, group_end, group_target, group_priority, true /* group */);
|
|
|
|
get_esb(qts, vp_irq, XIVE_EOI_PAGE, XIVE_ESB_SET_PQ_00);
|
|
set_esb(qts, vp_irq, XIVE_TRIGGER_PAGE, 0, 0);
|
|
vp_count[vp_priority]++;
|
|
|
|
get_esb(qts, group_irq, XIVE_EOI_PAGE, XIVE_ESB_SET_PQ_00);
|
|
set_esb(qts, group_irq, XIVE_TRIGGER_PAGE, 0, 0);
|
|
group_count[group_priority]++;
|
|
|
|
/* check the initial counters */
|
|
for (i = 0; i <= XIVE_PRIORITY_MAX; i++) {
|
|
count = nvpg_backlog_op(qts, READ_x, NVP, nvp_target, i, 0);
|
|
g_assert_cmpuint(count, ==, vp_count[i]);
|
|
|
|
count = nvpg_backlog_op(qts, READ_y, NVG, group_target, i, 0);
|
|
g_assert_cmpuint(count, ==, group_count[i]);
|
|
}
|
|
|
|
/* do a few ops on the VP. Counter can only be 0 and 1 */
|
|
vp_priority = 2;
|
|
delta = 7;
|
|
nvpg_backlog_op(qts, INCR_STORE, NVP, nvp_target, vp_priority, delta);
|
|
vp_count[vp_priority] = 1;
|
|
count = nvpg_backlog_op(qts, INCR_LOAD, NVP, nvp_target, vp_priority, 0);
|
|
g_assert_cmpuint(count, ==, vp_count[vp_priority]);
|
|
count = nvpg_backlog_op(qts, READ_y, NVP, nvp_target, vp_priority, 0);
|
|
g_assert_cmpuint(count, ==, vp_count[vp_priority]);
|
|
|
|
count = nvpg_backlog_op(qts, DECR_LOAD, NVP, nvp_target, vp_priority, 0);
|
|
g_assert_cmpuint(count, ==, vp_count[vp_priority]);
|
|
vp_count[vp_priority] = 0;
|
|
nvpg_backlog_op(qts, DECR_STORE, NVP, nvp_target, vp_priority, delta);
|
|
count = nvpg_backlog_op(qts, READ_x, NVP, nvp_target, vp_priority, 0);
|
|
g_assert_cmpuint(count, ==, vp_count[vp_priority]);
|
|
|
|
/* do a few ops on the group */
|
|
group_priority = 2;
|
|
delta = 9;
|
|
/* can't go negative */
|
|
nvpg_backlog_op(qts, DECR_STORE, NVG, group_target, group_priority, delta);
|
|
count = nvpg_backlog_op(qts, READ_y, NVG, group_target, group_priority, 0);
|
|
g_assert_cmpuint(count, ==, 0);
|
|
nvpg_backlog_op(qts, INCR_STORE, NVG, group_target, group_priority, delta);
|
|
group_count[group_priority] += delta;
|
|
count = nvpg_backlog_op(qts, INCR_LOAD, NVG, group_target,
|
|
group_priority, delta);
|
|
g_assert_cmpuint(count, ==, group_count[group_priority]);
|
|
group_count[group_priority]++;
|
|
|
|
count = nvpg_backlog_op(qts, DECR_LOAD, NVG, group_target,
|
|
group_priority, delta);
|
|
g_assert_cmpuint(count, ==, group_count[group_priority]);
|
|
group_count[group_priority]--;
|
|
count = nvpg_backlog_op(qts, READ_x, NVG, group_target, group_priority, 0);
|
|
g_assert_cmpuint(count, ==, group_count[group_priority]);
|
|
}
|