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