From nobody Wed Feb 11 06:51:11 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; 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; dmarc=fail(p=none dis=none) header.from=univ-grenoble-alpes.fr Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1635167313393219.5509505321238; Mon, 25 Oct 2021 06:08:33 -0700 (PDT) Received: from localhost ([::1]:50614 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1meziK-0006vR-BO for importer@patchew.org; Mon, 25 Oct 2021 09:08:32 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:53266) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mez6F-0006Vh-86; Mon, 25 Oct 2021 08:29:11 -0400 Received: from zm-mta-out-3.u-ga.fr ([152.77.200.56]:43124) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mez69-00087v-P2; Mon, 25 Oct 2021 08:29:10 -0400 Received: from mailhost.u-ga.fr (mailhost2.u-ga.fr [129.88.177.242]) by zm-mta-out-3.u-ga.fr (Postfix) with ESMTP id 6036841AF5; Mon, 25 Oct 2021 14:28:36 +0200 (CEST) Received: from smtps.univ-grenoble-alpes.fr (smtps2.u-ga.fr [152.77.18.2]) by mailhost.u-ga.fr (Postfix) with ESMTP id 477FB60067; Mon, 25 Oct 2021 14:28:36 +0200 (CEST) Received: from palmier.tima.u-ga.fr (35.201.90.79.rev.sfr.net [79.90.201.35]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: petrotf@univ-grenoble-alpes.fr) by smtps.univ-grenoble-alpes.fr (Postfix) with ESMTPSA id 0CE3414005A; Mon, 25 Oct 2021 14:28:36 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=univ-grenoble-alpes.fr; s=2020; t=1635164916; bh=LHXXR6Q50Mnx7d6EjTMhVtLQyiFgFNK/2y3j4fnKcAo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Fros4MempNgsmbyn2ZIDFRdz0qG3hv0Si0iP40SwAZqUeyQ9o3pTqpC1Y58Q5r4YH Td6guK88Gs0djPH0GJq3znvASAJhsOpT7gOwILxRIpogx2+Igumk2+ubdrlDf68tDp +rBdeQyW9kvZF5PpF6eiCrqTZ00sKLfnntqoFKJ65vEI8QGitGF9FdJCaYu8NwSqHe BXl4Ka/IftsQ4fI7OE5QirgqrIkAWNICjVxnuEIjz3kaq0YFJUND2+uBDwsWaaYli7 q4ShF4I52KBYNSHNHBjw+4e0wTaxPnwIxiMk9p7+j0FRrn+VzxOtuuEUecfs0MqiU0 hfxybG3mCPkjg== From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9trot?= To: qemu-devel@nongnu.org, qemu-riscv@nongnu.org Subject: [PATCH v4 17/17] target/riscv: actual functions to realize crs 128-bit insns Date: Mon, 25 Oct 2021 14:28:18 +0200 Message-Id: <20211025122818.168890-18-frederic.petrot@univ-grenoble-alpes.fr> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20211025122818.168890-1-frederic.petrot@univ-grenoble-alpes.fr> References: <20211025122818.168890-1-frederic.petrot@univ-grenoble-alpes.fr> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Greylist: Whitelist-UGA SMTP Authentifie (petrotf@univ-grenoble-alpes.fr) via submission-587 ACL (41) X-Greylist: Whitelist-UGA MAILHOST (SMTP non authentifie) depuis 152.77.18.2 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=152.77.200.56; envelope-from=frederic.petrot@univ-grenoble-alpes.fr; helo=zm-mta-out-3.u-ga.fr X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_MSPIKE_H2=-0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: bin.meng@windriver.com, richard.henderson@linaro.org, alistair.francis@wdc.com, fabien.portas@grenoble-inp.org, palmer@dabbelt.com, =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9trot?= , philmd@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1635167315632100001 The csrs are accessed through function pointers: we add read operations in the table for two 128-bit accesses (writes fallback to the 64-bit version): - misa, as mxl is needed for proper operation, - mstatus, as sd needs to be known also In addition, we also add read and write accesses to the machine and supervisor scratch registers. Signed-off-by: Fr=C3=A9d=C3=A9ric P=C3=A9trot Co-authored-by: Fabien Portas --- target/riscv/cpu.h | 12 +++ target/riscv/cpu_bits.h | 1 + target/riscv/csr.c | 192 +++++++++++++++++++++++++++++++++------- 3 files changed, 172 insertions(+), 33 deletions(-) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 328ba42a30..d1af4a9ba3 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -474,12 +474,24 @@ RISCVException riscv_csrrw_i128(CPURISCVState *env, i= nt csrno, Int128 *ret_value, Int128 new_value, Int128 write_mask); =20 +typedef RISCVException (*riscv_csr_read128_fn)(CPURISCVState *env, int csr= no, + Int128 *ret_value); +typedef RISCVException (*riscv_csr_write128_fn)(CPURISCVState *env, int cs= rno, + Int128 new_value); +typedef RISCVException (*riscv_csr_op128_fn)(CPURISCVState *env, int csrno, + Int128 *ret_value, + Int128 new_value, + Int128 write_mask); + typedef struct { const char *name; riscv_csr_predicate_fn predicate; riscv_csr_read_fn read; riscv_csr_write_fn write; riscv_csr_op_fn op; + riscv_csr_read128_fn read128; + riscv_csr_write128_fn write128; + riscv_csr_op128_fn op128; } riscv_csr_operations; =20 /* CSR function table constants */ diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h index cffcd3a5df..1f8fda2d83 100644 --- a/target/riscv/cpu_bits.h +++ b/target/riscv/cpu_bits.h @@ -360,6 +360,7 @@ =20 #define MSTATUS32_SD 0x80000000 #define MSTATUS64_SD 0x8000000000000000ULL +#define MSTATUSH128_SD 0x8000000000000000ULL =20 #define MISA32_MXL 0xC0000000 #define MISA64_MXL 0xC000000000000000ULL diff --git a/target/riscv/csr.c b/target/riscv/csr.c index 8a791d6b7c..68cf74a92c 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -488,6 +488,8 @@ static uint64_t add_status_sd(RISCVMXL xl, uint64_t sta= tus) return status | MSTATUS32_SD; case MXL_RV64: return status | MSTATUS64_SD; + case MXL_RV128: + return MSTATUSH128_SD; default: g_assert_not_reached(); } @@ -537,10 +539,11 @@ static RISCVException write_mstatus(CPURISCVState *en= v, int csrno, =20 mstatus =3D (mstatus & ~mask) | (val & mask); =20 - if (riscv_cpu_mxl(env) =3D=3D MXL_RV64) { + RISCVMXL xl =3D riscv_cpu_mxl(env); + if (xl > MXL_RV32) { /* SXL and UXL fields are for now read only */ - mstatus =3D set_field(mstatus, MSTATUS64_SXL, MXL_RV64); - mstatus =3D set_field(mstatus, MSTATUS64_UXL, MXL_RV64); + mstatus =3D set_field(mstatus, MSTATUS64_SXL, xl); + mstatus =3D set_field(mstatus, MSTATUS64_UXL, xl); } env->mstatus =3D mstatus; =20 @@ -569,6 +572,20 @@ static RISCVException write_mstatush(CPURISCVState *en= v, int csrno, return RISCV_EXCP_NONE; } =20 +static RISCVException read_mstatus_i128(CPURISCVState *env, int csrno, + Int128 *val) +{ + *val =3D int128_make128(env->mstatus, add_status_sd(riscv_cpu_mxl(env)= , 0)); + return RISCV_EXCP_NONE; +} + +static RISCVException read_misa_i128(CPURISCVState *env, int csrno, + Int128 *val) +{ + *val =3D int128_make128(env->misa_ext, (uint64_t)MXL_RV128 << 62); + return RISCV_EXCP_NONE; +} + static RISCVException read_misa(CPURISCVState *env, int csrno, target_ulong *val) { @@ -726,6 +743,21 @@ static RISCVException write_mcounteren(CPURISCVState *= env, int csrno, } =20 /* Machine Trap Handling */ +static RISCVException read_mscratch_i128(CPURISCVState *env, int csrno, + Int128 *val) +{ + *val =3D int128_make128(env->mscratch, env->mscratchh); + return RISCV_EXCP_NONE; +} + +static RISCVException write_mscratch_i128(CPURISCVState *env, int csrno, + Int128 val) +{ + env->mscratch =3D int128_getlo(val); + env->mscratchh =3D int128_gethi(val); + return RISCV_EXCP_NONE; +} + static RISCVException read_mscratch(CPURISCVState *env, int csrno, target_ulong *val) { @@ -898,6 +930,21 @@ static RISCVException write_scounteren(CPURISCVState *= env, int csrno, } =20 /* Supervisor Trap Handling */ +static RISCVException read_sscratch_i128(CPURISCVState *env, int csrno, + Int128 *val) +{ + *val =3D int128_make128(env->sscratch, env->sscratchh); + return RISCV_EXCP_NONE; +} + +static RISCVException write_sscratch_i128(CPURISCVState *env, int csrno, + Int128 val) +{ + env->sscratch =3D int128_getlo(val); + env->sscratchh =3D int128_gethi(val); + return RISCV_EXCP_NONE; +} + static RISCVException read_sscratch(CPURISCVState *env, int csrno, target_ulong *val) { @@ -1436,18 +1483,15 @@ static RISCVException write_pmpaddr(CPURISCVState *= env, int csrno, * csrrc <-> riscv_csrrw(env, csrno, ret_value, 0, value); */ =20 -RISCVException riscv_csrrw(CPURISCVState *env, int csrno, - target_ulong *ret_value, - target_ulong new_value, target_ulong write_mask) +static inline RISCVException riscv_csrrw_check(CPURISCVState *env, + int csrno, + bool write_mask, + RISCVCPU *cpu) { - RISCVException ret; - target_ulong old_value; - RISCVCPU *cpu =3D env_archcpu(env); - int read_only =3D get_field(csrno, 0xC00) =3D=3D 3; - - /* check privileges and return RISCV_EXCP_ILLEGAL_INST if check fails = */ + /* check privileges and return -1 if check fails */ #if !defined(CONFIG_USER_ONLY) int effective_priv =3D env->priv; + int read_only =3D get_field(csrno, 0xc00) =3D=3D 3; =20 if (riscv_has_ext(env, RVH) && env->priv =3D=3D PRV_S && @@ -1460,13 +1504,11 @@ RISCVException riscv_csrrw(CPURISCVState *env, int = csrno, effective_priv++; } =20 - if (!env->debugger && (effective_priv < get_field(csrno, 0x300))) { + if ((write_mask && read_only) || + (!env->debugger && (effective_priv < get_field(csrno, 0x300)))) { return RISCV_EXCP_ILLEGAL_INST; } #endif - if (write_mask && read_only) { - return RISCV_EXCP_ILLEGAL_INST; - } =20 /* ensure the CSR extension is enabled. */ if (!cpu->cfg.ext_icsr) { @@ -1477,10 +1519,17 @@ RISCVException riscv_csrrw(CPURISCVState *env, int = csrno, if (!csr_ops[csrno].predicate) { return RISCV_EXCP_ILLEGAL_INST; } - ret =3D csr_ops[csrno].predicate(env, csrno); - if (ret !=3D RISCV_EXCP_NONE) { - return ret; - } + + return csr_ops[csrno].predicate(env, csrno); +} + +static RISCVException riscv_csrrw_do64(CPURISCVState *env, int csrno, + target_ulong *ret_value, + target_ulong new_value, + target_ulong write_mask) +{ + RISCVException ret; + target_ulong old_value; =20 /* execute combined read/write operation if it exists */ if (csr_ops[csrno].op) { @@ -1516,20 +1565,93 @@ RISCVException riscv_csrrw(CPURISCVState *env, int = csrno, return RISCV_EXCP_NONE; } =20 +RISCVException riscv_csrrw(CPURISCVState *env, int csrno, + target_ulong *ret_value, + target_ulong new_value, target_ulong write_mask) +{ + RISCVCPU *cpu =3D env_archcpu(env); + + RISCVException ret =3D riscv_csrrw_check(env, csrno, write_mask, cpu); + if (ret !=3D RISCV_EXCP_NONE) { + return ret; + } + + return riscv_csrrw_do64(env, csrno, ret_value, new_value, write_mask); +} + +static RISCVException riscv_csrrw_do128(CPURISCVState *env, int csrno, + Int128 *ret_value, + Int128 new_value, + Int128 write_mask) +{ + RISCVException ret; + Int128 old_value; + + /* execute combined read/write operation if it exists */ + if (csr_ops[csrno].op128) { + return csr_ops[csrno].op128(env, csrno, ret_value, + new_value, write_mask); + } + + /* if no accessor exists then return failure */ + if (!csr_ops[csrno].read128) { + return RISCV_EXCP_ILLEGAL_INST; + } + /* read old value */ + ret =3D csr_ops[csrno].read128(env, csrno, &old_value); + if (ret !=3D RISCV_EXCP_NONE) { + return ret; + } + + /* write value if writable and write mask set, otherwise drop writes */ + if (int128_nz(write_mask)) { + new_value =3D int128_or(int128_and(old_value, int128_not(write_mas= k)), + int128_and(new_value, write_mask)); + if (csr_ops[csrno].write128) { + ret =3D csr_ops[csrno].write128(env, csrno, new_value); + if (ret !=3D RISCV_EXCP_NONE) { + return ret; + } + } + } + + /* return old value */ + if (ret_value) { + *ret_value =3D old_value; + } + + return RISCV_EXCP_NONE; +} + RISCVException riscv_csrrw_i128(CPURISCVState *env, int csrno, - Int128 *ret_value, - Int128 new_value, Int128 write_mask) + Int128 *ret_value, + Int128 new_value, Int128 write_mask) { - /* fall back to 64-bit version for now */ - target_ulong ret_64; - RISCVException ret =3D riscv_csrrw(env, csrno, &ret_64, - int128_getlo(new_value), - int128_getlo(write_mask)); + RISCVException ret; + RISCVCPU *cpu =3D env_archcpu(env); =20 - if (ret_value) { - *ret_value =3D int128_make64(ret_64); + ret =3D riscv_csrrw_check(env, csrno, int128_nz(write_mask), cpu); + if (ret !=3D RISCV_EXCP_NONE) { + return ret; } =20 + if (csr_ops[csrno].read128 || csr_ops[csrno].op128) { + return riscv_csrrw_do128(env, csrno, ret_value, new_value, write_m= ask); + } + + /* + * Fall back to 64-bit version for now, if the 128-bit + * alternative isn't defined. + * Note, some CSRs don't extend to MXLEN, for those, + * this fallback is correctly handling the read/write. + */ + target_ulong old_value; + ret =3D riscv_csrrw_do64(env, csrno, &old_value, + int128_getlo(new_value), + int128_getlo(write_mask)); + if (ret =3D=3D RISCV_EXCP_NONE) { + *ret_value =3D int128_make64(old_value); + } return ret; } =20 @@ -1592,8 +1714,10 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] =3D { [CSR_MHARTID] =3D { "mhartid", any, read_mhartid }, =20 /* Machine Trap Setup */ - [CSR_MSTATUS] =3D { "mstatus", any, read_mstatus, write_m= status }, - [CSR_MISA] =3D { "misa", any, read_misa, write_m= isa }, + [CSR_MSTATUS] =3D { "mstatus", any, read_mstatus, write_m= status, NULL, + read_mstatus_i128 = }, + [CSR_MISA] =3D { "misa", any, read_misa, write_m= isa, NULL, + read_misa_i128 = }, [CSR_MIDELEG] =3D { "mideleg", any, read_mideleg, write_m= ideleg }, [CSR_MEDELEG] =3D { "medeleg", any, read_medeleg, write_m= edeleg }, [CSR_MIE] =3D { "mie", any, read_mie, write_m= ie }, @@ -1603,7 +1727,8 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] =3D { [CSR_MSTATUSH] =3D { "mstatush", any32, read_mstatush, write_m= statush }, =20 /* Machine Trap Handling */ - [CSR_MSCRATCH] =3D { "mscratch", any, read_mscratch, write_mscratch }, + [CSR_MSCRATCH] =3D { "mscratch", any, read_mscratch, write_mscra= tch, NULL, + read_mscratch_i128, write_mscratc= h_i128 }, [CSR_MEPC] =3D { "mepc", any, read_mepc, write_mepc }, [CSR_MCAUSE] =3D { "mcause", any, read_mcause, write_mcause }, [CSR_MTVAL] =3D { "mtval", any, read_mtval, write_mtval }, @@ -1616,7 +1741,8 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] =3D { [CSR_SCOUNTEREN] =3D { "scounteren", smode, read_scounteren, write_sco= unteren }, =20 /* Supervisor Trap Handling */ - [CSR_SSCRATCH] =3D { "sscratch", smode, read_sscratch, write_sscratch = }, + [CSR_SSCRATCH] =3D { "sscratch", smode, read_sscratch, write_sscratch,= NULL, + read_sscratch_i128, write_sscrat= ch_i128 }, [CSR_SEPC] =3D { "sepc", smode, read_sepc, write_sepc = }, [CSR_SCAUSE] =3D { "scause", smode, read_scause, write_scause = }, [CSR_STVAL] =3D { "stval", smode, read_stval, write_stval }, --=20 2.33.0