diff options
author | Xiaojuan Yang <yangxiaojuan@loongson.cn> | 2022-06-06 20:43:16 +0800 |
---|---|---|
committer | Richard Henderson <richard.henderson@linaro.org> | 2022-06-06 18:09:03 +0000 |
commit | f84a2aacf5d1679b1d1cceabb6006e02864232f3 (patch) | |
tree | 7ab99d30271e045fd93932c599aa8d6901aa54ae /target | |
parent | 5b1dedfe848b61521aa5b46b81a4cc676e9e7c1b (diff) | |
download | qemu-f84a2aacf5d1679b1d1cceabb6006e02864232f3.zip qemu-f84a2aacf5d1679b1d1cceabb6006e02864232f3.tar.gz qemu-f84a2aacf5d1679b1d1cceabb6006e02864232f3.tar.bz2 |
target/loongarch: Add LoongArch IOCSR instruction
This includes:
- IOCSR{RD/WR}.{B/H/W/D}
Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn>
Signed-off-by: Song Gao <gaosong@loongson.cn>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-Id: <20220606124333.2060567-27-yangxiaojuan@loongson.cn>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Diffstat (limited to 'target')
-rw-r--r-- | target/loongarch/cpu.c | 44 | ||||
-rw-r--r-- | target/loongarch/cpu.h | 25 | ||||
-rw-r--r-- | target/loongarch/disas.c | 8 | ||||
-rw-r--r-- | target/loongarch/helper.h | 8 | ||||
-rw-r--r-- | target/loongarch/insn_trans/trans_privileged.c.inc | 35 | ||||
-rw-r--r-- | target/loongarch/insns.decode | 9 | ||||
-rw-r--r-- | target/loongarch/iocsr_helper.c | 67 | ||||
-rw-r--r-- | target/loongarch/meson.build | 1 |
8 files changed, 197 insertions, 0 deletions
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c index 5ec0ba1..b846bd1 100644 --- a/target/loongarch/cpu.c +++ b/target/loongarch/cpu.c @@ -17,6 +17,8 @@ #include "internals.h" #include "fpu/softfloat-helpers.h" #include "cpu-csr.h" +#include "sysemu/reset.h" +#include "hw/loader.h" const char * const regnames[32] = { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", @@ -489,14 +491,56 @@ static void loongarch_cpu_realizefn(DeviceState *dev, Error **errp) lacc->parent_realize(dev, errp); } +static void loongarch_qemu_write(void *opaque, hwaddr addr, + uint64_t val, unsigned size) +{ +} + +static uint64_t loongarch_qemu_read(void *opaque, hwaddr addr, unsigned size) +{ + switch (addr) { + case FEATURE_REG: + return 1ULL << IOCSRF_MSI | 1ULL << IOCSRF_EXTIOI | + 1ULL << IOCSRF_CSRIPI; + case VENDOR_REG: + return 0x6e6f73676e6f6f4cULL; /* "Loongson" */ + case CPUNAME_REG: + return 0x303030354133ULL; /* "3A5000" */ + case MISC_FUNC_REG: + return 1ULL << IOCSRM_EXTIOI_EN; + } + return 0ULL; +} + +static const MemoryRegionOps loongarch_qemu_ops = { + .read = loongarch_qemu_read, + .write = loongarch_qemu_write, + .endianness = DEVICE_LITTLE_ENDIAN, + .valid = { + .min_access_size = 4, + .max_access_size = 8, + }, + .impl = { + .min_access_size = 8, + .max_access_size = 8, + }, +}; + static void loongarch_cpu_init(Object *obj) { LoongArchCPU *cpu = LOONGARCH_CPU(obj); + CPULoongArchState *env = &cpu->env; cpu_set_cpustate_pointers(cpu); qdev_init_gpio_in(DEVICE(cpu), loongarch_cpu_set_irq, N_IRQS); timer_init_ns(&cpu->timer, QEMU_CLOCK_VIRTUAL, &loongarch_constant_timer_cb, cpu); + memory_region_init_io(&env->system_iocsr, OBJECT(cpu), NULL, + env, "iocsr", UINT64_MAX); + address_space_init(&env->address_space_iocsr, &env->system_iocsr, "IOCSR"); + memory_region_init_io(&env->iocsr_mem, OBJECT(cpu), &loongarch_qemu_ops, + NULL, "iocsr_misc", 0x428); + memory_region_add_subregion(&env->system_iocsr, 0, &env->iocsr_mem); } static ObjectClass *loongarch_cpu_class_by_name(const char *cpu_model) diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h index 2081902..03cc96e 100644 --- a/target/loongarch/cpu.h +++ b/target/loongarch/cpu.h @@ -12,6 +12,27 @@ #include "fpu/softfloat-types.h" #include "hw/registerfields.h" #include "qemu/timer.h" +#include "exec/memory.h" +#include "hw/sysbus.h" + +#define IOCSRF_TEMP 0 +#define IOCSRF_NODECNT 1 +#define IOCSRF_MSI 2 +#define IOCSRF_EXTIOI 3 +#define IOCSRF_CSRIPI 4 +#define IOCSRF_FREQCSR 5 +#define IOCSRF_FREQSCALE 6 +#define IOCSRF_DVFSV1 7 +#define IOCSRF_GMOD 9 +#define IOCSRF_VM 11 + +#define FEATURE_REG 0x8 +#define VENDOR_REG 0x10 +#define CPUNAME_REG 0x20 +#define MISC_FUNC_REG 0x420 +#define IOCSRM_EXTIOI_EN 48 + +#define IOCSR_MEM_SIZE 0x428 #define TCG_GUEST_DEFAULT_MO (0) @@ -283,6 +304,10 @@ typedef struct CPUArchState { uint64_t CSR_DSAVE; LoongArchTLB tlb[LOONGARCH_TLB_MAX]; + + AddressSpace address_space_iocsr; + MemoryRegion system_iocsr; + MemoryRegion iocsr_mem; } CPULoongArchState; /** diff --git a/target/loongarch/disas.c b/target/loongarch/disas.c index 11a704f..ea26aea 100644 --- a/target/loongarch/disas.c +++ b/target/loongarch/disas.c @@ -615,6 +615,14 @@ INSN(bgeu, rr_offs) INSN(csrrd, r_csr) INSN(csrwr, r_csr) INSN(csrxchg, rr_csr) +INSN(iocsrrd_b, rr) +INSN(iocsrrd_h, rr) +INSN(iocsrrd_w, rr) +INSN(iocsrrd_d, rr) +INSN(iocsrwr_b, rr) +INSN(iocsrwr_h, rr) +INSN(iocsrwr_w, rr) +INSN(iocsrwr_d, rr) #define output_fcmp(C, PREFIX, SUFFIX) \ { \ diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h index 5a6754e..4664a02 100644 --- a/target/loongarch/helper.h +++ b/target/loongarch/helper.h @@ -100,3 +100,11 @@ DEF_HELPER_2(csrwr_estat, i64, env, tl) DEF_HELPER_2(csrwr_asid, i64, env, tl) DEF_HELPER_2(csrwr_tcfg, i64, env, tl) DEF_HELPER_2(csrwr_ticlr, i64, env, tl) +DEF_HELPER_2(iocsrrd_b, i64, env, tl) +DEF_HELPER_2(iocsrrd_h, i64, env, tl) +DEF_HELPER_2(iocsrrd_w, i64, env, tl) +DEF_HELPER_2(iocsrrd_d, i64, env, tl) +DEF_HELPER_3(iocsrwr_b, void, env, tl, tl) +DEF_HELPER_3(iocsrwr_h, void, env, tl, tl) +DEF_HELPER_3(iocsrwr_w, void, env, tl, tl) +DEF_HELPER_3(iocsrwr_d, void, env, tl, tl) diff --git a/target/loongarch/insn_trans/trans_privileged.c.inc b/target/loongarch/insn_trans/trans_privileged.c.inc index f984e3f..3e50cd3 100644 --- a/target/loongarch/insn_trans/trans_privileged.c.inc +++ b/target/loongarch/insn_trans/trans_privileged.c.inc @@ -262,3 +262,38 @@ static bool trans_csrxchg(DisasContext *ctx, arg_csrxchg *a) tcg_temp_free(oldv); return true; } + +static bool gen_iocsrrd(DisasContext *ctx, arg_rr *a, + void (*func)(TCGv, TCGv_ptr, TCGv)) +{ + TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE); + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); + + if (check_plv(ctx)) { + return false; + } + func(dest, cpu_env, src1); + return true; +} + +static bool gen_iocsrwr(DisasContext *ctx, arg_rr *a, + void (*func)(TCGv_ptr, TCGv, TCGv)) +{ + TCGv val = gpr_src(ctx, a->rd, EXT_NONE); + TCGv addr = gpr_src(ctx, a->rj, EXT_NONE); + + if (check_plv(ctx)) { + return false; + } + func(cpu_env, addr, val); + return true; +} + +TRANS(iocsrrd_b, gen_iocsrrd, gen_helper_iocsrrd_b) +TRANS(iocsrrd_h, gen_iocsrrd, gen_helper_iocsrrd_h) +TRANS(iocsrrd_w, gen_iocsrrd, gen_helper_iocsrrd_w) +TRANS(iocsrrd_d, gen_iocsrrd, gen_helper_iocsrrd_d) +TRANS(iocsrwr_b, gen_iocsrwr, gen_helper_iocsrwr_b) +TRANS(iocsrwr_h, gen_iocsrwr, gen_helper_iocsrwr_h) +TRANS(iocsrwr_w, gen_iocsrwr, gen_helper_iocsrwr_w) +TRANS(iocsrwr_d, gen_iocsrwr, gen_helper_iocsrwr_d) diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode index 43005ca..2b436d3 100644 --- a/target/loongarch/insns.decode +++ b/target/loongarch/insns.decode @@ -450,3 +450,12 @@ bgeu 0110 11 ................ ..... ..... @rr_offs16 csrwr 0000 0100 .............. 00001 ..... @r_csr csrxchg 0000 0100 .............. ..... ..... @rr_csr } + +iocsrrd_b 0000 01100100 10000 00000 ..... ..... @rr +iocsrrd_h 0000 01100100 10000 00001 ..... ..... @rr +iocsrrd_w 0000 01100100 10000 00010 ..... ..... @rr +iocsrrd_d 0000 01100100 10000 00011 ..... ..... @rr +iocsrwr_b 0000 01100100 10000 00100 ..... ..... @rr +iocsrwr_h 0000 01100100 10000 00101 ..... ..... @rr +iocsrwr_w 0000 01100100 10000 00110 ..... ..... @rr +iocsrwr_d 0000 01100100 10000 00111 ..... ..... @rr diff --git a/target/loongarch/iocsr_helper.c b/target/loongarch/iocsr_helper.c new file mode 100644 index 0000000..0e9c537 --- /dev/null +++ b/target/loongarch/iocsr_helper.c @@ -0,0 +1,67 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (c) 2021 Loongson Technology Corporation Limited + * + * Helpers for IOCSR reads/writes + */ + +#include "qemu/osdep.h" +#include "qemu/main-loop.h" +#include "cpu.h" +#include "qemu/host-utils.h" +#include "exec/helper-proto.h" +#include "exec/exec-all.h" +#include "exec/cpu_ldst.h" +#include "tcg/tcg-ldst.h" + +uint64_t helper_iocsrrd_b(CPULoongArchState *env, target_ulong r_addr) +{ + return address_space_ldub(&env->address_space_iocsr, r_addr, + MEMTXATTRS_UNSPECIFIED, NULL); +} + +uint64_t helper_iocsrrd_h(CPULoongArchState *env, target_ulong r_addr) +{ + return address_space_lduw(&env->address_space_iocsr, r_addr, + MEMTXATTRS_UNSPECIFIED, NULL); +} + +uint64_t helper_iocsrrd_w(CPULoongArchState *env, target_ulong r_addr) +{ + return address_space_ldl(&env->address_space_iocsr, r_addr, + MEMTXATTRS_UNSPECIFIED, NULL); +} + +uint64_t helper_iocsrrd_d(CPULoongArchState *env, target_ulong r_addr) +{ + return address_space_ldq(&env->address_space_iocsr, r_addr, + MEMTXATTRS_UNSPECIFIED, NULL); +} + +void helper_iocsrwr_b(CPULoongArchState *env, target_ulong w_addr, + target_ulong val) +{ + address_space_stb(&env->address_space_iocsr, w_addr, + val, MEMTXATTRS_UNSPECIFIED, NULL); +} + +void helper_iocsrwr_h(CPULoongArchState *env, target_ulong w_addr, + target_ulong val) +{ + address_space_stw(&env->address_space_iocsr, w_addr, + val, MEMTXATTRS_UNSPECIFIED, NULL); +} + +void helper_iocsrwr_w(CPULoongArchState *env, target_ulong w_addr, + target_ulong val) +{ + address_space_stl(&env->address_space_iocsr, w_addr, + val, MEMTXATTRS_UNSPECIFIED, NULL); +} + +void helper_iocsrwr_d(CPULoongArchState *env, target_ulong w_addr, + target_ulong val) +{ + address_space_stq(&env->address_space_iocsr, w_addr, + val, MEMTXATTRS_UNSPECIFIED, NULL); +} diff --git a/target/loongarch/meson.build b/target/loongarch/meson.build index d11829a..74e5f3b 100644 --- a/target/loongarch/meson.build +++ b/target/loongarch/meson.build @@ -20,6 +20,7 @@ loongarch_softmmu_ss.add(files( 'tlb_helper.c', 'constant_timer.c', 'csr_helper.c', + 'iocsr_helper.c', )) loongarch_ss.add_all(when: 'CONFIG_TCG', if_true: [loongarch_tcg_ss]) |