summary refs log tree commit diff stats
path: root/tests/qtest/pnv-xive2-flush-sync.c
diff options
context:
space:
mode:
Diffstat (limited to 'tests/qtest/pnv-xive2-flush-sync.c')
-rw-r--r--tests/qtest/pnv-xive2-flush-sync.c205
1 files changed, 205 insertions, 0 deletions
diff --git a/tests/qtest/pnv-xive2-flush-sync.c b/tests/qtest/pnv-xive2-flush-sync.c
new file mode 100644
index 0000000000..3b32446adb
--- /dev/null
+++ b/tests/qtest/pnv-xive2-flush-sync.c
@@ -0,0 +1,205 @@
+/*
+ * QTest testcase for PowerNV 10 interrupt controller (xive2)
+ *  - Test cache flush/queue sync injection
+ *
+ * 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"
+#include "hw/intc/pnv_xive2_regs.h"
+#include "hw/ppc/xive_regs.h"
+#include "hw/ppc/xive2_regs.h"
+
+#define PNV_XIVE2_QUEUE_IPI              0x00
+#define PNV_XIVE2_QUEUE_HW               0x01
+#define PNV_XIVE2_QUEUE_NXC              0x02
+#define PNV_XIVE2_QUEUE_INT              0x03
+#define PNV_XIVE2_QUEUE_OS               0x04
+#define PNV_XIVE2_QUEUE_POOL             0x05
+#define PNV_XIVE2_QUEUE_HARD             0x06
+#define PNV_XIVE2_CACHE_ENDC             0x08
+#define PNV_XIVE2_CACHE_ESBC             0x09
+#define PNV_XIVE2_CACHE_EASC             0x0a
+#define PNV_XIVE2_QUEUE_NXC_LD_LCL_NCO   0x10
+#define PNV_XIVE2_QUEUE_NXC_LD_LCL_CO    0x11
+#define PNV_XIVE2_QUEUE_NXC_ST_LCL_NCI   0x12
+#define PNV_XIVE2_QUEUE_NXC_ST_LCL_CI    0x13
+#define PNV_XIVE2_QUEUE_NXC_ST_RMT_NCI   0x14
+#define PNV_XIVE2_QUEUE_NXC_ST_RMT_CI    0x15
+#define PNV_XIVE2_CACHE_NXC              0x18
+
+#define PNV_XIVE2_SYNC_IPI              0x000
+#define PNV_XIVE2_SYNC_HW               0x080
+#define PNV_XIVE2_SYNC_NxC              0x100
+#define PNV_XIVE2_SYNC_INT              0x180
+#define PNV_XIVE2_SYNC_OS_ESC           0x200
+#define PNV_XIVE2_SYNC_POOL_ESC         0x280
+#define PNV_XIVE2_SYNC_HARD_ESC         0x300
+#define PNV_XIVE2_SYNC_NXC_LD_LCL_NCO   0x800
+#define PNV_XIVE2_SYNC_NXC_LD_LCL_CO    0x880
+#define PNV_XIVE2_SYNC_NXC_ST_LCL_NCI   0x900
+#define PNV_XIVE2_SYNC_NXC_ST_LCL_CI    0x980
+#define PNV_XIVE2_SYNC_NXC_ST_RMT_NCI   0xA00
+#define PNV_XIVE2_SYNC_NXC_ST_RMT_CI    0xA80
+
+
+static uint64_t get_sync_addr(uint32_t src_pir, int ic_topo_id, int type)
+{
+    int thread_nr = src_pir & 0x7f;
+    uint64_t addr = XIVE_SYNC_MEM +  thread_nr * 512 + ic_topo_id * 32 + type;
+    return addr;
+}
+
+static uint8_t get_sync(QTestState *qts, uint32_t src_pir, int ic_topo_id,
+                        int type)
+{
+    uint64_t addr = get_sync_addr(src_pir, ic_topo_id, type);
+    return qtest_readb(qts, addr);
+}
+
+static void clr_sync(QTestState *qts, uint32_t src_pir, int ic_topo_id,
+                        int type)
+{
+    uint64_t addr = get_sync_addr(src_pir, ic_topo_id, type);
+    qtest_writeb(qts, addr, 0x0);
+}
+
+static void inject_cache_flush(QTestState *qts, int ic_topo_id,
+                               uint64_t scom_addr)
+{
+    (void)ic_topo_id;
+    pnv_xive_xscom_write(qts, scom_addr, 0);
+}
+
+static void inject_queue_sync(QTestState *qts, int ic_topo_id, uint64_t offset)
+{
+    (void)ic_topo_id;
+    uint64_t addr = XIVE_IC_ADDR + (VST_SYNC << XIVE_PAGE_SHIFT) + offset;
+    qtest_writeq(qts, addr, 0);
+}
+
+static void inject_op(QTestState *qts, int ic_topo_id, int type)
+{
+    switch (type) {
+    case PNV_XIVE2_QUEUE_IPI:
+        inject_queue_sync(qts, ic_topo_id, PNV_XIVE2_SYNC_IPI);
+        break;
+    case PNV_XIVE2_QUEUE_HW:
+        inject_queue_sync(qts, ic_topo_id, PNV_XIVE2_SYNC_HW);
+        break;
+    case PNV_XIVE2_QUEUE_NXC:
+        inject_queue_sync(qts, ic_topo_id, PNV_XIVE2_SYNC_NxC);
+        break;
+    case PNV_XIVE2_QUEUE_INT:
+        inject_queue_sync(qts, ic_topo_id, PNV_XIVE2_SYNC_INT);
+        break;
+    case PNV_XIVE2_QUEUE_OS:
+        inject_queue_sync(qts, ic_topo_id, PNV_XIVE2_SYNC_OS_ESC);
+        break;
+    case PNV_XIVE2_QUEUE_POOL:
+        inject_queue_sync(qts, ic_topo_id, PNV_XIVE2_SYNC_POOL_ESC);
+        break;
+    case PNV_XIVE2_QUEUE_HARD:
+        inject_queue_sync(qts, ic_topo_id, PNV_XIVE2_SYNC_HARD_ESC);
+        break;
+    case PNV_XIVE2_CACHE_ENDC:
+        inject_cache_flush(qts, ic_topo_id, X_VC_ENDC_FLUSH_INJECT);
+        break;
+    case PNV_XIVE2_CACHE_ESBC:
+        inject_cache_flush(qts, ic_topo_id, X_VC_ESBC_FLUSH_INJECT);
+        break;
+    case PNV_XIVE2_CACHE_EASC:
+        inject_cache_flush(qts, ic_topo_id, X_VC_EASC_FLUSH_INJECT);
+        break;
+    case PNV_XIVE2_QUEUE_NXC_LD_LCL_NCO:
+        inject_queue_sync(qts, ic_topo_id, PNV_XIVE2_SYNC_NXC_LD_LCL_NCO);
+        break;
+    case PNV_XIVE2_QUEUE_NXC_LD_LCL_CO:
+        inject_queue_sync(qts, ic_topo_id, PNV_XIVE2_SYNC_NXC_LD_LCL_CO);
+        break;
+    case PNV_XIVE2_QUEUE_NXC_ST_LCL_NCI:
+        inject_queue_sync(qts, ic_topo_id, PNV_XIVE2_SYNC_NXC_ST_LCL_NCI);
+        break;
+    case PNV_XIVE2_QUEUE_NXC_ST_LCL_CI:
+        inject_queue_sync(qts, ic_topo_id, PNV_XIVE2_SYNC_NXC_ST_LCL_CI);
+        break;
+    case PNV_XIVE2_QUEUE_NXC_ST_RMT_NCI:
+        inject_queue_sync(qts, ic_topo_id, PNV_XIVE2_SYNC_NXC_ST_RMT_NCI);
+        break;
+    case PNV_XIVE2_QUEUE_NXC_ST_RMT_CI:
+        inject_queue_sync(qts, ic_topo_id, PNV_XIVE2_SYNC_NXC_ST_RMT_CI);
+        break;
+    case PNV_XIVE2_CACHE_NXC:
+        inject_cache_flush(qts, ic_topo_id, X_PC_NXC_FLUSH_INJECT);
+        break;
+    default:
+        g_assert_not_reached();
+        break;
+    }
+}
+
+const uint8_t xive_inject_tests[] = {
+    PNV_XIVE2_QUEUE_IPI,
+    PNV_XIVE2_QUEUE_HW,
+    PNV_XIVE2_QUEUE_NXC,
+    PNV_XIVE2_QUEUE_INT,
+    PNV_XIVE2_QUEUE_OS,
+    PNV_XIVE2_QUEUE_POOL,
+    PNV_XIVE2_QUEUE_HARD,
+    PNV_XIVE2_CACHE_ENDC,
+    PNV_XIVE2_CACHE_ESBC,
+    PNV_XIVE2_CACHE_EASC,
+    PNV_XIVE2_QUEUE_NXC_LD_LCL_NCO,
+    PNV_XIVE2_QUEUE_NXC_LD_LCL_CO,
+    PNV_XIVE2_QUEUE_NXC_ST_LCL_NCI,
+    PNV_XIVE2_QUEUE_NXC_ST_LCL_CI,
+    PNV_XIVE2_QUEUE_NXC_ST_RMT_NCI,
+    PNV_XIVE2_QUEUE_NXC_ST_RMT_CI,
+    PNV_XIVE2_CACHE_NXC,
+};
+
+void test_flush_sync_inject(QTestState *qts)
+{
+    int ic_topo_id = 0;
+
+    /*
+     * Writes performed by qtest are not done in the context of a thread.
+     * This means that QEMU XIVE code doesn't have a way to determine what
+     * thread is originating the write.  In order to allow for some testing,
+     * QEMU XIVE code will assume a PIR of 0 when unable to determine the
+     * source thread for cache flush and queue sync inject operations.
+     * See hw/intc/pnv_xive2.c: pnv_xive2_inject_notify() for details.
+     */
+    int src_pir = 0;
+    int test_nr;
+    uint8_t byte;
+
+    printf("# ============================================================\n");
+    printf("# Starting cache flush/queue sync injection tests...\n");
+
+    for (test_nr = 0; test_nr < sizeof(xive_inject_tests);
+         test_nr++) {
+        int op_type = xive_inject_tests[test_nr];
+
+        printf("# Running test %d\n", test_nr);
+
+        /* start with status byte set to 0 */
+        clr_sync(qts, src_pir, ic_topo_id, op_type);
+        byte = get_sync(qts, src_pir, ic_topo_id, op_type);
+        g_assert_cmphex(byte, ==, 0);
+
+        /* request cache flush or queue sync operation */
+        inject_op(qts, ic_topo_id, op_type);
+
+        /* verify that status byte was written to 0xff */
+        byte = get_sync(qts, src_pir, ic_topo_id, op_type);
+        g_assert_cmphex(byte, ==, 0xff);
+
+        clr_sync(qts, src_pir, ic_topo_id, op_type);
+    }
+}
+