1*31bfbc00SFrederic Barrat /*
2*31bfbc00SFrederic Barrat  * QTest testcase for PowerNV 10 interrupt controller (xive2)
3*31bfbc00SFrederic Barrat  *  - Test cache flush/queue sync injection
4*31bfbc00SFrederic Barrat  *
5*31bfbc00SFrederic Barrat  * Copyright (c) 2024, IBM Corporation.
6*31bfbc00SFrederic Barrat  *
7*31bfbc00SFrederic Barrat  * SPDX-License-Identifier: GPL-2.0-or-later
8*31bfbc00SFrederic Barrat  */
9*31bfbc00SFrederic Barrat #include "qemu/osdep.h"
10*31bfbc00SFrederic Barrat #include "libqtest.h"
11*31bfbc00SFrederic Barrat 
12*31bfbc00SFrederic Barrat #include "pnv-xive2-common.h"
13*31bfbc00SFrederic Barrat #include "hw/intc/pnv_xive2_regs.h"
14*31bfbc00SFrederic Barrat #include "hw/ppc/xive_regs.h"
15*31bfbc00SFrederic Barrat #include "hw/ppc/xive2_regs.h"
16*31bfbc00SFrederic Barrat 
17*31bfbc00SFrederic Barrat #define PNV_XIVE2_QUEUE_IPI              0x00
18*31bfbc00SFrederic Barrat #define PNV_XIVE2_QUEUE_HW               0x01
19*31bfbc00SFrederic Barrat #define PNV_XIVE2_QUEUE_NXC              0x02
20*31bfbc00SFrederic Barrat #define PNV_XIVE2_QUEUE_INT              0x03
21*31bfbc00SFrederic Barrat #define PNV_XIVE2_QUEUE_OS               0x04
22*31bfbc00SFrederic Barrat #define PNV_XIVE2_QUEUE_POOL             0x05
23*31bfbc00SFrederic Barrat #define PNV_XIVE2_QUEUE_HARD             0x06
24*31bfbc00SFrederic Barrat #define PNV_XIVE2_CACHE_ENDC             0x08
25*31bfbc00SFrederic Barrat #define PNV_XIVE2_CACHE_ESBC             0x09
26*31bfbc00SFrederic Barrat #define PNV_XIVE2_CACHE_EASC             0x0a
27*31bfbc00SFrederic Barrat #define PNV_XIVE2_QUEUE_NXC_LD_LCL_NCO   0x10
28*31bfbc00SFrederic Barrat #define PNV_XIVE2_QUEUE_NXC_LD_LCL_CO    0x11
29*31bfbc00SFrederic Barrat #define PNV_XIVE2_QUEUE_NXC_ST_LCL_NCI   0x12
30*31bfbc00SFrederic Barrat #define PNV_XIVE2_QUEUE_NXC_ST_LCL_CI    0x13
31*31bfbc00SFrederic Barrat #define PNV_XIVE2_QUEUE_NXC_ST_RMT_NCI   0x14
32*31bfbc00SFrederic Barrat #define PNV_XIVE2_QUEUE_NXC_ST_RMT_CI    0x15
33*31bfbc00SFrederic Barrat #define PNV_XIVE2_CACHE_NXC              0x18
34*31bfbc00SFrederic Barrat 
35*31bfbc00SFrederic Barrat #define PNV_XIVE2_SYNC_IPI              0x000
36*31bfbc00SFrederic Barrat #define PNV_XIVE2_SYNC_HW               0x080
37*31bfbc00SFrederic Barrat #define PNV_XIVE2_SYNC_NxC              0x100
38*31bfbc00SFrederic Barrat #define PNV_XIVE2_SYNC_INT              0x180
39*31bfbc00SFrederic Barrat #define PNV_XIVE2_SYNC_OS_ESC           0x200
40*31bfbc00SFrederic Barrat #define PNV_XIVE2_SYNC_POOL_ESC         0x280
41*31bfbc00SFrederic Barrat #define PNV_XIVE2_SYNC_HARD_ESC         0x300
42*31bfbc00SFrederic Barrat #define PNV_XIVE2_SYNC_NXC_LD_LCL_NCO   0x800
43*31bfbc00SFrederic Barrat #define PNV_XIVE2_SYNC_NXC_LD_LCL_CO    0x880
44*31bfbc00SFrederic Barrat #define PNV_XIVE2_SYNC_NXC_ST_LCL_NCI   0x900
45*31bfbc00SFrederic Barrat #define PNV_XIVE2_SYNC_NXC_ST_LCL_CI    0x980
46*31bfbc00SFrederic Barrat #define PNV_XIVE2_SYNC_NXC_ST_RMT_NCI   0xA00
47*31bfbc00SFrederic Barrat #define PNV_XIVE2_SYNC_NXC_ST_RMT_CI    0xA80
48*31bfbc00SFrederic Barrat 
49*31bfbc00SFrederic Barrat 
get_sync_addr(uint32_t src_pir,int ic_topo_id,int type)50*31bfbc00SFrederic Barrat static uint64_t get_sync_addr(uint32_t src_pir, int ic_topo_id, int type)
51*31bfbc00SFrederic Barrat {
52*31bfbc00SFrederic Barrat     int thread_nr = src_pir & 0x7f;
53*31bfbc00SFrederic Barrat     uint64_t addr = XIVE_SYNC_MEM +  thread_nr * 512 + ic_topo_id * 32 + type;
54*31bfbc00SFrederic Barrat     return addr;
55*31bfbc00SFrederic Barrat }
56*31bfbc00SFrederic Barrat 
get_sync(QTestState * qts,uint32_t src_pir,int ic_topo_id,int type)57*31bfbc00SFrederic Barrat static uint8_t get_sync(QTestState *qts, uint32_t src_pir, int ic_topo_id,
58*31bfbc00SFrederic Barrat                         int type)
59*31bfbc00SFrederic Barrat {
60*31bfbc00SFrederic Barrat     uint64_t addr = get_sync_addr(src_pir, ic_topo_id, type);
61*31bfbc00SFrederic Barrat     return qtest_readb(qts, addr);
62*31bfbc00SFrederic Barrat }
63*31bfbc00SFrederic Barrat 
clr_sync(QTestState * qts,uint32_t src_pir,int ic_topo_id,int type)64*31bfbc00SFrederic Barrat static void clr_sync(QTestState *qts, uint32_t src_pir, int ic_topo_id,
65*31bfbc00SFrederic Barrat                         int type)
66*31bfbc00SFrederic Barrat {
67*31bfbc00SFrederic Barrat     uint64_t addr = get_sync_addr(src_pir, ic_topo_id, type);
68*31bfbc00SFrederic Barrat     qtest_writeb(qts, addr, 0x0);
69*31bfbc00SFrederic Barrat }
70*31bfbc00SFrederic Barrat 
inject_cache_flush(QTestState * qts,int ic_topo_id,uint64_t scom_addr)71*31bfbc00SFrederic Barrat static void inject_cache_flush(QTestState *qts, int ic_topo_id,
72*31bfbc00SFrederic Barrat                                uint64_t scom_addr)
73*31bfbc00SFrederic Barrat {
74*31bfbc00SFrederic Barrat     (void)ic_topo_id;
75*31bfbc00SFrederic Barrat     pnv_xive_xscom_write(qts, scom_addr, 0);
76*31bfbc00SFrederic Barrat }
77*31bfbc00SFrederic Barrat 
inject_queue_sync(QTestState * qts,int ic_topo_id,uint64_t offset)78*31bfbc00SFrederic Barrat static void inject_queue_sync(QTestState *qts, int ic_topo_id, uint64_t offset)
79*31bfbc00SFrederic Barrat {
80*31bfbc00SFrederic Barrat     (void)ic_topo_id;
81*31bfbc00SFrederic Barrat     uint64_t addr = XIVE_IC_ADDR + (VST_SYNC << XIVE_PAGE_SHIFT) + offset;
82*31bfbc00SFrederic Barrat     qtest_writeq(qts, addr, 0);
83*31bfbc00SFrederic Barrat }
84*31bfbc00SFrederic Barrat 
inject_op(QTestState * qts,int ic_topo_id,int type)85*31bfbc00SFrederic Barrat static void inject_op(QTestState *qts, int ic_topo_id, int type)
86*31bfbc00SFrederic Barrat {
87*31bfbc00SFrederic Barrat     switch (type) {
88*31bfbc00SFrederic Barrat     case PNV_XIVE2_QUEUE_IPI:
89*31bfbc00SFrederic Barrat         inject_queue_sync(qts, ic_topo_id, PNV_XIVE2_SYNC_IPI);
90*31bfbc00SFrederic Barrat         break;
91*31bfbc00SFrederic Barrat     case PNV_XIVE2_QUEUE_HW:
92*31bfbc00SFrederic Barrat         inject_queue_sync(qts, ic_topo_id, PNV_XIVE2_SYNC_HW);
93*31bfbc00SFrederic Barrat         break;
94*31bfbc00SFrederic Barrat     case PNV_XIVE2_QUEUE_NXC:
95*31bfbc00SFrederic Barrat         inject_queue_sync(qts, ic_topo_id, PNV_XIVE2_SYNC_NxC);
96*31bfbc00SFrederic Barrat         break;
97*31bfbc00SFrederic Barrat     case PNV_XIVE2_QUEUE_INT:
98*31bfbc00SFrederic Barrat         inject_queue_sync(qts, ic_topo_id, PNV_XIVE2_SYNC_INT);
99*31bfbc00SFrederic Barrat         break;
100*31bfbc00SFrederic Barrat     case PNV_XIVE2_QUEUE_OS:
101*31bfbc00SFrederic Barrat         inject_queue_sync(qts, ic_topo_id, PNV_XIVE2_SYNC_OS_ESC);
102*31bfbc00SFrederic Barrat         break;
103*31bfbc00SFrederic Barrat     case PNV_XIVE2_QUEUE_POOL:
104*31bfbc00SFrederic Barrat         inject_queue_sync(qts, ic_topo_id, PNV_XIVE2_SYNC_POOL_ESC);
105*31bfbc00SFrederic Barrat         break;
106*31bfbc00SFrederic Barrat     case PNV_XIVE2_QUEUE_HARD:
107*31bfbc00SFrederic Barrat         inject_queue_sync(qts, ic_topo_id, PNV_XIVE2_SYNC_HARD_ESC);
108*31bfbc00SFrederic Barrat         break;
109*31bfbc00SFrederic Barrat     case PNV_XIVE2_CACHE_ENDC:
110*31bfbc00SFrederic Barrat         inject_cache_flush(qts, ic_topo_id, X_VC_ENDC_FLUSH_INJECT);
111*31bfbc00SFrederic Barrat         break;
112*31bfbc00SFrederic Barrat     case PNV_XIVE2_CACHE_ESBC:
113*31bfbc00SFrederic Barrat         inject_cache_flush(qts, ic_topo_id, X_VC_ESBC_FLUSH_INJECT);
114*31bfbc00SFrederic Barrat         break;
115*31bfbc00SFrederic Barrat     case PNV_XIVE2_CACHE_EASC:
116*31bfbc00SFrederic Barrat         inject_cache_flush(qts, ic_topo_id, X_VC_EASC_FLUSH_INJECT);
117*31bfbc00SFrederic Barrat         break;
118*31bfbc00SFrederic Barrat     case PNV_XIVE2_QUEUE_NXC_LD_LCL_NCO:
119*31bfbc00SFrederic Barrat         inject_queue_sync(qts, ic_topo_id, PNV_XIVE2_SYNC_NXC_LD_LCL_NCO);
120*31bfbc00SFrederic Barrat         break;
121*31bfbc00SFrederic Barrat     case PNV_XIVE2_QUEUE_NXC_LD_LCL_CO:
122*31bfbc00SFrederic Barrat         inject_queue_sync(qts, ic_topo_id, PNV_XIVE2_SYNC_NXC_LD_LCL_CO);
123*31bfbc00SFrederic Barrat         break;
124*31bfbc00SFrederic Barrat     case PNV_XIVE2_QUEUE_NXC_ST_LCL_NCI:
125*31bfbc00SFrederic Barrat         inject_queue_sync(qts, ic_topo_id, PNV_XIVE2_SYNC_NXC_ST_LCL_NCI);
126*31bfbc00SFrederic Barrat         break;
127*31bfbc00SFrederic Barrat     case PNV_XIVE2_QUEUE_NXC_ST_LCL_CI:
128*31bfbc00SFrederic Barrat         inject_queue_sync(qts, ic_topo_id, PNV_XIVE2_SYNC_NXC_ST_LCL_CI);
129*31bfbc00SFrederic Barrat         break;
130*31bfbc00SFrederic Barrat     case PNV_XIVE2_QUEUE_NXC_ST_RMT_NCI:
131*31bfbc00SFrederic Barrat         inject_queue_sync(qts, ic_topo_id, PNV_XIVE2_SYNC_NXC_ST_RMT_NCI);
132*31bfbc00SFrederic Barrat         break;
133*31bfbc00SFrederic Barrat     case PNV_XIVE2_QUEUE_NXC_ST_RMT_CI:
134*31bfbc00SFrederic Barrat         inject_queue_sync(qts, ic_topo_id, PNV_XIVE2_SYNC_NXC_ST_RMT_CI);
135*31bfbc00SFrederic Barrat         break;
136*31bfbc00SFrederic Barrat     case PNV_XIVE2_CACHE_NXC:
137*31bfbc00SFrederic Barrat         inject_cache_flush(qts, ic_topo_id, X_PC_NXC_FLUSH_INJECT);
138*31bfbc00SFrederic Barrat         break;
139*31bfbc00SFrederic Barrat     default:
140*31bfbc00SFrederic Barrat         g_assert_not_reached();
141*31bfbc00SFrederic Barrat         break;
142*31bfbc00SFrederic Barrat     }
143*31bfbc00SFrederic Barrat }
144*31bfbc00SFrederic Barrat 
145*31bfbc00SFrederic Barrat const uint8_t xive_inject_tests[] = {
146*31bfbc00SFrederic Barrat     PNV_XIVE2_QUEUE_IPI,
147*31bfbc00SFrederic Barrat     PNV_XIVE2_QUEUE_HW,
148*31bfbc00SFrederic Barrat     PNV_XIVE2_QUEUE_NXC,
149*31bfbc00SFrederic Barrat     PNV_XIVE2_QUEUE_INT,
150*31bfbc00SFrederic Barrat     PNV_XIVE2_QUEUE_OS,
151*31bfbc00SFrederic Barrat     PNV_XIVE2_QUEUE_POOL,
152*31bfbc00SFrederic Barrat     PNV_XIVE2_QUEUE_HARD,
153*31bfbc00SFrederic Barrat     PNV_XIVE2_CACHE_ENDC,
154*31bfbc00SFrederic Barrat     PNV_XIVE2_CACHE_ESBC,
155*31bfbc00SFrederic Barrat     PNV_XIVE2_CACHE_EASC,
156*31bfbc00SFrederic Barrat     PNV_XIVE2_QUEUE_NXC_LD_LCL_NCO,
157*31bfbc00SFrederic Barrat     PNV_XIVE2_QUEUE_NXC_LD_LCL_CO,
158*31bfbc00SFrederic Barrat     PNV_XIVE2_QUEUE_NXC_ST_LCL_NCI,
159*31bfbc00SFrederic Barrat     PNV_XIVE2_QUEUE_NXC_ST_LCL_CI,
160*31bfbc00SFrederic Barrat     PNV_XIVE2_QUEUE_NXC_ST_RMT_NCI,
161*31bfbc00SFrederic Barrat     PNV_XIVE2_QUEUE_NXC_ST_RMT_CI,
162*31bfbc00SFrederic Barrat     PNV_XIVE2_CACHE_NXC,
163*31bfbc00SFrederic Barrat };
164*31bfbc00SFrederic Barrat 
test_flush_sync_inject(QTestState * qts)165*31bfbc00SFrederic Barrat void test_flush_sync_inject(QTestState *qts)
166*31bfbc00SFrederic Barrat {
167*31bfbc00SFrederic Barrat     int ic_topo_id = 0;
168*31bfbc00SFrederic Barrat 
169*31bfbc00SFrederic Barrat     /*
170*31bfbc00SFrederic Barrat      * Writes performed by qtest are not done in the context of a thread.
171*31bfbc00SFrederic Barrat      * This means that QEMU XIVE code doesn't have a way to determine what
172*31bfbc00SFrederic Barrat      * thread is originating the write.  In order to allow for some testing,
173*31bfbc00SFrederic Barrat      * QEMU XIVE code will assume a PIR of 0 when unable to determine the
174*31bfbc00SFrederic Barrat      * source thread for cache flush and queue sync inject operations.
175*31bfbc00SFrederic Barrat      * See hw/intc/pnv_xive2.c: pnv_xive2_inject_notify() for details.
176*31bfbc00SFrederic Barrat      */
177*31bfbc00SFrederic Barrat     int src_pir = 0;
178*31bfbc00SFrederic Barrat     int test_nr;
179*31bfbc00SFrederic Barrat     uint8_t byte;
180*31bfbc00SFrederic Barrat 
181*31bfbc00SFrederic Barrat     printf("# ============================================================\n");
182*31bfbc00SFrederic Barrat     printf("# Starting cache flush/queue sync injection tests...\n");
183*31bfbc00SFrederic Barrat 
184*31bfbc00SFrederic Barrat     for (test_nr = 0; test_nr < sizeof(xive_inject_tests);
185*31bfbc00SFrederic Barrat          test_nr++) {
186*31bfbc00SFrederic Barrat         int op_type = xive_inject_tests[test_nr];
187*31bfbc00SFrederic Barrat 
188*31bfbc00SFrederic Barrat         printf("# Running test %d\n", test_nr);
189*31bfbc00SFrederic Barrat 
190*31bfbc00SFrederic Barrat         /* start with status byte set to 0 */
191*31bfbc00SFrederic Barrat         clr_sync(qts, src_pir, ic_topo_id, op_type);
192*31bfbc00SFrederic Barrat         byte = get_sync(qts, src_pir, ic_topo_id, op_type);
193*31bfbc00SFrederic Barrat         g_assert_cmphex(byte, ==, 0);
194*31bfbc00SFrederic Barrat 
195*31bfbc00SFrederic Barrat         /* request cache flush or queue sync operation */
196*31bfbc00SFrederic Barrat         inject_op(qts, ic_topo_id, op_type);
197*31bfbc00SFrederic Barrat 
198*31bfbc00SFrederic Barrat         /* verify that status byte was written to 0xff */
199*31bfbc00SFrederic Barrat         byte = get_sync(qts, src_pir, ic_topo_id, op_type);
200*31bfbc00SFrederic Barrat         g_assert_cmphex(byte, ==, 0xff);
201*31bfbc00SFrederic Barrat 
202*31bfbc00SFrederic Barrat         clr_sync(qts, src_pir, ic_topo_id, op_type);
203*31bfbc00SFrederic Barrat     }
204*31bfbc00SFrederic Barrat }
205*31bfbc00SFrederic Barrat 
206