Commit 5f42c337 authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/alistair/tags/pull-riscv-to-apply-20200702-1' into staging



This PR contains two patches to improve PLIC support in QEMU.

It also contains one patch that fixes CLINT accesses for RISC-V. This
fixes a regression for most RISC-V boards.

The rest of the PR is adding support for the v0.7.1 RISC-V vector
extensions. This is experimental support as the vector extensions are
still in a draft state.

This is a v2 pull request that has fixed the building on big endian
machines failure.

# gpg: Signature made Thu 02 Jul 2020 17:21:54 BST
# gpg:                using RSA key F6C4AC46D4934868D3B8CE8F21E10D29DF977054
# gpg: Good signature from "Alistair Francis <alistair@alistair23.me>" [full]
# Primary key fingerprint: F6C4 AC46 D493 4868 D3B8  CE8F 21E1 0D29 DF97 7054

* remotes/alistair/tags/pull-riscv-to-apply-20200702-1: (64 commits)
  target/riscv: configure and turn on vector extension from command line
  target/riscv: vector compress instruction
  target/riscv: vector register gather instruction
  target/riscv: vector slide instructions
  target/riscv: floating-point scalar move instructions
  target/riscv: integer scalar move instruction
  target/riscv: integer extract instruction
  target/riscv: vector element index instruction
  target/riscv: vector iota instruction
  target/riscv: set-X-first mask bit
  target/riscv: vmfirst find-first-set mask bit
  target/riscv: vector mask population count vmpopc
  target/riscv: vector mask-register logical instructions
  target/riscv: vector widening floating-point reduction instructions
  target/riscv: vector single-width floating-point reduction instructions
  target/riscv: vector wideing integer reduction instructions
  target/riscv: vector single-width integer reduction instructions
  target/riscv: narrowing floating-point/integer type-convert instructions
  target/riscv: widening floating-point/integer type-convert instructions
  target/riscv: vector floating-point/integer type-convert instructions
  ...

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 4abf70a6 6bf91617
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -181,7 +181,7 @@ static const MemoryRegionOps sifive_clint_ops = {
    .endianness = DEVICE_LITTLE_ENDIAN,
    .valid = {
        .min_access_size = 4,
        .max_access_size = 4
        .max_access_size = 8
    }
};

+14 −6
Original line number Diff line number Diff line
@@ -166,6 +166,9 @@ static void sifive_plic_update(SiFivePLICState *plic)
static uint32_t sifive_plic_claim(SiFivePLICState *plic, uint32_t addrid)
{
    int i, j;
    uint32_t max_irq = 0;
    uint32_t max_prio = plic->target_priority[addrid];

    for (i = 0; i < plic->bitfield_words; i++) {
        uint32_t pending_enabled_not_claimed =
            (plic->pending[i] & ~plic->claimed[i]) &
@@ -177,14 +180,18 @@ static uint32_t sifive_plic_claim(SiFivePLICState *plic, uint32_t addrid)
            int irq = (i << 5) + j;
            uint32_t prio = plic->source_priority[irq];
            int enabled = pending_enabled_not_claimed & (1 << j);
            if (enabled && prio > plic->target_priority[addrid]) {
                sifive_plic_set_pending(plic, irq, false);
                sifive_plic_set_claimed(plic, irq, true);
                return irq;
            if (enabled && prio > max_prio) {
                max_irq = irq;
                max_prio = prio;
            }
        }
    }
    return 0;

    if (max_irq) {
        sifive_plic_set_pending(plic, max_irq, false);
        sifive_plic_set_claimed(plic, max_irq, true);
    }
    return max_irq;
}

static uint64_t sifive_plic_read(void *opaque, hwaddr addr, unsigned size)
@@ -248,8 +255,8 @@ static uint64_t sifive_plic_read(void *opaque, hwaddr addr, unsigned size)
                    plic->addr_config[addrid].hartid,
                    mode_to_char(plic->addr_config[addrid].mode),
                    value);
                sifive_plic_print_state(plic);
            }
            sifive_plic_update(plic);
            return value;
        }
    }
@@ -280,6 +287,7 @@ static void sifive_plic_write(void *opaque, hwaddr addr, uint64_t value,
            qemu_log("plic: write priority: irq=%d priority=%d\n",
                irq, plic->source_priority[irq]);
        }
        sifive_plic_update(plic);
        return;
    } else if (addr >= plic->pending_base && /* 1 bit per source */
               addr < plic->pending_base + (plic->num_sources >> 3))
+1 −1
Original line number Diff line number Diff line
obj-y += translate.o op_helper.o cpu_helper.o cpu.o csr.o fpu_helper.o gdbstub.o
obj-y += translate.o op_helper.o cpu_helper.o cpu.o csr.o fpu_helper.o vector_helper.o gdbstub.o
obj-$(CONFIG_SOFTMMU) += pmp.o

ifeq ($(CONFIG_SOFTMMU),y)
+50 −0
Original line number Diff line number Diff line
@@ -106,6 +106,11 @@ static void set_priv_version(CPURISCVState *env, int priv_ver)
    env->priv_ver = priv_ver;
}

static void set_vext_version(CPURISCVState *env, int vext_ver)
{
    env->vext_ver = vext_ver;
}

static void set_feature(CPURISCVState *env, int feature)
{
    env->features |= (1ULL << feature);
@@ -334,6 +339,7 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
    CPURISCVState *env = &cpu->env;
    RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(dev);
    int priv_version = PRIV_VERSION_1_11_0;
    int vext_version = VEXT_VERSION_0_07_1;
    target_ulong target_misa = 0;
    Error *local_err = NULL;

@@ -357,6 +363,7 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
    }

    set_priv_version(env, priv_version);
    set_vext_version(env, vext_version);

    if (cpu->cfg.mmu) {
        set_feature(env, RISCV_FEATURE_MMU);
@@ -423,6 +430,45 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
        if (cpu->cfg.ext_h) {
            target_misa |= RVH;
        }
        if (cpu->cfg.ext_v) {
            target_misa |= RVV;
            if (!is_power_of_2(cpu->cfg.vlen)) {
                error_setg(errp,
                        "Vector extension VLEN must be power of 2");
                return;
            }
            if (cpu->cfg.vlen > RV_VLEN_MAX || cpu->cfg.vlen < 128) {
                error_setg(errp,
                        "Vector extension implementation only supports VLEN "
                        "in the range [128, %d]", RV_VLEN_MAX);
                return;
            }
            if (!is_power_of_2(cpu->cfg.elen)) {
                error_setg(errp,
                        "Vector extension ELEN must be power of 2");
                return;
            }
            if (cpu->cfg.elen > 64 || cpu->cfg.vlen < 8) {
                error_setg(errp,
                        "Vector extension implementation only supports ELEN "
                        "in the range [8, 64]");
                return;
            }
            if (cpu->cfg.vext_spec) {
                if (!g_strcmp0(cpu->cfg.vext_spec, "v0.7.1")) {
                    vext_version = VEXT_VERSION_0_07_1;
                } else {
                    error_setg(errp,
                           "Unsupported vector spec version '%s'",
                           cpu->cfg.vext_spec);
                    return;
                }
            } else {
                qemu_log("vector verison is not specified, "
                        "use the default value v0.7.1\n");
            }
            set_vext_version(env, vext_version);
        }

        set_misa(env, RVXLEN | target_misa);
    }
@@ -462,10 +508,14 @@ static Property riscv_cpu_properties[] = {
    DEFINE_PROP_BOOL("u", RISCVCPU, cfg.ext_u, true),
    /* This is experimental so mark with 'x-' */
    DEFINE_PROP_BOOL("x-h", RISCVCPU, cfg.ext_h, false),
    DEFINE_PROP_BOOL("x-v", RISCVCPU, cfg.ext_v, false),
    DEFINE_PROP_BOOL("Counters", RISCVCPU, cfg.ext_counters, true),
    DEFINE_PROP_BOOL("Zifencei", RISCVCPU, cfg.ext_ifencei, true),
    DEFINE_PROP_BOOL("Zicsr", RISCVCPU, cfg.ext_icsr, true),
    DEFINE_PROP_STRING("priv_spec", RISCVCPU, cfg.priv_spec),
    DEFINE_PROP_STRING("vext_spec", RISCVCPU, cfg.vext_spec),
    DEFINE_PROP_UINT16("vlen", RISCVCPU, cfg.vlen, 128),
    DEFINE_PROP_UINT16("elen", RISCVCPU, cfg.elen, 64),
    DEFINE_PROP_BOOL("mmu", RISCVCPU, cfg.mmu, true),
    DEFINE_PROP_BOOL("pmp", RISCVCPU, cfg.pmp, true),
    DEFINE_PROP_END_OF_LIST(),
+73 −9
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@
#define RISCV_CPU_H

#include "hw/core/cpu.h"
#include "hw/registerfields.h"
#include "exec/cpu-defs.h"
#include "fpu/softfloat-types.h"

@@ -59,6 +60,7 @@
#define RVA RV('A')
#define RVF RV('F')
#define RVD RV('D')
#define RVV RV('V')
#define RVC RV('C')
#define RVS RV('S')
#define RVU RV('U')
@@ -77,6 +79,8 @@ enum {
#define PRIV_VERSION_1_10_0 0x00011000
#define PRIV_VERSION_1_11_0 0x00011100

#define VEXT_VERSION_0_07_1 0x00000701

#define TRANSLATE_PMP_FAIL 2
#define TRANSLATE_FAIL 1
#define TRANSLATE_SUCCESS 0
@@ -88,9 +92,26 @@ typedef struct CPURISCVState CPURISCVState;

#include "pmp.h"

#define RV_VLEN_MAX 256

FIELD(VTYPE, VLMUL, 0, 2)
FIELD(VTYPE, VSEW, 2, 3)
FIELD(VTYPE, VEDIV, 5, 2)
FIELD(VTYPE, RESERVED, 7, sizeof(target_ulong) * 8 - 9)
FIELD(VTYPE, VILL, sizeof(target_ulong) * 8 - 2, 1)

struct CPURISCVState {
    target_ulong gpr[32];
    uint64_t fpr[32]; /* assume both F and D extensions */

    /* vector coprocessor state. */
    uint64_t vreg[32 * RV_VLEN_MAX / 64] QEMU_ALIGNED(16);
    target_ulong vxrm;
    target_ulong vxsat;
    target_ulong vl;
    target_ulong vstart;
    target_ulong vtype;

    target_ulong pc;
    target_ulong load_res;
    target_ulong load_val;
@@ -101,6 +122,7 @@ struct CPURISCVState {
    target_ulong guest_phys_fault_addr;

    target_ulong priv_ver;
    target_ulong vext_ver;
    target_ulong misa;
    target_ulong misa_mask;

@@ -257,12 +279,16 @@ typedef struct RISCVCPU {
        bool ext_s;
        bool ext_u;
        bool ext_h;
        bool ext_v;
        bool ext_counters;
        bool ext_ifencei;
        bool ext_icsr;

        char *priv_spec;
        char *user_spec;
        char *vext_spec;
        uint16_t vlen;
        uint16_t elen;
        bool mmu;
        bool pmp;
    } cfg;
@@ -335,19 +361,62 @@ void riscv_cpu_set_fflags(CPURISCVState *env, target_ulong);
#define TB_FLAGS_MMU_MASK   3
#define TB_FLAGS_MSTATUS_FS MSTATUS_FS

typedef CPURISCVState CPUArchState;
typedef RISCVCPU ArchCPU;
#include "exec/cpu-all.h"

FIELD(TB_FLAGS, VL_EQ_VLMAX, 2, 1)
FIELD(TB_FLAGS, LMUL, 3, 2)
FIELD(TB_FLAGS, SEW, 5, 3)
FIELD(TB_FLAGS, VILL, 8, 1)

/*
 * A simplification for VLMAX
 * = (1 << LMUL) * VLEN / (8 * (1 << SEW))
 * = (VLEN << LMUL) / (8 << SEW)
 * = (VLEN << LMUL) >> (SEW + 3)
 * = VLEN >> (SEW + 3 - LMUL)
 */
static inline uint32_t vext_get_vlmax(RISCVCPU *cpu, target_ulong vtype)
{
    uint8_t sew, lmul;

    sew = FIELD_EX64(vtype, VTYPE, VSEW);
    lmul = FIELD_EX64(vtype, VTYPE, VLMUL);
    return cpu->cfg.vlen >> (sew + 3 - lmul);
}

static inline void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
                                        target_ulong *cs_base, uint32_t *flags)
                                        target_ulong *cs_base, uint32_t *pflags)
{
    uint32_t flags = 0;

    *pc = env->pc;
    *cs_base = 0;

    if (riscv_has_ext(env, RVV)) {
        uint32_t vlmax = vext_get_vlmax(env_archcpu(env), env->vtype);
        bool vl_eq_vlmax = (env->vstart == 0) && (vlmax == env->vl);
        flags = FIELD_DP32(flags, TB_FLAGS, VILL,
                    FIELD_EX64(env->vtype, VTYPE, VILL));
        flags = FIELD_DP32(flags, TB_FLAGS, SEW,
                    FIELD_EX64(env->vtype, VTYPE, VSEW));
        flags = FIELD_DP32(flags, TB_FLAGS, LMUL,
                    FIELD_EX64(env->vtype, VTYPE, VLMUL));
        flags = FIELD_DP32(flags, TB_FLAGS, VL_EQ_VLMAX, vl_eq_vlmax);
    } else {
        flags = FIELD_DP32(flags, TB_FLAGS, VILL, 1);
    }

#ifdef CONFIG_USER_ONLY
    *flags = TB_FLAGS_MSTATUS_FS;
    flags |= TB_FLAGS_MSTATUS_FS;
#else
    *flags = cpu_mmu_index(env, 0);
    flags |= cpu_mmu_index(env, 0);
    if (riscv_cpu_fp_enabled(env)) {
        *flags |= env->mstatus & MSTATUS_FS;
        flags |= env->mstatus & MSTATUS_FS;
    }
#endif
    *pflags = flags;
}

int riscv_csrrw(CPURISCVState *env, int csrno, target_ulong *ret_value,
@@ -388,9 +457,4 @@ void riscv_set_csr_ops(int csrno, riscv_csr_operations *ops);

void riscv_cpu_register_gdb_regs_for_features(CPUState *cs);

typedef CPURISCVState CPUArchState;
typedef RISCVCPU ArchCPU;

#include "exec/cpu-all.h"

#endif /* RISCV_CPU_H */
Loading