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