mirror of https://github.com/xemu-project/xemu.git
ppc patch queue 2020-12-14
Here's my first pull request for qemu-6.0, with a bunch of things queued over the freeze. Highlights are: * A bunch of cleanups to hotplug error paths from Greg Kurz * A number of TCG fixes from new contributor Giuseppe Musacchio * Added Greg Kurz as co-maintainer * Assorted other bugfixes and cleanups This supersedes ppc-for-6.0-20201211, the only change are some patch authors to better match qemu conventions. -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEdfRlhq5hpmzETofcbDjKyiDZs5IFAl/W8KUACgkQbDjKyiDZ s5Jt4RAAhbYnMCPTj9zFsUwp1baJkDk8MYpDYGhcqvsYNPzejfTVSGFa3Db1t2JA JFGx1PU5tejpQx7BmwJnVAyzADIEuaeNbCSIx4RB8suVYA27YiTJLw16ycfp0sxh jgnCAOa9GJgZth3MBoaBtu5gsF1Ym3qf5vcMC+OwMTsLMSO0A343l+gOiiwZdQfl PAgV+Eu7BJWa8/lLAV1uh4Z0218Zp+PlHac0Kajz87gfzVGmAZ0Dp11HjxGnBInB 6toRE4vnttzIbTcHaHynB43uMHHUCTI3z3RjLTXGIbCdMLebr7K5XENG5bDH2Rkx OqO2+Fu+Gs16D/Cc8F56kpMFKGG3sdC9dV+gx9V16tA19zlRfjXpSmziOyPzkyGU VyT7p0WwmFc8PUkTAvtfAAHKpqKzw3ucwr1tPdKo/Cynt6SllBrAwTY8vTOq3caI n1kAtWVCxCZ9H3VXSOizbs7gM8LLpVjpY1WDpzgqCviaFZk8I0h38Qs/M3TpB4aT Nv7nyjT6zRIOYHKtrVSN5YLmEq5c8+OOyN2cH9Q05Jp2l3/A7faHHrOePwWrnIxn I54FCnBA0pm/xHv5Ho4bkstzshSXbaqP35SnwJ1ucJRWam/0tybxXNKCSOIdKIql y267445WfJruRoq1SkaCDeDopJ//d/dxvgNT65KpjV8Chih4uq4= =KLS8 -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/dg-gitlab/tags/ppc-for-6.0-20201214' into staging ppc patch queue 2020-12-14 Here's my first pull request for qemu-6.0, with a bunch of things queued over the freeze. Highlights are: * A bunch of cleanups to hotplug error paths from Greg Kurz * A number of TCG fixes from new contributor Giuseppe Musacchio * Added Greg Kurz as co-maintainer * Assorted other bugfixes and cleanups This supersedes ppc-for-6.0-20201211, the only change are some patch authors to better match qemu conventions. # gpg: Signature made Mon 14 Dec 2020 04:57:09 GMT # gpg: using RSA key 75F46586AE61A66CC44E87DC6C38CACA20D9B392 # gpg: Good signature from "David Gibson <david@gibson.dropbear.id.au>" [full] # gpg: aka "David Gibson (Red Hat) <dgibson@redhat.com>" [full] # gpg: aka "David Gibson (ozlabs.org) <dgibson@ozlabs.org>" [full] # gpg: aka "David Gibson (kernel.org) <dwg@kernel.org>" [unknown] # Primary key fingerprint: 75F4 6586 AE61 A66C C44E 87DC 6C38 CACA 20D9 B392 * remotes/dg-gitlab/tags/ppc-for-6.0-20201214: (30 commits) spapr.c: set a 'kvm-type' default value instead of relying on NULL spapr: Pass sPAPR machine state to some RTAS events handling functions spapr: Don't use qdev_get_machine() in spapr_msi_write() spapr: Pass sPAPR machine state down to spapr_pci_switch_vga() target/ppc: Introduce an mmu_is_64bit() helper ppc/translate: Use POWERPC_MMU_64 to detect 64-bit MMU models ppc/e500: Free irqs array to avoid memleak MAINTAINERS: Add Greg Kurz as co-maintainer for ppc hw/ppc: Do not re-read the clock on pre_save if doing savevm target/ppc: Remove "compat" property of server class POWER CPUs spapr: spapr_drc_attach() cannot fail spapr: Simplify error path of spapr_core_plug() spapr: Abort if ppc_set_compat() fails for hot-plugged CPUs spapr: Fix pre-2.10 dummy ICP hack xive: Add trace events hw/ppc/spapr_tpm_proxy: Fix hexadecimal format string specifier ppc/translate: Rewrite gen_lxvdsx to use gvec primitives ppc/translate: Raise exceptions after setting the cc ppc/translate: Delay NaN checking after comparison ppc/translate: Turn the helper macros into functions ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
37f04b71a9
17
MAINTAINERS
17
MAINTAINERS
|
@ -272,6 +272,7 @@ F: tests/tcg/openrisc/
|
|||
|
||||
PowerPC TCG CPUs
|
||||
M: David Gibson <david@gibson.dropbear.id.au>
|
||||
M: Greg Kurz <groug@kaod.org>
|
||||
L: qemu-ppc@nongnu.org
|
||||
S: Maintained
|
||||
F: target/ppc/
|
||||
|
@ -394,6 +395,7 @@ F: target/mips/kvm.c
|
|||
|
||||
PPC KVM CPUs
|
||||
M: David Gibson <david@gibson.dropbear.id.au>
|
||||
M: Greg Kurz <groug@kaod.org>
|
||||
S: Maintained
|
||||
F: target/ppc/kvm.c
|
||||
|
||||
|
@ -1184,18 +1186,21 @@ PowerPC Machines
|
|||
----------------
|
||||
405
|
||||
M: David Gibson <david@gibson.dropbear.id.au>
|
||||
M: Greg Kurz <groug@kaod.org>
|
||||
L: qemu-ppc@nongnu.org
|
||||
S: Odd Fixes
|
||||
F: hw/ppc/ppc405_boards.c
|
||||
|
||||
Bamboo
|
||||
M: David Gibson <david@gibson.dropbear.id.au>
|
||||
M: Greg Kurz <groug@kaod.org>
|
||||
L: qemu-ppc@nongnu.org
|
||||
S: Odd Fixes
|
||||
F: hw/ppc/ppc440_bamboo.c
|
||||
|
||||
e500
|
||||
M: David Gibson <david@gibson.dropbear.id.au>
|
||||
M: Greg Kurz <groug@kaod.org>
|
||||
L: qemu-ppc@nongnu.org
|
||||
S: Odd Fixes
|
||||
F: hw/ppc/e500*
|
||||
|
@ -1209,6 +1214,7 @@ F: pc-bios/u-boot.e500
|
|||
|
||||
mpc8544ds
|
||||
M: David Gibson <david@gibson.dropbear.id.au>
|
||||
M: Greg Kurz <groug@kaod.org>
|
||||
L: qemu-ppc@nongnu.org
|
||||
S: Odd Fixes
|
||||
F: hw/ppc/mpc8544ds.c
|
||||
|
@ -1217,6 +1223,7 @@ F: hw/ppc/mpc8544_guts.c
|
|||
New World (mac99)
|
||||
M: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
|
||||
R: David Gibson <david@gibson.dropbear.id.au>
|
||||
R: Greg Kurz <groug@kaod.org>
|
||||
L: qemu-ppc@nongnu.org
|
||||
S: Odd Fixes
|
||||
F: hw/ppc/mac_newworld.c
|
||||
|
@ -1236,6 +1243,7 @@ F: pc-bios/qemu_vga.ndrv
|
|||
Old World (g3beige)
|
||||
M: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
|
||||
R: David Gibson <david@gibson.dropbear.id.au>
|
||||
R: Greg Kurz <groug@kaod.org>
|
||||
L: qemu-ppc@nongnu.org
|
||||
S: Odd Fixes
|
||||
F: hw/ppc/mac_oldworld.c
|
||||
|
@ -1249,6 +1257,8 @@ F: pc-bios/qemu_vga.ndrv
|
|||
|
||||
PReP
|
||||
M: Hervé Poussineau <hpoussin@reactos.org>
|
||||
R: David Gibson <david@gibson.dropbear.id.au>
|
||||
R: Greg Kurz <groug@kaod.org>
|
||||
L: qemu-ppc@nongnu.org
|
||||
S: Maintained
|
||||
F: hw/ppc/prep.c
|
||||
|
@ -1265,6 +1275,7 @@ F: tests/acceptance/ppc_prep_40p.py
|
|||
|
||||
sPAPR
|
||||
M: David Gibson <david@gibson.dropbear.id.au>
|
||||
M: Greg Kurz <groug@kaod.org>
|
||||
L: qemu-ppc@nongnu.org
|
||||
S: Supported
|
||||
F: hw/*/spapr*
|
||||
|
@ -1282,6 +1293,7 @@ F: tests/qtest/libqos/rtas*
|
|||
PowerNV (Non-Virtualized)
|
||||
M: Cédric Le Goater <clg@kaod.org>
|
||||
M: David Gibson <david@gibson.dropbear.id.au>
|
||||
M: Greg Kurz <groug@kaod.org>
|
||||
L: qemu-ppc@nongnu.org
|
||||
S: Maintained
|
||||
F: hw/ppc/pnv*
|
||||
|
@ -1301,6 +1313,8 @@ F: hw/ppc/virtex_ml507.c
|
|||
|
||||
sam460ex
|
||||
M: BALATON Zoltan <balaton@eik.bme.hu>
|
||||
R: David Gibson <david@gibson.dropbear.id.au>
|
||||
R: Greg Kurz <groug@kaod.org>
|
||||
L: qemu-ppc@nongnu.org
|
||||
S: Maintained
|
||||
F: hw/ppc/sam460ex.c
|
||||
|
@ -2088,8 +2102,9 @@ F: tests/qtest/fw_cfg-test.c
|
|||
T: git https://github.com/philmd/qemu.git fw_cfg-next
|
||||
|
||||
XIVE
|
||||
M: David Gibson <david@gibson.dropbear.id.au>
|
||||
M: Cédric Le Goater <clg@kaod.org>
|
||||
R: David Gibson <david@gibson.dropbear.id.au>
|
||||
R: Greg Kurz <groug@kaod.org>
|
||||
L: qemu-ppc@nongnu.org
|
||||
S: Supported
|
||||
F: hw/*/*xive*
|
||||
|
|
|
@ -281,13 +281,6 @@ a future version of QEMU. It's unclear whether anybody is still using
|
|||
CPU emulation in QEMU, and there are no test images available to make
|
||||
sure that the code is still working.
|
||||
|
||||
``compat`` property of server class POWER CPUs (since 5.0)
|
||||
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
|
||||
|
||||
The ``compat`` property used to set backwards compatibility modes for
|
||||
the processor has been deprecated. The ``max-cpu-compat`` property of
|
||||
the ``pseries`` machine type should be used instead.
|
||||
|
||||
``lm32`` CPUs (since 5.2.0)
|
||||
'''''''''''''''''''''''''''
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "hw/ppc/xive.h"
|
||||
#include "hw/ppc/xive_regs.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
#include "trace.h"
|
||||
|
||||
/*
|
||||
* XIVE Virtualization Controller BAR and Thread Managment BAR that we
|
||||
|
@ -296,22 +297,16 @@ static void spapr_xive_realize(DeviceState *dev, Error **errp)
|
|||
XiveENDSource *end_xsrc = &xive->end_source;
|
||||
Error *local_err = NULL;
|
||||
|
||||
/* Set by spapr_irq_init() */
|
||||
g_assert(xive->nr_irqs);
|
||||
g_assert(xive->nr_ends);
|
||||
|
||||
sxc->parent_realize(dev, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!xive->nr_irqs) {
|
||||
error_setg(errp, "Number of interrupt needs to be greater 0");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!xive->nr_ends) {
|
||||
error_setg(errp, "Number of interrupt needs to be greater 0");
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the internal sources, for IPIs and virtual devices.
|
||||
*/
|
||||
|
@ -562,6 +557,8 @@ static int spapr_xive_claim_irq(SpaprInterruptController *intc, int lisn,
|
|||
|
||||
assert(lisn < xive->nr_irqs);
|
||||
|
||||
trace_spapr_xive_claim_irq(lisn, lsi);
|
||||
|
||||
if (xive_eas_is_valid(&xive->eat[lisn])) {
|
||||
error_setg(errp, "IRQ %d is not free", lisn);
|
||||
return -EBUSY;
|
||||
|
@ -587,6 +584,8 @@ static void spapr_xive_free_irq(SpaprInterruptController *intc, int lisn)
|
|||
SpaprXive *xive = SPAPR_XIVE(intc);
|
||||
assert(lisn < xive->nr_irqs);
|
||||
|
||||
trace_spapr_xive_free_irq(lisn);
|
||||
|
||||
xive->eat[lisn].w &= cpu_to_be64(~EAS_VALID);
|
||||
}
|
||||
|
||||
|
@ -653,6 +652,8 @@ static void spapr_xive_set_irq(SpaprInterruptController *intc, int irq, int val)
|
|||
{
|
||||
SpaprXive *xive = SPAPR_XIVE(intc);
|
||||
|
||||
trace_spapr_xive_set_irq(irq, val);
|
||||
|
||||
if (spapr_xive_in_kernel(xive)) {
|
||||
kvmppc_xive_source_set_irq(&xive->source, irq, val);
|
||||
} else {
|
||||
|
@ -900,6 +901,8 @@ static target_ulong h_int_get_source_info(PowerPCCPU *cpu,
|
|||
target_ulong flags = args[0];
|
||||
target_ulong lisn = args[1];
|
||||
|
||||
trace_spapr_xive_get_source_info(flags, lisn);
|
||||
|
||||
if (!spapr_ovec_test(spapr->ov5_cas, OV5_XIVE_EXPLOIT)) {
|
||||
return H_FUNCTION;
|
||||
}
|
||||
|
@ -1015,6 +1018,8 @@ static target_ulong h_int_set_source_config(PowerPCCPU *cpu,
|
|||
uint8_t end_blk;
|
||||
uint32_t end_idx;
|
||||
|
||||
trace_spapr_xive_set_source_config(flags, lisn, target, priority, eisn);
|
||||
|
||||
if (!spapr_ovec_test(spapr->ov5_cas, OV5_XIVE_EXPLOIT)) {
|
||||
return H_FUNCTION;
|
||||
}
|
||||
|
@ -1120,6 +1125,8 @@ static target_ulong h_int_get_source_config(PowerPCCPU *cpu,
|
|||
uint8_t nvt_blk;
|
||||
uint32_t end_idx, nvt_idx;
|
||||
|
||||
trace_spapr_xive_get_source_config(flags, lisn);
|
||||
|
||||
if (!spapr_ovec_test(spapr->ov5_cas, OV5_XIVE_EXPLOIT)) {
|
||||
return H_FUNCTION;
|
||||
}
|
||||
|
@ -1194,6 +1201,8 @@ static target_ulong h_int_get_queue_info(PowerPCCPU *cpu,
|
|||
uint8_t end_blk;
|
||||
uint32_t end_idx;
|
||||
|
||||
trace_spapr_xive_get_queue_info(flags, target, priority);
|
||||
|
||||
if (!spapr_ovec_test(spapr->ov5_cas, OV5_XIVE_EXPLOIT)) {
|
||||
return H_FUNCTION;
|
||||
}
|
||||
|
@ -1281,6 +1290,8 @@ static target_ulong h_int_set_queue_config(PowerPCCPU *cpu,
|
|||
uint8_t end_blk, nvt_blk;
|
||||
uint32_t end_idx, nvt_idx;
|
||||
|
||||
trace_spapr_xive_set_queue_config(flags, target, priority, qpage, qsize);
|
||||
|
||||
if (!spapr_ovec_test(spapr->ov5_cas, OV5_XIVE_EXPLOIT)) {
|
||||
return H_FUNCTION;
|
||||
}
|
||||
|
@ -1448,6 +1459,8 @@ static target_ulong h_int_get_queue_config(PowerPCCPU *cpu,
|
|||
uint8_t end_blk;
|
||||
uint32_t end_idx;
|
||||
|
||||
trace_spapr_xive_get_queue_config(flags, target, priority);
|
||||
|
||||
if (!spapr_ovec_test(spapr->ov5_cas, OV5_XIVE_EXPLOIT)) {
|
||||
return H_FUNCTION;
|
||||
}
|
||||
|
@ -1541,6 +1554,10 @@ static target_ulong h_int_set_os_reporting_line(PowerPCCPU *cpu,
|
|||
target_ulong opcode,
|
||||
target_ulong *args)
|
||||
{
|
||||
target_ulong flags = args[0];
|
||||
|
||||
trace_spapr_xive_set_os_reporting_line(flags);
|
||||
|
||||
if (!spapr_ovec_test(spapr->ov5_cas, OV5_XIVE_EXPLOIT)) {
|
||||
return H_FUNCTION;
|
||||
}
|
||||
|
@ -1577,6 +1594,10 @@ static target_ulong h_int_get_os_reporting_line(PowerPCCPU *cpu,
|
|||
target_ulong opcode,
|
||||
target_ulong *args)
|
||||
{
|
||||
target_ulong flags = args[0];
|
||||
|
||||
trace_spapr_xive_get_os_reporting_line(flags);
|
||||
|
||||
if (!spapr_ovec_test(spapr->ov5_cas, OV5_XIVE_EXPLOIT)) {
|
||||
return H_FUNCTION;
|
||||
}
|
||||
|
@ -1629,6 +1650,8 @@ static target_ulong h_int_esb(PowerPCCPU *cpu,
|
|||
hwaddr mmio_addr;
|
||||
XiveSource *xsrc = &xive->source;
|
||||
|
||||
trace_spapr_xive_esb(flags, lisn, offset, data);
|
||||
|
||||
if (!spapr_ovec_test(spapr->ov5_cas, OV5_XIVE_EXPLOIT)) {
|
||||
return H_FUNCTION;
|
||||
}
|
||||
|
@ -1698,6 +1721,8 @@ static target_ulong h_int_sync(PowerPCCPU *cpu,
|
|||
target_ulong flags = args[0];
|
||||
target_ulong lisn = args[1];
|
||||
|
||||
trace_spapr_xive_sync(flags, lisn);
|
||||
|
||||
if (!spapr_ovec_test(spapr->ov5_cas, OV5_XIVE_EXPLOIT)) {
|
||||
return H_FUNCTION;
|
||||
}
|
||||
|
@ -1763,6 +1788,8 @@ static target_ulong h_int_reset(PowerPCCPU *cpu,
|
|||
SpaprXive *xive = spapr->xive;
|
||||
target_ulong flags = args[0];
|
||||
|
||||
trace_spapr_xive_reset(flags);
|
||||
|
||||
if (!spapr_ovec_test(spapr->ov5_cas, OV5_XIVE_EXPLOIT)) {
|
||||
return H_FUNCTION;
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "hw/ppc/spapr_xive.h"
|
||||
#include "hw/ppc/xive.h"
|
||||
#include "kvm_ppc.h"
|
||||
#include "trace.h"
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
|
@ -163,6 +164,8 @@ int kvmppc_xive_cpu_connect(XiveTCTX *tctx, Error **errp)
|
|||
|
||||
vcpu_id = kvm_arch_vcpu_id(tctx->cs);
|
||||
|
||||
trace_kvm_xive_cpu_connect(vcpu_id);
|
||||
|
||||
ret = kvm_vcpu_enable_cap(tctx->cs, KVM_CAP_PPC_IRQ_XIVE, 0, xive->fd,
|
||||
vcpu_id, 0);
|
||||
if (ret < 0) {
|
||||
|
@ -308,6 +311,8 @@ uint64_t kvmppc_xive_esb_rw(XiveSource *xsrc, int srcno, uint32_t offset,
|
|||
return xive_esb_rw(xsrc, srcno, offset, data, 1);
|
||||
}
|
||||
|
||||
trace_kvm_xive_source_reset(srcno);
|
||||
|
||||
/*
|
||||
* Special Load EOI handling for LSI sources. Q bit is never set
|
||||
* and the interrupt should be re-triggered if the level is still
|
||||
|
|
|
@ -203,3 +203,36 @@ heathrow_set_irq(int num, int level) "set_irq: num=0x%02x level=%d"
|
|||
# bcm2835_ic.c
|
||||
bcm2835_ic_set_gpu_irq(int irq, int level) "GPU irq #%d level %d"
|
||||
bcm2835_ic_set_cpu_irq(int irq, int level) "CPU irq #%d level %d"
|
||||
|
||||
# spapr_xive.c
|
||||
spapr_xive_claim_irq(uint32_t lisn, bool lsi) "lisn=0x%x lsi=%d"
|
||||
spapr_xive_free_irq(uint32_t lisn) "lisn=0x%x"
|
||||
spapr_xive_set_irq(uint32_t lisn, uint32_t val) "lisn=0x%x val=%d"
|
||||
spapr_xive_get_source_info(uint64_t flags, uint64_t lisn) "flags=0x%"PRIx64" lisn=0x%"PRIx64
|
||||
spapr_xive_set_source_config(uint64_t flags, uint64_t lisn, uint64_t target, uint64_t priority, uint64_t eisn) "flags=0x%"PRIx64" lisn=0x%"PRIx64" target=0x%"PRIx64" priority=0x%"PRIx64" eisn=0x%"PRIx64
|
||||
spapr_xive_get_source_config(uint64_t flags, uint64_t lisn) "flags=0x%"PRIx64" lisn=0x%"PRIx64
|
||||
spapr_xive_get_queue_info(uint64_t flags, uint64_t target, uint64_t priority) "flags=0x%"PRIx64" target=0x%"PRIx64" priority=0x%"PRIx64
|
||||
spapr_xive_set_queue_config(uint64_t flags, uint64_t target, uint64_t priority, uint64_t qpage, uint64_t qsize) "flags=0x%"PRIx64" target=0x%"PRIx64" priority=0x%"PRIx64" qpage=0x%"PRIx64" qsize=0x%"PRIx64
|
||||
spapr_xive_get_queue_config(uint64_t flags, uint64_t target, uint64_t priority) "flags=0x%"PRIx64" target=0x%"PRIx64" priority=0x%"PRIx64
|
||||
spapr_xive_set_os_reporting_line(uint64_t flags) "flags=0x%"PRIx64
|
||||
spapr_xive_get_os_reporting_line(uint64_t flags) "flags=0x%"PRIx64
|
||||
spapr_xive_esb(uint64_t flags, uint64_t lisn, uint64_t offset, uint64_t data) "flags=0x%"PRIx64" lisn=0x%"PRIx64" offset=0x%"PRIx64" data=0x%"PRIx64
|
||||
spapr_xive_sync(uint64_t flags, uint64_t lisn) "flags=0x%"PRIx64" lisn=0x%"PRIx64
|
||||
spapr_xive_reset(uint64_t flags) "flags=0x%"PRIx64
|
||||
|
||||
# spapr_xive_kvm.c
|
||||
kvm_xive_cpu_connect(uint32_t id) "connect CPU%d to KVM device"
|
||||
kvm_xive_source_reset(uint32_t srcno) "IRQ 0x%x"
|
||||
|
||||
# xive.c
|
||||
xive_tctx_accept(uint32_t index, uint8_t ring, uint8_t ipb, uint8_t pipr, uint8_t cppr, uint8_t nsr) "target=%d ring=0x%x IBP=0x%02x PIPR=0x%02x CPPR=0x%02x NSR=0x%02x ACK"
|
||||
xive_tctx_notify(uint32_t index, uint8_t ring, uint8_t ipb, uint8_t pipr, uint8_t cppr, uint8_t nsr) "target=%d ring=0x%x IBP=0x%02x PIPR=0x%02x CPPR=0x%02x NSR=0x%02x raise !"
|
||||
xive_tctx_set_cppr(uint32_t index, uint8_t ring, uint8_t ipb, uint8_t pipr, uint8_t cppr, uint8_t nsr) "target=%d ring=0x%x IBP=0x%02x PIPR=0x%02x new CPPR=0x%02x NSR=0x%02x"
|
||||
xive_source_esb_read(uint64_t addr, uint32_t srcno, uint64_t value) "@0x0x%"PRIx64" IRQ 0x%x val=0x0x%"PRIx64
|
||||
xive_source_esb_write(uint64_t addr, uint32_t srcno, uint64_t value) "@0x0x%"PRIx64" IRQ 0x%x val=0x0x%"PRIx64
|
||||
xive_router_end_notify(uint8_t end_blk, uint32_t end_idx, uint32_t end_data) "END 0x%02x/0x%04x -> enqueue 0x%08x"
|
||||
xive_router_end_escalate(uint8_t end_blk, uint32_t end_idx, uint8_t esc_blk, uint32_t esc_idx, uint32_t end_data) "END 0x%02x/0x%04x -> escalate END 0x%02x/0x%04x data 0x%08x"
|
||||
xive_tctx_tm_write(uint64_t offset, unsigned int size, uint64_t value) "@0x0x%"PRIx64" sz=%d val=0x%" PRIx64
|
||||
xive_tctx_tm_read(uint64_t offset, unsigned int size, uint64_t value) "@0x0x%"PRIx64" sz=%d val=0x%" PRIx64
|
||||
xive_presenter_notify(uint8_t nvt_blk, uint32_t nvt_idx, uint8_t ring) "found NVT 0x%x/0x%x ring=0x%x"
|
||||
xive_end_source_read(uint8_t end_blk, uint32_t end_idx, uint64_t addr) "END 0x%x/0x%x @0x0x%"PRIx64
|
||||
|
|
|
@ -484,7 +484,7 @@ void xics_kvm_disconnect(SpaprInterruptController *intc)
|
|||
* support destruction of a KVM XICS device while the VM is running.
|
||||
* Required to start a spapr machine with ic-mode=dual,kernel-irqchip=on.
|
||||
*/
|
||||
bool xics_kvm_has_broken_disconnect(SpaprMachineState *spapr)
|
||||
bool xics_kvm_has_broken_disconnect(void)
|
||||
{
|
||||
int rc;
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "hw/irq.h"
|
||||
#include "hw/ppc/xive.h"
|
||||
#include "hw/ppc/xive_regs.h"
|
||||
#include "trace.h"
|
||||
|
||||
/*
|
||||
* XIVE Thread Interrupt Management context
|
||||
|
@ -93,6 +94,10 @@ static uint64_t xive_tctx_accept(XiveTCTX *tctx, uint8_t ring)
|
|||
|
||||
/* Drop Exception bit */
|
||||
regs[TM_NSR] &= ~mask;
|
||||
|
||||
trace_xive_tctx_accept(tctx->cs->cpu_index, ring,
|
||||
regs[TM_IPB], regs[TM_PIPR],
|
||||
regs[TM_CPPR], regs[TM_NSR]);
|
||||
}
|
||||
|
||||
return (nsr << 8) | regs[TM_CPPR];
|
||||
|
@ -113,12 +118,21 @@ static void xive_tctx_notify(XiveTCTX *tctx, uint8_t ring)
|
|||
default:
|
||||
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]);
|
||||
qemu_irq_raise(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];
|
||||
|
||||
trace_xive_tctx_set_cppr(tctx->cs->cpu_index, ring,
|
||||
regs[TM_IPB], regs[TM_PIPR],
|
||||
cppr, regs[TM_NSR]);
|
||||
|
||||
if (cppr > XIVE_PRIORITY_MAX) {
|
||||
cppr = 0xff;
|
||||
}
|
||||
|
@ -508,6 +522,8 @@ void xive_tctx_tm_write(XivePresenter *xptr, XiveTCTX *tctx, hwaddr offset,
|
|||
{
|
||||
const XiveTmOp *xto;
|
||||
|
||||
trace_xive_tctx_tm_write(offset, size, value);
|
||||
|
||||
/*
|
||||
* TODO: check V bit in Q[0-3]W2
|
||||
*/
|
||||
|
@ -545,6 +561,7 @@ uint64_t xive_tctx_tm_read(XivePresenter *xptr, XiveTCTX *tctx, hwaddr offset,
|
|||
unsigned size)
|
||||
{
|
||||
const XiveTmOp *xto;
|
||||
uint64_t ret;
|
||||
|
||||
/*
|
||||
* TODO: check V bit in Q[0-3]W2
|
||||
|
@ -560,7 +577,8 @@ uint64_t xive_tctx_tm_read(XivePresenter *xptr, XiveTCTX *tctx, hwaddr offset,
|
|||
"@%"HWADDR_PRIx"\n", offset);
|
||||
return -1;
|
||||
}
|
||||
return xto->read_handler(xptr, tctx, offset, size);
|
||||
ret = xto->read_handler(xptr, tctx, offset, size);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -568,13 +586,17 @@ uint64_t xive_tctx_tm_read(XivePresenter *xptr, XiveTCTX *tctx, hwaddr offset,
|
|||
*/
|
||||
xto = xive_tm_find_op(offset, size, false);
|
||||
if (xto) {
|
||||
return xto->read_handler(xptr, tctx, offset, size);
|
||||
ret = xto->read_handler(xptr, tctx, offset, size);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Finish with raw access to the register values
|
||||
*/
|
||||
return xive_tm_raw_read(tctx, offset, size);
|
||||
ret = xive_tm_raw_read(tctx, offset, size);
|
||||
out:
|
||||
trace_xive_tctx_tm_read(offset, size, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static char *xive_tctx_ring_print(uint8_t *ring)
|
||||
|
@ -1005,6 +1027,8 @@ static uint64_t xive_source_esb_read(void *opaque, hwaddr addr, unsigned size)
|
|||
offset);
|
||||
}
|
||||
|
||||
trace_xive_source_esb_read(addr, srcno, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1030,6 +1054,8 @@ static void xive_source_esb_write(void *opaque, hwaddr addr,
|
|||
uint32_t srcno = addr >> xsrc->esb_shift;
|
||||
bool notify = false;
|
||||
|
||||
trace_xive_source_esb_write(addr, srcno, value);
|
||||
|
||||
/* In a two pages ESB MMIO setting, trigger page only triggers */
|
||||
if (xive_source_is_trigger_page(xsrc, addr)) {
|
||||
notify = xive_source_esb_trigger(xsrc, srcno);
|
||||
|
@ -1507,6 +1533,7 @@ static bool xive_presenter_notify(XiveFabric *xfb, uint8_t format,
|
|||
|
||||
/* handle CPU exception delivery */
|
||||
if (count) {
|
||||
trace_xive_presenter_notify(nvt_blk, nvt_idx, match.ring);
|
||||
xive_tctx_ipb_update(match.tctx, match.ring, priority_to_ipb(priority));
|
||||
}
|
||||
|
||||
|
@ -1558,6 +1585,7 @@ static void xive_router_end_notify(XiveRouter *xrtr, uint8_t end_blk,
|
|||
}
|
||||
|
||||
if (!xive_end_is_valid(&end)) {
|
||||
trace_xive_router_end_notify(end_blk, end_idx, end_data);
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "XIVE: END %x/%x is invalid\n",
|
||||
end_blk, end_idx);
|
||||
return;
|
||||
|
@ -1683,6 +1711,10 @@ do_escalation:
|
|||
}
|
||||
}
|
||||
|
||||
trace_xive_router_end_escalate(end_blk, end_idx,
|
||||
(uint8_t) xive_get_field32(END_W4_ESC_END_BLOCK, end.w4),
|
||||
(uint32_t) xive_get_field32(END_W4_ESC_END_INDEX, end.w4),
|
||||
(uint32_t) xive_get_field32(END_W5_ESC_END_DATA, end.w5));
|
||||
/*
|
||||
* The END trigger becomes an Escalation trigger
|
||||
*/
|
||||
|
@ -1796,6 +1828,8 @@ static uint64_t xive_end_source_read(void *opaque, hwaddr addr, unsigned size)
|
|||
end_blk = xive_router_get_block_id(xsrc->xrtr);
|
||||
end_idx = addr >> (xsrc->esb_shift + 1);
|
||||
|
||||
trace_xive_end_source_read(end_blk, end_idx, addr);
|
||||
|
||||
if (xive_router_get_end(xsrc->xrtr, end_blk, end_idx, &end)) {
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "XIVE: No END %x/%x\n", end_blk,
|
||||
end_idx);
|
||||
|
|
|
@ -926,6 +926,7 @@ void ppce500_init(MachineState *machine)
|
|||
ccsr_addr_space);
|
||||
|
||||
mpicdev = ppce500_init_mpic(pms, ccsr_addr_space, irqs);
|
||||
g_free(irqs);
|
||||
|
||||
/* Serial */
|
||||
if (serial_hd(0)) {
|
||||
|
|
|
@ -120,6 +120,7 @@ static void ppc6xx_set_irq(void *opaque, int pin, int level)
|
|||
} else {
|
||||
cpu_ppc_tb_stop(env);
|
||||
}
|
||||
break;
|
||||
case PPC6xx_INPUT_INT:
|
||||
/* Level sensitive - active high */
|
||||
LOG_IRQ("%s: set the external IRQ state to %d\n",
|
||||
|
@ -1026,7 +1027,8 @@ static void timebase_save(PPCTimebase *tb)
|
|||
*/
|
||||
tb->guest_timebase = ticks + first_ppc_cpu->env.tb_env->tb_offset;
|
||||
|
||||
tb->runstate_paused = runstate_check(RUN_STATE_PAUSED);
|
||||
tb->runstate_paused =
|
||||
runstate_check(RUN_STATE_PAUSED) || runstate_check(RUN_STATE_SAVE_VM);
|
||||
}
|
||||
|
||||
static void timebase_load(PPCTimebase *tb)
|
||||
|
@ -1087,7 +1089,7 @@ static int timebase_pre_save(void *opaque)
|
|||
{
|
||||
PPCTimebase *tb = opaque;
|
||||
|
||||
/* guest_timebase won't be overridden in case of paused guest */
|
||||
/* guest_timebase won't be overridden in case of paused guest or savevm */
|
||||
if (!tb->runstate_paused) {
|
||||
timebase_save(tb);
|
||||
}
|
||||
|
|
192
hw/ppc/spapr.c
192
hw/ppc/spapr.c
|
@ -3021,17 +3021,25 @@ static void spapr_machine_init(MachineState *machine)
|
|||
qemu_cond_init(&spapr->fwnmi_machine_check_interlock_cond);
|
||||
}
|
||||
|
||||
#define DEFAULT_KVM_TYPE "auto"
|
||||
static int spapr_kvm_type(MachineState *machine, const char *vm_type)
|
||||
{
|
||||
if (!vm_type) {
|
||||
/*
|
||||
* The use of g_ascii_strcasecmp() for 'hv' and 'pr' is to
|
||||
* accomodate the 'HV' and 'PV' formats that exists in the
|
||||
* wild. The 'auto' mode is being introduced already as
|
||||
* lower-case, thus we don't need to bother checking for
|
||||
* "AUTO".
|
||||
*/
|
||||
if (!vm_type || !strcmp(vm_type, DEFAULT_KVM_TYPE)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!strcmp(vm_type, "HV")) {
|
||||
if (!g_ascii_strcasecmp(vm_type, "hv")) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!strcmp(vm_type, "PR")) {
|
||||
if (!g_ascii_strcasecmp(vm_type, "pr")) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
@ -3270,10 +3278,15 @@ static void spapr_instance_init(Object *obj)
|
|||
|
||||
spapr->htab_fd = -1;
|
||||
spapr->use_hotplug_event_source = true;
|
||||
spapr->kvm_type = g_strdup(DEFAULT_KVM_TYPE);
|
||||
object_property_add_str(obj, "kvm-type",
|
||||
spapr_get_kvm_type, spapr_set_kvm_type);
|
||||
object_property_set_description(obj, "kvm-type",
|
||||
"Specifies the KVM virtualization mode (HV, PR)");
|
||||
"Specifies the KVM virtualization mode (auto,"
|
||||
" hv, pr). Defaults to 'auto'. This mode will use"
|
||||
" any available KVM module loaded in the host,"
|
||||
" where kvm_hv takes precedence if both kvm_hv and"
|
||||
" kvm_pr are loaded.");
|
||||
object_property_add_bool(obj, "modern-hotplug-events",
|
||||
spapr_get_modern_hotplug_events,
|
||||
spapr_set_modern_hotplug_events);
|
||||
|
@ -3379,8 +3392,8 @@ int spapr_lmb_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool spapr_add_lmbs(DeviceState *dev, uint64_t addr_start, uint64_t size,
|
||||
bool dedicated_hp_event_source, Error **errp)
|
||||
static void spapr_add_lmbs(DeviceState *dev, uint64_t addr_start, uint64_t size,
|
||||
bool dedicated_hp_event_source)
|
||||
{
|
||||
SpaprDrc *drc;
|
||||
uint32_t nr_lmbs = size/SPAPR_MEMORY_BLOCK_SIZE;
|
||||
|
@ -3393,15 +3406,12 @@ static bool spapr_add_lmbs(DeviceState *dev, uint64_t addr_start, uint64_t size,
|
|||
addr / SPAPR_MEMORY_BLOCK_SIZE);
|
||||
g_assert(drc);
|
||||
|
||||
if (!spapr_drc_attach(drc, dev, errp)) {
|
||||
while (addr > addr_start) {
|
||||
addr -= SPAPR_MEMORY_BLOCK_SIZE;
|
||||
drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB,
|
||||
addr / SPAPR_MEMORY_BLOCK_SIZE);
|
||||
spapr_drc_detach(drc);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/*
|
||||
* memory_device_get_free_addr() provided a range of free addresses
|
||||
* that doesn't overlap with any existing mapping at pre-plug. The
|
||||
* corresponding LMB DRCs are thus assumed to be all attachable.
|
||||
*/
|
||||
spapr_drc_attach(drc, dev);
|
||||
if (!hotplugged) {
|
||||
spapr_drc_reset(drc);
|
||||
}
|
||||
|
@ -3422,11 +3432,9 @@ static bool spapr_add_lmbs(DeviceState *dev, uint64_t addr_start, uint64_t size,
|
|||
nr_lmbs);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void spapr_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
|
||||
Error **errp)
|
||||
static void spapr_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev)
|
||||
{
|
||||
SpaprMachineState *ms = SPAPR_MACHINE(hotplug_dev);
|
||||
PCDIMMDevice *dimm = PC_DIMM(dev);
|
||||
|
@ -3441,24 +3449,15 @@ static void spapr_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
|
|||
if (!is_nvdimm) {
|
||||
addr = object_property_get_uint(OBJECT(dimm),
|
||||
PC_DIMM_ADDR_PROP, &error_abort);
|
||||
if (!spapr_add_lmbs(dev, addr, size,
|
||||
spapr_ovec_test(ms->ov5_cas, OV5_HP_EVT), errp)) {
|
||||
goto out_unplug;
|
||||
}
|
||||
spapr_add_lmbs(dev, addr, size,
|
||||
spapr_ovec_test(ms->ov5_cas, OV5_HP_EVT));
|
||||
} else {
|
||||
slot = object_property_get_int(OBJECT(dimm),
|
||||
PC_DIMM_SLOT_PROP, &error_abort);
|
||||
/* We should have valid slot number at this point */
|
||||
g_assert(slot >= 0);
|
||||
if (!spapr_add_nvdimm(dev, slot, errp)) {
|
||||
goto out_unplug;
|
||||
}
|
||||
spapr_add_nvdimm(dev, slot);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
out_unplug:
|
||||
pc_dimm_unplug(dimm, MACHINE(ms));
|
||||
}
|
||||
|
||||
static void spapr_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
|
||||
|
@ -3752,8 +3751,7 @@ int spapr_core_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void spapr_core_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
|
||||
Error **errp)
|
||||
static void spapr_core_plug(HotplugHandler *hotplug_dev, DeviceState *dev)
|
||||
{
|
||||
SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev));
|
||||
MachineClass *mc = MACHINE_GET_CLASS(spapr);
|
||||
|
@ -3768,20 +3766,20 @@ static void spapr_core_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
|
|||
int i;
|
||||
|
||||
core_slot = spapr_find_cpu_slot(MACHINE(hotplug_dev), cc->core_id, &index);
|
||||
if (!core_slot) {
|
||||
error_setg(errp, "Unable to find CPU core with core-id: %d",
|
||||
cc->core_id);
|
||||
return;
|
||||
}
|
||||
g_assert(core_slot); /* Already checked in spapr_core_pre_plug() */
|
||||
|
||||
drc = spapr_drc_by_id(TYPE_SPAPR_DRC_CPU,
|
||||
spapr_vcpu_id(spapr, cc->core_id));
|
||||
|
||||
g_assert(drc || !mc->has_hotpluggable_cpus);
|
||||
|
||||
if (drc) {
|
||||
if (!spapr_drc_attach(drc, dev, errp)) {
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* spapr_core_pre_plug() already buys us this is a brand new
|
||||
* core being plugged into a free slot. Nothing should already
|
||||
* be attached to the corresponding DRC.
|
||||
*/
|
||||
spapr_drc_attach(drc, dev);
|
||||
|
||||
if (hotplugged) {
|
||||
/*
|
||||
|
@ -3796,26 +3794,24 @@ static void spapr_core_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
|
|||
|
||||
core_slot->cpu = OBJECT(dev);
|
||||
|
||||
/*
|
||||
* Set compatibility mode to match the boot CPU, which was either set
|
||||
* by the machine reset code or by CAS. This really shouldn't fail at
|
||||
* this point.
|
||||
*/
|
||||
if (hotplugged) {
|
||||
for (i = 0; i < cc->nr_threads; i++) {
|
||||
ppc_set_compat(core->threads[i], POWERPC_CPU(first_cpu)->compat_pvr,
|
||||
&error_abort);
|
||||
}
|
||||
}
|
||||
|
||||
if (smc->pre_2_10_has_unused_icps) {
|
||||
for (i = 0; i < cc->nr_threads; i++) {
|
||||
cs = CPU(core->threads[i]);
|
||||
pre_2_10_vmstate_unregister_dummy_icp(cs->cpu_index);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Set compatibility mode to match the boot CPU, which was either set
|
||||
* by the machine reset code or by CAS.
|
||||
*/
|
||||
if (hotplugged) {
|
||||
for (i = 0; i < cc->nr_threads; i++) {
|
||||
if (ppc_set_compat(core->threads[i],
|
||||
POWERPC_CPU(first_cpu)->compat_pvr,
|
||||
errp) < 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void spapr_core_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
|
||||
|
@ -3893,38 +3889,45 @@ int spapr_phb_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void spapr_phb_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
|
||||
static bool spapr_phb_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
|
||||
Error **errp)
|
||||
{
|
||||
SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev));
|
||||
SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(dev);
|
||||
SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
|
||||
const unsigned windows_supported = spapr_phb_windows_supported(sphb);
|
||||
SpaprDrc *drc;
|
||||
|
||||
if (dev->hotplugged && !smc->dr_phb_enabled) {
|
||||
error_setg(errp, "PHB hotplug not supported for this machine");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sphb->index == (uint32_t)-1) {
|
||||
error_setg(errp, "\"index\" for PAPR PHB is mandatory");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
drc = spapr_drc_by_id(TYPE_SPAPR_DRC_PHB, sphb->index);
|
||||
if (drc && drc->dev) {
|
||||
error_setg(errp, "PHB %d already attached", sphb->index);
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* This will check that sphb->index doesn't exceed the maximum number of
|
||||
* PHBs for the current machine type.
|
||||
*/
|
||||
smc->phb_placement(spapr, sphb->index,
|
||||
&sphb->buid, &sphb->io_win_addr,
|
||||
&sphb->mem_win_addr, &sphb->mem64_win_addr,
|
||||
windows_supported, sphb->dma_liobn,
|
||||
&sphb->nv2_gpa_win_addr, &sphb->nv2_atsd_win_addr,
|
||||
errp);
|
||||
return
|
||||
smc->phb_placement(spapr, sphb->index,
|
||||
&sphb->buid, &sphb->io_win_addr,
|
||||
&sphb->mem_win_addr, &sphb->mem64_win_addr,
|
||||
windows_supported, sphb->dma_liobn,
|
||||
&sphb->nv2_gpa_win_addr, &sphb->nv2_atsd_win_addr,
|
||||
errp);
|
||||
}
|
||||
|
||||
static void spapr_phb_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
|
||||
Error **errp)
|
||||
static void spapr_phb_plug(HotplugHandler *hotplug_dev, DeviceState *dev)
|
||||
{
|
||||
SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev));
|
||||
SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
|
||||
|
@ -3940,9 +3943,8 @@ static void spapr_phb_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
|
|||
/* hotplug hooks should check it's enabled before getting this far */
|
||||
assert(drc);
|
||||
|
||||
if (!spapr_drc_attach(drc, dev, errp)) {
|
||||
return;
|
||||
}
|
||||
/* spapr_phb_pre_plug() already checked the DRC is attachable */
|
||||
spapr_drc_attach(drc, dev);
|
||||
|
||||
if (hotplugged) {
|
||||
spapr_hotplug_req_add_by_index(drc);
|
||||
|
@ -3979,16 +3981,27 @@ static void spapr_phb_unplug_request(HotplugHandler *hotplug_dev,
|
|||
}
|
||||
}
|
||||
|
||||
static void spapr_tpm_proxy_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
|
||||
Error **errp)
|
||||
static
|
||||
bool spapr_tpm_proxy_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
|
||||
Error **errp)
|
||||
{
|
||||
SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev));
|
||||
|
||||
if (spapr->tpm_proxy != NULL) {
|
||||
error_setg(errp, "Only one TPM proxy can be specified for this machine");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void spapr_tpm_proxy_plug(HotplugHandler *hotplug_dev, DeviceState *dev)
|
||||
{
|
||||
SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev));
|
||||
SpaprTpmProxy *tpm_proxy = SPAPR_TPM_PROXY(dev);
|
||||
|
||||
if (spapr->tpm_proxy != NULL) {
|
||||
error_setg(errp, "Only one TPM proxy can be specified for this machine");
|
||||
return;
|
||||
}
|
||||
/* Already checked in spapr_tpm_proxy_pre_plug() */
|
||||
g_assert(spapr->tpm_proxy == NULL);
|
||||
|
||||
spapr->tpm_proxy = tpm_proxy;
|
||||
}
|
||||
|
@ -4006,13 +4019,13 @@ static void spapr_machine_device_plug(HotplugHandler *hotplug_dev,
|
|||
DeviceState *dev, Error **errp)
|
||||
{
|
||||
if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
|
||||
spapr_memory_plug(hotplug_dev, dev, errp);
|
||||
spapr_memory_plug(hotplug_dev, dev);
|
||||
} else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) {
|
||||
spapr_core_plug(hotplug_dev, dev, errp);
|
||||
spapr_core_plug(hotplug_dev, dev);
|
||||
} else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) {
|
||||
spapr_phb_plug(hotplug_dev, dev, errp);
|
||||
spapr_phb_plug(hotplug_dev, dev);
|
||||
} else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_TPM_PROXY)) {
|
||||
spapr_tpm_proxy_plug(hotplug_dev, dev, errp);
|
||||
spapr_tpm_proxy_plug(hotplug_dev, dev);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4075,6 +4088,8 @@ static void spapr_machine_device_pre_plug(HotplugHandler *hotplug_dev,
|
|||
spapr_core_pre_plug(hotplug_dev, dev, errp);
|
||||
} else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) {
|
||||
spapr_phb_pre_plug(hotplug_dev, dev, errp);
|
||||
} else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_TPM_PROXY)) {
|
||||
spapr_tpm_proxy_pre_plug(hotplug_dev, dev, errp);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4158,7 +4173,7 @@ static const CPUArchIdList *spapr_possible_cpu_arch_ids(MachineState *machine)
|
|||
return machine->possible_cpus;
|
||||
}
|
||||
|
||||
static void spapr_phb_placement(SpaprMachineState *spapr, uint32_t index,
|
||||
static bool spapr_phb_placement(SpaprMachineState *spapr, uint32_t index,
|
||||
uint64_t *buid, hwaddr *pio,
|
||||
hwaddr *mmio32, hwaddr *mmio64,
|
||||
unsigned n_dma, uint32_t *liobns,
|
||||
|
@ -4196,7 +4211,7 @@ static void spapr_phb_placement(SpaprMachineState *spapr, uint32_t index,
|
|||
if (index >= SPAPR_MAX_PHBS) {
|
||||
error_setg(errp, "\"index\" for PAPR PHB is too large (max %llu)",
|
||||
SPAPR_MAX_PHBS - 1);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
*buid = base_buid + index;
|
||||
|
@ -4210,6 +4225,7 @@ static void spapr_phb_placement(SpaprMachineState *spapr, uint32_t index,
|
|||
|
||||
*nv2gpa = SPAPR_PCI_NV2RAM64_WIN_BASE + index * SPAPR_PCI_NV2RAM64_WIN_SIZE;
|
||||
*nv2atsd = SPAPR_PCI_NV2ATSD_WIN_BASE + index * SPAPR_PCI_NV2ATSD_WIN_SIZE;
|
||||
return true;
|
||||
}
|
||||
|
||||
static ICSState *spapr_ics_get(XICSFabric *dev, int irq)
|
||||
|
@ -4600,18 +4616,21 @@ DEFINE_SPAPR_MACHINE(4_1, "4.1", false);
|
|||
/*
|
||||
* pseries-4.0
|
||||
*/
|
||||
static void phb_placement_4_0(SpaprMachineState *spapr, uint32_t index,
|
||||
static bool phb_placement_4_0(SpaprMachineState *spapr, uint32_t index,
|
||||
uint64_t *buid, hwaddr *pio,
|
||||
hwaddr *mmio32, hwaddr *mmio64,
|
||||
unsigned n_dma, uint32_t *liobns,
|
||||
hwaddr *nv2gpa, hwaddr *nv2atsd, Error **errp)
|
||||
{
|
||||
spapr_phb_placement(spapr, index, buid, pio, mmio32, mmio64, n_dma, liobns,
|
||||
nv2gpa, nv2atsd, errp);
|
||||
if (!spapr_phb_placement(spapr, index, buid, pio, mmio32, mmio64, n_dma,
|
||||
liobns, nv2gpa, nv2atsd, errp)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*nv2gpa = 0;
|
||||
*nv2atsd = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void spapr_machine_4_0_class_options(MachineClass *mc)
|
||||
{
|
||||
SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
|
||||
|
@ -4771,7 +4790,7 @@ DEFINE_SPAPR_MACHINE(2_8, "2.8", false);
|
|||
* pseries-2.7
|
||||
*/
|
||||
|
||||
static void phb_placement_2_7(SpaprMachineState *spapr, uint32_t index,
|
||||
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,
|
||||
|
@ -4803,7 +4822,7 @@ static void phb_placement_2_7(SpaprMachineState *spapr, uint32_t index,
|
|||
if (index > max_index) {
|
||||
error_setg(errp, "\"index\" for PAPR PHB is too large (max %u)",
|
||||
max_index);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
*buid = base_buid + index;
|
||||
|
@ -4822,6 +4841,7 @@ static void phb_placement_2_7(SpaprMachineState *spapr, uint32_t index,
|
|||
|
||||
*nv2gpa = 0;
|
||||
*nv2atsd = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void spapr_machine_2_7_class_options(MachineClass *mc)
|
||||
|
|
|
@ -369,14 +369,11 @@ static void prop_get_fdt(Object *obj, Visitor *v, const char *name,
|
|||
} while (fdt_depth != 0);
|
||||
}
|
||||
|
||||
bool spapr_drc_attach(SpaprDrc *drc, DeviceState *d, Error **errp)
|
||||
void spapr_drc_attach(SpaprDrc *drc, DeviceState *d)
|
||||
{
|
||||
trace_spapr_drc_attach(spapr_drc_index(drc));
|
||||
|
||||
if (drc->dev) {
|
||||
error_setg(errp, "an attached device is still awaiting release");
|
||||
return false;
|
||||
}
|
||||
g_assert(!drc->dev);
|
||||
g_assert((drc->state == SPAPR_DRC_STATE_LOGICAL_UNUSABLE)
|
||||
|| (drc->state == SPAPR_DRC_STATE_PHYSICAL_POWERON));
|
||||
|
||||
|
@ -386,7 +383,6 @@ bool spapr_drc_attach(SpaprDrc *drc, DeviceState *d, Error **errp)
|
|||
object_get_typename(OBJECT(drc->dev)),
|
||||
(Object **)(&drc->dev),
|
||||
NULL, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void spapr_drc_release(SpaprDrc *drc)
|
||||
|
|
|
@ -480,9 +480,8 @@ static SpaprEventLogEntry *rtas_event_log_dequeue(SpaprMachineState *spapr,
|
|||
return entry;
|
||||
}
|
||||
|
||||
static bool rtas_event_log_contains(uint32_t event_mask)
|
||||
static bool rtas_event_log_contains(SpaprMachineState *spapr, uint32_t event_mask)
|
||||
{
|
||||
SpaprMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
|
||||
SpaprEventLogEntry *entry = NULL;
|
||||
|
||||
QTAILQ_FOREACH(entry, &spapr->pending_events, next) {
|
||||
|
@ -509,10 +508,10 @@ static void spapr_init_v6hdr(struct rtas_event_log_v6 *v6hdr)
|
|||
v6hdr->company = cpu_to_be32(RTAS_LOG_V6_COMPANY_IBM);
|
||||
}
|
||||
|
||||
static void spapr_init_maina(struct rtas_event_log_v6_maina *maina,
|
||||
static void spapr_init_maina(SpaprMachineState *spapr,
|
||||
struct rtas_event_log_v6_maina *maina,
|
||||
int section_count)
|
||||
{
|
||||
SpaprMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
|
||||
struct tm tm;
|
||||
int year;
|
||||
|
||||
|
@ -560,7 +559,7 @@ static void spapr_powerdown_req(Notifier *n, void *opaque)
|
|||
entry->extended_length = sizeof(*new_epow);
|
||||
|
||||
spapr_init_v6hdr(v6hdr);
|
||||
spapr_init_maina(maina, 3 /* Main-A, Main-B and EPOW */);
|
||||
spapr_init_maina(spapr, maina, 3 /* Main-A, Main-B and EPOW */);
|
||||
|
||||
mainb->hdr.section_id = cpu_to_be16(RTAS_LOG_V6_SECTION_ID_MAINB);
|
||||
mainb->hdr.section_length = cpu_to_be16(sizeof(*mainb));
|
||||
|
@ -613,7 +612,7 @@ static void spapr_hotplug_req_event(uint8_t hp_id, uint8_t hp_action,
|
|||
entry->extended_length = sizeof(*new_hp);
|
||||
|
||||
spapr_init_v6hdr(v6hdr);
|
||||
spapr_init_maina(maina, 3 /* Main-A, Main-B, HP */);
|
||||
spapr_init_maina(spapr, maina, 3 /* Main-A, Main-B, HP */);
|
||||
|
||||
mainb->hdr.section_id = cpu_to_be16(RTAS_LOG_V6_SECTION_ID_MAINB);
|
||||
mainb->hdr.section_length = cpu_to_be16(sizeof(*mainb));
|
||||
|
@ -808,9 +807,9 @@ static uint32_t spapr_mce_get_elog_type(PowerPCCPU *cpu, bool recovered,
|
|||
return summary;
|
||||
}
|
||||
|
||||
static void spapr_mce_dispatch_elog(PowerPCCPU *cpu, bool recovered)
|
||||
static void spapr_mce_dispatch_elog(SpaprMachineState *spapr, PowerPCCPU *cpu,
|
||||
bool recovered)
|
||||
{
|
||||
SpaprMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
|
||||
CPUState *cs = CPU(cpu);
|
||||
CPUPPCState *env = &cpu->env;
|
||||
uint64_t rtas_addr;
|
||||
|
@ -927,7 +926,7 @@ void spapr_mce_req_event(PowerPCCPU *cpu, bool recovered)
|
|||
warn_report("Received a fwnmi while migration was in progress");
|
||||
}
|
||||
|
||||
spapr_mce_dispatch_elog(cpu, recovered);
|
||||
spapr_mce_dispatch_elog(spapr, cpu, recovered);
|
||||
}
|
||||
|
||||
static void check_exception(PowerPCCPU *cpu, SpaprMachineState *spapr,
|
||||
|
@ -980,7 +979,7 @@ static void check_exception(PowerPCCPU *cpu, SpaprMachineState *spapr,
|
|||
* interrupts.
|
||||
*/
|
||||
for (i = 0; i < EVENT_CLASS_MAX; i++) {
|
||||
if (rtas_event_log_contains(EVENT_CLASS_MASK(i))) {
|
||||
if (rtas_event_log_contains(spapr, EVENT_CLASS_MASK(i))) {
|
||||
const SpaprEventSource *source =
|
||||
spapr_event_sources_get_source(spapr->event_sources, i);
|
||||
|
||||
|
@ -1007,7 +1006,7 @@ static void event_scan(PowerPCCPU *cpu, SpaprMachineState *spapr,
|
|||
}
|
||||
|
||||
for (i = 0; i < EVENT_CLASS_MAX; i++) {
|
||||
if (rtas_event_log_contains(EVENT_CLASS_MASK(i))) {
|
||||
if (rtas_event_log_contains(spapr, EVENT_CLASS_MASK(i))) {
|
||||
const SpaprEventSource *source =
|
||||
spapr_event_sources_get_source(spapr->event_sources, i);
|
||||
|
||||
|
|
|
@ -1351,6 +1351,7 @@ static target_ulong h_logical_dcbf(PowerPCCPU *cpu, SpaprMachineState *spapr,
|
|||
}
|
||||
|
||||
static target_ulong h_set_mode_resource_le(PowerPCCPU *cpu,
|
||||
SpaprMachineState *spapr,
|
||||
target_ulong mflags,
|
||||
target_ulong value1,
|
||||
target_ulong value2)
|
||||
|
@ -1365,12 +1366,12 @@ static target_ulong h_set_mode_resource_le(PowerPCCPU *cpu,
|
|||
switch (mflags) {
|
||||
case H_SET_MODE_ENDIAN_BIG:
|
||||
spapr_set_all_lpcrs(0, LPCR_ILE);
|
||||
spapr_pci_switch_vga(true);
|
||||
spapr_pci_switch_vga(spapr, true);
|
||||
return H_SUCCESS;
|
||||
|
||||
case H_SET_MODE_ENDIAN_LITTLE:
|
||||
spapr_set_all_lpcrs(LPCR_ILE, LPCR_ILE);
|
||||
spapr_pci_switch_vga(false);
|
||||
spapr_pci_switch_vga(spapr, false);
|
||||
return H_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -1411,7 +1412,7 @@ static target_ulong h_set_mode(PowerPCCPU *cpu, SpaprMachineState *spapr,
|
|||
|
||||
switch (resource) {
|
||||
case H_SET_MODE_RESOURCE_LE:
|
||||
ret = h_set_mode_resource_le(cpu, args[0], args[2], args[3]);
|
||||
ret = h_set_mode_resource_le(cpu, spapr, args[0], args[2], args[3]);
|
||||
break;
|
||||
case H_SET_MODE_RESOURCE_ADDR_TRANS_MODE:
|
||||
ret = h_set_mode_resource_addr_trans_mode(cpu, args[0],
|
||||
|
|
|
@ -186,7 +186,7 @@ static int spapr_irq_check(SpaprMachineState *spapr, Error **errp)
|
|||
if (kvm_enabled() &&
|
||||
spapr->irq == &spapr_irq_dual &&
|
||||
kvm_kernel_irqchip_required() &&
|
||||
xics_kvm_has_broken_disconnect(spapr)) {
|
||||
xics_kvm_has_broken_disconnect()) {
|
||||
error_setg(errp,
|
||||
"KVM is incompatible with ic-mode=dual,kernel-irqchip=on");
|
||||
error_append_hint(errp,
|
||||
|
|
|
@ -89,7 +89,7 @@ bool spapr_nvdimm_validate(HotplugHandler *hotplug_dev, NVDIMMDevice *nvdimm,
|
|||
}
|
||||
|
||||
|
||||
bool spapr_add_nvdimm(DeviceState *dev, uint64_t slot, Error **errp)
|
||||
void spapr_add_nvdimm(DeviceState *dev, uint64_t slot)
|
||||
{
|
||||
SpaprDrc *drc;
|
||||
bool hotplugged = spapr_drc_hotplugged(dev);
|
||||
|
@ -97,14 +97,15 @@ bool spapr_add_nvdimm(DeviceState *dev, uint64_t slot, Error **errp)
|
|||
drc = spapr_drc_by_id(TYPE_SPAPR_DRC_PMEM, slot);
|
||||
g_assert(drc);
|
||||
|
||||
if (!spapr_drc_attach(drc, dev, errp)) {
|
||||
return false;
|
||||
}
|
||||
/*
|
||||
* pc_dimm_get_free_slot() provided a free slot at pre-plug. The
|
||||
* corresponding DRC is thus assumed to be attachable.
|
||||
*/
|
||||
spapr_drc_attach(drc, dev);
|
||||
|
||||
if (hotplugged) {
|
||||
spapr_hotplug_req_add_by_index(drc);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static int spapr_dt_nvdimm(SpaprMachineState *spapr, void *fdt,
|
||||
|
|
|
@ -747,7 +747,7 @@ static PCIINTxRoute spapr_route_intx_pin_to_irq(void *opaque, int pin)
|
|||
static void spapr_msi_write(void *opaque, hwaddr addr,
|
||||
uint64_t data, unsigned size)
|
||||
{
|
||||
SpaprMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
|
||||
SpaprMachineState *spapr = opaque;
|
||||
uint32_t irq = data;
|
||||
|
||||
trace_spapr_pci_msi_write(addr, data, irq);
|
||||
|
@ -1532,8 +1532,8 @@ static bool bridge_has_valid_chassis_nr(Object *bridge, Error **errp)
|
|||
return true;
|
||||
}
|
||||
|
||||
static void spapr_pci_plug(HotplugHandler *plug_handler,
|
||||
DeviceState *plugged_dev, Error **errp)
|
||||
static void spapr_pci_pre_plug(HotplugHandler *plug_handler,
|
||||
DeviceState *plugged_dev, Error **errp)
|
||||
{
|
||||
SpaprPhbState *phb = SPAPR_PCI_HOST_BRIDGE(DEVICE(plug_handler));
|
||||
PCIDevice *pdev = PCI_DEVICE(plugged_dev);
|
||||
|
@ -1542,9 +1542,6 @@ static void spapr_pci_plug(HotplugHandler *plug_handler,
|
|||
PCIBus *bus = PCI_BUS(qdev_get_parent_bus(DEVICE(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) {
|
||||
/* if this is a hotplug operation initiated by the user
|
||||
* we need to let them know it's not enabled
|
||||
|
@ -1552,17 +1549,14 @@ static void spapr_pci_plug(HotplugHandler *plug_handler,
|
|||
if (plugged_dev->hotplugged) {
|
||||
error_setg(errp, QERR_BUS_NO_HOTPLUG,
|
||||
object_get_typename(OBJECT(phb)));
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
g_assert(drc);
|
||||
|
||||
if (pc->is_bridge) {
|
||||
if (!bridge_has_valid_chassis_nr(OBJECT(plugged_dev), errp)) {
|
||||
return;
|
||||
}
|
||||
spapr_pci_bridge_plug(phb, PCI_BRIDGE(plugged_dev));
|
||||
}
|
||||
|
||||
/* Following the QEMU convention used for PCIe multifunction
|
||||
|
@ -1574,13 +1568,41 @@ static void spapr_pci_plug(HotplugHandler *plug_handler,
|
|||
error_setg(errp, "PCI: slot %d function 0 already occupied by %s,"
|
||||
" additional functions can no longer be exposed to guest.",
|
||||
slotnr, bus->devices[PCI_DEVFN(slotnr, 0)]->name);
|
||||
}
|
||||
|
||||
if (drc && drc->dev) {
|
||||
error_setg(errp, "PCI: slot %d already occupied by %s", slotnr,
|
||||
pci_get_function_0(PCI_DEVICE(drc->dev))->name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void spapr_pci_plug(HotplugHandler *plug_handler,
|
||||
DeviceState *plugged_dev, Error **errp)
|
||||
{
|
||||
SpaprPhbState *phb = SPAPR_PCI_HOST_BRIDGE(DEVICE(plug_handler));
|
||||
PCIDevice *pdev = PCI_DEVICE(plugged_dev);
|
||||
PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(plugged_dev);
|
||||
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;
|
||||
}
|
||||
|
||||
if (!spapr_drc_attach(drc, DEVICE(pdev), errp)) {
|
||||
return;
|
||||
g_assert(drc);
|
||||
|
||||
if (pc->is_bridge) {
|
||||
spapr_pci_bridge_plug(phb, PCI_BRIDGE(plugged_dev));
|
||||
}
|
||||
|
||||
/* spapr_pci_pre_plug() already checked the DRC is attachable */
|
||||
spapr_drc_attach(drc, DEVICE(pdev));
|
||||
|
||||
/* If this is function 0, signal hotplug for all the device functions.
|
||||
* Otherwise defer sending the hotplug event.
|
||||
*/
|
||||
|
@ -2223,6 +2245,7 @@ static void spapr_phb_class_init(ObjectClass *klass, void *data)
|
|||
/* Supported by TYPE_SPAPR_MACHINE */
|
||||
dc->user_creatable = true;
|
||||
set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
|
||||
hp->pre_plug = spapr_pci_pre_plug;
|
||||
hp->plug = spapr_pci_plug;
|
||||
hp->unplug = spapr_pci_unplug;
|
||||
hp->unplug_request = spapr_pci_unplug_request;
|
||||
|
@ -2470,9 +2493,8 @@ static int spapr_switch_one_vga(DeviceState *dev, void *opaque)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void spapr_pci_switch_vga(bool big_endian)
|
||||
void spapr_pci_switch_vga(SpaprMachineState *spapr, bool big_endian)
|
||||
{
|
||||
SpaprMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
|
||||
SpaprPhbState *sphb;
|
||||
|
||||
/*
|
||||
|
|
|
@ -19,7 +19,7 @@ spapr_update_dt_failed_size(unsigned cbold, unsigned cbnew, unsigned magic) "Old
|
|||
spapr_update_dt_failed_check(unsigned cbold, unsigned cbnew, unsigned magic) "Old blob %u bytes, new blob %u bytes, magic 0x%x"
|
||||
|
||||
# spapr_tpm_proxy.c
|
||||
spapr_h_tpm_comm(const char *device_path, uint64_t operation) "tpm_device_path=%s operation=0x%"PRIu64
|
||||
spapr_h_tpm_comm(const char *device_path, uint64_t operation) "tpm_device_path=%s operation=0x%"PRIx64
|
||||
spapr_tpm_execute(uint64_t data_in, uint64_t data_in_sz, uint64_t data_out, uint64_t data_out_sz) "data_in=0x%"PRIx64", data_in_sz=%"PRIu64", data_out=0x%"PRIx64", data_out_sz=%"PRIu64
|
||||
|
||||
# spapr_iommu.c
|
||||
|
|
|
@ -140,7 +140,7 @@ struct SpaprMachineClass {
|
|||
bool pre_5_1_assoc_refpoints;
|
||||
bool pre_5_2_numa_associativity;
|
||||
|
||||
void (*phb_placement)(SpaprMachineState *spapr, uint32_t index,
|
||||
bool (*phb_placement)(SpaprMachineState *spapr, uint32_t index,
|
||||
uint64_t *buid, hwaddr *pio,
|
||||
hwaddr *mmio32, hwaddr *mmio64,
|
||||
unsigned n_dma, uint32_t *liobns, hwaddr *nv2gpa,
|
||||
|
@ -834,7 +834,7 @@ int spapr_dma_dt(void *fdt, int node_off, const char *propname,
|
|||
uint32_t liobn, uint64_t window, uint32_t size);
|
||||
int spapr_tcet_dma_dt(void *fdt, int node_off, const char *propname,
|
||||
SpaprTceTable *tcet);
|
||||
void spapr_pci_switch_vga(bool big_endian);
|
||||
void spapr_pci_switch_vga(SpaprMachineState *spapr, bool big_endian);
|
||||
void spapr_hotplug_req_add_by_index(SpaprDrc *drc);
|
||||
void spapr_hotplug_req_remove_by_index(SpaprDrc *drc);
|
||||
void spapr_hotplug_req_add_by_count(SpaprDrcType drc_type,
|
||||
|
|
|
@ -235,7 +235,13 @@ SpaprDrc *spapr_drc_by_index(uint32_t index);
|
|||
SpaprDrc *spapr_drc_by_id(const char *type, uint32_t id);
|
||||
int spapr_dt_drc(void *fdt, int offset, Object *owner, uint32_t drc_type_mask);
|
||||
|
||||
bool spapr_drc_attach(SpaprDrc *drc, DeviceState *d, Error **errp);
|
||||
/*
|
||||
* These functions respectively abort if called with a device already
|
||||
* attached or no device attached. In the case of spapr_drc_attach(),
|
||||
* this means that the attachability of the DRC *must* be checked
|
||||
* beforehand (eg. check drc->dev at pre-plug).
|
||||
*/
|
||||
void spapr_drc_attach(SpaprDrc *drc, DeviceState *d);
|
||||
void spapr_drc_detach(SpaprDrc *drc);
|
||||
|
||||
/* Returns true if a hot plug/unplug request is pending */
|
||||
|
|
|
@ -30,6 +30,6 @@ int spapr_pmem_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr,
|
|||
void spapr_dt_persistent_memory(SpaprMachineState *spapr, void *fdt);
|
||||
bool spapr_nvdimm_validate(HotplugHandler *hotplug_dev, NVDIMMDevice *nvdimm,
|
||||
uint64_t size, Error **errp);
|
||||
bool spapr_add_nvdimm(DeviceState *dev, uint64_t slot, Error **errp);
|
||||
void spapr_add_nvdimm(DeviceState *dev, uint64_t slot);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -38,6 +38,6 @@ DECLARE_INSTANCE_CHECKER(ICSState, ICS_SPAPR,
|
|||
int xics_kvm_connect(SpaprInterruptController *intc, uint32_t nr_servers,
|
||||
Error **errp);
|
||||
void xics_kvm_disconnect(SpaprInterruptController *intc);
|
||||
bool xics_kvm_has_broken_disconnect(SpaprMachineState *spapr);
|
||||
bool xics_kvm_has_broken_disconnect(void);
|
||||
|
||||
#endif /* XICS_SPAPR_H */
|
||||
|
|
|
@ -74,6 +74,11 @@ enum powerpc_mmu_t {
|
|||
POWERPC_MMU_3_00 = POWERPC_MMU_64 | 0x00000005,
|
||||
};
|
||||
|
||||
static inline bool mmu_is_64bit(powerpc_mmu_t mmu_model)
|
||||
{
|
||||
return mmu_model & POWERPC_MMU_64;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Exception model */
|
||||
typedef enum powerpc_excp_t powerpc_excp_t;
|
||||
|
|
|
@ -266,7 +266,7 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
|
|||
*/
|
||||
if (excp == POWERPC_EXCP_HV_EMU
|
||||
#if defined(TARGET_PPC64)
|
||||
&& !((env->mmu_model & POWERPC_MMU_64) && (env->msr_mask & MSR_HVB))
|
||||
&& !(mmu_is_64bit(env->mmu_model) && (env->msr_mask & MSR_HVB))
|
||||
#endif /* defined(TARGET_PPC64) */
|
||||
|
||||
) {
|
||||
|
@ -824,7 +824,7 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
|
|||
vector = (uint32_t)vector;
|
||||
}
|
||||
} else {
|
||||
if (!msr_isf && !(env->mmu_model & POWERPC_MMU_64)) {
|
||||
if (!msr_isf && !mmu_is_64bit(env->mmu_model)) {
|
||||
vector = (uint32_t)vector;
|
||||
} else {
|
||||
new_msr |= (target_ulong)1 << MSR_SF;
|
||||
|
|
|
@ -2467,101 +2467,135 @@ void helper_xscmpexpqp(CPUPPCState *env, uint32_t opcode,
|
|||
do_float_check_status(env, GETPC());
|
||||
}
|
||||
|
||||
#define VSX_SCALAR_CMP(op, ordered) \
|
||||
void helper_##op(CPUPPCState *env, uint32_t opcode, \
|
||||
ppc_vsr_t *xa, ppc_vsr_t *xb) \
|
||||
{ \
|
||||
uint32_t cc = 0; \
|
||||
bool vxsnan_flag = false, vxvc_flag = false; \
|
||||
\
|
||||
helper_reset_fpstatus(env); \
|
||||
\
|
||||
if (float64_is_signaling_nan(xa->VsrD(0), &env->fp_status) || \
|
||||
float64_is_signaling_nan(xb->VsrD(0), &env->fp_status)) { \
|
||||
vxsnan_flag = true; \
|
||||
cc = CRF_SO; \
|
||||
if (fpscr_ve == 0 && ordered) { \
|
||||
vxvc_flag = true; \
|
||||
} \
|
||||
} else if (float64_is_quiet_nan(xa->VsrD(0), &env->fp_status) || \
|
||||
float64_is_quiet_nan(xb->VsrD(0), &env->fp_status)) { \
|
||||
cc = CRF_SO; \
|
||||
if (ordered) { \
|
||||
vxvc_flag = true; \
|
||||
} \
|
||||
} \
|
||||
if (vxsnan_flag) { \
|
||||
float_invalid_op_vxsnan(env, GETPC()); \
|
||||
} \
|
||||
if (vxvc_flag) { \
|
||||
float_invalid_op_vxvc(env, 0, GETPC()); \
|
||||
} \
|
||||
\
|
||||
if (float64_lt(xa->VsrD(0), xb->VsrD(0), &env->fp_status)) { \
|
||||
cc |= CRF_LT; \
|
||||
} else if (!float64_le(xa->VsrD(0), xb->VsrD(0), &env->fp_status)) { \
|
||||
cc |= CRF_GT; \
|
||||
} else { \
|
||||
cc |= CRF_EQ; \
|
||||
} \
|
||||
\
|
||||
env->fpscr &= ~FP_FPCC; \
|
||||
env->fpscr |= cc << FPSCR_FPCC; \
|
||||
env->crf[BF(opcode)] = cc; \
|
||||
\
|
||||
do_float_check_status(env, GETPC()); \
|
||||
static inline void do_scalar_cmp(CPUPPCState *env, ppc_vsr_t *xa, ppc_vsr_t *xb,
|
||||
int crf_idx, bool ordered)
|
||||
{
|
||||
uint32_t cc;
|
||||
bool vxsnan_flag = false, vxvc_flag = false;
|
||||
|
||||
helper_reset_fpstatus(env);
|
||||
|
||||
switch (float64_compare(xa->VsrD(0), xb->VsrD(0), &env->fp_status)) {
|
||||
case float_relation_less:
|
||||
cc = CRF_LT;
|
||||
break;
|
||||
case float_relation_equal:
|
||||
cc = CRF_EQ;
|
||||
break;
|
||||
case float_relation_greater:
|
||||
cc = CRF_GT;
|
||||
break;
|
||||
case float_relation_unordered:
|
||||
cc = CRF_SO;
|
||||
|
||||
if (float64_is_signaling_nan(xa->VsrD(0), &env->fp_status) ||
|
||||
float64_is_signaling_nan(xb->VsrD(0), &env->fp_status)) {
|
||||
vxsnan_flag = true;
|
||||
if (fpscr_ve == 0 && ordered) {
|
||||
vxvc_flag = true;
|
||||
}
|
||||
} else if (float64_is_quiet_nan(xa->VsrD(0), &env->fp_status) ||
|
||||
float64_is_quiet_nan(xb->VsrD(0), &env->fp_status)) {
|
||||
if (ordered) {
|
||||
vxvc_flag = true;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
env->fpscr &= ~FP_FPCC;
|
||||
env->fpscr |= cc << FPSCR_FPCC;
|
||||
env->crf[crf_idx] = cc;
|
||||
|
||||
if (vxsnan_flag) {
|
||||
float_invalid_op_vxsnan(env, GETPC());
|
||||
}
|
||||
if (vxvc_flag) {
|
||||
float_invalid_op_vxvc(env, 0, GETPC());
|
||||
}
|
||||
|
||||
do_float_check_status(env, GETPC());
|
||||
}
|
||||
|
||||
VSX_SCALAR_CMP(xscmpodp, 1)
|
||||
VSX_SCALAR_CMP(xscmpudp, 0)
|
||||
|
||||
#define VSX_SCALAR_CMPQ(op, ordered) \
|
||||
void helper_##op(CPUPPCState *env, uint32_t opcode, \
|
||||
ppc_vsr_t *xa, ppc_vsr_t *xb) \
|
||||
{ \
|
||||
uint32_t cc = 0; \
|
||||
bool vxsnan_flag = false, vxvc_flag = false; \
|
||||
\
|
||||
helper_reset_fpstatus(env); \
|
||||
\
|
||||
if (float128_is_signaling_nan(xa->f128, &env->fp_status) || \
|
||||
float128_is_signaling_nan(xb->f128, &env->fp_status)) { \
|
||||
vxsnan_flag = true; \
|
||||
cc = CRF_SO; \
|
||||
if (fpscr_ve == 0 && ordered) { \
|
||||
vxvc_flag = true; \
|
||||
} \
|
||||
} else if (float128_is_quiet_nan(xa->f128, &env->fp_status) || \
|
||||
float128_is_quiet_nan(xb->f128, &env->fp_status)) { \
|
||||
cc = CRF_SO; \
|
||||
if (ordered) { \
|
||||
vxvc_flag = true; \
|
||||
} \
|
||||
} \
|
||||
if (vxsnan_flag) { \
|
||||
float_invalid_op_vxsnan(env, GETPC()); \
|
||||
} \
|
||||
if (vxvc_flag) { \
|
||||
float_invalid_op_vxvc(env, 0, GETPC()); \
|
||||
} \
|
||||
\
|
||||
if (float128_lt(xa->f128, xb->f128, &env->fp_status)) { \
|
||||
cc |= CRF_LT; \
|
||||
} else if (!float128_le(xa->f128, xb->f128, &env->fp_status)) { \
|
||||
cc |= CRF_GT; \
|
||||
} else { \
|
||||
cc |= CRF_EQ; \
|
||||
} \
|
||||
\
|
||||
env->fpscr &= ~FP_FPCC; \
|
||||
env->fpscr |= cc << FPSCR_FPCC; \
|
||||
env->crf[BF(opcode)] = cc; \
|
||||
\
|
||||
do_float_check_status(env, GETPC()); \
|
||||
void helper_xscmpodp(CPUPPCState *env, uint32_t opcode, ppc_vsr_t *xa,
|
||||
ppc_vsr_t *xb)
|
||||
{
|
||||
do_scalar_cmp(env, xa, xb, BF(opcode), true);
|
||||
}
|
||||
|
||||
VSX_SCALAR_CMPQ(xscmpoqp, 1)
|
||||
VSX_SCALAR_CMPQ(xscmpuqp, 0)
|
||||
void helper_xscmpudp(CPUPPCState *env, uint32_t opcode, ppc_vsr_t *xa,
|
||||
ppc_vsr_t *xb)
|
||||
{
|
||||
do_scalar_cmp(env, xa, xb, BF(opcode), false);
|
||||
}
|
||||
|
||||
static inline void do_scalar_cmpq(CPUPPCState *env, ppc_vsr_t *xa,
|
||||
ppc_vsr_t *xb, int crf_idx, bool ordered)
|
||||
{
|
||||
uint32_t cc;
|
||||
bool vxsnan_flag = false, vxvc_flag = false;
|
||||
|
||||
helper_reset_fpstatus(env);
|
||||
|
||||
switch (float128_compare(xa->f128, xb->f128, &env->fp_status)) {
|
||||
case float_relation_less:
|
||||
cc = CRF_LT;
|
||||
break;
|
||||
case float_relation_equal:
|
||||
cc = CRF_EQ;
|
||||
break;
|
||||
case float_relation_greater:
|
||||
cc = CRF_GT;
|
||||
break;
|
||||
case float_relation_unordered:
|
||||
cc = CRF_SO;
|
||||
|
||||
if (float128_is_signaling_nan(xa->f128, &env->fp_status) ||
|
||||
float128_is_signaling_nan(xb->f128, &env->fp_status)) {
|
||||
vxsnan_flag = true;
|
||||
if (fpscr_ve == 0 && ordered) {
|
||||
vxvc_flag = true;
|
||||
}
|
||||
} else if (float128_is_quiet_nan(xa->f128, &env->fp_status) ||
|
||||
float128_is_quiet_nan(xb->f128, &env->fp_status)) {
|
||||
if (ordered) {
|
||||
vxvc_flag = true;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
env->fpscr &= ~FP_FPCC;
|
||||
env->fpscr |= cc << FPSCR_FPCC;
|
||||
env->crf[crf_idx] = cc;
|
||||
|
||||
if (vxsnan_flag) {
|
||||
float_invalid_op_vxsnan(env, GETPC());
|
||||
}
|
||||
if (vxvc_flag) {
|
||||
float_invalid_op_vxvc(env, 0, GETPC());
|
||||
}
|
||||
|
||||
do_float_check_status(env, GETPC());
|
||||
}
|
||||
|
||||
void helper_xscmpoqp(CPUPPCState *env, uint32_t opcode, ppc_vsr_t *xa,
|
||||
ppc_vsr_t *xb)
|
||||
{
|
||||
do_scalar_cmpq(env, xa, xb, BF(opcode), true);
|
||||
}
|
||||
|
||||
void helper_xscmpuqp(CPUPPCState *env, uint32_t opcode, ppc_vsr_t *xa,
|
||||
ppc_vsr_t *xb)
|
||||
{
|
||||
do_scalar_cmpq(env, xa, xb, BF(opcode), false);
|
||||
}
|
||||
|
||||
/*
|
||||
* VSX_MAX_MIN - VSX floating point maximum/minimum
|
||||
|
|
|
@ -550,7 +550,7 @@ static bool sr_needed(void *opaque)
|
|||
#ifdef TARGET_PPC64
|
||||
PowerPCCPU *cpu = opaque;
|
||||
|
||||
return !(cpu->env.mmu_model & POWERPC_MMU_64);
|
||||
return !mmu_is_64bit(cpu->env.mmu_model);
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
|
@ -606,7 +606,7 @@ static bool slb_needed(void *opaque)
|
|||
PowerPCCPU *cpu = opaque;
|
||||
|
||||
/* We don't support any of the old segment table based 64-bit CPUs */
|
||||
return cpu->env.mmu_model & POWERPC_MMU_64;
|
||||
return mmu_is_64bit(cpu->env.mmu_model);
|
||||
}
|
||||
|
||||
static int slb_post_load(void *opaque, int version_id)
|
||||
|
|
|
@ -1140,7 +1140,7 @@ void ppc_hash64_init(PowerPCCPU *cpu)
|
|||
PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
|
||||
|
||||
if (!pcc->hash64_opts) {
|
||||
assert(!(env->mmu_model & POWERPC_MMU_64));
|
||||
assert(!mmu_is_64bit(env->mmu_model));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -1349,11 +1349,12 @@ void dump_mmu(CPUPPCState *env)
|
|||
break;
|
||||
case POWERPC_MMU_3_00:
|
||||
if (ppc64_v3_radix(env_archcpu(env))) {
|
||||
/* TODO - Unsupported */
|
||||
qemu_log_mask(LOG_UNIMP, "%s: the PPC64 MMU is unsupported\n",
|
||||
__func__);
|
||||
} else {
|
||||
dump_slb(env_archcpu(env));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
qemu_log_mask(LOG_UNIMP, "%s: unimplemented\n", __func__);
|
||||
|
@ -2001,7 +2002,7 @@ void helper_store_601_batl(CPUPPCState *env, uint32_t nr, target_ulong value)
|
|||
void ppc_tlb_invalidate_all(CPUPPCState *env)
|
||||
{
|
||||
#if defined(TARGET_PPC64)
|
||||
if (env->mmu_model & POWERPC_MMU_64) {
|
||||
if (mmu_is_64bit(env->mmu_model)) {
|
||||
env->tlb_need_flush = 0;
|
||||
tlb_flush(env_cpu(env));
|
||||
} else
|
||||
|
@ -2045,7 +2046,7 @@ void ppc_tlb_invalidate_one(CPUPPCState *env, target_ulong addr)
|
|||
#if !defined(FLUSH_ALL_TLBS)
|
||||
addr &= TARGET_PAGE_MASK;
|
||||
#if defined(TARGET_PPC64)
|
||||
if (env->mmu_model & POWERPC_MMU_64) {
|
||||
if (mmu_is_64bit(env->mmu_model)) {
|
||||
/* tlbie invalidate TLBs for all segments */
|
||||
/*
|
||||
* XXX: given the fact that there are too many segments to invalidate,
|
||||
|
@ -2090,7 +2091,7 @@ void ppc_store_sdr1(CPUPPCState *env, target_ulong value)
|
|||
qemu_log_mask(CPU_LOG_MMU, "%s: " TARGET_FMT_lx "\n", __func__, value);
|
||||
assert(!cpu->vhyp);
|
||||
#if defined(TARGET_PPC64)
|
||||
if (env->mmu_model & POWERPC_MMU_64) {
|
||||
if (mmu_is_64bit(env->mmu_model)) {
|
||||
target_ulong sdr_mask = SDR_64_HTABORG | SDR_64_HTABSIZE;
|
||||
target_ulong htabsize = value & SDR_64_HTABSIZE;
|
||||
|
||||
|
@ -2143,7 +2144,7 @@ void ppc_store_ptcr(CPUPPCState *env, target_ulong value)
|
|||
target_ulong helper_load_sr(CPUPPCState *env, target_ulong sr_num)
|
||||
{
|
||||
#if defined(TARGET_PPC64)
|
||||
if (env->mmu_model & POWERPC_MMU_64) {
|
||||
if (mmu_is_64bit(env->mmu_model)) {
|
||||
/* XXX */
|
||||
return 0;
|
||||
}
|
||||
|
@ -2157,7 +2158,7 @@ void helper_store_sr(CPUPPCState *env, target_ulong srnum, target_ulong value)
|
|||
"%s: reg=%d " TARGET_FMT_lx " " TARGET_FMT_lx "\n", __func__,
|
||||
(int)srnum, value, env->sr[srnum]);
|
||||
#if defined(TARGET_PPC64)
|
||||
if (env->mmu_model & POWERPC_MMU_64) {
|
||||
if (mmu_is_64bit(env->mmu_model)) {
|
||||
PowerPCCPU *cpu = env_archcpu(env);
|
||||
uint64_t esid, vsid;
|
||||
|
||||
|
|
|
@ -7892,7 +7892,7 @@ static void ppc_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
|
|||
ctx->insns_flags = env->insns_flags;
|
||||
ctx->insns_flags2 = env->insns_flags2;
|
||||
ctx->access_type = -1;
|
||||
ctx->need_access_type = !(env->mmu_model & POWERPC_MMU_64B);
|
||||
ctx->need_access_type = !mmu_is_64bit(env->mmu_model);
|
||||
ctx->le_mode = !!(env->hflags & (1 << MSR_LE));
|
||||
ctx->default_tcg_memop_mask = ctx->le_mode ? MO_LE : MO_BE;
|
||||
ctx->flags = env->flags;
|
||||
|
@ -7902,7 +7902,7 @@ static void ppc_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
|
|||
#endif
|
||||
ctx->lazy_tlb_flush = env->mmu_model == POWERPC_MMU_32B
|
||||
|| env->mmu_model == POWERPC_MMU_601
|
||||
|| (env->mmu_model & POWERPC_MMU_64B);
|
||||
|| env->mmu_model & POWERPC_MMU_64;
|
||||
|
||||
ctx->fpu_enabled = !!msr_fp;
|
||||
if ((env->flags & POWERPC_FLAG_SPE) && msr_spe) {
|
||||
|
|
|
@ -75,29 +75,6 @@ static void gen_lxvd2x(DisasContext *ctx)
|
|||
tcg_temp_free_i64(t0);
|
||||
}
|
||||
|
||||
static void gen_lxvdsx(DisasContext *ctx)
|
||||
{
|
||||
TCGv EA;
|
||||
TCGv_i64 t0;
|
||||
TCGv_i64 t1;
|
||||
if (unlikely(!ctx->vsx_enabled)) {
|
||||
gen_exception(ctx, POWERPC_EXCP_VSXU);
|
||||
return;
|
||||
}
|
||||
t0 = tcg_temp_new_i64();
|
||||
t1 = tcg_temp_new_i64();
|
||||
gen_set_access_type(ctx, ACCESS_INT);
|
||||
EA = tcg_temp_new();
|
||||
gen_addr_reg_index(ctx, EA);
|
||||
gen_qemu_ld64_i64(ctx, t0, EA);
|
||||
set_cpu_vsrh(xT(ctx->opcode), t0);
|
||||
tcg_gen_mov_i64(t1, t0);
|
||||
set_cpu_vsrl(xT(ctx->opcode), t1);
|
||||
tcg_temp_free(EA);
|
||||
tcg_temp_free_i64(t0);
|
||||
tcg_temp_free_i64(t1);
|
||||
}
|
||||
|
||||
static void gen_lxvw4x(DisasContext *ctx)
|
||||
{
|
||||
TCGv EA;
|
||||
|
@ -169,6 +146,29 @@ static void gen_lxvwsx(DisasContext *ctx)
|
|||
tcg_temp_free_i32(data);
|
||||
}
|
||||
|
||||
static void gen_lxvdsx(DisasContext *ctx)
|
||||
{
|
||||
TCGv EA;
|
||||
TCGv_i64 data;
|
||||
|
||||
if (unlikely(!ctx->vsx_enabled)) {
|
||||
gen_exception(ctx, POWERPC_EXCP_VSXU);
|
||||
return;
|
||||
}
|
||||
|
||||
gen_set_access_type(ctx, ACCESS_INT);
|
||||
EA = tcg_temp_new();
|
||||
|
||||
gen_addr_reg_index(ctx, EA);
|
||||
|
||||
data = tcg_temp_new_i64();
|
||||
tcg_gen_qemu_ld_i64(data, EA, ctx->mem_idx, MO_TEQ);
|
||||
tcg_gen_gvec_dup_i64(MO_Q, vsr_full_offset(xT(ctx->opcode)), 16, 16, data);
|
||||
|
||||
tcg_temp_free(EA);
|
||||
tcg_temp_free_i64(data);
|
||||
}
|
||||
|
||||
static void gen_bswap16x8(TCGv_i64 outh, TCGv_i64 outl,
|
||||
TCGv_i64 inh, TCGv_i64 inl)
|
||||
{
|
||||
|
|
|
@ -10470,63 +10470,6 @@ static ObjectClass *ppc_cpu_class_by_name(const char *name)
|
|||
return oc;
|
||||
}
|
||||
|
||||
static void ppc_cpu_parse_featurestr(const char *type, char *features,
|
||||
Error **errp)
|
||||
{
|
||||
Object *machine = qdev_get_machine();
|
||||
const PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(object_class_by_name(type));
|
||||
|
||||
if (!features) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (object_property_find(machine, "max-cpu-compat")) {
|
||||
int i;
|
||||
char **inpieces;
|
||||
char *s = features;
|
||||
Error *local_err = NULL;
|
||||
char *compat_str = NULL;
|
||||
|
||||
/*
|
||||
* Backwards compatibility hack:
|
||||
*
|
||||
* CPUs had a "compat=" property which didn't make sense for
|
||||
* anything except pseries. It was replaced by "max-cpu-compat"
|
||||
* machine option. This supports old command lines like
|
||||
* -cpu POWER8,compat=power7
|
||||
* By stripping the compat option and applying it to the machine
|
||||
* before passing it on to the cpu level parser.
|
||||
*/
|
||||
inpieces = g_strsplit(features, ",", 0);
|
||||
*s = '\0';
|
||||
for (i = 0; inpieces[i]; i++) {
|
||||
if (g_str_has_prefix(inpieces[i], "compat=")) {
|
||||
warn_report_once("CPU 'compat' property is deprecated; "
|
||||
"use max-cpu-compat machine property instead");
|
||||
compat_str = inpieces[i];
|
||||
continue;
|
||||
}
|
||||
if ((i != 0) && (s != features)) {
|
||||
s = g_stpcpy(s, ",");
|
||||
}
|
||||
s = g_stpcpy(s, inpieces[i]);
|
||||
}
|
||||
|
||||
if (compat_str) {
|
||||
char *v = compat_str + strlen("compat=");
|
||||
object_property_set_str(machine, "max-cpu-compat", v, &local_err);
|
||||
}
|
||||
g_strfreev(inpieces);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* do property processing with generic handler */
|
||||
pcc->parent_parse_features(type, features, errp);
|
||||
}
|
||||
|
||||
PowerPCCPUClass *ppc_cpu_get_family_class(PowerPCCPUClass *pcc)
|
||||
{
|
||||
ObjectClass *oc = OBJECT_CLASS(pcc);
|
||||
|
@ -10728,7 +10671,7 @@ static void ppc_cpu_reset(DeviceState *dev)
|
|||
#endif
|
||||
|
||||
#if defined(TARGET_PPC64)
|
||||
if (env->mmu_model & POWERPC_MMU_64) {
|
||||
if (mmu_is_64bit(env->mmu_model)) {
|
||||
msr |= (1ULL << MSR_SF);
|
||||
}
|
||||
#endif
|
||||
|
@ -10905,8 +10848,6 @@ static void ppc_cpu_class_init(ObjectClass *oc, void *data)
|
|||
device_class_set_parent_reset(dc, ppc_cpu_reset, &pcc->parent_reset);
|
||||
|
||||
cc->class_by_name = ppc_cpu_class_by_name;
|
||||
pcc->parent_parse_features = cc->parse_features;
|
||||
cc->parse_features = ppc_cpu_parse_featurestr;
|
||||
cc->has_work = ppc_cpu_has_work;
|
||||
cc->do_interrupt = ppc_cpu_do_interrupt;
|
||||
cc->cpu_exec_interrupt = ppc_cpu_exec_interrupt;
|
||||
|
|
Loading…
Reference in New Issue