diff options
130 files changed, 3031 insertions, 1773 deletions
diff --git a/.gitlab-ci.d/windows.yml b/.gitlab-ci.d/windows.yml index c4bde758be..da6013904a 100644 --- a/.gitlab-ci.d/windows.yml +++ b/.gitlab-ci.d/windows.yml @@ -61,7 +61,7 @@ msys2-64bit: - .\msys64\usr\bin\bash -lc './configure --target-list=x86_64-softmmu --enable-capstone --without-default-devices' - .\msys64\usr\bin\bash -lc "sed -i '/^ROMS=/d' build/config-host.mak" - - .\msys64\usr\bin\bash -lc 'make -j2' + - .\msys64\usr\bin\bash -lc 'make' - .\msys64\usr\bin\bash -lc 'make check' msys2-32bit: @@ -94,5 +94,5 @@ msys2-32bit: - mkdir output - cd output - ..\msys64\usr\bin\bash -lc "../configure --target-list=ppc64-softmmu" - - ..\msys64\usr\bin\bash -lc 'make -j2' + - ..\msys64\usr\bin\bash -lc 'make' - ..\msys64\usr\bin\bash -lc 'make check' diff --git a/MAINTAINERS b/MAINTAINERS index 5ce4227ff6..1729c0901c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1282,7 +1282,7 @@ F: hw/openrisc/openrisc_sim.c PowerPC Machines ---------------- -405 (ref405ep and taihu) +405 (ref405ep) L: qemu-ppc@nongnu.org S: Orphan F: hw/ppc/ppc405_boards.c diff --git a/backends/hostmem.c b/backends/hostmem.c index 624bb7ecd3..4428e06738 100644 --- a/backends/hostmem.c +++ b/backends/hostmem.c @@ -306,22 +306,12 @@ bool host_memory_backend_is_mapped(HostMemoryBackend *backend) return backend->is_mapped; } -#ifdef __linux__ size_t host_memory_backend_pagesize(HostMemoryBackend *memdev) { - Object *obj = OBJECT(memdev); - char *path = object_property_get_str(obj, "mem-path", NULL); - size_t pagesize = qemu_mempath_getpagesize(path); - - g_free(path); + size_t pagesize = qemu_ram_pagesize(memdev->mr.ram_block); + g_assert(pagesize >= qemu_real_host_page_size()); return pagesize; } -#else -size_t host_memory_backend_pagesize(HostMemoryBackend *memdev) -{ - return qemu_real_host_page_size(); -} -#endif static void host_memory_backend_memory_complete(UserCreatable *uc, Error **errp) diff --git a/backends/tpm/tpm_ioctl.h b/backends/tpm/tpm_ioctl.h index bd6c12cb86..d67bf0283b 100644 --- a/backends/tpm/tpm_ioctl.h +++ b/backends/tpm/tpm_ioctl.h @@ -9,8 +9,10 @@ #ifndef TPM_IOCTL_H #define TPM_IOCTL_H +#ifndef _WIN32 #include <sys/uio.h> #include <sys/ioctl.h> +#endif #ifdef HAVE_SYS_IOCCOM_H #include <sys/ioccom.h> @@ -222,6 +224,7 @@ typedef struct ptm_setbuffersize ptm_setbuffersize; #define PTM_CAP_SET_DATAFD (1 << 12) #define PTM_CAP_SET_BUFFERSIZE (1 << 13) +#ifndef _WIN32 enum { PTM_GET_CAPABILITY = _IOR('P', 0, ptm_cap), PTM_INIT = _IOWR('P', 1, ptm_init), @@ -241,6 +244,7 @@ enum { PTM_SET_DATAFD = _IOR('P', 15, ptm_res), PTM_SET_BUFFERSIZE = _IOWR('P', 16, ptm_setbuffersize), }; +#endif /* * Commands used by the non-CUSE TPMs diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst index 91b03115ee..c75a25daad 100644 --- a/docs/about/deprecated.rst +++ b/docs/about/deprecated.rst @@ -233,15 +233,6 @@ deprecated; use the new name ``dtb-randomness`` instead. The new name better reflects the way this property affects all random data within the device tree blob, not just the ``kaslr-seed`` node. -PPC 405 ``taihu`` machine (since 7.0) -''''''''''''''''''''''''''''''''''''' - -The PPC 405 CPU is a system-on-a-chip, so all 405 machines are very similar, -except for some external periphery. However, the periphery of the ``taihu`` -machine is hardly emulated at all (e.g. neither the LCD nor the USB part had -been implemented), so there is not much value added by this board. Use the -``ref405ep`` machine instead. - ``pc-i440fx-1.4`` up to ``pc-i440fx-1.7`` (since 7.0) ''''''''''''''''''''''''''''''''''''''''''''''''''''' diff --git a/docs/about/removed-features.rst b/docs/about/removed-features.rst index 925e22016f..a4aa3dca69 100644 --- a/docs/about/removed-features.rst +++ b/docs/about/removed-features.rst @@ -668,6 +668,12 @@ Aspeed ``swift-bmc`` machine (removed in 7.0) This machine was removed because it was unused. Alternative AST2500 based OpenPOWER machines are ``witherspoon-bmc`` and ``romulus-bmc``. +ppc ``taihu`` machine (removed in 7.2) +''''''''''''''''''''''''''''''''''''''''''''' + +This machine was removed because it was partially emulated and 405 +machines are very similar. Use the ``ref405ep`` machine instead. + linux-user mode CPUs -------------------- diff --git a/docs/devel/testing.rst b/docs/devel/testing.rst index 3f6ebd5073..f35f117d95 100644 --- a/docs/devel/testing.rst +++ b/docs/devel/testing.rst @@ -297,7 +297,7 @@ build and test QEMU in predefined and widely accessible Linux environments. This makes it possible to expand the test coverage across distros, toolchain flavors and library versions. The support was originally written for Docker although we also support Podman as -an alternative container runtime. Although the many of the target +an alternative container runtime. Although many of the target names and scripts are prefixed with "docker" the system will automatically run on whichever is configured. diff --git a/docs/system/ppc/embedded.rst b/docs/system/ppc/embedded.rst index cfffbda24d..af3b3d9fa4 100644 --- a/docs/system/ppc/embedded.rst +++ b/docs/system/ppc/embedded.rst @@ -6,5 +6,4 @@ Embedded family boards - ``ppce500`` generic paravirt e500 platform - ``ref405ep`` ref405ep - ``sam460ex`` aCube Sam460ex -- ``taihu`` taihu - ``virtex-ml507`` Xilinx Virtex ML507 reference design diff --git a/docs/system/ppc/pseries.rst b/docs/system/ppc/pseries.rst index 3e1bbe6726..a876d897b6 100644 --- a/docs/system/ppc/pseries.rst +++ b/docs/system/ppc/pseries.rst @@ -62,7 +62,7 @@ Booting via ``-kernel`` supports the following: +-------------------+-------------------+------------------+ | vmlinux LE | ✓ | ✓ | +-------------------+-------------------+------------------+ -| zImage.pseries BE | x | ✓¹ | +| zImage.pseries BE | ✓¹ | ✓¹ | +-------------------+-------------------+------------------+ | zImage.pseries LE | ✓ | ✓ | +-------------------+-------------------+------------------+ diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc index bbeadaa189..a9f268fcab 100644 --- a/fpu/softfloat-parts.c.inc +++ b/fpu/softfloat-parts.c.inc @@ -214,18 +214,35 @@ static void partsN(uncanon_normal)(FloatPartsN *p, float_status *s, p->frac_lo &= ~round_mask; } } else if (unlikely(exp >= exp_max)) { - flags |= float_flag_overflow | float_flag_inexact; - if (overflow_norm) { + flags |= float_flag_overflow; + if (s->rebias_overflow) { + exp -= fmt->exp_re_bias; + } else if (overflow_norm) { + flags |= float_flag_inexact; exp = exp_max - 1; frac_allones(p); p->frac_lo &= ~round_mask; } else { + flags |= float_flag_inexact; p->cls = float_class_inf; exp = exp_max; frac_clear(p); } } frac_shr(p, frac_shift); + } else if (unlikely(s->rebias_underflow)) { + flags |= float_flag_underflow; + exp += fmt->exp_re_bias; + if (p->frac_lo & round_mask) { + flags |= float_flag_inexact; + if (frac_addi(p, p, inc)) { + frac_shr(p, 1); + p->frac_hi |= DECOMPOSED_IMPLICIT_BIT; + exp++; + } + p->frac_lo &= ~round_mask; + } + frac_shr(p, frac_shift); } else if (s->flush_to_zero) { flags |= float_flag_output_denormal; p->cls = float_class_zero; diff --git a/fpu/softfloat.c b/fpu/softfloat.c index 4a871ef2a1..c7454c3eb1 100644 --- a/fpu/softfloat.c +++ b/fpu/softfloat.c @@ -521,6 +521,7 @@ typedef struct { typedef struct { int exp_size; int exp_bias; + int exp_re_bias; int exp_max; int frac_size; int frac_shift; @@ -532,6 +533,7 @@ typedef struct { #define FLOAT_PARAMS_(E) \ .exp_size = E, \ .exp_bias = ((1 << E) - 1) >> 1, \ + .exp_re_bias = (1 << (E - 1)) + (1 << (E - 2)), \ .exp_max = (1 << E) - 1 #define FLOAT_PARAMS(E, F) \ diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 9633f822f3..1a6480fd2a 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -3094,10 +3094,17 @@ static void machvirt_machine_init(void) } type_init(machvirt_machine_init); +static void virt_machine_7_2_options(MachineClass *mc) +{ +} +DEFINE_VIRT_MACHINE_AS_LATEST(7, 2) + static void virt_machine_7_1_options(MachineClass *mc) { + virt_machine_7_2_options(mc); + compat_props_add(mc->compat_props, hw_compat_7_1, hw_compat_7_1_len); } -DEFINE_VIRT_MACHINE_AS_LATEST(7, 1) +DEFINE_VIRT_MACHINE(7, 1) static void virt_machine_7_0_options(MachineClass *mc) { diff --git a/hw/core/machine.c b/hw/core/machine.c index a673302cce..aa520e74a8 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -40,6 +40,9 @@ #include "hw/virtio/virtio-pci.h" #include "qom/object_interfaces.h" +GlobalProperty hw_compat_7_1[] = {}; +const size_t hw_compat_7_1_len = G_N_ELEMENTS(hw_compat_7_1); + GlobalProperty hw_compat_7_0[] = { { "arm-gicv3-common", "force-8-bit-prio", "on" }, { "nvme-ns", "eui64-default", "on"}, diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 7280c02ce3..566accf7e6 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -107,6 +107,9 @@ { "qemu64-" TYPE_X86_CPU, "model-id", "QEMU Virtual CPU version " v, },\ { "athlon-" TYPE_X86_CPU, "model-id", "QEMU Virtual CPU version " v, }, +GlobalProperty pc_compat_7_1[] = {}; +const size_t pc_compat_7_1_len = G_N_ELEMENTS(pc_compat_7_1); + GlobalProperty pc_compat_7_0[] = {}; const size_t pc_compat_7_0_len = G_N_ELEMENTS(pc_compat_7_0); diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index 20962c34e7..8043a250ad 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -432,7 +432,7 @@ static void pc_i440fx_machine_options(MachineClass *m) machine_class_allow_dynamic_sysbus_dev(m, TYPE_VMBUS_BRIDGE); } -static void pc_i440fx_7_1_machine_options(MachineClass *m) +static void pc_i440fx_7_2_machine_options(MachineClass *m) { PCMachineClass *pcmc = PC_MACHINE_CLASS(m); pc_i440fx_machine_options(m); @@ -442,6 +442,18 @@ static void pc_i440fx_7_1_machine_options(MachineClass *m) pcmc->legacy_no_rng_seed = true; } +DEFINE_I440FX_MACHINE(v7_2, "pc-i440fx-7.2", NULL, + pc_i440fx_7_2_machine_options); + +static void pc_i440fx_7_1_machine_options(MachineClass *m) +{ + pc_i440fx_7_2_machine_options(m); + m->alias = NULL; + m->is_default = false; + compat_props_add(m->compat_props, hw_compat_7_1, hw_compat_7_1_len); + compat_props_add(m->compat_props, pc_compat_7_1, pc_compat_7_1_len); +} + DEFINE_I440FX_MACHINE(v7_1, "pc-i440fx-7.1", NULL, pc_i440fx_7_1_machine_options); diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c index 2e5dae9a89..53eda50e81 100644 --- a/hw/i386/pc_q35.c +++ b/hw/i386/pc_q35.c @@ -370,7 +370,7 @@ static void pc_q35_machine_options(MachineClass *m) m->max_cpus = 288; } -static void pc_q35_7_1_machine_options(MachineClass *m) +static void pc_q35_7_2_machine_options(MachineClass *m) { PCMachineClass *pcmc = PC_MACHINE_CLASS(m); pc_q35_machine_options(m); @@ -379,6 +379,17 @@ static void pc_q35_7_1_machine_options(MachineClass *m) pcmc->legacy_no_rng_seed = true; } +DEFINE_Q35_MACHINE(v7_2, "pc-q35-7.2", NULL, + pc_q35_7_2_machine_options); + +static void pc_q35_7_1_machine_options(MachineClass *m) +{ + pc_q35_7_2_machine_options(m); + m->alias = NULL; + compat_props_add(m->compat_props, hw_compat_7_1, hw_compat_7_1_len); + compat_props_add(m->compat_props, pc_compat_7_1, pc_compat_7_1_len); +} + DEFINE_Q35_MACHINE(v7_1, "pc-q35-7.1", NULL, pc_q35_7_1_machine_options); diff --git a/hw/intc/ppc-uic.c b/hw/intc/ppc-uic.c index 60013f2dde..dcf5de5d43 100644 --- a/hw/intc/ppc-uic.c +++ b/hw/intc/ppc-uic.c @@ -25,11 +25,8 @@ #include "qemu/osdep.h" #include "hw/intc/ppc-uic.h" #include "hw/irq.h" -#include "cpu.h" -#include "hw/ppc/ppc.h" #include "hw/qdev-properties.h" #include "migration/vmstate.h" -#include "qapi/error.h" enum { DCR_UICSR = 0x000, @@ -105,10 +102,9 @@ static void ppcuic_trigger_irq(PPCUIC *uic) static void ppcuic_set_irq(void *opaque, int irq_num, int level) { - PPCUIC *uic; + PPCUIC *uic = opaque; uint32_t mask, sr; - uic = opaque; mask = 1U << (31 - irq_num); LOG_UIC("%s: irq %d level %d uicsr %08" PRIx32 " mask %08" PRIx32 " => %08" PRIx32 " %08" PRIx32 "\n", @@ -144,10 +140,9 @@ static void ppcuic_set_irq(void *opaque, int irq_num, int level) static uint32_t dcr_read_uic(void *opaque, int dcrn) { - PPCUIC *uic; + PPCUIC *uic = opaque; uint32_t ret; - uic = opaque; dcrn -= uic->dcr_base; switch (dcrn) { case DCR_UICSR: @@ -192,9 +187,8 @@ static uint32_t dcr_read_uic(void *opaque, int dcrn) static void dcr_write_uic(void *opaque, int dcrn, uint32_t val) { - PPCUIC *uic; + PPCUIC *uic = opaque; - uic = opaque; dcrn -= uic->dcr_base; LOG_UIC("%s: dcr %d val 0x%x\n", __func__, dcrn, val); switch (dcrn) { @@ -251,19 +245,12 @@ static void ppc_uic_reset(DeviceState *dev) static void ppc_uic_realize(DeviceState *dev, Error **errp) { PPCUIC *uic = PPC_UIC(dev); + Ppc4xxDcrDeviceState *dcr = PPC4xx_DCR_DEVICE(dev); SysBusDevice *sbd = SYS_BUS_DEVICE(dev); - PowerPCCPU *cpu; int i; - if (!uic->cpu) { - /* This is a programming error in the code using this device */ - error_setg(errp, "ppc-uic 'cpu' link property was not set"); - return; - } - - cpu = POWERPC_CPU(uic->cpu); for (i = 0; i < DCR_UICMAX; i++) { - ppc_dcr_register(&cpu->env, uic->dcr_base + i, uic, + ppc4xx_dcr_register(dcr, uic->dcr_base + i, uic, &dcr_read_uic, &dcr_write_uic); } @@ -273,7 +260,6 @@ static void ppc_uic_realize(DeviceState *dev, Error **errp) } static Property ppc_uic_properties[] = { - DEFINE_PROP_LINK("cpu", PPCUIC, cpu, TYPE_CPU, CPUState *), DEFINE_PROP_UINT32("dcr-base", PPCUIC, dcr_base, 0xc0), DEFINE_PROP_BOOL("use-vectors", PPCUIC, use_vectors, true), DEFINE_PROP_END_OF_LIST() @@ -308,7 +294,7 @@ static void ppc_uic_class_init(ObjectClass *klass, void *data) static const TypeInfo ppc_uic_info = { .name = TYPE_PPC_UIC, - .parent = TYPE_SYS_BUS_DEVICE, + .parent = TYPE_PPC4xx_DCR_DEVICE, .instance_size = sizeof(PPCUIC), .class_init = ppc_uic_class_init, }; diff --git a/hw/m68k/virt.c b/hw/m68k/virt.c index 0aa383fa6b..3122c8ef2c 100644 --- a/hw/m68k/virt.c +++ b/hw/m68k/virt.c @@ -322,10 +322,17 @@ type_init(virt_machine_register_types) } \ type_init(machvirt_machine_##major##_##minor##_init); +static void virt_machine_7_2_options(MachineClass *mc) +{ +} +DEFINE_VIRT_MACHINE(7, 2, true) + static void virt_machine_7_1_options(MachineClass *mc) { + virt_machine_7_2_options(mc); + compat_props_add(mc->compat_props, hw_compat_7_1, hw_compat_7_1_len); } -DEFINE_VIRT_MACHINE(7, 1, true) +DEFINE_VIRT_MACHINE(7, 1, false) static void virt_machine_7_0_options(MachineClass *mc) { diff --git a/hw/pci-host/meson.build b/hw/pci-host/meson.build index c07596d0d1..e832babc9d 100644 --- a/hw/pci-host/meson.build +++ b/hw/pci-host/meson.build @@ -35,5 +35,6 @@ specific_ss.add(when: 'CONFIG_PCI_POWERNV', if_true: files( 'pnv_phb3_msi.c', 'pnv_phb3_pbcq.c', 'pnv_phb4.c', - 'pnv_phb4_pec.c' + 'pnv_phb4_pec.c', + 'pnv_phb.c', )) diff --git a/hw/pci-host/pnv_phb.c b/hw/pci-host/pnv_phb.c new file mode 100644 index 0000000000..7b11f1e8dd --- /dev/null +++ b/hw/pci-host/pnv_phb.c @@ -0,0 +1,337 @@ +/* + * QEMU PowerPC PowerNV Proxy PHB model + * + * Copyright (c) 2022, IBM Corporation. + * + * This code is licensed under the GPL version 2 or later. See the + * COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qapi/visitor.h" +#include "qapi/error.h" +#include "hw/pci-host/pnv_phb.h" +#include "hw/pci-host/pnv_phb3.h" +#include "hw/pci-host/pnv_phb4.h" +#include "hw/ppc/pnv.h" +#include "hw/qdev-properties.h" +#include "qom/object.h" +#include "sysemu/sysemu.h" + + +/* + * Set the QOM parent and parent bus of an object child. If the device + * state associated with the child has an id, use it as QOM id. + * Otherwise use object_typename[index] as QOM id. + * + * This helper does both operations at the same time because seting + * a new QOM child will erase the bus parent of the device. This happens + * because object_unparent() will call object_property_del_child(), + * which in turn calls the property release callback prop->release if + * it's defined. In our case this callback is set to + * object_finalize_child_property(), which was assigned during the + * first object_property_add_child() call. This callback will end up + * calling device_unparent(), and this function removes the device + * from its parent bus. + * + * The QOM and parent bus to be set aren´t necessarily related, so + * let's receive both as arguments. + */ +static bool pnv_parent_fixup(Object *parent, BusState *parent_bus, + Object *child, int index, + Error **errp) +{ + g_autofree char *default_id = + g_strdup_printf("%s[%d]", object_get_typename(child), index); + const char *dev_id = DEVICE(child)->id; + + if (child->parent == parent) { + return true; + } + + object_ref(child); + object_unparent(child); + object_property_add_child(parent, dev_id ? dev_id : default_id, child); + object_unref(child); + + if (!qdev_set_parent_bus(DEVICE(child), parent_bus, errp)) { + return false; + } + + return true; +} + +/* + * User created devices won't have the initial setup that default + * devices have. This setup consists of assigning a parent device + * (chip for PHB3, PEC for PHB4/5) that will be the QOM/bus parent + * of the PHB. + */ +static bool pnv_phb_user_device_init(PnvPHB *phb, Error **errp) +{ + PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine()); + PnvChip *chip = pnv_get_chip(pnv, phb->chip_id); + Object *parent = NULL; + + if (!chip) { + error_setg(errp, "invalid chip id: %d", phb->chip_id); + return false; + } + + parent = pnv_chip_add_phb(chip, phb, errp); + if (!parent) { + return false; + } + + /* + * Reparent user created devices to the chip to build + * correctly the device tree. pnv_xscom_dt() needs every + * PHB to be a child of the chip to build the DT correctly. + */ + if (!pnv_parent_fixup(parent, qdev_get_parent_bus(DEVICE(chip)), + OBJECT(phb), phb->phb_id, errp)) { + return false; + } + + return true; +} + +static void pnv_phb_realize(DeviceState *dev, Error **errp) +{ + PnvPHB *phb = PNV_PHB(dev); + PCIHostState *pci = PCI_HOST_BRIDGE(dev); + g_autofree char *phb_typename = NULL; + + if (!phb->version) { + error_setg(errp, "version not specified"); + return; + } + + switch (phb->version) { + case 3: + phb_typename = g_strdup(TYPE_PNV_PHB3); + break; + case 4: + phb_typename = g_strdup(TYPE_PNV_PHB4); + break; + case 5: + phb_typename = g_strdup(TYPE_PNV_PHB5); + break; + default: + g_assert_not_reached(); + } + + phb->backend = object_new(phb_typename); + object_property_add_child(OBJECT(dev), "phb-backend", phb->backend); + + /* Passthrough child device properties to the proxy device */ + object_property_set_uint(phb->backend, "index", phb->phb_id, errp); + object_property_set_uint(phb->backend, "chip-id", phb->chip_id, errp); + object_property_set_link(phb->backend, "phb-base", OBJECT(phb), errp); + + /* + * Handle user created devices. User devices will not have a + * pointer to a chip (PHB3) and a PEC (PHB4/5). + */ + if (!phb->chip && !phb->pec) { + if (!pnv_phb_user_device_init(phb, errp)) { + return; + } + } + + if (phb->version == 3) { + object_property_set_link(phb->backend, "chip", + OBJECT(phb->chip), errp); + } else { + object_property_set_link(phb->backend, "pec", OBJECT(phb->pec), errp); + } + + if (!qdev_realize(DEVICE(phb->backend), NULL, errp)) { + return; + } + + if (phb->version == 3) { + pnv_phb3_bus_init(dev, PNV_PHB3(phb->backend)); + } else { + pnv_phb4_bus_init(dev, PNV_PHB4(phb->backend)); + } + + if (defaults_enabled()) { + PCIDevice *root = pci_new(PCI_DEVFN(0, 0), TYPE_PNV_PHB_ROOT_PORT); + + pci_realize_and_unref(root, pci->bus, errp); + } +} + +static const char *pnv_phb_root_bus_path(PCIHostState *host_bridge, + PCIBus *rootbus) +{ + PnvPHB *phb = PNV_PHB(host_bridge); + + snprintf(phb->bus_path, sizeof(phb->bus_path), "00%02x:%02x", + phb->chip_id, phb->phb_id); + return phb->bus_path; +} + +static Property pnv_phb_properties[] = { + DEFINE_PROP_UINT32("index", PnvPHB, phb_id, 0), + DEFINE_PROP_UINT32("chip-id", PnvPHB, chip_id, 0), + DEFINE_PROP_UINT32("version", PnvPHB, version, 0), + + DEFINE_PROP_LINK("chip", PnvPHB, chip, TYPE_PNV_CHIP, PnvChip *), + + DEFINE_PROP_LINK("pec", PnvPHB, pec, TYPE_PNV_PHB4_PEC, + PnvPhb4PecState *), + + DEFINE_PROP_END_OF_LIST(), +}; + +static void pnv_phb_class_init(ObjectClass *klass, void *data) +{ + PCIHostBridgeClass *hc = PCI_HOST_BRIDGE_CLASS(klass); + DeviceClass *dc = DEVICE_CLASS(klass); + + hc->root_bus_path = pnv_phb_root_bus_path; + dc->realize = pnv_phb_realize; + device_class_set_props(dc, pnv_phb_properties); + set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); + dc->user_creatable = true; +} + +static void pnv_phb_root_port_reset(DeviceState *dev) +{ + PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(dev); + PnvPHBRootPort *phb_rp = PNV_PHB_ROOT_PORT(dev); + PCIDevice *d = PCI_DEVICE(dev); + uint8_t *conf = d->config; + + rpc->parent_reset(dev); + + if (phb_rp->version == 3) { + return; + } + + /* PHB4 and later requires these extra reset steps */ + pci_byte_test_and_set_mask(conf + PCI_IO_BASE, + PCI_IO_RANGE_MASK & 0xff); + pci_byte_test_and_clear_mask(conf + PCI_IO_LIMIT, + PCI_IO_RANGE_MASK & 0xff); + pci_set_word(conf + PCI_MEMORY_BASE, 0); + pci_set_word(conf + PCI_MEMORY_LIMIT, 0xfff0); + pci_set_word(conf + PCI_PREF_MEMORY_BASE, 0x1); + pci_set_word(conf + PCI_PREF_MEMORY_LIMIT, 0xfff1); + pci_set_long(conf + PCI_PREF_BASE_UPPER32, 0x1); /* Hack */ + pci_set_long(conf + PCI_PREF_LIMIT_UPPER32, 0xffffffff); + pci_config_set_interrupt_pin(conf, 0); +} + +static void pnv_phb_root_port_realize(DeviceState *dev, Error **errp) +{ + PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(dev); + PnvPHBRootPort *phb_rp = PNV_PHB_ROOT_PORT(dev); + PCIBus *bus = PCI_BUS(qdev_get_parent_bus(dev)); + PCIDevice *pci = PCI_DEVICE(dev); + uint16_t device_id = 0; + Error *local_err = NULL; + int chip_id, index; + + /* + * 'index' will be used both as a PCIE slot value and to calculate + * QOM id. 'chip_id' is going to be used as PCIE chassis for the + * root port. + */ + chip_id = object_property_get_int(OBJECT(bus), "chip-id", &error_fatal); + index = object_property_get_int(OBJECT(bus), "phb-id", &error_fatal); + + /* Set unique chassis/slot values for the root port */ + qdev_prop_set_uint8(dev, "chassis", chip_id); + qdev_prop_set_uint16(dev, "slot", index); + + /* + * User created root ports are QOM parented to one of + * the peripheral containers but it's already at the right + * parent bus. Change the QOM parent to be the same as the + * parent bus it's already assigned to. + */ + if (!pnv_parent_fixup(OBJECT(bus), BUS(bus), OBJECT(dev), + index, errp)) { + return; + } + + rpc->parent_realize(dev, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + + switch (phb_rp->version) { + case 3: + device_id = PNV_PHB3_DEVICE_ID; + break; + case 4: + device_id = PNV_PHB4_DEVICE_ID; + break; + case 5: + device_id = PNV_PHB5_DEVICE_ID; + break; + default: + g_assert_not_reached(); + } + + pci_config_set_device_id(pci->config, device_id); + pci_config_set_interrupt_pin(pci->config, 0); +} + +static Property pnv_phb_root_port_properties[] = { + DEFINE_PROP_UINT32("version", PnvPHBRootPort, version, 0), + + DEFINE_PROP_END_OF_LIST(), +}; + +static void pnv_phb_root_port_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); + PCIERootPortClass *rpc = PCIE_ROOT_PORT_CLASS(klass); + + dc->desc = "IBM PHB PCIE Root Port"; + + device_class_set_props(dc, pnv_phb_root_port_properties); + device_class_set_parent_realize(dc, pnv_phb_root_port_realize, + &rpc->parent_realize); + device_class_set_parent_reset(dc, pnv_phb_root_port_reset, + &rpc->parent_reset); + dc->reset = &pnv_phb_root_port_reset; + dc->user_creatable = true; + + k->vendor_id = PCI_VENDOR_ID_IBM; + /* device_id will be written during realize() */ + k->device_id = 0; + k->revision = 0; + + rpc->exp_offset = 0x48; + rpc->aer_offset = 0x100; +} + +static const TypeInfo pnv_phb_type_info = { + .name = TYPE_PNV_PHB, + .parent = TYPE_PCIE_HOST_BRIDGE, + .instance_size = sizeof(PnvPHB), + .class_init = pnv_phb_class_init, +}; + +static const TypeInfo pnv_phb_root_port_info = { + .name = TYPE_PNV_PHB_ROOT_PORT, + .parent = TYPE_PCIE_ROOT_PORT, + .instance_size = sizeof(PnvPHBRootPort), + .class_init = pnv_phb_root_port_class_init, +}; + +static void pnv_phb_register_types(void) +{ + type_register_static(&pnv_phb_type_info); + type_register_static(&pnv_phb_root_port_info); +} + +type_init(pnv_phb_register_types) diff --git a/hw/pci-host/pnv_phb.h b/hw/pci-host/pnv_phb.h new file mode 100644 index 0000000000..58ebd6dd0f --- /dev/null +++ b/hw/pci-host/pnv_phb.h @@ -0,0 +1,55 @@ +/* + * QEMU PowerPC PowerNV Proxy PHB model + * + * Copyright (c) 2022, IBM Corporation. + * + * This code is licensed under the GPL version 2 or later. See the + * COPYING file in the top-level directory. + */ + +#ifndef PCI_HOST_PNV_PHB_H +#define PCI_HOST_PNV_PHB_H + +#include "hw/pci/pcie_host.h" +#include "hw/pci/pcie_port.h" +#include "qom/object.h" + +typedef struct PnvChip PnvChip; +typedef struct PnvPhb4PecState PnvPhb4PecState; + +struct PnvPHB { + PCIExpressHost parent_obj; + + uint32_t chip_id; + uint32_t phb_id; + uint32_t version; + char bus_path[8]; + + PnvChip *chip; + + PnvPhb4PecState *pec; + + /* The PHB backend (PnvPHB3, PnvPHB4 ...) being used */ + Object *backend; +}; + +#define TYPE_PNV_PHB "pnv-phb" +OBJECT_DECLARE_SIMPLE_TYPE(PnvPHB, PNV_PHB) + +/* + * PHB PCIe Root port + */ +#define PNV_PHB3_DEVICE_ID 0x03dc +#define PNV_PHB4_DEVICE_ID 0x04c1 +#define PNV_PHB5_DEVICE_ID 0x0652 + +typedef struct PnvPHBRootPort { + PCIESlot parent_obj; + + uint32_t version; +} PnvPHBRootPort; + +#define TYPE_PNV_PHB_ROOT_PORT "pnv-phb-root-port" +OBJECT_DECLARE_SIMPLE_TYPE(PnvPHBRootPort, PNV_PHB_ROOT_PORT) + +#endif /* PCI_HOST_PNV_PHB_H */ diff --git a/hw/pci-host/pnv_phb3.c b/hw/pci-host/pnv_phb3.c index d58d3c1701..af8575c007 100644 --- a/hw/pci-host/pnv_phb3.c +++ b/hw/pci-host/pnv_phb3.c @@ -11,6 +11,7 @@ #include "qapi/visitor.h" #include "qapi/error.h" #include "hw/pci-host/pnv_phb3_regs.h" +#include "hw/pci-host/pnv_phb.h" #include "hw/pci-host/pnv_phb3.h" #include "hw/pci/pcie_host.h" #include "hw/pci/pcie_port.h" @@ -26,7 +27,7 @@ static PCIDevice *pnv_phb3_find_cfg_dev(PnvPHB3 *phb) { - PCIHostState *pci = PCI_HOST_BRIDGE(phb); + PCIHostState *pci = PCI_HOST_BRIDGE(phb->phb_base); uint64_t addr = phb->regs[PHB_CONFIG_ADDRESS >> 3]; uint8_t bus, devfn; @@ -590,7 +591,7 @@ void pnv_phb3_reg_write(void *opaque, hwaddr off, uint64_t val, unsigned size) uint64_t pnv_phb3_reg_read(void *opaque, hwaddr off, unsigned size) { PnvPHB3 *phb = opaque; - PCIHostState *pci = PCI_HOST_BRIDGE(phb); + PCIHostState *pci = PCI_HOST_BRIDGE(phb->phb_base); uint64_t val; if ((off & 0xfffc) == PHB_CONFIG_DATA) { @@ -986,10 +987,36 @@ static void pnv_phb3_instance_init(Object *obj) } +void pnv_phb3_bus_init(DeviceState *dev, PnvPHB3 *phb) +{ + PCIHostState *pci = PCI_HOST_BRIDGE(dev); + + /* + * PHB3 doesn't support IO space. However, qemu gets very upset if + * we don't have an IO region to anchor IO BARs onto so we just + * initialize one which we never hook up to anything + */ + memory_region_init(&phb->pci_io, OBJECT(phb), "pci-io", 0x10000); + memory_region_init(&phb->pci_mmio, OBJECT(phb), "pci-mmio", + PCI_MMIO_TOTAL_SIZE); + + pci->bus = pci_register_root_bus(dev, + dev->id ? dev->id : NULL, + pnv_phb3_set_irq, pnv_phb3_map_irq, phb, + &phb->pci_mmio, &phb->pci_io, + 0, 4, TYPE_PNV_PHB3_ROOT_BUS); + + object_property_set_int(OBJECT(pci->bus), "phb-id", phb->phb_id, + &error_abort); + object_property_set_int(OBJECT(pci->bus), "chip-id", phb->chip_id, + &error_abort); + + pci_setup_iommu(pci->bus, pnv_phb3_dma_iommu, phb); +} + static void pnv_phb3_realize(DeviceState *dev, Error **errp) { PnvPHB3 *phb = PNV_PHB3(dev); - PCIHostState *pci = PCI_HOST_BRIDGE(dev); PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine()); int i; @@ -1034,26 +1061,6 @@ static void pnv_phb3_realize(DeviceState *dev, Error **errp) /* Controller Registers */ memory_region_init_io(&phb->mr_regs, OBJECT(phb), &pnv_phb3_reg_ops, phb, "phb3-regs", 0x1000); - - /* - * PHB3 doesn't support IO space. However, qemu gets very upset if - * we don't have an IO region to anchor IO BARs onto so we just - * initialize one which we never hook up to anything - */ - memory_region_init(&phb->pci_io, OBJECT(phb), "pci-io", 0x10000); - memory_region_init(&phb->pci_mmio, OBJECT(phb), "pci-mmio", - PCI_MMIO_TOTAL_SIZE); - - pci->bus = pci_register_root_bus(dev, - dev->id ? dev->id : NULL, - pnv_phb3_set_irq, pnv_phb3_map_irq, phb, - &phb->pci_mmio, &phb->pci_io, - 0, 4, TYPE_PNV_PHB3_ROOT_BUS); - - pci_setup_iommu(pci->bus, pnv_phb3_dma_iommu, phb); - - pnv_phb_attach_root_port(pci, TYPE_PNV_PHB3_ROOT_PORT, - phb->phb_id, phb->chip_id); } void pnv_phb3_update_regions(PnvPHB3 *phb) @@ -1078,105 +1085,96 @@ void pnv_phb3_update_regions(PnvPHB3 *phb) pnv_phb3_check_all_m64s(phb); } -static const char *pnv_phb3_root_bus_path(PCIHostState *host_bridge, - PCIBus *rootbus) -{ - PnvPHB3 *phb = PNV_PHB3(host_bridge); - - snprintf(phb->bus_path, sizeof(phb->bus_path), "00%02x:%02x", - phb->chip_id, phb->phb_id); - return phb->bus_path; -} - static Property pnv_phb3_properties[] = { DEFINE_PROP_UINT32("index", PnvPHB3, phb_id, 0), DEFINE_PROP_UINT32("chip-id", PnvPHB3, chip_id, 0), DEFINE_PROP_LINK("chip", PnvPHB3, chip, TYPE_PNV_CHIP, PnvChip *), + DEFINE_PROP_LINK("phb-base", PnvPHB3, phb_base, TYPE_PNV_PHB, PnvPHB *), DEFINE_PROP_END_OF_LIST(), }; static void pnv_phb3_class_init(ObjectClass *klass, void *data) { - PCIHostBridgeClass *hc = PCI_HOST_BRIDGE_CLASS(klass); DeviceClass *dc = DEVICE_CLASS(klass); - hc->root_bus_path = pnv_phb3_root_bus_path; dc->realize = pnv_phb3_realize; device_class_set_props(dc, pnv_phb3_properties); - set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); dc->user_creatable = false; } static const TypeInfo pnv_phb3_type_info = { .name = TYPE_PNV_PHB3, - .parent = TYPE_PCIE_HOST_BRIDGE, + .parent = TYPE_DEVICE, .instance_size = sizeof(PnvPHB3), .class_init = pnv_phb3_class_init, .instance_init = pnv_phb3_instance_init, }; -static void pnv_phb3_root_bus_class_init(ObjectClass *klass, void *data) +static void pnv_phb3_root_bus_get_prop(Object *obj, Visitor *v, + const char *name, + void *opaque, Error **errp) { - BusClass *k = BUS_CLASS(klass); + PnvPHB3RootBus *bus = PNV_PHB3_ROOT_BUS(obj); + uint64_t value = 0; - /* - * PHB3 has only a single root complex. Enforce the limit on the - * parent bus - */ - k->max_dev = 1; + if (strcmp(name, "phb-id") == 0) { + value = bus->phb_id; + } else { + value = bus->chip_id; + } + + visit_type_size(v, name, &value, errp); } -static const TypeInfo pnv_phb3_root_bus_info = { - .name = TYPE_PNV_PHB3_ROOT_BUS, - .parent = TYPE_PCIE_BUS, - .class_init = pnv_phb3_root_bus_class_init, -}; +static void pnv_phb3_root_bus_set_prop(Object *obj, Visitor *v, + const char *name, + void *opaque, Error **errp) -static void pnv_phb3_root_port_realize(DeviceState *dev, Error **errp) { - PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(dev); - PCIDevice *pci = PCI_DEVICE(dev); - Error *local_err = NULL; + PnvPHB3RootBus *bus = PNV_PHB3_ROOT_BUS(obj); + uint64_t value; - rpc->parent_realize(dev, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!visit_type_size(v, name, &value, errp)) { return; } - pci_config_set_interrupt_pin(pci->config, 0); + + if (strcmp(name, "phb-id") == 0) { + bus->phb_id = value; + } else { + bus->chip_id = value; + } } -static void pnv_phb3_root_port_class_init(ObjectClass *klass, void *data) +static void pnv_phb3_root_bus_class_init(ObjectClass *klass, void *data) { - DeviceClass *dc = DEVICE_CLASS(klass); - PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - PCIERootPortClass *rpc = PCIE_ROOT_PORT_CLASS(klass); - - dc->desc = "IBM PHB3 PCIE Root Port"; + BusClass *k = BUS_CLASS(klass); - device_class_set_parent_realize(dc, pnv_phb3_root_port_realize, - &rpc->parent_realize); - dc->user_creatable = false; + object_class_property_add(klass, "phb-id", "int", + pnv_phb3_root_bus_get_prop, + pnv_phb3_root_bus_set_prop, + NULL, NULL); - k->vendor_id = PCI_VENDOR_ID_IBM; - k->device_id = 0x03dc; - k->revision = 0; + object_class_property_add(klass, "chip-id", "int", + pnv_phb3_root_bus_get_prop, + pnv_phb3_root_bus_set_prop, + NULL, NULL); - rpc->exp_offset = 0x48; - rpc->aer_offset = 0x100; + /* + * PHB3 has only a single root complex. Enforce the limit on the + * parent bus + */ + k->max_dev = 1; } -static const TypeInfo pnv_phb3_root_port_info = { - .name = TYPE_PNV_PHB3_ROOT_PORT, - .parent = TYPE_PCIE_ROOT_PORT, - .instance_size = sizeof(PnvPHB3RootPort), - .class_init = pnv_phb3_root_port_class_init, +static const TypeInfo pnv_phb3_root_bus_info = { + .name = TYPE_PNV_PHB3_ROOT_BUS, + .parent = TYPE_PCIE_BUS, + .class_init = pnv_phb3_root_bus_class_init, }; static void pnv_phb3_register_types(void) { type_register_static(&pnv_phb3_root_bus_info); - type_register_static(&pnv_phb3_root_port_info); type_register_static(&pnv_phb3_type_info); type_register_static(&pnv_phb3_iommu_memory_region_info); } diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c index 67ddde4a6e..824e1a73fb 100644 --- a/hw/pci-host/pnv_phb4.c +++ b/hw/pci-host/pnv_phb4.c @@ -33,7 +33,7 @@ static PCIDevice *pnv_phb4_find_cfg_dev(PnvPHB4 *phb) { - PCIHostState *pci = PCI_HOST_BRIDGE(phb); + PCIHostState *pci = PCI_HOST_BRIDGE(phb->phb_base); uint64_t addr = phb->regs[PHB_CONFIG_ADDRESS >> 3]; uint8_t bus, devfn; @@ -129,7 +129,7 @@ static uint64_t pnv_phb4_config_read(PnvPHB4 *phb, unsigned off, static void pnv_phb4_rc_config_write(PnvPHB4 *phb, unsigned off, unsigned size, uint64_t val) { - PCIHostState *pci = PCI_HOST_BRIDGE(phb); + PCIHostState *pci = PCI_HOST_BRIDGE(phb->phb_base); PCIDevice *pdev; if (size != 4) { @@ -150,7 +150,7 @@ static void pnv_phb4_rc_config_write(PnvPHB4 *phb, unsigned off, static uint64_t pnv_phb4_rc_config_read(PnvPHB4 *phb, unsigned off, unsigned size) { - PCIHostState *pci = PCI_HOST_BRIDGE(phb); + PCIHostState *pci = PCI_HOST_BRIDGE(phb->phb_base); PCIDevice *pdev; uint64_t val; @@ -1528,30 +1528,16 @@ static void pnv_phb4_instance_init(Object *obj) object_initialize_child(obj, "source", &phb->xsrc, TYPE_XIVE_SOURCE); } -static void pnv_phb4_realize(DeviceState *dev, Error **errp) +void pnv_phb4_bus_init(DeviceState *dev, PnvPHB4 *phb) { - PnvPHB4 *phb = PNV_PHB4(dev); - PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(phb->pec); PCIHostState *pci = PCI_HOST_BRIDGE(dev); - XiveSource *xsrc = &phb->xsrc; - int nr_irqs; char name[32]; - /* Set the "big_phb" flag */ - phb->big_phb = phb->phb_id == 0 || phb->phb_id == 3; - - /* Controller Registers */ - snprintf(name, sizeof(name), "phb4-%d.%d-regs", phb->chip_id, - phb->phb_id); - memory_region_init_io(&phb->mr_regs, OBJECT(phb), &pnv_phb4_reg_ops, phb, - name, 0x2000); - /* * PHB4 doesn't support IO space. However, qemu gets very upset if * we don't have an IO region to anchor IO BARs onto so we just * initialize one which we never hook up to anything */ - snprintf(name, sizeof(name), "phb4-%d.%d-pci-io", phb->chip_id, phb->phb_id); memory_region_init(&phb->pci_io, OBJECT(phb), name, 0x10000); @@ -1561,16 +1547,35 @@ static void pnv_phb4_realize(DeviceState *dev, Error **errp) memory_region_init(&phb->pci_mmio, OBJECT(phb), name, PCI_MMIO_TOTAL_SIZE); - pci->bus = pci_register_root_bus(dev, dev->id, + pci->bus = pci_register_root_bus(dev, dev->id ? dev->id : NULL, pnv_phb4_set_irq, pnv_phb4_map_irq, phb, &phb->pci_mmio, &phb->pci_io, 0, 4, TYPE_PNV_PHB4_ROOT_BUS); + + object_property_set_int(OBJECT(pci->bus), "phb-id", phb->phb_id, + &error_abort); + object_property_set_int(OBJECT(pci->bus), "chip-id", phb->chip_id, + &error_abort); + pci_setup_iommu(pci->bus, pnv_phb4_dma_iommu, phb); pci->bus->flags |= PCI_BUS_EXTENDED_CONFIG_SPACE; +} + +static void pnv_phb4_realize(DeviceState *dev, Error **errp) +{ + PnvPHB4 *phb = PNV_PHB4(dev); + XiveSource *xsrc = &phb->xsrc; + int nr_irqs; + char name[32]; + + /* Set the "big_phb" flag */ + phb->big_phb = phb->phb_id == 0 || phb->phb_id == 3; - /* Add a single Root port if running with defaults */ - pnv_phb_attach_root_port(pci, pecc->rp_model, - phb->phb_id, phb->chip_id); + /* Controller Registers */ + snprintf(name, sizeof(name), "phb4-%d.%d-regs", phb->chip_id, + phb->phb_id); + memory_region_init_io(&phb->mr_regs, OBJECT(phb), &pnv_phb4_reg_ops, phb, + name, 0x2000); /* Setup XIVE Source */ if (phb->big_phb) { @@ -1591,16 +1596,6 @@ static void pnv_phb4_realize(DeviceState *dev, Error **errp) pnv_phb4_xscom_realize(phb); } -static const char *pnv_phb4_root_bus_path(PCIHostState *host_bridge, - PCIBus *rootbus) -{ - PnvPHB4 *phb = PNV_PHB4(host_bridge); - - snprintf(phb->bus_path, sizeof(phb->bus_path), "00%02x:%02x", - phb->chip_id, phb->phb_id); - return phb->bus_path; -} - /* * Address base trigger mode (POWER10) * @@ -1685,19 +1680,17 @@ static Property pnv_phb4_properties[] = { DEFINE_PROP_UINT32("chip-id", PnvPHB4, chip_id, 0), DEFINE_PROP_LINK("pec", PnvPHB4, pec, TYPE_PNV_PHB4_PEC, PnvPhb4PecState *), + DEFINE_PROP_LINK("phb-base", PnvPHB4, phb_base, TYPE_PNV_PHB, PnvPHB *), DEFINE_PROP_END_OF_LIST(), }; static void pnv_phb4_class_init(ObjectClass *klass, void *data) { - PCIHostBridgeClass *hc = PCI_HOST_BRIDGE_CLASS(klass); DeviceClass *dc = DEVICE_CLASS(klass); XiveNotifierClass *xfc = XIVE_NOTIFIER_CLASS(klass); - hc->root_bus_path = pnv_phb4_root_bus_path; dc->realize = pnv_phb4_realize; device_class_set_props(dc, pnv_phb4_properties); - set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); dc->user_creatable = false; xfc->notify = pnv_phb4_xive_notify; @@ -1705,7 +1698,7 @@ static void pnv_phb4_class_init(ObjectClass *klass, void *data) static const TypeInfo pnv_phb4_type_info = { .name = TYPE_PNV_PHB4, - .parent = TYPE_PCIE_HOST_BRIDGE, + .parent = TYPE_DEVICE, .instance_init = pnv_phb4_instance_init, .instance_size = sizeof(PnvPHB4), .class_init = pnv_phb4_class_init, @@ -1721,111 +1714,71 @@ static const TypeInfo pnv_phb5_type_info = { .instance_size = sizeof(PnvPHB4), }; -static void pnv_phb4_root_bus_class_init(ObjectClass *klass, void *data) +static void pnv_phb4_root_bus_get_prop(Object *obj, Visitor *v, + const char *name, + void *opaque, Error **errp) { - BusClass *k = BUS_CLASS(klass); + PnvPHB4RootBus *bus = PNV_PHB4_ROOT_BUS(obj); + uint64_t value = 0; - /* - * PHB4 has only a single root complex. Enforce the limit on the - * parent bus - */ - k->max_dev = 1; -} - -static const TypeInfo pnv_phb4_root_bus_info = { - .name = TYPE_PNV_PHB4_ROOT_BUS, - .parent = TYPE_PCIE_BUS, - .class_init = pnv_phb4_root_bus_class_init, -}; + if (strcmp(name, "phb-id") == 0) { + value = bus->phb_id; + } else { + value = bus->chip_id; + } -static void pnv_phb4_root_port_reset(DeviceState *dev) -{ - PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(dev); - PCIDevice *d = PCI_DEVICE(dev); - uint8_t *conf = d->config; - - rpc->parent_reset(dev); - - pci_byte_test_and_set_mask(conf + PCI_IO_BASE, - PCI_IO_RANGE_MASK & 0xff); - pci_byte_test_and_clear_mask(conf + PCI_IO_LIMIT, - PCI_IO_RANGE_MASK & 0xff); - pci_set_word(conf + PCI_MEMORY_BASE, 0); - pci_set_word(conf + PCI_MEMORY_LIMIT, 0xfff0); - pci_set_word(conf + PCI_PREF_MEMORY_BASE, 0x1); - pci_set_word(conf + PCI_PREF_MEMORY_LIMIT, 0xfff1); - pci_set_long(conf + PCI_PREF_BASE_UPPER32, 0x1); /* Hack */ - pci_set_long(conf + PCI_PREF_LIMIT_UPPER32, 0xffffffff); - pci_config_set_interrupt_pin(conf, 0); + visit_type_size(v, name, &value, errp); } -static void pnv_phb4_root_port_realize(DeviceState *dev, Error **errp) +static void pnv_phb4_root_bus_set_prop(Object *obj, Visitor *v, + const char *name, + void *opaque, Error **errp) + { - PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(dev); - Error *local_err = NULL; + PnvPHB4RootBus *bus = PNV_PHB4_ROOT_BUS(obj); + uint64_t value; - rpc->parent_realize(dev, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (!visit_type_size(v, name, &value, errp)) { return; } -} - -static void pnv_phb4_root_port_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - PCIERootPortClass *rpc = PCIE_ROOT_PORT_CLASS(klass); - - dc->desc = "IBM PHB4 PCIE Root Port"; - dc->user_creatable = false; - - device_class_set_parent_realize(dc, pnv_phb4_root_port_realize, - &rpc->parent_realize); - device_class_set_parent_reset(dc, pnv_phb4_root_port_reset, - &rpc->parent_reset); - k->vendor_id = PCI_VENDOR_ID_IBM; - k->device_id = PNV_PHB4_DEVICE_ID; - k->revision = 0; - - rpc->exp_offset = 0x48; - rpc->aer_offset = 0x100; - - dc->reset = &pnv_phb4_root_port_reset; + if (strcmp(name, "phb-id") == 0) { + bus->phb_id = value; + } else { + bus->chip_id = value; + } } -static const TypeInfo pnv_phb4_root_port_info = { - .name = TYPE_PNV_PHB4_ROOT_PORT, - .parent = TYPE_PCIE_ROOT_PORT, - .instance_size = sizeof(PnvPHB4RootPort), - .class_init = pnv_phb4_root_port_class_init, -}; - -static void pnv_phb5_root_port_class_init(ObjectClass *klass, void *data) +static void pnv_phb4_root_bus_class_init(ObjectClass *klass, void *data) { - DeviceClass *dc = DEVICE_CLASS(klass); - PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); + BusClass *k = BUS_CLASS(klass); + + object_class_property_add(klass, "phb-id", "int", + pnv_phb4_root_bus_get_prop, + pnv_phb4_root_bus_set_prop, + NULL, NULL); - dc->desc = "IBM PHB5 PCIE Root Port"; - dc->user_creatable = false; + object_class_property_add(klass, "chip-id", "int", + pnv_phb4_root_bus_get_prop, + pnv_phb4_root_bus_set_prop, + NULL, NULL); - k->vendor_id = PCI_VENDOR_ID_IBM; - k->device_id = PNV_PHB5_DEVICE_ID; + /* + * PHB4 has only a single root complex. Enforce the limit on the + * parent bus + */ + k->max_dev = 1; } -static const TypeInfo pnv_phb5_root_port_info = { - .name = TYPE_PNV_PHB5_ROOT_PORT, - .parent = TYPE_PNV_PHB4_ROOT_PORT, - .instance_size = sizeof(PnvPHB4RootPort), - .class_init = pnv_phb5_root_port_class_init, +static const TypeInfo pnv_phb4_root_bus_info = { + .name = TYPE_PNV_PHB4_ROOT_BUS, + .parent = TYPE_PCIE_BUS, + .class_init = pnv_phb4_root_bus_class_init, }; static void pnv_phb4_register_types(void) { type_register_static(&pnv_phb4_root_bus_info); - type_register_static(&pnv_phb5_root_port_info); - type_register_static(&pnv_phb4_root_port_info); type_register_static(&pnv_phb4_type_info); type_register_static(&pnv_phb5_type_info); type_register_static(&pnv_phb4_iommu_memory_region_info); diff --git a/hw/pci-host/pnv_phb4_pec.c b/hw/pci-host/pnv_phb4_pec.c index c9aaf1c28e..9871f462cd 100644 --- a/hw/pci-host/pnv_phb4_pec.c +++ b/hw/pci-host/pnv_phb4_pec.c @@ -115,8 +115,7 @@ static void pnv_pec_default_phb_realize(PnvPhb4PecState *pec, int stack_no, Error **errp) { - PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec); - PnvPHB4 *phb = PNV_PHB4(qdev_new(pecc->phb_type)); + PnvPHB *phb = PNV_PHB(qdev_new(TYPE_PNV_PHB)); int phb_id = pnv_phb4_pec_get_phb_id(pec, stack_no); object_property_add_child(OBJECT(pec), "phb[*]", OBJECT(phb)); @@ -147,8 +146,10 @@ static void pnv_pec_realize(DeviceState *dev, Error **errp) pec->num_phbs = pecc->num_phbs[pec->index]; /* Create PHBs if running with defaults */ - for (i = 0; i < pec->num_phbs; i++) { - pnv_pec_default_phb_realize(pec, i, errp); + if (defaults_enabled()) { + for (i = 0; i < pec->num_phbs; i++) { + pnv_pec_default_phb_realize(pec, i, errp); + } } /* Initialize the XSCOM regions for the PEC registers */ @@ -261,7 +262,6 @@ static void pnv_pec_class_init(ObjectClass *klass, void *data) pecc->version = PNV_PHB4_VERSION; pecc->phb_type = TYPE_PNV_PHB4; pecc->num_phbs = pnv_pec_num_phbs; - pecc->rp_model = TYPE_PNV_PHB4_ROOT_PORT; } static const TypeInfo pnv_pec_type_info = { @@ -314,7 +314,6 @@ static void pnv_phb5_pec_class_init(ObjectClass *klass, void *data) pecc->version = PNV_PHB5_VERSION; pecc->phb_type = TYPE_PNV_PHB5; pecc->num_phbs = pnv_phb5_pec_num_stacks; - pecc->rp_model = TYPE_PNV_PHB5_ROOT_PORT; } static const TypeInfo pnv_phb5_pec_type_info = { diff --git a/hw/ppc/Kconfig b/hw/ppc/Kconfig index 400511c6b7..3a4418a69e 100644 --- a/hw/ppc/Kconfig +++ b/hw/ppc/Kconfig @@ -58,7 +58,6 @@ config PPC4XX config SAM460EX bool - select PPC405 select PFLASH_CFI01 select IDE_SII3112 select M41T80 @@ -72,6 +71,7 @@ config SAM460EX config PEGASOS2 bool + imply ATI_VGA select MV64361 select VT82C686 select IDE_VIA @@ -79,7 +79,6 @@ config PEGASOS2 select VOF # This should come with VT82C686 select ACPI_X86 - imply ATI_VGA config PREP bool diff --git a/hw/ppc/meson.build b/hw/ppc/meson.build index aa4c8e6a2e..62801923f3 100644 --- a/hw/ppc/meson.build +++ b/hw/ppc/meson.build @@ -46,6 +46,7 @@ ppc_ss.add(when: 'CONFIG_POWERNV', if_true: files( 'pnv_lpc.c', 'pnv_psi.c', 'pnv_occ.c', + 'pnv_sbe.c', 'pnv_bmc.c', 'pnv_homer.c', 'pnv_pnor.c', diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index d3f77c8367..354aa289d1 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -43,6 +43,7 @@ #include "hw/ipmi/ipmi.h" #include "target/ppc/mmu-hash64.h" #include "hw/pci/msi.h" +#include "hw/pci-host/pnv_phb.h" #include "hw/ppc/xics.h" #include "hw/qdev-properties.h" @@ -280,6 +281,75 @@ static void pnv_dt_icp(PnvChip *chip, void *fdt, uint32_t pir, g_free(reg); } +static PnvPhb4PecState *pnv_phb4_get_pec(PnvChip *chip, PnvPHB4 *phb, + Error **errp) +{ + PnvPHB *phb_base = phb->phb_base; + PnvPhb4PecState *pecs = NULL; + int chip_id = phb->chip_id; + int index = phb->phb_id; + int i, j; + + if (phb_base->version == 4) { + Pnv9Chip *chip9 = PNV9_CHIP(chip); + + pecs = chip9->pecs; + } else if (phb_base->version == 5) { + Pnv10Chip *chip10 = PNV10_CHIP(chip); + + pecs = chip10->pecs; + } else { + g_assert_not_reached(); + } + + for (i = 0; i < chip->num_pecs; i++) { + /* + * For each PEC, check the amount of phbs it supports + * and see if the given phb4 index matches an index. + */ + PnvPhb4PecState *pec = &pecs[i]; + + for (j = 0; j < pec->num_phbs; j++) { + if (index == pnv_phb4_pec_get_phb_id(pec, j)) { + return pec; + } + } + } + error_setg(errp, + "pnv-phb4 chip-id %d index %d didn't match any existing PEC", + chip_id, index); + + return NULL; +} + +/* + * Adds a PnvPHB to the chip. Returns the parent obj of the + * PHB which varies with each version (phb version 3 is parented + * by the chip, version 4 and 5 are parented by the PEC + * device). + * + * TODO: for version 3 we're still parenting the PHB with the + * chip. We should parent with a (so far not implemented) + * PHB3 PEC device. + */ +Object *pnv_chip_add_phb(PnvChip *chip, PnvPHB *phb, Error **errp) +{ + if (phb->version == 3) { + Pnv8Chip *chip8 = PNV8_CHIP(chip); + + phb->chip = chip; + + chip8->phbs[chip8->num_phbs] = phb; + chip8->num_phbs++; + + return OBJECT(chip); + } + + phb->pec = pnv_phb4_get_pec(chip, PNV_PHB4(phb->backend), errp); + + return OBJECT(phb->pec); +} + static void pnv_chip_power8_dt_populate(PnvChip *chip, void *fdt) { static const char compat[] = "ibm,power8-xscom\0ibm,xscom"; @@ -660,7 +730,8 @@ static void pnv_chip_power8_pic_print_info(PnvChip *chip, Monitor *mon) ics_pic_print_info(&chip8->psi.ics, mon); for (i = 0; i < chip8->num_phbs; i++) { - PnvPHB3 *phb3 = &chip8->phbs[i]; + PnvPHB *phb = chip8->phbs[i]; + PnvPHB3 *phb3 = PNV_PHB3(phb->backend); pnv_phb3_msi_pic_print_info(&phb3->msis, mon); ics_pic_print_info(&phb3->lsis, mon); @@ -670,11 +741,14 @@ static void pnv_chip_power8_pic_print_info(PnvChip *chip, Monitor *mon) static int pnv_chip_power9_pic_print_info_child(Object *child, void *opaque) { Monitor *mon = opaque; - PnvPHB4 *phb4 = (PnvPHB4 *) object_dynamic_cast(child, TYPE_PNV_PHB4); + PnvPHB *phb = (PnvPHB *) object_dynamic_cast(child, TYPE_PNV_PHB); - if (phb4) { - pnv_phb4_pic_print_info(phb4, mon); + if (!phb) { + return 0; } + + pnv_phb4_pic_print_info(PNV_PHB4(phb->backend), mon); + return 0; } @@ -714,7 +788,7 @@ static bool pnv_match_cpu(const char *default_type, const char *cpu_type) PowerPCCPUClass *ppc = POWERPC_CPU_CLASS(object_class_by_name(cpu_type)); - return ppc_default->pvr_match(ppc_default, ppc->pvr); + return ppc_default->pvr_match(ppc_default, ppc->pvr, false); } static void pnv_ipmi_bt_init(ISABus *bus, IPMIBmc *bmc, uint32_t irq) @@ -1146,10 +1220,22 @@ static void pnv_chip_power8_instance_init(Object *obj) object_initialize_child(obj, "homer", &chip8->homer, TYPE_PNV8_HOMER); - chip8->num_phbs = pcc->num_phbs; - - for (i = 0; i < chip8->num_phbs; i++) { - object_initialize_child(obj, "phb[*]", &chip8->phbs[i], TYPE_PNV_PHB3); + if (defaults_enabled()) { + chip8->num_phbs = pcc->num_phbs; + + for (i = 0; i < chip8->num_phbs; i++) { + Object *phb = object_new(TYPE_PNV_PHB); + + /* + * We need the chip to parent the PHB to allow the DT + * to build correctly (via pnv_xscom_dt()). + * + * TODO: the PHB should be parented by a PEC device that, at + * this moment, is not modelled powernv8/phb3. + */ + object_property_add_child(obj, "phb[*]", phb); + chip8->phbs[i] = PNV_PHB(phb); + } } } @@ -1183,30 +1269,6 @@ static void pnv_chip_icp_realize(Pnv8Chip *chip8, Error **errp) } } -/* - * Attach a root port device. - * - * 'index' will be used both as a PCIE slot value and to calculate - * QOM id. 'chip_id' is going to be used as PCIE chassis for the - * root port. - */ -void pnv_phb_attach_root_port(PCIHostState *pci, const char *name, - int index, int chip_id) -{ - PCIDevice *root = pci_new(PCI_DEVFN(0, 0), name); - g_autofree char *default_id = g_strdup_printf("%s[%d]", name, index); - const char *dev_id = DEVICE(root)->id; - - object_property_add_child(OBJECT(pci->bus), dev_id ? dev_id : default_id, - OBJECT(root)); - - /* Set unique chassis/slot values for the root port */ - qdev_prop_set_uint8(DEVICE(root), "chassis", chip_id); - qdev_prop_set_uint16(DEVICE(root), "slot", index); - - pci_realize_and_unref(root, pci->bus, &error_fatal); -} - static void pnv_chip_power8_realize(DeviceState *dev, Error **errp) { PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev); @@ -1287,9 +1349,9 @@ static void pnv_chip_power8_realize(DeviceState *dev, Error **errp) memory_region_add_subregion(get_system_memory(), PNV_HOMER_BASE(chip), &chip8->homer.regs); - /* PHB3 controllers */ + /* PHB controllers */ for (i = 0; i < chip8->num_phbs; i++) { - PnvPHB3 *phb = &chip8->phbs[i]; + PnvPHB *phb = chip8->phbs[i]; object_property_set_int(OBJECT(phb), "index", i, &error_fatal); object_property_set_int(OBJECT(phb), "chip-id", chip->chip_id, @@ -1397,6 +1459,8 @@ static void pnv_chip_power9_instance_init(Object *obj) object_initialize_child(obj, "occ", &chip9->occ, TYPE_PNV9_OCC); + object_initialize_child(obj, "sbe", &chip9->sbe, TYPE_PNV9_SBE); + object_initialize_child(obj, "homer", &chip9->homer, TYPE_PNV9_HOMER); /* Number of PECs is the chip default */ @@ -1549,6 +1613,17 @@ static void pnv_chip_power9_realize(DeviceState *dev, Error **errp) memory_region_add_subregion(get_system_memory(), PNV9_OCC_SENSOR_BASE(chip), &chip9->occ.sram_regs); + /* SBE */ + if (!qdev_realize(DEVICE(&chip9->sbe), NULL, errp)) { + return; + } + pnv_xscom_add_subregion(chip, PNV9_XSCOM_SBE_CTRL_BASE, + &chip9->sbe.xscom_ctrl_regs); + pnv_xscom_add_subregion(chip, PNV9_XSCOM_SBE_MBOX_BASE, + &chip9->sbe.xscom_mbox_regs); + qdev_connect_gpio_out(DEVICE(&chip9->sbe), 0, qdev_get_gpio_in( + DEVICE(&chip9->psi), PSIHB9_IRQ_PSU)); + /* HOMER */ object_property_set_link(OBJECT(&chip9->homer), "chip", OBJECT(chip), &error_abort); @@ -1613,6 +1688,7 @@ static void pnv_chip_power10_instance_init(Object *obj) object_initialize_child(obj, "psi", &chip10->psi, TYPE_PNV10_PSI); object_initialize_child(obj, "lpc", &chip10->lpc, TYPE_PNV10_LPC); object_initialize_child(obj, "occ", &chip10->occ, TYPE_PNV10_OCC); + object_initialize_child(obj, "sbe", &chip10->sbe, TYPE_PNV10_SBE); object_initialize_child(obj, "homer", &chip10->homer, TYPE_PNV10_HOMER); chip->num_pecs = pcc->num_pecs; @@ -1754,6 +1830,17 @@ static void pnv_chip_power10_realize(DeviceState *dev, Error **errp) PNV10_OCC_SENSOR_BASE(chip), &chip10->occ.sram_regs); + /* SBE */ + if (!qdev_realize(DEVICE(&chip10->sbe), NULL, errp)) { + return; + } + pnv_xscom_add_subregion(chip, PNV10_XSCOM_SBE_CTRL_BASE, + &chip10->sbe.xscom_ctrl_regs); + pnv_xscom_add_subregion(chip, PNV10_XSCOM_SBE_MBOX_BASE, + &chip10->sbe.xscom_mbox_regs); + qdev_connect_gpio_out(DEVICE(&chip10->sbe), 0, qdev_get_gpio_in( + DEVICE(&chip10->psi), PSIHB9_IRQ_PSU)); + /* HOMER */ object_property_set_link(OBJECT(&chip10->homer), "chip", OBJECT(chip), &error_abort); @@ -1957,7 +2044,8 @@ static ICSState *pnv_ics_get(XICSFabric *xi, int irq) } for (j = 0; j < chip8->num_phbs; j++) { - PnvPHB3 *phb3 = &chip8->phbs[j]; + PnvPHB *phb = chip8->phbs[j]; + PnvPHB3 *phb3 = PNV_PHB3(phb->backend); if (ics_valid_irq(&phb3->lsis, irq)) { return &phb3->lsis; @@ -1995,7 +2083,8 @@ static void pnv_ics_resend(XICSFabric *xi) ics_resend(&chip8->psi.ics); for (j = 0; j < chip8->num_phbs; j++) { - PnvPHB3 *phb3 = &chip8->phbs[j]; + PnvPHB *phb = chip8->phbs[j]; + PnvPHB3 *phb3 = PNV_PHB3(phb->backend); ics_resend(&phb3->lsis); ics_resend(ICS(&phb3->msis)); @@ -2095,8 +2184,14 @@ static void pnv_machine_power8_class_init(ObjectClass *oc, void *data) PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc); static const char compat[] = "qemu,powernv8\0qemu,powernv\0ibm,powernv"; + static GlobalProperty phb_compat[] = { + { TYPE_PNV_PHB, "version", "3" }, + { TYPE_PNV_PHB_ROOT_PORT, "version", "3" }, + }; + mc->desc = "IBM PowerNV (Non-Virtualized) POWER8"; mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0"); + compat_props_add(mc->compat_props, phb_compat, G_N_ELEMENTS(phb_compat)); xic->icp_get = pnv_icp_get; xic->ics_get = pnv_ics_get; @@ -2104,6 +2199,8 @@ static void pnv_machine_power8_class_init(ObjectClass *oc, void *data) pmc->compat = compat; pmc->compat_size = sizeof(compat); + + machine_class_allow_dynamic_sysbus_dev(mc, TYPE_PNV_PHB); } static void pnv_machine_power9_class_init(ObjectClass *oc, void *data) @@ -2113,8 +2210,15 @@ static void pnv_machine_power9_class_init(ObjectClass *oc, void *data) PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc); static const char compat[] = "qemu,powernv9\0ibm,powernv"; + static GlobalProperty phb_compat[] = { + { TYPE_PNV_PHB, "version", "4" }, + { TYPE_PNV_PHB_ROOT_PORT, "version", "4" }, + }; + mc->desc = "IBM PowerNV (Non-Virtualized) POWER9"; mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power9_v2.0"); + compat_props_add(mc->compat_props, phb_compat, G_N_ELEMENTS(phb_compat)); + xfc->match_nvt = pnv_match_nvt; mc->alias = "powernv"; @@ -2122,6 +2226,8 @@ static void pnv_machine_power9_class_init(ObjectClass *oc, void *data) pmc->compat = compat; pmc->compat_size = sizeof(compat); pmc->dt_power_mgt = pnv_dt_power_mgt; + + machine_class_allow_dynamic_sysbus_dev(mc, TYPE_PNV_PHB); } static void pnv_machine_power10_class_init(ObjectClass *oc, void *data) @@ -2131,14 +2237,22 @@ static void pnv_machine_power10_class_init(ObjectClass *oc, void *data) XiveFabricClass *xfc = XIVE_FABRIC_CLASS(oc); static const char compat[] = "qemu,powernv10\0ibm,powernv"; + static GlobalProperty phb_compat[] = { + { TYPE_PNV_PHB, "version", "5" }, + { TYPE_PNV_PHB_ROOT_PORT, "version", "5" }, + }; + mc->desc = "IBM PowerNV (Non-Virtualized) POWER10"; mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power10_v2.0"); + compat_props_add(mc->compat_props, phb_compat, G_N_ELEMENTS(phb_compat)); pmc->compat = compat; pmc->compat_size = sizeof(compat); pmc->dt_power_mgt = pnv_dt_power_mgt; xfc->match_nvt = pnv10_xive_match_nvt; + + machine_class_allow_dynamic_sysbus_dev(mc, TYPE_PNV_PHB); } static bool pnv_machine_get_hb(Object *obj, Error **errp) diff --git a/hw/ppc/pnv_sbe.c b/hw/ppc/pnv_sbe.c new file mode 100644 index 0000000000..1c7812a135 --- /dev/null +++ b/hw/ppc/pnv_sbe.c @@ -0,0 +1,414 @@ +/* + * QEMU PowerPC PowerNV Emulation of some SBE behaviour + * + * Copyright (c) 2022, IBM Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#include "qemu/osdep.h" +#include "target/ppc/cpu.h" +#include "qapi/error.h" +#include "qemu/log.h" +#include "qemu/module.h" +#include "hw/irq.h" +#include "hw/qdev-properties.h" +#include "hw/ppc/pnv.h" +#include "hw/ppc/pnv_xscom.h" +#include "hw/ppc/pnv_sbe.h" +#include "trace.h" + +/* + * Most register and command definitions come from skiboot. + * + * xscom addresses are adjusted to be relative to xscom subregion bases + */ + +/* + * SBE MBOX register address + * Reg 0 - 3 : Host to send command packets to SBE + * Reg 4 - 7 : SBE to send response packets to Host + */ +#define PSU_HOST_SBE_MBOX_REG0 0x00000000 +#define PSU_HOST_SBE_MBOX_REG1 0x00000001 +#define PSU_HOST_SBE_MBOX_REG2 0x00000002 +#define PSU_HOST_SBE_MBOX_REG3 0x00000003 +#define PSU_HOST_SBE_MBOX_REG4 0x00000004 +#define PSU_HOST_SBE_MBOX_REG5 0x00000005 +#define PSU_HOST_SBE_MBOX_REG6 0x00000006 +#define PSU_HOST_SBE_MBOX_REG7 0x00000007 +#define PSU_SBE_DOORBELL_REG_RW 0x00000010 +#define PSU_SBE_DOORBELL_REG_AND 0x00000011 +#define PSU_SBE_DOORBELL_REG_OR 0x00000012 +#define PSU_HOST_DOORBELL_REG_RW 0x00000013 +#define PSU_HOST_DOORBELL_REG_AND 0x00000014 +#define PSU_HOST_DOORBELL_REG_OR 0x00000015 + +/* + * Doorbell register to trigger SBE interrupt. Set by OPAL to inform + * the SBE about a waiting message in the Host/SBE mailbox registers + */ +#define HOST_SBE_MSG_WAITING PPC_BIT(0) + +/* + * Doorbell register for host bridge interrupt. Set by the SBE to inform + * host about a response message in the Host/SBE mailbox registers + */ +#define SBE_HOST_RESPONSE_WAITING PPC_BIT(0) +#define SBE_HOST_MSG_READ PPC_BIT(1) +#define SBE_HOST_STOP15_EXIT PPC_BIT(2) +#define SBE_HOST_RESET PPC_BIT(3) +#define SBE_HOST_PASSTHROUGH PPC_BIT(4) +#define SBE_HOST_TIMER_EXPIRY PPC_BIT(14) +#define SBE_HOST_RESPONSE_MASK (PPC_BITMASK(0, 4) | \ + SBE_HOST_TIMER_EXPIRY) + +/* SBE Control Register */ +#define SBE_CONTROL_REG_RW 0x00000000 + +/* SBE interrupt s0/s1 bits */ +#define SBE_CONTROL_REG_S0 PPC_BIT(14) +#define SBE_CONTROL_REG_S1 PPC_BIT(15) + +struct sbe_msg { + uint64_t reg[4]; +}; + +static uint64_t pnv_sbe_power9_xscom_ctrl_read(void *opaque, hwaddr addr, + unsigned size) +{ + uint32_t offset = addr >> 3; + uint64_t val = 0; + + switch (offset) { + default: + qemu_log_mask(LOG_UNIMP, "SBE Unimplemented register: Ox%" + HWADDR_PRIx "\n", addr >> 3); + } + + trace_pnv_sbe_xscom_ctrl_read(addr, val); + + return val; +} + +static void pnv_sbe_power9_xscom_ctrl_write(void *opaque, hwaddr addr, + uint64_t val, unsigned size) +{ + uint32_t offset = addr >> 3; + + trace_pnv_sbe_xscom_ctrl_write(addr, val); + + switch (offset) { + default: + qemu_log_mask(LOG_UNIMP, "SBE Unimplemented register: Ox%" + HWADDR_PRIx "\n", addr >> 3); + } +} + +static const MemoryRegionOps pnv_sbe_power9_xscom_ctrl_ops = { + .read = pnv_sbe_power9_xscom_ctrl_read, + .write = pnv_sbe_power9_xscom_ctrl_write, + .valid.min_access_size = 8, + .valid.max_access_size = 8, + .impl.min_access_size = 8, + .impl.max_access_size = 8, + .endianness = DEVICE_BIG_ENDIAN, +}; + +static void pnv_sbe_set_host_doorbell(PnvSBE *sbe, uint64_t val) +{ + val &= SBE_HOST_RESPONSE_MASK; /* Is this right? What does HW do? */ + sbe->host_doorbell = val; + + trace_pnv_sbe_reg_set_host_doorbell(val); + qemu_set_irq(sbe->psi_irq, !!val); +} + +/* SBE Target Type */ +#define SBE_TARGET_TYPE_PROC 0x00 +#define SBE_TARGET_TYPE_EX 0x01 +#define SBE_TARGET_TYPE_PERV 0x02 +#define SBE_TARGET_TYPE_MCS 0x03 +#define SBE_TARGET_TYPE_EQ 0x04 +#define SBE_TARGET_TYPE_CORE 0x05 + +/* SBE MBOX command class */ +#define SBE_MCLASS_FIRST 0xD1 +#define SBE_MCLASS_CORE_STATE 0xD1 +#define SBE_MCLASS_SCOM 0xD2 +#define SBE_MCLASS_RING 0xD3 +#define SBE_MCLASS_TIMER 0xD4 +#define SBE_MCLASS_MPIPL 0xD5 +#define SBE_MCLASS_SECURITY 0xD6 +#define SBE_MCLASS_GENERIC 0xD7 +#define SBE_MCLASS_LAST 0xD7 + +/* + * Commands are provided in xxyy form where: + * - xx : command class + * - yy : command + * + * Both request and response message uses same seq ID, + * command class and command. + */ +#define SBE_CMD_CTRL_DEADMAN_LOOP 0xD101 +#define SBE_CMD_MULTI_SCOM 0xD201 +#define SBE_CMD_PUT_RING_FORM_IMAGE 0xD301 +#define SBE_CMD_CONTROL_TIMER 0xD401 +#define SBE_CMD_GET_ARCHITECTED_REG 0xD501 +#define SBE_CMD_CLR_ARCHITECTED_REG 0xD502 +#define SBE_CMD_SET_UNSEC_MEM_WINDOW 0xD601 +#define SBE_CMD_GET_SBE_FFDC 0xD701 +#define SBE_CMD_GET_CAPABILITY 0xD702 +#define SBE_CMD_READ_SBE_SEEPROM 0xD703 +#define SBE_CMD_SET_FFDC_ADDR 0xD704 +#define SBE_CMD_QUIESCE_SBE 0xD705 +#define SBE_CMD_SET_FABRIC_ID_MAP 0xD706 +#define SBE_CMD_STASH_MPIPL_CONFIG 0xD707 + +/* SBE MBOX control flags */ + +/* Generic flags */ +#define SBE_CMD_CTRL_RESP_REQ 0x0100 +#define SBE_CMD_CTRL_ACK_REQ 0x0200 + +/* Deadman loop */ +#define CTRL_DEADMAN_LOOP_START 0x0001 +#define CTRL_DEADMAN_LOOP_STOP 0x0002 + +/* Control timer */ +#define CONTROL_TIMER_START 0x0001 +#define CONTROL_TIMER_STOP 0x0002 + +/* Stash MPIPL config */ +#define SBE_STASH_KEY_SKIBOOT_BASE 0x03 + +static void sbe_timer(void *opaque) +{ + PnvSBE *sbe = opaque; + + trace_pnv_sbe_cmd_timer_expired(); + + pnv_sbe_set_host_doorbell(sbe, sbe->host_doorbell | SBE_HOST_TIMER_EXPIRY); +} + +static void do_sbe_msg(PnvSBE *sbe) +{ + struct sbe_msg msg; + uint16_t cmd, ctrl_flags, seq_id; + int i; + + memset(&msg, 0, sizeof(msg)); + + for (i = 0; i < 4; i++) { + msg.reg[i] = sbe->mbox[i]; + } + + cmd = msg.reg[0]; + seq_id = msg.reg[0] >> 16; + ctrl_flags = msg.reg[0] >> 32; + + trace_pnv_sbe_msg_recv(cmd, seq_id, ctrl_flags); + + if (ctrl_flags & SBE_CMD_CTRL_ACK_REQ) { + pnv_sbe_set_host_doorbell(sbe, sbe->host_doorbell | SBE_HOST_MSG_READ); + } + + switch (cmd) { + case SBE_CMD_CONTROL_TIMER: + if (ctrl_flags & CONTROL_TIMER_START) { + uint64_t us = msg.reg[1]; + trace_pnv_sbe_cmd_timer_start(us); + timer_mod(sbe->timer, qemu_clock_get_us(QEMU_CLOCK_VIRTUAL) + us); + } + if (ctrl_flags & CONTROL_TIMER_STOP) { + trace_pnv_sbe_cmd_timer_stop(); + timer_del(sbe->timer); + } + break; + default: + qemu_log_mask(LOG_UNIMP, "SBE Unimplemented command: 0x%x\n", cmd); + } +} + +static void pnv_sbe_set_sbe_doorbell(PnvSBE *sbe, uint64_t val) +{ + val &= HOST_SBE_MSG_WAITING; + sbe->sbe_doorbell = val; + + if (val & HOST_SBE_MSG_WAITING) { + sbe->sbe_doorbell &= ~HOST_SBE_MSG_WAITING; + do_sbe_msg(sbe); + } +} + +static uint64_t pnv_sbe_power9_xscom_mbox_read(void *opaque, hwaddr addr, + unsigned size) +{ + PnvSBE *sbe = PNV_SBE(opaque); + uint32_t offset = addr >> 3; + uint64_t val = 0; + + if (offset <= PSU_HOST_SBE_MBOX_REG7) { + uint32_t idx = offset - PSU_HOST_SBE_MBOX_REG0; + val = sbe->mbox[idx]; + } else { + switch (offset) { + case PSU_SBE_DOORBELL_REG_RW: + val = sbe->sbe_doorbell; + break; + case PSU_HOST_DOORBELL_REG_RW: + val = sbe->host_doorbell; + break; + default: + qemu_log_mask(LOG_UNIMP, "SBE Unimplemented register: Ox%" + HWADDR_PRIx "\n", addr >> 3); + } + } + + trace_pnv_sbe_xscom_mbox_read(addr, val); + + return val; +} + +static void pnv_sbe_power9_xscom_mbox_write(void *opaque, hwaddr addr, + uint64_t val, unsigned size) +{ + PnvSBE *sbe = PNV_SBE(opaque); + uint32_t offset = addr >> 3; + + trace_pnv_sbe_xscom_mbox_write(addr, val); + + if (offset <= PSU_HOST_SBE_MBOX_REG7) { + uint32_t idx = offset - PSU_HOST_SBE_MBOX_REG0; + sbe->mbox[idx] = val; + } else { + switch (offset) { + case PSU_SBE_DOORBELL_REG_RW: + pnv_sbe_set_sbe_doorbell(sbe, val); + break; + case PSU_SBE_DOORBELL_REG_AND: + pnv_sbe_set_sbe_doorbell(sbe, sbe->sbe_doorbell & val); + break; + case PSU_SBE_DOORBELL_REG_OR: + pnv_sbe_set_sbe_doorbell(sbe, sbe->sbe_doorbell | val); + break; + + case PSU_HOST_DOORBELL_REG_RW: + pnv_sbe_set_host_doorbell(sbe, val); + break; + case PSU_HOST_DOORBELL_REG_AND: + pnv_sbe_set_host_doorbell(sbe, sbe->host_doorbell & val); + break; + case PSU_HOST_DOORBELL_REG_OR: + pnv_sbe_set_host_doorbell(sbe, sbe->host_doorbell | val); + break; + + default: + qemu_log_mask(LOG_UNIMP, "SBE Unimplemented register: Ox%" + HWADDR_PRIx "\n", addr >> 3); + } + } +} + +static const MemoryRegionOps pnv_sbe_power9_xscom_mbox_ops = { + .read = pnv_sbe_power9_xscom_mbox_read, + .write = pnv_sbe_power9_xscom_mbox_write, + .valid.min_access_size = 8, + .valid.max_access_size = 8, + .impl.min_access_size = 8, + .impl.max_access_size = 8, + .endianness = DEVICE_BIG_ENDIAN, +}; + +static void pnv_sbe_power9_class_init(ObjectClass *klass, void *data) +{ + PnvSBEClass *psc = PNV_SBE_CLASS(klass); + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->desc = "PowerNV SBE Controller (POWER9)"; + psc->xscom_ctrl_size = PNV9_XSCOM_SBE_CTRL_SIZE; + psc->xscom_ctrl_ops = &pnv_sbe_power9_xscom_ctrl_ops; + psc->xscom_mbox_size = PNV9_XSCOM_SBE_MBOX_SIZE; + psc->xscom_mbox_ops = &pnv_sbe_power9_xscom_mbox_ops; +} + +static const TypeInfo pnv_sbe_power9_type_info = { + .name = TYPE_PNV9_SBE, + .parent = TYPE_PNV_SBE, + .instance_size = sizeof(PnvSBE), + .class_init = pnv_sbe_power9_class_init, +}; + +static void pnv_sbe_power10_class_init(ObjectClass *klass, void *data) +{ + PnvSBEClass *psc = PNV_SBE_CLASS(klass); + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->desc = "PowerNV SBE Controller (POWER10)"; + psc->xscom_ctrl_size = PNV10_XSCOM_SBE_CTRL_SIZE; + psc->xscom_ctrl_ops = &pnv_sbe_power9_xscom_ctrl_ops; + psc->xscom_mbox_size = PNV10_XSCOM_SBE_MBOX_SIZE; + psc->xscom_mbox_ops = &pnv_sbe_power9_xscom_mbox_ops; +} + +static const TypeInfo pnv_sbe_power10_type_info = { + .name = TYPE_PNV10_SBE, + .parent = TYPE_PNV9_SBE, + .class_init = pnv_sbe_power10_class_init, +}; + +static void pnv_sbe_realize(DeviceState *dev, Error **errp) +{ + PnvSBE *sbe = PNV_SBE(dev); + PnvSBEClass *psc = PNV_SBE_GET_CLASS(sbe); + + /* XScom regions for SBE registers */ + pnv_xscom_region_init(&sbe->xscom_ctrl_regs, OBJECT(dev), + psc->xscom_ctrl_ops, sbe, "xscom-sbe-ctrl", + psc->xscom_ctrl_size); + pnv_xscom_region_init(&sbe->xscom_mbox_regs, OBJECT(dev), + psc->xscom_mbox_ops, sbe, "xscom-sbe-mbox", + psc->xscom_mbox_size); + + qdev_init_gpio_out(DEVICE(dev), &sbe->psi_irq, 1); + + sbe->timer = timer_new_us(QEMU_CLOCK_VIRTUAL, sbe_timer, sbe); +} + +static void pnv_sbe_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->realize = pnv_sbe_realize; + dc->desc = "PowerNV SBE Controller"; + dc->user_creatable = false; +} + +static const TypeInfo pnv_sbe_type_info = { + .name = TYPE_PNV_SBE, + .parent = TYPE_DEVICE, + .instance_size = sizeof(PnvSBE), + .class_init = pnv_sbe_class_init, + .class_size = sizeof(PnvSBEClass), + .abstract = true, +}; + +static void pnv_sbe_register_types(void) +{ + type_register_static(&pnv_sbe_type_info); + type_register_static(&pnv_sbe_power9_type_info); + type_register_static(&pnv_sbe_power10_type_info); +} + +type_init(pnv_sbe_register_types); diff --git a/hw/ppc/pnv_xscom.c b/hw/ppc/pnv_xscom.c index 9ce018dbc2..79f10de57f 100644 --- a/hw/ppc/pnv_xscom.c +++ b/hw/ppc/pnv_xscom.c @@ -295,6 +295,9 @@ int pnv_dt_xscom(PnvChip *chip, void *fdt, int root_offset, _FDT((fdt_setprop(fdt, xscom_offset, "reg", reg, sizeof(reg)))); _FDT((fdt_setprop(fdt, xscom_offset, "compatible", compat, compat_size))); _FDT((fdt_setprop(fdt, xscom_offset, "scom-controller", NULL, 0))); + if (chip->chip_id == 0) { + _FDT((fdt_setprop(fdt, xscom_offset, "primary", NULL, 0))); + } args.fdt = fdt; args.xscom_offset = xscom_offset; diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h index 83f156f585..1e558c7831 100644 --- a/hw/ppc/ppc405.h +++ b/hw/ppc/ppc405.h @@ -25,54 +25,168 @@ #ifndef PPC405_H #define PPC405_H +#include "qom/object.h" #include "hw/ppc/ppc4xx.h" +#include "hw/intc/ppc-uic.h" +#include "hw/i2c/ppc4xx_i2c.h" -#define PPC405EP_SDRAM_BASE 0x00000000 -#define PPC405EP_NVRAM_BASE 0xF0000000 -#define PPC405EP_FPGA_BASE 0xF0300000 -#define PPC405EP_SRAM_BASE 0xFFF00000 -#define PPC405EP_SRAM_SIZE (512 * KiB) -#define PPC405EP_FLASH_BASE 0xFFF80000 - -/* Bootinfo as set-up by u-boot */ -typedef struct ppc4xx_bd_info_t ppc4xx_bd_info_t; -struct ppc4xx_bd_info_t { - uint32_t bi_memstart; - uint32_t bi_memsize; - uint32_t bi_flashstart; - uint32_t bi_flashsize; - uint32_t bi_flashoffset; /* 0x10 */ - uint32_t bi_sramstart; - uint32_t bi_sramsize; - uint32_t bi_bootflags; - uint32_t bi_ipaddr; /* 0x20 */ - uint8_t bi_enetaddr[6]; - uint16_t bi_ethspeed; - uint32_t bi_intfreq; - uint32_t bi_busfreq; /* 0x30 */ - uint32_t bi_baudrate; - uint8_t bi_s_version[4]; - uint8_t bi_r_version[32]; - uint32_t bi_procfreq; - uint32_t bi_plb_busfreq; - uint32_t bi_pci_busfreq; - uint8_t bi_pci_enetaddr[6]; - uint8_t bi_pci_enetaddr2[6]; /* PPC405EP specific */ - uint32_t bi_opbfreq; - uint32_t bi_iic_fast[2]; +/* PLB to OPB bridge */ +#define TYPE_PPC405_POB "ppc405-pob" +OBJECT_DECLARE_SIMPLE_TYPE(Ppc405PobState, PPC405_POB); +struct Ppc405PobState { + Ppc4xxDcrDeviceState parent_obj; + + uint32_t bear; + uint32_t besr0; + uint32_t besr1; +}; + +/* OPB arbitrer */ +#define TYPE_PPC405_OPBA "ppc405-opba" +OBJECT_DECLARE_SIMPLE_TYPE(Ppc405OpbaState, PPC405_OPBA); +struct Ppc405OpbaState { + SysBusDevice parent_obj; + + MemoryRegion io; + uint8_t cr; + uint8_t pr; +}; + +/* DMA controller */ +#define TYPE_PPC405_DMA "ppc405-dma" +OBJECT_DECLARE_SIMPLE_TYPE(Ppc405DmaState, PPC405_DMA); +struct Ppc405DmaState { + Ppc4xxDcrDeviceState parent_obj; + + qemu_irq irqs[4]; + uint32_t cr[4]; + uint32_t ct[4]; + uint32_t da[4]; + uint32_t sa[4]; + uint32_t sg[4]; + uint32_t sr; + uint32_t sgc; + uint32_t slp; + uint32_t pol; +}; + +/* GPIO */ +#define TYPE_PPC405_GPIO "ppc405-gpio" +OBJECT_DECLARE_SIMPLE_TYPE(Ppc405GpioState, PPC405_GPIO); +struct Ppc405GpioState { + SysBusDevice parent_obj; + + MemoryRegion io; + uint32_t or; + uint32_t tcr; + uint32_t osrh; + uint32_t osrl; + uint32_t tsrh; + uint32_t tsrl; + uint32_t odr; + uint32_t ir; + uint32_t rr1; + uint32_t isr1h; + uint32_t isr1l; +}; + +/* On Chip Memory */ +#define TYPE_PPC405_OCM "ppc405-ocm" +OBJECT_DECLARE_SIMPLE_TYPE(Ppc405OcmState, PPC405_OCM); +struct Ppc405OcmState { + Ppc4xxDcrDeviceState parent_obj; + + MemoryRegion ram; + MemoryRegion isarc_ram; + MemoryRegion dsarc_ram; + uint32_t isarc; + uint32_t isacntl; + uint32_t dsarc; + uint32_t dsacntl; }; -/* PowerPC 405 core */ -ram_addr_t ppc405_set_bootinfo(CPUPPCState *env, ram_addr_t ram_size); +/* General purpose timers */ +#define TYPE_PPC405_GPT "ppc405-gpt" +OBJECT_DECLARE_SIMPLE_TYPE(Ppc405GptState, PPC405_GPT); +struct Ppc405GptState { + SysBusDevice parent_obj; -void ppc4xx_plb_init(CPUPPCState *env); -void ppc405_ebc_init(CPUPPCState *env); + MemoryRegion iomem; -PowerPCCPU *ppc405ep_init(MemoryRegion *address_space_mem, - MemoryRegion ram_memories[2], - hwaddr ram_bases[2], - hwaddr ram_sizes[2], - uint32_t sysclk, DeviceState **uicdev, - int do_init); + int64_t tb_offset; + uint32_t tb_freq; + QEMUTimer *timer; + qemu_irq irqs[5]; + uint32_t oe; + uint32_t ol; + uint32_t im; + uint32_t is; + uint32_t ie; + uint32_t comp[5]; + uint32_t mask[5]; +}; + +#define TYPE_PPC405_CPC "ppc405-cpc" +OBJECT_DECLARE_SIMPLE_TYPE(Ppc405CpcState, PPC405_CPC); + +enum { + PPC405EP_CPU_CLK = 0, + PPC405EP_PLB_CLK = 1, + PPC405EP_OPB_CLK = 2, + PPC405EP_EBC_CLK = 3, + PPC405EP_MAL_CLK = 4, + PPC405EP_PCI_CLK = 5, + PPC405EP_UART0_CLK = 6, + PPC405EP_UART1_CLK = 7, + PPC405EP_CLK_NB = 8, +}; + +struct Ppc405CpcState { + Ppc4xxDcrDeviceState parent_obj; + + uint32_t sysclk; + clk_setup_t clk_setup[PPC405EP_CLK_NB]; + uint32_t boot; + uint32_t epctl; + uint32_t pllmr[2]; + uint32_t ucr; + uint32_t srr; + uint32_t jtagid; + uint32_t pci; + /* Clock and power management */ + uint32_t er; + uint32_t fr; + uint32_t sr; +}; + +#define TYPE_PPC405_SOC "ppc405-soc" +OBJECT_DECLARE_SIMPLE_TYPE(Ppc405SoCState, PPC405_SOC); + +struct Ppc405SoCState { + /* Private */ + DeviceState parent_obj; + + /* Public */ + MemoryRegion ram_banks[2]; + hwaddr ram_bases[2], ram_sizes[2]; + bool do_dram_init; + + MemoryRegion *dram_mr; + hwaddr ram_size; + + PowerPCCPU cpu; + PPCUIC uic; + Ppc405CpcState cpc; + Ppc405GptState gpt; + Ppc405OcmState ocm; + Ppc405GpioState gpio; + Ppc405DmaState dma; + PPC4xxI2CState i2c; + Ppc4xxEbcState ebc; + Ppc405OpbaState opba; + Ppc405PobState pob; + Ppc4xxPlbState plb; + Ppc4xxMalState mal; +}; #endif /* PPC405_H */ diff --git a/hw/ppc/ppc405_boards.c b/hw/ppc/ppc405_boards.c index a66ad05e3a..083f12b23e 100644 --- a/hw/ppc/ppc405_boards.c +++ b/hw/ppc/ppc405_boards.c @@ -48,97 +48,24 @@ #define KERNEL_LOAD_ADDR 0x01000000 #define INITRD_LOAD_ADDR 0x01800000 -#define USE_FLASH_BIOS - -/*****************************************************************************/ -/* PPC405EP reference board (IBM) */ -/* Standalone board with: - * - PowerPC 405EP CPU - * - SDRAM (0x00000000) - * - Flash (0xFFF80000) - * - SRAM (0xFFF00000) - * - NVRAM (0xF0000000) - * - FPGA (0xF0300000) - */ -typedef struct ref405ep_fpga_t ref405ep_fpga_t; -struct ref405ep_fpga_t { - uint8_t reg0; - uint8_t reg1; -}; +#define PPC405EP_SDRAM_BASE 0x00000000 +#define PPC405EP_SRAM_BASE 0xFFF00000 +#define PPC405EP_SRAM_SIZE (512 * KiB) -static uint64_t ref405ep_fpga_readb(void *opaque, hwaddr addr, unsigned size) -{ - ref405ep_fpga_t *fpga; - uint32_t ret; - - fpga = opaque; - switch (addr) { - case 0x0: - ret = fpga->reg0; - break; - case 0x1: - ret = fpga->reg1; - break; - default: - ret = 0; - break; - } +#define USE_FLASH_BIOS - return ret; -} +#define TYPE_PPC405_MACHINE MACHINE_TYPE_NAME("ppc405") +OBJECT_DECLARE_SIMPLE_TYPE(Ppc405MachineState, PPC405_MACHINE); -static void ref405ep_fpga_writeb(void *opaque, hwaddr addr, uint64_t value, - unsigned size) -{ - ref405ep_fpga_t *fpga; +struct Ppc405MachineState { + /* Private */ + MachineState parent_obj; + /* Public */ - fpga = opaque; - switch (addr) { - case 0x0: - /* Read only */ - break; - case 0x1: - fpga->reg1 = value; - break; - default: - break; - } -} - -static const MemoryRegionOps ref405ep_fpga_ops = { - .read = ref405ep_fpga_readb, - .write = ref405ep_fpga_writeb, - .impl.min_access_size = 1, - .impl.max_access_size = 1, - .valid.min_access_size = 1, - .valid.max_access_size = 4, - .endianness = DEVICE_BIG_ENDIAN, + Ppc405SoCState soc; }; -static void ref405ep_fpga_reset (void *opaque) -{ - ref405ep_fpga_t *fpga; - - fpga = opaque; - fpga->reg0 = 0x00; - fpga->reg1 = 0x0F; -} - -static void ref405ep_fpga_init(MemoryRegion *sysmem, uint32_t base) -{ - ref405ep_fpga_t *fpga; - MemoryRegion *fpga_memory = g_new(MemoryRegion, 1); - - fpga = g_new0(ref405ep_fpga_t, 1); - memory_region_init_io(fpga_memory, NULL, &ref405ep_fpga_ops, fpga, - "fpga", 0x00000100); - memory_region_add_subregion(sysmem, base, fpga_memory); - qemu_register_reset(&ref405ep_fpga_reset, fpga); -} - -/* - * CPU reset handler when booting directly from a loaded kernel - */ +/* CPU reset handler when booting directly from a loaded kernel */ static struct boot_info { uint32_t entry; uint32_t bdloc; @@ -169,6 +96,126 @@ static void main_cpu_reset(void *opaque) env->nip = bi->entry; } +/* Bootinfo as set-up by u-boot */ +typedef struct { + uint32_t bi_memstart; + uint32_t bi_memsize; + uint32_t bi_flashstart; + uint32_t bi_flashsize; + uint32_t bi_flashoffset; /* 0x10 */ + uint32_t bi_sramstart; + uint32_t bi_sramsize; + uint32_t bi_bootflags; + uint32_t bi_ipaddr; /* 0x20 */ + uint8_t bi_enetaddr[6]; + uint16_t bi_ethspeed; + uint32_t bi_intfreq; + uint32_t bi_busfreq; /* 0x30 */ + uint32_t bi_baudrate; + uint8_t bi_s_version[4]; + uint8_t bi_r_version[32]; + uint32_t bi_procfreq; + uint32_t bi_plb_busfreq; + uint32_t bi_pci_busfreq; + uint8_t bi_pci_enetaddr[6]; + uint8_t bi_pci_enetaddr2[6]; /* PPC405EP specific */ + uint32_t bi_opbfreq; + uint32_t bi_iic_fast[2]; +} ppc4xx_bd_info_t; + +static void ppc405_set_default_bootinfo(ppc4xx_bd_info_t *bd, + ram_addr_t ram_size) +{ + memset(bd, 0, sizeof(*bd)); + + bd->bi_memstart = PPC405EP_SDRAM_BASE; + bd->bi_memsize = ram_size; + bd->bi_sramstart = PPC405EP_SRAM_BASE; + bd->bi_sramsize = PPC405EP_SRAM_SIZE; + bd->bi_bootflags = 0; + bd->bi_intfreq = 133333333; + bd->bi_busfreq = 33333333; + bd->bi_baudrate = 115200; + bd->bi_s_version[0] = 'Q'; + bd->bi_s_version[1] = 'M'; + bd->bi_s_version[2] = 'U'; + bd->bi_s_version[3] = '\0'; + bd->bi_r_version[0] = 'Q'; + bd->bi_r_version[1] = 'E'; + bd->bi_r_version[2] = 'M'; + bd->bi_r_version[3] = 'U'; + bd->bi_r_version[4] = '\0'; + bd->bi_procfreq = 133333333; + bd->bi_plb_busfreq = 33333333; + bd->bi_pci_busfreq = 33333333; + bd->bi_opbfreq = 33333333; +} + +static ram_addr_t __ppc405_set_bootinfo(CPUPPCState *env, ppc4xx_bd_info_t *bd) +{ + CPUState *cs = env_cpu(env); + ram_addr_t bdloc; + int i, n; + + /* We put the bd structure at the top of memory */ + if (bd->bi_memsize >= 0x01000000UL) { + bdloc = 0x01000000UL - sizeof(ppc4xx_bd_info_t); + } else { + bdloc = bd->bi_memsize - sizeof(ppc4xx_bd_info_t); + } + stl_be_phys(cs->as, bdloc + 0x00, bd->bi_memstart); + stl_be_phys(cs->as, bdloc + 0x04, bd->bi_memsize); + stl_be_phys(cs->as, bdloc + 0x08, bd->bi_flashstart); + stl_be_phys(cs->as, bdloc + 0x0C, bd->bi_flashsize); + stl_be_phys(cs->as, bdloc + 0x10, bd->bi_flashoffset); + stl_be_phys(cs->as, bdloc + 0x14, bd->bi_sramstart); + stl_be_phys(cs->as, bdloc + 0x18, bd->bi_sramsize); + stl_be_phys(cs->as, bdloc + 0x1C, bd->bi_bootflags); + stl_be_phys(cs->as, bdloc + 0x20, bd->bi_ipaddr); + for (i = 0; i < 6; i++) { + stb_phys(cs->as, bdloc + 0x24 + i, bd->bi_enetaddr[i]); + } + stw_be_phys(cs->as, bdloc + 0x2A, bd->bi_ethspeed); + stl_be_phys(cs->as, bdloc + 0x2C, bd->bi_intfreq); + stl_be_phys(cs->as, bdloc + 0x30, bd->bi_busfreq); + stl_be_phys(cs->as, bdloc + 0x34, bd->bi_baudrate); + for (i = 0; i < 4; i++) { + stb_phys(cs->as, bdloc + 0x38 + i, bd->bi_s_version[i]); + } + for (i = 0; i < 32; i++) { + stb_phys(cs->as, bdloc + 0x3C + i, bd->bi_r_version[i]); + } + stl_be_phys(cs->as, bdloc + 0x5C, bd->bi_procfreq); + stl_be_phys(cs->as, bdloc + 0x60, bd->bi_plb_busfreq); + stl_be_phys(cs->as, bdloc + 0x64, bd->bi_pci_busfreq); + for (i = 0; i < 6; i++) { + stb_phys(cs->as, bdloc + 0x68 + i, bd->bi_pci_enetaddr[i]); + } + n = 0x70; /* includes 2 bytes hole */ + for (i = 0; i < 6; i++) { + stb_phys(cs->as, bdloc + n++, bd->bi_pci_enetaddr2[i]); + } + stl_be_phys(cs->as, bdloc + n, bd->bi_opbfreq); + n += 4; + for (i = 0; i < 2; i++) { + stl_be_phys(cs->as, bdloc + n, bd->bi_iic_fast[i]); + n += 4; + } + + return bdloc; +} + +static ram_addr_t ppc405_set_bootinfo(CPUPPCState *env, ram_addr_t ram_size) +{ + ppc4xx_bd_info_t bd; + + memset(&bd, 0, sizeof(bd)); + + ppc405_set_default_bootinfo(&bd, ram_size); + + return __ppc405_set_bootinfo(env, &bd); +} + static void boot_from_kernel(MachineState *machine, PowerPCCPU *cpu) { CPUPPCState *env = &cpu->env; @@ -221,18 +268,12 @@ static void boot_from_kernel(MachineState *machine, PowerPCCPU *cpu) env->load_info = &boot_info; } -static void ref405ep_init(MachineState *machine) +static void ppc405_init(MachineState *machine) { + Ppc405MachineState *ppc405 = PPC405_MACHINE(machine); MachineClass *mc = MACHINE_GET_CLASS(machine); const char *kernel_filename = machine->kernel_filename; - PowerPCCPU *cpu; - DeviceState *dev; - SysBusDevice *s; - MemoryRegion *sram = g_new(MemoryRegion, 1); - MemoryRegion *ram_memories = g_new(MemoryRegion, 2); - hwaddr ram_bases[2], ram_sizes[2]; MemoryRegion *sysmem = get_system_memory(); - DeviceState *uicdev; if (machine->ram_size != mc->default_ram_size) { char *sz = size_to_str(mc->default_ram_size); @@ -241,22 +282,17 @@ static void ref405ep_init(MachineState *machine) exit(EXIT_FAILURE); } - /* XXX: fix this */ - memory_region_init_alias(&ram_memories[0], NULL, "ef405ep.ram.alias", - machine->ram, 0, machine->ram_size); - ram_bases[0] = 0; - ram_sizes[0] = machine->ram_size; - memory_region_init(&ram_memories[1], NULL, "ef405ep.ram1", 0); - ram_bases[1] = 0x00000000; - ram_sizes[1] = 0x00000000; - - cpu = ppc405ep_init(sysmem, ram_memories, ram_bases, ram_sizes, - 33333333, &uicdev, kernel_filename == NULL ? 0 : 1); - - /* allocate SRAM */ - memory_region_init_ram(sram, NULL, "ef405ep.sram", PPC405EP_SRAM_SIZE, - &error_fatal); - memory_region_add_subregion(sysmem, PPC405EP_SRAM_BASE, sram); + object_initialize_child(OBJECT(machine), "soc", &ppc405->soc, + TYPE_PPC405_SOC); + object_property_set_uint(OBJECT(&ppc405->soc), "ram-size", + machine->ram_size, &error_fatal); + object_property_set_link(OBJECT(&ppc405->soc), "dram", + OBJECT(machine->ram), &error_abort); + object_property_set_bool(OBJECT(&ppc405->soc), "dram-init", + kernel_filename != NULL, &error_abort); + object_property_set_uint(OBJECT(&ppc405->soc), "sys-clk", 33333333, + &error_abort); + qdev_realize(DEVICE(&ppc405->soc), NULL, &error_fatal); /* allocate and load BIOS */ if (machine->firmware) { @@ -285,15 +321,6 @@ static void ref405ep_init(MachineState *machine) memory_region_add_subregion(sysmem, (uint32_t)(-bios_size), bios); } - /* Register FPGA */ - ref405ep_fpga_init(sysmem, PPC405EP_FPGA_BASE); - /* Register NVRAM */ - dev = qdev_new("sysbus-m48t08"); - qdev_prop_set_int32(dev, "base-year", 1968); - s = SYS_BUS_DEVICE(dev); - sysbus_realize_and_unref(s, &error_fatal); - sysbus_mmio_map(s, 0, PPC405EP_NVRAM_BASE); - /* Load kernel and initrd using U-Boot images */ if (kernel_filename && machine->firmware) { target_ulong kernel_base, initrd_base; @@ -322,63 +349,66 @@ static void ref405ep_init(MachineState *machine) /* Load ELF kernel and rootfs.cpio */ } else if (kernel_filename && !machine->firmware) { - boot_from_kernel(machine, cpu); + boot_from_kernel(machine, &ppc405->soc.cpu); } } -static void ref405ep_class_init(ObjectClass *oc, void *data) +static void ppc405_machine_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); - mc->desc = "ref405ep"; - mc->init = ref405ep_init; - mc->default_ram_size = 0x08000000; - mc->default_ram_id = "ef405ep.ram"; + mc->desc = "PPC405 generic machine"; + mc->init = ppc405_init; + mc->default_ram_size = 128 * MiB; + mc->default_ram_id = "ppc405.ram"; } -static const TypeInfo ref405ep_type = { - .name = MACHINE_TYPE_NAME("ref405ep"), +static const TypeInfo ppc405_machine_type = { + .name = TYPE_PPC405_MACHINE, .parent = TYPE_MACHINE, - .class_init = ref405ep_class_init, + .instance_size = sizeof(Ppc405MachineState), + .class_init = ppc405_machine_class_init, + .abstract = true, }; /*****************************************************************************/ -/* AMCC Taihu evaluation board */ -/* - PowerPC 405EP processor - * - SDRAM 128 MB at 0x00000000 - * - Boot flash 2 MB at 0xFFE00000 - * - Application flash 32 MB at 0xFC000000 - * - 2 serial ports - * - 2 ethernet PHY - * - 1 USB 1.1 device 0x50000000 - * - 1 LCD display 0x50100000 - * - 1 CPLD 0x50100000 - * - 1 I2C EEPROM - * - 1 I2C thermal sensor - * - a set of LEDs - * - bit-bang SPI port using GPIOs - * - 1 EBC interface connector 0 0x50200000 - * - 1 cardbus controller + expansion slot. - * - 1 PCI expansion slot. +/* PPC405EP reference board (IBM) */ +/* + * Standalone board with: + * - PowerPC 405EP CPU + * - SDRAM (0x00000000) + * - Flash (0xFFF80000) + * - SRAM (0xFFF00000) + * - NVRAM (0xF0000000) + * - FPGA (0xF0300000) */ -typedef struct taihu_cpld_t taihu_cpld_t; -struct taihu_cpld_t { + +#define PPC405EP_NVRAM_BASE 0xF0000000 +#define PPC405EP_FPGA_BASE 0xF0300000 +#define PPC405EP_FLASH_BASE 0xFFF80000 + +#define TYPE_REF405EP_FPGA "ref405ep-fpga" +OBJECT_DECLARE_SIMPLE_TYPE(Ref405epFpgaState, REF405EP_FPGA); +struct Ref405epFpgaState { + SysBusDevice parent_obj; + + MemoryRegion iomem; + uint8_t reg0; uint8_t reg1; }; -static uint64_t taihu_cpld_read(void *opaque, hwaddr addr, unsigned size) +static uint64_t ref405ep_fpga_readb(void *opaque, hwaddr addr, unsigned size) { - taihu_cpld_t *cpld; + Ref405epFpgaState *fpga = opaque; uint32_t ret; - cpld = opaque; switch (addr) { case 0x0: - ret = cpld->reg0; + ret = fpga->reg0; break; case 0x1: - ret = cpld->reg1; + ret = fpga->reg1; break; default: ret = 0; @@ -388,195 +418,113 @@ static uint64_t taihu_cpld_read(void *opaque, hwaddr addr, unsigned size) return ret; } -static void taihu_cpld_write(void *opaque, hwaddr addr, - uint64_t value, unsigned size) +static void ref405ep_fpga_writeb(void *opaque, hwaddr addr, uint64_t value, + unsigned size) { - taihu_cpld_t *cpld; + Ref405epFpgaState *fpga = opaque; - cpld = opaque; switch (addr) { case 0x0: /* Read only */ break; case 0x1: - cpld->reg1 = value; + fpga->reg1 = value; break; default: break; } } -static const MemoryRegionOps taihu_cpld_ops = { - .read = taihu_cpld_read, - .write = taihu_cpld_write, - .impl = { - .min_access_size = 1, - .max_access_size = 1, - }, - .endianness = DEVICE_NATIVE_ENDIAN, +static const MemoryRegionOps ref405ep_fpga_ops = { + .read = ref405ep_fpga_readb, + .write = ref405ep_fpga_writeb, + .impl.min_access_size = 1, + .impl.max_access_size = 1, + .valid.min_access_size = 1, + .valid.max_access_size = 4, + .endianness = DEVICE_BIG_ENDIAN, }; -static void taihu_cpld_reset (void *opaque) +static void ref405ep_fpga_reset(DeviceState *dev) { - taihu_cpld_t *cpld; + Ref405epFpgaState *fpga = REF405EP_FPGA(dev); - cpld = opaque; - cpld->reg0 = 0x01; - cpld->reg1 = 0x80; + fpga->reg0 = 0x00; + fpga->reg1 = 0x0F; } -static void taihu_cpld_init(MemoryRegion *sysmem, uint32_t base) +static void ref405ep_fpga_realize(DeviceState *dev, Error **errp) { - taihu_cpld_t *cpld; - MemoryRegion *cpld_memory = g_new(MemoryRegion, 1); + Ref405epFpgaState *s = REF405EP_FPGA(dev); - cpld = g_new0(taihu_cpld_t, 1); - memory_region_init_io(cpld_memory, NULL, &taihu_cpld_ops, cpld, "cpld", 0x100); - memory_region_add_subregion(sysmem, base, cpld_memory); - qemu_register_reset(&taihu_cpld_reset, cpld); + memory_region_init_io(&s->iomem, OBJECT(s), &ref405ep_fpga_ops, s, + "fpga", 0x00000100); + sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem); } -static void taihu_405ep_init(MachineState *machine) +static void ref405ep_fpga_class_init(ObjectClass *oc, void *data) { - MachineClass *mc = MACHINE_GET_CLASS(machine); - const char *bios_name = machine->firmware ?: BIOS_FILENAME; - const char *kernel_filename = machine->kernel_filename; - const char *initrd_filename = machine->initrd_filename; - char *filename; - MemoryRegion *sysmem = get_system_memory(); - MemoryRegion *bios; - MemoryRegion *ram_memories = g_new(MemoryRegion, 2); - hwaddr ram_bases[2], ram_sizes[2]; - long bios_size; - target_ulong kernel_base, initrd_base; - long kernel_size, initrd_size; - int linux_boot; - int fl_idx; - DriveInfo *dinfo; - DeviceState *uicdev; + DeviceClass *dc = DEVICE_CLASS(oc); - if (machine->ram_size != mc->default_ram_size) { - char *sz = size_to_str(mc->default_ram_size); - error_report("Invalid RAM size, should be %s", sz); - g_free(sz); - exit(EXIT_FAILURE); - } + dc->realize = ref405ep_fpga_realize; + dc->reset = ref405ep_fpga_reset; + /* Reason: only works as part of a ppc405 board */ + dc->user_creatable = false; +} - ram_bases[0] = 0; - ram_sizes[0] = 0x04000000; - memory_region_init_alias(&ram_memories[0], NULL, - "taihu_405ep.ram-0", machine->ram, ram_bases[0], - ram_sizes[0]); - ram_bases[1] = 0x04000000; - ram_sizes[1] = 0x04000000; - memory_region_init_alias(&ram_memories[1], NULL, - "taihu_405ep.ram-1", machine->ram, ram_bases[1], - ram_sizes[1]); - ppc405ep_init(sysmem, ram_memories, ram_bases, ram_sizes, - 33333333, &uicdev, kernel_filename == NULL ? 0 : 1); - /* allocate and load BIOS */ - fl_idx = 0; -#if defined(USE_FLASH_BIOS) - dinfo = drive_get(IF_PFLASH, 0, fl_idx); - if (dinfo) { - bios_size = 2 * MiB; - pflash_cfi02_register(0xFFE00000, - "taihu_405ep.bios", bios_size, - blk_by_legacy_dinfo(dinfo), - 64 * KiB, 1, - 4, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA, - 1); - fl_idx++; - } else -#endif - { - bios = g_new(MemoryRegion, 1); - memory_region_init_rom(bios, NULL, "taihu_405ep.bios", BIOS_SIZE, - &error_fatal); - filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); - if (filename) { - bios_size = load_image_size(filename, - memory_region_get_ram_ptr(bios), - BIOS_SIZE); - g_free(filename); - if (bios_size < 0) { - error_report("Could not load PowerPC BIOS '%s'", bios_name); - exit(1); - } - bios_size = (bios_size + 0xfff) & ~0xfff; - memory_region_add_subregion(sysmem, (uint32_t)(-bios_size), bios); - } else if (!qtest_enabled()) { - error_report("Could not load PowerPC BIOS '%s'", bios_name); - exit(1); - } - } - /* Register Linux flash */ - dinfo = drive_get(IF_PFLASH, 0, fl_idx); - if (dinfo) { - bios_size = 32 * MiB; - pflash_cfi02_register(0xfc000000, "taihu_405ep.flash", bios_size, - blk_by_legacy_dinfo(dinfo), - 64 * KiB, 1, - 4, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA, - 1); - fl_idx++; - } - /* Register CLPD & LCD display */ - taihu_cpld_init(sysmem, 0x50100000); - /* Load kernel */ - linux_boot = (kernel_filename != NULL); - if (linux_boot) { - kernel_base = KERNEL_LOAD_ADDR; - /* now we can load the kernel */ - kernel_size = load_image_targphys(kernel_filename, kernel_base, - machine->ram_size - kernel_base); - if (kernel_size < 0) { - error_report("could not load kernel '%s'", kernel_filename); - exit(1); - } - /* load initrd */ - if (initrd_filename) { - initrd_base = INITRD_LOAD_ADDR; - initrd_size = load_image_targphys(initrd_filename, initrd_base, - machine->ram_size - initrd_base); - if (initrd_size < 0) { - error_report("could not load initial ram disk '%s'", - initrd_filename); - exit(1); - } - } else { - initrd_base = 0; - initrd_size = 0; - } - } else { - kernel_base = 0; - kernel_size = 0; - initrd_base = 0; - initrd_size = 0; - } +static const TypeInfo ref405ep_fpga_type = { + .name = TYPE_REF405EP_FPGA, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(Ref405epFpgaState), + .class_init = ref405ep_fpga_class_init, +}; + +static void ref405ep_init(MachineState *machine) +{ + DeviceState *dev; + SysBusDevice *s; + MemoryRegion *sram = g_new(MemoryRegion, 1); + + ppc405_init(machine); + + /* allocate SRAM */ + memory_region_init_ram(sram, NULL, "ref405ep.sram", PPC405EP_SRAM_SIZE, + &error_fatal); + memory_region_add_subregion(get_system_memory(), PPC405EP_SRAM_BASE, sram); + + /* Register FPGA */ + dev = qdev_new(TYPE_REF405EP_FPGA); + object_property_add_child(OBJECT(machine), "fpga", OBJECT(dev)); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, PPC405EP_FPGA_BASE); + + /* Register NVRAM */ + dev = qdev_new("sysbus-m48t08"); + qdev_prop_set_int32(dev, "base-year", 1968); + s = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(s, &error_fatal); + sysbus_mmio_map(s, 0, PPC405EP_NVRAM_BASE); } -static void taihu_class_init(ObjectClass *oc, void *data) +static void ref405ep_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); - mc->desc = "taihu"; - mc->init = taihu_405ep_init; - mc->default_ram_size = 0x08000000; - mc->default_ram_id = "taihu_405ep.ram"; - mc->deprecation_reason = "incomplete, use 'ref405ep' instead"; + mc->desc = "ref405ep"; + mc->init = ref405ep_init; } -static const TypeInfo taihu_type = { - .name = MACHINE_TYPE_NAME("taihu"), - .parent = TYPE_MACHINE, - .class_init = taihu_class_init, +static const TypeInfo ref405ep_type = { + .name = MACHINE_TYPE_NAME("ref405ep"), + .parent = TYPE_PPC405_MACHINE, + .class_init = ref405ep_class_init, }; static void ppc405_machine_init(void) { + type_register_static(&ppc405_machine_type); type_register_static(&ref405ep_type); - type_register_static(&taihu_type); + type_register_static(&ref405ep_fpga_type); } type_init(ppc405_machine_init) diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c index d6420c88d3..2ca42fdef6 100644 --- a/hw/ppc/ppc405_uc.c +++ b/hw/ppc/ppc405_uc.c @@ -30,6 +30,7 @@ #include "hw/ppc/ppc.h" #include "hw/i2c/ppc4xx_i2c.h" #include "hw/irq.h" +#include "hw/qdev-properties.h" #include "ppc405.h" #include "hw/char/serial.h" #include "qemu/timer.h" @@ -41,191 +42,10 @@ #include "qapi/error.h" #include "trace.h" -static void ppc405_set_default_bootinfo(ppc4xx_bd_info_t *bd, - ram_addr_t ram_size) -{ - memset(bd, 0, sizeof(*bd)); - - bd->bi_memstart = PPC405EP_SDRAM_BASE; - bd->bi_memsize = ram_size; - bd->bi_sramstart = PPC405EP_SRAM_BASE; - bd->bi_sramsize = PPC405EP_SRAM_SIZE; - bd->bi_bootflags = 0; - bd->bi_intfreq = 133333333; - bd->bi_busfreq = 33333333; - bd->bi_baudrate = 115200; - bd->bi_s_version[0] = 'Q'; - bd->bi_s_version[1] = 'M'; - bd->bi_s_version[2] = 'U'; - bd->bi_s_version[3] = '\0'; - bd->bi_r_version[0] = 'Q'; - bd->bi_r_version[1] = 'E'; - bd->bi_r_version[2] = 'M'; - bd->bi_r_version[3] = 'U'; - bd->bi_r_version[4] = '\0'; - bd->bi_procfreq = 133333333; - bd->bi_plb_busfreq = 33333333; - bd->bi_pci_busfreq = 33333333; - bd->bi_opbfreq = 33333333; -} - -static ram_addr_t __ppc405_set_bootinfo(CPUPPCState *env, ppc4xx_bd_info_t *bd) -{ - CPUState *cs = env_cpu(env); - ram_addr_t bdloc; - int i, n; - - /* We put the bd structure at the top of memory */ - if (bd->bi_memsize >= 0x01000000UL) - bdloc = 0x01000000UL - sizeof(struct ppc4xx_bd_info_t); - else - bdloc = bd->bi_memsize - sizeof(struct ppc4xx_bd_info_t); - stl_be_phys(cs->as, bdloc + 0x00, bd->bi_memstart); - stl_be_phys(cs->as, bdloc + 0x04, bd->bi_memsize); - stl_be_phys(cs->as, bdloc + 0x08, bd->bi_flashstart); - stl_be_phys(cs->as, bdloc + 0x0C, bd->bi_flashsize); - stl_be_phys(cs->as, bdloc + 0x10, bd->bi_flashoffset); - stl_be_phys(cs->as, bdloc + 0x14, bd->bi_sramstart); - stl_be_phys(cs->as, bdloc + 0x18, bd->bi_sramsize); - stl_be_phys(cs->as, bdloc + 0x1C, bd->bi_bootflags); - stl_be_phys(cs->as, bdloc + 0x20, bd->bi_ipaddr); - for (i = 0; i < 6; i++) { - stb_phys(cs->as, bdloc + 0x24 + i, bd->bi_enetaddr[i]); - } - stw_be_phys(cs->as, bdloc + 0x2A, bd->bi_ethspeed); - stl_be_phys(cs->as, bdloc + 0x2C, bd->bi_intfreq); - stl_be_phys(cs->as, bdloc + 0x30, bd->bi_busfreq); - stl_be_phys(cs->as, bdloc + 0x34, bd->bi_baudrate); - for (i = 0; i < 4; i++) { - stb_phys(cs->as, bdloc + 0x38 + i, bd->bi_s_version[i]); - } - for (i = 0; i < 32; i++) { - stb_phys(cs->as, bdloc + 0x3C + i, bd->bi_r_version[i]); - } - stl_be_phys(cs->as, bdloc + 0x5C, bd->bi_procfreq); - stl_be_phys(cs->as, bdloc + 0x60, bd->bi_plb_busfreq); - stl_be_phys(cs->as, bdloc + 0x64, bd->bi_pci_busfreq); - for (i = 0; i < 6; i++) { - stb_phys(cs->as, bdloc + 0x68 + i, bd->bi_pci_enetaddr[i]); - } - n = 0x70; /* includes 2 bytes hole */ - for (i = 0; i < 6; i++) { - stb_phys(cs->as, bdloc + n++, bd->bi_pci_enetaddr2[i]); - } - stl_be_phys(cs->as, bdloc + n, bd->bi_opbfreq); - n += 4; - for (i = 0; i < 2; i++) { - stl_be_phys(cs->as, bdloc + n, bd->bi_iic_fast[i]); - n += 4; - } - - return bdloc; -} - -ram_addr_t ppc405_set_bootinfo(CPUPPCState *env, ram_addr_t ram_size) -{ - ppc4xx_bd_info_t bd; - - memset(&bd, 0, sizeof(bd)); - - ppc405_set_default_bootinfo(&bd, ram_size); - - return __ppc405_set_bootinfo(env, &bd); -} - /*****************************************************************************/ /* Shared peripherals */ /*****************************************************************************/ -/* Peripheral local bus arbitrer */ -enum { - PLB3A0_ACR = 0x077, - PLB4A0_ACR = 0x081, - PLB0_BESR = 0x084, - PLB0_BEAR = 0x086, - PLB0_ACR = 0x087, - PLB4A1_ACR = 0x089, -}; - -typedef struct ppc4xx_plb_t ppc4xx_plb_t; -struct ppc4xx_plb_t { - uint32_t acr; - uint32_t bear; - uint32_t besr; -}; - -static uint32_t dcr_read_plb (void *opaque, int dcrn) -{ - ppc4xx_plb_t *plb; - uint32_t ret; - - plb = opaque; - switch (dcrn) { - case PLB0_ACR: - ret = plb->acr; - break; - case PLB0_BEAR: - ret = plb->bear; - break; - case PLB0_BESR: - ret = plb->besr; - break; - default: - /* Avoid gcc warning */ - ret = 0; - break; - } - - return ret; -} - -static void dcr_write_plb (void *opaque, int dcrn, uint32_t val) -{ - ppc4xx_plb_t *plb; - - plb = opaque; - switch (dcrn) { - case PLB0_ACR: - /* We don't care about the actual parameters written as - * we don't manage any priorities on the bus - */ - plb->acr = val & 0xF8000000; - break; - case PLB0_BEAR: - /* Read only */ - break; - case PLB0_BESR: - /* Write-clear */ - plb->besr &= ~val; - break; - } -} - -static void ppc4xx_plb_reset (void *opaque) -{ - ppc4xx_plb_t *plb; - - plb = opaque; - plb->acr = 0x00000000; - plb->bear = 0x00000000; - plb->besr = 0x00000000; -} - -void ppc4xx_plb_init(CPUPPCState *env) -{ - ppc4xx_plb_t *plb; - - plb = g_new0(ppc4xx_plb_t, 1); - ppc_dcr_register(env, PLB3A0_ACR, plb, &dcr_read_plb, &dcr_write_plb); - ppc_dcr_register(env, PLB4A0_ACR, plb, &dcr_read_plb, &dcr_write_plb); - ppc_dcr_register(env, PLB0_ACR, plb, &dcr_read_plb, &dcr_write_plb); - ppc_dcr_register(env, PLB0_BEAR, plb, &dcr_read_plb, &dcr_write_plb); - ppc_dcr_register(env, PLB0_BESR, plb, &dcr_read_plb, &dcr_write_plb); - ppc_dcr_register(env, PLB4A1_ACR, plb, &dcr_read_plb, &dcr_write_plb); - qemu_register_reset(ppc4xx_plb_reset, plb); -} - -/*****************************************************************************/ /* PLB to OPB bridge */ enum { POB0_BESR0 = 0x0A0, @@ -233,19 +53,11 @@ enum { POB0_BEAR = 0x0A4, }; -typedef struct ppc4xx_pob_t ppc4xx_pob_t; -struct ppc4xx_pob_t { - uint32_t bear; - uint32_t besr0; - uint32_t besr1; -}; - -static uint32_t dcr_read_pob (void *opaque, int dcrn) +static uint32_t dcr_read_pob(void *opaque, int dcrn) { - ppc4xx_pob_t *pob; + Ppc405PobState *pob = opaque; uint32_t ret; - pob = opaque; switch (dcrn) { case POB0_BEAR: ret = pob->bear; @@ -265,11 +77,10 @@ static uint32_t dcr_read_pob (void *opaque, int dcrn) return ret; } -static void dcr_write_pob (void *opaque, int dcrn, uint32_t val) +static void dcr_write_pob(void *opaque, int dcrn, uint32_t val) { - ppc4xx_pob_t *pob; + Ppc405PobState *pob = opaque; - pob = opaque; switch (dcrn) { case POB0_BEAR: /* Read only */ @@ -285,40 +96,41 @@ static void dcr_write_pob (void *opaque, int dcrn, uint32_t val) } } -static void ppc4xx_pob_reset (void *opaque) +static void ppc405_pob_reset(DeviceState *dev) { - ppc4xx_pob_t *pob; + Ppc405PobState *pob = PPC405_POB(dev); - pob = opaque; /* No error */ pob->bear = 0x00000000; pob->besr0 = 0x0000000; pob->besr1 = 0x0000000; } -static void ppc4xx_pob_init(CPUPPCState *env) +static void ppc405_pob_realize(DeviceState *dev, Error **errp) { - ppc4xx_pob_t *pob; + Ppc405PobState *pob = PPC405_POB(dev); + Ppc4xxDcrDeviceState *dcr = PPC4xx_DCR_DEVICE(dev); - pob = g_new0(ppc4xx_pob_t, 1); - ppc_dcr_register(env, POB0_BEAR, pob, &dcr_read_pob, &dcr_write_pob); - ppc_dcr_register(env, POB0_BESR0, pob, &dcr_read_pob, &dcr_write_pob); - ppc_dcr_register(env, POB0_BESR1, pob, &dcr_read_pob, &dcr_write_pob); - qemu_register_reset(ppc4xx_pob_reset, pob); + ppc4xx_dcr_register(dcr, POB0_BEAR, pob, &dcr_read_pob, &dcr_write_pob); + ppc4xx_dcr_register(dcr, POB0_BESR0, pob, &dcr_read_pob, &dcr_write_pob); + ppc4xx_dcr_register(dcr, POB0_BESR1, pob, &dcr_read_pob, &dcr_write_pob); +} + +static void ppc405_pob_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + + dc->realize = ppc405_pob_realize; + dc->reset = ppc405_pob_reset; + /* Reason: only works as function of a ppc4xx SoC */ + dc->user_creatable = false; } /*****************************************************************************/ /* OPB arbitrer */ -typedef struct ppc4xx_opba_t ppc4xx_opba_t; -struct ppc4xx_opba_t { - MemoryRegion io; - uint8_t cr; - uint8_t pr; -}; - static uint64_t opba_readb(void *opaque, hwaddr addr, unsigned size) { - ppc4xx_opba_t *opba = opaque; + Ppc405OpbaState *opba = opaque; uint32_t ret; switch (addr) { @@ -340,7 +152,7 @@ static uint64_t opba_readb(void *opaque, hwaddr addr, unsigned size) static void opba_writeb(void *opaque, hwaddr addr, uint64_t value, unsigned size) { - ppc4xx_opba_t *opba = opaque; + Ppc405OpbaState *opba = opaque; trace_opba_writeb(addr, value); @@ -365,223 +177,35 @@ static const MemoryRegionOps opba_ops = { .endianness = DEVICE_BIG_ENDIAN, }; -static void ppc4xx_opba_reset (void *opaque) +static void ppc405_opba_reset(DeviceState *dev) { - ppc4xx_opba_t *opba; + Ppc405OpbaState *opba = PPC405_OPBA(dev); - opba = opaque; opba->cr = 0x00; /* No dynamic priorities - park disabled */ opba->pr = 0x11; } -static void ppc4xx_opba_init(hwaddr base) +static void ppc405_opba_realize(DeviceState *dev, Error **errp) { - ppc4xx_opba_t *opba; + Ppc405OpbaState *s = PPC405_OPBA(dev); - trace_opba_init(base); - - opba = g_new0(ppc4xx_opba_t, 1); - memory_region_init_io(&opba->io, NULL, &opba_ops, opba, "opba", 0x002); - memory_region_add_subregion(get_system_memory(), base, &opba->io); - qemu_register_reset(ppc4xx_opba_reset, opba); + memory_region_init_io(&s->io, OBJECT(s), &opba_ops, s, "opba", 2); + sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->io); } -/*****************************************************************************/ -/* Code decompression controller */ -/* XXX: TODO */ - -/*****************************************************************************/ -/* Peripheral controller */ -typedef struct ppc4xx_ebc_t ppc4xx_ebc_t; -struct ppc4xx_ebc_t { - uint32_t addr; - uint32_t bcr[8]; - uint32_t bap[8]; - uint32_t bear; - uint32_t besr0; - uint32_t besr1; - uint32_t cfg; -}; - -enum { - EBC0_CFGADDR = 0x012, - EBC0_CFGDATA = 0x013, -}; - -static uint32_t dcr_read_ebc (void *opaque, int dcrn) +static void ppc405_opba_class_init(ObjectClass *oc, void *data) { - ppc4xx_ebc_t *ebc; - uint32_t ret; + DeviceClass *dc = DEVICE_CLASS(oc); - ebc = opaque; - switch (dcrn) { - case EBC0_CFGADDR: - ret = ebc->addr; - break; - case EBC0_CFGDATA: - switch (ebc->addr) { - case 0x00: /* B0CR */ - ret = ebc->bcr[0]; - break; - case 0x01: /* B1CR */ - ret = ebc->bcr[1]; - break; - case 0x02: /* B2CR */ - ret = ebc->bcr[2]; - break; - case 0x03: /* B3CR */ - ret = ebc->bcr[3]; - break; - case 0x04: /* B4CR */ - ret = ebc->bcr[4]; - break; - case 0x05: /* B5CR */ - ret = ebc->bcr[5]; - break; - case 0x06: /* B6CR */ - ret = ebc->bcr[6]; - break; - case 0x07: /* B7CR */ - ret = ebc->bcr[7]; - break; - case 0x10: /* B0AP */ - ret = ebc->bap[0]; - break; - case 0x11: /* B1AP */ - ret = ebc->bap[1]; - break; - case 0x12: /* B2AP */ - ret = ebc->bap[2]; - break; - case 0x13: /* B3AP */ - ret = ebc->bap[3]; - break; - case 0x14: /* B4AP */ - ret = ebc->bap[4]; - break; - case 0x15: /* B5AP */ - ret = ebc->bap[5]; - break; - case 0x16: /* B6AP */ - ret = ebc->bap[6]; - break; - case 0x17: /* B7AP */ - ret = ebc->bap[7]; - break; - case 0x20: /* BEAR */ - ret = ebc->bear; - break; - case 0x21: /* BESR0 */ - ret = ebc->besr0; - break; - case 0x22: /* BESR1 */ - ret = ebc->besr1; - break; - case 0x23: /* CFG */ - ret = ebc->cfg; - break; - default: - ret = 0x00000000; - break; - } - break; - default: - ret = 0x00000000; - break; - } - - return ret; -} - -static void dcr_write_ebc (void *opaque, int dcrn, uint32_t val) -{ - ppc4xx_ebc_t *ebc; - - ebc = opaque; - switch (dcrn) { - case EBC0_CFGADDR: - ebc->addr = val; - break; - case EBC0_CFGDATA: - switch (ebc->addr) { - case 0x00: /* B0CR */ - break; - case 0x01: /* B1CR */ - break; - case 0x02: /* B2CR */ - break; - case 0x03: /* B3CR */ - break; - case 0x04: /* B4CR */ - break; - case 0x05: /* B5CR */ - break; - case 0x06: /* B6CR */ - break; - case 0x07: /* B7CR */ - break; - case 0x10: /* B0AP */ - break; - case 0x11: /* B1AP */ - break; - case 0x12: /* B2AP */ - break; - case 0x13: /* B3AP */ - break; - case 0x14: /* B4AP */ - break; - case 0x15: /* B5AP */ - break; - case 0x16: /* B6AP */ - break; - case 0x17: /* B7AP */ - break; - case 0x20: /* BEAR */ - break; - case 0x21: /* BESR0 */ - break; - case 0x22: /* BESR1 */ - break; - case 0x23: /* CFG */ - break; - default: - break; - } - break; - default: - break; - } -} - -static void ebc_reset (void *opaque) -{ - ppc4xx_ebc_t *ebc; - int i; - - ebc = opaque; - ebc->addr = 0x00000000; - ebc->bap[0] = 0x7F8FFE80; - ebc->bcr[0] = 0xFFE28000; - for (i = 0; i < 8; i++) { - ebc->bap[i] = 0x00000000; - ebc->bcr[i] = 0x00000000; - } - ebc->besr0 = 0x00000000; - ebc->besr1 = 0x00000000; - ebc->cfg = 0x80400000; + dc->realize = ppc405_opba_realize; + dc->reset = ppc405_opba_reset; + /* Reason: only works as function of a ppc4xx SoC */ + dc->user_creatable = false; } -void ppc405_ebc_init(CPUPPCState *env) -{ - ppc4xx_ebc_t *ebc; - - ebc = g_new0(ppc4xx_ebc_t, 1); - qemu_register_reset(&ebc_reset, ebc); - ppc_dcr_register(env, EBC0_CFGADDR, - ebc, &dcr_read_ebc, &dcr_write_ebc); - ppc_dcr_register(env, EBC0_CFGDATA, - ebc, &dcr_read_ebc, &dcr_write_ebc); -} +/*****************************************************************************/ +/* Code decompression controller */ +/* XXX: TODO */ /*****************************************************************************/ /* DMA controller */ @@ -612,35 +236,20 @@ enum { DMA0_POL = 0x126, }; -typedef struct ppc405_dma_t ppc405_dma_t; -struct ppc405_dma_t { - qemu_irq irqs[4]; - uint32_t cr[4]; - uint32_t ct[4]; - uint32_t da[4]; - uint32_t sa[4]; - uint32_t sg[4]; - uint32_t sr; - uint32_t sgc; - uint32_t slp; - uint32_t pol; -}; - -static uint32_t dcr_read_dma (void *opaque, int dcrn) +static uint32_t dcr_read_dma(void *opaque, int dcrn) { return 0; } -static void dcr_write_dma (void *opaque, int dcrn, uint32_t val) +static void dcr_write_dma(void *opaque, int dcrn, uint32_t val) { } -static void ppc405_dma_reset (void *opaque) +static void ppc405_dma_reset(DeviceState *dev) { - ppc405_dma_t *dma; + Ppc405DmaState *dma = PPC405_DMA(dev); int i; - dma = opaque; for (i = 0; i < 4; i++) { dma->cr[i] = 0x00000000; dma->ct[i] = 0x00000000; @@ -654,81 +263,54 @@ static void ppc405_dma_reset (void *opaque) dma->pol = 0x00000000; } -static void ppc405_dma_init(CPUPPCState *env, qemu_irq irqs[4]) +static void ppc405_dma_realize(DeviceState *dev, Error **errp) { - ppc405_dma_t *dma; - - dma = g_new0(ppc405_dma_t, 1); - memcpy(dma->irqs, irqs, 4 * sizeof(qemu_irq)); - qemu_register_reset(&ppc405_dma_reset, dma); - ppc_dcr_register(env, DMA0_CR0, - dma, &dcr_read_dma, &dcr_write_dma); - ppc_dcr_register(env, DMA0_CT0, - dma, &dcr_read_dma, &dcr_write_dma); - ppc_dcr_register(env, DMA0_DA0, - dma, &dcr_read_dma, &dcr_write_dma); - ppc_dcr_register(env, DMA0_SA0, - dma, &dcr_read_dma, &dcr_write_dma); - ppc_dcr_register(env, DMA0_SG0, - dma, &dcr_read_dma, &dcr_write_dma); - ppc_dcr_register(env, DMA0_CR1, - dma, &dcr_read_dma, &dcr_write_dma); - ppc_dcr_register(env, DMA0_CT1, - dma, &dcr_read_dma, &dcr_write_dma); - ppc_dcr_register(env, DMA0_DA1, - dma, &dcr_read_dma, &dcr_write_dma); - ppc_dcr_register(env, DMA0_SA1, - dma, &dcr_read_dma, &dcr_write_dma); - ppc_dcr_register(env, DMA0_SG1, - dma, &dcr_read_dma, &dcr_write_dma); - ppc_dcr_register(env, DMA0_CR2, - dma, &dcr_read_dma, &dcr_write_dma); - ppc_dcr_register(env, DMA0_CT2, - dma, &dcr_read_dma, &dcr_write_dma); - ppc_dcr_register(env, DMA0_DA2, - dma, &dcr_read_dma, &dcr_write_dma); - ppc_dcr_register(env, DMA0_SA2, - dma, &dcr_read_dma, &dcr_write_dma); - ppc_dcr_register(env, DMA0_SG2, - dma, &dcr_read_dma, &dcr_write_dma); - ppc_dcr_register(env, DMA0_CR3, - dma, &dcr_read_dma, &dcr_write_dma); - ppc_dcr_register(env, DMA0_CT3, - dma, &dcr_read_dma, &dcr_write_dma); - ppc_dcr_register(env, DMA0_DA3, - dma, &dcr_read_dma, &dcr_write_dma); - ppc_dcr_register(env, DMA0_SA3, - dma, &dcr_read_dma, &dcr_write_dma); - ppc_dcr_register(env, DMA0_SG3, - dma, &dcr_read_dma, &dcr_write_dma); - ppc_dcr_register(env, DMA0_SR, - dma, &dcr_read_dma, &dcr_write_dma); - ppc_dcr_register(env, DMA0_SGC, - dma, &dcr_read_dma, &dcr_write_dma); - ppc_dcr_register(env, DMA0_SLP, - dma, &dcr_read_dma, &dcr_write_dma); - ppc_dcr_register(env, DMA0_POL, - dma, &dcr_read_dma, &dcr_write_dma); + Ppc405DmaState *dma = PPC405_DMA(dev); + Ppc4xxDcrDeviceState *dcr = PPC4xx_DCR_DEVICE(dev); + int i; + + for (i = 0; i < ARRAY_SIZE(dma->irqs); i++) { + sysbus_init_irq(SYS_BUS_DEVICE(dma), &dma->irqs[i]); + } + + ppc4xx_dcr_register(dcr, DMA0_CR0, dma, &dcr_read_dma, &dcr_write_dma); + ppc4xx_dcr_register(dcr, DMA0_CT0, dma, &dcr_read_dma, &dcr_write_dma); + ppc4xx_dcr_register(dcr, DMA0_DA0, dma, &dcr_read_dma, &dcr_write_dma); + ppc4xx_dcr_register(dcr, DMA0_SA0, dma, &dcr_read_dma, &dcr_write_dma); + ppc4xx_dcr_register(dcr, DMA0_SG0, dma, &dcr_read_dma, &dcr_write_dma); + ppc4xx_dcr_register(dcr, DMA0_CR1, dma, &dcr_read_dma, &dcr_write_dma); + ppc4xx_dcr_register(dcr, DMA0_CT1, dma, &dcr_read_dma, &dcr_write_dma); + ppc4xx_dcr_register(dcr, DMA0_DA1, dma, &dcr_read_dma, &dcr_write_dma); + ppc4xx_dcr_register(dcr, DMA0_SA1, dma, &dcr_read_dma, &dcr_write_dma); + ppc4xx_dcr_register(dcr, DMA0_SG1, dma, &dcr_read_dma, &dcr_write_dma); + ppc4xx_dcr_register(dcr, DMA0_CR2, dma, &dcr_read_dma, &dcr_write_dma); + ppc4xx_dcr_register(dcr, DMA0_CT2, dma, &dcr_read_dma, &dcr_write_dma); + ppc4xx_dcr_register(dcr, DMA0_DA2, dma, &dcr_read_dma, &dcr_write_dma); + ppc4xx_dcr_register(dcr, DMA0_SA2, dma, &dcr_read_dma, &dcr_write_dma); + ppc4xx_dcr_register(dcr, DMA0_SG2, dma, &dcr_read_dma, &dcr_write_dma); + ppc4xx_dcr_register(dcr, DMA0_CR3, dma, &dcr_read_dma, &dcr_write_dma); + ppc4xx_dcr_register(dcr, DMA0_CT3, dma, &dcr_read_dma, &dcr_write_dma); + ppc4xx_dcr_register(dcr, DMA0_DA3, dma, &dcr_read_dma, &dcr_write_dma); + ppc4xx_dcr_register(dcr, DMA0_SA3, dma, &dcr_read_dma, &dcr_write_dma); + ppc4xx_dcr_register(dcr, DMA0_SG3, dma, &dcr_read_dma, &dcr_write_dma); + ppc4xx_dcr_register(dcr, DMA0_SR, dma, &dcr_read_dma, &dcr_write_dma); + ppc4xx_dcr_register(dcr, DMA0_SGC, dma, &dcr_read_dma, &dcr_write_dma); + ppc4xx_dcr_register(dcr, DMA0_SLP, dma, &dcr_read_dma, &dcr_write_dma); + ppc4xx_dcr_register(dcr, DMA0_POL, dma, &dcr_read_dma, &dcr_write_dma); +} + +static void ppc405_dma_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + + dc->realize = ppc405_dma_realize; + dc->reset = ppc405_dma_reset; + /* Reason: only works as function of a ppc4xx SoC */ + dc->user_creatable = false; } /*****************************************************************************/ /* GPIO */ -typedef struct ppc405_gpio_t ppc405_gpio_t; -struct ppc405_gpio_t { - MemoryRegion io; - uint32_t or; - uint32_t tcr; - uint32_t osrh; - uint32_t osrl; - uint32_t tsrh; - uint32_t tsrl; - uint32_t odr; - uint32_t ir; - uint32_t rr1; - uint32_t isr1h; - uint32_t isr1l; -}; - static uint64_t ppc405_gpio_read(void *opaque, hwaddr addr, unsigned size) { trace_ppc405_gpio_read(addr, size); @@ -747,20 +329,22 @@ static const MemoryRegionOps ppc405_gpio_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -static void ppc405_gpio_reset (void *opaque) +static void ppc405_gpio_realize(DeviceState *dev, Error **errp) { + Ppc405GpioState *s = PPC405_GPIO(dev); + + memory_region_init_io(&s->io, OBJECT(s), &ppc405_gpio_ops, s, "gpio", + 0x38); + sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->io); } -static void ppc405_gpio_init(hwaddr base) +static void ppc405_gpio_class_init(ObjectClass *oc, void *data) { - ppc405_gpio_t *gpio; - - trace_ppc405_gpio_init(base); + DeviceClass *dc = DEVICE_CLASS(oc); - gpio = g_new0(ppc405_gpio_t, 1); - memory_region_init_io(&gpio->io, NULL, &ppc405_gpio_ops, gpio, "pgio", 0x038); - memory_region_add_subregion(get_system_memory(), base, &gpio->io); - qemu_register_reset(&ppc405_gpio_reset, gpio); + dc->realize = ppc405_gpio_realize; + /* Reason: only works as function of a ppc4xx SoC */ + dc->user_creatable = false; } /*****************************************************************************/ @@ -772,20 +356,9 @@ enum { OCM0_DSACNTL = 0x01B, }; -typedef struct ppc405_ocm_t ppc405_ocm_t; -struct ppc405_ocm_t { - MemoryRegion ram; - MemoryRegion isarc_ram; - MemoryRegion dsarc_ram; - uint32_t isarc; - uint32_t isacntl; - uint32_t dsarc; - uint32_t dsacntl; -}; - -static void ocm_update_mappings (ppc405_ocm_t *ocm, - uint32_t isarc, uint32_t isacntl, - uint32_t dsarc, uint32_t dsacntl) +static void ocm_update_mappings(Ppc405OcmState *ocm, + uint32_t isarc, uint32_t isacntl, + uint32_t dsarc, uint32_t dsacntl) { trace_ocm_update_mappings(isarc, isacntl, dsarc, dsacntl, ocm->isarc, ocm->isacntl, ocm->dsarc, ocm->dsacntl); @@ -827,12 +400,11 @@ static void ocm_update_mappings (ppc405_ocm_t *ocm, } } -static uint32_t dcr_read_ocm (void *opaque, int dcrn) +static uint32_t dcr_read_ocm(void *opaque, int dcrn) { - ppc405_ocm_t *ocm; + Ppc405OcmState *ocm = opaque; uint32_t ret; - ocm = opaque; switch (dcrn) { case OCM0_ISARC: ret = ocm->isarc; @@ -854,12 +426,11 @@ static uint32_t dcr_read_ocm (void *opaque, int dcrn) return ret; } -static void dcr_write_ocm (void *opaque, int dcrn, uint32_t val) +static void dcr_write_ocm(void *opaque, int dcrn, uint32_t val) { - ppc405_ocm_t *ocm; + Ppc405OcmState *ocm = opaque; uint32_t isarc, dsarc, isacntl, dsacntl; - ocm = opaque; isarc = ocm->isarc; dsarc = ocm->dsarc; isacntl = ocm->isacntl; @@ -885,12 +456,11 @@ static void dcr_write_ocm (void *opaque, int dcrn, uint32_t val) ocm->dsacntl = dsacntl; } -static void ocm_reset (void *opaque) +static void ppc405_ocm_reset(DeviceState *dev) { - ppc405_ocm_t *ocm; + Ppc405OcmState *ocm = PPC405_OCM(dev); uint32_t isarc, dsarc, isacntl, dsacntl; - ocm = opaque; isarc = 0x00000000; isacntl = 0x00000000; dsarc = 0x00000000; @@ -902,57 +472,47 @@ static void ocm_reset (void *opaque) ocm->dsacntl = dsacntl; } -static void ppc405_ocm_init(CPUPPCState *env) +static void ppc405_ocm_realize(DeviceState *dev, Error **errp) { - ppc405_ocm_t *ocm; + Ppc405OcmState *ocm = PPC405_OCM(dev); + Ppc4xxDcrDeviceState *dcr = PPC4xx_DCR_DEVICE(dev); - ocm = g_new0(ppc405_ocm_t, 1); /* XXX: Size is 4096 or 0x04000000 */ - memory_region_init_ram(&ocm->isarc_ram, NULL, "ppc405.ocm", 4 * KiB, + memory_region_init_ram(&ocm->isarc_ram, OBJECT(ocm), "ppc405.ocm", 4 * KiB, &error_fatal); - memory_region_init_alias(&ocm->dsarc_ram, NULL, "ppc405.dsarc", + memory_region_init_alias(&ocm->dsarc_ram, OBJECT(ocm), "ppc405.dsarc", &ocm->isarc_ram, 0, 4 * KiB); - qemu_register_reset(&ocm_reset, ocm); - ppc_dcr_register(env, OCM0_ISARC, - ocm, &dcr_read_ocm, &dcr_write_ocm); - ppc_dcr_register(env, OCM0_ISACNTL, - ocm, &dcr_read_ocm, &dcr_write_ocm); - ppc_dcr_register(env, OCM0_DSARC, - ocm, &dcr_read_ocm, &dcr_write_ocm); - ppc_dcr_register(env, OCM0_DSACNTL, - ocm, &dcr_read_ocm, &dcr_write_ocm); + + ppc4xx_dcr_register(dcr, OCM0_ISARC, ocm, &dcr_read_ocm, &dcr_write_ocm); + ppc4xx_dcr_register(dcr, OCM0_ISACNTL, ocm, &dcr_read_ocm, &dcr_write_ocm); + ppc4xx_dcr_register(dcr, OCM0_DSARC, ocm, &dcr_read_ocm, &dcr_write_ocm); + ppc4xx_dcr_register(dcr, OCM0_DSACNTL, ocm, &dcr_read_ocm, &dcr_write_ocm); +} + +static void ppc405_ocm_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + + dc->realize = ppc405_ocm_realize; + dc->reset = ppc405_ocm_reset; + /* Reason: only works as function of a ppc4xx SoC */ + dc->user_creatable = false; } /*****************************************************************************/ /* General purpose timers */ -typedef struct ppc4xx_gpt_t ppc4xx_gpt_t; -struct ppc4xx_gpt_t { - MemoryRegion iomem; - int64_t tb_offset; - uint32_t tb_freq; - QEMUTimer *timer; - qemu_irq irqs[5]; - uint32_t oe; - uint32_t ol; - uint32_t im; - uint32_t is; - uint32_t ie; - uint32_t comp[5]; - uint32_t mask[5]; -}; - -static int ppc4xx_gpt_compare (ppc4xx_gpt_t *gpt, int n) +static int ppc4xx_gpt_compare(Ppc405GptState *gpt, int n) { /* XXX: TODO */ return 0; } -static void ppc4xx_gpt_set_output (ppc4xx_gpt_t *gpt, int n, int level) +static void ppc4xx_gpt_set_output(Ppc405GptState *gpt, int n, int level) { /* XXX: TODO */ } -static void ppc4xx_gpt_set_outputs (ppc4xx_gpt_t *gpt) +static void ppc4xx_gpt_set_outputs(Ppc405GptState *gpt) { uint32_t mask; int i; @@ -973,29 +533,30 @@ static void ppc4xx_gpt_set_outputs (ppc4xx_gpt_t *gpt) } } -static void ppc4xx_gpt_set_irqs (ppc4xx_gpt_t *gpt) +static void ppc4xx_gpt_set_irqs(Ppc405GptState *gpt) { uint32_t mask; int i; mask = 0x00008000; for (i = 0; i < 5; i++) { - if (gpt->is & gpt->im & mask) + if (gpt->is & gpt->im & mask) { qemu_irq_raise(gpt->irqs[i]); - else + } else { qemu_irq_lower(gpt->irqs[i]); + } mask = mask >> 1; } } -static void ppc4xx_gpt_compute_timer (ppc4xx_gpt_t *gpt) +static void ppc4xx_gpt_compute_timer(Ppc405GptState *gpt) { /* XXX: TODO */ } static uint64_t ppc4xx_gpt_read(void *opaque, hwaddr addr, unsigned size) { - ppc4xx_gpt_t *gpt = opaque; + Ppc405GptState *gpt = opaque; uint32_t ret; int idx; @@ -1049,7 +610,7 @@ static uint64_t ppc4xx_gpt_read(void *opaque, hwaddr addr, unsigned size) static void ppc4xx_gpt_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { - ppc4xx_gpt_t *gpt = opaque; + Ppc405GptState *gpt = opaque; int idx; trace_ppc4xx_gpt_write(addr, size, value); @@ -1113,22 +674,20 @@ static const MemoryRegionOps gpt_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -static void ppc4xx_gpt_cb (void *opaque) +static void ppc4xx_gpt_cb(void *opaque) { - ppc4xx_gpt_t *gpt; + Ppc405GptState *gpt = opaque; - gpt = opaque; ppc4xx_gpt_set_irqs(gpt); ppc4xx_gpt_set_outputs(gpt); ppc4xx_gpt_compute_timer(gpt); } -static void ppc4xx_gpt_reset (void *opaque) +static void ppc405_gpt_reset(DeviceState *dev) { - ppc4xx_gpt_t *gpt; + Ppc405GptState *gpt = PPC405_GPT(dev); int i; - gpt = opaque; timer_del(gpt->timer); gpt->oe = 0x00000000; gpt->ol = 0x00000000; @@ -1141,21 +700,37 @@ static void ppc4xx_gpt_reset (void *opaque) } } -static void ppc4xx_gpt_init(hwaddr base, qemu_irq irqs[5]) +static void ppc405_gpt_realize(DeviceState *dev, Error **errp) { - ppc4xx_gpt_t *gpt; + Ppc405GptState *s = PPC405_GPT(dev); + SysBusDevice *sbd = SYS_BUS_DEVICE(dev); int i; - trace_ppc4xx_gpt_init(base); + s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &ppc4xx_gpt_cb, s); + memory_region_init_io(&s->iomem, OBJECT(s), &gpt_ops, s, "gpt", 0xd4); + sysbus_init_mmio(sbd, &s->iomem); - gpt = g_new0(ppc4xx_gpt_t, 1); - for (i = 0; i < 5; i++) { - gpt->irqs[i] = irqs[i]; + for (i = 0; i < ARRAY_SIZE(s->irqs); i++) { + sysbus_init_irq(sbd, &s->irqs[i]); } - gpt->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &ppc4xx_gpt_cb, gpt); - memory_region_init_io(&gpt->iomem, NULL, &gpt_ops, gpt, "gpt", 0x0d4); - memory_region_add_subregion(get_system_memory(), base, &gpt->iomem); - qemu_register_reset(ppc4xx_gpt_reset, gpt); +} + +static void ppc405_gpt_finalize(Object *obj) +{ + /* timer will be NULL if the GPT wasn't realized */ + if (PPC405_GPT(obj)->timer) { + timer_del(PPC405_GPT(obj)->timer); + } +} + +static void ppc405_gpt_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + + dc->realize = ppc405_gpt_realize; + dc->reset = ppc405_gpt_reset; + /* Reason: only works as function of a ppc4xx SoC */ + dc->user_creatable = false; } /*****************************************************************************/ @@ -1177,36 +752,7 @@ enum { #endif }; -enum { - PPC405EP_CPU_CLK = 0, - PPC405EP_PLB_CLK = 1, - PPC405EP_OPB_CLK = 2, - PPC405EP_EBC_CLK = 3, - PPC405EP_MAL_CLK = 4, - PPC405EP_PCI_CLK = 5, - PPC405EP_UART0_CLK = 6, - PPC405EP_UART1_CLK = 7, - PPC405EP_CLK_NB = 8, -}; - -typedef struct ppc405ep_cpc_t ppc405ep_cpc_t; -struct ppc405ep_cpc_t { - uint32_t sysclk; - clk_setup_t clk_setup[PPC405EP_CLK_NB]; - uint32_t boot; - uint32_t epctl; - uint32_t pllmr[2]; - uint32_t ucr; - uint32_t srr; - uint32_t jtagid; - uint32_t pci; - /* Clock and power management */ - uint32_t er; - uint32_t fr; - uint32_t sr; -}; - -static void ppc405ep_compute_clocks (ppc405ep_cpc_t *cpc) +static void ppc405ep_compute_clocks(Ppc405CpcState *cpc) { uint32_t CPU_clk, PLB_clk, OPB_clk, EBC_clk, MAL_clk, PCI_clk; uint32_t UART0_clk, UART1_clk; @@ -1299,12 +845,11 @@ static void ppc405ep_compute_clocks (ppc405ep_cpc_t *cpc) clk_setup(&cpc->clk_setup[PPC405EP_UART1_CLK], UART1_clk); } -static uint32_t dcr_read_epcpc (void *opaque, int dcrn) +static uint32_t dcr_read_epcpc(void *opaque, int dcrn) { - ppc405ep_cpc_t *cpc; + Ppc405CpcState *cpc = opaque; uint32_t ret; - cpc = opaque; switch (dcrn) { case PPC405EP_CPC0_BOOT: ret = cpc->boot; @@ -1339,11 +884,10 @@ static uint32_t dcr_read_epcpc (void *opaque, int dcrn) return ret; } -static void dcr_write_epcpc (void *opaque, int dcrn, uint32_t val) +static void dcr_write_epcpc(void *opaque, int dcrn, uint32_t val) { - ppc405ep_cpc_t *cpc; + Ppc405CpcState *cpc = opaque; - cpc = opaque; switch (dcrn) { case PPC405EP_CPC0_BOOT: /* Read-only register */ @@ -1376,9 +920,9 @@ static void dcr_write_epcpc (void *opaque, int dcrn, uint32_t val) } } -static void ppc405ep_cpc_reset (void *opaque) +static void ppc405_cpc_reset(DeviceState *dev) { - ppc405ep_cpc_t *cpc = opaque; + Ppc405CpcState *cpc = PPC405_CPC(dev); cpc->boot = 0x00000010; /* Boot from PCI - IIC EEPROM disabled */ cpc->epctl = 0x00000000; @@ -1390,143 +934,291 @@ static void ppc405ep_cpc_reset (void *opaque) cpc->er = 0x00000000; cpc->fr = 0x00000000; cpc->sr = 0x00000000; + cpc->jtagid = 0x20267049; ppc405ep_compute_clocks(cpc); } /* XXX: sysclk should be between 25 and 100 MHz */ -static void ppc405ep_cpc_init (CPUPPCState *env, clk_setup_t clk_setup[8], - uint32_t sysclk) +static void ppc405_cpc_realize(DeviceState *dev, Error **errp) { - ppc405ep_cpc_t *cpc; + Ppc405CpcState *cpc = PPC405_CPC(dev); + Ppc4xxDcrDeviceState *dcr = PPC4xx_DCR_DEVICE(dev); + + assert(dcr->cpu); + cpc->clk_setup[PPC405EP_CPU_CLK].cb = + ppc_40x_timers_init(&dcr->cpu->env, cpc->sysclk, PPC_INTERRUPT_PIT); + cpc->clk_setup[PPC405EP_CPU_CLK].opaque = &dcr->cpu->env; + + ppc4xx_dcr_register(dcr, PPC405EP_CPC0_BOOT, cpc, + &dcr_read_epcpc, &dcr_write_epcpc); + ppc4xx_dcr_register(dcr, PPC405EP_CPC0_EPCTL, cpc, + &dcr_read_epcpc, &dcr_write_epcpc); + ppc4xx_dcr_register(dcr, PPC405EP_CPC0_PLLMR0, cpc, + &dcr_read_epcpc, &dcr_write_epcpc); + ppc4xx_dcr_register(dcr, PPC405EP_CPC0_PLLMR1, cpc, + &dcr_read_epcpc, &dcr_write_epcpc); + ppc4xx_dcr_register(dcr, PPC405EP_CPC0_UCR, cpc, + &dcr_read_epcpc, &dcr_write_epcpc); + ppc4xx_dcr_register(dcr, PPC405EP_CPC0_SRR, cpc, + &dcr_read_epcpc, &dcr_write_epcpc); + ppc4xx_dcr_register(dcr, PPC405EP_CPC0_JTAGID, cpc, + &dcr_read_epcpc, &dcr_write_epcpc); + ppc4xx_dcr_register(dcr, PPC405EP_CPC0_PCI, cpc, + &dcr_read_epcpc, &dcr_write_epcpc); +} - cpc = g_new0(ppc405ep_cpc_t, 1); - memcpy(cpc->clk_setup, clk_setup, - PPC405EP_CLK_NB * sizeof(clk_setup_t)); - cpc->jtagid = 0x20267049; - cpc->sysclk = sysclk; - qemu_register_reset(&ppc405ep_cpc_reset, cpc); - ppc_dcr_register(env, PPC405EP_CPC0_BOOT, cpc, - &dcr_read_epcpc, &dcr_write_epcpc); - ppc_dcr_register(env, PPC405EP_CPC0_EPCTL, cpc, - &dcr_read_epcpc, &dcr_write_epcpc); - ppc_dcr_register(env, PPC405EP_CPC0_PLLMR0, cpc, - &dcr_read_epcpc, &dcr_write_epcpc); - ppc_dcr_register(env, PPC405EP_CPC0_PLLMR1, cpc, - &dcr_read_epcpc, &dcr_write_epcpc); - ppc_dcr_register(env, PPC405EP_CPC0_UCR, cpc, - &dcr_read_epcpc, &dcr_write_epcpc); - ppc_dcr_register(env, PPC405EP_CPC0_SRR, cpc, - &dcr_read_epcpc, &dcr_write_epcpc); - ppc_dcr_register(env, PPC405EP_CPC0_JTAGID, cpc, - &dcr_read_epcpc, &dcr_write_epcpc); - ppc_dcr_register(env, PPC405EP_CPC0_PCI, cpc, - &dcr_read_epcpc, &dcr_write_epcpc); -#if 0 - ppc_dcr_register(env, PPC405EP_CPC0_ER, cpc, - &dcr_read_epcpc, &dcr_write_epcpc); - ppc_dcr_register(env, PPC405EP_CPC0_FR, cpc, - &dcr_read_epcpc, &dcr_write_epcpc); - ppc_dcr_register(env, PPC405EP_CPC0_SR, cpc, - &dcr_read_epcpc, &dcr_write_epcpc); -#endif +static Property ppc405_cpc_properties[] = { + DEFINE_PROP_UINT32("sys-clk", Ppc405CpcState, sysclk, 0), + DEFINE_PROP_END_OF_LIST(), +}; + +static void ppc405_cpc_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + + dc->realize = ppc405_cpc_realize; + dc->reset = ppc405_cpc_reset; + /* Reason: only works as function of a ppc4xx SoC */ + dc->user_creatable = false; + device_class_set_props(dc, ppc405_cpc_properties); } -PowerPCCPU *ppc405ep_init(MemoryRegion *address_space_mem, - MemoryRegion ram_memories[2], - hwaddr ram_bases[2], - hwaddr ram_sizes[2], - uint32_t sysclk, DeviceState **uicdevp, - int do_init) +/* PPC405_SOC */ + +static void ppc405_soc_instance_init(Object *obj) { - clk_setup_t clk_setup[PPC405EP_CLK_NB], tlb_clk_setup; - qemu_irq dma_irqs[4], gpt_irqs[5], mal_irqs[4]; - PowerPCCPU *cpu; + Ppc405SoCState *s = PPC405_SOC(obj); + + object_initialize_child(obj, "cpu", &s->cpu, + POWERPC_CPU_TYPE_NAME("405ep")); + + object_initialize_child(obj, "uic", &s->uic, TYPE_PPC_UIC); + + object_initialize_child(obj, "cpc", &s->cpc, TYPE_PPC405_CPC); + object_property_add_alias(obj, "sys-clk", OBJECT(&s->cpc), "sys-clk"); + + object_initialize_child(obj, "gpt", &s->gpt, TYPE_PPC405_GPT); + + object_initialize_child(obj, "ocm", &s->ocm, TYPE_PPC405_OCM); + + object_initialize_child(obj, "gpio", &s->gpio, TYPE_PPC405_GPIO); + + object_initialize_child(obj, "dma", &s->dma, TYPE_PPC405_DMA); + + object_initialize_child(obj, "i2c", &s->i2c, TYPE_PPC4xx_I2C); + + object_initialize_child(obj, "ebc", &s->ebc, TYPE_PPC4xx_EBC); + + object_initialize_child(obj, "opba", &s->opba, TYPE_PPC405_OPBA); + + object_initialize_child(obj, "pob", &s->pob, TYPE_PPC405_POB); + + object_initialize_child(obj, "plb", &s->plb, TYPE_PPC4xx_PLB); + + object_initialize_child(obj, "mal", &s->mal, TYPE_PPC4xx_MAL); +} + +static void ppc405_reset(void *opaque) +{ + cpu_reset(CPU(opaque)); +} + +static void ppc405_soc_realize(DeviceState *dev, Error **errp) +{ + Ppc405SoCState *s = PPC405_SOC(dev); CPUPPCState *env; - DeviceState *uicdev; - SysBusDevice *uicsbd; + SysBusDevice *sbd; + int i; - memset(clk_setup, 0, sizeof(clk_setup)); /* init CPUs */ - cpu = ppc4xx_init(POWERPC_CPU_TYPE_NAME("405ep"), - &clk_setup[PPC405EP_CPU_CLK], - &tlb_clk_setup, sysclk); - env = &cpu->env; - clk_setup[PPC405EP_CPU_CLK].cb = tlb_clk_setup.cb; - clk_setup[PPC405EP_CPU_CLK].opaque = tlb_clk_setup.opaque; - /* Internal devices init */ - /* Memory mapped devices registers */ + if (!qdev_realize(DEVICE(&s->cpu), NULL, errp)) { + return; + } + qemu_register_reset(ppc405_reset, &s->cpu); + + env = &s->cpu.env; + + ppc_dcr_init(env, NULL, NULL); + + /* CPU control */ + if (!ppc4xx_dcr_realize(PPC4xx_DCR_DEVICE(&s->cpc), &s->cpu, errp)) { + return; + } + /* PLB arbitrer */ - ppc4xx_plb_init(env); - /* PLB to OPB bridge */ - ppc4xx_pob_init(env); - /* OBP arbitrer */ - ppc4xx_opba_init(0xef600600); - /* Universal interrupt controller */ - uicdev = qdev_new(TYPE_PPC_UIC); - uicsbd = SYS_BUS_DEVICE(uicdev); + if (!ppc4xx_dcr_realize(PPC4xx_DCR_DEVICE(&s->plb), &s->cpu, errp)) { + return; + } - object_property_set_link(OBJECT(uicdev), "cpu", OBJECT(cpu), - &error_fatal); - sysbus_realize_and_unref(uicsbd, &error_fatal); + /* PLB to OPB bridge */ + if (!ppc4xx_dcr_realize(PPC4xx_DCR_DEVICE(&s->pob), &s->cpu, errp)) { + return; + } - sysbus_connect_irq(uicsbd, PPCUIC_OUTPUT_INT, - qdev_get_gpio_in(DEVICE(cpu), PPC40x_INPUT_INT)); - sysbus_connect_irq(uicsbd, PPCUIC_OUTPUT_CINT, - qdev_get_gpio_in(DEVICE(cpu), PPC40x_INPUT_CINT)); + /* OBP arbitrer */ + sbd = SYS_BUS_DEVICE(&s->opba); + if (!sysbus_realize(sbd, errp)) { + return; + } + sysbus_mmio_map(sbd, 0, 0xef600600); - *uicdevp = uicdev; + /* Universal interrupt controller */ + if (!ppc4xx_dcr_realize(PPC4xx_DCR_DEVICE(&s->uic), &s->cpu, errp)) { + return; + } + sbd = SYS_BUS_DEVICE(&s->uic); + sysbus_connect_irq(sbd, PPCUIC_OUTPUT_INT, + qdev_get_gpio_in(DEVICE(&s->cpu), PPC40x_INPUT_INT)); + sysbus_connect_irq(sbd, PPCUIC_OUTPUT_CINT, + qdev_get_gpio_in(DEVICE(&s->cpu), PPC40x_INPUT_CINT)); /* SDRAM controller */ /* XXX 405EP has no ECC interrupt */ - ppc4xx_sdram_init(env, qdev_get_gpio_in(uicdev, 17), 2, ram_memories, - ram_bases, ram_sizes, do_init); + s->ram_bases[0] = 0; + s->ram_sizes[0] = s->ram_size; + memory_region_init_alias(&s->ram_banks[0], OBJECT(s), + "ppc405.sdram0", s->dram_mr, + s->ram_bases[0], s->ram_sizes[0]); + + ppc4xx_sdram_init(env, qdev_get_gpio_in(DEVICE(&s->uic), 17), 1, + s->ram_banks, s->ram_bases, s->ram_sizes, + s->do_dram_init); + /* External bus controller */ - ppc405_ebc_init(env); + if (!ppc4xx_dcr_realize(PPC4xx_DCR_DEVICE(&s->ebc), &s->cpu, errp)) { + return; + } + /* DMA controller */ - dma_irqs[0] = qdev_get_gpio_in(uicdev, 5); - dma_irqs[1] = qdev_get_gpio_in(uicdev, 6); - dma_irqs[2] = qdev_get_gpio_in(uicdev, 7); - dma_irqs[3] = qdev_get_gpio_in(uicdev, 8); - ppc405_dma_init(env, dma_irqs); - /* IIC controller */ - sysbus_create_simple(TYPE_PPC4xx_I2C, 0xef600500, - qdev_get_gpio_in(uicdev, 2)); + if (!ppc4xx_dcr_realize(PPC4xx_DCR_DEVICE(&s->dma), &s->cpu, errp)) { + return; + } + sbd = SYS_BUS_DEVICE(&s->dma); + for (i = 0; i < ARRAY_SIZE(s->dma.irqs); i++) { + sysbus_connect_irq(sbd, i, qdev_get_gpio_in(DEVICE(&s->uic), 5 + i)); + } + + /* I2C controller */ + sbd = SYS_BUS_DEVICE(&s->i2c); + if (!sysbus_realize(sbd, errp)) { + return; + } + sysbus_mmio_map(sbd, 0, 0xef600500); + sysbus_connect_irq(sbd, 0, qdev_get_gpio_in(DEVICE(&s->uic), 2)); + /* GPIO */ - ppc405_gpio_init(0xef600700); + sbd = SYS_BUS_DEVICE(&s->gpio); + if (!sysbus_realize(sbd, errp)) { + return; + } + sysbus_mmio_map(sbd, 0, 0xef600700); + /* Serial ports */ if (serial_hd(0) != NULL) { - serial_mm_init(address_space_mem, 0xef600300, 0, - qdev_get_gpio_in(uicdev, 0), + serial_mm_init(get_system_memory(), 0xef600300, 0, + qdev_get_gpio_in(DEVICE(&s->uic), 0), PPC_SERIAL_MM_BAUDBASE, serial_hd(0), DEVICE_BIG_ENDIAN); } if (serial_hd(1) != NULL) { - serial_mm_init(address_space_mem, 0xef600400, 0, - qdev_get_gpio_in(uicdev, 1), + serial_mm_init(get_system_memory(), 0xef600400, 0, + qdev_get_gpio_in(DEVICE(&s->uic), 1), PPC_SERIAL_MM_BAUDBASE, serial_hd(1), DEVICE_BIG_ENDIAN); } + /* OCM */ - ppc405_ocm_init(env); + if (!ppc4xx_dcr_realize(PPC4xx_DCR_DEVICE(&s->ocm), &s->cpu, errp)) { + return; + } + /* GPT */ - gpt_irqs[0] = qdev_get_gpio_in(uicdev, 19); - gpt_irqs[1] = qdev_get_gpio_in(uicdev, 20); - gpt_irqs[2] = qdev_get_gpio_in(uicdev, 21); - gpt_irqs[3] = qdev_get_gpio_in(uicdev, 22); - gpt_irqs[4] = qdev_get_gpio_in(uicdev, 23); - ppc4xx_gpt_init(0xef600000, gpt_irqs); - /* PCI */ - /* Uses UIC IRQs 3, 16, 18 */ + sbd = SYS_BUS_DEVICE(&s->gpt); + if (!sysbus_realize(sbd, errp)) { + return; + } + sysbus_mmio_map(sbd, 0, 0xef600000); + for (i = 0; i < ARRAY_SIZE(s->gpt.irqs); i++) { + sysbus_connect_irq(sbd, i, qdev_get_gpio_in(DEVICE(&s->uic), 19 + i)); + } + /* MAL */ - mal_irqs[0] = qdev_get_gpio_in(uicdev, 11); - mal_irqs[1] = qdev_get_gpio_in(uicdev, 12); - mal_irqs[2] = qdev_get_gpio_in(uicdev, 13); - mal_irqs[3] = qdev_get_gpio_in(uicdev, 14); - ppc4xx_mal_init(env, 4, 2, mal_irqs); + object_property_set_int(OBJECT(&s->mal), "txc-num", 4, &error_abort); + object_property_set_int(OBJECT(&s->mal), "rxc-num", 2, &error_abort); + if (!ppc4xx_dcr_realize(PPC4xx_DCR_DEVICE(&s->mal), &s->cpu, errp)) { + return; + } + sbd = SYS_BUS_DEVICE(&s->mal); + for (i = 0; i < ARRAY_SIZE(s->mal.irqs); i++) { + sysbus_connect_irq(sbd, i, qdev_get_gpio_in(DEVICE(&s->uic), 11 + i)); + } + /* Ethernet */ /* Uses UIC IRQs 9, 15, 17 */ - /* CPU control */ - ppc405ep_cpc_init(env, clk_setup, sysclk); +} + +static Property ppc405_soc_properties[] = { + DEFINE_PROP_LINK("dram", Ppc405SoCState, dram_mr, TYPE_MEMORY_REGION, + MemoryRegion *), + DEFINE_PROP_BOOL("dram-init", Ppc405SoCState, do_dram_init, 0), + DEFINE_PROP_UINT64("ram-size", Ppc405SoCState, ram_size, 0), + DEFINE_PROP_END_OF_LIST(), +}; + +static void ppc405_soc_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); - return cpu; + dc->realize = ppc405_soc_realize; + /* Reason: only works as part of a ppc405 board/machine */ + dc->user_creatable = false; + device_class_set_props(dc, ppc405_soc_properties); } + +static const TypeInfo ppc405_types[] = { + { + .name = TYPE_PPC405_POB, + .parent = TYPE_PPC4xx_DCR_DEVICE, + .instance_size = sizeof(Ppc405PobState), + .class_init = ppc405_pob_class_init, + }, { + .name = TYPE_PPC405_OPBA, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(Ppc405OpbaState), + .class_init = ppc405_opba_class_init, + }, { + .name = TYPE_PPC405_DMA, + .parent = TYPE_PPC4xx_DCR_DEVICE, + .instance_size = sizeof(Ppc405DmaState), + .class_init = ppc405_dma_class_init, + }, { + .name = TYPE_PPC405_GPIO, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(Ppc405GpioState), + .class_init = ppc405_gpio_class_init, + }, { + .name = TYPE_PPC405_OCM, + .parent = TYPE_PPC4xx_DCR_DEVICE, + .instance_size = sizeof(Ppc405OcmState), + .class_init = ppc405_ocm_class_init, + }, { + .name = TYPE_PPC405_GPT, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(Ppc405GptState), + .instance_finalize = ppc405_gpt_finalize, + .class_init = ppc405_gpt_class_init, + }, { + .name = TYPE_PPC405_CPC, + .parent = TYPE_PPC4xx_DCR_DEVICE, + .instance_size = sizeof(Ppc405CpcState), + .class_init = ppc405_cpc_class_init, + }, { + .name = TYPE_PPC405_SOC, + .parent = TYPE_DEVICE, + .instance_size = sizeof(Ppc405SoCState), + .instance_init = ppc405_soc_instance_init, + .class_init = ppc405_soc_class_init, + } +}; + +DEFINE_TYPES(ppc405_types) diff --git a/hw/ppc/ppc440_bamboo.c b/hw/ppc/ppc440_bamboo.c index 873f930c77..ea945a1c99 100644 --- a/hw/ppc/ppc440_bamboo.c +++ b/hw/ppc/ppc440_bamboo.c @@ -84,27 +84,30 @@ static int bamboo_load_device_tree(hwaddr addr, ret = qemu_fdt_setprop(fdt, "/memory", "reg", mem_reg_property, sizeof(mem_reg_property)); - if (ret < 0) + if (ret < 0) { fprintf(stderr, "couldn't set /memory/reg\n"); - + } ret = qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-start", initrd_base); - if (ret < 0) + if (ret < 0) { fprintf(stderr, "couldn't set /chosen/linux,initrd-start\n"); - + } ret = qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-end", (initrd_base + initrd_size)); - if (ret < 0) + if (ret < 0) { fprintf(stderr, "couldn't set /chosen/linux,initrd-end\n"); - + } ret = qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", kernel_cmdline); - if (ret < 0) + if (ret < 0) { fprintf(stderr, "couldn't set /chosen/bootargs\n"); + } - /* Copy data from the host device tree into the guest. Since the guest can + /* + * Copy data from the host device tree into the guest. Since the guest can * directly access the timebase without host involvement, we must expose - * the correct frequencies. */ + * the correct frequencies. + */ if (kvm_enabled()) { tb_freq = kvmppc_get_tbfreq(); clock_freq = kvmppc_get_clockfreq(); @@ -193,12 +196,9 @@ static void bamboo_init(MachineState *machine) /* interrupt controller */ uicdev = qdev_new(TYPE_PPC_UIC); + ppc4xx_dcr_realize(PPC4xx_DCR_DEVICE(uicdev), cpu, &error_fatal); + object_unref(OBJECT(uicdev)); uicsbd = SYS_BUS_DEVICE(uicdev); - - object_property_set_link(OBJECT(uicdev), "cpu", OBJECT(cpu), - &error_fatal); - sysbus_realize_and_unref(uicsbd, &error_fatal); - sysbus_connect_irq(uicsbd, PPCUIC_OUTPUT_INT, qdev_get_gpio_in(DEVICE(cpu), PPC40x_INPUT_INT)); sysbus_connect_irq(uicsbd, PPCUIC_OUTPUT_CINT, @@ -249,8 +249,10 @@ static void bamboo_init(MachineState *machine) if (pcibus) { /* Register network interfaces. */ for (i = 0; i < nb_nics; i++) { - /* There are no PCI NICs on the Bamboo board, but there are - * PCI slots, so we can pick whatever default model we want. */ + /* + * There are no PCI NICs on the Bamboo board, but there are + * PCI slots, so we can pick whatever default model we want. + */ pci_nic_init_nofail(&nd_table[i], pcibus, "e1000", NULL); } } diff --git a/hw/ppc/ppc440_uc.c b/hw/ppc/ppc440_uc.c index 11fdb88c22..53e981ddf4 100644 --- a/hw/ppc/ppc440_uc.c +++ b/hw/ppc/ppc440_uc.c @@ -1028,7 +1028,8 @@ void ppc4xx_dma_init(CPUPPCState *env, int dcr_base) /*****************************************************************************/ /* PCI Express controller */ -/* FIXME: This is not complete and does not work, only implemented partially +/* + * FIXME: This is not complete and does not work, only implemented partially * to allow firmware and guests to find an empty bus. Cards should use PCI. */ #include "hw/pci/pcie_host.h" diff --git a/hw/ppc/ppc4xx_devs.c b/hw/ppc/ppc4xx_devs.c index 737c0896b4..ce38ae65e6 100644 --- a/hw/ppc/ppc4xx_devs.c +++ b/hw/ppc/ppc4xx_devs.c @@ -29,7 +29,6 @@ #include "hw/irq.h" #include "hw/ppc/ppc.h" #include "hw/ppc/ppc4xx.h" -#include "hw/intc/ppc-uic.h" #include "hw/qdev-properties.h" #include "qemu/log.h" #include "exec/address-spaces.h" @@ -37,38 +36,6 @@ #include "qapi/error.h" #include "trace.h" -static void ppc4xx_reset(void *opaque) -{ - PowerPCCPU *cpu = opaque; - - cpu_reset(CPU(cpu)); -} - -/*****************************************************************************/ -/* Generic PowerPC 4xx processor instantiation */ -PowerPCCPU *ppc4xx_init(const char *cpu_type, - clk_setup_t *cpu_clk, clk_setup_t *tb_clk, - uint32_t sysclk) -{ - PowerPCCPU *cpu; - CPUPPCState *env; - - /* init CPUs */ - cpu = POWERPC_CPU(cpu_create(cpu_type)); - env = &cpu->env; - - cpu_clk->cb = NULL; /* We don't care about CPU clock frequency changes */ - cpu_clk->opaque = env; - /* Set time-base frequency to sysclk */ - tb_clk->cb = ppc_40x_timers_init(env, sysclk, PPC_INTERRUPT_PIT); - tb_clk->opaque = env; - ppc_dcr_init(env, NULL, NULL); - /* Register qemu callbacks */ - qemu_register_reset(ppc4xx_reset, cpu); - - return cpu; -} - /*****************************************************************************/ /* SDRAM controller */ typedef struct ppc4xx_sdram_t ppc4xx_sdram_t; @@ -98,12 +65,12 @@ enum { SDRAM0_CFGDATA = 0x011, }; -/* XXX: TOFIX: some patches have made this code become inconsistent: +/* + * XXX: TOFIX: some patches have made this code become inconsistent: * there are type inconsistencies, mixing hwaddr, target_ulong * and uint32_t */ -static uint32_t sdram_bcr (hwaddr ram_base, - hwaddr ram_size) +static uint32_t sdram_bcr(hwaddr ram_base, hwaddr ram_size) { uint32_t bcr; @@ -146,16 +113,17 @@ static inline hwaddr sdram_base(uint32_t bcr) return bcr & 0xFF800000; } -static target_ulong sdram_size (uint32_t bcr) +static target_ulong sdram_size(uint32_t bcr) { target_ulong size; int sh; sh = (bcr >> 17) & 0x7; - if (sh == 7) + if (sh == 7) { size = -1; - else + } else { size = (4 * MiB) << sh; + } return size; } @@ -175,7 +143,7 @@ static void sdram_set_bcr(ppc4xx_sdram_t *sdram, int i, } sdram->bcr[i] = bcr & 0xFFDEE001; if (enabled && (bcr & 0x00000001)) { - trace_ppc4xx_sdram_unmap(sdram_base(bcr), sdram_size(bcr)); + trace_ppc4xx_sdram_map(sdram_base(bcr), sdram_size(bcr)); memory_region_init(&sdram->containers[i], NULL, "sdram-containers", sdram_size(bcr)); memory_region_add_subregion(&sdram->containers[i], 0, @@ -186,7 +154,7 @@ static void sdram_set_bcr(ppc4xx_sdram_t *sdram, int i, } } -static void sdram_map_bcr (ppc4xx_sdram_t *sdram) +static void sdram_map_bcr(ppc4xx_sdram_t *sdram) { int i; @@ -200,7 +168,7 @@ static void sdram_map_bcr (ppc4xx_sdram_t *sdram) } } -static void sdram_unmap_bcr (ppc4xx_sdram_t *sdram) +static void sdram_unmap_bcr(ppc4xx_sdram_t *sdram) { int i; @@ -212,7 +180,7 @@ static void sdram_unmap_bcr (ppc4xx_sdram_t *sdram) } } -static uint32_t dcr_read_sdram (void *opaque, int dcrn) +static uint32_t dcr_read_sdram(void *opaque, int dcrn) { ppc4xx_sdram_t *sdram; uint32_t ret; @@ -280,7 +248,7 @@ static uint32_t dcr_read_sdram (void *opaque, int dcrn) return ret; } -static void dcr_write_sdram (void *opaque, int dcrn, uint32_t val) +static void dcr_write_sdram(void *opaque, int dcrn, uint32_t val) { ppc4xx_sdram_t *sdram; @@ -313,10 +281,11 @@ static void dcr_write_sdram (void *opaque, int dcrn, uint32_t val) sdram_unmap_bcr(sdram); sdram->status |= 0x80000000; } - if (!(sdram->cfg & 0x40000000) && (val & 0x40000000)) + if (!(sdram->cfg & 0x40000000) && (val & 0x40000000)) { sdram->status |= 0x40000000; - else if ((sdram->cfg & 0x40000000) && !(val & 0x40000000)) + } else if ((sdram->cfg & 0x40000000) && !(val & 0x40000000)) { sdram->status &= ~0x40000000; + } sdram->cfg = val; break; case 0x24: /* SDRAM_STATUS */ @@ -348,10 +317,11 @@ static void dcr_write_sdram (void *opaque, int dcrn, uint32_t val) break; case 0x98: /* SDRAM_ECCESR */ val &= 0xFFF0F000; - if (sdram->eccesr == 0 && val != 0) + if (sdram->eccesr == 0 && val != 0) { qemu_irq_raise(sdram->irq); - else if (sdram->eccesr != 0 && val == 0) + } else if (sdram->eccesr != 0 && val == 0) { qemu_irq_lower(sdram->irq); + } sdram->eccesr = val; break; default: /* Error */ @@ -361,7 +331,7 @@ static void dcr_write_sdram (void *opaque, int dcrn, uint32_t val) } } -static void sdram_reset (void *opaque) +static void sdram_reset(void *opaque) { ppc4xx_sdram_t *sdram; @@ -381,11 +351,11 @@ static void sdram_reset (void *opaque) sdram->cfg = 0x00800000; } -void ppc4xx_sdram_init (CPUPPCState *env, qemu_irq irq, int nbanks, - MemoryRegion *ram_memories, - hwaddr *ram_bases, - hwaddr *ram_sizes, - int do_init) +void ppc4xx_sdram_init(CPUPPCState *env, qemu_irq irq, int nbanks, + MemoryRegion *ram_memories, + hwaddr *ram_bases, + hwaddr *ram_sizes, + int do_init) { ppc4xx_sdram_t *sdram; @@ -404,8 +374,9 @@ void ppc4xx_sdram_init (CPUPPCState *env, qemu_irq irq, int nbanks, sdram, &dcr_read_sdram, &dcr_write_sdram); ppc_dcr_register(env, SDRAM0_CFGDATA, sdram, &dcr_read_sdram, &dcr_write_sdram); - if (do_init) + if (do_init) { sdram_map_bcr(sdram); + } } /* @@ -462,7 +433,7 @@ void ppc4xx_sdram_banks(MemoryRegion *ram, int nr_banks, } error_report("at most %d bank%s of %s MiB each supported", nr_banks, nr_banks == 1 ? "" : "s", s->str); - error_printf("Possible valid RAM size: %" PRIi64 " MiB \n", + error_printf("Possible valid RAM size: %" PRIi64 " MiB\n", used_size ? used_size / MiB : sdram_bank_sizes[i - 1] / MiB); g_string_free(s, true); @@ -491,32 +462,10 @@ enum { MAL0_RCBS1 = 0x1E1, }; -typedef struct ppc4xx_mal_t ppc4xx_mal_t; -struct ppc4xx_mal_t { - qemu_irq irqs[4]; - uint32_t cfg; - uint32_t esr; - uint32_t ier; - uint32_t txcasr; - uint32_t txcarr; - uint32_t txeobisr; - uint32_t txdeir; - uint32_t rxcasr; - uint32_t rxcarr; - uint32_t rxeobisr; - uint32_t rxdeir; - uint32_t *txctpr; - uint32_t *rxctpr; - uint32_t *rcbs; - uint8_t txcnum; - uint8_t rxcnum; -}; - -static void ppc4xx_mal_reset(void *opaque) +static void ppc4xx_mal_reset(DeviceState *dev) { - ppc4xx_mal_t *mal; + Ppc4xxMalState *mal = PPC4xx_MAL(dev); - mal = opaque; mal->cfg = 0x0007C000; mal->esr = 0x00000000; mal->ier = 0x00000000; @@ -530,10 +479,9 @@ static void ppc4xx_mal_reset(void *opaque) static uint32_t dcr_read_mal(void *opaque, int dcrn) { - ppc4xx_mal_t *mal; + Ppc4xxMalState *mal = opaque; uint32_t ret; - mal = opaque; switch (dcrn) { case MAL0_CFG: ret = mal->cfg; @@ -587,13 +535,12 @@ static uint32_t dcr_read_mal(void *opaque, int dcrn) static void dcr_write_mal(void *opaque, int dcrn, uint32_t val) { - ppc4xx_mal_t *mal; + Ppc4xxMalState *mal = opaque; - mal = opaque; switch (dcrn) { case MAL0_CFG: if (val & 0x80000000) { - ppc4xx_mal_reset(mal); + ppc4xx_mal_reset(DEVICE(mal)); } mal->cfg = val & 0x00FFC087; break; @@ -644,55 +591,404 @@ static void dcr_write_mal(void *opaque, int dcrn, uint32_t val) } } -void ppc4xx_mal_init(CPUPPCState *env, uint8_t txcnum, uint8_t rxcnum, - qemu_irq irqs[4]) +static void ppc4xx_mal_realize(DeviceState *dev, Error **errp) { - ppc4xx_mal_t *mal; + Ppc4xxMalState *mal = PPC4xx_MAL(dev); + Ppc4xxDcrDeviceState *dcr = PPC4xx_DCR_DEVICE(dev); int i; - assert(txcnum <= 32 && rxcnum <= 32); - mal = g_malloc0(sizeof(*mal)); - mal->txcnum = txcnum; - mal->rxcnum = rxcnum; - mal->txctpr = g_new0(uint32_t, txcnum); - mal->rxctpr = g_new0(uint32_t, rxcnum); - mal->rcbs = g_new0(uint32_t, rxcnum); - for (i = 0; i < 4; i++) { - mal->irqs[i] = irqs[i]; + if (mal->txcnum > 32 || mal->rxcnum > 32) { + error_setg(errp, "invalid TXC/RXC number"); + return; } - qemu_register_reset(&ppc4xx_mal_reset, mal); - ppc_dcr_register(env, MAL0_CFG, - mal, &dcr_read_mal, &dcr_write_mal); - ppc_dcr_register(env, MAL0_ESR, - mal, &dcr_read_mal, &dcr_write_mal); - ppc_dcr_register(env, MAL0_IER, - mal, &dcr_read_mal, &dcr_write_mal); - ppc_dcr_register(env, MAL0_TXCASR, - mal, &dcr_read_mal, &dcr_write_mal); - ppc_dcr_register(env, MAL0_TXCARR, - mal, &dcr_read_mal, &dcr_write_mal); - ppc_dcr_register(env, MAL0_TXEOBISR, - mal, &dcr_read_mal, &dcr_write_mal); - ppc_dcr_register(env, MAL0_TXDEIR, - mal, &dcr_read_mal, &dcr_write_mal); - ppc_dcr_register(env, MAL0_RXCASR, - mal, &dcr_read_mal, &dcr_write_mal); - ppc_dcr_register(env, MAL0_RXCARR, - mal, &dcr_read_mal, &dcr_write_mal); - ppc_dcr_register(env, MAL0_RXEOBISR, - mal, &dcr_read_mal, &dcr_write_mal); - ppc_dcr_register(env, MAL0_RXDEIR, - mal, &dcr_read_mal, &dcr_write_mal); - for (i = 0; i < txcnum; i++) { - ppc_dcr_register(env, MAL0_TXCTP0R + i, - mal, &dcr_read_mal, &dcr_write_mal); + + mal->txctpr = g_new0(uint32_t, mal->txcnum); + mal->rxctpr = g_new0(uint32_t, mal->rxcnum); + mal->rcbs = g_new0(uint32_t, mal->rxcnum); + + for (i = 0; i < ARRAY_SIZE(mal->irqs); i++) { + sysbus_init_irq(SYS_BUS_DEVICE(dev), &mal->irqs[i]); + } + + ppc4xx_dcr_register(dcr, MAL0_CFG, mal, &dcr_read_mal, &dcr_write_mal); + ppc4xx_dcr_register(dcr, MAL0_ESR, mal, &dcr_read_mal, &dcr_write_mal); + ppc4xx_dcr_register(dcr, MAL0_IER, mal, &dcr_read_mal, &dcr_write_mal); + ppc4xx_dcr_register(dcr, MAL0_TXCASR, mal, &dcr_read_mal, &dcr_write_mal); + ppc4xx_dcr_register(dcr, MAL0_TXCARR, mal, &dcr_read_mal, &dcr_write_mal); + ppc4xx_dcr_register(dcr, MAL0_TXEOBISR, mal, &dcr_read_mal, &dcr_write_mal); + ppc4xx_dcr_register(dcr, MAL0_TXDEIR, mal, &dcr_read_mal, &dcr_write_mal); + ppc4xx_dcr_register(dcr, MAL0_RXCASR, mal, &dcr_read_mal, &dcr_write_mal); + ppc4xx_dcr_register(dcr, MAL0_RXCARR, mal, &dcr_read_mal, &dcr_write_mal); + ppc4xx_dcr_register(dcr, MAL0_RXEOBISR, mal, &dcr_read_mal, &dcr_write_mal); + ppc4xx_dcr_register(dcr, MAL0_RXDEIR, mal, &dcr_read_mal, &dcr_write_mal); + for (i = 0; i < mal->txcnum; i++) { + ppc4xx_dcr_register(dcr, MAL0_TXCTP0R + i, + mal, &dcr_read_mal, &dcr_write_mal); } - for (i = 0; i < rxcnum; i++) { - ppc_dcr_register(env, MAL0_RXCTP0R + i, - mal, &dcr_read_mal, &dcr_write_mal); + for (i = 0; i < mal->rxcnum; i++) { + ppc4xx_dcr_register(dcr, MAL0_RXCTP0R + i, + mal, &dcr_read_mal, &dcr_write_mal); } - for (i = 0; i < rxcnum; i++) { - ppc_dcr_register(env, MAL0_RCBS0 + i, - mal, &dcr_read_mal, &dcr_write_mal); + for (i = 0; i < mal->rxcnum; i++) { + ppc4xx_dcr_register(dcr, MAL0_RCBS0 + i, + mal, &dcr_read_mal, &dcr_write_mal); } } + +static void ppc4xx_mal_finalize(Object *obj) +{ + Ppc4xxMalState *mal = PPC4xx_MAL(obj); + + g_free(mal->rcbs); + g_free(mal->rxctpr); + g_free(mal->txctpr); +} + +static Property ppc4xx_mal_properties[] = { + DEFINE_PROP_UINT8("txc-num", Ppc4xxMalState, txcnum, 0), + DEFINE_PROP_UINT8("rxc-num", Ppc4xxMalState, rxcnum, 0), + DEFINE_PROP_END_OF_LIST(), +}; + +static void ppc4xx_mal_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + + dc->realize = ppc4xx_mal_realize; + dc->reset = ppc4xx_mal_reset; + /* Reason: only works as function of a ppc4xx SoC */ + dc->user_creatable = false; + device_class_set_props(dc, ppc4xx_mal_properties); +} + +/*****************************************************************************/ +/* Peripheral local bus arbitrer */ +enum { + PLB3A0_ACR = 0x077, + PLB4A0_ACR = 0x081, + PLB0_BESR = 0x084, + PLB0_BEAR = 0x086, + PLB0_ACR = 0x087, + PLB4A1_ACR = 0x089, +}; + +static uint32_t dcr_read_plb(void *opaque, int dcrn) +{ + Ppc4xxPlbState *plb = opaque; + uint32_t ret; + + switch (dcrn) { + case PLB0_ACR: + ret = plb->acr; + break; + case PLB0_BEAR: + ret = plb->bear; + break; + case PLB0_BESR: + ret = plb->besr; + break; + default: + /* Avoid gcc warning */ + ret = 0; + break; + } + + return ret; +} + +static void dcr_write_plb(void *opaque, int dcrn, uint32_t val) +{ + Ppc4xxPlbState *plb = opaque; + + switch (dcrn) { + case PLB0_ACR: + /* + * We don't care about the actual parameters written as + * we don't manage any priorities on the bus + */ + plb->acr = val & 0xF8000000; + break; + case PLB0_BEAR: + /* Read only */ + break; + case PLB0_BESR: + /* Write-clear */ + plb->besr &= ~val; + break; + } +} + +static void ppc405_plb_reset(DeviceState *dev) +{ + Ppc4xxPlbState *plb = PPC4xx_PLB(dev); + + plb->acr = 0x00000000; + plb->bear = 0x00000000; + plb->besr = 0x00000000; +} + +static void ppc405_plb_realize(DeviceState *dev, Error **errp) +{ + Ppc4xxPlbState *plb = PPC4xx_PLB(dev); + Ppc4xxDcrDeviceState *dcr = PPC4xx_DCR_DEVICE(dev); + + ppc4xx_dcr_register(dcr, PLB3A0_ACR, plb, &dcr_read_plb, &dcr_write_plb); + ppc4xx_dcr_register(dcr, PLB4A0_ACR, plb, &dcr_read_plb, &dcr_write_plb); + ppc4xx_dcr_register(dcr, PLB0_ACR, plb, &dcr_read_plb, &dcr_write_plb); + ppc4xx_dcr_register(dcr, PLB0_BEAR, plb, &dcr_read_plb, &dcr_write_plb); + ppc4xx_dcr_register(dcr, PLB0_BESR, plb, &dcr_read_plb, &dcr_write_plb); + ppc4xx_dcr_register(dcr, PLB4A1_ACR, plb, &dcr_read_plb, &dcr_write_plb); +} + +static void ppc405_plb_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + + dc->realize = ppc405_plb_realize; + dc->reset = ppc405_plb_reset; + /* Reason: only works as function of a ppc4xx SoC */ + dc->user_creatable = false; +} + +/*****************************************************************************/ +/* Peripheral controller */ +enum { + EBC0_CFGADDR = 0x012, + EBC0_CFGDATA = 0x013, +}; + +static uint32_t dcr_read_ebc(void *opaque, int dcrn) +{ + Ppc4xxEbcState *ebc = opaque; + uint32_t ret; + + switch (dcrn) { + case EBC0_CFGADDR: + ret = ebc->addr; + break; + case EBC0_CFGDATA: + switch (ebc->addr) { + case 0x00: /* B0CR */ + ret = ebc->bcr[0]; + break; + case 0x01: /* B1CR */ + ret = ebc->bcr[1]; + break; + case 0x02: /* B2CR */ + ret = ebc->bcr[2]; + break; + case 0x03: /* B3CR */ + ret = ebc->bcr[3]; + break; + case 0x04: /* B4CR */ + ret = ebc->bcr[4]; + break; + case 0x05: /* B5CR */ + ret = ebc->bcr[5]; + break; + case 0x06: /* B6CR */ + ret = ebc->bcr[6]; + break; + case 0x07: /* B7CR */ + ret = ebc->bcr[7]; + break; + case 0x10: /* B0AP */ + ret = ebc->bap[0]; + break; + case 0x11: /* B1AP */ + ret = ebc->bap[1]; + break; + case 0x12: /* B2AP */ + ret = ebc->bap[2]; + break; + case 0x13: /* B3AP */ + ret = ebc->bap[3]; + break; + case 0x14: /* B4AP */ + ret = ebc->bap[4]; + break; + case 0x15: /* B5AP */ + ret = ebc->bap[5]; + break; + case 0x16: /* B6AP */ + ret = ebc->bap[6]; + break; + case 0x17: /* B7AP */ + ret = ebc->bap[7]; + break; + case 0x20: /* BEAR */ + ret = ebc->bear; + break; + case 0x21: /* BESR0 */ + ret = ebc->besr0; + break; + case 0x22: /* BESR1 */ + ret = ebc->besr1; + break; + case 0x23: /* CFG */ + ret = ebc->cfg; + break; + default: + ret = 0x00000000; + break; + } + break; + default: + ret = 0x00000000; + break; + } + + return ret; +} + +static void dcr_write_ebc(void *opaque, int dcrn, uint32_t val) +{ + Ppc4xxEbcState *ebc = opaque; + + switch (dcrn) { + case EBC0_CFGADDR: + ebc->addr = val; + break; + case EBC0_CFGDATA: + switch (ebc->addr) { + case 0x00: /* B0CR */ + break; + case 0x01: /* B1CR */ + break; + case 0x02: /* B2CR */ + break; + case 0x03: /* B3CR */ + break; + case 0x04: /* B4CR */ + break; + case 0x05: /* B5CR */ + break; + case 0x06: /* B6CR */ + break; + case 0x07: /* B7CR */ + break; + case 0x10: /* B0AP */ + break; + case 0x11: /* B1AP */ + break; + case 0x12: /* B2AP */ + break; + case 0x13: /* B3AP */ + break; + case 0x14: /* B4AP */ + break; + case 0x15: /* B5AP */ + break; + case 0x16: /* B6AP */ + break; + case 0x17: /* B7AP */ + break; + case 0x20: /* BEAR */ + break; + case 0x21: /* BESR0 */ + break; + case 0x22: /* BESR1 */ + break; + case 0x23: /* CFG */ + break; + default: + break; + } + break; + default: + break; + } +} + +static void ppc405_ebc_reset(DeviceState *dev) +{ + Ppc4xxEbcState *ebc = PPC4xx_EBC(dev); + int i; + + ebc->addr = 0x00000000; + ebc->bap[0] = 0x7F8FFE80; + ebc->bcr[0] = 0xFFE28000; + for (i = 0; i < 8; i++) { + ebc->bap[i] = 0x00000000; + ebc->bcr[i] = 0x00000000; + } + ebc->besr0 = 0x00000000; + ebc->besr1 = 0x00000000; + ebc->cfg = 0x80400000; +} + +static void ppc405_ebc_realize(DeviceState *dev, Error **errp) +{ + Ppc4xxEbcState *ebc = PPC4xx_EBC(dev); + Ppc4xxDcrDeviceState *dcr = PPC4xx_DCR_DEVICE(dev); + + ppc4xx_dcr_register(dcr, EBC0_CFGADDR, ebc, &dcr_read_ebc, &dcr_write_ebc); + ppc4xx_dcr_register(dcr, EBC0_CFGDATA, ebc, &dcr_read_ebc, &dcr_write_ebc); +} + +static void ppc405_ebc_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + + dc->realize = ppc405_ebc_realize; + dc->reset = ppc405_ebc_reset; + /* Reason: only works as function of a ppc4xx SoC */ + dc->user_creatable = false; +} + +/* PPC4xx_DCR_DEVICE */ + +void ppc4xx_dcr_register(Ppc4xxDcrDeviceState *dev, int dcrn, void *opaque, + dcr_read_cb dcr_read, dcr_write_cb dcr_write) +{ + assert(dev->cpu); + ppc_dcr_register(&dev->cpu->env, dcrn, opaque, dcr_read, dcr_write); +} + +bool ppc4xx_dcr_realize(Ppc4xxDcrDeviceState *dev, PowerPCCPU *cpu, + Error **errp) +{ + object_property_set_link(OBJECT(dev), "cpu", OBJECT(cpu), &error_abort); + return sysbus_realize(SYS_BUS_DEVICE(dev), errp); +} + +static Property ppc4xx_dcr_properties[] = { + DEFINE_PROP_LINK("cpu", Ppc4xxDcrDeviceState, cpu, TYPE_POWERPC_CPU, + PowerPCCPU *), + DEFINE_PROP_END_OF_LIST(), +}; + +static void ppc4xx_dcr_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + + device_class_set_props(dc, ppc4xx_dcr_properties); +} + +static const TypeInfo ppc4xx_types[] = { + { + .name = TYPE_PPC4xx_MAL, + .parent = TYPE_PPC4xx_DCR_DEVICE, + .instance_size = sizeof(Ppc4xxMalState), + .instance_finalize = ppc4xx_mal_finalize, + .class_init = ppc4xx_mal_class_init, + }, { + .name = TYPE_PPC4xx_PLB, + .parent = TYPE_PPC4xx_DCR_DEVICE, + .instance_size = sizeof(Ppc4xxPlbState), + .class_init = ppc405_plb_class_init, + }, { + .name = TYPE_PPC4xx_EBC, + .parent = TYPE_PPC4xx_DCR_DEVICE, + .instance_size = sizeof(Ppc4xxEbcState), + .class_init = ppc405_ebc_class_init, + }, { + .name = TYPE_PPC4xx_DCR_DEVICE, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(Ppc4xxDcrDeviceState), + .class_init = ppc4xx_dcr_class_init, + .abstract = true, + } +}; + +DEFINE_TYPES(ppc4xx_types) diff --git a/hw/ppc/ppc4xx_pci.c b/hw/ppc/ppc4xx_pci.c index 5df97e6d15..8642b96455 100644 --- a/hw/ppc/ppc4xx_pci.c +++ b/hw/ppc/ppc4xx_pci.c @@ -16,8 +16,10 @@ * Authors: Hollis Blanchard <hollisb@us.ibm.com> */ -/* This file implements emulation of the 32-bit PCI controller found in some - * 4xx SoCs, such as the 440EP. */ +/* + * This file implements emulation of the 32-bit PCI controller found in some + * 4xx SoCs, such as the 440EP. + */ #include "qemu/osdep.h" #include "qemu/log.h" @@ -65,8 +67,10 @@ struct PPC4xxPCIState { #define PCIC0_CFGADDR 0x0 #define PCIC0_CFGDATA 0x4 -/* PLB Memory Map (PMM) registers specify which PLB addresses are translated to - * PCI accesses. */ +/* + * PLB Memory Map (PMM) registers specify which PLB addresses are translated to + * PCI accesses. + */ #define PCIL0_PMM0LA 0x0 #define PCIL0_PMM0MA 0x4 #define PCIL0_PMM0PCILA 0x8 @@ -80,8 +84,10 @@ struct PPC4xxPCIState { #define PCIL0_PMM2PCILA 0x28 #define PCIL0_PMM2PCIHA 0x2c -/* PCI Target Map (PTM) registers specify which PCI addresses are translated to - * PLB accesses. */ +/* + * PCI Target Map (PTM) registers specify which PCI addresses are translated to + * PLB accesses. + */ #define PCIL0_PTM1MS 0x30 #define PCIL0_PTM1LA 0x34 #define PCIL0_PTM2MS 0x38 @@ -96,9 +102,10 @@ static void ppc4xx_pci_reg_write4(void *opaque, hwaddr offset, { struct PPC4xxPCIState *pci = opaque; - /* We ignore all target attempts at PCI configuration, effectively - * assuming a bidirectional 1:1 mapping of PLB and PCI space. */ - + /* + * We ignore all target attempts at PCI configuration, effectively + * assuming a bidirectional 1:1 mapping of PLB and PCI space. + */ switch (offset) { case PCIL0_PMM0LA: pci->pmm[0].la = value; @@ -243,8 +250,10 @@ static void ppc4xx_pci_reset(void *opaque) memset(pci->ptm, 0, sizeof(pci->ptm)); } -/* On Bamboo, all pins from each slot are tied to a single board IRQ. This - * may need further refactoring for other boards. */ +/* + * On Bamboo, all pins from each slot are tied to a single board IRQ. + * This may need further refactoring for other boards. + */ static int ppc4xx_pci_map_irq(PCIDevice *pci_dev, int irq_num) { int slot = PCI_SLOT(pci_dev->devfn); diff --git a/hw/ppc/sam460ex.c b/hw/ppc/sam460ex.c index 0357ee077f..850bb3b817 100644 --- a/hw/ppc/sam460ex.c +++ b/hw/ppc/sam460ex.c @@ -25,7 +25,6 @@ #include "elf.h" #include "exec/memory.h" #include "ppc440.h" -#include "ppc405.h" #include "hw/block/flash.h" #include "sysemu/sysemu.h" #include "sysemu/reset.h" @@ -280,7 +279,6 @@ static void sam460ex_init(MachineState *machine) hwaddr ram_sizes[SDRAM_NR_BANKS] = {0}; MemoryRegion *l2cache_ram = g_new(MemoryRegion, 1); DeviceState *uic[4]; - qemu_irq mal_irqs[4]; int i; PCIBus *pci_bus; PowerPCCPU *cpu; @@ -309,11 +307,12 @@ static void sam460ex_init(MachineState *machine) ppc_dcr_init(env, NULL, NULL); /* PLB arbitrer */ - ppc4xx_plb_init(env); + dev = qdev_new(TYPE_PPC4xx_PLB); + ppc4xx_dcr_realize(PPC4xx_DCR_DEVICE(dev), cpu, &error_fatal); + object_unref(OBJECT(dev)); /* interrupt controllers */ for (i = 0; i < ARRAY_SIZE(uic); i++) { - SysBusDevice *sbd; /* * UICs 1, 2 and 3 are cascaded through UIC 0. * input_ints[n] is the interrupt number on UIC 0 which @@ -325,22 +324,20 @@ static void sam460ex_init(MachineState *machine) const int input_ints[] = { -1, 30, 10, 16 }; uic[i] = qdev_new(TYPE_PPC_UIC); - sbd = SYS_BUS_DEVICE(uic[i]); - qdev_prop_set_uint32(uic[i], "dcr-base", 0xc0 + i * 0x10); - object_property_set_link(OBJECT(uic[i]), "cpu", OBJECT(cpu), - &error_fatal); - sysbus_realize_and_unref(sbd, &error_fatal); + ppc4xx_dcr_realize(PPC4xx_DCR_DEVICE(uic[i]), cpu, &error_fatal); + object_unref(OBJECT(uic[i])); + sbdev = SYS_BUS_DEVICE(uic[i]); if (i == 0) { - sysbus_connect_irq(sbd, PPCUIC_OUTPUT_INT, + sysbus_connect_irq(sbdev, PPCUIC_OUTPUT_INT, qdev_get_gpio_in(DEVICE(cpu), PPC40x_INPUT_INT)); - sysbus_connect_irq(sbd, PPCUIC_OUTPUT_CINT, + sysbus_connect_irq(sbdev, PPCUIC_OUTPUT_CINT, qdev_get_gpio_in(DEVICE(cpu), PPC40x_INPUT_CINT)); } else { - sysbus_connect_irq(sbd, PPCUIC_OUTPUT_INT, + sysbus_connect_irq(sbdev, PPCUIC_OUTPUT_INT, qdev_get_gpio_in(uic[0], input_ints[i])); - sysbus_connect_irq(sbd, PPCUIC_OUTPUT_CINT, + sysbus_connect_irq(sbdev, PPCUIC_OUTPUT_CINT, qdev_get_gpio_in(uic[0], input_ints[i] + 1)); } } @@ -371,7 +368,9 @@ static void sam460ex_init(MachineState *machine) qdev_get_gpio_in(uic[0], 3)); /* External bus controller */ - ppc405_ebc_init(env); + dev = qdev_new(TYPE_PPC4xx_EBC); + ppc4xx_dcr_realize(PPC4xx_DCR_DEVICE(dev), cpu, &error_fatal); + object_unref(OBJECT(dev)); /* CPR */ ppc4xx_cpr_init(env); @@ -383,10 +382,15 @@ static void sam460ex_init(MachineState *machine) ppc4xx_sdr_init(env); /* MAL */ - for (i = 0; i < ARRAY_SIZE(mal_irqs); i++) { - mal_irqs[i] = qdev_get_gpio_in(uic[2], 3 + i); + dev = qdev_new(TYPE_PPC4xx_MAL); + qdev_prop_set_uint32(dev, "txc-num", 4); + qdev_prop_set_uint32(dev, "rxc-num", 16); + ppc4xx_dcr_realize(PPC4xx_DCR_DEVICE(dev), cpu, &error_fatal); + object_unref(OBJECT(dev)); + sbdev = SYS_BUS_DEVICE(dev); + for (i = 0; i < ARRAY_SIZE(PPC4xx_MAL(dev)->irqs); i++) { + sysbus_connect_irq(sbdev, i, qdev_get_gpio_in(uic[2], 3 + i)); } - ppc4xx_mal_init(env, 4, 16, mal_irqs); /* DMA */ ppc4xx_dma_init(env, 0x200); diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index bc9ba6e6dc..fb790b61e4 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -4731,14 +4731,25 @@ static void spapr_machine_latest_class_options(MachineClass *mc) type_init(spapr_machine_register_##suffix) /* + * pseries-7.2 + */ +static void spapr_machine_7_2_class_options(MachineClass *mc) +{ + /* Defaults for the latest behaviour inherited from the base class */ +} + +DEFINE_SPAPR_MACHINE(7_2, "7.2", true); + +/* * pseries-7.1 */ static void spapr_machine_7_1_class_options(MachineClass *mc) { - /* Defaults for the latest behaviour inherited from the base class */ + spapr_machine_7_2_class_options(mc); + compat_props_add(mc->compat_props, hw_compat_7_1, hw_compat_7_1_len); } -DEFINE_SPAPR_MACHINE(7_1, "7.1", true); +DEFINE_SPAPR_MACHINE(7_1, "7.1", false); /* * pseries-7.0 diff --git a/hw/ppc/trace-events b/hw/ppc/trace-events index 5c0a215cad..a07d5aca0f 100644 --- a/hw/ppc/trace-events +++ b/hw/ppc/trace-events @@ -95,6 +95,17 @@ vof_write(uint32_t ih, unsigned cb, const char *msg) "ih=0x%x [%u] \"%s\"" vof_avail(uint64_t start, uint64_t end, uint64_t size) "0x%"PRIx64"..0x%"PRIx64" size=0x%"PRIx64 vof_claimed(uint64_t start, uint64_t end, uint64_t size) "0x%"PRIx64"..0x%"PRIx64" size=0x%"PRIx64 +# pnv_sbe.c +pnv_sbe_xscom_ctrl_read(uint64_t addr, uint64_t val) "addr 0x%" PRIx64 " val 0x%" PRIx64 +pnv_sbe_xscom_ctrl_write(uint64_t addr, uint64_t val) "addr 0x%" PRIx64 " val 0x%" PRIx64 +pnv_sbe_xscom_mbox_read(uint64_t addr, uint64_t val) "addr 0x%" PRIx64 " val 0x%" PRIx64 +pnv_sbe_xscom_mbox_write(uint64_t addr, uint64_t val) "addr 0x%" PRIx64 " val 0x%" PRIx64 +pnv_sbe_reg_set_host_doorbell(uint64_t val) "val 0x%" PRIx64 +pnv_sbe_cmd_timer_start(uint64_t ns) "ns 0x%" PRIu64 +pnv_sbe_cmd_timer_stop(void) "" +pnv_sbe_cmd_timer_expired(void) "" +pnv_sbe_msg_recv(uint16_t cmd, uint16_t seq, uint16_t ctrl_flags) "cmd 0x%" PRIx16 " seq %"PRIu16 " ctrl_flags 0x%" PRIx16 + # ppc.c ppc_tb_adjust(uint64_t offs1, uint64_t offs2, int64_t diff, int64_t seconds) "adjusted from 0x%"PRIx64" to 0x%"PRIx64", diff %"PRId64" (%"PRId64"s)" ppc_tb_load(uint64_t tb) "tb 0x%016" PRIx64 @@ -150,11 +161,9 @@ ppc440_pcix_reg_write(uint64_t addr, uint32_t val, uint32_t size) "addr 0x%" PRI # ppc405_boards.c opba_readb(uint64_t addr, uint32_t val) "addr 0x%" PRIx64 " = 0x%" PRIx32 opba_writeb(uint64_t addr, uint64_t val) "addr 0x%" PRIx64 " = 0x%" PRIx64 -opba_init(uint64_t addr) "offet 0x%" PRIx64 ppc405_gpio_read(uint64_t addr, uint32_t size) "addr 0x%" PRIx64 " size %d" ppc405_gpio_write(uint64_t addr, uint32_t size, uint64_t val) "addr 0x%" PRIx64 " size %d = 0x%" PRIx64 -ppc405_gpio_init(uint64_t addr) "offet 0x%" PRIx64 ocm_update_mappings(uint32_t isarc, uint32_t isacntl, uint32_t dsarc, uint32_t dsacntl, uint32_t ocm_isarc, uint32_t ocm_isacntl, uint32_t ocm_dsarc, uint32_t ocm_dsacntl) "OCM update ISA 0x%08" PRIx32 " 0x%08" PRIx32 " (0x%08" PRIx32" 0x%08" PRIx32 ") DSA 0x%08" PRIx32 " 0x%08" PRIx32" (0x%08" PRIx32 " 0x%08" PRIx32 ")" ocm_map(const char* prefix, uint32_t isarc) "OCM map %s 0x%08" PRIx32 @@ -162,7 +171,6 @@ ocm_unmap(const char* prefix, uint32_t isarc) "OCM unmap %s 0x%08" PRIx32 ppc4xx_gpt_read(uint64_t addr, uint32_t size) "addr 0x%" PRIx64 " size %d" ppc4xx_gpt_write(uint64_t addr, uint32_t size, uint64_t val) "addr 0x%" PRIx64 " size %d = 0x%" PRIx64 -ppc4xx_gpt_init(uint64_t addr) "offet 0x%" PRIx64 ppc405ep_clocks_compute(const char *param, uint32_t param2, uint32_t val) "%s 0x%1" PRIx32 " %d" ppc405ep_clocks_setup(const char *trace) "%s" diff --git a/hw/ppc/virtex_ml507.c b/hw/ppc/virtex_ml507.c index 53b126ff48..493ea0c19f 100644 --- a/hw/ppc/virtex_ml507.c +++ b/hw/ppc/virtex_ml507.c @@ -104,12 +104,9 @@ static PowerPCCPU *ppc440_init_xilinx(const char *cpu_type, uint32_t sysclk) /* interrupt controller */ uicdev = qdev_new(TYPE_PPC_UIC); + ppc4xx_dcr_realize(PPC4xx_DCR_DEVICE(uicdev), cpu, &error_fatal); + object_unref(OBJECT(uicdev)); uicsbd = SYS_BUS_DEVICE(uicdev); - - object_property_set_link(OBJECT(uicdev), "cpu", OBJECT(cpu), - &error_fatal); - sysbus_realize_and_unref(uicsbd, &error_fatal); - sysbus_connect_irq(uicsbd, PPCUIC_OUTPUT_INT, qdev_get_gpio_in(DEVICE(cpu), PPC40x_INPUT_INT)); sysbus_connect_irq(uicsbd, PPCUIC_OUTPUT_CINT, diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c index cc3097bfee..9a2467c889 100644 --- a/hw/s390x/s390-virtio-ccw.c +++ b/hw/s390x/s390-virtio-ccw.c @@ -792,14 +792,27 @@ bool css_migration_enabled(void) } \ type_init(ccw_machine_register_##suffix) +static void ccw_machine_7_2_instance_options(MachineState *machine) +{ +} + +static void ccw_machine_7_2_class_options(MachineClass *mc) +{ +} +DEFINE_CCW_MACHINE(7_2, "7.2", true); + static void ccw_machine_7_1_instance_options(MachineState *machine) { + ccw_machine_7_2_instance_options(machine); + s390_cpudef_featoff_greater(16, 1, S390_FEAT_PAIE); } static void ccw_machine_7_1_class_options(MachineClass *mc) { + ccw_machine_7_2_class_options(mc); + compat_props_add(mc->compat_props, hw_compat_7_1, hw_compat_7_1_len); } -DEFINE_CCW_MACHINE(7_1, "7.1", true); +DEFINE_CCW_MACHINE(7_1, "7.1", false); static void ccw_machine_7_0_instance_options(MachineState *machine) { diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h index 7a6ea881d8..0884ec4ef7 100644 --- a/include/fpu/softfloat-types.h +++ b/include/fpu/softfloat-types.h @@ -195,6 +195,10 @@ typedef struct float_status { bool snan_bit_is_one; bool use_first_nan; bool no_signaling_nans; + /* should overflowed results subtract re_bias to its exponent? */ + bool rebias_overflow; + /* should underflowed results add re_bias to its exponent? */ + bool rebias_underflow; } float_status; #endif /* SOFTFLOAT_TYPES_H */ diff --git a/include/hw/boards.h b/include/hw/boards.h index 7b416c9787..311ed17e18 100644 --- a/include/hw/boards.h +++ b/include/hw/boards.h @@ -379,6 +379,9 @@ struct MachineState { } \ type_init(machine_initfn##_register_types) +extern GlobalProperty hw_compat_7_1[]; +extern const size_t hw_compat_7_1_len; + extern GlobalProperty hw_compat_7_0[]; extern const size_t hw_compat_7_0_len; diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h index 8435733bd6..c95333514e 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -200,6 +200,9 @@ void pc_madt_cpu_entry(AcpiDeviceIf *adev, int uid, /* sgx.c */ void pc_machine_init_sgx_epc(PCMachineState *pcms); +extern GlobalProperty pc_compat_7_1[]; +extern const size_t pc_compat_7_1_len; + extern GlobalProperty pc_compat_7_0[]; extern const size_t pc_compat_7_0_len; diff --git a/include/hw/intc/ppc-uic.h b/include/hw/intc/ppc-uic.h index 22dd5e5ac2..4d82e9a3c6 100644 --- a/include/hw/intc/ppc-uic.h +++ b/include/hw/intc/ppc-uic.h @@ -25,8 +25,7 @@ #ifndef HW_INTC_PPC_UIC_H #define HW_INTC_PPC_UIC_H -#include "hw/sysbus.h" -#include "qom/object.h" +#include "hw/ppc/ppc4xx.h" #define TYPE_PPC_UIC "ppc-uic" OBJECT_DECLARE_SIMPLE_TYPE(PPCUIC, PPC_UIC) @@ -56,14 +55,13 @@ enum { struct PPCUIC { /*< private >*/ - SysBusDevice parent_obj; + Ppc4xxDcrDeviceState parent_obj; /*< public >*/ qemu_irq output_int; qemu_irq output_cint; /* properties */ - CPUState *cpu; uint32_t dcr_base; bool use_vectors; diff --git a/include/hw/pci-host/pnv_phb3.h b/include/hw/pci-host/pnv_phb3.h index af6ec83cf6..4854f6d2f6 100644 --- a/include/hw/pci-host/pnv_phb3.h +++ b/include/hw/pci-host/pnv_phb3.h @@ -14,6 +14,7 @@ #include "hw/pci/pcie_port.h" #include "hw/ppc/xics.h" #include "qom/object.h" +#include "hw/pci-host/pnv_phb.h" typedef struct PnvPHB3 PnvPHB3; typedef struct PnvChip PnvChip; @@ -103,15 +104,16 @@ struct PnvPBCQState { }; /* - * PHB3 PCIe Root port + * PHB3 PCIe Root Bus */ #define TYPE_PNV_PHB3_ROOT_BUS "pnv-phb3-root" +struct PnvPHB3RootBus { + PCIBus parent; -#define TYPE_PNV_PHB3_ROOT_PORT "pnv-phb3-root-port" - -typedef struct PnvPHB3RootPort { - PCIESlot parent_obj; -} PnvPHB3RootPort; + uint32_t chip_id; + uint32_t phb_id; +}; +OBJECT_DECLARE_SIMPLE_TYPE(PnvPHB3RootBus, PNV_PHB3_ROOT_BUS) /* * PHB3 PCIe Host Bridge for PowerNV machines (POWER8) @@ -127,7 +129,9 @@ OBJECT_DECLARE_SIMPLE_TYPE(PnvPHB3, PNV_PHB3) #define PCI_MMIO_TOTAL_SIZE (0x1ull << 60) struct PnvPHB3 { - PCIExpressHost parent_obj; + DeviceState parent; + + PnvPHB *phb_base; uint32_t chip_id; uint32_t phb_id; @@ -164,5 +168,6 @@ uint64_t pnv_phb3_reg_read(void *opaque, hwaddr off, unsigned size); void pnv_phb3_reg_write(void *opaque, hwaddr off, uint64_t val, unsigned size); void pnv_phb3_update_regions(PnvPHB3 *phb); void pnv_phb3_remap_irqs(PnvPHB3 *phb); +void pnv_phb3_bus_init(DeviceState *dev, PnvPHB3 *phb); #endif /* PCI_HOST_PNV_PHB3_H */ diff --git a/include/hw/pci-host/pnv_phb4.h b/include/hw/pci-host/pnv_phb4.h index 19dcbd6f87..50d4faa001 100644 --- a/include/hw/pci-host/pnv_phb4.h +++ b/include/hw/pci-host/pnv_phb4.h @@ -18,6 +18,7 @@ typedef struct PnvPhb4PecState PnvPhb4PecState; typedef struct PnvPhb4PecStack PnvPhb4PecStack; typedef struct PnvPHB4 PnvPHB4; +typedef struct PnvPHB PnvPHB; typedef struct PnvChip PnvChip; /* @@ -45,15 +46,16 @@ typedef struct PnvPhb4DMASpace { } PnvPhb4DMASpace; /* - * PHB4 PCIe Root port + * PHB4 PCIe Root Bus */ #define TYPE_PNV_PHB4_ROOT_BUS "pnv-phb4-root" -#define TYPE_PNV_PHB4_ROOT_PORT "pnv-phb4-root-port" -#define TYPE_PNV_PHB5_ROOT_PORT "pnv-phb5-root-port" +struct PnvPHB4RootBus { + PCIBus parent; -typedef struct PnvPHB4RootPort { - PCIESlot parent_obj; -} PnvPHB4RootPort; + uint32_t chip_id; + uint32_t phb_id; +}; +OBJECT_DECLARE_SIMPLE_TYPE(PnvPHB4RootBus, PNV_PHB4_ROOT_BUS) /* * PHB4 PCIe Host Bridge for PowerNV machines (POWER9) @@ -78,13 +80,13 @@ OBJECT_DECLARE_SIMPLE_TYPE(PnvPHB4, PNV_PHB4) #define PCI_MMIO_TOTAL_SIZE (0x1ull << 60) struct PnvPHB4 { - PCIExpressHost parent_obj; + DeviceState parent; + + PnvPHB *phb_base; uint32_t chip_id; uint32_t phb_id; - uint64_t version; - /* The owner PEC */ PnvPhb4PecState *pec; @@ -157,6 +159,7 @@ struct PnvPHB4 { void pnv_phb4_pic_print_info(PnvPHB4 *phb, Monitor *mon); int pnv_phb4_pec_get_phb_id(PnvPhb4PecState *pec, int stack_index); +void pnv_phb4_bus_init(DeviceState *dev, PnvPHB4 *phb); extern const MemoryRegionOps pnv_phb4_xscom_ops; /* @@ -205,7 +208,6 @@ struct PnvPhb4PecClass { uint64_t version; const char *phb_type; const uint32_t *num_phbs; - const char *rp_model; }; /* diff --git a/include/hw/ppc/pnv.h b/include/hw/ppc/pnv.h index b991194223..9ef7e2d0dc 100644 --- a/include/hw/ppc/pnv.h +++ b/include/hw/ppc/pnv.h @@ -27,11 +27,13 @@ #include "hw/ppc/pnv_pnor.h" #include "hw/ppc/pnv_psi.h" #include "hw/ppc/pnv_occ.h" +#include "hw/ppc/pnv_sbe.h" #include "hw/ppc/pnv_homer.h" #include "hw/ppc/pnv_xive.h" #include "hw/ppc/pnv_core.h" #include "hw/pci-host/pnv_phb3.h" #include "hw/pci-host/pnv_phb4.h" +#include "hw/pci-host/pnv_phb.h" #include "qom/object.h" #define TYPE_PNV_CHIP "pnv-chip" @@ -80,7 +82,11 @@ struct Pnv8Chip { PnvHomer homer; #define PNV8_CHIP_PHB3_MAX 4 - PnvPHB3 phbs[PNV8_CHIP_PHB3_MAX]; + /* + * The array is used to allow quick access to the phbs by + * pnv_ics_get_child() and pnv_ics_resend_child(). + */ + PnvPHB *phbs[PNV8_CHIP_PHB3_MAX]; uint32_t num_phbs; XICSFabric *xics; @@ -100,6 +106,7 @@ struct Pnv9Chip { Pnv9Psi psi; PnvLpcController lpc; PnvOCC occ; + PnvSBE sbe; PnvHomer homer; uint32_t nr_quads; @@ -129,6 +136,7 @@ struct Pnv10Chip { Pnv9Psi psi; PnvLpcController lpc; PnvOCC occ; + PnvSBE sbe; PnvHomer homer; uint32_t nr_quads; @@ -189,8 +197,6 @@ DECLARE_INSTANCE_CHECKER(PnvChip, PNV_CHIP_POWER10, TYPE_PNV_CHIP_POWER10) PowerPCCPU *pnv_chip_find_cpu(PnvChip *chip, uint32_t pir); -void pnv_phb_attach_root_port(PCIHostState *pci, const char *name, - int index, int chip_id); #define TYPE_PNV_MACHINE MACHINE_TYPE_NAME("powernv") typedef struct PnvMachineClass PnvMachineClass; @@ -232,6 +238,7 @@ struct PnvMachineState { }; PnvChip *pnv_get_chip(PnvMachineState *pnv, uint32_t chip_id); +Object *pnv_chip_add_phb(PnvChip *chip, PnvPHB *phb, Error **errp); #define PNV_FDT_ADDR 0x01000000 #define PNV_TIMEBASE_FREQ 512000000ULL diff --git a/include/hw/ppc/pnv_sbe.h b/include/hw/ppc/pnv_sbe.h new file mode 100644 index 0000000000..f54a3ae9ba --- /dev/null +++ b/include/hw/ppc/pnv_sbe.h @@ -0,0 +1,55 @@ +/* + * QEMU PowerPC PowerNV Emulation of some SBE behaviour + * + * Copyright (c) 2022, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef PPC_PNV_SBE_H +#define PPC_PNV_SBE_H + +#include "qom/object.h" + +#define TYPE_PNV_SBE "pnv-sbe" +OBJECT_DECLARE_TYPE(PnvSBE, PnvSBEClass, PNV_SBE) +#define TYPE_PNV9_SBE TYPE_PNV_SBE "-POWER9" +DECLARE_INSTANCE_CHECKER(PnvSBE, PNV9_SBE, TYPE_PNV9_SBE) +#define TYPE_PNV10_SBE TYPE_PNV_SBE "-POWER10" +DECLARE_INSTANCE_CHECKER(PnvSBE, PNV10_SBE, TYPE_PNV10_SBE) + +struct PnvSBE { + DeviceState xd; + + uint64_t mbox[8]; + uint64_t sbe_doorbell; + uint64_t host_doorbell; + + qemu_irq psi_irq; + QEMUTimer *timer; + + MemoryRegion xscom_mbox_regs; + MemoryRegion xscom_ctrl_regs; +}; + +struct PnvSBEClass { + DeviceClass parent_class; + + int xscom_ctrl_size; + int xscom_mbox_size; + const MemoryRegionOps *xscom_ctrl_ops; + const MemoryRegionOps *xscom_mbox_ops; +}; + +#endif /* PPC_PNV_SBE_H */ diff --git a/include/hw/ppc/pnv_xscom.h b/include/hw/ppc/pnv_xscom.h index 7c7440de0c..c6e9ef8dd2 100644 --- a/include/hw/ppc/pnv_xscom.h +++ b/include/hw/ppc/pnv_xscom.h @@ -92,6 +92,12 @@ struct PnvXScomInterfaceClass { #define PNV9_XSCOM_OCC_BASE PNV_XSCOM_OCC_BASE #define PNV9_XSCOM_OCC_SIZE 0x8000 +#define PNV9_XSCOM_SBE_CTRL_BASE 0x00050008 +#define PNV9_XSCOM_SBE_CTRL_SIZE 0x1 + +#define PNV9_XSCOM_SBE_MBOX_BASE 0x000D0050 +#define PNV9_XSCOM_SBE_MBOX_SIZE 0x16 + #define PNV9_XSCOM_PBA_BASE 0x5012b00 #define PNV9_XSCOM_PBA_SIZE 0x40 @@ -134,6 +140,12 @@ struct PnvXScomInterfaceClass { #define PNV10_XSCOM_OCC_BASE PNV9_XSCOM_OCC_BASE #define PNV10_XSCOM_OCC_SIZE PNV9_XSCOM_OCC_SIZE +#define PNV10_XSCOM_SBE_CTRL_BASE PNV9_XSCOM_SBE_CTRL_BASE +#define PNV10_XSCOM_SBE_CTRL_SIZE PNV9_XSCOM_SBE_CTRL_SIZE + +#define PNV10_XSCOM_SBE_MBOX_BASE PNV9_XSCOM_SBE_MBOX_BASE +#define PNV10_XSCOM_SBE_MBOX_SIZE PNV9_XSCOM_SBE_MBOX_SIZE + #define PNV10_XSCOM_PBA_BASE 0x01010CDA #define PNV10_XSCOM_PBA_SIZE 0x40 diff --git a/include/hw/ppc/ppc4xx.h b/include/hw/ppc/ppc4xx.h index 980f964b5a..a1781afa8e 100644 --- a/include/hw/ppc/ppc4xx.h +++ b/include/hw/ppc/ppc4xx.h @@ -27,11 +27,7 @@ #include "hw/ppc/ppc.h" #include "exec/memory.h" - -/* PowerPC 4xx core initialization */ -PowerPCCPU *ppc4xx_init(const char *cpu_model, - clk_setup_t *cpu_clk, clk_setup_t *tb_clk, - uint32_t sysclk); +#include "hw/sysbus.h" void ppc4xx_sdram_banks(MemoryRegion *ram, int nr_banks, MemoryRegion ram_memories[], @@ -44,9 +40,73 @@ void ppc4xx_sdram_init (CPUPPCState *env, qemu_irq irq, int nbanks, hwaddr *ram_sizes, int do_init); -void ppc4xx_mal_init(CPUPPCState *env, uint8_t txcnum, uint8_t rxcnum, - qemu_irq irqs[4]); - #define TYPE_PPC4xx_PCI_HOST_BRIDGE "ppc4xx-pcihost" +/* + * Generic DCR device + */ +#define TYPE_PPC4xx_DCR_DEVICE "ppc4xx-dcr-device" +OBJECT_DECLARE_SIMPLE_TYPE(Ppc4xxDcrDeviceState, PPC4xx_DCR_DEVICE); +struct Ppc4xxDcrDeviceState { + SysBusDevice parent_obj; + + PowerPCCPU *cpu; +}; + +void ppc4xx_dcr_register(Ppc4xxDcrDeviceState *dev, int dcrn, void *opaque, + dcr_read_cb dcr_read, dcr_write_cb dcr_write); +bool ppc4xx_dcr_realize(Ppc4xxDcrDeviceState *dev, PowerPCCPU *cpu, + Error **errp); + +/* Memory Access Layer (MAL) */ +#define TYPE_PPC4xx_MAL "ppc4xx-mal" +OBJECT_DECLARE_SIMPLE_TYPE(Ppc4xxMalState, PPC4xx_MAL); +struct Ppc4xxMalState { + Ppc4xxDcrDeviceState parent_obj; + + qemu_irq irqs[4]; + uint32_t cfg; + uint32_t esr; + uint32_t ier; + uint32_t txcasr; + uint32_t txcarr; + uint32_t txeobisr; + uint32_t txdeir; + uint32_t rxcasr; + uint32_t rxcarr; + uint32_t rxeobisr; + uint32_t rxdeir; + uint32_t *txctpr; + uint32_t *rxctpr; + uint32_t *rcbs; + uint8_t txcnum; + uint8_t rxcnum; +}; + +/* Peripheral local bus arbitrer */ +#define TYPE_PPC4xx_PLB "ppc4xx-plb" +OBJECT_DECLARE_SIMPLE_TYPE(Ppc4xxPlbState, PPC4xx_PLB); +struct Ppc4xxPlbState { + Ppc4xxDcrDeviceState parent_obj; + + uint32_t acr; + uint32_t bear; + uint32_t besr; +}; + +/* Peripheral controller */ +#define TYPE_PPC4xx_EBC "ppc4xx-ebc" +OBJECT_DECLARE_SIMPLE_TYPE(Ppc4xxEbcState, PPC4xx_EBC); +struct Ppc4xxEbcState { + Ppc4xxDcrDeviceState parent_obj; + + uint32_t addr; + uint32_t bcr[8]; + uint32_t bap[8]; + uint32_t bear; + uint32_t besr0; + uint32_t besr1; + uint32_t cfg; +}; + #endif /* PPC4XX_H */ diff --git a/include/qemu/mmap-alloc.h b/include/qemu/mmap-alloc.h index 5076695cc8..2825e231a7 100644 --- a/include/qemu/mmap-alloc.h +++ b/include/qemu/mmap-alloc.h @@ -4,8 +4,6 @@ size_t qemu_fd_getpagesize(int fd); -size_t qemu_mempath_getpagesize(const char *mem_path); - /** * qemu_ram_mmap: mmap anonymous memory, the specified file or device. * diff --git a/pc-bios/README b/pc-bios/README index ba6c15e769..b94f3fb081 100644 --- a/pc-bios/README +++ b/pc-bios/README @@ -14,7 +14,7 @@ - SLOF (Slimline Open Firmware) is a free IEEE 1275 Open Firmware implementation for certain IBM POWER hardware. The sources are at https://github.com/aik/SLOF, and the image currently in qemu is - built from git tag qemu-slof-20220110. + built from git tag qemu-slof-20220719. - VOF (Virtual Open Firmware) is a minimalistic firmware to work with -machine pseries,x-vof=on. When enabled, the firmware acts as a slim shim and diff --git a/pc-bios/slof.bin b/pc-bios/slof.bin Binary files differindex cbbe23e910..ef9b81d628 100644 --- a/pc-bios/slof.bin +++ b/pc-bios/slof.bin diff --git a/roms/SLOF b/roms/SLOF -Subproject 5b4c5acdcd552a4e1796aeca6bb700f6cbb0282 +Subproject 6b6c16b4b40763507cf1f518096f3c3883c5cf2 diff --git a/softmmu/physmem.c b/softmmu/physmem.c index dc3c3e5f2e..50231bab30 100644 --- a/softmmu/physmem.c +++ b/softmmu/physmem.c @@ -1331,13 +1331,6 @@ GString *ram_block_format(void) return buf; } -#ifdef __linux__ -/* - * FIXME TOCTTOU: this iterates over memory backends' mem-path, which - * may or may not name the same files / on the same filesystem now as - * when we actually open and map them. Iterate over the file - * descriptors instead, and use qemu_fd_getpagesize(). - */ static int find_min_backend_pagesize(Object *obj, void *opaque) { long *hpsize_min = opaque; @@ -1391,16 +1384,6 @@ long qemu_maxrampagesize(void) object_child_foreach(memdev_root, find_max_backend_pagesize, &pagesize); return pagesize; } -#else -long qemu_minrampagesize(void) -{ - return qemu_real_host_page_size(); -} -long qemu_maxrampagesize(void) -{ - return qemu_real_host_page_size(); -} -#endif #ifdef CONFIG_POSIX static int64_t get_file_size(int fd) diff --git a/target/avr/helper.c b/target/avr/helper.c index db76452f9a..156dde4e92 100644 --- a/target/avr/helper.c +++ b/target/avr/helper.c @@ -28,36 +28,41 @@ bool avr_cpu_exec_interrupt(CPUState *cs, int interrupt_request) { - bool ret = false; - CPUClass *cc = CPU_GET_CLASS(cs); AVRCPU *cpu = AVR_CPU(cs); CPUAVRState *env = &cpu->env; + /* + * We cannot separate a skip from the next instruction, + * as the skip would not be preserved across the interrupt. + * Separating the two insn normally only happens at page boundaries. + */ + if (env->skip) { + return false; + } + if (interrupt_request & CPU_INTERRUPT_RESET) { if (cpu_interrupts_enabled(env)) { cs->exception_index = EXCP_RESET; - cc->tcg_ops->do_interrupt(cs); + avr_cpu_do_interrupt(cs); cs->interrupt_request &= ~CPU_INTERRUPT_RESET; - - ret = true; + return true; } } if (interrupt_request & CPU_INTERRUPT_HARD) { if (cpu_interrupts_enabled(env) && env->intsrc != 0) { int index = ctz32(env->intsrc); cs->exception_index = EXCP_INT(index); - cc->tcg_ops->do_interrupt(cs); + avr_cpu_do_interrupt(cs); env->intsrc &= env->intsrc - 1; /* clear the interrupt */ if (!env->intsrc) { cs->interrupt_request &= ~CPU_INTERRUPT_HARD; } - - ret = true; + return true; } } - return ret; + return false; } void avr_cpu_do_interrupt(CPUState *cs) @@ -102,38 +107,50 @@ bool avr_cpu_tlb_fill(CPUState *cs, vaddr address, int size, MMUAccessType access_type, int mmu_idx, bool probe, uintptr_t retaddr) { - int prot = 0; - MemTxAttrs attrs = {}; + int prot, page_size = TARGET_PAGE_SIZE; uint32_t paddr; address &= TARGET_PAGE_MASK; if (mmu_idx == MMU_CODE_IDX) { - /* access to code in flash */ + /* Access to code in flash. */ paddr = OFFSET_CODE + address; prot = PAGE_READ | PAGE_EXEC; - if (paddr + TARGET_PAGE_SIZE > OFFSET_DATA) { + if (paddr >= OFFSET_DATA) { + /* + * This should not be possible via any architectural operations. + * There is certainly not an exception that we can deliver. + * Accept probing that might come from generic code. + */ + if (probe) { + return false; + } error_report("execution left flash memory"); abort(); } - } else if (address < NUMBER_OF_CPU_REGISTERS + NUMBER_OF_IO_REGISTERS) { - /* - * access to CPU registers, exit and rebuilt this TB to use full access - * incase it touches specially handled registers like SREG or SP - */ - AVRCPU *cpu = AVR_CPU(cs); - CPUAVRState *env = &cpu->env; - env->fullacc = 1; - cpu_loop_exit_restore(cs, retaddr); } else { - /* access to memory. nothing special */ + /* Access to memory. */ paddr = OFFSET_DATA + address; prot = PAGE_READ | PAGE_WRITE; + if (address < NUMBER_OF_CPU_REGISTERS + NUMBER_OF_IO_REGISTERS) { + /* + * Access to CPU registers, exit and rebuilt this TB to use + * full access in case it touches specially handled registers + * like SREG or SP. For probing, set page_size = 1, in order + * to force tlb_fill to be called for the next access. + */ + if (probe) { + page_size = 1; + } else { + AVRCPU *cpu = AVR_CPU(cs); + CPUAVRState *env = &cpu->env; + env->fullacc = 1; + cpu_loop_exit_restore(cs, retaddr); + } + } } - tlb_set_page_with_attrs(cs, address, paddr, attrs, prot, - mmu_idx, TARGET_PAGE_SIZE); - + tlb_set_page(cs, address, paddr, prot, mmu_idx, page_size); return true; } diff --git a/target/avr/translate.c b/target/avr/translate.c index dc9c3d6bcc..026753c963 100644 --- a/target/avr/translate.c +++ b/target/avr/translate.c @@ -2971,8 +2971,18 @@ static void avr_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) if (skip_label) { canonicalize_skip(ctx); gen_set_label(skip_label); - if (ctx->base.is_jmp == DISAS_NORETURN) { + + switch (ctx->base.is_jmp) { + case DISAS_NORETURN: ctx->base.is_jmp = DISAS_CHAIN; + break; + case DISAS_NEXT: + if (ctx->base.tb->flags & TB_FLAGS_SKIP) { + ctx->base.is_jmp = DISAS_TOO_MANY; + } + break; + default: + break; } } @@ -2989,6 +2999,11 @@ static void avr_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs) { DisasContext *ctx = container_of(dcbase, DisasContext, base); bool nonconst_skip = canonicalize_skip(ctx); + /* + * Because we disable interrupts while env->skip is set, + * we must return to the main loop to re-evaluate afterward. + */ + bool force_exit = ctx->base.tb->flags & TB_FLAGS_SKIP; switch (ctx->base.is_jmp) { case DISAS_NORETURN: @@ -2997,7 +3012,7 @@ static void avr_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs) case DISAS_NEXT: case DISAS_TOO_MANY: case DISAS_CHAIN: - if (!nonconst_skip) { + if (!nonconst_skip && !force_exit) { /* Note gen_goto_tb checks singlestep. */ gen_goto_tb(ctx, 1, ctx->npc); break; @@ -3005,8 +3020,11 @@ static void avr_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs) tcg_gen_movi_tl(cpu_pc, ctx->npc); /* fall through */ case DISAS_LOOKUP: - tcg_gen_lookup_and_goto_ptr(); - break; + if (!force_exit) { + tcg_gen_lookup_and_goto_ptr(); + break; + } + /* fall through */ case DISAS_EXIT: tcg_gen_exit_tb(NULL, 0); break; diff --git a/target/ppc/cpu-qom.h b/target/ppc/cpu-qom.h index ad7e3c3db9..89ff88f28c 100644 --- a/target/ppc/cpu-qom.h +++ b/target/ppc/cpu-qom.h @@ -158,7 +158,11 @@ struct PowerPCCPUClass { void (*parent_parse_features)(const char *type, char *str, Error **errp); uint32_t pvr; - bool (*pvr_match)(struct PowerPCCPUClass *pcc, uint32_t pvr); + /* + * If @best is false, match if pcc is in the family of pvr + * Else match only if pcc is the best match for pvr in this family. + */ + bool (*pvr_match)(struct PowerPCCPUClass *pcc, uint32_t pvr, bool best); uint64_t pcr_mask; /* Available bits in PCR register */ uint64_t pcr_supported; /* Bits for supported PowerISA versions */ uint32_t svr; diff --git a/target/ppc/cpu.c b/target/ppc/cpu.c index 401b6f9e63..0ebac04bc4 100644 --- a/target/ppc/cpu.c +++ b/target/ppc/cpu.c @@ -120,6 +120,8 @@ void ppc_store_fpscr(CPUPPCState *env, target_ulong val) val |= FP_FEX; } env->fpscr = val; + env->fp_status.rebias_overflow = (FP_OE & env->fpscr) ? true : false; + env->fp_status.rebias_underflow = (FP_UE & env->fpscr) ? true : false; if (tcg_enabled()) { fpscr_set_rounding_mode(env); } diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c index d1493a660c..899c4a586e 100644 --- a/target/ppc/cpu_init.c +++ b/target/ppc/cpu_init.c @@ -5912,15 +5912,25 @@ static void init_proc_POWER7(CPUPPCState *env) ppcPOWER7_irq_init(env_archcpu(env)); } -static bool ppc_pvr_match_power7(PowerPCCPUClass *pcc, uint32_t pvr) +static bool ppc_pvr_match_power7(PowerPCCPUClass *pcc, uint32_t pvr, bool best) { - if ((pvr & CPU_POWERPC_POWER_SERVER_MASK) == CPU_POWERPC_POWER7P_BASE) { - return true; + uint32_t base = pvr & CPU_POWERPC_POWER_SERVER_MASK; + uint32_t pcc_base = pcc->pvr & CPU_POWERPC_POWER_SERVER_MASK; + + if (!best) { + if (base == CPU_POWERPC_POWER7_BASE) { + return true; + } + if (base == CPU_POWERPC_POWER7P_BASE) { + return true; + } } - if ((pvr & CPU_POWERPC_POWER_SERVER_MASK) == CPU_POWERPC_POWER7_BASE) { - return true; + + if (base != pcc_base) { + return false; } - return false; + + return true; } static bool cpu_has_work_POWER7(CPUState *cs) @@ -6073,18 +6083,27 @@ static void init_proc_POWER8(CPUPPCState *env) ppcPOWER7_irq_init(env_archcpu(env)); } -static bool ppc_pvr_match_power8(PowerPCCPUClass *pcc, uint32_t pvr) +static bool ppc_pvr_match_power8(PowerPCCPUClass *pcc, uint32_t pvr, bool best) { - if ((pvr & CPU_POWERPC_POWER_SERVER_MASK) == CPU_POWERPC_POWER8NVL_BASE) { - return true; - } - if ((pvr & CPU_POWERPC_POWER_SERVER_MASK) == CPU_POWERPC_POWER8E_BASE) { - return true; + uint32_t base = pvr & CPU_POWERPC_POWER_SERVER_MASK; + uint32_t pcc_base = pcc->pvr & CPU_POWERPC_POWER_SERVER_MASK; + + if (!best) { + if (base == CPU_POWERPC_POWER8_BASE) { + return true; + } + if (base == CPU_POWERPC_POWER8E_BASE) { + return true; + } + if (base == CPU_POWERPC_POWER8NVL_BASE) { + return true; + } } - if ((pvr & CPU_POWERPC_POWER_SERVER_MASK) == CPU_POWERPC_POWER8_BASE) { - return true; + if (base != pcc_base) { + return false; } - return false; + + return true; } static bool cpu_has_work_POWER8(CPUState *cs) @@ -6282,11 +6301,26 @@ static void init_proc_POWER9(CPUPPCState *env) ppcPOWER9_irq_init(env_archcpu(env)); } -static bool ppc_pvr_match_power9(PowerPCCPUClass *pcc, uint32_t pvr) +static bool ppc_pvr_match_power9(PowerPCCPUClass *pcc, uint32_t pvr, bool best) { - if ((pvr & CPU_POWERPC_POWER_SERVER_MASK) == CPU_POWERPC_POWER9_BASE) { + uint32_t base = pvr & CPU_POWERPC_POWER_SERVER_MASK; + uint32_t pcc_base = pcc->pvr & CPU_POWERPC_POWER_SERVER_MASK; + + if (!best) { + if (base == CPU_POWERPC_POWER9_BASE) { + return true; + } + } + + if (base != pcc_base) { + return false; + } + + if ((pvr & 0x0f00) == (pcc->pvr & 0x0f00)) { + /* Major DD version matches to power9_v1.0 and power9_v2.0 */ return true; } + return false; } @@ -6499,11 +6533,26 @@ static void init_proc_POWER10(CPUPPCState *env) ppcPOWER9_irq_init(env_archcpu(env)); } -static bool ppc_pvr_match_power10(PowerPCCPUClass *pcc, uint32_t pvr) +static bool ppc_pvr_match_power10(PowerPCCPUClass *pcc, uint32_t pvr, bool best) { - if ((pvr & CPU_POWERPC_POWER_SERVER_MASK) == CPU_POWERPC_POWER10_BASE) { + uint32_t base = pvr & CPU_POWERPC_POWER_SERVER_MASK; + uint32_t pcc_base = pcc->pvr & CPU_POWERPC_POWER_SERVER_MASK; + + if (!best) { + if (base == CPU_POWERPC_POWER10_BASE) { + return true; + } + } + + if (base != pcc_base) { + return false; + } + + if ((pvr & 0x0f00) == (pcc->pvr & 0x0f00)) { + /* Major DD version matches to power10_v1.0 and power10_v2.0 */ return true; } + return false; } @@ -6910,7 +6959,7 @@ static gint ppc_cpu_compare_class_pvr_mask(gconstpointer a, gconstpointer b) return -1; } - if (pcc->pvr_match(pcc, pvr)) { + if (pcc->pvr_match(pcc, pvr, true)) { return 0; } @@ -7308,7 +7357,7 @@ static void ppc_cpu_instance_finalize(Object *obj) ppc_hash64_finalize(cpu); } -static bool ppc_pvr_match_default(PowerPCCPUClass *pcc, uint32_t pvr) +static bool ppc_pvr_match_default(PowerPCCPUClass *pcc, uint32_t pvr, bool best) { return pcc->pvr == pvr; } diff --git a/target/ppc/fpu_helper.c b/target/ppc/fpu_helper.c index 7ab6beadad..0f045b70f8 100644 --- a/target/ppc/fpu_helper.c +++ b/target/ppc/fpu_helper.c @@ -348,7 +348,6 @@ static inline int float_overflow_excp(CPUPPCState *env) bool overflow_enabled = !!(env->fpscr & FP_OE); if (overflow_enabled) { - /* XXX: should adjust the result */ /* Update the floating-point enabled exception summary */ env->fpscr |= FP_FEX; /* We must update the target FPR before raising the exception */ @@ -367,7 +366,6 @@ static inline void float_underflow_excp(CPUPPCState *env) /* Update the floating-point exception summary */ env->fpscr |= FP_FX; if (env->fpscr & FP_UE) { - /* XXX: should adjust the result */ /* Update the floating-point enabled exception summary */ env->fpscr |= FP_FEX; /* We must update the target FPR before raising the exception */ diff --git a/target/ppc/machine.c b/target/ppc/machine.c index a7d9036c09..be6eb3d968 100644 --- a/target/ppc/machine.c +++ b/target/ppc/machine.c @@ -234,7 +234,7 @@ static bool pvr_match(PowerPCCPU *cpu, uint32_t pvr) if (pvr == pcc->pvr) { return true; } - return pcc->pvr_match(pcc, pvr); + return pcc->pvr_match(pcc, pvr, true); } static int cpu_post_load(void *opaque, int version_id) diff --git a/target/s390x/cpu_features_def.h.inc b/target/s390x/cpu_features_def.h.inc index 3603e5fb12..e3cfe63735 100644 --- a/target/s390x/cpu_features_def.h.inc +++ b/target/s390x/cpu_features_def.h.inc @@ -114,6 +114,7 @@ DEF_FEAT(VECTOR_PACKED_DECIMAL_ENH2, "vxpdeh2", STFL, 192, "Vector-Packed-Decima DEF_FEAT(BEAR_ENH, "beareh", STFL, 193, "BEAR-enhancement facility") DEF_FEAT(RDP, "rdp", STFL, 194, "Reset-DAT-protection facility") DEF_FEAT(PAI, "pai", STFL, 196, "Processor-Activity-Instrumentation facility") +DEF_FEAT(PAIE, "paie", STFL, 197, "Processor-Activity-Instrumentation extension-1") /* Features exposed via SCLP SCCB Byte 80 - 98 (bit numbers relative to byte-80) */ DEF_FEAT(SIE_GSLS, "gsls", SCLP_CONF_CHAR, 40, "SIE: Guest-storage-limit-suppression facility") diff --git a/target/s390x/gen-features.c b/target/s390x/gen-features.c index ad140184b9..1558c52626 100644 --- a/target/s390x/gen-features.c +++ b/target/s390x/gen-features.c @@ -575,6 +575,7 @@ static uint16_t full_GEN16_GA1[] = { S390_FEAT_BEAR_ENH, S390_FEAT_RDP, S390_FEAT_PAI, + S390_FEAT_PAIE, }; @@ -669,6 +670,7 @@ static uint16_t default_GEN16_GA1[] = { S390_FEAT_BEAR_ENH, S390_FEAT_RDP, S390_FEAT_PAI, + S390_FEAT_PAIE, }; /* QEMU (CPU model) features */ diff --git a/target/s390x/tcg/insn-data.def b/target/s390x/tcg/insn-data.def index 5e448bb2c4..6d2cfe5fa2 100644 --- a/target/s390x/tcg/insn-data.def +++ b/target/s390x/tcg/insn-data.def @@ -290,8 +290,8 @@ D(0xb961, CLGRT, RRF_c, GIE, r1_o, r2_o, 0, 0, ct, 0, 1) D(0xeb23, CLT, RSY_b, MIE, r1_32u, m2_32u, 0, 0, ct, 0, 1) D(0xeb2b, CLGT, RSY_b, MIE, r1_o, m2_64, 0, 0, ct, 0, 1) - D(0xec73, CLFIT, RIE_a, GIE, r1_32u, i2_32u, 0, 0, ct, 0, 1) - D(0xec71, CLGIT, RIE_a, GIE, r1_o, i2_32u, 0, 0, ct, 0, 1) + D(0xec73, CLFIT, RIE_a, GIE, r1_32u, i2_16u, 0, 0, ct, 0, 1) + D(0xec71, CLGIT, RIE_a, GIE, r1_o, i2_16u, 0, 0, ct, 0, 1) /* CONVERT TO DECIMAL */ C(0x4e00, CVD, RX_a, Z, r1_o, a2, 0, 0, cvd, 0) diff --git a/tests/avocado/avocado_qemu/__init__.py b/tests/avocado/avocado_qemu/__init__.py index 9d17a287cf..5f1d3e551c 100644 --- a/tests/avocado/avocado_qemu/__init__.py +++ b/tests/avocado/avocado_qemu/__init__.py @@ -299,6 +299,12 @@ class QemuSystemTest(QemuBaseTest): self.cancel("%s accelerator does not seem to be " "available" % accelerator) + def require_netdev(self, netdevname): + netdevhelp = run_cmd([self.qemu_bin, + '-M', 'none', '-netdev', 'help'])[0]; + if netdevhelp.find('\n' + netdevname + '\n') < 0: + self.cancel('no support for user networking') + def _new_vm(self, name, *args): self._sd = tempfile.TemporaryDirectory(prefix="avo_qemu_sock_") vm = QEMUMachine(self.qemu_bin, base_temp_dir=self.workdir, @@ -512,7 +518,7 @@ class LinuxDistro: class LinuxTest(LinuxSSHMixIn, QemuSystemTest): """Facilitates having a cloud-image Linux based available. - For tests that indent to interact with guests, this is a better choice + For tests that intend to interact with guests, this is a better choice to start with than the more vanilla `QemuSystemTest` class. """ @@ -550,6 +556,7 @@ class LinuxTest(LinuxSSHMixIn, QemuSystemTest): def setUp(self, ssh_pubkey=None, network_device_type='virtio-net'): super().setUp() + self.require_netdev('user') self._set_distro() self.vm.add_args('-smp', self.smp) self.vm.add_args('-m', self.memory) diff --git a/tests/avocado/info_usernet.py b/tests/avocado/info_usernet.py index dc01f74150..b862a47dba 100644 --- a/tests/avocado/info_usernet.py +++ b/tests/avocado/info_usernet.py @@ -16,6 +16,7 @@ from qemu.utils import get_info_usernet_hostfwd_port class InfoUsernet(QemuSystemTest): def test_hostfwd(self): + self.require_netdev('user') self.vm.add_args('-netdev', 'user,id=vnet,hostfwd=:127.0.0.1:0-:22') self.vm.launch() res = self.vm.command('human-monitor-command', diff --git a/tests/avocado/migration.py b/tests/avocado/migration.py index 584d6ef53f..4b25680c50 100644 --- a/tests/avocado/migration.py +++ b/tests/avocado/migration.py @@ -14,7 +14,7 @@ import tempfile from avocado_qemu import QemuSystemTest from avocado import skipUnless -from avocado.utils import network +from avocado.utils.network import ports from avocado.utils import wait from avocado.utils.path import find_command @@ -57,7 +57,7 @@ class Migration(QemuSystemTest): self.assert_migration(source_vm, dest_vm) def _get_free_port(self): - port = network.find_free_port() + port = ports.find_free_port() if port is None: self.cancel('Failed to find a free port') return port diff --git a/tests/avocado/replay_linux.py b/tests/avocado/replay_linux.py index e1f9981a34..a76dd507fc 100644 --- a/tests/avocado/replay_linux.py +++ b/tests/avocado/replay_linux.py @@ -55,6 +55,7 @@ class ReplayLinux(LinuxTest): '%s,drive=disk%s-rr%s' % (device, id, bus_string)) def launch_and_wait(self, record, args, shift): + self.require_netdev('user') vm = self.get_vm() vm.add_args('-smp', '1') vm.add_args('-m', '1024') diff --git a/tests/migration/stress.c b/tests/migration/stress.c index b7240a15c8..88acf8dc25 100644 --- a/tests/migration/stress.c +++ b/tests/migration/stress.c @@ -232,7 +232,7 @@ static void stress(unsigned long long ramsizeGB, int ncpus) static int mount_misc(const char *fstype, const char *dir) { - if (mkdir(dir, 0755) < 0 && errno != EEXIST) { + if (g_mkdir_with_parents(dir, 0755) < 0 && errno != EEXIST) { fprintf(stderr, "%s (%05d): ERROR: cannot create %s: %s\n", argv0, gettid(), dir, strerror(errno)); return -1; diff --git a/tests/qtest/ac97-test.c b/tests/qtest/ac97-test.c index b084e31bff..74103efdfa 100644 --- a/tests/qtest/ac97-test.c +++ b/tests/qtest/ac97-test.c @@ -28,7 +28,7 @@ static void *ac97_get_driver(void *obj, const char *interface) return &ac97->dev; } - fprintf(stderr, "%s not present in e1000e\n", interface); + fprintf(stderr, "%s not present in ac97\n", interface); g_assert_not_reached(); } diff --git a/tests/qtest/bios-tables-test.c b/tests/qtest/bios-tables-test.c index 7c5f736b51..36783966b0 100644 --- a/tests/qtest/bios-tables-test.c +++ b/tests/qtest/bios-tables-test.c @@ -1461,6 +1461,7 @@ static void test_acpi_piix4_tcg_acpi_hmat(void) test_acpi_tcg_acpi_hmat(MACHINE_PC); } +#ifdef CONFIG_POSIX static void test_acpi_erst(const char *machine) { gchar *tmp_path = g_dir_make_tmp("qemu-test-erst.XXXXXX", NULL); @@ -1511,6 +1512,7 @@ static void test_acpi_microvm_acpi_erst(void) g_free(tmp_path); free_test_data(&data); } +#endif /* CONFIG_POSIX */ static void test_acpi_virt_tcg(void) { @@ -1551,6 +1553,7 @@ static void test_acpi_q35_viot(void) free_test_data(&data); } +#ifdef CONFIG_POSIX static void test_acpi_q35_cxl(void) { gchar *tmp_path = g_dir_make_tmp("qemu-test-cxl.XXXXXX", NULL); @@ -1593,6 +1596,7 @@ static void test_acpi_q35_cxl(void) g_free(tmp_path); free_test_data(&data); } +#endif /* CONFIG_POSIX */ static void test_acpi_virt_viot(void) { @@ -1805,8 +1809,10 @@ int main(int argc, char *argv[]) qtest_add_func("acpi/q35/dimmpxm", test_acpi_q35_tcg_dimm_pxm); qtest_add_func("acpi/piix4/acpihmat", test_acpi_piix4_tcg_acpi_hmat); qtest_add_func("acpi/q35/acpihmat", test_acpi_q35_tcg_acpi_hmat); +#ifdef CONFIG_POSIX qtest_add_func("acpi/piix4/acpierst", test_acpi_piix4_acpi_erst); qtest_add_func("acpi/q35/acpierst", test_acpi_q35_acpi_erst); +#endif qtest_add_func("acpi/q35/applesmc", test_acpi_q35_applesmc); qtest_add_func("acpi/q35/pvpanic-isa", test_acpi_q35_pvpanic_isa); qtest_add_func("acpi/microvm", test_acpi_microvm_tcg); @@ -1818,7 +1824,9 @@ int main(int argc, char *argv[]) qtest_add_func("acpi/q35/ivrs", test_acpi_q35_tcg_ivrs); if (strcmp(arch, "x86_64") == 0) { qtest_add_func("acpi/microvm/pcie", test_acpi_microvm_pcie_tcg); +#ifdef CONFIG_POSIX qtest_add_func("acpi/microvm/acpierst", test_acpi_microvm_acpi_erst); +#endif } } if (has_kvm) { @@ -1826,7 +1834,9 @@ int main(int argc, char *argv[]) qtest_add_func("acpi/q35/kvm/dmar", test_acpi_q35_kvm_dmar); } qtest_add_func("acpi/q35/viot", test_acpi_q35_viot); +#ifdef CONFIG_POSIX qtest_add_func("acpi/q35/cxl", test_acpi_q35_cxl); +#endif qtest_add_func("acpi/q35/slic", test_acpi_q35_slic); } else if (strcmp(arch, "aarch64") == 0) { if (has_tcg) { diff --git a/tests/qtest/cdrom-test.c b/tests/qtest/cdrom-test.c index a7766a9e65..26a2400181 100644 --- a/tests/qtest/cdrom-test.c +++ b/tests/qtest/cdrom-test.c @@ -52,7 +52,7 @@ static int prepare_image(const char *arch, char *isoimage) perror("Error creating temporary iso image file"); return -1; } - if (!mkdtemp(srcdir)) { + if (!g_mkdtemp(srcdir)) { perror("Error creating temporary directory"); goto cleanup; } diff --git a/tests/qtest/cxl-test.c b/tests/qtest/cxl-test.c index 2133e973f4..2e14da7dee 100644 --- a/tests/qtest/cxl-test.c +++ b/tests/qtest/cxl-test.c @@ -89,13 +89,14 @@ static void cxl_2root_port(void) qtest_end(); } +#ifdef CONFIG_POSIX static void cxl_t3d(void) { g_autoptr(GString) cmdline = g_string_new(NULL); char template[] = "/tmp/cxl-test-XXXXXX"; const char *tmpfs; - tmpfs = mkdtemp(template); + tmpfs = g_mkdtemp(template); g_string_printf(cmdline, QEMU_PXB_CMD QEMU_RP QEMU_T3D, tmpfs, tmpfs); @@ -109,7 +110,7 @@ static void cxl_1pxb_2rp_2t3d(void) char template[] = "/tmp/cxl-test-XXXXXX"; const char *tmpfs; - tmpfs = mkdtemp(template); + tmpfs = g_mkdtemp(template); g_string_printf(cmdline, QEMU_PXB_CMD QEMU_2RP QEMU_2T3D, tmpfs, tmpfs, tmpfs, tmpfs); @@ -124,7 +125,7 @@ static void cxl_2pxb_4rp_4t3d(void) char template[] = "/tmp/cxl-test-XXXXXX"; const char *tmpfs; - tmpfs = mkdtemp(template); + tmpfs = g_mkdtemp(template); g_string_printf(cmdline, QEMU_2PXB_CMD QEMU_4RP QEMU_4T3D, tmpfs, tmpfs, tmpfs, tmpfs, tmpfs, tmpfs, @@ -133,6 +134,7 @@ static void cxl_2pxb_4rp_4t3d(void) qtest_start(cmdline->str); qtest_end(); } +#endif /* CONFIG_POSIX */ int main(int argc, char **argv) { @@ -144,8 +146,10 @@ int main(int argc, char **argv) qtest_add_func("/pci/cxl/pxb_x2_with_window", cxl_2pxb_with_window); qtest_add_func("/pci/cxl/rp", cxl_root_port); qtest_add_func("/pci/cxl/rp_x2", cxl_2root_port); +#ifdef CONFIG_POSIX qtest_add_func("/pci/cxl/type3_device", cxl_t3d); qtest_add_func("/pci/cxl/rp_x2_type3_x2", cxl_1pxb_2rp_2t3d); qtest_add_func("/pci/cxl/pxb_x2_root_port_x4_type3_x4", cxl_2pxb_4rp_4t3d); +#endif return g_test_run(); } diff --git a/tests/qtest/device-plug-test.c b/tests/qtest/device-plug-test.c index 2e3137843e..a1fb99c8ff 100644 --- a/tests/qtest/device-plug-test.c +++ b/tests/qtest/device-plug-test.c @@ -95,7 +95,7 @@ static void test_pci_unplug_json_request(void) } QTestState *qtest = qtest_initf( - "%s -device '{\"driver\": \"virtio-mouse-pci\", \"id\": \"dev0\"}'", + "%s -device \"{'driver': 'virtio-mouse-pci', 'id': 'dev0'}\"", machine_addition); /* diff --git a/tests/qtest/e1000e-test.c b/tests/qtest/e1000e-test.c index c98779c7c0..4cdd8238f2 100644 --- a/tests/qtest/e1000e-test.c +++ b/tests/qtest/e1000e-test.c @@ -31,7 +31,7 @@ #include "qemu/iov.h" #include "qemu/module.h" #include "qemu/bitops.h" -#include "libqos/malloc.h" +#include "libqos/libqos-malloc.h" #include "libqos/e1000e.h" static void e1000e_send_verify(QE1000E *d, int *test_sockets, QGuestAllocator *alloc) diff --git a/tests/qtest/fuzz/generic_fuzz.c b/tests/qtest/fuzz/generic_fuzz.c index 447ffe8178..afc1d20355 100644 --- a/tests/qtest/fuzz/generic_fuzz.c +++ b/tests/qtest/fuzz/generic_fuzz.c @@ -994,16 +994,16 @@ static GString *generic_fuzz_predefined_config_cmdline(FuzzTarget *t) g_assert(t->opaque); config = t->opaque; - setenv("QEMU_AVOID_DOUBLE_FETCH", "1", 1); + g_setenv("QEMU_AVOID_DOUBLE_FETCH", "1", 1); if (config->argfunc) { args = config->argfunc(); - setenv("QEMU_FUZZ_ARGS", args, 1); + g_setenv("QEMU_FUZZ_ARGS", args, 1); g_free(args); } else { g_assert_nonnull(config->args); - setenv("QEMU_FUZZ_ARGS", config->args, 1); + g_setenv("QEMU_FUZZ_ARGS", config->args, 1); } - setenv("QEMU_FUZZ_OBJECTS", config->objects, 1); + g_setenv("QEMU_FUZZ_OBJECTS", config->objects, 1); return generic_fuzz_cmdline(t); } diff --git a/tests/qtest/fuzz/generic_fuzz_configs.h b/tests/qtest/fuzz/generic_fuzz_configs.h index 004c701915..0775e6702b 100644 --- a/tests/qtest/fuzz/generic_fuzz_configs.h +++ b/tests/qtest/fuzz/generic_fuzz_configs.h @@ -21,7 +21,7 @@ typedef struct generic_fuzz_config { static inline gchar *generic_fuzzer_virtio_9p_args(void){ char tmpdir[] = "/tmp/qemu-fuzz.XXXXXX"; - g_assert_nonnull(mkdtemp(tmpdir)); + g_assert_nonnull(g_mkdtemp(tmpdir)); return g_strdup_printf("-machine q35 -nodefaults " "-device virtio-9p,fsdev=hshare,mount_tag=hshare " diff --git a/tests/qtest/fuzz/qos_fuzz.c b/tests/qtest/fuzz/qos_fuzz.c index c856d3d500..3a3d9c16dd 100644 --- a/tests/qtest/fuzz/qos_fuzz.c +++ b/tests/qtest/fuzz/qos_fuzz.c @@ -23,7 +23,7 @@ #include "qemu/main-loop.h" #include "tests/qtest/libqtest.h" -#include "tests/qtest/libqos/malloc.h" +#include "tests/qtest/libqos/libqos-malloc.h" #include "tests/qtest/libqos/qgraph.h" #include "tests/qtest/libqos/qgraph_internal.h" #include "tests/qtest/libqos/qos_external.h" diff --git a/tests/qtest/i440fx-test.c b/tests/qtest/i440fx-test.c index 6d7d4d8d8f..3890f1237c 100644 --- a/tests/qtest/i440fx-test.c +++ b/tests/qtest/i440fx-test.c @@ -278,6 +278,8 @@ static void test_i440fx_pam(gconstpointer opaque) qtest_end(); } +#ifndef _WIN32 + #define BLOB_SIZE ((size_t)65536) #define ISA_BIOS_MAXSZ ((size_t)(128 * 1024)) @@ -396,6 +398,8 @@ static void request_pflash(FirmwareTestFixture *fixture, fixture->is_bios = false; } +#endif /* _WIN32 */ + int main(int argc, char **argv) { TestData data; @@ -406,8 +410,10 @@ int main(int argc, char **argv) qtest_add_data_func("i440fx/defaults", &data, test_i440fx_defaults); qtest_add_data_func("i440fx/pam", &data, test_i440fx_pam); +#ifndef _WIN32 add_firmware_test("i440fx/firmware/bios", request_bios); add_firmware_test("i440fx/firmware/pflash", request_pflash); +#endif return g_test_run(); } diff --git a/tests/qtest/ivshmem-test.c b/tests/qtest/ivshmem-test.c index e23a97fa8e..9611d05eb5 100644 --- a/tests/qtest/ivshmem-test.c +++ b/tests/qtest/ivshmem-test.c @@ -481,8 +481,8 @@ int main(int argc, char **argv) tmpshmem = mmap(0, TMPSHMSIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); g_assert(tmpshmem != MAP_FAILED); /* server */ - if (mkdtemp(dir) == NULL) { - g_error("mkdtemp: %s", g_strerror(errno)); + if (g_mkdtemp(dir) == NULL) { + g_error("g_mkdtemp: %s", g_strerror(errno)); } tmpdir = dir; tmpserver = g_strconcat(tmpdir, "/server", NULL); diff --git a/tests/qtest/libqos/aarch64-xlnx-zcu102-machine.c b/tests/qtest/libqos/aarch64-xlnx-zcu102-machine.c index c8a3ea11eb..ab24add8eb 100644 --- a/tests/qtest/libqos/aarch64-xlnx-zcu102-machine.c +++ b/tests/qtest/libqos/aarch64-xlnx-zcu102-machine.c @@ -19,7 +19,7 @@ #include "qemu/osdep.h" #include "../libqtest.h" #include "qemu/module.h" -#include "malloc.h" +#include "libqos-malloc.h" #include "qgraph.h" #include "sdhci.h" diff --git a/tests/qtest/libqos/arm-imx25-pdk-machine.c b/tests/qtest/libqos/arm-imx25-pdk-machine.c index 54d0c95330..8fe128fae8 100644 --- a/tests/qtest/libqos/arm-imx25-pdk-machine.c +++ b/tests/qtest/libqos/arm-imx25-pdk-machine.c @@ -20,7 +20,7 @@ #include "qemu/osdep.h" #include "../libqtest.h" -#include "malloc.h" +#include "libqos-malloc.h" #include "qgraph.h" #include "i2c.h" diff --git a/tests/qtest/libqos/arm-n800-machine.c b/tests/qtest/libqos/arm-n800-machine.c index ecd46b1daf..4e5afe0164 100644 --- a/tests/qtest/libqos/arm-n800-machine.c +++ b/tests/qtest/libqos/arm-n800-machine.c @@ -20,7 +20,7 @@ #include "qemu/osdep.h" #include "../libqtest.h" -#include "malloc.h" +#include "libqos-malloc.h" #include "qgraph.h" #include "i2c.h" diff --git a/tests/qtest/libqos/arm-raspi2-machine.c b/tests/qtest/libqos/arm-raspi2-machine.c index 0a2943440b..367c6c17a5 100644 --- a/tests/qtest/libqos/arm-raspi2-machine.c +++ b/tests/qtest/libqos/arm-raspi2-machine.c @@ -19,7 +19,7 @@ #include "qemu/osdep.h" #include "../libqtest.h" #include "qemu/module.h" -#include "malloc.h" +#include "libqos-malloc.h" #include "qgraph.h" #include "sdhci.h" diff --git a/tests/qtest/libqos/arm-sabrelite-machine.c b/tests/qtest/libqos/arm-sabrelite-machine.c index ec19a01660..94f6a20fc7 100644 --- a/tests/qtest/libqos/arm-sabrelite-machine.c +++ b/tests/qtest/libqos/arm-sabrelite-machine.c @@ -19,7 +19,7 @@ #include "qemu/osdep.h" #include "../libqtest.h" #include "qemu/module.h" -#include "malloc.h" +#include "libqos-malloc.h" #include "qgraph.h" #include "sdhci.h" diff --git a/tests/qtest/libqos/arm-smdkc210-machine.c b/tests/qtest/libqos/arm-smdkc210-machine.c index 4bff249ee8..9bbce924ea 100644 --- a/tests/qtest/libqos/arm-smdkc210-machine.c +++ b/tests/qtest/libqos/arm-smdkc210-machine.c @@ -19,7 +19,7 @@ #include "qemu/osdep.h" #include "../libqtest.h" #include "qemu/module.h" -#include "malloc.h" +#include "libqos-malloc.h" #include "qgraph.h" #include "sdhci.h" diff --git a/tests/qtest/libqos/arm-virt-machine.c b/tests/qtest/libqos/arm-virt-machine.c index 139eaba142..4e87405b58 100644 --- a/tests/qtest/libqos/arm-virt-machine.c +++ b/tests/qtest/libqos/arm-virt-machine.c @@ -19,7 +19,7 @@ #include "qemu/osdep.h" #include "../libqtest.h" #include "qemu/module.h" -#include "malloc.h" +#include "libqos-malloc.h" #include "qgraph.h" #include "virtio-mmio.h" #include "generic-pcihost.h" diff --git a/tests/qtest/libqos/arm-xilinx-zynq-a9-machine.c b/tests/qtest/libqos/arm-xilinx-zynq-a9-machine.c index 3be80020a6..daac762a06 100644 --- a/tests/qtest/libqos/arm-xilinx-zynq-a9-machine.c +++ b/tests/qtest/libqos/arm-xilinx-zynq-a9-machine.c @@ -19,7 +19,7 @@ #include "qemu/osdep.h" #include "../libqtest.h" #include "qemu/module.h" -#include "malloc.h" +#include "libqos-malloc.h" #include "qgraph.h" #include "sdhci.h" diff --git a/tests/qtest/libqos/e1000e.c b/tests/qtest/libqos/e1000e.c index f87e0e84b2..fc14b07884 100644 --- a/tests/qtest/libqos/e1000e.c +++ b/tests/qtest/libqos/e1000e.c @@ -23,7 +23,7 @@ #include "qemu/iov.h" #include "qemu/module.h" #include "qemu/bitops.h" -#include "malloc.h" +#include "libqos-malloc.h" #include "qgraph.h" #include "e1000e.h" diff --git a/tests/qtest/libqos/generic-pcihost.h b/tests/qtest/libqos/generic-pcihost.h index c693c769df..6493a8712a 100644 --- a/tests/qtest/libqos/generic-pcihost.h +++ b/tests/qtest/libqos/generic-pcihost.h @@ -14,7 +14,7 @@ #define LIBQOS_GENERIC_PCIHOST_H #include "pci.h" -#include "malloc.h" +#include "libqos-malloc.h" #include "qgraph.h" typedef struct QGenericPCIBus { diff --git a/tests/qtest/libqos/malloc.c b/tests/qtest/libqos/libqos-malloc.c index f0c8f950c8..d7566972c4 100644 --- a/tests/qtest/libqos/malloc.c +++ b/tests/qtest/libqos/libqos-malloc.c @@ -11,7 +11,7 @@ */ #include "qemu/osdep.h" -#include "malloc.h" +#include "libqos-malloc.h" #include "qemu/host-utils.h" typedef struct MemBlock { diff --git a/tests/qtest/libqos/malloc.h b/tests/qtest/libqos/libqos-malloc.h index bbb8c743cc..bbb8c743cc 100644 --- a/tests/qtest/libqos/malloc.h +++ b/tests/qtest/libqos/libqos-malloc.h diff --git a/tests/qtest/libqos/libqos.c b/tests/qtest/libqos/libqos.c index 85c7641add..5ffda080ec 100644 --- a/tests/qtest/libqos/libqos.c +++ b/tests/qtest/libqos/libqos.c @@ -1,6 +1,4 @@ #include "qemu/osdep.h" -#include <sys/wait.h> - #include "../libqtest.h" #include "libqos.h" #include "pci.h" diff --git a/tests/qtest/libqos/libqos.h b/tests/qtest/libqos/libqos.h index ba7df448ca..9b4dd509f0 100644 --- a/tests/qtest/libqos/libqos.h +++ b/tests/qtest/libqos/libqos.h @@ -3,7 +3,7 @@ #include "../libqtest.h" #include "pci.h" -#include "malloc.h" +#include "libqos-malloc.h" typedef struct QOSState QOSState; diff --git a/tests/qtest/libqos/malloc-pc.h b/tests/qtest/libqos/malloc-pc.h index d8d79853c8..e531473601 100644 --- a/tests/qtest/libqos/malloc-pc.h +++ b/tests/qtest/libqos/malloc-pc.h @@ -13,7 +13,7 @@ #ifndef LIBQOS_MALLOC_PC_H #define LIBQOS_MALLOC_PC_H -#include "malloc.h" +#include "libqos-malloc.h" void pc_alloc_init(QGuestAllocator *s, QTestState *qts, QAllocOpts flags); diff --git a/tests/qtest/libqos/malloc-spapr.h b/tests/qtest/libqos/malloc-spapr.h index f99572fd71..f544c0d611 100644 --- a/tests/qtest/libqos/malloc-spapr.h +++ b/tests/qtest/libqos/malloc-spapr.h @@ -8,7 +8,7 @@ #ifndef LIBQOS_MALLOC_SPAPR_H #define LIBQOS_MALLOC_SPAPR_H -#include "malloc.h" +#include "libqos-malloc.h" void spapr_alloc_init(QGuestAllocator *s, QTestState *qts, QAllocOpts flags); diff --git a/tests/qtest/libqos/meson.build b/tests/qtest/libqos/meson.build index fd5d6e5ae1..cff83c86d9 100644 --- a/tests/qtest/libqos/meson.build +++ b/tests/qtest/libqos/meson.build @@ -6,7 +6,7 @@ libqos_srcs = files( 'qos_external.c', 'pci.c', 'fw_cfg.c', - 'malloc.c', + 'libqos-malloc.c', 'libqos.c', 'sdhci-cmd.c', diff --git a/tests/qtest/libqos/pci-pc.h b/tests/qtest/libqos/pci-pc.h index 49ec9507f2..849bd493de 100644 --- a/tests/qtest/libqos/pci-pc.h +++ b/tests/qtest/libqos/pci-pc.h @@ -14,7 +14,7 @@ #define LIBQOS_PCI_PC_H #include "pci.h" -#include "malloc.h" +#include "libqos-malloc.h" #include "qgraph.h" typedef struct QPCIBusPC { diff --git a/tests/qtest/libqos/pci-spapr.h b/tests/qtest/libqos/pci-spapr.h index 20a43718b7..3dbf1e58ae 100644 --- a/tests/qtest/libqos/pci-spapr.h +++ b/tests/qtest/libqos/pci-spapr.h @@ -8,7 +8,7 @@ #ifndef LIBQOS_PCI_SPAPR_H #define LIBQOS_PCI_SPAPR_H -#include "malloc.h" +#include "libqos-malloc.h" #include "pci.h" #include "qgraph.h" diff --git a/tests/qtest/libqos/qgraph.h b/tests/qtest/libqos/qgraph.h index 871740c0dc..6e94824d09 100644 --- a/tests/qtest/libqos/qgraph.h +++ b/tests/qtest/libqos/qgraph.h @@ -21,7 +21,7 @@ #include <gmodule.h> #include "qemu/module.h" -#include "malloc.h" +#include "libqos-malloc.h" /* maximum path length */ #define QOS_PATH_MAX_ELEMENT_SIZE 50 diff --git a/tests/qtest/libqos/qos_external.c b/tests/qtest/libqos/qos_external.c index b7a0b873a3..c6bb8bff09 100644 --- a/tests/qtest/libqos/qos_external.c +++ b/tests/qtest/libqos/qos_external.c @@ -24,7 +24,7 @@ #include "qapi/qmp/qstring.h" #include "qemu/module.h" #include "qapi/qmp/qlist.h" -#include "malloc.h" +#include "libqos-malloc.h" #include "qgraph.h" #include "qgraph_internal.h" #include "qos_external.h" diff --git a/tests/qtest/libqos/qos_external.h b/tests/qtest/libqos/qos_external.h index 8446e3df0b..ea37364887 100644 --- a/tests/qtest/libqos/qos_external.h +++ b/tests/qtest/libqos/qos_external.h @@ -21,7 +21,7 @@ #include "qgraph.h" -#include "malloc.h" +#include "libqos-malloc.h" #include "qapi/qapi-types-machine.h" #include "qapi/qapi-types-qom.h" diff --git a/tests/qtest/libqos/rtas.h b/tests/qtest/libqos/rtas.h index f38f99dfab..be8353d505 100644 --- a/tests/qtest/libqos/rtas.h +++ b/tests/qtest/libqos/rtas.h @@ -5,7 +5,7 @@ #ifndef LIBQOS_RTAS_H #define LIBQOS_RTAS_H -#include "malloc.h" +#include "libqos-malloc.h" int qrtas_get_time_of_day(QTestState *qts, QGuestAllocator *alloc, struct tm *tm, uint32_t *ns); diff --git a/tests/qtest/libqos/virtio-9p.c b/tests/qtest/libqos/virtio-9p.c index 70aea8bf62..ae9b0a20e2 100644 --- a/tests/qtest/libqos/virtio-9p.c +++ b/tests/qtest/libqos/virtio-9p.c @@ -48,9 +48,9 @@ void virtio_9p_create_local_test_dir(void) */ char *template = concat_path(pwd, "qtest-9p-local-XXXXXX"); - local_test_path = mkdtemp(template); + local_test_path = g_mkdtemp(template); if (!local_test_path) { - g_test_message("mkdtemp('%s') failed: %s", template, strerror(errno)); + g_test_message("g_mkdtemp('%s') failed: %s", template, strerror(errno)); } g_assert(local_test_path != NULL); diff --git a/tests/qtest/libqos/virtio-mmio.c b/tests/qtest/libqos/virtio-mmio.c index a6cca8613b..bd0b1d890b 100644 --- a/tests/qtest/libqos/virtio-mmio.c +++ b/tests/qtest/libqos/virtio-mmio.c @@ -12,7 +12,7 @@ #include "qemu/module.h" #include "virtio.h" #include "virtio-mmio.h" -#include "malloc.h" +#include "libqos-malloc.h" #include "qgraph.h" #include "standard-headers/linux/virtio_ring.h" diff --git a/tests/qtest/libqos/virtio-pci.c b/tests/qtest/libqos/virtio-pci.c index 67c2498c84..485b8f6b7e 100644 --- a/tests/qtest/libqos/virtio-pci.c +++ b/tests/qtest/libqos/virtio-pci.c @@ -13,7 +13,7 @@ #include "virtio-pci.h" #include "pci.h" #include "pci-pc.h" -#include "malloc.h" +#include "libqos-malloc.h" #include "malloc-pc.h" #include "qgraph.h" #include "standard-headers/linux/virtio_ring.h" diff --git a/tests/qtest/libqos/virtio.h b/tests/qtest/libqos/virtio.h index b8bd06e1b8..7adc7cbd10 100644 --- a/tests/qtest/libqos/virtio.h +++ b/tests/qtest/libqos/virtio.h @@ -10,7 +10,7 @@ #ifndef LIBQOS_VIRTIO_H #define LIBQOS_VIRTIO_H -#include "malloc.h" +#include "libqos-malloc.h" #include "standard-headers/linux/virtio_ring.h" #define QVIRTIO_F_BAD_FEATURE 0x40000000ull diff --git a/tests/qtest/libqtest.c b/tests/qtest/libqtest.c index 8c159eacf5..7c9fc07de4 100644 --- a/tests/qtest/libqtest.c +++ b/tests/qtest/libqtest.c @@ -393,7 +393,7 @@ QTestState *qtest_init_with_serial(const char *extra_args, int *sock_fd) char *sock_path, sock_dir[] = "/tmp/qtest-serial-XXXXXX"; QTestState *qts; - g_assert_true(mkdtemp(sock_dir) != NULL); + g_assert_true(g_mkdtemp(sock_dir) != NULL); sock_path = g_strdup_printf("%s/sock", sock_dir); sock_fd_init = init_socket(sock_path); @@ -1424,7 +1424,7 @@ QTestState *qtest_inproc_init(QTestState **s, bool log, const char* arch, * way, qtest_get_arch works for inproc qtest. */ gchar *bin_path = g_strconcat("/qemu-system-", arch, NULL); - setenv("QTEST_QEMU_BINARY", bin_path, 0); + g_setenv("QTEST_QEMU_BINARY", bin_path, 0); g_free(bin_path); return qts; diff --git a/tests/qtest/m48t59-test.c b/tests/qtest/m48t59-test.c index b94a1230f7..843d2ced8e 100644 --- a/tests/qtest/m48t59-test.c +++ b/tests/qtest/m48t59-test.c @@ -137,7 +137,7 @@ static void cmos_get_date_time(QTestState *s, struct tm *date) date->tm_mday = mday; date->tm_mon = mon - 1; date->tm_year = base_year + year - 1900; -#ifndef __sun__ +#if !defined(__sun__) && !defined(_WIN32) date->tm_gmtoff = 0; #endif diff --git a/tests/qtest/machine-none-test.c b/tests/qtest/machine-none-test.c index f92fab479f..31cc0bfb01 100644 --- a/tests/qtest/machine-none-test.c +++ b/tests/qtest/machine-none-test.c @@ -81,7 +81,7 @@ static void test_machine_cpu_cli(void) " add it to cpus_map\n", arch); return; /* TODO: die here to force all targets have a test */ } - qts = qtest_initf("-machine none -cpu '%s'", cpu_model); + qts = qtest_initf("-machine none -cpu \"%s\"", cpu_model); response = qtest_qmp(qts, "{ 'execute': 'quit' }"); g_assert(qdict_haskey(response, "return")); diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build index be4b30dea2..e910cb32ca 100644 --- a/tests/qtest/meson.build +++ b/tests/qtest/meson.build @@ -71,7 +71,8 @@ qtests_i386 = \ (config_all_devices.has_key('CONFIG_SB16') ? ['fuzz-sb16-test'] : []) + \ (config_all_devices.has_key('CONFIG_SDHCI_PCI') ? ['fuzz-sdcard-test'] : []) + \ (config_all_devices.has_key('CONFIG_ESP_PCI') ? ['am53c974-test'] : []) + \ - (config_all_devices.has_key('CONFIG_ACPI_ERST') ? ['erst-test'] : []) + \ + (config_host.has_key('CONFIG_POSIX') and \ + config_all_devices.has_key('CONFIG_ACPI_ERST') ? ['erst-test'] : []) + \ (config_all_devices.has_key('CONFIG_VIRTIO_NET') and \ config_all_devices.has_key('CONFIG_Q35') and \ config_all_devices.has_key('CONFIG_VIRTIO_PCI') and \ @@ -239,7 +240,6 @@ qos_test_ss.add( 'adm1272-test.c', 'ds1338-test.c', 'e1000-test.c', - 'e1000e-test.c', 'eepro100-test.c', 'es1370-test.c', 'ipoctal232-test.c', @@ -267,6 +267,9 @@ qos_test_ss.add( 'virtio-iommu-test.c', 'vmxnet3-test.c', ) +if config_host.has_key('CONFIG_POSIX') + qos_test_ss.add(files('e1000e-test.c')) +endif if have_virtfs qos_test_ss.add(files('virtio-9p-test.c')) endif diff --git a/tests/qtest/migration-helpers.c b/tests/qtest/migration-helpers.c index c6fbeb3974..f6f3c6680f 100644 --- a/tests/qtest/migration-helpers.c +++ b/tests/qtest/migration-helpers.c @@ -34,6 +34,7 @@ static void check_stop_event(QTestState *who) } } +#ifndef _WIN32 /* * Events can get in the way of responses we are actually waiting for. */ @@ -58,6 +59,7 @@ QDict *wait_command_fd(QTestState *who, int fd, const char *command, ...) return ret; } +#endif /* * Events can get in the way of responses we are actually waiting for. diff --git a/tests/qtest/migration-helpers.h b/tests/qtest/migration-helpers.h index 59561898d0..db0684de48 100644 --- a/tests/qtest/migration-helpers.h +++ b/tests/qtest/migration-helpers.h @@ -17,8 +17,10 @@ extern bool got_stop; +#ifndef _WIN32 G_GNUC_PRINTF(3, 4) QDict *wait_command_fd(QTestState *who, int fd, const char *command, ...); +#endif G_GNUC_PRINTF(2, 3) QDict *wait_command(QTestState *who, const char *command, ...); diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c index f63edd0bc8..4728d528bb 100644 --- a/tests/qtest/migration-test.c +++ b/tests/qtest/migration-test.c @@ -761,14 +761,14 @@ test_migrate_tls_psk_start_common(QTestState *from, data->workdir = g_strdup_printf("%s/tlscredspsk0", tmpfs); data->pskfile = g_strdup_printf("%s/%s", data->workdir, QCRYPTO_TLS_CREDS_PSKFILE); - mkdir(data->workdir, 0700); + g_mkdir_with_parents(data->workdir, 0700); test_tls_psk_init(data->pskfile); if (mismatch) { data->workdiralt = g_strdup_printf("%s/tlscredspskalt0", tmpfs); data->pskfilealt = g_strdup_printf("%s/%s", data->workdiralt, QCRYPTO_TLS_CREDS_PSKFILE); - mkdir(data->workdiralt, 0700); + g_mkdir_with_parents(data->workdiralt, 0700); test_tls_psk_init_alt(data->pskfilealt); } @@ -873,12 +873,20 @@ test_migrate_tls_x509_start_common(QTestState *from, data->clientcert = g_strdup_printf("%s/client-cert.pem", data->workdir); } - mkdir(data->workdir, 0700); + g_mkdir_with_parents(data->workdir, 0700); test_tls_init(data->keyfile); +#ifndef _WIN32 g_assert(link(data->keyfile, data->serverkey) == 0); +#else + g_assert(CreateHardLink(data->serverkey, data->keyfile, NULL) != 0); +#endif if (args->clientcert) { +#ifndef _WIN32 g_assert(link(data->keyfile, data->clientkey) == 0); +#else + g_assert(CreateHardLink(data->clientkey, data->keyfile, NULL) != 0); +#endif } TLS_ROOT_REQ_SIMPLE(cacertreq, data->cacert); @@ -1623,6 +1631,7 @@ static void test_precopy_tcp_tls_x509_reject_anon_client(void) #endif /* CONFIG_TASN1 */ #endif /* CONFIG_GNUTLS */ +#ifndef _WIN32 static void *test_migrate_fd_start_hook(QTestState *from, QTestState *to) { @@ -1691,6 +1700,7 @@ static void test_migrate_fd_proto(void) }; test_precopy_common(&args); } +#endif /* _WIN32 */ static void do_test_validate_uuid(MigrateStart *args, bool should_fail) { @@ -2452,9 +2462,9 @@ int main(int argc, char **argv) return g_test_run(); } - tmpfs = mkdtemp(template); + tmpfs = g_mkdtemp(template); if (!tmpfs) { - g_test_message("mkdtemp on path (%s): %s", template, strerror(errno)); + g_test_message("g_mkdtemp on path (%s): %s", template, strerror(errno)); } g_assert(tmpfs); @@ -2523,7 +2533,9 @@ int main(int argc, char **argv) #endif /* CONFIG_GNUTLS */ /* qtest_add_func("/migration/ignore_shared", test_ignore_shared); */ +#ifndef _WIN32 qtest_add_func("/migration/fd_proto", test_migrate_fd_proto); +#endif qtest_add_func("/migration/validate_uuid", test_validate_uuid); qtest_add_func("/migration/validate_uuid_error", test_validate_uuid_error); qtest_add_func("/migration/validate_uuid_src_not_set", diff --git a/tests/qtest/npcm7xx_emc-test.c b/tests/qtest/npcm7xx_emc-test.c index a353fef0ca..c373d24e1e 100644 --- a/tests/qtest/npcm7xx_emc-test.c +++ b/tests/qtest/npcm7xx_emc-test.c @@ -209,6 +209,7 @@ static int emc_module_index(const EMCModule *mod) return diff; } +#ifndef _WIN32 static void packet_test_clear(void *sockets) { int *test_sockets = sockets; @@ -243,6 +244,7 @@ static int *packet_test_init(int module_num, GString *cmd_line) g_test_queue_destroy(packet_test_clear, test_sockets); return test_sockets; } +#endif /* _WIN32 */ static uint32_t emc_read(QTestState *qts, const EMCModule *mod, NPCM7xxPWMRegister regno) @@ -250,6 +252,7 @@ static uint32_t emc_read(QTestState *qts, const EMCModule *mod, return qtest_readl(qts, mod->base_addr + regno * sizeof(uint32_t)); } +#ifndef _WIN32 static void emc_write(QTestState *qts, const EMCModule *mod, NPCM7xxPWMRegister regno, uint32_t value) { @@ -339,6 +342,7 @@ static bool emc_soft_reset(QTestState *qts, const EMCModule *mod) g_message("%s: Timeout expired", __func__); return false; } +#endif /* _WIN32 */ /* Check emc registers are reset to default value. */ static void test_init(gconstpointer test_data) @@ -387,6 +391,7 @@ static void test_init(gconstpointer test_data) qtest_quit(qts); } +#ifndef _WIN32 static bool emc_wait_irq(QTestState *qts, const EMCModule *mod, int step, bool is_tx) { @@ -843,6 +848,7 @@ static void test_rx(gconstpointer test_data) qtest_quit(qts); } +#endif /* _WIN32 */ static void emc_add_test(const char *name, const TestData* td, GTestDataFunc fn) @@ -865,8 +871,10 @@ int main(int argc, char **argv) td->module = &emc_module_list[i]; add_test(init, td); +#ifndef _WIN32 add_test(tx, td); add_test(rx, td); +#endif } return g_test_run(); diff --git a/tests/qtest/prom-env-test.c b/tests/qtest/prom-env-test.c index c2b0448e55..39ccb59797 100644 --- a/tests/qtest/prom-env-test.c +++ b/tests/qtest/prom-env-test.c @@ -58,8 +58,8 @@ static void test_machine(const void *machine) " -machine " PSERIES_DEFAULT_CAPABILITIES; } - qts = qtest_initf("-M %s -accel tcg %s -prom-env 'use-nvramrc?=true' " - "-prom-env 'nvramrc=%x %x l!' ", (const char *)machine, + qts = qtest_initf("-M %s -accel tcg %s -prom-env \"use-nvramrc?=true\" " + "-prom-env \"nvramrc=%x %x l!\" ", (const char *)machine, extra_args, MAGIC, ADDRESS); check_guest_memory(qts); qtest_quit(qts); diff --git a/tests/qtest/qmp-test.c b/tests/qtest/qmp-test.c index 9a42480cef..bf7304c7dc 100644 --- a/tests/qtest/qmp-test.c +++ b/tests/qtest/qmp-test.c @@ -166,8 +166,8 @@ char *fifo_name; static void setup_blocking_cmd(void) { - if (!mkdtemp(tmpdir)) { - g_error("mkdtemp: %s", strerror(errno)); + if (!g_mkdtemp(tmpdir)) { + g_error("g_mkdtemp: %s", strerror(errno)); } fifo_name = g_strdup_printf("%s/fifo", tmpdir); if (mkfifo(fifo_name, 0666)) { diff --git a/tests/qtest/qos-test.c b/tests/qtest/qos-test.c index f97d0a08fd..831db5cf2a 100644 --- a/tests/qtest/qos-test.c +++ b/tests/qtest/qos-test.c @@ -25,7 +25,7 @@ #include "qapi/qobject-input-visitor.h" #include "qapi/qapi-visit-machine.h" #include "qapi/qapi-visit-qom.h" -#include "libqos/malloc.h" +#include "libqos/libqos-malloc.h" #include "libqos/qgraph.h" #include "libqos/qgraph_internal.h" #include "libqos/qos_external.h" diff --git a/tests/qtest/rtc-test.c b/tests/qtest/rtc-test.c index 8126ab1bdb..02ed4e1238 100644 --- a/tests/qtest/rtc-test.c +++ b/tests/qtest/rtc-test.c @@ -111,7 +111,7 @@ static void cmos_get_date_time(struct tm *date) date->tm_mday = mday; date->tm_mon = mon - 1; date->tm_year = base_year + year - 1900; -#ifndef __sun__ +#if !defined(__sun__) && !defined(_WIN32) date->tm_gmtoff = 0; #endif diff --git a/tests/qtest/vhost-user-test.c b/tests/qtest/vhost-user-test.c index 8bf390be20..d7d6cfc9bd 100644 --- a/tests/qtest/vhost-user-test.c +++ b/tests/qtest/vhost-user-test.c @@ -491,9 +491,9 @@ static TestServer *test_server_new(const gchar *name, /* run the main loop thread so the chardev may operate */ server->thread = g_thread_new(NULL, thread_function, server->loop); - tmpfs = mkdtemp(template); + tmpfs = g_mkdtemp(template); if (!tmpfs) { - g_test_message("mkdtemp on path (%s): %s", template, strerror(errno)); + g_test_message("g_mkdtemp on path (%s): %s", template, strerror(errno)); } g_assert(tmpfs); diff --git a/tests/unit/test-crypto-tlscredsx509.c b/tests/unit/test-crypto-tlscredsx509.c index aab4149b56..3c25d75ca1 100644 --- a/tests/unit/test-crypto-tlscredsx509.c +++ b/tests/unit/test-crypto-tlscredsx509.c @@ -75,7 +75,7 @@ static void test_tls_creds(const void *opaque) QCryptoTLSCreds *creds; #define CERT_DIR "tests/test-crypto-tlscredsx509-certs/" - mkdir(CERT_DIR, 0700); + g_mkdir_with_parents(CERT_DIR, 0700); unlink(CERT_DIR QCRYPTO_TLS_CREDS_X509_CA_CERT); if (data->isServer) { @@ -141,7 +141,7 @@ int main(int argc, char **argv) g_test_init(&argc, &argv, NULL); g_setenv("GNUTLS_FORCE_FIPS_MODE", "2", 1); - mkdir(WORKDIR, 0700); + g_mkdir_with_parents(WORKDIR, 0700); test_tls_init(KEYFILE); diff --git a/tests/unit/test-crypto-tlssession.c b/tests/unit/test-crypto-tlssession.c index f222959d36..615a1344b4 100644 --- a/tests/unit/test-crypto-tlssession.c +++ b/tests/unit/test-crypto-tlssession.c @@ -249,8 +249,8 @@ static void test_crypto_tls_session_x509(const void *opaque) #define CLIENT_CERT_DIR "tests/test-crypto-tlssession-client/" #define SERVER_CERT_DIR "tests/test-crypto-tlssession-server/" - mkdir(CLIENT_CERT_DIR, 0700); - mkdir(SERVER_CERT_DIR, 0700); + g_mkdir_with_parents(CLIENT_CERT_DIR, 0700); + g_mkdir_with_parents(SERVER_CERT_DIR, 0700); unlink(SERVER_CERT_DIR QCRYPTO_TLS_CREDS_X509_CA_CERT); unlink(SERVER_CERT_DIR QCRYPTO_TLS_CREDS_X509_SERVER_CERT); @@ -398,7 +398,7 @@ int main(int argc, char **argv) g_test_init(&argc, &argv, NULL); g_setenv("GNUTLS_FORCE_FIPS_MODE", "2", 1); - mkdir(WORKDIR, 0700); + g_mkdir_with_parents(WORKDIR, 0700); test_tls_init(KEYFILE); test_tls_psk_init(PSKFILE); diff --git a/tests/unit/test-io-channel-tls.c b/tests/unit/test-io-channel-tls.c index f6fb988c01..cc39247556 100644 --- a/tests/unit/test-io-channel-tls.c +++ b/tests/unit/test-io-channel-tls.c @@ -125,8 +125,8 @@ static void test_io_channel_tls(const void *opaque) #define CLIENT_CERT_DIR "tests/test-io-channel-tls-client/" #define SERVER_CERT_DIR "tests/test-io-channel-tls-server/" - mkdir(CLIENT_CERT_DIR, 0700); - mkdir(SERVER_CERT_DIR, 0700); + g_mkdir_with_parents(CLIENT_CERT_DIR, 0700); + g_mkdir_with_parents(SERVER_CERT_DIR, 0700); unlink(SERVER_CERT_DIR QCRYPTO_TLS_CREDS_X509_CA_CERT); unlink(SERVER_CERT_DIR QCRYPTO_TLS_CREDS_X509_SERVER_CERT); @@ -273,7 +273,7 @@ int main(int argc, char **argv) g_test_init(&argc, &argv, NULL); g_setenv("GNUTLS_FORCE_FIPS_MODE", "2", 1); - mkdir(WORKDIR, 0700); + g_mkdir_with_parents(WORKDIR, 0700); test_tls_init(KEYFILE); diff --git a/tests/unit/test-qga.c b/tests/unit/test-qga.c index b27c77a695..a05a4628ed 100644 --- a/tests/unit/test-qga.c +++ b/tests/unit/test-qga.c @@ -60,7 +60,7 @@ fixture_setup(TestFixture *fixture, gconstpointer data, gchar **envp) fixture->loop = g_main_loop_new(NULL, FALSE); fixture->test_dir = g_strdup("/tmp/qgatest.XXXXXX"); - g_assert_nonnull(mkdtemp(fixture->test_dir)); + g_assert_nonnull(g_mkdtemp(fixture->test_dir)); path = g_build_filename(fixture->test_dir, "sock", NULL); cwd = g_get_current_dir(); diff --git a/tests/vm/freebsd b/tests/vm/freebsd index cd1fabde52..3643fe325d 100755 --- a/tests/vm/freebsd +++ b/tests/vm/freebsd @@ -63,6 +63,9 @@ class FreeBSDVM(basevm.BaseVM): # libs: migration "zstd", + + # libs: networking + "libslirp", ] BUILD_SCRIPT = """ diff --git a/tests/vm/haiku.x86_64 b/tests/vm/haiku.x86_64 index 936f7d2ae2..29668bc272 100755 --- a/tests/vm/haiku.x86_64 +++ b/tests/vm/haiku.x86_64 @@ -71,6 +71,7 @@ class HaikuVM(basevm.BaseVM): "devel:libpixman_1", "devel:libpng16", "devel:libsdl2_2.0", + "devel:libslirp", "devel:libsnappy", "devel:libssh2", "devel:libtasn1", @@ -89,7 +90,7 @@ class HaikuVM(basevm.BaseVM): mkdir -p /usr/bin ln -s /boot/system/bin/env /usr/bin/env cd ../build - ../src/configure --disable-slirp {configure_opts}; + ../src/configure {configure_opts}; make --output-sync -j{jobs} {target} {verbose}; """ diff --git a/tests/vm/netbsd b/tests/vm/netbsd index aa883ec23c..da6773ff59 100755 --- a/tests/vm/netbsd +++ b/tests/vm/netbsd @@ -54,6 +54,9 @@ class NetBSDVM(basevm.BaseVM): # libs: migration "zstd", + + # libs: networking + "libslirp", ] BUILD_SCRIPT = """ diff --git a/util/mmap-alloc.c b/util/mmap-alloc.c index 5b90cb68ea..5ed7d29183 100644 --- a/util/mmap-alloc.c +++ b/util/mmap-alloc.c @@ -53,37 +53,6 @@ size_t qemu_fd_getpagesize(int fd) return qemu_real_host_page_size(); } -size_t qemu_mempath_getpagesize(const char *mem_path) -{ -#ifdef CONFIG_LINUX - struct statfs fs; - int ret; - - if (mem_path) { - do { - ret = statfs(mem_path, &fs); - } while (ret != 0 && errno == EINTR); - - if (ret != 0) { - fprintf(stderr, "Couldn't statfs() memory path: %s\n", - strerror(errno)); - exit(1); - } - - if (fs.f_type == HUGETLBFS_MAGIC) { - /* It's hugepage, return the huge page size */ - return fs.f_bsize; - } - } -#ifdef __sparc__ - /* SPARC Linux needs greater alignment than the pagesize */ - return QEMU_VMALLOC_ALIGN; -#endif -#endif - - return qemu_real_host_page_size(); -} - #define OVERCOMMIT_MEMORY_PATH "/proc/sys/vm/overcommit_memory" static bool map_noreserve_effective(int fd, uint32_t qemu_map_flags) { |