diff --git a/block/iscsi.c b/block/iscsi.c index 7d4b3b56d5..4d2a416ce7 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -1524,12 +1524,10 @@ static void iscsi_detach_aio_context(BlockDriverState *bs) iscsilun->events = 0; if (iscsilun->nop_timer) { - timer_del(iscsilun->nop_timer); timer_free(iscsilun->nop_timer); iscsilun->nop_timer = NULL; } if (iscsilun->event_timer) { - timer_del(iscsilun->event_timer); timer_free(iscsilun->event_timer); iscsilun->event_timer = NULL; } diff --git a/block/nbd.c b/block/nbd.c index 42536702b6..242a258f3a 100644 --- a/block/nbd.c +++ b/block/nbd.c @@ -194,7 +194,6 @@ static void nbd_recv_coroutines_wake_all(BDRVNBDState *s) static void reconnect_delay_timer_del(BDRVNBDState *s) { if (s->reconnect_delay_timer) { - timer_del(s->reconnect_delay_timer); timer_free(s->reconnect_delay_timer); s->reconnect_delay_timer = NULL; } diff --git a/block/qcow2.c b/block/qcow2.c index 3a90ef2786..5d94f45be9 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -852,7 +852,6 @@ static void cache_clean_timer_del(BlockDriverState *bs) { BDRVQcow2State *s = bs->opaque; if (s->cache_clean_timer) { - timer_del(s->cache_clean_timer); timer_free(s->cache_clean_timer); s->cache_clean_timer = NULL; } diff --git a/docs/system/arm/sabrelite.rst b/docs/system/arm/sabrelite.rst new file mode 100644 index 0000000000..71713310e3 --- /dev/null +++ b/docs/system/arm/sabrelite.rst @@ -0,0 +1,119 @@ +Boundary Devices SABRE Lite (``sabrelite``) +=========================================== + +Boundary Devices SABRE Lite i.MX6 Development Board is a low-cost development +platform featuring the powerful Freescale / NXP Semiconductor's i.MX 6 Quad +Applications Processor. + +Supported devices +----------------- + +The SABRE Lite machine supports the following devices: + + * Up to 4 Cortex A9 cores + * Generic Interrupt Controller + * 1 Clock Controller Module + * 1 System Reset Controller + * 5 UARTs + * 2 EPIC timers + * 1 GPT timer + * 2 Watchdog timers + * 1 FEC Ethernet controller + * 3 I2C controllers + * 7 GPIO controllers + * 4 SDHC storage controllers + * 4 USB 2.0 host controllers + * 5 ECSPI controllers + * 1 SST 25VF016B flash + +Please note above list is a complete superset the QEMU SABRE Lite machine can +support. For a normal use case, a device tree blob that represents a real world +SABRE Lite board, only exposes a subset of devices to the guest software. + +Boot options +------------ + +The SABRE Lite machine can start using the standard -kernel functionality +for loading a Linux kernel, U-Boot bootloader or ELF executable. + +Running Linux kernel +-------------------- + +Linux mainline v5.10 release is tested at the time of writing. To build a Linux +mainline kernel that can be booted by the SABRE Lite machine, simply configure +the kernel using the imx_v6_v7_defconfig configuration: + +.. code-block:: bash + + $ export ARCH=arm + $ export CROSS_COMPILE=arm-linux-gnueabihf- + $ make imx_v6_v7_defconfig + $ make + +To boot the newly built Linux kernel in QEMU with the SABRE Lite machine, use: + +.. code-block:: bash + + $ qemu-system-arm -M sabrelite -smp 4 -m 1G \ + -display none -serial null -serial stdio \ + -kernel arch/arm/boot/zImage \ + -dtb arch/arm/boot/dts/imx6q-sabrelite.dtb \ + -initrd /path/to/rootfs.ext4 \ + -append "root=/dev/ram" + +Running U-Boot +-------------- + +U-Boot mainline v2020.10 release is tested at the time of writing. To build a +U-Boot mainline bootloader that can be booted by the SABRE Lite machine, use +the mx6qsabrelite_defconfig with similar commands as described above for Linux: + +.. code-block:: bash + + $ export CROSS_COMPILE=arm-linux-gnueabihf- + $ make mx6qsabrelite_defconfig + +Note we need to adjust settings by: + +.. code-block:: bash + + $ make menuconfig + +then manually select the following configuration in U-Boot: + + Device Tree Control > Provider of DTB for DT Control > Embedded DTB + +To start U-Boot using the SABRE Lite machine, provide the u-boot binary to +the -kernel argument, along with an SD card image with rootfs: + +.. code-block:: bash + + $ qemu-system-arm -M sabrelite -smp 4 -m 1G \ + -display none -serial null -serial stdio \ + -kernel u-boot + +The following example shows booting Linux kernel from dhcp, and uses the +rootfs on an SD card. This requires some additional command line parameters +for QEMU: + +.. code-block:: none + + -nic user,tftp=/path/to/kernel/zImage \ + -drive file=sdcard.img,id=rootfs -device sd-card,drive=rootfs + +The directory for the built-in TFTP server should also contain the device tree +blob of the SABRE Lite board. The sample SD card image was populated with the +root file system with one single partition. You may adjust the kernel "root=" +boot parameter accordingly. + +After U-Boot boots, type the following commands in the U-Boot command shell to +boot the Linux kernel: + +.. code-block:: none + + => setenv ethaddr 00:11:22:33:44:55 + => setenv bootfile zImage + => dhcp + => tftpboot 14000000 imx6q-sabrelite.dtb + => setenv bootargs root=/dev/mmcblk3p1 + => bootz 12000000 - 14000000 diff --git a/docs/system/target-arm.rst b/docs/system/target-arm.rst index bde4b8e044..edd013c7bb 100644 --- a/docs/system/target-arm.rst +++ b/docs/system/target-arm.rst @@ -83,6 +83,7 @@ undocumented; you can get a complete list by running arm/versatile arm/vexpress arm/aspeed + arm/sabrelite arm/digic arm/musicpal arm/gumstix diff --git a/hw/arm/highbank.c b/hw/arm/highbank.c index bf7b8f4c64..bf886268c5 100644 --- a/hw/arm/highbank.c +++ b/hw/arm/highbank.c @@ -26,7 +26,6 @@ #include "hw/arm/boot.h" #include "hw/loader.h" #include "net/net.h" -#include "sysemu/kvm.h" #include "sysemu/runstate.h" #include "sysemu/sysemu.h" #include "hw/boards.h" @@ -38,6 +37,7 @@ #include "hw/cpu/a15mpcore.h" #include "qemu/log.h" #include "qom/object.h" +#include "cpu.h" #define SMP_BOOT_ADDR 0x100 #define SMP_BOOT_REG 0x40 @@ -396,15 +396,9 @@ static void calxeda_init(MachineState *machine, enum cxmachines machine_id) highbank_binfo.loader_start = 0; highbank_binfo.write_secondary_boot = hb_write_secondary; highbank_binfo.secondary_cpu_reset_hook = hb_reset_secondary; - if (!kvm_enabled()) { - highbank_binfo.board_setup_addr = BOARD_SETUP_ADDR; - highbank_binfo.write_board_setup = hb_write_board_setup; - highbank_binfo.secure_board_setup = true; - } else { - warn_report("cannot load built-in Monitor support " - "if KVM is enabled. Some guests (such as Linux) " - "may not boot."); - } + highbank_binfo.board_setup_addr = BOARD_SETUP_ADDR; + highbank_binfo.write_board_setup = hb_write_board_setup; + highbank_binfo.secure_board_setup = true; arm_load_kernel(ARM_CPU(first_cpu), machine, &highbank_binfo); } diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c index 458b1cbeb7..6aec84aeed 100644 --- a/hw/arm/musicpal.c +++ b/hw/arm/musicpal.c @@ -959,6 +959,17 @@ static void mv88w8618_pit_init(Object *obj) sysbus_init_mmio(dev, &s->iomem); } +static void mv88w8618_pit_finalize(Object *obj) +{ + SysBusDevice *dev = SYS_BUS_DEVICE(obj); + mv88w8618_pit_state *s = MV88W8618_PIT(dev); + int i; + + for (i = 0; i < 4; i++) { + ptimer_free(s->timer[i].ptimer); + } +} + static const VMStateDescription mv88w8618_timer_vmsd = { .name = "timer", .version_id = 1, @@ -994,6 +1005,7 @@ static const TypeInfo mv88w8618_pit_info = { .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(mv88w8618_pit_state), .instance_init = mv88w8618_pit_init, + .instance_finalize = mv88w8618_pit_finalize, .class_init = mv88w8618_pit_class_init, }; diff --git a/hw/arm/sabrelite.c b/hw/arm/sabrelite.c index 91d8c43a7e..a3dbf85e0e 100644 --- a/hw/arm/sabrelite.c +++ b/hw/arm/sabrelite.c @@ -51,6 +51,10 @@ static void sabrelite_init(MachineState *machine) s = FSL_IMX6(object_new(TYPE_FSL_IMX6)); object_property_add_child(OBJECT(machine), "soc", OBJECT(s)); + + /* Ethernet PHY address is 6 */ + object_property_set_int(OBJECT(s), "fec-phy-num", 6, &error_fatal); + qdev_realize(DEVICE(s), NULL, &error_fatal); memory_region_add_subregion(get_system_memory(), FSL_IMX6_MMDC_ADDR, diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index 711cf2069f..9d9ee24053 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -59,11 +59,12 @@ #define ACPI_BUILD_TABLE_SIZE 0x20000 -static void acpi_dsdt_add_cpus(Aml *scope, int smp_cpus) +static void acpi_dsdt_add_cpus(Aml *scope, VirtMachineState *vms) { + MachineState *ms = MACHINE(vms); uint16_t i; - for (i = 0; i < smp_cpus; i++) { + for (i = 0; i < ms->smp.cpus; i++) { Aml *dev = aml_device("C%.03X", i); aml_append(dev, aml_name_decl("_HID", aml_string("ACPI0007"))); aml_append(dev, aml_name_decl("_UID", aml_int(i))); @@ -484,7 +485,7 @@ build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) gicd->base_address = cpu_to_le64(memmap[VIRT_GIC_DIST].base); gicd->version = vms->gic_version; - for (i = 0; i < vms->smp_cpus; i++) { + for (i = 0; i < MACHINE(vms)->smp.cpus; i++) { AcpiMadtGenericCpuInterface *gicc = acpi_data_push(table_data, sizeof(*gicc)); ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(i)); @@ -603,7 +604,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) * the RTC ACPI device at all when using UEFI. */ scope = aml_scope("\\_SB"); - acpi_dsdt_add_cpus(scope, vms->smp_cpus); + acpi_dsdt_add_cpus(scope, vms); acpi_dsdt_add_uart(scope, &memmap[VIRT_UART], (irqmap[VIRT_UART] + ARM_SPI_BASE)); if (vmc->acpi_expose_flash) { diff --git a/hw/arm/virt.c b/hw/arm/virt.c index bf3a717111..86070dfd98 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -323,7 +323,7 @@ static void fdt_add_timer_nodes(const VirtMachineState *vms) if (vms->gic_version == VIRT_GIC_VERSION_2) { irqflags = deposit32(irqflags, GIC_FDT_IRQ_PPI_CPU_START, GIC_FDT_IRQ_PPI_CPU_WIDTH, - (1 << vms->smp_cpus) - 1); + (1 << MACHINE(vms)->smp.cpus) - 1); } qemu_fdt_add_subnode(vms->fdt, "/timer"); @@ -350,6 +350,7 @@ static void fdt_add_cpu_nodes(const VirtMachineState *vms) int cpu; int addr_cells = 1; const MachineState *ms = MACHINE(vms); + int smp_cpus = ms->smp.cpus; /* * From Documentation/devicetree/bindings/arm/cpus.txt @@ -364,7 +365,7 @@ static void fdt_add_cpu_nodes(const VirtMachineState *vms) * The simplest way to go is to examine affinity IDs of all our CPUs. If * at least one of them has Aff3 populated, we set #address-cells to 2. */ - for (cpu = 0; cpu < vms->smp_cpus; cpu++) { + for (cpu = 0; cpu < smp_cpus; cpu++) { ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(cpu)); if (armcpu->mp_affinity & ARM_AFF3_MASK) { @@ -377,7 +378,7 @@ static void fdt_add_cpu_nodes(const VirtMachineState *vms) qemu_fdt_setprop_cell(vms->fdt, "/cpus", "#address-cells", addr_cells); qemu_fdt_setprop_cell(vms->fdt, "/cpus", "#size-cells", 0x0); - for (cpu = vms->smp_cpus - 1; cpu >= 0; cpu--) { + for (cpu = smp_cpus - 1; cpu >= 0; cpu--) { char *nodename = g_strdup_printf("/cpus/cpu@%d", cpu); ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(cpu)); CPUState *cs = CPU(armcpu); @@ -387,8 +388,7 @@ static void fdt_add_cpu_nodes(const VirtMachineState *vms) qemu_fdt_setprop_string(vms->fdt, nodename, "compatible", armcpu->dtb_compatible); - if (vms->psci_conduit != QEMU_PSCI_CONDUIT_DISABLED - && vms->smp_cpus > 1) { + if (vms->psci_conduit != QEMU_PSCI_CONDUIT_DISABLED && smp_cpus > 1) { qemu_fdt_setprop_string(vms->fdt, nodename, "enable-method", "psci"); } @@ -534,7 +534,7 @@ static void fdt_add_pmu_nodes(const VirtMachineState *vms) if (vms->gic_version == VIRT_GIC_VERSION_2) { irqflags = deposit32(irqflags, GIC_FDT_IRQ_PPI_CPU_START, GIC_FDT_IRQ_PPI_CPU_WIDTH, - (1 << vms->smp_cpus) - 1); + (1 << MACHINE(vms)->smp.cpus) - 1); } qemu_fdt_add_subnode(vms->fdt, "/pmu"); @@ -1674,9 +1674,9 @@ static void finalize_gic_version(VirtMachineState *vms) * virt_cpu_post_init() must be called after the CPUs have * been realized and the GIC has been created. */ -static void virt_cpu_post_init(VirtMachineState *vms, int max_cpus, - MemoryRegion *sysmem) +static void virt_cpu_post_init(VirtMachineState *vms, MemoryRegion *sysmem) { + int max_cpus = MACHINE(vms)->smp.max_cpus; bool aarch64, pmu, steal_time; CPUState *cpu; @@ -1829,8 +1829,6 @@ static void machvirt_init(MachineState *machine) exit(1); } - vms->smp_cpus = smp_cpus; - if (vms->virt && kvm_enabled()) { error_report("mach-virt: KVM does not support providing " "Virtualization extensions to the guest CPU"); @@ -1846,6 +1844,7 @@ static void machvirt_init(MachineState *machine) create_fdt(vms); possible_cpus = mc->possible_cpu_arch_ids(machine); + assert(possible_cpus->len == max_cpus); for (n = 0; n < possible_cpus->len; n++) { Object *cpuobj; CPUState *cs; @@ -1966,7 +1965,7 @@ static void machvirt_init(MachineState *machine) create_gic(vms); - virt_cpu_post_init(vms, possible_cpus->len, sysmem); + virt_cpu_post_init(vms, sysmem); fdt_add_pmu_nodes(vms); diff --git a/hw/block/nvme.c b/hw/block/nvme.c index 01b657b1c5..27d2c72716 100644 --- a/hw/block/nvme.c +++ b/hw/block/nvme.c @@ -1052,7 +1052,6 @@ static uint16_t nvme_io_cmd(NvmeCtrl *n, NvmeRequest *req) static void nvme_free_sq(NvmeSQueue *sq, NvmeCtrl *n) { n->sq[sq->sqid] = NULL; - timer_del(sq->timer); timer_free(sq->timer); g_free(sq->io_req); if (sq->sqid) { @@ -1334,7 +1333,6 @@ static uint16_t nvme_get_log(NvmeCtrl *n, NvmeRequest *req) static void nvme_free_cq(NvmeCQueue *cq, NvmeCtrl *n) { n->cq[cq->cqid] = NULL; - timer_del(cq->timer); timer_free(cq->timer); msix_vector_unuse(&n->parent_obj, cq->vector); if (cq->cqid) { diff --git a/hw/char/serial.c b/hw/char/serial.c index 6e52539648..bc2e322970 100644 --- a/hw/char/serial.c +++ b/hw/char/serial.c @@ -941,10 +941,8 @@ static void serial_unrealize(DeviceState *dev) qemu_chr_fe_deinit(&s->chr, false); - timer_del(s->modem_status_poll); timer_free(s->modem_status_poll); - timer_del(s->fifo_timeout_timer); timer_free(s->fifo_timeout_timer); fifo8_destroy(&s->recv_fifo); diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c index cf08ef9728..b20038991a 100644 --- a/hw/char/virtio-serial-bus.c +++ b/hw/char/virtio-serial-bus.c @@ -741,7 +741,6 @@ static void virtio_serial_post_load_timer_cb(void *opaque) } } g_free(s->post_load->connected); - timer_del(s->post_load->timer); timer_free(s->post_load->timer); g_free(s->post_load); s->post_load = NULL; @@ -1138,7 +1137,6 @@ static void virtio_serial_device_unrealize(DeviceState *dev) g_free(vser->ports_map); if (vser->post_load) { g_free(vser->post_load->connected); - timer_del(vser->post_load->timer); timer_free(vser->post_load->timer); g_free(vser->post_load); } diff --git a/hw/ide/core.c b/hw/ide/core.c index e85821637c..b49e4cfbc6 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -2716,7 +2716,6 @@ void ide_init2(IDEBus *bus, qemu_irq irq) void ide_exit(IDEState *s) { - timer_del(s->sector_write_timer); timer_free(s->sector_write_timer); qemu_vfree(s->smart_selftest_data); qemu_vfree(s->io_buffer); diff --git a/hw/input/hid.c b/hw/input/hid.c index 89239b5634..e1d2e46083 100644 --- a/hw/input/hid.c +++ b/hw/input/hid.c @@ -88,7 +88,6 @@ static void hid_idle_timer(void *opaque) static void hid_del_idle_timer(HIDState *hs) { if (hs->idle_timer) { - timer_del(hs->idle_timer); timer_free(hs->idle_timer); hs->idle_timer = NULL; } diff --git a/hw/intc/apic.c b/hw/intc/apic.c index 1c8be40d8b..3ada22f427 100644 --- a/hw/intc/apic.c +++ b/hw/intc/apic.c @@ -888,7 +888,6 @@ static void apic_unrealize(DeviceState *dev) { APICCommonState *s = APIC(dev); - timer_del(s->timer); timer_free(s->timer); local_apics[s->id] = NULL; } diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c index c60dc6b5e6..af41e2fb44 100644 --- a/hw/intc/arm_gic.c +++ b/hw/intc/arm_gic.c @@ -141,6 +141,8 @@ static inline void gic_get_best_virq(GICState *s, int cpu, static inline bool gic_irq_signaling_enabled(GICState *s, int cpu, bool virt, int group_mask) { + int cpu_iface = virt ? (cpu + GIC_NCPU) : cpu; + if (!virt && !(s->ctlr & group_mask)) { return false; } @@ -149,7 +151,7 @@ static inline bool gic_irq_signaling_enabled(GICState *s, int cpu, bool virt, return false; } - if (!(s->cpu_ctlr[cpu] & group_mask)) { + if (!(s->cpu_ctlr[cpu_iface] & group_mask)) { return false; } diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c index f63aa2d871..0d8426dafc 100644 --- a/hw/intc/armv7m_nvic.c +++ b/hw/intc/armv7m_nvic.c @@ -1106,6 +1106,12 @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs) */ val = cpu->env.v7m.ccr[attrs.secure]; val |= cpu->env.v7m.ccr[M_REG_NS] & R_V7M_CCR_BFHFNMIGN_MASK; + /* BFHFNMIGN is RAZ/WI from NS if AIRCR.BFHFNMINS is 0 */ + if (!attrs.secure) { + if (!(cpu->env.v7m.aircr & R_V7M_AIRCR_BFHFNMINS_MASK)) { + val &= ~R_V7M_CCR_BFHFNMIGN_MASK; + } + } return val; case 0xd24: /* System Handler Control and State (SHCSR) */ if (!arm_feature(&cpu->env, ARM_FEATURE_V7)) { @@ -1683,6 +1689,15 @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value, (cpu->env.v7m.ccr[M_REG_NS] & ~R_V7M_CCR_BFHFNMIGN_MASK) | (value & R_V7M_CCR_BFHFNMIGN_MASK); value &= ~R_V7M_CCR_BFHFNMIGN_MASK; + } else { + /* + * BFHFNMIGN is RAZ/WI from NS if AIRCR.BFHFNMINS is 0, so + * preserve the state currently in the NS element of the array + */ + if (!(cpu->env.v7m.aircr & R_V7M_AIRCR_BFHFNMINS_MASK)) { + value &= ~R_V7M_CCR_BFHFNMIGN_MASK; + value |= cpu->env.v7m.ccr[M_REG_NS] & R_V7M_CCR_BFHFNMIGN_MASK; + } } cpu->env.v7m.ccr[attrs.secure] = value; diff --git a/hw/intc/ioapic.c b/hw/intc/ioapic.c index a3021a4de1..264262959d 100644 --- a/hw/intc/ioapic.c +++ b/hw/intc/ioapic.c @@ -474,7 +474,6 @@ static void ioapic_unrealize(DeviceState *dev) { IOAPICCommonState *s = IOAPIC_COMMON(dev); - timer_del(s->delayed_ioapic_service_timer); timer_free(s->delayed_ioapic_service_timer); } diff --git a/hw/ipmi/ipmi_bmc_extern.c b/hw/ipmi/ipmi_bmc_extern.c index e141a5cd45..acf2bab35f 100644 --- a/hw/ipmi/ipmi_bmc_extern.c +++ b/hw/ipmi/ipmi_bmc_extern.c @@ -511,7 +511,6 @@ static void ipmi_bmc_extern_finalize(Object *obj) { IPMIBmcExtern *ibe = IPMI_BMC_EXTERN(obj); - timer_del(ibe->extern_timer); timer_free(ibe->extern_timer); } diff --git a/hw/misc/imx6_ccm.c b/hw/misc/imx6_ccm.c index cb740427ec..4c830fd89a 100644 --- a/hw/misc/imx6_ccm.c +++ b/hw/misc/imx6_ccm.c @@ -450,7 +450,7 @@ static void imx6_ccm_reset(DeviceState *dev) s->analog[PMU_REG_3P0] = 0x00000F74; s->analog[PMU_REG_2P5] = 0x00005071; s->analog[PMU_REG_CORE] = 0x00402010; - s->analog[PMU_MISC0] = 0x04000000; + s->analog[PMU_MISC0] = 0x04000080; s->analog[PMU_MISC1] = 0x00000000; s->analog[PMU_MISC2] = 0x00272727; @@ -462,7 +462,7 @@ static void imx6_ccm_reset(DeviceState *dev) s->analog[USB_ANALOG_USB2_VBUS_DETECT] = 0x00000004; s->analog[USB_ANALOG_USB2_CHRG_DETECT] = 0x00000000; s->analog[USB_ANALOG_USB2_MISC] = 0x00000002; - s->analog[USB_ANALOG_DIGPROG] = 0x00000000; + s->analog[USB_ANALOG_DIGPROG] = 0x00630000; /* all PLLs need to be locked */ s->analog[CCM_ANALOG_PLL_ARM] |= CCM_ANALOG_PLL_LOCK; diff --git a/hw/net/e1000.c b/hw/net/e1000.c index d7d05ae30a..d8da2f6528 100644 --- a/hw/net/e1000.c +++ b/hw/net/e1000.c @@ -1647,11 +1647,8 @@ pci_e1000_uninit(PCIDevice *dev) { E1000State *d = E1000(dev); - timer_del(d->autoneg_timer); timer_free(d->autoneg_timer); - timer_del(d->mit_timer); timer_free(d->mit_timer); - timer_del(d->flush_queue_timer); timer_free(d->flush_queue_timer); qemu_del_nic(d->nic); } diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c index 095c01ebc6..4dcb92d966 100644 --- a/hw/net/e1000e_core.c +++ b/hw/net/e1000e_core.c @@ -434,23 +434,16 @@ e1000e_intrmgr_pci_unint(E1000ECore *core) { int i; - timer_del(core->radv.timer); timer_free(core->radv.timer); - timer_del(core->rdtr.timer); timer_free(core->rdtr.timer); - timer_del(core->raid.timer); timer_free(core->raid.timer); - timer_del(core->tadv.timer); timer_free(core->tadv.timer); - timer_del(core->tidv.timer); timer_free(core->tidv.timer); - timer_del(core->itr.timer); timer_free(core->itr.timer); for (i = 0; i < E1000E_MSIX_VEC_NUM; i++) { - timer_del(core->eitr[i].timer); timer_free(core->eitr[i].timer); } } @@ -3355,7 +3348,6 @@ e1000e_core_pci_uninit(E1000ECore *core) { int i; - timer_del(core->autoneg_timer); timer_free(core->autoneg_timer); e1000e_intrmgr_pci_unint(core); diff --git a/hw/net/pcnet-pci.c b/hw/net/pcnet-pci.c index ccc3fce2a0..95d27102aa 100644 --- a/hw/net/pcnet-pci.c +++ b/hw/net/pcnet-pci.c @@ -183,7 +183,6 @@ static void pci_pcnet_uninit(PCIDevice *dev) PCIPCNetState *d = PCI_PCNET(dev); qemu_free_irq(d->state.irq); - timer_del(d->state.poll_timer); timer_free(d->state.poll_timer); qemu_del_nic(d->state.nic); } diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c index ba5ace1ab7..4675ac878e 100644 --- a/hw/net/rtl8139.c +++ b/hw/net/rtl8139.c @@ -3338,7 +3338,6 @@ static void pci_rtl8139_uninit(PCIDevice *dev) g_free(s->cplus_txbuffer); s->cplus_txbuffer = NULL; - timer_del(s->timer); timer_free(s->timer); qemu_del_nic(s->nic); } diff --git a/hw/net/spapr_llan.c b/hw/net/spapr_llan.c index 581320a0e7..10e85a4556 100644 --- a/hw/net/spapr_llan.c +++ b/hw/net/spapr_llan.c @@ -363,7 +363,6 @@ static void spapr_vlan_instance_finalize(Object *obj) } if (dev->rxp_timer) { - timer_del(dev->rxp_timer); timer_free(dev->rxp_timer); } } diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index 8356eeec13..09ceb02c9d 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -1862,7 +1862,6 @@ static void virtio_net_rsc_cleanup(VirtIONet *n) g_free(seg); } - timer_del(chain->drain_timer); timer_free(chain->drain_timer); QTAILQ_REMOVE(&n->rsc_chains, chain, next); g_free(chain); @@ -2645,7 +2644,6 @@ static void virtio_net_del_queue(VirtIONet *n, int index) virtio_del_queue(vdev, index * 2); if (q->tx_timer) { - timer_del(q->tx_timer); timer_free(q->tx_timer); q->tx_timer = NULL; } else { diff --git a/hw/rtc/exynos4210_rtc.c b/hw/rtc/exynos4210_rtc.c index 4c97624478..45c0a951c4 100644 --- a/hw/rtc/exynos4210_rtc.c +++ b/hw/rtc/exynos4210_rtc.c @@ -584,6 +584,14 @@ static void exynos4210_rtc_init(Object *obj) sysbus_init_mmio(dev, &s->iomem); } +static void exynos4210_rtc_finalize(Object *obj) +{ + Exynos4210RTCState *s = EXYNOS4210_RTC(obj); + + ptimer_free(s->ptimer); + ptimer_free(s->ptimer_1Hz); +} + static void exynos4210_rtc_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); @@ -597,6 +605,7 @@ static const TypeInfo exynos4210_rtc_info = { .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(Exynos4210RTCState), .instance_init = exynos4210_rtc_init, + .instance_finalize = exynos4210_rtc_finalize, .class_init = exynos4210_rtc_class_init, }; diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c index 76b08a39a7..654fac6c0a 100644 --- a/hw/s390x/s390-pci-inst.c +++ b/hw/s390x/s390-pci-inst.c @@ -955,7 +955,6 @@ void pci_dereg_ioat(S390PCIIOMMU *iommu) void fmb_timer_free(S390PCIBusDevice *pbdev) { if (pbdev->fmb_timer) { - timer_del(pbdev->fmb_timer); timer_free(pbdev->fmb_timer); pbdev->fmb_timer = NULL; } diff --git a/hw/sd/sd.c b/hw/sd/sd.c index 2aeab39c3f..4375ed5b8b 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -2133,7 +2133,6 @@ static void sd_instance_finalize(Object *obj) { SDState *sd = SD_CARD(obj); - timer_del(sd->ocr_power_timer); timer_free(sd->ocr_power_timer); } diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c index 2f8b74a84f..8ffa53999d 100644 --- a/hw/sd/sdhci.c +++ b/hw/sd/sdhci.c @@ -1330,9 +1330,7 @@ void sdhci_initfn(SDHCIState *s) void sdhci_uninitfn(SDHCIState *s) { - timer_del(s->insert_timer); timer_free(s->insert_timer); - timer_del(s->transfer_timer); timer_free(s->transfer_timer); g_free(s->fifo_buffer); diff --git a/hw/timer/allwinner-a10-pit.c b/hw/timer/allwinner-a10-pit.c index f84fc0ea25..c3fc2a4daa 100644 --- a/hw/timer/allwinner-a10-pit.c +++ b/hw/timer/allwinner-a10-pit.c @@ -279,6 +279,16 @@ static void a10_pit_init(Object *obj) } } +static void a10_pit_finalize(Object *obj) +{ + AwA10PITState *s = AW_A10_PIT(obj); + int i; + + for (i = 0; i < AW_A10_PIT_TIMER_NR; i++) { + ptimer_free(s->timer[i]); + } +} + static void a10_pit_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); @@ -294,6 +304,7 @@ static const TypeInfo a10_pit_info = { .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(AwA10PITState), .instance_init = a10_pit_init, + .instance_finalize = a10_pit_finalize, .class_init = a10_pit_class_init, }; diff --git a/hw/timer/digic-timer.c b/hw/timer/digic-timer.c index 32612228da..e3aae4a45a 100644 --- a/hw/timer/digic-timer.c +++ b/hw/timer/digic-timer.c @@ -154,6 +154,13 @@ static void digic_timer_init(Object *obj) sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->iomem); } +static void digic_timer_finalize(Object *obj) +{ + DigicTimerState *s = DIGIC_TIMER(obj); + + ptimer_free(s->ptimer); +} + static void digic_timer_class_init(ObjectClass *klass, void *class_data) { DeviceClass *dc = DEVICE_CLASS(klass); @@ -167,6 +174,7 @@ static const TypeInfo digic_timer_info = { .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(DigicTimerState), .instance_init = digic_timer_init, + .instance_finalize = digic_timer_finalize, .class_init = digic_timer_class_init, }; diff --git a/hw/timer/exynos4210_mct.c b/hw/timer/exynos4210_mct.c index 439053acd2..d0e5343996 100644 --- a/hw/timer/exynos4210_mct.c +++ b/hw/timer/exynos4210_mct.c @@ -1530,6 +1530,19 @@ static void exynos4210_mct_init(Object *obj) sysbus_init_mmio(dev, &s->iomem); } +static void exynos4210_mct_finalize(Object *obj) +{ + int i; + Exynos4210MCTState *s = EXYNOS4210_MCT(obj); + + ptimer_free(s->g_timer.ptimer_frc); + + for (i = 0; i < 2; i++) { + ptimer_free(s->l_timer[i].tick_timer.ptimer_tick); + ptimer_free(s->l_timer[i].ptimer_frc); + } +} + static void exynos4210_mct_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); @@ -1543,6 +1556,7 @@ static const TypeInfo exynos4210_mct_info = { .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(Exynos4210MCTState), .instance_init = exynos4210_mct_init, + .instance_finalize = exynos4210_mct_finalize, .class_init = exynos4210_mct_class_init, }; diff --git a/hw/timer/exynos4210_pwm.c b/hw/timer/exynos4210_pwm.c index de181428b4..220088120e 100644 --- a/hw/timer/exynos4210_pwm.c +++ b/hw/timer/exynos4210_pwm.c @@ -410,6 +410,16 @@ static void exynos4210_pwm_init(Object *obj) sysbus_init_mmio(dev, &s->iomem); } +static void exynos4210_pwm_finalize(Object *obj) +{ + Exynos4210PWMState *s = EXYNOS4210_PWM(obj); + int i; + + for (i = 0; i < EXYNOS4210_PWM_TIMERS_NUM; i++) { + ptimer_free(s->timer[i].ptimer); + } +} + static void exynos4210_pwm_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); @@ -423,6 +433,7 @@ static const TypeInfo exynos4210_pwm_info = { .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(Exynos4210PWMState), .instance_init = exynos4210_pwm_init, + .instance_finalize = exynos4210_pwm_finalize, .class_init = exynos4210_pwm_class_init, }; diff --git a/hw/timer/mss-timer.c b/hw/timer/mss-timer.c index 29943fd744..fe0ca905f3 100644 --- a/hw/timer/mss-timer.c +++ b/hw/timer/mss-timer.c @@ -244,6 +244,18 @@ static void mss_timer_init(Object *obj) sysbus_init_mmio(SYS_BUS_DEVICE(obj), &t->mmio); } +static void mss_timer_finalize(Object *obj) +{ + MSSTimerState *t = MSS_TIMER(obj); + int i; + + for (i = 0; i < NUM_TIMERS; i++) { + struct Msf2Timer *st = &t->timers[i]; + + ptimer_free(st->ptimer); + } +} + static const VMStateDescription vmstate_timers = { .name = "mss-timer-block", .version_id = 1, @@ -287,6 +299,7 @@ static const TypeInfo mss_timer_info = { .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(MSSTimerState), .instance_init = mss_timer_init, + .instance_finalize = mss_timer_finalize, .class_init = mss_timer_class_init, }; diff --git a/hw/usb/dev-hub.c b/hw/usb/dev-hub.c index 40c1f90694..e35813d772 100644 --- a/hw/usb/dev-hub.c +++ b/hw/usb/dev-hub.c @@ -576,7 +576,6 @@ static void usb_hub_unrealize(USBDevice *dev) &s->ports[i].port); } - timer_del(s->port_timer); timer_free(s->port_timer); } diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index ae7f20c502..aca018d8b5 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -2534,7 +2534,6 @@ void usb_ehci_unrealize(EHCIState *s, DeviceState *dev) trace_usb_ehci_unrealize(); if (s->frame_timer) { - timer_del(s->frame_timer); timer_free(s->frame_timer); s->frame_timer = NULL; } diff --git a/hw/usb/hcd-ohci-pci.c b/hw/usb/hcd-ohci-pci.c index f95199e0bb..8e1146b862 100644 --- a/hw/usb/hcd-ohci-pci.c +++ b/hw/usb/hcd-ohci-pci.c @@ -97,7 +97,6 @@ static void usb_ohci_exit(PCIDevice *dev) usb_bus_release(&s->bus); } - timer_del(s->eof_timer); timer_free(s->eof_timer); } diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c index 27ca237d71..5969eb86b3 100644 --- a/hw/usb/hcd-uhci.c +++ b/hw/usb/hcd-uhci.c @@ -1283,7 +1283,6 @@ static void usb_uhci_exit(PCIDevice *dev) trace_usb_uhci_exit(); if (s->frame_timer) { - timer_del(s->frame_timer); timer_free(s->frame_timer); s->frame_timer = NULL; } diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index 9ce7ca706e..46212b1e69 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -3395,7 +3395,6 @@ static void usb_xhci_unrealize(DeviceState *dev) } if (xhci->mfwrap_timer) { - timer_del(xhci->mfwrap_timer); timer_free(xhci->mfwrap_timer); xhci->mfwrap_timer = NULL; } diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c index 03b6f61f75..7e9e3fecbf 100644 --- a/hw/usb/redirect.c +++ b/hw/usb/redirect.c @@ -1481,7 +1481,6 @@ static void usbredir_unrealize(USBDevice *udev) qemu_bh_delete(dev->chardev_close_bh); qemu_bh_delete(dev->device_reject_bh); - timer_del(dev->attach_timer); timer_free(dev->attach_timer); usbredir_cleanup_device_queues(dev); diff --git a/hw/vfio/display.c b/hw/vfio/display.c index 342054193b..42d67e870b 100644 --- a/hw/vfio/display.c +++ b/hw/vfio/display.c @@ -186,7 +186,6 @@ static void vfio_display_edid_exit(VFIODisplay *dpy) g_free(dpy->edid_regs); g_free(dpy->edid_blob); - timer_del(dpy->edid_link_timer); timer_free(dpy->edid_link_timer); } diff --git a/hw/virtio/vhost-vsock-common.c b/hw/virtio/vhost-vsock-common.c index 5b2ebf3496..4ad6e234ad 100644 --- a/hw/virtio/vhost-vsock-common.c +++ b/hw/virtio/vhost-vsock-common.c @@ -151,7 +151,6 @@ static void vhost_vsock_common_post_load_timer_cleanup(VHostVSockCommon *vvc) return; } - timer_del(vvc->post_load_timer); timer_free(vvc->post_load_timer); vvc->post_load_timer = NULL; } diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c index e83017c02d..e770955176 100644 --- a/hw/virtio/virtio-balloon.c +++ b/hw/virtio/virtio-balloon.c @@ -204,7 +204,6 @@ static bool balloon_stats_enabled(const VirtIOBalloon *s) static void balloon_stats_destroy_timer(VirtIOBalloon *s) { if (balloon_stats_enabled(s)) { - timer_del(s->stats_timer); timer_free(s->stats_timer); s->stats_timer = NULL; s->stats_poll_interval = 0; diff --git a/hw/virtio/virtio-rng.c b/hw/virtio/virtio-rng.c index 2886c0ce2a..76ce937693 100644 --- a/hw/virtio/virtio-rng.c +++ b/hw/virtio/virtio-rng.c @@ -233,7 +233,6 @@ static void virtio_rng_device_unrealize(DeviceState *dev) VirtIORNG *vrng = VIRTIO_RNG(dev); qemu_del_vm_change_state_handler(vrng->vmstate); - timer_del(vrng->rate_limit_timer); timer_free(vrng->rate_limit_timer); virtio_del_queue(vdev, 0); virtio_cleanup(vdev); diff --git a/hw/watchdog/wdt_diag288.c b/hw/watchdog/wdt_diag288.c index 4c4b6a6ab7..e135a4de8b 100644 --- a/hw/watchdog/wdt_diag288.c +++ b/hw/watchdog/wdt_diag288.c @@ -110,7 +110,6 @@ static void wdt_diag288_unrealize(DeviceState *dev) { DIAG288State *diag288 = DIAG288(dev); - timer_del(diag288->timer); timer_free(diag288->timer); } diff --git a/hw/watchdog/wdt_i6300esb.c b/hw/watchdog/wdt_i6300esb.c index 502f45a939..4c52e3bb9e 100644 --- a/hw/watchdog/wdt_i6300esb.c +++ b/hw/watchdog/wdt_i6300esb.c @@ -454,7 +454,6 @@ static void i6300esb_exit(PCIDevice *dev) { I6300State *d = WATCHDOG_I6300ESB_DEVICE(dev); - timer_del(d->timer); timer_free(d->timer); } diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h index abf54fab49..e4a2d21642 100644 --- a/include/hw/arm/virt.h +++ b/include/hw/arm/virt.h @@ -151,7 +151,6 @@ struct VirtMachineState { MemMapEntry *memmap; char *pciehb_nodename; const int *irqmap; - int smp_cpus; void *fdt; int fdt_size; uint32_t clock_phandle; @@ -182,7 +181,7 @@ static inline int virt_gicv3_redist_region_count(VirtMachineState *vms) assert(vms->gic_version == VIRT_GIC_VERSION_3); - return vms->smp_cpus > redist0_capacity ? 2 : 1; + return MACHINE(vms)->smp.cpus > redist0_capacity ? 2 : 1; } #endif /* QEMU_ARM_VIRT_H */ diff --git a/include/qemu/timer.h b/include/qemu/timer.h index bdecc5b41f..61296ea980 100644 --- a/include/qemu/timer.h +++ b/include/qemu/timer.h @@ -609,17 +609,6 @@ static inline QEMUTimer *timer_new_ms(QEMUClockType type, QEMUTimerCB *cb, */ void timer_deinit(QEMUTimer *ts); -/** - * timer_free: - * @ts: the timer - * - * Free a timer (it must not be on the active list) - */ -static inline void timer_free(QEMUTimer *ts) -{ - g_free(ts); -} - /** * timer_del: * @ts: the timer @@ -631,6 +620,19 @@ static inline void timer_free(QEMUTimer *ts) */ void timer_del(QEMUTimer *ts); +/** + * timer_free: + * @ts: the timer + * + * Free a timer. This will call timer_del() for you to remove + * the timer from the active list if it was still active. + */ +static inline void timer_free(QEMUTimer *ts) +{ + timer_del(ts); + g_free(ts); +} + /** * timer_mod_ns: * @ts: the timer diff --git a/migration/colo.c b/migration/colo.c index 3f1d3dfd95..de27662cab 100644 --- a/migration/colo.c +++ b/migration/colo.c @@ -636,7 +636,6 @@ out: * error. */ colo_compare_unregister_notifier(&packets_compare_notifier); - timer_del(s->colo_delay_timer); timer_free(s->colo_delay_timer); qemu_event_destroy(&s->colo_checkpoint_event); diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c index 0dd594f92b..fd4d77e246 100644 --- a/monitor/hmp-cmds.c +++ b/monitor/hmp-cmds.c @@ -1586,7 +1586,6 @@ static void hmp_migrate_status_cb(void *opaque) error_report("%s", info->error_desc); } monitor_resume(status->mon); - timer_del(status->timer); timer_free(status->timer); g_free(status); } diff --git a/net/announce.c b/net/announce.c index db90d3bd4b..26f057f5ee 100644 --- a/net/announce.c +++ b/net/announce.c @@ -41,7 +41,6 @@ void qemu_announce_timer_del(AnnounceTimer *timer, bool free_named) { bool free_timer = false; if (timer->tm) { - timer_del(timer->tm); timer_free(timer->tm); timer->tm = NULL; } diff --git a/net/colo-compare.c b/net/colo-compare.c index 337025b44f..84db4978ac 100644 --- a/net/colo-compare.c +++ b/net/colo-compare.c @@ -951,7 +951,6 @@ static void colo_compare_timer_init(CompareState *s) static void colo_compare_timer_del(CompareState *s) { if (s->packet_check_timer) { - timer_del(s->packet_check_timer); timer_free(s->packet_check_timer); s->packet_check_timer = NULL; } diff --git a/net/slirp.c b/net/slirp.c index 77042e6df7..8350c6d45f 100644 --- a/net/slirp.c +++ b/net/slirp.c @@ -184,7 +184,6 @@ static void *net_slirp_timer_new(SlirpTimerCb cb, static void net_slirp_timer_free(void *timer, void *opaque) { - timer_del(timer); timer_free(timer); } diff --git a/replay/replay-debugging.c b/replay/replay-debugging.c index 1d6a968406..5ec574724a 100644 --- a/replay/replay-debugging.c +++ b/replay/replay-debugging.c @@ -78,7 +78,6 @@ static void replay_delete_break(void) assert(replay_mutex_locked()); if (replay_break_timer) { - timer_del(replay_break_timer); timer_free(replay_break_timer); replay_break_timer = NULL; } diff --git a/scripts/coccinelle/timer-del-timer-free.cocci b/scripts/coccinelle/timer-del-timer-free.cocci new file mode 100644 index 0000000000..c3cfd42803 --- /dev/null +++ b/scripts/coccinelle/timer-del-timer-free.cocci @@ -0,0 +1,18 @@ +// Remove superfluous timer_del() calls +// +// Copyright Linaro Limited 2020 +// This work is licensed under the terms of the GNU GPLv2 or later. +// +// spatch --macro-file scripts/cocci-macro-file.h \ +// --sp-file scripts/coccinelle/timer-del-timer-free.cocci \ +// --in-place --dir . +// +// The timer_free() function now implicitly calls timer_del() +// for you, so calls to timer_del() immediately before the +// timer_free() of the same timer can be deleted. + +@@ +expression T; +@@ +-timer_del(T); + timer_free(T); diff --git a/target/arm/cpu.c b/target/arm/cpu.c index 62e319eb6a..8387e94b94 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c @@ -1305,8 +1305,6 @@ static void arm_cpu_finalizefn(Object *obj) } #ifndef CONFIG_USER_ONLY if (cpu->pmu_timer) { - timer_del(cpu->pmu_timer); - timer_deinit(cpu->pmu_timer); timer_free(cpu->pmu_timer); } #endif diff --git a/target/arm/cpu_tcg.c b/target/arm/cpu_tcg.c index 0013e25412..98544db2df 100644 --- a/target/arm/cpu_tcg.c +++ b/target/arm/cpu_tcg.c @@ -401,6 +401,46 @@ static void cortex_m33_initfn(Object *obj) cpu->ctr = 0x8000c000; } +static void cortex_m55_initfn(Object *obj) +{ + ARMCPU *cpu = ARM_CPU(obj); + + set_feature(&cpu->env, ARM_FEATURE_V8); + set_feature(&cpu->env, ARM_FEATURE_V8_1M); + set_feature(&cpu->env, ARM_FEATURE_M); + set_feature(&cpu->env, ARM_FEATURE_M_MAIN); + set_feature(&cpu->env, ARM_FEATURE_M_SECURITY); + set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP); + cpu->midr = 0x410fd221; /* r0p1 */ + cpu->revidr = 0; + cpu->pmsav7_dregion = 16; + cpu->sau_sregion = 8; + /* + * These are the MVFR* values for the FPU, no MVE configuration; + * we will update them later when we implement MVE + */ + cpu->isar.mvfr0 = 0x10110221; + cpu->isar.mvfr1 = 0x12100011; + cpu->isar.mvfr2 = 0x00000040; + cpu->isar.id_pfr0 = 0x20000030; + cpu->isar.id_pfr1 = 0x00000230; + cpu->isar.id_dfr0 = 0x10200000; + cpu->id_afr0 = 0x00000000; + cpu->isar.id_mmfr0 = 0x00111040; + cpu->isar.id_mmfr1 = 0x00000000; + cpu->isar.id_mmfr2 = 0x01000000; + cpu->isar.id_mmfr3 = 0x00000011; + cpu->isar.id_isar0 = 0x01103110; + cpu->isar.id_isar1 = 0x02212000; + cpu->isar.id_isar2 = 0x20232232; + cpu->isar.id_isar3 = 0x01111131; + cpu->isar.id_isar4 = 0x01310132; + cpu->isar.id_isar5 = 0x00000000; + cpu->isar.id_isar6 = 0x00000000; + cpu->clidr = 0x00000000; /* caches not implemented */ + cpu->ctr = 0x8303c003; +} + static const ARMCPRegInfo cortexr5_cp_reginfo[] = { /* Dummy the TCM region regs for the moment */ { .name = "ATCM", .cp = 15, .opc1 = 0, .crn = 9, .crm = 1, .opc2 = 0, @@ -655,6 +695,8 @@ static const ARMCPUInfo arm_tcg_cpus[] = { .class_init = arm_v7m_class_init }, { .name = "cortex-m33", .initfn = cortex_m33_initfn, .class_init = arm_v7m_class_init }, + { .name = "cortex-m55", .initfn = cortex_m55_initfn, + .class_init = arm_v7m_class_init }, { .name = "cortex-r5", .initfn = cortex_r5_initfn }, { .name = "cortex-r5f", .initfn = cortex_r5f_initfn }, { .name = "ti925t", .initfn = ti925t_initfn }, diff --git a/target/arm/helper.c b/target/arm/helper.c index 2d0d4cd1e1..d077dd9ef5 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -12928,7 +12928,7 @@ static uint32_t rebuild_hflags_a64(CPUARMState *env, int el, int fp_el, if (FIELD_EX32(flags, TBFLAG_A64, UNPRIV) && tbid && !(env->pstate & PSTATE_TCO) - && (sctlr & SCTLR_TCF0) + && (sctlr & SCTLR_TCF) && allocation_tag_access_enabled(env, 0, sctlr)) { flags = FIELD_DP32(flags, TBFLAG_A64, MTE0_ACTIVE, 1); } diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc index 0db936084b..10766f210c 100644 --- a/target/arm/translate-vfp.c.inc +++ b/target/arm/translate-vfp.c.inc @@ -663,6 +663,7 @@ static FPSysRegCheckResult fp_sysreg_checks(DisasContext *s, int regno) } break; case ARM_VFP_FPCXT_S: + case ARM_VFP_FPCXT_NS: if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) { return false; } @@ -674,13 +675,48 @@ static FPSysRegCheckResult fp_sysreg_checks(DisasContext *s, int regno) return FPSysRegCheckFailed; } - if (!vfp_access_check(s)) { + /* + * FPCXT_NS is a special case: it has specific handling for + * "current FP state is inactive", and must do the PreserveFPState() + * but not the usual full set of actions done by ExecuteFPCheck(). + * So we don't call vfp_access_check() and the callers must handle this. + */ + if (regno != ARM_VFP_FPCXT_NS && !vfp_access_check(s)) { return FPSysRegCheckDone; } - return FPSysRegCheckContinue; } +static void gen_branch_fpInactive(DisasContext *s, TCGCond cond, + TCGLabel *label) +{ + /* + * FPCXT_NS is a special case: it has specific handling for + * "current FP state is inactive", and must do the PreserveFPState() + * but not the usual full set of actions done by ExecuteFPCheck(). + * We don't have a TB flag that matches the fpInactive check, so we + * do it at runtime as we don't expect FPCXT_NS accesses to be frequent. + * + * Emit code that checks fpInactive and does a conditional + * branch to label based on it: + * if cond is TCG_COND_NE then branch if fpInactive != 0 (ie if inactive) + * if cond is TCG_COND_EQ then branch if fpInactive == 0 (ie if active) + */ + assert(cond == TCG_COND_EQ || cond == TCG_COND_NE); + + /* fpInactive = FPCCR_NS.ASPEN == 1 && CONTROL.FPCA == 0 */ + TCGv_i32 aspen, fpca; + aspen = load_cpu_field(v7m.fpccr[M_REG_NS]); + fpca = load_cpu_field(v7m.control[M_REG_S]); + tcg_gen_andi_i32(aspen, aspen, R_V7M_FPCCR_ASPEN_MASK); + tcg_gen_xori_i32(aspen, aspen, R_V7M_FPCCR_ASPEN_MASK); + tcg_gen_andi_i32(fpca, fpca, R_V7M_CONTROL_FPCA_MASK); + tcg_gen_or_i32(fpca, fpca, aspen); + tcg_gen_brcondi_i32(tcg_invert_cond(cond), fpca, 0, label); + tcg_temp_free_i32(aspen); + tcg_temp_free_i32(fpca); +} + static bool gen_M_fp_sysreg_write(DisasContext *s, int regno, fp_sysreg_loadfn *loadfn, @@ -688,6 +724,7 @@ static bool gen_M_fp_sysreg_write(DisasContext *s, int regno, { /* Do a write to an M-profile floating point system register */ TCGv_i32 tmp; + TCGLabel *lab_end = NULL; switch (fp_sysreg_checks(s, regno)) { case FPSysRegCheckFailed: @@ -721,10 +758,20 @@ static bool gen_M_fp_sysreg_write(DisasContext *s, int regno, tcg_temp_free_i32(tmp); break; } + case ARM_VFP_FPCXT_NS: + lab_end = gen_new_label(); + /* fpInactive case: write is a NOP, so branch to end */ + gen_branch_fpInactive(s, TCG_COND_NE, lab_end); + /* !fpInactive: PreserveFPState(), and reads same as FPCXT_S */ + gen_preserve_fp_state(s); + /* fall through */ case ARM_VFP_FPCXT_S: { - TCGv_i32 sfpa, control, fpscr; - /* Set FPSCR[27:0] and CONTROL.SFPA from value */ + TCGv_i32 sfpa, control; + /* + * Set FPSCR and CONTROL.SFPA from value; the new FPSCR takes + * bits [27:0] from value and zeroes bits [31:28]. + */ tmp = loadfn(s, opaque); sfpa = tcg_temp_new_i32(); tcg_gen_shri_i32(sfpa, tmp, 31); @@ -732,11 +779,8 @@ static bool gen_M_fp_sysreg_write(DisasContext *s, int regno, tcg_gen_deposit_i32(control, control, sfpa, R_V7M_CONTROL_SFPA_SHIFT, 1); store_cpu_field(control, v7m.control[M_REG_S]); - fpscr = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]); - tcg_gen_andi_i32(fpscr, fpscr, FPCR_NZCV_MASK); tcg_gen_andi_i32(tmp, tmp, ~FPCR_NZCV_MASK); - tcg_gen_or_i32(fpscr, fpscr, tmp); - store_cpu_field(fpscr, vfp.xregs[ARM_VFP_FPSCR]); + gen_helper_vfp_set_fpscr(cpu_env, tmp); tcg_temp_free_i32(tmp); tcg_temp_free_i32(sfpa); break; @@ -744,6 +788,9 @@ static bool gen_M_fp_sysreg_write(DisasContext *s, int regno, default: g_assert_not_reached(); } + if (lab_end) { + gen_set_label(lab_end); + } return true; } @@ -753,6 +800,8 @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno, { /* Do a read from an M-profile floating point system register */ TCGv_i32 tmp; + TCGLabel *lab_end = NULL; + bool lookup_tb = false; switch (fp_sysreg_checks(s, regno)) { case FPSysRegCheckFailed: @@ -811,12 +860,59 @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno, fpscr = load_cpu_field(v7m.fpdscr[M_REG_NS]); gen_helper_vfp_set_fpscr(cpu_env, fpscr); tcg_temp_free_i32(fpscr); - gen_lookup_tb(s); + lookup_tb = true; + break; + } + case ARM_VFP_FPCXT_NS: + { + TCGv_i32 control, sfpa, fpscr, fpdscr, zero; + TCGLabel *lab_active = gen_new_label(); + + lookup_tb = true; + + gen_branch_fpInactive(s, TCG_COND_EQ, lab_active); + /* fpInactive case: reads as FPDSCR_NS */ + TCGv_i32 tmp = load_cpu_field(v7m.fpdscr[M_REG_NS]); + storefn(s, opaque, tmp); + lab_end = gen_new_label(); + tcg_gen_br(lab_end); + + gen_set_label(lab_active); + /* !fpInactive: Reads the same as FPCXT_S, but side effects differ */ + gen_preserve_fp_state(s); + tmp = tcg_temp_new_i32(); + sfpa = tcg_temp_new_i32(); + fpscr = tcg_temp_new_i32(); + gen_helper_vfp_get_fpscr(fpscr, cpu_env); + tcg_gen_andi_i32(tmp, fpscr, ~FPCR_NZCV_MASK); + control = load_cpu_field(v7m.control[M_REG_S]); + tcg_gen_andi_i32(sfpa, control, R_V7M_CONTROL_SFPA_MASK); + tcg_gen_shli_i32(sfpa, sfpa, 31 - R_V7M_CONTROL_SFPA_SHIFT); + tcg_gen_or_i32(tmp, tmp, sfpa); + tcg_temp_free_i32(control); + /* Store result before updating FPSCR, in case it faults */ + storefn(s, opaque, tmp); + /* If SFPA is zero then set FPSCR from FPDSCR_NS */ + fpdscr = load_cpu_field(v7m.fpdscr[M_REG_NS]); + zero = tcg_const_i32(0); + tcg_gen_movcond_i32(TCG_COND_EQ, fpscr, sfpa, zero, fpdscr, fpscr); + gen_helper_vfp_set_fpscr(cpu_env, fpscr); + tcg_temp_free_i32(zero); + tcg_temp_free_i32(sfpa); + tcg_temp_free_i32(fpdscr); + tcg_temp_free_i32(fpscr); break; } default: g_assert_not_reached(); } + + if (lab_end) { + gen_set_label(lab_end); + } + if (lookup_tb) { + gen_lookup_tb(s); + } return true; } diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c index 8a734c2f8c..7da70afbf2 100644 --- a/target/s390x/cpu.c +++ b/target/s390x/cpu.c @@ -313,9 +313,7 @@ static void s390_cpu_finalize(Object *obj) #if !defined(CONFIG_USER_ONLY) S390CPU *cpu = S390_CPU(obj); - timer_del(cpu->env.tod_timer); timer_free(cpu->env.tod_timer); - timer_del(cpu->env.cpu_timer); timer_free(cpu->env.cpu_timer); qemu_unregister_reset(s390_cpu_machine_reset_cb, cpu); diff --git a/ui/console.c b/ui/console.c index 4db5b04cc2..d80ce7037c 100644 --- a/ui/console.c +++ b/ui/console.c @@ -253,7 +253,6 @@ static void gui_setup_refresh(DisplayState *ds) timer_mod(ds->gui_timer, qemu_clock_get_ms(QEMU_CLOCK_REALTIME)); } if (!need_timer && ds->gui_timer != NULL) { - timer_del(ds->gui_timer); timer_free(ds->gui_timer); ds->gui_timer = NULL; } diff --git a/ui/spice-core.c b/ui/spice-core.c index eea52f5389..5746d0aae7 100644 --- a/ui/spice-core.c +++ b/ui/spice-core.c @@ -76,7 +76,6 @@ static void timer_cancel(SpiceTimer *timer) static void timer_remove(SpiceTimer *timer) { - timer_del(timer->timer); timer_free(timer->timer); g_free(timer); } diff --git a/util/throttle.c b/util/throttle.c index b38e742da5..81f247a8d1 100644 --- a/util/throttle.c +++ b/util/throttle.c @@ -247,7 +247,6 @@ static void throttle_timer_destroy(QEMUTimer **timer) { assert(*timer != NULL); - timer_del(*timer); timer_free(*timer); *timer = NULL; }