From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id CDF3EC636CC for ; Fri, 3 Feb 2023 08:00:07 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pNqyJ-0004w8-7H; Fri, 03 Feb 2023 02:58:59 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pNqxw-0004r7-Os for qemu-devel@nongnu.org; Fri, 03 Feb 2023 02:58:37 -0500 Received: from mail-oi1-x232.google.com ([2607:f8b0:4864:20::232]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1pNqxj-0007sR-Mi for qemu-devel@nongnu.org; Fri, 03 Feb 2023 02:58:34 -0500 Received: by mail-oi1-x232.google.com with SMTP id r205so3507487oib.9 for ; Thu, 02 Feb 2023 23:58:18 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sifive.com; s=google; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=kcefwA5K6WcbLC0SdGXIhhLFpzcpFgtKkLin8cMadwo=; b=W8+jQ4zPjqtBqxXi1DRqDUC5CQfrmmb5ETQBJVIfxTKm7xFHNxoyxcNC2IcLvU6on/ H9oPi4lwDv+DuvTwf9G5g50w0GKZpcNZgout8xUheKDZfVG6GJkYG9kiqaU0A6cR/WBI gJQHesTm1cuo1h8wfpm2kS5x0aDfkvOGGrPJ6g/QG2lHIEILjMEtGsGcIs3gbV2YLWTb eF8kE1imD1ja8RzK9emCX0RO+ZLRXmiPLvha5IKNQHWGa9bmUPjSNSji91swRMbIVOf5 o64Mhn4eie31M1A9dPHuv2/9V41dq2/xRZXaJpYcIhVZlWmtrU8PkmpOaGiEs7lsblpl 65+w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=kcefwA5K6WcbLC0SdGXIhhLFpzcpFgtKkLin8cMadwo=; b=BauSXEsqUu1FHNAa43wUUUez7Aj1iNOg2gZ+x2uZ3uPLm/QhsZLPUrvRTlHNPW65rX u2GoNLh9g4VLborzf2tYzA4vG+G4ChGhceKPkfOwVgvGI/PblnkrfothXkC86bRbzWVZ fREDFsH2umAo7+B5D9fpPmUlrsrqUqQr5U5GOYUdBby9jn5dftSMN6B4BUwSJHIsxzn4 GdOpMcQnxkxxXVDiIneOQzAlgeIYO+eItm0nXZ6u3dcMPw04D5wkVRa69p4+SuPLPi6V Bn+3ODH1+wbVrDTaTNYKvl8pDQEdsZT19pzdAJ8LzCpbRN9A3dLQva2yN9s1eKwYwp9r 0UwA== X-Gm-Message-State: AO0yUKUgO2ylSexV4o/3NEsrzAeJn//6RqzPgn3LpRdr7oVO5mEDqOBW +RozpaQuueHsIx5OCLfseKs4R6bp9c0ga4Or1r9GHQ== X-Google-Smtp-Source: AK7set+XqgbOzC0DHVum758vkSXYkp57orxQwgPWWZoFV1534DtsHmfXgsguwOd/j+x7NoQxl9UvPpvZWwTdWe07nzI= X-Received: by 2002:aca:5986:0:b0:378:721e:ab8c with SMTP id n128-20020aca5986000000b00378721eab8cmr390682oib.4.1675411097743; Thu, 02 Feb 2023 23:58:17 -0800 (PST) MIME-Version: 1.0 References: <20230203055812.257458-1-alexghiti@rivosinc.com> <20230203055812.257458-5-alexghiti@rivosinc.com> In-Reply-To: <20230203055812.257458-5-alexghiti@rivosinc.com> From: Frank Chang Date: Fri, 3 Feb 2023 15:58:06 +0800 Message-ID: Subject: Re: [PATCH v10 4/5] riscv: Introduce satp mode hw capabilities To: Alexandre Ghiti Cc: Palmer Dabbelt , Alistair Francis , Bin Meng , Andrew Jones , qemu-riscv@nongnu.org, qemu-devel@nongnu.org, Bin Meng Content-Type: multipart/alternative; boundary="0000000000005597ba05f3c70b1d" Received-SPF: pass client-ip=2607:f8b0:4864:20::232; envelope-from=frank.chang@sifive.com; helo=mail-oi1-x232.google.com 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, HTML_MESSAGE=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=unavailable 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: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org --0000000000005597ba05f3c70b1d Content-Type: text/plain; charset="UTF-8" Reviewed-by: Frank Chang On Fri, Feb 3, 2023 at 2:02 PM Alexandre Ghiti wrote: > Currently, the max satp mode is set with the only constraint that it must > be > implemented in QEMU, i.e. set in valid_vm_1_10_[32|64]. > > But we actually need to add another level of constraint: what the hw is > actually capable of, because currently, a linux booting on a sifive-u54 > boots in sv57 mode which is incompatible with the cpu's sv39 max > capability. > > So add a new bitmap to RISCVSATPMap which contains this capability and > initialize it in every XXX_cpu_init. > > Finally: > - valid_vm_1_10_[32|64] constrains which satp mode the CPU can use > - the CPU hw capabilities constrains what the user may select > - the user's selection then constrains what's available to the guest > OS. > > Signed-off-by: Alexandre Ghiti > Reviewed-by: Andrew Jones > Reviewed-by: Bin Meng > --- > target/riscv/cpu.c | 91 +++++++++++++++++++++++++++++++++------------- > target/riscv/cpu.h | 8 +++- > 2 files changed, 72 insertions(+), 27 deletions(-) > > diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c > index 56057cf87c..7e9924ede9 100644 > --- a/target/riscv/cpu.c > +++ b/target/riscv/cpu.c > @@ -293,18 +293,24 @@ const char *satp_mode_str(uint8_t satp_mode, bool > is_32_bit) > g_assert_not_reached(); > } > > -/* Sets the satp mode to the max supported */ > -static void set_satp_mode_default_map(RISCVCPU *cpu) > +static void set_satp_mode_max_supported(RISCVCPU *cpu, > + uint8_t satp_mode) > { > bool rv32 = riscv_cpu_mxl(&cpu->env) == MXL_RV32; > + const bool *valid_vm = rv32 ? valid_vm_1_10_32 : valid_vm_1_10_64; > > - if (riscv_feature(&cpu->env, RISCV_FEATURE_MMU)) { > - cpu->cfg.satp_mode.map |= > - (1 << satp_mode_from_str(rv32 ? "sv32" : "sv57")); > - } else { > - cpu->cfg.satp_mode.map |= (1 << satp_mode_from_str("mbare")); > + for (int i = 0; i <= satp_mode; ++i) { > + if (valid_vm[i]) { > + cpu->cfg.satp_mode.supported |= (1 << i); > + } > } > } > + > +/* Set the satp mode to the max supported */ > +static void set_satp_mode_default_map(RISCVCPU *cpu) > +{ > + cpu->cfg.satp_mode.map = cpu->cfg.satp_mode.supported; > +} > #endif > > static void riscv_any_cpu_init(Object *obj) > @@ -315,6 +321,13 @@ static void riscv_any_cpu_init(Object *obj) > #elif defined(TARGET_RISCV64) > set_misa(env, MXL_RV64, RVI | RVM | RVA | RVF | RVD | RVC | RVU); > #endif > + > +#ifndef CONFIG_USER_ONLY > + set_satp_mode_max_supported(RISCV_CPU(obj), > + riscv_cpu_mxl(&RISCV_CPU(obj)->env) == MXL_RV32 ? > + VM_1_10_SV32 : VM_1_10_SV57); > +#endif > + > set_priv_version(env, PRIV_VERSION_1_12_0); > register_cpu_props(obj); > } > @@ -328,6 +341,9 @@ static void rv64_base_cpu_init(Object *obj) > register_cpu_props(obj); > /* Set latest version of privileged specification */ > set_priv_version(env, PRIV_VERSION_1_12_0); > +#ifndef CONFIG_USER_ONLY > + set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV57); > +#endif > } > > static void rv64_sifive_u_cpu_init(Object *obj) > @@ -335,6 +351,9 @@ static void rv64_sifive_u_cpu_init(Object *obj) > CPURISCVState *env = &RISCV_CPU(obj)->env; > set_misa(env, MXL_RV64, RVI | RVM | RVA | RVF | RVD | RVC | RVS | > RVU); > set_priv_version(env, PRIV_VERSION_1_10_0); > +#ifndef CONFIG_USER_ONLY > + set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV39); > +#endif > } > > static void rv64_sifive_e_cpu_init(Object *obj) > @@ -345,6 +364,9 @@ static void rv64_sifive_e_cpu_init(Object *obj) > set_misa(env, MXL_RV64, RVI | RVM | RVA | RVC | RVU); > set_priv_version(env, PRIV_VERSION_1_10_0); > cpu->cfg.mmu = false; > +#ifndef CONFIG_USER_ONLY > + set_satp_mode_max_supported(cpu, VM_1_10_MBARE); > +#endif > } > > static void rv128_base_cpu_init(Object *obj) > @@ -361,6 +383,9 @@ static void rv128_base_cpu_init(Object *obj) > register_cpu_props(obj); > /* Set latest version of privileged specification */ > set_priv_version(env, PRIV_VERSION_1_12_0); > +#ifndef CONFIG_USER_ONLY > + set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV57); > +#endif > } > #else > static void rv32_base_cpu_init(Object *obj) > @@ -371,6 +396,9 @@ static void rv32_base_cpu_init(Object *obj) > register_cpu_props(obj); > /* Set latest version of privileged specification */ > set_priv_version(env, PRIV_VERSION_1_12_0); > +#ifndef CONFIG_USER_ONLY > + set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV32); > +#endif > } > > static void rv32_sifive_u_cpu_init(Object *obj) > @@ -378,6 +406,9 @@ static void rv32_sifive_u_cpu_init(Object *obj) > CPURISCVState *env = &RISCV_CPU(obj)->env; > set_misa(env, MXL_RV32, RVI | RVM | RVA | RVF | RVD | RVC | RVS | > RVU); > set_priv_version(env, PRIV_VERSION_1_10_0); > +#ifndef CONFIG_USER_ONLY > + set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV32); > +#endif > } > > static void rv32_sifive_e_cpu_init(Object *obj) > @@ -388,6 +419,9 @@ static void rv32_sifive_e_cpu_init(Object *obj) > set_misa(env, MXL_RV32, RVI | RVM | RVA | RVC | RVU); > set_priv_version(env, PRIV_VERSION_1_10_0); > cpu->cfg.mmu = false; > +#ifndef CONFIG_USER_ONLY > + set_satp_mode_max_supported(cpu, VM_1_10_MBARE); > +#endif > } > > static void rv32_ibex_cpu_init(Object *obj) > @@ -398,6 +432,9 @@ static void rv32_ibex_cpu_init(Object *obj) > set_misa(env, MXL_RV32, RVI | RVM | RVC | RVU); > set_priv_version(env, PRIV_VERSION_1_11_0); > cpu->cfg.mmu = false; > +#ifndef CONFIG_USER_ONLY > + set_satp_mode_max_supported(cpu, VM_1_10_MBARE); > +#endif > cpu->cfg.epmp = true; > } > > @@ -409,6 +446,9 @@ static void rv32_imafcu_nommu_cpu_init(Object *obj) > set_misa(env, MXL_RV32, RVI | RVM | RVA | RVF | RVC | RVU); > set_priv_version(env, PRIV_VERSION_1_10_0); > cpu->cfg.mmu = false; > +#ifndef CONFIG_USER_ONLY > + set_satp_mode_max_supported(cpu, VM_1_10_MBARE); > +#endif > } > #endif > > @@ -701,8 +741,9 @@ static void riscv_cpu_disas_set_info(CPUState *s, > disassemble_info *info) > static void riscv_cpu_satp_mode_finalize(RISCVCPU *cpu, Error **errp) > { > bool rv32 = riscv_cpu_mxl(&cpu->env) == MXL_RV32; > - const bool *valid_vm = rv32 ? valid_vm_1_10_32 : valid_vm_1_10_64; > - uint8_t satp_mode_max; > + uint8_t satp_mode_map_max; > + uint8_t satp_mode_supported_max = > + > satp_mode_max_from_map(cpu->cfg.satp_mode.supported); > > if (cpu->cfg.satp_mode.map == 0) { > if (cpu->cfg.satp_mode.init == 0) { > @@ -715,9 +756,10 @@ static void riscv_cpu_satp_mode_finalize(RISCVCPU > *cpu, Error **errp) > * valid_vm_1_10_32/64. > */ > for (int i = 1; i < 16; ++i) { > - if ((cpu->cfg.satp_mode.init & (1 << i)) && valid_vm[i]) { > + if ((cpu->cfg.satp_mode.init & (1 << i)) && > + (cpu->cfg.satp_mode.supported & (1 << i))) { > for (int j = i - 1; j >= 0; --j) { > - if (valid_vm[j]) { > + if (cpu->cfg.satp_mode.supported & (1 << j)) { > cpu->cfg.satp_mode.map |= (1 << j); > break; > } > @@ -728,37 +770,36 @@ static void riscv_cpu_satp_mode_finalize(RISCVCPU > *cpu, Error **errp) > } > } > > - /* Make sure the configuration asked is supported by qemu */ > - for (int i = 0; i < 16; ++i) { > - if ((cpu->cfg.satp_mode.map & (1 << i)) && !valid_vm[i]) { > - error_setg(errp, "satp_mode %s is not valid", > - satp_mode_str(i, rv32)); > - return; > - } > + satp_mode_map_max = satp_mode_max_from_map(cpu->cfg.satp_mode.map); > + > + /* Make sure the user asked for a supported configuration (HW and > qemu) */ > + if (satp_mode_map_max > satp_mode_supported_max) { > + error_setg(errp, "satp_mode %s is higher than hw max capability > %s", > + satp_mode_str(satp_mode_map_max, rv32), > + satp_mode_str(satp_mode_supported_max, rv32)); > + return; > } > > /* > * Make sure the user did not ask for an invalid configuration as per > * the specification. > */ > - satp_mode_max = satp_mode_max_from_map(cpu->cfg.satp_mode.map); > - > if (!rv32) { > - for (int i = satp_mode_max - 1; i >= 0; --i) { > + for (int i = satp_mode_map_max - 1; i >= 0; --i) { > if (!(cpu->cfg.satp_mode.map & (1 << i)) && > (cpu->cfg.satp_mode.init & (1 << i)) && > - valid_vm[i]) { > + (cpu->cfg.satp_mode.supported & (1 << i))) { > error_setg(errp, "cannot disable %s satp mode if %s " > "is enabled", satp_mode_str(i, false), > - satp_mode_str(satp_mode_max, false)); > + satp_mode_str(satp_mode_map_max, false)); > return; > } > } > } > > /* Finally expand the map so that all valid modes are set */ > - for (int i = satp_mode_max - 1; i >= 0; --i) { > - if (valid_vm[i]) { > + for (int i = satp_mode_map_max - 1; i >= 0; --i) { > + if (cpu->cfg.satp_mode.supported & (1 << i)) { > cpu->cfg.satp_mode.map |= (1 << i); > } > } > diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h > index df6d9e06e4..defc5769b5 100644 > --- a/target/riscv/cpu.h > +++ b/target/riscv/cpu.h > @@ -416,13 +416,17 @@ struct RISCVCPUClass { > > /* > * map is a 16-bit bitmap: the most significant set bit in map is the > maximum > - * satp mode that is supported. > + * satp mode that is supported. It may be chosen by the user and must > respect > + * what qemu implements (valid_1_10_32/64) and what the hw is capable of > + * (supported bitmap below). > * > * init is a 16-bit bitmap used to make sure the user selected a correct > * configuration as per the specification. > + * > + * supported is a 16-bit bitmap used to reflect the hw capabilities. > */ > typedef struct { > - uint16_t map, init; > + uint16_t map, init, supported; > } RISCVSATPMap; > > struct RISCVCPUConfig { > -- > 2.37.2 > > --0000000000005597ba05f3c70b1d Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
Reviewed-by: Frank Chang <frank.chang@sifive.com>

On Fri, Feb 3, 2023 at 2:02 PM A= lexandre Ghiti <alexghiti@rivo= sinc.com> wrote:
Currently, the max satp mode is set with the only constraint that i= t must be
implemented in QEMU, i.e. set in valid_vm_1_10_[32|64].

But we actually need to add another level of constraint: what the hw is
actually capable of, because currently, a linux booting on a sifive-u54
boots in sv57 mode which is incompatible with the cpu's sv39 max
capability.

So add a new bitmap to RISCVSATPMap which contains this capability and
initialize it in every XXX_cpu_init.

Finally:
- valid_vm_1_10_[32|64] constrains which satp mode the CPU can use
- the CPU hw capabilities constrains what the user may select
- the user's selection then constrains what's available to the gues= t
=C2=A0 OS.

Signed-off-by: Alexandre Ghiti <alexghiti@rivosinc.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
Reviewed-by: Bin Meng <bmeng@tinylab.org>
---
=C2=A0target/riscv/cpu.c | 91 +++++++++++++++++++++++++++++++++------------= -
=C2=A0target/riscv/cpu.h |=C2=A0 8 +++-
=C2=A02 files changed, 72 insertions(+), 27 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 56057cf87c..7e9924ede9 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -293,18 +293,24 @@ const char *satp_mode_str(uint8_t satp_mode, bool is_= 32_bit)
=C2=A0 =C2=A0 =C2=A0g_assert_not_reached();
=C2=A0}

-/* Sets the satp mode to the max supported */
-static void set_satp_mode_default_map(RISCVCPU *cpu)
+static void set_satp_mode_max_supported(RISCVCPU *cpu,
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 uint8_t = satp_mode)
=C2=A0{
=C2=A0 =C2=A0 =C2=A0bool rv32 =3D riscv_cpu_mxl(&cpu->env) =3D=3D MX= L_RV32;
+=C2=A0 =C2=A0 const bool *valid_vm =3D rv32 ? valid_vm_1_10_32 : valid_vm_= 1_10_64;

-=C2=A0 =C2=A0 if (riscv_feature(&cpu->env, RISCV_FEATURE_MMU)) { -=C2=A0 =C2=A0 =C2=A0 =C2=A0 cpu->cfg.satp_mode.map |=3D
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 (1 << satp_mode_from_str(rv32 ? "sv32" : "s= v57"));
-=C2=A0 =C2=A0 } else {
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 cpu->cfg.satp_mode.map |=3D (1 << sat= p_mode_from_str("mbare"));
+=C2=A0 =C2=A0 for (int i =3D 0; i <=3D satp_mode; ++i) {
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 if (valid_vm[i]) {
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 cpu->cfg.satp_mode.supported = |=3D (1 << i);
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 }
=C2=A0 =C2=A0 =C2=A0}
=C2=A0}
+
+/* Set the satp mode to the max supported */
+static void set_satp_mode_default_map(RISCVCPU *cpu)
+{
+=C2=A0 =C2=A0 cpu->cfg.satp_mode.map =3D cpu->cfg.satp_mode.supporte= d;
+}
=C2=A0#endif

=C2=A0static void riscv_any_cpu_init(Object *obj)
@@ -315,6 +321,13 @@ static void riscv_any_cpu_init(Object *obj)
=C2=A0#elif defined(TARGET_RISCV64)
=C2=A0 =C2=A0 =C2=A0set_misa(env, MXL_RV64, RVI | RVM | RVA | RVF | RVD | R= VC | RVU);
=C2=A0#endif
+
+#ifndef CONFIG_USER_ONLY
+=C2=A0 =C2=A0 set_satp_mode_max_supported(RISCV_CPU(obj),
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 riscv_cpu_mxl(&RISCV_CPU(obj= )->env) =3D=3D MXL_RV32 ?
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 VM_1_10_SV32 : VM_1_10= _SV57);
+#endif
+
=C2=A0 =C2=A0 =C2=A0set_priv_version(env, PRIV_VERSION_1_12_0);
=C2=A0 =C2=A0 =C2=A0register_cpu_props(obj);
=C2=A0}
@@ -328,6 +341,9 @@ static void rv64_base_cpu_init(Object *obj)
=C2=A0 =C2=A0 =C2=A0register_cpu_props(obj);
=C2=A0 =C2=A0 =C2=A0/* Set latest version of privileged specification */ =C2=A0 =C2=A0 =C2=A0set_priv_version(env, PRIV_VERSION_1_12_0);
+#ifndef CONFIG_USER_ONLY
+=C2=A0 =C2=A0 set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV57); +#endif
=C2=A0}

=C2=A0static void rv64_sifive_u_cpu_init(Object *obj)
@@ -335,6 +351,9 @@ static void rv64_sifive_u_cpu_init(Object *obj)
=C2=A0 =C2=A0 =C2=A0CPURISCVState *env =3D &RISCV_CPU(obj)->env;
=C2=A0 =C2=A0 =C2=A0set_misa(env, MXL_RV64, RVI | RVM | RVA | RVF | RVD | R= VC | RVS | RVU);
=C2=A0 =C2=A0 =C2=A0set_priv_version(env, PRIV_VERSION_1_10_0);
+#ifndef CONFIG_USER_ONLY
+=C2=A0 =C2=A0 set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV39); +#endif
=C2=A0}

=C2=A0static void rv64_sifive_e_cpu_init(Object *obj)
@@ -345,6 +364,9 @@ static void rv64_sifive_e_cpu_init(Object *obj)
=C2=A0 =C2=A0 =C2=A0set_misa(env, MXL_RV64, RVI | RVM | RVA | RVC | RVU); =C2=A0 =C2=A0 =C2=A0set_priv_version(env, PRIV_VERSION_1_10_0);
=C2=A0 =C2=A0 =C2=A0cpu->cfg.mmu =3D false;
+#ifndef CONFIG_USER_ONLY
+=C2=A0 =C2=A0 set_satp_mode_max_supported(cpu, VM_1_10_MBARE);
+#endif
=C2=A0}

=C2=A0static void rv128_base_cpu_init(Object *obj)
@@ -361,6 +383,9 @@ static void rv128_base_cpu_init(Object *obj)
=C2=A0 =C2=A0 =C2=A0register_cpu_props(obj);
=C2=A0 =C2=A0 =C2=A0/* Set latest version of privileged specification */ =C2=A0 =C2=A0 =C2=A0set_priv_version(env, PRIV_VERSION_1_12_0);
+#ifndef CONFIG_USER_ONLY
+=C2=A0 =C2=A0 set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV57); +#endif
=C2=A0}
=C2=A0#else
=C2=A0static void rv32_base_cpu_init(Object *obj)
@@ -371,6 +396,9 @@ static void rv32_base_cpu_init(Object *obj)
=C2=A0 =C2=A0 =C2=A0register_cpu_props(obj);
=C2=A0 =C2=A0 =C2=A0/* Set latest version of privileged specification */ =C2=A0 =C2=A0 =C2=A0set_priv_version(env, PRIV_VERSION_1_12_0);
+#ifndef CONFIG_USER_ONLY
+=C2=A0 =C2=A0 set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV32); +#endif
=C2=A0}

=C2=A0static void rv32_sifive_u_cpu_init(Object *obj)
@@ -378,6 +406,9 @@ static void rv32_sifive_u_cpu_init(Object *obj)
=C2=A0 =C2=A0 =C2=A0CPURISCVState *env =3D &RISCV_CPU(obj)->env;
=C2=A0 =C2=A0 =C2=A0set_misa(env, MXL_RV32, RVI | RVM | RVA | RVF | RVD | R= VC | RVS | RVU);
=C2=A0 =C2=A0 =C2=A0set_priv_version(env, PRIV_VERSION_1_10_0);
+#ifndef CONFIG_USER_ONLY
+=C2=A0 =C2=A0 set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV32); +#endif
=C2=A0}

=C2=A0static void rv32_sifive_e_cpu_init(Object *obj)
@@ -388,6 +419,9 @@ static void rv32_sifive_e_cpu_init(Object *obj)
=C2=A0 =C2=A0 =C2=A0set_misa(env, MXL_RV32, RVI | RVM | RVA | RVC | RVU); =C2=A0 =C2=A0 =C2=A0set_priv_version(env, PRIV_VERSION_1_10_0);
=C2=A0 =C2=A0 =C2=A0cpu->cfg.mmu =3D false;
+#ifndef CONFIG_USER_ONLY
+=C2=A0 =C2=A0 set_satp_mode_max_supported(cpu, VM_1_10_MBARE);
+#endif
=C2=A0}

=C2=A0static void rv32_ibex_cpu_init(Object *obj)
@@ -398,6 +432,9 @@ static void rv32_ibex_cpu_init(Object *obj)
=C2=A0 =C2=A0 =C2=A0set_misa(env, MXL_RV32, RVI | RVM | RVC | RVU);
=C2=A0 =C2=A0 =C2=A0set_priv_version(env, PRIV_VERSION_1_11_0);
=C2=A0 =C2=A0 =C2=A0cpu->cfg.mmu =3D false;
+#ifndef CONFIG_USER_ONLY
+=C2=A0 =C2=A0 set_satp_mode_max_supported(cpu, VM_1_10_MBARE);
+#endif
=C2=A0 =C2=A0 =C2=A0cpu->cfg.epmp =3D true;
=C2=A0}

@@ -409,6 +446,9 @@ static void rv32_imafcu_nommu_cpu_init(Object *obj)
=C2=A0 =C2=A0 =C2=A0set_misa(env, MXL_RV32, RVI | RVM | RVA | RVF | RVC | R= VU);
=C2=A0 =C2=A0 =C2=A0set_priv_version(env, PRIV_VERSION_1_10_0);
=C2=A0 =C2=A0 =C2=A0cpu->cfg.mmu =3D false;
+#ifndef CONFIG_USER_ONLY
+=C2=A0 =C2=A0 set_satp_mode_max_supported(cpu, VM_1_10_MBARE);
+#endif
=C2=A0}
=C2=A0#endif

@@ -701,8 +741,9 @@ static void riscv_cpu_disas_set_info(CPUState *s, disas= semble_info *info)
=C2=A0static void riscv_cpu_satp_mode_finalize(RISCVCPU *cpu, Error **errp)=
=C2=A0{
=C2=A0 =C2=A0 =C2=A0bool rv32 =3D riscv_cpu_mxl(&cpu->env) =3D=3D MX= L_RV32;
-=C2=A0 =C2=A0 const bool *valid_vm =3D rv32 ? valid_vm_1_10_32 : valid_vm_= 1_10_64;
-=C2=A0 =C2=A0 uint8_t satp_mode_max;
+=C2=A0 =C2=A0 uint8_t satp_mode_map_max;
+=C2=A0 =C2=A0 uint8_t satp_mode_supported_max =3D
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 satp_mode_max_from_map(cpu->cfg.satp_mode.supported);

=C2=A0 =C2=A0 =C2=A0if (cpu->cfg.satp_mode.map =3D=3D 0) {
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0if (cpu->cfg.satp_mode.init =3D=3D 0) = {
@@ -715,9 +756,10 @@ static void riscv_cpu_satp_mode_finalize(RISCVCPU *cpu= , Error **errp)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 * valid_vm_1_10_32/64.
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 */
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0for (int i =3D 1; i < 16= ; ++i) {
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 if ((cpu->cfg.s= atp_mode.init & (1 << i)) && valid_vm[i]) {
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 if ((cpu->cfg.s= atp_mode.init & (1 << i)) &&
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (cpu= ->cfg.satp_mode.supported & (1 << i))) {
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0for (int j =3D i - 1; j >=3D 0; --j) {
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 if (valid_vm[j]) {
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 if (cpu->cfg.satp_mode.supported & (1 << j)) {
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0cpu->cfg.satp_mode.map |=3D (1 << j= );
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0break;
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0}
@@ -728,37 +770,36 @@ static void riscv_cpu_satp_mode_finalize(RISCVCPU *cp= u, Error **errp)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0}
=C2=A0 =C2=A0 =C2=A0}

-=C2=A0 =C2=A0 /* Make sure the configuration asked is supported by qemu */=
-=C2=A0 =C2=A0 for (int i =3D 0; i < 16; ++i) {
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 if ((cpu->cfg.satp_mode.map & (1 <&l= t; i)) && !valid_vm[i]) {
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 error_setg(errp, "satp_mode= %s is not valid",
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0satp_mode_str(i, rv32));
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 return;
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 }
+=C2=A0 =C2=A0 satp_mode_map_max =3D satp_mode_max_from_map(cpu->cfg.sat= p_mode.map);
+
+=C2=A0 =C2=A0 /* Make sure the user asked for a supported configuration (H= W and qemu) */
+=C2=A0 =C2=A0 if (satp_mode_map_max > satp_mode_supported_max) {
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 error_setg(errp, "satp_mode %s is higher = than hw max capability %s",
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0satp_= mode_str(satp_mode_map_max, rv32),
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0satp_= mode_str(satp_mode_supported_max, rv32));
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 return;
=C2=A0 =C2=A0 =C2=A0}

=C2=A0 =C2=A0 =C2=A0/*
=C2=A0 =C2=A0 =C2=A0 * Make sure the user did not ask for an invalid config= uration as per
=C2=A0 =C2=A0 =C2=A0 * the specification.
=C2=A0 =C2=A0 =C2=A0 */
-=C2=A0 =C2=A0 satp_mode_max =3D satp_mode_max_from_map(cpu->cfg.satp_mo= de.map);
-
=C2=A0 =C2=A0 =C2=A0if (!rv32) {
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 for (int i =3D satp_mode_max - 1; i >=3D 0;= --i) {
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 for (int i =3D satp_mode_map_max - 1; i >= =3D 0; --i) {
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0if (!(cpu->cfg.satp_mode= .map & (1 << i)) &&
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(cpu->cfg.= satp_mode.init & (1 << i)) &&
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 valid_vm[i]) {
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (cpu->cfg.satp_= mode.supported & (1 << i))) {
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0error_setg(er= rp, "cannot disable %s satp mode if %s "
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 "is enabled", satp_mode_str(i, false), -=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0satp_mode_str(satp_mode_max, false));
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0satp_mode_str(satp_mode_map_max, false));
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return;
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0}
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0}
=C2=A0 =C2=A0 =C2=A0}

=C2=A0 =C2=A0 =C2=A0/* Finally expand the map so that all valid modes are s= et */
-=C2=A0 =C2=A0 for (int i =3D satp_mode_max - 1; i >=3D 0; --i) {
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 if (valid_vm[i]) {
+=C2=A0 =C2=A0 for (int i =3D satp_mode_map_max - 1; i >=3D 0; --i) { +=C2=A0 =C2=A0 =C2=A0 =C2=A0 if (cpu->cfg.satp_mode.supported & (1 &= lt;< i)) {
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0cpu->cfg.satp_mode.map |= =3D (1 << i);
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0}
=C2=A0 =C2=A0 =C2=A0}
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index df6d9e06e4..defc5769b5 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -416,13 +416,17 @@ struct RISCVCPUClass {

=C2=A0/*
=C2=A0 * map is a 16-bit bitmap: the most significant set bit in map is the= maximum
- * satp mode that is supported.
+ * satp mode that is supported. It may be chosen by the user and must resp= ect
+ * what qemu implements (valid_1_10_32/64) and what the hw is capable of + * (supported bitmap below).
=C2=A0 *
=C2=A0 * init is a 16-bit bitmap used to make sure the user selected a corr= ect
=C2=A0 * configuration as per the specification.
+ *
+ * supported is a 16-bit bitmap used to reflect the hw capabilities.
=C2=A0 */
=C2=A0typedef struct {
-=C2=A0 =C2=A0 uint16_t map, init;
+=C2=A0 =C2=A0 uint16_t map, init, supported;
=C2=A0} RISCVSATPMap;

=C2=A0struct RISCVCPUConfig {
--
2.37.2

--0000000000005597ba05f3c70b1d--