diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2019-02-18 16:20:13 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2019-02-18 16:20:13 +0000 |
commit | 2e68b8620637a4ee8c79b5724144b726af1e261b (patch) | |
tree | e53cbfaf5cbdd0d0b0c326838634e92096540256 | |
parent | a0430dd8abb8a2f31c5ee919daab2e3d76353c04 (diff) | |
parent | 73e14c6a9cdefb94c01ea488f04e7fba7ac0dc5b (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>
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; |