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 -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEdfRlhq5hpmzETofcbDjKyiDZs5IFAlxqt4oACgkQbDjKyiDZ s5KeaBAAzHortvO/rKiQ0hkhKdy9MtaBbuPIYwMYA5dQXYH2gOi/VZxXHBhwDczy MdXv+5Y+OYEWL0RC6kJGceM4xCD4b+WzZMriwYA5q32YeiUHmduyWxdq8Ulasm32 xok5DheVjyJLS970Q8Qp1Ck7vRXfYVd/7R/hNExcKkYU3wczqVEDqglHyThxaP0s pTKrPGSuT+kHfi4kuLQ2qyKeNe6XWrvmgBAnXsud6lqWQ7D0ZAalnzhEoMrEMeyK ldjh/suB68WyJZ7Sl0REV2DlILLKc/wDSL4HMmjmyuV5ldEKVyqhM8f7tHMtzeET Ab8zKd0F4L1ffjyN3gmrh4WtyTa5L1s8av/bJFfESFNT3ioPFuDeMYQGQH4y3hJg nNGSJaWXRu/3c0/uRcA9SSxWQYSzKCz2WFEV06UK2JlajVd6Wy5zpjy/7spZhbQH z4TOSQrnRdIveRBTyUTUkJjbAitocUfHs2vCfzDBhACfj2LovSicNG284LlZXF1U /d6F668Z2aoDpdpgKh1QSOJ6bTS/1KwKCvZ89L15EUYOcCrZlZjECJR+WtGhTP7A YKyylvBkZ5a+M7t0f/Rm8KAy5QnpEAy7fKqLGQw8aldqX2MK46acjEwA5v696yZk iCyAas5gu0U6ytKMOYwT1Lq1hmID/fyBApXIeFJhz2KFzTb4PqM= =QQra -----END PGP SIGNATURE----- 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>
This commit is contained in:
commit
2e68b86206
hw
acpi
char
core
intc
misc/macio
pci
ppc
s390x
scsi
usb
include/hw
target/ppc
@ -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));
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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),
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
|
@ -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"
|
||||
|
@ -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");
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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()
|
||||
},
|
||||
};
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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()) {
|
||||
|
@ -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,39 +840,31 @@ 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;
|
||||
|
||||
if (unlikely(!ctx->altivec_enabled)) {
|
||||
gen_exception(ctx, POWERPC_EXCP_VPU);
|
||||
return;
|
||||
}
|
||||
|
||||
#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); \
|
||||
}
|
||||
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
|
||||
|
@ -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;
|
||||
tcg_gen_and_i64(b, b, c);
|
||||
tcg_gen_andc_i64(a, a, c);
|
||||
tcg_gen_or_i64(t, a, b);
|
||||
}
|
||||
|
||||
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_xxsel(DisasContext *ctx)
|
||||
{
|
||||
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;
|
||||
}
|
||||
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_temp_free_i64(a);
|
||||
tcg_temp_free_i64(b);
|
||||
tcg_temp_free_i64(c);
|
||||
tcg_temp_free_i64(tmp);
|
||||
tcg_gen_gvec_4(vsr_full_offset(rt), vsr_full_offset(ra),
|
||||
vsr_full_offset(rb), vsr_full_offset(rc), 16, 16, &g);
|
||||
}
|
||||
|
||||
static void gen_xxspltw(DisasContext *ctx)
|
||||
{
|
||||
TCGv_i64 b, b2;
|
||||
TCGv_i64 vsr;
|
||||
int rt = xT(ctx->opcode);
|
||||
int rb = xB(ctx->opcode);
|
||||
int uim = UIM(ctx->opcode);
|
||||
int tofs, bofs;
|
||||
|
||||
if (unlikely(!ctx->vsx_enabled)) {
|
||||
gen_exception(ctx, POWERPC_EXCP_VSXU);
|
||||
return;
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
tofs = vsr_full_offset(rt);
|
||||
bofs = vsr_full_offset(rb);
|
||||
bofs += uim << MO_32;
|
||||
#ifndef HOST_WORDS_BIG_ENDIAN
|
||||
bofs ^= 8 | 4;
|
||||
#endif
|
||||
|
||||
b = tcg_temp_new_i64();
|
||||
b2 = tcg_temp_new_i64();
|
||||
|
||||
if (UIM(ctx->opcode) & 1) {
|
||||
tcg_gen_ext32u_i64(b, vsr);
|
||||
} else {
|
||||
tcg_gen_shri_i64(b, vsr, 32);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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)
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user