From 4663b72a48fd540cbe16053b01d6839a95656440 Mon Sep 17 00:00:00 2001 From: "Edgar E. Iglesias" Date: Mon, 14 Dec 2020 23:21:54 +0100 Subject: [PATCH 01/23] intc/arm_gic: Fix gic_irq_signaling_enabled() for vCPUs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Correct the indexing into s->cpu_ctlr for vCPUs. Signed-off-by: Edgar E. Iglesias Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Luc Michel Message-id: 20201214222154.3480243-2-edgar.iglesias@gmail.com Signed-off-by: Peter Maydell --- hw/intc/arm_gic.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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; } From 9cd07db94b41e849dab8a547fb778718a11f487d Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Tue, 15 Dec 2020 18:48:15 +0100 Subject: [PATCH 02/23] hw/arm/virt: Remove virt machine state 'smp_cpus' virt machine's 'smp_cpus' and machine->smp.cpus must always have the same value. And, anywhere we have virt machine state we have machine state. So let's remove the redundancy. Also, to make it easier to see that machine->smp is the true source for "smp_cpus" and "max_cpus", avoid passing them in function parameters, preferring instead to get them from the state. No functional change intended. Signed-off-by: Andrew Jones Reviewed-by: David Edmondson Reviewed-by: Ying Fang Message-id: 20201215174815.51520-1-drjones@redhat.com [PMM: minor formatting tweak to smp_cpus variable declaration] Signed-off-by: Peter Maydell --- hw/arm/virt-acpi-build.c | 9 +++++---- hw/arm/virt.c | 21 ++++++++++----------- include/hw/arm/virt.h | 3 +-- 3 files changed, 16 insertions(+), 17 deletions(-) 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/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 */ From cc97b0019bb590b9b3c2a623e9ebee48831e0ce3 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 21 Dec 2020 12:44:26 -0800 Subject: [PATCH 03/23] target/arm: Fix MTE0_ACTIVE In 50244cc76abc we updated mte_check_fail to match the ARM pseudocode, using the correct EL to select the TCF field. But we failed to update MTE0_ACTIVE the same way, which led to g_assert_not_reached(). Cc: qemu-stable@nongnu.org Buglink: https://bugs.launchpad.net/bugs/1907137 Signed-off-by: Richard Henderson Message-id: 20201221204426.88514-1-richard.henderson@linaro.org Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- target/arm/helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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); } From 5b7d63706ea460d3999ee9ff3e3e010419d906ca Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 10 Dec 2020 20:14:30 +0000 Subject: [PATCH 04/23] hw/intc/armv7m_nvic: Correct handling of CCR.BFHFNMIGN The CCR is a register most of whose bits are banked between security states but where BFHFNMIGN is not, and we keep it in the non-secure entry of the v7m.ccr[] array. The logic which tries to handle this bit fails to implement the "RAZ/WI from Nonsecure if AIRCR.BFHFNMINS is zero" requirement; correct the omission. Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Message-id: 20201210201433.26262-2-peter.maydell@linaro.org --- hw/intc/armv7m_nvic.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) 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; From 7fbf95a037d79c5e923ffb51ac902dbe9599c87f Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 10 Dec 2020 20:14:31 +0000 Subject: [PATCH 05/23] target/arm: Correct store of FPSCR value via FPCXT_S In commit 64f863baeedc8659 we implemented the v8.1M FPCXT_S register, but we got the write behaviour wrong. On read, this register reads bits [27:0] of FPSCR plus the CONTROL.SFPA bit. On write, it doesn't just write back those bits -- it writes a value to the whole FPSCR, whose upper 4 bits are zeroes. We also incorrectly implemented the write-to-FPSCR as a simple store to vfp.xregs; this skips the "update the softfloat flags" part of the vfp_set_fpscr helper so the value would read back correctly but not actually take effect. Fix both of these things by doing a complete write to the FPSCR using the helper function. Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Message-id: 20201210201433.26262-3-peter.maydell@linaro.org --- target/arm/translate-vfp.c.inc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc index 0db936084b..8b4cfd68ca 100644 --- a/target/arm/translate-vfp.c.inc +++ b/target/arm/translate-vfp.c.inc @@ -723,8 +723,11 @@ static bool gen_M_fp_sysreg_write(DisasContext *s, int regno, } 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 +735,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; From eb20dafdbff92063a88624176fdc396e01961bf3 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 10 Dec 2020 20:14:32 +0000 Subject: [PATCH 06/23] target/arm: Implement FPCXT_NS fp system register Implement the v8.1M FPCXT_NS floating-point system register. This is a little more complicated than FPCXT_S, because it has specific handling for "current FP state is inactive", and it only wants to do PreserveFPState(), not the full set of actions done by ExecuteFPCheck() which vfp_access_check() implements. Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Message-id: 20201210201433.26262-4-peter.maydell@linaro.org --- target/arm/translate-vfp.c.inc | 102 ++++++++++++++++++++++++++++++++- 1 file changed, 99 insertions(+), 3 deletions(-) diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc index 8b4cfd68ca..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,6 +758,13 @@ 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; @@ -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; } From 590e05d6b48937f6d3c631354fd706f8e005b8f6 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 10 Dec 2020 20:14:33 +0000 Subject: [PATCH 07/23] target/arm: Implement Cortex-M55 model Now that we have implemented all the features needed by the v8.1M architecture, we can add the model of the Cortex-M55. This is the configuration without MVE support; we'll add MVE later. Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Message-id: 20201210201433.26262-5-peter.maydell@linaro.org --- target/arm/cpu_tcg.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) 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 }, From 416dd95295b1c13fc9f1f2dbb2803ad581de415a Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 15 Dec 2020 14:42:15 +0000 Subject: [PATCH 08/23] hw/arm/highbank: Drop dead KVM support code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Support for running KVM on 32-bit Arm hosts was removed in commit 82bf7ae84ce739e. You can still run a 32-bit guest on a 64-bit Arm host CPU, but because Arm KVM requires the host and guest CPU types to match, it is not possible to run a guest that requires a Cortex-A9 or Cortex-A15 CPU there. That means that the code in the highbank/midway board models to support KVM is no longer used, and we can delete it. Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé Message-id: 20201215144215.28482-1-peter.maydell@linaro.org --- hw/arm/highbank.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) 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); } From 5f8e93c3e262ab518c9e8f9a5bb2b391b3d64be9 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 15 Dec 2020 15:41:04 +0000 Subject: [PATCH 09/23] util/qemu-timer: Make timer_free() imply timer_del() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently timer_free() is a simple wrapper for g_free(). This means that the timer being freed must not be currently active, as otherwise QEMU might crash later when the active list is processed and still has a pointer to freed memory on it. As a result almost all calls to timer_free() are preceded by a timer_del() call, as can be seen in the output of git grep -B1 '\' This is unfortunate API design as it makes it easy to accidentally misuse (by forgetting the timer_del()), and the correct use is annoyingly verbose. Make timer_free() imply a timer_del(). Signed-off-by: Peter Maydell Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-id: 20201215154107.3255-2-peter.maydell@linaro.org --- include/qemu/timer.h | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) 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 From 01b3e68bb18d1a37f013ffac41423faa7c00958f Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 15 Dec 2020 15:41:05 +0000 Subject: [PATCH 10/23] scripts/coccinelle: New script to remove unnecessary timer_del() calls MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that timer_free() implicitly calls timer_del(), sequences timer_del(mytimer); timer_free(mytimer); can be simplified to just timer_free(mytimer); Add a Coccinelle script to do this transformation. Signed-off-by: Peter Maydell Acked-by: Paolo Bonzini Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-id: 20201215154107.3255-3-peter.maydell@linaro.org --- scripts/coccinelle/timer-del-timer-free.cocci | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 scripts/coccinelle/timer-del-timer-free.cocci 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); From 729cc683735309bdcd55604be19292950877ecf5 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 15 Dec 2020 15:41:06 +0000 Subject: [PATCH 11/23] Remove superfluous timer_del() calls MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit is the result of running the timer-del-timer-free.cocci script on the whole source tree. Signed-off-by: Peter Maydell Acked-by: Corey Minyard Acked-by: Paolo Bonzini Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-id: 20201215154107.3255-4-peter.maydell@linaro.org --- block/iscsi.c | 2 -- block/nbd.c | 1 - block/qcow2.c | 1 - hw/block/nvme.c | 2 -- hw/char/serial.c | 2 -- hw/char/virtio-serial-bus.c | 2 -- hw/ide/core.c | 1 - hw/input/hid.c | 1 - hw/intc/apic.c | 1 - hw/intc/ioapic.c | 1 - hw/ipmi/ipmi_bmc_extern.c | 1 - hw/net/e1000.c | 3 --- hw/net/e1000e_core.c | 8 -------- hw/net/pcnet-pci.c | 1 - hw/net/rtl8139.c | 1 - hw/net/spapr_llan.c | 1 - hw/net/virtio-net.c | 2 -- hw/s390x/s390-pci-inst.c | 1 - hw/sd/sd.c | 1 - hw/sd/sdhci.c | 2 -- hw/usb/dev-hub.c | 1 - hw/usb/hcd-ehci.c | 1 - hw/usb/hcd-ohci-pci.c | 1 - hw/usb/hcd-uhci.c | 1 - hw/usb/hcd-xhci.c | 1 - hw/usb/redirect.c | 1 - hw/vfio/display.c | 1 - hw/virtio/vhost-vsock-common.c | 1 - hw/virtio/virtio-balloon.c | 1 - hw/virtio/virtio-rng.c | 1 - hw/watchdog/wdt_diag288.c | 1 - hw/watchdog/wdt_i6300esb.c | 1 - migration/colo.c | 1 - monitor/hmp-cmds.c | 1 - net/announce.c | 1 - net/colo-compare.c | 1 - net/slirp.c | 1 - replay/replay-debugging.c | 1 - target/s390x/cpu.c | 2 -- ui/console.c | 1 - ui/spice-core.c | 1 - util/throttle.c | 1 - 42 files changed, 58 deletions(-) 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/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/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/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/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/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/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/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; } From 2d3bf6532733a07671141019f784c945e997d285 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 15 Dec 2020 15:41:07 +0000 Subject: [PATCH 12/23] target/arm: Remove timer_del()/timer_deinit() before timer_free() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Arm CPU finalize function uses a sequence of timer_del(), timer_deinit(), timer_free() to free the timer. The timer_deinit() step in this was always unnecessary, and now the timer_del() is implied by timer_free(), so we can collapse this down to simply calling timer_free(). Signed-off-by: Peter Maydell Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-id: 20201215154107.3255-5-peter.maydell@linaro.org --- target/arm/cpu.c | 2 -- 1 file changed, 2 deletions(-) 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 From ea492b124586d224ffb962f62c201adb862ca5c7 Mon Sep 17 00:00:00 2001 From: Gan Qixin Date: Thu, 17 Dec 2020 19:31:49 +0800 Subject: [PATCH 13/23] digic-timer: Use ptimer_free() in the finalize function to avoid memleaks When running device-introspect-test, a memory leak occurred in the digic_timer_init function, so use ptimer_free() in the finalize function to avoid it. ASAN shows memory leak stack: Indirect leak of 288 byte(s) in 3 object(s) allocated from: #0 0xffffab97e1f0 in __interceptor_calloc (/lib64/libasan.so.5+0xee1f0) #1 0xffffab256800 in g_malloc0 (/lib64/libglib-2.0.so.0+0x56800) #2 0xaaabf555db78 in ptimer_init /qemu/hw/core/ptimer.c:432 #3 0xaaabf5b04084 in digic_timer_init /qemu/hw/timer/digic-timer.c:142 #4 0xaaabf6339f6c in object_initialize_with_type /qemu/qom/object.c:515 #5 0xaaabf633ca04 in object_initialize_child_with_propsv /qemu/qom/object.c:564 #6 0xaaabf633cc08 in object_initialize_child_with_props /qemu/qom/object.c:547 #7 0xaaabf5b40e84 in digic_init /qemu/hw/arm/digic.c:46 #8 0xaaabf6339f6c in object_initialize_with_type /qemu/qom/object.c:515 #9 0xaaabf633a1e0 in object_new_with_type /qemu/qom/object.c:729 #10 0xaaabf6375e40 in qmp_device_list_properties /qemu/qom/qom-qmp-cmds.c:153 #11 0xaaabf653d8ec in qmp_marshal_device_list_properties /qemu/qapi/qapi-commands-qdev.c:59 #12 0xaaabf6587d08 in do_qmp_dispatch_bh /qemu/qapi/qmp-dispatch.c:110 Reported-by: Euler Robot Signed-off-by: Gan Qixin Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/timer/digic-timer.c | 8 ++++++++ 1 file changed, 8 insertions(+) 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, }; From e1c5909b294f1059c46186dcc4aa7901ca19447e Mon Sep 17 00:00:00 2001 From: Gan Qixin Date: Thu, 17 Dec 2020 19:31:48 +0800 Subject: [PATCH 14/23] allwinner-a10-pit: Use ptimer_free() in the finalize function to avoid memleaks When running device-introspect-test, a memory leak occurred in the a10_pit_init function, so use ptimer_free() in the finalize function to avoid it. ASAN shows memory leak stack: Indirect leak of 288 byte(s) in 6 object(s) allocated from: #0 0xffffab97e1f0 in __interceptor_calloc (/lib64/libasan.so.5+0xee1f0) #1 0xffffab256800 in g_malloc0 (/lib64/libglib-2.0.so.0+0x56800) #2 0xaaabf555db84 in timer_new_full /qemu/include/qemu/timer.h:523 #3 0xaaabf555db84 in timer_new /qemu/include/qemu/timer.h:544 #4 0xaaabf555db84 in timer_new_ns /qemu/include/qemu/timer.h:562 #5 0xaaabf555db84 in ptimer_init /qemu/hw/core/ptimer.c:433 #6 0xaaabf57415e8 in a10_pit_init /qemu/hw/timer/allwinner-a10-pit.c:278 #7 0xaaabf6339f6c in object_initialize_with_type /qemu/qom/object.c:515 #8 0xaaabf633ca04 in object_initialize_child_with_propsv /qemu/qom/object.c:564 #9 0xaaabf633cc08 in object_initialize_child_with_props /qemu/qom/object.c:547 #10 0xaaabf5b94680 in aw_a10_init /qemu/hw/arm/allwinner-a10.c:49 #11 0xaaabf6339f6c in object_initialize_with_type /qemu/qom/object.c:515 #12 0xaaabf633a1e0 in object_new_with_type /qemu/qom/object.c:729 Reported-by: Euler Robot Signed-off-by: Gan Qixin Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/timer/allwinner-a10-pit.c | 11 +++++++++++ 1 file changed, 11 insertions(+) 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, }; From 3fabd51994566053a65df1c1e10cd96f96e0c30e Mon Sep 17 00:00:00 2001 From: Gan Qixin Date: Thu, 17 Dec 2020 19:31:52 +0800 Subject: [PATCH 15/23] exynos4210_rtc: Use ptimer_free() in the finalize function to avoid memleaks When running device-introspect-test, a memory leak occurred in the exynos4210_rtc_init function, so use ptimer_free() in the finalize function to avoid it. ASAN shows memory leak stack: Indirect leak of 96 byte(s) in 1 object(s) allocated from: #0 0xffffab97e1f0 in __interceptor_calloc (/lib64/libasan.so.5+0xee1f0) #1 0xffffab256800 in g_malloc0 (/lib64/libglib-2.0.so.0+0x56800) #2 0xaaabf555db78 in ptimer_init /qemu/hw/core/ptimer.c:432 #3 0xaaabf57b3934 in exynos4210_rtc_init /qemu/hw/rtc/exynos4210_rtc.c:567 #4 0xaaabf6339f6c in object_initialize_with_type /qemu/qom/object.c:515 #5 0xaaabf633a1e0 in object_new_with_type /qemu/qom/object.c:729 #6 0xaaabf6375e40 in qmp_device_list_properties /qemu/qom/qom-qmp-cmds.c:153 #7 0xaaabf653d8ec in qmp_marshal_device_list_properties /qemu/qapi/qapi-commands-qdev.c:59 #8 0xaaabf6587d08 in do_qmp_dispatch_bh /qemu/qapi/qmp-dispatch.c:110 #9 0xaaabf6552708 in aio_bh_call /qemu/util/async.c:136 #10 0xaaabf6552708 in aio_bh_poll /qemu/util/async.c:164 #11 0xaaabf655f19c in aio_dispatch /qemu/util/aio-posix.c:381 #12 0xaaabf65523f4 in aio_ctx_dispatch /qemu/util/async.c:306 Reported-by: Euler Robot Signed-off-by: Gan Qixin Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/rtc/exynos4210_rtc.c | 9 +++++++++ 1 file changed, 9 insertions(+) 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, }; From c9342c09f85a5f2f442fabcac58517bbba74b19f Mon Sep 17 00:00:00 2001 From: Gan Qixin Date: Thu, 17 Dec 2020 19:31:51 +0800 Subject: [PATCH 16/23] exynos4210_pwm: Use ptimer_free() in the finalize function to avoid memleaks When running device-introspect-test, a memory leak occurred in the exynos4210_pwm_init function, so use ptimer_free() in the finalize function to avoid it. ASAN shows memory leak stack: Indirect leak of 240 byte(s) in 5 object(s) allocated from: #0 0xffffab97e1f0 in __interceptor_calloc (/lib64/libasan.so.5+0xee1f0) #1 0xffffab256800 in g_malloc0 (/lib64/libglib-2.0.so.0+0x56800) #2 0xaaabf555db84 in timer_new_full /qemu/include/qemu/timer.h:523 #3 0xaaabf555db84 in timer_new /qemu/include/qemu/timer.h:544 #4 0xaaabf555db84 in timer_new_ns /qemu/include/qemu/timer.h:562 #5 0xaaabf555db84 in ptimer_init /qemu/hw/core/ptimer.c:433 #6 0xaaabf56a36cc in exynos4210_pwm_init /qemu/hw/timer/exynos4210_pwm.c:401 #7 0xaaabf6339f6c in object_initialize_with_type /qemu/qom/object.c:515 #8 0xaaabf633a1e0 in object_new_with_type /qemu/qom/object.c:729 #9 0xaaabf6375e40 in qmp_device_list_properties /qemu/qom/qom-qmp-cmds.c:153 #10 0xaaabf653d8ec in qmp_marshal_device_list_properties /qemu/qapi/qapi-commands-qdev.c:59 #11 0xaaabf6587d08 in do_qmp_dispatch_bh /qemu/qapi/qmp-dispatch.c:110 #12 0xaaabf6552708 in aio_bh_call /qemu/util/async.c:136 Reported-by: Euler Robot Signed-off-by: Gan Qixin Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/timer/exynos4210_pwm.c | 11 +++++++++++ 1 file changed, 11 insertions(+) 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, }; From e4940041f68213437e81792fbd3f06c3609e94f3 Mon Sep 17 00:00:00 2001 From: Gan Qixin Date: Thu, 17 Dec 2020 19:31:53 +0800 Subject: [PATCH 17/23] mss-timer: Use ptimer_free() in the finalize function to avoid memleaks When running device-introspect-test, a memory leak occurred in the mss_timer_init function, so use ptimer_free() in the finalize function to avoid it. ASAN shows memory leak stack: Indirect leak of 192 byte(s) in 2 object(s) allocated from: #0 0xffffab97e1f0 in __interceptor_calloc (/lib64/libasan.so.5+0xee1f0) #1 0xffffab256800 in g_malloc0 (/lib64/libglib-2.0.so.0+0x56800) #2 0xaaabf555db78 in ptimer_init /qemu/hw/core/ptimer.c:432 #3 0xaaabf58a0010 in mss_timer_init /qemu/hw/timer/mss-timer.c:235 #4 0xaaabf6339f6c in object_initialize_with_type /qemu/qom/object.c:515 #5 0xaaabf633ca04 in object_initialize_child_with_propsv /qemu/qom/object.c:564 #6 0xaaabf633cc08 in object_initialize_child_with_props /qemu/qom/object.c:547 #7 0xaaabf5b8316c in m2sxxx_soc_initfn /qemu/hw/arm/msf2-soc.c:70 #8 0xaaabf6339f6c in object_initialize_with_type /qemu/qom/object.c:515 #9 0xaaabf633a1e0 in object_new_with_type /qemu/qom/object.c:729 #10 0xaaabf6375e40 in qmp_device_list_properties /qemu/qom/qom-qmp-cmds.c:153 #11 0xaaabf653d8ec in qmp_marshal_device_list_properties /qemu/qapi/qapi-commands-qdev.c:59 #12 0xaaabf6587d08 in do_qmp_dispatch_bh /qemu/qapi/qmp-dispatch.c:110 Reported-by: Euler Robot Signed-off-by: Gan Qixin Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/timer/mss-timer.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) 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, }; From a4bc0334bc51fcb975d796f3057c3561e186cde3 Mon Sep 17 00:00:00 2001 From: Gan Qixin Date: Thu, 17 Dec 2020 19:31:54 +0800 Subject: [PATCH 18/23] musicpal: Use ptimer_free() in the finalize function to avoid memleaks When running device-introspect-test, a memory leak occurred in the mv88w8618_pit_init function, so use ptimer_free() in the finalize function to avoid it. ASAN shows memory leak stack: Indirect leak of 192 byte(s) in 4 object(s) allocated from: #0 0xffffab97e1f0 in __interceptor_calloc (/lib64/libasan.so.5+0xee1f0) #1 0xffffab256800 in g_malloc0 (/lib64/libglib-2.0.so.0+0x56800) #2 0xaaabf555db84 in timer_new_full /qemu/include/qemu/timer.h:523 #3 0xaaabf555db84 in timer_new /qemu/include/qemu/timer.h:544 #4 0xaaabf555db84 in timer_new_ns /qemu/include/qemu/timer.h:562 #5 0xaaabf555db84 in ptimer_init /qemu/hw/core/ptimer.c:433 #6 0xaaabf5bb2290 in mv88w8618_timer_init /qemu/hw/arm/musicpal.c:862 #7 0xaaabf5bb2290 in mv88w8618_pit_init /qemu/hw/arm/musicpal.c:954 #8 0xaaabf6339f6c in object_initialize_with_type /qemu/qom/object.c:515 #9 0xaaabf633a1e0 in object_new_with_type /qemu/qom/object.c:729 #10 0xaaabf6375e40 in qmp_device_list_properties /qemu/qom/qom-qmp-cmds.c:153 #11 0xaaabf5a95540 in qdev_device_help /qemu/softmmu/qdev-monitor.c:283 #12 0xaaabf5a96940 in qmp_device_add /qemu/softmmu/qdev-monitor.c:801 Reported-by: Euler Robot Signed-off-by: Gan Qixin Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/arm/musicpal.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) 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, }; From d97d9152c7baa9f3743aea7ffe124c7977a9b0fa Mon Sep 17 00:00:00 2001 From: Gan Qixin Date: Thu, 17 Dec 2020 19:31:50 +0800 Subject: [PATCH 19/23] exynos4210_mct: Use ptimer_free() in the finalize function to avoid memleaks When running device-introspect-test, a memory leak occurred in the exynos4210_mct_init function, so use ptimer_free() in the finalize function to avoid it. ASAN shows memory leak stack: Indirect leak of 96 byte(s) in 1 object(s) allocated from: #0 0xffffab97e1f0 in __interceptor_calloc (/lib64/libasan.so.5+0xee1f0) #1 0xffffab256800 in g_malloc0 (/lib64/libglib-2.0.so.0+0x56800) #2 0xaaabf555db78 in ptimer_init /qemu/hw/core/ptimer.c:432 #3 0xaaabf56b01a0 in exynos4210_mct_init /qemu/hw/timer/exynos4210_mct.c:1505 #4 0xaaabf6339f6c in object_initialize_with_type /qemu/qom/object.c:515 #5 0xaaabf633a1e0 in object_new_with_type /qemu/qom/object.c:729 #6 0xaaabf6375e40 in qmp_device_list_properties /qemu/qom/qom-qmp-cmds.c:153 #7 0xaaabf653d8ec in qmp_marshal_device_list_properties /qemu/qapi/qapi-commands-qdev.c:59 #8 0xaaabf6587d08 in do_qmp_dispatch_bh /qemu/qapi/qmp-dispatch.c:110 #9 0xaaabf6552708 in aio_bh_call /qemu/util/async.c:136 #10 0xaaabf6552708 in aio_bh_poll /qemu/util/async.c:164 #11 0xaaabf655f19c in aio_dispatch /qemu/util/aio-posix.c:381 #12 0xaaabf65523f4 in aio_ctx_dispatch /qemu/util/async.c:306 Reported-by: Euler Robot Signed-off-by: Gan Qixin Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/timer/exynos4210_mct.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) 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, }; From 56a11a9b7580b576a9db930667be07f1dd1564d5 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 6 Jan 2021 14:35:01 +0800 Subject: [PATCH 20/23] hw/misc: imx6_ccm: Update PMU_MISC0 reset value MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit U-Boot expects PMU_MISC0 register bit 7 is set (see init_bandgap() in arch/arm/mach-imx/mx6/soc.c) during boot. This bit indicates the bandgap has stabilized. With this change, the latest upstream U-Boot (v2021.01-rc3) for imx6 sabrelite board (mx6qsabrelite_defconfig), with a slight change made by switching CONFIG_OF_SEPARATE to CONFIG_OF_EMBED, boots to U-Boot shell on QEMU with the following command: $ qemu-system-arm -M sabrelite -smp 4 -m 1G -kernel u-boot \ -display none -serial null -serial stdio Boot log below: U-Boot 2021.01-rc3 (Dec 12 2020 - 17:40:02 +0800) CPU: Freescale i.MX?? rev1.0 at 792 MHz Reset cause: POR Model: Freescale i.MX6 Quad SABRE Lite Board Board: SABRE Lite I2C: ready DRAM: 1 GiB force_idle_bus: sda=0 scl=0 sda.gp=0x5c scl.gp=0x55 force_idle_bus: failed to clear bus, sda=0 scl=0 force_idle_bus: sda=0 scl=0 sda.gp=0x6d scl.gp=0x6c force_idle_bus: failed to clear bus, sda=0 scl=0 force_idle_bus: sda=0 scl=0 sda.gp=0xcb scl.gp=0x5 force_idle_bus: failed to clear bus, sda=0 scl=0 MMC: FSL_SDHC: 0, FSL_SDHC: 1 Loading Environment from MMC... *** Warning - No block device, using default environment In: serial Out: serial Err: serial Net: Board Net Initialization Failed No ethernet found. starting USB... Bus usb@2184000: usb dr_mode not found USB EHCI 1.00 Bus usb@2184200: USB EHCI 1.00 scanning bus usb@2184000 for devices... 1 USB Device(s) found scanning bus usb@2184200 for devices... 1 USB Device(s) found scanning usb for storage devices... 0 Storage Device(s) found scanning usb for ethernet devices... 0 Ethernet Device(s) found Hit any key to stop autoboot: 0 => Signed-off-by: Bin Meng Reviewed-by: Alex Bennée Message-id: 20210106063504.10841-2-bmeng.cn@gmail.com Signed-off-by: Peter Maydell --- hw/misc/imx6_ccm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/misc/imx6_ccm.c b/hw/misc/imx6_ccm.c index cb740427ec..7e031b6775 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; From 459149716331dbf06e21da6e72c0fb4340b47bd2 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 6 Jan 2021 14:35:02 +0800 Subject: [PATCH 21/23] hw/msic: imx6_ccm: Correct register value for silicon type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently when U-Boot boots, it prints "??" for i.MX processor: CPU: Freescale i.MX?? rev1.0 at 792 MHz The register that was used to determine the silicon type is undocumented in the latest IMX6DQRM (Rev. 6, 05/2020), but we can refer to get_cpu_rev() in arch/arm/mach-imx/mx6/soc.c in the U-Boot source codes that USB_ANALOG_DIGPROG is used. Update its reset value to indicate i.MX6Q. Signed-off-by: Bin Meng Reviewed-by: Alex Bennée Message-id: 20210106063504.10841-3-bmeng.cn@gmail.com Signed-off-by: Peter Maydell --- hw/misc/imx6_ccm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/misc/imx6_ccm.c b/hw/misc/imx6_ccm.c index 7e031b6775..4c830fd89a 100644 --- a/hw/misc/imx6_ccm.c +++ b/hw/misc/imx6_ccm.c @@ -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; From 37e33be7ea6b34e0c883f2b39b0c82d6c2b65bc7 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 6 Jan 2021 14:35:03 +0800 Subject: [PATCH 22/23] hw/arm: sabrelite: Connect the Ethernet PHY at address 6 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit At present, when booting U-Boot on QEMU sabrelite, we see: Net: Board Net Initialization Failed No ethernet found. U-Boot scans PHY at address 4/5/6/7 (see board_eth_init() in the U-Boot source: board/boundary/nitrogen6x/nitrogen6x.c). On the real board, the Ethernet PHY is at address 6. Adjust this by updating the "fec-phy-num" property of the fsl_imx6 SoC object. With this change, U-Boot sees the PHY but complains MAC address: Net: using phy at 6 FEC [PRIME] Error: FEC address not set. This is due to U-Boot tries to read the MAC address from the fuse, which QEMU does not have any valid content filled in. However this does not prevent the Ethernet from working in QEMU. We just need to set up the MAC address later in the U-Boot command shell, by: => setenv ethaddr 00:11:22:33:44:55 Signed-off-by: Bin Meng Reviewed-by: Alex Bennée Message-id: 20210106063504.10841-4-bmeng.cn@gmail.com Signed-off-by: Peter Maydell --- hw/arm/sabrelite.c | 4 ++++ 1 file changed, 4 insertions(+) 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, From c9f8511ea8d2b80723af0fea1f716d752c1b5208 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 6 Jan 2021 14:35:04 +0800 Subject: [PATCH 23/23] docs/system: arm: Add sabrelite board description MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds the target guide for SABRE Lite board, and documents how to boot a Linux kernel and U-Boot bootloader. Signed-off-by: Bin Meng Reviewed-by: Alex Bennée Message-id: 20210106063504.10841-5-bmeng.cn@gmail.com Signed-off-by: Peter Maydell --- docs/system/arm/sabrelite.rst | 119 ++++++++++++++++++++++++++++++++++ docs/system/target-arm.rst | 1 + 2 files changed, 120 insertions(+) create mode 100644 docs/system/arm/sabrelite.rst 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