aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2019-02-18 16:20:13 +0000
committerPeter Maydell <peter.maydell@linaro.org>2019-02-18 16:20:13 +0000
commit2e68b8620637a4ee8c79b5724144b726af1e261b (patch)
treee53cbfaf5cbdd0d0b0c326838634e92096540256
parenta0430dd8abb8a2f31c5ee919daab2e3d76353c04 (diff)
parent73e14c6a9cdefb94c01ea488f04e7fba7ac0dc5b (diff)
Merge remote-tracking branch 'remotes/dgibson/tags/ppc-for-4.0-20190219' into staging
ppc patch queue 2019-02-19 Here's the next batch of ppc and spapr patches. Higlights are: * A bunch of improvements to TCG handling of vector instructions from Richard Henderson and Marc Cave-Ayland * Cleanup to the XICS interrupt controller from Greg Kurz, removing the special KVM subclasses which were a bad idea * Some refinements to the XIVE interrupt controller from Cédric Le Goater * Fix from Fabiano Rosas for a really dumb buffer overflow in the device tree code for memory hotplug * Code for allowing access to SPRs from the gdb stub from Fabiano Rosas * Assorted minor fixes and cleanups # gpg: Signature made Mon 18 Feb 2019 13:47:54 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/dgibson/tags/ppc-for-4.0-20190219: (43 commits) target/ppc: convert vmin* and vmax* to vector operations target/ppc: convert vadd*s and vsub*s to vector operations target/ppc: Split out VSCR_SAT to a vector field target/ppc: Add set_vscr_sat target/ppc: Use mtvscr/mfvscr for vmstate target/ppc: Add helper_mfvscr target/ppc: Remove vscr_nj and vscr_sat target/ppc: Use helper_mtvscr for reset and gdb target/ppc: Pass integer to helper_mtvscr target/ppc: convert xxsel to vector operations target/ppc: convert xxspltw to vector operations target/ppc: convert xxspltib to vector operations target/ppc: convert VSX logical operations to vector operations target/ppc: convert vsplt[bhw] to use vector operations target/ppc: convert vspltis[bhw] to use vector operations target/ppc: convert vaddu[b,h,w,d] and vsubu[b,h,w,d] over to use vector operations target/ppc: convert VMX logical instructions to use vector operations xics: Drop the KVM ICS class spapr/irq: Use the "simple" ICS class for KVM xics: Handle KVM interrupt presentation from "simple" ICS code ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r--hw/acpi/pcihp.c2
-rw-r--r--hw/acpi/piix4.c2
-rw-r--r--hw/char/virtio-serial-bus.c2
-rw-r--r--hw/core/bus.c11
-rw-r--r--hw/intc/spapr_xive.c7
-rw-r--r--hw/intc/xics.c76
-rw-r--r--hw/intc/xics_kvm.c120
-rw-r--r--hw/misc/macio/cuda.c11
-rw-r--r--hw/pci/pcie.c2
-rw-r--r--hw/pci/shpc.c2
-rw-r--r--hw/ppc/mac_newworld.c2
-rw-r--r--hw/ppc/prep.c1
-rw-r--r--hw/ppc/spapr.c10
-rw-r--r--hw/ppc/spapr_events.c2
-rw-r--r--hw/ppc/spapr_irq.c86
-rw-r--r--hw/ppc/spapr_pci.c14
-rw-r--r--hw/ppc/spapr_vio.c2
-rw-r--r--hw/s390x/css-bridge.c2
-rw-r--r--hw/s390x/s390-pci-bus.c6
-rw-r--r--hw/scsi/virtio-scsi.c2
-rw-r--r--hw/scsi/vmw_pvscsi.c2
-rw-r--r--hw/usb/dev-smartcard-reader.c2
-rw-r--r--include/hw/pci-host/spapr.h2
-rw-r--r--include/hw/ppc/spapr.h3
-rw-r--r--include/hw/ppc/spapr_irq.h2
-rw-r--r--include/hw/ppc/xics.h26
-rw-r--r--include/hw/ppc/xive.h7
-rw-r--r--include/hw/qdev-core.h3
-rw-r--r--target/ppc/arch_dump.c3
-rw-r--r--target/ppc/cpu-qom.h4
-rw-r--r--target/ppc/cpu.h11
-rw-r--r--target/ppc/excp_helper.c12
-rw-r--r--target/ppc/gdbstub.c61
-rw-r--r--target/ppc/helper.h57
-rw-r--r--target/ppc/int_helper.c129
-rw-r--r--target/ppc/machine.c44
-rw-r--r--target/ppc/mmu_helper.c12
-rw-r--r--target/ppc/translate.c49
-rw-r--r--target/ppc/translate/vmx-impl.inc.c251
-rw-r--r--target/ppc/translate/vsx-impl.inc.c147
-rw-r--r--target/ppc/translate_init.inc.c71
41 files changed, 581 insertions, 679 deletions
diff --git a/hw/acpi/pcihp.c b/hw/acpi/pcihp.c
index 7bc7a72340..9429181323 100644
--- a/hw/acpi/pcihp.c
+++ b/hw/acpi/pcihp.c
@@ -251,7 +251,7 @@ void acpi_pcihp_device_plug_cb(HotplugHandler *hotplug_dev, AcpiPciHpState *s,
object_dynamic_cast(OBJECT(dev), TYPE_PCI_BRIDGE)) {
PCIBus *sec = pci_bridge_get_sec_bus(PCI_BRIDGE(pdev));
- qbus_set_hotplug_handler(BUS(sec), DEVICE(hotplug_dev),
+ qbus_set_hotplug_handler(BUS(sec), OBJECT(hotplug_dev),
&error_abort);
/* We don't have to overwrite any other hotplug handler yet */
assert(QLIST_EMPTY(&sec->child));
diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c
index 88f9a9ec09..df8c0db909 100644
--- a/hw/acpi/piix4.c
+++ b/hw/acpi/piix4.c
@@ -536,7 +536,7 @@ static void piix4_pm_realize(PCIDevice *dev, Error **errp)
piix4_acpi_system_hot_add_init(pci_address_space_io(dev),
pci_get_bus(dev), s);
- qbus_set_hotplug_handler(BUS(pci_get_bus(dev)), DEVICE(s), &error_abort);
+ qbus_set_hotplug_handler(BUS(pci_get_bus(dev)), OBJECT(s), &error_abort);
piix4_pm_add_propeties(s);
}
diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c
index d76351d748..bdd917bbb8 100644
--- a/hw/char/virtio-serial-bus.c
+++ b/hw/char/virtio-serial-bus.c
@@ -1052,7 +1052,7 @@ static void virtio_serial_device_realize(DeviceState *dev, Error **errp)
/* Spawn a new virtio-serial bus on which the ports will ride as devices */
qbus_create_inplace(&vser->bus, sizeof(vser->bus), TYPE_VIRTIO_SERIAL_BUS,
dev, vdev->bus_name);
- qbus_set_hotplug_handler(BUS(&vser->bus), DEVICE(vser), errp);
+ qbus_set_hotplug_handler(BUS(&vser->bus), OBJECT(vser), errp);
vser->bus.vser = vser;
QTAILQ_INIT(&vser->ports);
diff --git a/hw/core/bus.c b/hw/core/bus.c
index 4651f24486..e09843f6ab 100644
--- a/hw/core/bus.c
+++ b/hw/core/bus.c
@@ -22,22 +22,15 @@
#include "hw/qdev.h"
#include "qapi/error.h"
-static void qbus_set_hotplug_handler_internal(BusState *bus, Object *handler,
- Error **errp)
+void qbus_set_hotplug_handler(BusState *bus, Object *handler, Error **errp)
{
-
object_property_set_link(OBJECT(bus), OBJECT(handler),
QDEV_HOTPLUG_HANDLER_PROPERTY, errp);
}
-void qbus_set_hotplug_handler(BusState *bus, DeviceState *handler, Error **errp)
-{
- qbus_set_hotplug_handler_internal(bus, OBJECT(handler), errp);
-}
-
void qbus_set_bus_hotplug_handler(BusState *bus, Error **errp)
{
- qbus_set_hotplug_handler_internal(bus, OBJECT(bus), errp);
+ qbus_set_hotplug_handler(bus, OBJECT(bus), errp);
}
int qbus_walk_children(BusState *bus,
diff --git a/hw/intc/spapr_xive.c b/hw/intc/spapr_xive.c
index a0f5ff9294..290a290e43 100644
--- a/hw/intc/spapr_xive.c
+++ b/hw/intc/spapr_xive.c
@@ -489,20 +489,19 @@ bool spapr_xive_irq_claim(sPAPRXive *xive, uint32_t lisn, bool lsi)
}
xive->eat[lisn].w |= cpu_to_be64(EAS_VALID);
- xive_source_irq_set(xsrc, lisn, lsi);
+ if (lsi) {
+ xive_source_irq_set_lsi(xsrc, lisn);
+ }
return true;
}
bool spapr_xive_irq_free(sPAPRXive *xive, uint32_t lisn)
{
- XiveSource *xsrc = &xive->source;
-
if (lisn >= xive->nr_irqs) {
return false;
}
xive->eat[lisn].w &= cpu_to_be64(~EAS_VALID);
- xive_source_irq_set(xsrc, lisn, false);
return true;
}
diff --git a/hw/intc/xics.c b/hw/intc/xics.c
index 16e8ffa2aa..3009fa7472 100644
--- a/hw/intc/xics.c
+++ b/hw/intc/xics.c
@@ -37,18 +37,18 @@
#include "qapi/visitor.h"
#include "monitor/monitor.h"
#include "hw/intc/intc.h"
+#include "sysemu/kvm.h"
void icp_pic_print_info(ICPState *icp, Monitor *mon)
{
- ICPStateClass *icpc = ICP_GET_CLASS(icp);
int cpu_index = icp->cs ? icp->cs->cpu_index : -1;
if (!icp->output) {
return;
}
- if (icpc->synchronize_state) {
- icpc->synchronize_state(icp);
+ if (kvm_irqchip_in_kernel()) {
+ icp_synchronize_state(icp);
}
monitor_printf(mon, "CPU %d XIRR=%08x (%p) PP=%02x MFRR=%02x\n",
@@ -58,7 +58,6 @@ void icp_pic_print_info(ICPState *icp, Monitor *mon)
void ics_pic_print_info(ICSState *ics, Monitor *mon)
{
- ICSStateClass *icsc = ICS_BASE_GET_CLASS(ics);
uint32_t i;
monitor_printf(mon, "ICS %4x..%4x %p\n",
@@ -68,8 +67,8 @@ void ics_pic_print_info(ICSState *ics, Monitor *mon)
return;
}
- if (icsc->synchronize_state) {
- icsc->synchronize_state(ics);
+ if (kvm_irqchip_in_kernel()) {
+ ics_synchronize_state(ics);
}
for (i = 0; i < ics->nr_irqs; i++) {
@@ -252,25 +251,23 @@ static void icp_irq(ICSState *ics, int server, int nr, uint8_t priority)
}
}
-static int icp_dispatch_pre_save(void *opaque)
+static int icp_pre_save(void *opaque)
{
ICPState *icp = opaque;
- ICPStateClass *info = ICP_GET_CLASS(icp);
- if (info->pre_save) {
- info->pre_save(icp);
+ if (kvm_irqchip_in_kernel()) {
+ icp_get_kvm_state(icp);
}
return 0;
}
-static int icp_dispatch_post_load(void *opaque, int version_id)
+static int icp_post_load(void *opaque, int version_id)
{
ICPState *icp = opaque;
- ICPStateClass *info = ICP_GET_CLASS(icp);
- if (info->post_load) {
- return info->post_load(icp, version_id);
+ if (kvm_irqchip_in_kernel()) {
+ return icp_set_kvm_state(icp);
}
return 0;
@@ -280,8 +277,8 @@ static const VMStateDescription vmstate_icp_server = {
.name = "icp/server",
.version_id = 1,
.minimum_version_id = 1,
- .pre_save = icp_dispatch_pre_save,
- .post_load = icp_dispatch_post_load,
+ .pre_save = icp_pre_save,
+ .post_load = icp_post_load,
.fields = (VMStateField[]) {
/* Sanity check */
VMSTATE_UINT32(xirr, ICPState),
@@ -291,7 +288,7 @@ static const VMStateDescription vmstate_icp_server = {
},
};
-static void icp_reset(DeviceState *dev)
+static void icp_reset_handler(void *dev)
{
ICPState *icp = ICP(dev);
@@ -301,13 +298,10 @@ static void icp_reset(DeviceState *dev)
/* Make all outputs are deasserted */
qemu_set_irq(icp->output, 0);
-}
-
-static void icp_reset_handler(void *dev)
-{
- DeviceClass *dc = DEVICE_GET_CLASS(dev);
- dc->reset(dev);
+ if (kvm_irqchip_in_kernel()) {
+ icp_set_kvm_state(ICP(dev));
+ }
}
static void icp_realize(DeviceState *dev, Error **errp)
@@ -354,6 +348,14 @@ static void icp_realize(DeviceState *dev, Error **errp)
return;
}
+ if (kvm_irqchip_in_kernel()) {
+ icp_kvm_realize(dev, &err);
+ if (err) {
+ error_propagate(errp, err);
+ return;
+ }
+ }
+
qemu_register_reset(icp_reset_handler, dev);
vmstate_register(NULL, icp->cs->cpu_index, &vmstate_icp_server, icp);
}
@@ -372,7 +374,6 @@ static void icp_class_init(ObjectClass *klass, void *data)
dc->realize = icp_realize;
dc->unrealize = icp_unrealize;
- dc->reset = icp_reset;
}
static const TypeInfo icp_info = {
@@ -465,6 +466,11 @@ void ics_simple_set_irq(void *opaque, int srcno, int val)
{
ICSState *ics = (ICSState *)opaque;
+ if (kvm_irqchip_in_kernel()) {
+ ics_kvm_set_irq(ics, srcno, val);
+ return;
+ }
+
if (ics->irqs[srcno].flags & XICS_FLAGS_IRQ_LSI) {
ics_simple_set_irq_lsi(ics, srcno, val);
} else {
@@ -552,6 +558,10 @@ static void ics_simple_reset(DeviceState *dev)
ICSStateClass *icsc = ICS_BASE_GET_CLASS(dev);
icsc->parent_reset(dev);
+
+ if (kvm_irqchip_in_kernel()) {
+ ics_set_kvm_state(ICS_BASE(dev));
+ }
}
static void ics_simple_reset_handler(void *dev)
@@ -645,25 +655,23 @@ static void ics_base_instance_init(Object *obj)
ics->offset = XICS_IRQ_BASE;
}
-static int ics_base_dispatch_pre_save(void *opaque)
+static int ics_base_pre_save(void *opaque)
{
ICSState *ics = opaque;
- ICSStateClass *info = ICS_BASE_GET_CLASS(ics);
- if (info->pre_save) {
- info->pre_save(ics);
+ if (kvm_irqchip_in_kernel()) {
+ ics_get_kvm_state(ics);
}
return 0;
}
-static int ics_base_dispatch_post_load(void *opaque, int version_id)
+static int ics_base_post_load(void *opaque, int version_id)
{
ICSState *ics = opaque;
- ICSStateClass *info = ICS_BASE_GET_CLASS(ics);
- if (info->post_load) {
- return info->post_load(ics, version_id);
+ if (kvm_irqchip_in_kernel()) {
+ return ics_set_kvm_state(ics);
}
return 0;
@@ -687,8 +695,8 @@ static const VMStateDescription vmstate_ics_base = {
.name = "ics",
.version_id = 1,
.minimum_version_id = 1,
- .pre_save = ics_base_dispatch_pre_save,
- .post_load = ics_base_dispatch_post_load,
+ .pre_save = ics_base_pre_save,
+ .post_load = ics_base_post_load,
.fields = (VMStateField[]) {
/* Sanity check */
VMSTATE_UINT32_EQUAL(nr_irqs, ICSState, NULL),
diff --git a/hw/intc/xics_kvm.c b/hw/intc/xics_kvm.c
index dff1330050..a00d0a7962 100644
--- a/hw/intc/xics_kvm.c
+++ b/hw/intc/xics_kvm.c
@@ -54,7 +54,7 @@ static QLIST_HEAD(, KVMEnabledICP)
/*
* ICP-KVM
*/
-static void icp_get_kvm_state(ICPState *icp)
+void icp_get_kvm_state(ICPState *icp)
{
uint64_t state;
int ret;
@@ -83,14 +83,14 @@ static void do_icp_synchronize_state(CPUState *cpu, run_on_cpu_data arg)
icp_get_kvm_state(arg.host_ptr);
}
-static void icp_synchronize_state(ICPState *icp)
+void icp_synchronize_state(ICPState *icp)
{
if (icp->cs) {
run_on_cpu(icp->cs, do_icp_synchronize_state, RUN_ON_CPU_HOST_PTR(icp));
}
}
-static int icp_set_kvm_state(ICPState *icp, int version_id)
+int icp_set_kvm_state(ICPState *icp)
{
uint64_t state;
int ret;
@@ -115,20 +115,9 @@ static int icp_set_kvm_state(ICPState *icp, int version_id)
return 0;
}
-static void icp_kvm_reset(DeviceState *dev)
-{
- ICPStateClass *icpc = ICP_GET_CLASS(dev);
-
- icpc->parent_reset(dev);
-
- icp_set_kvm_state(ICP(dev), 1);
-}
-
-static void icp_kvm_realize(DeviceState *dev, Error **errp)
+void icp_kvm_realize(DeviceState *dev, Error **errp)
{
ICPState *icp = ICP(dev);
- ICPStateClass *icpc = ICP_GET_CLASS(icp);
- Error *local_err = NULL;
CPUState *cs;
KVMEnabledICP *enabled_icp;
unsigned long vcpu_id;
@@ -138,12 +127,6 @@ static void icp_kvm_realize(DeviceState *dev, Error **errp)
abort();
}
- icpc->parent_realize(dev, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- return;
- }
-
cs = icp->cs;
vcpu_id = kvm_arch_vcpu_id(cs);
@@ -169,33 +152,10 @@ static void icp_kvm_realize(DeviceState *dev, Error **errp)
QLIST_INSERT_HEAD(&kvm_enabled_icps, enabled_icp, node);
}
-static void icp_kvm_class_init(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
- ICPStateClass *icpc = ICP_CLASS(klass);
-
- device_class_set_parent_realize(dc, icp_kvm_realize,
- &icpc->parent_realize);
- device_class_set_parent_reset(dc, icp_kvm_reset,
- &icpc->parent_reset);
-
- icpc->pre_save = icp_get_kvm_state;
- icpc->post_load = icp_set_kvm_state;
- icpc->synchronize_state = icp_synchronize_state;
-}
-
-static const TypeInfo icp_kvm_info = {
- .name = TYPE_KVM_ICP,
- .parent = TYPE_ICP,
- .instance_size = sizeof(ICPState),
- .class_init = icp_kvm_class_init,
- .class_size = sizeof(ICPStateClass),
-};
-
/*
* ICS-KVM
*/
-static void ics_get_kvm_state(ICSState *ics)
+void ics_get_kvm_state(ICSState *ics)
{
uint64_t state;
int i;
@@ -248,12 +208,12 @@ static void ics_get_kvm_state(ICSState *ics)
}
}
-static void ics_synchronize_state(ICSState *ics)
+void ics_synchronize_state(ICSState *ics)
{
ics_get_kvm_state(ics);
}
-static int ics_set_kvm_state(ICSState *ics, int version_id)
+int ics_set_kvm_state(ICSState *ics)
{
uint64_t state;
int i;
@@ -299,9 +259,8 @@ static int ics_set_kvm_state(ICSState *ics, int version_id)
return 0;
}
-void ics_kvm_set_irq(void *opaque, int srcno, int val)
+void ics_kvm_set_irq(ICSState *ics, int srcno, int val)
{
- ICSState *ics = opaque;
struct kvm_irq_level args;
int rc;
@@ -320,61 +279,6 @@ void ics_kvm_set_irq(void *opaque, int srcno, int val)
}
}
-static void ics_kvm_reset(DeviceState *dev)
-{
- ICSStateClass *icsc = ICS_BASE_GET_CLASS(dev);
-
- icsc->parent_reset(dev);
-
- ics_set_kvm_state(ICS_KVM(dev), 1);
-}
-
-static void ics_kvm_reset_handler(void *dev)
-{
- ics_kvm_reset(dev);
-}
-
-static void ics_kvm_realize(DeviceState *dev, Error **errp)
-{
- ICSState *ics = ICS_KVM(dev);
- ICSStateClass *icsc = ICS_BASE_GET_CLASS(ics);
- Error *local_err = NULL;
-
- icsc->parent_realize(dev, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- return;
- }
-
- qemu_register_reset(ics_kvm_reset_handler, ics);
-}
-
-static void ics_kvm_class_init(ObjectClass *klass, void *data)
-{
- ICSStateClass *icsc = ICS_BASE_CLASS(klass);
- DeviceClass *dc = DEVICE_CLASS(klass);
-
- device_class_set_parent_realize(dc, ics_kvm_realize,
- &icsc->parent_realize);
- device_class_set_parent_reset(dc, ics_kvm_reset,
- &icsc->parent_reset);
-
- icsc->pre_save = ics_get_kvm_state;
- icsc->post_load = ics_set_kvm_state;
- icsc->synchronize_state = ics_synchronize_state;
-}
-
-static const TypeInfo ics_kvm_info = {
- .name = TYPE_ICS_KVM,
- .parent = TYPE_ICS_BASE,
- .instance_size = sizeof(ICSState),
- .class_init = ics_kvm_class_init,
-};
-
-/*
- * XICS-KVM
- */
-
static void rtas_dummy(PowerPCCPU *cpu, sPAPRMachineState *spapr,
uint32_t token,
uint32_t nargs, target_ulong args,
@@ -444,11 +348,3 @@ fail:
kvmppc_define_rtas_kernel_token(0, "ibm,int-off");
return -1;
}
-
-static void xics_kvm_register_types(void)
-{
- type_register_static(&ics_kvm_info);
- type_register_static(&icp_kvm_info);
-}
-
-type_init(xics_kvm_register_types)
diff --git a/hw/misc/macio/cuda.c b/hw/misc/macio/cuda.c
index c4f7a2f39b..3febacdd1e 100644
--- a/hw/misc/macio/cuda.c
+++ b/hw/misc/macio/cuda.c
@@ -97,17 +97,8 @@ static void cuda_set_sr_int(void *opaque)
static void cuda_delay_set_sr_int(CUDAState *s)
{
- MOS6522CUDAState *mcs = &s->mos6522_cuda;
- MOS6522State *ms = MOS6522(mcs);
- MOS6522DeviceClass *mdc = MOS6522_DEVICE_GET_CLASS(ms);
int64_t expire;
- if (ms->dirb == 0xff || s->sr_delay_ns == 0) {
- /* Disabled or not in Mac OS, fire the IRQ directly */
- mdc->set_sr_int(ms);
- return;
- }
-
trace_cuda_delay_set_sr_int();
expire = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + s->sr_delay_ns;
@@ -542,7 +533,7 @@ static void cuda_realize(DeviceState *dev, Error **errp)
s->tick_offset = (uint32_t)mktimegm(&tm) + RTC_OFFSET;
s->sr_delay_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, cuda_set_sr_int, s);
- s->sr_delay_ns = 300 * SCALE_US;
+ s->sr_delay_ns = 20 * SCALE_US;
s->adb_poll_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, cuda_adb_poll, s);
s->adb_poll_mask = 0xffff;
diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c
index 230478faab..3f7c366093 100644
--- a/hw/pci/pcie.c
+++ b/hw/pci/pcie.c
@@ -543,7 +543,7 @@ void pcie_cap_slot_init(PCIDevice *dev, uint16_t slot)
dev->exp.hpev_notified = false;
qbus_set_hotplug_handler(BUS(pci_bridge_get_sec_bus(PCI_BRIDGE(dev))),
- DEVICE(dev), NULL);
+ OBJECT(dev), NULL);
}
void pcie_cap_slot_reset(PCIDevice *dev)
diff --git a/hw/pci/shpc.c b/hw/pci/shpc.c
index 45053b39b9..52ccdc5ae3 100644
--- a/hw/pci/shpc.c
+++ b/hw/pci/shpc.c
@@ -648,7 +648,7 @@ int shpc_init(PCIDevice *d, PCIBus *sec_bus, MemoryRegion *bar,
shpc_cap_update_dword(d);
memory_region_add_subregion(bar, offset, &shpc->mmio);
- qbus_set_hotplug_handler(BUS(sec_bus), DEVICE(d), NULL);
+ qbus_set_hotplug_handler(BUS(sec_bus), OBJECT(d), NULL);
d->cap_present |= QEMU_PCI_CAP_SHPC;
return 0;
diff --git a/hw/ppc/mac_newworld.c b/hw/ppc/mac_newworld.c
index 10be728c37..98461052ac 100644
--- a/hw/ppc/mac_newworld.c
+++ b/hw/ppc/mac_newworld.c
@@ -432,7 +432,7 @@ static void ppc_core99_init(MachineState *machine)
}
for (i = 0; i < nb_nics; i++) {
- pci_nic_init_nofail(&nd_table[i], pci_bus, "ne2k_pci", NULL);
+ pci_nic_init_nofail(&nd_table[i], pci_bus, "sungem", NULL);
}
/* The NewWorld NVRAM is not located in the MacIO device */
diff --git a/hw/ppc/prep.c b/hw/ppc/prep.c
index 7bda86a7d0..847d320465 100644
--- a/hw/ppc/prep.c
+++ b/hw/ppc/prep.c
@@ -26,7 +26,6 @@
#include "cpu.h"
#include "hw/hw.h"
#include "hw/timer/m48t59.h"
-#include "hw/i386/pc.h"
#include "hw/char/serial.h"
#include "hw/block/fdc.h"
#include "net/net.h"
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 332cba89d4..abf9ebce59 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -96,7 +96,7 @@
#define MIN_RMA_SLOF 128UL
-#define PHANDLE_XICP 0x00001111
+#define PHANDLE_INTC 0x00001111
/* These two functions implement the VCPU id numbering: one to compute them
* all and one to identify thread 0 of a VCORE. Any change to the first one
@@ -687,14 +687,14 @@ static int spapr_populate_drmem_v2(sPAPRMachineState *spapr, void *fdt,
int offset, MemoryDeviceInfoList *dimms)
{
MachineState *machine = MACHINE(spapr);
- uint8_t *int_buf, *cur_index, buf_len;
+ uint8_t *int_buf, *cur_index;
int ret;
uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE;
uint64_t addr, cur_addr, size;
uint32_t nr_boot_lmbs = (machine->device_memory->base / lmb_size);
uint64_t mem_end = machine->device_memory->base +
memory_region_size(&machine->device_memory->mr);
- uint32_t node, nr_entries = 0;
+ uint32_t node, buf_len, nr_entries = 0;
sPAPRDRConnector *drc;
DrconfCellQueue *elem, *next;
MemoryDeviceInfoList *info;
@@ -1274,7 +1274,7 @@ static void *spapr_build_fdt(sPAPRMachineState *spapr)
/* /interrupt controller */
spapr->irq->dt_populate(spapr, spapr_max_server_number(spapr), fdt,
- PHANDLE_XICP);
+ PHANDLE_INTC);
ret = spapr_populate_memory(spapr, fdt);
if (ret < 0) {
@@ -1294,7 +1294,7 @@ static void *spapr_build_fdt(sPAPRMachineState *spapr)
}
QLIST_FOREACH(phb, &spapr->phbs, list) {
- ret = spapr_populate_pci_dt(phb, PHANDLE_XICP, fdt,
+ ret = spapr_populate_pci_dt(phb, PHANDLE_INTC, fdt,
spapr->irq->nr_msis);
if (ret < 0) {
error_report("couldn't setup PCI devices in fdt");
diff --git a/hw/ppc/spapr_events.c b/hw/ppc/spapr_events.c
index 32719a1b72..b9c7ecb9e9 100644
--- a/hw/ppc/spapr_events.c
+++ b/hw/ppc/spapr_events.c
@@ -282,7 +282,7 @@ void spapr_dt_events(sPAPRMachineState *spapr, void *fdt)
continue;
}
- spapr_dt_xics_irq(interrupts, source->irq, false);
+ spapr_dt_irq(interrupts, source->irq, false);
_FDT(node_offset = fdt_add_subnode(fdt, event_sources, source_name));
_FDT(fdt_setprop(fdt, node_offset, "interrupts", interrupts,
diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c
index 2d7a7c1638..4297eed600 100644
--- a/hw/ppc/spapr_irq.c
+++ b/hw/ppc/spapr_irq.c
@@ -67,13 +67,12 @@ void spapr_irq_msi_reset(sPAPRMachineState *spapr)
*/
static ICSState *spapr_ics_create(sPAPRMachineState *spapr,
- const char *type_ics,
int nr_irqs, Error **errp)
{
Error *local_err = NULL;
Object *obj;
- obj = object_new(type_ics);
+ obj = object_new(TYPE_ICS_SIMPLE);
object_property_add_child(OBJECT(spapr), "ics", obj, &error_abort);
object_property_add_const_link(obj, ICS_PROP_XICS, OBJECT(spapr),
&error_abort);
@@ -93,20 +92,19 @@ error:
return NULL;
}
-static void spapr_irq_init_xics(sPAPRMachineState *spapr, Error **errp)
+static void spapr_irq_init_xics(sPAPRMachineState *spapr, int nr_irqs,
+ Error **errp)
{
MachineState *machine = MACHINE(spapr);
- int nr_irqs = spapr->irq->nr_irqs;
Error *local_err = NULL;
+ bool xics_kvm = false;
if (kvm_enabled()) {
if (machine_kernel_irqchip_allowed(machine) &&
!xics_kvm_init(spapr, &local_err)) {
- spapr->icp_type = TYPE_KVM_ICP;
- spapr->ics = spapr_ics_create(spapr, TYPE_ICS_KVM, nr_irqs,
- &local_err);
+ xics_kvm = true;
}
- if (machine_kernel_irqchip_required(machine) && !spapr->ics) {
+ if (machine_kernel_irqchip_required(machine) && !xics_kvm) {
error_prepend(&local_err,
"kernel_irqchip requested but unavailable: ");
goto error;
@@ -115,13 +113,12 @@ static void spapr_irq_init_xics(sPAPRMachineState *spapr, Error **errp)
local_err = NULL;
}
- if (!spapr->ics) {
+ if (!xics_kvm) {
xics_spapr_init(spapr);
- spapr->icp_type = TYPE_ICP;
- spapr->ics = spapr_ics_create(spapr, TYPE_ICS_SIMPLE, nr_irqs,
- &local_err);
}
+ spapr->ics = spapr_ics_create(spapr, nr_irqs, &local_err);
+
error:
error_propagate(errp, local_err);
}
@@ -199,7 +196,7 @@ static void spapr_irq_cpu_intc_create_xics(sPAPRMachineState *spapr,
Object *obj;
sPAPRCPUState *spapr_cpu = spapr_cpu_state(cpu);
- obj = icp_create(OBJECT(cpu), spapr->icp_type, XICS_FABRIC(spapr),
+ obj = icp_create(OBJECT(cpu), TYPE_ICP, XICS_FABRIC(spapr),
&local_err);
if (local_err) {
error_propagate(errp, local_err);
@@ -211,7 +208,7 @@ static void spapr_irq_cpu_intc_create_xics(sPAPRMachineState *spapr,
static int spapr_irq_post_load_xics(sPAPRMachineState *spapr, int version_id)
{
- if (!object_dynamic_cast(OBJECT(spapr->ics), TYPE_ICS_KVM)) {
+ if (!kvm_irqchip_in_kernel()) {
CPUState *cs;
CPU_FOREACH(cs) {
PowerPCCPU *cpu = POWERPC_CPU(cs);
@@ -224,13 +221,8 @@ static int spapr_irq_post_load_xics(sPAPRMachineState *spapr, int version_id)
static void spapr_irq_set_irq_xics(void *opaque, int srcno, int val)
{
sPAPRMachineState *spapr = opaque;
- MachineState *machine = MACHINE(opaque);
- if (kvm_enabled() && machine_kernel_irqchip_allowed(machine)) {
- ics_kvm_set_irq(spapr->ics, srcno, val);
- } else {
- ics_simple_set_irq(spapr->ics, srcno, val);
- }
+ ics_simple_set_irq(spapr->ics, srcno, val);
}
static void spapr_irq_reset_xics(sPAPRMachineState *spapr, Error **errp)
@@ -262,7 +254,8 @@ sPAPRIrq spapr_irq_xics = {
/*
* XIVE IRQ backend.
*/
-static void spapr_irq_init_xive(sPAPRMachineState *spapr, Error **errp)
+static void spapr_irq_init_xive(sPAPRMachineState *spapr, int nr_irqs,
+ Error **errp)
{
MachineState *machine = MACHINE(spapr);
uint32_t nr_servers = spapr_max_server_number(spapr);
@@ -278,7 +271,7 @@ static void spapr_irq_init_xive(sPAPRMachineState *spapr, Error **errp)
}
dev = qdev_create(NULL, TYPE_SPAPR_XIVE);
- qdev_prop_set_uint32(dev, "nr-irqs", spapr->irq->nr_irqs);
+ qdev_prop_set_uint32(dev, "nr-irqs", nr_irqs);
/*
* 8 XIVE END structures per CPU. One for each available priority
*/
@@ -435,7 +428,8 @@ static sPAPRIrq *spapr_irq_current(sPAPRMachineState *spapr)
&spapr_irq_xive : &spapr_irq_xics;
}
-static void spapr_irq_init_dual(sPAPRMachineState *spapr, Error **errp)
+static void spapr_irq_init_dual(sPAPRMachineState *spapr, int nr_irqs,
+ Error **errp)
{
MachineState *machine = MACHINE(spapr);
Error *local_err = NULL;
@@ -445,24 +439,13 @@ static void spapr_irq_init_dual(sPAPRMachineState *spapr, Error **errp)
return;
}
- spapr_irq_xics.init(spapr, &local_err);
+ spapr_irq_xics.init(spapr, spapr_irq_xics.nr_irqs, &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
}
- /*
- * Align the XICS and the XIVE IRQ number space under QEMU.
- *
- * However, the XICS KVM device still considers that the IRQ
- * numbers should start at XICS_IRQ_BASE (0x1000). Either we
- * should introduce a KVM device ioctl to set the offset or ignore
- * the lower 4K numbers when using the get/set ioctl of the XICS
- * KVM device. The second option seems the least intrusive.
- */
- spapr->ics->offset = 0;
-
- spapr_irq_xive.init(spapr, &local_err);
+ spapr_irq_xive.init(spapr, spapr_irq_xive.nr_irqs, &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
@@ -498,21 +481,7 @@ static void spapr_irq_free_dual(sPAPRMachineState *spapr, int irq, int num)
static qemu_irq spapr_qirq_dual(sPAPRMachineState *spapr, int irq)
{
- sPAPRXive *xive = spapr->xive;
- ICSState *ics = spapr->ics;
-
- if (irq >= spapr->irq->nr_irqs) {
- return NULL;
- }
-
- /*
- * The IRQ number should have been claimed under both interrupt
- * controllers.
- */
- assert(!ICS_IRQ_FREE(ics, irq - ics->offset));
- assert(xive_eas_is_valid(&xive->eat[irq]));
-
- return spapr->qirqs[irq];
+ return spapr_irq_current(spapr)->qirq(spapr, irq);
}
static void spapr_irq_print_info_dual(sPAPRMachineState *spapr, Monitor *mon)
@@ -600,12 +569,25 @@ sPAPRIrq spapr_irq_dual = {
*/
void spapr_irq_init(sPAPRMachineState *spapr, Error **errp)
{
+ MachineState *machine = MACHINE(spapr);
+
+ if (machine_kernel_irqchip_split(machine)) {
+ error_setg(errp, "kernel_irqchip split mode not supported on pseries");
+ return;
+ }
+
+ if (!kvm_enabled() && machine_kernel_irqchip_required(machine)) {
+ error_setg(errp,
+ "kernel_irqchip requested but only available with KVM");
+ return;
+ }
+
/* Initialize the MSI IRQ allocator. */
if (!SPAPR_MACHINE_GET_CLASS(spapr)->legacy_irq_allocation) {
spapr_irq_msi_init(spapr, spapr->irq->nr_msis);
}
- spapr->irq->init(spapr, errp);
+ spapr->irq->init(spapr, spapr->irq->nr_irqs, errp);
spapr->qirqs = qemu_allocate_irqs(spapr->irq->set_irq, spapr,
spapr->irq->nr_irqs);
diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
index c99721cde8..60777b2355 100644
--- a/hw/ppc/spapr_pci.c
+++ b/hw/ppc/spapr_pci.c
@@ -393,6 +393,12 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPRMachineState *spapr,
for (i = 0; i < req_num; i++) {
spapr_irq_claim(spapr, irq + i, false, &err);
if (err) {
+ if (i) {
+ spapr_irq_free(spapr, irq, i);
+ }
+ if (!smc->legacy_irq_allocation) {
+ spapr_irq_msi_free(spapr, irq, req_num);
+ }
error_reportf_err(err, "Can't allocate MSIs for device %x: ",
config_addr);
rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
@@ -1680,7 +1686,7 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp)
&sphb->memspace, &sphb->iospace,
PCI_DEVFN(0, 0), PCI_NUM_PINS, TYPE_PCI_BUS);
phb->bus = bus;
- qbus_set_hotplug_handler(BUS(phb->bus), DEVICE(sphb), NULL);
+ qbus_set_hotplug_handler(BUS(phb->bus), OBJECT(sphb), NULL);
/*
* Initialize PHB address space.
@@ -2063,7 +2069,7 @@ static void spapr_phb_pci_enumerate(sPAPRPHBState *phb)
}
-int spapr_populate_pci_dt(sPAPRPHBState *phb, uint32_t xics_phandle, void *fdt,
+int spapr_populate_pci_dt(sPAPRPHBState *phb, uint32_t intc_phandle, void *fdt,
uint32_t nr_msis)
{
int bus_off, i, j, ret;
@@ -2161,8 +2167,8 @@ int spapr_populate_pci_dt(sPAPRPHBState *phb, uint32_t xics_phandle, void *fdt,
irqmap[1] = 0;
irqmap[2] = 0;
irqmap[3] = cpu_to_be32(j+1);
- irqmap[4] = cpu_to_be32(xics_phandle);
- spapr_dt_xics_irq(&irqmap[5], phb->lsi_table[lsi_num].irq, true);
+ irqmap[4] = cpu_to_be32(intc_phandle);
+ spapr_dt_irq(&irqmap[5], phb->lsi_table[lsi_num].irq, true);
}
}
/* Write interrupt map */
diff --git a/hw/ppc/spapr_vio.c b/hw/ppc/spapr_vio.c
index 414673d313..2b7e7ecac5 100644
--- a/hw/ppc/spapr_vio.c
+++ b/hw/ppc/spapr_vio.c
@@ -126,7 +126,7 @@ static int vio_make_devnode(VIOsPAPRDevice *dev,
if (dev->irq) {
uint32_t ints_prop[2];
- spapr_dt_xics_irq(ints_prop, dev->irq, false);
+ spapr_dt_irq(ints_prop, dev->irq, false);
ret = fdt_setprop(fdt, node_off, "interrupts", ints_prop,
sizeof(ints_prop));
if (ret < 0) {
diff --git a/hw/s390x/css-bridge.c b/hw/s390x/css-bridge.c
index 1bd6c8b458..7573c40bad 100644
--- a/hw/s390x/css-bridge.c
+++ b/hw/s390x/css-bridge.c
@@ -108,7 +108,7 @@ VirtualCssBus *virtual_css_bus_init(void)
cbus = VIRTUAL_CSS_BUS(bus);
/* Enable hotplugging */
- qbus_set_hotplug_handler(bus, dev, &error_abort);
+ qbus_set_hotplug_handler(bus, OBJECT(dev), &error_abort);
css_register_io_adapters(CSS_IO_ADAPTER_VIRTIO, true, false,
0, &error_abort);
diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c
index 80ff1ce33f..5998942b4c 100644
--- a/hw/s390x/s390-pci-bus.c
+++ b/hw/s390x/s390-pci-bus.c
@@ -742,7 +742,7 @@ static void s390_pcihost_realize(DeviceState *dev, Error **errp)
pci_setup_iommu(b, s390_pci_dma_iommu, s);
bus = BUS(b);
- qbus_set_hotplug_handler(bus, dev, &local_err);
+ qbus_set_hotplug_handler(bus, OBJECT(dev), &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
@@ -750,7 +750,7 @@ static void s390_pcihost_realize(DeviceState *dev, Error **errp)
phb->bus = b;
s->bus = S390_PCI_BUS(qbus_create(TYPE_S390_PCI_BUS, dev, NULL));
- qbus_set_hotplug_handler(BUS(s->bus), dev, &local_err);
+ qbus_set_hotplug_handler(BUS(s->bus), OBJECT(dev), &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
@@ -912,7 +912,7 @@ static void s390_pcihost_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
pci_bridge_map_irq(pb, dev->id, s390_pci_map_irq);
pci_setup_iommu(&pb->sec_bus, s390_pci_dma_iommu, s);
- qbus_set_hotplug_handler(BUS(&pb->sec_bus), DEVICE(s), errp);
+ qbus_set_hotplug_handler(BUS(&pb->sec_bus), OBJECT(s), errp);
if (dev->hotplugged) {
pci_default_write_config(pdev, PCI_PRIMARY_BUS,
diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
index eb90288f47..ce99d288b0 100644
--- a/hw/scsi/virtio-scsi.c
+++ b/hw/scsi/virtio-scsi.c
@@ -906,7 +906,7 @@ static void virtio_scsi_device_realize(DeviceState *dev, Error **errp)
scsi_bus_new(&s->bus, sizeof(s->bus), dev,
&virtio_scsi_scsi_info, vdev->bus_name);
/* override default SCSI bus hotplug-handler, with virtio-scsi's one */
- qbus_set_hotplug_handler(BUS(&s->bus), dev, &error_abort);
+ qbus_set_hotplug_handler(BUS(&s->bus), OBJECT(dev), &error_abort);
virtio_scsi_dataplane_setup(s, errp);
}
diff --git a/hw/scsi/vmw_pvscsi.c b/hw/scsi/vmw_pvscsi.c
index a3a019e30a..584b4be07e 100644
--- a/hw/scsi/vmw_pvscsi.c
+++ b/hw/scsi/vmw_pvscsi.c
@@ -1142,7 +1142,7 @@ pvscsi_realizefn(PCIDevice *pci_dev, Error **errp)
scsi_bus_new(&s->bus, sizeof(s->bus), DEVICE(pci_dev),
&pvscsi_scsi_info, NULL);
/* override default SCSI bus hotplug-handler, with pvscsi's one */
- qbus_set_hotplug_handler(BUS(&s->bus), DEVICE(s), &error_abort);
+ qbus_set_hotplug_handler(BUS(&s->bus), OBJECT(s), &error_abort);
pvscsi_reset_state(s);
}
diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c
index 8f716fc165..6b0137bb76 100644
--- a/hw/usb/dev-smartcard-reader.c
+++ b/hw/usb/dev-smartcard-reader.c
@@ -1322,7 +1322,7 @@ static void ccid_realize(USBDevice *dev, Error **errp)
usb_desc_init(dev);
qbus_create_inplace(&s->bus, sizeof(s->bus), TYPE_CCID_BUS, DEVICE(dev),
NULL);
- qbus_set_hotplug_handler(BUS(&s->bus), DEVICE(dev), &error_abort);
+ qbus_set_hotplug_handler(BUS(&s->bus), OBJECT(dev), &error_abort);
s->intr = usb_ep_get(dev, USB_TOKEN_IN, CCID_INT_IN_EP);
s->bulk = usb_ep_get(dev, USB_TOKEN_IN, CCID_BULK_IN_EP);
s->card = NULL;
diff --git a/include/hw/pci-host/spapr.h b/include/hw/pci-host/spapr.h
index a5a7bf4837..51d81c4b7c 100644
--- a/include/hw/pci-host/spapr.h
+++ b/include/hw/pci-host/spapr.h
@@ -112,7 +112,7 @@ static inline qemu_irq spapr_phb_lsi_qirq(struct sPAPRPHBState *phb, int pin)
return spapr_qirq(spapr, phb->lsi_table[pin].irq);
}
-int spapr_populate_pci_dt(sPAPRPHBState *phb, uint32_t xics_phandle, void *fdt,
+int spapr_populate_pci_dt(sPAPRPHBState *phb, uint32_t intc_phandle, void *fdt,
uint32_t nr_msis);
void spapr_pci_rtas_init(void);
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index a947a0a0dc..631fc5103b 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -178,7 +178,6 @@ struct sPAPRMachineState {
/*< public >*/
char *kvm_type;
- const char *icp_type;
int32_t irq_map_nr;
unsigned long *irq_map;
sPAPRXive *xive;
@@ -683,7 +682,7 @@ void spapr_load_rtas(sPAPRMachineState *spapr, void *fdt, hwaddr addr);
* "interrupt-controller" node has its "#interrupt-cells" property set to 2 (ie,
* VIO devices, RTAS event sources and PHBs).
*/
-static inline void spapr_dt_xics_irq(uint32_t *intspec, int irq, bool is_lsi)
+static inline void spapr_dt_irq(uint32_t *intspec, int irq, bool is_lsi)
{
intspec[0] = cpu_to_be32(irq);
intspec[1] = is_lsi ? cpu_to_be32(1) : 0;
diff --git a/include/hw/ppc/spapr_irq.h b/include/hw/ppc/spapr_irq.h
index 14b02c3aca..488511c3d8 100644
--- a/include/hw/ppc/spapr_irq.h
+++ b/include/hw/ppc/spapr_irq.h
@@ -35,7 +35,7 @@ typedef struct sPAPRIrq {
uint32_t nr_msis;
uint8_t ov5;
- void (*init)(sPAPRMachineState *spapr, Error **errp);
+ void (*init)(sPAPRMachineState *spapr, int nr_irqs, Error **errp);
int (*claim)(sPAPRMachineState *spapr, int irq, bool lsi, Error **errp);
void (*free)(sPAPRMachineState *spapr, int irq, int num);
qemu_irq (*qirq)(sPAPRMachineState *spapr, int irq);
diff --git a/include/hw/ppc/xics.h b/include/hw/ppc/xics.h
index fad786e8b2..d36bbe11ee 100644
--- a/include/hw/ppc/xics.h
+++ b/include/hw/ppc/xics.h
@@ -50,9 +50,6 @@ typedef struct XICSFabric XICSFabric;
#define TYPE_ICP "icp"
#define ICP(obj) OBJECT_CHECK(ICPState, (obj), TYPE_ICP)
-#define TYPE_KVM_ICP "icp-kvm"
-#define KVM_ICP(obj) OBJECT_CHECK(ICPState, (obj), TYPE_KVM_ICP)
-
#define TYPE_PNV_ICP "pnv-icp"
#define PNV_ICP(obj) OBJECT_CHECK(PnvICPState, (obj), TYPE_PNV_ICP)
@@ -65,11 +62,6 @@ struct ICPStateClass {
DeviceClass parent_class;
DeviceRealize parent_realize;
- DeviceReset parent_reset;
-
- void (*pre_save)(ICPState *icp);
- int (*post_load)(ICPState *icp, int version_id);
- void (*synchronize_state)(ICPState *icp);
};
struct ICPState {
@@ -103,9 +95,6 @@ struct PnvICPState {
#define TYPE_ICS_SIMPLE "ics"
#define ICS_SIMPLE(obj) OBJECT_CHECK(ICSState, (obj), TYPE_ICS_SIMPLE)
-#define TYPE_ICS_KVM "icskvm"
-#define ICS_KVM(obj) OBJECT_CHECK(ICSState, (obj), TYPE_ICS_KVM)
-
#define ICS_BASE_CLASS(klass) \
OBJECT_CLASS_CHECK(ICSStateClass, (klass), TYPE_ICS_BASE)
#define ICS_BASE_GET_CLASS(obj) \
@@ -117,12 +106,9 @@ struct ICSStateClass {
DeviceRealize parent_realize;
DeviceReset parent_reset;
- void (*pre_save)(ICSState *s);
- int (*post_load)(ICSState *s, int version_id);
void (*reject)(ICSState *s, uint32_t irq);
void (*resend)(ICSState *s);
void (*eoi)(ICSState *s, uint32_t irq);
- void (*synchronize_state)(ICSState *s);
};
struct ICSState {
@@ -191,7 +177,6 @@ void icp_eoi(ICPState *icp, uint32_t xirr);
void ics_simple_write_xive(ICSState *ics, int nr, int server,
uint8_t priority, uint8_t saved_priority);
void ics_simple_set_irq(void *opaque, int srcno, int val);
-void ics_kvm_set_irq(void *opaque, int srcno, int val);
void ics_set_irq_type(ICSState *ics, int srcno, bool lsi);
void icp_pic_print_info(ICPState *icp, Monitor *mon);
@@ -203,4 +188,15 @@ void icp_resend(ICPState *ss);
Object *icp_create(Object *cpu, const char *type, XICSFabric *xi,
Error **errp);
+/* KVM */
+void icp_get_kvm_state(ICPState *icp);
+int icp_set_kvm_state(ICPState *icp);
+void icp_synchronize_state(ICPState *icp);
+void icp_kvm_realize(DeviceState *dev, Error **errp);
+
+void ics_get_kvm_state(ICSState *ics);
+int ics_set_kvm_state(ICSState *ics);
+void ics_synchronize_state(ICSState *ics);
+void ics_kvm_set_irq(ICSState *ics, int srcno, int val);
+
#endif /* XICS_H */
diff --git a/include/hw/ppc/xive.h b/include/hw/ppc/xive.h
index ec3bb2aae4..13a487527b 100644
--- a/include/hw/ppc/xive.h
+++ b/include/hw/ppc/xive.h
@@ -283,13 +283,10 @@ static inline bool xive_source_irq_is_lsi(XiveSource *xsrc, uint32_t srcno)
return test_bit(srcno, xsrc->lsi_map);
}
-static inline void xive_source_irq_set(XiveSource *xsrc, uint32_t srcno,
- bool lsi)
+static inline void xive_source_irq_set_lsi(XiveSource *xsrc, uint32_t srcno)
{
assert(srcno < xsrc->nr_irqs);
- if (lsi) {
- bitmap_set(xsrc->lsi_map, srcno, 1);
- }
+ bitmap_set(xsrc->lsi_map, srcno, 1);
}
void xive_source_set_irq(void *opaque, int srcno, int val);
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
index 0a84c42756..e70a4bfa49 100644
--- a/include/hw/qdev-core.h
+++ b/include/hw/qdev-core.h
@@ -430,8 +430,7 @@ char *qdev_get_dev_path(DeviceState *dev);
GSList *qdev_build_hotpluggable_device_list(Object *peripheral);
-void qbus_set_hotplug_handler(BusState *bus, DeviceState *handler,
- Error **errp);
+void qbus_set_hotplug_handler(BusState *bus, Object *handler, Error **errp);
void qbus_set_bus_hotplug_handler(BusState *bus, Error **errp);
diff --git a/target/ppc/arch_dump.c b/target/ppc/arch_dump.c
index 3a00606d01..9ab04b2c38 100644
--- a/target/ppc/arch_dump.c
+++ b/target/ppc/arch_dump.c
@@ -17,6 +17,7 @@
#include "elf.h"
#include "sysemu/dump.h"
#include "sysemu/kvm.h"
+#include "exec/helper-proto.h"
#ifdef TARGET_PPC64
#define ELFCLASS ELFCLASS64
@@ -175,7 +176,7 @@ static void ppc_write_elf_vmxregset(NoteFuncArg *arg, PowerPCCPU *cpu)
vmxregset->avr[i].u64[1] = avr->u64[1];
}
}
- vmxregset->vscr.u32[3] = cpu_to_dump32(s, cpu->env.vscr);
+ vmxregset->vscr.u32[3] = cpu_to_dump32(s, helper_mfvscr(&cpu->env));
}
static void ppc_write_elf_vsxregset(NoteFuncArg *arg, PowerPCCPU *cpu)
diff --git a/target/ppc/cpu-qom.h b/target/ppc/cpu-qom.h
index 4ea67692e2..3130802304 100644
--- a/target/ppc/cpu-qom.h
+++ b/target/ppc/cpu-qom.h
@@ -179,6 +179,10 @@ typedef struct PowerPCCPUClass {
uint32_t flags;
int bfd_mach;
uint32_t l1_dcache_size, l1_icache_size;
+#ifndef CONFIG_USER_ONLY
+ unsigned int gdb_num_sprs;
+ const char *gdb_spr_xml;
+#endif
const PPCHash64Options *hash64_opts;
struct ppc_radix_page_info *radix_page_info;
void (*init_proc)(CPUPPCState *env);
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index 2c22292e7f..325ebbeb98 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -230,6 +230,7 @@ struct ppc_spr_t {
void (*oea_write)(DisasContext *ctx, int spr_num, int gpr_num);
void (*hea_read)(DisasContext *ctx, int gpr_num, int spr_num);
void (*hea_write)(DisasContext *ctx, int spr_num, int gpr_num);
+ unsigned int gdb_id;
#endif
const char *name;
target_ulong default_value;
@@ -688,8 +689,6 @@ enum {
/* Vector status and control register */
#define VSCR_NJ 16 /* Vector non-java */
#define VSCR_SAT 0 /* Vector saturation */
-#define vscr_nj (((env->vscr) >> VSCR_NJ) & 0x1)
-#define vscr_sat (((env->vscr) >> VSCR_SAT) & 0x1)
/*****************************************************************************/
/* BookE e500 MMU registers */
@@ -1053,10 +1052,12 @@ struct CPUPPCState {
/* Special purpose registers */
target_ulong spr[1024];
ppc_spr_t spr_cb[1024];
- /* Vector status and control register */
+ /* Vector status and control register, minus VSCR_SAT. */
uint32_t vscr;
/* VSX registers (including FP and AVR) */
ppc_vsr_t vsr[64] QEMU_ALIGNED(16);
+ /* Non-zero if and only if VSCR_SAT should be set. */
+ ppc_vsr_t vscr_sat QEMU_ALIGNED(16);
/* SPE registers */
uint64_t spe_acc;
uint32_t spe_fscr;
@@ -1263,6 +1264,10 @@ int ppc_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
int ppc_cpu_gdb_read_register_apple(CPUState *cpu, uint8_t *buf, int reg);
int ppc_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
int ppc_cpu_gdb_write_register_apple(CPUState *cpu, uint8_t *buf, int reg);
+#ifndef CONFIG_USER_ONLY
+void ppc_gdb_gen_spr_xml(PowerPCCPU *cpu);
+const char *ppc_gdb_get_dynamic_xml(CPUState *cs, const char *xml_name);
+#endif
int ppc64_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
int cpuid, void *opaque);
int ppc32_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs,
diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
index 0ec7ae1ad4..751d759fcc 100644
--- a/target/ppc/excp_helper.c
+++ b/target/ppc/excp_helper.c
@@ -748,13 +748,7 @@ void ppc_cpu_do_interrupt(CPUState *cs)
static void ppc_hw_interrupt(CPUPPCState *env)
{
PowerPCCPU *cpu = ppc_env_get_cpu(env);
-#if 0
- CPUState *cs = CPU(cpu);
- qemu_log_mask(CPU_LOG_INT, "%s: %p pending %08x req %08x me %d ee %d\n",
- __func__, env, env->pending_interrupts,
- cs->interrupt_request, (int)msr_me, (int)msr_ee);
-#endif
/* External reset */
if (env->pending_interrupts & (1 << PPC_INTERRUPT_RESET)) {
env->pending_interrupts &= ~(1 << PPC_INTERRUPT_RESET);
@@ -797,12 +791,6 @@ static void ppc_hw_interrupt(CPUPPCState *env)
if (msr_ce != 0) {
/* External critical interrupt */
if (env->pending_interrupts & (1 << PPC_INTERRUPT_CEXT)) {
- /* Taking a critical external interrupt does not clear the external
- * critical interrupt status
- */
-#if 0
- env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CEXT);
-#endif
powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_CRITICAL);
return;
}
diff --git a/target/ppc/gdbstub.c b/target/ppc/gdbstub.c
index 19565b584d..fbf3821f4b 100644
--- a/target/ppc/gdbstub.c
+++ b/target/ppc/gdbstub.c
@@ -319,3 +319,64 @@ int ppc_cpu_gdb_write_register_apple(CPUState *cs, uint8_t *mem_buf, int n)
}
return r;
}
+
+#ifndef CONFIG_USER_ONLY
+void ppc_gdb_gen_spr_xml(PowerPCCPU *cpu)
+{
+ PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
+ CPUPPCState *env = &cpu->env;
+ GString *xml;
+ char *spr_name;
+ unsigned int num_regs = 0;
+ int i;
+
+ if (pcc->gdb_spr_xml) {
+ return;
+ }
+
+ xml = g_string_new("<?xml version=\"1.0\"?>");
+ g_string_append(xml, "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">");
+ g_string_append(xml, "<feature name=\"org.qemu.power.spr\">");
+
+ for (i = 0; i < ARRAY_SIZE(env->spr_cb); i++) {
+ ppc_spr_t *spr = &env->spr_cb[i];
+
+ if (!spr->name) {
+ continue;
+ }
+
+ spr_name = g_ascii_strdown(spr->name, -1);
+ g_string_append_printf(xml, "<reg name=\"%s\"", spr_name);
+ g_free(spr_name);
+
+ g_string_append_printf(xml, " bitsize=\"%d\"", TARGET_LONG_BITS);
+ g_string_append(xml, " group=\"spr\"/>");
+
+ /*
+ * GDB identifies registers based on the order they are
+ * presented in the XML. These ids will not match QEMU's
+ * representation (which follows the PowerISA).
+ *
+ * Store the position of the current register description so
+ * we can make the correspondence later.
+ */
+ spr->gdb_id = num_regs;
+ num_regs++;
+ }
+
+ g_string_append(xml, "</feature>");
+
+ pcc->gdb_num_sprs = num_regs;
+ pcc->gdb_spr_xml = g_string_free(xml, false);
+}
+
+const char *ppc_gdb_get_dynamic_xml(CPUState *cs, const char *xml_name)
+{
+ PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs);
+
+ if (strcmp(xml_name, "power-spr.xml") == 0) {
+ return pcc->gdb_spr_xml;
+ }
+ return NULL;
+}
+#endif
diff --git a/target/ppc/helper.h b/target/ppc/helper.h
index c7de04e068..18910d18a4 100644
--- a/target/ppc/helper.h
+++ b/target/ppc/helper.h
@@ -108,14 +108,6 @@ DEF_HELPER_FLAGS_1(ftsqrt, TCG_CALL_NO_RWG_SE, i32, i64)
#define dh_ctype_avr ppc_avr_t *
#define dh_is_signed_avr dh_is_signed_ptr
-DEF_HELPER_3(vaddubm, void, avr, avr, avr)
-DEF_HELPER_3(vadduhm, void, avr, avr, avr)
-DEF_HELPER_3(vadduwm, void, avr, avr, avr)
-DEF_HELPER_3(vaddudm, void, avr, avr, avr)
-DEF_HELPER_3(vsububm, void, avr, avr, avr)
-DEF_HELPER_3(vsubuhm, void, avr, avr, avr)
-DEF_HELPER_3(vsubuwm, void, avr, avr, avr)
-DEF_HELPER_3(vsubudm, void, avr, avr, avr)
DEF_HELPER_3(vavgub, void, avr, avr, avr)
DEF_HELPER_3(vavguh, void, avr, avr, avr)
DEF_HELPER_3(vavguw, void, avr, avr, avr)
@@ -125,22 +117,6 @@ DEF_HELPER_3(vabsduw, void, avr, avr, avr)
DEF_HELPER_3(vavgsb, void, avr, avr, avr)
DEF_HELPER_3(vavgsh, void, avr, avr, avr)
DEF_HELPER_3(vavgsw, void, avr, avr, avr)
-DEF_HELPER_3(vminsb, void, avr, avr, avr)
-DEF_HELPER_3(vminsh, void, avr, avr, avr)
-DEF_HELPER_3(vminsw, void, avr, avr, avr)
-DEF_HELPER_3(vminsd, void, avr, avr, avr)
-DEF_HELPER_3(vmaxsb, void, avr, avr, avr)
-DEF_HELPER_3(vmaxsh, void, avr, avr, avr)
-DEF_HELPER_3(vmaxsw, void, avr, avr, avr)
-DEF_HELPER_3(vmaxsd, void, avr, avr, avr)
-DEF_HELPER_3(vminub, void, avr, avr, avr)
-DEF_HELPER_3(vminuh, void, avr, avr, avr)
-DEF_HELPER_3(vminuw, void, avr, avr, avr)
-DEF_HELPER_3(vminud, void, avr, avr, avr)
-DEF_HELPER_3(vmaxub, void, avr, avr, avr)
-DEF_HELPER_3(vmaxuh, void, avr, avr, avr)
-DEF_HELPER_3(vmaxuw, void, avr, avr, avr)
-DEF_HELPER_3(vmaxud, void, avr, avr, avr)
DEF_HELPER_4(vcmpequb, void, env, avr, avr, avr)
DEF_HELPER_4(vcmpequh, void, env, avr, avr, avr)
DEF_HELPER_4(vcmpequw, void, env, avr, avr, avr)
@@ -227,18 +203,18 @@ DEF_HELPER_2(vprtybq, void, avr, avr)
DEF_HELPER_3(vsubcuw, void, avr, avr, avr)
DEF_HELPER_2(lvsl, void, avr, tl)
DEF_HELPER_2(lvsr, void, avr, tl)
-DEF_HELPER_4(vaddsbs, void, env, avr, avr, avr)
-DEF_HELPER_4(vaddshs, void, env, avr, avr, avr)
-DEF_HELPER_4(vaddsws, void, env, avr, avr, avr)
-DEF_HELPER_4(vsubsbs, void, env, avr, avr, avr)
-DEF_HELPER_4(vsubshs, void, env, avr, avr, avr)
-DEF_HELPER_4(vsubsws, void, env, avr, avr, avr)
-DEF_HELPER_4(vaddubs, void, env, avr, avr, avr)
-DEF_HELPER_4(vadduhs, void, env, avr, avr, avr)
-DEF_HELPER_4(vadduws, void, env, avr, avr, avr)
-DEF_HELPER_4(vsububs, void, env, avr, avr, avr)
-DEF_HELPER_4(vsubuhs, void, env, avr, avr, avr)
-DEF_HELPER_4(vsubuws, void, env, avr, avr, avr)
+DEF_HELPER_FLAGS_5(vaddsbs, TCG_CALL_NO_RWG, void, avr, avr, avr, avr, i32)
+DEF_HELPER_FLAGS_5(vaddshs, TCG_CALL_NO_RWG, void, avr, avr, avr, avr, i32)
+DEF_HELPER_FLAGS_5(vaddsws, TCG_CALL_NO_RWG, void, avr, avr, avr, avr, i32)
+DEF_HELPER_FLAGS_5(vsubsbs, TCG_CALL_NO_RWG, void, avr, avr, avr, avr, i32)
+DEF_HELPER_FLAGS_5(vsubshs, TCG_CALL_NO_RWG, void, avr, avr, avr, avr, i32)
+DEF_HELPER_FLAGS_5(vsubsws, TCG_CALL_NO_RWG, void, avr, avr, avr, avr, i32)
+DEF_HELPER_FLAGS_5(vaddubs, TCG_CALL_NO_RWG, void, avr, avr, avr, avr, i32)
+DEF_HELPER_FLAGS_5(vadduhs, TCG_CALL_NO_RWG, void, avr, avr, avr, avr, i32)
+DEF_HELPER_FLAGS_5(vadduws, TCG_CALL_NO_RWG, void, avr, avr, avr, avr, i32)
+DEF_HELPER_FLAGS_5(vsububs, TCG_CALL_NO_RWG, void, avr, avr, avr, avr, i32)
+DEF_HELPER_FLAGS_5(vsubuhs, TCG_CALL_NO_RWG, void, avr, avr, avr, avr, i32)
+DEF_HELPER_FLAGS_5(vsubuws, TCG_CALL_NO_RWG, void, avr, avr, avr, avr, i32)
DEF_HELPER_3(vadduqm, void, avr, avr, avr)
DEF_HELPER_4(vaddecuq, void, avr, avr, avr, avr)
DEF_HELPER_4(vaddeuqm, void, avr, avr, avr, avr)
@@ -254,12 +230,6 @@ DEF_HELPER_3(vrld, void, avr, avr, avr)
DEF_HELPER_3(vsl, void, avr, avr, avr)
DEF_HELPER_3(vsr, void, avr, avr, avr)
DEF_HELPER_4(vsldoi, void, avr, avr, avr, i32)
-DEF_HELPER_2(vspltisb, void, avr, i32)
-DEF_HELPER_2(vspltish, void, avr, i32)
-DEF_HELPER_2(vspltisw, void, avr, i32)
-DEF_HELPER_3(vspltb, void, avr, avr, i32)
-DEF_HELPER_3(vsplth, void, avr, avr, i32)
-DEF_HELPER_3(vspltw, void, avr, avr, i32)
DEF_HELPER_3(vextractub, void, avr, avr, i32)
DEF_HELPER_3(vextractuh, void, avr, avr, i32)
DEF_HELPER_3(vextractuw, void, avr, avr, i32)
@@ -308,7 +278,8 @@ DEF_HELPER_5(vmsumuhs, void, env, avr, avr, avr, avr)
DEF_HELPER_5(vmsumshm, void, env, avr, avr, avr, avr)
DEF_HELPER_5(vmsumshs, void, env, avr, avr, avr, avr)
DEF_HELPER_4(vmladduhm, void, avr, avr, avr, avr)
-DEF_HELPER_2(mtvscr, void, env, avr)
+DEF_HELPER_FLAGS_2(mtvscr, TCG_CALL_NO_RWG, void, env, i32)
+DEF_HELPER_FLAGS_1(mfvscr, TCG_CALL_NO_RWG, i32, env)
DEF_HELPER_3(lvebx, void, env, avr, tl)
DEF_HELPER_3(lvehx, void, env, avr, tl)
DEF_HELPER_3(lvewx, void, env, avr, tl)
diff --git a/target/ppc/int_helper.c b/target/ppc/int_helper.c
index 8efc283388..162add561e 100644
--- a/target/ppc/int_helper.c
+++ b/target/ppc/int_helper.c
@@ -457,10 +457,25 @@ void helper_lvsr(ppc_avr_t *r, target_ulong sh)
}
}
-void helper_mtvscr(CPUPPCState *env, ppc_avr_t *r)
+void helper_mtvscr(CPUPPCState *env, uint32_t vscr)
{
- env->vscr = r->VsrW(3);
- set_flush_to_zero(vscr_nj, &env->vec_status);
+ env->vscr = vscr & ~(1u << VSCR_SAT);
+ /* Which bit we set is completely arbitrary, but clear the rest. */
+ env->vscr_sat.u64[0] = vscr & (1u << VSCR_SAT);
+ env->vscr_sat.u64[1] = 0;
+ set_flush_to_zero((vscr >> VSCR_NJ) & 1, &env->vec_status);
+}
+
+uint32_t helper_mfvscr(CPUPPCState *env)
+{
+ uint32_t sat = (env->vscr_sat.u64[0] | env->vscr_sat.u64[1]) != 0;
+ return env->vscr | (sat << VSCR_SAT);
+}
+
+static inline void set_vscr_sat(CPUPPCState *env)
+{
+ /* The choice of non-zero value is arbitrary. */
+ env->vscr_sat.u32[0] = 1;
}
void helper_vaddcuw(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
@@ -515,13 +530,6 @@ void helper_vprtybq(ppc_avr_t *r, ppc_avr_t *b)
r->element[i] = a->element[i] op b->element[i]; \
} \
}
-#define VARITH(suffix, element) \
- VARITH_DO(add##suffix, +, element) \
- VARITH_DO(sub##suffix, -, element)
-VARITH(ubm, u8)
-VARITH(uhm, u16)
-VARITH(uwm, u32)
-VARITH(udm, u64)
VARITH_DO(muluwm, *, u32)
#undef VARITH_DO
#undef VARITH
@@ -563,27 +571,17 @@ VARITHFPFMA(nmsubfp, float_muladd_negate_result | float_muladd_negate_c);
}
#define VARITHSAT_DO(name, op, optype, cvt, element) \
- void helper_v##name(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, \
- ppc_avr_t *b) \
+ void helper_v##name(ppc_avr_t *r, ppc_avr_t *vscr_sat, \
+ ppc_avr_t *a, ppc_avr_t *b, uint32_t desc) \
{ \
int sat = 0; \
int i; \
\
for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
- switch (sizeof(r->element[0])) { \
- case 1: \
- VARITHSAT_CASE(optype, op, cvt, element); \
- break; \
- case 2: \
- VARITHSAT_CASE(optype, op, cvt, element); \
- break; \
- case 4: \
- VARITHSAT_CASE(optype, op, cvt, element); \
- break; \
- } \
+ VARITHSAT_CASE(optype, op, cvt, element); \
} \
if (sat) { \
- env->vscr |= (1 << VSCR_SAT); \
+ vscr_sat->u32[0] = 1; \
} \
}
#define VARITHSAT_SIGNED(suffix, element, optype, cvt) \
@@ -855,7 +853,7 @@ void helper_vcmpbfp_dot(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
} \
} \
if (sat) { \
- env->vscr |= (1 << VSCR_SAT); \
+ set_vscr_sat(env); \
} \
}
VCT(uxs, cvtsduw, u32)
@@ -902,7 +900,7 @@ void helper_vmhaddshs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
}
if (sat) {
- env->vscr |= (1 << VSCR_SAT);
+ set_vscr_sat(env);
}
}
@@ -919,37 +917,10 @@ void helper_vmhraddshs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
}
if (sat) {
- env->vscr |= (1 << VSCR_SAT);
+ set_vscr_sat(env);
}
}
-#define VMINMAX_DO(name, compare, element) \
- void helper_v##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
- { \
- int i; \
- \
- for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
- if (a->element[i] compare b->element[i]) { \
- r->element[i] = b->element[i]; \
- } else { \
- r->element[i] = a->element[i]; \
- } \
- } \
- }
-#define VMINMAX(suffix, element) \
- VMINMAX_DO(min##suffix, >, element) \
- VMINMAX_DO(max##suffix, <, element)
-VMINMAX(sb, s8)
-VMINMAX(sh, s16)
-VMINMAX(sw, s32)
-VMINMAX(sd, s64)
-VMINMAX(ub, u8)
-VMINMAX(uh, u16)
-VMINMAX(uw, u32)
-VMINMAX(ud, u64)
-#undef VMINMAX_DO
-#undef VMINMAX
-
void helper_vmladduhm(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
{
int i;
@@ -1031,7 +1002,7 @@ void helper_vmsumshs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
}
if (sat) {
- env->vscr |= (1 << VSCR_SAT);
+ set_vscr_sat(env);
}
}
@@ -1084,7 +1055,7 @@ void helper_vmsumuhs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
}
if (sat) {
- env->vscr |= (1 << VSCR_SAT);
+ set_vscr_sat(env);
}
}
@@ -1601,7 +1572,7 @@ void helper_vpkpx(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
} \
*r = result; \
if (dosat && sat) { \
- env->vscr |= (1 << VSCR_SAT); \
+ set_vscr_sat(env); \
} \
}
#define I(x, y) (x)
@@ -1876,25 +1847,6 @@ void helper_vslo(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
#endif
}
-/* Experimental testing shows that hardware masks the immediate. */
-#define _SPLAT_MASKED(element) (splat & (ARRAY_SIZE(r->element) - 1))
-#define SPLAT_ELEMENT(element) _SPLAT_MASKED(element)
-#define VSPLT(suffix, element, access) \
- void helper_vsplt##suffix(ppc_avr_t *r, ppc_avr_t *b, uint32_t splat) \
- { \
- uint32_t s = b->access(SPLAT_ELEMENT(element)); \
- int i; \
- \
- for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
- r->access(i) = s; \
- } \
- }
-VSPLT(b, u8, VsrB)
-VSPLT(h, u16, VsrH)
-VSPLT(w, u32, VsrW)
-#undef VSPLT
-#undef SPLAT_ELEMENT
-#undef _SPLAT_MASKED
#if defined(HOST_WORDS_BIGENDIAN)
#define VINSERT(suffix, element) \
void helper_vinsert##suffix(ppc_avr_t *r, ppc_avr_t *b, uint32_t index) \
@@ -2005,21 +1957,6 @@ VNEG(vnegw, s32)
VNEG(vnegd, s64)
#undef VNEG
-#define VSPLTI(suffix, element, splat_type) \
- void helper_vspltis##suffix(ppc_avr_t *r, uint32_t splat) \
- { \
- splat_type x = (int8_t)(splat << 3) >> 3; \
- int i; \
- \
- for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
- r->element[i] = x; \
- } \
- }
-VSPLTI(b, s8, int8_t)
-VSPLTI(h, s16, int16_t)
-VSPLTI(w, s32, int32_t)
-#undef VSPLTI
-
#define VSR(suffix, element, mask) \
void helper_vsr##suffix(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
{ \
@@ -2079,7 +2016,7 @@ void helper_vsumsws(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
*r = result;
if (sat) {
- env->vscr |= (1 << VSCR_SAT);
+ set_vscr_sat(env);
}
}
@@ -2102,7 +2039,7 @@ void helper_vsum2sws(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
*r = result;
if (sat) {
- env->vscr |= (1 << VSCR_SAT);
+ set_vscr_sat(env);
}
}
@@ -2121,7 +2058,7 @@ void helper_vsum4sbs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
}
if (sat) {
- env->vscr |= (1 << VSCR_SAT);
+ set_vscr_sat(env);
}
}
@@ -2138,7 +2075,7 @@ void helper_vsum4shs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
}
if (sat) {
- env->vscr |= (1 << VSCR_SAT);
+ set_vscr_sat(env);
}
}
@@ -2157,7 +2094,7 @@ void helper_vsum4ubs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
}
if (sat) {
- env->vscr |= (1 << VSCR_SAT);
+ set_vscr_sat(env);
}
}
diff --git a/target/ppc/machine.c b/target/ppc/machine.c
index eff30053b0..756b6d2971 100644
--- a/target/ppc/machine.c
+++ b/target/ppc/machine.c
@@ -10,6 +10,7 @@
#include "migration/cpu.h"
#include "qapi/error.h"
#include "kvm_ppc.h"
+#include "exec/helper-proto.h"
static int cpu_load_old(QEMUFile *f, void *opaque, int version_id)
{
@@ -17,7 +18,7 @@ static int cpu_load_old(QEMUFile *f, void *opaque, int version_id)
CPUPPCState *env = &cpu->env;
unsigned int i, j;
target_ulong sdr1;
- uint32_t fpscr;
+ uint32_t fpscr, vscr;
#if defined(TARGET_PPC64)
int32_t slb_nr;
#endif
@@ -84,7 +85,8 @@ static int cpu_load_old(QEMUFile *f, void *opaque, int version_id)
if (!cpu->vhyp) {
ppc_store_sdr1(env, sdr1);
}
- qemu_get_be32s(f, &env->vscr);
+ qemu_get_be32s(f, &vscr);
+ helper_mtvscr(env, vscr);
qemu_get_be64s(f, &env->spe_acc);
qemu_get_be32s(f, &env->spe_fscr);
qemu_get_betls(f, &env->msr_mask);
@@ -429,6 +431,28 @@ static bool altivec_needed(void *opaque)
return (cpu->env.insns_flags & PPC_ALTIVEC);
}
+static int get_vscr(QEMUFile *f, void *opaque, size_t size,
+ const VMStateField *field)
+{
+ PowerPCCPU *cpu = opaque;
+ helper_mtvscr(&cpu->env, qemu_get_be32(f));
+ return 0;
+}
+
+static int put_vscr(QEMUFile *f, void *opaque, size_t size,
+ const VMStateField *field, QJSON *vmdesc)
+{
+ PowerPCCPU *cpu = opaque;
+ qemu_put_be32(f, helper_mfvscr(&cpu->env));
+ return 0;
+}
+
+static const VMStateInfo vmstate_vscr = {
+ .name = "cpu/altivec/vscr",
+ .get = get_vscr,
+ .put = put_vscr,
+};
+
static const VMStateDescription vmstate_altivec = {
.name = "cpu/altivec",
.version_id = 1,
@@ -436,7 +460,21 @@ static const VMStateDescription vmstate_altivec = {
.needed = altivec_needed,
.fields = (VMStateField[]) {
VMSTATE_AVR_ARRAY(env.vsr, PowerPCCPU, 32),
- VMSTATE_UINT32(env.vscr, PowerPCCPU),
+ /*
+ * Save the architecture value of the vscr, not the internally
+ * expanded version. Since this architecture value does not
+ * exist in memory to be stored, this requires a but of hoop
+ * jumping. We want OFFSET=0 so that we effectively pass CPU
+ * to the helper functions.
+ */
+ {
+ .name = "vscr",
+ .version_id = 0,
+ .size = sizeof(uint32_t),
+ .info = &vmstate_vscr,
+ .flags = VMS_SINGLE,
+ .offset = 0
+ },
VMSTATE_END_OF_LIST()
},
};
diff --git a/target/ppc/mmu_helper.c b/target/ppc/mmu_helper.c
index cefed34da4..bcf19da61d 100644
--- a/target/ppc/mmu_helper.c
+++ b/target/ppc/mmu_helper.c
@@ -1415,10 +1415,6 @@ static int get_physical_address_wtlb(
bool real_mode = (access_type == ACCESS_CODE && msr_ir == 0)
|| (access_type != ACCESS_CODE && msr_dr == 0);
-#if 0
- qemu_log("%s\n", __func__);
-#endif
-
switch (env->mmu_model) {
case POWERPC_MMU_SOFT_6xx:
case POWERPC_MMU_SOFT_74xx:
@@ -1468,10 +1464,6 @@ static int get_physical_address_wtlb(
cpu_abort(CPU(cpu), "Unknown or invalid MMU model\n");
return -1;
}
-#if 0
- qemu_log("%s address " TARGET_FMT_lx " => %d " TARGET_FMT_plx "\n",
- __func__, eaddr, ret, ctx->raddr);
-#endif
return ret;
}
@@ -1805,10 +1797,6 @@ static int cpu_ppc_handle_mmu_fault(CPUPPCState *env, target_ulong address,
break;
}
}
-#if 0
- printf("%s: set exception to %d %02x\n", __func__,
- cs->exception, env->error_code);
-#endif
ret = 1;
}
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index e169c43643..f4d70e725a 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -24,6 +24,7 @@
#include "disas/disas.h"
#include "exec/exec-all.h"
#include "tcg-op.h"
+#include "tcg-op-gvec.h"
#include "qemu/host-utils.h"
#include "exec/cpu_ldst.h"
@@ -287,26 +288,22 @@ static void gen_exception_nip(DisasContext *ctx, uint32_t excp,
ctx->exception = (excp);
}
-/* Translates the EXCP_TRACE/BRANCH exceptions used on most PowerPCs to
- * EXCP_DEBUG, if we are running on cores using the debug enable bit (e.g.
- * BookE).
+/*
+ * Tells the caller what is the appropriate exception to generate and prepares
+ * SPR registers for this exception.
+ *
+ * The exception can be either POWERPC_EXCP_TRACE (on most PowerPCs) or
+ * POWERPC_EXCP_DEBUG (on BookE).
*/
-static uint32_t gen_prep_dbgex(DisasContext *ctx, uint32_t excp)
+static uint32_t gen_prep_dbgex(DisasContext *ctx)
{
- if ((ctx->singlestep_enabled & CPU_SINGLE_STEP)
- && (excp == POWERPC_EXCP_BRANCH)) {
- /* Trace excpt. has priority */
- excp = POWERPC_EXCP_TRACE;
- }
if (ctx->flags & POWERPC_FLAG_DE) {
target_ulong dbsr = 0;
- switch (excp) {
- case POWERPC_EXCP_TRACE:
+ if (ctx->singlestep_enabled & CPU_SINGLE_STEP) {
dbsr = DBCR0_ICMP;
- break;
- case POWERPC_EXCP_BRANCH:
+ } else {
+ /* Must have been branch */
dbsr = DBCR0_BRT;
- break;
}
TCGv t0 = tcg_temp_new();
gen_load_spr(t0, SPR_BOOKE_DBSR);
@@ -315,7 +312,7 @@ static uint32_t gen_prep_dbgex(DisasContext *ctx, uint32_t excp)
tcg_temp_free(t0);
return POWERPC_EXCP_DEBUG;
} else {
- return excp;
+ return POWERPC_EXCP_TRACE;
}
}
@@ -3652,10 +3649,8 @@ static void gen_lookup_and_goto_ptr(DisasContext *ctx)
if (sse & GDBSTUB_SINGLE_STEP) {
gen_debug_exception(ctx);
} else if (sse & (CPU_SINGLE_STEP | CPU_BRANCH_STEP)) {
- uint32_t excp = gen_prep_dbgex(ctx, POWERPC_EXCP_BRANCH);
- if (excp != POWERPC_EXCP_NONE) {
- gen_exception(ctx, excp);
- }
+ uint32_t excp = gen_prep_dbgex(ctx);
+ gen_exception(ctx, excp);
}
tcg_gen_exit_tb(NULL, 0);
} else {
@@ -6476,7 +6471,12 @@ static void gen_mbar(DisasContext *ctx)
/* msync replaces sync on 440 */
static void gen_msync_4xx(DisasContext *ctx)
{
- /* interpreted as no-op */
+ /* Only e500 seems to treat reserved bits as invalid */
+ if ((ctx->insns_flags2 & PPC2_BOOKE206) &&
+ (ctx->opcode & 0x03FFF801)) {
+ gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
+ }
+ /* otherwise interpreted as no-op */
}
/* icbt */
@@ -7054,11 +7054,11 @@ GEN_HANDLER(wrteei, 0x1F, 0x03, 0x05, 0x000E7C01, PPC_WRTEE),
GEN_HANDLER(dlmzb, 0x1F, 0x0E, 0x02, 0x00000000, PPC_440_SPEC),
GEN_HANDLER_E(mbar, 0x1F, 0x16, 0x1a, 0x001FF801,
PPC_BOOKE, PPC2_BOOKE206),
-GEN_HANDLER(msync_4xx, 0x1F, 0x16, 0x12, 0x03FFF801, PPC_BOOKE),
+GEN_HANDLER(msync_4xx, 0x1F, 0x16, 0x12, 0x039FF801, PPC_BOOKE),
GEN_HANDLER2_E(icbt_440, "icbt", 0x1F, 0x16, 0x00, 0x03E00001,
PPC_BOOKE, PPC2_BOOKE206),
GEN_HANDLER2(icbt_440, "icbt", 0x1F, 0x06, 0x08, 0x03E00001,
- PPC_440_SPEC),
+ PPC_440_SPEC),
GEN_HANDLER(lvsl, 0x1f, 0x06, 0x00, 0x00000001, PPC_ALTIVEC),
GEN_HANDLER(lvsr, 0x1f, 0x06, 0x01, 0x00000001, PPC_ALTIVEC),
GEN_HANDLER(mfvscr, 0x04, 0x2, 0x18, 0x001ff800, PPC_ALTIVEC),
@@ -7785,9 +7785,8 @@ static void ppc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
ctx->exception != POWERPC_SYSCALL &&
ctx->exception != POWERPC_EXCP_TRAP &&
ctx->exception != POWERPC_EXCP_BRANCH)) {
- uint32_t excp = gen_prep_dbgex(ctx, POWERPC_EXCP_TRACE);
- if (excp != POWERPC_EXCP_NONE)
- gen_exception_nip(ctx, excp, ctx->base.pc_next);
+ uint32_t excp = gen_prep_dbgex(ctx);
+ gen_exception_nip(ctx, excp, ctx->base.pc_next);
}
if (tcg_check_temp_count()) {
diff --git a/target/ppc/translate/vmx-impl.inc.c b/target/ppc/translate/vmx-impl.inc.c
index f99d0284c2..f1b15ae2cb 100644
--- a/target/ppc/translate/vmx-impl.inc.c
+++ b/target/ppc/translate/vmx-impl.inc.c
@@ -187,7 +187,7 @@ static void gen_mfvscr(DisasContext *ctx)
tcg_gen_movi_i64(avr, 0);
set_avr64(rD(ctx->opcode), avr, true);
t = tcg_temp_new_i32();
- tcg_gen_ld_i32(t, cpu_env, offsetof(CPUPPCState, vscr));
+ gen_helper_mfvscr(t, cpu_env);
tcg_gen_extu_i32_i64(avr, t);
set_avr64(rD(ctx->opcode), avr, false);
tcg_temp_free_i32(t);
@@ -196,14 +196,23 @@ static void gen_mfvscr(DisasContext *ctx)
static void gen_mtvscr(DisasContext *ctx)
{
- TCGv_ptr p;
+ TCGv_i32 val;
+ int bofs;
+
if (unlikely(!ctx->altivec_enabled)) {
gen_exception(ctx, POWERPC_EXCP_VPU);
return;
}
- p = gen_avr_ptr(rB(ctx->opcode));
- gen_helper_mtvscr(cpu_env, p);
- tcg_temp_free_ptr(p);
+
+ val = tcg_temp_new_i32();
+ bofs = avr64_offset(rB(ctx->opcode), true);
+#ifdef HOST_WORDS_BIGENDIAN
+ bofs += 3 * 4;
+#endif
+
+ tcg_gen_ld_i32(val, cpu_env, bofs);
+ gen_helper_mtvscr(cpu_env, val);
+ tcg_temp_free_i32(val);
}
#define GEN_VX_VMUL10(name, add_cin, ret_carry) \
@@ -266,45 +275,30 @@ GEN_VX_VMUL10(vmul10euq, 1, 0);
GEN_VX_VMUL10(vmul10cuq, 0, 1);
GEN_VX_VMUL10(vmul10ecuq, 1, 1);
-/* Logical operations */
-#define GEN_VX_LOGICAL(name, tcg_op, opc2, opc3) \
-static void glue(gen_, name)(DisasContext *ctx) \
+#define GEN_VXFORM_V(name, vece, tcg_op, opc2, opc3) \
+static void glue(gen_, name)(DisasContext *ctx) \
{ \
- TCGv_i64 t0; \
- TCGv_i64 t1; \
- TCGv_i64 avr; \
- \
if (unlikely(!ctx->altivec_enabled)) { \
gen_exception(ctx, POWERPC_EXCP_VPU); \
return; \
} \
- t0 = tcg_temp_new_i64(); \
- t1 = tcg_temp_new_i64(); \
- avr = tcg_temp_new_i64(); \
- \
- get_avr64(t0, rA(ctx->opcode), true); \
- get_avr64(t1, rB(ctx->opcode), true); \
- tcg_op(avr, t0, t1); \
- set_avr64(rD(ctx->opcode), avr, true); \
\
- get_avr64(t0, rA(ctx->opcode), false); \
- get_avr64(t1, rB(ctx->opcode), false); \
- tcg_op(avr, t0, t1); \
- set_avr64(rD(ctx->opcode), avr, false); \
- \
- tcg_temp_free_i64(t0); \
- tcg_temp_free_i64(t1); \
- tcg_temp_free_i64(avr); \
+ tcg_op(vece, \
+ avr64_offset(rD(ctx->opcode), true), \
+ avr64_offset(rA(ctx->opcode), true), \
+ avr64_offset(rB(ctx->opcode), true), \
+ 16, 16); \
}
-GEN_VX_LOGICAL(vand, tcg_gen_and_i64, 2, 16);
-GEN_VX_LOGICAL(vandc, tcg_gen_andc_i64, 2, 17);
-GEN_VX_LOGICAL(vor, tcg_gen_or_i64, 2, 18);
-GEN_VX_LOGICAL(vxor, tcg_gen_xor_i64, 2, 19);
-GEN_VX_LOGICAL(vnor, tcg_gen_nor_i64, 2, 20);
-GEN_VX_LOGICAL(veqv, tcg_gen_eqv_i64, 2, 26);
-GEN_VX_LOGICAL(vnand, tcg_gen_nand_i64, 2, 22);
-GEN_VX_LOGICAL(vorc, tcg_gen_orc_i64, 2, 21);
+/* Logical operations */
+GEN_VXFORM_V(vand, MO_64, tcg_gen_gvec_and, 2, 16);
+GEN_VXFORM_V(vandc, MO_64, tcg_gen_gvec_andc, 2, 17);
+GEN_VXFORM_V(vor, MO_64, tcg_gen_gvec_or, 2, 18);
+GEN_VXFORM_V(vxor, MO_64, tcg_gen_gvec_xor, 2, 19);
+GEN_VXFORM_V(vnor, MO_64, tcg_gen_gvec_nor, 2, 20);
+GEN_VXFORM_V(veqv, MO_64, tcg_gen_gvec_eqv, 2, 26);
+GEN_VXFORM_V(vnand, MO_64, tcg_gen_gvec_nand, 2, 22);
+GEN_VXFORM_V(vorc, MO_64, tcg_gen_gvec_orc, 2, 21);
#define GEN_VXFORM(name, opc2, opc3) \
static void glue(gen_, name)(DisasContext *ctx) \
@@ -410,34 +404,34 @@ static void glue(gen_, name)(DisasContext *ctx) \
tcg_temp_free_ptr(rb); \
}
-GEN_VXFORM(vaddubm, 0, 0);
+GEN_VXFORM_V(vaddubm, MO_8, tcg_gen_gvec_add, 0, 0);
GEN_VXFORM_DUAL_EXT(vaddubm, PPC_ALTIVEC, PPC_NONE, 0, \
vmul10cuq, PPC_NONE, PPC2_ISA300, 0x0000F800)
-GEN_VXFORM(vadduhm, 0, 1);
+GEN_VXFORM_V(vadduhm, MO_16, tcg_gen_gvec_add, 0, 1);
GEN_VXFORM_DUAL(vadduhm, PPC_ALTIVEC, PPC_NONE, \
vmul10ecuq, PPC_NONE, PPC2_ISA300)
-GEN_VXFORM(vadduwm, 0, 2);
-GEN_VXFORM(vaddudm, 0, 3);
-GEN_VXFORM(vsububm, 0, 16);
-GEN_VXFORM(vsubuhm, 0, 17);
-GEN_VXFORM(vsubuwm, 0, 18);
-GEN_VXFORM(vsubudm, 0, 19);
-GEN_VXFORM(vmaxub, 1, 0);
-GEN_VXFORM(vmaxuh, 1, 1);
-GEN_VXFORM(vmaxuw, 1, 2);
-GEN_VXFORM(vmaxud, 1, 3);
-GEN_VXFORM(vmaxsb, 1, 4);
-GEN_VXFORM(vmaxsh, 1, 5);
-GEN_VXFORM(vmaxsw, 1, 6);
-GEN_VXFORM(vmaxsd, 1, 7);
-GEN_VXFORM(vminub, 1, 8);
-GEN_VXFORM(vminuh, 1, 9);
-GEN_VXFORM(vminuw, 1, 10);
-GEN_VXFORM(vminud, 1, 11);
-GEN_VXFORM(vminsb, 1, 12);
-GEN_VXFORM(vminsh, 1, 13);
-GEN_VXFORM(vminsw, 1, 14);
-GEN_VXFORM(vminsd, 1, 15);
+GEN_VXFORM_V(vadduwm, MO_32, tcg_gen_gvec_add, 0, 2);
+GEN_VXFORM_V(vaddudm, MO_64, tcg_gen_gvec_add, 0, 3);
+GEN_VXFORM_V(vsububm, MO_8, tcg_gen_gvec_sub, 0, 16);
+GEN_VXFORM_V(vsubuhm, MO_16, tcg_gen_gvec_sub, 0, 17);
+GEN_VXFORM_V(vsubuwm, MO_32, tcg_gen_gvec_sub, 0, 18);
+GEN_VXFORM_V(vsubudm, MO_64, tcg_gen_gvec_sub, 0, 19);
+GEN_VXFORM_V(vmaxub, MO_8, tcg_gen_gvec_umax, 1, 0);
+GEN_VXFORM_V(vmaxuh, MO_16, tcg_gen_gvec_umax, 1, 1);
+GEN_VXFORM_V(vmaxuw, MO_32, tcg_gen_gvec_umax, 1, 2);
+GEN_VXFORM_V(vmaxud, MO_64, tcg_gen_gvec_umax, 1, 3);
+GEN_VXFORM_V(vmaxsb, MO_8, tcg_gen_gvec_smax, 1, 4);
+GEN_VXFORM_V(vmaxsh, MO_16, tcg_gen_gvec_smax, 1, 5);
+GEN_VXFORM_V(vmaxsw, MO_32, tcg_gen_gvec_smax, 1, 6);
+GEN_VXFORM_V(vmaxsd, MO_64, tcg_gen_gvec_smax, 1, 7);
+GEN_VXFORM_V(vminub, MO_8, tcg_gen_gvec_umin, 1, 8);
+GEN_VXFORM_V(vminuh, MO_16, tcg_gen_gvec_umin, 1, 9);
+GEN_VXFORM_V(vminuw, MO_32, tcg_gen_gvec_umin, 1, 10);
+GEN_VXFORM_V(vminud, MO_64, tcg_gen_gvec_umin, 1, 11);
+GEN_VXFORM_V(vminsb, MO_8, tcg_gen_gvec_smin, 1, 12);
+GEN_VXFORM_V(vminsh, MO_16, tcg_gen_gvec_smin, 1, 13);
+GEN_VXFORM_V(vminsw, MO_32, tcg_gen_gvec_smin, 1, 14);
+GEN_VXFORM_V(vminsd, MO_64, tcg_gen_gvec_smin, 1, 15);
GEN_VXFORM(vavgub, 1, 16);
GEN_VXFORM(vabsdub, 1, 16);
GEN_VXFORM_DUAL(vavgub, PPC_ALTIVEC, PPC_NONE, \
@@ -558,22 +552,55 @@ GEN_VXFORM(vslo, 6, 16);
GEN_VXFORM(vsro, 6, 17);
GEN_VXFORM(vaddcuw, 0, 6);
GEN_VXFORM(vsubcuw, 0, 22);
-GEN_VXFORM_ENV(vaddubs, 0, 8);
+
+#define GEN_VXFORM_SAT(NAME, VECE, NORM, SAT, OPC2, OPC3) \
+static void glue(glue(gen_, NAME), _vec)(unsigned vece, TCGv_vec t, \
+ TCGv_vec sat, TCGv_vec a, \
+ TCGv_vec b) \
+{ \
+ TCGv_vec x = tcg_temp_new_vec_matching(t); \
+ glue(glue(tcg_gen_, NORM), _vec)(VECE, x, a, b); \
+ glue(glue(tcg_gen_, SAT), _vec)(VECE, t, a, b); \
+ tcg_gen_cmp_vec(TCG_COND_NE, VECE, x, x, t); \
+ tcg_gen_or_vec(VECE, sat, sat, x); \
+ tcg_temp_free_vec(x); \
+} \
+static void glue(gen_, NAME)(DisasContext *ctx) \
+{ \
+ static const GVecGen4 g = { \
+ .fniv = glue(glue(gen_, NAME), _vec), \
+ .fno = glue(gen_helper_, NAME), \
+ .opc = glue(glue(INDEX_op_, SAT), _vec), \
+ .write_aofs = true, \
+ .vece = VECE, \
+ }; \
+ if (unlikely(!ctx->altivec_enabled)) { \
+ gen_exception(ctx, POWERPC_EXCP_VPU); \
+ return; \
+ } \
+ tcg_gen_gvec_4(avr64_offset(rD(ctx->opcode), true), \
+ offsetof(CPUPPCState, vscr_sat), \
+ avr64_offset(rA(ctx->opcode), true), \
+ avr64_offset(rB(ctx->opcode), true), \
+ 16, 16, &g); \
+}
+
+GEN_VXFORM_SAT(vaddubs, MO_8, add, usadd, 0, 8);
GEN_VXFORM_DUAL_EXT(vaddubs, PPC_ALTIVEC, PPC_NONE, 0, \
vmul10uq, PPC_NONE, PPC2_ISA300, 0x0000F800)
-GEN_VXFORM_ENV(vadduhs, 0, 9);
+GEN_VXFORM_SAT(vadduhs, MO_16, add, usadd, 0, 9);
GEN_VXFORM_DUAL(vadduhs, PPC_ALTIVEC, PPC_NONE, \
vmul10euq, PPC_NONE, PPC2_ISA300)
-GEN_VXFORM_ENV(vadduws, 0, 10);
-GEN_VXFORM_ENV(vaddsbs, 0, 12);
-GEN_VXFORM_ENV(vaddshs, 0, 13);
-GEN_VXFORM_ENV(vaddsws, 0, 14);
-GEN_VXFORM_ENV(vsububs, 0, 24);
-GEN_VXFORM_ENV(vsubuhs, 0, 25);
-GEN_VXFORM_ENV(vsubuws, 0, 26);
-GEN_VXFORM_ENV(vsubsbs, 0, 28);
-GEN_VXFORM_ENV(vsubshs, 0, 29);
-GEN_VXFORM_ENV(vsubsws, 0, 30);
+GEN_VXFORM_SAT(vadduws, MO_32, add, usadd, 0, 10);
+GEN_VXFORM_SAT(vaddsbs, MO_8, add, ssadd, 0, 12);
+GEN_VXFORM_SAT(vaddshs, MO_16, add, ssadd, 0, 13);
+GEN_VXFORM_SAT(vaddsws, MO_32, add, ssadd, 0, 14);
+GEN_VXFORM_SAT(vsububs, MO_8, sub, ussub, 0, 24);
+GEN_VXFORM_SAT(vsubuhs, MO_16, sub, ussub, 0, 25);
+GEN_VXFORM_SAT(vsubuws, MO_32, sub, ussub, 0, 26);
+GEN_VXFORM_SAT(vsubsbs, MO_8, sub, sssub, 0, 28);
+GEN_VXFORM_SAT(vsubshs, MO_16, sub, sssub, 0, 29);
+GEN_VXFORM_SAT(vsubsws, MO_32, sub, sssub, 0, 30);
GEN_VXFORM(vadduqm, 0, 4);
GEN_VXFORM(vaddcuq, 0, 5);
GEN_VXFORM3(vaddeuqm, 30, 0);
@@ -719,25 +746,21 @@ GEN_VXRFORM_DUAL(vcmpbfp, PPC_ALTIVEC, PPC_NONE, \
GEN_VXRFORM_DUAL(vcmpgtfp, PPC_ALTIVEC, PPC_NONE, \
vcmpgtud, PPC_NONE, PPC2_ALTIVEC_207)
-#define GEN_VXFORM_SIMM(name, opc2, opc3) \
+#define GEN_VXFORM_DUPI(name, tcg_op, opc2, opc3) \
static void glue(gen_, name)(DisasContext *ctx) \
{ \
- TCGv_ptr rd; \
- TCGv_i32 simm; \
+ int simm; \
if (unlikely(!ctx->altivec_enabled)) { \
gen_exception(ctx, POWERPC_EXCP_VPU); \
return; \
} \
- simm = tcg_const_i32(SIMM5(ctx->opcode)); \
- rd = gen_avr_ptr(rD(ctx->opcode)); \
- gen_helper_##name (rd, simm); \
- tcg_temp_free_i32(simm); \
- tcg_temp_free_ptr(rd); \
+ simm = SIMM5(ctx->opcode); \
+ tcg_op(avr64_offset(rD(ctx->opcode), true), 16, 16, simm); \
}
-GEN_VXFORM_SIMM(vspltisb, 6, 12);
-GEN_VXFORM_SIMM(vspltish, 6, 13);
-GEN_VXFORM_SIMM(vspltisw, 6, 14);
+GEN_VXFORM_DUPI(vspltisb, tcg_gen_gvec_dup8i, 6, 12);
+GEN_VXFORM_DUPI(vspltish, tcg_gen_gvec_dup16i, 6, 13);
+GEN_VXFORM_DUPI(vspltisw, tcg_gen_gvec_dup32i, 6, 14);
#define GEN_VXFORM_NOA(name, opc2, opc3) \
static void glue(gen_, name)(DisasContext *ctx) \
@@ -817,40 +840,32 @@ GEN_VXFORM_NOA(vprtybw, 1, 24);
GEN_VXFORM_NOA(vprtybd, 1, 24);
GEN_VXFORM_NOA(vprtybq, 1, 24);
-#define GEN_VXFORM_SIMM(name, opc2, opc3) \
-static void glue(gen_, name)(DisasContext *ctx) \
- { \
- TCGv_ptr rd; \
- TCGv_i32 simm; \
- if (unlikely(!ctx->altivec_enabled)) { \
- gen_exception(ctx, POWERPC_EXCP_VPU); \
- return; \
- } \
- simm = tcg_const_i32(SIMM5(ctx->opcode)); \
- rd = gen_avr_ptr(rD(ctx->opcode)); \
- gen_helper_##name (rd, simm); \
- tcg_temp_free_i32(simm); \
- tcg_temp_free_ptr(rd); \
- }
+static void gen_vsplt(DisasContext *ctx, int vece)
+{
+ int uimm, dofs, bofs;
-#define GEN_VXFORM_UIMM(name, opc2, opc3) \
-static void glue(gen_, name)(DisasContext *ctx) \
- { \
- TCGv_ptr rb, rd; \
- TCGv_i32 uimm; \
- if (unlikely(!ctx->altivec_enabled)) { \
- gen_exception(ctx, POWERPC_EXCP_VPU); \
- return; \
- } \
- uimm = tcg_const_i32(UIMM5(ctx->opcode)); \
- rb = gen_avr_ptr(rB(ctx->opcode)); \
- rd = gen_avr_ptr(rD(ctx->opcode)); \
- gen_helper_##name (rd, rb, uimm); \
- tcg_temp_free_i32(uimm); \
- tcg_temp_free_ptr(rb); \
- tcg_temp_free_ptr(rd); \
+ if (unlikely(!ctx->altivec_enabled)) {
+ gen_exception(ctx, POWERPC_EXCP_VPU);
+ return;
}
+ uimm = UIMM5(ctx->opcode);
+ bofs = avr64_offset(rB(ctx->opcode), true);
+ dofs = avr64_offset(rD(ctx->opcode), true);
+
+ /* Experimental testing shows that hardware masks the immediate. */
+ bofs += (uimm << vece) & 15;
+#ifndef HOST_WORDS_BIGENDIAN
+ bofs ^= 15;
+ bofs &= ~((1 << vece) - 1);
+#endif
+
+ tcg_gen_gvec_dup_mem(vece, dofs, bofs, 16, 16);
+}
+
+#define GEN_VXFORM_VSPLT(name, vece, opc2, opc3) \
+static void glue(gen_, name)(DisasContext *ctx) { gen_vsplt(ctx, vece); }
+
#define GEN_VXFORM_UIMM_ENV(name, opc2, opc3) \
static void glue(gen_, name)(DisasContext *ctx) \
{ \
@@ -893,9 +908,9 @@ static void glue(gen_, name)(DisasContext *ctx) \
tcg_temp_free_ptr(rd); \
}
-GEN_VXFORM_UIMM(vspltb, 6, 8);
-GEN_VXFORM_UIMM(vsplth, 6, 9);
-GEN_VXFORM_UIMM(vspltw, 6, 10);
+GEN_VXFORM_VSPLT(vspltb, MO_8, 6, 8);
+GEN_VXFORM_VSPLT(vsplth, MO_16, 6, 9);
+GEN_VXFORM_VSPLT(vspltw, MO_32, 6, 10);
GEN_VXFORM_UIMM_SPLAT(vextractub, 6, 8, 15);
GEN_VXFORM_UIMM_SPLAT(vextractuh, 6, 9, 14);
GEN_VXFORM_UIMM_SPLAT(vextractuw, 6, 10, 12);
@@ -1255,7 +1270,7 @@ GEN_VXFORM_DUAL(vsldoi, PPC_ALTIVEC, PPC_NONE,
#undef GEN_VXRFORM_DUAL
#undef GEN_VXRFORM1
#undef GEN_VXRFORM
-#undef GEN_VXFORM_SIMM
+#undef GEN_VXFORM_DUPI
#undef GEN_VXFORM_NOA
#undef GEN_VXFORM_UIMM
#undef GEN_VAFORM_PAIRED
diff --git a/target/ppc/translate/vsx-impl.inc.c b/target/ppc/translate/vsx-impl.inc.c
index ed4fdceacf..e73197e717 100644
--- a/target/ppc/translate/vsx-impl.inc.c
+++ b/target/ppc/translate/vsx-impl.inc.c
@@ -10,6 +10,11 @@ static inline void set_vsr(int n, TCGv_i64 src)
tcg_gen_st_i64(src, cpu_env, offsetof(CPUPPCState, vsr[n].u64[1]));
}
+static inline int vsr_full_offset(int n)
+{
+ return offsetof(CPUPPCState, vsr[n].u64[0]);
+}
+
static inline void get_cpu_vsrh(TCGv_i64 dst, int n)
{
if (n < 32) {
@@ -1255,40 +1260,26 @@ static void gen_xxbrw(DisasContext *ctx)
tcg_temp_free_i64(xbl);
}
-#define VSX_LOGICAL(name, tcg_op) \
+#define VSX_LOGICAL(name, vece, tcg_op) \
static void glue(gen_, name)(DisasContext * ctx) \
{ \
- TCGv_i64 t0; \
- TCGv_i64 t1; \
- TCGv_i64 t2; \
if (unlikely(!ctx->vsx_enabled)) { \
gen_exception(ctx, POWERPC_EXCP_VSXU); \
return; \
} \
- t0 = tcg_temp_new_i64(); \
- t1 = tcg_temp_new_i64(); \
- t2 = tcg_temp_new_i64(); \
- get_cpu_vsrh(t0, xA(ctx->opcode)); \
- get_cpu_vsrh(t1, xB(ctx->opcode)); \
- tcg_op(t2, t0, t1); \
- set_cpu_vsrh(xT(ctx->opcode), t2); \
- get_cpu_vsrl(t0, xA(ctx->opcode)); \
- get_cpu_vsrl(t1, xB(ctx->opcode)); \
- tcg_op(t2, t0, t1); \
- set_cpu_vsrl(xT(ctx->opcode), t2); \
- tcg_temp_free_i64(t0); \
- tcg_temp_free_i64(t1); \
- tcg_temp_free_i64(t2); \
+ tcg_op(vece, vsr_full_offset(xT(ctx->opcode)), \
+ vsr_full_offset(xA(ctx->opcode)), \
+ vsr_full_offset(xB(ctx->opcode)), 16, 16); \
}
-VSX_LOGICAL(xxland, tcg_gen_and_i64)
-VSX_LOGICAL(xxlandc, tcg_gen_andc_i64)
-VSX_LOGICAL(xxlor, tcg_gen_or_i64)
-VSX_LOGICAL(xxlxor, tcg_gen_xor_i64)
-VSX_LOGICAL(xxlnor, tcg_gen_nor_i64)
-VSX_LOGICAL(xxleqv, tcg_gen_eqv_i64)
-VSX_LOGICAL(xxlnand, tcg_gen_nand_i64)
-VSX_LOGICAL(xxlorc, tcg_gen_orc_i64)
+VSX_LOGICAL(xxland, MO_64, tcg_gen_gvec_and)
+VSX_LOGICAL(xxlandc, MO_64, tcg_gen_gvec_andc)
+VSX_LOGICAL(xxlor, MO_64, tcg_gen_gvec_or)
+VSX_LOGICAL(xxlxor, MO_64, tcg_gen_gvec_xor)
+VSX_LOGICAL(xxlnor, MO_64, tcg_gen_gvec_nor)
+VSX_LOGICAL(xxleqv, MO_64, tcg_gen_gvec_eqv)
+VSX_LOGICAL(xxlnand, MO_64, tcg_gen_gvec_nand)
+VSX_LOGICAL(xxlorc, MO_64, tcg_gen_gvec_orc)
#define VSX_XXMRG(name, high) \
static void glue(gen_, name)(DisasContext * ctx) \
@@ -1330,85 +1321,71 @@ static void glue(gen_, name)(DisasContext * ctx) \
VSX_XXMRG(xxmrghw, 1)
VSX_XXMRG(xxmrglw, 0)
-static void gen_xxsel(DisasContext * ctx)
+static void xxsel_i64(TCGv_i64 t, TCGv_i64 a, TCGv_i64 b, TCGv_i64 c)
{
- TCGv_i64 a, b, c, tmp;
- if (unlikely(!ctx->vsx_enabled)) {
- gen_exception(ctx, POWERPC_EXCP_VSXU);
- return;
- }
- a = tcg_temp_new_i64();
- b = tcg_temp_new_i64();
- c = tcg_temp_new_i64();
- tmp = tcg_temp_new_i64();
-
- get_cpu_vsrh(a, xA(ctx->opcode));
- get_cpu_vsrh(b, xB(ctx->opcode));
- get_cpu_vsrh(c, xC(ctx->opcode));
-
tcg_gen_and_i64(b, b, c);
tcg_gen_andc_i64(a, a, c);
- tcg_gen_or_i64(tmp, a, b);
- set_cpu_vsrh(xT(ctx->opcode), tmp);
-
- get_cpu_vsrl(a, xA(ctx->opcode));
- get_cpu_vsrl(b, xB(ctx->opcode));
- get_cpu_vsrl(c, xC(ctx->opcode));
-
- tcg_gen_and_i64(b, b, c);
- tcg_gen_andc_i64(a, a, c);
- tcg_gen_or_i64(tmp, a, b);
- set_cpu_vsrl(xT(ctx->opcode), tmp);
+ tcg_gen_or_i64(t, a, b);
+}
- tcg_temp_free_i64(a);
- tcg_temp_free_i64(b);
- tcg_temp_free_i64(c);
- tcg_temp_free_i64(tmp);
+static void xxsel_vec(unsigned vece, TCGv_vec t, TCGv_vec a,
+ TCGv_vec b, TCGv_vec c)
+{
+ tcg_gen_and_vec(vece, b, b, c);
+ tcg_gen_andc_vec(vece, a, a, c);
+ tcg_gen_or_vec(vece, t, a, b);
}
-static void gen_xxspltw(DisasContext *ctx)
+static void gen_xxsel(DisasContext *ctx)
{
- TCGv_i64 b, b2;
- TCGv_i64 vsr;
+ static const GVecGen4 g = {
+ .fni8 = xxsel_i64,
+ .fniv = xxsel_vec,
+ .vece = MO_64,
+ };
+ int rt = xT(ctx->opcode);
+ int ra = xA(ctx->opcode);
+ int rb = xB(ctx->opcode);
+ int rc = xC(ctx->opcode);
if (unlikely(!ctx->vsx_enabled)) {
gen_exception(ctx, POWERPC_EXCP_VSXU);
return;
}
+ tcg_gen_gvec_4(vsr_full_offset(rt), vsr_full_offset(ra),
+ vsr_full_offset(rb), vsr_full_offset(rc), 16, 16, &g);
+}
- vsr = tcg_temp_new_i64();
- if (UIM(ctx->opcode) & 2) {
- get_cpu_vsrl(vsr, xB(ctx->opcode));
- } else {
- get_cpu_vsrh(vsr, xB(ctx->opcode));
- }
-
- b = tcg_temp_new_i64();
- b2 = tcg_temp_new_i64();
+static void gen_xxspltw(DisasContext *ctx)
+{
+ int rt = xT(ctx->opcode);
+ int rb = xB(ctx->opcode);
+ int uim = UIM(ctx->opcode);
+ int tofs, bofs;
- if (UIM(ctx->opcode) & 1) {
- tcg_gen_ext32u_i64(b, vsr);
- } else {
- tcg_gen_shri_i64(b, vsr, 32);
+ if (unlikely(!ctx->vsx_enabled)) {
+ gen_exception(ctx, POWERPC_EXCP_VSXU);
+ return;
}
- tcg_gen_shli_i64(b2, b, 32);
- tcg_gen_or_i64(vsr, b, b2);
- set_cpu_vsrh(xT(ctx->opcode), vsr);
- set_cpu_vsrl(xT(ctx->opcode), vsr);
+ tofs = vsr_full_offset(rt);
+ bofs = vsr_full_offset(rb);
+ bofs += uim << MO_32;
+#ifndef HOST_WORDS_BIG_ENDIAN
+ bofs ^= 8 | 4;
+#endif
- tcg_temp_free_i64(vsr);
- tcg_temp_free_i64(b);
- tcg_temp_free_i64(b2);
+ tcg_gen_gvec_dup_mem(MO_32, tofs, bofs, 16, 16);
}
#define pattern(x) (((x) & 0xff) * (~(uint64_t)0 / 0xff))
static void gen_xxspltib(DisasContext *ctx)
{
- unsigned char uim8 = IMM8(ctx->opcode);
- TCGv_i64 vsr;
- if (xS(ctx->opcode) < 32) {
+ uint8_t uim8 = IMM8(ctx->opcode);
+ int rt = xT(ctx->opcode);
+
+ if (rt < 32) {
if (unlikely(!ctx->altivec_enabled)) {
gen_exception(ctx, POWERPC_EXCP_VPU);
return;
@@ -1419,11 +1396,7 @@ static void gen_xxspltib(DisasContext *ctx)
return;
}
}
- vsr = tcg_temp_new_i64();
- tcg_gen_movi_i64(vsr, pattern(uim8));
- set_cpu_vsrh(xT(ctx->opcode), vsr);
- set_cpu_vsrl(xT(ctx->opcode), vsr);
- tcg_temp_free_i64(vsr);
+ tcg_gen_gvec_dup8i(vsr_full_offset(rt), 16, 16, uim8);
}
static void gen_xxsldwi(DisasContext *ctx)
diff --git a/target/ppc/translate_init.inc.c b/target/ppc/translate_init.inc.c
index f393a408ac..d884906004 100644
--- a/target/ppc/translate_init.inc.c
+++ b/target/ppc/translate_init.inc.c
@@ -602,10 +602,9 @@ static void spr_write_excp_vector(DisasContext *ctx, int sprn, int gprn)
static inline void vscr_init(CPUPPCState *env, uint32_t val)
{
- env->vscr = val;
/* Altivec always uses round-to-nearest */
set_float_rounding_mode(float_round_nearest_even, &env->vec_status);
- set_flush_to_zero(vscr_nj, &env->vec_status);
+ helper_mtvscr(env, val);
}
#ifdef CONFIG_USER_ONLY
@@ -8874,7 +8873,7 @@ POWERPC_FAMILY(POWER9)(ObjectClass *oc, void *data)
PPC2_FP_TST_ISA206 | PPC2_BCTAR_ISA207 |
PPC2_LSQ_ISA207 | PPC2_ALTIVEC_207 |
PPC2_ISA205 | PPC2_ISA207S | PPC2_FP_CVT_S64 |
- PPC2_TM | PPC2_PM_ISA206 | PPC2_ISA300 | PPC2_PRCNTL;
+ PPC2_TM | PPC2_ISA300 | PPC2_PRCNTL;
pcc->msr_mask = (1ull << MSR_SF) |
(1ull << MSR_TM) |
(1ull << MSR_VR) |
@@ -8980,6 +8979,10 @@ static void init_ppc_proc(PowerPCCPU *cpu)
/* PowerPC implementation specific initialisations (SPRs, timers, ...) */
(*pcc->init_proc)(env);
+#if !defined(CONFIG_USER_ONLY)
+ ppc_gdb_gen_spr_xml(cpu);
+#endif
+
/* MSR bits & flags consistency checks */
if (env->msr_mask & (1 << 25)) {
switch (env->flags & (POWERPC_FLAG_SPE | POWERPC_FLAG_VRE)) {
@@ -9476,6 +9479,55 @@ static bool avr_need_swap(CPUPPCState *env)
#endif
}
+#if !defined(CONFIG_USER_ONLY)
+static int gdb_find_spr_idx(CPUPPCState *env, int n)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(env->spr_cb); i++) {
+ ppc_spr_t *spr = &env->spr_cb[i];
+
+ if (spr->name && spr->gdb_id == n) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+static int gdb_get_spr_reg(CPUPPCState *env, uint8_t *mem_buf, int n)
+{
+ int reg;
+ int len;
+
+ reg = gdb_find_spr_idx(env, n);
+ if (reg < 0) {
+ return 0;
+ }
+
+ len = TARGET_LONG_SIZE;
+ stn_p(mem_buf, len, env->spr[reg]);
+ ppc_maybe_bswap_register(env, mem_buf, len);
+ return len;
+}
+
+static int gdb_set_spr_reg(CPUPPCState *env, uint8_t *mem_buf, int n)
+{
+ int reg;
+ int len;
+
+ reg = gdb_find_spr_idx(env, n);
+ if (reg < 0) {
+ return 0;
+ }
+
+ len = TARGET_LONG_SIZE;
+ ppc_maybe_bswap_register(env, mem_buf, len);
+ env->spr[reg] = ldn_p(mem_buf, len);
+
+ return len;
+}
+#endif
+
static int gdb_get_float_reg(CPUPPCState *env, uint8_t *mem_buf, int n)
{
if (n < 32) {
@@ -9522,7 +9574,7 @@ static int gdb_get_avr_reg(CPUPPCState *env, uint8_t *mem_buf, int n)
return 16;
}
if (n == 32) {
- stl_p(mem_buf, env->vscr);
+ stl_p(mem_buf, helper_mfvscr(env));
ppc_maybe_bswap_register(env, mem_buf, 4);
return 4;
}
@@ -9551,7 +9603,7 @@ static int gdb_set_avr_reg(CPUPPCState *env, uint8_t *mem_buf, int n)
}
if (n == 32) {
ppc_maybe_bswap_register(env, mem_buf, 4);
- env->vscr = ldl_p(mem_buf);
+ helper_mtvscr(env, ldl_p(mem_buf));
return 4;
}
if (n == 33) {
@@ -9705,7 +9757,10 @@ static void ppc_cpu_realize(DeviceState *dev, Error **errp)
gdb_register_coprocessor(cs, gdb_get_vsx_reg, gdb_set_vsx_reg,
32, "power-vsx.xml", 0);
}
-
+#ifndef CONFIG_USER_ONLY
+ gdb_register_coprocessor(cs, gdb_get_spr_reg, gdb_set_spr_reg,
+ pcc->gdb_num_sprs, "power-spr.xml", 0);
+#endif
qemu_init_vcpu(cs);
pcc->parent_realize(dev, errp);
@@ -10468,7 +10523,9 @@ static void ppc_cpu_class_init(ObjectClass *oc, void *data)
#endif
cc->gdb_num_core_regs = 71;
-
+#ifndef CONFIG_USER_ONLY
+ cc->gdb_get_dynamic_xml = ppc_gdb_get_dynamic_xml;
+#endif
#ifdef USE_APPLE_GDB
cc->gdb_read_register = ppc_cpu_gdb_read_register_apple;
cc->gdb_write_register = ppc_cpu_gdb_write_register_apple;