|
@@ -84,28 +84,6 @@ static uint8_t pnv_xive_block_id(PnvXive *xive)
|
|
|
return blk;
|
|
|
}
|
|
|
|
|
|
-/*
|
|
|
- * Remote access to controllers. HW uses MMIOs. For now, a simple scan
|
|
|
- * of the chips is good enough.
|
|
|
- *
|
|
|
- * TODO: Block scope support
|
|
|
- */
|
|
|
-static PnvXive *pnv_xive_get_remote(uint8_t blk)
|
|
|
-{
|
|
|
- PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine());
|
|
|
- int i;
|
|
|
-
|
|
|
- for (i = 0; i < pnv->num_chips; i++) {
|
|
|
- Pnv9Chip *chip9 = PNV9_CHIP(pnv->chips[i]);
|
|
|
- PnvXive *xive = &chip9->xive;
|
|
|
-
|
|
|
- if (pnv_xive_block_id(xive) == blk) {
|
|
|
- return xive;
|
|
|
- }
|
|
|
- }
|
|
|
- return NULL;
|
|
|
-}
|
|
|
-
|
|
|
/*
|
|
|
* VST accessors for SBE, EAT, ENDT, NVT
|
|
|
*
|
|
@@ -209,6 +187,42 @@ static uint64_t pnv_xive_vst_addr_indirect(PnvXive *xive, uint32_t type,
|
|
|
return pnv_xive_vst_addr_direct(xive, type, vsd, (idx % vst_per_page));
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * This is a simplified model of operation forwarding on a remote IC.
|
|
|
+ *
|
|
|
+ * A PC MMIO address is built to identify the NVT structure. The load
|
|
|
+ * on the remote IC will return the address of the structure in RAM,
|
|
|
+ * which will then be used by pnv_xive_vst_write/read to perform the
|
|
|
+ * RAM operation.
|
|
|
+ */
|
|
|
+static uint64_t pnv_xive_vst_addr_remote(PnvXive *xive, uint32_t type,
|
|
|
+ uint64_t vsd, uint8_t blk,
|
|
|
+ uint32_t idx)
|
|
|
+{
|
|
|
+ const XiveVstInfo *info = &vst_infos[type];
|
|
|
+ uint64_t remote_addr = vsd & VSD_ADDRESS_MASK;
|
|
|
+ uint64_t vst_addr;
|
|
|
+ MemTxResult result;
|
|
|
+
|
|
|
+ if (type != VST_TSEL_VPDT) {
|
|
|
+ xive_error(xive, "VST: invalid access on remote VST %s %x/%x !?",
|
|
|
+ info->name, blk, idx);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ remote_addr |= idx << xive->pc_shift;
|
|
|
+
|
|
|
+ vst_addr = address_space_ldq_be(&address_space_memory, remote_addr,
|
|
|
+ MEMTXATTRS_UNSPECIFIED, &result);
|
|
|
+ if (result != MEMTX_OK) {
|
|
|
+ xive_error(xive, "VST: read failed at @0x%" HWADDR_PRIx
|
|
|
+ " for NVT %x/%x\n", remote_addr, blk, idx);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ return vst_addr;
|
|
|
+}
|
|
|
+
|
|
|
static uint64_t pnv_xive_vst_addr(PnvXive *xive, uint32_t type, uint8_t blk,
|
|
|
uint32_t idx)
|
|
|
{
|
|
@@ -225,14 +239,7 @@ static uint64_t pnv_xive_vst_addr(PnvXive *xive, uint32_t type, uint8_t blk,
|
|
|
|
|
|
/* Remote VST access */
|
|
|
if (GETFIELD(VSD_MODE, vsd) == VSD_MODE_FORWARD) {
|
|
|
- if (type != VST_TSEL_VPDT) {
|
|
|
- xive_error(xive, "VST: invalid access on remote VST %s %x/%x !?",
|
|
|
- info->name, blk, idx);
|
|
|
- return 0;
|
|
|
- }
|
|
|
- xive = pnv_xive_get_remote(blk);
|
|
|
-
|
|
|
- return xive ? pnv_xive_vst_addr(xive, type, blk, idx) : 0;
|
|
|
+ return pnv_xive_vst_addr_remote(xive, type, vsd, blk, idx);
|
|
|
}
|
|
|
|
|
|
if (VSD_INDIRECT & vsd) {
|
|
@@ -1785,16 +1792,20 @@ static const MemoryRegionOps pnv_xive_vc_ops = {
|
|
|
};
|
|
|
|
|
|
/*
|
|
|
- * Presenter Controller MMIO region. The Virtualization Controller
|
|
|
- * updates the IPB in the NVT table when required. Not modeled.
|
|
|
+ * Presenter Controller MMIO region. Points to the NVT sets.
|
|
|
+ *
|
|
|
+ * HW implements all possible mem ops to the underlying NVT structure
|
|
|
+ * but QEMU does not need to be so precise. The model implementation
|
|
|
+ * simply returns the RAM address of the NVT structure which is then
|
|
|
+ * used by pnv_xive_vst_write/read to perform the RAM operation.
|
|
|
*/
|
|
|
-static uint64_t pnv_xive_pc_read(void *opaque, hwaddr addr,
|
|
|
- unsigned size)
|
|
|
+static uint64_t pnv_xive_pc_read(void *opaque, hwaddr offset, unsigned size)
|
|
|
{
|
|
|
PnvXive *xive = PNV_XIVE(opaque);
|
|
|
+ uint32_t nvt_idx = offset >> xive->pc_shift;
|
|
|
+ uint8_t blk = pnv_xive_block_id(xive); /* TODO: VDT -> block xlate */
|
|
|
|
|
|
- xive_error(xive, "PC: invalid read @%"HWADDR_PRIx, addr);
|
|
|
- return -1;
|
|
|
+ return pnv_xive_vst_addr(xive, VST_TSEL_VPDT, blk, nvt_idx);
|
|
|
}
|
|
|
|
|
|
static void pnv_xive_pc_write(void *opaque, hwaddr addr,
|
|
@@ -2016,6 +2027,7 @@ static void pnv_xive_realize(DeviceState *dev, Error **errp)
|
|
|
/* Presenter Controller MMIO region (not modeled) */
|
|
|
memory_region_init_io(&xive->pc_mmio, OBJECT(xive), &pnv_xive_pc_ops, xive,
|
|
|
"xive-pc", PNV9_XIVE_PC_SIZE);
|
|
|
+ xive->pc_mmio.disable_reentrancy_guard = true;
|
|
|
|
|
|
/* Thread Interrupt Management Area (Direct) */
|
|
|
memory_region_init_io(&xive->tm_mmio, OBJECT(xive), &pnv_xive_tm_ops,
|