1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
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);
}
}
|