diff options
-rw-r--r-- | MAINTAINERS | 2 | ||||
-rwxr-xr-x | configure | 2 | ||||
-rw-r--r-- | docs/system/arm/cpu-features.rst | 15 | ||||
-rw-r--r-- | hw/arm/nseries.c | 2 | ||||
-rw-r--r-- | hw/arm/smmuv3-internal.h | 2 | ||||
-rw-r--r-- | hw/gpio/aspeed_gpio.c | 3 | ||||
-rw-r--r-- | hw/intc/armv7m_nvic.c | 40 | ||||
-rw-r--r-- | qemu-options.hx | 30 | ||||
-rw-r--r-- | target/arm/cpu.c | 14 | ||||
-rw-r--r-- | target/arm/cpu.h | 5 | ||||
-rw-r--r-- | target/arm/cpu64.c | 60 | ||||
-rw-r--r-- | target/arm/gdbstub.c | 4 | ||||
-rw-r--r-- | target/arm/helper.c | 8 | ||||
-rw-r--r-- | target/arm/internals.h | 10 | ||||
-rw-r--r-- | target/arm/m_helper.c | 24 | ||||
-rw-r--r-- | target/arm/translate.c | 3 | ||||
-rw-r--r-- | target/i386/cpu.c | 2 |
17 files changed, 183 insertions, 43 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 445f7fe2d1..42ac45c3e5 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3439,7 +3439,7 @@ F: contrib/gitdm/* Incompatible changes R: libvir-list@redhat.com -F: docs/system/deprecated.rst +F: docs/about/deprecated.rst Build System ------------ @@ -5230,7 +5230,7 @@ fi if test -n "${deprecated_features}"; then echo "Warning, deprecated features enabled." - echo "Please see docs/system/deprecated.rst" + echo "Please see docs/about/deprecated.rst" echo " features: ${deprecated_features}" fi diff --git a/docs/system/arm/cpu-features.rst b/docs/system/arm/cpu-features.rst index c455442eaf..11dce5c603 100644 --- a/docs/system/arm/cpu-features.rst +++ b/docs/system/arm/cpu-features.rst @@ -376,3 +376,18 @@ verbose command lines. However, the recommended way to select vector lengths is to explicitly enable each desired length. Therefore only example's (1), (4), and (6) exhibit recommended uses of the properties. +SVE User-mode Default Vector Length Property +-------------------------------------------- + +For qemu-aarch64, the cpu property ``sve-default-vector-length=N`` is +defined to mirror the Linux kernel parameter file +``/proc/sys/abi/sve_default_vector_length``. The default length, ``N``, +is in units of bytes and must be between 16 and 8192. +If not specified, the default vector length is 64. + +If the default length is larger than the maximum vector length enabled, +the actual vector length will be reduced. Note that the maximum vector +length supported by QEMU is 256. + +If this property is set to ``-1`` then the default vector length +is set to the maximum possible length. diff --git a/hw/arm/nseries.c b/hw/arm/nseries.c index 906c915df7..af3164c551 100644 --- a/hw/arm/nseries.c +++ b/hw/arm/nseries.c @@ -692,7 +692,7 @@ static uint32_t mipid_txrx(void *opaque, uint32_t cmd, int len) default: bad_cmd: qemu_log_mask(LOG_GUEST_ERROR, - "%s: unknown command %02x\n", __func__, s->cmd); + "%s: unknown command 0x%02x\n", __func__, s->cmd); break; } diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h index 3dac5766ca..d1885ae3f2 100644 --- a/hw/arm/smmuv3-internal.h +++ b/hw/arm/smmuv3-internal.h @@ -570,7 +570,7 @@ static inline int pa_range(STE *ste) /* CD fields */ -#define CD_VALID(x) extract32((x)->word[0], 30, 1) +#define CD_VALID(x) extract32((x)->word[0], 31, 1) #define CD_ASID(x) extract32((x)->word[1], 16, 16) #define CD_TTB(x, sel) \ ({ \ diff --git a/hw/gpio/aspeed_gpio.c b/hw/gpio/aspeed_gpio.c index 6ae0116be7..b3dec44480 100644 --- a/hw/gpio/aspeed_gpio.c +++ b/hw/gpio/aspeed_gpio.c @@ -207,7 +207,6 @@ #define GPIO_1_8V_MEM_SIZE 0x9D8 #define GPIO_1_8V_REG_ARRAY_SIZE ((GPIO_1_8V_MEM_SIZE - \ GPIO_1_8V_REG_OFFSET) >> 2) -#define GPIO_MAX_MEM_SIZE MAX(GPIO_3_6V_MEM_SIZE, GPIO_1_8V_MEM_SIZE) static int aspeed_evaluate_irq(GPIOSets *regs, int gpio_prev_high, int gpio) { @@ -849,7 +848,7 @@ static void aspeed_gpio_realize(DeviceState *dev, Error **errp) } memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_gpio_ops, s, - TYPE_ASPEED_GPIO, GPIO_MAX_MEM_SIZE); + TYPE_ASPEED_GPIO, 0x800); sysbus_init_mmio(sbd, &s->iomem); } diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c index 94fe00235a..1e7ddcb94c 100644 --- a/hw/intc/armv7m_nvic.c +++ b/hw/intc/armv7m_nvic.c @@ -127,15 +127,14 @@ static bool nvic_isrpending(NVICState *s) { int irq; - /* We can shortcut if the highest priority pending interrupt - * happens to be external or if there is nothing pending. + /* + * We can shortcut if the highest priority pending interrupt + * happens to be external; if not we need to check the whole + * vectors[] array. */ if (s->vectpending > NVIC_FIRST_IRQ) { return true; } - if (s->vectpending == 0) { - return false; - } for (irq = NVIC_FIRST_IRQ; irq < s->num_irq; irq++) { if (s->vectors[irq].pending) { @@ -805,6 +804,16 @@ void armv7m_nvic_acknowledge_irq(void *opaque) nvic_irq_update(s); } +static bool vectpending_targets_secure(NVICState *s) +{ + /* Return true if s->vectpending targets Secure state */ + if (s->vectpending_is_s_banked) { + return true; + } + return !exc_is_banked(s->vectpending) && + exc_targets_secure(s, s->vectpending); +} + void armv7m_nvic_get_pending_irq_info(void *opaque, int *pirq, bool *ptargets_secure) { @@ -814,12 +823,7 @@ void armv7m_nvic_get_pending_irq_info(void *opaque, assert(pending > ARMV7M_EXCP_RESET && pending < s->num_irq); - if (s->vectpending_is_s_banked) { - targets_secure = true; - } else { - targets_secure = !exc_is_banked(pending) && - exc_targets_secure(s, pending); - } + targets_secure = vectpending_targets_secure(s); trace_nvic_get_pending_irq_info(pending, targets_secure); @@ -1040,7 +1044,19 @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs) /* VECTACTIVE */ val = cpu->env.v7m.exception; /* VECTPENDING */ - val |= (s->vectpending & 0xff) << 12; + if (s->vectpending) { + /* + * From v8.1M VECTPENDING must read as 1 if accessed as + * NonSecure and the highest priority pending and enabled + * exception targets Secure. + */ + int vp = s->vectpending; + if (!attrs.secure && arm_feature(&cpu->env, ARM_FEATURE_V8_1M) && + vectpending_targets_secure(s)) { + vp = 1; + } + val |= (vp & 0x1ff) << 12; + } /* ISRPENDING - set if any external IRQ is pending */ if (nvic_isrpending(s)) { val |= (1 << 22); diff --git a/qemu-options.hx b/qemu-options.hx index 99ed5ec5f1..83aa59a920 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -98,28 +98,32 @@ SRST Enables or disables ACPI Heterogeneous Memory Attribute Table (HMAT) support. The default is off. - ``memory-backend='id'`` + ``memory-backend='id'`` An alternative to legacy ``-mem-path`` and ``mem-prealloc`` options. Allows to use a memory backend as main RAM. For example: :: - -object memory-backend-file,id=pc.ram,size=512M,mem-path=/hugetlbfs,prealloc=on,share=on - -machine memory-backend=pc.ram - -m 512M + + -object memory-backend-file,id=pc.ram,size=512M,mem-path=/hugetlbfs,prealloc=on,share=on + -machine memory-backend=pc.ram + -m 512M Migration compatibility note: - a) as backend id one shall use value of 'default-ram-id', advertised by - machine type (available via ``query-machines`` QMP command), if migration - to/from old QEMU (<5.0) is expected. - b) for machine types 4.0 and older, user shall - use ``x-use-canonical-path-for-ramblock-id=off`` backend option - if migration to/from old QEMU (<5.0) is expected. + + * as backend id one shall use value of 'default-ram-id', advertised by + machine type (available via ``query-machines`` QMP command), if migration + to/from old QEMU (<5.0) is expected. + * for machine types 4.0 and older, user shall + use ``x-use-canonical-path-for-ramblock-id=off`` backend option + if migration to/from old QEMU (<5.0) is expected. + For example: :: - -object memory-backend-ram,id=pc.ram,size=512M,x-use-canonical-path-for-ramblock-id=off - -machine memory-backend=pc.ram - -m 512M + + -object memory-backend-ram,id=pc.ram,size=512M,x-use-canonical-path-for-ramblock-id=off + -machine memory-backend=pc.ram + -m 512M ERST HXCOMM Deprecated by -machine diff --git a/target/arm/cpu.c b/target/arm/cpu.c index 752b15bb79..2866dd7658 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c @@ -201,7 +201,8 @@ static void arm_cpu_reset(DeviceState *dev) env->cp15.cpacr_el1 = deposit64(env->cp15.cpacr_el1, 16, 2, 3); /* with reasonable vector length */ if (cpu_isar_feature(aa64_sve, cpu)) { - env->vfp.zcr_el[1] = MIN(cpu->sve_max_vq - 1, 3); + env->vfp.zcr_el[1] = + aarch64_sve_zcr_get_valid_len(cpu, cpu->sve_default_vq - 1); } /* * Enable TBI0 but not TBI1. @@ -1051,7 +1052,16 @@ static void arm_cpu_initfn(Object *obj) QLIST_INIT(&cpu->pre_el_change_hooks); QLIST_INIT(&cpu->el_change_hooks); -#ifndef CONFIG_USER_ONLY +#ifdef CONFIG_USER_ONLY +# ifdef TARGET_AARCH64 + /* + * The linux kernel defaults to 512-bit vectors, when sve is supported. + * See documentation for /proc/sys/abi/sve_default_vector_length, and + * our corresponding sve-default-vector-length cpu property. + */ + cpu->sve_default_vq = 4; +# endif +#else /* Our inbound IRQ and FIQ lines */ if (kvm_enabled()) { /* VIRQ and VFIQ are unused with KVM but we add them to maintain diff --git a/target/arm/cpu.h b/target/arm/cpu.h index be9a4dceae..9f0a5f84d5 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -1006,6 +1006,11 @@ struct ARMCPU { /* Used to set the maximum vector length the cpu will support. */ uint32_t sve_max_vq; +#ifdef CONFIG_USER_ONLY + /* Used to set the default vector length at process start. */ + uint32_t sve_default_vq; +#endif + /* * In sve_vq_map each set bit is a supported vector length of * (bit-number + 1) * 16 bytes, i.e. each bit number + 1 is the vector diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c index c7a1626bec..c690318a9b 100644 --- a/target/arm/cpu64.c +++ b/target/arm/cpu64.c @@ -559,6 +559,59 @@ static void cpu_arm_set_sve(Object *obj, bool value, Error **errp) cpu->isar.id_aa64pfr0 = t; } +#ifdef CONFIG_USER_ONLY +/* Mirror linux /proc/sys/abi/sve_default_vector_length. */ +static void cpu_arm_set_sve_default_vec_len(Object *obj, Visitor *v, + const char *name, void *opaque, + Error **errp) +{ + ARMCPU *cpu = ARM_CPU(obj); + int32_t default_len, default_vq, remainder; + + if (!visit_type_int32(v, name, &default_len, errp)) { + return; + } + + /* Undocumented, but the kernel allows -1 to indicate "maximum". */ + if (default_len == -1) { + cpu->sve_default_vq = ARM_MAX_VQ; + return; + } + + default_vq = default_len / 16; + remainder = default_len % 16; + + /* + * Note that the 512 max comes from include/uapi/asm/sve_context.h + * and is the maximum architectural width of ZCR_ELx.LEN. + */ + if (remainder || default_vq < 1 || default_vq > 512) { + error_setg(errp, "cannot set sve-default-vector-length"); + if (remainder) { + error_append_hint(errp, "Vector length not a multiple of 16\n"); + } else if (default_vq < 1) { + error_append_hint(errp, "Vector length smaller than 16\n"); + } else { + error_append_hint(errp, "Vector length larger than %d\n", + 512 * 16); + } + return; + } + + cpu->sve_default_vq = default_vq; +} + +static void cpu_arm_get_sve_default_vec_len(Object *obj, Visitor *v, + const char *name, void *opaque, + Error **errp) +{ + ARMCPU *cpu = ARM_CPU(obj); + int32_t value = cpu->sve_default_vq * 16; + + visit_type_int32(v, name, &value, errp); +} +#endif + void aarch64_add_sve_properties(Object *obj) { uint32_t vq; @@ -571,6 +624,13 @@ void aarch64_add_sve_properties(Object *obj) object_property_add(obj, name, "bool", cpu_arm_get_sve_vq, cpu_arm_set_sve_vq, NULL, NULL); } + +#ifdef CONFIG_USER_ONLY + /* Mirror linux /proc/sys/abi/sve_default_vector_length. */ + object_property_add(obj, "sve-default-vector-length", "int32", + cpu_arm_get_sve_default_vec_len, + cpu_arm_set_sve_default_vec_len, NULL, NULL); +#endif } void arm_cpu_pauth_finalize(ARMCPU *cpu, Error **errp) diff --git a/target/arm/gdbstub.c b/target/arm/gdbstub.c index a8fff2a3d0..826601b341 100644 --- a/target/arm/gdbstub.c +++ b/target/arm/gdbstub.c @@ -84,6 +84,10 @@ int arm_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) if (n < 16) { /* Core integer register. */ + if (n == 13 && arm_feature(env, ARM_FEATURE_M)) { + /* M profile SP low bits are always 0 */ + tmp &= ~3; + } env->regs[n] = tmp; return 4; } diff --git a/target/arm/helper.c b/target/arm/helper.c index 0c07ca9837..155d8bf239 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -6457,11 +6457,13 @@ int sve_exception_el(CPUARMState *env, int el) return 0; } -static uint32_t sve_zcr_get_valid_len(ARMCPU *cpu, uint32_t start_len) +uint32_t aarch64_sve_zcr_get_valid_len(ARMCPU *cpu, uint32_t start_len) { uint32_t end_len; - end_len = start_len &= 0xf; + start_len = MIN(start_len, ARM_MAX_VQ - 1); + end_len = start_len; + if (!test_bit(start_len, cpu->sve_vq_map)) { end_len = find_last_bit(cpu->sve_vq_map, start_len); assert(end_len < start_len); @@ -6487,7 +6489,7 @@ uint32_t sve_zcr_len_for_el(CPUARMState *env, int el) zcr_len = MIN(zcr_len, 0xf & (uint32_t)env->vfp.zcr_el[3]); } - return sve_zcr_get_valid_len(cpu, zcr_len); + return aarch64_sve_zcr_get_valid_len(cpu, zcr_len); } static void zcr_write(CPUARMState *env, const ARMCPRegInfo *ri, diff --git a/target/arm/internals.h b/target/arm/internals.h index 11a72013f5..cd2ea8a388 100644 --- a/target/arm/internals.h +++ b/target/arm/internals.h @@ -177,6 +177,16 @@ void arm_translate_init(void); void arm_cpu_synchronize_from_tb(CPUState *cs, const TranslationBlock *tb); #endif /* CONFIG_TCG */ +/** + * aarch64_sve_zcr_get_valid_len: + * @cpu: cpu context + * @start_len: maximum len to consider + * + * Return the maximum supported sve vector length <= @start_len. + * Note that both @start_len and the return value are in units + * of ZCR_ELx.LEN, so the vector bit length is (x + 1) * 128. + */ +uint32_t aarch64_sve_zcr_get_valid_len(ARMCPU *cpu, uint32_t start_len); enum arm_fprounding { FPROUNDING_TIEEVEN, diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c index 7a1e35ab5b..20761c9487 100644 --- a/target/arm/m_helper.c +++ b/target/arm/m_helper.c @@ -1554,6 +1554,7 @@ static void do_v7m_exception_exit(ARMCPU *cpu) qemu_log_mask(CPU_LOG_INT, "...taking UsageFault on existing " "stackframe: NSACR prevents clearing FPU registers\n"); v7m_exception_taken(cpu, excret, true, false); + return; } else if (!cpacr_pass) { armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE, exc_secure); @@ -1561,6 +1562,7 @@ static void do_v7m_exception_exit(ARMCPU *cpu) qemu_log_mask(CPU_LOG_INT, "...taking UsageFault on existing " "stackframe: CPACR prevents clearing FPU registers\n"); v7m_exception_taken(cpu, excret, true, false); + return; } } /* Clear s0..s15, FPSCR and VPR */ @@ -2246,6 +2248,7 @@ void arm_v7m_cpu_do_interrupt(CPUState *cs) env->v7m.sfsr |= R_V7M_SFSR_LSERR_MASK; break; case EXCP_UNALIGNED: + /* Unaligned faults reported by M-profile aware code */ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE, env->v7m.secure); env->v7m.cfsr[env->v7m.secure] |= R_V7M_CFSR_UNALIGNED_MASK; break; @@ -2318,6 +2321,13 @@ void arm_v7m_cpu_do_interrupt(CPUState *cs) } armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_BUS, false); break; + case 0x1: /* Alignment fault reported by generic code */ + qemu_log_mask(CPU_LOG_INT, + "...really UsageFault with UFSR.UNALIGNED\n"); + env->v7m.cfsr[env->v7m.secure] |= R_V7M_CFSR_UNALIGNED_MASK; + armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE, + env->v7m.secure); + break; default: /* * All other FSR values are either MPU faults or "can't happen @@ -2563,13 +2573,13 @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val) if (!env->v7m.secure) { return; } - env->v7m.other_ss_msp = val; + env->v7m.other_ss_msp = val & ~3; return; case 0x89: /* PSP_NS */ if (!env->v7m.secure) { return; } - env->v7m.other_ss_psp = val; + env->v7m.other_ss_psp = val & ~3; return; case 0x8a: /* MSPLIM_NS */ if (!env->v7m.secure) { @@ -2638,6 +2648,8 @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val) limit = is_psp ? env->v7m.psplim[false] : env->v7m.msplim[false]; + val &= ~0x3; + if (val < limit) { raise_exception_ra(env, EXCP_STKOF, 0, 1, GETPC()); } @@ -2660,16 +2672,16 @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val) break; case 8: /* MSP */ if (v7m_using_psp(env)) { - env->v7m.other_sp = val; + env->v7m.other_sp = val & ~3; } else { - env->regs[13] = val; + env->regs[13] = val & ~3; } break; case 9: /* PSP */ if (v7m_using_psp(env)) { - env->regs[13] = val; + env->regs[13] = val & ~3; } else { - env->v7m.other_sp = val; + env->v7m.other_sp = val & ~3; } break; case 10: /* MSPLIM */ diff --git a/target/arm/translate.c b/target/arm/translate.c index 351afa43a2..80c282669f 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -291,6 +291,9 @@ void store_reg(DisasContext *s, int reg, TCGv_i32 var) */ tcg_gen_andi_i32(var, var, s->thumb ? ~1 : ~3); s->base.is_jmp = DISAS_JUMP; + } else if (reg == 13 && arm_dc_feature(s, ARM_FEATURE_M)) { + /* For M-profile SP bits [1:0] are always zero */ + tcg_gen_andi_i32(var, var, ~3); } tcg_gen_mov_i32(cpu_R[reg], var); tcg_temp_free_i32(var); diff --git a/target/i386/cpu.c b/target/i386/cpu.c index edb97ebbbe..34a7ce865b 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -4110,7 +4110,7 @@ static const X86CPUDefinition builtin_x86_defs[] = { * none", but this is just for compatibility while libvirt isn't * adapted to resolve CPU model versions before creating VMs. * See "Runnability guarantee of CPU models" at - * docs/system/deprecated.rst. + * docs/about/deprecated.rst. */ X86CPUVersion default_cpu_version = 1; |