Commit 6e553f2a authored by Richard Henderson's avatar Richard Henderson Committed by Peter Maydell
Browse files

target/arm: Merge arm_cpu_vq_map_next_smaller into sole caller



Coverity reports, in sve_zcr_get_valid_len,

"Subtract operation overflows on operands
arm_cpu_vq_map_next_smaller(cpu, start_vq + 1U) and 1U"

First, the aarch32 stub version of arm_cpu_vq_map_next_smaller,
returning 0, does exactly what Coverity reports.  Remove it.

Second, the aarch64 version of arm_cpu_vq_map_next_smaller has
a set of asserts, but they don't cover the case in question.
Further, there is a fair amount of extra arithmetic needed to
convert from the 0-based zcr register, to the 1-base vq form,
to the 0-based bitmap, and back again.  This can be simplified
by leaving the value in the 0-based form.

Finally, use test_bit to simplify the common case, where the
length in the zcr registers is in fact a supported length.

Reported-by: Coverity (CID 1407217)
Signed-off-by: default avatarRichard Henderson <richard.henderson@linaro.org>
Reviewed-by: default avatarAndrew Jones <drjones@redhat.com>
Message-id: 20191118091414.19440-1-richard.henderson@linaro.org
Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parent 83ad9595
Loading
Loading
Loading
Loading
+0 −3
Original line number Diff line number Diff line
@@ -185,12 +185,9 @@ typedef struct {
#ifdef TARGET_AARCH64
# define ARM_MAX_VQ    16
void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp);
uint32_t arm_cpu_vq_map_next_smaller(ARMCPU *cpu, uint32_t vq);
#else
# define ARM_MAX_VQ    1
static inline void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp) { }
static inline uint32_t arm_cpu_vq_map_next_smaller(ARMCPU *cpu, uint32_t vq)
{ return 0; }
#endif

typedef struct ARMVectorReg {
+0 −15
Original line number Diff line number Diff line
@@ -458,21 +458,6 @@ void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp)
    cpu->sve_max_vq = max_vq;
}

uint32_t arm_cpu_vq_map_next_smaller(ARMCPU *cpu, uint32_t vq)
{
    uint32_t bitnum;

    /*
     * We allow vq == ARM_MAX_VQ + 1 to be input because the caller may want
     * to find the maximum vq enabled, which may be ARM_MAX_VQ, but this
     * function always returns the next smaller than the input.
     */
    assert(vq && vq <= ARM_MAX_VQ + 1);

    bitnum = find_last_bit(cpu->sve_vq_map, vq - 1);
    return bitnum == vq - 1 ? 0 : bitnum + 1;
}

static void cpu_max_get_sve_max_vq(Object *obj, Visitor *v, const char *name,
                                   void *opaque, Error **errp)
{
+7 −2
Original line number Diff line number Diff line
@@ -5363,9 +5363,14 @@ int sve_exception_el(CPUARMState *env, int el)

static uint32_t sve_zcr_get_valid_len(ARMCPU *cpu, uint32_t start_len)
{
    uint32_t start_vq = (start_len & 0xf) + 1;
    uint32_t end_len;

    return arm_cpu_vq_map_next_smaller(cpu, start_vq + 1) - 1;
    end_len = start_len &= 0xf;
    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);
    }
    return end_len;
}

/*