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