aboutsummaryrefslogtreecommitdiff
path: root/tests/qtest/pnv-xive2-flush-sync.c
blob: 3b32446adba2160e4b05f02f98aec850f63c747b (plain)
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);
    }
}