xref: /qemu/tests/qtest/pnv-xive2-nvpg_bar.c (revision 71569cd8aba31fcb3a326c56c307d2b811417c0b)
1 /*
2  * QTest testcase for PowerNV 10 interrupt controller (xive2)
3  *  - Test NVPG BAR MMIO operations
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 
14 #define NVPG_BACKLOG_OP_SHIFT   10
15 #define NVPG_BACKLOG_PRIO_SHIFT 4
16 
17 #define XIVE_PRIORITY_MAX       7
18 
19 enum NVx {
20     NVP,
21     NVG,
22     NVC
23 };
24 
25 typedef enum {
26     INCR_STORE = 0b100,
27     INCR_LOAD  = 0b000,
28     DECR_STORE = 0b101,
29     DECR_LOAD  = 0b001,
30     READ_x     = 0b010,
31     READ_y     = 0b011,
32 } backlog_op;
33 
nvpg_backlog_op(QTestState * qts,backlog_op op,enum NVx type,uint64_t index,uint8_t priority,uint8_t delta)34 static uint32_t nvpg_backlog_op(QTestState *qts, backlog_op op,
35                                 enum NVx type, uint64_t index,
36                                 uint8_t priority, uint8_t delta)
37 {
38     uint64_t addr, offset;
39     uint32_t count = 0;
40 
41     switch (type) {
42     case NVP:
43         addr = XIVE_NVPG_ADDR + (index << (XIVE_PAGE_SHIFT + 1));
44         break;
45     case NVG:
46         addr = XIVE_NVPG_ADDR + (index << (XIVE_PAGE_SHIFT + 1)) +
47             (1 << XIVE_PAGE_SHIFT);
48         break;
49     case NVC:
50         addr = XIVE_NVC_ADDR + (index << XIVE_PAGE_SHIFT);
51         break;
52     default:
53         g_assert_not_reached();
54     }
55 
56     offset = (op & 0b11) << NVPG_BACKLOG_OP_SHIFT;
57     offset |= priority << NVPG_BACKLOG_PRIO_SHIFT;
58     if (op >> 2) {
59         qtest_writeb(qts, addr + offset, delta);
60     } else {
61         count = qtest_readw(qts, addr + offset);
62     }
63     return count;
64 }
65 
test_nvpg_bar(QTestState * qts)66 void test_nvpg_bar(QTestState *qts)
67 {
68     uint32_t nvp_target = 0x11;
69     uint32_t group_target = 0x17; /* size 16 */
70     uint32_t vp_irq = 33, group_irq = 47;
71     uint32_t vp_end = 3, group_end = 97;
72     uint32_t vp_irq_data = 0x33333333;
73     uint32_t group_irq_data = 0x66666666;
74     uint8_t vp_priority = 0, group_priority = 5;
75     uint32_t vp_count[XIVE_PRIORITY_MAX + 1] = { 0 };
76     uint32_t group_count[XIVE_PRIORITY_MAX + 1] = { 0 };
77     uint32_t count, delta;
78     uint8_t i;
79 
80     g_test_message("=========================================================");
81     g_test_message("Testing NVPG BAR operations");
82 
83     set_nvg(qts, group_target, 0);
84     set_nvp(qts, nvp_target, 0x04);
85     set_nvp(qts, group_target, 0x04);
86 
87     /*
88      * Setup: trigger a VP-specific interrupt and a group interrupt
89      * so that the backlog counters are initialized to something else
90      * than 0 for at least one priority level
91      */
92     set_eas(qts, vp_irq, vp_end, vp_irq_data);
93     set_end(qts, vp_end, nvp_target, vp_priority, false /* group */);
94 
95     set_eas(qts, group_irq, group_end, group_irq_data);
96     set_end(qts, group_end, group_target, group_priority, true /* group */);
97 
98     get_esb(qts, vp_irq, XIVE_EOI_PAGE, XIVE_ESB_SET_PQ_00);
99     set_esb(qts, vp_irq, XIVE_TRIGGER_PAGE, 0, 0);
100     vp_count[vp_priority]++;
101 
102     get_esb(qts, group_irq, XIVE_EOI_PAGE, XIVE_ESB_SET_PQ_00);
103     set_esb(qts, group_irq, XIVE_TRIGGER_PAGE, 0, 0);
104     group_count[group_priority]++;
105 
106     /* check the initial counters */
107     for (i = 0; i <= XIVE_PRIORITY_MAX; i++) {
108         count = nvpg_backlog_op(qts, READ_x, NVP, nvp_target, i, 0);
109         g_assert_cmpuint(count, ==, vp_count[i]);
110 
111         count = nvpg_backlog_op(qts, READ_y, NVG, group_target, i, 0);
112         g_assert_cmpuint(count, ==, group_count[i]);
113     }
114 
115     /* do a few ops on the VP. Counter can only be 0 and 1 */
116     vp_priority = 2;
117     delta = 7;
118     nvpg_backlog_op(qts, INCR_STORE, NVP, nvp_target, vp_priority, delta);
119     vp_count[vp_priority] = 1;
120     count = nvpg_backlog_op(qts, INCR_LOAD, NVP, nvp_target, vp_priority, 0);
121     g_assert_cmpuint(count, ==, vp_count[vp_priority]);
122     count = nvpg_backlog_op(qts, READ_y, NVP, nvp_target, vp_priority, 0);
123     g_assert_cmpuint(count, ==, vp_count[vp_priority]);
124 
125     count = nvpg_backlog_op(qts, DECR_LOAD, NVP, nvp_target, vp_priority, 0);
126     g_assert_cmpuint(count, ==, vp_count[vp_priority]);
127     vp_count[vp_priority] = 0;
128     nvpg_backlog_op(qts, DECR_STORE, NVP, nvp_target, vp_priority, delta);
129     count = nvpg_backlog_op(qts, READ_x, NVP, nvp_target, vp_priority, 0);
130     g_assert_cmpuint(count, ==, vp_count[vp_priority]);
131 
132     /* do a few ops on the group */
133     group_priority = 2;
134     delta = 9;
135     /* can't go negative */
136     nvpg_backlog_op(qts, DECR_STORE, NVG, group_target, group_priority, delta);
137     count = nvpg_backlog_op(qts, READ_y, NVG, group_target, group_priority, 0);
138     g_assert_cmpuint(count, ==, 0);
139     nvpg_backlog_op(qts, INCR_STORE, NVG, group_target, group_priority, delta);
140     group_count[group_priority] += delta;
141     count = nvpg_backlog_op(qts, INCR_LOAD, NVG, group_target,
142                             group_priority, delta);
143     g_assert_cmpuint(count, ==, group_count[group_priority]);
144     group_count[group_priority]++;
145 
146     count = nvpg_backlog_op(qts, DECR_LOAD, NVG, group_target,
147                             group_priority, delta);
148     g_assert_cmpuint(count, ==,  group_count[group_priority]);
149     group_count[group_priority]--;
150     count = nvpg_backlog_op(qts, READ_x, NVG, group_target, group_priority, 0);
151     g_assert_cmpuint(count, ==, group_count[group_priority]);
152 }
153