From nobody Wed Feb 11 01:43:31 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; 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 1633557660340361.6661514510588; Wed, 6 Oct 2021 15:01:00 -0700 (PDT) Received: from localhost ([::1]:33636 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mYEyB-0006Yr-5g for importer@patchew.org; Wed, 06 Oct 2021 18:00:59 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:49874) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mYEUd-0000Kx-JR; Wed, 06 Oct 2021 17:30:31 -0400 Received: from zm-mta-out-3.u-ga.fr ([152.77.200.56]:44136) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mYEUZ-0008SF-9z; Wed, 06 Oct 2021 17:30:26 -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 7398841F28; Wed, 6 Oct 2021 23:29:47 +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 5DA0560066; Wed, 6 Oct 2021 23:29:47 +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 26D3314005C; Wed, 6 Oct 2021 23:29:47 +0200 (CEST) From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9trot?= To: qemu-devel@nongnu.org, qemu-riscv@nongnu.org Subject: [PATCH v2 27/27] target/riscv: support for 128-bit satp Date: Wed, 6 Oct 2021 23:28:33 +0200 Message-Id: <20211006212833.108706-28-frederic.petrot@univ-grenoble-alpes.fr> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20211006212833.108706-1-frederic.petrot@univ-grenoble-alpes.fr> References: <20211006212833.108706-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: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, 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-ZM-MESSAGEID: 1633557661746100001 Support for a 128-bit satp. This is a bit more involved than necessary because we took the opportunity to increase the page size to 16kB, and change the page table geometry, which makes the page walk a bit more parametrizable (variables instead of defines). Note that is anyway a necessary step for the merging of the 32-bit and 64-bit riscv versions in a single executable. Signed-off-by: Fr=C3=A9d=C3=A9ric P=C3=A9trot Co-authored-by: Fabien Portas --- target/riscv/cpu-param.h | 9 ++++- target/riscv/cpu_bits.h | 10 +++++ target/riscv/cpu_helper.c | 54 +++++++++++++++++++-------- target/riscv/csr.c | 77 +++++++++++++++++++++++++++++++++++++-- 4 files changed, 130 insertions(+), 20 deletions(-) diff --git a/target/riscv/cpu-param.h b/target/riscv/cpu-param.h index c10459b56f..78f0916403 100644 --- a/target/riscv/cpu-param.h +++ b/target/riscv/cpu-param.h @@ -19,10 +19,15 @@ #else /* 64-bit target, since QEMU isn't built to have TARGET_LONG_BITS over 64 = */ # define TARGET_LONG_BITS 64 -# define TARGET_PHYS_ADDR_SPACE_BITS 56 /* 44-bit PPN */ -# define TARGET_VIRT_ADDR_SPACE_BITS 48 /* sv48 */ +# define TARGET_PHYS_ADDR_SPACE_BITS 64 /* 54-bit PPN */ +# define TARGET_VIRT_ADDR_SPACE_BITS 44 /* sv44 */ #endif + +#if defined(TARGET_RISCV32) || defined(TARGET_RISCV64) #define TARGET_PAGE_BITS 12 /* 4 KiB Pages */ +#else +#define TARGET_PAGE_BITS 14 /* 16 KiB pages for RV128 */ +#endif /* * The current MMU Modes are: * - U mode 0b000 diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h index 553b0a3d71..a4f6ba927f 100644 --- a/target/riscv/cpu_bits.h +++ b/target/riscv/cpu_bits.h @@ -428,6 +428,11 @@ #define SATP64_ASID 0x0FFFF00000000000ULL #define SATP64_PPN 0x00000FFFFFFFFFFFULL =20 +/* RV128 satp CSR field masks (H/L for high/low dword) */ +#define SATP128_HMODE 0xFF00000000000000ULL +#define SATP128_HASID 0x00FFFFFFFF000000ULL +#define SATP128_LPPN 0x0003FFFFFFFFFFFFULL + /* VM modes (mstatus.vm) privileged ISA 1.9.1 */ #define VM_1_09_MBARE 0 #define VM_1_09_MBB 1 @@ -443,6 +448,9 @@ #define VM_1_10_SV48 9 #define VM_1_10_SV57 10 #define VM_1_10_SV64 11 +#define VM_1_10_SV44 12 +#define VM_1_10_SV54 13 + =20 /* Page table entry (PTE) fields */ #define PTE_V 0x001 /* Valid */ @@ -460,6 +468,8 @@ =20 /* Leaf page shift amount */ #define PGSHIFT 12 +/* For now, pages in RV128 are 16 KiB. */ +#define PGSHIFT128 14 =20 /* Default Reset Vector adress */ #define DEFAULT_RSTVEC 0x1000 diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index d41d5cd27c..55dea1f58b 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -391,7 +391,7 @@ static int get_physical_address(CPURISCVState *env, hwa= ddr *physical, *prot =3D 0; =20 hwaddr base; - int levels, ptidxbits, ptesize, vm, sum, mxr, widened; + int levels, ptidxbits, ptesize, vm, sum, mxr, widened, pgshift; =20 if (first_stage =3D=3D true) { mxr =3D get_field(env->mstatus, MSTATUS_MXR); @@ -404,17 +404,25 @@ static int get_physical_address(CPURISCVState *env, h= waddr *physical, if (riscv_cpu_is_32bit(env)) { base =3D (hwaddr)get_field(env->vsatp, SATP32_PPN) << PGSH= IFT; vm =3D get_field(env->vsatp, SATP32_MODE); - } else { + } else if (riscv_cpu_is_64bit(env)) { base =3D (hwaddr)get_field(env->vsatp, SATP64_PPN) << PGSH= IFT; vm =3D get_field(env->vsatp, SATP64_MODE); + } else { + /* TODO : Hypervisor extension not supported yet in RV128.= */ + g_assert_not_reached(); } } else { if (riscv_cpu_is_32bit(env)) { base =3D (hwaddr)get_field(env->satp, SATP32_PPN) << PGSHI= FT; vm =3D get_field(env->satp, SATP32_MODE); - } else { + } else if (riscv_cpu_is_64bit(env)) { base =3D (hwaddr)get_field(env->satp, SATP64_PPN) << PGSHI= FT; vm =3D get_field(env->satp, SATP64_MODE); + } else if (riscv_cpu_is_128bit(env)) { + base =3D (hwaddr)get_field(env->satp, SATP128_LPPN) << PGS= HIFT128; + vm =3D get_field(env->satph, SATP128_HMODE); + } else { + g_assert_not_reached(); } } widened =3D 0; @@ -422,9 +430,15 @@ static int get_physical_address(CPURISCVState *env, hw= addr *physical, if (riscv_cpu_is_32bit(env)) { base =3D (hwaddr)get_field(env->hgatp, SATP32_PPN) << PGSHIFT; vm =3D get_field(env->hgatp, SATP32_MODE); - } else { + } else if (riscv_cpu_is_64bit(env)) { base =3D (hwaddr)get_field(env->hgatp, SATP64_PPN) << PGSHIFT; vm =3D get_field(env->hgatp, SATP64_MODE); + } else { + /* + * TODO : Hypervisor extension not supported yet in RV128, + * so there shouldn't be any two-stage address lookups. + */ + g_assert_not_reached(); } widened =3D 2; } @@ -432,13 +446,17 @@ static int get_physical_address(CPURISCVState *env, h= waddr *physical, sum =3D get_field(env->mstatus, MSTATUS_SUM) || use_background || is_d= ebug; switch (vm) { case VM_1_10_SV32: - levels =3D 2; ptidxbits =3D 10; ptesize =3D 4; break; + levels =3D 2; ptidxbits =3D 10; ptesize =3D 4; pgshift =3D 12; break; case VM_1_10_SV39: - levels =3D 3; ptidxbits =3D 9; ptesize =3D 8; break; + levels =3D 3; ptidxbits =3D 9; ptesize =3D 8; pgshift =3D 12; break; case VM_1_10_SV48: - levels =3D 4; ptidxbits =3D 9; ptesize =3D 8; break; + levels =3D 4; ptidxbits =3D 9; ptesize =3D 8; pgshift =3D 12; break; case VM_1_10_SV57: - levels =3D 5; ptidxbits =3D 9; ptesize =3D 8; break; + levels =3D 5; ptidxbits =3D 9; ptesize =3D 8; pgshift =3D 12; break; + case VM_1_10_SV44: + levels =3D 3; ptidxbits =3D 10; ptesize =3D 16; pgshift =3D 14; brea= k; + case VM_1_10_SV54: + levels =3D 4; ptidxbits =3D 10; ptesize =3D 16; pgshift =3D 14; bre= ak; case VM_1_10_MBARE: *physical =3D addr; *prot =3D PAGE_READ | PAGE_WRITE | PAGE_EXEC; @@ -448,7 +466,7 @@ static int get_physical_address(CPURISCVState *env, hwa= ddr *physical, } =20 CPUState *cs =3D env_cpu(env); - int va_bits =3D PGSHIFT + levels * ptidxbits + widened; + int va_bits =3D pgshift + levels * ptidxbits + widened; target_ulong mask, masked_msbs; =20 if (TARGET_LONG_BITS > (va_bits - 1)) { @@ -463,6 +481,7 @@ static int get_physical_address(CPURISCVState *env, hwa= ddr *physical, } =20 int ptshift =3D (levels - 1) * ptidxbits; + uint64_t pgoff_mask =3D (1ULL << pgshift) - 1; int i; =20 #if !TCG_OVERSIZED_GUEST @@ -471,10 +490,10 @@ restart: for (i =3D 0; i < levels; i++, ptshift -=3D ptidxbits) { target_ulong idx; if (i =3D=3D 0) { - idx =3D (addr >> (PGSHIFT + ptshift)) & + idx =3D (addr >> (pgshift + ptshift)) & ((1 << (ptidxbits + widened)) - 1); } else { - idx =3D (addr >> (PGSHIFT + ptshift)) & + idx =3D (addr >> (pgshift + ptshift)) & ((1 << ptidxbits) - 1); } =20 @@ -482,6 +501,7 @@ restart: hwaddr pte_addr; =20 if (two_stage && first_stage) { + /* TODO : Two-stage translation for RV128 */ int vbase_prot; hwaddr vbase; =20 @@ -515,6 +535,10 @@ restart: if (riscv_cpu_is_32bit(env)) { pte =3D address_space_ldl(cs->as, pte_addr, attrs, &res); } else { + /* + * For RV128, load only lower 64 bits as only those + * are used for now + */ pte =3D address_space_ldq(cs->as, pte_addr, attrs, &res); } =20 @@ -529,7 +553,7 @@ restart: return TRANSLATE_FAIL; } else if (!(pte & (PTE_R | PTE_W | PTE_X))) { /* Inner PTE, continue walking */ - base =3D ppn << PGSHIFT; + base =3D ppn << pgshift; } else if ((pte & (PTE_R | PTE_W | PTE_X)) =3D=3D PTE_W) { /* Reserved leaf PTE flags: PTE_W */ return TRANSLATE_FAIL; @@ -601,9 +625,9 @@ restart: =20 /* for superpage mappings, make a fake leaf PTE for the TLB's benefit. */ - target_ulong vpn =3D addr >> PGSHIFT; - *physical =3D ((ppn | (vpn & ((1L << ptshift) - 1))) << PGSHIF= T) | - (addr & ~TARGET_PAGE_MASK); + target_ulong vpn =3D addr >> pgshift; + *physical =3D ((ppn | (vpn & ((1L << ptshift) - 1))) << pgshif= t) | + (addr & pgoff_mask); =20 /* set permissions on the TLB entry */ if ((pte & PTE_R) || ((pte & PTE_X) && mxr)) { diff --git a/target/riscv/csr.c b/target/riscv/csr.c index a9146a4496..3a6bc02571 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -461,6 +461,12 @@ static const char valid_vm_1_10_64[16] =3D { [VM_1_10_SV57] =3D 1 }; =20 +static const bool valid_vm_1_10_128[16] =3D { + [VM_1_10_MBARE] =3D 1, + [VM_1_10_SV44] =3D 1, + [VM_1_10_SV54] =3D 1 +}; + /* Machine Information Registers */ static RISCVException read_zero_i128(CPURISCVState *env, int csrno, Int128 *val) @@ -557,8 +563,12 @@ static int validate_vm(CPURISCVState *env, target_ulon= g vm) { if (riscv_cpu_is_32bit(env)) { return valid_vm_1_10_32[vm & 0xf]; - } else { + } else if (riscv_cpu_is_64bit(env)) { return valid_vm_1_10_64[vm & 0xf]; + } else if (riscv_cpu_is_128bit(env)) { + return valid_vm_1_10_128[vm & 0xf]; + } else { + return 0; } } =20 @@ -1090,6 +1100,67 @@ static RISCVException rmw_sip(CPURISCVState *env, in= t csrno, } =20 /* Supervisor Protection and Translation */ +static RISCVException read_satp_i128(CPURISCVState *env, int csrno, + Int128 *val) +{ + if (!riscv_feature(env, RISCV_FEATURE_MMU)) { + *val =3D int128_zero(); + return RISCV_EXCP_NONE; + } + + if (env->priv =3D=3D PRV_S && get_field(env->mstatus, MSTATUS_TVM)) { + return RISCV_EXCP_ILLEGAL_INST; + } else { + *val =3D int128_make128(env->satp, env->satph); + } + + return RISCV_EXCP_NONE; +} + +static RISCVException write_satp_i128(CPURISCVState *env, int csrno, + Int128 val) +{ + uint32_t asid; + bool vm_ok; + Int128 mask; + + if (!riscv_feature(env, RISCV_FEATURE_MMU)) { + return RISCV_EXCP_NONE; + } + + if (riscv_cpu_is_32bit(env)) { + vm_ok =3D validate_vm(env, get_field(int128_getlo(val), SATP32_MOD= E)); + mask =3D int128_make64((int128_getlo(val) ^ env->satp) + & (SATP32_MODE | SATP32_ASID | SATP32_PPN)); + asid =3D (int128_getlo(val) ^ env->satp) & SATP32_ASID; + } else if (riscv_cpu_is_64bit(env)) { + vm_ok =3D validate_vm(env, get_field(int128_getlo(val), SATP64_MOD= E)); + mask =3D int128_make64((int128_getlo(val) ^ env->satp) + & (SATP64_MODE | SATP64_ASID | SATP64_PPN)); + asid =3D (int128_getlo(val) ^ env->satp) & SATP64_ASID; + } else { + vm_ok =3D validate_vm(env, get_field(int128_gethi(val), SATP128_HM= ODE)); + mask =3D int128_and( + int128_xor(val, int128_make128(env->satp, env->satph)), + int128_make128(SATP128_LPPN, SATP128_HMODE | SATP128_HA= SID)); + asid =3D (int128_gethi(val) ^ env->satph) & SATP128_HASID; + } + + + if (vm_ok && int128_nz(mask)) { + if (env->priv =3D=3D PRV_S && get_field(env->mstatus, MSTATUS_TVM)= ) { + return RISCV_EXCP_ILLEGAL_INST; + } else { + if (asid) { + tlb_flush(env_cpu(env)); + } + env->satp =3D int128_getlo(val); + env->satph =3D int128_gethi(val); + } + } + return RISCV_EXCP_NONE; +} + static RISCVException read_satp(CPURISCVState *env, int csrno, target_ulong *val) { @@ -1624,7 +1695,7 @@ static inline RISCVException riscv_csrrw_check_i128(C= PURISCVState *env, /* 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; + int read_only =3D get_field(csrno, 0xC00) =3D=3D 3; =20 if (riscv_has_ext(env, RVH) && env->priv =3D=3D PRV_S && @@ -1765,7 +1836,7 @@ riscv_csr_operations128 csr_ops_128[CSR_TABLE_SIZE] = =3D { [CSR_MSCRATCH] =3D { read_mscratch_i128, write_mscratch_i128 }, [CSR_MEPC] =3D { read_mepc_i128, write_mepc_i128 }, =20 - [CSR_SATP] =3D { read_zero_i128 }, + [CSR_SATP] =3D { read_satp_i128, write_satp_i128 }, #endif }; =20 --=20 2.33.0