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:
Peter Maydell 2020-12-14 16:31:15 +00:00
commit 37f04b71a9
30 changed files with 480 additions and 344 deletions

View File

@ -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*

View File

@ -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)
'''''''''''''''''''''''''''

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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)) {

View File

@ -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);
}

View File

@ -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)

View File

@ -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)

View File

@ -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);

View File

@ -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],

View File

@ -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,

View File

@ -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,

View File

@ -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;
/*

View File

@ -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

View File

@ -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,

View File

@ -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 */

View File

@ -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

View File

@ -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 */

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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)

View File

@ -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;
}

View File

@ -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;

View File

@ -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) {

View File

@ -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)
{

View File

@ -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;