xref: /openbmc/qemu/hw/intc/pnv_xive.c (revision 80748eb4fbc70f0a3ae423f2c01cb5a4584d803f)
12dfa91a2SCédric Le Goater /*
22dfa91a2SCédric Le Goater  * QEMU PowerPC XIVE interrupt controller model
32dfa91a2SCédric Le Goater  *
42dfa91a2SCédric Le Goater  * Copyright (c) 2017-2019, IBM Corporation.
52dfa91a2SCédric Le Goater  *
62dfa91a2SCédric Le Goater  * This code is licensed under the GPL version 2 or later. See the
72dfa91a2SCédric Le Goater  * COPYING file in the top-level directory.
82dfa91a2SCédric Le Goater  */
92dfa91a2SCédric Le Goater 
102dfa91a2SCédric Le Goater #include "qemu/osdep.h"
112dfa91a2SCédric Le Goater #include "qemu/log.h"
120b8fa32fSMarkus Armbruster #include "qemu/module.h"
132dfa91a2SCédric Le Goater #include "qapi/error.h"
142dfa91a2SCédric Le Goater #include "target/ppc/cpu.h"
152dfa91a2SCédric Le Goater #include "sysemu/cpus.h"
162dfa91a2SCédric Le Goater #include "sysemu/dma.h"
1771e8a915SMarkus Armbruster #include "sysemu/reset.h"
182dfa91a2SCédric Le Goater #include "hw/ppc/fdt.h"
192dfa91a2SCédric Le Goater #include "hw/ppc/pnv.h"
202c6fe2e2SMarkus Armbruster #include "hw/ppc/pnv_chip.h"
212dfa91a2SCédric Le Goater #include "hw/ppc/pnv_core.h"
222dfa91a2SCédric Le Goater #include "hw/ppc/pnv_xscom.h"
232dfa91a2SCédric Le Goater #include "hw/ppc/pnv_xive.h"
242dfa91a2SCédric Le Goater #include "hw/ppc/xive_regs.h"
25a27bd6c7SMarkus Armbruster #include "hw/qdev-properties.h"
262dfa91a2SCédric Le Goater #include "hw/ppc/ppc.h"
272cfc9f1aSCédric Le Goater #include "trace.h"
282dfa91a2SCédric Le Goater 
292dfa91a2SCédric Le Goater #include <libfdt.h>
302dfa91a2SCédric Le Goater 
312dfa91a2SCédric Le Goater #include "pnv_xive_regs.h"
322dfa91a2SCédric Le Goater 
33cd55b127SCédric Le Goater #undef XIVE_DEBUG
342dfa91a2SCédric Le Goater 
352dfa91a2SCédric Le Goater /*
362dfa91a2SCédric Le Goater  * Virtual structures table (VST)
372dfa91a2SCédric Le Goater  */
382dfa91a2SCédric Le Goater #define SBE_PER_BYTE   4
392dfa91a2SCédric Le Goater 
402dfa91a2SCédric Le Goater typedef struct XiveVstInfo {
412dfa91a2SCédric Le Goater     const char *name;
422dfa91a2SCédric Le Goater     uint32_t    size;
432dfa91a2SCédric Le Goater     uint32_t    max_blocks;
442dfa91a2SCédric Le Goater } XiveVstInfo;
452dfa91a2SCédric Le Goater 
462dfa91a2SCédric Le Goater static const XiveVstInfo vst_infos[] = {
472dfa91a2SCédric Le Goater     [VST_TSEL_IVT]  = { "EAT",  sizeof(XiveEAS), 16 },
482dfa91a2SCédric Le Goater     [VST_TSEL_SBE]  = { "SBE",  1,               16 },
492dfa91a2SCédric Le Goater     [VST_TSEL_EQDT] = { "ENDT", sizeof(XiveEND), 16 },
502dfa91a2SCédric Le Goater     [VST_TSEL_VPDT] = { "VPDT", sizeof(XiveNVT), 32 },
512dfa91a2SCédric Le Goater 
522dfa91a2SCédric Le Goater     /*
532dfa91a2SCédric Le Goater      *  Interrupt fifo backing store table (not modeled) :
542dfa91a2SCédric Le Goater      *
552dfa91a2SCédric Le Goater      * 0 - IPI,
562dfa91a2SCédric Le Goater      * 1 - HWD,
572dfa91a2SCédric Le Goater      * 2 - First escalate,
582dfa91a2SCédric Le Goater      * 3 - Second escalate,
592dfa91a2SCédric Le Goater      * 4 - Redistribution,
602dfa91a2SCédric Le Goater      * 5 - IPI cascaded queue ?
612dfa91a2SCédric Le Goater      */
622dfa91a2SCédric Le Goater     [VST_TSEL_IRQ]  = { "IRQ",  1,               6  },
632dfa91a2SCédric Le Goater };
642dfa91a2SCédric Le Goater 
652dfa91a2SCédric Le Goater #define xive_error(xive, fmt, ...)                                      \
662dfa91a2SCédric Le Goater     qemu_log_mask(LOG_GUEST_ERROR, "XIVE[%x] - " fmt "\n",              \
672dfa91a2SCédric Le Goater                   (xive)->chip->chip_id, ## __VA_ARGS__);
682dfa91a2SCédric Le Goater 
692dfa91a2SCédric Le Goater /*
70dc2526e4SCédric Le Goater  * When PC_TCTXT_CHIPID_OVERRIDE is configured, the PC_TCTXT_CHIPID
71dc2526e4SCédric Le Goater  * field overrides the hardwired chip ID in the Powerbus operations
72dc2526e4SCédric Le Goater  * and for CAM compares
73dc2526e4SCédric Le Goater  */
pnv_xive_block_id(PnvXive * xive)74dc2526e4SCédric Le Goater static uint8_t pnv_xive_block_id(PnvXive *xive)
75dc2526e4SCédric Le Goater {
76dc2526e4SCédric Le Goater     uint8_t blk = xive->chip->chip_id;
77dc2526e4SCédric Le Goater     uint64_t cfg_val = xive->regs[PC_TCTXT_CFG >> 3];
78dc2526e4SCédric Le Goater 
79dc2526e4SCédric Le Goater     if (cfg_val & PC_TCTXT_CHIPID_OVERRIDE) {
80dc2526e4SCédric Le Goater         blk = GETFIELD(PC_TCTXT_CHIPID, cfg_val);
81dc2526e4SCédric Le Goater     }
82dc2526e4SCédric Le Goater 
83dc2526e4SCédric Le Goater     return blk;
84dc2526e4SCédric Le Goater }
85dc2526e4SCédric Le Goater 
86dc2526e4SCédric Le Goater /*
872dfa91a2SCédric Le Goater  * VST accessors for SBE, EAT, ENDT, NVT
882dfa91a2SCédric Le Goater  *
892dfa91a2SCédric Le Goater  * Indirect VST tables are arrays of VSDs pointing to a page (of same
902dfa91a2SCédric Le Goater  * size). Each page is a direct VST table.
912dfa91a2SCédric Le Goater  */
922dfa91a2SCédric Le Goater 
932dfa91a2SCédric Le Goater #define XIVE_VSD_SIZE 8
942dfa91a2SCédric Le Goater 
952dfa91a2SCédric Le Goater /* Indirect page size can be 4K, 64K, 2M, 16M. */
pnv_xive_vst_page_size_allowed(uint32_t page_shift)962dfa91a2SCédric Le Goater static uint64_t pnv_xive_vst_page_size_allowed(uint32_t page_shift)
972dfa91a2SCédric Le Goater {
982dfa91a2SCédric Le Goater      return page_shift == 12 || page_shift == 16 ||
992dfa91a2SCédric Le Goater          page_shift == 21 || page_shift == 24;
1002dfa91a2SCédric Le Goater }
1012dfa91a2SCédric Le Goater 
pnv_xive_vst_addr_direct(PnvXive * xive,uint32_t type,uint64_t vsd,uint32_t idx)1022dfa91a2SCédric Le Goater static uint64_t pnv_xive_vst_addr_direct(PnvXive *xive, uint32_t type,
1032dfa91a2SCédric Le Goater                                          uint64_t vsd, uint32_t idx)
1042dfa91a2SCédric Le Goater {
1052dfa91a2SCédric Le Goater     const XiveVstInfo *info = &vst_infos[type];
1062dfa91a2SCédric Le Goater     uint64_t vst_addr = vsd & VSD_ADDRESS_MASK;
1077aa22e18SCédric Le Goater     uint64_t vst_tsize = 1ull << (GETFIELD(VSD_TSIZE, vsd) + 12);
1087aa22e18SCédric Le Goater     uint32_t idx_max;
1097aa22e18SCédric Le Goater 
1107aa22e18SCédric Le Goater     idx_max = vst_tsize / info->size - 1;
1117aa22e18SCédric Le Goater     if (idx > idx_max) {
1127aa22e18SCédric Le Goater #ifdef XIVE_DEBUG
1137aa22e18SCédric Le Goater         xive_error(xive, "VST: %s entry %x out of range [ 0 .. %x ] !?",
1147aa22e18SCédric Le Goater                    info->name, idx, idx_max);
1157aa22e18SCédric Le Goater #endif
1167aa22e18SCédric Le Goater         return 0;
1177aa22e18SCédric Le Goater     }
1182dfa91a2SCédric Le Goater 
1192dfa91a2SCédric Le Goater     return vst_addr + idx * info->size;
1202dfa91a2SCédric Le Goater }
1212dfa91a2SCédric Le Goater 
pnv_xive_vst_addr_indirect(PnvXive * xive,uint32_t type,uint64_t vsd,uint32_t idx)1222dfa91a2SCédric Le Goater static uint64_t pnv_xive_vst_addr_indirect(PnvXive *xive, uint32_t type,
1232dfa91a2SCédric Le Goater                                            uint64_t vsd, uint32_t idx)
1242dfa91a2SCédric Le Goater {
1252dfa91a2SCédric Le Goater     const XiveVstInfo *info = &vst_infos[type];
1262dfa91a2SCédric Le Goater     uint64_t vsd_addr;
1272dfa91a2SCédric Le Goater     uint32_t vsd_idx;
1282dfa91a2SCédric Le Goater     uint32_t page_shift;
1292dfa91a2SCédric Le Goater     uint32_t vst_per_page;
1302dfa91a2SCédric Le Goater 
1312dfa91a2SCédric Le Goater     /* Get the page size of the indirect table. */
1322dfa91a2SCédric Le Goater     vsd_addr = vsd & VSD_ADDRESS_MASK;
133e9711c61SCédric Le Goater     if (ldq_be_dma(&address_space_memory, vsd_addr, &vsd,
134e9711c61SCédric Le Goater                     MEMTXATTRS_UNSPECIFIED)) {
135e9711c61SCédric Le Goater         xive_error(xive, "VST: failed to access %s entry %x @0x%" PRIx64,
136e9711c61SCédric Le Goater                    info->name, idx, vsd_addr);
137e9711c61SCédric Le Goater         return 0;
138e9711c61SCédric Le Goater     }
1392dfa91a2SCédric Le Goater 
1402dfa91a2SCédric Le Goater     if (!(vsd & VSD_ADDRESS_MASK)) {
141cd55b127SCédric Le Goater #ifdef XIVE_DEBUG
1420df68c7eSCédric Le Goater         xive_error(xive, "VST: invalid %s entry %x !?", info->name, idx);
143cd55b127SCédric Le Goater #endif
1442dfa91a2SCédric Le Goater         return 0;
1452dfa91a2SCédric Le Goater     }
1462dfa91a2SCédric Le Goater 
1472dfa91a2SCédric Le Goater     page_shift = GETFIELD(VSD_TSIZE, vsd) + 12;
1482dfa91a2SCédric Le Goater 
1492dfa91a2SCédric Le Goater     if (!pnv_xive_vst_page_size_allowed(page_shift)) {
1502dfa91a2SCédric Le Goater         xive_error(xive, "VST: invalid %s page shift %d", info->name,
1512dfa91a2SCédric Le Goater                    page_shift);
1522dfa91a2SCédric Le Goater         return 0;
1532dfa91a2SCédric Le Goater     }
1542dfa91a2SCédric Le Goater 
1552dfa91a2SCédric Le Goater     vst_per_page = (1ull << page_shift) / info->size;
1562dfa91a2SCédric Le Goater     vsd_idx = idx / vst_per_page;
1572dfa91a2SCédric Le Goater 
1582dfa91a2SCédric Le Goater     /* Load the VSD we are looking for, if not already done */
1592dfa91a2SCédric Le Goater     if (vsd_idx) {
1602dfa91a2SCédric Le Goater         vsd_addr = vsd_addr + vsd_idx * XIVE_VSD_SIZE;
161e9711c61SCédric Le Goater         if (ldq_be_dma(&address_space_memory, vsd_addr, &vsd,
162e9711c61SCédric Le Goater                        MEMTXATTRS_UNSPECIFIED)) {
163e9711c61SCédric Le Goater             xive_error(xive, "VST: failed to access %s entry %x @0x%"
164e9711c61SCédric Le Goater                        PRIx64, info->name, vsd_idx, vsd_addr);
165e9711c61SCédric Le Goater             return 0;
166e9711c61SCédric Le Goater         }
1672dfa91a2SCédric Le Goater 
1682dfa91a2SCédric Le Goater         if (!(vsd & VSD_ADDRESS_MASK)) {
169cd55b127SCédric Le Goater #ifdef XIVE_DEBUG
1700df68c7eSCédric Le Goater             xive_error(xive, "VST: invalid %s entry %x !?", info->name, idx);
171cd55b127SCédric Le Goater #endif
1722dfa91a2SCédric Le Goater             return 0;
1732dfa91a2SCédric Le Goater         }
1742dfa91a2SCédric Le Goater 
1752dfa91a2SCédric Le Goater         /*
1762dfa91a2SCédric Le Goater          * Check that the pages have a consistent size across the
1772dfa91a2SCédric Le Goater          * indirect table
1782dfa91a2SCédric Le Goater          */
1792dfa91a2SCédric Le Goater         if (page_shift != GETFIELD(VSD_TSIZE, vsd) + 12) {
1802dfa91a2SCédric Le Goater             xive_error(xive, "VST: %s entry %x indirect page size differ !?",
1812dfa91a2SCédric Le Goater                        info->name, idx);
1822dfa91a2SCédric Le Goater             return 0;
1832dfa91a2SCédric Le Goater         }
1842dfa91a2SCédric Le Goater     }
1852dfa91a2SCédric Le Goater 
1862dfa91a2SCédric Le Goater     return pnv_xive_vst_addr_direct(xive, type, vsd, (idx % vst_per_page));
1872dfa91a2SCédric Le Goater }
1882dfa91a2SCédric Le Goater 
189b68147b7SCédric Le Goater /*
190b68147b7SCédric Le Goater  * This is a simplified model of operation forwarding on a remote IC.
191b68147b7SCédric Le Goater  *
192b68147b7SCédric Le Goater  * A PC MMIO address is built to identify the NVT structure. The load
193b68147b7SCédric Le Goater  * on the remote IC will return the address of the structure in RAM,
194b68147b7SCédric Le Goater  * which will then be used by pnv_xive_vst_write/read to perform the
195b68147b7SCédric Le Goater  * RAM operation.
196b68147b7SCédric Le Goater  */
pnv_xive_vst_addr_remote(PnvXive * xive,uint32_t type,uint64_t vsd,uint8_t blk,uint32_t idx)197b68147b7SCédric Le Goater static uint64_t pnv_xive_vst_addr_remote(PnvXive *xive, uint32_t type,
198b68147b7SCédric Le Goater                                          uint64_t vsd, uint8_t blk,
199b68147b7SCédric Le Goater                                          uint32_t idx)
200b68147b7SCédric Le Goater {
201b68147b7SCédric Le Goater     const XiveVstInfo *info = &vst_infos[type];
202b68147b7SCédric Le Goater     uint64_t remote_addr = vsd & VSD_ADDRESS_MASK;
203b68147b7SCédric Le Goater     uint64_t vst_addr;
204b68147b7SCédric Le Goater     MemTxResult result;
205b68147b7SCédric Le Goater 
206b68147b7SCédric Le Goater     if (type != VST_TSEL_VPDT) {
207b68147b7SCédric Le Goater         xive_error(xive, "VST: invalid access on remote VST %s %x/%x !?",
208b68147b7SCédric Le Goater                    info->name, blk, idx);
209b68147b7SCédric Le Goater         return 0;
210b68147b7SCédric Le Goater     }
211b68147b7SCédric Le Goater 
212527b2383SCédric Le Goater     remote_addr |= ((uint64_t)idx) << xive->pc_shift;
213b68147b7SCédric Le Goater 
214b68147b7SCédric Le Goater     vst_addr = address_space_ldq_be(&address_space_memory, remote_addr,
215b68147b7SCédric Le Goater                                     MEMTXATTRS_UNSPECIFIED, &result);
216b68147b7SCédric Le Goater     if (result != MEMTX_OK) {
217b68147b7SCédric Le Goater         xive_error(xive, "VST: read failed at @0x%"  HWADDR_PRIx
218b68147b7SCédric Le Goater                    " for NVT %x/%x\n", remote_addr, blk, idx);
219b68147b7SCédric Le Goater         return 0;
220b68147b7SCédric Le Goater     }
221b68147b7SCédric Le Goater 
222b68147b7SCédric Le Goater     return vst_addr;
223b68147b7SCédric Le Goater }
224b68147b7SCédric Le Goater 
pnv_xive_vst_addr(PnvXive * xive,uint32_t type,uint8_t blk,uint32_t idx)2252dfa91a2SCédric Le Goater static uint64_t pnv_xive_vst_addr(PnvXive *xive, uint32_t type, uint8_t blk,
2262dfa91a2SCédric Le Goater                                   uint32_t idx)
2272dfa91a2SCédric Le Goater {
2282dfa91a2SCédric Le Goater     const XiveVstInfo *info = &vst_infos[type];
2292dfa91a2SCédric Le Goater     uint64_t vsd;
2302dfa91a2SCédric Le Goater 
2312dfa91a2SCédric Le Goater     if (blk >= info->max_blocks) {
2322dfa91a2SCédric Le Goater         xive_error(xive, "VST: invalid block id %d for VST %s %d !?",
2332dfa91a2SCédric Le Goater                    blk, info->name, idx);
2342dfa91a2SCédric Le Goater         return 0;
2352dfa91a2SCédric Le Goater     }
2362dfa91a2SCédric Le Goater 
2372dfa91a2SCédric Le Goater     vsd = xive->vsds[type][blk];
2382dfa91a2SCédric Le Goater 
2392dfa91a2SCédric Le Goater     /* Remote VST access */
2402dfa91a2SCédric Le Goater     if (GETFIELD(VSD_MODE, vsd) == VSD_MODE_FORWARD) {
241b68147b7SCédric Le Goater         return pnv_xive_vst_addr_remote(xive, type, vsd, blk, idx);
2422dfa91a2SCédric Le Goater     }
2432dfa91a2SCédric Le Goater 
2442dfa91a2SCédric Le Goater     if (VSD_INDIRECT & vsd) {
2452dfa91a2SCédric Le Goater         return pnv_xive_vst_addr_indirect(xive, type, vsd, idx);
2462dfa91a2SCédric Le Goater     }
2472dfa91a2SCédric Le Goater 
2482dfa91a2SCédric Le Goater     return pnv_xive_vst_addr_direct(xive, type, vsd, idx);
2492dfa91a2SCédric Le Goater }
2502dfa91a2SCédric Le Goater 
pnv_xive_vst_read(PnvXive * xive,uint32_t type,uint8_t blk,uint32_t idx,void * data)2512dfa91a2SCédric Le Goater static int pnv_xive_vst_read(PnvXive *xive, uint32_t type, uint8_t blk,
2522dfa91a2SCédric Le Goater                              uint32_t idx, void *data)
2532dfa91a2SCédric Le Goater {
2542dfa91a2SCédric Le Goater     const XiveVstInfo *info = &vst_infos[type];
2552dfa91a2SCédric Le Goater     uint64_t addr = pnv_xive_vst_addr(xive, type, blk, idx);
256ed409be1SCédric Le Goater     MemTxResult result;
2572dfa91a2SCédric Le Goater 
2582dfa91a2SCédric Le Goater     if (!addr) {
2592dfa91a2SCédric Le Goater         return -1;
2602dfa91a2SCédric Le Goater     }
2612dfa91a2SCédric Le Goater 
262ed409be1SCédric Le Goater     result = address_space_read(&address_space_memory, addr,
263ed409be1SCédric Le Goater                                 MEMTXATTRS_UNSPECIFIED, data,
264ed409be1SCédric Le Goater                                 info->size);
265ed409be1SCédric Le Goater     if (result != MEMTX_OK) {
266ed409be1SCédric Le Goater         xive_error(xive, "VST: read failed at @0x%" HWADDR_PRIx
267ed409be1SCédric Le Goater                    " for VST %s %x/%x\n", addr, info->name, blk, idx);
268ed409be1SCédric Le Goater         return -1;
269ed409be1SCédric Le Goater     }
2702dfa91a2SCédric Le Goater     return 0;
2712dfa91a2SCédric Le Goater }
2722dfa91a2SCédric Le Goater 
2732dfa91a2SCédric Le Goater #define XIVE_VST_WORD_ALL -1
2742dfa91a2SCédric Le Goater 
pnv_xive_vst_write(PnvXive * xive,uint32_t type,uint8_t blk,uint32_t idx,void * data,uint32_t word_number)2752dfa91a2SCédric Le Goater static int pnv_xive_vst_write(PnvXive *xive, uint32_t type, uint8_t blk,
2762dfa91a2SCédric Le Goater                               uint32_t idx, void *data, uint32_t word_number)
2772dfa91a2SCédric Le Goater {
2782dfa91a2SCédric Le Goater     const XiveVstInfo *info = &vst_infos[type];
2792dfa91a2SCédric Le Goater     uint64_t addr = pnv_xive_vst_addr(xive, type, blk, idx);
280ed409be1SCédric Le Goater     MemTxResult result;
2812dfa91a2SCédric Le Goater 
2822dfa91a2SCédric Le Goater     if (!addr) {
2832dfa91a2SCédric Le Goater         return -1;
2842dfa91a2SCédric Le Goater     }
2852dfa91a2SCédric Le Goater 
2862dfa91a2SCédric Le Goater     if (word_number == XIVE_VST_WORD_ALL) {
287ed409be1SCédric Le Goater         result = address_space_write(&address_space_memory, addr,
288ed409be1SCédric Le Goater                                      MEMTXATTRS_UNSPECIFIED, data,
289ed409be1SCédric Le Goater                                      info->size);
2902dfa91a2SCédric Le Goater     } else {
291ed409be1SCédric Le Goater         result = address_space_write(&address_space_memory,
292ed409be1SCédric Le Goater                                      addr + word_number * 4,
293ed409be1SCédric Le Goater                                      MEMTXATTRS_UNSPECIFIED,
2942dfa91a2SCédric Le Goater                                      data + word_number * 4, 4);
2952dfa91a2SCédric Le Goater     }
296ed409be1SCédric Le Goater 
297ed409be1SCédric Le Goater     if (result != MEMTX_OK) {
298ed409be1SCédric Le Goater         xive_error(xive, "VST: write failed at @0x%" HWADDR_PRIx
299ed409be1SCédric Le Goater                     "for VST %s %x/%x\n", addr, info->name, blk, idx);
300ed409be1SCédric Le Goater         return -1;
301ed409be1SCédric Le Goater     }
3022dfa91a2SCédric Le Goater     return 0;
3032dfa91a2SCédric Le Goater }
3042dfa91a2SCédric Le Goater 
pnv_xive_get_end(XiveRouter * xrtr,uint8_t blk,uint32_t idx,XiveEND * end)3052dfa91a2SCédric Le Goater static int pnv_xive_get_end(XiveRouter *xrtr, uint8_t blk, uint32_t idx,
3062dfa91a2SCédric Le Goater                             XiveEND *end)
3072dfa91a2SCédric Le Goater {
308f2c1e591SCédric Le Goater     PnvXive *xive = PNV_XIVE(xrtr);
309f2c1e591SCédric Le Goater 
310f2c1e591SCédric Le Goater     if (pnv_xive_block_id(xive) != blk) {
311f2c1e591SCédric Le Goater         xive_error(xive, "VST: END %x/%x is remote !?", blk, idx);
312f2c1e591SCédric Le Goater         return -1;
313f2c1e591SCédric Le Goater     }
314f2c1e591SCédric Le Goater 
3152dfa91a2SCédric Le Goater     return pnv_xive_vst_read(PNV_XIVE(xrtr), VST_TSEL_EQDT, blk, idx, end);
3162dfa91a2SCédric Le Goater }
3172dfa91a2SCédric Le Goater 
pnv_xive_write_end(XiveRouter * xrtr,uint8_t blk,uint32_t idx,XiveEND * end,uint8_t word_number)3182dfa91a2SCédric Le Goater static int pnv_xive_write_end(XiveRouter *xrtr, uint8_t blk, uint32_t idx,
3192dfa91a2SCédric Le Goater                               XiveEND *end, uint8_t word_number)
3202dfa91a2SCédric Le Goater {
321f2c1e591SCédric Le Goater     PnvXive *xive = PNV_XIVE(xrtr);
322f2c1e591SCédric Le Goater 
323f2c1e591SCédric Le Goater     if (pnv_xive_block_id(xive) != blk) {
324f2c1e591SCédric Le Goater         xive_error(xive, "VST: END %x/%x is remote !?", blk, idx);
325f2c1e591SCédric Le Goater         return -1;
326f2c1e591SCédric Le Goater     }
327f2c1e591SCédric Le Goater 
3282dfa91a2SCédric Le Goater     return pnv_xive_vst_write(PNV_XIVE(xrtr), VST_TSEL_EQDT, blk, idx, end,
3292dfa91a2SCédric Le Goater                               word_number);
3302dfa91a2SCédric Le Goater }
3312dfa91a2SCédric Le Goater 
pnv_xive_end_update(PnvXive * xive)3320df68c7eSCédric Le Goater static int pnv_xive_end_update(PnvXive *xive)
3332dfa91a2SCédric Le Goater {
3340df68c7eSCédric Le Goater     uint8_t  blk = GETFIELD(VC_EQC_CWATCH_BLOCKID,
3350df68c7eSCédric Le Goater                            xive->regs[(VC_EQC_CWATCH_SPEC >> 3)]);
3360df68c7eSCédric Le Goater     uint32_t idx = GETFIELD(VC_EQC_CWATCH_OFFSET,
3370df68c7eSCédric Le Goater                            xive->regs[(VC_EQC_CWATCH_SPEC >> 3)]);
3382dfa91a2SCédric Le Goater     int i;
3392dfa91a2SCédric Le Goater     uint64_t eqc_watch[4];
3402dfa91a2SCédric Le Goater 
3412dfa91a2SCédric Le Goater     for (i = 0; i < ARRAY_SIZE(eqc_watch); i++) {
3422dfa91a2SCédric Le Goater         eqc_watch[i] = cpu_to_be64(xive->regs[(VC_EQC_CWATCH_DAT0 >> 3) + i]);
3432dfa91a2SCédric Le Goater     }
3442dfa91a2SCédric Le Goater 
3452dfa91a2SCédric Le Goater     return pnv_xive_vst_write(xive, VST_TSEL_EQDT, blk, idx, eqc_watch,
3462dfa91a2SCédric Le Goater                               XIVE_VST_WORD_ALL);
3472dfa91a2SCédric Le Goater }
3482dfa91a2SCédric Le Goater 
pnv_xive_end_cache_load(PnvXive * xive)3490df68c7eSCédric Le Goater static void pnv_xive_end_cache_load(PnvXive *xive)
3500df68c7eSCédric Le Goater {
3510df68c7eSCédric Le Goater     uint8_t  blk = GETFIELD(VC_EQC_CWATCH_BLOCKID,
3520df68c7eSCédric Le Goater                            xive->regs[(VC_EQC_CWATCH_SPEC >> 3)]);
3530df68c7eSCédric Le Goater     uint32_t idx = GETFIELD(VC_EQC_CWATCH_OFFSET,
3540df68c7eSCédric Le Goater                            xive->regs[(VC_EQC_CWATCH_SPEC >> 3)]);
3550df68c7eSCédric Le Goater     uint64_t eqc_watch[4] = { 0 };
3560df68c7eSCédric Le Goater     int i;
3570df68c7eSCédric Le Goater 
3580df68c7eSCédric Le Goater     if (pnv_xive_vst_read(xive, VST_TSEL_EQDT, blk, idx, eqc_watch)) {
3590df68c7eSCédric Le Goater         xive_error(xive, "VST: no END entry %x/%x !?", blk, idx);
3600df68c7eSCédric Le Goater     }
3610df68c7eSCédric Le Goater 
3620df68c7eSCédric Le Goater     for (i = 0; i < ARRAY_SIZE(eqc_watch); i++) {
3630df68c7eSCédric Le Goater         xive->regs[(VC_EQC_CWATCH_DAT0 >> 3) + i] = be64_to_cpu(eqc_watch[i]);
3640df68c7eSCédric Le Goater     }
3650df68c7eSCédric Le Goater }
3660df68c7eSCédric Le Goater 
pnv_xive_get_nvt(XiveRouter * xrtr,uint8_t blk,uint32_t idx,XiveNVT * nvt)3672dfa91a2SCédric Le Goater static int pnv_xive_get_nvt(XiveRouter *xrtr, uint8_t blk, uint32_t idx,
3682dfa91a2SCédric Le Goater                             XiveNVT *nvt)
3692dfa91a2SCédric Le Goater {
3702dfa91a2SCédric Le Goater     return pnv_xive_vst_read(PNV_XIVE(xrtr), VST_TSEL_VPDT, blk, idx, nvt);
3712dfa91a2SCédric Le Goater }
3722dfa91a2SCédric Le Goater 
pnv_xive_write_nvt(XiveRouter * xrtr,uint8_t blk,uint32_t idx,XiveNVT * nvt,uint8_t word_number)3732dfa91a2SCédric Le Goater static int pnv_xive_write_nvt(XiveRouter *xrtr, uint8_t blk, uint32_t idx,
3742dfa91a2SCédric Le Goater                               XiveNVT *nvt, uint8_t word_number)
3752dfa91a2SCédric Le Goater {
3762dfa91a2SCédric Le Goater     return pnv_xive_vst_write(PNV_XIVE(xrtr), VST_TSEL_VPDT, blk, idx, nvt,
3772dfa91a2SCédric Le Goater                               word_number);
3782dfa91a2SCédric Le Goater }
3792dfa91a2SCédric Le Goater 
pnv_xive_nvt_update(PnvXive * xive)3800df68c7eSCédric Le Goater static int pnv_xive_nvt_update(PnvXive *xive)
3812dfa91a2SCédric Le Goater {
3820df68c7eSCédric Le Goater     uint8_t  blk = GETFIELD(PC_VPC_CWATCH_BLOCKID,
3830df68c7eSCédric Le Goater                            xive->regs[(PC_VPC_CWATCH_SPEC >> 3)]);
3840df68c7eSCédric Le Goater     uint32_t idx = GETFIELD(PC_VPC_CWATCH_OFFSET,
3850df68c7eSCédric Le Goater                            xive->regs[(PC_VPC_CWATCH_SPEC >> 3)]);
3862dfa91a2SCédric Le Goater     int i;
3872dfa91a2SCédric Le Goater     uint64_t vpc_watch[8];
3882dfa91a2SCédric Le Goater 
3892dfa91a2SCédric Le Goater     for (i = 0; i < ARRAY_SIZE(vpc_watch); i++) {
3902dfa91a2SCédric Le Goater         vpc_watch[i] = cpu_to_be64(xive->regs[(PC_VPC_CWATCH_DAT0 >> 3) + i]);
3912dfa91a2SCédric Le Goater     }
3922dfa91a2SCédric Le Goater 
3932dfa91a2SCédric Le Goater     return pnv_xive_vst_write(xive, VST_TSEL_VPDT, blk, idx, vpc_watch,
3942dfa91a2SCédric Le Goater                               XIVE_VST_WORD_ALL);
3952dfa91a2SCédric Le Goater }
3962dfa91a2SCédric Le Goater 
pnv_xive_nvt_cache_load(PnvXive * xive)3970df68c7eSCédric Le Goater static void pnv_xive_nvt_cache_load(PnvXive *xive)
3980df68c7eSCédric Le Goater {
3990df68c7eSCédric Le Goater     uint8_t  blk = GETFIELD(PC_VPC_CWATCH_BLOCKID,
4000df68c7eSCédric Le Goater                            xive->regs[(PC_VPC_CWATCH_SPEC >> 3)]);
4010df68c7eSCédric Le Goater     uint32_t idx = GETFIELD(PC_VPC_CWATCH_OFFSET,
4020df68c7eSCédric Le Goater                            xive->regs[(PC_VPC_CWATCH_SPEC >> 3)]);
4030df68c7eSCédric Le Goater     uint64_t vpc_watch[8] = { 0 };
4040df68c7eSCédric Le Goater     int i;
4050df68c7eSCédric Le Goater 
4060df68c7eSCédric Le Goater     if (pnv_xive_vst_read(xive, VST_TSEL_VPDT, blk, idx, vpc_watch)) {
4070df68c7eSCédric Le Goater         xive_error(xive, "VST: no NVT entry %x/%x !?", blk, idx);
4080df68c7eSCédric Le Goater     }
4090df68c7eSCédric Le Goater 
4100df68c7eSCédric Le Goater     for (i = 0; i < ARRAY_SIZE(vpc_watch); i++) {
4110df68c7eSCédric Le Goater         xive->regs[(PC_VPC_CWATCH_DAT0 >> 3) + i] = be64_to_cpu(vpc_watch[i]);
4120df68c7eSCédric Le Goater     }
4130df68c7eSCédric Le Goater }
4140df68c7eSCédric Le Goater 
pnv_xive_get_eas(XiveRouter * xrtr,uint8_t blk,uint32_t idx,XiveEAS * eas)4152dfa91a2SCédric Le Goater static int pnv_xive_get_eas(XiveRouter *xrtr, uint8_t blk, uint32_t idx,
4162dfa91a2SCédric Le Goater                             XiveEAS *eas)
4172dfa91a2SCédric Le Goater {
4182dfa91a2SCédric Le Goater     PnvXive *xive = PNV_XIVE(xrtr);
4192dfa91a2SCédric Le Goater 
420dc2526e4SCédric Le Goater     /*
421dc2526e4SCédric Le Goater      * EAT lookups should be local to the IC
422dc2526e4SCédric Le Goater      */
423dc2526e4SCédric Le Goater     if (pnv_xive_block_id(xive) != blk) {
424106695abSCédric Le Goater         xive_error(xive, "VST: EAS %x is remote !?", XIVE_EAS(blk, idx));
4252dfa91a2SCédric Le Goater         return -1;
4262dfa91a2SCédric Le Goater     }
4272dfa91a2SCédric Le Goater 
4282dfa91a2SCédric Le Goater     return pnv_xive_vst_read(xive, VST_TSEL_IVT, blk, idx, eas);
4292dfa91a2SCédric Le Goater }
4302dfa91a2SCédric Le Goater 
pnv_xive_get_pq(XiveRouter * xrtr,uint8_t blk,uint32_t idx,uint8_t * pq)4310aa2612aSCédric Le Goater static int pnv_xive_get_pq(XiveRouter *xrtr, uint8_t blk, uint32_t idx,
4320aa2612aSCédric Le Goater                            uint8_t *pq)
4330aa2612aSCédric Le Goater {
4340aa2612aSCédric Le Goater     PnvXive *xive = PNV_XIVE(xrtr);
4350aa2612aSCédric Le Goater 
4360aa2612aSCédric Le Goater     if (pnv_xive_block_id(xive) != blk) {
4370aa2612aSCédric Le Goater         xive_error(xive, "VST: EAS %x is remote !?", XIVE_EAS(blk, idx));
4380aa2612aSCédric Le Goater         return -1;
4390aa2612aSCédric Le Goater     }
4400aa2612aSCédric Le Goater 
4410aa2612aSCédric Le Goater     *pq = xive_source_esb_get(&xive->ipi_source, idx);
4420aa2612aSCédric Le Goater     return 0;
4430aa2612aSCédric Le Goater }
4440aa2612aSCédric Le Goater 
pnv_xive_set_pq(XiveRouter * xrtr,uint8_t blk,uint32_t idx,uint8_t * pq)4450aa2612aSCédric Le Goater static int pnv_xive_set_pq(XiveRouter *xrtr, uint8_t blk, uint32_t idx,
4460aa2612aSCédric Le Goater                            uint8_t *pq)
4470aa2612aSCédric Le Goater {
4480aa2612aSCédric Le Goater     PnvXive *xive = PNV_XIVE(xrtr);
4490aa2612aSCédric Le Goater 
4500aa2612aSCédric Le Goater     if (pnv_xive_block_id(xive) != blk) {
4510aa2612aSCédric Le Goater         xive_error(xive, "VST: EAS %x is remote !?", XIVE_EAS(blk, idx));
4520aa2612aSCédric Le Goater         return -1;
4530aa2612aSCédric Le Goater     }
4540aa2612aSCédric Le Goater 
4550aa2612aSCédric Le Goater     *pq = xive_source_esb_set(&xive->ipi_source, idx, *pq);
4560aa2612aSCédric Le Goater     return 0;
4570aa2612aSCédric Le Goater }
4580aa2612aSCédric Le Goater 
4595014c602SCédric Le Goater /*
4605014c602SCédric Le Goater  * One bit per thread id. The first register PC_THREAD_EN_REG0 covers
4615014c602SCédric Le Goater  * the first cores 0-15 (normal) of the chip or 0-7 (fused). The
4625014c602SCédric Le Goater  * second register covers cores 16-23 (normal) or 8-11 (fused).
4635014c602SCédric Le Goater  */
pnv_xive_is_cpu_enabled(PnvXive * xive,PowerPCCPU * cpu)4645014c602SCédric Le Goater static bool pnv_xive_is_cpu_enabled(PnvXive *xive, PowerPCCPU *cpu)
4655014c602SCédric Le Goater {
4665014c602SCédric Le Goater     int pir = ppc_cpu_pir(cpu);
4675014c602SCédric Le Goater     uint32_t fc = PNV9_PIR2FUSEDCORE(pir);
4685014c602SCédric Le Goater     uint64_t reg = fc < 8 ? PC_THREAD_EN_REG0 : PC_THREAD_EN_REG1;
4695014c602SCédric Le Goater     uint32_t bit = pir & 0x3f;
4705014c602SCédric Le Goater 
4715014c602SCédric Le Goater     return xive->regs[reg >> 3] & PPC_BIT(bit);
4725014c602SCédric Le Goater }
4735014c602SCédric Le Goater 
pnv_xive_match_nvt(XivePresenter * xptr,uint8_t format,uint8_t nvt_blk,uint32_t nvt_idx,bool cam_ignore,uint8_t priority,uint32_t logic_serv,XiveTCTXMatch * match)474f87dae18SCédric Le Goater static int pnv_xive_match_nvt(XivePresenter *xptr, uint8_t format,
475f87dae18SCédric Le Goater                               uint8_t nvt_blk, uint32_t nvt_idx,
476f87dae18SCédric Le Goater                               bool cam_ignore, uint8_t priority,
477f87dae18SCédric Le Goater                               uint32_t logic_serv, XiveTCTXMatch *match)
478f87dae18SCédric Le Goater {
479feecc6a0SCédric Le Goater     PnvXive *xive = PNV_XIVE(xptr);
480feecc6a0SCédric Le Goater     PnvChip *chip = xive->chip;
481f87dae18SCédric Le Goater     int count = 0;
482feecc6a0SCédric Le Goater     int i, j;
483f87dae18SCédric Le Goater 
484feecc6a0SCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
485feecc6a0SCédric Le Goater         PnvCore *pc = chip->cores[i];
486feecc6a0SCédric Le Goater         CPUCore *cc = CPU_CORE(pc);
487feecc6a0SCédric Le Goater 
488feecc6a0SCédric Le Goater         for (j = 0; j < cc->nr_threads; j++) {
489feecc6a0SCédric Le Goater             PowerPCCPU *cpu = pc->threads[j];
490feecc6a0SCédric Le Goater             XiveTCTX *tctx;
491f87dae18SCédric Le Goater             int ring;
492f87dae18SCédric Le Goater 
4935014c602SCédric Le Goater             if (!pnv_xive_is_cpu_enabled(xive, cpu)) {
4945014c602SCédric Le Goater                 continue;
4955014c602SCédric Le Goater             }
4965014c602SCédric Le Goater 
497feecc6a0SCédric Le Goater             tctx = XIVE_TCTX(pnv_cpu_state(cpu)->intc);
498feecc6a0SCédric Le Goater 
499f87dae18SCédric Le Goater             /*
500f87dae18SCédric Le Goater              * Check the thread context CAM lines and record matches.
501f87dae18SCédric Le Goater              */
502feecc6a0SCédric Le Goater             ring = xive_presenter_tctx_match(xptr, tctx, format, nvt_blk,
503feecc6a0SCédric Le Goater                                              nvt_idx, cam_ignore, logic_serv);
504f87dae18SCédric Le Goater             /*
505f87dae18SCédric Le Goater              * Save the context and follow on to catch duplicates, that we
506f87dae18SCédric Le Goater              * don't support yet.
507f87dae18SCédric Le Goater              */
508f87dae18SCédric Le Goater             if (ring != -1) {
509f87dae18SCédric Le Goater                 if (match->tctx) {
510f87dae18SCédric Le Goater                     qemu_log_mask(LOG_GUEST_ERROR, "XIVE: already found a "
511f87dae18SCédric Le Goater                                   "thread context NVT %x/%x\n",
512f87dae18SCédric Le Goater                                   nvt_blk, nvt_idx);
513f87dae18SCédric Le Goater                     return -1;
514f87dae18SCédric Le Goater                 }
515f87dae18SCédric Le Goater 
516f87dae18SCédric Le Goater                 match->ring = ring;
517f87dae18SCédric Le Goater                 match->tctx = tctx;
518f87dae18SCédric Le Goater                 count++;
519f87dae18SCédric Le Goater             }
520f87dae18SCédric Le Goater         }
521feecc6a0SCédric Le Goater     }
522f87dae18SCédric Le Goater 
523f87dae18SCédric Le Goater     return count;
524f87dae18SCédric Le Goater }
525f87dae18SCédric Le Goater 
pnv_xive_presenter_get_config(XivePresenter * xptr)5262a24e6e3SFrederic Barrat static uint32_t pnv_xive_presenter_get_config(XivePresenter *xptr)
5272a24e6e3SFrederic Barrat {
5282a24e6e3SFrederic Barrat     uint32_t cfg = 0;
5292a24e6e3SFrederic Barrat 
5302a24e6e3SFrederic Barrat     /* TIMA GEN1 is all P9 knows */
5312a24e6e3SFrederic Barrat     cfg |= XIVE_PRESENTER_GEN1_TIMA_OS;
5322a24e6e3SFrederic Barrat 
5332a24e6e3SFrederic Barrat     return cfg;
5342a24e6e3SFrederic Barrat }
5352a24e6e3SFrederic Barrat 
pnv_xive_get_block_id(XiveRouter * xrtr)536f22f56ddSCédric Le Goater static uint8_t pnv_xive_get_block_id(XiveRouter *xrtr)
537f22f56ddSCédric Le Goater {
538f22f56ddSCédric Le Goater     return pnv_xive_block_id(PNV_XIVE(xrtr));
539f22f56ddSCédric Le Goater }
540f22f56ddSCédric Le Goater 
5415373c61dSCédric Le Goater /*
5425373c61dSCédric Le Goater  * The TIMA MMIO space is shared among the chips and to identify the
5435373c61dSCédric Le Goater  * chip from which the access is being done, we extract the chip id
5445373c61dSCédric Le Goater  * from the PIR.
5455373c61dSCédric Le Goater  */
pnv_xive_tm_get_xive(PowerPCCPU * cpu)5465373c61dSCédric Le Goater static PnvXive *pnv_xive_tm_get_xive(PowerPCCPU *cpu)
5475373c61dSCédric Le Goater {
5485373c61dSCédric Le Goater     int pir = ppc_cpu_pir(cpu);
549806fed59SGreg Kurz     XivePresenter *xptr = XIVE_TCTX(pnv_cpu_state(cpu)->intc)->xptr;
550806fed59SGreg Kurz     PnvXive *xive = PNV_XIVE(xptr);
5515373c61dSCédric Le Goater 
5525373c61dSCédric Le Goater     if (!pnv_xive_is_cpu_enabled(xive, cpu)) {
5535373c61dSCédric Le Goater         xive_error(xive, "IC: CPU %x is not enabled", pir);
5545373c61dSCédric Le Goater     }
5555373c61dSCédric Le Goater     return xive;
5565373c61dSCédric Le Goater }
5575373c61dSCédric Le Goater 
5582dfa91a2SCédric Le Goater /*
5592dfa91a2SCédric Le Goater  * The internal sources (IPIs) of the interrupt controller have no
5602dfa91a2SCédric Le Goater  * knowledge of the XIVE chip on which they reside. Encode the block
5612dfa91a2SCédric Le Goater  * id in the source interrupt number before forwarding the source
5622dfa91a2SCédric Le Goater  * event notification to the Router. This is required on a multichip
5632dfa91a2SCédric Le Goater  * system.
5642dfa91a2SCédric Le Goater  */
pnv_xive_notify(XiveNotifier * xn,uint32_t srcno,bool pq_checked)5650aa2612aSCédric Le Goater static void pnv_xive_notify(XiveNotifier *xn, uint32_t srcno, bool pq_checked)
5662dfa91a2SCédric Le Goater {
5672dfa91a2SCédric Le Goater     PnvXive *xive = PNV_XIVE(xn);
568dc2526e4SCédric Le Goater     uint8_t blk = pnv_xive_block_id(xive);
5692dfa91a2SCédric Le Goater 
5700aa2612aSCédric Le Goater     xive_router_notify(xn, XIVE_EAS(blk, srcno), pq_checked);
5712dfa91a2SCédric Le Goater }
5722dfa91a2SCédric Le Goater 
5732dfa91a2SCédric Le Goater /*
5742dfa91a2SCédric Le Goater  * XIVE helpers
5752dfa91a2SCédric Le Goater  */
5762dfa91a2SCédric Le Goater 
pnv_xive_vc_size(PnvXive * xive)5772dfa91a2SCédric Le Goater static uint64_t pnv_xive_vc_size(PnvXive *xive)
5782dfa91a2SCédric Le Goater {
5792dfa91a2SCédric Le Goater     return (~xive->regs[CQ_VC_BARM >> 3] + 1) & CQ_VC_BARM_MASK;
5802dfa91a2SCédric Le Goater }
5812dfa91a2SCédric Le Goater 
pnv_xive_edt_shift(PnvXive * xive)5822dfa91a2SCédric Le Goater static uint64_t pnv_xive_edt_shift(PnvXive *xive)
5832dfa91a2SCédric Le Goater {
5842dfa91a2SCédric Le Goater     return ctz64(pnv_xive_vc_size(xive) / XIVE_TABLE_EDT_MAX);
5852dfa91a2SCédric Le Goater }
5862dfa91a2SCédric Le Goater 
pnv_xive_pc_size(PnvXive * xive)5872dfa91a2SCédric Le Goater static uint64_t pnv_xive_pc_size(PnvXive *xive)
5882dfa91a2SCédric Le Goater {
5892dfa91a2SCédric Le Goater     return (~xive->regs[CQ_PC_BARM >> 3] + 1) & CQ_PC_BARM_MASK;
5902dfa91a2SCédric Le Goater }
5912dfa91a2SCédric Le Goater 
pnv_xive_nr_ipis(PnvXive * xive,uint8_t blk)5927aa22e18SCédric Le Goater static uint32_t pnv_xive_nr_ipis(PnvXive *xive, uint8_t blk)
5932dfa91a2SCédric Le Goater {
5947aa22e18SCédric Le Goater     uint64_t vsd = xive->vsds[VST_TSEL_SBE][blk];
5957aa22e18SCédric Le Goater     uint64_t vst_tsize = 1ull << (GETFIELD(VSD_TSIZE, vsd) + 12);
5962dfa91a2SCédric Le Goater 
5977aa22e18SCédric Le Goater     return VSD_INDIRECT & vsd ? 0 : vst_tsize * SBE_PER_BYTE;
5982dfa91a2SCédric Le Goater }
5992dfa91a2SCédric Le Goater 
6002dfa91a2SCédric Le Goater /*
601d302e000SCédric Le Goater  * Compute the number of entries per indirect subpage.
602d302e000SCédric Le Goater  */
pnv_xive_vst_per_subpage(PnvXive * xive,uint32_t type)603d302e000SCédric Le Goater static uint64_t pnv_xive_vst_per_subpage(PnvXive *xive, uint32_t type)
604d302e000SCédric Le Goater {
605d302e000SCédric Le Goater     uint8_t blk = pnv_xive_block_id(xive);
606d302e000SCédric Le Goater     uint64_t vsd = xive->vsds[type][blk];
607d302e000SCédric Le Goater     const XiveVstInfo *info = &vst_infos[type];
608d302e000SCédric Le Goater     uint64_t vsd_addr;
609d302e000SCédric Le Goater     uint32_t page_shift;
610d302e000SCédric Le Goater 
611d302e000SCédric Le Goater     /* For direct tables, fake a valid value */
612d302e000SCédric Le Goater     if (!(VSD_INDIRECT & vsd)) {
613d302e000SCédric Le Goater         return 1;
614d302e000SCédric Le Goater     }
615d302e000SCédric Le Goater 
616d302e000SCédric Le Goater     /* Get the page size of the indirect table. */
617d302e000SCédric Le Goater     vsd_addr = vsd & VSD_ADDRESS_MASK;
618e9711c61SCédric Le Goater     if (ldq_be_dma(&address_space_memory, vsd_addr, &vsd,
619e9711c61SCédric Le Goater                    MEMTXATTRS_UNSPECIFIED)) {
620e9711c61SCédric Le Goater         xive_error(xive, "VST: failed to access %s entry @0x%" PRIx64,
621e9711c61SCédric Le Goater                    info->name, vsd_addr);
622e9711c61SCédric Le Goater         return 0;
623e9711c61SCédric Le Goater     }
624d302e000SCédric Le Goater 
625d302e000SCédric Le Goater     if (!(vsd & VSD_ADDRESS_MASK)) {
626d302e000SCédric Le Goater #ifdef XIVE_DEBUG
627d302e000SCédric Le Goater         xive_error(xive, "VST: invalid %s entry %x !?", info->name, idx);
628d302e000SCédric Le Goater #endif
629d302e000SCédric Le Goater         return 0;
630d302e000SCédric Le Goater     }
631d302e000SCédric Le Goater 
632d302e000SCédric Le Goater     page_shift = GETFIELD(VSD_TSIZE, vsd) + 12;
633d302e000SCédric Le Goater 
634d302e000SCédric Le Goater     if (!pnv_xive_vst_page_size_allowed(page_shift)) {
635d302e000SCédric Le Goater         xive_error(xive, "VST: invalid %s page shift %d", info->name,
636d302e000SCédric Le Goater                    page_shift);
637d302e000SCédric Le Goater         return 0;
638d302e000SCédric Le Goater     }
639d302e000SCédric Le Goater 
640d302e000SCédric Le Goater     return (1ull << page_shift) / info->size;
641d302e000SCédric Le Goater }
642d302e000SCédric Le Goater 
643d302e000SCédric Le Goater /*
6442dfa91a2SCédric Le Goater  * EDT Table
6452dfa91a2SCédric Le Goater  *
6462dfa91a2SCédric Le Goater  * The Virtualization Controller MMIO region containing the IPI ESB
6472dfa91a2SCédric Le Goater  * pages and END ESB pages is sub-divided into "sets" which map
6482dfa91a2SCédric Le Goater  * portions of the VC region to the different ESB pages. It is
6492dfa91a2SCédric Le Goater  * configured at runtime through the EDT "Domain Table" to let the
6502dfa91a2SCédric Le Goater  * firmware decide how to split the VC address space between IPI ESB
6512dfa91a2SCédric Le Goater  * pages and END ESB pages.
6522dfa91a2SCédric Le Goater  */
6532dfa91a2SCédric Le Goater 
6542dfa91a2SCédric Le Goater /*
6552dfa91a2SCédric Le Goater  * Computes the overall size of the IPI or the END ESB pages
6562dfa91a2SCédric Le Goater  */
pnv_xive_edt_size(PnvXive * xive,uint64_t type)6572dfa91a2SCédric Le Goater static uint64_t pnv_xive_edt_size(PnvXive *xive, uint64_t type)
6582dfa91a2SCédric Le Goater {
6592dfa91a2SCédric Le Goater     uint64_t edt_size = 1ull << pnv_xive_edt_shift(xive);
6602dfa91a2SCédric Le Goater     uint64_t size = 0;
6612dfa91a2SCédric Le Goater     int i;
6622dfa91a2SCédric Le Goater 
6632dfa91a2SCédric Le Goater     for (i = 0; i < XIVE_TABLE_EDT_MAX; i++) {
6642dfa91a2SCédric Le Goater         uint64_t edt_type = GETFIELD(CQ_TDR_EDT_TYPE, xive->edt[i]);
6652dfa91a2SCédric Le Goater 
6662dfa91a2SCédric Le Goater         if (edt_type == type) {
6672dfa91a2SCédric Le Goater             size += edt_size;
6682dfa91a2SCédric Le Goater         }
6692dfa91a2SCédric Le Goater     }
6702dfa91a2SCédric Le Goater 
6712dfa91a2SCédric Le Goater     return size;
6722dfa91a2SCédric Le Goater }
6732dfa91a2SCédric Le Goater 
6742dfa91a2SCédric Le Goater /*
6752dfa91a2SCédric Le Goater  * Maps an offset of the VC region in the IPI or END region using the
6762dfa91a2SCédric Le Goater  * layout defined by the EDT "Domaine Table"
6772dfa91a2SCédric Le Goater  */
pnv_xive_edt_offset(PnvXive * xive,uint64_t vc_offset,uint64_t type)6782dfa91a2SCédric Le Goater static uint64_t pnv_xive_edt_offset(PnvXive *xive, uint64_t vc_offset,
6792dfa91a2SCédric Le Goater                                               uint64_t type)
6802dfa91a2SCédric Le Goater {
6812dfa91a2SCédric Le Goater     int i;
6822dfa91a2SCédric Le Goater     uint64_t edt_size = 1ull << pnv_xive_edt_shift(xive);
6832dfa91a2SCédric Le Goater     uint64_t edt_offset = vc_offset;
6842dfa91a2SCédric Le Goater 
6852dfa91a2SCédric Le Goater     for (i = 0; i < XIVE_TABLE_EDT_MAX && (i * edt_size) < vc_offset; i++) {
6862dfa91a2SCédric Le Goater         uint64_t edt_type = GETFIELD(CQ_TDR_EDT_TYPE, xive->edt[i]);
6872dfa91a2SCédric Le Goater 
6882dfa91a2SCédric Le Goater         if (edt_type != type) {
6892dfa91a2SCédric Le Goater             edt_offset -= edt_size;
6902dfa91a2SCédric Le Goater         }
6912dfa91a2SCédric Le Goater     }
6922dfa91a2SCédric Le Goater 
6932dfa91a2SCédric Le Goater     return edt_offset;
6942dfa91a2SCédric Le Goater }
6952dfa91a2SCédric Le Goater 
pnv_xive_edt_resize(PnvXive * xive)6962dfa91a2SCédric Le Goater static void pnv_xive_edt_resize(PnvXive *xive)
6972dfa91a2SCédric Le Goater {
6982dfa91a2SCédric Le Goater     uint64_t ipi_edt_size = pnv_xive_edt_size(xive, CQ_TDR_EDT_IPI);
6992dfa91a2SCédric Le Goater     uint64_t end_edt_size = pnv_xive_edt_size(xive, CQ_TDR_EDT_EQ);
7002dfa91a2SCédric Le Goater 
7012dfa91a2SCédric Le Goater     memory_region_set_size(&xive->ipi_edt_mmio, ipi_edt_size);
7022dfa91a2SCédric Le Goater     memory_region_add_subregion(&xive->ipi_mmio, 0, &xive->ipi_edt_mmio);
7032dfa91a2SCédric Le Goater 
7042dfa91a2SCédric Le Goater     memory_region_set_size(&xive->end_edt_mmio, end_edt_size);
7052dfa91a2SCédric Le Goater     memory_region_add_subregion(&xive->end_mmio, 0, &xive->end_edt_mmio);
7062dfa91a2SCédric Le Goater }
7072dfa91a2SCédric Le Goater 
7082dfa91a2SCédric Le Goater /*
7092dfa91a2SCédric Le Goater  * XIVE Table configuration. Only EDT is supported.
7102dfa91a2SCédric Le Goater  */
pnv_xive_table_set_data(PnvXive * xive,uint64_t val)7112dfa91a2SCédric Le Goater static int pnv_xive_table_set_data(PnvXive *xive, uint64_t val)
7122dfa91a2SCédric Le Goater {
7132dfa91a2SCédric Le Goater     uint64_t tsel = xive->regs[CQ_TAR >> 3] & CQ_TAR_TSEL;
7142dfa91a2SCédric Le Goater     uint8_t tsel_index = GETFIELD(CQ_TAR_TSEL_INDEX, xive->regs[CQ_TAR >> 3]);
7152dfa91a2SCédric Le Goater     uint64_t *xive_table;
7162dfa91a2SCédric Le Goater     uint8_t max_index;
7172dfa91a2SCédric Le Goater 
7182dfa91a2SCédric Le Goater     switch (tsel) {
7192dfa91a2SCédric Le Goater     case CQ_TAR_TSEL_BLK:
7202dfa91a2SCédric Le Goater         max_index = ARRAY_SIZE(xive->blk);
7212dfa91a2SCédric Le Goater         xive_table = xive->blk;
7222dfa91a2SCédric Le Goater         break;
7232dfa91a2SCédric Le Goater     case CQ_TAR_TSEL_MIG:
7242dfa91a2SCédric Le Goater         max_index = ARRAY_SIZE(xive->mig);
7252dfa91a2SCédric Le Goater         xive_table = xive->mig;
7262dfa91a2SCédric Le Goater         break;
7272dfa91a2SCédric Le Goater     case CQ_TAR_TSEL_EDT:
7282dfa91a2SCédric Le Goater         max_index = ARRAY_SIZE(xive->edt);
7292dfa91a2SCédric Le Goater         xive_table = xive->edt;
7302dfa91a2SCédric Le Goater         break;
7312dfa91a2SCédric Le Goater     case CQ_TAR_TSEL_VDT:
7322dfa91a2SCédric Le Goater         max_index = ARRAY_SIZE(xive->vdt);
7332dfa91a2SCédric Le Goater         xive_table = xive->vdt;
7342dfa91a2SCédric Le Goater         break;
7352dfa91a2SCédric Le Goater     default:
7362dfa91a2SCédric Le Goater         xive_error(xive, "IC: invalid table %d", (int) tsel);
7372dfa91a2SCédric Le Goater         return -1;
7382dfa91a2SCédric Le Goater     }
7392dfa91a2SCédric Le Goater 
7402dfa91a2SCédric Le Goater     if (tsel_index >= max_index) {
7412dfa91a2SCédric Le Goater         xive_error(xive, "IC: invalid index %d", (int) tsel_index);
7422dfa91a2SCédric Le Goater         return -1;
7432dfa91a2SCédric Le Goater     }
7442dfa91a2SCédric Le Goater 
7452dfa91a2SCédric Le Goater     xive_table[tsel_index] = val;
7462dfa91a2SCédric Le Goater 
7472dfa91a2SCédric Le Goater     if (xive->regs[CQ_TAR >> 3] & CQ_TAR_TBL_AUTOINC) {
7482dfa91a2SCédric Le Goater         xive->regs[CQ_TAR >> 3] =
7492dfa91a2SCédric Le Goater             SETFIELD(CQ_TAR_TSEL_INDEX, xive->regs[CQ_TAR >> 3], ++tsel_index);
7502dfa91a2SCédric Le Goater     }
7512dfa91a2SCédric Le Goater 
7522dfa91a2SCédric Le Goater     /*
7532dfa91a2SCédric Le Goater      * EDT configuration is complete. Resize the MMIO windows exposing
7542dfa91a2SCédric Le Goater      * the IPI and the END ESBs in the VC region.
7552dfa91a2SCédric Le Goater      */
7562dfa91a2SCédric Le Goater     if (tsel == CQ_TAR_TSEL_EDT && tsel_index == ARRAY_SIZE(xive->edt)) {
7572dfa91a2SCédric Le Goater         pnv_xive_edt_resize(xive);
7582dfa91a2SCédric Le Goater     }
7592dfa91a2SCédric Le Goater 
7602dfa91a2SCédric Le Goater     return 0;
7612dfa91a2SCédric Le Goater }
7622dfa91a2SCédric Le Goater 
7632dfa91a2SCédric Le Goater /*
7642dfa91a2SCédric Le Goater  * Virtual Structure Tables (VST) configuration
7652dfa91a2SCédric Le Goater  */
pnv_xive_vst_set_exclusive(PnvXive * xive,uint8_t type,uint8_t blk,uint64_t vsd)7662dfa91a2SCédric Le Goater static void pnv_xive_vst_set_exclusive(PnvXive *xive, uint8_t type,
7672dfa91a2SCédric Le Goater                                        uint8_t blk, uint64_t vsd)
7682dfa91a2SCédric Le Goater {
7692dfa91a2SCédric Le Goater     XiveENDSource *end_xsrc = &xive->end_source;
7702dfa91a2SCédric Le Goater     XiveSource *xsrc = &xive->ipi_source;
7712dfa91a2SCédric Le Goater     const XiveVstInfo *info = &vst_infos[type];
7722dfa91a2SCédric Le Goater     uint32_t page_shift = GETFIELD(VSD_TSIZE, vsd) + 12;
7737aa22e18SCédric Le Goater     uint64_t vst_tsize = 1ull << page_shift;
7742dfa91a2SCédric Le Goater     uint64_t vst_addr = vsd & VSD_ADDRESS_MASK;
7752dfa91a2SCédric Le Goater 
7762dfa91a2SCédric Le Goater     /* Basic checks */
7772dfa91a2SCédric Le Goater 
7782dfa91a2SCédric Le Goater     if (VSD_INDIRECT & vsd) {
7792dfa91a2SCédric Le Goater         if (!(xive->regs[VC_GLOBAL_CONFIG >> 3] & VC_GCONF_INDIRECT)) {
7802dfa91a2SCédric Le Goater             xive_error(xive, "VST: %s indirect tables are not enabled",
7812dfa91a2SCédric Le Goater                        info->name);
7822dfa91a2SCédric Le Goater             return;
7832dfa91a2SCédric Le Goater         }
7842dfa91a2SCédric Le Goater 
7852dfa91a2SCédric Le Goater         if (!pnv_xive_vst_page_size_allowed(page_shift)) {
7862dfa91a2SCédric Le Goater             xive_error(xive, "VST: invalid %s page shift %d", info->name,
7872dfa91a2SCédric Le Goater                        page_shift);
7882dfa91a2SCédric Le Goater             return;
7892dfa91a2SCédric Le Goater         }
7902dfa91a2SCédric Le Goater     }
7912dfa91a2SCédric Le Goater 
7922dfa91a2SCédric Le Goater     if (!QEMU_IS_ALIGNED(vst_addr, 1ull << page_shift)) {
7932dfa91a2SCédric Le Goater         xive_error(xive, "VST: %s table address 0x%"PRIx64" is not aligned with"
7942dfa91a2SCédric Le Goater                    " page shift %d", info->name, vst_addr, page_shift);
7952dfa91a2SCédric Le Goater         return;
7962dfa91a2SCédric Le Goater     }
7972dfa91a2SCédric Le Goater 
7982dfa91a2SCédric Le Goater     /* Record the table configuration (in SRAM on HW) */
7992dfa91a2SCédric Le Goater     xive->vsds[type][blk] = vsd;
8002dfa91a2SCédric Le Goater 
8012dfa91a2SCédric Le Goater     /* Now tune the models with the configuration provided by the FW */
8022dfa91a2SCédric Le Goater 
8032dfa91a2SCédric Le Goater     switch (type) {
8042dfa91a2SCédric Le Goater     case VST_TSEL_IVT:  /* Nothing to be done */
8052dfa91a2SCédric Le Goater         break;
8062dfa91a2SCédric Le Goater 
8072dfa91a2SCédric Le Goater     case VST_TSEL_EQDT:
8082dfa91a2SCédric Le Goater         /*
8097aa22e18SCédric Le Goater          * Backing store pages for the END.
8107aa22e18SCédric Le Goater          *
8117aa22e18SCédric Le Goater          * If the table is direct, we can compute the number of PQ
8127aa22e18SCédric Le Goater          * entries provisioned by FW (such as skiboot) and resize the
8137aa22e18SCédric Le Goater          * END ESB window accordingly.
8142dfa91a2SCédric Le Goater          */
8157aa22e18SCédric Le Goater         if (!(VSD_INDIRECT & vsd)) {
8167aa22e18SCédric Le Goater             memory_region_set_size(&end_xsrc->esb_mmio, (vst_tsize / info->size)
8177aa22e18SCédric Le Goater                                    * (1ull << xsrc->esb_shift));
8187aa22e18SCédric Le Goater         }
8192dfa91a2SCédric Le Goater         memory_region_add_subregion(&xive->end_edt_mmio, 0,
8202dfa91a2SCédric Le Goater                                     &end_xsrc->esb_mmio);
8212dfa91a2SCédric Le Goater         break;
8222dfa91a2SCédric Le Goater 
8232dfa91a2SCédric Le Goater     case VST_TSEL_SBE:
8242dfa91a2SCédric Le Goater         /*
8252dfa91a2SCédric Le Goater          * Backing store pages for the source PQ bits. The model does
8262dfa91a2SCédric Le Goater          * not use these PQ bits backed in RAM because the XiveSource
8277aa22e18SCédric Le Goater          * model has its own.
8287aa22e18SCédric Le Goater          *
8297aa22e18SCédric Le Goater          * If the table is direct, we can compute the number of PQ
8307aa22e18SCédric Le Goater          * entries provisioned by FW (such as skiboot) and resize the
8317aa22e18SCédric Le Goater          * ESB window accordingly.
8322dfa91a2SCédric Le Goater          */
8337aa22e18SCédric Le Goater         if (!(VSD_INDIRECT & vsd)) {
8347aa22e18SCédric Le Goater             memory_region_set_size(&xsrc->esb_mmio, vst_tsize * SBE_PER_BYTE
8357aa22e18SCédric Le Goater                                    * (1ull << xsrc->esb_shift));
8367aa22e18SCédric Le Goater         }
8372dfa91a2SCédric Le Goater         memory_region_add_subregion(&xive->ipi_edt_mmio, 0, &xsrc->esb_mmio);
8382dfa91a2SCédric Le Goater         break;
8392dfa91a2SCédric Le Goater 
8402dfa91a2SCédric Le Goater     case VST_TSEL_VPDT: /* Not modeled */
8412dfa91a2SCédric Le Goater     case VST_TSEL_IRQ:  /* Not modeled */
8422dfa91a2SCédric Le Goater         /*
8432dfa91a2SCédric Le Goater          * These tables contains the backing store pages for the
8442dfa91a2SCédric Le Goater          * interrupt fifos of the VC sub-engine in case of overflow.
8452dfa91a2SCédric Le Goater          */
8462dfa91a2SCédric Le Goater         break;
8472dfa91a2SCédric Le Goater 
8482dfa91a2SCédric Le Goater     default:
8492dfa91a2SCédric Le Goater         g_assert_not_reached();
8502dfa91a2SCédric Le Goater     }
8512dfa91a2SCédric Le Goater }
8522dfa91a2SCédric Le Goater 
8532dfa91a2SCédric Le Goater /*
8542dfa91a2SCédric Le Goater  * Both PC and VC sub-engines are configured as each use the Virtual
8552dfa91a2SCédric Le Goater  * Structure Tables : SBE, EAS, END and NVT.
8562dfa91a2SCédric Le Goater  */
pnv_xive_vst_set_data(PnvXive * xive,uint64_t vsd,bool pc_engine)8572dfa91a2SCédric Le Goater static void pnv_xive_vst_set_data(PnvXive *xive, uint64_t vsd, bool pc_engine)
8582dfa91a2SCédric Le Goater {
8592dfa91a2SCédric Le Goater     uint8_t mode = GETFIELD(VSD_MODE, vsd);
8602dfa91a2SCédric Le Goater     uint8_t type = GETFIELD(VST_TABLE_SELECT,
8612dfa91a2SCédric Le Goater                             xive->regs[VC_VSD_TABLE_ADDR >> 3]);
8622dfa91a2SCédric Le Goater     uint8_t blk = GETFIELD(VST_TABLE_BLOCK,
8632dfa91a2SCédric Le Goater                            xive->regs[VC_VSD_TABLE_ADDR >> 3]);
8642dfa91a2SCédric Le Goater     uint64_t vst_addr = vsd & VSD_ADDRESS_MASK;
8652dfa91a2SCédric Le Goater 
8662dfa91a2SCédric Le Goater     if (type > VST_TSEL_IRQ) {
8672dfa91a2SCédric Le Goater         xive_error(xive, "VST: invalid table type %d", type);
8682dfa91a2SCédric Le Goater         return;
8692dfa91a2SCédric Le Goater     }
8702dfa91a2SCédric Le Goater 
8712dfa91a2SCédric Le Goater     if (blk >= vst_infos[type].max_blocks) {
8722dfa91a2SCédric Le Goater         xive_error(xive, "VST: invalid block id %d for"
8732dfa91a2SCédric Le Goater                       " %s table", blk, vst_infos[type].name);
8742dfa91a2SCédric Le Goater         return;
8752dfa91a2SCédric Le Goater     }
8762dfa91a2SCédric Le Goater 
8772dfa91a2SCédric Le Goater     /*
8782dfa91a2SCédric Le Goater      * Only take the VC sub-engine configuration into account because
8792dfa91a2SCédric Le Goater      * the XiveRouter model combines both VC and PC sub-engines
8802dfa91a2SCédric Le Goater      */
8812dfa91a2SCédric Le Goater     if (pc_engine) {
8822dfa91a2SCédric Le Goater         return;
8832dfa91a2SCédric Le Goater     }
8842dfa91a2SCédric Le Goater 
8852dfa91a2SCédric Le Goater     if (!vst_addr) {
8862dfa91a2SCédric Le Goater         xive_error(xive, "VST: invalid %s table address", vst_infos[type].name);
8872dfa91a2SCédric Le Goater         return;
8882dfa91a2SCédric Le Goater     }
8892dfa91a2SCédric Le Goater 
8902dfa91a2SCédric Le Goater     switch (mode) {
8912dfa91a2SCédric Le Goater     case VSD_MODE_FORWARD:
8922dfa91a2SCédric Le Goater         xive->vsds[type][blk] = vsd;
8932dfa91a2SCédric Le Goater         break;
8942dfa91a2SCédric Le Goater 
8952dfa91a2SCédric Le Goater     case VSD_MODE_EXCLUSIVE:
8962dfa91a2SCédric Le Goater         pnv_xive_vst_set_exclusive(xive, type, blk, vsd);
8972dfa91a2SCédric Le Goater         break;
8982dfa91a2SCédric Le Goater 
8992dfa91a2SCédric Le Goater     default:
9002dfa91a2SCédric Le Goater         xive_error(xive, "VST: unsupported table mode %d", mode);
9012dfa91a2SCédric Le Goater         return;
9022dfa91a2SCédric Le Goater     }
9032dfa91a2SCédric Le Goater }
9042dfa91a2SCédric Le Goater 
9052dfa91a2SCédric Le Goater /*
9062dfa91a2SCédric Le Goater  * Interrupt controller MMIO region. The layout is compatible between
9072dfa91a2SCédric Le Goater  * 4K and 64K pages :
9082dfa91a2SCédric Le Goater  *
9092dfa91a2SCédric Le Goater  * Page 0           sub-engine BARs
9102dfa91a2SCédric Le Goater  *  0x000 - 0x3FF   IC registers
9112dfa91a2SCédric Le Goater  *  0x400 - 0x7FF   PC registers
9122dfa91a2SCédric Le Goater  *  0x800 - 0xFFF   VC registers
9132dfa91a2SCédric Le Goater  *
9142dfa91a2SCédric Le Goater  * Page 1           Notify page (writes only)
9152dfa91a2SCédric Le Goater  *  0x000 - 0x7FF   HW interrupt triggers (PSI, PHB)
9162dfa91a2SCédric Le Goater  *  0x800 - 0xFFF   forwards and syncs
9172dfa91a2SCédric Le Goater  *
9182dfa91a2SCédric Le Goater  * Page 2           LSI Trigger page (writes only) (not modeled)
9192dfa91a2SCédric Le Goater  * Page 3           LSI SB EOI page (reads only) (not modeled)
9202dfa91a2SCédric Le Goater  *
9212dfa91a2SCédric Le Goater  * Page 4-7         indirect TIMA
9222dfa91a2SCédric Le Goater  */
9232dfa91a2SCédric Le Goater 
9242dfa91a2SCédric Le Goater /*
9252dfa91a2SCédric Le Goater  * IC - registers MMIO
9262dfa91a2SCédric Le Goater  */
pnv_xive_ic_reg_write(void * opaque,hwaddr offset,uint64_t val,unsigned size)9272dfa91a2SCédric Le Goater static void pnv_xive_ic_reg_write(void *opaque, hwaddr offset,
9282dfa91a2SCédric Le Goater                                   uint64_t val, unsigned size)
9292dfa91a2SCédric Le Goater {
9302dfa91a2SCédric Le Goater     PnvXive *xive = PNV_XIVE(opaque);
9312dfa91a2SCédric Le Goater     MemoryRegion *sysmem = get_system_memory();
9322dfa91a2SCédric Le Goater     uint32_t reg = offset >> 3;
9332dfa91a2SCédric Le Goater     bool is_chip0 = xive->chip->chip_id == 0;
9342dfa91a2SCédric Le Goater 
9352dfa91a2SCédric Le Goater     switch (offset) {
9362dfa91a2SCédric Le Goater 
9372dfa91a2SCédric Le Goater     /*
9382dfa91a2SCédric Le Goater      * XIVE CQ (PowerBus bridge) settings
9392dfa91a2SCédric Le Goater      */
9402dfa91a2SCédric Le Goater     case CQ_MSGSND:     /* msgsnd for doorbells */
9412dfa91a2SCédric Le Goater     case CQ_FIRMASK_OR: /* FIR error reporting */
9422dfa91a2SCédric Le Goater         break;
9432dfa91a2SCédric Le Goater     case CQ_PBI_CTL:
9442dfa91a2SCédric Le Goater         if (val & CQ_PBI_PC_64K) {
9452dfa91a2SCédric Le Goater             xive->pc_shift = 16;
9462dfa91a2SCédric Le Goater         }
9472dfa91a2SCédric Le Goater         if (val & CQ_PBI_VC_64K) {
9482dfa91a2SCédric Le Goater             xive->vc_shift = 16;
9492dfa91a2SCédric Le Goater         }
9502dfa91a2SCédric Le Goater         break;
9512dfa91a2SCédric Le Goater     case CQ_CFG_PB_GEN: /* PowerBus General Configuration */
9522dfa91a2SCédric Le Goater         /*
9532dfa91a2SCédric Le Goater          * TODO: CQ_INT_ADDR_OPT for 1-block-per-chip mode
9542dfa91a2SCédric Le Goater          */
9552dfa91a2SCédric Le Goater         break;
9562dfa91a2SCédric Le Goater 
9572dfa91a2SCédric Le Goater     /*
9582dfa91a2SCédric Le Goater      * XIVE Virtualization Controller settings
9592dfa91a2SCédric Le Goater      */
9602dfa91a2SCédric Le Goater     case VC_GLOBAL_CONFIG:
9612dfa91a2SCédric Le Goater         break;
9622dfa91a2SCédric Le Goater 
9632dfa91a2SCédric Le Goater     /*
9642dfa91a2SCédric Le Goater      * XIVE Presenter Controller settings
9652dfa91a2SCédric Le Goater      */
9662dfa91a2SCédric Le Goater     case PC_GLOBAL_CONFIG:
9672dfa91a2SCédric Le Goater         /*
9682dfa91a2SCédric Le Goater          * PC_GCONF_CHIPID_OVR
9692dfa91a2SCédric Le Goater          *   Overrides Int command Chip ID with the Chip ID field (DEBUG)
9702dfa91a2SCédric Le Goater          */
9712dfa91a2SCédric Le Goater         break;
9722dfa91a2SCédric Le Goater     case PC_TCTXT_CFG:
9732dfa91a2SCédric Le Goater         /*
9742dfa91a2SCédric Le Goater          * TODO: block group support
9752dfa91a2SCédric Le Goater          */
9762dfa91a2SCédric Le Goater         break;
9772dfa91a2SCédric Le Goater     case PC_TCTXT_TRACK:
9782dfa91a2SCédric Le Goater         /*
9792dfa91a2SCédric Le Goater          * PC_TCTXT_TRACK_EN:
9802dfa91a2SCédric Le Goater          *   enable block tracking and exchange of block ownership
9812dfa91a2SCédric Le Goater          *   information between Interrupt controllers
9822dfa91a2SCédric Le Goater          */
9832dfa91a2SCédric Le Goater         break;
9842dfa91a2SCédric Le Goater 
9852dfa91a2SCédric Le Goater     /*
9862dfa91a2SCédric Le Goater      * Misc settings
9872dfa91a2SCédric Le Goater      */
9882dfa91a2SCédric Le Goater     case VC_SBC_CONFIG: /* Store EOI configuration */
9892dfa91a2SCédric Le Goater         /*
9909b4b4e51SMichael Tokarev          * Configure store EOI if required by firmware (skiboot has removed
9912dfa91a2SCédric Le Goater          * support recently though)
9922dfa91a2SCédric Le Goater          */
9932dfa91a2SCédric Le Goater         if (val & (VC_SBC_CONF_CPLX_CIST | VC_SBC_CONF_CIST_BOTH)) {
994e1a9b7d1SCédric Le Goater             xive->ipi_source.esb_flags |= XIVE_SRC_STORE_EOI;
9952dfa91a2SCédric Le Goater         }
9962dfa91a2SCédric Le Goater         break;
9972dfa91a2SCédric Le Goater 
9982dfa91a2SCédric Le Goater     case VC_EQC_CONFIG: /* TODO: silent escalation */
9992dfa91a2SCédric Le Goater     case VC_AIB_TX_ORDER_TAG2: /* relax ordering */
10002dfa91a2SCédric Le Goater         break;
10012dfa91a2SCédric Le Goater 
10022dfa91a2SCédric Le Goater     /*
10032dfa91a2SCédric Le Goater      * XIVE BAR settings (XSCOM only)
10042dfa91a2SCédric Le Goater      */
10052dfa91a2SCédric Le Goater     case CQ_RST_CTL:
10062dfa91a2SCédric Le Goater         /* bit4: resets all BAR registers */
10072dfa91a2SCédric Le Goater         break;
10082dfa91a2SCédric Le Goater 
10092dfa91a2SCédric Le Goater     case CQ_IC_BAR: /* IC BAR. 8 pages */
10102dfa91a2SCédric Le Goater         xive->ic_shift = val & CQ_IC_BAR_64K ? 16 : 12;
10112dfa91a2SCédric Le Goater         if (!(val & CQ_IC_BAR_VALID)) {
10122dfa91a2SCédric Le Goater             xive->ic_base = 0;
10132dfa91a2SCédric Le Goater             if (xive->regs[reg] & CQ_IC_BAR_VALID) {
10142dfa91a2SCédric Le Goater                 memory_region_del_subregion(&xive->ic_mmio,
10152dfa91a2SCédric Le Goater                                             &xive->ic_reg_mmio);
10162dfa91a2SCédric Le Goater                 memory_region_del_subregion(&xive->ic_mmio,
10172dfa91a2SCédric Le Goater                                             &xive->ic_notify_mmio);
10182dfa91a2SCédric Le Goater                 memory_region_del_subregion(&xive->ic_mmio,
10192dfa91a2SCédric Le Goater                                             &xive->ic_lsi_mmio);
10202dfa91a2SCédric Le Goater                 memory_region_del_subregion(&xive->ic_mmio,
10212dfa91a2SCédric Le Goater                                             &xive->tm_indirect_mmio);
10222dfa91a2SCédric Le Goater 
10232dfa91a2SCédric Le Goater                 memory_region_del_subregion(sysmem, &xive->ic_mmio);
10242dfa91a2SCédric Le Goater             }
10252dfa91a2SCédric Le Goater         } else {
10262dfa91a2SCédric Le Goater             xive->ic_base = val & ~(CQ_IC_BAR_VALID | CQ_IC_BAR_64K);
10272dfa91a2SCédric Le Goater             if (!(xive->regs[reg] & CQ_IC_BAR_VALID)) {
10282dfa91a2SCédric Le Goater                 memory_region_add_subregion(sysmem, xive->ic_base,
10292dfa91a2SCédric Le Goater                                             &xive->ic_mmio);
10302dfa91a2SCédric Le Goater 
10312dfa91a2SCédric Le Goater                 memory_region_add_subregion(&xive->ic_mmio,  0,
10322dfa91a2SCédric Le Goater                                             &xive->ic_reg_mmio);
10332dfa91a2SCédric Le Goater                 memory_region_add_subregion(&xive->ic_mmio,
10342dfa91a2SCédric Le Goater                                             1ul << xive->ic_shift,
10352dfa91a2SCédric Le Goater                                             &xive->ic_notify_mmio);
10362dfa91a2SCédric Le Goater                 memory_region_add_subregion(&xive->ic_mmio,
10372dfa91a2SCédric Le Goater                                             2ul << xive->ic_shift,
10382dfa91a2SCédric Le Goater                                             &xive->ic_lsi_mmio);
10392dfa91a2SCédric Le Goater                 memory_region_add_subregion(&xive->ic_mmio,
10402dfa91a2SCédric Le Goater                                             4ull << xive->ic_shift,
10412dfa91a2SCédric Le Goater                                             &xive->tm_indirect_mmio);
10422dfa91a2SCédric Le Goater             }
10432dfa91a2SCédric Le Goater         }
10442dfa91a2SCédric Le Goater         break;
10452dfa91a2SCédric Le Goater 
10462dfa91a2SCédric Le Goater     case CQ_TM1_BAR: /* TM BAR. 4 pages. Map only once */
10472dfa91a2SCédric Le Goater     case CQ_TM2_BAR: /* second TM BAR. for hotplug. Not modeled */
10482dfa91a2SCédric Le Goater         xive->tm_shift = val & CQ_TM_BAR_64K ? 16 : 12;
10492dfa91a2SCédric Le Goater         if (!(val & CQ_TM_BAR_VALID)) {
10502dfa91a2SCédric Le Goater             xive->tm_base = 0;
10512dfa91a2SCédric Le Goater             if (xive->regs[reg] & CQ_TM_BAR_VALID && is_chip0) {
10522dfa91a2SCédric Le Goater                 memory_region_del_subregion(sysmem, &xive->tm_mmio);
10532dfa91a2SCédric Le Goater             }
10542dfa91a2SCédric Le Goater         } else {
10552dfa91a2SCédric Le Goater             xive->tm_base = val & ~(CQ_TM_BAR_VALID | CQ_TM_BAR_64K);
10562dfa91a2SCédric Le Goater             if (!(xive->regs[reg] & CQ_TM_BAR_VALID) && is_chip0) {
10572dfa91a2SCédric Le Goater                 memory_region_add_subregion(sysmem, xive->tm_base,
10582dfa91a2SCédric Le Goater                                             &xive->tm_mmio);
10592dfa91a2SCédric Le Goater             }
10602dfa91a2SCédric Le Goater         }
10612dfa91a2SCédric Le Goater         break;
10622dfa91a2SCédric Le Goater 
10632dfa91a2SCédric Le Goater     case CQ_PC_BARM:
10642dfa91a2SCédric Le Goater         xive->regs[reg] = val;
10652dfa91a2SCédric Le Goater         memory_region_set_size(&xive->pc_mmio, pnv_xive_pc_size(xive));
10662dfa91a2SCédric Le Goater         break;
10672dfa91a2SCédric Le Goater     case CQ_PC_BAR: /* From 32M to 512G */
10682dfa91a2SCédric Le Goater         if (!(val & CQ_PC_BAR_VALID)) {
10692dfa91a2SCédric Le Goater             xive->pc_base = 0;
10702dfa91a2SCédric Le Goater             if (xive->regs[reg] & CQ_PC_BAR_VALID) {
10712dfa91a2SCédric Le Goater                 memory_region_del_subregion(sysmem, &xive->pc_mmio);
10722dfa91a2SCédric Le Goater             }
10732dfa91a2SCédric Le Goater         } else {
10742dfa91a2SCédric Le Goater             xive->pc_base = val & ~(CQ_PC_BAR_VALID);
10752dfa91a2SCédric Le Goater             if (!(xive->regs[reg] & CQ_PC_BAR_VALID)) {
10762dfa91a2SCédric Le Goater                 memory_region_add_subregion(sysmem, xive->pc_base,
10772dfa91a2SCédric Le Goater                                             &xive->pc_mmio);
10782dfa91a2SCédric Le Goater             }
10792dfa91a2SCédric Le Goater         }
10802dfa91a2SCédric Le Goater         break;
10812dfa91a2SCédric Le Goater 
10822dfa91a2SCédric Le Goater     case CQ_VC_BARM:
10832dfa91a2SCédric Le Goater         xive->regs[reg] = val;
10842dfa91a2SCédric Le Goater         memory_region_set_size(&xive->vc_mmio, pnv_xive_vc_size(xive));
10852dfa91a2SCédric Le Goater         break;
10862dfa91a2SCédric Le Goater     case CQ_VC_BAR: /* From 64M to 4TB */
10872dfa91a2SCédric Le Goater         if (!(val & CQ_VC_BAR_VALID)) {
10882dfa91a2SCédric Le Goater             xive->vc_base = 0;
10892dfa91a2SCédric Le Goater             if (xive->regs[reg] & CQ_VC_BAR_VALID) {
10902dfa91a2SCédric Le Goater                 memory_region_del_subregion(sysmem, &xive->vc_mmio);
10912dfa91a2SCédric Le Goater             }
10922dfa91a2SCédric Le Goater         } else {
10932dfa91a2SCédric Le Goater             xive->vc_base = val & ~(CQ_VC_BAR_VALID);
10942dfa91a2SCédric Le Goater             if (!(xive->regs[reg] & CQ_VC_BAR_VALID)) {
10952dfa91a2SCédric Le Goater                 memory_region_add_subregion(sysmem, xive->vc_base,
10962dfa91a2SCédric Le Goater                                             &xive->vc_mmio);
10972dfa91a2SCédric Le Goater             }
10982dfa91a2SCédric Le Goater         }
10992dfa91a2SCédric Le Goater         break;
11002dfa91a2SCédric Le Goater 
11012dfa91a2SCédric Le Goater     /*
11022dfa91a2SCédric Le Goater      * XIVE Table settings.
11032dfa91a2SCédric Le Goater      */
11042dfa91a2SCédric Le Goater     case CQ_TAR: /* Table Address */
11052dfa91a2SCédric Le Goater         break;
11062dfa91a2SCédric Le Goater     case CQ_TDR: /* Table Data */
11072dfa91a2SCédric Le Goater         pnv_xive_table_set_data(xive, val);
11082dfa91a2SCédric Le Goater         break;
11092dfa91a2SCédric Le Goater 
11102dfa91a2SCédric Le Goater     /*
11112dfa91a2SCédric Le Goater      * XIVE VC & PC Virtual Structure Table settings
11122dfa91a2SCédric Le Goater      */
11132dfa91a2SCédric Le Goater     case VC_VSD_TABLE_ADDR:
11142dfa91a2SCédric Le Goater     case PC_VSD_TABLE_ADDR: /* Virtual table selector */
11152dfa91a2SCédric Le Goater         break;
11162dfa91a2SCédric Le Goater     case VC_VSD_TABLE_DATA: /* Virtual table setting */
11172dfa91a2SCédric Le Goater     case PC_VSD_TABLE_DATA:
11182dfa91a2SCédric Le Goater         pnv_xive_vst_set_data(xive, val, offset == PC_VSD_TABLE_DATA);
11192dfa91a2SCédric Le Goater         break;
11202dfa91a2SCédric Le Goater 
11212dfa91a2SCédric Le Goater     /*
11222dfa91a2SCédric Le Goater      * Interrupt fifo overflow in memory backing store (Not modeled)
11232dfa91a2SCédric Le Goater      */
11242dfa91a2SCédric Le Goater     case VC_IRQ_CONFIG_IPI:
11252dfa91a2SCédric Le Goater     case VC_IRQ_CONFIG_HW:
11262dfa91a2SCédric Le Goater     case VC_IRQ_CONFIG_CASCADE1:
11272dfa91a2SCédric Le Goater     case VC_IRQ_CONFIG_CASCADE2:
11282dfa91a2SCédric Le Goater     case VC_IRQ_CONFIG_REDIST:
11292dfa91a2SCédric Le Goater     case VC_IRQ_CONFIG_IPI_CASC:
11302dfa91a2SCédric Le Goater         break;
11312dfa91a2SCédric Le Goater 
11322dfa91a2SCédric Le Goater     /*
11332dfa91a2SCédric Le Goater      * XIVE hardware thread enablement
11342dfa91a2SCédric Le Goater      */
11352dfa91a2SCédric Le Goater     case PC_THREAD_EN_REG0: /* Physical Thread Enable */
11362dfa91a2SCédric Le Goater     case PC_THREAD_EN_REG1: /* Physical Thread Enable (fused core) */
11372dfa91a2SCédric Le Goater         break;
11382dfa91a2SCédric Le Goater 
11392dfa91a2SCédric Le Goater     case PC_THREAD_EN_REG0_SET:
11402dfa91a2SCédric Le Goater         xive->regs[PC_THREAD_EN_REG0 >> 3] |= val;
11412dfa91a2SCédric Le Goater         break;
11422dfa91a2SCédric Le Goater     case PC_THREAD_EN_REG1_SET:
11432dfa91a2SCédric Le Goater         xive->regs[PC_THREAD_EN_REG1 >> 3] |= val;
11442dfa91a2SCédric Le Goater         break;
11452dfa91a2SCédric Le Goater     case PC_THREAD_EN_REG0_CLR:
11462dfa91a2SCédric Le Goater         xive->regs[PC_THREAD_EN_REG0 >> 3] &= ~val;
11472dfa91a2SCédric Le Goater         break;
11482dfa91a2SCédric Le Goater     case PC_THREAD_EN_REG1_CLR:
11492dfa91a2SCédric Le Goater         xive->regs[PC_THREAD_EN_REG1 >> 3] &= ~val;
11502dfa91a2SCédric Le Goater         break;
11512dfa91a2SCédric Le Goater 
11522dfa91a2SCédric Le Goater     /*
11532dfa91a2SCédric Le Goater      * Indirect TIMA access set up. Defines the PIR of the HW thread
11542dfa91a2SCédric Le Goater      * to use.
11552dfa91a2SCédric Le Goater      */
11562dfa91a2SCédric Le Goater     case PC_TCTXT_INDIR0 ... PC_TCTXT_INDIR3:
11572dfa91a2SCédric Le Goater         break;
11582dfa91a2SCédric Le Goater 
11592dfa91a2SCédric Le Goater     /*
11602dfa91a2SCédric Le Goater      * XIVE PC & VC cache updates for EAS, NVT and END
11612dfa91a2SCédric Le Goater      */
11622dfa91a2SCédric Le Goater     case VC_IVC_SCRUB_MASK:
11632dfa91a2SCédric Le Goater     case VC_IVC_SCRUB_TRIG:
11642dfa91a2SCédric Le Goater         break;
11652dfa91a2SCédric Le Goater 
11662dfa91a2SCédric Le Goater     case VC_EQC_CWATCH_SPEC:
11670df68c7eSCédric Le Goater         val &= ~VC_EQC_CWATCH_CONFLICT; /* HW resets this bit */
11682dfa91a2SCédric Le Goater         break;
11690df68c7eSCédric Le Goater     case VC_EQC_CWATCH_DAT1 ... VC_EQC_CWATCH_DAT3:
11700df68c7eSCédric Le Goater         break;
11710df68c7eSCédric Le Goater     case VC_EQC_CWATCH_DAT0:
11720df68c7eSCédric Le Goater         /* writing to DATA0 triggers the cache write */
11730df68c7eSCédric Le Goater         xive->regs[reg] = val;
11740df68c7eSCédric Le Goater         pnv_xive_end_update(xive);
11750df68c7eSCédric Le Goater         break;
11760df68c7eSCédric Le Goater     case VC_EQC_SCRUB_MASK:
11772dfa91a2SCédric Le Goater     case VC_EQC_SCRUB_TRIG:
11780df68c7eSCédric Le Goater         /*
11790df68c7eSCédric Le Goater          * The scrubbing registers flush the cache in RAM and can also
11800df68c7eSCédric Le Goater          * invalidate.
11810df68c7eSCédric Le Goater          */
11822dfa91a2SCédric Le Goater         break;
11832dfa91a2SCédric Le Goater 
11842dfa91a2SCédric Le Goater     case PC_VPC_CWATCH_SPEC:
11850df68c7eSCédric Le Goater         val &= ~PC_VPC_CWATCH_CONFLICT; /* HW resets this bit */
11862dfa91a2SCédric Le Goater         break;
11870df68c7eSCédric Le Goater     case PC_VPC_CWATCH_DAT1 ... PC_VPC_CWATCH_DAT7:
11880df68c7eSCédric Le Goater         break;
11890df68c7eSCédric Le Goater     case PC_VPC_CWATCH_DAT0:
11900df68c7eSCédric Le Goater         /* writing to DATA0 triggers the cache write */
11910df68c7eSCédric Le Goater         xive->regs[reg] = val;
11920df68c7eSCédric Le Goater         pnv_xive_nvt_update(xive);
11930df68c7eSCédric Le Goater         break;
11940df68c7eSCédric Le Goater     case PC_VPC_SCRUB_MASK:
11952dfa91a2SCédric Le Goater     case PC_VPC_SCRUB_TRIG:
11960df68c7eSCédric Le Goater         /*
11970df68c7eSCédric Le Goater          * The scrubbing registers flush the cache in RAM and can also
11980df68c7eSCédric Le Goater          * invalidate.
11990df68c7eSCédric Le Goater          */
12002dfa91a2SCédric Le Goater         break;
12012dfa91a2SCédric Le Goater 
12022dfa91a2SCédric Le Goater 
12032dfa91a2SCédric Le Goater     /*
12042dfa91a2SCédric Le Goater      * XIVE PC & VC cache invalidation
12052dfa91a2SCédric Le Goater      */
12062dfa91a2SCédric Le Goater     case PC_AT_KILL:
12072dfa91a2SCédric Le Goater         break;
12082dfa91a2SCédric Le Goater     case VC_AT_MACRO_KILL:
12092dfa91a2SCédric Le Goater         break;
12102dfa91a2SCédric Le Goater     case PC_AT_KILL_MASK:
12112dfa91a2SCédric Le Goater     case VC_AT_MACRO_KILL_MASK:
12122dfa91a2SCédric Le Goater         break;
12132dfa91a2SCédric Le Goater 
12142dfa91a2SCédric Le Goater     default:
12152dfa91a2SCédric Le Goater         xive_error(xive, "IC: invalid write to reg=0x%"HWADDR_PRIx, offset);
12162dfa91a2SCédric Le Goater         return;
12172dfa91a2SCédric Le Goater     }
12182dfa91a2SCédric Le Goater 
12192dfa91a2SCédric Le Goater     xive->regs[reg] = val;
12202dfa91a2SCédric Le Goater }
12212dfa91a2SCédric Le Goater 
pnv_xive_ic_reg_read(void * opaque,hwaddr offset,unsigned size)12222dfa91a2SCédric Le Goater static uint64_t pnv_xive_ic_reg_read(void *opaque, hwaddr offset, unsigned size)
12232dfa91a2SCédric Le Goater {
12242dfa91a2SCédric Le Goater     PnvXive *xive = PNV_XIVE(opaque);
12252dfa91a2SCédric Le Goater     uint64_t val = 0;
12262dfa91a2SCédric Le Goater     uint32_t reg = offset >> 3;
12272dfa91a2SCédric Le Goater 
12282dfa91a2SCédric Le Goater     switch (offset) {
12292dfa91a2SCédric Le Goater     case CQ_CFG_PB_GEN:
12302dfa91a2SCédric Le Goater     case CQ_IC_BAR:
12312dfa91a2SCédric Le Goater     case CQ_TM1_BAR:
12322dfa91a2SCédric Le Goater     case CQ_TM2_BAR:
12332dfa91a2SCédric Le Goater     case CQ_PC_BAR:
12342dfa91a2SCédric Le Goater     case CQ_PC_BARM:
12352dfa91a2SCédric Le Goater     case CQ_VC_BAR:
12362dfa91a2SCédric Le Goater     case CQ_VC_BARM:
12372dfa91a2SCédric Le Goater     case CQ_TAR:
12382dfa91a2SCédric Le Goater     case CQ_TDR:
12392dfa91a2SCédric Le Goater     case CQ_PBI_CTL:
12402dfa91a2SCédric Le Goater 
12412dfa91a2SCédric Le Goater     case PC_TCTXT_CFG:
12422dfa91a2SCédric Le Goater     case PC_TCTXT_TRACK:
12432dfa91a2SCédric Le Goater     case PC_TCTXT_INDIR0:
12442dfa91a2SCédric Le Goater     case PC_TCTXT_INDIR1:
12452dfa91a2SCédric Le Goater     case PC_TCTXT_INDIR2:
12462dfa91a2SCédric Le Goater     case PC_TCTXT_INDIR3:
12472dfa91a2SCédric Le Goater     case PC_GLOBAL_CONFIG:
12482dfa91a2SCédric Le Goater 
12492dfa91a2SCédric Le Goater     case PC_VPC_SCRUB_MASK:
12502dfa91a2SCédric Le Goater 
12512dfa91a2SCédric Le Goater     case VC_GLOBAL_CONFIG:
12522dfa91a2SCédric Le Goater     case VC_AIB_TX_ORDER_TAG2:
12532dfa91a2SCédric Le Goater 
12542dfa91a2SCédric Le Goater     case VC_IRQ_CONFIG_IPI:
12552dfa91a2SCédric Le Goater     case VC_IRQ_CONFIG_HW:
12562dfa91a2SCédric Le Goater     case VC_IRQ_CONFIG_CASCADE1:
12572dfa91a2SCédric Le Goater     case VC_IRQ_CONFIG_CASCADE2:
12582dfa91a2SCédric Le Goater     case VC_IRQ_CONFIG_REDIST:
12592dfa91a2SCédric Le Goater     case VC_IRQ_CONFIG_IPI_CASC:
12602dfa91a2SCédric Le Goater 
12612dfa91a2SCédric Le Goater     case VC_EQC_SCRUB_MASK:
12622dfa91a2SCédric Le Goater     case VC_IVC_SCRUB_MASK:
12632dfa91a2SCédric Le Goater     case VC_SBC_CONFIG:
12642dfa91a2SCédric Le Goater     case VC_AT_MACRO_KILL_MASK:
12652dfa91a2SCédric Le Goater     case VC_VSD_TABLE_ADDR:
12662dfa91a2SCédric Le Goater     case PC_VSD_TABLE_ADDR:
12672dfa91a2SCédric Le Goater     case VC_VSD_TABLE_DATA:
12682dfa91a2SCédric Le Goater     case PC_VSD_TABLE_DATA:
12692dfa91a2SCédric Le Goater     case PC_THREAD_EN_REG0:
12702dfa91a2SCédric Le Goater     case PC_THREAD_EN_REG1:
12712dfa91a2SCédric Le Goater         val = xive->regs[reg];
12722dfa91a2SCédric Le Goater         break;
12732dfa91a2SCédric Le Goater 
12742dfa91a2SCédric Le Goater     /*
12752dfa91a2SCédric Le Goater      * XIVE hardware thread enablement
12762dfa91a2SCédric Le Goater      */
12772dfa91a2SCédric Le Goater     case PC_THREAD_EN_REG0_SET:
12782dfa91a2SCédric Le Goater     case PC_THREAD_EN_REG0_CLR:
12792dfa91a2SCédric Le Goater         val = xive->regs[PC_THREAD_EN_REG0 >> 3];
12802dfa91a2SCédric Le Goater         break;
12812dfa91a2SCédric Le Goater     case PC_THREAD_EN_REG1_SET:
12822dfa91a2SCédric Le Goater     case PC_THREAD_EN_REG1_CLR:
12832dfa91a2SCédric Le Goater         val = xive->regs[PC_THREAD_EN_REG1 >> 3];
12842dfa91a2SCédric Le Goater         break;
12852dfa91a2SCédric Le Goater 
12862dfa91a2SCédric Le Goater     case CQ_MSGSND: /* Identifies which cores have msgsnd enabled. */
12872dfa91a2SCédric Le Goater         val = 0xffffff0000000000;
12882dfa91a2SCédric Le Goater         break;
12892dfa91a2SCédric Le Goater 
12902dfa91a2SCédric Le Goater     /*
12912dfa91a2SCédric Le Goater      * XIVE PC & VC cache updates for EAS, NVT and END
12922dfa91a2SCédric Le Goater      */
12930df68c7eSCédric Le Goater     case VC_EQC_CWATCH_SPEC:
12940df68c7eSCédric Le Goater         xive->regs[reg] = ~(VC_EQC_CWATCH_FULL | VC_EQC_CWATCH_CONFLICT);
12950df68c7eSCédric Le Goater         val = xive->regs[reg];
12960df68c7eSCédric Le Goater         break;
12970df68c7eSCédric Le Goater     case VC_EQC_CWATCH_DAT0:
12980df68c7eSCédric Le Goater         /*
12990df68c7eSCédric Le Goater          * Load DATA registers from cache with data requested by the
13000df68c7eSCédric Le Goater          * SPEC register
13010df68c7eSCédric Le Goater          */
13020df68c7eSCédric Le Goater         pnv_xive_end_cache_load(xive);
13030df68c7eSCédric Le Goater         val = xive->regs[reg];
13040df68c7eSCédric Le Goater         break;
13050df68c7eSCédric Le Goater     case VC_EQC_CWATCH_DAT1 ... VC_EQC_CWATCH_DAT3:
13060df68c7eSCédric Le Goater         val = xive->regs[reg];
13070df68c7eSCédric Le Goater         break;
13080df68c7eSCédric Le Goater 
13090df68c7eSCédric Le Goater     case PC_VPC_CWATCH_SPEC:
13100df68c7eSCédric Le Goater         xive->regs[reg] = ~(PC_VPC_CWATCH_FULL | PC_VPC_CWATCH_CONFLICT);
13110df68c7eSCédric Le Goater         val = xive->regs[reg];
13120df68c7eSCédric Le Goater         break;
13130df68c7eSCédric Le Goater     case PC_VPC_CWATCH_DAT0:
13140df68c7eSCédric Le Goater         /*
13150df68c7eSCédric Le Goater          * Load DATA registers from cache with data requested by the
13160df68c7eSCédric Le Goater          * SPEC register
13170df68c7eSCédric Le Goater          */
13180df68c7eSCédric Le Goater         pnv_xive_nvt_cache_load(xive);
13190df68c7eSCédric Le Goater         val = xive->regs[reg];
13200df68c7eSCédric Le Goater         break;
13210df68c7eSCédric Le Goater     case PC_VPC_CWATCH_DAT1 ... PC_VPC_CWATCH_DAT7:
13220df68c7eSCédric Le Goater         val = xive->regs[reg];
13230df68c7eSCédric Le Goater         break;
13240df68c7eSCédric Le Goater 
13252dfa91a2SCédric Le Goater     case PC_VPC_SCRUB_TRIG:
13262dfa91a2SCédric Le Goater     case VC_IVC_SCRUB_TRIG:
13272dfa91a2SCédric Le Goater     case VC_EQC_SCRUB_TRIG:
13282dfa91a2SCédric Le Goater         xive->regs[reg] &= ~VC_SCRUB_VALID;
13292dfa91a2SCédric Le Goater         val = xive->regs[reg];
13302dfa91a2SCédric Le Goater         break;
13312dfa91a2SCédric Le Goater 
13322dfa91a2SCédric Le Goater     /*
13332dfa91a2SCédric Le Goater      * XIVE PC & VC cache invalidation
13342dfa91a2SCédric Le Goater      */
13352dfa91a2SCédric Le Goater     case PC_AT_KILL:
13362dfa91a2SCédric Le Goater         xive->regs[reg] &= ~PC_AT_KILL_VALID;
13372dfa91a2SCédric Le Goater         val = xive->regs[reg];
13382dfa91a2SCédric Le Goater         break;
13392dfa91a2SCédric Le Goater     case VC_AT_MACRO_KILL:
13402dfa91a2SCédric Le Goater         xive->regs[reg] &= ~VC_KILL_VALID;
13412dfa91a2SCédric Le Goater         val = xive->regs[reg];
13422dfa91a2SCédric Le Goater         break;
13432dfa91a2SCédric Le Goater 
13442dfa91a2SCédric Le Goater     /*
13452dfa91a2SCédric Le Goater      * XIVE synchronisation
13462dfa91a2SCédric Le Goater      */
13472dfa91a2SCédric Le Goater     case VC_EQC_CONFIG:
13482dfa91a2SCédric Le Goater         val = VC_EQC_SYNC_MASK;
13492dfa91a2SCédric Le Goater         break;
13502dfa91a2SCédric Le Goater 
13512dfa91a2SCédric Le Goater     default:
13522dfa91a2SCédric Le Goater         xive_error(xive, "IC: invalid read reg=0x%"HWADDR_PRIx, offset);
13532dfa91a2SCédric Le Goater     }
13542dfa91a2SCédric Le Goater 
13552dfa91a2SCédric Le Goater     return val;
13562dfa91a2SCédric Le Goater }
13572dfa91a2SCédric Le Goater 
13582dfa91a2SCédric Le Goater static const MemoryRegionOps pnv_xive_ic_reg_ops = {
13592dfa91a2SCédric Le Goater     .read = pnv_xive_ic_reg_read,
13602dfa91a2SCédric Le Goater     .write = pnv_xive_ic_reg_write,
13612dfa91a2SCédric Le Goater     .endianness = DEVICE_BIG_ENDIAN,
13622dfa91a2SCédric Le Goater     .valid = {
13632dfa91a2SCédric Le Goater         .min_access_size = 8,
13642dfa91a2SCédric Le Goater         .max_access_size = 8,
13652dfa91a2SCédric Le Goater     },
13662dfa91a2SCédric Le Goater     .impl = {
13672dfa91a2SCédric Le Goater         .min_access_size = 8,
13682dfa91a2SCédric Le Goater         .max_access_size = 8,
13692dfa91a2SCédric Le Goater     },
13702dfa91a2SCédric Le Goater };
13712dfa91a2SCédric Le Goater 
13722dfa91a2SCédric Le Goater /*
13732dfa91a2SCédric Le Goater  * IC - Notify MMIO port page (write only)
13742dfa91a2SCédric Le Goater  */
13752dfa91a2SCédric Le Goater #define PNV_XIVE_FORWARD_IPI        0x800 /* Forward IPI */
13762dfa91a2SCédric Le Goater #define PNV_XIVE_FORWARD_HW         0x880 /* Forward HW */
13772dfa91a2SCédric Le Goater #define PNV_XIVE_FORWARD_OS_ESC     0x900 /* Forward OS escalation */
13782dfa91a2SCédric Le Goater #define PNV_XIVE_FORWARD_HW_ESC     0x980 /* Forward Hyp escalation */
13792dfa91a2SCédric Le Goater #define PNV_XIVE_FORWARD_REDIS      0xa00 /* Forward Redistribution */
13802dfa91a2SCédric Le Goater #define PNV_XIVE_RESERVED5          0xa80 /* Cache line 5 PowerBUS operation */
13812dfa91a2SCédric Le Goater #define PNV_XIVE_RESERVED6          0xb00 /* Cache line 6 PowerBUS operation */
13822dfa91a2SCédric Le Goater #define PNV_XIVE_RESERVED7          0xb80 /* Cache line 7 PowerBUS operation */
13832dfa91a2SCédric Le Goater 
13842dfa91a2SCédric Le Goater /* VC synchronisation */
13852dfa91a2SCédric Le Goater #define PNV_XIVE_SYNC_IPI           0xc00 /* Sync IPI */
13862dfa91a2SCédric Le Goater #define PNV_XIVE_SYNC_HW            0xc80 /* Sync HW */
13872dfa91a2SCédric Le Goater #define PNV_XIVE_SYNC_OS_ESC        0xd00 /* Sync OS escalation */
13882dfa91a2SCédric Le Goater #define PNV_XIVE_SYNC_HW_ESC        0xd80 /* Sync Hyp escalation */
13892dfa91a2SCédric Le Goater #define PNV_XIVE_SYNC_REDIS         0xe00 /* Sync Redistribution */
13902dfa91a2SCédric Le Goater 
13912dfa91a2SCédric Le Goater /* PC synchronisation */
13922dfa91a2SCédric Le Goater #define PNV_XIVE_SYNC_PULL          0xe80 /* Sync pull context */
13932dfa91a2SCédric Le Goater #define PNV_XIVE_SYNC_PUSH          0xf00 /* Sync push context */
13942dfa91a2SCédric Le Goater #define PNV_XIVE_SYNC_VPC           0xf80 /* Sync remove VPC store */
13952dfa91a2SCédric Le Goater 
pnv_xive_end_notify(XiveRouter * xrtr,XiveEAS * eas)1396f2c1e591SCédric Le Goater static void pnv_xive_end_notify(XiveRouter *xrtr, XiveEAS *eas)
1397f2c1e591SCédric Le Goater {
1398f2c1e591SCédric Le Goater     PnvXive *xive = PNV_XIVE(xrtr);
1399f2c1e591SCédric Le Goater     uint8_t end_blk = xive_get_field64(EAS_END_BLOCK, eas->w);
1400f2c1e591SCédric Le Goater     uint32_t end_idx = xive_get_field64(EAS_END_INDEX, eas->w);
1401f2c1e591SCédric Le Goater     uint32_t end_data = xive_get_field64(EAS_END_DATA, eas->w);
1402f2c1e591SCédric Le Goater     uint64_t end_vsd = xive->vsds[VST_TSEL_EQDT][end_blk];
1403f2c1e591SCédric Le Goater 
1404f2c1e591SCédric Le Goater     switch (GETFIELD(VSD_MODE, end_vsd)) {
1405f2c1e591SCédric Le Goater     case VSD_MODE_EXCLUSIVE:
1406f2c1e591SCédric Le Goater         /* Perform the END notification on the local IC. */
1407f2c1e591SCédric Le Goater         xive_router_end_notify(xrtr, eas);
1408f2c1e591SCédric Le Goater         break;
1409f2c1e591SCédric Le Goater 
1410f2c1e591SCédric Le Goater     case VSD_MODE_FORWARD: {
1411f2c1e591SCédric Le Goater         MemTxResult result;
1412f2c1e591SCédric Le Goater         uint64_t notif_port = end_vsd & VSD_ADDRESS_MASK;
1413f2c1e591SCédric Le Goater         uint64_t data = XIVE_TRIGGER_END | XIVE_TRIGGER_PQ |
1414f2c1e591SCédric Le Goater             be64_to_cpu(eas->w);
1415f2c1e591SCédric Le Goater 
1416f2c1e591SCédric Le Goater         /* Forward the store on the remote IC notify page. */
1417f2c1e591SCédric Le Goater         address_space_stq_be(&address_space_memory, notif_port, data,
1418f2c1e591SCédric Le Goater                              MEMTXATTRS_UNSPECIFIED, &result);
1419f2c1e591SCédric Le Goater         if (result != MEMTX_OK) {
1420f2c1e591SCédric Le Goater             xive_error(xive, "IC: Forward notif END %x/%x [%x] failed @%"
1421f2c1e591SCédric Le Goater                        HWADDR_PRIx, end_blk, end_idx, end_data, notif_port);
1422f2c1e591SCédric Le Goater             return;
1423f2c1e591SCédric Le Goater         }
1424f2c1e591SCédric Le Goater         break;
1425f2c1e591SCédric Le Goater     }
1426f2c1e591SCédric Le Goater 
1427f2c1e591SCédric Le Goater     case VSD_MODE_INVALID:
1428f2c1e591SCédric Le Goater     default:
1429f2c1e591SCédric Le Goater         /* Set FIR */
1430f2c1e591SCédric Le Goater         xive_error(xive, "IC: Invalid END VSD for block %x", end_blk);
1431f2c1e591SCédric Le Goater         return;
1432f2c1e591SCédric Le Goater     }
1433f2c1e591SCédric Le Goater }
1434f2c1e591SCédric Le Goater 
1435f2c1e591SCédric Le Goater /*
1436f2c1e591SCédric Le Goater  * The notify page can either be used to receive trigger events from
1437f2c1e591SCédric Le Goater  * the HW controllers (PHB, PSI) or to reroute interrupts between
1438f2c1e591SCédric Le Goater  * Interrupt controllers.
1439f2c1e591SCédric Le Goater  */
pnv_xive_ic_hw_trigger(PnvXive * xive,hwaddr addr,uint64_t val)14402dfa91a2SCédric Le Goater static void pnv_xive_ic_hw_trigger(PnvXive *xive, hwaddr addr, uint64_t val)
14412dfa91a2SCédric Le Goater {
1442106695abSCédric Le Goater     uint8_t blk;
1443106695abSCédric Le Goater     uint32_t idx;
1444106695abSCédric Le Goater 
14452cfc9f1aSCédric Le Goater     trace_pnv_xive_ic_hw_trigger(addr, val);
14462cfc9f1aSCédric Le Goater 
1447106695abSCédric Le Goater     if (val & XIVE_TRIGGER_END) {
1448f2c1e591SCédric Le Goater         val = cpu_to_be64(val);
1449f2c1e591SCédric Le Goater         pnv_xive_end_notify(XIVE_ROUTER(xive), (XiveEAS *) &val);
1450106695abSCédric Le Goater         return;
1451106695abSCédric Le Goater     }
1452106695abSCédric Le Goater 
14532dfa91a2SCédric Le Goater     /*
14542dfa91a2SCédric Le Goater      * Forward the source event notification directly to the Router.
14552dfa91a2SCédric Le Goater      * The source interrupt number should already be correctly encoded
14562dfa91a2SCédric Le Goater      * with the chip block id by the sending device (PHB, PSI).
14572dfa91a2SCédric Le Goater      */
1458106695abSCédric Le Goater     blk = XIVE_EAS_BLOCK(val);
1459106695abSCédric Le Goater     idx = XIVE_EAS_INDEX(val);
1460106695abSCédric Le Goater 
14610aa2612aSCédric Le Goater     xive_router_notify(XIVE_NOTIFIER(xive), XIVE_EAS(blk, idx),
14620aa2612aSCédric Le Goater                        !!(val & XIVE_TRIGGER_PQ));
14632dfa91a2SCédric Le Goater }
14642dfa91a2SCédric Le Goater 
pnv_xive_ic_notify_write(void * opaque,hwaddr addr,uint64_t val,unsigned size)14652dfa91a2SCédric Le Goater static void pnv_xive_ic_notify_write(void *opaque, hwaddr addr, uint64_t val,
14662dfa91a2SCédric Le Goater                                      unsigned size)
14672dfa91a2SCédric Le Goater {
14682dfa91a2SCédric Le Goater     PnvXive *xive = PNV_XIVE(opaque);
14692dfa91a2SCédric Le Goater 
14702dfa91a2SCédric Le Goater     /* VC: HW triggers */
14712dfa91a2SCédric Le Goater     switch (addr) {
14722dfa91a2SCédric Le Goater     case 0x000 ... 0x7FF:
14732dfa91a2SCédric Le Goater         pnv_xive_ic_hw_trigger(opaque, addr, val);
14742dfa91a2SCédric Le Goater         break;
14752dfa91a2SCédric Le Goater 
14762dfa91a2SCédric Le Goater     /* VC: Forwarded IRQs */
14772dfa91a2SCédric Le Goater     case PNV_XIVE_FORWARD_IPI:
14782dfa91a2SCédric Le Goater     case PNV_XIVE_FORWARD_HW:
14792dfa91a2SCédric Le Goater     case PNV_XIVE_FORWARD_OS_ESC:
14802dfa91a2SCédric Le Goater     case PNV_XIVE_FORWARD_HW_ESC:
14812dfa91a2SCédric Le Goater     case PNV_XIVE_FORWARD_REDIS:
14822dfa91a2SCédric Le Goater         /* TODO: forwarded IRQs. Should be like HW triggers */
14832dfa91a2SCédric Le Goater         xive_error(xive, "IC: forwarded at @0x%"HWADDR_PRIx" IRQ 0x%"PRIx64,
14842dfa91a2SCédric Le Goater                    addr, val);
14852dfa91a2SCédric Le Goater         break;
14862dfa91a2SCédric Le Goater 
14872dfa91a2SCédric Le Goater     /* VC syncs */
14882dfa91a2SCédric Le Goater     case PNV_XIVE_SYNC_IPI:
14892dfa91a2SCédric Le Goater     case PNV_XIVE_SYNC_HW:
14902dfa91a2SCédric Le Goater     case PNV_XIVE_SYNC_OS_ESC:
14912dfa91a2SCédric Le Goater     case PNV_XIVE_SYNC_HW_ESC:
14922dfa91a2SCédric Le Goater     case PNV_XIVE_SYNC_REDIS:
14932dfa91a2SCédric Le Goater         break;
14942dfa91a2SCédric Le Goater 
14952dfa91a2SCédric Le Goater     /* PC syncs */
14962dfa91a2SCédric Le Goater     case PNV_XIVE_SYNC_PULL:
14972dfa91a2SCédric Le Goater     case PNV_XIVE_SYNC_PUSH:
14982dfa91a2SCédric Le Goater     case PNV_XIVE_SYNC_VPC:
14992dfa91a2SCédric Le Goater         break;
15002dfa91a2SCédric Le Goater 
15012dfa91a2SCédric Le Goater     default:
15022dfa91a2SCédric Le Goater         xive_error(xive, "IC: invalid notify write @%"HWADDR_PRIx, addr);
15032dfa91a2SCédric Le Goater     }
15042dfa91a2SCédric Le Goater }
15052dfa91a2SCédric Le Goater 
pnv_xive_ic_notify_read(void * opaque,hwaddr addr,unsigned size)15062dfa91a2SCédric Le Goater static uint64_t pnv_xive_ic_notify_read(void *opaque, hwaddr addr,
15072dfa91a2SCédric Le Goater                                         unsigned size)
15082dfa91a2SCédric Le Goater {
15092dfa91a2SCédric Le Goater     PnvXive *xive = PNV_XIVE(opaque);
15102dfa91a2SCédric Le Goater 
15112dfa91a2SCédric Le Goater     /* loads are invalid */
15122dfa91a2SCédric Le Goater     xive_error(xive, "IC: invalid notify read @%"HWADDR_PRIx, addr);
15132dfa91a2SCédric Le Goater     return -1;
15142dfa91a2SCédric Le Goater }
15152dfa91a2SCédric Le Goater 
15162dfa91a2SCédric Le Goater static const MemoryRegionOps pnv_xive_ic_notify_ops = {
15172dfa91a2SCédric Le Goater     .read = pnv_xive_ic_notify_read,
15182dfa91a2SCédric Le Goater     .write = pnv_xive_ic_notify_write,
15192dfa91a2SCédric Le Goater     .endianness = DEVICE_BIG_ENDIAN,
15202dfa91a2SCédric Le Goater     .valid = {
15212dfa91a2SCédric Le Goater         .min_access_size = 8,
15222dfa91a2SCédric Le Goater         .max_access_size = 8,
15232dfa91a2SCédric Le Goater     },
15242dfa91a2SCédric Le Goater     .impl = {
15252dfa91a2SCédric Le Goater         .min_access_size = 8,
15262dfa91a2SCédric Le Goater         .max_access_size = 8,
15272dfa91a2SCédric Le Goater     },
15282dfa91a2SCédric Le Goater };
15292dfa91a2SCédric Le Goater 
15302dfa91a2SCédric Le Goater /*
15312dfa91a2SCédric Le Goater  * IC - LSI MMIO handlers (not modeled)
15322dfa91a2SCédric Le Goater  */
15332dfa91a2SCédric Le Goater 
pnv_xive_ic_lsi_write(void * opaque,hwaddr addr,uint64_t val,unsigned size)15342dfa91a2SCédric Le Goater static void pnv_xive_ic_lsi_write(void *opaque, hwaddr addr,
15352dfa91a2SCédric Le Goater                               uint64_t val, unsigned size)
15362dfa91a2SCédric Le Goater {
15372dfa91a2SCédric Le Goater     PnvXive *xive = PNV_XIVE(opaque);
15382dfa91a2SCédric Le Goater 
15392dfa91a2SCédric Le Goater     xive_error(xive, "IC: LSI invalid write @%"HWADDR_PRIx, addr);
15402dfa91a2SCédric Le Goater }
15412dfa91a2SCédric Le Goater 
pnv_xive_ic_lsi_read(void * opaque,hwaddr addr,unsigned size)15422dfa91a2SCédric Le Goater static uint64_t pnv_xive_ic_lsi_read(void *opaque, hwaddr addr, unsigned size)
15432dfa91a2SCédric Le Goater {
15442dfa91a2SCédric Le Goater     PnvXive *xive = PNV_XIVE(opaque);
15452dfa91a2SCédric Le Goater 
15462dfa91a2SCédric Le Goater     xive_error(xive, "IC: LSI invalid read @%"HWADDR_PRIx, addr);
15472dfa91a2SCédric Le Goater     return -1;
15482dfa91a2SCédric Le Goater }
15492dfa91a2SCédric Le Goater 
15502dfa91a2SCédric Le Goater static const MemoryRegionOps pnv_xive_ic_lsi_ops = {
15512dfa91a2SCédric Le Goater     .read = pnv_xive_ic_lsi_read,
15522dfa91a2SCédric Le Goater     .write = pnv_xive_ic_lsi_write,
15532dfa91a2SCédric Le Goater     .endianness = DEVICE_BIG_ENDIAN,
15542dfa91a2SCédric Le Goater     .valid = {
15552dfa91a2SCédric Le Goater         .min_access_size = 8,
15562dfa91a2SCédric Le Goater         .max_access_size = 8,
15572dfa91a2SCédric Le Goater     },
15582dfa91a2SCédric Le Goater     .impl = {
15592dfa91a2SCédric Le Goater         .min_access_size = 8,
15602dfa91a2SCédric Le Goater         .max_access_size = 8,
15612dfa91a2SCédric Le Goater     },
15622dfa91a2SCédric Le Goater };
15632dfa91a2SCédric Le Goater 
15642dfa91a2SCédric Le Goater /*
15652dfa91a2SCédric Le Goater  * IC - Indirect TIMA MMIO handlers
15662dfa91a2SCédric Le Goater  */
15672dfa91a2SCédric Le Goater 
15682dfa91a2SCédric Le Goater /*
1569119eaa9dSCédric Le Goater  * When the TIMA is accessed from the indirect page, the thread id of
1570119eaa9dSCédric Le Goater  * the target CPU is configured in the PC_TCTXT_INDIR0 register before
1571119eaa9dSCédric Le Goater  * use. This is used for resets and for debug purpose also.
15722dfa91a2SCédric Le Goater  */
pnv_xive_get_indirect_tctx(PnvXive * xive)15732dfa91a2SCédric Le Goater static XiveTCTX *pnv_xive_get_indirect_tctx(PnvXive *xive)
15742dfa91a2SCédric Le Goater {
1575119eaa9dSCédric Le Goater     PnvChip *chip = xive->chip;
15762dfa91a2SCédric Le Goater     uint64_t tctxt_indir = xive->regs[PC_TCTXT_INDIR0 >> 3];
15772dfa91a2SCédric Le Goater     PowerPCCPU *cpu = NULL;
15782dfa91a2SCédric Le Goater     int pir;
15792dfa91a2SCédric Le Goater 
15802dfa91a2SCédric Le Goater     if (!(tctxt_indir & PC_TCTXT_INDIR_VALID)) {
15812dfa91a2SCédric Le Goater         xive_error(xive, "IC: no indirect TIMA access in progress");
15822dfa91a2SCédric Le Goater         return NULL;
15832dfa91a2SCédric Le Goater     }
15842dfa91a2SCédric Le Goater 
1585119eaa9dSCédric Le Goater     pir = (chip->chip_id << 8) | GETFIELD(PC_TCTXT_INDIR_THRDID, tctxt_indir);
1586119eaa9dSCédric Le Goater     cpu = pnv_chip_find_cpu(chip, pir);
15872dfa91a2SCédric Le Goater     if (!cpu) {
15882dfa91a2SCédric Le Goater         xive_error(xive, "IC: invalid PIR %x for indirect access", pir);
15892dfa91a2SCédric Le Goater         return NULL;
15902dfa91a2SCédric Le Goater     }
15912dfa91a2SCédric Le Goater 
15922dfa91a2SCédric Le Goater     /* Check that HW thread is XIVE enabled */
1593119eaa9dSCédric Le Goater     if (!pnv_xive_is_cpu_enabled(xive, cpu)) {
15942dfa91a2SCédric Le Goater         xive_error(xive, "IC: CPU %x is not enabled", pir);
15952dfa91a2SCédric Le Goater     }
15962dfa91a2SCédric Le Goater 
15972dfa91a2SCédric Le Goater     return XIVE_TCTX(pnv_cpu_state(cpu)->intc);
15982dfa91a2SCédric Le Goater }
15992dfa91a2SCédric Le Goater 
xive_tm_indirect_write(void * opaque,hwaddr offset,uint64_t value,unsigned size)16002dfa91a2SCédric Le Goater static void xive_tm_indirect_write(void *opaque, hwaddr offset,
16012dfa91a2SCédric Le Goater                                    uint64_t value, unsigned size)
16022dfa91a2SCédric Le Goater {
16032dfa91a2SCédric Le Goater     XiveTCTX *tctx = pnv_xive_get_indirect_tctx(PNV_XIVE(opaque));
16042dfa91a2SCédric Le Goater 
16054fb42350SCédric Le Goater     xive_tctx_tm_write(XIVE_PRESENTER(opaque), tctx, offset, value, size);
16062dfa91a2SCédric Le Goater }
16072dfa91a2SCédric Le Goater 
xive_tm_indirect_read(void * opaque,hwaddr offset,unsigned size)16082dfa91a2SCédric Le Goater static uint64_t xive_tm_indirect_read(void *opaque, hwaddr offset,
16092dfa91a2SCédric Le Goater                                       unsigned size)
16102dfa91a2SCédric Le Goater {
16112dfa91a2SCédric Le Goater     XiveTCTX *tctx = pnv_xive_get_indirect_tctx(PNV_XIVE(opaque));
16122dfa91a2SCédric Le Goater 
16134fb42350SCédric Le Goater     return xive_tctx_tm_read(XIVE_PRESENTER(opaque), tctx, offset, size);
16142dfa91a2SCédric Le Goater }
16152dfa91a2SCédric Le Goater 
16162dfa91a2SCédric Le Goater static const MemoryRegionOps xive_tm_indirect_ops = {
16172dfa91a2SCédric Le Goater     .read = xive_tm_indirect_read,
16182dfa91a2SCédric Le Goater     .write = xive_tm_indirect_write,
16192dfa91a2SCédric Le Goater     .endianness = DEVICE_BIG_ENDIAN,
16202dfa91a2SCédric Le Goater     .valid = {
16212dfa91a2SCédric Le Goater         .min_access_size = 1,
16222dfa91a2SCédric Le Goater         .max_access_size = 8,
16232dfa91a2SCédric Le Goater     },
16242dfa91a2SCédric Le Goater     .impl = {
16252dfa91a2SCédric Le Goater         .min_access_size = 1,
16262dfa91a2SCédric Le Goater         .max_access_size = 8,
16272dfa91a2SCédric Le Goater     },
16282dfa91a2SCédric Le Goater };
16292dfa91a2SCédric Le Goater 
pnv_xive_tm_write(void * opaque,hwaddr offset,uint64_t value,unsigned size)1630d024a2c1SCédric Le Goater static void pnv_xive_tm_write(void *opaque, hwaddr offset,
1631d024a2c1SCédric Le Goater                               uint64_t value, unsigned size)
1632d024a2c1SCédric Le Goater {
1633d024a2c1SCédric Le Goater     PowerPCCPU *cpu = POWERPC_CPU(current_cpu);
1634d024a2c1SCédric Le Goater     PnvXive *xive = pnv_xive_tm_get_xive(cpu);
1635d024a2c1SCédric Le Goater     XiveTCTX *tctx = XIVE_TCTX(pnv_cpu_state(cpu)->intc);
1636d024a2c1SCédric Le Goater 
1637d024a2c1SCédric Le Goater     xive_tctx_tm_write(XIVE_PRESENTER(xive), tctx, offset, value, size);
1638d024a2c1SCédric Le Goater }
1639d024a2c1SCédric Le Goater 
pnv_xive_tm_read(void * opaque,hwaddr offset,unsigned size)1640d024a2c1SCédric Le Goater static uint64_t pnv_xive_tm_read(void *opaque, hwaddr offset, unsigned size)
1641d024a2c1SCédric Le Goater {
1642d024a2c1SCédric Le Goater     PowerPCCPU *cpu = POWERPC_CPU(current_cpu);
1643d024a2c1SCédric Le Goater     PnvXive *xive = pnv_xive_tm_get_xive(cpu);
1644d024a2c1SCédric Le Goater     XiveTCTX *tctx = XIVE_TCTX(pnv_cpu_state(cpu)->intc);
1645d024a2c1SCédric Le Goater 
1646d024a2c1SCédric Le Goater     return xive_tctx_tm_read(XIVE_PRESENTER(xive), tctx, offset, size);
1647d024a2c1SCédric Le Goater }
1648d024a2c1SCédric Le Goater 
1649d024a2c1SCédric Le Goater const MemoryRegionOps pnv_xive_tm_ops = {
1650d024a2c1SCédric Le Goater     .read = pnv_xive_tm_read,
1651d024a2c1SCédric Le Goater     .write = pnv_xive_tm_write,
1652d024a2c1SCédric Le Goater     .endianness = DEVICE_BIG_ENDIAN,
1653d024a2c1SCédric Le Goater     .valid = {
1654d024a2c1SCédric Le Goater         .min_access_size = 1,
1655d024a2c1SCédric Le Goater         .max_access_size = 8,
1656d024a2c1SCédric Le Goater     },
1657d024a2c1SCédric Le Goater     .impl = {
1658d024a2c1SCédric Le Goater         .min_access_size = 1,
1659d024a2c1SCédric Le Goater         .max_access_size = 8,
1660d024a2c1SCédric Le Goater     },
1661d024a2c1SCédric Le Goater };
1662d024a2c1SCédric Le Goater 
16632dfa91a2SCédric Le Goater /*
16642dfa91a2SCédric Le Goater  * Interrupt controller XSCOM region.
16652dfa91a2SCédric Le Goater  */
pnv_xive_xscom_read(void * opaque,hwaddr addr,unsigned size)16662dfa91a2SCédric Le Goater static uint64_t pnv_xive_xscom_read(void *opaque, hwaddr addr, unsigned size)
16672dfa91a2SCédric Le Goater {
16682dfa91a2SCédric Le Goater     switch (addr >> 3) {
16692dfa91a2SCédric Le Goater     case X_VC_EQC_CONFIG:
16702dfa91a2SCédric Le Goater         /* FIXME (skiboot): This is the only XSCOM load. Bizarre. */
16712dfa91a2SCédric Le Goater         return VC_EQC_SYNC_MASK;
16722dfa91a2SCédric Le Goater     default:
16732dfa91a2SCédric Le Goater         return pnv_xive_ic_reg_read(opaque, addr, size);
16742dfa91a2SCédric Le Goater     }
16752dfa91a2SCédric Le Goater }
16762dfa91a2SCédric Le Goater 
pnv_xive_xscom_write(void * opaque,hwaddr addr,uint64_t val,unsigned size)16772dfa91a2SCédric Le Goater static void pnv_xive_xscom_write(void *opaque, hwaddr addr,
16782dfa91a2SCédric Le Goater                                 uint64_t val, unsigned size)
16792dfa91a2SCédric Le Goater {
16802dfa91a2SCédric Le Goater     pnv_xive_ic_reg_write(opaque, addr, val, size);
16812dfa91a2SCédric Le Goater }
16822dfa91a2SCédric Le Goater 
16832dfa91a2SCédric Le Goater static const MemoryRegionOps pnv_xive_xscom_ops = {
16842dfa91a2SCédric Le Goater     .read = pnv_xive_xscom_read,
16852dfa91a2SCédric Le Goater     .write = pnv_xive_xscom_write,
16862dfa91a2SCédric Le Goater     .endianness = DEVICE_BIG_ENDIAN,
16872dfa91a2SCédric Le Goater     .valid = {
16882dfa91a2SCédric Le Goater         .min_access_size = 8,
16892dfa91a2SCédric Le Goater         .max_access_size = 8,
16902dfa91a2SCédric Le Goater     },
16912dfa91a2SCédric Le Goater     .impl = {
16922dfa91a2SCédric Le Goater         .min_access_size = 8,
16932dfa91a2SCédric Le Goater         .max_access_size = 8,
16942dfa91a2SCédric Le Goater     }
16952dfa91a2SCédric Le Goater };
16962dfa91a2SCédric Le Goater 
16972dfa91a2SCédric Le Goater /*
16982dfa91a2SCédric Le Goater  * Virtualization Controller MMIO region containing the IPI and END ESB pages
16992dfa91a2SCédric Le Goater  */
pnv_xive_vc_read(void * opaque,hwaddr offset,unsigned size)17002dfa91a2SCédric Le Goater static uint64_t pnv_xive_vc_read(void *opaque, hwaddr offset,
17012dfa91a2SCédric Le Goater                                  unsigned size)
17022dfa91a2SCédric Le Goater {
17032dfa91a2SCédric Le Goater     PnvXive *xive = PNV_XIVE(opaque);
17042dfa91a2SCédric Le Goater     uint64_t edt_index = offset >> pnv_xive_edt_shift(xive);
17052dfa91a2SCédric Le Goater     uint64_t edt_type = 0;
17062dfa91a2SCédric Le Goater     uint64_t edt_offset;
17072dfa91a2SCédric Le Goater     MemTxResult result;
17082dfa91a2SCédric Le Goater     AddressSpace *edt_as = NULL;
17092dfa91a2SCédric Le Goater     uint64_t ret = -1;
17102dfa91a2SCédric Le Goater 
17112dfa91a2SCédric Le Goater     if (edt_index < XIVE_TABLE_EDT_MAX) {
17122dfa91a2SCédric Le Goater         edt_type = GETFIELD(CQ_TDR_EDT_TYPE, xive->edt[edt_index]);
17132dfa91a2SCédric Le Goater     }
17142dfa91a2SCédric Le Goater 
17152dfa91a2SCédric Le Goater     switch (edt_type) {
17162dfa91a2SCédric Le Goater     case CQ_TDR_EDT_IPI:
17172dfa91a2SCédric Le Goater         edt_as = &xive->ipi_as;
17182dfa91a2SCédric Le Goater         break;
17192dfa91a2SCédric Le Goater     case CQ_TDR_EDT_EQ:
17202dfa91a2SCédric Le Goater         edt_as = &xive->end_as;
17212dfa91a2SCédric Le Goater         break;
17222dfa91a2SCédric Le Goater     default:
17232dfa91a2SCédric Le Goater         xive_error(xive, "VC: invalid EDT type for read @%"HWADDR_PRIx, offset);
17242dfa91a2SCédric Le Goater         return -1;
17252dfa91a2SCédric Le Goater     }
17262dfa91a2SCédric Le Goater 
17272dfa91a2SCédric Le Goater     /* Remap the offset for the targeted address space */
17282dfa91a2SCédric Le Goater     edt_offset = pnv_xive_edt_offset(xive, offset, edt_type);
17292dfa91a2SCédric Le Goater 
17302dfa91a2SCédric Le Goater     ret = address_space_ldq(edt_as, edt_offset, MEMTXATTRS_UNSPECIFIED,
17312dfa91a2SCédric Le Goater                             &result);
17322dfa91a2SCédric Le Goater 
17332dfa91a2SCédric Le Goater     if (result != MEMTX_OK) {
17342dfa91a2SCédric Le Goater         xive_error(xive, "VC: %s read failed at @0x%"HWADDR_PRIx " -> @0x%"
17352dfa91a2SCédric Le Goater                    HWADDR_PRIx, edt_type == CQ_TDR_EDT_IPI ? "IPI" : "END",
17362dfa91a2SCédric Le Goater                    offset, edt_offset);
17372dfa91a2SCédric Le Goater         return -1;
17382dfa91a2SCédric Le Goater     }
17392dfa91a2SCédric Le Goater 
17402dfa91a2SCédric Le Goater     return ret;
17412dfa91a2SCédric Le Goater }
17422dfa91a2SCédric Le Goater 
pnv_xive_vc_write(void * opaque,hwaddr offset,uint64_t val,unsigned size)17432dfa91a2SCédric Le Goater static void pnv_xive_vc_write(void *opaque, hwaddr offset,
17442dfa91a2SCédric Le Goater                               uint64_t val, unsigned size)
17452dfa91a2SCédric Le Goater {
17462dfa91a2SCédric Le Goater     PnvXive *xive = PNV_XIVE(opaque);
17472dfa91a2SCédric Le Goater     uint64_t edt_index = offset >> pnv_xive_edt_shift(xive);
17482dfa91a2SCédric Le Goater     uint64_t edt_type = 0;
17492dfa91a2SCédric Le Goater     uint64_t edt_offset;
17502dfa91a2SCédric Le Goater     MemTxResult result;
17512dfa91a2SCédric Le Goater     AddressSpace *edt_as = NULL;
17522dfa91a2SCédric Le Goater 
17532dfa91a2SCédric Le Goater     if (edt_index < XIVE_TABLE_EDT_MAX) {
17542dfa91a2SCédric Le Goater         edt_type = GETFIELD(CQ_TDR_EDT_TYPE, xive->edt[edt_index]);
17552dfa91a2SCédric Le Goater     }
17562dfa91a2SCédric Le Goater 
17572dfa91a2SCédric Le Goater     switch (edt_type) {
17582dfa91a2SCédric Le Goater     case CQ_TDR_EDT_IPI:
17592dfa91a2SCédric Le Goater         edt_as = &xive->ipi_as;
17602dfa91a2SCédric Le Goater         break;
17612dfa91a2SCédric Le Goater     case CQ_TDR_EDT_EQ:
17622dfa91a2SCédric Le Goater         edt_as = &xive->end_as;
17632dfa91a2SCédric Le Goater         break;
17642dfa91a2SCédric Le Goater     default:
17652dfa91a2SCédric Le Goater         xive_error(xive, "VC: invalid EDT type for write @%"HWADDR_PRIx,
17662dfa91a2SCédric Le Goater                    offset);
17672dfa91a2SCédric Le Goater         return;
17682dfa91a2SCédric Le Goater     }
17692dfa91a2SCédric Le Goater 
17702dfa91a2SCédric Le Goater     /* Remap the offset for the targeted address space */
17712dfa91a2SCédric Le Goater     edt_offset = pnv_xive_edt_offset(xive, offset, edt_type);
17722dfa91a2SCédric Le Goater 
17732dfa91a2SCédric Le Goater     address_space_stq(edt_as, edt_offset, val, MEMTXATTRS_UNSPECIFIED, &result);
17742dfa91a2SCédric Le Goater     if (result != MEMTX_OK) {
17752dfa91a2SCédric Le Goater         xive_error(xive, "VC: write failed at @0x%"HWADDR_PRIx, edt_offset);
17762dfa91a2SCédric Le Goater     }
17772dfa91a2SCédric Le Goater }
17782dfa91a2SCédric Le Goater 
17792dfa91a2SCédric Le Goater static const MemoryRegionOps pnv_xive_vc_ops = {
17802dfa91a2SCédric Le Goater     .read = pnv_xive_vc_read,
17812dfa91a2SCédric Le Goater     .write = pnv_xive_vc_write,
17822dfa91a2SCédric Le Goater     .endianness = DEVICE_BIG_ENDIAN,
17832dfa91a2SCédric Le Goater     .valid = {
17842dfa91a2SCédric Le Goater         .min_access_size = 8,
17852dfa91a2SCédric Le Goater         .max_access_size = 8,
17862dfa91a2SCédric Le Goater     },
17872dfa91a2SCédric Le Goater     .impl = {
17882dfa91a2SCédric Le Goater         .min_access_size = 8,
17892dfa91a2SCédric Le Goater         .max_access_size = 8,
17902dfa91a2SCédric Le Goater     },
17912dfa91a2SCédric Le Goater };
17922dfa91a2SCédric Le Goater 
17932dfa91a2SCédric Le Goater /*
1794b68147b7SCédric Le Goater  * Presenter Controller MMIO region. Points to the NVT sets.
1795b68147b7SCédric Le Goater  *
1796b68147b7SCédric Le Goater  * HW implements all possible mem ops to the underlying NVT structure
1797b68147b7SCédric Le Goater  * but QEMU does not need to be so precise. The model implementation
1798b68147b7SCédric Le Goater  * simply returns the RAM address of the NVT structure which is then
1799b68147b7SCédric Le Goater  * used by pnv_xive_vst_write/read to perform the RAM operation.
18002dfa91a2SCédric Le Goater  */
pnv_xive_pc_read(void * opaque,hwaddr offset,unsigned size)1801b68147b7SCédric Le Goater static uint64_t pnv_xive_pc_read(void *opaque, hwaddr offset, unsigned size)
18022dfa91a2SCédric Le Goater {
18032dfa91a2SCédric Le Goater     PnvXive *xive = PNV_XIVE(opaque);
1804b68147b7SCédric Le Goater     uint32_t nvt_idx = offset >> xive->pc_shift;
1805b68147b7SCédric Le Goater     uint8_t blk = pnv_xive_block_id(xive); /* TODO: VDT -> block xlate */
18062dfa91a2SCédric Le Goater 
1807b68147b7SCédric Le Goater     return pnv_xive_vst_addr(xive, VST_TSEL_VPDT, blk, nvt_idx);
18082dfa91a2SCédric Le Goater }
18092dfa91a2SCédric Le Goater 
pnv_xive_pc_write(void * opaque,hwaddr addr,uint64_t value,unsigned size)18102dfa91a2SCédric Le Goater static void pnv_xive_pc_write(void *opaque, hwaddr addr,
18112dfa91a2SCédric Le Goater                               uint64_t value, unsigned size)
18122dfa91a2SCédric Le Goater {
18132dfa91a2SCédric Le Goater     PnvXive *xive = PNV_XIVE(opaque);
18142dfa91a2SCédric Le Goater 
18152dfa91a2SCédric Le Goater     xive_error(xive, "PC: invalid write to VC @%"HWADDR_PRIx, addr);
18162dfa91a2SCédric Le Goater }
18172dfa91a2SCédric Le Goater 
18182dfa91a2SCédric Le Goater static const MemoryRegionOps pnv_xive_pc_ops = {
18192dfa91a2SCédric Le Goater     .read = pnv_xive_pc_read,
18202dfa91a2SCédric Le Goater     .write = pnv_xive_pc_write,
18212dfa91a2SCédric Le Goater     .endianness = DEVICE_BIG_ENDIAN,
18222dfa91a2SCédric Le Goater     .valid = {
18232dfa91a2SCédric Le Goater         .min_access_size = 8,
18242dfa91a2SCédric Le Goater         .max_access_size = 8,
18252dfa91a2SCédric Le Goater     },
18262dfa91a2SCédric Le Goater     .impl = {
18272dfa91a2SCédric Le Goater         .min_access_size = 8,
18282dfa91a2SCédric Le Goater         .max_access_size = 8,
18292dfa91a2SCédric Le Goater     },
18302dfa91a2SCédric Le Goater };
18312dfa91a2SCédric Le Goater 
xive_nvt_pic_print_info(XiveNVT * nvt,uint32_t nvt_idx,GString * buf)1832d302e000SCédric Le Goater static void xive_nvt_pic_print_info(XiveNVT *nvt, uint32_t nvt_idx,
18331a40b0caSPhilippe Mathieu-Daudé                                     GString *buf)
1834d302e000SCédric Le Goater {
1835d302e000SCédric Le Goater     uint8_t  eq_blk = xive_get_field32(NVT_W1_EQ_BLOCK, nvt->w1);
1836d302e000SCédric Le Goater     uint32_t eq_idx = xive_get_field32(NVT_W1_EQ_INDEX, nvt->w1);
1837d302e000SCédric Le Goater 
1838d302e000SCédric Le Goater     if (!xive_nvt_is_valid(nvt)) {
1839d302e000SCédric Le Goater         return;
1840d302e000SCédric Le Goater     }
1841d302e000SCédric Le Goater 
18421a40b0caSPhilippe Mathieu-Daudé     g_string_append_printf(buf, "  %08x end:%02x/%04x IPB:%02x\n",
18431a40b0caSPhilippe Mathieu-Daudé                            nvt_idx, eq_blk, eq_idx,
1844d302e000SCédric Le Goater                            xive_get_field32(NVT_W4_IPB, nvt->w4));
1845d302e000SCédric Le Goater }
1846d302e000SCédric Le Goater 
pnv_xive_pic_print_info(PnvXive * xive,GString * buf)1847*0527563aSPhilippe Mathieu-Daudé void pnv_xive_pic_print_info(PnvXive *xive, GString *buf)
18482dfa91a2SCédric Le Goater {
18492dfa91a2SCédric Le Goater     XiveRouter *xrtr = XIVE_ROUTER(xive);
1850dc2526e4SCédric Le Goater     uint8_t blk = pnv_xive_block_id(xive);
1851dc2526e4SCédric Le Goater     uint8_t chip_id = xive->chip->chip_id;
1852106695abSCédric Le Goater     uint32_t srcno0 = XIVE_EAS(blk, 0);
18537aa22e18SCédric Le Goater     uint32_t nr_ipis = pnv_xive_nr_ipis(xive, blk);
18542dfa91a2SCédric Le Goater     XiveEAS eas;
18552dfa91a2SCédric Le Goater     XiveEND end;
1856d302e000SCédric Le Goater     XiveNVT nvt;
18572dfa91a2SCédric Le Goater     int i;
1858d302e000SCédric Le Goater     uint64_t xive_nvt_per_subpage;
18592dfa91a2SCédric Le Goater 
1860b71a3f67SPhilippe Mathieu-Daudé     g_string_append_printf(buf, "XIVE[%x] #%d Source %08x .. %08x\n",
1861b71a3f67SPhilippe Mathieu-Daudé                            chip_id, blk, srcno0, srcno0 + nr_ipis - 1);
1862b71a3f67SPhilippe Mathieu-Daudé     xive_source_pic_print_info(&xive->ipi_source, srcno0, buf);
18632dfa91a2SCédric Le Goater 
1864bc8c553bSPhilippe Mathieu-Daudé     g_string_append_printf(buf, "XIVE[%x] #%d EAT %08x .. %08x\n",
1865bc8c553bSPhilippe Mathieu-Daudé                            chip_id, blk, srcno0, srcno0 + nr_ipis - 1);
18662dfa91a2SCédric Le Goater     for (i = 0; i < nr_ipis; i++) {
18672dfa91a2SCédric Le Goater         if (xive_router_get_eas(xrtr, blk, i, &eas)) {
18682dfa91a2SCédric Le Goater             break;
18692dfa91a2SCédric Le Goater         }
18702dfa91a2SCédric Le Goater         if (!xive_eas_is_masked(&eas)) {
1871bc8c553bSPhilippe Mathieu-Daudé             xive_eas_pic_print_info(&eas, i, buf);
18722dfa91a2SCédric Le Goater         }
18732dfa91a2SCédric Le Goater     }
18742dfa91a2SCédric Le Goater 
1875f1bca2caSPhilippe Mathieu-Daudé     g_string_append_printf(buf, "XIVE[%x] #%d ENDT\n", chip_id, blk);
18767aa22e18SCédric Le Goater     i = 0;
18777aa22e18SCédric Le Goater     while (!xive_router_get_end(xrtr, blk, i, &end)) {
1878f1bca2caSPhilippe Mathieu-Daudé         xive_end_pic_print_info(&end, i++, buf);
18792dfa91a2SCédric Le Goater     }
1880c5e760e0SCédric Le Goater 
18813d1e062cSPhilippe Mathieu-Daudé     g_string_append_printf(buf, "XIVE[%x] #%d END Escalation EAT\n",
18823d1e062cSPhilippe Mathieu-Daudé                            chip_id, blk);
18837aa22e18SCédric Le Goater     i = 0;
18847aa22e18SCédric Le Goater     while (!xive_router_get_end(xrtr, blk, i, &end)) {
18853d1e062cSPhilippe Mathieu-Daudé         xive_end_eas_pic_print_info(&end, i++, buf);
1886c5e760e0SCédric Le Goater     }
1887d302e000SCédric Le Goater 
18881a40b0caSPhilippe Mathieu-Daudé     g_string_append_printf(buf, "XIVE[%x] #%d NVTT %08x .. %08x\n",
18891a40b0caSPhilippe Mathieu-Daudé                            chip_id, blk, 0, XIVE_NVT_COUNT - 1);
1890d302e000SCédric Le Goater     xive_nvt_per_subpage = pnv_xive_vst_per_subpage(xive, VST_TSEL_VPDT);
1891d302e000SCédric Le Goater     for (i = 0; i < XIVE_NVT_COUNT; i += xive_nvt_per_subpage) {
1892d302e000SCédric Le Goater         while (!xive_router_get_nvt(xrtr, blk, i, &nvt)) {
18931a40b0caSPhilippe Mathieu-Daudé             xive_nvt_pic_print_info(&nvt, i++, buf);
1894d302e000SCédric Le Goater         }
1895d302e000SCédric Le Goater     }
18962dfa91a2SCédric Le Goater }
18972dfa91a2SCédric Le Goater 
pnv_xive_reset(void * dev)18982dfa91a2SCédric Le Goater static void pnv_xive_reset(void *dev)
18992dfa91a2SCédric Le Goater {
19002dfa91a2SCédric Le Goater     PnvXive *xive = PNV_XIVE(dev);
19012dfa91a2SCédric Le Goater     XiveSource *xsrc = &xive->ipi_source;
19022dfa91a2SCédric Le Goater     XiveENDSource *end_xsrc = &xive->end_source;
19032dfa91a2SCédric Le Goater 
19042dfa91a2SCédric Le Goater     /* Default page size (Should be changed at runtime to 64k) */
19052dfa91a2SCédric Le Goater     xive->ic_shift = xive->vc_shift = xive->pc_shift = 12;
19062dfa91a2SCédric Le Goater 
19072dfa91a2SCédric Le Goater     /* Clear subregions */
19082dfa91a2SCédric Le Goater     if (memory_region_is_mapped(&xsrc->esb_mmio)) {
19092dfa91a2SCédric Le Goater         memory_region_del_subregion(&xive->ipi_edt_mmio, &xsrc->esb_mmio);
19102dfa91a2SCédric Le Goater     }
19112dfa91a2SCédric Le Goater 
19122dfa91a2SCédric Le Goater     if (memory_region_is_mapped(&xive->ipi_edt_mmio)) {
19132dfa91a2SCédric Le Goater         memory_region_del_subregion(&xive->ipi_mmio, &xive->ipi_edt_mmio);
19142dfa91a2SCédric Le Goater     }
19152dfa91a2SCédric Le Goater 
19162dfa91a2SCédric Le Goater     if (memory_region_is_mapped(&end_xsrc->esb_mmio)) {
19172dfa91a2SCédric Le Goater         memory_region_del_subregion(&xive->end_edt_mmio, &end_xsrc->esb_mmio);
19182dfa91a2SCédric Le Goater     }
19192dfa91a2SCédric Le Goater 
19202dfa91a2SCédric Le Goater     if (memory_region_is_mapped(&xive->end_edt_mmio)) {
19212dfa91a2SCédric Le Goater         memory_region_del_subregion(&xive->end_mmio, &xive->end_edt_mmio);
19222dfa91a2SCédric Le Goater     }
19232dfa91a2SCédric Le Goater }
19242dfa91a2SCédric Le Goater 
pnv_xive_init(Object * obj)19252dfa91a2SCédric Le Goater static void pnv_xive_init(Object *obj)
19262dfa91a2SCédric Le Goater {
19272dfa91a2SCédric Le Goater     PnvXive *xive = PNV_XIVE(obj);
19282dfa91a2SCédric Le Goater 
19292dfa91a2SCédric Le Goater     object_initialize_child(obj, "ipi_source", &xive->ipi_source,
19309fc7fc4dSMarkus Armbruster                             TYPE_XIVE_SOURCE);
19312dfa91a2SCédric Le Goater     object_initialize_child(obj, "end_source", &xive->end_source,
19329fc7fc4dSMarkus Armbruster                             TYPE_XIVE_END_SOURCE);
19332dfa91a2SCédric Le Goater }
19342dfa91a2SCédric Le Goater 
19352dfa91a2SCédric Le Goater /*
19362dfa91a2SCédric Le Goater  *  Maximum number of IRQs and ENDs supported by HW
19372dfa91a2SCédric Le Goater  */
19382dfa91a2SCédric Le Goater #define PNV_XIVE_NR_IRQS (PNV9_XIVE_VC_SIZE / (1ull << XIVE_ESB_64K_2PAGE))
19392dfa91a2SCédric Le Goater #define PNV_XIVE_NR_ENDS (PNV9_XIVE_VC_SIZE / (1ull << XIVE_ESB_64K_2PAGE))
19402dfa91a2SCédric Le Goater 
pnv_xive_realize(DeviceState * dev,Error ** errp)19412dfa91a2SCédric Le Goater static void pnv_xive_realize(DeviceState *dev, Error **errp)
19422dfa91a2SCédric Le Goater {
19432dfa91a2SCédric Le Goater     PnvXive *xive = PNV_XIVE(dev);
19440da41d3cSGreg Kurz     PnvXiveClass *pxc = PNV_XIVE_GET_CLASS(dev);
19452dfa91a2SCédric Le Goater     XiveSource *xsrc = &xive->ipi_source;
19462dfa91a2SCédric Le Goater     XiveENDSource *end_xsrc = &xive->end_source;
19472dfa91a2SCédric Le Goater     Error *local_err = NULL;
19482dfa91a2SCédric Le Goater 
19490da41d3cSGreg Kurz     pxc->parent_realize(dev, &local_err);
19500da41d3cSGreg Kurz     if (local_err) {
19510da41d3cSGreg Kurz         error_propagate(errp, local_err);
19520da41d3cSGreg Kurz         return;
19530da41d3cSGreg Kurz     }
19540da41d3cSGreg Kurz 
19557ae54cc3SGreg Kurz     assert(xive->chip);
19562dfa91a2SCédric Le Goater 
19572dfa91a2SCédric Le Goater     /*
19582dfa91a2SCédric Le Goater      * The XiveSource and XiveENDSource objects are realized with the
19592dfa91a2SCédric Le Goater      * maximum allowed HW configuration. The ESB MMIO regions will be
19602dfa91a2SCédric Le Goater      * resized dynamically when the controller is configured by the FW
19612dfa91a2SCédric Le Goater      * to limit accesses to resources not provisioned.
19622dfa91a2SCédric Le Goater      */
19635325cc34SMarkus Armbruster     object_property_set_int(OBJECT(xsrc), "nr-irqs", PNV_XIVE_NR_IRQS,
19642dfa91a2SCédric Le Goater                             &error_fatal);
19655325cc34SMarkus Armbruster     object_property_set_link(OBJECT(xsrc), "xive", OBJECT(xive), &error_abort);
1966668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(xsrc), NULL, errp)) {
19672dfa91a2SCédric Le Goater         return;
19682dfa91a2SCédric Le Goater     }
19692dfa91a2SCédric Le Goater 
19705325cc34SMarkus Armbruster     object_property_set_int(OBJECT(end_xsrc), "nr-ends", PNV_XIVE_NR_ENDS,
19712dfa91a2SCédric Le Goater                             &error_fatal);
19725325cc34SMarkus Armbruster     object_property_set_link(OBJECT(end_xsrc), "xive", OBJECT(xive),
19730ab2316eSGreg Kurz                              &error_abort);
1974668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(end_xsrc), NULL, errp)) {
19752dfa91a2SCédric Le Goater         return;
19762dfa91a2SCédric Le Goater     }
19772dfa91a2SCédric Le Goater 
19782dfa91a2SCédric Le Goater     /* Default page size. Generally changed at runtime to 64k */
19792dfa91a2SCédric Le Goater     xive->ic_shift = xive->vc_shift = xive->pc_shift = 12;
19802dfa91a2SCédric Le Goater 
19812dfa91a2SCédric Le Goater     /* XSCOM region, used for initial configuration of the BARs */
19822dfa91a2SCédric Le Goater     memory_region_init_io(&xive->xscom_regs, OBJECT(dev), &pnv_xive_xscom_ops,
19832dfa91a2SCédric Le Goater                           xive, "xscom-xive", PNV9_XSCOM_XIVE_SIZE << 3);
19842dfa91a2SCédric Le Goater 
19852dfa91a2SCédric Le Goater     /* Interrupt controller MMIO regions */
19862dfa91a2SCédric Le Goater     memory_region_init(&xive->ic_mmio, OBJECT(dev), "xive-ic",
19872dfa91a2SCédric Le Goater                        PNV9_XIVE_IC_SIZE);
19882dfa91a2SCédric Le Goater 
19892dfa91a2SCédric Le Goater     memory_region_init_io(&xive->ic_reg_mmio, OBJECT(dev), &pnv_xive_ic_reg_ops,
19902dfa91a2SCédric Le Goater                           xive, "xive-ic-reg", 1 << xive->ic_shift);
19912dfa91a2SCédric Le Goater     memory_region_init_io(&xive->ic_notify_mmio, OBJECT(dev),
19922dfa91a2SCédric Le Goater                           &pnv_xive_ic_notify_ops,
19932dfa91a2SCédric Le Goater                           xive, "xive-ic-notify", 1 << xive->ic_shift);
1994f2c1e591SCédric Le Goater     xive->ic_notify_mmio.disable_reentrancy_guard = true;
19952dfa91a2SCédric Le Goater 
19962dfa91a2SCédric Le Goater     /* The Pervasive LSI trigger and EOI pages (not modeled) */
19972dfa91a2SCédric Le Goater     memory_region_init_io(&xive->ic_lsi_mmio, OBJECT(dev), &pnv_xive_ic_lsi_ops,
19982dfa91a2SCédric Le Goater                           xive, "xive-ic-lsi", 2 << xive->ic_shift);
19992dfa91a2SCédric Le Goater 
20002dfa91a2SCédric Le Goater     /* Thread Interrupt Management Area (Indirect) */
20012dfa91a2SCédric Le Goater     memory_region_init_io(&xive->tm_indirect_mmio, OBJECT(dev),
20022dfa91a2SCédric Le Goater                           &xive_tm_indirect_ops,
20032dfa91a2SCédric Le Goater                           xive, "xive-tima-indirect", PNV9_XIVE_TM_SIZE);
20042dfa91a2SCédric Le Goater     /*
20052dfa91a2SCédric Le Goater      * Overall Virtualization Controller MMIO region containing the
20062dfa91a2SCédric Le Goater      * IPI ESB pages and END ESB pages. The layout is defined by the
20072dfa91a2SCédric Le Goater      * EDT "Domain table" and the accesses are dispatched using
20082dfa91a2SCédric Le Goater      * address spaces for each.
20092dfa91a2SCédric Le Goater      */
20102dfa91a2SCédric Le Goater     memory_region_init_io(&xive->vc_mmio, OBJECT(xive), &pnv_xive_vc_ops, xive,
20112dfa91a2SCédric Le Goater                           "xive-vc", PNV9_XIVE_VC_SIZE);
20122dfa91a2SCédric Le Goater 
20132dfa91a2SCédric Le Goater     memory_region_init(&xive->ipi_mmio, OBJECT(xive), "xive-vc-ipi",
20142dfa91a2SCédric Le Goater                        PNV9_XIVE_VC_SIZE);
20152dfa91a2SCédric Le Goater     address_space_init(&xive->ipi_as, &xive->ipi_mmio, "xive-vc-ipi");
20162dfa91a2SCédric Le Goater     memory_region_init(&xive->end_mmio, OBJECT(xive), "xive-vc-end",
20172dfa91a2SCédric Le Goater                        PNV9_XIVE_VC_SIZE);
20182dfa91a2SCédric Le Goater     address_space_init(&xive->end_as, &xive->end_mmio, "xive-vc-end");
20192dfa91a2SCédric Le Goater 
20202dfa91a2SCédric Le Goater     /*
20212dfa91a2SCédric Le Goater      * The MMIO windows exposing the IPI ESBs and the END ESBs in the
20222dfa91a2SCédric Le Goater      * VC region. Their size is configured by the FW in the EDT table.
20232dfa91a2SCédric Le Goater      */
20242dfa91a2SCédric Le Goater     memory_region_init(&xive->ipi_edt_mmio, OBJECT(xive), "xive-vc-ipi-edt", 0);
20252dfa91a2SCédric Le Goater     memory_region_init(&xive->end_edt_mmio, OBJECT(xive), "xive-vc-end-edt", 0);
20262dfa91a2SCédric Le Goater 
20272dfa91a2SCédric Le Goater     /* Presenter Controller MMIO region (not modeled) */
20282dfa91a2SCédric Le Goater     memory_region_init_io(&xive->pc_mmio, OBJECT(xive), &pnv_xive_pc_ops, xive,
20292dfa91a2SCédric Le Goater                           "xive-pc", PNV9_XIVE_PC_SIZE);
2030b68147b7SCédric Le Goater     xive->pc_mmio.disable_reentrancy_guard = true;
20312dfa91a2SCédric Le Goater 
20322dfa91a2SCédric Le Goater     /* Thread Interrupt Management Area (Direct) */
2033d024a2c1SCédric Le Goater     memory_region_init_io(&xive->tm_mmio, OBJECT(xive), &pnv_xive_tm_ops,
20342dfa91a2SCédric Le Goater                           xive, "xive-tima", PNV9_XIVE_TM_SIZE);
20352dfa91a2SCédric Le Goater 
20362dfa91a2SCédric Le Goater     qemu_register_reset(pnv_xive_reset, dev);
20372dfa91a2SCédric Le Goater }
20382dfa91a2SCédric Le Goater 
pnv_xive_dt_xscom(PnvXScomInterface * dev,void * fdt,int xscom_offset)20392dfa91a2SCédric Le Goater static int pnv_xive_dt_xscom(PnvXScomInterface *dev, void *fdt,
20402dfa91a2SCédric Le Goater                              int xscom_offset)
20412dfa91a2SCédric Le Goater {
20422dfa91a2SCédric Le Goater     const char compat[] = "ibm,power9-xive-x";
20432dfa91a2SCédric Le Goater     char *name;
20442dfa91a2SCédric Le Goater     int offset;
20452dfa91a2SCédric Le Goater     uint32_t lpc_pcba = PNV9_XSCOM_XIVE_BASE;
20462dfa91a2SCédric Le Goater     uint32_t reg[] = {
20472dfa91a2SCédric Le Goater         cpu_to_be32(lpc_pcba),
20482dfa91a2SCédric Le Goater         cpu_to_be32(PNV9_XSCOM_XIVE_SIZE)
20492dfa91a2SCédric Le Goater     };
20502dfa91a2SCédric Le Goater 
20512dfa91a2SCédric Le Goater     name = g_strdup_printf("xive@%x", lpc_pcba);
20522dfa91a2SCédric Le Goater     offset = fdt_add_subnode(fdt, xscom_offset, name);
20532dfa91a2SCédric Le Goater     _FDT(offset);
20542dfa91a2SCédric Le Goater     g_free(name);
20552dfa91a2SCédric Le Goater 
20562dfa91a2SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "reg", reg, sizeof(reg))));
20572dfa91a2SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "compatible", compat,
20582dfa91a2SCédric Le Goater                       sizeof(compat))));
20592dfa91a2SCédric Le Goater     return 0;
20602dfa91a2SCédric Le Goater }
20612dfa91a2SCédric Le Goater 
20622dfa91a2SCédric Le Goater static Property pnv_xive_properties[] = {
20632dfa91a2SCédric Le Goater     DEFINE_PROP_UINT64("ic-bar", PnvXive, ic_base, 0),
20642dfa91a2SCédric Le Goater     DEFINE_PROP_UINT64("vc-bar", PnvXive, vc_base, 0),
20652dfa91a2SCédric Le Goater     DEFINE_PROP_UINT64("pc-bar", PnvXive, pc_base, 0),
20662dfa91a2SCédric Le Goater     DEFINE_PROP_UINT64("tm-bar", PnvXive, tm_base, 0),
20677ae54cc3SGreg Kurz     /* The PnvChip id identifies the XIVE interrupt controller. */
20687ae54cc3SGreg Kurz     DEFINE_PROP_LINK("chip", PnvXive, chip, TYPE_PNV_CHIP, PnvChip *),
20692dfa91a2SCédric Le Goater     DEFINE_PROP_END_OF_LIST(),
20702dfa91a2SCédric Le Goater };
20712dfa91a2SCédric Le Goater 
pnv_xive_class_init(ObjectClass * klass,void * data)20722dfa91a2SCédric Le Goater static void pnv_xive_class_init(ObjectClass *klass, void *data)
20732dfa91a2SCédric Le Goater {
20742dfa91a2SCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
20752dfa91a2SCédric Le Goater     PnvXScomInterfaceClass *xdc = PNV_XSCOM_INTERFACE_CLASS(klass);
20762dfa91a2SCédric Le Goater     XiveRouterClass *xrc = XIVE_ROUTER_CLASS(klass);
20772dfa91a2SCédric Le Goater     XiveNotifierClass *xnc = XIVE_NOTIFIER_CLASS(klass);
2078f87dae18SCédric Le Goater     XivePresenterClass *xpc = XIVE_PRESENTER_CLASS(klass);
20790da41d3cSGreg Kurz     PnvXiveClass *pxc = PNV_XIVE_CLASS(klass);
20802dfa91a2SCédric Le Goater 
20812dfa91a2SCédric Le Goater     xdc->dt_xscom = pnv_xive_dt_xscom;
20822dfa91a2SCédric Le Goater 
20832dfa91a2SCédric Le Goater     dc->desc = "PowerNV XIVE Interrupt Controller";
20840da41d3cSGreg Kurz     device_class_set_parent_realize(dc, pnv_xive_realize, &pxc->parent_realize);
20852dfa91a2SCédric Le Goater     dc->realize = pnv_xive_realize;
20864f67d30bSMarc-André Lureau     device_class_set_props(dc, pnv_xive_properties);
20872dfa91a2SCédric Le Goater 
20882dfa91a2SCédric Le Goater     xrc->get_eas = pnv_xive_get_eas;
20890aa2612aSCédric Le Goater     xrc->get_pq = pnv_xive_get_pq;
20900aa2612aSCédric Le Goater     xrc->set_pq = pnv_xive_set_pq;
20912dfa91a2SCédric Le Goater     xrc->get_end = pnv_xive_get_end;
20922dfa91a2SCédric Le Goater     xrc->write_end = pnv_xive_write_end;
20932dfa91a2SCédric Le Goater     xrc->get_nvt = pnv_xive_get_nvt;
20942dfa91a2SCédric Le Goater     xrc->write_nvt = pnv_xive_write_nvt;
2095f22f56ddSCédric Le Goater     xrc->get_block_id = pnv_xive_get_block_id;
2096f2c1e591SCédric Le Goater     xrc->end_notify = pnv_xive_end_notify;
20972dfa91a2SCédric Le Goater 
20982dfa91a2SCédric Le Goater     xnc->notify = pnv_xive_notify;
2099f87dae18SCédric Le Goater     xpc->match_nvt  = pnv_xive_match_nvt;
21002a24e6e3SFrederic Barrat     xpc->get_config = pnv_xive_presenter_get_config;
21012dfa91a2SCédric Le Goater };
21022dfa91a2SCédric Le Goater 
21032dfa91a2SCédric Le Goater static const TypeInfo pnv_xive_info = {
21042dfa91a2SCédric Le Goater     .name          = TYPE_PNV_XIVE,
21052dfa91a2SCédric Le Goater     .parent        = TYPE_XIVE_ROUTER,
21062dfa91a2SCédric Le Goater     .instance_init = pnv_xive_init,
21072dfa91a2SCédric Le Goater     .instance_size = sizeof(PnvXive),
21082dfa91a2SCédric Le Goater     .class_init    = pnv_xive_class_init,
21090da41d3cSGreg Kurz     .class_size    = sizeof(PnvXiveClass),
21102dfa91a2SCédric Le Goater     .interfaces    = (InterfaceInfo[]) {
21112dfa91a2SCédric Le Goater         { TYPE_PNV_XSCOM_INTERFACE },
21122dfa91a2SCédric Le Goater         { }
21132dfa91a2SCédric Le Goater     }
21142dfa91a2SCédric Le Goater };
21152dfa91a2SCédric Le Goater 
pnv_xive_register_types(void)21162dfa91a2SCédric Le Goater static void pnv_xive_register_types(void)
21172dfa91a2SCédric Le Goater {
21182dfa91a2SCédric Le Goater     type_register_static(&pnv_xive_info);
21192dfa91a2SCédric Le Goater }
21202dfa91a2SCédric Le Goater 
21212dfa91a2SCédric Le Goater type_init(pnv_xive_register_types)
2122