1*da71b7e3SCédric Le Goater /* 2*da71b7e3SCédric Le Goater * QEMU PowerPC XIVE2 interrupt controller model (POWER10) 3*da71b7e3SCédric Le Goater * 4*da71b7e3SCédric Le Goater * Copyright (c) 2019-2022, IBM Corporation. 5*da71b7e3SCédric Le Goater * 6*da71b7e3SCédric Le Goater * This code is licensed under the GPL version 2 or later. See the 7*da71b7e3SCédric Le Goater * COPYING file in the top-level directory. 8*da71b7e3SCédric Le Goater */ 9*da71b7e3SCédric Le Goater 10*da71b7e3SCédric Le Goater #include "qemu/osdep.h" 11*da71b7e3SCédric Le Goater #include "qemu/log.h" 12*da71b7e3SCédric Le Goater #include "qapi/error.h" 13*da71b7e3SCédric Le Goater #include "target/ppc/cpu.h" 14*da71b7e3SCédric Le Goater #include "sysemu/cpus.h" 15*da71b7e3SCédric Le Goater #include "sysemu/dma.h" 16*da71b7e3SCédric Le Goater #include "monitor/monitor.h" 17*da71b7e3SCédric Le Goater #include "hw/ppc/fdt.h" 18*da71b7e3SCédric Le Goater #include "hw/ppc/pnv.h" 19*da71b7e3SCédric Le Goater #include "hw/ppc/pnv_core.h" 20*da71b7e3SCédric Le Goater #include "hw/ppc/pnv_xscom.h" 21*da71b7e3SCédric Le Goater #include "hw/ppc/xive2.h" 22*da71b7e3SCédric Le Goater #include "hw/ppc/pnv_xive.h" 23*da71b7e3SCédric Le Goater #include "hw/ppc/xive_regs.h" 24*da71b7e3SCédric Le Goater #include "hw/ppc/xive2_regs.h" 25*da71b7e3SCédric Le Goater #include "hw/ppc/ppc.h" 26*da71b7e3SCédric Le Goater #include "hw/qdev-properties.h" 27*da71b7e3SCédric Le Goater #include "sysemu/reset.h" 28*da71b7e3SCédric Le Goater 29*da71b7e3SCédric Le Goater #include <libfdt.h> 30*da71b7e3SCédric Le Goater 31*da71b7e3SCédric Le Goater #include "pnv_xive2_regs.h" 32*da71b7e3SCédric Le Goater 33*da71b7e3SCédric Le Goater #undef XIVE2_DEBUG 34*da71b7e3SCédric Le Goater 35*da71b7e3SCédric Le Goater /* 36*da71b7e3SCédric Le Goater * Virtual structures table (VST) 37*da71b7e3SCédric Le Goater */ 38*da71b7e3SCédric Le Goater #define SBE_PER_BYTE 4 39*da71b7e3SCédric Le Goater 40*da71b7e3SCédric Le Goater typedef struct XiveVstInfo { 41*da71b7e3SCédric Le Goater const char *name; 42*da71b7e3SCédric Le Goater uint32_t size; 43*da71b7e3SCédric Le Goater uint32_t max_blocks; 44*da71b7e3SCédric Le Goater } XiveVstInfo; 45*da71b7e3SCédric Le Goater 46*da71b7e3SCédric Le Goater static const XiveVstInfo vst_infos[] = { 47*da71b7e3SCédric Le Goater 48*da71b7e3SCédric Le Goater [VST_EAS] = { "EAT", sizeof(Xive2Eas), 16 }, 49*da71b7e3SCédric Le Goater [VST_ESB] = { "ESB", 1, 16 }, 50*da71b7e3SCédric Le Goater [VST_END] = { "ENDT", sizeof(Xive2End), 16 }, 51*da71b7e3SCédric Le Goater 52*da71b7e3SCédric Le Goater [VST_NVP] = { "NVPT", sizeof(Xive2Nvp), 16 }, 53*da71b7e3SCédric Le Goater [VST_NVG] = { "NVGT", sizeof(Xive2Nvgc), 16 }, 54*da71b7e3SCédric Le Goater [VST_NVC] = { "NVCT", sizeof(Xive2Nvgc), 16 }, 55*da71b7e3SCédric Le Goater 56*da71b7e3SCédric Le Goater [VST_IC] = { "IC", 1 /* ? */ , 16 }, /* Topology # */ 57*da71b7e3SCédric Le Goater [VST_SYNC] = { "SYNC", 1 /* ? */ , 16 }, /* Topology # */ 58*da71b7e3SCédric Le Goater 59*da71b7e3SCédric Le Goater /* 60*da71b7e3SCédric Le Goater * This table contains the backing store pages for the interrupt 61*da71b7e3SCédric Le Goater * fifos of the VC sub-engine in case of overflow. 62*da71b7e3SCédric Le Goater * 63*da71b7e3SCédric Le Goater * 0 - IPI, 64*da71b7e3SCédric Le Goater * 1 - HWD, 65*da71b7e3SCédric Le Goater * 2 - NxC, 66*da71b7e3SCédric Le Goater * 3 - INT, 67*da71b7e3SCédric Le Goater * 4 - OS-Queue, 68*da71b7e3SCédric Le Goater * 5 - Pool-Queue, 69*da71b7e3SCédric Le Goater * 6 - Hard-Queue 70*da71b7e3SCédric Le Goater */ 71*da71b7e3SCédric Le Goater [VST_ERQ] = { "ERQ", 1, VC_QUEUE_COUNT }, 72*da71b7e3SCédric Le Goater }; 73*da71b7e3SCédric Le Goater 74*da71b7e3SCédric Le Goater #define xive2_error(xive, fmt, ...) \ 75*da71b7e3SCédric Le Goater qemu_log_mask(LOG_GUEST_ERROR, "XIVE[%x] - " fmt "\n", \ 76*da71b7e3SCédric Le Goater (xive)->chip->chip_id, ## __VA_ARGS__); 77*da71b7e3SCédric Le Goater 78*da71b7e3SCédric Le Goater /* 79*da71b7e3SCédric Le Goater * QEMU version of the GETFIELD/SETFIELD macros 80*da71b7e3SCédric Le Goater * 81*da71b7e3SCédric Le Goater * TODO: It might be better to use the existing extract64() and 82*da71b7e3SCédric Le Goater * deposit64() but this means that all the register definitions will 83*da71b7e3SCédric Le Goater * change and become incompatible with the ones found in skiboot. 84*da71b7e3SCédric Le Goater * 85*da71b7e3SCédric Le Goater * Keep it as it is for now until we find a common ground. 86*da71b7e3SCédric Le Goater */ 87*da71b7e3SCédric Le Goater static inline uint64_t GETFIELD(uint64_t mask, uint64_t word) 88*da71b7e3SCédric Le Goater { 89*da71b7e3SCédric Le Goater return (word & mask) >> ctz64(mask); 90*da71b7e3SCédric Le Goater } 91*da71b7e3SCédric Le Goater 92*da71b7e3SCédric Le Goater static inline uint64_t SETFIELD(uint64_t mask, uint64_t word, 93*da71b7e3SCédric Le Goater uint64_t value) 94*da71b7e3SCédric Le Goater { 95*da71b7e3SCédric Le Goater return (word & ~mask) | ((value << ctz64(mask)) & mask); 96*da71b7e3SCédric Le Goater } 97*da71b7e3SCédric Le Goater 98*da71b7e3SCédric Le Goater /* 99*da71b7e3SCédric Le Goater * TODO: Document block id override 100*da71b7e3SCédric Le Goater */ 101*da71b7e3SCédric Le Goater static uint32_t pnv_xive2_block_id(PnvXive2 *xive) 102*da71b7e3SCédric Le Goater { 103*da71b7e3SCédric Le Goater uint8_t blk = xive->chip->chip_id; 104*da71b7e3SCédric Le Goater uint64_t cfg_val = xive->cq_regs[CQ_XIVE_CFG >> 3]; 105*da71b7e3SCédric Le Goater 106*da71b7e3SCédric Le Goater if (cfg_val & CQ_XIVE_CFG_HYP_HARD_BLKID_OVERRIDE) { 107*da71b7e3SCédric Le Goater blk = GETFIELD(CQ_XIVE_CFG_HYP_HARD_BLOCK_ID, cfg_val); 108*da71b7e3SCédric Le Goater } 109*da71b7e3SCédric Le Goater 110*da71b7e3SCédric Le Goater return blk; 111*da71b7e3SCédric Le Goater } 112*da71b7e3SCédric Le Goater 113*da71b7e3SCédric Le Goater /* 114*da71b7e3SCédric Le Goater * Remote access to controllers. HW uses MMIOs. For now, a simple scan 115*da71b7e3SCédric Le Goater * of the chips is good enough. 116*da71b7e3SCédric Le Goater * 117*da71b7e3SCédric Le Goater * TODO: Block scope support 118*da71b7e3SCédric Le Goater */ 119*da71b7e3SCédric Le Goater static PnvXive2 *pnv_xive2_get_remote(uint8_t blk) 120*da71b7e3SCédric Le Goater { 121*da71b7e3SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine()); 122*da71b7e3SCédric Le Goater int i; 123*da71b7e3SCédric Le Goater 124*da71b7e3SCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 125*da71b7e3SCédric Le Goater Pnv10Chip *chip10 = PNV10_CHIP(pnv->chips[i]); 126*da71b7e3SCédric Le Goater PnvXive2 *xive = &chip10->xive; 127*da71b7e3SCédric Le Goater 128*da71b7e3SCédric Le Goater if (pnv_xive2_block_id(xive) == blk) { 129*da71b7e3SCédric Le Goater return xive; 130*da71b7e3SCédric Le Goater } 131*da71b7e3SCédric Le Goater } 132*da71b7e3SCédric Le Goater return NULL; 133*da71b7e3SCédric Le Goater } 134*da71b7e3SCédric Le Goater 135*da71b7e3SCédric Le Goater /* 136*da71b7e3SCédric Le Goater * VST accessors for ESB, EAT, ENDT, NVP 137*da71b7e3SCédric Le Goater * 138*da71b7e3SCédric Le Goater * Indirect VST tables are arrays of VSDs pointing to a page (of same 139*da71b7e3SCédric Le Goater * size). Each page is a direct VST table. 140*da71b7e3SCédric Le Goater */ 141*da71b7e3SCédric Le Goater 142*da71b7e3SCédric Le Goater #define XIVE_VSD_SIZE 8 143*da71b7e3SCédric Le Goater 144*da71b7e3SCédric Le Goater /* Indirect page size can be 4K, 64K, 2M, 16M. */ 145*da71b7e3SCédric Le Goater static uint64_t pnv_xive2_vst_page_size_allowed(uint32_t page_shift) 146*da71b7e3SCédric Le Goater { 147*da71b7e3SCédric Le Goater return page_shift == 12 || page_shift == 16 || 148*da71b7e3SCédric Le Goater page_shift == 21 || page_shift == 24; 149*da71b7e3SCédric Le Goater } 150*da71b7e3SCédric Le Goater 151*da71b7e3SCédric Le Goater static uint64_t pnv_xive2_vst_addr_direct(PnvXive2 *xive, uint32_t type, 152*da71b7e3SCédric Le Goater uint64_t vsd, uint32_t idx) 153*da71b7e3SCédric Le Goater { 154*da71b7e3SCédric Le Goater const XiveVstInfo *info = &vst_infos[type]; 155*da71b7e3SCédric Le Goater uint64_t vst_addr = vsd & VSD_ADDRESS_MASK; 156*da71b7e3SCédric Le Goater uint64_t vst_tsize = 1ull << (GETFIELD(VSD_TSIZE, vsd) + 12); 157*da71b7e3SCédric Le Goater uint32_t idx_max; 158*da71b7e3SCédric Le Goater 159*da71b7e3SCédric Le Goater idx_max = vst_tsize / info->size - 1; 160*da71b7e3SCédric Le Goater if (idx > idx_max) { 161*da71b7e3SCédric Le Goater #ifdef XIVE2_DEBUG 162*da71b7e3SCédric Le Goater xive2_error(xive, "VST: %s entry %x out of range [ 0 .. %x ] !?", 163*da71b7e3SCédric Le Goater info->name, idx, idx_max); 164*da71b7e3SCédric Le Goater #endif 165*da71b7e3SCédric Le Goater return 0; 166*da71b7e3SCédric Le Goater } 167*da71b7e3SCédric Le Goater 168*da71b7e3SCédric Le Goater return vst_addr + idx * info->size; 169*da71b7e3SCédric Le Goater } 170*da71b7e3SCédric Le Goater 171*da71b7e3SCédric Le Goater static uint64_t pnv_xive2_vst_addr_indirect(PnvXive2 *xive, uint32_t type, 172*da71b7e3SCédric Le Goater uint64_t vsd, uint32_t idx) 173*da71b7e3SCédric Le Goater { 174*da71b7e3SCédric Le Goater const XiveVstInfo *info = &vst_infos[type]; 175*da71b7e3SCédric Le Goater uint64_t vsd_addr; 176*da71b7e3SCédric Le Goater uint32_t vsd_idx; 177*da71b7e3SCédric Le Goater uint32_t page_shift; 178*da71b7e3SCédric Le Goater uint32_t vst_per_page; 179*da71b7e3SCédric Le Goater 180*da71b7e3SCédric Le Goater /* Get the page size of the indirect table. */ 181*da71b7e3SCédric Le Goater vsd_addr = vsd & VSD_ADDRESS_MASK; 182*da71b7e3SCédric Le Goater ldq_be_dma(&address_space_memory, vsd_addr, &vsd, MEMTXATTRS_UNSPECIFIED); 183*da71b7e3SCédric Le Goater 184*da71b7e3SCédric Le Goater if (!(vsd & VSD_ADDRESS_MASK)) { 185*da71b7e3SCédric Le Goater xive2_error(xive, "VST: invalid %s entry %x !?", info->name, idx); 186*da71b7e3SCédric Le Goater return 0; 187*da71b7e3SCédric Le Goater } 188*da71b7e3SCédric Le Goater 189*da71b7e3SCédric Le Goater page_shift = GETFIELD(VSD_TSIZE, vsd) + 12; 190*da71b7e3SCédric Le Goater 191*da71b7e3SCédric Le Goater if (!pnv_xive2_vst_page_size_allowed(page_shift)) { 192*da71b7e3SCédric Le Goater xive2_error(xive, "VST: invalid %s page shift %d", info->name, 193*da71b7e3SCédric Le Goater page_shift); 194*da71b7e3SCédric Le Goater return 0; 195*da71b7e3SCédric Le Goater } 196*da71b7e3SCédric Le Goater 197*da71b7e3SCédric Le Goater vst_per_page = (1ull << page_shift) / info->size; 198*da71b7e3SCédric Le Goater vsd_idx = idx / vst_per_page; 199*da71b7e3SCédric Le Goater 200*da71b7e3SCédric Le Goater /* Load the VSD we are looking for, if not already done */ 201*da71b7e3SCédric Le Goater if (vsd_idx) { 202*da71b7e3SCédric Le Goater vsd_addr = vsd_addr + vsd_idx * XIVE_VSD_SIZE; 203*da71b7e3SCédric Le Goater ldq_be_dma(&address_space_memory, vsd_addr, &vsd, 204*da71b7e3SCédric Le Goater MEMTXATTRS_UNSPECIFIED); 205*da71b7e3SCédric Le Goater 206*da71b7e3SCédric Le Goater if (!(vsd & VSD_ADDRESS_MASK)) { 207*da71b7e3SCédric Le Goater xive2_error(xive, "VST: invalid %s entry %x !?", info->name, idx); 208*da71b7e3SCédric Le Goater return 0; 209*da71b7e3SCédric Le Goater } 210*da71b7e3SCédric Le Goater 211*da71b7e3SCédric Le Goater /* 212*da71b7e3SCédric Le Goater * Check that the pages have a consistent size across the 213*da71b7e3SCédric Le Goater * indirect table 214*da71b7e3SCédric Le Goater */ 215*da71b7e3SCédric Le Goater if (page_shift != GETFIELD(VSD_TSIZE, vsd) + 12) { 216*da71b7e3SCédric Le Goater xive2_error(xive, "VST: %s entry %x indirect page size differ !?", 217*da71b7e3SCédric Le Goater info->name, idx); 218*da71b7e3SCédric Le Goater return 0; 219*da71b7e3SCédric Le Goater } 220*da71b7e3SCédric Le Goater } 221*da71b7e3SCédric Le Goater 222*da71b7e3SCédric Le Goater return pnv_xive2_vst_addr_direct(xive, type, vsd, (idx % vst_per_page)); 223*da71b7e3SCédric Le Goater } 224*da71b7e3SCédric Le Goater 225*da71b7e3SCédric Le Goater static uint64_t pnv_xive2_vst_addr(PnvXive2 *xive, uint32_t type, uint8_t blk, 226*da71b7e3SCédric Le Goater uint32_t idx) 227*da71b7e3SCédric Le Goater { 228*da71b7e3SCédric Le Goater const XiveVstInfo *info = &vst_infos[type]; 229*da71b7e3SCédric Le Goater uint64_t vsd; 230*da71b7e3SCédric Le Goater 231*da71b7e3SCédric Le Goater if (blk >= info->max_blocks) { 232*da71b7e3SCédric Le Goater xive2_error(xive, "VST: invalid block id %d for VST %s %d !?", 233*da71b7e3SCédric Le Goater blk, info->name, idx); 234*da71b7e3SCédric Le Goater return 0; 235*da71b7e3SCédric Le Goater } 236*da71b7e3SCédric Le Goater 237*da71b7e3SCédric Le Goater vsd = xive->vsds[type][blk]; 238*da71b7e3SCédric Le Goater 239*da71b7e3SCédric Le Goater /* Remote VST access */ 240*da71b7e3SCédric Le Goater if (GETFIELD(VSD_MODE, vsd) == VSD_MODE_FORWARD) { 241*da71b7e3SCédric Le Goater xive = pnv_xive2_get_remote(blk); 242*da71b7e3SCédric Le Goater 243*da71b7e3SCédric Le Goater return xive ? pnv_xive2_vst_addr(xive, type, blk, idx) : 0; 244*da71b7e3SCédric Le Goater } 245*da71b7e3SCédric Le Goater 246*da71b7e3SCédric Le Goater if (VSD_INDIRECT & vsd) { 247*da71b7e3SCédric Le Goater return pnv_xive2_vst_addr_indirect(xive, type, vsd, idx); 248*da71b7e3SCédric Le Goater } 249*da71b7e3SCédric Le Goater 250*da71b7e3SCédric Le Goater return pnv_xive2_vst_addr_direct(xive, type, vsd, idx); 251*da71b7e3SCédric Le Goater } 252*da71b7e3SCédric Le Goater 253*da71b7e3SCédric Le Goater static int pnv_xive2_vst_read(PnvXive2 *xive, uint32_t type, uint8_t blk, 254*da71b7e3SCédric Le Goater uint32_t idx, void *data) 255*da71b7e3SCédric Le Goater { 256*da71b7e3SCédric Le Goater const XiveVstInfo *info = &vst_infos[type]; 257*da71b7e3SCédric Le Goater uint64_t addr = pnv_xive2_vst_addr(xive, type, blk, idx); 258*da71b7e3SCédric Le Goater 259*da71b7e3SCédric Le Goater if (!addr) { 260*da71b7e3SCédric Le Goater return -1; 261*da71b7e3SCédric Le Goater } 262*da71b7e3SCédric Le Goater 263*da71b7e3SCédric Le Goater cpu_physical_memory_read(addr, data, info->size); 264*da71b7e3SCédric Le Goater return 0; 265*da71b7e3SCédric Le Goater } 266*da71b7e3SCédric Le Goater 267*da71b7e3SCédric Le Goater #define XIVE_VST_WORD_ALL -1 268*da71b7e3SCédric Le Goater 269*da71b7e3SCédric Le Goater static int pnv_xive2_vst_write(PnvXive2 *xive, uint32_t type, uint8_t blk, 270*da71b7e3SCédric Le Goater uint32_t idx, void *data, uint32_t word_number) 271*da71b7e3SCédric Le Goater { 272*da71b7e3SCédric Le Goater const XiveVstInfo *info = &vst_infos[type]; 273*da71b7e3SCédric Le Goater uint64_t addr = pnv_xive2_vst_addr(xive, type, blk, idx); 274*da71b7e3SCédric Le Goater 275*da71b7e3SCédric Le Goater if (!addr) { 276*da71b7e3SCédric Le Goater return -1; 277*da71b7e3SCédric Le Goater } 278*da71b7e3SCédric Le Goater 279*da71b7e3SCédric Le Goater if (word_number == XIVE_VST_WORD_ALL) { 280*da71b7e3SCédric Le Goater cpu_physical_memory_write(addr, data, info->size); 281*da71b7e3SCédric Le Goater } else { 282*da71b7e3SCédric Le Goater cpu_physical_memory_write(addr + word_number * 4, 283*da71b7e3SCédric Le Goater data + word_number * 4, 4); 284*da71b7e3SCédric Le Goater } 285*da71b7e3SCédric Le Goater return 0; 286*da71b7e3SCédric Le Goater } 287*da71b7e3SCédric Le Goater 288*da71b7e3SCédric Le Goater static int pnv_xive2_get_end(Xive2Router *xrtr, uint8_t blk, uint32_t idx, 289*da71b7e3SCédric Le Goater Xive2End *end) 290*da71b7e3SCédric Le Goater { 291*da71b7e3SCédric Le Goater return pnv_xive2_vst_read(PNV_XIVE2(xrtr), VST_END, blk, idx, end); 292*da71b7e3SCédric Le Goater } 293*da71b7e3SCédric Le Goater 294*da71b7e3SCédric Le Goater static int pnv_xive2_write_end(Xive2Router *xrtr, uint8_t blk, uint32_t idx, 295*da71b7e3SCédric Le Goater Xive2End *end, uint8_t word_number) 296*da71b7e3SCédric Le Goater { 297*da71b7e3SCédric Le Goater return pnv_xive2_vst_write(PNV_XIVE2(xrtr), VST_END, blk, idx, end, 298*da71b7e3SCédric Le Goater word_number); 299*da71b7e3SCédric Le Goater } 300*da71b7e3SCédric Le Goater 301*da71b7e3SCédric Le Goater static int pnv_xive2_end_update(PnvXive2 *xive) 302*da71b7e3SCédric Le Goater { 303*da71b7e3SCédric Le Goater uint8_t blk = GETFIELD(VC_ENDC_WATCH_BLOCK_ID, 304*da71b7e3SCédric Le Goater xive->vc_regs[(VC_ENDC_WATCH0_SPEC >> 3)]); 305*da71b7e3SCédric Le Goater uint32_t idx = GETFIELD(VC_ENDC_WATCH_INDEX, 306*da71b7e3SCédric Le Goater xive->vc_regs[(VC_ENDC_WATCH0_SPEC >> 3)]); 307*da71b7e3SCédric Le Goater int i; 308*da71b7e3SCédric Le Goater uint64_t endc_watch[4]; 309*da71b7e3SCédric Le Goater 310*da71b7e3SCédric Le Goater for (i = 0; i < ARRAY_SIZE(endc_watch); i++) { 311*da71b7e3SCédric Le Goater endc_watch[i] = 312*da71b7e3SCédric Le Goater cpu_to_be64(xive->vc_regs[(VC_ENDC_WATCH0_DATA0 >> 3) + i]); 313*da71b7e3SCédric Le Goater } 314*da71b7e3SCédric Le Goater 315*da71b7e3SCédric Le Goater return pnv_xive2_vst_write(xive, VST_END, blk, idx, endc_watch, 316*da71b7e3SCédric Le Goater XIVE_VST_WORD_ALL); 317*da71b7e3SCédric Le Goater } 318*da71b7e3SCédric Le Goater 319*da71b7e3SCédric Le Goater static void pnv_xive2_end_cache_load(PnvXive2 *xive) 320*da71b7e3SCédric Le Goater { 321*da71b7e3SCédric Le Goater uint8_t blk = GETFIELD(VC_ENDC_WATCH_BLOCK_ID, 322*da71b7e3SCédric Le Goater xive->vc_regs[(VC_ENDC_WATCH0_SPEC >> 3)]); 323*da71b7e3SCédric Le Goater uint32_t idx = GETFIELD(VC_ENDC_WATCH_INDEX, 324*da71b7e3SCédric Le Goater xive->vc_regs[(VC_ENDC_WATCH0_SPEC >> 3)]); 325*da71b7e3SCédric Le Goater uint64_t endc_watch[4] = { 0 }; 326*da71b7e3SCédric Le Goater int i; 327*da71b7e3SCédric Le Goater 328*da71b7e3SCédric Le Goater if (pnv_xive2_vst_read(xive, VST_END, blk, idx, endc_watch)) { 329*da71b7e3SCédric Le Goater xive2_error(xive, "VST: no END entry %x/%x !?", blk, idx); 330*da71b7e3SCédric Le Goater } 331*da71b7e3SCédric Le Goater 332*da71b7e3SCédric Le Goater for (i = 0; i < ARRAY_SIZE(endc_watch); i++) { 333*da71b7e3SCédric Le Goater xive->vc_regs[(VC_ENDC_WATCH0_DATA0 >> 3) + i] = 334*da71b7e3SCédric Le Goater be64_to_cpu(endc_watch[i]); 335*da71b7e3SCédric Le Goater } 336*da71b7e3SCédric Le Goater } 337*da71b7e3SCédric Le Goater 338*da71b7e3SCédric Le Goater static int pnv_xive2_get_nvp(Xive2Router *xrtr, uint8_t blk, uint32_t idx, 339*da71b7e3SCédric Le Goater Xive2Nvp *nvp) 340*da71b7e3SCédric Le Goater { 341*da71b7e3SCédric Le Goater return pnv_xive2_vst_read(PNV_XIVE2(xrtr), VST_NVP, blk, idx, nvp); 342*da71b7e3SCédric Le Goater } 343*da71b7e3SCédric Le Goater 344*da71b7e3SCédric Le Goater static int pnv_xive2_write_nvp(Xive2Router *xrtr, uint8_t blk, uint32_t idx, 345*da71b7e3SCédric Le Goater Xive2Nvp *nvp, uint8_t word_number) 346*da71b7e3SCédric Le Goater { 347*da71b7e3SCédric Le Goater return pnv_xive2_vst_write(PNV_XIVE2(xrtr), VST_NVP, blk, idx, nvp, 348*da71b7e3SCédric Le Goater word_number); 349*da71b7e3SCédric Le Goater } 350*da71b7e3SCédric Le Goater 351*da71b7e3SCédric Le Goater static int pnv_xive2_nvp_update(PnvXive2 *xive) 352*da71b7e3SCédric Le Goater { 353*da71b7e3SCédric Le Goater uint8_t blk = GETFIELD(PC_NXC_WATCH_BLOCK_ID, 354*da71b7e3SCédric Le Goater xive->pc_regs[(PC_NXC_WATCH0_SPEC >> 3)]); 355*da71b7e3SCédric Le Goater uint32_t idx = GETFIELD(PC_NXC_WATCH_INDEX, 356*da71b7e3SCédric Le Goater xive->pc_regs[(PC_NXC_WATCH0_SPEC >> 3)]); 357*da71b7e3SCédric Le Goater int i; 358*da71b7e3SCédric Le Goater uint64_t nxc_watch[4]; 359*da71b7e3SCédric Le Goater 360*da71b7e3SCédric Le Goater for (i = 0; i < ARRAY_SIZE(nxc_watch); i++) { 361*da71b7e3SCédric Le Goater nxc_watch[i] = 362*da71b7e3SCédric Le Goater cpu_to_be64(xive->pc_regs[(PC_NXC_WATCH0_DATA0 >> 3) + i]); 363*da71b7e3SCédric Le Goater } 364*da71b7e3SCédric Le Goater 365*da71b7e3SCédric Le Goater return pnv_xive2_vst_write(xive, VST_NVP, blk, idx, nxc_watch, 366*da71b7e3SCédric Le Goater XIVE_VST_WORD_ALL); 367*da71b7e3SCédric Le Goater } 368*da71b7e3SCédric Le Goater 369*da71b7e3SCédric Le Goater static void pnv_xive2_nvp_cache_load(PnvXive2 *xive) 370*da71b7e3SCédric Le Goater { 371*da71b7e3SCédric Le Goater uint8_t blk = GETFIELD(PC_NXC_WATCH_BLOCK_ID, 372*da71b7e3SCédric Le Goater xive->pc_regs[(PC_NXC_WATCH0_SPEC >> 3)]); 373*da71b7e3SCédric Le Goater uint32_t idx = GETFIELD(PC_NXC_WATCH_INDEX, 374*da71b7e3SCédric Le Goater xive->pc_regs[(PC_NXC_WATCH0_SPEC >> 3)]); 375*da71b7e3SCédric Le Goater uint64_t nxc_watch[4] = { 0 }; 376*da71b7e3SCédric Le Goater int i; 377*da71b7e3SCédric Le Goater 378*da71b7e3SCédric Le Goater if (pnv_xive2_vst_read(xive, VST_NVP, blk, idx, nxc_watch)) { 379*da71b7e3SCédric Le Goater xive2_error(xive, "VST: no NVP entry %x/%x !?", blk, idx); 380*da71b7e3SCédric Le Goater } 381*da71b7e3SCédric Le Goater 382*da71b7e3SCédric Le Goater for (i = 0; i < ARRAY_SIZE(nxc_watch); i++) { 383*da71b7e3SCédric Le Goater xive->pc_regs[(PC_NXC_WATCH0_DATA0 >> 3) + i] = 384*da71b7e3SCédric Le Goater be64_to_cpu(nxc_watch[i]); 385*da71b7e3SCédric Le Goater } 386*da71b7e3SCédric Le Goater } 387*da71b7e3SCédric Le Goater 388*da71b7e3SCédric Le Goater static int pnv_xive2_get_eas(Xive2Router *xrtr, uint8_t blk, uint32_t idx, 389*da71b7e3SCédric Le Goater Xive2Eas *eas) 390*da71b7e3SCédric Le Goater { 391*da71b7e3SCédric Le Goater PnvXive2 *xive = PNV_XIVE2(xrtr); 392*da71b7e3SCédric Le Goater 393*da71b7e3SCédric Le Goater if (pnv_xive2_block_id(xive) != blk) { 394*da71b7e3SCédric Le Goater xive2_error(xive, "VST: EAS %x is remote !?", XIVE_EAS(blk, idx)); 395*da71b7e3SCédric Le Goater return -1; 396*da71b7e3SCédric Le Goater } 397*da71b7e3SCédric Le Goater 398*da71b7e3SCédric Le Goater return pnv_xive2_vst_read(xive, VST_EAS, blk, idx, eas); 399*da71b7e3SCédric Le Goater } 400*da71b7e3SCédric Le Goater 401*da71b7e3SCédric Le Goater static bool pnv_xive2_is_cpu_enabled(PnvXive2 *xive, PowerPCCPU *cpu) 402*da71b7e3SCédric Le Goater { 403*da71b7e3SCédric Le Goater int pir = ppc_cpu_pir(cpu); 404*da71b7e3SCédric Le Goater uint32_t fc = PNV10_PIR2FUSEDCORE(pir); 405*da71b7e3SCédric Le Goater uint64_t reg = fc < 8 ? TCTXT_EN0 : TCTXT_EN1; 406*da71b7e3SCédric Le Goater uint32_t bit = pir & 0x3f; 407*da71b7e3SCédric Le Goater 408*da71b7e3SCédric Le Goater return xive->tctxt_regs[reg >> 3] & PPC_BIT(bit); 409*da71b7e3SCédric Le Goater } 410*da71b7e3SCédric Le Goater 411*da71b7e3SCédric Le Goater static int pnv_xive2_match_nvt(XivePresenter *xptr, uint8_t format, 412*da71b7e3SCédric Le Goater uint8_t nvt_blk, uint32_t nvt_idx, 413*da71b7e3SCédric Le Goater bool cam_ignore, uint8_t priority, 414*da71b7e3SCédric Le Goater uint32_t logic_serv, XiveTCTXMatch *match) 415*da71b7e3SCédric Le Goater { 416*da71b7e3SCédric Le Goater PnvXive2 *xive = PNV_XIVE2(xptr); 417*da71b7e3SCédric Le Goater PnvChip *chip = xive->chip; 418*da71b7e3SCédric Le Goater int count = 0; 419*da71b7e3SCédric Le Goater int i, j; 420*da71b7e3SCédric Le Goater 421*da71b7e3SCédric Le Goater for (i = 0; i < chip->nr_cores; i++) { 422*da71b7e3SCédric Le Goater PnvCore *pc = chip->cores[i]; 423*da71b7e3SCédric Le Goater CPUCore *cc = CPU_CORE(pc); 424*da71b7e3SCédric Le Goater 425*da71b7e3SCédric Le Goater for (j = 0; j < cc->nr_threads; j++) { 426*da71b7e3SCédric Le Goater PowerPCCPU *cpu = pc->threads[j]; 427*da71b7e3SCédric Le Goater XiveTCTX *tctx; 428*da71b7e3SCédric Le Goater int ring; 429*da71b7e3SCédric Le Goater 430*da71b7e3SCédric Le Goater if (!pnv_xive2_is_cpu_enabled(xive, cpu)) { 431*da71b7e3SCédric Le Goater continue; 432*da71b7e3SCédric Le Goater } 433*da71b7e3SCédric Le Goater 434*da71b7e3SCédric Le Goater tctx = XIVE_TCTX(pnv_cpu_state(cpu)->intc); 435*da71b7e3SCédric Le Goater 436*da71b7e3SCédric Le Goater ring = xive2_presenter_tctx_match(xptr, tctx, format, nvt_blk, 437*da71b7e3SCédric Le Goater nvt_idx, cam_ignore, 438*da71b7e3SCédric Le Goater logic_serv); 439*da71b7e3SCédric Le Goater 440*da71b7e3SCédric Le Goater /* 441*da71b7e3SCédric Le Goater * Save the context and follow on to catch duplicates, 442*da71b7e3SCédric Le Goater * that we don't support yet. 443*da71b7e3SCédric Le Goater */ 444*da71b7e3SCédric Le Goater if (ring != -1) { 445*da71b7e3SCédric Le Goater if (match->tctx) { 446*da71b7e3SCédric Le Goater qemu_log_mask(LOG_GUEST_ERROR, "XIVE: already found a " 447*da71b7e3SCédric Le Goater "thread context NVT %x/%x\n", 448*da71b7e3SCédric Le Goater nvt_blk, nvt_idx); 449*da71b7e3SCédric Le Goater return false; 450*da71b7e3SCédric Le Goater } 451*da71b7e3SCédric Le Goater 452*da71b7e3SCédric Le Goater match->ring = ring; 453*da71b7e3SCédric Le Goater match->tctx = tctx; 454*da71b7e3SCédric Le Goater count++; 455*da71b7e3SCédric Le Goater } 456*da71b7e3SCédric Le Goater } 457*da71b7e3SCédric Le Goater } 458*da71b7e3SCédric Le Goater 459*da71b7e3SCédric Le Goater return count; 460*da71b7e3SCédric Le Goater } 461*da71b7e3SCédric Le Goater 462*da71b7e3SCédric Le Goater static uint8_t pnv_xive2_get_block_id(Xive2Router *xrtr) 463*da71b7e3SCédric Le Goater { 464*da71b7e3SCédric Le Goater return pnv_xive2_block_id(PNV_XIVE2(xrtr)); 465*da71b7e3SCédric Le Goater } 466*da71b7e3SCédric Le Goater 467*da71b7e3SCédric Le Goater /* 468*da71b7e3SCédric Le Goater * The TIMA MMIO space is shared among the chips and to identify the 469*da71b7e3SCédric Le Goater * chip from which the access is being done, we extract the chip id 470*da71b7e3SCédric Le Goater * from the PIR. 471*da71b7e3SCédric Le Goater */ 472*da71b7e3SCédric Le Goater static PnvXive2 *pnv_xive2_tm_get_xive(PowerPCCPU *cpu) 473*da71b7e3SCédric Le Goater { 474*da71b7e3SCédric Le Goater int pir = ppc_cpu_pir(cpu); 475*da71b7e3SCédric Le Goater XivePresenter *xptr = XIVE_TCTX(pnv_cpu_state(cpu)->intc)->xptr; 476*da71b7e3SCédric Le Goater PnvXive2 *xive = PNV_XIVE2(xptr); 477*da71b7e3SCédric Le Goater 478*da71b7e3SCédric Le Goater if (!pnv_xive2_is_cpu_enabled(xive, cpu)) { 479*da71b7e3SCédric Le Goater xive2_error(xive, "IC: CPU %x is not enabled", pir); 480*da71b7e3SCédric Le Goater } 481*da71b7e3SCédric Le Goater return xive; 482*da71b7e3SCédric Le Goater } 483*da71b7e3SCédric Le Goater 484*da71b7e3SCédric Le Goater /* 485*da71b7e3SCédric Le Goater * The internal sources of the interrupt controller have no knowledge 486*da71b7e3SCédric Le Goater * of the XIVE2 chip on which they reside. Encode the block id in the 487*da71b7e3SCédric Le Goater * source interrupt number before forwarding the source event 488*da71b7e3SCédric Le Goater * notification to the Router. This is required on a multichip system. 489*da71b7e3SCédric Le Goater */ 490*da71b7e3SCédric Le Goater static void pnv_xive2_notify(XiveNotifier *xn, uint32_t srcno) 491*da71b7e3SCédric Le Goater { 492*da71b7e3SCédric Le Goater PnvXive2 *xive = PNV_XIVE2(xn); 493*da71b7e3SCédric Le Goater uint8_t blk = pnv_xive2_block_id(xive); 494*da71b7e3SCédric Le Goater 495*da71b7e3SCédric Le Goater xive2_router_notify(xn, XIVE_EAS(blk, srcno)); 496*da71b7e3SCédric Le Goater } 497*da71b7e3SCédric Le Goater 498*da71b7e3SCédric Le Goater /* 499*da71b7e3SCédric Le Goater * Set Translation Tables 500*da71b7e3SCédric Le Goater * 501*da71b7e3SCédric Le Goater * TODO add support for multiple sets 502*da71b7e3SCédric Le Goater */ 503*da71b7e3SCédric Le Goater static int pnv_xive2_stt_set_data(PnvXive2 *xive, uint64_t val) 504*da71b7e3SCédric Le Goater { 505*da71b7e3SCédric Le Goater uint8_t tsel = GETFIELD(CQ_TAR_SELECT, xive->cq_regs[CQ_TAR >> 3]); 506*da71b7e3SCédric Le Goater uint8_t entry = GETFIELD(CQ_TAR_ENTRY_SELECT, 507*da71b7e3SCédric Le Goater xive->cq_regs[CQ_TAR >> 3]); 508*da71b7e3SCédric Le Goater 509*da71b7e3SCédric Le Goater switch (tsel) { 510*da71b7e3SCédric Le Goater case CQ_TAR_NVPG: 511*da71b7e3SCédric Le Goater case CQ_TAR_ESB: 512*da71b7e3SCédric Le Goater case CQ_TAR_END: 513*da71b7e3SCédric Le Goater xive->tables[tsel][entry] = val; 514*da71b7e3SCédric Le Goater break; 515*da71b7e3SCédric Le Goater default: 516*da71b7e3SCédric Le Goater xive2_error(xive, "IC: unsupported table %d", tsel); 517*da71b7e3SCédric Le Goater return -1; 518*da71b7e3SCédric Le Goater } 519*da71b7e3SCédric Le Goater 520*da71b7e3SCédric Le Goater if (xive->cq_regs[CQ_TAR >> 3] & CQ_TAR_AUTOINC) { 521*da71b7e3SCédric Le Goater xive->cq_regs[CQ_TAR >> 3] = SETFIELD(CQ_TAR_ENTRY_SELECT, 522*da71b7e3SCédric Le Goater xive->cq_regs[CQ_TAR >> 3], ++entry); 523*da71b7e3SCédric Le Goater } 524*da71b7e3SCédric Le Goater 525*da71b7e3SCédric Le Goater return 0; 526*da71b7e3SCédric Le Goater } 527*da71b7e3SCédric Le Goater /* 528*da71b7e3SCédric Le Goater * Virtual Structure Tables (VST) configuration 529*da71b7e3SCédric Le Goater */ 530*da71b7e3SCédric Le Goater static void pnv_xive2_vst_set_exclusive(PnvXive2 *xive, uint8_t type, 531*da71b7e3SCédric Le Goater uint8_t blk, uint64_t vsd) 532*da71b7e3SCédric Le Goater { 533*da71b7e3SCédric Le Goater Xive2EndSource *end_xsrc = &xive->end_source; 534*da71b7e3SCédric Le Goater XiveSource *xsrc = &xive->ipi_source; 535*da71b7e3SCédric Le Goater const XiveVstInfo *info = &vst_infos[type]; 536*da71b7e3SCédric Le Goater uint32_t page_shift = GETFIELD(VSD_TSIZE, vsd) + 12; 537*da71b7e3SCédric Le Goater uint64_t vst_tsize = 1ull << page_shift; 538*da71b7e3SCédric Le Goater uint64_t vst_addr = vsd & VSD_ADDRESS_MASK; 539*da71b7e3SCédric Le Goater 540*da71b7e3SCédric Le Goater /* Basic checks */ 541*da71b7e3SCédric Le Goater 542*da71b7e3SCédric Le Goater if (VSD_INDIRECT & vsd) { 543*da71b7e3SCédric Le Goater if (!pnv_xive2_vst_page_size_allowed(page_shift)) { 544*da71b7e3SCédric Le Goater xive2_error(xive, "VST: invalid %s page shift %d", info->name, 545*da71b7e3SCédric Le Goater page_shift); 546*da71b7e3SCédric Le Goater return; 547*da71b7e3SCédric Le Goater } 548*da71b7e3SCédric Le Goater } 549*da71b7e3SCédric Le Goater 550*da71b7e3SCédric Le Goater if (!QEMU_IS_ALIGNED(vst_addr, 1ull << page_shift)) { 551*da71b7e3SCédric Le Goater xive2_error(xive, "VST: %s table address 0x%"PRIx64 552*da71b7e3SCédric Le Goater " is not aligned with page shift %d", 553*da71b7e3SCédric Le Goater info->name, vst_addr, page_shift); 554*da71b7e3SCédric Le Goater return; 555*da71b7e3SCédric Le Goater } 556*da71b7e3SCédric Le Goater 557*da71b7e3SCédric Le Goater /* Record the table configuration (in SRAM on HW) */ 558*da71b7e3SCédric Le Goater xive->vsds[type][blk] = vsd; 559*da71b7e3SCédric Le Goater 560*da71b7e3SCédric Le Goater /* Now tune the models with the configuration provided by the FW */ 561*da71b7e3SCédric Le Goater 562*da71b7e3SCédric Le Goater switch (type) { 563*da71b7e3SCédric Le Goater case VST_ESB: 564*da71b7e3SCédric Le Goater /* 565*da71b7e3SCédric Le Goater * Backing store pages for the source PQ bits. The model does 566*da71b7e3SCédric Le Goater * not use these PQ bits backed in RAM because the XiveSource 567*da71b7e3SCédric Le Goater * model has its own. 568*da71b7e3SCédric Le Goater * 569*da71b7e3SCédric Le Goater * If the table is direct, we can compute the number of PQ 570*da71b7e3SCédric Le Goater * entries provisioned by FW (such as skiboot) and resize the 571*da71b7e3SCédric Le Goater * ESB window accordingly. 572*da71b7e3SCédric Le Goater */ 573*da71b7e3SCédric Le Goater if (!(VSD_INDIRECT & vsd)) { 574*da71b7e3SCédric Le Goater memory_region_set_size(&xsrc->esb_mmio, vst_tsize * SBE_PER_BYTE 575*da71b7e3SCédric Le Goater * (1ull << xsrc->esb_shift)); 576*da71b7e3SCédric Le Goater } 577*da71b7e3SCédric Le Goater 578*da71b7e3SCédric Le Goater memory_region_add_subregion(&xive->esb_mmio, 0, &xsrc->esb_mmio); 579*da71b7e3SCédric Le Goater break; 580*da71b7e3SCédric Le Goater 581*da71b7e3SCédric Le Goater case VST_EAS: /* Nothing to be done */ 582*da71b7e3SCédric Le Goater break; 583*da71b7e3SCédric Le Goater 584*da71b7e3SCédric Le Goater case VST_END: 585*da71b7e3SCédric Le Goater /* 586*da71b7e3SCédric Le Goater * Backing store pages for the END. 587*da71b7e3SCédric Le Goater */ 588*da71b7e3SCédric Le Goater if (!(VSD_INDIRECT & vsd)) { 589*da71b7e3SCédric Le Goater memory_region_set_size(&end_xsrc->esb_mmio, (vst_tsize / info->size) 590*da71b7e3SCédric Le Goater * (1ull << end_xsrc->esb_shift)); 591*da71b7e3SCédric Le Goater } 592*da71b7e3SCédric Le Goater memory_region_add_subregion(&xive->end_mmio, 0, &end_xsrc->esb_mmio); 593*da71b7e3SCédric Le Goater break; 594*da71b7e3SCédric Le Goater 595*da71b7e3SCédric Le Goater case VST_NVP: /* Not modeled */ 596*da71b7e3SCédric Le Goater case VST_NVG: /* Not modeled */ 597*da71b7e3SCédric Le Goater case VST_NVC: /* Not modeled */ 598*da71b7e3SCédric Le Goater case VST_IC: /* Not modeled */ 599*da71b7e3SCédric Le Goater case VST_SYNC: /* Not modeled */ 600*da71b7e3SCédric Le Goater case VST_ERQ: /* Not modeled */ 601*da71b7e3SCédric Le Goater break; 602*da71b7e3SCédric Le Goater 603*da71b7e3SCédric Le Goater default: 604*da71b7e3SCédric Le Goater g_assert_not_reached(); 605*da71b7e3SCédric Le Goater } 606*da71b7e3SCédric Le Goater } 607*da71b7e3SCédric Le Goater 608*da71b7e3SCédric Le Goater /* 609*da71b7e3SCédric Le Goater * Both PC and VC sub-engines are configured as each use the Virtual 610*da71b7e3SCédric Le Goater * Structure Tables 611*da71b7e3SCédric Le Goater */ 612*da71b7e3SCédric Le Goater static void pnv_xive2_vst_set_data(PnvXive2 *xive, uint64_t vsd) 613*da71b7e3SCédric Le Goater { 614*da71b7e3SCédric Le Goater uint8_t mode = GETFIELD(VSD_MODE, vsd); 615*da71b7e3SCédric Le Goater uint8_t type = GETFIELD(VC_VSD_TABLE_SELECT, 616*da71b7e3SCédric Le Goater xive->vc_regs[VC_VSD_TABLE_ADDR >> 3]); 617*da71b7e3SCédric Le Goater uint8_t blk = GETFIELD(VC_VSD_TABLE_ADDRESS, 618*da71b7e3SCédric Le Goater xive->vc_regs[VC_VSD_TABLE_ADDR >> 3]); 619*da71b7e3SCédric Le Goater uint64_t vst_addr = vsd & VSD_ADDRESS_MASK; 620*da71b7e3SCédric Le Goater 621*da71b7e3SCédric Le Goater if (type > VST_ERQ) { 622*da71b7e3SCédric Le Goater xive2_error(xive, "VST: invalid table type %d", type); 623*da71b7e3SCédric Le Goater return; 624*da71b7e3SCédric Le Goater } 625*da71b7e3SCédric Le Goater 626*da71b7e3SCédric Le Goater if (blk >= vst_infos[type].max_blocks) { 627*da71b7e3SCédric Le Goater xive2_error(xive, "VST: invalid block id %d for" 628*da71b7e3SCédric Le Goater " %s table", blk, vst_infos[type].name); 629*da71b7e3SCédric Le Goater return; 630*da71b7e3SCédric Le Goater } 631*da71b7e3SCédric Le Goater 632*da71b7e3SCédric Le Goater if (!vst_addr) { 633*da71b7e3SCédric Le Goater xive2_error(xive, "VST: invalid %s table address", 634*da71b7e3SCédric Le Goater vst_infos[type].name); 635*da71b7e3SCédric Le Goater return; 636*da71b7e3SCédric Le Goater } 637*da71b7e3SCédric Le Goater 638*da71b7e3SCédric Le Goater switch (mode) { 639*da71b7e3SCédric Le Goater case VSD_MODE_FORWARD: 640*da71b7e3SCédric Le Goater xive->vsds[type][blk] = vsd; 641*da71b7e3SCédric Le Goater break; 642*da71b7e3SCédric Le Goater 643*da71b7e3SCédric Le Goater case VSD_MODE_EXCLUSIVE: 644*da71b7e3SCédric Le Goater pnv_xive2_vst_set_exclusive(xive, type, blk, vsd); 645*da71b7e3SCédric Le Goater break; 646*da71b7e3SCédric Le Goater 647*da71b7e3SCédric Le Goater default: 648*da71b7e3SCédric Le Goater xive2_error(xive, "VST: unsupported table mode %d", mode); 649*da71b7e3SCédric Le Goater return; 650*da71b7e3SCédric Le Goater } 651*da71b7e3SCédric Le Goater } 652*da71b7e3SCédric Le Goater 653*da71b7e3SCédric Le Goater /* 654*da71b7e3SCédric Le Goater * MMIO handlers 655*da71b7e3SCédric Le Goater */ 656*da71b7e3SCédric Le Goater 657*da71b7e3SCédric Le Goater 658*da71b7e3SCédric Le Goater /* 659*da71b7e3SCédric Le Goater * IC BAR layout 660*da71b7e3SCédric Le Goater * 661*da71b7e3SCédric Le Goater * Page 0: Internal CQ register accesses (reads & writes) 662*da71b7e3SCédric Le Goater * Page 1: Internal PC register accesses (reads & writes) 663*da71b7e3SCédric Le Goater * Page 2: Internal VC register accesses (reads & writes) 664*da71b7e3SCédric Le Goater * Page 3: Internal TCTXT (TIMA) reg accesses (read & writes) 665*da71b7e3SCédric Le Goater * Page 4: Notify Port page (writes only, w/data), 666*da71b7e3SCédric Le Goater * Page 5: Reserved 667*da71b7e3SCédric Le Goater * Page 6: Sync Poll page (writes only, dataless) 668*da71b7e3SCédric Le Goater * Page 7: Sync Inject page (writes only, dataless) 669*da71b7e3SCédric Le Goater * Page 8: LSI Trigger page (writes only, dataless) 670*da71b7e3SCédric Le Goater * Page 9: LSI SB Management page (reads & writes dataless) 671*da71b7e3SCédric Le Goater * Pages 10-255: Reserved 672*da71b7e3SCédric Le Goater * Pages 256-383: Direct mapped Thread Context Area (reads & writes) 673*da71b7e3SCédric Le Goater * covering the 128 threads in P10. 674*da71b7e3SCédric Le Goater * Pages 384-511: Reserved 675*da71b7e3SCédric Le Goater */ 676*da71b7e3SCédric Le Goater typedef struct PnvXive2Region { 677*da71b7e3SCédric Le Goater const char *name; 678*da71b7e3SCédric Le Goater uint32_t pgoff; 679*da71b7e3SCédric Le Goater uint32_t pgsize; 680*da71b7e3SCédric Le Goater const MemoryRegionOps *ops; 681*da71b7e3SCédric Le Goater } PnvXive2Region; 682*da71b7e3SCédric Le Goater 683*da71b7e3SCédric Le Goater static const MemoryRegionOps pnv_xive2_ic_cq_ops; 684*da71b7e3SCédric Le Goater static const MemoryRegionOps pnv_xive2_ic_pc_ops; 685*da71b7e3SCédric Le Goater static const MemoryRegionOps pnv_xive2_ic_vc_ops; 686*da71b7e3SCédric Le Goater static const MemoryRegionOps pnv_xive2_ic_tctxt_ops; 687*da71b7e3SCédric Le Goater static const MemoryRegionOps pnv_xive2_ic_notify_ops; 688*da71b7e3SCédric Le Goater static const MemoryRegionOps pnv_xive2_ic_sync_ops; 689*da71b7e3SCédric Le Goater static const MemoryRegionOps pnv_xive2_ic_lsi_ops; 690*da71b7e3SCédric Le Goater static const MemoryRegionOps pnv_xive2_ic_tm_indirect_ops; 691*da71b7e3SCédric Le Goater 692*da71b7e3SCédric Le Goater /* 512 pages. 4K: 2M range, 64K: 32M range */ 693*da71b7e3SCédric Le Goater static const PnvXive2Region pnv_xive2_ic_regions[] = { 694*da71b7e3SCédric Le Goater { "xive-ic-cq", 0, 1, &pnv_xive2_ic_cq_ops }, 695*da71b7e3SCédric Le Goater { "xive-ic-vc", 1, 1, &pnv_xive2_ic_vc_ops }, 696*da71b7e3SCédric Le Goater { "xive-ic-pc", 2, 1, &pnv_xive2_ic_pc_ops }, 697*da71b7e3SCédric Le Goater { "xive-ic-tctxt", 3, 1, &pnv_xive2_ic_tctxt_ops }, 698*da71b7e3SCédric Le Goater { "xive-ic-notify", 4, 1, &pnv_xive2_ic_notify_ops }, 699*da71b7e3SCédric Le Goater /* page 5 reserved */ 700*da71b7e3SCédric Le Goater { "xive-ic-sync", 6, 2, &pnv_xive2_ic_sync_ops }, 701*da71b7e3SCédric Le Goater { "xive-ic-lsi", 8, 2, &pnv_xive2_ic_lsi_ops }, 702*da71b7e3SCédric Le Goater /* pages 10-255 reserved */ 703*da71b7e3SCédric Le Goater { "xive-ic-tm-indirect", 256, 128, &pnv_xive2_ic_tm_indirect_ops }, 704*da71b7e3SCédric Le Goater /* pages 384-511 reserved */ 705*da71b7e3SCédric Le Goater }; 706*da71b7e3SCédric Le Goater 707*da71b7e3SCédric Le Goater /* 708*da71b7e3SCédric Le Goater * CQ operations 709*da71b7e3SCédric Le Goater */ 710*da71b7e3SCédric Le Goater 711*da71b7e3SCédric Le Goater static uint64_t pnv_xive2_ic_cq_read(void *opaque, hwaddr offset, 712*da71b7e3SCédric Le Goater unsigned size) 713*da71b7e3SCédric Le Goater { 714*da71b7e3SCédric Le Goater PnvXive2 *xive = PNV_XIVE2(opaque); 715*da71b7e3SCédric Le Goater uint32_t reg = offset >> 3; 716*da71b7e3SCédric Le Goater uint64_t val = 0; 717*da71b7e3SCédric Le Goater 718*da71b7e3SCédric Le Goater switch (offset) { 719*da71b7e3SCédric Le Goater case CQ_XIVE_CAP: /* Set at reset */ 720*da71b7e3SCédric Le Goater case CQ_XIVE_CFG: 721*da71b7e3SCédric Le Goater val = xive->cq_regs[reg]; 722*da71b7e3SCédric Le Goater break; 723*da71b7e3SCédric Le Goater case CQ_MSGSND: /* TODO check the #cores of the machine */ 724*da71b7e3SCédric Le Goater val = 0xffffffff00000000; 725*da71b7e3SCédric Le Goater break; 726*da71b7e3SCédric Le Goater case CQ_CFG_PB_GEN: 727*da71b7e3SCédric Le Goater val = CQ_CFG_PB_GEN_PB_INIT; /* TODO: fix CQ_CFG_PB_GEN default value */ 728*da71b7e3SCédric Le Goater break; 729*da71b7e3SCédric Le Goater default: 730*da71b7e3SCédric Le Goater xive2_error(xive, "CQ: invalid read @%"HWADDR_PRIx, offset); 731*da71b7e3SCédric Le Goater } 732*da71b7e3SCédric Le Goater 733*da71b7e3SCédric Le Goater return val; 734*da71b7e3SCédric Le Goater } 735*da71b7e3SCédric Le Goater 736*da71b7e3SCédric Le Goater static uint64_t pnv_xive2_bar_size(uint64_t val) 737*da71b7e3SCédric Le Goater { 738*da71b7e3SCédric Le Goater return 1ull << (GETFIELD(CQ_BAR_RANGE, val) + 24); 739*da71b7e3SCédric Le Goater } 740*da71b7e3SCédric Le Goater 741*da71b7e3SCédric Le Goater static void pnv_xive2_ic_cq_write(void *opaque, hwaddr offset, 742*da71b7e3SCédric Le Goater uint64_t val, unsigned size) 743*da71b7e3SCédric Le Goater { 744*da71b7e3SCédric Le Goater PnvXive2 *xive = PNV_XIVE2(opaque); 745*da71b7e3SCédric Le Goater MemoryRegion *sysmem = get_system_memory(); 746*da71b7e3SCédric Le Goater uint32_t reg = offset >> 3; 747*da71b7e3SCédric Le Goater int i; 748*da71b7e3SCédric Le Goater 749*da71b7e3SCédric Le Goater switch (offset) { 750*da71b7e3SCédric Le Goater case CQ_XIVE_CFG: 751*da71b7e3SCédric Le Goater case CQ_RST_CTL: /* TODO: reset all BARs */ 752*da71b7e3SCédric Le Goater break; 753*da71b7e3SCédric Le Goater 754*da71b7e3SCédric Le Goater case CQ_IC_BAR: 755*da71b7e3SCédric Le Goater xive->ic_shift = val & CQ_IC_BAR_64K ? 16 : 12; 756*da71b7e3SCédric Le Goater if (!(val & CQ_IC_BAR_VALID)) { 757*da71b7e3SCédric Le Goater xive->ic_base = 0; 758*da71b7e3SCédric Le Goater if (xive->cq_regs[reg] & CQ_IC_BAR_VALID) { 759*da71b7e3SCédric Le Goater for (i = 0; i < ARRAY_SIZE(xive->ic_mmios); i++) { 760*da71b7e3SCédric Le Goater memory_region_del_subregion(&xive->ic_mmio, 761*da71b7e3SCédric Le Goater &xive->ic_mmios[i]); 762*da71b7e3SCédric Le Goater } 763*da71b7e3SCédric Le Goater memory_region_del_subregion(sysmem, &xive->ic_mmio); 764*da71b7e3SCédric Le Goater } 765*da71b7e3SCédric Le Goater } else { 766*da71b7e3SCédric Le Goater xive->ic_base = val & ~(CQ_IC_BAR_VALID | CQ_IC_BAR_64K); 767*da71b7e3SCédric Le Goater if (!(xive->cq_regs[reg] & CQ_IC_BAR_VALID)) { 768*da71b7e3SCédric Le Goater for (i = 0; i < ARRAY_SIZE(xive->ic_mmios); i++) { 769*da71b7e3SCédric Le Goater memory_region_add_subregion(&xive->ic_mmio, 770*da71b7e3SCédric Le Goater pnv_xive2_ic_regions[i].pgoff << xive->ic_shift, 771*da71b7e3SCédric Le Goater &xive->ic_mmios[i]); 772*da71b7e3SCédric Le Goater } 773*da71b7e3SCédric Le Goater memory_region_add_subregion(sysmem, xive->ic_base, 774*da71b7e3SCédric Le Goater &xive->ic_mmio); 775*da71b7e3SCédric Le Goater } 776*da71b7e3SCédric Le Goater } 777*da71b7e3SCédric Le Goater break; 778*da71b7e3SCédric Le Goater 779*da71b7e3SCédric Le Goater case CQ_TM_BAR: 780*da71b7e3SCédric Le Goater xive->tm_shift = val & CQ_TM_BAR_64K ? 16 : 12; 781*da71b7e3SCédric Le Goater if (!(val & CQ_TM_BAR_VALID)) { 782*da71b7e3SCédric Le Goater xive->tm_base = 0; 783*da71b7e3SCédric Le Goater if (xive->cq_regs[reg] & CQ_TM_BAR_VALID) { 784*da71b7e3SCédric Le Goater memory_region_del_subregion(sysmem, &xive->tm_mmio); 785*da71b7e3SCédric Le Goater } 786*da71b7e3SCédric Le Goater } else { 787*da71b7e3SCédric Le Goater xive->tm_base = val & ~(CQ_TM_BAR_VALID | CQ_TM_BAR_64K); 788*da71b7e3SCédric Le Goater if (!(xive->cq_regs[reg] & CQ_TM_BAR_VALID)) { 789*da71b7e3SCédric Le Goater memory_region_add_subregion(sysmem, xive->tm_base, 790*da71b7e3SCédric Le Goater &xive->tm_mmio); 791*da71b7e3SCédric Le Goater } 792*da71b7e3SCédric Le Goater } 793*da71b7e3SCédric Le Goater break; 794*da71b7e3SCédric Le Goater 795*da71b7e3SCédric Le Goater case CQ_ESB_BAR: 796*da71b7e3SCédric Le Goater xive->esb_shift = val & CQ_BAR_64K ? 16 : 12; 797*da71b7e3SCédric Le Goater if (!(val & CQ_BAR_VALID)) { 798*da71b7e3SCédric Le Goater xive->esb_base = 0; 799*da71b7e3SCédric Le Goater if (xive->cq_regs[reg] & CQ_BAR_VALID) { 800*da71b7e3SCédric Le Goater memory_region_del_subregion(sysmem, &xive->esb_mmio); 801*da71b7e3SCédric Le Goater } 802*da71b7e3SCédric Le Goater } else { 803*da71b7e3SCédric Le Goater xive->esb_base = val & CQ_BAR_ADDR; 804*da71b7e3SCédric Le Goater if (!(xive->cq_regs[reg] & CQ_BAR_VALID)) { 805*da71b7e3SCédric Le Goater memory_region_set_size(&xive->esb_mmio, 806*da71b7e3SCédric Le Goater pnv_xive2_bar_size(val)); 807*da71b7e3SCédric Le Goater memory_region_add_subregion(sysmem, xive->esb_base, 808*da71b7e3SCédric Le Goater &xive->esb_mmio); 809*da71b7e3SCédric Le Goater } 810*da71b7e3SCédric Le Goater } 811*da71b7e3SCédric Le Goater break; 812*da71b7e3SCédric Le Goater 813*da71b7e3SCédric Le Goater case CQ_END_BAR: 814*da71b7e3SCédric Le Goater xive->end_shift = val & CQ_BAR_64K ? 16 : 12; 815*da71b7e3SCédric Le Goater if (!(val & CQ_BAR_VALID)) { 816*da71b7e3SCédric Le Goater xive->end_base = 0; 817*da71b7e3SCédric Le Goater if (xive->cq_regs[reg] & CQ_BAR_VALID) { 818*da71b7e3SCédric Le Goater memory_region_del_subregion(sysmem, &xive->end_mmio); 819*da71b7e3SCédric Le Goater } 820*da71b7e3SCédric Le Goater } else { 821*da71b7e3SCédric Le Goater xive->end_base = val & CQ_BAR_ADDR; 822*da71b7e3SCédric Le Goater if (!(xive->cq_regs[reg] & CQ_BAR_VALID)) { 823*da71b7e3SCédric Le Goater memory_region_set_size(&xive->end_mmio, 824*da71b7e3SCédric Le Goater pnv_xive2_bar_size(val)); 825*da71b7e3SCédric Le Goater memory_region_add_subregion(sysmem, xive->end_base, 826*da71b7e3SCédric Le Goater &xive->end_mmio); 827*da71b7e3SCédric Le Goater } 828*da71b7e3SCédric Le Goater } 829*da71b7e3SCédric Le Goater break; 830*da71b7e3SCédric Le Goater 831*da71b7e3SCédric Le Goater case CQ_NVC_BAR: 832*da71b7e3SCédric Le Goater xive->nvc_shift = val & CQ_BAR_64K ? 16 : 12; 833*da71b7e3SCédric Le Goater if (!(val & CQ_BAR_VALID)) { 834*da71b7e3SCédric Le Goater xive->nvc_base = 0; 835*da71b7e3SCédric Le Goater if (xive->cq_regs[reg] & CQ_BAR_VALID) { 836*da71b7e3SCédric Le Goater memory_region_del_subregion(sysmem, &xive->nvc_mmio); 837*da71b7e3SCédric Le Goater } 838*da71b7e3SCédric Le Goater } else { 839*da71b7e3SCédric Le Goater xive->nvc_base = val & CQ_BAR_ADDR; 840*da71b7e3SCédric Le Goater if (!(xive->cq_regs[reg] & CQ_BAR_VALID)) { 841*da71b7e3SCédric Le Goater memory_region_set_size(&xive->nvc_mmio, 842*da71b7e3SCédric Le Goater pnv_xive2_bar_size(val)); 843*da71b7e3SCédric Le Goater memory_region_add_subregion(sysmem, xive->nvc_base, 844*da71b7e3SCédric Le Goater &xive->nvc_mmio); 845*da71b7e3SCédric Le Goater } 846*da71b7e3SCédric Le Goater } 847*da71b7e3SCédric Le Goater break; 848*da71b7e3SCédric Le Goater 849*da71b7e3SCédric Le Goater case CQ_NVPG_BAR: 850*da71b7e3SCédric Le Goater xive->nvpg_shift = val & CQ_BAR_64K ? 16 : 12; 851*da71b7e3SCédric Le Goater if (!(val & CQ_BAR_VALID)) { 852*da71b7e3SCédric Le Goater xive->nvpg_base = 0; 853*da71b7e3SCédric Le Goater if (xive->cq_regs[reg] & CQ_BAR_VALID) { 854*da71b7e3SCédric Le Goater memory_region_del_subregion(sysmem, &xive->nvpg_mmio); 855*da71b7e3SCédric Le Goater } 856*da71b7e3SCédric Le Goater } else { 857*da71b7e3SCédric Le Goater xive->nvpg_base = val & CQ_BAR_ADDR; 858*da71b7e3SCédric Le Goater if (!(xive->cq_regs[reg] & CQ_BAR_VALID)) { 859*da71b7e3SCédric Le Goater memory_region_set_size(&xive->nvpg_mmio, 860*da71b7e3SCédric Le Goater pnv_xive2_bar_size(val)); 861*da71b7e3SCédric Le Goater memory_region_add_subregion(sysmem, xive->nvpg_base, 862*da71b7e3SCédric Le Goater &xive->nvpg_mmio); 863*da71b7e3SCédric Le Goater } 864*da71b7e3SCédric Le Goater } 865*da71b7e3SCédric Le Goater break; 866*da71b7e3SCédric Le Goater 867*da71b7e3SCédric Le Goater case CQ_TAR: /* Set Translation Table Address */ 868*da71b7e3SCédric Le Goater break; 869*da71b7e3SCédric Le Goater case CQ_TDR: /* Set Translation Table Data */ 870*da71b7e3SCédric Le Goater pnv_xive2_stt_set_data(xive, val); 871*da71b7e3SCédric Le Goater break; 872*da71b7e3SCédric Le Goater case CQ_FIRMASK_OR: /* FIR error reporting */ 873*da71b7e3SCédric Le Goater break; 874*da71b7e3SCédric Le Goater default: 875*da71b7e3SCédric Le Goater xive2_error(xive, "CQ: invalid write 0x%"HWADDR_PRIx, offset); 876*da71b7e3SCédric Le Goater return; 877*da71b7e3SCédric Le Goater } 878*da71b7e3SCédric Le Goater 879*da71b7e3SCédric Le Goater xive->cq_regs[reg] = val; 880*da71b7e3SCédric Le Goater } 881*da71b7e3SCédric Le Goater 882*da71b7e3SCédric Le Goater static const MemoryRegionOps pnv_xive2_ic_cq_ops = { 883*da71b7e3SCédric Le Goater .read = pnv_xive2_ic_cq_read, 884*da71b7e3SCédric Le Goater .write = pnv_xive2_ic_cq_write, 885*da71b7e3SCédric Le Goater .endianness = DEVICE_BIG_ENDIAN, 886*da71b7e3SCédric Le Goater .valid = { 887*da71b7e3SCédric Le Goater .min_access_size = 8, 888*da71b7e3SCédric Le Goater .max_access_size = 8, 889*da71b7e3SCédric Le Goater }, 890*da71b7e3SCédric Le Goater .impl = { 891*da71b7e3SCédric Le Goater .min_access_size = 8, 892*da71b7e3SCédric Le Goater .max_access_size = 8, 893*da71b7e3SCédric Le Goater }, 894*da71b7e3SCédric Le Goater }; 895*da71b7e3SCédric Le Goater 896*da71b7e3SCédric Le Goater static uint64_t pnv_xive2_ic_vc_read(void *opaque, hwaddr offset, 897*da71b7e3SCédric Le Goater unsigned size) 898*da71b7e3SCédric Le Goater { 899*da71b7e3SCédric Le Goater PnvXive2 *xive = PNV_XIVE2(opaque); 900*da71b7e3SCédric Le Goater uint64_t val = 0; 901*da71b7e3SCédric Le Goater uint32_t reg = offset >> 3; 902*da71b7e3SCédric Le Goater 903*da71b7e3SCédric Le Goater switch (offset) { 904*da71b7e3SCédric Le Goater /* 905*da71b7e3SCédric Le Goater * VSD table settings. 906*da71b7e3SCédric Le Goater */ 907*da71b7e3SCédric Le Goater case VC_VSD_TABLE_ADDR: 908*da71b7e3SCédric Le Goater case VC_VSD_TABLE_DATA: 909*da71b7e3SCédric Le Goater val = xive->vc_regs[reg]; 910*da71b7e3SCédric Le Goater break; 911*da71b7e3SCédric Le Goater 912*da71b7e3SCédric Le Goater /* 913*da71b7e3SCédric Le Goater * ESB cache updates (not modeled) 914*da71b7e3SCédric Le Goater */ 915*da71b7e3SCédric Le Goater case VC_ESBC_FLUSH_CTRL: 916*da71b7e3SCédric Le Goater xive->vc_regs[reg] &= ~VC_ESBC_FLUSH_CTRL_POLL_VALID; 917*da71b7e3SCédric Le Goater val = xive->vc_regs[reg]; 918*da71b7e3SCédric Le Goater break; 919*da71b7e3SCédric Le Goater 920*da71b7e3SCédric Le Goater /* 921*da71b7e3SCédric Le Goater * EAS cache updates (not modeled) 922*da71b7e3SCédric Le Goater */ 923*da71b7e3SCédric Le Goater case VC_EASC_FLUSH_CTRL: 924*da71b7e3SCédric Le Goater xive->vc_regs[reg] &= ~VC_EASC_FLUSH_CTRL_POLL_VALID; 925*da71b7e3SCédric Le Goater val = xive->vc_regs[reg]; 926*da71b7e3SCédric Le Goater break; 927*da71b7e3SCédric Le Goater 928*da71b7e3SCédric Le Goater /* 929*da71b7e3SCédric Le Goater * END cache updates 930*da71b7e3SCédric Le Goater */ 931*da71b7e3SCédric Le Goater case VC_ENDC_WATCH0_SPEC: 932*da71b7e3SCédric Le Goater xive->vc_regs[reg] &= ~(VC_ENDC_WATCH_FULL | VC_ENDC_WATCH_CONFLICT); 933*da71b7e3SCédric Le Goater val = xive->vc_regs[reg]; 934*da71b7e3SCédric Le Goater break; 935*da71b7e3SCédric Le Goater 936*da71b7e3SCédric Le Goater case VC_ENDC_WATCH0_DATA0: 937*da71b7e3SCédric Le Goater /* 938*da71b7e3SCédric Le Goater * Load DATA registers from cache with data requested by the 939*da71b7e3SCédric Le Goater * SPEC register 940*da71b7e3SCédric Le Goater */ 941*da71b7e3SCédric Le Goater pnv_xive2_end_cache_load(xive); 942*da71b7e3SCédric Le Goater val = xive->vc_regs[reg]; 943*da71b7e3SCédric Le Goater break; 944*da71b7e3SCédric Le Goater 945*da71b7e3SCédric Le Goater case VC_ENDC_WATCH0_DATA1 ... VC_ENDC_WATCH0_DATA3: 946*da71b7e3SCédric Le Goater val = xive->vc_regs[reg]; 947*da71b7e3SCédric Le Goater break; 948*da71b7e3SCédric Le Goater 949*da71b7e3SCédric Le Goater case VC_ENDC_FLUSH_CTRL: 950*da71b7e3SCédric Le Goater xive->vc_regs[reg] &= ~VC_ENDC_FLUSH_CTRL_POLL_VALID; 951*da71b7e3SCédric Le Goater val = xive->vc_regs[reg]; 952*da71b7e3SCédric Le Goater break; 953*da71b7e3SCédric Le Goater 954*da71b7e3SCédric Le Goater /* 955*da71b7e3SCédric Le Goater * Indirect invalidation 956*da71b7e3SCédric Le Goater */ 957*da71b7e3SCédric Le Goater case VC_AT_MACRO_KILL_MASK: 958*da71b7e3SCédric Le Goater val = xive->vc_regs[reg]; 959*da71b7e3SCédric Le Goater break; 960*da71b7e3SCédric Le Goater 961*da71b7e3SCédric Le Goater case VC_AT_MACRO_KILL: 962*da71b7e3SCédric Le Goater xive->vc_regs[reg] &= ~VC_AT_MACRO_KILL_VALID; 963*da71b7e3SCédric Le Goater val = xive->vc_regs[reg]; 964*da71b7e3SCédric Le Goater break; 965*da71b7e3SCédric Le Goater 966*da71b7e3SCédric Le Goater /* 967*da71b7e3SCédric Le Goater * Interrupt fifo overflow in memory backing store (Not modeled) 968*da71b7e3SCédric Le Goater */ 969*da71b7e3SCédric Le Goater case VC_QUEUES_CFG_REM0 ... VC_QUEUES_CFG_REM6: 970*da71b7e3SCédric Le Goater val = xive->vc_regs[reg]; 971*da71b7e3SCédric Le Goater break; 972*da71b7e3SCédric Le Goater 973*da71b7e3SCédric Le Goater /* 974*da71b7e3SCédric Le Goater * Synchronisation 975*da71b7e3SCédric Le Goater */ 976*da71b7e3SCédric Le Goater case VC_ENDC_SYNC_DONE: 977*da71b7e3SCédric Le Goater val = VC_ENDC_SYNC_POLL_DONE; 978*da71b7e3SCédric Le Goater break; 979*da71b7e3SCédric Le Goater default: 980*da71b7e3SCédric Le Goater xive2_error(xive, "VC: invalid read @%"HWADDR_PRIx, offset); 981*da71b7e3SCédric Le Goater } 982*da71b7e3SCédric Le Goater 983*da71b7e3SCédric Le Goater return val; 984*da71b7e3SCédric Le Goater } 985*da71b7e3SCédric Le Goater 986*da71b7e3SCédric Le Goater static void pnv_xive2_ic_vc_write(void *opaque, hwaddr offset, 987*da71b7e3SCédric Le Goater uint64_t val, unsigned size) 988*da71b7e3SCédric Le Goater { 989*da71b7e3SCédric Le Goater PnvXive2 *xive = PNV_XIVE2(opaque); 990*da71b7e3SCédric Le Goater uint32_t reg = offset >> 3; 991*da71b7e3SCédric Le Goater 992*da71b7e3SCédric Le Goater switch (offset) { 993*da71b7e3SCédric Le Goater /* 994*da71b7e3SCédric Le Goater * VSD table settings. 995*da71b7e3SCédric Le Goater */ 996*da71b7e3SCédric Le Goater case VC_VSD_TABLE_ADDR: 997*da71b7e3SCédric Le Goater break; 998*da71b7e3SCédric Le Goater case VC_VSD_TABLE_DATA: 999*da71b7e3SCédric Le Goater pnv_xive2_vst_set_data(xive, val); 1000*da71b7e3SCédric Le Goater break; 1001*da71b7e3SCédric Le Goater 1002*da71b7e3SCédric Le Goater /* 1003*da71b7e3SCédric Le Goater * ESB cache updates (not modeled) 1004*da71b7e3SCédric Le Goater */ 1005*da71b7e3SCédric Le Goater /* case VC_ESBC_FLUSH_CTRL: */ 1006*da71b7e3SCédric Le Goater case VC_ESBC_FLUSH_POLL: 1007*da71b7e3SCédric Le Goater xive->vc_regs[VC_ESBC_FLUSH_CTRL >> 3] |= VC_ESBC_FLUSH_CTRL_POLL_VALID; 1008*da71b7e3SCédric Le Goater /* ESB update */ 1009*da71b7e3SCédric Le Goater break; 1010*da71b7e3SCédric Le Goater 1011*da71b7e3SCédric Le Goater /* 1012*da71b7e3SCédric Le Goater * EAS cache updates (not modeled) 1013*da71b7e3SCédric Le Goater */ 1014*da71b7e3SCédric Le Goater /* case VC_EASC_FLUSH_CTRL: */ 1015*da71b7e3SCédric Le Goater case VC_EASC_FLUSH_POLL: 1016*da71b7e3SCédric Le Goater xive->vc_regs[VC_EASC_FLUSH_CTRL >> 3] |= VC_EASC_FLUSH_CTRL_POLL_VALID; 1017*da71b7e3SCédric Le Goater /* EAS update */ 1018*da71b7e3SCédric Le Goater break; 1019*da71b7e3SCédric Le Goater 1020*da71b7e3SCédric Le Goater /* 1021*da71b7e3SCédric Le Goater * END cache updates 1022*da71b7e3SCédric Le Goater */ 1023*da71b7e3SCédric Le Goater case VC_ENDC_WATCH0_SPEC: 1024*da71b7e3SCédric Le Goater val &= ~VC_ENDC_WATCH_CONFLICT; /* HW will set this bit */ 1025*da71b7e3SCédric Le Goater break; 1026*da71b7e3SCédric Le Goater 1027*da71b7e3SCédric Le Goater case VC_ENDC_WATCH0_DATA1 ... VC_ENDC_WATCH0_DATA3: 1028*da71b7e3SCédric Le Goater break; 1029*da71b7e3SCédric Le Goater case VC_ENDC_WATCH0_DATA0: 1030*da71b7e3SCédric Le Goater /* writing to DATA0 triggers the cache write */ 1031*da71b7e3SCédric Le Goater xive->vc_regs[reg] = val; 1032*da71b7e3SCédric Le Goater pnv_xive2_end_update(xive); 1033*da71b7e3SCédric Le Goater break; 1034*da71b7e3SCédric Le Goater 1035*da71b7e3SCédric Le Goater 1036*da71b7e3SCédric Le Goater /* case VC_ENDC_FLUSH_CTRL: */ 1037*da71b7e3SCédric Le Goater case VC_ENDC_FLUSH_POLL: 1038*da71b7e3SCédric Le Goater xive->vc_regs[VC_ENDC_FLUSH_CTRL >> 3] |= VC_ENDC_FLUSH_CTRL_POLL_VALID; 1039*da71b7e3SCédric Le Goater break; 1040*da71b7e3SCédric Le Goater 1041*da71b7e3SCédric Le Goater /* 1042*da71b7e3SCédric Le Goater * Indirect invalidation 1043*da71b7e3SCédric Le Goater */ 1044*da71b7e3SCédric Le Goater case VC_AT_MACRO_KILL: 1045*da71b7e3SCédric Le Goater case VC_AT_MACRO_KILL_MASK: 1046*da71b7e3SCédric Le Goater break; 1047*da71b7e3SCédric Le Goater 1048*da71b7e3SCédric Le Goater /* 1049*da71b7e3SCédric Le Goater * Interrupt fifo overflow in memory backing store (Not modeled) 1050*da71b7e3SCédric Le Goater */ 1051*da71b7e3SCédric Le Goater case VC_QUEUES_CFG_REM0 ... VC_QUEUES_CFG_REM6: 1052*da71b7e3SCédric Le Goater break; 1053*da71b7e3SCédric Le Goater 1054*da71b7e3SCédric Le Goater /* 1055*da71b7e3SCédric Le Goater * Synchronisation 1056*da71b7e3SCédric Le Goater */ 1057*da71b7e3SCédric Le Goater case VC_ENDC_SYNC_DONE: 1058*da71b7e3SCédric Le Goater break; 1059*da71b7e3SCédric Le Goater 1060*da71b7e3SCédric Le Goater default: 1061*da71b7e3SCédric Le Goater xive2_error(xive, "VC: invalid write @%"HWADDR_PRIx, offset); 1062*da71b7e3SCédric Le Goater return; 1063*da71b7e3SCédric Le Goater } 1064*da71b7e3SCédric Le Goater 1065*da71b7e3SCédric Le Goater xive->vc_regs[reg] = val; 1066*da71b7e3SCédric Le Goater } 1067*da71b7e3SCédric Le Goater 1068*da71b7e3SCédric Le Goater static const MemoryRegionOps pnv_xive2_ic_vc_ops = { 1069*da71b7e3SCédric Le Goater .read = pnv_xive2_ic_vc_read, 1070*da71b7e3SCédric Le Goater .write = pnv_xive2_ic_vc_write, 1071*da71b7e3SCédric Le Goater .endianness = DEVICE_BIG_ENDIAN, 1072*da71b7e3SCédric Le Goater .valid = { 1073*da71b7e3SCédric Le Goater .min_access_size = 8, 1074*da71b7e3SCédric Le Goater .max_access_size = 8, 1075*da71b7e3SCédric Le Goater }, 1076*da71b7e3SCédric Le Goater .impl = { 1077*da71b7e3SCédric Le Goater .min_access_size = 8, 1078*da71b7e3SCédric Le Goater .max_access_size = 8, 1079*da71b7e3SCédric Le Goater }, 1080*da71b7e3SCédric Le Goater }; 1081*da71b7e3SCédric Le Goater 1082*da71b7e3SCédric Le Goater static uint64_t pnv_xive2_ic_pc_read(void *opaque, hwaddr offset, 1083*da71b7e3SCédric Le Goater unsigned size) 1084*da71b7e3SCédric Le Goater { 1085*da71b7e3SCédric Le Goater PnvXive2 *xive = PNV_XIVE2(opaque); 1086*da71b7e3SCédric Le Goater uint64_t val = -1; 1087*da71b7e3SCédric Le Goater uint32_t reg = offset >> 3; 1088*da71b7e3SCédric Le Goater 1089*da71b7e3SCédric Le Goater switch (offset) { 1090*da71b7e3SCédric Le Goater /* 1091*da71b7e3SCédric Le Goater * VSD table settings. 1092*da71b7e3SCédric Le Goater */ 1093*da71b7e3SCédric Le Goater case PC_VSD_TABLE_ADDR: 1094*da71b7e3SCédric Le Goater case PC_VSD_TABLE_DATA: 1095*da71b7e3SCédric Le Goater val = xive->pc_regs[reg]; 1096*da71b7e3SCédric Le Goater break; 1097*da71b7e3SCédric Le Goater 1098*da71b7e3SCédric Le Goater /* 1099*da71b7e3SCédric Le Goater * cache updates 1100*da71b7e3SCédric Le Goater */ 1101*da71b7e3SCédric Le Goater case PC_NXC_WATCH0_SPEC: 1102*da71b7e3SCédric Le Goater xive->pc_regs[reg] &= ~(PC_NXC_WATCH_FULL | PC_NXC_WATCH_CONFLICT); 1103*da71b7e3SCédric Le Goater val = xive->pc_regs[reg]; 1104*da71b7e3SCédric Le Goater break; 1105*da71b7e3SCédric Le Goater 1106*da71b7e3SCédric Le Goater case PC_NXC_WATCH0_DATA0: 1107*da71b7e3SCédric Le Goater /* 1108*da71b7e3SCédric Le Goater * Load DATA registers from cache with data requested by the 1109*da71b7e3SCédric Le Goater * SPEC register 1110*da71b7e3SCédric Le Goater */ 1111*da71b7e3SCédric Le Goater pnv_xive2_nvp_cache_load(xive); 1112*da71b7e3SCédric Le Goater val = xive->pc_regs[reg]; 1113*da71b7e3SCédric Le Goater break; 1114*da71b7e3SCédric Le Goater 1115*da71b7e3SCédric Le Goater case PC_NXC_WATCH0_DATA1 ... PC_NXC_WATCH0_DATA3: 1116*da71b7e3SCédric Le Goater val = xive->pc_regs[reg]; 1117*da71b7e3SCédric Le Goater break; 1118*da71b7e3SCédric Le Goater 1119*da71b7e3SCédric Le Goater case PC_NXC_FLUSH_CTRL: 1120*da71b7e3SCédric Le Goater xive->pc_regs[reg] &= ~PC_NXC_FLUSH_CTRL_POLL_VALID; 1121*da71b7e3SCédric Le Goater val = xive->pc_regs[reg]; 1122*da71b7e3SCédric Le Goater break; 1123*da71b7e3SCédric Le Goater 1124*da71b7e3SCédric Le Goater /* 1125*da71b7e3SCédric Le Goater * Indirect invalidation 1126*da71b7e3SCédric Le Goater */ 1127*da71b7e3SCédric Le Goater case PC_AT_KILL: 1128*da71b7e3SCédric Le Goater xive->pc_regs[reg] &= ~PC_AT_KILL_VALID; 1129*da71b7e3SCédric Le Goater val = xive->pc_regs[reg]; 1130*da71b7e3SCédric Le Goater break; 1131*da71b7e3SCédric Le Goater 1132*da71b7e3SCédric Le Goater default: 1133*da71b7e3SCédric Le Goater xive2_error(xive, "PC: invalid read @%"HWADDR_PRIx, offset); 1134*da71b7e3SCédric Le Goater } 1135*da71b7e3SCédric Le Goater 1136*da71b7e3SCédric Le Goater return val; 1137*da71b7e3SCédric Le Goater } 1138*da71b7e3SCédric Le Goater 1139*da71b7e3SCédric Le Goater static void pnv_xive2_ic_pc_write(void *opaque, hwaddr offset, 1140*da71b7e3SCédric Le Goater uint64_t val, unsigned size) 1141*da71b7e3SCédric Le Goater { 1142*da71b7e3SCédric Le Goater PnvXive2 *xive = PNV_XIVE2(opaque); 1143*da71b7e3SCédric Le Goater uint32_t reg = offset >> 3; 1144*da71b7e3SCédric Le Goater 1145*da71b7e3SCédric Le Goater switch (offset) { 1146*da71b7e3SCédric Le Goater 1147*da71b7e3SCédric Le Goater /* 1148*da71b7e3SCédric Le Goater * VSD table settings. Only taken into account in the VC 1149*da71b7e3SCédric Le Goater * sub-engine because the Xive2Router model combines both VC and PC 1150*da71b7e3SCédric Le Goater * sub-engines 1151*da71b7e3SCédric Le Goater */ 1152*da71b7e3SCédric Le Goater case PC_VSD_TABLE_ADDR: 1153*da71b7e3SCédric Le Goater case PC_VSD_TABLE_DATA: 1154*da71b7e3SCédric Le Goater break; 1155*da71b7e3SCédric Le Goater 1156*da71b7e3SCédric Le Goater /* 1157*da71b7e3SCédric Le Goater * cache updates 1158*da71b7e3SCédric Le Goater */ 1159*da71b7e3SCédric Le Goater case PC_NXC_WATCH0_SPEC: 1160*da71b7e3SCédric Le Goater val &= ~PC_NXC_WATCH_CONFLICT; /* HW will set this bit */ 1161*da71b7e3SCédric Le Goater break; 1162*da71b7e3SCédric Le Goater 1163*da71b7e3SCédric Le Goater case PC_NXC_WATCH0_DATA1 ... PC_NXC_WATCH0_DATA3: 1164*da71b7e3SCédric Le Goater break; 1165*da71b7e3SCédric Le Goater case PC_NXC_WATCH0_DATA0: 1166*da71b7e3SCédric Le Goater /* writing to DATA0 triggers the cache write */ 1167*da71b7e3SCédric Le Goater xive->pc_regs[reg] = val; 1168*da71b7e3SCédric Le Goater pnv_xive2_nvp_update(xive); 1169*da71b7e3SCédric Le Goater break; 1170*da71b7e3SCédric Le Goater 1171*da71b7e3SCédric Le Goater /* case PC_NXC_FLUSH_CTRL: */ 1172*da71b7e3SCédric Le Goater case PC_NXC_FLUSH_POLL: 1173*da71b7e3SCédric Le Goater xive->pc_regs[PC_NXC_FLUSH_CTRL >> 3] |= PC_NXC_FLUSH_CTRL_POLL_VALID; 1174*da71b7e3SCédric Le Goater break; 1175*da71b7e3SCédric Le Goater 1176*da71b7e3SCédric Le Goater /* 1177*da71b7e3SCédric Le Goater * Indirect invalidation 1178*da71b7e3SCédric Le Goater */ 1179*da71b7e3SCédric Le Goater case PC_AT_KILL: 1180*da71b7e3SCédric Le Goater case PC_AT_KILL_MASK: 1181*da71b7e3SCédric Le Goater break; 1182*da71b7e3SCédric Le Goater 1183*da71b7e3SCédric Le Goater default: 1184*da71b7e3SCédric Le Goater xive2_error(xive, "PC: invalid write @%"HWADDR_PRIx, offset); 1185*da71b7e3SCédric Le Goater return; 1186*da71b7e3SCédric Le Goater } 1187*da71b7e3SCédric Le Goater 1188*da71b7e3SCédric Le Goater xive->pc_regs[reg] = val; 1189*da71b7e3SCédric Le Goater } 1190*da71b7e3SCédric Le Goater 1191*da71b7e3SCédric Le Goater static const MemoryRegionOps pnv_xive2_ic_pc_ops = { 1192*da71b7e3SCédric Le Goater .read = pnv_xive2_ic_pc_read, 1193*da71b7e3SCédric Le Goater .write = pnv_xive2_ic_pc_write, 1194*da71b7e3SCédric Le Goater .endianness = DEVICE_BIG_ENDIAN, 1195*da71b7e3SCédric Le Goater .valid = { 1196*da71b7e3SCédric Le Goater .min_access_size = 8, 1197*da71b7e3SCédric Le Goater .max_access_size = 8, 1198*da71b7e3SCédric Le Goater }, 1199*da71b7e3SCédric Le Goater .impl = { 1200*da71b7e3SCédric Le Goater .min_access_size = 8, 1201*da71b7e3SCédric Le Goater .max_access_size = 8, 1202*da71b7e3SCédric Le Goater }, 1203*da71b7e3SCédric Le Goater }; 1204*da71b7e3SCédric Le Goater 1205*da71b7e3SCédric Le Goater 1206*da71b7e3SCédric Le Goater static uint64_t pnv_xive2_ic_tctxt_read(void *opaque, hwaddr offset, 1207*da71b7e3SCédric Le Goater unsigned size) 1208*da71b7e3SCédric Le Goater { 1209*da71b7e3SCédric Le Goater PnvXive2 *xive = PNV_XIVE2(opaque); 1210*da71b7e3SCédric Le Goater uint64_t val = -1; 1211*da71b7e3SCédric Le Goater uint32_t reg = offset >> 3; 1212*da71b7e3SCédric Le Goater 1213*da71b7e3SCédric Le Goater switch (offset) { 1214*da71b7e3SCédric Le Goater /* 1215*da71b7e3SCédric Le Goater * XIVE2 hardware thread enablement 1216*da71b7e3SCédric Le Goater */ 1217*da71b7e3SCédric Le Goater case TCTXT_EN0: 1218*da71b7e3SCédric Le Goater case TCTXT_EN1: 1219*da71b7e3SCédric Le Goater val = xive->tctxt_regs[reg]; 1220*da71b7e3SCédric Le Goater break; 1221*da71b7e3SCédric Le Goater 1222*da71b7e3SCédric Le Goater case TCTXT_EN0_SET: 1223*da71b7e3SCédric Le Goater case TCTXT_EN0_RESET: 1224*da71b7e3SCédric Le Goater val = xive->tctxt_regs[TCTXT_EN0 >> 3]; 1225*da71b7e3SCédric Le Goater break; 1226*da71b7e3SCédric Le Goater case TCTXT_EN1_SET: 1227*da71b7e3SCédric Le Goater case TCTXT_EN1_RESET: 1228*da71b7e3SCédric Le Goater val = xive->tctxt_regs[TCTXT_EN1 >> 3]; 1229*da71b7e3SCédric Le Goater break; 1230*da71b7e3SCédric Le Goater default: 1231*da71b7e3SCédric Le Goater xive2_error(xive, "TCTXT: invalid read @%"HWADDR_PRIx, offset); 1232*da71b7e3SCédric Le Goater } 1233*da71b7e3SCédric Le Goater 1234*da71b7e3SCédric Le Goater return val; 1235*da71b7e3SCédric Le Goater } 1236*da71b7e3SCédric Le Goater 1237*da71b7e3SCédric Le Goater static void pnv_xive2_ic_tctxt_write(void *opaque, hwaddr offset, 1238*da71b7e3SCédric Le Goater uint64_t val, unsigned size) 1239*da71b7e3SCédric Le Goater { 1240*da71b7e3SCédric Le Goater PnvXive2 *xive = PNV_XIVE2(opaque); 1241*da71b7e3SCédric Le Goater uint32_t reg = offset >> 3; 1242*da71b7e3SCédric Le Goater 1243*da71b7e3SCédric Le Goater switch (offset) { 1244*da71b7e3SCédric Le Goater /* 1245*da71b7e3SCédric Le Goater * XIVE2 hardware thread enablement 1246*da71b7e3SCédric Le Goater */ 1247*da71b7e3SCédric Le Goater case TCTXT_EN0: /* Physical Thread Enable */ 1248*da71b7e3SCédric Le Goater case TCTXT_EN1: /* Physical Thread Enable (fused core) */ 1249*da71b7e3SCédric Le Goater break; 1250*da71b7e3SCédric Le Goater 1251*da71b7e3SCédric Le Goater case TCTXT_EN0_SET: 1252*da71b7e3SCédric Le Goater xive->tctxt_regs[TCTXT_EN0 >> 3] |= val; 1253*da71b7e3SCédric Le Goater break; 1254*da71b7e3SCédric Le Goater case TCTXT_EN1_SET: 1255*da71b7e3SCédric Le Goater xive->tctxt_regs[TCTXT_EN1 >> 3] |= val; 1256*da71b7e3SCédric Le Goater break; 1257*da71b7e3SCédric Le Goater case TCTXT_EN0_RESET: 1258*da71b7e3SCédric Le Goater xive->tctxt_regs[TCTXT_EN0 >> 3] &= ~val; 1259*da71b7e3SCédric Le Goater break; 1260*da71b7e3SCédric Le Goater case TCTXT_EN1_RESET: 1261*da71b7e3SCédric Le Goater xive->tctxt_regs[TCTXT_EN1 >> 3] &= ~val; 1262*da71b7e3SCédric Le Goater break; 1263*da71b7e3SCédric Le Goater 1264*da71b7e3SCédric Le Goater default: 1265*da71b7e3SCédric Le Goater xive2_error(xive, "TCTXT: invalid write @%"HWADDR_PRIx, offset); 1266*da71b7e3SCédric Le Goater return; 1267*da71b7e3SCédric Le Goater } 1268*da71b7e3SCédric Le Goater 1269*da71b7e3SCédric Le Goater xive->pc_regs[reg] = val; 1270*da71b7e3SCédric Le Goater } 1271*da71b7e3SCédric Le Goater 1272*da71b7e3SCédric Le Goater static const MemoryRegionOps pnv_xive2_ic_tctxt_ops = { 1273*da71b7e3SCédric Le Goater .read = pnv_xive2_ic_tctxt_read, 1274*da71b7e3SCédric Le Goater .write = pnv_xive2_ic_tctxt_write, 1275*da71b7e3SCédric Le Goater .endianness = DEVICE_BIG_ENDIAN, 1276*da71b7e3SCédric Le Goater .valid = { 1277*da71b7e3SCédric Le Goater .min_access_size = 8, 1278*da71b7e3SCédric Le Goater .max_access_size = 8, 1279*da71b7e3SCédric Le Goater }, 1280*da71b7e3SCédric Le Goater .impl = { 1281*da71b7e3SCédric Le Goater .min_access_size = 8, 1282*da71b7e3SCédric Le Goater .max_access_size = 8, 1283*da71b7e3SCédric Le Goater }, 1284*da71b7e3SCédric Le Goater }; 1285*da71b7e3SCédric Le Goater 1286*da71b7e3SCédric Le Goater /* 1287*da71b7e3SCédric Le Goater * Redirect XSCOM to MMIO handlers 1288*da71b7e3SCédric Le Goater */ 1289*da71b7e3SCédric Le Goater static uint64_t pnv_xive2_xscom_read(void *opaque, hwaddr offset, 1290*da71b7e3SCédric Le Goater unsigned size) 1291*da71b7e3SCédric Le Goater { 1292*da71b7e3SCédric Le Goater PnvXive2 *xive = PNV_XIVE2(opaque); 1293*da71b7e3SCédric Le Goater uint64_t val = -1; 1294*da71b7e3SCédric Le Goater uint32_t xscom_reg = offset >> 3; 1295*da71b7e3SCédric Le Goater uint32_t mmio_offset = (xscom_reg & 0xFF) << 3; 1296*da71b7e3SCédric Le Goater 1297*da71b7e3SCédric Le Goater switch (xscom_reg) { 1298*da71b7e3SCédric Le Goater case 0x000 ... 0x0FF: 1299*da71b7e3SCédric Le Goater val = pnv_xive2_ic_cq_read(opaque, mmio_offset, size); 1300*da71b7e3SCédric Le Goater break; 1301*da71b7e3SCédric Le Goater case 0x100 ... 0x1FF: 1302*da71b7e3SCédric Le Goater val = pnv_xive2_ic_vc_read(opaque, mmio_offset, size); 1303*da71b7e3SCédric Le Goater break; 1304*da71b7e3SCédric Le Goater case 0x200 ... 0x2FF: 1305*da71b7e3SCédric Le Goater val = pnv_xive2_ic_pc_read(opaque, mmio_offset, size); 1306*da71b7e3SCédric Le Goater break; 1307*da71b7e3SCédric Le Goater case 0x300 ... 0x3FF: 1308*da71b7e3SCédric Le Goater val = pnv_xive2_ic_tctxt_read(opaque, mmio_offset, size); 1309*da71b7e3SCédric Le Goater break; 1310*da71b7e3SCédric Le Goater default: 1311*da71b7e3SCédric Le Goater xive2_error(xive, "XSCOM: invalid read @%"HWADDR_PRIx, offset); 1312*da71b7e3SCédric Le Goater } 1313*da71b7e3SCédric Le Goater 1314*da71b7e3SCédric Le Goater return val; 1315*da71b7e3SCédric Le Goater } 1316*da71b7e3SCédric Le Goater 1317*da71b7e3SCédric Le Goater static void pnv_xive2_xscom_write(void *opaque, hwaddr offset, 1318*da71b7e3SCédric Le Goater uint64_t val, unsigned size) 1319*da71b7e3SCédric Le Goater { 1320*da71b7e3SCédric Le Goater PnvXive2 *xive = PNV_XIVE2(opaque); 1321*da71b7e3SCédric Le Goater uint32_t xscom_reg = offset >> 3; 1322*da71b7e3SCédric Le Goater uint32_t mmio_offset = (xscom_reg & 0xFF) << 3; 1323*da71b7e3SCédric Le Goater 1324*da71b7e3SCédric Le Goater switch (xscom_reg) { 1325*da71b7e3SCédric Le Goater case 0x000 ... 0x0FF: 1326*da71b7e3SCédric Le Goater pnv_xive2_ic_cq_write(opaque, mmio_offset, val, size); 1327*da71b7e3SCédric Le Goater break; 1328*da71b7e3SCédric Le Goater case 0x100 ... 0x1FF: 1329*da71b7e3SCédric Le Goater pnv_xive2_ic_vc_write(opaque, mmio_offset, val, size); 1330*da71b7e3SCédric Le Goater break; 1331*da71b7e3SCédric Le Goater case 0x200 ... 0x2FF: 1332*da71b7e3SCédric Le Goater pnv_xive2_ic_pc_write(opaque, mmio_offset, val, size); 1333*da71b7e3SCédric Le Goater break; 1334*da71b7e3SCédric Le Goater case 0x300 ... 0x3FF: 1335*da71b7e3SCédric Le Goater pnv_xive2_ic_tctxt_write(opaque, mmio_offset, val, size); 1336*da71b7e3SCédric Le Goater break; 1337*da71b7e3SCédric Le Goater default: 1338*da71b7e3SCédric Le Goater xive2_error(xive, "XSCOM: invalid write @%"HWADDR_PRIx, offset); 1339*da71b7e3SCédric Le Goater } 1340*da71b7e3SCédric Le Goater } 1341*da71b7e3SCédric Le Goater 1342*da71b7e3SCédric Le Goater static const MemoryRegionOps pnv_xive2_xscom_ops = { 1343*da71b7e3SCédric Le Goater .read = pnv_xive2_xscom_read, 1344*da71b7e3SCédric Le Goater .write = pnv_xive2_xscom_write, 1345*da71b7e3SCédric Le Goater .endianness = DEVICE_BIG_ENDIAN, 1346*da71b7e3SCédric Le Goater .valid = { 1347*da71b7e3SCédric Le Goater .min_access_size = 8, 1348*da71b7e3SCédric Le Goater .max_access_size = 8, 1349*da71b7e3SCédric Le Goater }, 1350*da71b7e3SCédric Le Goater .impl = { 1351*da71b7e3SCédric Le Goater .min_access_size = 8, 1352*da71b7e3SCédric Le Goater .max_access_size = 8, 1353*da71b7e3SCédric Le Goater }, 1354*da71b7e3SCédric Le Goater }; 1355*da71b7e3SCédric Le Goater 1356*da71b7e3SCédric Le Goater /* 1357*da71b7e3SCédric Le Goater * Notify port page. The layout is compatible between 4K and 64K pages : 1358*da71b7e3SCédric Le Goater * 1359*da71b7e3SCédric Le Goater * Page 1 Notify page (writes only) 1360*da71b7e3SCédric Le Goater * 0x000 - 0x7FF IPI interrupt (NPU) 1361*da71b7e3SCédric Le Goater * 0x800 - 0xFFF HW interrupt triggers (PSI, PHB) 1362*da71b7e3SCédric Le Goater */ 1363*da71b7e3SCédric Le Goater 1364*da71b7e3SCédric Le Goater static void pnv_xive2_ic_hw_trigger(PnvXive2 *xive, hwaddr addr, 1365*da71b7e3SCédric Le Goater uint64_t val) 1366*da71b7e3SCédric Le Goater { 1367*da71b7e3SCédric Le Goater uint8_t blk; 1368*da71b7e3SCédric Le Goater uint32_t idx; 1369*da71b7e3SCédric Le Goater 1370*da71b7e3SCédric Le Goater if (val & XIVE_TRIGGER_END) { 1371*da71b7e3SCédric Le Goater xive2_error(xive, "IC: END trigger at @0x%"HWADDR_PRIx" data 0x%"PRIx64, 1372*da71b7e3SCédric Le Goater addr, val); 1373*da71b7e3SCédric Le Goater return; 1374*da71b7e3SCédric Le Goater } 1375*da71b7e3SCédric Le Goater 1376*da71b7e3SCédric Le Goater /* 1377*da71b7e3SCédric Le Goater * Forward the source event notification directly to the Router. 1378*da71b7e3SCédric Le Goater * The source interrupt number should already be correctly encoded 1379*da71b7e3SCédric Le Goater * with the chip block id by the sending device (PHB, PSI). 1380*da71b7e3SCédric Le Goater */ 1381*da71b7e3SCédric Le Goater blk = XIVE_EAS_BLOCK(val); 1382*da71b7e3SCédric Le Goater idx = XIVE_EAS_INDEX(val); 1383*da71b7e3SCédric Le Goater 1384*da71b7e3SCédric Le Goater xive2_router_notify(XIVE_NOTIFIER(xive), XIVE_EAS(blk, idx)); 1385*da71b7e3SCédric Le Goater } 1386*da71b7e3SCédric Le Goater 1387*da71b7e3SCédric Le Goater static void pnv_xive2_ic_notify_write(void *opaque, hwaddr offset, 1388*da71b7e3SCédric Le Goater uint64_t val, unsigned size) 1389*da71b7e3SCédric Le Goater { 1390*da71b7e3SCédric Le Goater PnvXive2 *xive = PNV_XIVE2(opaque); 1391*da71b7e3SCédric Le Goater 1392*da71b7e3SCédric Le Goater /* VC: IPI triggers */ 1393*da71b7e3SCédric Le Goater switch (offset) { 1394*da71b7e3SCédric Le Goater case 0x000 ... 0x7FF: 1395*da71b7e3SCédric Le Goater /* TODO: check IPI notify sub-page routing */ 1396*da71b7e3SCédric Le Goater pnv_xive2_ic_hw_trigger(opaque, offset, val); 1397*da71b7e3SCédric Le Goater break; 1398*da71b7e3SCédric Le Goater 1399*da71b7e3SCédric Le Goater /* VC: HW triggers */ 1400*da71b7e3SCédric Le Goater case 0x800 ... 0xFFF: 1401*da71b7e3SCédric Le Goater pnv_xive2_ic_hw_trigger(opaque, offset, val); 1402*da71b7e3SCédric Le Goater break; 1403*da71b7e3SCédric Le Goater 1404*da71b7e3SCédric Le Goater default: 1405*da71b7e3SCédric Le Goater xive2_error(xive, "NOTIFY: invalid write @%"HWADDR_PRIx, offset); 1406*da71b7e3SCédric Le Goater } 1407*da71b7e3SCédric Le Goater } 1408*da71b7e3SCédric Le Goater 1409*da71b7e3SCédric Le Goater static uint64_t pnv_xive2_ic_notify_read(void *opaque, hwaddr offset, 1410*da71b7e3SCédric Le Goater unsigned size) 1411*da71b7e3SCédric Le Goater { 1412*da71b7e3SCédric Le Goater PnvXive2 *xive = PNV_XIVE2(opaque); 1413*da71b7e3SCédric Le Goater 1414*da71b7e3SCédric Le Goater /* loads are invalid */ 1415*da71b7e3SCédric Le Goater xive2_error(xive, "NOTIFY: invalid read @%"HWADDR_PRIx, offset); 1416*da71b7e3SCédric Le Goater return -1; 1417*da71b7e3SCédric Le Goater } 1418*da71b7e3SCédric Le Goater 1419*da71b7e3SCédric Le Goater static const MemoryRegionOps pnv_xive2_ic_notify_ops = { 1420*da71b7e3SCédric Le Goater .read = pnv_xive2_ic_notify_read, 1421*da71b7e3SCédric Le Goater .write = pnv_xive2_ic_notify_write, 1422*da71b7e3SCédric Le Goater .endianness = DEVICE_BIG_ENDIAN, 1423*da71b7e3SCédric Le Goater .valid = { 1424*da71b7e3SCédric Le Goater .min_access_size = 8, 1425*da71b7e3SCédric Le Goater .max_access_size = 8, 1426*da71b7e3SCédric Le Goater }, 1427*da71b7e3SCédric Le Goater .impl = { 1428*da71b7e3SCédric Le Goater .min_access_size = 8, 1429*da71b7e3SCédric Le Goater .max_access_size = 8, 1430*da71b7e3SCédric Le Goater }, 1431*da71b7e3SCédric Le Goater }; 1432*da71b7e3SCédric Le Goater 1433*da71b7e3SCédric Le Goater static uint64_t pnv_xive2_ic_lsi_read(void *opaque, hwaddr offset, 1434*da71b7e3SCédric Le Goater unsigned size) 1435*da71b7e3SCédric Le Goater { 1436*da71b7e3SCédric Le Goater PnvXive2 *xive = PNV_XIVE2(opaque); 1437*da71b7e3SCédric Le Goater 1438*da71b7e3SCédric Le Goater xive2_error(xive, "LSI: invalid read @%"HWADDR_PRIx, offset); 1439*da71b7e3SCédric Le Goater return -1; 1440*da71b7e3SCédric Le Goater } 1441*da71b7e3SCédric Le Goater 1442*da71b7e3SCédric Le Goater static void pnv_xive2_ic_lsi_write(void *opaque, hwaddr offset, 1443*da71b7e3SCédric Le Goater uint64_t val, unsigned size) 1444*da71b7e3SCédric Le Goater { 1445*da71b7e3SCédric Le Goater PnvXive2 *xive = PNV_XIVE2(opaque); 1446*da71b7e3SCédric Le Goater 1447*da71b7e3SCédric Le Goater xive2_error(xive, "LSI: invalid write @%"HWADDR_PRIx, offset); 1448*da71b7e3SCédric Le Goater } 1449*da71b7e3SCédric Le Goater 1450*da71b7e3SCédric Le Goater static const MemoryRegionOps pnv_xive2_ic_lsi_ops = { 1451*da71b7e3SCédric Le Goater .read = pnv_xive2_ic_lsi_read, 1452*da71b7e3SCédric Le Goater .write = pnv_xive2_ic_lsi_write, 1453*da71b7e3SCédric Le Goater .endianness = DEVICE_BIG_ENDIAN, 1454*da71b7e3SCédric Le Goater .valid = { 1455*da71b7e3SCédric Le Goater .min_access_size = 8, 1456*da71b7e3SCédric Le Goater .max_access_size = 8, 1457*da71b7e3SCédric Le Goater }, 1458*da71b7e3SCédric Le Goater .impl = { 1459*da71b7e3SCédric Le Goater .min_access_size = 8, 1460*da71b7e3SCédric Le Goater .max_access_size = 8, 1461*da71b7e3SCédric Le Goater }, 1462*da71b7e3SCédric Le Goater }; 1463*da71b7e3SCédric Le Goater 1464*da71b7e3SCédric Le Goater /* 1465*da71b7e3SCédric Le Goater * Sync MMIO page (write only) 1466*da71b7e3SCédric Le Goater */ 1467*da71b7e3SCédric Le Goater #define PNV_XIVE2_SYNC_IPI 0x000 1468*da71b7e3SCédric Le Goater #define PNV_XIVE2_SYNC_HW 0x080 1469*da71b7e3SCédric Le Goater #define PNV_XIVE2_SYNC_NxC 0x100 1470*da71b7e3SCédric Le Goater #define PNV_XIVE2_SYNC_INT 0x180 1471*da71b7e3SCédric Le Goater #define PNV_XIVE2_SYNC_OS_ESC 0x200 1472*da71b7e3SCédric Le Goater #define PNV_XIVE2_SYNC_POOL_ESC 0x280 1473*da71b7e3SCédric Le Goater #define PNV_XIVE2_SYNC_HARD_ESC 0x300 1474*da71b7e3SCédric Le Goater 1475*da71b7e3SCédric Le Goater static uint64_t pnv_xive2_ic_sync_read(void *opaque, hwaddr offset, 1476*da71b7e3SCédric Le Goater unsigned size) 1477*da71b7e3SCédric Le Goater { 1478*da71b7e3SCédric Le Goater PnvXive2 *xive = PNV_XIVE2(opaque); 1479*da71b7e3SCédric Le Goater 1480*da71b7e3SCédric Le Goater /* loads are invalid */ 1481*da71b7e3SCédric Le Goater xive2_error(xive, "SYNC: invalid read @%"HWADDR_PRIx, offset); 1482*da71b7e3SCédric Le Goater return -1; 1483*da71b7e3SCédric Le Goater } 1484*da71b7e3SCédric Le Goater 1485*da71b7e3SCédric Le Goater static void pnv_xive2_ic_sync_write(void *opaque, hwaddr offset, 1486*da71b7e3SCédric Le Goater uint64_t val, unsigned size) 1487*da71b7e3SCédric Le Goater { 1488*da71b7e3SCédric Le Goater PnvXive2 *xive = PNV_XIVE2(opaque); 1489*da71b7e3SCédric Le Goater 1490*da71b7e3SCédric Le Goater switch (offset) { 1491*da71b7e3SCédric Le Goater case PNV_XIVE2_SYNC_IPI: 1492*da71b7e3SCédric Le Goater case PNV_XIVE2_SYNC_HW: 1493*da71b7e3SCédric Le Goater case PNV_XIVE2_SYNC_NxC: 1494*da71b7e3SCédric Le Goater case PNV_XIVE2_SYNC_INT: 1495*da71b7e3SCédric Le Goater case PNV_XIVE2_SYNC_OS_ESC: 1496*da71b7e3SCédric Le Goater case PNV_XIVE2_SYNC_POOL_ESC: 1497*da71b7e3SCédric Le Goater case PNV_XIVE2_SYNC_HARD_ESC: 1498*da71b7e3SCédric Le Goater break; 1499*da71b7e3SCédric Le Goater default: 1500*da71b7e3SCédric Le Goater xive2_error(xive, "SYNC: invalid write @%"HWADDR_PRIx, offset); 1501*da71b7e3SCédric Le Goater } 1502*da71b7e3SCédric Le Goater } 1503*da71b7e3SCédric Le Goater 1504*da71b7e3SCédric Le Goater static const MemoryRegionOps pnv_xive2_ic_sync_ops = { 1505*da71b7e3SCédric Le Goater .read = pnv_xive2_ic_sync_read, 1506*da71b7e3SCédric Le Goater .write = pnv_xive2_ic_sync_write, 1507*da71b7e3SCédric Le Goater .endianness = DEVICE_BIG_ENDIAN, 1508*da71b7e3SCédric Le Goater .valid = { 1509*da71b7e3SCédric Le Goater .min_access_size = 8, 1510*da71b7e3SCédric Le Goater .max_access_size = 8, 1511*da71b7e3SCédric Le Goater }, 1512*da71b7e3SCédric Le Goater .impl = { 1513*da71b7e3SCédric Le Goater .min_access_size = 8, 1514*da71b7e3SCédric Le Goater .max_access_size = 8, 1515*da71b7e3SCédric Le Goater }, 1516*da71b7e3SCédric Le Goater }; 1517*da71b7e3SCédric Le Goater 1518*da71b7e3SCédric Le Goater /* 1519*da71b7e3SCédric Le Goater * When the TM direct pages of the IC controller are accessed, the 1520*da71b7e3SCédric Le Goater * target HW thread is deduced from the page offset. 1521*da71b7e3SCédric Le Goater */ 1522*da71b7e3SCédric Le Goater static XiveTCTX *pnv_xive2_get_indirect_tctx(PnvXive2 *xive, uint32_t pir) 1523*da71b7e3SCédric Le Goater { 1524*da71b7e3SCédric Le Goater PnvChip *chip = xive->chip; 1525*da71b7e3SCédric Le Goater PowerPCCPU *cpu = NULL; 1526*da71b7e3SCédric Le Goater 1527*da71b7e3SCédric Le Goater cpu = pnv_chip_find_cpu(chip, pir); 1528*da71b7e3SCédric Le Goater if (!cpu) { 1529*da71b7e3SCédric Le Goater xive2_error(xive, "IC: invalid PIR %x for indirect access", pir); 1530*da71b7e3SCédric Le Goater return NULL; 1531*da71b7e3SCédric Le Goater } 1532*da71b7e3SCédric Le Goater 1533*da71b7e3SCédric Le Goater if (!pnv_xive2_is_cpu_enabled(xive, cpu)) { 1534*da71b7e3SCédric Le Goater xive2_error(xive, "IC: CPU %x is not enabled", pir); 1535*da71b7e3SCédric Le Goater } 1536*da71b7e3SCédric Le Goater 1537*da71b7e3SCédric Le Goater return XIVE_TCTX(pnv_cpu_state(cpu)->intc); 1538*da71b7e3SCédric Le Goater } 1539*da71b7e3SCédric Le Goater 1540*da71b7e3SCédric Le Goater static uint64_t pnv_xive2_ic_tm_indirect_read(void *opaque, hwaddr offset, 1541*da71b7e3SCédric Le Goater unsigned size) 1542*da71b7e3SCédric Le Goater { 1543*da71b7e3SCédric Le Goater PnvXive2 *xive = PNV_XIVE2(opaque); 1544*da71b7e3SCédric Le Goater uint32_t pir = offset >> xive->ic_shift; 1545*da71b7e3SCédric Le Goater XiveTCTX *tctx = pnv_xive2_get_indirect_tctx(xive, pir); 1546*da71b7e3SCédric Le Goater uint64_t val = -1; 1547*da71b7e3SCédric Le Goater 1548*da71b7e3SCédric Le Goater if (tctx) { 1549*da71b7e3SCédric Le Goater val = xive_tctx_tm_read(NULL, tctx, offset, size); 1550*da71b7e3SCédric Le Goater } 1551*da71b7e3SCédric Le Goater 1552*da71b7e3SCédric Le Goater return val; 1553*da71b7e3SCédric Le Goater } 1554*da71b7e3SCédric Le Goater 1555*da71b7e3SCédric Le Goater static void pnv_xive2_ic_tm_indirect_write(void *opaque, hwaddr offset, 1556*da71b7e3SCédric Le Goater uint64_t val, unsigned size) 1557*da71b7e3SCédric Le Goater { 1558*da71b7e3SCédric Le Goater PnvXive2 *xive = PNV_XIVE2(opaque); 1559*da71b7e3SCédric Le Goater uint32_t pir = offset >> xive->ic_shift; 1560*da71b7e3SCédric Le Goater XiveTCTX *tctx = pnv_xive2_get_indirect_tctx(xive, pir); 1561*da71b7e3SCédric Le Goater 1562*da71b7e3SCédric Le Goater if (tctx) { 1563*da71b7e3SCédric Le Goater xive_tctx_tm_write(NULL, tctx, offset, val, size); 1564*da71b7e3SCédric Le Goater } 1565*da71b7e3SCédric Le Goater } 1566*da71b7e3SCédric Le Goater 1567*da71b7e3SCédric Le Goater static const MemoryRegionOps pnv_xive2_ic_tm_indirect_ops = { 1568*da71b7e3SCédric Le Goater .read = pnv_xive2_ic_tm_indirect_read, 1569*da71b7e3SCédric Le Goater .write = pnv_xive2_ic_tm_indirect_write, 1570*da71b7e3SCédric Le Goater .endianness = DEVICE_BIG_ENDIAN, 1571*da71b7e3SCédric Le Goater .valid = { 1572*da71b7e3SCédric Le Goater .min_access_size = 8, 1573*da71b7e3SCédric Le Goater .max_access_size = 8, 1574*da71b7e3SCédric Le Goater }, 1575*da71b7e3SCédric Le Goater .impl = { 1576*da71b7e3SCédric Le Goater .min_access_size = 8, 1577*da71b7e3SCédric Le Goater .max_access_size = 8, 1578*da71b7e3SCédric Le Goater }, 1579*da71b7e3SCédric Le Goater }; 1580*da71b7e3SCédric Le Goater 1581*da71b7e3SCédric Le Goater /* 1582*da71b7e3SCédric Le Goater * TIMA ops 1583*da71b7e3SCédric Le Goater */ 1584*da71b7e3SCédric Le Goater 1585*da71b7e3SCédric Le Goater static void pnv_xive2_tm_write(void *opaque, hwaddr offset, 1586*da71b7e3SCédric Le Goater uint64_t value, unsigned size) 1587*da71b7e3SCédric Le Goater { 1588*da71b7e3SCédric Le Goater PowerPCCPU *cpu = POWERPC_CPU(current_cpu); 1589*da71b7e3SCédric Le Goater PnvXive2 *xive = pnv_xive2_tm_get_xive(cpu); 1590*da71b7e3SCédric Le Goater XiveTCTX *tctx = XIVE_TCTX(pnv_cpu_state(cpu)->intc); 1591*da71b7e3SCédric Le Goater 1592*da71b7e3SCédric Le Goater /* Other TM ops are the same as XIVE1 */ 1593*da71b7e3SCédric Le Goater xive_tctx_tm_write(XIVE_PRESENTER(xive), tctx, offset, value, size); 1594*da71b7e3SCédric Le Goater } 1595*da71b7e3SCédric Le Goater 1596*da71b7e3SCédric Le Goater static uint64_t pnv_xive2_tm_read(void *opaque, hwaddr offset, unsigned size) 1597*da71b7e3SCédric Le Goater { 1598*da71b7e3SCédric Le Goater PowerPCCPU *cpu = POWERPC_CPU(current_cpu); 1599*da71b7e3SCédric Le Goater PnvXive2 *xive = pnv_xive2_tm_get_xive(cpu); 1600*da71b7e3SCédric Le Goater XiveTCTX *tctx = XIVE_TCTX(pnv_cpu_state(cpu)->intc); 1601*da71b7e3SCédric Le Goater 1602*da71b7e3SCédric Le Goater /* Other TM ops are the same as XIVE1 */ 1603*da71b7e3SCédric Le Goater return xive_tctx_tm_read(XIVE_PRESENTER(xive), tctx, offset, size); 1604*da71b7e3SCédric Le Goater } 1605*da71b7e3SCédric Le Goater 1606*da71b7e3SCédric Le Goater static const MemoryRegionOps pnv_xive2_tm_ops = { 1607*da71b7e3SCédric Le Goater .read = pnv_xive2_tm_read, 1608*da71b7e3SCédric Le Goater .write = pnv_xive2_tm_write, 1609*da71b7e3SCédric Le Goater .endianness = DEVICE_BIG_ENDIAN, 1610*da71b7e3SCédric Le Goater .valid = { 1611*da71b7e3SCédric Le Goater .min_access_size = 1, 1612*da71b7e3SCédric Le Goater .max_access_size = 8, 1613*da71b7e3SCédric Le Goater }, 1614*da71b7e3SCédric Le Goater .impl = { 1615*da71b7e3SCédric Le Goater .min_access_size = 1, 1616*da71b7e3SCédric Le Goater .max_access_size = 8, 1617*da71b7e3SCédric Le Goater }, 1618*da71b7e3SCédric Le Goater }; 1619*da71b7e3SCédric Le Goater 1620*da71b7e3SCédric Le Goater static uint64_t pnv_xive2_nvc_read(void *opaque, hwaddr offset, 1621*da71b7e3SCédric Le Goater unsigned size) 1622*da71b7e3SCédric Le Goater { 1623*da71b7e3SCédric Le Goater PnvXive2 *xive = PNV_XIVE2(opaque); 1624*da71b7e3SCédric Le Goater 1625*da71b7e3SCédric Le Goater xive2_error(xive, "NVC: invalid read @%"HWADDR_PRIx, offset); 1626*da71b7e3SCédric Le Goater return -1; 1627*da71b7e3SCédric Le Goater } 1628*da71b7e3SCédric Le Goater 1629*da71b7e3SCédric Le Goater static void pnv_xive2_nvc_write(void *opaque, hwaddr offset, 1630*da71b7e3SCédric Le Goater uint64_t val, unsigned size) 1631*da71b7e3SCédric Le Goater { 1632*da71b7e3SCédric Le Goater PnvXive2 *xive = PNV_XIVE2(opaque); 1633*da71b7e3SCédric Le Goater 1634*da71b7e3SCédric Le Goater xive2_error(xive, "NVC: invalid write @%"HWADDR_PRIx, offset); 1635*da71b7e3SCédric Le Goater } 1636*da71b7e3SCédric Le Goater 1637*da71b7e3SCédric Le Goater static const MemoryRegionOps pnv_xive2_nvc_ops = { 1638*da71b7e3SCédric Le Goater .read = pnv_xive2_nvc_read, 1639*da71b7e3SCédric Le Goater .write = pnv_xive2_nvc_write, 1640*da71b7e3SCédric Le Goater .endianness = DEVICE_BIG_ENDIAN, 1641*da71b7e3SCédric Le Goater .valid = { 1642*da71b7e3SCédric Le Goater .min_access_size = 8, 1643*da71b7e3SCédric Le Goater .max_access_size = 8, 1644*da71b7e3SCédric Le Goater }, 1645*da71b7e3SCédric Le Goater .impl = { 1646*da71b7e3SCédric Le Goater .min_access_size = 8, 1647*da71b7e3SCédric Le Goater .max_access_size = 8, 1648*da71b7e3SCédric Le Goater }, 1649*da71b7e3SCédric Le Goater }; 1650*da71b7e3SCédric Le Goater 1651*da71b7e3SCédric Le Goater static uint64_t pnv_xive2_nvpg_read(void *opaque, hwaddr offset, 1652*da71b7e3SCédric Le Goater unsigned size) 1653*da71b7e3SCédric Le Goater { 1654*da71b7e3SCédric Le Goater PnvXive2 *xive = PNV_XIVE2(opaque); 1655*da71b7e3SCédric Le Goater 1656*da71b7e3SCédric Le Goater xive2_error(xive, "NVPG: invalid read @%"HWADDR_PRIx, offset); 1657*da71b7e3SCédric Le Goater return -1; 1658*da71b7e3SCédric Le Goater } 1659*da71b7e3SCédric Le Goater 1660*da71b7e3SCédric Le Goater static void pnv_xive2_nvpg_write(void *opaque, hwaddr offset, 1661*da71b7e3SCédric Le Goater uint64_t val, unsigned size) 1662*da71b7e3SCédric Le Goater { 1663*da71b7e3SCédric Le Goater PnvXive2 *xive = PNV_XIVE2(opaque); 1664*da71b7e3SCédric Le Goater 1665*da71b7e3SCédric Le Goater xive2_error(xive, "NVPG: invalid write @%"HWADDR_PRIx, offset); 1666*da71b7e3SCédric Le Goater } 1667*da71b7e3SCédric Le Goater 1668*da71b7e3SCédric Le Goater static const MemoryRegionOps pnv_xive2_nvpg_ops = { 1669*da71b7e3SCédric Le Goater .read = pnv_xive2_nvpg_read, 1670*da71b7e3SCédric Le Goater .write = pnv_xive2_nvpg_write, 1671*da71b7e3SCédric Le Goater .endianness = DEVICE_BIG_ENDIAN, 1672*da71b7e3SCédric Le Goater .valid = { 1673*da71b7e3SCédric Le Goater .min_access_size = 8, 1674*da71b7e3SCédric Le Goater .max_access_size = 8, 1675*da71b7e3SCédric Le Goater }, 1676*da71b7e3SCédric Le Goater .impl = { 1677*da71b7e3SCédric Le Goater .min_access_size = 8, 1678*da71b7e3SCédric Le Goater .max_access_size = 8, 1679*da71b7e3SCédric Le Goater }, 1680*da71b7e3SCédric Le Goater }; 1681*da71b7e3SCédric Le Goater 1682*da71b7e3SCédric Le Goater /* 1683*da71b7e3SCédric Le Goater * POWER10 default capabilities: 0x2000120076f00000 1684*da71b7e3SCédric Le Goater */ 1685*da71b7e3SCédric Le Goater #define PNV_XIVE2_CAPABILITIES 0x2000120076f00000 1686*da71b7e3SCédric Le Goater 1687*da71b7e3SCédric Le Goater /* 1688*da71b7e3SCédric Le Goater * POWER10 default configuration: 0x0030000033000000 1689*da71b7e3SCédric Le Goater * 1690*da71b7e3SCédric Le Goater * 8bits thread id was dropped for P10 1691*da71b7e3SCédric Le Goater */ 1692*da71b7e3SCédric Le Goater #define PNV_XIVE2_CONFIGURATION 0x0030000033000000 1693*da71b7e3SCédric Le Goater 1694*da71b7e3SCédric Le Goater static void pnv_xive2_reset(void *dev) 1695*da71b7e3SCédric Le Goater { 1696*da71b7e3SCédric Le Goater PnvXive2 *xive = PNV_XIVE2(dev); 1697*da71b7e3SCédric Le Goater XiveSource *xsrc = &xive->ipi_source; 1698*da71b7e3SCédric Le Goater Xive2EndSource *end_xsrc = &xive->end_source; 1699*da71b7e3SCédric Le Goater 1700*da71b7e3SCédric Le Goater xive->cq_regs[CQ_XIVE_CAP >> 3] = xive->capabilities; 1701*da71b7e3SCédric Le Goater xive->cq_regs[CQ_XIVE_CFG >> 3] = xive->config; 1702*da71b7e3SCédric Le Goater 1703*da71b7e3SCédric Le Goater /* HW hardwires the #Topology of the chip in the block field */ 1704*da71b7e3SCédric Le Goater xive->cq_regs[CQ_XIVE_CFG >> 3] |= 1705*da71b7e3SCédric Le Goater SETFIELD(CQ_XIVE_CFG_HYP_HARD_BLOCK_ID, 0ull, xive->chip->chip_id); 1706*da71b7e3SCédric Le Goater 1707*da71b7e3SCédric Le Goater /* Set default page size to 64k */ 1708*da71b7e3SCédric Le Goater xive->ic_shift = xive->esb_shift = xive->end_shift = 16; 1709*da71b7e3SCédric Le Goater xive->nvc_shift = xive->nvpg_shift = xive->tm_shift = 16; 1710*da71b7e3SCédric Le Goater 1711*da71b7e3SCédric Le Goater /* Clear source MMIOs */ 1712*da71b7e3SCédric Le Goater if (memory_region_is_mapped(&xsrc->esb_mmio)) { 1713*da71b7e3SCédric Le Goater memory_region_del_subregion(&xive->esb_mmio, &xsrc->esb_mmio); 1714*da71b7e3SCédric Le Goater } 1715*da71b7e3SCédric Le Goater 1716*da71b7e3SCédric Le Goater if (memory_region_is_mapped(&end_xsrc->esb_mmio)) { 1717*da71b7e3SCédric Le Goater memory_region_del_subregion(&xive->end_mmio, &end_xsrc->esb_mmio); 1718*da71b7e3SCédric Le Goater } 1719*da71b7e3SCédric Le Goater } 1720*da71b7e3SCédric Le Goater 1721*da71b7e3SCédric Le Goater /* 1722*da71b7e3SCédric Le Goater * Maximum number of IRQs and ENDs supported by HW. Will be tuned by 1723*da71b7e3SCédric Le Goater * software. 1724*da71b7e3SCédric Le Goater */ 1725*da71b7e3SCédric Le Goater #define PNV_XIVE2_NR_IRQS (PNV10_XIVE2_ESB_SIZE / (1ull << XIVE_ESB_64K_2PAGE)) 1726*da71b7e3SCédric Le Goater #define PNV_XIVE2_NR_ENDS (PNV10_XIVE2_END_SIZE / (1ull << XIVE_ESB_64K_2PAGE)) 1727*da71b7e3SCédric Le Goater 1728*da71b7e3SCédric Le Goater static void pnv_xive2_realize(DeviceState *dev, Error **errp) 1729*da71b7e3SCédric Le Goater { 1730*da71b7e3SCédric Le Goater PnvXive2 *xive = PNV_XIVE2(dev); 1731*da71b7e3SCédric Le Goater PnvXive2Class *pxc = PNV_XIVE2_GET_CLASS(dev); 1732*da71b7e3SCédric Le Goater XiveSource *xsrc = &xive->ipi_source; 1733*da71b7e3SCédric Le Goater Xive2EndSource *end_xsrc = &xive->end_source; 1734*da71b7e3SCédric Le Goater Error *local_err = NULL; 1735*da71b7e3SCédric Le Goater int i; 1736*da71b7e3SCédric Le Goater 1737*da71b7e3SCédric Le Goater pxc->parent_realize(dev, &local_err); 1738*da71b7e3SCédric Le Goater if (local_err) { 1739*da71b7e3SCédric Le Goater error_propagate(errp, local_err); 1740*da71b7e3SCédric Le Goater return; 1741*da71b7e3SCédric Le Goater } 1742*da71b7e3SCédric Le Goater 1743*da71b7e3SCédric Le Goater assert(xive->chip); 1744*da71b7e3SCédric Le Goater 1745*da71b7e3SCédric Le Goater /* 1746*da71b7e3SCédric Le Goater * The XiveSource and Xive2EndSource objects are realized with the 1747*da71b7e3SCédric Le Goater * maximum allowed HW configuration. The ESB MMIO regions will be 1748*da71b7e3SCédric Le Goater * resized dynamically when the controller is configured by the FW 1749*da71b7e3SCédric Le Goater * to limit accesses to resources not provisioned. 1750*da71b7e3SCédric Le Goater */ 1751*da71b7e3SCédric Le Goater object_property_set_int(OBJECT(xsrc), "flags", XIVE_SRC_STORE_EOI, 1752*da71b7e3SCédric Le Goater &error_fatal); 1753*da71b7e3SCédric Le Goater object_property_set_int(OBJECT(xsrc), "nr-irqs", PNV_XIVE2_NR_IRQS, 1754*da71b7e3SCédric Le Goater &error_fatal); 1755*da71b7e3SCédric Le Goater object_property_set_link(OBJECT(xsrc), "xive", OBJECT(xive), 1756*da71b7e3SCédric Le Goater &error_fatal); 1757*da71b7e3SCédric Le Goater qdev_realize(DEVICE(xsrc), NULL, &local_err); 1758*da71b7e3SCédric Le Goater if (local_err) { 1759*da71b7e3SCédric Le Goater error_propagate(errp, local_err); 1760*da71b7e3SCédric Le Goater return; 1761*da71b7e3SCédric Le Goater } 1762*da71b7e3SCédric Le Goater 1763*da71b7e3SCédric Le Goater object_property_set_int(OBJECT(end_xsrc), "nr-ends", PNV_XIVE2_NR_ENDS, 1764*da71b7e3SCédric Le Goater &error_fatal); 1765*da71b7e3SCédric Le Goater object_property_set_link(OBJECT(end_xsrc), "xive", OBJECT(xive), 1766*da71b7e3SCédric Le Goater &error_abort); 1767*da71b7e3SCédric Le Goater qdev_realize(DEVICE(end_xsrc), NULL, &local_err); 1768*da71b7e3SCédric Le Goater if (local_err) { 1769*da71b7e3SCédric Le Goater error_propagate(errp, local_err); 1770*da71b7e3SCédric Le Goater return; 1771*da71b7e3SCédric Le Goater } 1772*da71b7e3SCédric Le Goater 1773*da71b7e3SCédric Le Goater /* XSCOM region, used for initial configuration of the BARs */ 1774*da71b7e3SCédric Le Goater memory_region_init_io(&xive->xscom_regs, OBJECT(dev), 1775*da71b7e3SCédric Le Goater &pnv_xive2_xscom_ops, xive, "xscom-xive", 1776*da71b7e3SCédric Le Goater PNV10_XSCOM_XIVE2_SIZE << 3); 1777*da71b7e3SCédric Le Goater 1778*da71b7e3SCédric Le Goater /* Interrupt controller MMIO regions */ 1779*da71b7e3SCédric Le Goater xive->ic_shift = 16; 1780*da71b7e3SCédric Le Goater memory_region_init(&xive->ic_mmio, OBJECT(dev), "xive-ic", 1781*da71b7e3SCédric Le Goater PNV10_XIVE2_IC_SIZE); 1782*da71b7e3SCédric Le Goater 1783*da71b7e3SCédric Le Goater for (i = 0; i < ARRAY_SIZE(xive->ic_mmios); i++) { 1784*da71b7e3SCédric Le Goater memory_region_init_io(&xive->ic_mmios[i], OBJECT(dev), 1785*da71b7e3SCédric Le Goater pnv_xive2_ic_regions[i].ops, xive, 1786*da71b7e3SCédric Le Goater pnv_xive2_ic_regions[i].name, 1787*da71b7e3SCédric Le Goater pnv_xive2_ic_regions[i].pgsize << xive->ic_shift); 1788*da71b7e3SCédric Le Goater } 1789*da71b7e3SCédric Le Goater 1790*da71b7e3SCédric Le Goater /* 1791*da71b7e3SCédric Le Goater * VC MMIO regions. 1792*da71b7e3SCédric Le Goater */ 1793*da71b7e3SCédric Le Goater xive->esb_shift = 16; 1794*da71b7e3SCédric Le Goater xive->end_shift = 16; 1795*da71b7e3SCédric Le Goater memory_region_init(&xive->esb_mmio, OBJECT(xive), "xive-esb", 1796*da71b7e3SCédric Le Goater PNV10_XIVE2_ESB_SIZE); 1797*da71b7e3SCédric Le Goater memory_region_init(&xive->end_mmio, OBJECT(xive), "xive-end", 1798*da71b7e3SCédric Le Goater PNV10_XIVE2_END_SIZE); 1799*da71b7e3SCédric Le Goater 1800*da71b7e3SCédric Le Goater /* Presenter Controller MMIO region (not modeled) */ 1801*da71b7e3SCédric Le Goater xive->nvc_shift = 16; 1802*da71b7e3SCédric Le Goater xive->nvpg_shift = 16; 1803*da71b7e3SCédric Le Goater memory_region_init_io(&xive->nvc_mmio, OBJECT(dev), 1804*da71b7e3SCédric Le Goater &pnv_xive2_nvc_ops, xive, 1805*da71b7e3SCédric Le Goater "xive-nvc", PNV10_XIVE2_NVC_SIZE); 1806*da71b7e3SCédric Le Goater 1807*da71b7e3SCédric Le Goater memory_region_init_io(&xive->nvpg_mmio, OBJECT(dev), 1808*da71b7e3SCédric Le Goater &pnv_xive2_nvpg_ops, xive, 1809*da71b7e3SCédric Le Goater "xive-nvpg", PNV10_XIVE2_NVPG_SIZE); 1810*da71b7e3SCédric Le Goater 1811*da71b7e3SCédric Le Goater /* Thread Interrupt Management Area (Direct) */ 1812*da71b7e3SCédric Le Goater xive->tm_shift = 16; 1813*da71b7e3SCédric Le Goater memory_region_init_io(&xive->tm_mmio, OBJECT(dev), &pnv_xive2_tm_ops, 1814*da71b7e3SCédric Le Goater xive, "xive-tima", PNV10_XIVE2_TM_SIZE); 1815*da71b7e3SCédric Le Goater 1816*da71b7e3SCédric Le Goater qemu_register_reset(pnv_xive2_reset, dev); 1817*da71b7e3SCédric Le Goater } 1818*da71b7e3SCédric Le Goater 1819*da71b7e3SCédric Le Goater static Property pnv_xive2_properties[] = { 1820*da71b7e3SCédric Le Goater DEFINE_PROP_UINT64("ic-bar", PnvXive2, ic_base, 0), 1821*da71b7e3SCédric Le Goater DEFINE_PROP_UINT64("esb-bar", PnvXive2, esb_base, 0), 1822*da71b7e3SCédric Le Goater DEFINE_PROP_UINT64("end-bar", PnvXive2, end_base, 0), 1823*da71b7e3SCédric Le Goater DEFINE_PROP_UINT64("nvc-bar", PnvXive2, nvc_base, 0), 1824*da71b7e3SCédric Le Goater DEFINE_PROP_UINT64("nvpg-bar", PnvXive2, nvpg_base, 0), 1825*da71b7e3SCédric Le Goater DEFINE_PROP_UINT64("tm-bar", PnvXive2, tm_base, 0), 1826*da71b7e3SCédric Le Goater DEFINE_PROP_UINT64("capabilities", PnvXive2, capabilities, 1827*da71b7e3SCédric Le Goater PNV_XIVE2_CAPABILITIES), 1828*da71b7e3SCédric Le Goater DEFINE_PROP_UINT64("config", PnvXive2, config, 1829*da71b7e3SCédric Le Goater PNV_XIVE2_CONFIGURATION), 1830*da71b7e3SCédric Le Goater DEFINE_PROP_LINK("chip", PnvXive2, chip, TYPE_PNV_CHIP, PnvChip *), 1831*da71b7e3SCédric Le Goater DEFINE_PROP_END_OF_LIST(), 1832*da71b7e3SCédric Le Goater }; 1833*da71b7e3SCédric Le Goater 1834*da71b7e3SCédric Le Goater static void pnv_xive2_instance_init(Object *obj) 1835*da71b7e3SCédric Le Goater { 1836*da71b7e3SCédric Le Goater PnvXive2 *xive = PNV_XIVE2(obj); 1837*da71b7e3SCédric Le Goater 1838*da71b7e3SCédric Le Goater object_initialize_child(obj, "ipi_source", &xive->ipi_source, 1839*da71b7e3SCédric Le Goater TYPE_XIVE_SOURCE); 1840*da71b7e3SCédric Le Goater object_initialize_child(obj, "end_source", &xive->end_source, 1841*da71b7e3SCédric Le Goater TYPE_XIVE2_END_SOURCE); 1842*da71b7e3SCédric Le Goater } 1843*da71b7e3SCédric Le Goater 1844*da71b7e3SCédric Le Goater static int pnv_xive2_dt_xscom(PnvXScomInterface *dev, void *fdt, 1845*da71b7e3SCédric Le Goater int xscom_offset) 1846*da71b7e3SCédric Le Goater { 1847*da71b7e3SCédric Le Goater const char compat_p10[] = "ibm,power10-xive-x"; 1848*da71b7e3SCédric Le Goater char *name; 1849*da71b7e3SCédric Le Goater int offset; 1850*da71b7e3SCédric Le Goater uint32_t reg[] = { 1851*da71b7e3SCédric Le Goater cpu_to_be32(PNV10_XSCOM_XIVE2_BASE), 1852*da71b7e3SCédric Le Goater cpu_to_be32(PNV10_XSCOM_XIVE2_SIZE) 1853*da71b7e3SCédric Le Goater }; 1854*da71b7e3SCédric Le Goater 1855*da71b7e3SCédric Le Goater name = g_strdup_printf("xive@%x", PNV10_XSCOM_XIVE2_BASE); 1856*da71b7e3SCédric Le Goater offset = fdt_add_subnode(fdt, xscom_offset, name); 1857*da71b7e3SCédric Le Goater _FDT(offset); 1858*da71b7e3SCédric Le Goater g_free(name); 1859*da71b7e3SCédric Le Goater 1860*da71b7e3SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "reg", reg, sizeof(reg)))); 1861*da71b7e3SCédric Le Goater _FDT(fdt_setprop(fdt, offset, "compatible", compat_p10, 1862*da71b7e3SCédric Le Goater sizeof(compat_p10))); 1863*da71b7e3SCédric Le Goater return 0; 1864*da71b7e3SCédric Le Goater } 1865*da71b7e3SCédric Le Goater 1866*da71b7e3SCédric Le Goater static void pnv_xive2_class_init(ObjectClass *klass, void *data) 1867*da71b7e3SCédric Le Goater { 1868*da71b7e3SCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 1869*da71b7e3SCédric Le Goater PnvXScomInterfaceClass *xdc = PNV_XSCOM_INTERFACE_CLASS(klass); 1870*da71b7e3SCédric Le Goater Xive2RouterClass *xrc = XIVE2_ROUTER_CLASS(klass); 1871*da71b7e3SCédric Le Goater XiveNotifierClass *xnc = XIVE_NOTIFIER_CLASS(klass); 1872*da71b7e3SCédric Le Goater XivePresenterClass *xpc = XIVE_PRESENTER_CLASS(klass); 1873*da71b7e3SCédric Le Goater PnvXive2Class *pxc = PNV_XIVE2_CLASS(klass); 1874*da71b7e3SCédric Le Goater 1875*da71b7e3SCédric Le Goater xdc->dt_xscom = pnv_xive2_dt_xscom; 1876*da71b7e3SCédric Le Goater 1877*da71b7e3SCédric Le Goater dc->desc = "PowerNV XIVE2 Interrupt Controller (POWER10)"; 1878*da71b7e3SCédric Le Goater device_class_set_parent_realize(dc, pnv_xive2_realize, 1879*da71b7e3SCédric Le Goater &pxc->parent_realize); 1880*da71b7e3SCédric Le Goater device_class_set_props(dc, pnv_xive2_properties); 1881*da71b7e3SCédric Le Goater 1882*da71b7e3SCédric Le Goater xrc->get_eas = pnv_xive2_get_eas; 1883*da71b7e3SCédric Le Goater xrc->get_end = pnv_xive2_get_end; 1884*da71b7e3SCédric Le Goater xrc->write_end = pnv_xive2_write_end; 1885*da71b7e3SCédric Le Goater xrc->get_nvp = pnv_xive2_get_nvp; 1886*da71b7e3SCédric Le Goater xrc->write_nvp = pnv_xive2_write_nvp; 1887*da71b7e3SCédric Le Goater xrc->get_block_id = pnv_xive2_get_block_id; 1888*da71b7e3SCédric Le Goater 1889*da71b7e3SCédric Le Goater xnc->notify = pnv_xive2_notify; 1890*da71b7e3SCédric Le Goater 1891*da71b7e3SCédric Le Goater xpc->match_nvt = pnv_xive2_match_nvt; 1892*da71b7e3SCédric Le Goater }; 1893*da71b7e3SCédric Le Goater 1894*da71b7e3SCédric Le Goater static const TypeInfo pnv_xive2_info = { 1895*da71b7e3SCédric Le Goater .name = TYPE_PNV_XIVE2, 1896*da71b7e3SCédric Le Goater .parent = TYPE_XIVE2_ROUTER, 1897*da71b7e3SCédric Le Goater .instance_init = pnv_xive2_instance_init, 1898*da71b7e3SCédric Le Goater .instance_size = sizeof(PnvXive2), 1899*da71b7e3SCédric Le Goater .class_init = pnv_xive2_class_init, 1900*da71b7e3SCédric Le Goater .class_size = sizeof(PnvXive2Class), 1901*da71b7e3SCédric Le Goater .interfaces = (InterfaceInfo[]) { 1902*da71b7e3SCédric Le Goater { TYPE_PNV_XSCOM_INTERFACE }, 1903*da71b7e3SCédric Le Goater { } 1904*da71b7e3SCédric Le Goater } 1905*da71b7e3SCédric Le Goater }; 1906*da71b7e3SCédric Le Goater 1907*da71b7e3SCédric Le Goater static void pnv_xive2_register_types(void) 1908*da71b7e3SCédric Le Goater { 1909*da71b7e3SCédric Le Goater type_register_static(&pnv_xive2_info); 1910*da71b7e3SCédric Le Goater } 1911*da71b7e3SCédric Le Goater 1912*da71b7e3SCédric Le Goater type_init(pnv_xive2_register_types) 1913*da71b7e3SCédric Le Goater 1914*da71b7e3SCédric Le Goater static void xive2_nvp_pic_print_info(Xive2Nvp *nvp, uint32_t nvp_idx, 1915*da71b7e3SCédric Le Goater Monitor *mon) 1916*da71b7e3SCédric Le Goater { 1917*da71b7e3SCédric Le Goater uint8_t eq_blk = xive_get_field32(NVP2_W5_VP_END_BLOCK, nvp->w5); 1918*da71b7e3SCédric Le Goater uint32_t eq_idx = xive_get_field32(NVP2_W5_VP_END_INDEX, nvp->w5); 1919*da71b7e3SCédric Le Goater 1920*da71b7e3SCédric Le Goater if (!xive2_nvp_is_valid(nvp)) { 1921*da71b7e3SCédric Le Goater return; 1922*da71b7e3SCédric Le Goater } 1923*da71b7e3SCédric Le Goater 1924*da71b7e3SCédric Le Goater monitor_printf(mon, " %08x end:%02x/%04x IPB:%02x\n", 1925*da71b7e3SCédric Le Goater nvp_idx, eq_blk, eq_idx, 1926*da71b7e3SCédric Le Goater xive_get_field32(NVP2_W2_IPB, nvp->w2)); 1927*da71b7e3SCédric Le Goater } 1928*da71b7e3SCédric Le Goater 1929*da71b7e3SCédric Le Goater /* 1930*da71b7e3SCédric Le Goater * If the table is direct, we can compute the number of PQ entries 1931*da71b7e3SCédric Le Goater * provisioned by FW. 1932*da71b7e3SCédric Le Goater */ 1933*da71b7e3SCédric Le Goater static uint32_t pnv_xive2_nr_esbs(PnvXive2 *xive) 1934*da71b7e3SCédric Le Goater { 1935*da71b7e3SCédric Le Goater uint8_t blk = pnv_xive2_block_id(xive); 1936*da71b7e3SCédric Le Goater uint64_t vsd = xive->vsds[VST_ESB][blk]; 1937*da71b7e3SCédric Le Goater uint64_t vst_tsize = 1ull << (GETFIELD(VSD_TSIZE, vsd) + 12); 1938*da71b7e3SCédric Le Goater 1939*da71b7e3SCédric Le Goater return VSD_INDIRECT & vsd ? 0 : vst_tsize * SBE_PER_BYTE; 1940*da71b7e3SCédric Le Goater } 1941*da71b7e3SCédric Le Goater 1942*da71b7e3SCédric Le Goater /* 1943*da71b7e3SCédric Le Goater * Compute the number of entries per indirect subpage. 1944*da71b7e3SCédric Le Goater */ 1945*da71b7e3SCédric Le Goater static uint64_t pnv_xive2_vst_per_subpage(PnvXive2 *xive, uint32_t type) 1946*da71b7e3SCédric Le Goater { 1947*da71b7e3SCédric Le Goater uint8_t blk = pnv_xive2_block_id(xive); 1948*da71b7e3SCédric Le Goater uint64_t vsd = xive->vsds[type][blk]; 1949*da71b7e3SCédric Le Goater const XiveVstInfo *info = &vst_infos[type]; 1950*da71b7e3SCédric Le Goater uint64_t vsd_addr; 1951*da71b7e3SCédric Le Goater uint32_t page_shift; 1952*da71b7e3SCédric Le Goater 1953*da71b7e3SCédric Le Goater /* For direct tables, fake a valid value */ 1954*da71b7e3SCédric Le Goater if (!(VSD_INDIRECT & vsd)) { 1955*da71b7e3SCédric Le Goater return 1; 1956*da71b7e3SCédric Le Goater } 1957*da71b7e3SCédric Le Goater 1958*da71b7e3SCédric Le Goater /* Get the page size of the indirect table. */ 1959*da71b7e3SCédric Le Goater vsd_addr = vsd & VSD_ADDRESS_MASK; 1960*da71b7e3SCédric Le Goater ldq_be_dma(&address_space_memory, vsd_addr, &vsd, MEMTXATTRS_UNSPECIFIED); 1961*da71b7e3SCédric Le Goater 1962*da71b7e3SCédric Le Goater if (!(vsd & VSD_ADDRESS_MASK)) { 1963*da71b7e3SCédric Le Goater #ifdef XIVE2_DEBUG 1964*da71b7e3SCédric Le Goater xive2_error(xive, "VST: invalid %s entry!?", info->name); 1965*da71b7e3SCédric Le Goater #endif 1966*da71b7e3SCédric Le Goater return 0; 1967*da71b7e3SCédric Le Goater } 1968*da71b7e3SCédric Le Goater 1969*da71b7e3SCédric Le Goater page_shift = GETFIELD(VSD_TSIZE, vsd) + 12; 1970*da71b7e3SCédric Le Goater 1971*da71b7e3SCédric Le Goater if (!pnv_xive2_vst_page_size_allowed(page_shift)) { 1972*da71b7e3SCédric Le Goater xive2_error(xive, "VST: invalid %s page shift %d", info->name, 1973*da71b7e3SCédric Le Goater page_shift); 1974*da71b7e3SCédric Le Goater return 0; 1975*da71b7e3SCédric Le Goater } 1976*da71b7e3SCédric Le Goater 1977*da71b7e3SCédric Le Goater return (1ull << page_shift) / info->size; 1978*da71b7e3SCédric Le Goater } 1979*da71b7e3SCédric Le Goater 1980*da71b7e3SCédric Le Goater void pnv_xive2_pic_print_info(PnvXive2 *xive, Monitor *mon) 1981*da71b7e3SCédric Le Goater { 1982*da71b7e3SCédric Le Goater Xive2Router *xrtr = XIVE2_ROUTER(xive); 1983*da71b7e3SCédric Le Goater uint8_t blk = pnv_xive2_block_id(xive); 1984*da71b7e3SCédric Le Goater uint8_t chip_id = xive->chip->chip_id; 1985*da71b7e3SCédric Le Goater uint32_t srcno0 = XIVE_EAS(blk, 0); 1986*da71b7e3SCédric Le Goater uint32_t nr_esbs = pnv_xive2_nr_esbs(xive); 1987*da71b7e3SCédric Le Goater Xive2Eas eas; 1988*da71b7e3SCédric Le Goater Xive2End end; 1989*da71b7e3SCédric Le Goater Xive2Nvp nvp; 1990*da71b7e3SCédric Le Goater int i; 1991*da71b7e3SCédric Le Goater uint64_t xive_nvp_per_subpage; 1992*da71b7e3SCédric Le Goater 1993*da71b7e3SCédric Le Goater monitor_printf(mon, "XIVE[%x] Source %08x .. %08x\n", blk, srcno0, 1994*da71b7e3SCédric Le Goater srcno0 + nr_esbs - 1); 1995*da71b7e3SCédric Le Goater xive_source_pic_print_info(&xive->ipi_source, srcno0, mon); 1996*da71b7e3SCédric Le Goater 1997*da71b7e3SCédric Le Goater monitor_printf(mon, "XIVE[%x] EAT %08x .. %08x\n", blk, srcno0, 1998*da71b7e3SCédric Le Goater srcno0 + nr_esbs - 1); 1999*da71b7e3SCédric Le Goater for (i = 0; i < nr_esbs; i++) { 2000*da71b7e3SCédric Le Goater if (xive2_router_get_eas(xrtr, blk, i, &eas)) { 2001*da71b7e3SCédric Le Goater break; 2002*da71b7e3SCédric Le Goater } 2003*da71b7e3SCédric Le Goater if (!xive2_eas_is_masked(&eas)) { 2004*da71b7e3SCédric Le Goater xive2_eas_pic_print_info(&eas, i, mon); 2005*da71b7e3SCédric Le Goater } 2006*da71b7e3SCédric Le Goater } 2007*da71b7e3SCédric Le Goater 2008*da71b7e3SCédric Le Goater monitor_printf(mon, "XIVE[%x] #%d END Escalation EAT\n", chip_id, blk); 2009*da71b7e3SCédric Le Goater i = 0; 2010*da71b7e3SCédric Le Goater while (!xive2_router_get_end(xrtr, blk, i, &end)) { 2011*da71b7e3SCédric Le Goater xive2_end_eas_pic_print_info(&end, i++, mon); 2012*da71b7e3SCédric Le Goater } 2013*da71b7e3SCédric Le Goater 2014*da71b7e3SCédric Le Goater monitor_printf(mon, "XIVE[%x] #%d ENDT\n", chip_id, blk); 2015*da71b7e3SCédric Le Goater i = 0; 2016*da71b7e3SCédric Le Goater while (!xive2_router_get_end(xrtr, blk, i, &end)) { 2017*da71b7e3SCédric Le Goater xive2_end_pic_print_info(&end, i++, mon); 2018*da71b7e3SCédric Le Goater } 2019*da71b7e3SCédric Le Goater 2020*da71b7e3SCédric Le Goater monitor_printf(mon, "XIVE[%x] #%d NVPT %08x .. %08x\n", chip_id, blk, 2021*da71b7e3SCédric Le Goater 0, XIVE2_NVP_COUNT - 1); 2022*da71b7e3SCédric Le Goater xive_nvp_per_subpage = pnv_xive2_vst_per_subpage(xive, VST_NVP); 2023*da71b7e3SCédric Le Goater for (i = 0; i < XIVE2_NVP_COUNT; i += xive_nvp_per_subpage) { 2024*da71b7e3SCédric Le Goater while (!xive2_router_get_nvp(xrtr, blk, i, &nvp)) { 2025*da71b7e3SCédric Le Goater xive2_nvp_pic_print_info(&nvp, i++, mon); 2026*da71b7e3SCédric Le Goater } 2027*da71b7e3SCédric Le Goater } 2028*da71b7e3SCédric Le Goater } 2029