From nobody Wed Feb 11 00:56:23 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1648472863123279.64195107948467; Mon, 28 Mar 2022 06:07:43 -0700 (PDT) Received: from localhost ([::1]:48748 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1nYp5x-0003wS-Dw for importer@patchew.org; Mon, 28 Mar 2022 09:07:41 -0400 Received: from eggs.gnu.org ([209.51.188.92]:48538) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1nYox2-0002qB-RE for qemu-devel@nongnu.org; Mon, 28 Mar 2022 08:58:29 -0400 Received: from mail.loongson.cn ([114.242.206.163]:34874 helo=loongson.cn) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1nYowz-0001Qq-ML for qemu-devel@nongnu.org; Mon, 28 Mar 2022 08:58:28 -0400 Received: from localhost.localdomain (unknown [10.2.5.185]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9DxbxPOsEFih08RAA--.17957S10; Mon, 28 Mar 2022 20:58:20 +0800 (CST) From: Xiaojuan Yang To: qemu-devel@nongnu.org Subject: [RFC PATCH v7 08/29] target/loongarch: Add LoongArch IOCSR instruction Date: Mon, 28 Mar 2022 20:57:28 +0800 Message-Id: <20220328125749.2918087-9-yangxiaojuan@loongson.cn> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20220328125749.2918087-1-yangxiaojuan@loongson.cn> References: <20220328125749.2918087-1-yangxiaojuan@loongson.cn> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: AQAAf9DxbxPOsEFih08RAA--.17957S10 X-Coremail-Antispam: 1UD129KBjvJXoW3ZF4kKr4kKF45ur15JF43KFg_yoWDZrW5pr 17Cr1jkrW8G393Aasagw13WFn8Zan7ua17XaySyw1F9w47XF9rZrW8t3sIgFWUJrykXrW8 XF4rA3yjqFW5XaUanT9S1TB71UUUUUUqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnUUvcSsGvfC2KfnxnUUI43ZEXa7xR_UUUUUUUUU== X-CM-SenderInfo: p1dqw5xldry3tdq6z05rqj20fqof0/ Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=114.242.206.163; envelope-from=yangxiaojuan@loongson.cn; helo=loongson.cn X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: mark.cave-ayland@ilande.co.uk, richard.henderson@linaro.org, Song Gao Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZM-MESSAGEID: 1648473767567100001 Content-Type: text/plain; charset="utf-8" This includes: - IOCSR{RD/WR}.{B/H/W/D} Signed-off-by: Xiaojuan Yang Signed-off-by: Song Gao --- target/loongarch/cpu.h | 4 + target/loongarch/disas.c | 8 + target/loongarch/helper.h | 2 + .../insn_trans/trans_privileged.c.inc | 103 +++++++++++++ target/loongarch/insns.decode | 9 ++ target/loongarch/iocsr_helper.c | 139 ++++++++++++++++++ target/loongarch/meson.build | 1 + 7 files changed, 266 insertions(+) create mode 100644 target/loongarch/iocsr_helper.c diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h index f682dd33fe..08af634307 100644 --- a/target/loongarch/cpu.h +++ b/target/loongarch/cpu.h @@ -151,6 +151,7 @@ extern const char * const fregnames[32]; =20 #define N_IRQS 14 #define IRQ_TIMER 11 +#define IRQ_IPI 12 =20 #define LOONGARCH_STLB 2048 /* 2048 STLB */ #define LOONGARCH_MTLB 64 /* 64 MTLB */ @@ -248,6 +249,9 @@ typedef struct CPUArchState { =20 #ifndef CONFIG_USER_ONLY LoongArchTLB tlb[LOONGARCH_TLB_MAX]; + + AddressSpace address_space_iocsr; + MemoryRegion system_iocsr; #endif } CPULoongArchState; =20 diff --git a/target/loongarch/disas.c b/target/loongarch/disas.c index b83022468e..90f469bdc0 100644 --- a/target/loongarch/disas.c +++ b/target/loongarch/disas.c @@ -532,6 +532,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) =20 #define output_fcmp(C, PREFIX, SUFFIX) = \ { = \ diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h index 036dbf31f8..1bcd082858 100644 --- a/target/loongarch/helper.h +++ b/target/loongarch/helper.h @@ -98,4 +98,6 @@ DEF_HELPER_FLAGS_2(set_rounding_mode, TCG_CALL_NO_RWG, vo= id, env, i32) DEF_HELPER_2(csr_rdq, i64, env, i64) DEF_HELPER_3(csr_wrq, i64, env, tl, i64) DEF_HELPER_4(csr_xchgq, i64, env, tl, tl, i64) +DEF_HELPER_3(iocsr_read, i64, env, tl, i32) +DEF_HELPER_4(iocsr_write, void, env, tl, tl, i32) #endif /* !CONFIG_USER_ONLY */ diff --git a/target/loongarch/insn_trans/trans_privileged.c.inc b/target/lo= ongarch/insn_trans/trans_privileged.c.inc index 9354697894..30f1e688e8 100644 --- a/target/loongarch/insn_trans/trans_privileged.c.inc +++ b/target/loongarch/insn_trans/trans_privileged.c.inc @@ -18,6 +18,14 @@ static bool trans_##name(DisasContext *ctx, arg_##name *= a) \ GEN_FALSE_TRANS(csrrd) GEN_FALSE_TRANS(csrwr) GEN_FALSE_TRANS(csrxchg) +GEN_FALSE_TRANS(iocsrrd_b) +GEN_FALSE_TRANS(iocsrrd_h) +GEN_FALSE_TRANS(iocsrrd_w) +GEN_FALSE_TRANS(iocsrrd_d) +GEN_FALSE_TRANS(iocsrwr_b) +GEN_FALSE_TRANS(iocsrwr_h) +GEN_FALSE_TRANS(iocsrwr_w) +GEN_FALSE_TRANS(iocsrwr_d) =20 #else =20 @@ -122,4 +130,99 @@ static bool trans_csrxchg(DisasContext *ctx, arg_csrxc= hg *a) return true; } =20 +static bool trans_iocsrrd_b(DisasContext *ctx, arg_iocsrrd_b *a) +{ + TCGv dest =3D gpr_dst(ctx, a->rd, EXT_NONE); + TCGv src1 =3D gpr_src(ctx, a->rj, EXT_NONE); + + if (check_plv(ctx)) { + return false; + } + gen_helper_iocsr_read(dest, cpu_env, src1, tcg_constant_i32(1)); + return true; +} + +static bool trans_iocsrrd_h(DisasContext *ctx, arg_iocsrrd_h *a) +{ + TCGv dest =3D gpr_dst(ctx, a->rd, EXT_NONE); + TCGv src1 =3D gpr_src(ctx, a->rj, EXT_NONE); + + if (check_plv(ctx)) { + return false; + } + gen_helper_iocsr_read(dest, cpu_env, src1, tcg_constant_i32(2)); + return true; +} + +static bool trans_iocsrrd_w(DisasContext *ctx, arg_iocsrrd_w *a) +{ + TCGv dest =3D gpr_dst(ctx, a->rd, EXT_NONE); + TCGv src1 =3D gpr_src(ctx, a->rj, EXT_NONE); + + if (check_plv(ctx)) { + return false; + } + gen_helper_iocsr_read(dest, cpu_env, src1, tcg_constant_i32(4)); + return true; +} + +static bool trans_iocsrrd_d(DisasContext *ctx, arg_iocsrrd_d *a) +{ + TCGv dest =3D gpr_dst(ctx, a->rd, EXT_NONE); + TCGv src1 =3D gpr_src(ctx, a->rj, EXT_NONE); + + if (check_plv(ctx)) { + return false; + } + gen_helper_iocsr_read(dest, cpu_env, src1, tcg_constant_i32(8)); + return true; +} + +static bool trans_iocsrwr_b(DisasContext *ctx, arg_iocsrwr_b *a) +{ + TCGv val =3D gpr_src(ctx, a->rd, EXT_NONE); + TCGv addr =3D gpr_src(ctx, a->rj, EXT_NONE); + + if (check_plv(ctx)) { + return false; + } + gen_helper_iocsr_write(cpu_env, addr, val, tcg_constant_i32(1)); + return true; +} + +static bool trans_iocsrwr_h(DisasContext *ctx, arg_iocsrwr_h *a) +{ + TCGv val =3D gpr_src(ctx, a->rd, EXT_NONE); + TCGv addr =3D gpr_src(ctx, a->rj, EXT_NONE); + + if (check_plv(ctx)) { + return false; + } + gen_helper_iocsr_write(cpu_env, addr, val, tcg_constant_i32(2)); + return true; +} + +static bool trans_iocsrwr_w(DisasContext *ctx, arg_iocsrwr_w *a) +{ + TCGv val =3D gpr_src(ctx, a->rd, EXT_NONE); + TCGv addr =3D gpr_src(ctx, a->rj, EXT_NONE); + + if (check_plv(ctx)) { + return false; + } + gen_helper_iocsr_write(cpu_env, addr, val, tcg_constant_i32(4)); + return true; +} + +static bool trans_iocsrwr_d(DisasContext *ctx, arg_iocsrwr_d *a) +{ + TCGv val =3D gpr_src(ctx, a->rd, EXT_NONE); + TCGv addr =3D gpr_src(ctx, a->rj, EXT_NONE); + + if (check_plv(ctx)) { + return false; + } + gen_helper_iocsr_write(cpu_env, addr, val, tcg_constant_i32(8)); + return true; +} #endif diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode index 647fcb9def..9a43f288c3 100644 --- a/target/loongarch/insns.decode +++ b/target/loongarch/insns.decode @@ -453,3 +453,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_helpe= r.c new file mode 100644 index 0000000000..72ac3806b6 --- /dev/null +++ b/target/loongarch/iocsr_helper.c @@ -0,0 +1,139 @@ +/* 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 "internals.h" +#include "qemu/host-utils.h" +#include "exec/helper-proto.h" +#include "exec/exec-all.h" +#include "exec/cpu_ldst.h" +#include "hw/irq.h" +#include "cpu-csr.h" +#include "hw/loongarch/loongarch.h" +#include "tcg/tcg-ldst.h" + +uint64_t helper_iocsr_read(CPULoongArchState *env, target_ulong r_addr, + uint32_t size) +{ + int cpuid =3D env_cpu(env)->cpu_index; + CPUState *cs =3D qemu_get_cpu(cpuid); + env =3D cs->env_ptr; + uint64_t ret; + + /* + * Adjust the per core address such as 0x10xx(IPI)/0x18xx(EXTIOI) + */ + if (((r_addr & 0xff00) =3D=3D 0x1000) || ((r_addr & 0xff00) =3D=3D 0x1= 800)) { + r_addr =3D r_addr + ((target_ulong)(cpuid & 0x3) << 8); + } + + switch (size) { + case 1: + ret =3D address_space_ldub(&env->address_space_iocsr, r_addr, + MEMTXATTRS_UNSPECIFIED, NULL); + break; + case 2: + ret =3D address_space_lduw(&env->address_space_iocsr, r_addr, + MEMTXATTRS_UNSPECIFIED, NULL); + break; + case 4: + ret =3D address_space_ldl(&env->address_space_iocsr, r_addr, + MEMTXATTRS_UNSPECIFIED, NULL); + break; + case 8: + ret =3D address_space_ldq(&env->address_space_iocsr, r_addr, + MEMTXATTRS_UNSPECIFIED, NULL); + break; + default: + break; + } + + return ret; +} + +void helper_iocsr_write(CPULoongArchState *env, target_ulong w_addr, + target_ulong val, uint32_t size) +{ + int cpuid =3D env_cpu(env)->cpu_index; + CPUState *cs =3D qemu_get_cpu(cpuid); + int mask, i; + env =3D cs->env_ptr; + + /* + * For IPI send, Mailbox send and ANY send, adjust the addr and + * val accordingly. The IOCSR writes are turned to different + * MMIO writes respectively + */ + switch (w_addr) { + case 0x1040: /* IPI send */ + cpuid =3D (val >> 16) & 0x3ff; + val =3D 1UL << (val & 0x1f); + if (val) { + qemu_mutex_lock_iothread(); + cs =3D qemu_get_cpu(cpuid); + env =3D cs->env_ptr; + env->CSR_ESTAT |=3D 1 << IRQ_IPI; + cpu_interrupt(cs, CPU_INTERRUPT_HARD); + qemu_mutex_unlock_iothread(); + } + break; + case 0x1048: /* Mail Send */ + cpuid =3D (val >> 16) & 0x3ff; + w_addr =3D 0x1020 + (val & 0x1c); + val =3D val >> 32; + mask =3D (val >> 27) & 0xf; + size =3D 4; + env =3D (qemu_get_cpu(cpuid))->env_ptr; + break; + case 0x1158: /* ANY send */ + cpuid =3D (val >> 16) & 0x3ff; + w_addr =3D val & 0xffff; + val =3D val >> 32; + mask =3D (val >> 27) & 0xf; + size =3D 1; + env =3D (qemu_get_cpu(cpuid))->env_ptr; + + for (i =3D 0; i < 4; i++) { + if (!((mask >> i) & 1)) { + address_space_stb(&env->address_space_iocsr, w_addr, + val, MEMTXATTRS_UNSPECIFIED, NULL); + } + w_addr =3D w_addr + 1; + val =3D val >> 8; + } + return; + default: + break; + } + + if (((w_addr & 0xff00) =3D=3D 0x1000) || ((w_addr & 0xff00) =3D=3D 0x1= 800)) { + w_addr =3D w_addr + ((target_ulong)(cpuid & 0x3) << 8); + } + + switch (size) { + case 1: + address_space_stb(&env->address_space_iocsr, w_addr, + val, MEMTXATTRS_UNSPECIFIED, NULL); + break; + case 2: + address_space_stw(&env->address_space_iocsr, w_addr, + val, MEMTXATTRS_UNSPECIFIED, NULL); + break; + case 4: + address_space_stl(&env->address_space_iocsr, w_addr, + val, MEMTXATTRS_UNSPECIFIED, NULL); + break; + case 8: + address_space_stq(&env->address_space_iocsr, w_addr, + val, MEMTXATTRS_UNSPECIFIED, NULL); + break; + default: + break; + } +} diff --git a/target/loongarch/meson.build b/target/loongarch/meson.build index 5fb7542e88..072684ca6d 100644 --- a/target/loongarch/meson.build +++ b/target/loongarch/meson.build @@ -20,6 +20,7 @@ loongarch_softmmu_ss.add(files( 'constant_timer.c', 'tlb_helper.c', 'csr_helper.c', + 'iocsr_helper.c', )) =20 loongarch_ss.add_all(when: 'CONFIG_TCG', if_true: [loongarch_tcg_ss]) --=20 2.31.1