aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2024-11-05 10:05:59 +0000
committerPeter Maydell <peter.maydell@linaro.org>2024-11-05 10:05:59 +0000
commit6b829602e2f10f301ff8508f3a6850a0e913142c (patch)
tree3f8d300b297aaa3d0e94bde69a53f9ef88e529ce /hw
parent11b8920ed2093848f79f93d106afe8a69a61a523 (diff)
parentbd4be4d9bd20a252e677239a18b6409ecee98f56 (diff)
downloadqemu-6b829602e2f10f301ff8508f3a6850a0e913142c.zip
qemu-6b829602e2f10f301ff8508f3a6850a0e913142c.tar.gz
qemu-6b829602e2f10f301ff8508f3a6850a0e913142c.tar.bz2
Merge tag 'pull-ppc-for-9.2-1-20241104' of https://gitlab.com/npiggin/qemu into staging
* Various bug fixes * Big cleanup of deprecated machines * Power11 support for spapr * XIVE improvements * Goodbye to Cedric and David as ppc reviewers, thank you both o7 # -----BEGIN PGP SIGNATURE----- # # iQIzBAABCgAdFiEETkN92lZhb0MpsKeVZ7MCdqhiHK4FAmcoEicACgkQZ7MCdqhi # HK5M8Q//fz+ZkJndXkBjb1Oinx+q+eVtNm2JrvcWIsXyhG3K+6VxYPp69H+SRv/Z # TWuUqMQPxq8mhQvBJlDAttp/oaUEiOcCRvs/iUoBN12L4mVxXfdoT88TZ4frN3eP # 8bePq+DW2N/7gpmsJm5CyEZPpcf9AjVHgLRp3KYFkOJ/14uzvuwnocU39gl+2IUh # MXHTedQgMNXaKorJXk1NVdM6NxMuVhOvwxAs6ya2gwhxyA5tteo5PiQOnDJWkejf # xg3RRsNzGYcs1Qg/3kFIf3RfEB0aYbPxROM8IfPaJWKN5KnMggj/JAkHyK1x/V3J # wml7+cB0doMt/yRiuYJhXpyrtOqpvjRWPA6RhxECWW2kwrovv8NAF8IrFnw9NvOQ # QC66ZaaFcbAcFrVT1e/iggU76d01II6m4OAgKcXw+FRHgps4VU9y83j7ApNnNUWN # IXp9hkzoHi5VwX0FrG4ELUr2iEf1HASMvM8EZ/0AxzWj5iNtQB8lFsrEdaGVXyIS # M5JaJeNjCn4koCyYaFSctH5eKtbzIwnGWnDcdTwaOuQ+9itBvY8O+HZalE6sAc5S # kLFZ7i/Ut/qxbY5pMumt8LKD4pR1SsOxFB8dJCmn/f/tvRGtIVsoY6btNe4M0+24 # 42MxZbWO6W379C32bwbtsPiGA+aLSgShjP4cWm9cgRjz4RJFnwg= # =vmIG # -----END PGP SIGNATURE----- # gpg: Signature made Mon 04 Nov 2024 00:15:35 GMT # gpg: using RSA key 4E437DDA56616F4329B0A79567B30276A8621CAE # gpg: Good signature from "Nicholas Piggin <npiggin@gmail.com>" [unknown] # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: 4E43 7DDA 5661 6F43 29B0 A795 67B3 0276 A862 1CAE * tag 'pull-ppc-for-9.2-1-20241104' of https://gitlab.com/npiggin/qemu: (67 commits) MAINTAINERS: Remove myself as reviewer MAINTAINERS: Remove myself from XIVE MAINTAINERS: Remove myself from the PowerNV machines hw/ppc: Consolidate ppc440 initial mapping creation functions hw/ppc: Consolidate e500 initial mapping creation functions tests/qtest: Add XIVE tests for the powernv10 machine pnv/xive2: TIMA CI ops using alternative offsets or byte lengths pnv/xive2: TIMA support for 8-byte OS context push for PHYP pnv/xive: Update PIPR when updating CPPR pnv/xive: Add special handling for pool targets ppc/xive2: Support "Pull Thread Context to Odd Thread Reporting Line" ppc/xive2: Change context/ring specific functions to be generic ppc/xive2: Support "Pull Thread Context to Register" operation ppc/xive2: Allow 1-byte write of Target field in TIMA ppc/xive2: Dump the VP-group and crowd tables with 'info pic' ppc/xive2: Dump more NVP state with 'info pic' pnv/xive2: Support for "OS LGS Push" TIMA operation ppc/xive2: Support TIMA "Pull OS Context to Odd Thread Reporting Line" pnv/xive2: Define OGEN field in the TIMA pnv/xive: TIMA patch sets pre-req alignment and formatting changes ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw')
-rw-r--r--hw/core/machine.c27
-rw-r--r--hw/intc/pnv_xive2.c44
-rw-r--r--hw/intc/spapr_xive_kvm.c4
-rw-r--r--hw/intc/xics.c16
-rw-r--r--hw/intc/xive.c203
-rw-r--r--hw/intc/xive2.c317
-rw-r--r--hw/ppc/e500.c41
-rw-r--r--hw/ppc/e500.h2
-rw-r--r--hw/ppc/pnv.c51
-rw-r--r--hw/ppc/pnv_adu.c12
-rw-r--r--hw/ppc/pnv_lpc.c14
-rw-r--r--hw/ppc/ppc.c4
-rw-r--r--hw/ppc/ppc440_bamboo.c28
-rw-r--r--hw/ppc/ppc_booke.c10
-rw-r--r--hw/ppc/ppce500_spin.c30
-rw-r--r--hw/ppc/sam460ex.c45
-rw-r--r--hw/ppc/spapr.c387
-rw-r--r--hw/ppc/spapr_cpu_core.c13
-rw-r--r--hw/ppc/spapr_nested.c13
-rw-r--r--hw/ppc/spapr_pci.c92
-rw-r--r--hw/ppc/virtex_ml507.c28
-rw-r--r--hw/ssi/pnv_spi.c12
22 files changed, 628 insertions, 765 deletions
diff --git a/hw/core/machine.c b/hw/core/machine.c
index 222799b..901c64b 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -281,33 +281,6 @@ GlobalProperty hw_compat_2_4[] = {
};
const size_t hw_compat_2_4_len = G_N_ELEMENTS(hw_compat_2_4);
-GlobalProperty hw_compat_2_3[] = {
- { "virtio-blk-pci", "any_layout", "off" },
- { "virtio-balloon-pci", "any_layout", "off" },
- { "virtio-serial-pci", "any_layout", "off" },
- { "virtio-9p-pci", "any_layout", "off" },
- { "virtio-rng-pci", "any_layout", "off" },
- { TYPE_PCI_DEVICE, "x-pcie-lnksta-dllla", "off" },
- { "migration", "send-configuration", "off" },
- { "migration", "send-section-footer", "off" },
- { "migration", "store-global-state", "off" },
-};
-const size_t hw_compat_2_3_len = G_N_ELEMENTS(hw_compat_2_3);
-
-GlobalProperty hw_compat_2_2[] = {};
-const size_t hw_compat_2_2_len = G_N_ELEMENTS(hw_compat_2_2);
-
-GlobalProperty hw_compat_2_1[] = {
- { "intel-hda", "old_msi_addr", "on" },
- { "VGA", "qemu-extended-regs", "off" },
- { "secondary-vga", "qemu-extended-regs", "off" },
- { "virtio-scsi-pci", "any_layout", "off" },
- { "usb-mouse", "usb_version", "1" },
- { "usb-kbd", "usb_version", "1" },
- { "virtio-pci", "virtio-pci-bus-master-bug-migration", "on" },
-};
-const size_t hw_compat_2_1_len = G_N_ELEMENTS(hw_compat_2_1);
-
MachineState *current_machine;
static char *machine_get_kernel(Object *obj, Error **errp)
diff --git a/hw/intc/pnv_xive2.c b/hw/intc/pnv_xive2.c
index 7860910..834d322 100644
--- a/hw/intc/pnv_xive2.c
+++ b/hw/intc/pnv_xive2.c
@@ -490,6 +490,23 @@ static int pnv_xive2_write_nvp(Xive2Router *xrtr, uint8_t blk, uint32_t idx,
word_number);
}
+static int pnv_xive2_get_nvgc(Xive2Router *xrtr, bool crowd,
+ uint8_t blk, uint32_t idx,
+ Xive2Nvgc *nvgc)
+{
+ return pnv_xive2_vst_read(PNV_XIVE2(xrtr), crowd ? VST_NVC : VST_NVG,
+ blk, idx, nvgc);
+}
+
+static int pnv_xive2_write_nvgc(Xive2Router *xrtr, bool crowd,
+ uint8_t blk, uint32_t idx,
+ Xive2Nvgc *nvgc)
+{
+ return pnv_xive2_vst_write(PNV_XIVE2(xrtr), crowd ? VST_NVC : VST_NVG,
+ blk, idx, nvgc,
+ XIVE_VST_WORD_ALL);
+}
+
static int pnv_xive2_nxc_to_table_type(uint8_t nxc_type, uint32_t *table_type)
{
switch (nxc_type) {
@@ -2407,6 +2424,8 @@ static void pnv_xive2_class_init(ObjectClass *klass, void *data)
xrc->write_end = pnv_xive2_write_end;
xrc->get_nvp = pnv_xive2_get_nvp;
xrc->write_nvp = pnv_xive2_write_nvp;
+ xrc->get_nvgc = pnv_xive2_get_nvgc;
+ xrc->write_nvgc = pnv_xive2_write_nvgc;
xrc->get_config = pnv_xive2_get_config;
xrc->get_block_id = pnv_xive2_get_block_id;
@@ -2497,8 +2516,9 @@ void pnv_xive2_pic_print_info(PnvXive2 *xive, GString *buf)
Xive2Eas eas;
Xive2End end;
Xive2Nvp nvp;
+ Xive2Nvgc nvgc;
int i;
- uint64_t xive_nvp_per_subpage;
+ uint64_t entries_per_subpage;
g_string_append_printf(buf, "XIVE[%x] Source %08x .. %08x\n",
blk, srcno0, srcno0 + nr_esbs - 1);
@@ -2530,10 +2550,28 @@ void pnv_xive2_pic_print_info(PnvXive2 *xive, GString *buf)
g_string_append_printf(buf, "XIVE[%x] #%d NVPT %08x .. %08x\n",
chip_id, blk, 0, XIVE2_NVP_COUNT - 1);
- xive_nvp_per_subpage = pnv_xive2_vst_per_subpage(xive, VST_NVP);
- for (i = 0; i < XIVE2_NVP_COUNT; i += xive_nvp_per_subpage) {
+ entries_per_subpage = pnv_xive2_vst_per_subpage(xive, VST_NVP);
+ for (i = 0; i < XIVE2_NVP_COUNT; i += entries_per_subpage) {
while (!xive2_router_get_nvp(xrtr, blk, i, &nvp)) {
xive2_nvp_pic_print_info(&nvp, i++, buf);
}
}
+
+ g_string_append_printf(buf, "XIVE[%x] #%d NVGT %08x .. %08x\n",
+ chip_id, blk, 0, XIVE2_NVP_COUNT - 1);
+ entries_per_subpage = pnv_xive2_vst_per_subpage(xive, VST_NVG);
+ for (i = 0; i < XIVE2_NVP_COUNT; i += entries_per_subpage) {
+ while (!xive2_router_get_nvgc(xrtr, false, blk, i, &nvgc)) {
+ xive2_nvgc_pic_print_info(&nvgc, i++, buf);
+ }
+ }
+
+ g_string_append_printf(buf, "XIVE[%x] #%d NVCT %08x .. %08x\n",
+ chip_id, blk, 0, XIVE2_NVP_COUNT - 1);
+ entries_per_subpage = pnv_xive2_vst_per_subpage(xive, VST_NVC);
+ for (i = 0; i < XIVE2_NVP_COUNT; i += entries_per_subpage) {
+ while (!xive2_router_get_nvgc(xrtr, true, blk, i, &nvgc)) {
+ xive2_nvgc_pic_print_info(&nvgc, i++, buf);
+ }
+ }
}
diff --git a/hw/intc/spapr_xive_kvm.c b/hw/intc/spapr_xive_kvm.c
index 5789062..7a86197 100644
--- a/hw/intc/spapr_xive_kvm.c
+++ b/hw/intc/spapr_xive_kvm.c
@@ -720,7 +720,7 @@ int kvmppc_xive_connect(SpaprInterruptController *intc, uint32_t nr_servers,
{
SpaprXive *xive = SPAPR_XIVE(intc);
XiveSource *xsrc = &xive->source;
- size_t esb_len = xive_source_esb_len(xsrc);
+ uint64_t esb_len = xive_source_esb_len(xsrc);
size_t tima_len = 4ull << TM_SHIFT;
CPUState *cs;
int fd;
@@ -824,7 +824,7 @@ void kvmppc_xive_disconnect(SpaprInterruptController *intc)
{
SpaprXive *xive = SPAPR_XIVE(intc);
XiveSource *xsrc;
- size_t esb_len;
+ uint64_t esb_len;
assert(xive->fd != -1);
diff --git a/hw/intc/xics.c b/hw/intc/xics.c
index 6f4d527..e893363 100644
--- a/hw/intc/xics.c
+++ b/hw/intc/xics.c
@@ -335,22 +335,6 @@ static void icp_realize(DeviceState *dev, Error **errp)
return;
}
}
- /*
- * The way that pre_2_10_icp is handling is really, really hacky.
- * We used to have here this call:
- *
- * vmstate_register(NULL, icp->cs->cpu_index, &vmstate_icp_server, icp);
- *
- * But we were doing:
- * pre_2_10_vmstate_register_dummy_icp()
- * this vmstate_register()
- * pre_2_10_vmstate_unregister_dummy_icp()
- *
- * So for a short amount of time we had to vmstate entries with
- * the same name. This fixes it.
- */
- vmstate_replace_hack_for_ppc(NULL, icp->cs->cpu_index,
- &vmstate_icp_server, icp);
}
static void icp_unrealize(DeviceState *dev)
diff --git a/hw/intc/xive.c b/hw/intc/xive.c
index 5a02dd8..245e4d1 100644
--- a/hw/intc/xive.c
+++ b/hw/intc/xive.c
@@ -74,33 +74,48 @@ static uint64_t xive_tctx_accept(XiveTCTX *tctx, uint8_t ring)
if (regs[TM_NSR] & mask) {
uint8_t cppr = regs[TM_PIPR];
+ uint8_t alt_ring;
+ uint8_t *alt_regs;
+
+ /* POOL interrupt uses IPB in QW2, POOL ring */
+ if ((ring == TM_QW3_HV_PHYS) && (nsr & (TM_QW3_NSR_HE_POOL << 6))) {
+ alt_ring = TM_QW2_HV_POOL;
+ } else {
+ alt_ring = ring;
+ }
+ alt_regs = &tctx->regs[alt_ring];
regs[TM_CPPR] = cppr;
/* Reset the pending buffer bit */
- regs[TM_IPB] &= ~xive_priority_to_ipb(cppr);
- regs[TM_PIPR] = ipb_to_pipr(regs[TM_IPB]);
+ alt_regs[TM_IPB] &= ~xive_priority_to_ipb(cppr);
/* Drop Exception bit */
regs[TM_NSR] &= ~mask;
- trace_xive_tctx_accept(tctx->cs->cpu_index, ring,
- regs[TM_IPB], regs[TM_PIPR],
+ trace_xive_tctx_accept(tctx->cs->cpu_index, alt_ring,
+ alt_regs[TM_IPB], regs[TM_PIPR],
regs[TM_CPPR], regs[TM_NSR]);
}
- return (nsr << 8) | regs[TM_CPPR];
+ return ((uint64_t)nsr << 8) | regs[TM_CPPR];
}
static void xive_tctx_notify(XiveTCTX *tctx, uint8_t ring)
{
+ /* HV_POOL ring uses HV_PHYS NSR, CPPR and PIPR registers */
+ uint8_t alt_ring = (ring == TM_QW2_HV_POOL) ? TM_QW3_HV_PHYS : ring;
+ uint8_t *alt_regs = &tctx->regs[alt_ring];
uint8_t *regs = &tctx->regs[ring];
- if (regs[TM_PIPR] < regs[TM_CPPR]) {
+ if (alt_regs[TM_PIPR] < alt_regs[TM_CPPR]) {
switch (ring) {
case TM_QW1_OS:
regs[TM_NSR] |= TM_QW1_NSR_EO;
break;
+ case TM_QW2_HV_POOL:
+ alt_regs[TM_NSR] = (TM_QW3_NSR_HE_POOL << 6);
+ break;
case TM_QW3_HV_PHYS:
regs[TM_NSR] |= (TM_QW3_NSR_HE_PHYS << 6);
break;
@@ -108,26 +123,27 @@ static void xive_tctx_notify(XiveTCTX *tctx, uint8_t ring)
g_assert_not_reached();
}
trace_xive_tctx_notify(tctx->cs->cpu_index, ring,
- regs[TM_IPB], regs[TM_PIPR],
- regs[TM_CPPR], regs[TM_NSR]);
+ regs[TM_IPB], alt_regs[TM_PIPR],
+ alt_regs[TM_CPPR], alt_regs[TM_NSR]);
qemu_irq_raise(xive_tctx_output(tctx, ring));
}
}
-void xive_tctx_reset_os_signal(XiveTCTX *tctx)
+void xive_tctx_reset_signal(XiveTCTX *tctx, uint8_t ring)
{
/*
- * Lower the External interrupt. Used when pulling an OS
- * context. It is necessary to avoid catching it in the hypervisor
- * context. It should be raised again when re-pushing the OS
- * context.
+ * Lower the External interrupt. Used when pulling a context. It is
+ * necessary to avoid catching it in the higher privilege context. It
+ * should be raised again when re-pushing the lower privilege context.
*/
- qemu_irq_lower(xive_tctx_output(tctx, TM_QW1_OS));
+ qemu_irq_lower(xive_tctx_output(tctx, ring));
}
static void xive_tctx_set_cppr(XiveTCTX *tctx, uint8_t ring, uint8_t cppr)
{
uint8_t *regs = &tctx->regs[ring];
+ uint8_t pipr_min;
+ uint8_t ring_min;
trace_xive_tctx_set_cppr(tctx->cs->cpu_index, ring,
regs[TM_IPB], regs[TM_PIPR],
@@ -139,8 +155,37 @@ static void xive_tctx_set_cppr(XiveTCTX *tctx, uint8_t ring, uint8_t cppr)
tctx->regs[ring + TM_CPPR] = cppr;
+ /*
+ * Recompute the PIPR based on local pending interrupts. The PHYS
+ * ring must take the minimum of both the PHYS and POOL PIPR values.
+ */
+ pipr_min = ipb_to_pipr(regs[TM_IPB]);
+ ring_min = ring;
+
+ /* PHYS updates also depend on POOL values */
+ if (ring == TM_QW3_HV_PHYS) {
+ uint8_t *pool_regs = &tctx->regs[TM_QW2_HV_POOL];
+
+ /* POOL values only matter if POOL ctx is valid */
+ if (pool_regs[TM_WORD2] & 0x80) {
+
+ uint8_t pool_pipr = ipb_to_pipr(pool_regs[TM_IPB]);
+
+ /*
+ * Determine highest priority interrupt and
+ * remember which ring has it.
+ */
+ if (pool_pipr < pipr_min) {
+ pipr_min = pool_pipr;
+ ring_min = TM_QW2_HV_POOL;
+ }
+ }
+ }
+
+ regs[TM_PIPR] = pipr_min;
+
/* CPPR has changed, check if we need to raise a pending exception */
- xive_tctx_notify(tctx, ring);
+ xive_tctx_notify(tctx, ring_min);
}
void xive_tctx_ipb_update(XiveTCTX *tctx, uint8_t ring, uint8_t ipb)
@@ -179,6 +224,17 @@ static uint64_t xive_tm_pull_pool_ctx(XivePresenter *xptr, XiveTCTX *tctx,
return qw2w2;
}
+static uint64_t xive_tm_pull_phys_ctx(XivePresenter *xptr, XiveTCTX *tctx,
+ hwaddr offset, unsigned size)
+{
+ uint8_t qw3b8_prev = tctx->regs[TM_QW3_HV_PHYS + TM_WORD2];
+ uint8_t qw3b8;
+
+ qw3b8 = qw3b8_prev & ~TM_QW3B8_VT;
+ tctx->regs[TM_QW3_HV_PHYS + TM_WORD2] = qw3b8;
+ return qw3b8;
+}
+
static void xive_tm_vt_push(XivePresenter *xptr, XiveTCTX *tctx, hwaddr offset,
uint64_t value, unsigned size)
{
@@ -207,14 +263,14 @@ static uint64_t xive_tm_vt_poll(XivePresenter *xptr, XiveTCTX *tctx,
static const uint8_t xive_tm_hw_view[] = {
3, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, 0, 0, 0, /* QW-0 User */
3, 3, 3, 3, 3, 3, 0, 2, 3, 3, 3, 3, 0, 0, 0, 0, /* QW-1 OS */
- 0, 0, 3, 3, 0, 0, 0, 0, 3, 3, 3, 3, 0, 0, 0, 0, /* QW-2 POOL */
+ 0, 0, 3, 3, 0, 3, 3, 0, 3, 3, 3, 3, 0, 0, 0, 0, /* QW-2 POOL */
3, 3, 3, 3, 0, 3, 0, 2, 3, 0, 0, 3, 3, 3, 3, 0, /* QW-3 PHYS */
};
static const uint8_t xive_tm_hv_view[] = {
3, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, 0, 0, 0, /* QW-0 User */
3, 3, 3, 3, 3, 3, 0, 2, 3, 3, 3, 3, 0, 0, 0, 0, /* QW-1 OS */
- 0, 0, 3, 3, 0, 0, 0, 0, 0, 3, 3, 3, 0, 0, 0, 0, /* QW-2 POOL */
+ 0, 0, 3, 3, 0, 3, 3, 0, 0, 3, 3, 3, 0, 0, 0, 0, /* QW-2 POOL */
3, 3, 3, 3, 0, 3, 0, 2, 3, 0, 0, 3, 0, 0, 0, 0, /* QW-3 PHYS */
};
@@ -341,6 +397,19 @@ static void xive_tm_set_os_cppr(XivePresenter *xptr, XiveTCTX *tctx,
xive_tctx_set_cppr(tctx, TM_QW1_OS, value & 0xff);
}
+static void xive_tctx_set_lgs(XiveTCTX *tctx, uint8_t ring, uint8_t lgs)
+{
+ uint8_t *regs = &tctx->regs[ring];
+
+ regs[TM_LGS] = lgs;
+}
+
+static void xive_tm_set_os_lgs(XivePresenter *xptr, XiveTCTX *tctx,
+ hwaddr offset, uint64_t value, unsigned size)
+{
+ xive_tctx_set_lgs(tctx, TM_QW1_OS, value & 0xff);
+}
+
/*
* Adjust the IPB to allow a CPU to process event queues of other
* priorities during one physical interrupt cycle.
@@ -400,7 +469,7 @@ static uint64_t xive_tm_pull_os_ctx(XivePresenter *xptr, XiveTCTX *tctx,
qw1w2_new = xive_set_field32(TM_QW1W2_VO, qw1w2, 0);
xive_tctx_set_os_cam(tctx, qw1w2_new);
- xive_tctx_reset_os_signal(tctx);
+ xive_tctx_reset_signal(tctx, TM_QW1_OS);
return qw1w2;
}
@@ -488,20 +557,34 @@ static const XiveTmOp xive_tm_operations[] = {
* MMIOs below 2K : raw values and special operations without side
* effects
*/
- { XIVE_TM_OS_PAGE, TM_QW1_OS + TM_CPPR, 1, xive_tm_set_os_cppr, NULL },
- { XIVE_TM_HV_PAGE, TM_QW1_OS + TM_WORD2, 4, xive_tm_push_os_ctx, NULL },
- { XIVE_TM_HV_PAGE, TM_QW3_HV_PHYS + TM_CPPR, 1, xive_tm_set_hv_cppr, NULL },
- { XIVE_TM_HV_PAGE, TM_QW3_HV_PHYS + TM_WORD2, 1, xive_tm_vt_push, NULL },
- { XIVE_TM_HV_PAGE, TM_QW3_HV_PHYS + TM_WORD2, 1, NULL, xive_tm_vt_poll },
+ { XIVE_TM_OS_PAGE, TM_QW1_OS + TM_CPPR, 1, xive_tm_set_os_cppr,
+ NULL },
+ { XIVE_TM_HV_PAGE, TM_QW1_OS + TM_WORD2, 4, xive_tm_push_os_ctx,
+ NULL },
+ { XIVE_TM_HV_PAGE, TM_QW3_HV_PHYS + TM_CPPR, 1, xive_tm_set_hv_cppr,
+ NULL },
+ { XIVE_TM_HV_PAGE, TM_QW3_HV_PHYS + TM_WORD2, 1, xive_tm_vt_push,
+ NULL },
+ { XIVE_TM_HV_PAGE, TM_QW3_HV_PHYS + TM_WORD2, 1, NULL,
+ xive_tm_vt_poll },
/* MMIOs above 2K : special operations with side effects */
- { XIVE_TM_OS_PAGE, TM_SPC_ACK_OS_REG, 2, NULL, xive_tm_ack_os_reg },
- { XIVE_TM_OS_PAGE, TM_SPC_SET_OS_PENDING, 1, xive_tm_set_os_pending, NULL },
- { XIVE_TM_HV_PAGE, TM_SPC_PULL_OS_CTX, 4, NULL, xive_tm_pull_os_ctx },
- { XIVE_TM_HV_PAGE, TM_SPC_PULL_OS_CTX, 8, NULL, xive_tm_pull_os_ctx },
- { XIVE_TM_HV_PAGE, TM_SPC_ACK_HV_REG, 2, NULL, xive_tm_ack_hv_reg },
- { XIVE_TM_HV_PAGE, TM_SPC_PULL_POOL_CTX, 4, NULL, xive_tm_pull_pool_ctx },
- { XIVE_TM_HV_PAGE, TM_SPC_PULL_POOL_CTX, 8, NULL, xive_tm_pull_pool_ctx },
+ { XIVE_TM_OS_PAGE, TM_SPC_ACK_OS_REG, 2, NULL,
+ xive_tm_ack_os_reg },
+ { XIVE_TM_OS_PAGE, TM_SPC_SET_OS_PENDING, 1, xive_tm_set_os_pending,
+ NULL },
+ { XIVE_TM_HV_PAGE, TM_SPC_PULL_OS_CTX, 4, NULL,
+ xive_tm_pull_os_ctx },
+ { XIVE_TM_HV_PAGE, TM_SPC_PULL_OS_CTX, 8, NULL,
+ xive_tm_pull_os_ctx },
+ { XIVE_TM_HV_PAGE, TM_SPC_ACK_HV_REG, 2, NULL,
+ xive_tm_ack_hv_reg },
+ { XIVE_TM_HV_PAGE, TM_SPC_PULL_POOL_CTX, 4, NULL,
+ xive_tm_pull_pool_ctx },
+ { XIVE_TM_HV_PAGE, TM_SPC_PULL_POOL_CTX, 8, NULL,
+ xive_tm_pull_pool_ctx },
+ { XIVE_TM_HV_PAGE, TM_SPC_PULL_PHYS_CTX, 1, NULL,
+ xive_tm_pull_phys_ctx },
};
static const XiveTmOp xive2_tm_operations[] = {
@@ -509,20 +592,50 @@ static const XiveTmOp xive2_tm_operations[] = {
* MMIOs below 2K : raw values and special operations without side
* effects
*/
- { XIVE_TM_OS_PAGE, TM_QW1_OS + TM_CPPR, 1, xive_tm_set_os_cppr, NULL },
- { XIVE_TM_HV_PAGE, TM_QW1_OS + TM_WORD2, 4, xive2_tm_push_os_ctx, NULL },
- { XIVE_TM_HV_PAGE, TM_QW3_HV_PHYS + TM_CPPR, 1, xive_tm_set_hv_cppr, NULL },
- { XIVE_TM_HV_PAGE, TM_QW3_HV_PHYS + TM_WORD2, 1, xive_tm_vt_push, NULL },
- { XIVE_TM_HV_PAGE, TM_QW3_HV_PHYS + TM_WORD2, 1, NULL, xive_tm_vt_poll },
+ { XIVE_TM_OS_PAGE, TM_QW1_OS + TM_CPPR, 1, xive_tm_set_os_cppr,
+ NULL },
+ { XIVE_TM_HV_PAGE, TM_QW1_OS + TM_WORD2, 4, xive2_tm_push_os_ctx,
+ NULL },
+ { XIVE_TM_HV_PAGE, TM_QW1_OS + TM_WORD2, 8, xive2_tm_push_os_ctx,
+ NULL },
+ { XIVE_TM_OS_PAGE, TM_QW1_OS + TM_LGS, 1, xive_tm_set_os_lgs,
+ NULL },
+ { XIVE_TM_HV_PAGE, TM_QW3_HV_PHYS + TM_CPPR, 1, xive_tm_set_hv_cppr,
+ NULL },
+ { XIVE_TM_HV_PAGE, TM_QW3_HV_PHYS + TM_WORD2, 1, xive_tm_vt_push,
+ NULL },
+ { XIVE_TM_HV_PAGE, TM_QW3_HV_PHYS + TM_WORD2, 1, NULL,
+ xive_tm_vt_poll },
+ { XIVE_TM_HV_PAGE, TM_QW3_HV_PHYS + TM_T, 1, xive2_tm_set_hv_target,
+ NULL },
/* MMIOs above 2K : special operations with side effects */
- { XIVE_TM_OS_PAGE, TM_SPC_ACK_OS_REG, 2, NULL, xive_tm_ack_os_reg },
- { XIVE_TM_OS_PAGE, TM_SPC_SET_OS_PENDING, 1, xive_tm_set_os_pending, NULL },
- { XIVE_TM_HV_PAGE, TM_SPC_PULL_OS_CTX, 4, NULL, xive2_tm_pull_os_ctx },
- { XIVE_TM_HV_PAGE, TM_SPC_PULL_OS_CTX, 8, NULL, xive2_tm_pull_os_ctx },
- { XIVE_TM_HV_PAGE, TM_SPC_ACK_HV_REG, 2, NULL, xive_tm_ack_hv_reg },
- { XIVE_TM_HV_PAGE, TM_SPC_PULL_POOL_CTX, 4, NULL, xive_tm_pull_pool_ctx },
- { XIVE_TM_HV_PAGE, TM_SPC_PULL_POOL_CTX, 8, NULL, xive_tm_pull_pool_ctx },
+ { XIVE_TM_OS_PAGE, TM_SPC_ACK_OS_REG, 2, NULL,
+ xive_tm_ack_os_reg },
+ { XIVE_TM_OS_PAGE, TM_SPC_SET_OS_PENDING, 1, xive_tm_set_os_pending,
+ NULL },
+ { XIVE_TM_HV_PAGE, TM_SPC_PULL_OS_CTX_G2, 4, NULL,
+ xive2_tm_pull_os_ctx },
+ { XIVE_TM_HV_PAGE, TM_SPC_PULL_OS_CTX, 4, NULL,
+ xive2_tm_pull_os_ctx },
+ { XIVE_TM_HV_PAGE, TM_SPC_PULL_OS_CTX, 8, NULL,
+ xive2_tm_pull_os_ctx },
+ { XIVE_TM_HV_PAGE, TM_SPC_ACK_HV_REG, 2, NULL,
+ xive_tm_ack_hv_reg },
+ { XIVE_TM_HV_PAGE, TM_SPC_PULL_POOL_CTX_G2, 4, NULL,
+ xive_tm_pull_pool_ctx },
+ { XIVE_TM_HV_PAGE, TM_SPC_PULL_POOL_CTX, 4, NULL,
+ xive_tm_pull_pool_ctx },
+ { XIVE_TM_HV_PAGE, TM_SPC_PULL_POOL_CTX, 8, NULL,
+ xive_tm_pull_pool_ctx },
+ { XIVE_TM_HV_PAGE, TM_SPC_PULL_OS_CTX_OL, 1, xive2_tm_pull_os_ctx_ol,
+ NULL },
+ { XIVE_TM_HV_PAGE, TM_SPC_PULL_PHYS_CTX_G2, 4, NULL,
+ xive_tm_pull_phys_ctx },
+ { XIVE_TM_HV_PAGE, TM_SPC_PULL_PHYS_CTX, 1, NULL,
+ xive_tm_pull_phys_ctx },
+ { XIVE_TM_HV_PAGE, TM_SPC_PULL_PHYS_CTX_OL, 1, xive2_tm_pull_phys_ctx_ol,
+ NULL },
};
static const XiveTmOp *xive_tm_find_op(XivePresenter *xptr, hwaddr offset,
@@ -718,6 +831,10 @@ void xive_tctx_reset(XiveTCTX *tctx)
tctx->regs[TM_QW1_OS + TM_LSMFB] = 0xFF;
tctx->regs[TM_QW1_OS + TM_ACK_CNT] = 0xFF;
tctx->regs[TM_QW1_OS + TM_AGE] = 0xFF;
+ if (!(xive_presenter_get_config(tctx->xptr) &
+ XIVE_PRESENTER_GEN1_TIMA_OS)) {
+ tctx->regs[TM_QW1_OS + TM_OGEN] = 2;
+ }
/*
* Initialize PIPR to 0xFF to avoid phantom interrupts when the
@@ -1242,7 +1359,7 @@ static void xive_source_reset(void *dev)
static void xive_source_realize(DeviceState *dev, Error **errp)
{
XiveSource *xsrc = XIVE_SOURCE(dev);
- size_t esb_len = xive_source_esb_len(xsrc);
+ uint64_t esb_len = xive_source_esb_len(xsrc);
assert(xsrc->xive);
diff --git a/hw/intc/xive2.c b/hw/intc/xive2.c
index 1f15068..d1df35e 100644
--- a/hw/intc/xive2.c
+++ b/hw/intc/xive2.c
@@ -26,6 +26,43 @@ uint32_t xive2_router_get_config(Xive2Router *xrtr)
return xrc->get_config(xrtr);
}
+static int xive2_router_get_block_id(Xive2Router *xrtr)
+{
+ Xive2RouterClass *xrc = XIVE2_ROUTER_GET_CLASS(xrtr);
+
+ return xrc->get_block_id(xrtr);
+}
+
+static uint64_t xive2_nvp_reporting_addr(Xive2Nvp *nvp)
+{
+ uint64_t cache_addr;
+
+ cache_addr = xive_get_field32(NVP2_W6_REPORTING_LINE, nvp->w6) << 24 |
+ xive_get_field32(NVP2_W7_REPORTING_LINE, nvp->w7);
+ cache_addr <<= 8; /* aligned on a cache line pair */
+ return cache_addr;
+}
+
+static uint32_t xive2_nvgc_get_backlog(Xive2Nvgc *nvgc, uint8_t priority)
+{
+ uint32_t val = 0;
+ uint8_t *ptr, i;
+
+ if (priority > 7) {
+ return 0;
+ }
+
+ /*
+ * The per-priority backlog counters are 24-bit and the structure
+ * is stored in big endian
+ */
+ ptr = (uint8_t *)&nvgc->w2 + priority * 3;
+ for (i = 0; i < 3; i++, ptr++) {
+ val = (val << 8) + *ptr;
+ }
+ return val;
+}
+
void xive2_eas_pic_print_info(Xive2Eas *eas, uint32_t lisn, GString *buf)
{
if (!xive2_eas_is_valid(eas)) {
@@ -144,14 +181,20 @@ void xive2_nvp_pic_print_info(Xive2Nvp *nvp, uint32_t nvp_idx, GString *buf)
{
uint8_t eq_blk = xive_get_field32(NVP2_W5_VP_END_BLOCK, nvp->w5);
uint32_t eq_idx = xive_get_field32(NVP2_W5_VP_END_INDEX, nvp->w5);
+ uint64_t cache_line = xive2_nvp_reporting_addr(nvp);
if (!xive2_nvp_is_valid(nvp)) {
return;
}
- g_string_append_printf(buf, " %08x end:%02x/%04x IPB:%02x",
+ g_string_append_printf(buf, " %08x end:%02x/%04x IPB:%02x PGoFirst:%02x",
nvp_idx, eq_blk, eq_idx,
- xive_get_field32(NVP2_W2_IPB, nvp->w2));
+ xive_get_field32(NVP2_W2_IPB, nvp->w2),
+ xive_get_field32(NVP2_W0_PGOFIRST, nvp->w0));
+ if (cache_line) {
+ g_string_append_printf(buf, " reporting CL:%016"PRIx64, cache_line);
+ }
+
/*
* When the NVP is HW controlled, more fields are updated
*/
@@ -166,6 +209,23 @@ void xive2_nvp_pic_print_info(Xive2Nvp *nvp, uint32_t nvp_idx, GString *buf)
g_string_append_c(buf, '\n');
}
+void xive2_nvgc_pic_print_info(Xive2Nvgc *nvgc, uint32_t nvgc_idx, GString *buf)
+{
+ uint8_t i;
+
+ if (!xive2_nvgc_is_valid(nvgc)) {
+ return;
+ }
+
+ g_string_append_printf(buf, " %08x PGoNext:%02x bklog: ", nvgc_idx,
+ xive_get_field32(NVGC2_W0_PGONEXT, nvgc->w0));
+ for (i = 0; i <= XIVE_PRIORITY_MAX; i++) {
+ g_string_append_printf(buf, "[%d]=0x%x ",
+ i, xive2_nvgc_get_backlog(nvgc, i));
+ }
+ g_string_append_printf(buf, "\n");
+}
+
static void xive2_end_enqueue(Xive2End *end, uint32_t data)
{
uint64_t qaddr_base = xive2_end_qaddr(end);
@@ -210,13 +270,14 @@ static void xive2_end_enqueue(Xive2End *end, uint32_t data)
* the NVP by changing the H bit while the context is enabled
*/
-static void xive2_tctx_save_os_ctx(Xive2Router *xrtr, XiveTCTX *tctx,
- uint8_t nvp_blk, uint32_t nvp_idx)
+static void xive2_tctx_save_ctx(Xive2Router *xrtr, XiveTCTX *tctx,
+ uint8_t nvp_blk, uint32_t nvp_idx,
+ uint8_t ring)
{
CPUPPCState *env = &POWERPC_CPU(tctx->cs)->env;
uint32_t pir = env->spr_cb[SPR_PIR].default_value;
Xive2Nvp nvp;
- uint8_t *regs = &tctx->regs[TM_QW1_OS];
+ uint8_t *regs = &tctx->regs[ring];
if (xive2_router_get_nvp(xrtr, nvp_blk, nvp_idx, &nvp)) {
qemu_log_mask(LOG_GUEST_ERROR, "XIVE: No NVP %x/%x\n",
@@ -261,44 +322,190 @@ static void xive2_tctx_save_os_ctx(Xive2Router *xrtr, XiveTCTX *tctx,
xive2_router_write_nvp(xrtr, nvp_blk, nvp_idx, &nvp, 1);
}
-static void xive2_os_cam_decode(uint32_t cam, uint8_t *nvp_blk,
- uint32_t *nvp_idx, bool *vo, bool *ho)
+static void xive2_cam_decode(uint32_t cam, uint8_t *nvp_blk,
+ uint32_t *nvp_idx, bool *valid, bool *hw)
{
*nvp_blk = xive2_nvp_blk(cam);
*nvp_idx = xive2_nvp_idx(cam);
- *vo = !!(cam & TM2_QW1W2_VO);
- *ho = !!(cam & TM2_QW1W2_HO);
+ *valid = !!(cam & TM2_W2_VALID);
+ *hw = !!(cam & TM2_W2_HW);
}
-uint64_t xive2_tm_pull_os_ctx(XivePresenter *xptr, XiveTCTX *tctx,
- hwaddr offset, unsigned size)
+/*
+ * Encode the HW CAM line with 7bit or 8bit thread id. The thread id
+ * width and block id width is configurable at the IC level.
+ *
+ * chipid << 24 | 0000 0000 0000 0000 1 threadid (7Bit)
+ * chipid << 24 | 0000 0000 0000 0001 threadid (8Bit)
+ */
+static uint32_t xive2_tctx_hw_cam_line(XivePresenter *xptr, XiveTCTX *tctx)
{
Xive2Router *xrtr = XIVE2_ROUTER(xptr);
- uint32_t qw1w2 = xive_tctx_word2(&tctx->regs[TM_QW1_OS]);
- uint32_t qw1w2_new;
- uint32_t cam = be32_to_cpu(qw1w2);
+ CPUPPCState *env = &POWERPC_CPU(tctx->cs)->env;
+ uint32_t pir = env->spr_cb[SPR_PIR].default_value;
+ uint8_t blk = xive2_router_get_block_id(xrtr);
+ uint8_t tid_shift =
+ xive2_router_get_config(xrtr) & XIVE2_THREADID_8BITS ? 8 : 7;
+ uint8_t tid_mask = (1 << tid_shift) - 1;
+
+ return xive2_nvp_cam_line(blk, 1 << tid_shift | (pir & tid_mask));
+}
+
+static uint64_t xive2_tm_pull_ctx(XivePresenter *xptr, XiveTCTX *tctx,
+ hwaddr offset, unsigned size, uint8_t ring)
+{
+ Xive2Router *xrtr = XIVE2_ROUTER(xptr);
+ uint32_t target_ringw2 = xive_tctx_word2(&tctx->regs[ring]);
+ uint32_t cam = be32_to_cpu(target_ringw2);
uint8_t nvp_blk;
uint32_t nvp_idx;
- bool vo;
+ uint8_t cur_ring;
+ bool valid;
bool do_save;
- xive2_os_cam_decode(cam, &nvp_blk, &nvp_idx, &vo, &do_save);
+ xive2_cam_decode(cam, &nvp_blk, &nvp_idx, &valid, &do_save);
- if (!vo) {
+ if (!valid) {
qemu_log_mask(LOG_GUEST_ERROR, "XIVE: pulling invalid NVP %x/%x !?\n",
nvp_blk, nvp_idx);
}
- /* Invalidate CAM line */
- qw1w2_new = xive_set_field32(TM2_QW1W2_VO, qw1w2, 0);
- memcpy(&tctx->regs[TM_QW1_OS + TM_WORD2], &qw1w2_new, 4);
+ /* Invalidate CAM line of requested ring and all lower rings */
+ for (cur_ring = TM_QW0_USER; cur_ring <= ring;
+ cur_ring += XIVE_TM_RING_SIZE) {
+ uint32_t ringw2 = xive_tctx_word2(&tctx->regs[cur_ring]);
+ uint32_t ringw2_new = xive_set_field32(TM2_QW1W2_VO, ringw2, 0);
+ memcpy(&tctx->regs[cur_ring + TM_WORD2], &ringw2_new, 4);
+ }
if (xive2_router_get_config(xrtr) & XIVE2_VP_SAVE_RESTORE && do_save) {
- xive2_tctx_save_os_ctx(xrtr, tctx, nvp_blk, nvp_idx);
+ xive2_tctx_save_ctx(xrtr, tctx, nvp_blk, nvp_idx, ring);
+ }
+
+ /*
+ * Lower external interrupt line of requested ring and below except for
+ * USER, which doesn't exist.
+ */
+ for (cur_ring = TM_QW1_OS; cur_ring <= ring;
+ cur_ring += XIVE_TM_RING_SIZE) {
+ xive_tctx_reset_signal(tctx, cur_ring);
+ }
+ return target_ringw2;
+}
+
+uint64_t xive2_tm_pull_os_ctx(XivePresenter *xptr, XiveTCTX *tctx,
+ hwaddr offset, unsigned size)
+{
+ return xive2_tm_pull_ctx(xptr, tctx, offset, size, TM_QW1_OS);
+}
+
+#define REPORT_LINE_GEN1_SIZE 16
+
+static void xive2_tm_report_line_gen1(XiveTCTX *tctx, uint8_t *data,
+ uint8_t size)
+{
+ uint8_t *regs = tctx->regs;
+
+ g_assert(size == REPORT_LINE_GEN1_SIZE);
+ memset(data, 0, size);
+ /*
+ * See xive architecture for description of what is saved. It is
+ * hand-picked information to fit in 16 bytes.
+ */
+ data[0x0] = regs[TM_QW3_HV_PHYS + TM_NSR];
+ data[0x1] = regs[TM_QW3_HV_PHYS + TM_CPPR];
+ data[0x2] = regs[TM_QW3_HV_PHYS + TM_IPB];
+ data[0x3] = regs[TM_QW2_HV_POOL + TM_IPB];
+ data[0x4] = regs[TM_QW1_OS + TM_ACK_CNT];
+ data[0x5] = regs[TM_QW3_HV_PHYS + TM_LGS];
+ data[0x6] = 0xFF;
+ data[0x7] = regs[TM_QW3_HV_PHYS + TM_WORD2] & 0x80;
+ data[0x7] |= (regs[TM_QW2_HV_POOL + TM_WORD2] & 0x80) >> 1;
+ data[0x7] |= (regs[TM_QW1_OS + TM_WORD2] & 0x80) >> 2;
+ data[0x7] |= (regs[TM_QW3_HV_PHYS + TM_WORD2] & 0x3);
+ data[0x8] = regs[TM_QW1_OS + TM_NSR];
+ data[0x9] = regs[TM_QW1_OS + TM_CPPR];
+ data[0xA] = regs[TM_QW1_OS + TM_IPB];
+ data[0xB] = regs[TM_QW1_OS + TM_LGS];
+ if (regs[TM_QW0_USER + TM_WORD2] & 0x80) {
+ /*
+ * Logical server extension, except VU bit replaced by EB bit
+ * from NSR
+ */
+ data[0xC] = regs[TM_QW0_USER + TM_WORD2];
+ data[0xC] &= ~0x80;
+ data[0xC] |= regs[TM_QW0_USER + TM_NSR] & 0x80;
+ data[0xD] = regs[TM_QW0_USER + TM_WORD2 + 1];
+ data[0xE] = regs[TM_QW0_USER + TM_WORD2 + 2];
+ data[0xF] = regs[TM_QW0_USER + TM_WORD2 + 3];
}
+}
+
+static void xive2_tm_pull_ctx_ol(XivePresenter *xptr, XiveTCTX *tctx,
+ hwaddr offset, uint64_t value,
+ unsigned size, uint8_t ring)
+{
+ Xive2Router *xrtr = XIVE2_ROUTER(xptr);
+ uint32_t hw_cam, nvp_idx, xive2_cfg, reserved;
+ uint8_t nvp_blk;
+ Xive2Nvp nvp;
+ uint64_t phys_addr;
+ MemTxResult result;
- xive_tctx_reset_os_signal(tctx);
- return qw1w2;
+ hw_cam = xive2_tctx_hw_cam_line(xptr, tctx);
+ nvp_blk = xive2_nvp_blk(hw_cam);
+ nvp_idx = xive2_nvp_idx(hw_cam);
+
+ if (xive2_router_get_nvp(xrtr, nvp_blk, nvp_idx, &nvp)) {
+ qemu_log_mask(LOG_GUEST_ERROR, "XIVE: No NVP %x/%x\n",
+ nvp_blk, nvp_idx);
+ return;
+ }
+
+ if (!xive2_nvp_is_valid(&nvp)) {
+ qemu_log_mask(LOG_GUEST_ERROR, "XIVE: invalid NVP %x/%x\n",
+ nvp_blk, nvp_idx);
+ return;
+ }
+
+ xive2_cfg = xive2_router_get_config(xrtr);
+
+ phys_addr = xive2_nvp_reporting_addr(&nvp) + 0x80; /* odd line */
+ if (xive2_cfg & XIVE2_GEN1_TIMA_OS) {
+ uint8_t pull_ctxt[REPORT_LINE_GEN1_SIZE];
+
+ xive2_tm_report_line_gen1(tctx, pull_ctxt, REPORT_LINE_GEN1_SIZE);
+ result = dma_memory_write(&address_space_memory, phys_addr,
+ pull_ctxt, REPORT_LINE_GEN1_SIZE,
+ MEMTXATTRS_UNSPECIFIED);
+ assert(result == MEMTX_OK);
+ } else {
+ result = dma_memory_write(&address_space_memory, phys_addr,
+ &tctx->regs, sizeof(tctx->regs),
+ MEMTXATTRS_UNSPECIFIED);
+ assert(result == MEMTX_OK);
+ reserved = 0xFFFFFFFF;
+ result = dma_memory_write(&address_space_memory, phys_addr + 12,
+ &reserved, sizeof(reserved),
+ MEMTXATTRS_UNSPECIFIED);
+ assert(result == MEMTX_OK);
+ }
+
+ /* the rest is similar to pull context to registers */
+ xive2_tm_pull_ctx(xptr, tctx, offset, size, ring);
+}
+
+void xive2_tm_pull_os_ctx_ol(XivePresenter *xptr, XiveTCTX *tctx,
+ hwaddr offset, uint64_t value, unsigned size)
+{
+ xive2_tm_pull_ctx_ol(xptr, tctx, offset, value, size, TM_QW1_OS);
+}
+
+
+void xive2_tm_pull_phys_ctx_ol(XivePresenter *xptr, XiveTCTX *tctx,
+ hwaddr offset, uint64_t value, unsigned size)
+{
+ xive2_tm_pull_ctx_ol(xptr, tctx, offset, value, size, TM_QW3_HV_PHYS);
}
static uint8_t xive2_tctx_restore_os_ctx(Xive2Router *xrtr, XiveTCTX *tctx,
@@ -390,17 +597,31 @@ static void xive2_tctx_need_resend(Xive2Router *xrtr, XiveTCTX *tctx,
void xive2_tm_push_os_ctx(XivePresenter *xptr, XiveTCTX *tctx,
hwaddr offset, uint64_t value, unsigned size)
{
- uint32_t cam = value;
- uint32_t qw1w2 = cpu_to_be32(cam);
+ uint32_t cam;
+ uint32_t qw1w2;
+ uint64_t qw1dw1;
uint8_t nvp_blk;
uint32_t nvp_idx;
bool vo;
bool do_restore;
- xive2_os_cam_decode(cam, &nvp_blk, &nvp_idx, &vo, &do_restore);
-
/* First update the thead context */
- memcpy(&tctx->regs[TM_QW1_OS + TM_WORD2], &qw1w2, 4);
+ switch (size) {
+ case 4:
+ cam = value;
+ qw1w2 = cpu_to_be32(cam);
+ memcpy(&tctx->regs[TM_QW1_OS + TM_WORD2], &qw1w2, 4);
+ break;
+ case 8:
+ cam = value >> 32;
+ qw1dw1 = cpu_to_be64(value);
+ memcpy(&tctx->regs[TM_QW1_OS + TM_WORD2], &qw1dw1, 8);
+ break;
+ default:
+ g_assert_not_reached();
+ }
+
+ xive2_cam_decode(cam, &nvp_blk, &nvp_idx, &vo, &do_restore);
/* Check the interrupt pending bits */
if (vo) {
@@ -409,6 +630,19 @@ void xive2_tm_push_os_ctx(XivePresenter *xptr, XiveTCTX *tctx,
}
}
+static void xive2_tctx_set_target(XiveTCTX *tctx, uint8_t ring, uint8_t target)
+{
+ uint8_t *regs = &tctx->regs[ring];
+
+ regs[TM_T] = target;
+}
+
+void xive2_tm_set_hv_target(XivePresenter *xptr, XiveTCTX *tctx,
+ hwaddr offset, uint64_t value, unsigned size)
+{
+ xive2_tctx_set_target(tctx, TM_QW3_HV_PHYS, value & 0xff);
+}
+
/*
* XIVE Router (aka. Virtualization Controller or IVRE)
*/
@@ -471,31 +705,22 @@ int xive2_router_write_nvp(Xive2Router *xrtr, uint8_t nvp_blk, uint32_t nvp_idx,
return xrc->write_nvp(xrtr, nvp_blk, nvp_idx, nvp, word_number);
}
-static int xive2_router_get_block_id(Xive2Router *xrtr)
+int xive2_router_get_nvgc(Xive2Router *xrtr, bool crowd,
+ uint8_t nvgc_blk, uint32_t nvgc_idx,
+ Xive2Nvgc *nvgc)
{
Xive2RouterClass *xrc = XIVE2_ROUTER_GET_CLASS(xrtr);
- return xrc->get_block_id(xrtr);
+ return xrc->get_nvgc(xrtr, crowd, nvgc_blk, nvgc_idx, nvgc);
}
-/*
- * Encode the HW CAM line with 7bit or 8bit thread id. The thread id
- * width and block id width is configurable at the IC level.
- *
- * chipid << 24 | 0000 0000 0000 0000 1 threadid (7Bit)
- * chipid << 24 | 0000 0000 0000 0001 threadid (8Bit)
- */
-static uint32_t xive2_tctx_hw_cam_line(XivePresenter *xptr, XiveTCTX *tctx)
+int xive2_router_write_nvgc(Xive2Router *xrtr, bool crowd,
+ uint8_t nvgc_blk, uint32_t nvgc_idx,
+ Xive2Nvgc *nvgc)
{
- Xive2Router *xrtr = XIVE2_ROUTER(xptr);
- CPUPPCState *env = &POWERPC_CPU(tctx->cs)->env;
- uint32_t pir = env->spr_cb[SPR_PIR].default_value;
- uint8_t blk = xive2_router_get_block_id(xrtr);
- uint8_t tid_shift =
- xive2_router_get_config(xrtr) & XIVE2_THREADID_8BITS ? 8 : 7;
- uint8_t tid_mask = (1 << tid_shift) - 1;
+ Xive2RouterClass *xrc = XIVE2_ROUTER_GET_CLASS(xrtr);
- return xive2_nvp_cam_line(blk, 1 << tid_shift | (pir & tid_mask));
+ return xrc->write_nvgc(xrtr, crowd, nvgc_blk, nvgc_idx, nvgc);
}
/*
diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c
index b760c6d..6433348 100644
--- a/hw/ppc/e500.c
+++ b/hw/ppc/e500.c
@@ -721,11 +721,21 @@ static int ppce500_prep_device_tree(PPCE500MachineState *machine,
kernel_base, kernel_size, true);
}
-hwaddr booke206_page_size_to_tlb(uint64_t size)
+static hwaddr booke206_page_size_to_tlb(uint64_t size)
{
return 63 - clz64(size / KiB);
}
+void booke206_set_tlb(ppcmas_tlb_t *tlb, target_ulong va, hwaddr pa,
+ hwaddr len)
+{
+ tlb->mas1 = booke206_page_size_to_tlb(len) << MAS1_TSIZE_SHIFT;
+ tlb->mas1 |= MAS1_VALID;
+ tlb->mas2 = va & TARGET_PAGE_MASK;
+ tlb->mas7_3 = pa & TARGET_PAGE_MASK;
+ tlb->mas7_3 |= MAS3_UR | MAS3_UW | MAS3_UX | MAS3_SR | MAS3_SW | MAS3_SX;
+}
+
static int booke206_initial_map_tsize(CPUPPCState *env)
{
struct boot_info *bi = env->load_info;
@@ -751,25 +761,6 @@ static uint64_t mmubooke_initial_mapsize(CPUPPCState *env)
return (1ULL << 10 << tsize);
}
-/* Create -kernel TLB entries for BookE. */
-static void mmubooke_create_initial_mapping(CPUPPCState *env)
-{
- ppcmas_tlb_t *tlb = booke206_get_tlbm(env, 1, 0, 0);
- hwaddr size;
- int ps;
-
- ps = booke206_initial_map_tsize(env);
- size = (ps << MAS1_TSIZE_SHIFT);
- tlb->mas1 = MAS1_VALID | size;
- tlb->mas2 = 0;
- tlb->mas7_3 = 0;
- tlb->mas7_3 |= MAS3_UR | MAS3_UW | MAS3_UX | MAS3_SR | MAS3_SW | MAS3_SX;
-
-#ifdef CONFIG_KVM
- env->tlb_dirty = true;
-#endif
-}
-
static void ppce500_cpu_reset_sec(void *opaque)
{
PowerPCCPU *cpu = opaque;
@@ -786,6 +777,8 @@ static void ppce500_cpu_reset(void *opaque)
CPUState *cs = CPU(cpu);
CPUPPCState *env = &cpu->env;
struct boot_info *bi = env->load_info;
+ uint64_t map_size = mmubooke_initial_mapsize(env);
+ ppcmas_tlb_t *tlb = booke206_get_tlbm(env, 1, 0, 0);
cpu_reset(cs);
@@ -796,11 +789,15 @@ static void ppce500_cpu_reset(void *opaque)
env->gpr[4] = 0;
env->gpr[5] = 0;
env->gpr[6] = EPAPR_MAGIC;
- env->gpr[7] = mmubooke_initial_mapsize(env);
+ env->gpr[7] = map_size;
env->gpr[8] = 0;
env->gpr[9] = 0;
env->nip = bi->entry;
- mmubooke_create_initial_mapping(env);
+ /* create initial mapping */
+ booke206_set_tlb(tlb, 0, 0, map_size);
+#ifdef CONFIG_KVM
+ env->tlb_dirty = true;
+#endif
}
static DeviceState *ppce500_init_mpic_qemu(PPCE500MachineState *pms,
diff --git a/hw/ppc/e500.h b/hw/ppc/e500.h
index 8c09ef9..01db102 100644
--- a/hw/ppc/e500.h
+++ b/hw/ppc/e500.h
@@ -41,8 +41,6 @@ struct PPCE500MachineClass {
void ppce500_init(MachineState *machine);
-hwaddr booke206_page_size_to_tlb(uint64_t size);
-
#define TYPE_PPCE500_MACHINE "ppce500-base-machine"
OBJECT_DECLARE_TYPE(PPCE500MachineState, PPCE500MachineClass, PPCE500_MACHINE)
diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index 795acc2..f0f0d75 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -736,21 +736,27 @@ static void pnv_reset(MachineState *machine, ResetType type)
}
}
- fdt = pnv_dt_create(machine);
-
- /* Pack resulting tree */
- _FDT((fdt_pack(fdt)));
+ if (machine->fdt) {
+ fdt = machine->fdt;
+ } else {
+ fdt = pnv_dt_create(machine);
+ /* Pack resulting tree */
+ _FDT((fdt_pack(fdt)));
+ }
qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt));
cpu_physical_memory_write(PNV_FDT_ADDR, fdt, fdt_totalsize(fdt));
- /*
- * Set machine->fdt for 'dumpdtb' QMP/HMP command. Free
- * the existing machine->fdt to avoid leaking it during
- * a reset.
- */
- g_free(machine->fdt);
- machine->fdt = fdt;
+ /* Update machine->fdt with latest fdt */
+ if (machine->fdt != fdt) {
+ /*
+ * Set machine->fdt for 'dumpdtb' QMP/HMP command. Free
+ * the existing machine->fdt to avoid leaking it during
+ * a reset.
+ */
+ g_free(machine->fdt);
+ machine->fdt = fdt;
+ }
}
static ISABus *pnv_chip_power8_isa_create(PnvChip *chip, Error **errp)
@@ -952,6 +958,14 @@ static void pnv_init(MachineState *machine)
g_free(sz);
exit(EXIT_FAILURE);
}
+
+ /* checks for invalid option combinations */
+ if (machine->dtb && (strlen(machine->kernel_cmdline) != 0)) {
+ error_report("-append and -dtb cannot be used together, as passed"
+ " command line is ignored in case of custom dtb");
+ exit(EXIT_FAILURE);
+ }
+
memory_region_add_subregion(get_system_memory(), 0, machine->ram);
/*
@@ -1003,6 +1017,21 @@ static void pnv_init(MachineState *machine)
}
}
+ /* load dtb if passed */
+ if (machine->dtb) {
+ int fdt_size;
+
+ warn_report("with manually passed dtb, some options like '-append'"
+ " will get ignored and the dtb passed will be used as-is");
+
+ /* read the file 'machine->dtb', and load it into 'fdt' buffer */
+ machine->fdt = load_device_tree(machine->dtb, &fdt_size);
+ if (!machine->fdt) {
+ error_report("Could not load dtb '%s'", machine->dtb);
+ exit(1);
+ }
+ }
+
/* MSIs are supported on this platform */
msi_nonbroken = true;
diff --git a/hw/ppc/pnv_adu.c b/hw/ppc/pnv_adu.c
index 81b7d6e..f636ded 100644
--- a/hw/ppc/pnv_adu.c
+++ b/hw/ppc/pnv_adu.c
@@ -116,6 +116,12 @@ static void pnv_adu_xscom_write(void *opaque, hwaddr addr, uint64_t val,
uint32_t lpc_size = lpc_cmd_size(adu);
uint64_t data = 0;
+ if (!is_power_of_2(lpc_size) || lpc_size > sizeof(data)) {
+ qemu_log_mask(LOG_GUEST_ERROR, "ADU: Unsupported LPC access "
+ "size:%" PRId32 "\n", lpc_size);
+ break;
+ }
+
pnv_lpc_opb_read(adu->lpc, lpc_addr, (void *)&data, lpc_size);
/*
@@ -135,6 +141,12 @@ static void pnv_adu_xscom_write(void *opaque, hwaddr addr, uint64_t val,
uint32_t lpc_size = lpc_cmd_size(adu);
uint64_t data;
+ if (!is_power_of_2(lpc_size) || lpc_size > sizeof(data)) {
+ qemu_log_mask(LOG_GUEST_ERROR, "ADU: Unsupported LPC access "
+ "size:%" PRId32 "\n", lpc_size);
+ break;
+ }
+
data = cpu_to_be64(val) >> ((lpc_addr & 7) * 8); /* See above */
pnv_lpc_opb_write(adu->lpc, lpc_addr, (void *)&data, lpc_size);
}
diff --git a/hw/ppc/pnv_lpc.c b/hw/ppc/pnv_lpc.c
index f8aad95..8c203d2 100644
--- a/hw/ppc/pnv_lpc.c
+++ b/hw/ppc/pnv_lpc.c
@@ -427,21 +427,27 @@ static void pnv_lpc_eval_serirq_routes(PnvLpcController *lpc)
int irq;
if (!lpc->psi_has_serirq) {
- if ((lpc->opb_irq_route0 & PPC_BITMASK(8, 13)) ||
- (lpc->opb_irq_route1 & PPC_BITMASK(4, 31))) {
+ if ((lpc->opb_irq_route0 & PPC_BITMASK32(8, 13)) ||
+ (lpc->opb_irq_route1 & PPC_BITMASK32(4, 31))) {
qemu_log_mask(LOG_GUEST_ERROR,
"OPB: setting serirq routing on POWER8 system, ignoring.\n");
}
return;
}
+ /*
+ * Each of the ISA irqs is routed to one of the 4 SERIRQ irqs with 2
+ * bits, split across 2 OPB registers.
+ */
for (irq = 0; irq <= 13; irq++) {
- int serirq = (lpc->opb_irq_route1 >> (31 - 5 - (irq * 2))) & 0x3;
+ int serirq = extract32(lpc->opb_irq_route1,
+ PPC_BIT32_NR(5 + irq * 2), 2);
lpc->irq_to_serirq_route[irq] = serirq;
}
for (irq = 14; irq < ISA_NUM_IRQS; irq++) {
- int serirq = (lpc->opb_irq_route0 >> (31 - 9 - (irq * 2))) & 0x3;
+ int serirq = extract32(lpc->opb_irq_route0,
+ PPC_BIT32_NR(9 + (irq - 14) * 2), 2);
lpc->irq_to_serirq_route[irq] = serirq;
}
}
diff --git a/hw/ppc/ppc.c b/hw/ppc/ppc.c
index fde4619..b86b584 100644
--- a/hw/ppc/ppc.c
+++ b/hw/ppc/ppc.c
@@ -728,7 +728,9 @@ static inline int64_t __cpu_ppc_load_decr(CPUPPCState *env, int64_t now,
int64_t decr;
n = ns_to_tb(tb_env->decr_freq, now);
- if (next > n && tb_env->flags & PPC_TIMER_BOOKE) {
+
+ /* BookE timers stop when reaching 0. */
+ if (next < n && tb_env->flags & PPC_TIMER_BOOKE) {
decr = 0;
} else {
decr = next - n;
diff --git a/hw/ppc/ppc440_bamboo.c b/hw/ppc/ppc440_bamboo.c
index 96d9ce6..a55f108 100644
--- a/hw/ppc/ppc440_bamboo.c
+++ b/hw/ppc/ppc440_bamboo.c
@@ -110,29 +110,6 @@ static int bamboo_load_device_tree(MachineState *machine,
return 0;
}
-/* Create reset TLB entries for BookE, spanning the 32bit addr space. */
-static void mmubooke_create_initial_mapping(CPUPPCState *env,
- target_ulong va,
- hwaddr pa)
-{
- ppcemb_tlb_t *tlb = &env->tlb.tlbe[0];
-
- tlb->attr = 0;
- tlb->prot = PAGE_VALID | ((PAGE_READ | PAGE_WRITE | PAGE_EXEC) << 4);
- tlb->size = 1U << 31; /* up to 0x80000000 */
- tlb->EPN = va & TARGET_PAGE_MASK;
- tlb->RPN = pa & TARGET_PAGE_MASK;
- tlb->PID = 0;
-
- tlb = &env->tlb.tlbe[1];
- tlb->attr = 0;
- tlb->prot = PAGE_VALID | ((PAGE_READ | PAGE_WRITE | PAGE_EXEC) << 4);
- tlb->size = 1U << 31; /* up to 0xffffffff */
- tlb->EPN = 0x80000000 & TARGET_PAGE_MASK;
- tlb->RPN = 0x80000000 & TARGET_PAGE_MASK;
- tlb->PID = 0;
-}
-
static void main_cpu_reset(void *opaque)
{
PowerPCCPU *cpu = opaque;
@@ -143,8 +120,9 @@ static void main_cpu_reset(void *opaque)
env->gpr[3] = FDT_ADDR;
env->nip = entry;
- /* Create a mapping for the kernel. */
- mmubooke_create_initial_mapping(env, 0, 0);
+ /* Create a mapping spanning the 32bit addr space. */
+ booke_set_tlb(&env->tlb.tlbe[0], 0, 0, 1U << 31);
+ booke_set_tlb(&env->tlb.tlbe[1], 0x80000000, 0x80000000, 1U << 31);
}
static void bamboo_init(MachineState *machine)
diff --git a/hw/ppc/ppc_booke.c b/hw/ppc/ppc_booke.c
index ca22da1..c8849e6 100644
--- a/hw/ppc/ppc_booke.c
+++ b/hw/ppc/ppc_booke.c
@@ -31,6 +31,16 @@
#include "hw/loader.h"
#include "kvm_ppc.h"
+void booke_set_tlb(ppcemb_tlb_t *tlb, target_ulong va, hwaddr pa,
+ target_ulong size)
+{
+ tlb->attr = 0;
+ tlb->prot = PAGE_RWX << 4 | PAGE_VALID;
+ tlb->size = size;
+ tlb->EPN = va & TARGET_PAGE_MASK;
+ tlb->RPN = pa & TARGET_PAGE_MASK;
+ tlb->PID = 0;
+}
/* Timer Control Register */
diff --git a/hw/ppc/ppce500_spin.c b/hw/ppc/ppce500_spin.c
index e08739a..93b1632 100644
--- a/hw/ppc/ppce500_spin.c
+++ b/hw/ppc/ppce500_spin.c
@@ -33,6 +33,7 @@
#include "hw/hw.h"
#include "hw/sysbus.h"
#include "sysemu/hw_accel.h"
+#include "hw/ppc/ppc.h"
#include "e500.h"
#include "qom/object.h"
@@ -70,30 +71,12 @@ static void spin_reset(DeviceState *dev)
}
}
-static void mmubooke_create_initial_mapping(CPUPPCState *env,
- target_ulong va,
- hwaddr pa,
- hwaddr len)
-{
- ppcmas_tlb_t *tlb = booke206_get_tlbm(env, 1, 0, 1);
- hwaddr size;
-
- size = (booke206_page_size_to_tlb(len) << MAS1_TSIZE_SHIFT);
- tlb->mas1 = MAS1_VALID | size;
- tlb->mas2 = (va & TARGET_PAGE_MASK) | MAS2_M;
- tlb->mas7_3 = pa & TARGET_PAGE_MASK;
- tlb->mas7_3 |= MAS3_UR | MAS3_UW | MAS3_UX | MAS3_SR | MAS3_SW | MAS3_SX;
-#ifdef CONFIG_KVM
- env->tlb_dirty = true;
-#endif
-}
-
static void spin_kick(CPUState *cs, run_on_cpu_data data)
{
CPUPPCState *env = cpu_env(cs);
SpinInfo *curspin = data.host_ptr;
- hwaddr map_size = 64 * MiB;
- hwaddr map_start;
+ hwaddr map_start, map_size = 64 * MiB;
+ ppcmas_tlb_t *tlb = booke206_get_tlbm(env, 1, 0, 1);
cpu_synchronize_state(cs);
stl_p(&curspin->pir, env->spr[SPR_BOOKE_PIR]);
@@ -107,7 +90,12 @@ static void spin_kick(CPUState *cs, run_on_cpu_data data)
env->gpr[9] = 0;
map_start = ldq_p(&curspin->addr) & ~(map_size - 1);
- mmubooke_create_initial_mapping(env, 0, map_start, map_size);
+ /* create initial mapping */
+ booke206_set_tlb(tlb, 0, map_start, map_size);
+ tlb->mas2 |= MAS2_M;
+#ifdef CONFIG_KVM
+ env->tlb_dirty = true;
+#endif
cs->halted = 0;
cs->exception_index = -1;
diff --git a/hw/ppc/sam460ex.c b/hw/ppc/sam460ex.c
index 1fce093..78e2a46 100644
--- a/hw/ppc/sam460ex.c
+++ b/hw/ppc/sam460ex.c
@@ -213,38 +213,6 @@ static int sam460ex_load_device_tree(MachineState *machine,
return fdt_size;
}
-/* Create reset TLB entries for BookE, mapping only the flash memory. */
-static void mmubooke_create_initial_mapping_uboot(CPUPPCState *env)
-{
- ppcemb_tlb_t *tlb = &env->tlb.tlbe[0];
-
- /* on reset the flash is mapped by a shadow TLB,
- * but since we don't implement them we need to use
- * the same values U-Boot will use to avoid a fault.
- */
- tlb->attr = 0;
- tlb->prot = PAGE_VALID | ((PAGE_READ | PAGE_WRITE | PAGE_EXEC) << 4);
- tlb->size = 0x10000000; /* up to 0xffffffff */
- tlb->EPN = 0xf0000000 & TARGET_PAGE_MASK;
- tlb->RPN = (0xf0000000 & TARGET_PAGE_MASK) | 0x4;
- tlb->PID = 0;
-}
-
-/* Create reset TLB entries for BookE, spanning the 32bit addr space. */
-static void mmubooke_create_initial_mapping(CPUPPCState *env,
- target_ulong va,
- hwaddr pa)
-{
- ppcemb_tlb_t *tlb = &env->tlb.tlbe[0];
-
- tlb->attr = 0;
- tlb->prot = PAGE_VALID | ((PAGE_READ | PAGE_WRITE | PAGE_EXEC) << 4);
- tlb->size = 1 << 31; /* up to 0x80000000 */
- tlb->EPN = va & TARGET_PAGE_MASK;
- tlb->RPN = pa & TARGET_PAGE_MASK;
- tlb->PID = 0;
-}
-
static void main_cpu_reset(void *opaque)
{
PowerPCCPU *cpu = opaque;
@@ -253,20 +221,27 @@ static void main_cpu_reset(void *opaque)
cpu_reset(CPU(cpu));
- /* either we have a kernel to boot or we jump to U-Boot */
+ /*
+ * On reset the flash is mapped by a shadow TLB, but since we
+ * don't implement them we need to use the same values U-Boot
+ * will use to avoid a fault.
+ * either we have a kernel to boot or we jump to U-Boot
+ */
if (bi->entry != UBOOT_ENTRY) {
env->gpr[1] = (16 * MiB) - 8;
env->gpr[3] = FDT_ADDR;
env->nip = bi->entry;
/* Create a mapping for the kernel. */
- mmubooke_create_initial_mapping(env, 0, 0);
+ booke_set_tlb(&env->tlb.tlbe[0], 0, 0, 1 << 31);
env->gpr[6] = tswap32(EPAPR_MAGIC);
env->gpr[7] = (16 * MiB) - 8; /* bi->ima_size; */
} else {
env->nip = UBOOT_ENTRY;
- mmubooke_create_initial_mapping_uboot(env);
+ /* Create a mapping for U-Boot. */
+ booke_set_tlb(&env->tlb.tlbe[0], 0xf0000000, 0xf0000000, 0x10000000);
+ env->tlb.tlbe[0].RPN |= 4;
}
}
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 2c10a70..5c02037 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -132,61 +132,6 @@ static bool spapr_is_thread0_in_vcore(SpaprMachineState *spapr,
return spapr_get_vcpu_id(cpu) % spapr->vsmt == 0;
}
-static bool pre_2_10_vmstate_dummy_icp_needed(void *opaque)
-{
- /* Dummy entries correspond to unused ICPState objects in older QEMUs,
- * and newer QEMUs don't even have them. In both cases, we don't want
- * to send anything on the wire.
- */
- return false;
-}
-
-static const VMStateDescription pre_2_10_vmstate_dummy_icp = {
- /*
- * Hack ahead. We can't have two devices with the same name and
- * instance id. So I rename this to pass make check.
- * Real help from people who knows the hardware is needed.
- */
- .name = "icp/server",
- .version_id = 1,
- .minimum_version_id = 1,
- .needed = pre_2_10_vmstate_dummy_icp_needed,
- .fields = (const VMStateField[]) {
- VMSTATE_UNUSED(4), /* uint32_t xirr */
- VMSTATE_UNUSED(1), /* uint8_t pending_priority */
- VMSTATE_UNUSED(1), /* uint8_t mfrr */
- VMSTATE_END_OF_LIST()
- },
-};
-
-/*
- * See comment in hw/intc/xics.c:icp_realize()
- *
- * You have to remove vmstate_replace_hack_for_ppc() when you remove
- * the machine types that need the following function.
- */
-static void pre_2_10_vmstate_register_dummy_icp(int i)
-{
- vmstate_register(NULL, i, &pre_2_10_vmstate_dummy_icp,
- (void *)(uintptr_t) i);
-}
-
-/*
- * See comment in hw/intc/xics.c:icp_realize()
- *
- * You have to remove vmstate_replace_hack_for_ppc() when you remove
- * the machine types that need the following function.
- */
-static void pre_2_10_vmstate_unregister_dummy_icp(int i)
-{
- /*
- * This used to be:
- *
- * vmstate_unregister(NULL, &pre_2_10_vmstate_dummy_icp,
- * (void *)(uintptr_t) i);
- */
-}
-
int spapr_max_server_number(SpaprMachineState *spapr)
{
MachineState *ms = MACHINE(spapr);
@@ -682,7 +627,6 @@ static int spapr_dt_dynamic_reconfiguration_memory(SpaprMachineState *spapr,
static int spapr_dt_memory(SpaprMachineState *spapr, void *fdt)
{
MachineState *machine = MACHINE(spapr);
- SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
hwaddr mem_start, node_size;
int i, nb_nodes = machine->numa_state->num_nodes;
NodeInfo *nodes = machine->numa_state->nodes;
@@ -724,7 +668,6 @@ static int spapr_dt_memory(SpaprMachineState *spapr, void *fdt)
if (spapr_ovec_test(spapr->ov5_cas, OV5_DRCONF_MEMORY)) {
int ret;
- g_assert(smc->dr_lmb_enabled);
ret = spapr_dt_dynamic_reconfiguration_memory(spapr, fdt);
if (ret) {
return ret;
@@ -1307,9 +1250,7 @@ void *spapr_build_fdt(SpaprMachineState *spapr, bool reset, size_t space)
spapr_dt_cpus(fdt, spapr);
/* ibm,drc-indexes and friends */
- if (smc->dr_lmb_enabled) {
- root_drc_type_mask |= SPAPR_DR_CONNECTOR_TYPE_LMB;
- }
+ root_drc_type_mask |= SPAPR_DR_CONNECTOR_TYPE_LMB;
if (smc->dr_phb_enabled) {
root_drc_type_mask |= SPAPR_DR_CONNECTOR_TYPE_PHB;
}
@@ -2715,7 +2656,6 @@ static void spapr_init_cpus(SpaprMachineState *spapr)
{
MachineState *machine = MACHINE(spapr);
MachineClass *mc = MACHINE_GET_CLASS(machine);
- SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine);
const char *type = spapr_get_cpu_core_type(machine->cpu_type);
const CPUArchIdList *possible_cpus;
unsigned int smp_cpus = machine->smp.cpus;
@@ -2744,15 +2684,6 @@ static void spapr_init_cpus(SpaprMachineState *spapr)
boot_cores_nr = possible_cpus->len;
}
- if (smc->pre_2_10_has_unused_icps) {
- for (i = 0; i < spapr_max_server_number(spapr); i++) {
- /* Dummy entries get deregistered when real ICPState objects
- * are registered during CPU core hotplug.
- */
- pre_2_10_vmstate_register_dummy_icp(i);
- }
- }
-
for (i = 0; i < possible_cpus->len; i++) {
int core_id = i * smp_threads;
@@ -2929,10 +2860,8 @@ static void spapr_machine_init(MachineState *machine)
spapr->ov5 = spapr_ovec_new();
spapr->ov5_cas = spapr_ovec_new();
- if (smc->dr_lmb_enabled) {
- spapr_ovec_set(spapr->ov5, OV5_DRCONF_MEMORY);
- spapr_validate_node_memory(machine, &error_fatal);
- }
+ spapr_ovec_set(spapr->ov5, OV5_DRCONF_MEMORY);
+ spapr_validate_node_memory(machine, &error_fatal);
spapr_ovec_set(spapr->ov5, OV5_FORM1_AFFINITY);
@@ -3016,9 +2945,7 @@ static void spapr_machine_init(MachineState *machine)
machine_memory_devices_init(machine, device_mem_base, device_mem_size);
}
- if (smc->dr_lmb_enabled) {
- spapr_create_lmb_dr_connectors(spapr);
- }
+ spapr_create_lmb_dr_connectors(spapr);
if (mc->nvdimm_supported) {
spapr_create_nvdimm_dr_connectors(spapr);
@@ -3078,11 +3005,7 @@ static void spapr_machine_init(MachineState *machine)
}
if (machine->usb) {
- if (smc->use_ohci_by_default) {
- pci_create_simple(phb->bus, -1, "pci-ohci");
- } else {
- pci_create_simple(phb->bus, -1, "nec-usb-xhci");
- }
+ pci_create_simple(phb->bus, -1, "nec-usb-xhci");
if (has_vga) {
USBBus *usb_bus;
@@ -3662,7 +3585,6 @@ static void spapr_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev)
static void spapr_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
Error **errp)
{
- const SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(hotplug_dev);
SpaprMachineState *spapr = SPAPR_MACHINE(hotplug_dev);
bool is_nvdimm = object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM);
PCDIMMDevice *dimm = PC_DIMM(dev);
@@ -3671,11 +3593,6 @@ static void spapr_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
Object *memdev;
hwaddr pagesize;
- if (!smc->dr_lmb_enabled) {
- error_setg(errp, "Memory hotplug not supported for this machine");
- return;
- }
-
size = memory_device_get_region_size(MEMORY_DEVICE(dimm), &local_err);
if (local_err) {
error_propagate(errp, local_err);
@@ -3932,21 +3849,9 @@ void spapr_core_release(DeviceState *dev)
static void spapr_core_unplug(HotplugHandler *hotplug_dev, DeviceState *dev)
{
MachineState *ms = MACHINE(hotplug_dev);
- SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(ms);
CPUCore *cc = CPU_CORE(dev);
CPUArchId *core_slot = spapr_find_cpu_slot(ms, cc->core_id, NULL);
- if (smc->pre_2_10_has_unused_icps) {
- SpaprCpuCore *sc = SPAPR_CPU_CORE(OBJECT(dev));
- int i;
-
- for (i = 0; i < cc->nr_threads; i++) {
- CPUState *cs = CPU(sc->threads[i]);
-
- pre_2_10_vmstate_register_dummy_icp(cs->cpu_index);
- }
- }
-
assert(core_slot);
core_slot->cpu = NULL;
qdev_unrealize(dev);
@@ -4027,7 +3932,6 @@ static void spapr_core_plug(HotplugHandler *hotplug_dev, DeviceState *dev)
{
SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev));
MachineClass *mc = MACHINE_GET_CLASS(spapr);
- SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
SpaprCpuCore *core = SPAPR_CPU_CORE(OBJECT(dev));
CPUCore *cc = CPU_CORE(dev);
SpaprDrc *drc;
@@ -4077,12 +3981,6 @@ static void spapr_core_plug(HotplugHandler *hotplug_dev, DeviceState *dev)
}
}
- if (smc->pre_2_10_has_unused_icps) {
- for (i = 0; i < cc->nr_threads; i++) {
- CPUState *cs = CPU(core->threads[i]);
- pre_2_10_vmstate_unregister_dummy_icp(cs->cpu_index);
- }
- }
}
static void spapr_core_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
@@ -4713,7 +4611,6 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data)
hc->unplug_request = spapr_machine_device_unplug_request;
hc->unplug = spapr_machine_device_unplug;
- smc->dr_lmb_enabled = true;
smc->update_dt_enabled = true;
mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power10_v2.0");
mc->has_hotpluggable_cpus = true;
@@ -4834,8 +4731,6 @@ static void spapr_machine_latest_class_options(MachineClass *mc)
DEFINE_SPAPR_MACHINE_IMPL(true, major, minor)
#define DEFINE_SPAPR_MACHINE(major, minor) \
DEFINE_SPAPR_MACHINE_IMPL(false, major, minor)
-#define DEFINE_SPAPR_MACHINE_TAGGED(major, minor, tag) \
- DEFINE_SPAPR_MACHINE_IMPL(false, major, minor, _, tag)
/*
* pseries-9.2
@@ -5120,278 +5015,6 @@ static void spapr_machine_3_0_class_options(MachineClass *mc)
DEFINE_SPAPR_MACHINE(3, 0);
-/*
- * pseries-2.12
- */
-static void spapr_machine_2_12_class_options(MachineClass *mc)
-{
- SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
- static GlobalProperty compat[] = {
- { TYPE_POWERPC_CPU, "pre-3.0-migration", "on" },
- { TYPE_SPAPR_CPU_CORE, "pre-3.0-migration", "on" },
- };
-
- spapr_machine_3_0_class_options(mc);
- compat_props_add(mc->compat_props, hw_compat_2_12, hw_compat_2_12_len);
- compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat));
-
- /* We depend on kvm_enabled() to choose a default value for the
- * hpt-max-page-size capability. Of course we can't do it here
- * because this is too early and the HW accelerator isn't initialized
- * yet. Postpone this to machine init (see default_caps_with_cpu()).
- */
- smc->default_caps.caps[SPAPR_CAP_HPT_MAXPAGESIZE] = 0;
-}
-
-DEFINE_SPAPR_MACHINE(2, 12);
-
-static void spapr_machine_2_12_sxxm_class_options(MachineClass *mc)
-{
- SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
-
- spapr_machine_2_12_class_options(mc);
- smc->default_caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_WORKAROUND;
- smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_WORKAROUND;
- smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_FIXED_CCD;
-}
-
-DEFINE_SPAPR_MACHINE_TAGGED(2, 12, sxxm);
-
-/*
- * pseries-2.11
- */
-
-static void spapr_machine_2_11_class_options(MachineClass *mc)
-{
- SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
-
- spapr_machine_2_12_class_options(mc);
- smc->default_caps.caps[SPAPR_CAP_HTM] = SPAPR_CAP_ON;
- compat_props_add(mc->compat_props, hw_compat_2_11, hw_compat_2_11_len);
-}
-
-DEFINE_SPAPR_MACHINE(2, 11);
-
-/*
- * pseries-2.10
- */
-
-static void spapr_machine_2_10_class_options(MachineClass *mc)
-{
- spapr_machine_2_11_class_options(mc);
- compat_props_add(mc->compat_props, hw_compat_2_10, hw_compat_2_10_len);
-}
-
-DEFINE_SPAPR_MACHINE(2, 10);
-
-/*
- * pseries-2.9
- */
-
-static void spapr_machine_2_9_class_options(MachineClass *mc)
-{
- SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
- static GlobalProperty compat[] = {
- { TYPE_POWERPC_CPU, "pre-2.10-migration", "on" },
- };
-
- spapr_machine_2_10_class_options(mc);
- compat_props_add(mc->compat_props, hw_compat_2_9, hw_compat_2_9_len);
- compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat));
- smc->pre_2_10_has_unused_icps = true;
- smc->resize_hpt_default = SPAPR_RESIZE_HPT_DISABLED;
-}
-
-DEFINE_SPAPR_MACHINE(2, 9);
-
-/*
- * pseries-2.8
- */
-
-static void spapr_machine_2_8_class_options(MachineClass *mc)
-{
- static GlobalProperty compat[] = {
- { TYPE_SPAPR_PCI_HOST_BRIDGE, "pcie-extended-configuration-space", "off" },
- };
-
- spapr_machine_2_9_class_options(mc);
- compat_props_add(mc->compat_props, hw_compat_2_8, hw_compat_2_8_len);
- compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat));
- mc->numa_mem_align_shift = 23;
-}
-
-DEFINE_SPAPR_MACHINE(2, 8);
-
-/*
- * pseries-2.7
- */
-
-static bool phb_placement_2_7(SpaprMachineState *spapr, uint32_t index,
- uint64_t *buid, hwaddr *pio,
- hwaddr *mmio32, hwaddr *mmio64,
- unsigned n_dma, uint32_t *liobns, Error **errp)
-{
- /* Legacy PHB placement for pseries-2.7 and earlier machine types */
- const uint64_t base_buid = 0x800000020000000ULL;
- const hwaddr phb_spacing = 0x1000000000ULL; /* 64 GiB */
- const hwaddr mmio_offset = 0xa0000000; /* 2 GiB + 512 MiB */
- const hwaddr pio_offset = 0x80000000; /* 2 GiB */
- const uint32_t max_index = 255;
- const hwaddr phb0_alignment = 0x10000000000ULL; /* 1 TiB */
-
- uint64_t ram_top = MACHINE(spapr)->ram_size;
- hwaddr phb0_base, phb_base;
- int i;
-
- /* Do we have device memory? */
- if (MACHINE(spapr)->device_memory) {
- /* Can't just use maxram_size, because there may be an
- * alignment gap between normal and device memory regions
- */
- ram_top = MACHINE(spapr)->device_memory->base +
- memory_region_size(&MACHINE(spapr)->device_memory->mr);
- }
-
- phb0_base = QEMU_ALIGN_UP(ram_top, phb0_alignment);
-
- if (index > max_index) {
- error_setg(errp, "\"index\" for PAPR PHB is too large (max %u)",
- max_index);
- return false;
- }
-
- *buid = base_buid + index;
- for (i = 0; i < n_dma; ++i) {
- liobns[i] = SPAPR_PCI_LIOBN(index, i);
- }
-
- phb_base = phb0_base + index * phb_spacing;
- *pio = phb_base + pio_offset;
- *mmio32 = phb_base + mmio_offset;
- /*
- * We don't set the 64-bit MMIO window, relying on the PHB's
- * fallback behaviour of automatically splitting a large "32-bit"
- * window into contiguous 32-bit and 64-bit windows
- */
-
- return true;
-}
-
-static void spapr_machine_2_7_class_options(MachineClass *mc)
-{
- SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
- static GlobalProperty compat[] = {
- { TYPE_SPAPR_PCI_HOST_BRIDGE, "mem_win_size", "0xf80000000", },
- { TYPE_SPAPR_PCI_HOST_BRIDGE, "mem64_win_size", "0", },
- { TYPE_POWERPC_CPU, "pre-2.8-migration", "on", },
- { TYPE_SPAPR_PCI_HOST_BRIDGE, "pre-2.8-migration", "on", },
- };
-
- spapr_machine_2_8_class_options(mc);
- mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power7_v2.3");
- mc->default_machine_opts = "modern-hotplug-events=off";
- compat_props_add(mc->compat_props, hw_compat_2_7, hw_compat_2_7_len);
- compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat));
- smc->phb_placement = phb_placement_2_7;
-}
-
-DEFINE_SPAPR_MACHINE(2, 7);
-
-/*
- * pseries-2.6
- */
-
-static void spapr_machine_2_6_class_options(MachineClass *mc)
-{
- static GlobalProperty compat[] = {
- { TYPE_SPAPR_PCI_HOST_BRIDGE, "ddw", "off" },
- };
-
- spapr_machine_2_7_class_options(mc);
- mc->has_hotpluggable_cpus = false;
- compat_props_add(mc->compat_props, hw_compat_2_6, hw_compat_2_6_len);
- compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat));
-}
-
-DEFINE_SPAPR_MACHINE(2, 6);
-
-/*
- * pseries-2.5
- */
-
-static void spapr_machine_2_5_class_options(MachineClass *mc)
-{
- SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
- static GlobalProperty compat[] = {
- { "spapr-vlan", "use-rx-buffer-pools", "off" },
- };
-
- spapr_machine_2_6_class_options(mc);
- smc->use_ohci_by_default = true;
- compat_props_add(mc->compat_props, hw_compat_2_5, hw_compat_2_5_len);
- compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat));
-}
-
-DEFINE_SPAPR_MACHINE(2, 5);
-
-/*
- * pseries-2.4
- */
-
-static void spapr_machine_2_4_class_options(MachineClass *mc)
-{
- SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
-
- spapr_machine_2_5_class_options(mc);
- smc->dr_lmb_enabled = false;
- compat_props_add(mc->compat_props, hw_compat_2_4, hw_compat_2_4_len);
-}
-
-DEFINE_SPAPR_MACHINE(2, 4);
-
-/*
- * pseries-2.3
- */
-
-static void spapr_machine_2_3_class_options(MachineClass *mc)
-{
- static GlobalProperty compat[] = {
- { "spapr-pci-host-bridge", "dynamic-reconfiguration", "off" },
- };
- spapr_machine_2_4_class_options(mc);
- compat_props_add(mc->compat_props, hw_compat_2_3, hw_compat_2_3_len);
- compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat));
-}
-DEFINE_SPAPR_MACHINE(2, 3);
-
-/*
- * pseries-2.2
- */
-
-static void spapr_machine_2_2_class_options(MachineClass *mc)
-{
- static GlobalProperty compat[] = {
- { TYPE_SPAPR_PCI_HOST_BRIDGE, "mem_win_size", "0x20000000" },
- };
-
- spapr_machine_2_3_class_options(mc);
- compat_props_add(mc->compat_props, hw_compat_2_2, hw_compat_2_2_len);
- compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat));
- mc->default_machine_opts = "modern-hotplug-events=off,suppress-vmdesc=on";
-}
-DEFINE_SPAPR_MACHINE(2, 2);
-
-/*
- * pseries-2.1
- */
-
-static void spapr_machine_2_1_class_options(MachineClass *mc)
-{
- spapr_machine_2_2_class_options(mc);
- compat_props_add(mc->compat_props, hw_compat_2_1, hw_compat_2_1_len);
-}
-DEFINE_SPAPR_MACHINE(2, 1);
-
static void spapr_machine_register_types(void)
{
type_register_static(&spapr_machine_info);
diff --git a/hw/ppc/spapr_cpu_core.c b/hw/ppc/spapr_cpu_core.c
index 4642245..ada439e 100644
--- a/hw/ppc/spapr_cpu_core.c
+++ b/hw/ppc/spapr_cpu_core.c
@@ -197,9 +197,7 @@ static void spapr_unrealize_vcpu(PowerPCCPU *cpu, SpaprCpuCore *sc)
{
CPUPPCState *env = &cpu->env;
- if (!sc->pre_3_0_migration) {
- vmstate_unregister(NULL, &vmstate_spapr_cpu_state, cpu->machine_data);
- }
+ vmstate_unregister(NULL, &vmstate_spapr_cpu_state, cpu->machine_data);
spapr_irq_cpu_intc_destroy(SPAPR_MACHINE(qdev_get_machine()), cpu);
cpu_ppc_tb_free(env);
qdev_unrealize(DEVICE(cpu));
@@ -285,10 +283,8 @@ static bool spapr_realize_vcpu(PowerPCCPU *cpu, SpaprMachineState *spapr,
return false;
}
- if (!sc->pre_3_0_migration) {
- vmstate_register(NULL, cs->cpu_index, &vmstate_spapr_cpu_state,
- cpu->machine_data);
- }
+ vmstate_register(NULL, cs->cpu_index, &vmstate_spapr_cpu_state,
+ cpu->machine_data);
return true;
}
@@ -366,8 +362,6 @@ static void spapr_cpu_core_realize(DeviceState *dev, Error **errp)
static Property spapr_cpu_core_properties[] = {
DEFINE_PROP_INT32("node-id", SpaprCpuCore, node_id, CPU_UNSET_NUMA_NODE_ID),
- DEFINE_PROP_BOOL("pre-3.0-migration", SpaprCpuCore, pre_3_0_migration,
- false),
DEFINE_PROP_END_OF_LIST()
};
@@ -411,6 +405,7 @@ static const TypeInfo spapr_cpu_core_type_infos[] = {
DEFINE_SPAPR_CPU_CORE_TYPE("power9_v2.0"),
DEFINE_SPAPR_CPU_CORE_TYPE("power9_v2.2"),
DEFINE_SPAPR_CPU_CORE_TYPE("power10_v2.0"),
+ DEFINE_SPAPR_CPU_CORE_TYPE("power11_v2.0"),
#ifdef CONFIG_KVM
DEFINE_SPAPR_CPU_CORE_TYPE("host"),
#endif
diff --git a/hw/ppc/spapr_nested.c b/hw/ppc/spapr_nested.c
index c027857..7def8eb 100644
--- a/hw/ppc/spapr_nested.c
+++ b/hw/ppc/spapr_nested.c
@@ -771,6 +771,7 @@ static void copy_logical_pvr(void *a, void *b, bool set)
if (*pvr_logical_ptr) {
switch (*pvr_logical_ptr) {
+ case CPU_POWERPC_LOGICAL_3_10_P11:
case CPU_POWERPC_LOGICAL_3_10:
pcr = PCR_COMPAT_3_10 | PCR_COMPAT_3_00;
break;
@@ -982,6 +983,7 @@ struct guest_state_element_type guest_state_element_types[] = {
GUEST_STATE_ELEMENT_ENV_DW(GSB_VCPU_SPR_FSCR, fscr),
GUEST_STATE_ELEMENT_ENV_W(GSB_VCPU_SPR_PSPB, pspb),
GUEST_STATE_ELEMENT_ENV_DW(GSB_VCPU_SPR_CTRL, ctrl),
+ GUEST_STATE_ELEMENT_ENV_DW(GSB_VCPU_SPR_DPDES, dpdes),
GUEST_STATE_ELEMENT_ENV_W(GSB_VCPU_SPR_VRSAVE, vrsave),
GUEST_STATE_ELEMENT_ENV_DW(GSB_VCPU_SPR_DAR, dar),
GUEST_STATE_ELEMENT_ENV_W(GSB_VCPU_SPR_DSISR, dsisr),
@@ -1184,6 +1186,12 @@ static target_ulong h_guest_get_capabilities(PowerPCCPU *cpu,
return H_PARAMETER;
}
+ /* P11 capabilities */
+ if (ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_3_10_P11, 0,
+ spapr->max_compat_pvr)) {
+ env->gpr[4] |= H_GUEST_CAPABILITIES_P11_MODE;
+ }
+
/* P10 capabilities */
if (ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_3_10, 0,
spapr->max_compat_pvr)) {
@@ -1226,7 +1234,10 @@ static target_ulong h_guest_set_capabilities(PowerPCCPU *cpu,
env->gpr[4] = 1;
/* set R5 to the first supported Power Processor Mode */
- if (ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_3_10, 0,
+ if (ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_3_10_P11, 0,
+ spapr->max_compat_pvr)) {
+ env->gpr[5] = H_GUEST_CAP_P11_MODE_BMAP;
+ } else if (ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_3_10, 0,
spapr->max_compat_pvr)) {
env->gpr[5] = H_GUEST_CAP_P10_MODE_BMAP;
} else if (ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_3_00, 0,
diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
index 5c0024b..7e24084 100644
--- a/hw/ppc/spapr_pci.c
+++ b/hw/ppc/spapr_pci.c
@@ -1237,10 +1237,6 @@ static void add_drcs(SpaprPhbState *phb, PCIBus *bus)
int i;
uint8_t chassis;
- if (!phb->dr_enabled) {
- return;
- }
-
chassis = chassis_from_bus(bus);
if (pci_bus_is_root(bus)) {
@@ -1260,10 +1256,6 @@ static void remove_drcs(SpaprPhbState *phb, PCIBus *bus)
int i;
uint8_t chassis;
- if (!phb->dr_enabled) {
- return;
- }
-
chassis = chassis_from_bus(bus);
for (i = PCI_SLOT_MAX * PCI_FUNC_MAX - 1; i >= 0; i--) {
@@ -1548,17 +1540,6 @@ static void spapr_pci_pre_plug(HotplugHandler *plug_handler,
PCIBus *bus = PCI_BUS(qdev_get_parent_bus(DEVICE(pdev)));
uint32_t slotnr = PCI_SLOT(pdev->devfn);
- if (!phb->dr_enabled) {
- /* if this is a hotplug operation initiated by the user
- * we need to let them know it's not enabled
- */
- if (plugged_dev->hotplugged) {
- error_setg(errp, "Bus '%s' does not support hotplugging",
- phb->parent_obj.bus->qbus.name);
- return;
- }
- }
-
if (IS_PCI_BRIDGE(plugged_dev)) {
if (!bridge_has_valid_chassis_nr(OBJECT(plugged_dev), errp)) {
return;
@@ -1591,14 +1572,6 @@ static void spapr_pci_plug(HotplugHandler *plug_handler,
SpaprDrc *drc = drc_from_dev(phb, pdev);
uint32_t slotnr = PCI_SLOT(pdev->devfn);
- /*
- * If DR is disabled we don't need to do anything in the case of
- * hotplug or coldplug callbacks.
- */
- if (!phb->dr_enabled) {
- return;
- }
-
g_assert(drc);
if (IS_PCI_BRIDGE(plugged_dev)) {
@@ -1673,12 +1646,6 @@ static void spapr_pci_unplug_request(HotplugHandler *plug_handler,
PCIDevice *pdev = PCI_DEVICE(plugged_dev);
SpaprDrc *drc = drc_from_dev(phb, pdev);
- if (!phb->dr_enabled) {
- error_setg(errp, "Bus '%s' does not support hotplugging",
- phb->parent_obj.bus->qbus.name);
- return;
- }
-
g_assert(drc);
g_assert(drc->dev == plugged_dev);
@@ -1847,30 +1814,15 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp)
assert(sphb->index != (uint32_t)-1); /* checked in spapr_phb_pre_plug() */
- if (sphb->mem64_win_size != 0) {
- if (sphb->mem_win_size > SPAPR_PCI_MEM32_WIN_SIZE) {
- error_setg(errp, "32-bit memory window of size 0x%"HWADDR_PRIx
- " (max 2 GiB)", sphb->mem_win_size);
- return;
- }
-
- /* 64-bit window defaults to identity mapping */
- sphb->mem64_win_pciaddr = sphb->mem64_win_addr;
- } else if (sphb->mem_win_size > SPAPR_PCI_MEM32_WIN_SIZE) {
- /*
- * For compatibility with old configuration, if no 64-bit MMIO
- * window is specified, but the ordinary (32-bit) memory
- * window is specified as > 2GiB, we treat it as a 2GiB 32-bit
- * window, with a 64-bit MMIO window following on immediately
- * afterwards
- */
- sphb->mem64_win_size = sphb->mem_win_size - SPAPR_PCI_MEM32_WIN_SIZE;
- sphb->mem64_win_addr = sphb->mem_win_addr + SPAPR_PCI_MEM32_WIN_SIZE;
- sphb->mem64_win_pciaddr =
- SPAPR_PCI_MEM_WIN_BUS_OFFSET + SPAPR_PCI_MEM32_WIN_SIZE;
- sphb->mem_win_size = SPAPR_PCI_MEM32_WIN_SIZE;
+ if (sphb->mem_win_size > SPAPR_PCI_MEM32_WIN_SIZE) {
+ error_setg(errp, "32-bit memory window of size 0x%"HWADDR_PRIx
+ " (max 2 GiB)", sphb->mem_win_size);
+ return;
}
+ /* 64-bit window defaults to identity mapping */
+ sphb->mem64_win_pciaddr = sphb->mem64_win_addr;
+
if (spapr_pci_find_phb(spapr, sphb->buid)) {
SpaprPhbState *s;
@@ -2089,8 +2041,6 @@ static Property spapr_phb_properties[] = {
SPAPR_PCI_MEM64_WIN_SIZE),
DEFINE_PROP_UINT64("io_win_size", SpaprPhbState, io_win_size,
SPAPR_PCI_IO_WIN_SIZE),
- DEFINE_PROP_BOOL("dynamic-reconfiguration", SpaprPhbState, dr_enabled,
- true),
/* Default DMA window is 0..1GB */
DEFINE_PROP_UINT64("dma_win_addr", SpaprPhbState, dma_win_addr, 0),
DEFINE_PROP_UINT64("dma_win_size", SpaprPhbState, dma_win_size, 0x40000000),
@@ -2101,8 +2051,6 @@ static Property spapr_phb_properties[] = {
(1ULL << 12) | (1ULL << 16)
| (1ULL << 21) | (1ULL << 24)),
DEFINE_PROP_UINT32("numa_node", SpaprPhbState, numa_node, -1),
- DEFINE_PROP_BOOL("pre-2.8-migration", SpaprPhbState,
- pre_2_8_migration, false),
DEFINE_PROP_BOOL("pcie-extended-configuration-space", SpaprPhbState,
pcie_ecs, true),
DEFINE_PROP_BOOL("pre-5.1-associativity", SpaprPhbState,
@@ -2140,20 +2088,6 @@ static int spapr_pci_pre_save(void *opaque)
gpointer key, value;
int i;
- if (sphb->pre_2_8_migration) {
- sphb->mig_liobn = sphb->dma_liobn[0];
- sphb->mig_mem_win_addr = sphb->mem_win_addr;
- sphb->mig_mem_win_size = sphb->mem_win_size;
- sphb->mig_io_win_addr = sphb->io_win_addr;
- sphb->mig_io_win_size = sphb->io_win_size;
-
- if ((sphb->mem64_win_size != 0)
- && (sphb->mem64_win_addr
- == (sphb->mem_win_addr + sphb->mem_win_size))) {
- sphb->mig_mem_win_size += sphb->mem64_win_size;
- }
- }
-
g_free(sphb->msi_devs);
sphb->msi_devs = NULL;
sphb->msi_devs_num = g_hash_table_size(sphb->msi);
@@ -2200,13 +2134,6 @@ static int spapr_pci_post_load(void *opaque, int version_id)
return 0;
}
-static bool pre_2_8_migration(void *opaque, int version_id)
-{
- SpaprPhbState *sphb = opaque;
-
- return sphb->pre_2_8_migration;
-}
-
static const VMStateDescription vmstate_spapr_pci = {
.name = "spapr_pci",
.version_id = 2,
@@ -2216,11 +2143,6 @@ static const VMStateDescription vmstate_spapr_pci = {
.post_load = spapr_pci_post_load,
.fields = (const VMStateField[]) {
VMSTATE_UINT64_EQUAL(buid, SpaprPhbState, NULL),
- VMSTATE_UINT32_TEST(mig_liobn, SpaprPhbState, pre_2_8_migration),
- VMSTATE_UINT64_TEST(mig_mem_win_addr, SpaprPhbState, pre_2_8_migration),
- VMSTATE_UINT64_TEST(mig_mem_win_size, SpaprPhbState, pre_2_8_migration),
- VMSTATE_UINT64_TEST(mig_io_win_addr, SpaprPhbState, pre_2_8_migration),
- VMSTATE_UINT64_TEST(mig_io_win_size, SpaprPhbState, pre_2_8_migration),
VMSTATE_STRUCT_ARRAY(lsi_table, SpaprPhbState, PCI_NUM_PINS, 0,
vmstate_spapr_pci_lsi, SpaprPciLsi),
VMSTATE_INT32(msi_devs_num, SpaprPhbState),
diff --git a/hw/ppc/virtex_ml507.c b/hw/ppc/virtex_ml507.c
index 235281e..f378e5c 100644
--- a/hw/ppc/virtex_ml507.c
+++ b/hw/ppc/virtex_ml507.c
@@ -67,29 +67,6 @@ static struct boot_info
void *vfdt;
} boot_info;
-/* Create reset TLB entries for BookE, spanning the 32bit addr space. */
-static void mmubooke_create_initial_mapping(CPUPPCState *env,
- target_ulong va,
- hwaddr pa)
-{
- ppcemb_tlb_t *tlb = &env->tlb.tlbe[0];
-
- tlb->attr = 0;
- tlb->prot = PAGE_VALID | ((PAGE_READ | PAGE_WRITE | PAGE_EXEC) << 4);
- tlb->size = 1U << 31; /* up to 0x80000000 */
- tlb->EPN = va & TARGET_PAGE_MASK;
- tlb->RPN = pa & TARGET_PAGE_MASK;
- tlb->PID = 0;
-
- tlb = &env->tlb.tlbe[1];
- tlb->attr = 0;
- tlb->prot = PAGE_VALID | ((PAGE_READ | PAGE_WRITE | PAGE_EXEC) << 4);
- tlb->size = 1U << 31; /* up to 0xffffffff */
- tlb->EPN = 0x80000000 & TARGET_PAGE_MASK;
- tlb->RPN = 0x80000000 & TARGET_PAGE_MASK;
- tlb->PID = 0;
-}
-
static PowerPCCPU *ppc440_init_xilinx(const char *cpu_type, uint32_t sysclk)
{
PowerPCCPU *cpu;
@@ -139,8 +116,9 @@ static void main_cpu_reset(void *opaque)
env->gpr[3] = bi->fdt;
env->nip = bi->bootstrap_pc;
- /* Create a mapping for the kernel. */
- mmubooke_create_initial_mapping(env, 0, 0);
+ /* Create a mapping spanning the 32bit addr space. */
+ booke_set_tlb(&env->tlb.tlbe[0], 0, 0, 1U << 31);
+ booke_set_tlb(&env->tlb.tlbe[1], 0x80000000, 0x80000000, 1U << 31);
env->gpr[6] = tswap32(EPAPR_MAGIC);
env->gpr[7] = bi->ima_size;
}
diff --git a/hw/ssi/pnv_spi.c b/hw/ssi/pnv_spi.c
index 9e7207b..c21b2eb 100644
--- a/hw/ssi/pnv_spi.c
+++ b/hw/ssi/pnv_spi.c
@@ -53,8 +53,8 @@ static PnvXferBuffer *pnv_spi_xfer_buffer_new(void)
static void pnv_spi_xfer_buffer_free(PnvXferBuffer *payload)
{
- free(payload->data);
- free(payload);
+ g_free(payload->data);
+ g_free(payload);
}
static uint8_t *pnv_spi_xfer_buffer_write_ptr(PnvXferBuffer *payload,
@@ -217,6 +217,9 @@ static void transfer(PnvSpi *s, PnvXferBuffer *payload)
PnvXferBuffer *rsp_payload = NULL;
rsp_payload = pnv_spi_xfer_buffer_new();
+ if (!rsp_payload) {
+ return;
+ }
for (int offset = 0; offset < payload->len; offset += s->transfer_len) {
tx = 0;
for (int i = 0; i < s->transfer_len; i++) {
@@ -235,9 +238,8 @@ static void transfer(PnvSpi *s, PnvXferBuffer *payload)
(rx >> (8 * (s->transfer_len - 1) - i * 8)) & 0xFF;
}
}
- if (rsp_payload != NULL) {
- spi_response(s, s->N1_bits, rsp_payload);
- }
+ spi_response(s, s->N1_bits, rsp_payload);
+ pnv_spi_xfer_buffer_free(rsp_payload);
}
static inline uint8_t get_seq_index(PnvSpi *s)