131bfbc00SFrederic Barrat /* 231bfbc00SFrederic Barrat * QTest testcase for PowerNV 10 interrupt controller (xive2) 331bfbc00SFrederic Barrat * - Test irq to hardware thread 431bfbc00SFrederic Barrat * - Test 'Pull Thread Context to Odd Thread Reporting Line' 5c2b7fadeSFrederic Barrat * - Test irq to hardware group 6c2b7fadeSFrederic Barrat * - Test irq to hardware group going through backlog 7c4b50387SGlenn Miles * - Test irq to pool thread 831bfbc00SFrederic Barrat * 931bfbc00SFrederic Barrat * Copyright (c) 2024, IBM Corporation. 1031bfbc00SFrederic Barrat * 1131bfbc00SFrederic Barrat * SPDX-License-Identifier: GPL-2.0-or-later 1231bfbc00SFrederic Barrat */ 1331bfbc00SFrederic Barrat #include "qemu/osdep.h" 1431bfbc00SFrederic Barrat #include "libqtest.h" 1531bfbc00SFrederic Barrat 1631bfbc00SFrederic Barrat #include "pnv-xive2-common.h" 1731bfbc00SFrederic Barrat #include "hw/intc/pnv_xive2_regs.h" 1831bfbc00SFrederic Barrat #include "hw/ppc/xive_regs.h" 1931bfbc00SFrederic Barrat #include "hw/ppc/xive2_regs.h" 2031bfbc00SFrederic Barrat 2131bfbc00SFrederic Barrat #define SMT 4 /* some tests will break if less than 4 */ 2231bfbc00SFrederic Barrat 2331bfbc00SFrederic Barrat 2431bfbc00SFrederic Barrat static void set_table(QTestState *qts, uint64_t type, uint64_t addr) 2531bfbc00SFrederic Barrat { 2631bfbc00SFrederic Barrat uint64_t vsd, size, log_size; 2731bfbc00SFrederic Barrat 2831bfbc00SFrederic Barrat /* 2931bfbc00SFrederic Barrat * First, let's make sure that all the resources used fit in the 3031bfbc00SFrederic Barrat * given table. 3131bfbc00SFrederic Barrat */ 3231bfbc00SFrederic Barrat switch (type) { 3331bfbc00SFrederic Barrat case VST_ESB: 3431bfbc00SFrederic Barrat size = MAX_IRQS / 4; 3531bfbc00SFrederic Barrat break; 3631bfbc00SFrederic Barrat case VST_EAS: 3731bfbc00SFrederic Barrat size = MAX_IRQS * 8; 3831bfbc00SFrederic Barrat break; 3931bfbc00SFrederic Barrat case VST_END: 4031bfbc00SFrederic Barrat size = MAX_ENDS * 32; 4131bfbc00SFrederic Barrat break; 4231bfbc00SFrederic Barrat case VST_NVP: 4331bfbc00SFrederic Barrat case VST_NVG: 4431bfbc00SFrederic Barrat case VST_NVC: 4531bfbc00SFrederic Barrat size = MAX_VPS * 32; 4631bfbc00SFrederic Barrat break; 4731bfbc00SFrederic Barrat case VST_SYNC: 4831bfbc00SFrederic Barrat size = 64 * 1024; 4931bfbc00SFrederic Barrat break; 5031bfbc00SFrederic Barrat default: 5131bfbc00SFrederic Barrat g_assert_not_reached(); 5231bfbc00SFrederic Barrat } 5331bfbc00SFrederic Barrat 5431bfbc00SFrederic Barrat g_assert_cmpuint(size, <=, XIVE_VST_SIZE); 5531bfbc00SFrederic Barrat log_size = ctzl(XIVE_VST_SIZE) - 12; 5631bfbc00SFrederic Barrat 5731bfbc00SFrederic Barrat vsd = ((uint64_t) VSD_MODE_EXCLUSIVE) << 62 | addr | log_size; 5831bfbc00SFrederic Barrat pnv_xive_xscom_write(qts, X_VC_VSD_TABLE_ADDR, type << 48); 5931bfbc00SFrederic Barrat pnv_xive_xscom_write(qts, X_VC_VSD_TABLE_DATA, vsd); 6031bfbc00SFrederic Barrat 6131bfbc00SFrederic Barrat if (type != VST_EAS && type != VST_IC && type != VST_ERQ) { 6231bfbc00SFrederic Barrat pnv_xive_xscom_write(qts, X_PC_VSD_TABLE_ADDR, type << 48); 6331bfbc00SFrederic Barrat pnv_xive_xscom_write(qts, X_PC_VSD_TABLE_DATA, vsd); 6431bfbc00SFrederic Barrat } 6531bfbc00SFrederic Barrat } 6631bfbc00SFrederic Barrat 6731bfbc00SFrederic Barrat static void set_tima8(QTestState *qts, uint32_t pir, uint32_t offset, 6831bfbc00SFrederic Barrat uint8_t b) 6931bfbc00SFrederic Barrat { 7031bfbc00SFrederic Barrat uint64_t ic_addr; 7131bfbc00SFrederic Barrat 7231bfbc00SFrederic Barrat ic_addr = XIVE_IC_TM_INDIRECT + (pir << XIVE_PAGE_SHIFT); 7331bfbc00SFrederic Barrat qtest_writeb(qts, ic_addr + offset, b); 7431bfbc00SFrederic Barrat } 7531bfbc00SFrederic Barrat 7631bfbc00SFrederic Barrat static void set_tima32(QTestState *qts, uint32_t pir, uint32_t offset, 7731bfbc00SFrederic Barrat uint32_t l) 7831bfbc00SFrederic Barrat { 7931bfbc00SFrederic Barrat uint64_t ic_addr; 8031bfbc00SFrederic Barrat 8131bfbc00SFrederic Barrat ic_addr = XIVE_IC_TM_INDIRECT + (pir << XIVE_PAGE_SHIFT); 8231bfbc00SFrederic Barrat qtest_writel(qts, ic_addr + offset, l); 8331bfbc00SFrederic Barrat } 8431bfbc00SFrederic Barrat 8531bfbc00SFrederic Barrat static uint8_t get_tima8(QTestState *qts, uint32_t pir, uint32_t offset) 8631bfbc00SFrederic Barrat { 8731bfbc00SFrederic Barrat uint64_t ic_addr; 8831bfbc00SFrederic Barrat 8931bfbc00SFrederic Barrat ic_addr = XIVE_IC_TM_INDIRECT + (pir << XIVE_PAGE_SHIFT); 9031bfbc00SFrederic Barrat return qtest_readb(qts, ic_addr + offset); 9131bfbc00SFrederic Barrat } 9231bfbc00SFrederic Barrat 9331bfbc00SFrederic Barrat static uint16_t get_tima16(QTestState *qts, uint32_t pir, uint32_t offset) 9431bfbc00SFrederic Barrat { 9531bfbc00SFrederic Barrat uint64_t ic_addr; 9631bfbc00SFrederic Barrat 9731bfbc00SFrederic Barrat ic_addr = XIVE_IC_TM_INDIRECT + (pir << XIVE_PAGE_SHIFT); 9831bfbc00SFrederic Barrat return qtest_readw(qts, ic_addr + offset); 9931bfbc00SFrederic Barrat } 10031bfbc00SFrederic Barrat 10131bfbc00SFrederic Barrat static uint32_t get_tima32(QTestState *qts, uint32_t pir, uint32_t offset) 10231bfbc00SFrederic Barrat { 10331bfbc00SFrederic Barrat uint64_t ic_addr; 10431bfbc00SFrederic Barrat 10531bfbc00SFrederic Barrat ic_addr = XIVE_IC_TM_INDIRECT + (pir << XIVE_PAGE_SHIFT); 10631bfbc00SFrederic Barrat return qtest_readl(qts, ic_addr + offset); 10731bfbc00SFrederic Barrat } 10831bfbc00SFrederic Barrat 10931bfbc00SFrederic Barrat static void reset_pool_threads(QTestState *qts) 11031bfbc00SFrederic Barrat { 11131bfbc00SFrederic Barrat uint8_t first_group = 0; 11231bfbc00SFrederic Barrat int i; 11331bfbc00SFrederic Barrat 11431bfbc00SFrederic Barrat for (i = 0; i < SMT; i++) { 11531bfbc00SFrederic Barrat uint32_t nvp_idx = 0x100 + i; 11631bfbc00SFrederic Barrat set_nvp(qts, nvp_idx, first_group); 11731bfbc00SFrederic Barrat set_tima32(qts, i, TM_QW2_HV_POOL + TM_WORD0, 0x000000ff); 11831bfbc00SFrederic Barrat set_tima32(qts, i, TM_QW2_HV_POOL + TM_WORD1, 0); 11931bfbc00SFrederic Barrat set_tima32(qts, i, TM_QW2_HV_POOL + TM_WORD2, TM_QW2W2_VP | nvp_idx); 12031bfbc00SFrederic Barrat } 12131bfbc00SFrederic Barrat } 12231bfbc00SFrederic Barrat 12331bfbc00SFrederic Barrat static void reset_hw_threads(QTestState *qts) 12431bfbc00SFrederic Barrat { 12531bfbc00SFrederic Barrat uint8_t first_group = 0; 12631bfbc00SFrederic Barrat uint32_t w1 = 0x000000ff; 12731bfbc00SFrederic Barrat int i; 12831bfbc00SFrederic Barrat 12931bfbc00SFrederic Barrat if (SMT >= 4) { 13031bfbc00SFrederic Barrat /* define 2 groups of 2, part of a bigger group of size 4 */ 13131bfbc00SFrederic Barrat set_nvg(qts, 0x80, 0x02); 13231bfbc00SFrederic Barrat set_nvg(qts, 0x82, 0x02); 13331bfbc00SFrederic Barrat set_nvg(qts, 0x81, 0); 13431bfbc00SFrederic Barrat first_group = 0x01; 13531bfbc00SFrederic Barrat w1 = 0x000300ff; 13631bfbc00SFrederic Barrat } 13731bfbc00SFrederic Barrat 13831bfbc00SFrederic Barrat for (i = 0; i < SMT; i++) { 13931bfbc00SFrederic Barrat set_nvp(qts, 0x80 + i, first_group); 14031bfbc00SFrederic Barrat set_tima32(qts, i, TM_QW3_HV_PHYS + TM_WORD0, 0x00ff00ff); 14131bfbc00SFrederic Barrat set_tima32(qts, i, TM_QW3_HV_PHYS + TM_WORD1, w1); 14231bfbc00SFrederic Barrat set_tima32(qts, i, TM_QW3_HV_PHYS + TM_WORD2, 0x80000000); 14331bfbc00SFrederic Barrat } 14431bfbc00SFrederic Barrat } 14531bfbc00SFrederic Barrat 14631bfbc00SFrederic Barrat static void reset_state(QTestState *qts) 14731bfbc00SFrederic Barrat { 14831bfbc00SFrederic Barrat size_t mem_used = XIVE_MEM_END - XIVE_MEM_START; 14931bfbc00SFrederic Barrat 15031bfbc00SFrederic Barrat qtest_memset(qts, XIVE_MEM_START, 0, mem_used); 15131bfbc00SFrederic Barrat reset_hw_threads(qts); 15231bfbc00SFrederic Barrat reset_pool_threads(qts); 15331bfbc00SFrederic Barrat } 15431bfbc00SFrederic Barrat 15531bfbc00SFrederic Barrat static void init_xive(QTestState *qts) 15631bfbc00SFrederic Barrat { 15731bfbc00SFrederic Barrat uint64_t val1, val2, range; 15831bfbc00SFrederic Barrat 15931bfbc00SFrederic Barrat /* 16031bfbc00SFrederic Barrat * We can take a few shortcuts here, as we know the default values 16131bfbc00SFrederic Barrat * used for xive initialization 16231bfbc00SFrederic Barrat */ 16331bfbc00SFrederic Barrat 16431bfbc00SFrederic Barrat /* 16531bfbc00SFrederic Barrat * Set the BARs. 16631bfbc00SFrederic Barrat * We reuse the same values used by firmware to ease debug. 16731bfbc00SFrederic Barrat */ 16831bfbc00SFrederic Barrat pnv_xive_xscom_write(qts, X_CQ_IC_BAR, XIVE_IC_BAR); 16931bfbc00SFrederic Barrat pnv_xive_xscom_write(qts, X_CQ_TM_BAR, XIVE_TM_BAR); 17031bfbc00SFrederic Barrat 17131bfbc00SFrederic Barrat /* ESB and NVPG use 2 pages per resource. The others only one page */ 17231bfbc00SFrederic Barrat range = (MAX_IRQS << 17) >> 25; 17331bfbc00SFrederic Barrat val1 = XIVE_ESB_BAR | range; 17431bfbc00SFrederic Barrat pnv_xive_xscom_write(qts, X_CQ_ESB_BAR, val1); 17531bfbc00SFrederic Barrat 17631bfbc00SFrederic Barrat range = (MAX_ENDS << 16) >> 25; 17731bfbc00SFrederic Barrat val1 = XIVE_END_BAR | range; 17831bfbc00SFrederic Barrat pnv_xive_xscom_write(qts, X_CQ_END_BAR, val1); 17931bfbc00SFrederic Barrat 18031bfbc00SFrederic Barrat range = (MAX_VPS << 17) >> 25; 18131bfbc00SFrederic Barrat val1 = XIVE_NVPG_BAR | range; 18231bfbc00SFrederic Barrat pnv_xive_xscom_write(qts, X_CQ_NVPG_BAR, val1); 18331bfbc00SFrederic Barrat 18431bfbc00SFrederic Barrat range = (MAX_VPS << 16) >> 25; 18531bfbc00SFrederic Barrat val1 = XIVE_NVC_BAR | range; 18631bfbc00SFrederic Barrat pnv_xive_xscom_write(qts, X_CQ_NVC_BAR, val1); 18731bfbc00SFrederic Barrat 18831bfbc00SFrederic Barrat /* 18931bfbc00SFrederic Barrat * Enable hw threads. 19031bfbc00SFrederic Barrat * We check the value written. Useless with current 19131bfbc00SFrederic Barrat * implementation, but it validates the xscom read path and it's 19231bfbc00SFrederic Barrat * what the hardware procedure says 19331bfbc00SFrederic Barrat */ 19431bfbc00SFrederic Barrat val1 = 0xF000000000000000ull; /* core 0, 4 threads */ 19531bfbc00SFrederic Barrat pnv_xive_xscom_write(qts, X_TCTXT_EN0, val1); 19631bfbc00SFrederic Barrat val2 = pnv_xive_xscom_read(qts, X_TCTXT_EN0); 19731bfbc00SFrederic Barrat g_assert_cmphex(val1, ==, val2); 19831bfbc00SFrederic Barrat 19931bfbc00SFrederic Barrat /* Memory tables */ 20031bfbc00SFrederic Barrat set_table(qts, VST_ESB, XIVE_ESB_MEM); 20131bfbc00SFrederic Barrat set_table(qts, VST_EAS, XIVE_EAS_MEM); 20231bfbc00SFrederic Barrat set_table(qts, VST_END, XIVE_END_MEM); 20331bfbc00SFrederic Barrat set_table(qts, VST_NVP, XIVE_NVP_MEM); 20431bfbc00SFrederic Barrat set_table(qts, VST_NVG, XIVE_NVG_MEM); 20531bfbc00SFrederic Barrat set_table(qts, VST_NVC, XIVE_NVC_MEM); 20631bfbc00SFrederic Barrat set_table(qts, VST_SYNC, XIVE_SYNC_MEM); 20731bfbc00SFrederic Barrat 20831bfbc00SFrederic Barrat reset_hw_threads(qts); 20931bfbc00SFrederic Barrat reset_pool_threads(qts); 21031bfbc00SFrederic Barrat } 21131bfbc00SFrederic Barrat 21231bfbc00SFrederic Barrat static void test_hw_irq(QTestState *qts) 21331bfbc00SFrederic Barrat { 21431bfbc00SFrederic Barrat uint32_t irq = 2; 21531bfbc00SFrederic Barrat uint32_t irq_data = 0x600df00d; 21631bfbc00SFrederic Barrat uint32_t end_index = 5; 21731bfbc00SFrederic Barrat uint32_t target_pir = 1; 21831bfbc00SFrederic Barrat uint32_t target_nvp = 0x80 + target_pir; 21931bfbc00SFrederic Barrat uint8_t priority = 5; 22031bfbc00SFrederic Barrat uint32_t reg32; 22131bfbc00SFrederic Barrat uint16_t reg16; 22231bfbc00SFrederic Barrat uint8_t pq, nsr, cppr; 22331bfbc00SFrederic Barrat 224c4b50387SGlenn Miles g_test_message("========================================================="); 225c4b50387SGlenn Miles g_test_message("Testing irq %d to hardware thread %d", irq, target_pir); 22631bfbc00SFrederic Barrat 22731bfbc00SFrederic Barrat /* irq config */ 22831bfbc00SFrederic Barrat set_eas(qts, irq, end_index, irq_data); 22931bfbc00SFrederic Barrat set_end(qts, end_index, target_nvp, priority, false /* group */); 23031bfbc00SFrederic Barrat 23131bfbc00SFrederic Barrat /* enable and trigger irq */ 23231bfbc00SFrederic Barrat get_esb(qts, irq, XIVE_EOI_PAGE, XIVE_ESB_SET_PQ_00); 23331bfbc00SFrederic Barrat set_esb(qts, irq, XIVE_TRIGGER_PAGE, 0, 0); 23431bfbc00SFrederic Barrat 23531bfbc00SFrederic Barrat /* check irq is raised on cpu */ 23631bfbc00SFrederic Barrat pq = get_esb(qts, irq, XIVE_EOI_PAGE, XIVE_ESB_GET); 23731bfbc00SFrederic Barrat g_assert_cmpuint(pq, ==, XIVE_ESB_PENDING); 23831bfbc00SFrederic Barrat 23931bfbc00SFrederic Barrat reg32 = get_tima32(qts, target_pir, TM_QW3_HV_PHYS + TM_WORD0); 24031bfbc00SFrederic Barrat nsr = reg32 >> 24; 24131bfbc00SFrederic Barrat cppr = (reg32 >> 16) & 0xFF; 24231bfbc00SFrederic Barrat g_assert_cmphex(nsr, ==, 0x80); 24331bfbc00SFrederic Barrat g_assert_cmphex(cppr, ==, 0xFF); 24431bfbc00SFrederic Barrat 24531bfbc00SFrederic Barrat /* ack the irq */ 24631bfbc00SFrederic Barrat reg16 = get_tima16(qts, target_pir, TM_SPC_ACK_HV_REG); 24731bfbc00SFrederic Barrat nsr = reg16 >> 8; 24831bfbc00SFrederic Barrat cppr = reg16 & 0xFF; 24931bfbc00SFrederic Barrat g_assert_cmphex(nsr, ==, 0x80); 25031bfbc00SFrederic Barrat g_assert_cmphex(cppr, ==, priority); 25131bfbc00SFrederic Barrat 25231bfbc00SFrederic Barrat /* check irq data is what was configured */ 25331bfbc00SFrederic Barrat reg32 = qtest_readl(qts, xive_get_queue_addr(end_index)); 25431bfbc00SFrederic Barrat g_assert_cmphex((reg32 & 0x7fffffff), ==, (irq_data & 0x7fffffff)); 25531bfbc00SFrederic Barrat 25631bfbc00SFrederic Barrat /* End Of Interrupt */ 25731bfbc00SFrederic Barrat set_esb(qts, irq, XIVE_EOI_PAGE, XIVE_ESB_STORE_EOI, 0); 25831bfbc00SFrederic Barrat pq = get_esb(qts, irq, XIVE_EOI_PAGE, XIVE_ESB_GET); 25931bfbc00SFrederic Barrat g_assert_cmpuint(pq, ==, XIVE_ESB_RESET); 26031bfbc00SFrederic Barrat 26131bfbc00SFrederic Barrat /* reset CPPR */ 26231bfbc00SFrederic Barrat set_tima8(qts, target_pir, TM_QW3_HV_PHYS + TM_CPPR, 0xFF); 26331bfbc00SFrederic Barrat reg32 = get_tima32(qts, target_pir, TM_QW3_HV_PHYS + TM_WORD0); 26431bfbc00SFrederic Barrat nsr = reg32 >> 24; 26531bfbc00SFrederic Barrat cppr = (reg32 >> 16) & 0xFF; 26631bfbc00SFrederic Barrat g_assert_cmphex(nsr, ==, 0x00); 26731bfbc00SFrederic Barrat g_assert_cmphex(cppr, ==, 0xFF); 26831bfbc00SFrederic Barrat } 26931bfbc00SFrederic Barrat 270*ffc2cabeSGlenn Miles static void test_pool_irq(QTestState *qts) 271*ffc2cabeSGlenn Miles { 272*ffc2cabeSGlenn Miles uint32_t irq = 2; 273*ffc2cabeSGlenn Miles uint32_t irq_data = 0x600d0d06; 274*ffc2cabeSGlenn Miles uint32_t end_index = 5; 275*ffc2cabeSGlenn Miles uint32_t target_pir = 1; 276*ffc2cabeSGlenn Miles uint32_t target_nvp = 0x100 + target_pir; 277*ffc2cabeSGlenn Miles uint8_t priority = 5; 278*ffc2cabeSGlenn Miles uint32_t reg32; 279*ffc2cabeSGlenn Miles uint16_t reg16; 280*ffc2cabeSGlenn Miles uint8_t pq, nsr, cppr, ipb; 281*ffc2cabeSGlenn Miles 282*ffc2cabeSGlenn Miles g_test_message("========================================================="); 283*ffc2cabeSGlenn Miles g_test_message("Testing irq %d to pool thread %d", irq, target_pir); 284*ffc2cabeSGlenn Miles 285*ffc2cabeSGlenn Miles /* irq config */ 286*ffc2cabeSGlenn Miles set_eas(qts, irq, end_index, irq_data); 287*ffc2cabeSGlenn Miles set_end(qts, end_index, target_nvp, priority, false /* group */); 288*ffc2cabeSGlenn Miles 289*ffc2cabeSGlenn Miles /* enable and trigger irq */ 290*ffc2cabeSGlenn Miles get_esb(qts, irq, XIVE_EOI_PAGE, XIVE_ESB_SET_PQ_00); 291*ffc2cabeSGlenn Miles set_esb(qts, irq, XIVE_TRIGGER_PAGE, 0, 0); 292*ffc2cabeSGlenn Miles 293*ffc2cabeSGlenn Miles /* check irq is raised on cpu */ 294*ffc2cabeSGlenn Miles pq = get_esb(qts, irq, XIVE_EOI_PAGE, XIVE_ESB_GET); 295*ffc2cabeSGlenn Miles g_assert_cmpuint(pq, ==, XIVE_ESB_PENDING); 296*ffc2cabeSGlenn Miles 297*ffc2cabeSGlenn Miles /* check TIMA values in the PHYS ring (shared by POOL ring) */ 298*ffc2cabeSGlenn Miles reg32 = get_tima32(qts, target_pir, TM_QW3_HV_PHYS + TM_WORD0); 299*ffc2cabeSGlenn Miles nsr = reg32 >> 24; 300*ffc2cabeSGlenn Miles cppr = (reg32 >> 16) & 0xFF; 301*ffc2cabeSGlenn Miles g_assert_cmphex(nsr, ==, 0x40); 302*ffc2cabeSGlenn Miles g_assert_cmphex(cppr, ==, 0xFF); 303*ffc2cabeSGlenn Miles 304*ffc2cabeSGlenn Miles /* check TIMA values in the POOL ring */ 305*ffc2cabeSGlenn Miles reg32 = get_tima32(qts, target_pir, TM_QW2_HV_POOL + TM_WORD0); 306*ffc2cabeSGlenn Miles nsr = reg32 >> 24; 307*ffc2cabeSGlenn Miles cppr = (reg32 >> 16) & 0xFF; 308*ffc2cabeSGlenn Miles ipb = (reg32 >> 8) & 0xFF; 309*ffc2cabeSGlenn Miles g_assert_cmphex(nsr, ==, 0); 310*ffc2cabeSGlenn Miles g_assert_cmphex(cppr, ==, 0); 311*ffc2cabeSGlenn Miles g_assert_cmphex(ipb, ==, 0x80 >> priority); 312*ffc2cabeSGlenn Miles 313*ffc2cabeSGlenn Miles /* ack the irq */ 314*ffc2cabeSGlenn Miles reg16 = get_tima16(qts, target_pir, TM_SPC_ACK_HV_REG); 315*ffc2cabeSGlenn Miles nsr = reg16 >> 8; 316*ffc2cabeSGlenn Miles cppr = reg16 & 0xFF; 317*ffc2cabeSGlenn Miles g_assert_cmphex(nsr, ==, 0x40); 318*ffc2cabeSGlenn Miles g_assert_cmphex(cppr, ==, priority); 319*ffc2cabeSGlenn Miles 320*ffc2cabeSGlenn Miles /* check irq data is what was configured */ 321*ffc2cabeSGlenn Miles reg32 = qtest_readl(qts, xive_get_queue_addr(end_index)); 322*ffc2cabeSGlenn Miles g_assert_cmphex((reg32 & 0x7fffffff), ==, (irq_data & 0x7fffffff)); 323*ffc2cabeSGlenn Miles 324*ffc2cabeSGlenn Miles /* check IPB is cleared in the POOL ring */ 325*ffc2cabeSGlenn Miles reg32 = get_tima32(qts, target_pir, TM_QW2_HV_POOL + TM_WORD0); 326*ffc2cabeSGlenn Miles ipb = (reg32 >> 8) & 0xFF; 327*ffc2cabeSGlenn Miles g_assert_cmphex(ipb, ==, 0); 328*ffc2cabeSGlenn Miles 329*ffc2cabeSGlenn Miles /* End Of Interrupt */ 330*ffc2cabeSGlenn Miles set_esb(qts, irq, XIVE_EOI_PAGE, XIVE_ESB_STORE_EOI, 0); 331*ffc2cabeSGlenn Miles pq = get_esb(qts, irq, XIVE_EOI_PAGE, XIVE_ESB_GET); 332*ffc2cabeSGlenn Miles g_assert_cmpuint(pq, ==, XIVE_ESB_RESET); 333*ffc2cabeSGlenn Miles 334*ffc2cabeSGlenn Miles /* reset CPPR */ 335*ffc2cabeSGlenn Miles set_tima8(qts, target_pir, TM_QW3_HV_PHYS + TM_CPPR, 0xFF); 336*ffc2cabeSGlenn Miles reg32 = get_tima32(qts, target_pir, TM_QW3_HV_PHYS + TM_WORD0); 337*ffc2cabeSGlenn Miles nsr = reg32 >> 24; 338*ffc2cabeSGlenn Miles cppr = (reg32 >> 16) & 0xFF; 339*ffc2cabeSGlenn Miles g_assert_cmphex(nsr, ==, 0x00); 340*ffc2cabeSGlenn Miles g_assert_cmphex(cppr, ==, 0xFF); 341*ffc2cabeSGlenn Miles } 342*ffc2cabeSGlenn Miles 34331bfbc00SFrederic Barrat #define XIVE_ODD_CL 0x80 34431bfbc00SFrederic Barrat static void test_pull_thread_ctx_to_odd_thread_cl(QTestState *qts) 34531bfbc00SFrederic Barrat { 34631bfbc00SFrederic Barrat uint32_t target_pir = 1; 34731bfbc00SFrederic Barrat uint32_t target_nvp = 0x80 + target_pir; 34831bfbc00SFrederic Barrat Xive2Nvp nvp; 34931bfbc00SFrederic Barrat uint8_t cl_pair[XIVE_REPORT_SIZE]; 35031bfbc00SFrederic Barrat uint32_t qw1w0, qw3w0, qw1w2, qw2w2; 35131bfbc00SFrederic Barrat uint8_t qw3b8; 35231bfbc00SFrederic Barrat uint32_t cl_word; 35331bfbc00SFrederic Barrat uint32_t word2; 35431bfbc00SFrederic Barrat 355c4b50387SGlenn Miles g_test_message("========================================================="); 356c4b50387SGlenn Miles g_test_message("Testing 'Pull Thread Context to Odd Thread Reporting " \ 357c4b50387SGlenn Miles "Line'"); 35831bfbc00SFrederic Barrat 35931bfbc00SFrederic Barrat /* clear odd cache line prior to pull operation */ 36031bfbc00SFrederic Barrat memset(cl_pair, 0, sizeof(cl_pair)); 36131bfbc00SFrederic Barrat get_nvp(qts, target_nvp, &nvp); 36231bfbc00SFrederic Barrat set_cl_pair(qts, &nvp, cl_pair); 36331bfbc00SFrederic Barrat 36431bfbc00SFrederic Barrat /* Read some values from TIMA that we expect to see in cacheline */ 36531bfbc00SFrederic Barrat qw1w0 = get_tima32(qts, target_pir, TM_QW1_OS + TM_WORD0); 36631bfbc00SFrederic Barrat qw3w0 = get_tima32(qts, target_pir, TM_QW3_HV_PHYS + TM_WORD0); 36731bfbc00SFrederic Barrat qw1w2 = get_tima32(qts, target_pir, TM_QW1_OS + TM_WORD2); 36831bfbc00SFrederic Barrat qw2w2 = get_tima32(qts, target_pir, TM_QW2_HV_POOL + TM_WORD2); 36931bfbc00SFrederic Barrat qw3b8 = get_tima8(qts, target_pir, TM_QW3_HV_PHYS + TM_WORD2); 37031bfbc00SFrederic Barrat 37131bfbc00SFrederic Barrat /* Execute the pull operation */ 37231bfbc00SFrederic Barrat set_tima8(qts, target_pir, TM_SPC_PULL_PHYS_CTX_OL, 0); 37331bfbc00SFrederic Barrat 37431bfbc00SFrederic Barrat /* Verify odd cache line values match TIMA after pull operation */ 37531bfbc00SFrederic Barrat get_cl_pair(qts, &nvp, cl_pair); 37631bfbc00SFrederic Barrat memcpy(&cl_word, &cl_pair[XIVE_ODD_CL + TM_QW1_OS + TM_WORD0], 4); 37731bfbc00SFrederic Barrat g_assert_cmphex(qw1w0, ==, be32_to_cpu(cl_word)); 37831bfbc00SFrederic Barrat memcpy(&cl_word, &cl_pair[XIVE_ODD_CL + TM_QW3_HV_PHYS + TM_WORD0], 4); 37931bfbc00SFrederic Barrat g_assert_cmphex(qw3w0, ==, be32_to_cpu(cl_word)); 38031bfbc00SFrederic Barrat memcpy(&cl_word, &cl_pair[XIVE_ODD_CL + TM_QW1_OS + TM_WORD2], 4); 38131bfbc00SFrederic Barrat g_assert_cmphex(qw1w2, ==, be32_to_cpu(cl_word)); 38231bfbc00SFrederic Barrat memcpy(&cl_word, &cl_pair[XIVE_ODD_CL + TM_QW2_HV_POOL + TM_WORD2], 4); 38331bfbc00SFrederic Barrat g_assert_cmphex(qw2w2, ==, be32_to_cpu(cl_word)); 38431bfbc00SFrederic Barrat g_assert_cmphex(qw3b8, ==, 38531bfbc00SFrederic Barrat cl_pair[XIVE_ODD_CL + TM_QW3_HV_PHYS + TM_WORD2]); 38631bfbc00SFrederic Barrat 38731bfbc00SFrederic Barrat /* Verify that all TIMA valid bits for target thread are cleared */ 38831bfbc00SFrederic Barrat word2 = get_tima32(qts, target_pir, TM_QW1_OS + TM_WORD2); 38931bfbc00SFrederic Barrat g_assert_cmphex(xive_get_field32(TM_QW1W2_VO, word2), ==, 0); 39031bfbc00SFrederic Barrat word2 = get_tima32(qts, target_pir, TM_QW2_HV_POOL + TM_WORD2); 39131bfbc00SFrederic Barrat g_assert_cmphex(xive_get_field32(TM_QW2W2_VP, word2), ==, 0); 39231bfbc00SFrederic Barrat word2 = get_tima32(qts, target_pir, TM_QW3_HV_PHYS + TM_WORD2); 39331bfbc00SFrederic Barrat g_assert_cmphex(xive_get_field32(TM_QW3W2_VT, word2), ==, 0); 39431bfbc00SFrederic Barrat } 395c2b7fadeSFrederic Barrat 396c2b7fadeSFrederic Barrat static void test_hw_group_irq(QTestState *qts) 397c2b7fadeSFrederic Barrat { 398c2b7fadeSFrederic Barrat uint32_t irq = 100; 399c2b7fadeSFrederic Barrat uint32_t irq_data = 0xdeadbeef; 400c2b7fadeSFrederic Barrat uint32_t end_index = 23; 401c2b7fadeSFrederic Barrat uint32_t chosen_one; 402c2b7fadeSFrederic Barrat uint32_t target_nvp = 0x81; /* group size = 4 */ 403c2b7fadeSFrederic Barrat uint8_t priority = 6; 404c2b7fadeSFrederic Barrat uint32_t reg32; 405c2b7fadeSFrederic Barrat uint16_t reg16; 406c2b7fadeSFrederic Barrat uint8_t pq, nsr, cppr; 407c2b7fadeSFrederic Barrat 408c4b50387SGlenn Miles g_test_message("========================================================="); 409c4b50387SGlenn Miles g_test_message("Testing irq %d to hardware group of size 4", irq); 410c2b7fadeSFrederic Barrat 411c2b7fadeSFrederic Barrat /* irq config */ 412c2b7fadeSFrederic Barrat set_eas(qts, irq, end_index, irq_data); 413c2b7fadeSFrederic Barrat set_end(qts, end_index, target_nvp, priority, true /* group */); 414c2b7fadeSFrederic Barrat 415c2b7fadeSFrederic Barrat /* enable and trigger irq */ 416c2b7fadeSFrederic Barrat get_esb(qts, irq, XIVE_EOI_PAGE, XIVE_ESB_SET_PQ_00); 417c2b7fadeSFrederic Barrat set_esb(qts, irq, XIVE_TRIGGER_PAGE, 0, 0); 418c2b7fadeSFrederic Barrat 419c2b7fadeSFrederic Barrat /* check irq is raised on cpu */ 420c2b7fadeSFrederic Barrat pq = get_esb(qts, irq, XIVE_EOI_PAGE, XIVE_ESB_GET); 421c2b7fadeSFrederic Barrat g_assert_cmpuint(pq, ==, XIVE_ESB_PENDING); 422c2b7fadeSFrederic Barrat 423c2b7fadeSFrederic Barrat /* find the targeted vCPU */ 424c2b7fadeSFrederic Barrat for (chosen_one = 0; chosen_one < SMT; chosen_one++) { 425c2b7fadeSFrederic Barrat reg32 = get_tima32(qts, chosen_one, TM_QW3_HV_PHYS + TM_WORD0); 426c2b7fadeSFrederic Barrat nsr = reg32 >> 24; 427c2b7fadeSFrederic Barrat if (nsr == 0x82) { 428c2b7fadeSFrederic Barrat break; 429c2b7fadeSFrederic Barrat } 430c2b7fadeSFrederic Barrat } 431c2b7fadeSFrederic Barrat g_assert_cmphex(chosen_one, <, SMT); 432c2b7fadeSFrederic Barrat cppr = (reg32 >> 16) & 0xFF; 433c2b7fadeSFrederic Barrat g_assert_cmphex(nsr, ==, 0x82); 434c2b7fadeSFrederic Barrat g_assert_cmphex(cppr, ==, 0xFF); 435c2b7fadeSFrederic Barrat 436c2b7fadeSFrederic Barrat /* ack the irq */ 437c2b7fadeSFrederic Barrat reg16 = get_tima16(qts, chosen_one, TM_SPC_ACK_HV_REG); 438c2b7fadeSFrederic Barrat nsr = reg16 >> 8; 439c2b7fadeSFrederic Barrat cppr = reg16 & 0xFF; 440c2b7fadeSFrederic Barrat g_assert_cmphex(nsr, ==, 0x82); 441c2b7fadeSFrederic Barrat g_assert_cmphex(cppr, ==, priority); 442c2b7fadeSFrederic Barrat 443c2b7fadeSFrederic Barrat /* check irq data is what was configured */ 444c2b7fadeSFrederic Barrat reg32 = qtest_readl(qts, xive_get_queue_addr(end_index)); 445c2b7fadeSFrederic Barrat g_assert_cmphex((reg32 & 0x7fffffff), ==, (irq_data & 0x7fffffff)); 446c2b7fadeSFrederic Barrat 447c2b7fadeSFrederic Barrat /* End Of Interrupt */ 448c2b7fadeSFrederic Barrat set_esb(qts, irq, XIVE_EOI_PAGE, XIVE_ESB_STORE_EOI, 0); 449c2b7fadeSFrederic Barrat pq = get_esb(qts, irq, XIVE_EOI_PAGE, XIVE_ESB_GET); 450c2b7fadeSFrederic Barrat g_assert_cmpuint(pq, ==, XIVE_ESB_RESET); 451c2b7fadeSFrederic Barrat 452c2b7fadeSFrederic Barrat /* reset CPPR */ 453c2b7fadeSFrederic Barrat set_tima8(qts, chosen_one, TM_QW3_HV_PHYS + TM_CPPR, 0xFF); 454c2b7fadeSFrederic Barrat reg32 = get_tima32(qts, chosen_one, TM_QW3_HV_PHYS + TM_WORD0); 455c2b7fadeSFrederic Barrat nsr = reg32 >> 24; 456c2b7fadeSFrederic Barrat cppr = (reg32 >> 16) & 0xFF; 457c2b7fadeSFrederic Barrat g_assert_cmphex(nsr, ==, 0x00); 458c2b7fadeSFrederic Barrat g_assert_cmphex(cppr, ==, 0xFF); 459c2b7fadeSFrederic Barrat } 460c2b7fadeSFrederic Barrat 461c2b7fadeSFrederic Barrat static void test_hw_group_irq_backlog(QTestState *qts) 462c2b7fadeSFrederic Barrat { 463c2b7fadeSFrederic Barrat uint32_t irq = 31; 464c2b7fadeSFrederic Barrat uint32_t irq_data = 0x01234567; 465c2b7fadeSFrederic Barrat uint32_t end_index = 129; 466c2b7fadeSFrederic Barrat uint32_t target_nvp = 0x81; /* group size = 4 */ 467c2b7fadeSFrederic Barrat uint32_t chosen_one = 3; 468c2b7fadeSFrederic Barrat uint8_t blocking_priority, priority = 3; 469c2b7fadeSFrederic Barrat uint32_t reg32; 470c2b7fadeSFrederic Barrat uint16_t reg16; 471c2b7fadeSFrederic Barrat uint8_t pq, nsr, cppr, lsmfb, i; 472c2b7fadeSFrederic Barrat 473c4b50387SGlenn Miles g_test_message("========================================================="); 474c4b50387SGlenn Miles g_test_message("Testing irq %d to hardware group of size 4 going " \ 475c4b50387SGlenn Miles "through backlog", 476c2b7fadeSFrederic Barrat irq); 477c2b7fadeSFrederic Barrat 478c2b7fadeSFrederic Barrat /* 479c2b7fadeSFrederic Barrat * set current priority of all threads in the group to something 480c2b7fadeSFrederic Barrat * higher than what we're about to trigger 481c2b7fadeSFrederic Barrat */ 482c2b7fadeSFrederic Barrat blocking_priority = priority - 1; 483c2b7fadeSFrederic Barrat for (i = 0; i < SMT; i++) { 484c2b7fadeSFrederic Barrat set_tima8(qts, i, TM_QW3_HV_PHYS + TM_CPPR, blocking_priority); 485c2b7fadeSFrederic Barrat } 486c2b7fadeSFrederic Barrat 487c2b7fadeSFrederic Barrat /* irq config */ 488c2b7fadeSFrederic Barrat set_eas(qts, irq, end_index, irq_data); 489c2b7fadeSFrederic Barrat set_end(qts, end_index, target_nvp, priority, true /* group */); 490c2b7fadeSFrederic Barrat 491c2b7fadeSFrederic Barrat /* enable and trigger irq */ 492c2b7fadeSFrederic Barrat get_esb(qts, irq, XIVE_EOI_PAGE, XIVE_ESB_SET_PQ_00); 493c2b7fadeSFrederic Barrat set_esb(qts, irq, XIVE_TRIGGER_PAGE, 0, 0); 494c2b7fadeSFrederic Barrat 495c2b7fadeSFrederic Barrat /* check irq is raised on cpu */ 496c2b7fadeSFrederic Barrat pq = get_esb(qts, irq, XIVE_EOI_PAGE, XIVE_ESB_GET); 497c2b7fadeSFrederic Barrat g_assert_cmpuint(pq, ==, XIVE_ESB_PENDING); 498c2b7fadeSFrederic Barrat 499c2b7fadeSFrederic Barrat /* check no interrupt is pending on the 2 possible targets */ 500c2b7fadeSFrederic Barrat for (i = 0; i < SMT; i++) { 501c2b7fadeSFrederic Barrat reg32 = get_tima32(qts, i, TM_QW3_HV_PHYS + TM_WORD0); 502c2b7fadeSFrederic Barrat nsr = reg32 >> 24; 503c2b7fadeSFrederic Barrat cppr = (reg32 >> 16) & 0xFF; 504c2b7fadeSFrederic Barrat lsmfb = reg32 & 0xFF; 505c2b7fadeSFrederic Barrat g_assert_cmphex(nsr, ==, 0x0); 506c2b7fadeSFrederic Barrat g_assert_cmphex(cppr, ==, blocking_priority); 507c2b7fadeSFrederic Barrat g_assert_cmphex(lsmfb, ==, priority); 508c2b7fadeSFrederic Barrat } 509c2b7fadeSFrederic Barrat 510c2b7fadeSFrederic Barrat /* lower priority of one thread */ 511c2b7fadeSFrederic Barrat set_tima8(qts, chosen_one, TM_QW3_HV_PHYS + TM_CPPR, priority + 1); 512c2b7fadeSFrederic Barrat 513c2b7fadeSFrederic Barrat /* check backlogged interrupt is presented */ 514c2b7fadeSFrederic Barrat reg32 = get_tima32(qts, chosen_one, TM_QW3_HV_PHYS + TM_WORD0); 515c2b7fadeSFrederic Barrat nsr = reg32 >> 24; 516c2b7fadeSFrederic Barrat cppr = (reg32 >> 16) & 0xFF; 517c2b7fadeSFrederic Barrat g_assert_cmphex(nsr, ==, 0x82); 518c2b7fadeSFrederic Barrat g_assert_cmphex(cppr, ==, priority + 1); 519c2b7fadeSFrederic Barrat 520c2b7fadeSFrederic Barrat /* ack the irq */ 521c2b7fadeSFrederic Barrat reg16 = get_tima16(qts, chosen_one, TM_SPC_ACK_HV_REG); 522c2b7fadeSFrederic Barrat nsr = reg16 >> 8; 523c2b7fadeSFrederic Barrat cppr = reg16 & 0xFF; 524c2b7fadeSFrederic Barrat g_assert_cmphex(nsr, ==, 0x82); 525c2b7fadeSFrederic Barrat g_assert_cmphex(cppr, ==, priority); 526c2b7fadeSFrederic Barrat 527c2b7fadeSFrederic Barrat /* check irq data is what was configured */ 528c2b7fadeSFrederic Barrat reg32 = qtest_readl(qts, xive_get_queue_addr(end_index)); 529c2b7fadeSFrederic Barrat g_assert_cmphex((reg32 & 0x7fffffff), ==, (irq_data & 0x7fffffff)); 530c2b7fadeSFrederic Barrat 531c2b7fadeSFrederic Barrat /* End Of Interrupt */ 532c2b7fadeSFrederic Barrat set_esb(qts, irq, XIVE_EOI_PAGE, XIVE_ESB_STORE_EOI, 0); 533c2b7fadeSFrederic Barrat pq = get_esb(qts, irq, XIVE_EOI_PAGE, XIVE_ESB_GET); 534c2b7fadeSFrederic Barrat g_assert_cmpuint(pq, ==, XIVE_ESB_RESET); 535c2b7fadeSFrederic Barrat 536c2b7fadeSFrederic Barrat /* reset CPPR */ 537c2b7fadeSFrederic Barrat set_tima8(qts, chosen_one, TM_QW3_HV_PHYS + TM_CPPR, 0xFF); 538c2b7fadeSFrederic Barrat reg32 = get_tima32(qts, chosen_one, TM_QW3_HV_PHYS + TM_WORD0); 539c2b7fadeSFrederic Barrat nsr = reg32 >> 24; 540c2b7fadeSFrederic Barrat cppr = (reg32 >> 16) & 0xFF; 541c2b7fadeSFrederic Barrat lsmfb = reg32 & 0xFF; 542c2b7fadeSFrederic Barrat g_assert_cmphex(nsr, ==, 0x00); 543c2b7fadeSFrederic Barrat g_assert_cmphex(cppr, ==, 0xFF); 544c2b7fadeSFrederic Barrat g_assert_cmphex(lsmfb, ==, 0xFF); 545c2b7fadeSFrederic Barrat } 546c2b7fadeSFrederic Barrat 54731bfbc00SFrederic Barrat static void test_xive(void) 54831bfbc00SFrederic Barrat { 54931bfbc00SFrederic Barrat QTestState *qts; 55031bfbc00SFrederic Barrat 55131bfbc00SFrederic Barrat qts = qtest_initf("-M powernv10 -smp %d,cores=1,threads=%d -nographic " 55231bfbc00SFrederic Barrat "-nodefaults -serial mon:stdio -S " 55331bfbc00SFrederic Barrat "-d guest_errors -trace '*xive*'", 55431bfbc00SFrederic Barrat SMT, SMT); 55531bfbc00SFrederic Barrat init_xive(qts); 55631bfbc00SFrederic Barrat 55731bfbc00SFrederic Barrat test_hw_irq(qts); 55831bfbc00SFrederic Barrat 55931bfbc00SFrederic Barrat /* omit reset_state here and use settings from test_hw_irq */ 56031bfbc00SFrederic Barrat test_pull_thread_ctx_to_odd_thread_cl(qts); 56131bfbc00SFrederic Barrat 56231bfbc00SFrederic Barrat reset_state(qts); 563*ffc2cabeSGlenn Miles test_pool_irq(qts); 564*ffc2cabeSGlenn Miles 565*ffc2cabeSGlenn Miles reset_state(qts); 566c2b7fadeSFrederic Barrat test_hw_group_irq(qts); 567c2b7fadeSFrederic Barrat 568c2b7fadeSFrederic Barrat reset_state(qts); 569c2b7fadeSFrederic Barrat test_hw_group_irq_backlog(qts); 570c2b7fadeSFrederic Barrat 571c2b7fadeSFrederic Barrat reset_state(qts); 57231bfbc00SFrederic Barrat test_flush_sync_inject(qts); 57331bfbc00SFrederic Barrat 57496a2132cSFrederic Barrat reset_state(qts); 57596a2132cSFrederic Barrat test_nvpg_bar(qts); 57696a2132cSFrederic Barrat 57731bfbc00SFrederic Barrat qtest_quit(qts); 57831bfbc00SFrederic Barrat } 57931bfbc00SFrederic Barrat 58031bfbc00SFrederic Barrat int main(int argc, char **argv) 58131bfbc00SFrederic Barrat { 58231bfbc00SFrederic Barrat g_test_init(&argc, &argv, NULL); 58331bfbc00SFrederic Barrat qtest_add_func("xive2", test_xive); 58431bfbc00SFrederic Barrat return g_test_run(); 58531bfbc00SFrederic Barrat } 586