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' 5*c2b7fadeSFrederic Barrat * - Test irq to hardware group 6*c2b7fadeSFrederic Barrat * - Test irq to hardware group going through backlog 731bfbc00SFrederic Barrat * 831bfbc00SFrederic Barrat * Copyright (c) 2024, IBM Corporation. 931bfbc00SFrederic Barrat * 1031bfbc00SFrederic Barrat * SPDX-License-Identifier: GPL-2.0-or-later 1131bfbc00SFrederic Barrat */ 1231bfbc00SFrederic Barrat #include "qemu/osdep.h" 1331bfbc00SFrederic Barrat #include "libqtest.h" 1431bfbc00SFrederic Barrat 1531bfbc00SFrederic Barrat #include "pnv-xive2-common.h" 1631bfbc00SFrederic Barrat #include "hw/intc/pnv_xive2_regs.h" 1731bfbc00SFrederic Barrat #include "hw/ppc/xive_regs.h" 1831bfbc00SFrederic Barrat #include "hw/ppc/xive2_regs.h" 1931bfbc00SFrederic Barrat 2031bfbc00SFrederic Barrat #define SMT 4 /* some tests will break if less than 4 */ 2131bfbc00SFrederic Barrat 2231bfbc00SFrederic Barrat 2331bfbc00SFrederic Barrat static void set_table(QTestState *qts, uint64_t type, uint64_t addr) 2431bfbc00SFrederic Barrat { 2531bfbc00SFrederic Barrat uint64_t vsd, size, log_size; 2631bfbc00SFrederic Barrat 2731bfbc00SFrederic Barrat /* 2831bfbc00SFrederic Barrat * First, let's make sure that all the resources used fit in the 2931bfbc00SFrederic Barrat * given table. 3031bfbc00SFrederic Barrat */ 3131bfbc00SFrederic Barrat switch (type) { 3231bfbc00SFrederic Barrat case VST_ESB: 3331bfbc00SFrederic Barrat size = MAX_IRQS / 4; 3431bfbc00SFrederic Barrat break; 3531bfbc00SFrederic Barrat case VST_EAS: 3631bfbc00SFrederic Barrat size = MAX_IRQS * 8; 3731bfbc00SFrederic Barrat break; 3831bfbc00SFrederic Barrat case VST_END: 3931bfbc00SFrederic Barrat size = MAX_ENDS * 32; 4031bfbc00SFrederic Barrat break; 4131bfbc00SFrederic Barrat case VST_NVP: 4231bfbc00SFrederic Barrat case VST_NVG: 4331bfbc00SFrederic Barrat case VST_NVC: 4431bfbc00SFrederic Barrat size = MAX_VPS * 32; 4531bfbc00SFrederic Barrat break; 4631bfbc00SFrederic Barrat case VST_SYNC: 4731bfbc00SFrederic Barrat size = 64 * 1024; 4831bfbc00SFrederic Barrat break; 4931bfbc00SFrederic Barrat default: 5031bfbc00SFrederic Barrat g_assert_not_reached(); 5131bfbc00SFrederic Barrat } 5231bfbc00SFrederic Barrat 5331bfbc00SFrederic Barrat g_assert_cmpuint(size, <=, XIVE_VST_SIZE); 5431bfbc00SFrederic Barrat log_size = ctzl(XIVE_VST_SIZE) - 12; 5531bfbc00SFrederic Barrat 5631bfbc00SFrederic Barrat vsd = ((uint64_t) VSD_MODE_EXCLUSIVE) << 62 | addr | log_size; 5731bfbc00SFrederic Barrat pnv_xive_xscom_write(qts, X_VC_VSD_TABLE_ADDR, type << 48); 5831bfbc00SFrederic Barrat pnv_xive_xscom_write(qts, X_VC_VSD_TABLE_DATA, vsd); 5931bfbc00SFrederic Barrat 6031bfbc00SFrederic Barrat if (type != VST_EAS && type != VST_IC && type != VST_ERQ) { 6131bfbc00SFrederic Barrat pnv_xive_xscom_write(qts, X_PC_VSD_TABLE_ADDR, type << 48); 6231bfbc00SFrederic Barrat pnv_xive_xscom_write(qts, X_PC_VSD_TABLE_DATA, vsd); 6331bfbc00SFrederic Barrat } 6431bfbc00SFrederic Barrat } 6531bfbc00SFrederic Barrat 6631bfbc00SFrederic Barrat static void set_tima8(QTestState *qts, uint32_t pir, uint32_t offset, 6731bfbc00SFrederic Barrat uint8_t b) 6831bfbc00SFrederic Barrat { 6931bfbc00SFrederic Barrat uint64_t ic_addr; 7031bfbc00SFrederic Barrat 7131bfbc00SFrederic Barrat ic_addr = XIVE_IC_TM_INDIRECT + (pir << XIVE_PAGE_SHIFT); 7231bfbc00SFrederic Barrat qtest_writeb(qts, ic_addr + offset, b); 7331bfbc00SFrederic Barrat } 7431bfbc00SFrederic Barrat 7531bfbc00SFrederic Barrat static void set_tima32(QTestState *qts, uint32_t pir, uint32_t offset, 7631bfbc00SFrederic Barrat uint32_t l) 7731bfbc00SFrederic Barrat { 7831bfbc00SFrederic Barrat uint64_t ic_addr; 7931bfbc00SFrederic Barrat 8031bfbc00SFrederic Barrat ic_addr = XIVE_IC_TM_INDIRECT + (pir << XIVE_PAGE_SHIFT); 8131bfbc00SFrederic Barrat qtest_writel(qts, ic_addr + offset, l); 8231bfbc00SFrederic Barrat } 8331bfbc00SFrederic Barrat 8431bfbc00SFrederic Barrat static uint8_t get_tima8(QTestState *qts, uint32_t pir, uint32_t offset) 8531bfbc00SFrederic Barrat { 8631bfbc00SFrederic Barrat uint64_t ic_addr; 8731bfbc00SFrederic Barrat 8831bfbc00SFrederic Barrat ic_addr = XIVE_IC_TM_INDIRECT + (pir << XIVE_PAGE_SHIFT); 8931bfbc00SFrederic Barrat return qtest_readb(qts, ic_addr + offset); 9031bfbc00SFrederic Barrat } 9131bfbc00SFrederic Barrat 9231bfbc00SFrederic Barrat static uint16_t get_tima16(QTestState *qts, uint32_t pir, uint32_t offset) 9331bfbc00SFrederic Barrat { 9431bfbc00SFrederic Barrat uint64_t ic_addr; 9531bfbc00SFrederic Barrat 9631bfbc00SFrederic Barrat ic_addr = XIVE_IC_TM_INDIRECT + (pir << XIVE_PAGE_SHIFT); 9731bfbc00SFrederic Barrat return qtest_readw(qts, ic_addr + offset); 9831bfbc00SFrederic Barrat } 9931bfbc00SFrederic Barrat 10031bfbc00SFrederic Barrat static uint32_t get_tima32(QTestState *qts, uint32_t pir, uint32_t offset) 10131bfbc00SFrederic Barrat { 10231bfbc00SFrederic Barrat uint64_t ic_addr; 10331bfbc00SFrederic Barrat 10431bfbc00SFrederic Barrat ic_addr = XIVE_IC_TM_INDIRECT + (pir << XIVE_PAGE_SHIFT); 10531bfbc00SFrederic Barrat return qtest_readl(qts, ic_addr + offset); 10631bfbc00SFrederic Barrat } 10731bfbc00SFrederic Barrat 10831bfbc00SFrederic Barrat static void reset_pool_threads(QTestState *qts) 10931bfbc00SFrederic Barrat { 11031bfbc00SFrederic Barrat uint8_t first_group = 0; 11131bfbc00SFrederic Barrat int i; 11231bfbc00SFrederic Barrat 11331bfbc00SFrederic Barrat for (i = 0; i < SMT; i++) { 11431bfbc00SFrederic Barrat uint32_t nvp_idx = 0x100 + i; 11531bfbc00SFrederic Barrat set_nvp(qts, nvp_idx, first_group); 11631bfbc00SFrederic Barrat set_tima32(qts, i, TM_QW2_HV_POOL + TM_WORD0, 0x000000ff); 11731bfbc00SFrederic Barrat set_tima32(qts, i, TM_QW2_HV_POOL + TM_WORD1, 0); 11831bfbc00SFrederic Barrat set_tima32(qts, i, TM_QW2_HV_POOL + TM_WORD2, TM_QW2W2_VP | nvp_idx); 11931bfbc00SFrederic Barrat } 12031bfbc00SFrederic Barrat } 12131bfbc00SFrederic Barrat 12231bfbc00SFrederic Barrat static void reset_hw_threads(QTestState *qts) 12331bfbc00SFrederic Barrat { 12431bfbc00SFrederic Barrat uint8_t first_group = 0; 12531bfbc00SFrederic Barrat uint32_t w1 = 0x000000ff; 12631bfbc00SFrederic Barrat int i; 12731bfbc00SFrederic Barrat 12831bfbc00SFrederic Barrat if (SMT >= 4) { 12931bfbc00SFrederic Barrat /* define 2 groups of 2, part of a bigger group of size 4 */ 13031bfbc00SFrederic Barrat set_nvg(qts, 0x80, 0x02); 13131bfbc00SFrederic Barrat set_nvg(qts, 0x82, 0x02); 13231bfbc00SFrederic Barrat set_nvg(qts, 0x81, 0); 13331bfbc00SFrederic Barrat first_group = 0x01; 13431bfbc00SFrederic Barrat w1 = 0x000300ff; 13531bfbc00SFrederic Barrat } 13631bfbc00SFrederic Barrat 13731bfbc00SFrederic Barrat for (i = 0; i < SMT; i++) { 13831bfbc00SFrederic Barrat set_nvp(qts, 0x80 + i, first_group); 13931bfbc00SFrederic Barrat set_tima32(qts, i, TM_QW3_HV_PHYS + TM_WORD0, 0x00ff00ff); 14031bfbc00SFrederic Barrat set_tima32(qts, i, TM_QW3_HV_PHYS + TM_WORD1, w1); 14131bfbc00SFrederic Barrat set_tima32(qts, i, TM_QW3_HV_PHYS + TM_WORD2, 0x80000000); 14231bfbc00SFrederic Barrat } 14331bfbc00SFrederic Barrat } 14431bfbc00SFrederic Barrat 14531bfbc00SFrederic Barrat static void reset_state(QTestState *qts) 14631bfbc00SFrederic Barrat { 14731bfbc00SFrederic Barrat size_t mem_used = XIVE_MEM_END - XIVE_MEM_START; 14831bfbc00SFrederic Barrat 14931bfbc00SFrederic Barrat qtest_memset(qts, XIVE_MEM_START, 0, mem_used); 15031bfbc00SFrederic Barrat reset_hw_threads(qts); 15131bfbc00SFrederic Barrat reset_pool_threads(qts); 15231bfbc00SFrederic Barrat } 15331bfbc00SFrederic Barrat 15431bfbc00SFrederic Barrat static void init_xive(QTestState *qts) 15531bfbc00SFrederic Barrat { 15631bfbc00SFrederic Barrat uint64_t val1, val2, range; 15731bfbc00SFrederic Barrat 15831bfbc00SFrederic Barrat /* 15931bfbc00SFrederic Barrat * We can take a few shortcuts here, as we know the default values 16031bfbc00SFrederic Barrat * used for xive initialization 16131bfbc00SFrederic Barrat */ 16231bfbc00SFrederic Barrat 16331bfbc00SFrederic Barrat /* 16431bfbc00SFrederic Barrat * Set the BARs. 16531bfbc00SFrederic Barrat * We reuse the same values used by firmware to ease debug. 16631bfbc00SFrederic Barrat */ 16731bfbc00SFrederic Barrat pnv_xive_xscom_write(qts, X_CQ_IC_BAR, XIVE_IC_BAR); 16831bfbc00SFrederic Barrat pnv_xive_xscom_write(qts, X_CQ_TM_BAR, XIVE_TM_BAR); 16931bfbc00SFrederic Barrat 17031bfbc00SFrederic Barrat /* ESB and NVPG use 2 pages per resource. The others only one page */ 17131bfbc00SFrederic Barrat range = (MAX_IRQS << 17) >> 25; 17231bfbc00SFrederic Barrat val1 = XIVE_ESB_BAR | range; 17331bfbc00SFrederic Barrat pnv_xive_xscom_write(qts, X_CQ_ESB_BAR, val1); 17431bfbc00SFrederic Barrat 17531bfbc00SFrederic Barrat range = (MAX_ENDS << 16) >> 25; 17631bfbc00SFrederic Barrat val1 = XIVE_END_BAR | range; 17731bfbc00SFrederic Barrat pnv_xive_xscom_write(qts, X_CQ_END_BAR, val1); 17831bfbc00SFrederic Barrat 17931bfbc00SFrederic Barrat range = (MAX_VPS << 17) >> 25; 18031bfbc00SFrederic Barrat val1 = XIVE_NVPG_BAR | range; 18131bfbc00SFrederic Barrat pnv_xive_xscom_write(qts, X_CQ_NVPG_BAR, val1); 18231bfbc00SFrederic Barrat 18331bfbc00SFrederic Barrat range = (MAX_VPS << 16) >> 25; 18431bfbc00SFrederic Barrat val1 = XIVE_NVC_BAR | range; 18531bfbc00SFrederic Barrat pnv_xive_xscom_write(qts, X_CQ_NVC_BAR, val1); 18631bfbc00SFrederic Barrat 18731bfbc00SFrederic Barrat /* 18831bfbc00SFrederic Barrat * Enable hw threads. 18931bfbc00SFrederic Barrat * We check the value written. Useless with current 19031bfbc00SFrederic Barrat * implementation, but it validates the xscom read path and it's 19131bfbc00SFrederic Barrat * what the hardware procedure says 19231bfbc00SFrederic Barrat */ 19331bfbc00SFrederic Barrat val1 = 0xF000000000000000ull; /* core 0, 4 threads */ 19431bfbc00SFrederic Barrat pnv_xive_xscom_write(qts, X_TCTXT_EN0, val1); 19531bfbc00SFrederic Barrat val2 = pnv_xive_xscom_read(qts, X_TCTXT_EN0); 19631bfbc00SFrederic Barrat g_assert_cmphex(val1, ==, val2); 19731bfbc00SFrederic Barrat 19831bfbc00SFrederic Barrat /* Memory tables */ 19931bfbc00SFrederic Barrat set_table(qts, VST_ESB, XIVE_ESB_MEM); 20031bfbc00SFrederic Barrat set_table(qts, VST_EAS, XIVE_EAS_MEM); 20131bfbc00SFrederic Barrat set_table(qts, VST_END, XIVE_END_MEM); 20231bfbc00SFrederic Barrat set_table(qts, VST_NVP, XIVE_NVP_MEM); 20331bfbc00SFrederic Barrat set_table(qts, VST_NVG, XIVE_NVG_MEM); 20431bfbc00SFrederic Barrat set_table(qts, VST_NVC, XIVE_NVC_MEM); 20531bfbc00SFrederic Barrat set_table(qts, VST_SYNC, XIVE_SYNC_MEM); 20631bfbc00SFrederic Barrat 20731bfbc00SFrederic Barrat reset_hw_threads(qts); 20831bfbc00SFrederic Barrat reset_pool_threads(qts); 20931bfbc00SFrederic Barrat } 21031bfbc00SFrederic Barrat 21131bfbc00SFrederic Barrat static void test_hw_irq(QTestState *qts) 21231bfbc00SFrederic Barrat { 21331bfbc00SFrederic Barrat uint32_t irq = 2; 21431bfbc00SFrederic Barrat uint32_t irq_data = 0x600df00d; 21531bfbc00SFrederic Barrat uint32_t end_index = 5; 21631bfbc00SFrederic Barrat uint32_t target_pir = 1; 21731bfbc00SFrederic Barrat uint32_t target_nvp = 0x80 + target_pir; 21831bfbc00SFrederic Barrat uint8_t priority = 5; 21931bfbc00SFrederic Barrat uint32_t reg32; 22031bfbc00SFrederic Barrat uint16_t reg16; 22131bfbc00SFrederic Barrat uint8_t pq, nsr, cppr; 22231bfbc00SFrederic Barrat 22331bfbc00SFrederic Barrat printf("# ============================================================\n"); 22431bfbc00SFrederic Barrat printf("# Testing irq %d to hardware thread %d\n", irq, target_pir); 22531bfbc00SFrederic Barrat 22631bfbc00SFrederic Barrat /* irq config */ 22731bfbc00SFrederic Barrat set_eas(qts, irq, end_index, irq_data); 22831bfbc00SFrederic Barrat set_end(qts, end_index, target_nvp, priority, false /* group */); 22931bfbc00SFrederic Barrat 23031bfbc00SFrederic Barrat /* enable and trigger irq */ 23131bfbc00SFrederic Barrat get_esb(qts, irq, XIVE_EOI_PAGE, XIVE_ESB_SET_PQ_00); 23231bfbc00SFrederic Barrat set_esb(qts, irq, XIVE_TRIGGER_PAGE, 0, 0); 23331bfbc00SFrederic Barrat 23431bfbc00SFrederic Barrat /* check irq is raised on cpu */ 23531bfbc00SFrederic Barrat pq = get_esb(qts, irq, XIVE_EOI_PAGE, XIVE_ESB_GET); 23631bfbc00SFrederic Barrat g_assert_cmpuint(pq, ==, XIVE_ESB_PENDING); 23731bfbc00SFrederic Barrat 23831bfbc00SFrederic Barrat reg32 = get_tima32(qts, target_pir, TM_QW3_HV_PHYS + TM_WORD0); 23931bfbc00SFrederic Barrat nsr = reg32 >> 24; 24031bfbc00SFrederic Barrat cppr = (reg32 >> 16) & 0xFF; 24131bfbc00SFrederic Barrat g_assert_cmphex(nsr, ==, 0x80); 24231bfbc00SFrederic Barrat g_assert_cmphex(cppr, ==, 0xFF); 24331bfbc00SFrederic Barrat 24431bfbc00SFrederic Barrat /* ack the irq */ 24531bfbc00SFrederic Barrat reg16 = get_tima16(qts, target_pir, TM_SPC_ACK_HV_REG); 24631bfbc00SFrederic Barrat nsr = reg16 >> 8; 24731bfbc00SFrederic Barrat cppr = reg16 & 0xFF; 24831bfbc00SFrederic Barrat g_assert_cmphex(nsr, ==, 0x80); 24931bfbc00SFrederic Barrat g_assert_cmphex(cppr, ==, priority); 25031bfbc00SFrederic Barrat 25131bfbc00SFrederic Barrat /* check irq data is what was configured */ 25231bfbc00SFrederic Barrat reg32 = qtest_readl(qts, xive_get_queue_addr(end_index)); 25331bfbc00SFrederic Barrat g_assert_cmphex((reg32 & 0x7fffffff), ==, (irq_data & 0x7fffffff)); 25431bfbc00SFrederic Barrat 25531bfbc00SFrederic Barrat /* End Of Interrupt */ 25631bfbc00SFrederic Barrat set_esb(qts, irq, XIVE_EOI_PAGE, XIVE_ESB_STORE_EOI, 0); 25731bfbc00SFrederic Barrat pq = get_esb(qts, irq, XIVE_EOI_PAGE, XIVE_ESB_GET); 25831bfbc00SFrederic Barrat g_assert_cmpuint(pq, ==, XIVE_ESB_RESET); 25931bfbc00SFrederic Barrat 26031bfbc00SFrederic Barrat /* reset CPPR */ 26131bfbc00SFrederic Barrat set_tima8(qts, target_pir, TM_QW3_HV_PHYS + TM_CPPR, 0xFF); 26231bfbc00SFrederic Barrat reg32 = get_tima32(qts, target_pir, TM_QW3_HV_PHYS + TM_WORD0); 26331bfbc00SFrederic Barrat nsr = reg32 >> 24; 26431bfbc00SFrederic Barrat cppr = (reg32 >> 16) & 0xFF; 26531bfbc00SFrederic Barrat g_assert_cmphex(nsr, ==, 0x00); 26631bfbc00SFrederic Barrat g_assert_cmphex(cppr, ==, 0xFF); 26731bfbc00SFrederic Barrat } 26831bfbc00SFrederic Barrat 26931bfbc00SFrederic Barrat #define XIVE_ODD_CL 0x80 27031bfbc00SFrederic Barrat static void test_pull_thread_ctx_to_odd_thread_cl(QTestState *qts) 27131bfbc00SFrederic Barrat { 27231bfbc00SFrederic Barrat uint32_t target_pir = 1; 27331bfbc00SFrederic Barrat uint32_t target_nvp = 0x80 + target_pir; 27431bfbc00SFrederic Barrat Xive2Nvp nvp; 27531bfbc00SFrederic Barrat uint8_t cl_pair[XIVE_REPORT_SIZE]; 27631bfbc00SFrederic Barrat uint32_t qw1w0, qw3w0, qw1w2, qw2w2; 27731bfbc00SFrederic Barrat uint8_t qw3b8; 27831bfbc00SFrederic Barrat uint32_t cl_word; 27931bfbc00SFrederic Barrat uint32_t word2; 28031bfbc00SFrederic Barrat 28131bfbc00SFrederic Barrat printf("# ============================================================\n"); 28231bfbc00SFrederic Barrat printf("# Testing 'Pull Thread Context to Odd Thread Reporting Line'\n"); 28331bfbc00SFrederic Barrat 28431bfbc00SFrederic Barrat /* clear odd cache line prior to pull operation */ 28531bfbc00SFrederic Barrat memset(cl_pair, 0, sizeof(cl_pair)); 28631bfbc00SFrederic Barrat get_nvp(qts, target_nvp, &nvp); 28731bfbc00SFrederic Barrat set_cl_pair(qts, &nvp, cl_pair); 28831bfbc00SFrederic Barrat 28931bfbc00SFrederic Barrat /* Read some values from TIMA that we expect to see in cacheline */ 29031bfbc00SFrederic Barrat qw1w0 = get_tima32(qts, target_pir, TM_QW1_OS + TM_WORD0); 29131bfbc00SFrederic Barrat qw3w0 = get_tima32(qts, target_pir, TM_QW3_HV_PHYS + TM_WORD0); 29231bfbc00SFrederic Barrat qw1w2 = get_tima32(qts, target_pir, TM_QW1_OS + TM_WORD2); 29331bfbc00SFrederic Barrat qw2w2 = get_tima32(qts, target_pir, TM_QW2_HV_POOL + TM_WORD2); 29431bfbc00SFrederic Barrat qw3b8 = get_tima8(qts, target_pir, TM_QW3_HV_PHYS + TM_WORD2); 29531bfbc00SFrederic Barrat 29631bfbc00SFrederic Barrat /* Execute the pull operation */ 29731bfbc00SFrederic Barrat set_tima8(qts, target_pir, TM_SPC_PULL_PHYS_CTX_OL, 0); 29831bfbc00SFrederic Barrat 29931bfbc00SFrederic Barrat /* Verify odd cache line values match TIMA after pull operation */ 30031bfbc00SFrederic Barrat get_cl_pair(qts, &nvp, cl_pair); 30131bfbc00SFrederic Barrat memcpy(&cl_word, &cl_pair[XIVE_ODD_CL + TM_QW1_OS + TM_WORD0], 4); 30231bfbc00SFrederic Barrat g_assert_cmphex(qw1w0, ==, be32_to_cpu(cl_word)); 30331bfbc00SFrederic Barrat memcpy(&cl_word, &cl_pair[XIVE_ODD_CL + TM_QW3_HV_PHYS + TM_WORD0], 4); 30431bfbc00SFrederic Barrat g_assert_cmphex(qw3w0, ==, be32_to_cpu(cl_word)); 30531bfbc00SFrederic Barrat memcpy(&cl_word, &cl_pair[XIVE_ODD_CL + TM_QW1_OS + TM_WORD2], 4); 30631bfbc00SFrederic Barrat g_assert_cmphex(qw1w2, ==, be32_to_cpu(cl_word)); 30731bfbc00SFrederic Barrat memcpy(&cl_word, &cl_pair[XIVE_ODD_CL + TM_QW2_HV_POOL + TM_WORD2], 4); 30831bfbc00SFrederic Barrat g_assert_cmphex(qw2w2, ==, be32_to_cpu(cl_word)); 30931bfbc00SFrederic Barrat g_assert_cmphex(qw3b8, ==, 31031bfbc00SFrederic Barrat cl_pair[XIVE_ODD_CL + TM_QW3_HV_PHYS + TM_WORD2]); 31131bfbc00SFrederic Barrat 31231bfbc00SFrederic Barrat /* Verify that all TIMA valid bits for target thread are cleared */ 31331bfbc00SFrederic Barrat word2 = get_tima32(qts, target_pir, TM_QW1_OS + TM_WORD2); 31431bfbc00SFrederic Barrat g_assert_cmphex(xive_get_field32(TM_QW1W2_VO, word2), ==, 0); 31531bfbc00SFrederic Barrat word2 = get_tima32(qts, target_pir, TM_QW2_HV_POOL + TM_WORD2); 31631bfbc00SFrederic Barrat g_assert_cmphex(xive_get_field32(TM_QW2W2_VP, word2), ==, 0); 31731bfbc00SFrederic Barrat word2 = get_tima32(qts, target_pir, TM_QW3_HV_PHYS + TM_WORD2); 31831bfbc00SFrederic Barrat g_assert_cmphex(xive_get_field32(TM_QW3W2_VT, word2), ==, 0); 31931bfbc00SFrederic Barrat } 320*c2b7fadeSFrederic Barrat 321*c2b7fadeSFrederic Barrat static void test_hw_group_irq(QTestState *qts) 322*c2b7fadeSFrederic Barrat { 323*c2b7fadeSFrederic Barrat uint32_t irq = 100; 324*c2b7fadeSFrederic Barrat uint32_t irq_data = 0xdeadbeef; 325*c2b7fadeSFrederic Barrat uint32_t end_index = 23; 326*c2b7fadeSFrederic Barrat uint32_t chosen_one; 327*c2b7fadeSFrederic Barrat uint32_t target_nvp = 0x81; /* group size = 4 */ 328*c2b7fadeSFrederic Barrat uint8_t priority = 6; 329*c2b7fadeSFrederic Barrat uint32_t reg32; 330*c2b7fadeSFrederic Barrat uint16_t reg16; 331*c2b7fadeSFrederic Barrat uint8_t pq, nsr, cppr; 332*c2b7fadeSFrederic Barrat 333*c2b7fadeSFrederic Barrat printf("# ============================================================\n"); 334*c2b7fadeSFrederic Barrat printf("# Testing irq %d to hardware group of size 4\n", irq); 335*c2b7fadeSFrederic Barrat 336*c2b7fadeSFrederic Barrat /* irq config */ 337*c2b7fadeSFrederic Barrat set_eas(qts, irq, end_index, irq_data); 338*c2b7fadeSFrederic Barrat set_end(qts, end_index, target_nvp, priority, true /* group */); 339*c2b7fadeSFrederic Barrat 340*c2b7fadeSFrederic Barrat /* enable and trigger irq */ 341*c2b7fadeSFrederic Barrat get_esb(qts, irq, XIVE_EOI_PAGE, XIVE_ESB_SET_PQ_00); 342*c2b7fadeSFrederic Barrat set_esb(qts, irq, XIVE_TRIGGER_PAGE, 0, 0); 343*c2b7fadeSFrederic Barrat 344*c2b7fadeSFrederic Barrat /* check irq is raised on cpu */ 345*c2b7fadeSFrederic Barrat pq = get_esb(qts, irq, XIVE_EOI_PAGE, XIVE_ESB_GET); 346*c2b7fadeSFrederic Barrat g_assert_cmpuint(pq, ==, XIVE_ESB_PENDING); 347*c2b7fadeSFrederic Barrat 348*c2b7fadeSFrederic Barrat /* find the targeted vCPU */ 349*c2b7fadeSFrederic Barrat for (chosen_one = 0; chosen_one < SMT; chosen_one++) { 350*c2b7fadeSFrederic Barrat reg32 = get_tima32(qts, chosen_one, TM_QW3_HV_PHYS + TM_WORD0); 351*c2b7fadeSFrederic Barrat nsr = reg32 >> 24; 352*c2b7fadeSFrederic Barrat if (nsr == 0x82) { 353*c2b7fadeSFrederic Barrat break; 354*c2b7fadeSFrederic Barrat } 355*c2b7fadeSFrederic Barrat } 356*c2b7fadeSFrederic Barrat g_assert_cmphex(chosen_one, <, SMT); 357*c2b7fadeSFrederic Barrat cppr = (reg32 >> 16) & 0xFF; 358*c2b7fadeSFrederic Barrat g_assert_cmphex(nsr, ==, 0x82); 359*c2b7fadeSFrederic Barrat g_assert_cmphex(cppr, ==, 0xFF); 360*c2b7fadeSFrederic Barrat 361*c2b7fadeSFrederic Barrat /* ack the irq */ 362*c2b7fadeSFrederic Barrat reg16 = get_tima16(qts, chosen_one, TM_SPC_ACK_HV_REG); 363*c2b7fadeSFrederic Barrat nsr = reg16 >> 8; 364*c2b7fadeSFrederic Barrat cppr = reg16 & 0xFF; 365*c2b7fadeSFrederic Barrat g_assert_cmphex(nsr, ==, 0x82); 366*c2b7fadeSFrederic Barrat g_assert_cmphex(cppr, ==, priority); 367*c2b7fadeSFrederic Barrat 368*c2b7fadeSFrederic Barrat /* check irq data is what was configured */ 369*c2b7fadeSFrederic Barrat reg32 = qtest_readl(qts, xive_get_queue_addr(end_index)); 370*c2b7fadeSFrederic Barrat g_assert_cmphex((reg32 & 0x7fffffff), ==, (irq_data & 0x7fffffff)); 371*c2b7fadeSFrederic Barrat 372*c2b7fadeSFrederic Barrat /* End Of Interrupt */ 373*c2b7fadeSFrederic Barrat set_esb(qts, irq, XIVE_EOI_PAGE, XIVE_ESB_STORE_EOI, 0); 374*c2b7fadeSFrederic Barrat pq = get_esb(qts, irq, XIVE_EOI_PAGE, XIVE_ESB_GET); 375*c2b7fadeSFrederic Barrat g_assert_cmpuint(pq, ==, XIVE_ESB_RESET); 376*c2b7fadeSFrederic Barrat 377*c2b7fadeSFrederic Barrat /* reset CPPR */ 378*c2b7fadeSFrederic Barrat set_tima8(qts, chosen_one, TM_QW3_HV_PHYS + TM_CPPR, 0xFF); 379*c2b7fadeSFrederic Barrat reg32 = get_tima32(qts, chosen_one, TM_QW3_HV_PHYS + TM_WORD0); 380*c2b7fadeSFrederic Barrat nsr = reg32 >> 24; 381*c2b7fadeSFrederic Barrat cppr = (reg32 >> 16) & 0xFF; 382*c2b7fadeSFrederic Barrat g_assert_cmphex(nsr, ==, 0x00); 383*c2b7fadeSFrederic Barrat g_assert_cmphex(cppr, ==, 0xFF); 384*c2b7fadeSFrederic Barrat } 385*c2b7fadeSFrederic Barrat 386*c2b7fadeSFrederic Barrat static void test_hw_group_irq_backlog(QTestState *qts) 387*c2b7fadeSFrederic Barrat { 388*c2b7fadeSFrederic Barrat uint32_t irq = 31; 389*c2b7fadeSFrederic Barrat uint32_t irq_data = 0x01234567; 390*c2b7fadeSFrederic Barrat uint32_t end_index = 129; 391*c2b7fadeSFrederic Barrat uint32_t target_nvp = 0x81; /* group size = 4 */ 392*c2b7fadeSFrederic Barrat uint32_t chosen_one = 3; 393*c2b7fadeSFrederic Barrat uint8_t blocking_priority, priority = 3; 394*c2b7fadeSFrederic Barrat uint32_t reg32; 395*c2b7fadeSFrederic Barrat uint16_t reg16; 396*c2b7fadeSFrederic Barrat uint8_t pq, nsr, cppr, lsmfb, i; 397*c2b7fadeSFrederic Barrat 398*c2b7fadeSFrederic Barrat printf("# ============================================================\n"); 399*c2b7fadeSFrederic Barrat printf("# Testing irq %d to hardware group of size 4 going through " \ 400*c2b7fadeSFrederic Barrat "backlog\n", 401*c2b7fadeSFrederic Barrat irq); 402*c2b7fadeSFrederic Barrat 403*c2b7fadeSFrederic Barrat /* 404*c2b7fadeSFrederic Barrat * set current priority of all threads in the group to something 405*c2b7fadeSFrederic Barrat * higher than what we're about to trigger 406*c2b7fadeSFrederic Barrat */ 407*c2b7fadeSFrederic Barrat blocking_priority = priority - 1; 408*c2b7fadeSFrederic Barrat for (i = 0; i < SMT; i++) { 409*c2b7fadeSFrederic Barrat set_tima8(qts, i, TM_QW3_HV_PHYS + TM_CPPR, blocking_priority); 410*c2b7fadeSFrederic Barrat } 411*c2b7fadeSFrederic Barrat 412*c2b7fadeSFrederic Barrat /* irq config */ 413*c2b7fadeSFrederic Barrat set_eas(qts, irq, end_index, irq_data); 414*c2b7fadeSFrederic Barrat set_end(qts, end_index, target_nvp, priority, true /* group */); 415*c2b7fadeSFrederic Barrat 416*c2b7fadeSFrederic Barrat /* enable and trigger irq */ 417*c2b7fadeSFrederic Barrat get_esb(qts, irq, XIVE_EOI_PAGE, XIVE_ESB_SET_PQ_00); 418*c2b7fadeSFrederic Barrat set_esb(qts, irq, XIVE_TRIGGER_PAGE, 0, 0); 419*c2b7fadeSFrederic Barrat 420*c2b7fadeSFrederic Barrat /* check irq is raised on cpu */ 421*c2b7fadeSFrederic Barrat pq = get_esb(qts, irq, XIVE_EOI_PAGE, XIVE_ESB_GET); 422*c2b7fadeSFrederic Barrat g_assert_cmpuint(pq, ==, XIVE_ESB_PENDING); 423*c2b7fadeSFrederic Barrat 424*c2b7fadeSFrederic Barrat /* check no interrupt is pending on the 2 possible targets */ 425*c2b7fadeSFrederic Barrat for (i = 0; i < SMT; i++) { 426*c2b7fadeSFrederic Barrat reg32 = get_tima32(qts, i, TM_QW3_HV_PHYS + TM_WORD0); 427*c2b7fadeSFrederic Barrat nsr = reg32 >> 24; 428*c2b7fadeSFrederic Barrat cppr = (reg32 >> 16) & 0xFF; 429*c2b7fadeSFrederic Barrat lsmfb = reg32 & 0xFF; 430*c2b7fadeSFrederic Barrat g_assert_cmphex(nsr, ==, 0x0); 431*c2b7fadeSFrederic Barrat g_assert_cmphex(cppr, ==, blocking_priority); 432*c2b7fadeSFrederic Barrat g_assert_cmphex(lsmfb, ==, priority); 433*c2b7fadeSFrederic Barrat } 434*c2b7fadeSFrederic Barrat 435*c2b7fadeSFrederic Barrat /* lower priority of one thread */ 436*c2b7fadeSFrederic Barrat set_tima8(qts, chosen_one, TM_QW3_HV_PHYS + TM_CPPR, priority + 1); 437*c2b7fadeSFrederic Barrat 438*c2b7fadeSFrederic Barrat /* check backlogged interrupt is presented */ 439*c2b7fadeSFrederic Barrat reg32 = get_tima32(qts, chosen_one, TM_QW3_HV_PHYS + TM_WORD0); 440*c2b7fadeSFrederic Barrat nsr = reg32 >> 24; 441*c2b7fadeSFrederic Barrat cppr = (reg32 >> 16) & 0xFF; 442*c2b7fadeSFrederic Barrat g_assert_cmphex(nsr, ==, 0x82); 443*c2b7fadeSFrederic Barrat g_assert_cmphex(cppr, ==, priority + 1); 444*c2b7fadeSFrederic Barrat 445*c2b7fadeSFrederic Barrat /* ack the irq */ 446*c2b7fadeSFrederic Barrat reg16 = get_tima16(qts, chosen_one, TM_SPC_ACK_HV_REG); 447*c2b7fadeSFrederic Barrat nsr = reg16 >> 8; 448*c2b7fadeSFrederic Barrat cppr = reg16 & 0xFF; 449*c2b7fadeSFrederic Barrat g_assert_cmphex(nsr, ==, 0x82); 450*c2b7fadeSFrederic Barrat g_assert_cmphex(cppr, ==, priority); 451*c2b7fadeSFrederic Barrat 452*c2b7fadeSFrederic Barrat /* check irq data is what was configured */ 453*c2b7fadeSFrederic Barrat reg32 = qtest_readl(qts, xive_get_queue_addr(end_index)); 454*c2b7fadeSFrederic Barrat g_assert_cmphex((reg32 & 0x7fffffff), ==, (irq_data & 0x7fffffff)); 455*c2b7fadeSFrederic Barrat 456*c2b7fadeSFrederic Barrat /* End Of Interrupt */ 457*c2b7fadeSFrederic Barrat set_esb(qts, irq, XIVE_EOI_PAGE, XIVE_ESB_STORE_EOI, 0); 458*c2b7fadeSFrederic Barrat pq = get_esb(qts, irq, XIVE_EOI_PAGE, XIVE_ESB_GET); 459*c2b7fadeSFrederic Barrat g_assert_cmpuint(pq, ==, XIVE_ESB_RESET); 460*c2b7fadeSFrederic Barrat 461*c2b7fadeSFrederic Barrat /* reset CPPR */ 462*c2b7fadeSFrederic Barrat set_tima8(qts, chosen_one, TM_QW3_HV_PHYS + TM_CPPR, 0xFF); 463*c2b7fadeSFrederic Barrat reg32 = get_tima32(qts, chosen_one, TM_QW3_HV_PHYS + TM_WORD0); 464*c2b7fadeSFrederic Barrat nsr = reg32 >> 24; 465*c2b7fadeSFrederic Barrat cppr = (reg32 >> 16) & 0xFF; 466*c2b7fadeSFrederic Barrat lsmfb = reg32 & 0xFF; 467*c2b7fadeSFrederic Barrat g_assert_cmphex(nsr, ==, 0x00); 468*c2b7fadeSFrederic Barrat g_assert_cmphex(cppr, ==, 0xFF); 469*c2b7fadeSFrederic Barrat g_assert_cmphex(lsmfb, ==, 0xFF); 470*c2b7fadeSFrederic Barrat } 471*c2b7fadeSFrederic Barrat 47231bfbc00SFrederic Barrat static void test_xive(void) 47331bfbc00SFrederic Barrat { 47431bfbc00SFrederic Barrat QTestState *qts; 47531bfbc00SFrederic Barrat 47631bfbc00SFrederic Barrat qts = qtest_initf("-M powernv10 -smp %d,cores=1,threads=%d -nographic " 47731bfbc00SFrederic Barrat "-nodefaults -serial mon:stdio -S " 47831bfbc00SFrederic Barrat "-d guest_errors -trace '*xive*'", 47931bfbc00SFrederic Barrat SMT, SMT); 48031bfbc00SFrederic Barrat init_xive(qts); 48131bfbc00SFrederic Barrat 48231bfbc00SFrederic Barrat test_hw_irq(qts); 48331bfbc00SFrederic Barrat 48431bfbc00SFrederic Barrat /* omit reset_state here and use settings from test_hw_irq */ 48531bfbc00SFrederic Barrat test_pull_thread_ctx_to_odd_thread_cl(qts); 48631bfbc00SFrederic Barrat 48731bfbc00SFrederic Barrat reset_state(qts); 488*c2b7fadeSFrederic Barrat test_hw_group_irq(qts); 489*c2b7fadeSFrederic Barrat 490*c2b7fadeSFrederic Barrat reset_state(qts); 491*c2b7fadeSFrederic Barrat test_hw_group_irq_backlog(qts); 492*c2b7fadeSFrederic Barrat 493*c2b7fadeSFrederic Barrat reset_state(qts); 49431bfbc00SFrederic Barrat test_flush_sync_inject(qts); 49531bfbc00SFrederic Barrat 49631bfbc00SFrederic Barrat qtest_quit(qts); 49731bfbc00SFrederic Barrat } 49831bfbc00SFrederic Barrat 49931bfbc00SFrederic Barrat int main(int argc, char **argv) 50031bfbc00SFrederic Barrat { 50131bfbc00SFrederic Barrat g_test_init(&argc, &argv, NULL); 50231bfbc00SFrederic Barrat qtest_add_func("xive2", test_xive); 50331bfbc00SFrederic Barrat return g_test_run(); 50431bfbc00SFrederic Barrat } 505