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 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 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