qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v8 00/19] rv64i CPU, RVA22U64 profile support
@ 2023-11-01 20:41 Daniel Henrique Barboza
  2023-11-01 20:41 ` [PATCH v8 01/19] target/riscv: create TYPE_RISCV_VENDOR_CPU Daniel Henrique Barboza
                   ` (18 more replies)
  0 siblings, 19 replies; 31+ messages in thread
From: Daniel Henrique Barboza @ 2023-11-01 20:41 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-riscv, alistair.francis, bmeng, liweiwei, zhiwei_liu, palmer,
	ajones, Daniel Henrique Barboza

Hi,

This v8 contains a few more extra, trivial changes, related to the
design of the rv64i.

We stripped away all its defaults, including priv_ver and satp mode.
Handling priv_ver was somewhat trivial: profiles and regular extensions
that are user set will now bump the CPU priv_ver if needed. This will
only affect rv64i since generic CPUs are already set to
PRIV_VERSION_LATEST and vendor CPUs does not allow extensions to be
enabled.

Dealing with satp_mode was trickier. First we need to fix the setter()
of satp user flags to allow users to set satp_max_supported of the CPU
if none was set. Then we need extra code during finalize() to handle an
assert that csr.c is throwing due to the lack of a satp_max_supported
value in the CPU. We could either set a default value or error out, and
decided to set a default value. Otherwise, when doing a rv64i CPU
introspection (e.g. query-cpu-model-expansion), we would be obligated to
set a satp mode, which is silly.

I intend to add a proper documentation on both rv64i and the overall
profile extension design. Since documentation can be done after the code
freeze let's wait for this to be merged first.

No other major changes made. Patches based on Alistair's
riscv-to-apply.next.

Patches missing acks: 3, 4, 5, 6

Changes from v7:
- patch 3 (new):
  - allow users to set satp max supported via user flags
- patch 4 (new):
  - set default satp mode max to MBARE during finalize
- patch 5 (new):
  - update update priv_ver on user_set extensions
- patch 6 (patch 3 from v7):
  - remove default priv_ver and satp values from rv64i_bare_cpu_init()
  - remove default values of zicntr and zihpm from rv64i_bare_cpu_init()
- patch 18 (patch 15 from v7):
  - do not check 'edata' in cpu_cfg_ext_get_name() loop
  - remove extra blank line
- v7 link: https://lore.kernel.org/qemu-riscv/20231031203916.197332-1-dbarboza@ventanamicro.com/

Daniel Henrique Barboza (19):
  target/riscv: create TYPE_RISCV_VENDOR_CPU
  target/riscv/tcg: do not use "!generic" CPU checks
  target/riscv/cpu.c: set satp_max_supported in cpu_riscv_set_satp()
  target/riscv/cpu.c: set satp_mode_max MBARE during satp_finalize()
  target/riscv/tcg: update priv_ver on user_set extensions
  target/riscv: add rv64i CPU
  target/riscv: add zicbop extension flag
  target/riscv/tcg: add 'zic64b' support
  riscv-qmp-cmds.c: expose named features in cpu_model_expansion
  target/riscv: add rva22u64 profile definition
  target/riscv/kvm: add 'rva22u64' flag as unavailable
  target/riscv/tcg: add user flag for profile support
  target/riscv/tcg: add MISA user options hash
  target/riscv/tcg: add riscv_cpu_write_misa_bit()
  target/riscv/tcg: handle profile MISA bits
  target/riscv/tcg: add hash table insert helpers
  target/riscv/tcg: honor user choice for G MISA bits
  target/riscv/tcg: validate profiles during finalize
  riscv-qmp-cmds.c: add profile flags in cpu-model-expansion

 hw/riscv/virt.c               |   5 +
 target/riscv/cpu-qom.h        |   3 +
 target/riscv/cpu.c            | 119 ++++++++++--
 target/riscv/cpu.h            |  13 ++
 target/riscv/cpu_cfg.h        |   3 +
 target/riscv/kvm/kvm-cpu.c    |   7 +-
 target/riscv/riscv-qmp-cmds.c |  44 ++++-
 target/riscv/tcg/tcg-cpu.c    | 341 +++++++++++++++++++++++++++++-----
 8 files changed, 473 insertions(+), 62 deletions(-)

-- 
2.41.0



^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH v8 01/19] target/riscv: create TYPE_RISCV_VENDOR_CPU
  2023-11-01 20:41 [PATCH v8 00/19] rv64i CPU, RVA22U64 profile support Daniel Henrique Barboza
@ 2023-11-01 20:41 ` Daniel Henrique Barboza
  2023-11-02  2:32   ` Alistair Francis
  2023-11-01 20:41 ` [PATCH v8 02/19] target/riscv/tcg: do not use "!generic" CPU checks Daniel Henrique Barboza
                   ` (17 subsequent siblings)
  18 siblings, 1 reply; 31+ messages in thread
From: Daniel Henrique Barboza @ 2023-11-01 20:41 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-riscv, alistair.francis, bmeng, liweiwei, zhiwei_liu, palmer,
	ajones, Daniel Henrique Barboza

We want to add a new CPU type for bare CPUs that will inherit specific
traits of the 2 existing types:

- it will allow for extensions to be enabled/disabled, like generic
  CPUs;

- it will NOT inherit defaults, like vendor CPUs.

We can make this conditions met by adding an explicit type for the
existing vendor CPUs and change the existing logic to not imply that
"not generic" means vendor CPUs.

Let's add the "vendor" CPU type first.

Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
---
 target/riscv/cpu-qom.h |  1 +
 target/riscv/cpu.c     | 30 +++++++++++++++++++++---------
 2 files changed, 22 insertions(+), 9 deletions(-)

diff --git a/target/riscv/cpu-qom.h b/target/riscv/cpu-qom.h
index f3fbe37a2c..7831e86d37 100644
--- a/target/riscv/cpu-qom.h
+++ b/target/riscv/cpu-qom.h
@@ -24,6 +24,7 @@
 
 #define TYPE_RISCV_CPU "riscv-cpu"
 #define TYPE_RISCV_DYNAMIC_CPU "riscv-dynamic-cpu"
+#define TYPE_RISCV_VENDOR_CPU "riscv-vendor-cpu"
 
 #define RISCV_CPU_TYPE_SUFFIX "-" TYPE_RISCV_CPU
 #define RISCV_CPU_TYPE_NAME(name) (name RISCV_CPU_TYPE_SUFFIX)
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index f40da4c661..822970345c 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -1725,6 +1725,13 @@ void riscv_cpu_list(void)
         .instance_init = initfn               \
     }
 
+#define DEFINE_VENDOR_CPU(type_name, initfn) \
+    {                                        \
+        .name = type_name,                   \
+        .parent = TYPE_RISCV_VENDOR_CPU,     \
+        .instance_init = initfn              \
+    }
+
 static const TypeInfo riscv_cpu_type_infos[] = {
     {
         .name = TYPE_RISCV_CPU,
@@ -1742,21 +1749,26 @@ static const TypeInfo riscv_cpu_type_infos[] = {
         .parent = TYPE_RISCV_CPU,
         .abstract = true,
     },
+    {
+        .name = TYPE_RISCV_VENDOR_CPU,
+        .parent = TYPE_RISCV_CPU,
+        .abstract = true,
+    },
     DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_ANY,      riscv_any_cpu_init),
     DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_MAX,      riscv_max_cpu_init),
 #if defined(TARGET_RISCV32)
     DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_BASE32,   rv32_base_cpu_init),
-    DEFINE_CPU(TYPE_RISCV_CPU_IBEX,             rv32_ibex_cpu_init),
-    DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E31,       rv32_sifive_e_cpu_init),
-    DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E34,       rv32_imafcu_nommu_cpu_init),
-    DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_U34,       rv32_sifive_u_cpu_init),
+    DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_IBEX,        rv32_ibex_cpu_init),
+    DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_SIFIVE_E31,  rv32_sifive_e_cpu_init),
+    DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_SIFIVE_E34,  rv32_imafcu_nommu_cpu_init),
+    DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_SIFIVE_U34,  rv32_sifive_u_cpu_init),
 #elif defined(TARGET_RISCV64)
     DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_BASE64,   rv64_base_cpu_init),
-    DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E51,       rv64_sifive_e_cpu_init),
-    DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_U54,       rv64_sifive_u_cpu_init),
-    DEFINE_CPU(TYPE_RISCV_CPU_SHAKTI_C,         rv64_sifive_u_cpu_init),
-    DEFINE_CPU(TYPE_RISCV_CPU_THEAD_C906,       rv64_thead_c906_cpu_init),
-    DEFINE_CPU(TYPE_RISCV_CPU_VEYRON_V1,        rv64_veyron_v1_cpu_init),
+    DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_SIFIVE_E51,  rv64_sifive_e_cpu_init),
+    DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_SIFIVE_U54,  rv64_sifive_u_cpu_init),
+    DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_SHAKTI_C,    rv64_sifive_u_cpu_init),
+    DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_THEAD_C906,  rv64_thead_c906_cpu_init),
+    DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_VEYRON_V1,   rv64_veyron_v1_cpu_init),
     DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_BASE128,  rv128_base_cpu_init),
 #endif
 };
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH v8 02/19] target/riscv/tcg: do not use "!generic" CPU checks
  2023-11-01 20:41 [PATCH v8 00/19] rv64i CPU, RVA22U64 profile support Daniel Henrique Barboza
  2023-11-01 20:41 ` [PATCH v8 01/19] target/riscv: create TYPE_RISCV_VENDOR_CPU Daniel Henrique Barboza
@ 2023-11-01 20:41 ` Daniel Henrique Barboza
  2023-11-02  2:38   ` Alistair Francis
  2023-11-01 20:41 ` [PATCH v8 03/19] target/riscv/cpu.c: set satp_max_supported in cpu_riscv_set_satp() Daniel Henrique Barboza
                   ` (16 subsequent siblings)
  18 siblings, 1 reply; 31+ messages in thread
From: Daniel Henrique Barboza @ 2023-11-01 20:41 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-riscv, alistair.francis, bmeng, liweiwei, zhiwei_liu, palmer,
	ajones, Daniel Henrique Barboza

Our current logic in get/setters of MISA and multi-letter extensions
works because we have only 2 CPU types, generic and vendor, and by using
"!generic" we're implying that we're talking about vendor CPUs. When adding
a third CPU type this logic will break so let's handle it beforehand.

In set_misa_ext_cfg() and set_multi_ext_cfg(), check for "vendor" cpu instead
of "not generic". The "generic CPU" checks remaining are from
riscv_cpu_add_misa_properties() and cpu_add_multi_ext_prop() before
applying default values for the extensions.

This leaves us with:

- vendor CPUs will not allow extension enablement, all other CPUs will;

- generic CPUs will inherit default values for extensions, all others
  won't.

And now we can add a new, third CPU type, that will allow extensions to
be enabled and will not inherit defaults, without changing the existing
logic.

Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
---
 target/riscv/tcg/tcg-cpu.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
index 093bda2e75..f54069d06f 100644
--- a/target/riscv/tcg/tcg-cpu.c
+++ b/target/riscv/tcg/tcg-cpu.c
@@ -612,6 +612,11 @@ static bool riscv_cpu_is_generic(Object *cpu_obj)
     return object_dynamic_cast(cpu_obj, TYPE_RISCV_DYNAMIC_CPU) != NULL;
 }
 
+static bool riscv_cpu_is_vendor(Object *cpu_obj)
+{
+    return object_dynamic_cast(cpu_obj, TYPE_RISCV_VENDOR_CPU) != NULL;
+}
+
 /*
  * We'll get here via the following path:
  *
@@ -674,7 +679,7 @@ static void cpu_set_misa_ext_cfg(Object *obj, Visitor *v, const char *name,
     target_ulong misa_bit = misa_ext_cfg->misa_bit;
     RISCVCPU *cpu = RISCV_CPU(obj);
     CPURISCVState *env = &cpu->env;
-    bool generic_cpu = riscv_cpu_is_generic(obj);
+    bool vendor_cpu = riscv_cpu_is_vendor(obj);
     bool prev_val, value;
 
     if (!visit_type_bool(v, name, &value, errp)) {
@@ -688,7 +693,7 @@ static void cpu_set_misa_ext_cfg(Object *obj, Visitor *v, const char *name,
     }
 
     if (value) {
-        if (!generic_cpu) {
+        if (vendor_cpu) {
             g_autofree char *cpuname = riscv_cpu_get_name(cpu);
             error_setg(errp, "'%s' CPU does not allow enabling extensions",
                        cpuname);
@@ -793,7 +798,7 @@ static void cpu_set_multi_ext_cfg(Object *obj, Visitor *v, const char *name,
 {
     const RISCVCPUMultiExtConfig *multi_ext_cfg = opaque;
     RISCVCPU *cpu = RISCV_CPU(obj);
-    bool generic_cpu = riscv_cpu_is_generic(obj);
+    bool vendor_cpu = riscv_cpu_is_vendor(obj);
     bool prev_val, value;
 
     if (!visit_type_bool(v, name, &value, errp)) {
@@ -817,7 +822,7 @@ static void cpu_set_multi_ext_cfg(Object *obj, Visitor *v, const char *name,
         return;
     }
 
-    if (value && !generic_cpu) {
+    if (value && vendor_cpu) {
         g_autofree char *cpuname = riscv_cpu_get_name(cpu);
         error_setg(errp, "'%s' CPU does not allow enabling extensions",
                    cpuname);
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH v8 03/19] target/riscv/cpu.c: set satp_max_supported in cpu_riscv_set_satp()
  2023-11-01 20:41 [PATCH v8 00/19] rv64i CPU, RVA22U64 profile support Daniel Henrique Barboza
  2023-11-01 20:41 ` [PATCH v8 01/19] target/riscv: create TYPE_RISCV_VENDOR_CPU Daniel Henrique Barboza
  2023-11-01 20:41 ` [PATCH v8 02/19] target/riscv/tcg: do not use "!generic" CPU checks Daniel Henrique Barboza
@ 2023-11-01 20:41 ` Daniel Henrique Barboza
  2023-11-02  9:24   ` Andrew Jones
  2023-11-01 20:41 ` [PATCH v8 04/19] target/riscv/cpu.c: set satp_mode_max MBARE during satp_finalize() Daniel Henrique Barboza
                   ` (15 subsequent siblings)
  18 siblings, 1 reply; 31+ messages in thread
From: Daniel Henrique Barboza @ 2023-11-01 20:41 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-riscv, alistair.francis, bmeng, liweiwei, zhiwei_liu, palmer,
	ajones, Daniel Henrique Barboza

The setter() for the boolean attributes that set satp_mode (sv32, sv39,
sv48, sv57, sv64) considers that the CPU will always do a
set_satp_mode_max_supported() during cpu_init().

This is not the case for the KVM 'host' CPU, and we'll add another CPU
that won't set satp_mode_max() during cpu_init(). Users should be able
to set a max_support in these circunstances.

Allow cpu_riscv_set_satp() to set satp_mode_max_supported if the CPU
didn't set one prior.

Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
---
 target/riscv/cpu.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 822970345c..9f6837ecb7 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -1100,6 +1100,7 @@ static void cpu_riscv_get_satp(Object *obj, Visitor *v, const char *name,
 static void cpu_riscv_set_satp(Object *obj, Visitor *v, const char *name,
                                void *opaque, Error **errp)
 {
+    RISCVCPU *cpu = RISCV_CPU(obj);
     RISCVSATPMap *satp_map = opaque;
     uint8_t satp = satp_mode_from_str(name);
     bool value;
@@ -1108,6 +1109,16 @@ static void cpu_riscv_set_satp(Object *obj, Visitor *v, const char *name,
         return;
     }
 
+    /*
+     * Allow users to set satp max supported if the CPU didn't
+     * set any during cpu_init(). First value set to 'true'
+     * in this case is assumed to be the max supported for
+     * the CPU.
+     */
+    if (value && cpu->cfg.satp_mode.supported == 0) {
+        set_satp_mode_max_supported(cpu, satp);
+    }
+
     satp_map->map = deposit32(satp_map->map, satp, 1, value);
     satp_map->init |= 1 << satp;
 }
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH v8 04/19] target/riscv/cpu.c: set satp_mode_max MBARE during satp_finalize()
  2023-11-01 20:41 [PATCH v8 00/19] rv64i CPU, RVA22U64 profile support Daniel Henrique Barboza
                   ` (2 preceding siblings ...)
  2023-11-01 20:41 ` [PATCH v8 03/19] target/riscv/cpu.c: set satp_max_supported in cpu_riscv_set_satp() Daniel Henrique Barboza
@ 2023-11-01 20:41 ` Daniel Henrique Barboza
  2023-11-02  9:32   ` Andrew Jones
  2023-11-01 20:41 ` [PATCH v8 05/19] target/riscv/tcg: update priv_ver on user_set extensions Daniel Henrique Barboza
                   ` (14 subsequent siblings)
  18 siblings, 1 reply; 31+ messages in thread
From: Daniel Henrique Barboza @ 2023-11-01 20:41 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-riscv, alistair.francis, bmeng, liweiwei, zhiwei_liu, palmer,
	ajones, Daniel Henrique Barboza

KVM CPUs can handle "cpu->cfg.satp_mode.supported == 0" because KVM will
make it do internally, not requiring the current SATP support from TCG.

But other TCG CPUs doesn't deal well with it. We'll assert out before
OpenSBI if the CPU doesn't set a default:

ERROR:../target/riscv/cpu.c:317:satp_mode_max_from_map: assertion failed: (map > 0)
Bail out! ERROR:../target/riscv/cpu.c:317:satp_mode_max_from_map: assertion failed: (map > 0)

This will be thrown by target/riscv/csr.c, write_satp(), when stepping
in validate_vm().

There's no current CPUs affected by it, but next patch will add a new
CPU that doesn't have defaults and this assert will be hit.

Change riscv_cpu_satp_mode_finalize() to set satp_mode_max_supported()
to MBARE if the CPU happens to not have a max mode set yet.

Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
---
 target/riscv/cpu.c | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 9f6837ecb7..f7c1989d14 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -942,9 +942,19 @@ static void riscv_cpu_satp_mode_finalize(RISCVCPU *cpu, Error **errp)
     bool rv32 = riscv_cpu_mxl(&cpu->env) == MXL_RV32;
     uint8_t satp_mode_map_max, satp_mode_supported_max;
 
-    /* The CPU wants the OS to decide which satp mode to use */
     if (cpu->cfg.satp_mode.supported == 0) {
-        return;
+        if (kvm_enabled()) {
+            /* The CPU wants the OS to decide which satp mode to use */
+            return;
+        }
+
+        /*
+         * We do not handle cpu->cfg.satp_mode.supported == 0
+         * with TCG yet. Set to MBARE.
+         */
+        if (tcg_enabled()) {
+            set_satp_mode_max_supported(cpu, VM_1_10_MBARE);
+        }
     }
 
     satp_mode_supported_max =
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH v8 05/19] target/riscv/tcg: update priv_ver on user_set extensions
  2023-11-01 20:41 [PATCH v8 00/19] rv64i CPU, RVA22U64 profile support Daniel Henrique Barboza
                   ` (3 preceding siblings ...)
  2023-11-01 20:41 ` [PATCH v8 04/19] target/riscv/cpu.c: set satp_mode_max MBARE during satp_finalize() Daniel Henrique Barboza
@ 2023-11-01 20:41 ` Daniel Henrique Barboza
  2023-11-02  9:47   ` Andrew Jones
  2023-11-01 20:41 ` [PATCH v8 06/19] target/riscv: add rv64i CPU Daniel Henrique Barboza
                   ` (13 subsequent siblings)
  18 siblings, 1 reply; 31+ messages in thread
From: Daniel Henrique Barboza @ 2023-11-01 20:41 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-riscv, alistair.francis, bmeng, liweiwei, zhiwei_liu, palmer,
	ajones, Daniel Henrique Barboza

We'll add a new bare CPU type that won't have any default priv_ver. This
means that the CPU will default to priv_ver = 0, i.e. 1.10.0.

At the same we'll allow these CPUs to enable extensions at will, but
then, if the extension has a priv_ver newer than 1.10, we'll end up
disabling it. Users will then need to manually set priv_ver to something
other than 1.10 to enable the extensions they want, which is not ideal.

Change the setter() of multi letter extensions to allow user enabled
extensions to bump the priv_ver of the CPU. This will make it
conveniente for users to enable extensions for CPUs that doesn't set a
default priv_ver.

This change does not affect any existing CPU: vendor CPUs does not allow
extensions to be enabled, and generic CPUs are already set to priv_ver
LATEST.

Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
---
 target/riscv/tcg/tcg-cpu.c | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
index f54069d06f..b88fce98a4 100644
--- a/target/riscv/tcg/tcg-cpu.c
+++ b/target/riscv/tcg/tcg-cpu.c
@@ -114,6 +114,22 @@ static int cpu_cfg_ext_get_min_version(uint32_t ext_offset)
     g_assert_not_reached();
 }
 
+static void cpu_validate_multi_ext_priv_ver(CPURISCVState *env,
+                                            uint32_t ext_offset)
+{
+    int ext_priv_ver;
+
+    if (env->priv_ver == PRIV_VERSION_LATEST) {
+        return;
+    }
+
+    ext_priv_ver = cpu_cfg_ext_get_min_version(ext_offset);
+
+    if (env->priv_ver < ext_priv_ver) {
+        env->priv_ver = ext_priv_ver;
+    }
+}
+
 static void cpu_cfg_ext_auto_update(RISCVCPU *cpu, uint32_t ext_offset,
                                     bool value)
 {
@@ -829,6 +845,10 @@ static void cpu_set_multi_ext_cfg(Object *obj, Visitor *v, const char *name,
         return;
     }
 
+    if (value) {
+        cpu_validate_multi_ext_priv_ver(&cpu->env, multi_ext_cfg->offset);
+    }
+
     isa_ext_update_enabled(cpu, multi_ext_cfg->offset, value);
 }
 
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH v8 06/19] target/riscv: add rv64i CPU
  2023-11-01 20:41 [PATCH v8 00/19] rv64i CPU, RVA22U64 profile support Daniel Henrique Barboza
                   ` (4 preceding siblings ...)
  2023-11-01 20:41 ` [PATCH v8 05/19] target/riscv/tcg: update priv_ver on user_set extensions Daniel Henrique Barboza
@ 2023-11-01 20:41 ` Daniel Henrique Barboza
  2023-11-02  9:59   ` Andrew Jones
  2023-11-01 20:41 ` [PATCH v8 07/19] target/riscv: add zicbop extension flag Daniel Henrique Barboza
                   ` (12 subsequent siblings)
  18 siblings, 1 reply; 31+ messages in thread
From: Daniel Henrique Barboza @ 2023-11-01 20:41 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-riscv, alistair.francis, bmeng, liweiwei, zhiwei_liu, palmer,
	ajones, Daniel Henrique Barboza

We don't have any form of a 'bare bones' CPU. rv64, our default CPUs,
comes with a lot of defaults. This is fine for most regular uses but
it's not suitable when more control of what is actually loaded in the
CPU is required.

A bare-bones CPU would be annoying to deal with if not by profile
support, a way to load a multitude of extensions with a single flag.
Profile support is going to be implemented shortly, so let's add a CPU
for it.

The new 'rv64i' CPU will have only RVI loaded. It is inspired in the
profile specification that dictates, for RVA22U64 [1]:

"RVA22U64 Mandatory Base
 RV64I is the mandatory base ISA for RVA22U64"

And so it seems that RV64I is the mandatory base ISA for all profiles
listed in [1], making it an ideal CPU to use with profile support.

rv64i is a CPU of type TYPE_RISCV_BARE_CPU. It has a mix of features
from pre-existent CPUs:

- it allows extensions to be enabled, like generic CPUs;
- it will not inherit extension defaults, like vendor CPUs.

This is the minimum extension set to boot OpenSBI and buildroot using
rv64i:

./build/qemu-system-riscv64 -nographic -M virt \
    -cpu rv64i,sv39=true,g=true,c=true,s=true,u=true

Our minimal riscv,isa in this case will be:

 # cat /proc/device-tree/cpus/cpu@0/riscv,isa
rv64imafdc_zicntr_zicsr_zifencei_zihpm_zca_zcd#

[1] https://github.com/riscv/riscv-profiles/blob/main/profiles.adoc

Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
---
 target/riscv/cpu-qom.h |  2 ++
 target/riscv/cpu.c     | 23 +++++++++++++++++++++++
 2 files changed, 25 insertions(+)

diff --git a/target/riscv/cpu-qom.h b/target/riscv/cpu-qom.h
index 7831e86d37..ea9a752280 100644
--- a/target/riscv/cpu-qom.h
+++ b/target/riscv/cpu-qom.h
@@ -25,6 +25,7 @@
 #define TYPE_RISCV_CPU "riscv-cpu"
 #define TYPE_RISCV_DYNAMIC_CPU "riscv-dynamic-cpu"
 #define TYPE_RISCV_VENDOR_CPU "riscv-vendor-cpu"
+#define TYPE_RISCV_BARE_CPU "riscv-bare-cpu"
 
 #define RISCV_CPU_TYPE_SUFFIX "-" TYPE_RISCV_CPU
 #define RISCV_CPU_TYPE_NAME(name) (name RISCV_CPU_TYPE_SUFFIX)
@@ -35,6 +36,7 @@
 #define TYPE_RISCV_CPU_BASE32           RISCV_CPU_TYPE_NAME("rv32")
 #define TYPE_RISCV_CPU_BASE64           RISCV_CPU_TYPE_NAME("rv64")
 #define TYPE_RISCV_CPU_BASE128          RISCV_CPU_TYPE_NAME("x-rv128")
+#define TYPE_RISCV_CPU_RV64I            RISCV_CPU_TYPE_NAME("rv64i")
 #define TYPE_RISCV_CPU_IBEX             RISCV_CPU_TYPE_NAME("lowrisc-ibex")
 #define TYPE_RISCV_CPU_SHAKTI_C         RISCV_CPU_TYPE_NAME("shakti-c")
 #define TYPE_RISCV_CPU_SIFIVE_E31       RISCV_CPU_TYPE_NAME("sifive-e31")
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index f7c1989d14..4a6e544eaf 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -544,6 +544,16 @@ static void rv128_base_cpu_init(Object *obj)
     set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV57);
 #endif
 }
+
+static void rv64i_bare_cpu_init(Object *obj)
+{
+    CPURISCVState *env = &RISCV_CPU(obj)->env;
+    riscv_cpu_set_misa(env, MXL_RV64, RVI);
+
+    /* Remove the defaults from the parent class */
+    RISCV_CPU(obj)->cfg.ext_zicntr = false;
+    RISCV_CPU(obj)->cfg.ext_zihpm = false;
+}
 #else
 static void rv32_base_cpu_init(Object *obj)
 {
@@ -1753,6 +1763,13 @@ void riscv_cpu_list(void)
         .instance_init = initfn              \
     }
 
+#define DEFINE_BARE_CPU(type_name, initfn) \
+    {                                      \
+        .name = type_name,                 \
+        .parent = TYPE_RISCV_BARE_CPU,     \
+        .instance_init = initfn            \
+    }
+
 static const TypeInfo riscv_cpu_type_infos[] = {
     {
         .name = TYPE_RISCV_CPU,
@@ -1775,6 +1792,11 @@ static const TypeInfo riscv_cpu_type_infos[] = {
         .parent = TYPE_RISCV_CPU,
         .abstract = true,
     },
+    {
+        .name = TYPE_RISCV_BARE_CPU,
+        .parent = TYPE_RISCV_CPU,
+        .abstract = true,
+    },
     DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_ANY,      riscv_any_cpu_init),
     DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_MAX,      riscv_max_cpu_init),
 #if defined(TARGET_RISCV32)
@@ -1791,6 +1813,7 @@ static const TypeInfo riscv_cpu_type_infos[] = {
     DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_THEAD_C906,  rv64_thead_c906_cpu_init),
     DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_VEYRON_V1,   rv64_veyron_v1_cpu_init),
     DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_BASE128,  rv128_base_cpu_init),
+    DEFINE_BARE_CPU(TYPE_RISCV_CPU_RV64I, rv64i_bare_cpu_init),
 #endif
 };
 
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH v8 07/19] target/riscv: add zicbop extension flag
  2023-11-01 20:41 [PATCH v8 00/19] rv64i CPU, RVA22U64 profile support Daniel Henrique Barboza
                   ` (5 preceding siblings ...)
  2023-11-01 20:41 ` [PATCH v8 06/19] target/riscv: add rv64i CPU Daniel Henrique Barboza
@ 2023-11-01 20:41 ` Daniel Henrique Barboza
  2023-11-01 20:41 ` [PATCH v8 08/19] target/riscv/tcg: add 'zic64b' support Daniel Henrique Barboza
                   ` (11 subsequent siblings)
  18 siblings, 0 replies; 31+ messages in thread
From: Daniel Henrique Barboza @ 2023-11-01 20:41 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-riscv, alistair.francis, bmeng, liweiwei, zhiwei_liu, palmer,
	ajones, Daniel Henrique Barboza

QEMU already implements zicbom (Cache Block Management Operations) and
zicboz (Cache Block Zero Operations). Commit 59cb29d6a5 ("target/riscv:
add Zicbop cbo.prefetch{i, r, m} placeholder") added placeholders for
what would be the instructions for zicbop (Cache Block Prefetch
Operations), which are now no-ops.

The RVA22U64 profile mandates zicbop, which means that applications that
run with this profile might expect zicbop to be present in the riscv,isa
DT and might behave badly if it's absent.

Adding zicbop as an extension will make our future RVA22U64
implementation more in line with what userspace expects and, if/when
cache block prefetch operations became relevant to QEMU, we already have
the extension flag to turn then on/off as needed.

Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
---
 hw/riscv/virt.c        | 5 +++++
 target/riscv/cpu.c     | 3 +++
 target/riscv/cpu_cfg.h | 2 ++
 3 files changed, 10 insertions(+)

diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index 1732c42915..99c087240f 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -273,6 +273,11 @@ static void create_fdt_socket_cpus(RISCVVirtState *s, int socket,
                                   cpu_ptr->cfg.cboz_blocksize);
         }
 
+        if (cpu_ptr->cfg.ext_zicbop) {
+            qemu_fdt_setprop_cell(ms->fdt, cpu_name, "riscv,cbop-block-size",
+                                  cpu_ptr->cfg.cbop_blocksize);
+        }
+
         qemu_fdt_setprop_string(ms->fdt, cpu_name, "compatible", "riscv");
         qemu_fdt_setprop_string(ms->fdt, cpu_name, "status", "okay");
         qemu_fdt_setprop_cell(ms->fdt, cpu_name, "reg",
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 4a6e544eaf..92807f5324 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -78,6 +78,7 @@ const uint32_t misa_bits[] = {RVI, RVE, RVM, RVA, RVF, RVD, RVV,
  */
 const RISCVIsaExtData isa_edata_arr[] = {
     ISA_EXT_DATA_ENTRY(zicbom, PRIV_VERSION_1_12_0, ext_zicbom),
+    ISA_EXT_DATA_ENTRY(zicbop, PRIV_VERSION_1_12_0, ext_zicbop),
     ISA_EXT_DATA_ENTRY(zicboz, PRIV_VERSION_1_12_0, ext_zicboz),
     ISA_EXT_DATA_ENTRY(zicond, PRIV_VERSION_1_12_0, ext_zicond),
     ISA_EXT_DATA_ENTRY(zicntr, PRIV_VERSION_1_12_0, ext_zicntr),
@@ -1367,6 +1368,7 @@ const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = {
     MULTI_EXT_CFG_BOOL("zhinxmin", ext_zhinxmin, false),
 
     MULTI_EXT_CFG_BOOL("zicbom", ext_zicbom, true),
+    MULTI_EXT_CFG_BOOL("zicbop", ext_zicbop, true),
     MULTI_EXT_CFG_BOOL("zicboz", ext_zicboz, true),
 
     MULTI_EXT_CFG_BOOL("zmmul", ext_zmmul, false),
@@ -1455,6 +1457,7 @@ Property riscv_cpu_options[] = {
     DEFINE_PROP_UINT16("elen", RISCVCPU, cfg.elen, 64),
 
     DEFINE_PROP_UINT16("cbom_blocksize", RISCVCPU, cfg.cbom_blocksize, 64),
+    DEFINE_PROP_UINT16("cbop_blocksize", RISCVCPU, cfg.cbop_blocksize, 64),
     DEFINE_PROP_UINT16("cboz_blocksize", RISCVCPU, cfg.cboz_blocksize, 64),
 
     DEFINE_PROP_END_OF_LIST(),
diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h
index 6eef4a51ea..2203b4c45b 100644
--- a/target/riscv/cpu_cfg.h
+++ b/target/riscv/cpu_cfg.h
@@ -65,6 +65,7 @@ struct RISCVCPUConfig {
     bool ext_zicntr;
     bool ext_zicsr;
     bool ext_zicbom;
+    bool ext_zicbop;
     bool ext_zicboz;
     bool ext_zicond;
     bool ext_zihintntl;
@@ -134,6 +135,7 @@ struct RISCVCPUConfig {
     uint16_t vlen;
     uint16_t elen;
     uint16_t cbom_blocksize;
+    uint16_t cbop_blocksize;
     uint16_t cboz_blocksize;
     bool mmu;
     bool pmp;
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH v8 08/19] target/riscv/tcg: add 'zic64b' support
  2023-11-01 20:41 [PATCH v8 00/19] rv64i CPU, RVA22U64 profile support Daniel Henrique Barboza
                   ` (6 preceding siblings ...)
  2023-11-01 20:41 ` [PATCH v8 07/19] target/riscv: add zicbop extension flag Daniel Henrique Barboza
@ 2023-11-01 20:41 ` Daniel Henrique Barboza
  2023-11-01 20:41 ` [PATCH v8 09/19] riscv-qmp-cmds.c: expose named features in cpu_model_expansion Daniel Henrique Barboza
                   ` (10 subsequent siblings)
  18 siblings, 0 replies; 31+ messages in thread
From: Daniel Henrique Barboza @ 2023-11-01 20:41 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-riscv, alistair.francis, bmeng, liweiwei, zhiwei_liu, palmer,
	ajones, Daniel Henrique Barboza

zic64b is defined in the RVA22U64 profile [1] as a named feature for
"Cache blocks must be 64 bytes in size, naturally aligned in the address
space". It's a fantasy name for 64 bytes cache blocks. The RVA22U64
profile mandates this feature, meaning that applications using this
profile expects 64 bytes cache blocks.

To make the upcoming RVA22U64 implementation complete, we'll zic64b as
a 'named feature', not a regular extension. This means that:

- it won't be exposed to users;
- it won't be written in riscv,isa.

This will be extended to other named extensions in the future, so we're
creating some common boilerplate for them as well.

zic64b is default to 'true' since we're already using 64 bytes blocks.
If any cache block size (cbo{m,p,z}_blocksize) is changed to something
different than 64, zic64b is set to 'false'.

Our profile implementation will then be able to check the current state
of zic64b and take the appropriate action (e.g. throw a warning).

[1] https://github.com/riscv/riscv-profiles/releases/download/v1.0/profiles.pdf

Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
---
 target/riscv/cpu.c         |  6 ++++++
 target/riscv/cpu.h         |  1 +
 target/riscv/cpu_cfg.h     |  1 +
 target/riscv/tcg/tcg-cpu.c | 31 +++++++++++++++++++++++++++++++
 4 files changed, 39 insertions(+)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 92807f5324..c7c09c1f7c 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -1427,6 +1427,12 @@ const RISCVCPUMultiExtConfig riscv_cpu_experimental_exts[] = {
     DEFINE_PROP_END_OF_LIST(),
 };
 
+const RISCVCPUMultiExtConfig riscv_cpu_named_features[] = {
+    MULTI_EXT_CFG_BOOL("zic64b", zic64b, true),
+
+    DEFINE_PROP_END_OF_LIST(),
+};
+
 /* Deprecated entries marked for future removal */
 const RISCVCPUMultiExtConfig riscv_cpu_deprecated_exts[] = {
     MULTI_EXT_CFG_BOOL("Zifencei", ext_zifencei, true),
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 8efc4d83ec..bf12f34082 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -745,6 +745,7 @@ typedef struct RISCVCPUMultiExtConfig {
 extern const RISCVCPUMultiExtConfig riscv_cpu_extensions[];
 extern const RISCVCPUMultiExtConfig riscv_cpu_vendor_exts[];
 extern const RISCVCPUMultiExtConfig riscv_cpu_experimental_exts[];
+extern const RISCVCPUMultiExtConfig riscv_cpu_named_features[];
 extern const RISCVCPUMultiExtConfig riscv_cpu_deprecated_exts[];
 extern Property riscv_cpu_options[];
 
diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h
index 2203b4c45b..f61a8434c4 100644
--- a/target/riscv/cpu_cfg.h
+++ b/target/riscv/cpu_cfg.h
@@ -108,6 +108,7 @@ struct RISCVCPUConfig {
     bool ext_smepmp;
     bool rvv_ta_all_1s;
     bool rvv_ma_all_1s;
+    bool zic64b;
 
     uint32_t mvendorid;
     uint64_t marchid;
diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
index b88fce98a4..a577cd795a 100644
--- a/target/riscv/tcg/tcg-cpu.c
+++ b/target/riscv/tcg/tcg-cpu.c
@@ -114,6 +114,19 @@ static int cpu_cfg_ext_get_min_version(uint32_t ext_offset)
     g_assert_not_reached();
 }
 
+static bool cpu_cfg_offset_is_named_feat(uint32_t ext_offset)
+{
+    const RISCVCPUMultiExtConfig *feat;
+
+    for (feat = riscv_cpu_named_features; feat->name != NULL; feat++) {
+        if (feat->offset == ext_offset) {
+            return true;
+        }
+    }
+
+    return false;
+}
+
 static void cpu_validate_multi_ext_priv_ver(CPURISCVState *env,
                                             uint32_t ext_offset)
 {
@@ -123,6 +136,10 @@ static void cpu_validate_multi_ext_priv_ver(CPURISCVState *env,
         return;
     }
 
+    if (cpu_cfg_offset_is_named_feat(ext_offset)) {
+        return;
+    }
+
     ext_priv_ver = cpu_cfg_ext_get_min_version(ext_offset);
 
     if (env->priv_ver < ext_priv_ver) {
@@ -280,6 +297,18 @@ static void riscv_cpu_disable_priv_spec_isa_exts(RISCVCPU *cpu)
     }
 }
 
+static void riscv_cpu_validate_zic64b(RISCVCPU *cpu)
+{
+    cpu->cfg.zic64b = cpu->cfg.cbom_blocksize == 64 &&
+                      cpu->cfg.cbop_blocksize == 64 &&
+                      cpu->cfg.cboz_blocksize == 64;
+}
+
+static void riscv_cpu_validate_named_features(RISCVCPU *cpu)
+{
+    riscv_cpu_validate_zic64b(cpu);
+}
+
 /*
  * Check consistency between chosen extensions while setting
  * cpu->cfg accordingly.
@@ -602,6 +631,8 @@ void riscv_tcg_cpu_finalize_features(RISCVCPU *cpu, Error **errp)
         return;
     }
 
+    riscv_cpu_validate_named_features(cpu);
+
     if (cpu->cfg.ext_smepmp && !cpu->cfg.pmp) {
         /*
          * Enhanced PMP should only be available
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH v8 09/19] riscv-qmp-cmds.c: expose named features in cpu_model_expansion
  2023-11-01 20:41 [PATCH v8 00/19] rv64i CPU, RVA22U64 profile support Daniel Henrique Barboza
                   ` (7 preceding siblings ...)
  2023-11-01 20:41 ` [PATCH v8 08/19] target/riscv/tcg: add 'zic64b' support Daniel Henrique Barboza
@ 2023-11-01 20:41 ` Daniel Henrique Barboza
  2023-11-01 20:41 ` [PATCH v8 10/19] target/riscv: add rva22u64 profile definition Daniel Henrique Barboza
                   ` (9 subsequent siblings)
  18 siblings, 0 replies; 31+ messages in thread
From: Daniel Henrique Barboza @ 2023-11-01 20:41 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-riscv, alistair.francis, bmeng, liweiwei, zhiwei_liu, palmer,
	ajones, Daniel Henrique Barboza

Named features (zic64b the sole example at this moment) aren't expose to
users, thus we need another way to expose them.

Go through each named feature, get its boolean value, do the needed
conversions (bool to qbool, qbool to QObject) and add it to output dict.

Another adjustment is needed: named features are evaluated during
finalize(), so riscv_cpu_finalize_features() needs to be mandatory
regardless of whether we have an input dict or not. Otherwise zic64b
will always return 'false', which is incorrect: the default values of
cache blocksizes ([cbom/cbop/cboz]_blocksize) are set to 64, satisfying
the conditions for zic64b.

Here's an API usage example after this patch:

 $ ./build/qemu-system-riscv64 -S -M virt -display none
    -qmp tcp:localhost:1234,server,wait=off

 $ ./scripts/qmp/qmp-shell localhost:1234
Welcome to the QMP low-level shell!
Connected to QEMU 8.1.50

(QEMU) query-cpu-model-expansion type=full model={"name":"rv64"}
{"return": {"model":
    {"name": "rv64", "props": {... "zic64b": true, ...}}}}

zic64b is set to 'true', as expected, since all cache sizes are 64
bytes by default.

If we change one of the cache blocksizes, zic64b is returned as 'false':

(QEMU) query-cpu-model-expansion type=full model={"name":"rv64","props":{"cbom_blocksize":128}}
{"return": {"model":
    {"name": "rv64", "props": {... "zic64b": false, ...}}}}

Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
---
 target/riscv/riscv-qmp-cmds.c | 30 +++++++++++++++++++++++++-----
 1 file changed, 25 insertions(+), 5 deletions(-)

diff --git a/target/riscv/riscv-qmp-cmds.c b/target/riscv/riscv-qmp-cmds.c
index 2f2dbae7c8..5ada279776 100644
--- a/target/riscv/riscv-qmp-cmds.c
+++ b/target/riscv/riscv-qmp-cmds.c
@@ -26,6 +26,7 @@
 
 #include "qapi/error.h"
 #include "qapi/qapi-commands-machine-target.h"
+#include "qapi/qmp/qbool.h"
 #include "qapi/qmp/qdict.h"
 #include "qapi/qmp/qerror.h"
 #include "qapi/qobject-input-visitor.h"
@@ -99,6 +100,22 @@ static void riscv_obj_add_multiext_props(Object *obj, QDict *qdict_out,
     }
 }
 
+static void riscv_obj_add_named_feats_qdict(Object *obj, QDict *qdict_out)
+{
+    const RISCVCPUMultiExtConfig *named_cfg;
+    RISCVCPU *cpu = RISCV_CPU(obj);
+    QObject *value;
+    bool flag_val;
+
+    for (int i = 0; riscv_cpu_named_features[i].name != NULL; i++) {
+        named_cfg = &riscv_cpu_named_features[i];
+        flag_val = isa_ext_is_enabled(cpu, named_cfg->offset);
+        value = QOBJECT(qbool_from_bool(flag_val));
+
+        qdict_put_obj(qdict_out, named_cfg->name, value);
+    }
+}
+
 static void riscv_cpuobj_validate_qdict_in(Object *obj, QObject *props,
                                            const QDict *qdict_in,
                                            Error **errp)
@@ -129,11 +146,6 @@ static void riscv_cpuobj_validate_qdict_in(Object *obj, QObject *props,
         goto err;
     }
 
-    riscv_cpu_finalize_features(RISCV_CPU(obj), &local_err);
-    if (local_err) {
-        goto err;
-    }
-
     visit_end_struct(visitor, NULL);
 
 err:
@@ -191,6 +203,13 @@ CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type,
         }
     }
 
+    riscv_cpu_finalize_features(RISCV_CPU(obj), &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        object_unref(obj);
+        return NULL;
+    }
+
     expansion_info = g_new0(CpuModelExpansionInfo, 1);
     expansion_info->model = g_malloc0(sizeof(*expansion_info->model));
     expansion_info->model->name = g_strdup(model->name);
@@ -200,6 +219,7 @@ CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type,
     riscv_obj_add_multiext_props(obj, qdict_out, riscv_cpu_extensions);
     riscv_obj_add_multiext_props(obj, qdict_out, riscv_cpu_experimental_exts);
     riscv_obj_add_multiext_props(obj, qdict_out, riscv_cpu_vendor_exts);
+    riscv_obj_add_named_feats_qdict(obj, qdict_out);
 
     /* Add our CPU boolean options too */
     riscv_obj_add_qdict_prop(obj, qdict_out, "mmu");
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH v8 10/19] target/riscv: add rva22u64 profile definition
  2023-11-01 20:41 [PATCH v8 00/19] rv64i CPU, RVA22U64 profile support Daniel Henrique Barboza
                   ` (8 preceding siblings ...)
  2023-11-01 20:41 ` [PATCH v8 09/19] riscv-qmp-cmds.c: expose named features in cpu_model_expansion Daniel Henrique Barboza
@ 2023-11-01 20:41 ` Daniel Henrique Barboza
  2023-11-01 20:41 ` [PATCH v8 11/19] target/riscv/kvm: add 'rva22u64' flag as unavailable Daniel Henrique Barboza
                   ` (8 subsequent siblings)
  18 siblings, 0 replies; 31+ messages in thread
From: Daniel Henrique Barboza @ 2023-11-01 20:41 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-riscv, alistair.francis, bmeng, liweiwei, zhiwei_liu, palmer,
	ajones, Daniel Henrique Barboza

The rva22U64 profile, described in:

https://github.com/riscv/riscv-profiles/blob/main/profiles.adoc#rva22-profiles

Contains a set of CPU extensions aimed for 64-bit userspace
applications. Enabling this set to be enabled via a single user flag
makes it convenient to enable a predictable set of features for the CPU,
giving users more predicability when running/testing their workloads.

QEMU implements all possible extensions of this profile. All the so
called 'synthetic extensions' described in the profile that are cache
related are ignored/assumed enabled (Za64rs, Zic64b, Ziccif, Ziccrse,
Ziccamoa, Zicclsm) since we do not implement a cache model.

An abstraction called RISCVCPUProfile is created to store the profile.
'ext_offsets' contains mandatory extensions that QEMU supports. Same
thing with the 'misa_ext' mask. Optional extensions must be enabled
manually in the command line if desired.

The design here is to use the common target/riscv/cpu.c file to store
the profile declaration and export it to the accelerator files. Each
accelerator is then responsible to expose it (or not) to users and how
to enable the extensions.

Next patches will implement the profile for TCG and KVM.

Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
Acked-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
---
 target/riscv/cpu.c | 32 ++++++++++++++++++++++++++++++++
 target/riscv/cpu.h | 12 ++++++++++++
 2 files changed, 44 insertions(+)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index c7c09c1f7c..c5bb2210ab 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -1469,6 +1469,38 @@ Property riscv_cpu_options[] = {
     DEFINE_PROP_END_OF_LIST(),
 };
 
+/*
+ * RVA22U64 defines some 'named features' or 'synthetic extensions'
+ * that are cache related: Za64rs, Zic64b, Ziccif, Ziccrse, Ziccamoa
+ * and Zicclsm. We do not implement caching in QEMU so we'll consider
+ * all these named features as always enabled.
+ *
+ * There's no riscv,isa update for them (nor for zic64b, despite it
+ * having a cfg offset) at this moment.
+ */
+static RISCVCPUProfile RVA22U64 = {
+    .name = "rva22u64",
+    .misa_ext = RVI | RVM | RVA | RVF | RVD | RVC | RVU,
+    .ext_offsets = {
+        CPU_CFG_OFFSET(ext_zicsr), CPU_CFG_OFFSET(ext_zihintpause),
+        CPU_CFG_OFFSET(ext_zba), CPU_CFG_OFFSET(ext_zbb),
+        CPU_CFG_OFFSET(ext_zbs), CPU_CFG_OFFSET(ext_zfhmin),
+        CPU_CFG_OFFSET(ext_zkt), CPU_CFG_OFFSET(ext_zicntr),
+        CPU_CFG_OFFSET(ext_zihpm), CPU_CFG_OFFSET(ext_zicbom),
+        CPU_CFG_OFFSET(ext_zicbop), CPU_CFG_OFFSET(ext_zicboz),
+
+        /* mandatory named features for this profile */
+        CPU_CFG_OFFSET(zic64b),
+
+        RISCV_PROFILE_EXT_LIST_END
+    }
+};
+
+RISCVCPUProfile *riscv_profiles[] = {
+    &RVA22U64,
+    NULL,
+};
+
 static Property riscv_cpu_properties[] = {
     DEFINE_PROP_BOOL("debug", RISCVCPU, cfg.debug, true),
 
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index bf12f34082..e4d5d69207 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -66,6 +66,18 @@ const char *riscv_get_misa_ext_description(uint32_t bit);
 
 #define CPU_CFG_OFFSET(_prop) offsetof(struct RISCVCPUConfig, _prop)
 
+typedef struct riscv_cpu_profile {
+    const char *name;
+    uint32_t misa_ext;
+    bool enabled;
+    bool user_set;
+    const int32_t ext_offsets[];
+} RISCVCPUProfile;
+
+#define RISCV_PROFILE_EXT_LIST_END -1
+
+extern RISCVCPUProfile *riscv_profiles[];
+
 /* Privileged specification version */
 enum {
     PRIV_VERSION_1_10_0 = 0,
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH v8 11/19] target/riscv/kvm: add 'rva22u64' flag as unavailable
  2023-11-01 20:41 [PATCH v8 00/19] rv64i CPU, RVA22U64 profile support Daniel Henrique Barboza
                   ` (9 preceding siblings ...)
  2023-11-01 20:41 ` [PATCH v8 10/19] target/riscv: add rva22u64 profile definition Daniel Henrique Barboza
@ 2023-11-01 20:41 ` Daniel Henrique Barboza
  2023-11-01 20:41 ` [PATCH v8 12/19] target/riscv/tcg: add user flag for profile support Daniel Henrique Barboza
                   ` (7 subsequent siblings)
  18 siblings, 0 replies; 31+ messages in thread
From: Daniel Henrique Barboza @ 2023-11-01 20:41 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-riscv, alistair.francis, bmeng, liweiwei, zhiwei_liu, palmer,
	ajones, Daniel Henrique Barboza

KVM does not have the means to support enabling the rva22u64 profile.
The main reasons are:

- we're missing support for some mandatory rva22u64 extensions in the
  KVM module;

- we can't make promises about enabling a profile since it all depends
  on host support in the end.

We'll revisit this decision in the future if needed. For now mark the
'rva22u64' profile as unavailable when running a KVM CPU:

$ qemu-system-riscv64 -machine virt,accel=kvm -cpu rv64,rva22u64=true
qemu-system-riscv64: can't apply global rv64-riscv-cpu.rva22u64=true:
    'rva22u64' is not available with KVM

Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
---
 target/riscv/kvm/kvm-cpu.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c
index a11c0e4a99..c5167d474a 100644
--- a/target/riscv/kvm/kvm-cpu.c
+++ b/target/riscv/kvm/kvm-cpu.c
@@ -393,7 +393,7 @@ static void cpu_set_cfg_unavailable(Object *obj, Visitor *v,
     }
 
     if (value) {
-        error_setg(errp, "extension %s is not available with KVM",
+        error_setg(errp, "'%s' is not available with KVM",
                    propname);
     }
 }
@@ -474,6 +474,11 @@ static void kvm_riscv_add_cpu_user_properties(Object *cpu_obj)
     riscv_cpu_add_kvm_unavail_prop_array(cpu_obj, riscv_cpu_extensions);
     riscv_cpu_add_kvm_unavail_prop_array(cpu_obj, riscv_cpu_vendor_exts);
     riscv_cpu_add_kvm_unavail_prop_array(cpu_obj, riscv_cpu_experimental_exts);
+
+   /* We don't have the needed KVM support for profiles */
+    for (i = 0; riscv_profiles[i] != NULL; i++) {
+        riscv_cpu_add_kvm_unavail_prop(cpu_obj, riscv_profiles[i]->name);
+    }
 }
 
 static int kvm_riscv_get_regs_core(CPUState *cs)
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH v8 12/19] target/riscv/tcg: add user flag for profile support
  2023-11-01 20:41 [PATCH v8 00/19] rv64i CPU, RVA22U64 profile support Daniel Henrique Barboza
                   ` (10 preceding siblings ...)
  2023-11-01 20:41 ` [PATCH v8 11/19] target/riscv/kvm: add 'rva22u64' flag as unavailable Daniel Henrique Barboza
@ 2023-11-01 20:41 ` Daniel Henrique Barboza
  2023-11-01 20:41 ` [PATCH v8 13/19] target/riscv/tcg: add MISA user options hash Daniel Henrique Barboza
                   ` (6 subsequent siblings)
  18 siblings, 0 replies; 31+ messages in thread
From: Daniel Henrique Barboza @ 2023-11-01 20:41 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-riscv, alistair.francis, bmeng, liweiwei, zhiwei_liu, palmer,
	ajones, Daniel Henrique Barboza

The TCG emulation implements all the extensions described in the
RVA22U64 profile, both mandatory and optional. The mandatory extensions
will be enabled via the profile flag. We'll leave the optional
extensions to be enabled by hand.

Given that this is the first profile we're implementing in TCG we'll
need some ground work first:

- all profiles declared in riscv_profiles[] will be exposed to users.
TCG is the main accelerator we're considering when adding profile
support in QEMU, so for now it's safe to assume that all profiles in
riscv_profiles[] will be relevant to TCG;

- we'll not support user profile settings for vendor CPUs. The flags
will still be exposed but users won't be able to change them;

- profile support, albeit available for all non-vendor CPUs, will be
based on top of the new 'rv64i' CPU. Setting a profile to 'true' means
enable all mandatory extensions of this profile, setting it to 'false'
will disable all mandatory profile extensions of the CPU, which will
obliterate preset defaults. This is not a problem for a bare CPU like
rv64i but it can allow for silly scenarios when using other CPUs. E.g.
an user can do "-cpu rv64,rva22u64=false" and have a bunch of default
rv64 extensions disabled. The recommended way of using profiles is the
rv64i CPU, but users are free to experiment.

For now we'll handle multi-letter extensions only. MISA extensions need
additional steps that we'll take care later. At this point we can boot a
Linux buildroot using rva22u64 using the following options:

-cpu rv64i,rva22u64=true,sv39=true,g=true,c=true,s=true

Note that being an usermode/application profile we still need to
explicitly set 's=true' to enable Supervisor mode to boot Linux.

Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
---
 target/riscv/tcg/tcg-cpu.c | 63 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 63 insertions(+)

diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
index a577cd795a..cfe7375c42 100644
--- a/target/riscv/tcg/tcg-cpu.c
+++ b/target/riscv/tcg/tcg-cpu.c
@@ -821,6 +821,67 @@ static void riscv_cpu_add_misa_properties(Object *cpu_obj)
     }
 }
 
+static void cpu_set_profile(Object *obj, Visitor *v, const char *name,
+                            void *opaque, Error **errp)
+{
+    RISCVCPUProfile *profile = opaque;
+    RISCVCPU *cpu = RISCV_CPU(obj);
+    bool value;
+    int i, ext_offset;
+
+    if (object_dynamic_cast(obj, TYPE_RISCV_VENDOR_CPU) != NULL) {
+        error_setg(errp, "Profile %s is not available for vendor CPUs",
+                   profile->name);
+        return;
+    }
+
+    if (cpu->env.misa_mxl != MXL_RV64) {
+        error_setg(errp, "Profile %s only available for 64 bit CPUs",
+                   profile->name);
+        return;
+    }
+
+    if (!visit_type_bool(v, name, &value, errp)) {
+        return;
+    }
+
+    profile->user_set = true;
+    profile->enabled = value;
+
+    for (i = 0; profile->ext_offsets[i] != RISCV_PROFILE_EXT_LIST_END; i++) {
+        ext_offset = profile->ext_offsets[i];
+
+        if (profile->enabled) {
+            cpu_validate_multi_ext_priv_ver(&cpu->env, ext_offset);
+        }
+
+        g_hash_table_insert(multi_ext_user_opts,
+                            GUINT_TO_POINTER(ext_offset),
+                            (gpointer)profile->enabled);
+        isa_ext_update_enabled(cpu, ext_offset, profile->enabled);
+    }
+}
+
+static void cpu_get_profile(Object *obj, Visitor *v, const char *name,
+                            void *opaque, Error **errp)
+{
+    RISCVCPUProfile *profile = opaque;
+    bool value = profile->enabled;
+
+    visit_type_bool(v, name, &value, errp);
+}
+
+static void riscv_cpu_add_profiles(Object *cpu_obj)
+{
+    for (int i = 0; riscv_profiles[i] != NULL; i++) {
+        const RISCVCPUProfile *profile = riscv_profiles[i];
+
+        object_property_add(cpu_obj, profile->name, "bool",
+                            cpu_get_profile, cpu_set_profile,
+                            NULL, (void *)profile);
+    }
+}
+
 static bool cpu_ext_is_deprecated(const char *ext_name)
 {
     return isupper(ext_name[0]);
@@ -948,6 +1009,8 @@ static void riscv_cpu_add_user_properties(Object *obj)
 
     riscv_cpu_add_multiext_prop_array(obj, riscv_cpu_deprecated_exts);
 
+    riscv_cpu_add_profiles(obj);
+
     for (Property *prop = riscv_cpu_options; prop && prop->name; prop++) {
         qdev_property_add_static(DEVICE(obj), prop);
     }
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH v8 13/19] target/riscv/tcg: add MISA user options hash
  2023-11-01 20:41 [PATCH v8 00/19] rv64i CPU, RVA22U64 profile support Daniel Henrique Barboza
                   ` (11 preceding siblings ...)
  2023-11-01 20:41 ` [PATCH v8 12/19] target/riscv/tcg: add user flag for profile support Daniel Henrique Barboza
@ 2023-11-01 20:41 ` Daniel Henrique Barboza
  2023-11-01 20:41 ` [PATCH v8 14/19] target/riscv/tcg: add riscv_cpu_write_misa_bit() Daniel Henrique Barboza
                   ` (5 subsequent siblings)
  18 siblings, 0 replies; 31+ messages in thread
From: Daniel Henrique Barboza @ 2023-11-01 20:41 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-riscv, alistair.francis, bmeng, liweiwei, zhiwei_liu, palmer,
	ajones, Daniel Henrique Barboza

We already track user choice for multi-letter extensions because we
needed to honor user choice when enabling/disabling extensions during
realize(). We refrained from adding the same mechanism for MISA
extensions since we didn't need it.

Profile support requires tne need to check for user choice for MISA
extensions, so let's add the corresponding hash now. It works like the
existing multi-letter hash (multi_ext_user_opts) but tracking MISA bits
options in the cpu_set_misa_ext_cfg() callback.

Note that we can't re-use the same hash from multi-letter extensions
because that hash uses cpu->cfg offsets as keys, while for MISA
extensions we're using MISA bits as keys.

After adding the user hash in cpu_set_misa_ext_cfg(), setting default
values with object_property_set_bool() in add_misa_properties() will end
up marking the user choice hash with them. Set the default value
manually to avoid it.

Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
---
 target/riscv/tcg/tcg-cpu.c | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
index cfe7375c42..dd9eea3d0e 100644
--- a/target/riscv/tcg/tcg-cpu.c
+++ b/target/riscv/tcg/tcg-cpu.c
@@ -34,6 +34,7 @@
 
 /* Hash that stores user set extensions */
 static GHashTable *multi_ext_user_opts;
+static GHashTable *misa_ext_user_opts;
 
 static bool cpu_cfg_ext_is_user_set(uint32_t ext_offset)
 {
@@ -733,6 +734,10 @@ static void cpu_set_misa_ext_cfg(Object *obj, Visitor *v, const char *name,
         return;
     }
 
+    g_hash_table_insert(misa_ext_user_opts,
+                        GUINT_TO_POINTER(misa_bit),
+                        (gpointer)value);
+
     prev_val = env->misa_ext & misa_bit;
 
     if (value == prev_val) {
@@ -796,6 +801,7 @@ static const RISCVCPUMisaExtConfig misa_ext_cfgs[] = {
  */
 static void riscv_cpu_add_misa_properties(Object *cpu_obj)
 {
+    CPURISCVState *env = &RISCV_CPU(cpu_obj)->env;
     bool use_def_vals = riscv_cpu_is_generic(cpu_obj);
     int i;
 
@@ -816,7 +822,13 @@ static void riscv_cpu_add_misa_properties(Object *cpu_obj)
                             NULL, (void *)misa_cfg);
         object_property_set_description(cpu_obj, name, desc);
         if (use_def_vals) {
-            object_property_set_bool(cpu_obj, name, misa_cfg->enabled, NULL);
+            if (misa_cfg->enabled) {
+                env->misa_ext |= bit;
+                env->misa_ext_mask |= bit;
+            } else {
+                env->misa_ext &= ~bit;
+                env->misa_ext_mask &= ~bit;
+            }
         }
     }
 }
@@ -1061,6 +1073,7 @@ static void tcg_cpu_instance_init(CPUState *cs)
     RISCVCPU *cpu = RISCV_CPU(cs);
     Object *obj = OBJECT(cpu);
 
+    misa_ext_user_opts = g_hash_table_new(NULL, g_direct_equal);
     multi_ext_user_opts = g_hash_table_new(NULL, g_direct_equal);
     riscv_cpu_add_user_properties(obj);
 
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH v8 14/19] target/riscv/tcg: add riscv_cpu_write_misa_bit()
  2023-11-01 20:41 [PATCH v8 00/19] rv64i CPU, RVA22U64 profile support Daniel Henrique Barboza
                   ` (12 preceding siblings ...)
  2023-11-01 20:41 ` [PATCH v8 13/19] target/riscv/tcg: add MISA user options hash Daniel Henrique Barboza
@ 2023-11-01 20:41 ` Daniel Henrique Barboza
  2023-11-01 20:42 ` [PATCH v8 15/19] target/riscv/tcg: handle profile MISA bits Daniel Henrique Barboza
                   ` (4 subsequent siblings)
  18 siblings, 0 replies; 31+ messages in thread
From: Daniel Henrique Barboza @ 2023-11-01 20:41 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-riscv, alistair.francis, bmeng, liweiwei, zhiwei_liu, palmer,
	ajones, Daniel Henrique Barboza

We have two instances of the setting/clearing a MISA bit from
env->misa_ext and env->misa_ext_mask pattern. And the next patch will
end up adding one more.

Create a helper to avoid code repetition.

Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
---
 target/riscv/tcg/tcg-cpu.c | 44 ++++++++++++++++++++------------------
 1 file changed, 23 insertions(+), 21 deletions(-)

diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
index dd9eea3d0e..707da775a0 100644
--- a/target/riscv/tcg/tcg-cpu.c
+++ b/target/riscv/tcg/tcg-cpu.c
@@ -42,6 +42,20 @@ static bool cpu_cfg_ext_is_user_set(uint32_t ext_offset)
                                  GUINT_TO_POINTER(ext_offset));
 }
 
+static void riscv_cpu_write_misa_bit(RISCVCPU *cpu, uint32_t bit,
+                                     bool enabled)
+{
+    CPURISCVState *env = &cpu->env;
+
+    if (enabled) {
+        env->misa_ext |= bit;
+        env->misa_ext_mask |= bit;
+    } else {
+        env->misa_ext &= ~bit;
+        env->misa_ext_mask &= ~bit;
+    }
+}
+
 static void riscv_cpu_synchronize_from_tb(CPUState *cs,
                                           const TranslationBlock *tb)
 {
@@ -744,20 +758,14 @@ static void cpu_set_misa_ext_cfg(Object *obj, Visitor *v, const char *name,
         return;
     }
 
-    if (value) {
-        if (vendor_cpu) {
-            g_autofree char *cpuname = riscv_cpu_get_name(cpu);
-            error_setg(errp, "'%s' CPU does not allow enabling extensions",
-                       cpuname);
-            return;
-        }
-
-        env->misa_ext |= misa_bit;
-        env->misa_ext_mask |= misa_bit;
-    } else {
-        env->misa_ext &= ~misa_bit;
-        env->misa_ext_mask &= ~misa_bit;
+    if (value && vendor_cpu) {
+        g_autofree char *cpuname = riscv_cpu_get_name(cpu);
+        error_setg(errp, "'%s' CPU does not allow enabling extensions",
+                   cpuname);
+        return;
     }
+
+    riscv_cpu_write_misa_bit(cpu, misa_bit, value);
 }
 
 static void cpu_get_misa_ext_cfg(Object *obj, Visitor *v, const char *name,
@@ -801,7 +809,6 @@ static const RISCVCPUMisaExtConfig misa_ext_cfgs[] = {
  */
 static void riscv_cpu_add_misa_properties(Object *cpu_obj)
 {
-    CPURISCVState *env = &RISCV_CPU(cpu_obj)->env;
     bool use_def_vals = riscv_cpu_is_generic(cpu_obj);
     int i;
 
@@ -822,13 +829,8 @@ static void riscv_cpu_add_misa_properties(Object *cpu_obj)
                             NULL, (void *)misa_cfg);
         object_property_set_description(cpu_obj, name, desc);
         if (use_def_vals) {
-            if (misa_cfg->enabled) {
-                env->misa_ext |= bit;
-                env->misa_ext_mask |= bit;
-            } else {
-                env->misa_ext &= ~bit;
-                env->misa_ext_mask &= ~bit;
-            }
+            riscv_cpu_write_misa_bit(RISCV_CPU(cpu_obj), bit,
+                                     misa_cfg->enabled);
         }
     }
 }
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH v8 15/19] target/riscv/tcg: handle profile MISA bits
  2023-11-01 20:41 [PATCH v8 00/19] rv64i CPU, RVA22U64 profile support Daniel Henrique Barboza
                   ` (13 preceding siblings ...)
  2023-11-01 20:41 ` [PATCH v8 14/19] target/riscv/tcg: add riscv_cpu_write_misa_bit() Daniel Henrique Barboza
@ 2023-11-01 20:42 ` Daniel Henrique Barboza
  2023-11-01 20:42 ` [PATCH v8 16/19] target/riscv/tcg: add hash table insert helpers Daniel Henrique Barboza
                   ` (3 subsequent siblings)
  18 siblings, 0 replies; 31+ messages in thread
From: Daniel Henrique Barboza @ 2023-11-01 20:42 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-riscv, alistair.francis, bmeng, liweiwei, zhiwei_liu, palmer,
	ajones, Daniel Henrique Barboza

The profile support is handling multi-letter extensions only. Let's add
support for MISA bits as well.

We'll go through every known MISA bit. If the profile doesn't declare
the bit as mandatory, ignore it. Otherwise, set the bit in env->misa_ext
and env->misa_ext_mask.

Now that we're setting profile MISA bits, one can use the rv64i CPU to boot
Linux using the following options:

-cpu rv64i,rva22u64=true,rv39=true,s=true,zifencei=true

In the near future, when rva22s64 (where, 's', 'zifencei' and sv39 are
mandatory), is implemented, rv64i will be able to boot Linux loading
rva22s64 and no additional flags.

Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
Reviewed-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
---
 target/riscv/tcg/tcg-cpu.c | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
index 707da775a0..4b3e20545a 100644
--- a/target/riscv/tcg/tcg-cpu.c
+++ b/target/riscv/tcg/tcg-cpu.c
@@ -862,6 +862,27 @@ static void cpu_set_profile(Object *obj, Visitor *v, const char *name,
     profile->user_set = true;
     profile->enabled = value;
 
+    for (i = 0; misa_bits[i] != 0; i++) {
+        uint32_t bit = misa_bits[i];
+
+        if  (!(profile->misa_ext & bit)) {
+            continue;
+        }
+
+        if (bit == RVI && !profile->enabled) {
+            /*
+             * Disabling profiles will not disable the base
+             * ISA RV64I.
+             */
+            continue;
+        }
+
+        g_hash_table_insert(misa_ext_user_opts,
+                            GUINT_TO_POINTER(bit),
+                            (gpointer)value);
+        riscv_cpu_write_misa_bit(cpu, bit, profile->enabled);
+    }
+
     for (i = 0; profile->ext_offsets[i] != RISCV_PROFILE_EXT_LIST_END; i++) {
         ext_offset = profile->ext_offsets[i];
 
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH v8 16/19] target/riscv/tcg: add hash table insert helpers
  2023-11-01 20:41 [PATCH v8 00/19] rv64i CPU, RVA22U64 profile support Daniel Henrique Barboza
                   ` (14 preceding siblings ...)
  2023-11-01 20:42 ` [PATCH v8 15/19] target/riscv/tcg: handle profile MISA bits Daniel Henrique Barboza
@ 2023-11-01 20:42 ` Daniel Henrique Barboza
  2023-11-01 20:42 ` [PATCH v8 17/19] target/riscv/tcg: honor user choice for G MISA bits Daniel Henrique Barboza
                   ` (2 subsequent siblings)
  18 siblings, 0 replies; 31+ messages in thread
From: Daniel Henrique Barboza @ 2023-11-01 20:42 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-riscv, alistair.francis, bmeng, liweiwei, zhiwei_liu, palmer,
	ajones, Daniel Henrique Barboza

Previous patches added several g_hash_table_insert() patterns. Add two
helpers, one for each user hash, to make the code cleaner.

Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
---
 target/riscv/tcg/tcg-cpu.c | 28 ++++++++++++++++------------
 1 file changed, 16 insertions(+), 12 deletions(-)

diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
index 4b3e20545a..042f28a093 100644
--- a/target/riscv/tcg/tcg-cpu.c
+++ b/target/riscv/tcg/tcg-cpu.c
@@ -42,6 +42,18 @@ static bool cpu_cfg_ext_is_user_set(uint32_t ext_offset)
                                  GUINT_TO_POINTER(ext_offset));
 }
 
+static void cpu_cfg_ext_add_user_opt(uint32_t ext_offset, bool value)
+{
+    g_hash_table_insert(multi_ext_user_opts, GUINT_TO_POINTER(ext_offset),
+                        (gpointer)value);
+}
+
+static void cpu_misa_ext_add_user_opt(uint32_t bit, bool value)
+{
+    g_hash_table_insert(misa_ext_user_opts, GUINT_TO_POINTER(bit),
+                        (gpointer)value);
+}
+
 static void riscv_cpu_write_misa_bit(RISCVCPU *cpu, uint32_t bit,
                                      bool enabled)
 {
@@ -748,9 +760,7 @@ static void cpu_set_misa_ext_cfg(Object *obj, Visitor *v, const char *name,
         return;
     }
 
-    g_hash_table_insert(misa_ext_user_opts,
-                        GUINT_TO_POINTER(misa_bit),
-                        (gpointer)value);
+    cpu_misa_ext_add_user_opt(misa_bit, value);
 
     prev_val = env->misa_ext & misa_bit;
 
@@ -877,9 +887,7 @@ static void cpu_set_profile(Object *obj, Visitor *v, const char *name,
             continue;
         }
 
-        g_hash_table_insert(misa_ext_user_opts,
-                            GUINT_TO_POINTER(bit),
-                            (gpointer)value);
+        cpu_misa_ext_add_user_opt(bit, profile->enabled);
         riscv_cpu_write_misa_bit(cpu, bit, profile->enabled);
     }
 
@@ -890,9 +898,7 @@ static void cpu_set_profile(Object *obj, Visitor *v, const char *name,
             cpu_validate_multi_ext_priv_ver(&cpu->env, ext_offset);
         }
 
-        g_hash_table_insert(multi_ext_user_opts,
-                            GUINT_TO_POINTER(ext_offset),
-                            (gpointer)profile->enabled);
+        cpu_cfg_ext_add_user_opt(ext_offset, profile->enabled);
         isa_ext_update_enabled(cpu, ext_offset, profile->enabled);
     }
 }
@@ -955,9 +961,7 @@ static void cpu_set_multi_ext_cfg(Object *obj, Visitor *v, const char *name,
                     multi_ext_cfg->name, lower);
     }
 
-    g_hash_table_insert(multi_ext_user_opts,
-                        GUINT_TO_POINTER(multi_ext_cfg->offset),
-                        (gpointer)value);
+    cpu_cfg_ext_add_user_opt(multi_ext_cfg->offset, value);
 
     prev_val = isa_ext_is_enabled(cpu, multi_ext_cfg->offset);
 
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH v8 17/19] target/riscv/tcg: honor user choice for G MISA bits
  2023-11-01 20:41 [PATCH v8 00/19] rv64i CPU, RVA22U64 profile support Daniel Henrique Barboza
                   ` (15 preceding siblings ...)
  2023-11-01 20:42 ` [PATCH v8 16/19] target/riscv/tcg: add hash table insert helpers Daniel Henrique Barboza
@ 2023-11-01 20:42 ` Daniel Henrique Barboza
  2023-11-01 20:42 ` [PATCH v8 18/19] target/riscv/tcg: validate profiles during finalize Daniel Henrique Barboza
  2023-11-01 20:42 ` [PATCH v8 19/19] riscv-qmp-cmds.c: add profile flags in cpu-model-expansion Daniel Henrique Barboza
  18 siblings, 0 replies; 31+ messages in thread
From: Daniel Henrique Barboza @ 2023-11-01 20:42 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-riscv, alistair.francis, bmeng, liweiwei, zhiwei_liu, palmer,
	ajones, Daniel Henrique Barboza

RVG behaves like a profile: a single flag enables a set of bits. Right
now we're considering user choice when handling RVG and zicsr/zifencei
and ignoring user choice on MISA bits.

We'll add user warnings for profiles when the user disables its
mandatory extensions in the next patch. We'll do the same thing with RVG
now to keep consistency between RVG and profile handling.

First and foremost, create a new RVG only helper to avoid clogging
riscv_cpu_validate_set_extensions(). We do not want to annoy users with
RVG warnings like we did in the past (see 9b9741c38f), thus we'll only
warn if RVG was user set and the user disabled a RVG extension in the
command line.

For every RVG MISA bit (IMAFD), zicsr and zifencei, the logic then
becomes:

- if enabled, do nothing;
- if disabled and not user set, enable it;
- if disabled and user set, throw a warning that it's a RVG mandatory
  extension.

This same logic will be used for profiles in the next patch.

Note that this is a behavior change, where we would error out if the
user disabled either zicsr or zifencei. As long as users are explicitly
disabling things in the command line we'll let them have a go at it, at
least in this step. We'll error out later in the validation if needed.

Other notable changes from the previous RVG code:

- use riscv_cpu_write_misa_bit() instead of manually updating both
  env->misa_ext and env->misa_ext_mask;

- set zicsr and zifencei directly. We're already checking if they
  were user set and priv version will never fail for these
  extensions, making cpu_cfg_ext_auto_update() redundant.

Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
---
 target/riscv/tcg/tcg-cpu.c | 73 +++++++++++++++++++++++++-------------
 1 file changed, 48 insertions(+), 25 deletions(-)

diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
index 042f28a093..91459f2ce9 100644
--- a/target/riscv/tcg/tcg-cpu.c
+++ b/target/riscv/tcg/tcg-cpu.c
@@ -42,6 +42,12 @@ static bool cpu_cfg_ext_is_user_set(uint32_t ext_offset)
                                  GUINT_TO_POINTER(ext_offset));
 }
 
+static bool cpu_misa_ext_is_user_set(uint32_t misa_bit)
+{
+    return g_hash_table_contains(misa_ext_user_opts,
+                                 GUINT_TO_POINTER(misa_bit));
+}
+
 static void cpu_cfg_ext_add_user_opt(uint32_t ext_offset, bool value)
 {
     g_hash_table_insert(multi_ext_user_opts, GUINT_TO_POINTER(ext_offset),
@@ -336,6 +342,46 @@ static void riscv_cpu_validate_named_features(RISCVCPU *cpu)
     riscv_cpu_validate_zic64b(cpu);
 }
 
+static void riscv_cpu_validate_g(RISCVCPU *cpu)
+{
+    const char *warn_msg = "RVG mandates disabled extension %s";
+    uint32_t g_misa_bits[] = {RVI, RVM, RVA, RVF, RVD};
+    bool send_warn = cpu_misa_ext_is_user_set(RVG);
+
+    for (int i = 0; i < ARRAY_SIZE(g_misa_bits); i++) {
+        uint32_t bit = g_misa_bits[i];
+
+        if (riscv_has_ext(&cpu->env, bit)) {
+            continue;
+        }
+
+        if (!cpu_misa_ext_is_user_set(bit)) {
+            riscv_cpu_write_misa_bit(cpu, bit, true);
+            continue;
+        }
+
+        if (send_warn) {
+            warn_report(warn_msg, riscv_get_misa_ext_name(bit));
+        }
+    }
+
+    if (!cpu->cfg.ext_zicsr) {
+        if (!cpu_cfg_ext_is_user_set(CPU_CFG_OFFSET(ext_zicsr))) {
+            cpu->cfg.ext_zicsr = true;
+        } else if (send_warn) {
+            warn_report(warn_msg, "zicsr");
+        }
+    }
+
+    if (!cpu->cfg.ext_zifencei) {
+        if (!cpu_cfg_ext_is_user_set(CPU_CFG_OFFSET(ext_zifencei))) {
+            cpu->cfg.ext_zifencei = true;
+        } else if (send_warn) {
+            warn_report(warn_msg, "zifencei");
+        }
+    }
+}
+
 /*
  * Check consistency between chosen extensions while setting
  * cpu->cfg accordingly.
@@ -345,31 +391,8 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp)
     CPURISCVState *env = &cpu->env;
     Error *local_err = NULL;
 
-    /* Do some ISA extension error checking */
-    if (riscv_has_ext(env, RVG) &&
-        !(riscv_has_ext(env, RVI) && riscv_has_ext(env, RVM) &&
-          riscv_has_ext(env, RVA) && riscv_has_ext(env, RVF) &&
-          riscv_has_ext(env, RVD) &&
-          cpu->cfg.ext_zicsr && cpu->cfg.ext_zifencei)) {
-
-        if (cpu_cfg_ext_is_user_set(CPU_CFG_OFFSET(ext_zicsr)) &&
-            !cpu->cfg.ext_zicsr) {
-            error_setg(errp, "RVG requires Zicsr but user set Zicsr to false");
-            return;
-        }
-
-        if (cpu_cfg_ext_is_user_set(CPU_CFG_OFFSET(ext_zifencei)) &&
-            !cpu->cfg.ext_zifencei) {
-            error_setg(errp, "RVG requires Zifencei but user set "
-                       "Zifencei to false");
-            return;
-        }
-
-        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zicsr), true);
-        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zifencei), true);
-
-        env->misa_ext |= RVI | RVM | RVA | RVF | RVD;
-        env->misa_ext_mask |= RVI | RVM | RVA | RVF | RVD;
+    if (riscv_has_ext(env, RVG)) {
+        riscv_cpu_validate_g(cpu);
     }
 
     if (riscv_has_ext(env, RVI) && riscv_has_ext(env, RVE)) {
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH v8 18/19] target/riscv/tcg: validate profiles during finalize
  2023-11-01 20:41 [PATCH v8 00/19] rv64i CPU, RVA22U64 profile support Daniel Henrique Barboza
                   ` (16 preceding siblings ...)
  2023-11-01 20:42 ` [PATCH v8 17/19] target/riscv/tcg: honor user choice for G MISA bits Daniel Henrique Barboza
@ 2023-11-01 20:42 ` Daniel Henrique Barboza
  2023-11-01 20:42 ` [PATCH v8 19/19] riscv-qmp-cmds.c: add profile flags in cpu-model-expansion Daniel Henrique Barboza
  18 siblings, 0 replies; 31+ messages in thread
From: Daniel Henrique Barboza @ 2023-11-01 20:42 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-riscv, alistair.francis, bmeng, liweiwei, zhiwei_liu, palmer,
	ajones, Daniel Henrique Barboza

Enabling a profile and then disabling some of its mandatory extensions
is a valid use. It can be useful for debugging and testing. But the
common expected use of enabling a profile is to enable all its mandatory
extensions.

Add an user warning when mandatory extensions from an enabled profile
are disabled in the command line. We're also going to disable the
profile flag in this case since the profile must include all the
mandatory extensions. This flag can be exposed by QMP to indicate the
actual profile state after the CPU is realized.

After this patch, this will throw warnings:

-cpu rv64,rva22u64=true,zihintpause=false,zicbom=false,zicboz=false

qemu-system-riscv64: warning: Profile rva22u64 mandates disabled extension zihintpause
qemu-system-riscv64: warning: Profile rva22u64 mandates disabled extension zicbom
qemu-system-riscv64: warning: Profile rva22u64 mandates disabled extension zicboz

Note that the following will NOT throw warnings because the profile is
being enabled last, hence all its mandatory extensions will be enabled:

-cpu rv64,zihintpause=false,zicbom=false,zicboz=false,rva22u64=true

Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
---
 target/riscv/tcg/tcg-cpu.c | 69 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 69 insertions(+)

diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
index 91459f2ce9..ecf2bcd7ad 100644
--- a/target/riscv/tcg/tcg-cpu.c
+++ b/target/riscv/tcg/tcg-cpu.c
@@ -147,6 +147,26 @@ static int cpu_cfg_ext_get_min_version(uint32_t ext_offset)
     g_assert_not_reached();
 }
 
+static const char *cpu_cfg_ext_get_name(uint32_t ext_offset)
+{
+    const RISCVCPUMultiExtConfig *feat;
+    const RISCVIsaExtData *edata;
+
+    for (edata = isa_edata_arr; edata->name != NULL; edata++) {
+        if (edata->ext_enable_offset == ext_offset) {
+            return edata->name;
+        }
+    }
+
+    for (feat = riscv_cpu_named_features; feat->name != NULL; feat++) {
+        if (feat->offset == ext_offset) {
+            return feat->name;
+        }
+    }
+
+    g_assert_not_reached();
+}
+
 static bool cpu_cfg_offset_is_named_feat(uint32_t ext_offset)
 {
     const RISCVCPUMultiExtConfig *feat;
@@ -664,6 +684,54 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp)
     riscv_cpu_disable_priv_spec_isa_exts(cpu);
 }
 
+static void riscv_cpu_validate_profile(RISCVCPU *cpu,
+                                       RISCVCPUProfile *profile)
+{
+    const char *warn_msg = "Profile %s mandates disabled extension %s";
+    bool send_warn = profile->user_set && profile->enabled;
+    bool profile_impl = true;
+    int i;
+
+    for (i = 0; misa_bits[i] != 0; i++) {
+        uint32_t bit = misa_bits[i];
+
+        if (!(profile->misa_ext & bit)) {
+            continue;
+        }
+
+        if (!riscv_has_ext(&cpu->env, bit)) {
+            profile_impl = false;
+
+            if (send_warn) {
+                warn_report(warn_msg, profile->name,
+                            riscv_get_misa_ext_name(bit));
+            }
+        }
+    }
+
+    for (i = 0; profile->ext_offsets[i] != RISCV_PROFILE_EXT_LIST_END; i++) {
+        int ext_offset = profile->ext_offsets[i];
+
+        if (!isa_ext_is_enabled(cpu, ext_offset)) {
+            profile_impl = false;
+
+            if (send_warn) {
+                warn_report(warn_msg, profile->name,
+                            cpu_cfg_ext_get_name(ext_offset));
+            }
+        }
+    }
+
+    profile->enabled = profile_impl;
+}
+
+static void riscv_cpu_validate_profiles(RISCVCPU *cpu)
+{
+    for (int i = 0; riscv_profiles[i] != NULL; i++) {
+        riscv_cpu_validate_profile(cpu, riscv_profiles[i]);
+    }
+}
+
 void riscv_tcg_cpu_finalize_features(RISCVCPU *cpu, Error **errp)
 {
     CPURISCVState *env = &cpu->env;
@@ -682,6 +750,7 @@ void riscv_tcg_cpu_finalize_features(RISCVCPU *cpu, Error **errp)
     }
 
     riscv_cpu_validate_named_features(cpu);
+    riscv_cpu_validate_profiles(cpu);
 
     if (cpu->cfg.ext_smepmp && !cpu->cfg.pmp) {
         /*
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH v8 19/19] riscv-qmp-cmds.c: add profile flags in cpu-model-expansion
  2023-11-01 20:41 [PATCH v8 00/19] rv64i CPU, RVA22U64 profile support Daniel Henrique Barboza
                   ` (17 preceding siblings ...)
  2023-11-01 20:42 ` [PATCH v8 18/19] target/riscv/tcg: validate profiles during finalize Daniel Henrique Barboza
@ 2023-11-01 20:42 ` Daniel Henrique Barboza
  18 siblings, 0 replies; 31+ messages in thread
From: Daniel Henrique Barboza @ 2023-11-01 20:42 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-riscv, alistair.francis, bmeng, liweiwei, zhiwei_liu, palmer,
	ajones, Daniel Henrique Barboza

Expose all profile flags for all CPUs when executing
query-cpu-model-expansion. This will allow callers to quickly determine
if a certain profile is implemented by a given CPU. This includes
vendor CPUs - the fact that they don't have profile user flags doesn't
mean that they don't implement the profile.

After this change it's possible to quickly determine if our stock CPUs
implement the existing rva22u64 profile. Here's a few examples:

 $ ./build/qemu-system-riscv64 -S -M virt -display none
-qmp tcp:localhost:1234,server,wait=off

 $ ./scripts/qmp/qmp-shell localhost:1234
Welcome to the QMP low-level shell!
Connected to QEMU 8.1.50

- As expected, the 'max' CPU implements the rva22u64 profile.

(QEMU) query-cpu-model-expansion type=full model={"name":"max"}
    {"return": {"model":
        {"name": "rv64", "props": {... "rva22u64": true, ...}}}}

- rv64 is missing "zba", "zbb", "zbs", "zkt" and "zfhmin":

query-cpu-model-expansion type=full model={"name":"rv64"}
    {"return": {"model":
        {"name": "rv64", "props": {... "rva22u64": false, ...}}}}

query-cpu-model-expansion type=full model={"name":"rv64",
    "props":{"zba":true,"zbb":true,"zbs":true,"zkt":true,"zfhmin":true}}
    {"return": {"model":
        {"name": "rv64", "props": {... "rva22u64": true, ...}}}}

We have no vendor CPUs that supports rva22u64 (veyron-v1 is the closest
- it is missing just 'zkt').

In short, aside from the 'max' CPU, we have no CPUs that supports
rva22u64 by default.

Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
---
 target/riscv/riscv-qmp-cmds.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/target/riscv/riscv-qmp-cmds.c b/target/riscv/riscv-qmp-cmds.c
index 5ada279776..205aaabeb9 100644
--- a/target/riscv/riscv-qmp-cmds.c
+++ b/target/riscv/riscv-qmp-cmds.c
@@ -116,6 +116,19 @@ static void riscv_obj_add_named_feats_qdict(Object *obj, QDict *qdict_out)
     }
 }
 
+static void riscv_obj_add_profiles_qdict(Object *obj, QDict *qdict_out)
+{
+    RISCVCPUProfile *profile;
+    QObject *value;
+
+    for (int i = 0; riscv_profiles[i] != NULL; i++) {
+        profile = riscv_profiles[i];
+        value = QOBJECT(qbool_from_bool(profile->enabled));
+
+        qdict_put_obj(qdict_out, profile->name, value);
+    }
+}
+
 static void riscv_cpuobj_validate_qdict_in(Object *obj, QObject *props,
                                            const QDict *qdict_in,
                                            Error **errp)
@@ -220,6 +233,7 @@ CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type,
     riscv_obj_add_multiext_props(obj, qdict_out, riscv_cpu_experimental_exts);
     riscv_obj_add_multiext_props(obj, qdict_out, riscv_cpu_vendor_exts);
     riscv_obj_add_named_feats_qdict(obj, qdict_out);
+    riscv_obj_add_profiles_qdict(obj, qdict_out);
 
     /* Add our CPU boolean options too */
     riscv_obj_add_qdict_prop(obj, qdict_out, "mmu");
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 31+ messages in thread

* Re: [PATCH v8 01/19] target/riscv: create TYPE_RISCV_VENDOR_CPU
  2023-11-01 20:41 ` [PATCH v8 01/19] target/riscv: create TYPE_RISCV_VENDOR_CPU Daniel Henrique Barboza
@ 2023-11-02  2:32   ` Alistair Francis
  0 siblings, 0 replies; 31+ messages in thread
From: Alistair Francis @ 2023-11-02  2:32 UTC (permalink / raw)
  To: Daniel Henrique Barboza
  Cc: qemu-devel, qemu-riscv, alistair.francis, bmeng, liweiwei,
	zhiwei_liu, palmer, ajones

On Thu, Nov 2, 2023 at 7:53 AM Daniel Henrique Barboza
<dbarboza@ventanamicro.com> wrote:
>
> We want to add a new CPU type for bare CPUs that will inherit specific
> traits of the 2 existing types:
>
> - it will allow for extensions to be enabled/disabled, like generic
>   CPUs;
>
> - it will NOT inherit defaults, like vendor CPUs.
>
> We can make this conditions met by adding an explicit type for the
> existing vendor CPUs and change the existing logic to not imply that
> "not generic" means vendor CPUs.
>
> Let's add the "vendor" CPU type first.
>
> Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
> Reviewed-by: Andrew Jones <ajones@ventanamicro.com>

Reviewed-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>  target/riscv/cpu-qom.h |  1 +
>  target/riscv/cpu.c     | 30 +++++++++++++++++++++---------
>  2 files changed, 22 insertions(+), 9 deletions(-)
>
> diff --git a/target/riscv/cpu-qom.h b/target/riscv/cpu-qom.h
> index f3fbe37a2c..7831e86d37 100644
> --- a/target/riscv/cpu-qom.h
> +++ b/target/riscv/cpu-qom.h
> @@ -24,6 +24,7 @@
>
>  #define TYPE_RISCV_CPU "riscv-cpu"
>  #define TYPE_RISCV_DYNAMIC_CPU "riscv-dynamic-cpu"
> +#define TYPE_RISCV_VENDOR_CPU "riscv-vendor-cpu"
>
>  #define RISCV_CPU_TYPE_SUFFIX "-" TYPE_RISCV_CPU
>  #define RISCV_CPU_TYPE_NAME(name) (name RISCV_CPU_TYPE_SUFFIX)
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index f40da4c661..822970345c 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -1725,6 +1725,13 @@ void riscv_cpu_list(void)
>          .instance_init = initfn               \
>      }
>
> +#define DEFINE_VENDOR_CPU(type_name, initfn) \
> +    {                                        \
> +        .name = type_name,                   \
> +        .parent = TYPE_RISCV_VENDOR_CPU,     \
> +        .instance_init = initfn              \
> +    }
> +
>  static const TypeInfo riscv_cpu_type_infos[] = {
>      {
>          .name = TYPE_RISCV_CPU,
> @@ -1742,21 +1749,26 @@ static const TypeInfo riscv_cpu_type_infos[] = {
>          .parent = TYPE_RISCV_CPU,
>          .abstract = true,
>      },
> +    {
> +        .name = TYPE_RISCV_VENDOR_CPU,
> +        .parent = TYPE_RISCV_CPU,
> +        .abstract = true,
> +    },
>      DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_ANY,      riscv_any_cpu_init),
>      DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_MAX,      riscv_max_cpu_init),
>  #if defined(TARGET_RISCV32)
>      DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_BASE32,   rv32_base_cpu_init),
> -    DEFINE_CPU(TYPE_RISCV_CPU_IBEX,             rv32_ibex_cpu_init),
> -    DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E31,       rv32_sifive_e_cpu_init),
> -    DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E34,       rv32_imafcu_nommu_cpu_init),
> -    DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_U34,       rv32_sifive_u_cpu_init),
> +    DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_IBEX,        rv32_ibex_cpu_init),
> +    DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_SIFIVE_E31,  rv32_sifive_e_cpu_init),
> +    DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_SIFIVE_E34,  rv32_imafcu_nommu_cpu_init),
> +    DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_SIFIVE_U34,  rv32_sifive_u_cpu_init),
>  #elif defined(TARGET_RISCV64)
>      DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_BASE64,   rv64_base_cpu_init),
> -    DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E51,       rv64_sifive_e_cpu_init),
> -    DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_U54,       rv64_sifive_u_cpu_init),
> -    DEFINE_CPU(TYPE_RISCV_CPU_SHAKTI_C,         rv64_sifive_u_cpu_init),
> -    DEFINE_CPU(TYPE_RISCV_CPU_THEAD_C906,       rv64_thead_c906_cpu_init),
> -    DEFINE_CPU(TYPE_RISCV_CPU_VEYRON_V1,        rv64_veyron_v1_cpu_init),
> +    DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_SIFIVE_E51,  rv64_sifive_e_cpu_init),
> +    DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_SIFIVE_U54,  rv64_sifive_u_cpu_init),
> +    DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_SHAKTI_C,    rv64_sifive_u_cpu_init),
> +    DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_THEAD_C906,  rv64_thead_c906_cpu_init),
> +    DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_VEYRON_V1,   rv64_veyron_v1_cpu_init),
>      DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_BASE128,  rv128_base_cpu_init),
>  #endif
>  };
> --
> 2.41.0
>
>


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v8 02/19] target/riscv/tcg: do not use "!generic" CPU checks
  2023-11-01 20:41 ` [PATCH v8 02/19] target/riscv/tcg: do not use "!generic" CPU checks Daniel Henrique Barboza
@ 2023-11-02  2:38   ` Alistair Francis
  0 siblings, 0 replies; 31+ messages in thread
From: Alistair Francis @ 2023-11-02  2:38 UTC (permalink / raw)
  To: Daniel Henrique Barboza
  Cc: qemu-devel, qemu-riscv, alistair.francis, bmeng, liweiwei,
	zhiwei_liu, palmer, ajones

On Thu, Nov 2, 2023 at 8:13 AM Daniel Henrique Barboza
<dbarboza@ventanamicro.com> wrote:
>
> Our current logic in get/setters of MISA and multi-letter extensions
> works because we have only 2 CPU types, generic and vendor, and by using
> "!generic" we're implying that we're talking about vendor CPUs. When adding
> a third CPU type this logic will break so let's handle it beforehand.
>
> In set_misa_ext_cfg() and set_multi_ext_cfg(), check for "vendor" cpu instead
> of "not generic". The "generic CPU" checks remaining are from
> riscv_cpu_add_misa_properties() and cpu_add_multi_ext_prop() before
> applying default values for the extensions.
>
> This leaves us with:
>
> - vendor CPUs will not allow extension enablement, all other CPUs will;
>
> - generic CPUs will inherit default values for extensions, all others
>   won't.
>
> And now we can add a new, third CPU type, that will allow extensions to
> be enabled and will not inherit defaults, without changing the existing
> logic.
>
> Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
> Reviewed-by: Andrew Jones <ajones@ventanamicro.com>

Reviewed-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>  target/riscv/tcg/tcg-cpu.c | 13 +++++++++----
>  1 file changed, 9 insertions(+), 4 deletions(-)
>
> diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
> index 093bda2e75..f54069d06f 100644
> --- a/target/riscv/tcg/tcg-cpu.c
> +++ b/target/riscv/tcg/tcg-cpu.c
> @@ -612,6 +612,11 @@ static bool riscv_cpu_is_generic(Object *cpu_obj)
>      return object_dynamic_cast(cpu_obj, TYPE_RISCV_DYNAMIC_CPU) != NULL;
>  }
>
> +static bool riscv_cpu_is_vendor(Object *cpu_obj)
> +{
> +    return object_dynamic_cast(cpu_obj, TYPE_RISCV_VENDOR_CPU) != NULL;
> +}
> +
>  /*
>   * We'll get here via the following path:
>   *
> @@ -674,7 +679,7 @@ static void cpu_set_misa_ext_cfg(Object *obj, Visitor *v, const char *name,
>      target_ulong misa_bit = misa_ext_cfg->misa_bit;
>      RISCVCPU *cpu = RISCV_CPU(obj);
>      CPURISCVState *env = &cpu->env;
> -    bool generic_cpu = riscv_cpu_is_generic(obj);
> +    bool vendor_cpu = riscv_cpu_is_vendor(obj);
>      bool prev_val, value;
>
>      if (!visit_type_bool(v, name, &value, errp)) {
> @@ -688,7 +693,7 @@ static void cpu_set_misa_ext_cfg(Object *obj, Visitor *v, const char *name,
>      }
>
>      if (value) {
> -        if (!generic_cpu) {
> +        if (vendor_cpu) {
>              g_autofree char *cpuname = riscv_cpu_get_name(cpu);
>              error_setg(errp, "'%s' CPU does not allow enabling extensions",
>                         cpuname);
> @@ -793,7 +798,7 @@ static void cpu_set_multi_ext_cfg(Object *obj, Visitor *v, const char *name,
>  {
>      const RISCVCPUMultiExtConfig *multi_ext_cfg = opaque;
>      RISCVCPU *cpu = RISCV_CPU(obj);
> -    bool generic_cpu = riscv_cpu_is_generic(obj);
> +    bool vendor_cpu = riscv_cpu_is_vendor(obj);
>      bool prev_val, value;
>
>      if (!visit_type_bool(v, name, &value, errp)) {
> @@ -817,7 +822,7 @@ static void cpu_set_multi_ext_cfg(Object *obj, Visitor *v, const char *name,
>          return;
>      }
>
> -    if (value && !generic_cpu) {
> +    if (value && vendor_cpu) {
>          g_autofree char *cpuname = riscv_cpu_get_name(cpu);
>          error_setg(errp, "'%s' CPU does not allow enabling extensions",
>                     cpuname);
> --
> 2.41.0
>
>


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v8 03/19] target/riscv/cpu.c: set satp_max_supported in cpu_riscv_set_satp()
  2023-11-01 20:41 ` [PATCH v8 03/19] target/riscv/cpu.c: set satp_max_supported in cpu_riscv_set_satp() Daniel Henrique Barboza
@ 2023-11-02  9:24   ` Andrew Jones
  2023-11-02 12:53     ` Daniel Henrique Barboza
  0 siblings, 1 reply; 31+ messages in thread
From: Andrew Jones @ 2023-11-02  9:24 UTC (permalink / raw)
  To: Daniel Henrique Barboza
  Cc: qemu-devel, qemu-riscv, alistair.francis, bmeng, liweiwei,
	zhiwei_liu, palmer

On Wed, Nov 01, 2023 at 05:41:48PM -0300, Daniel Henrique Barboza wrote:
> The setter() for the boolean attributes that set satp_mode (sv32, sv39,
> sv48, sv57, sv64) considers that the CPU will always do a
> set_satp_mode_max_supported() during cpu_init().
> 
> This is not the case for the KVM 'host' CPU, and we'll add another CPU
> that won't set satp_mode_max() during cpu_init(). Users should be able
> to set a max_support in these circunstances.
> 
> Allow cpu_riscv_set_satp() to set satp_mode_max_supported if the CPU
> didn't set one prior.
> 
> Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
> ---
>  target/riscv/cpu.c | 11 +++++++++++
>  1 file changed, 11 insertions(+)
> 
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index 822970345c..9f6837ecb7 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -1100,6 +1100,7 @@ static void cpu_riscv_get_satp(Object *obj, Visitor *v, const char *name,
>  static void cpu_riscv_set_satp(Object *obj, Visitor *v, const char *name,
>                                 void *opaque, Error **errp)
>  {
> +    RISCVCPU *cpu = RISCV_CPU(obj);
>      RISCVSATPMap *satp_map = opaque;
>      uint8_t satp = satp_mode_from_str(name);
>      bool value;
> @@ -1108,6 +1109,16 @@ static void cpu_riscv_set_satp(Object *obj, Visitor *v, const char *name,
>          return;
>      }
>  
> +    /*
> +     * Allow users to set satp max supported if the CPU didn't
> +     * set any during cpu_init(). First value set to 'true'
> +     * in this case is assumed to be the max supported for
> +     * the CPU.

Hmm, doesn't that mean if a user does

 -cpu rv64,sv39=true,sv48=true

then the max is set to sv39 instead of sv48?

I made a mistake in my last review by stating we shouldn't set the max
supported satp for rv64i to the maximum satp that TCG supports. I forgot
how all of it worked. Setting the _supported_ modes to the maximum that
TCG supports makes sense as long as we don't default to any of them for
rv64i. So, I think we should return the set_satp_mode_max_supported() to
rv64i's definition (passing VM_1_10_SV57 or maybe even VM_1_10_SV64) and
then change set_satp_mode_default_map() to error out for rv64i (or maybe
for all "bare" type cpus).

> +     */
> +    if (value && cpu->cfg.satp_mode.supported == 0) {
> +        set_satp_mode_max_supported(cpu, satp);
> +    }
> +
>      satp_map->map = deposit32(satp_map->map, satp, 1, value);
>      satp_map->init |= 1 << satp;
>  }
> -- 
> 2.41.0
>

Thanks,
drew


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v8 04/19] target/riscv/cpu.c: set satp_mode_max MBARE during satp_finalize()
  2023-11-01 20:41 ` [PATCH v8 04/19] target/riscv/cpu.c: set satp_mode_max MBARE during satp_finalize() Daniel Henrique Barboza
@ 2023-11-02  9:32   ` Andrew Jones
  0 siblings, 0 replies; 31+ messages in thread
From: Andrew Jones @ 2023-11-02  9:32 UTC (permalink / raw)
  To: Daniel Henrique Barboza
  Cc: qemu-devel, qemu-riscv, alistair.francis, bmeng, liweiwei,
	zhiwei_liu, palmer

On Wed, Nov 01, 2023 at 05:41:49PM -0300, Daniel Henrique Barboza wrote:
> KVM CPUs can handle "cpu->cfg.satp_mode.supported == 0" because KVM will
> make it do internally, not requiring the current SATP support from TCG.
> 
> But other TCG CPUs doesn't deal well with it. We'll assert out before
> OpenSBI if the CPU doesn't set a default:
> 
> ERROR:../target/riscv/cpu.c:317:satp_mode_max_from_map: assertion failed: (map > 0)
> Bail out! ERROR:../target/riscv/cpu.c:317:satp_mode_max_from_map: assertion failed: (map > 0)
> 
> This will be thrown by target/riscv/csr.c, write_satp(), when stepping
> in validate_vm().
> 
> There's no current CPUs affected by it, but next patch will add a new
> CPU that doesn't have defaults and this assert will be hit.
> 
> Change riscv_cpu_satp_mode_finalize() to set satp_mode_max_supported()
> to MBARE if the CPU happens to not have a max mode set yet.
> 
> Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
> ---
>  target/riscv/cpu.c | 14 ++++++++++++--
>  1 file changed, 12 insertions(+), 2 deletions(-)
> 
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index 9f6837ecb7..f7c1989d14 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -942,9 +942,19 @@ static void riscv_cpu_satp_mode_finalize(RISCVCPU *cpu, Error **errp)
>      bool rv32 = riscv_cpu_mxl(&cpu->env) == MXL_RV32;
>      uint8_t satp_mode_map_max, satp_mode_supported_max;
>  
> -    /* The CPU wants the OS to decide which satp mode to use */
>      if (cpu->cfg.satp_mode.supported == 0) {
> -        return;
> +        if (kvm_enabled()) {
> +            /* The CPU wants the OS to decide which satp mode to use */
> +            return;
> +        }
> +
> +        /*
> +         * We do not handle cpu->cfg.satp_mode.supported == 0
> +         * with TCG yet. Set to MBARE.
> +         */
> +        if (tcg_enabled()) {
> +            set_satp_mode_max_supported(cpu, VM_1_10_MBARE);
> +        }
>      }
>  
>      satp_mode_supported_max =
> -- 
> 2.41.0
>

This patch should no longer be necessary if the suggestion I made in the
previous patch works the way I think it should. But, regarding this patch,
I do like that the "The CPU wants the OS to decide which satp mode to use"
comment became specific to KVM, which makes more sense to me. Maybe we
should just change that comment to something like

/*
 * With some accelerators, such as KVM, the OS dictates which satp mode to
 * use. For those cases, satp_mode.supported is zero and there's nothing
 * to do here.
 */

Thanks,
drew


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v8 05/19] target/riscv/tcg: update priv_ver on user_set extensions
  2023-11-01 20:41 ` [PATCH v8 05/19] target/riscv/tcg: update priv_ver on user_set extensions Daniel Henrique Barboza
@ 2023-11-02  9:47   ` Andrew Jones
  2023-11-02 13:42     ` Daniel Henrique Barboza
  0 siblings, 1 reply; 31+ messages in thread
From: Andrew Jones @ 2023-11-02  9:47 UTC (permalink / raw)
  To: Daniel Henrique Barboza
  Cc: qemu-devel, qemu-riscv, alistair.francis, bmeng, liweiwei,
	zhiwei_liu, palmer

On Wed, Nov 01, 2023 at 05:41:50PM -0300, Daniel Henrique Barboza wrote:
> We'll add a new bare CPU type that won't have any default priv_ver. This
> means that the CPU will default to priv_ver = 0, i.e. 1.10.0.
> 
> At the same we'll allow these CPUs to enable extensions at will, but
> then, if the extension has a priv_ver newer than 1.10, we'll end up
> disabling it. Users will then need to manually set priv_ver to something
> other than 1.10 to enable the extensions they want, which is not ideal.
> 
> Change the setter() of multi letter extensions to allow user enabled
> extensions to bump the priv_ver of the CPU. This will make it
> conveniente for users to enable extensions for CPUs that doesn't set a
> default priv_ver.
> 
> This change does not affect any existing CPU: vendor CPUs does not allow
> extensions to be enabled, and generic CPUs are already set to priv_ver
> LATEST.
> 
> Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
> ---
>  target/riscv/tcg/tcg-cpu.c | 20 ++++++++++++++++++++
>  1 file changed, 20 insertions(+)
> 
> diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
> index f54069d06f..b88fce98a4 100644
> --- a/target/riscv/tcg/tcg-cpu.c
> +++ b/target/riscv/tcg/tcg-cpu.c
> @@ -114,6 +114,22 @@ static int cpu_cfg_ext_get_min_version(uint32_t ext_offset)
>      g_assert_not_reached();
>  }
>  
> +static void cpu_validate_multi_ext_priv_ver(CPURISCVState *env,
> +                                            uint32_t ext_offset)
> +{
> +    int ext_priv_ver;
> +
> +    if (env->priv_ver == PRIV_VERSION_LATEST) {
> +        return;
> +    }
> +
> +    ext_priv_ver = cpu_cfg_ext_get_min_version(ext_offset);
> +
> +    if (env->priv_ver < ext_priv_ver) {
> +        env->priv_ver = ext_priv_ver;
> +    }

This will ignore user input. If the user, for example, does

 -cpu rv64,priv_spec=v1.10.0,zicbom=on

then, afaict, priv_spec will be silently bumped to 1.12. I think we should
error out in that case instead. And, we should also error out for

 -cpu rv64,zicbom=on,priv_spec=v1.10.0

which means we should know when priv_spec is either

 - its default value
 - has been bumped by an extension
 - has been explicitly set by the user

> +}
> +
>  static void cpu_cfg_ext_auto_update(RISCVCPU *cpu, uint32_t ext_offset,
>                                      bool value)
>  {
> @@ -829,6 +845,10 @@ static void cpu_set_multi_ext_cfg(Object *obj, Visitor *v, const char *name,
>          return;
>      }
>  
> +    if (value) {
> +        cpu_validate_multi_ext_priv_ver(&cpu->env, multi_ext_cfg->offset);
> +    }

Some misa extensions also have priv spec version dependencies. See
riscv_cpu_validate_misa_priv()

> +
>      isa_ext_update_enabled(cpu, multi_ext_cfg->offset, value);
>  }
>  
> -- 
> 2.41.0
>

Thanks,
drew


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v8 06/19] target/riscv: add rv64i CPU
  2023-11-01 20:41 ` [PATCH v8 06/19] target/riscv: add rv64i CPU Daniel Henrique Barboza
@ 2023-11-02  9:59   ` Andrew Jones
  2023-11-02 14:23     ` Daniel Henrique Barboza
  0 siblings, 1 reply; 31+ messages in thread
From: Andrew Jones @ 2023-11-02  9:59 UTC (permalink / raw)
  To: Daniel Henrique Barboza
  Cc: qemu-devel, qemu-riscv, alistair.francis, bmeng, liweiwei,
	zhiwei_liu, palmer

On Wed, Nov 01, 2023 at 05:41:51PM -0300, Daniel Henrique Barboza wrote:
> We don't have any form of a 'bare bones' CPU. rv64, our default CPUs,
> comes with a lot of defaults. This is fine for most regular uses but
> it's not suitable when more control of what is actually loaded in the
> CPU is required.
> 
> A bare-bones CPU would be annoying to deal with if not by profile
> support, a way to load a multitude of extensions with a single flag.
> Profile support is going to be implemented shortly, so let's add a CPU
> for it.
> 
> The new 'rv64i' CPU will have only RVI loaded. It is inspired in the
> profile specification that dictates, for RVA22U64 [1]:
> 
> "RVA22U64 Mandatory Base
>  RV64I is the mandatory base ISA for RVA22U64"
> 
> And so it seems that RV64I is the mandatory base ISA for all profiles
> listed in [1], making it an ideal CPU to use with profile support.
> 
> rv64i is a CPU of type TYPE_RISCV_BARE_CPU. It has a mix of features
> from pre-existent CPUs:
> 
> - it allows extensions to be enabled, like generic CPUs;
> - it will not inherit extension defaults, like vendor CPUs.
> 
> This is the minimum extension set to boot OpenSBI and buildroot using
> rv64i:
> 
> ./build/qemu-system-riscv64 -nographic -M virt \
>     -cpu rv64i,sv39=true,g=true,c=true,s=true,u=true
> 
> Our minimal riscv,isa in this case will be:
> 
>  # cat /proc/device-tree/cpus/cpu@0/riscv,isa
> rv64imafdc_zicntr_zicsr_zifencei_zihpm_zca_zcd#
> 
> [1] https://github.com/riscv/riscv-profiles/blob/main/profiles.adoc
> 
> Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
> ---
>  target/riscv/cpu-qom.h |  2 ++
>  target/riscv/cpu.c     | 23 +++++++++++++++++++++++
>  2 files changed, 25 insertions(+)
> 
> diff --git a/target/riscv/cpu-qom.h b/target/riscv/cpu-qom.h
> index 7831e86d37..ea9a752280 100644
> --- a/target/riscv/cpu-qom.h
> +++ b/target/riscv/cpu-qom.h
> @@ -25,6 +25,7 @@
>  #define TYPE_RISCV_CPU "riscv-cpu"
>  #define TYPE_RISCV_DYNAMIC_CPU "riscv-dynamic-cpu"
>  #define TYPE_RISCV_VENDOR_CPU "riscv-vendor-cpu"
> +#define TYPE_RISCV_BARE_CPU "riscv-bare-cpu"
>  
>  #define RISCV_CPU_TYPE_SUFFIX "-" TYPE_RISCV_CPU
>  #define RISCV_CPU_TYPE_NAME(name) (name RISCV_CPU_TYPE_SUFFIX)
> @@ -35,6 +36,7 @@
>  #define TYPE_RISCV_CPU_BASE32           RISCV_CPU_TYPE_NAME("rv32")
>  #define TYPE_RISCV_CPU_BASE64           RISCV_CPU_TYPE_NAME("rv64")
>  #define TYPE_RISCV_CPU_BASE128          RISCV_CPU_TYPE_NAME("x-rv128")
> +#define TYPE_RISCV_CPU_RV64I            RISCV_CPU_TYPE_NAME("rv64i")
>  #define TYPE_RISCV_CPU_IBEX             RISCV_CPU_TYPE_NAME("lowrisc-ibex")
>  #define TYPE_RISCV_CPU_SHAKTI_C         RISCV_CPU_TYPE_NAME("shakti-c")
>  #define TYPE_RISCV_CPU_SIFIVE_E31       RISCV_CPU_TYPE_NAME("sifive-e31")
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index f7c1989d14..4a6e544eaf 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -544,6 +544,16 @@ static void rv128_base_cpu_init(Object *obj)
>      set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV57);
>  #endif
>  }
> +
> +static void rv64i_bare_cpu_init(Object *obj)
> +{
> +    CPURISCVState *env = &RISCV_CPU(obj)->env;
> +    riscv_cpu_set_misa(env, MXL_RV64, RVI);
> +
> +    /* Remove the defaults from the parent class */
> +    RISCV_CPU(obj)->cfg.ext_zicntr = false;
> +    RISCV_CPU(obj)->cfg.ext_zihpm = false;

Good catch since v1, but having to do this is a bit gross. I'd prefer the
parent class not enable any extensions. Each CPU type that needs these
can just set them themselves.

> +}
>  #else
>  static void rv32_base_cpu_init(Object *obj)
>  {
> @@ -1753,6 +1763,13 @@ void riscv_cpu_list(void)
>          .instance_init = initfn              \
>      }
>  
> +#define DEFINE_BARE_CPU(type_name, initfn) \
> +    {                                      \
> +        .name = type_name,                 \
> +        .parent = TYPE_RISCV_BARE_CPU,     \
> +        .instance_init = initfn            \
> +    }
> +
>  static const TypeInfo riscv_cpu_type_infos[] = {
>      {
>          .name = TYPE_RISCV_CPU,
> @@ -1775,6 +1792,11 @@ static const TypeInfo riscv_cpu_type_infos[] = {
>          .parent = TYPE_RISCV_CPU,
>          .abstract = true,
>      },
> +    {
> +        .name = TYPE_RISCV_BARE_CPU,
> +        .parent = TYPE_RISCV_CPU,
> +        .abstract = true,
> +    },
>      DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_ANY,      riscv_any_cpu_init),
>      DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_MAX,      riscv_max_cpu_init),
>  #if defined(TARGET_RISCV32)
> @@ -1791,6 +1813,7 @@ static const TypeInfo riscv_cpu_type_infos[] = {
>      DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_THEAD_C906,  rv64_thead_c906_cpu_init),
>      DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_VEYRON_V1,   rv64_veyron_v1_cpu_init),
>      DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_BASE128,  rv128_base_cpu_init),
> +    DEFINE_BARE_CPU(TYPE_RISCV_CPU_RV64I, rv64i_bare_cpu_init),
>  #endif
>  };
>  
> -- 
> 2.41.0
>

We'll probably need to bring back the satp supported mode setting, as
suggested on a previous patch, but otherwise

Reviewed-by: Andrew Jones <ajones@ventanamicro.com>

Thanks,
drew


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v8 03/19] target/riscv/cpu.c: set satp_max_supported in cpu_riscv_set_satp()
  2023-11-02  9:24   ` Andrew Jones
@ 2023-11-02 12:53     ` Daniel Henrique Barboza
  2023-11-02 13:11       ` Andrew Jones
  0 siblings, 1 reply; 31+ messages in thread
From: Daniel Henrique Barboza @ 2023-11-02 12:53 UTC (permalink / raw)
  To: Andrew Jones
  Cc: qemu-devel, qemu-riscv, alistair.francis, bmeng, liweiwei,
	zhiwei_liu, palmer



On 11/2/23 06:24, Andrew Jones wrote:
> On Wed, Nov 01, 2023 at 05:41:48PM -0300, Daniel Henrique Barboza wrote:
>> The setter() for the boolean attributes that set satp_mode (sv32, sv39,
>> sv48, sv57, sv64) considers that the CPU will always do a
>> set_satp_mode_max_supported() during cpu_init().
>>
>> This is not the case for the KVM 'host' CPU, and we'll add another CPU
>> that won't set satp_mode_max() during cpu_init(). Users should be able
>> to set a max_support in these circunstances.
>>
>> Allow cpu_riscv_set_satp() to set satp_mode_max_supported if the CPU
>> didn't set one prior.
>>
>> Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
>> ---
>>   target/riscv/cpu.c | 11 +++++++++++
>>   1 file changed, 11 insertions(+)
>>
>> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
>> index 822970345c..9f6837ecb7 100644
>> --- a/target/riscv/cpu.c
>> +++ b/target/riscv/cpu.c
>> @@ -1100,6 +1100,7 @@ static void cpu_riscv_get_satp(Object *obj, Visitor *v, const char *name,
>>   static void cpu_riscv_set_satp(Object *obj, Visitor *v, const char *name,
>>                                  void *opaque, Error **errp)
>>   {
>> +    RISCVCPU *cpu = RISCV_CPU(obj);
>>       RISCVSATPMap *satp_map = opaque;
>>       uint8_t satp = satp_mode_from_str(name);
>>       bool value;
>> @@ -1108,6 +1109,16 @@ static void cpu_riscv_set_satp(Object *obj, Visitor *v, const char *name,
>>           return;
>>       }
>>   
>> +    /*
>> +     * Allow users to set satp max supported if the CPU didn't
>> +     * set any during cpu_init(). First value set to 'true'
>> +     * in this case is assumed to be the max supported for
>> +     * the CPU.
> 
> Hmm, doesn't that mean if a user does
> 
>   -cpu rv64,sv39=true,sv48=true
> 
> then the max is set to sv39 instead of sv48?
> 
> I made a mistake in my last review by stating we shouldn't set the max
> supported satp for rv64i to the maximum satp that TCG supports. I forgot
> how all of it worked. Setting the _supported_ modes to the maximum that
> TCG supports makes sense as long as we don't default to any of them for
> rv64i. So, I think we should return the set_satp_mode_max_supported() to
> rv64i's definition (passing VM_1_10_SV57 or maybe even VM_1_10_SV64) and
> then change set_satp_mode_default_map() to error out for rv64i (or maybe
> for all "bare" type cpus).

Ok, then let's set max supported mode to SV64 (the maximum we allow).

Then we don't need to do anything else - setting a max supported value will allow
TCG to handle it accordingly with OpenSBI and the kernel, and a suitable satp_mode
will be picked by them. We can leave finalize() untouched.

I'll make a note in cpu_init() to remind ourselves that we're not setting a default
satp_mode value, but a *limit* for the satp_mode value the CPU can handle. This can be
done in the 'rv64i' patch.


Thanks,


Daniel




> 
>> +     */
>> +    if (value && cpu->cfg.satp_mode.supported == 0) {
>> +        set_satp_mode_max_supported(cpu, satp);
>> +    }
>> +
>>       satp_map->map = deposit32(satp_map->map, satp, 1, value);
>>       satp_map->init |= 1 << satp;
>>   }
>> -- 
>> 2.41.0
>>
> 
> Thanks,
> drew


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v8 03/19] target/riscv/cpu.c: set satp_max_supported in cpu_riscv_set_satp()
  2023-11-02 12:53     ` Daniel Henrique Barboza
@ 2023-11-02 13:11       ` Andrew Jones
  0 siblings, 0 replies; 31+ messages in thread
From: Andrew Jones @ 2023-11-02 13:11 UTC (permalink / raw)
  To: Daniel Henrique Barboza
  Cc: qemu-devel, qemu-riscv, alistair.francis, bmeng, liweiwei,
	zhiwei_liu, palmer

On Thu, Nov 02, 2023 at 09:53:50AM -0300, Daniel Henrique Barboza wrote:
> 
> 
> On 11/2/23 06:24, Andrew Jones wrote:
> > On Wed, Nov 01, 2023 at 05:41:48PM -0300, Daniel Henrique Barboza wrote:
> > > The setter() for the boolean attributes that set satp_mode (sv32, sv39,
> > > sv48, sv57, sv64) considers that the CPU will always do a
> > > set_satp_mode_max_supported() during cpu_init().
> > > 
> > > This is not the case for the KVM 'host' CPU, and we'll add another CPU
> > > that won't set satp_mode_max() during cpu_init(). Users should be able
> > > to set a max_support in these circunstances.
> > > 
> > > Allow cpu_riscv_set_satp() to set satp_mode_max_supported if the CPU
> > > didn't set one prior.
> > > 
> > > Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
> > > ---
> > >   target/riscv/cpu.c | 11 +++++++++++
> > >   1 file changed, 11 insertions(+)
> > > 
> > > diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> > > index 822970345c..9f6837ecb7 100644
> > > --- a/target/riscv/cpu.c
> > > +++ b/target/riscv/cpu.c
> > > @@ -1100,6 +1100,7 @@ static void cpu_riscv_get_satp(Object *obj, Visitor *v, const char *name,
> > >   static void cpu_riscv_set_satp(Object *obj, Visitor *v, const char *name,
> > >                                  void *opaque, Error **errp)
> > >   {
> > > +    RISCVCPU *cpu = RISCV_CPU(obj);
> > >       RISCVSATPMap *satp_map = opaque;
> > >       uint8_t satp = satp_mode_from_str(name);
> > >       bool value;
> > > @@ -1108,6 +1109,16 @@ static void cpu_riscv_set_satp(Object *obj, Visitor *v, const char *name,
> > >           return;
> > >       }
> > > +    /*
> > > +     * Allow users to set satp max supported if the CPU didn't
> > > +     * set any during cpu_init(). First value set to 'true'
> > > +     * in this case is assumed to be the max supported for
> > > +     * the CPU.
> > 
> > Hmm, doesn't that mean if a user does
> > 
> >   -cpu rv64,sv39=true,sv48=true
> > 
> > then the max is set to sv39 instead of sv48?
> > 
> > I made a mistake in my last review by stating we shouldn't set the max
> > supported satp for rv64i to the maximum satp that TCG supports. I forgot
> > how all of it worked. Setting the _supported_ modes to the maximum that
> > TCG supports makes sense as long as we don't default to any of them for
> > rv64i. So, I think we should return the set_satp_mode_max_supported() to
> > rv64i's definition (passing VM_1_10_SV57 or maybe even VM_1_10_SV64) and
> > then change set_satp_mode_default_map() to error out for rv64i (or maybe
> > for all "bare" type cpus).
> 
> Ok, then let's set max supported mode to SV64 (the maximum we allow).
> 
> Then we don't need to do anything else - setting a max supported value will allow
> TCG to handle it accordingly with OpenSBI and the kernel, and a suitable satp_mode
> will be picked by them. We can leave finalize() untouched.
> 
> I'll make a note in cpu_init() to remind ourselves that we're not setting a default
> satp_mode value, but a *limit* for the satp_mode value the CPU can handle.

It's both. It's the limit and, in the absence of user input, its used as
the default. Setting the limit is fine for a no-default cpu type, but
allowing it to become the default is not. We need to also modify
set_satp_mode_default_map() to only do what it does for non no-default
cpus types.

Thanks,
drew


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v8 05/19] target/riscv/tcg: update priv_ver on user_set extensions
  2023-11-02  9:47   ` Andrew Jones
@ 2023-11-02 13:42     ` Daniel Henrique Barboza
  2023-11-02 13:48       ` Andrew Jones
  0 siblings, 1 reply; 31+ messages in thread
From: Daniel Henrique Barboza @ 2023-11-02 13:42 UTC (permalink / raw)
  To: Andrew Jones
  Cc: qemu-devel, qemu-riscv, alistair.francis, bmeng, liweiwei,
	zhiwei_liu, palmer



On 11/2/23 06:47, Andrew Jones wrote:
> On Wed, Nov 01, 2023 at 05:41:50PM -0300, Daniel Henrique Barboza wrote:
>> We'll add a new bare CPU type that won't have any default priv_ver. This
>> means that the CPU will default to priv_ver = 0, i.e. 1.10.0.
>>
>> At the same we'll allow these CPUs to enable extensions at will, but
>> then, if the extension has a priv_ver newer than 1.10, we'll end up
>> disabling it. Users will then need to manually set priv_ver to something
>> other than 1.10 to enable the extensions they want, which is not ideal.
>>
>> Change the setter() of multi letter extensions to allow user enabled
>> extensions to bump the priv_ver of the CPU. This will make it
>> conveniente for users to enable extensions for CPUs that doesn't set a
>> default priv_ver.
>>
>> This change does not affect any existing CPU: vendor CPUs does not allow
>> extensions to be enabled, and generic CPUs are already set to priv_ver
>> LATEST.
>>
>> Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
>> ---
>>   target/riscv/tcg/tcg-cpu.c | 20 ++++++++++++++++++++
>>   1 file changed, 20 insertions(+)
>>
>> diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
>> index f54069d06f..b88fce98a4 100644
>> --- a/target/riscv/tcg/tcg-cpu.c
>> +++ b/target/riscv/tcg/tcg-cpu.c
>> @@ -114,6 +114,22 @@ static int cpu_cfg_ext_get_min_version(uint32_t ext_offset)
>>       g_assert_not_reached();
>>   }
>>   
>> +static void cpu_validate_multi_ext_priv_ver(CPURISCVState *env,
>> +                                            uint32_t ext_offset)
>> +{
>> +    int ext_priv_ver;
>> +
>> +    if (env->priv_ver == PRIV_VERSION_LATEST) {
>> +        return;
>> +    }
>> +
>> +    ext_priv_ver = cpu_cfg_ext_get_min_version(ext_offset);
>> +
>> +    if (env->priv_ver < ext_priv_ver) {
>> +        env->priv_ver = ext_priv_ver;
>> +    }
> 
> This will ignore user input. If the user, for example, does
> 
>   -cpu rv64,priv_spec=v1.10.0,zicbom=on


This won't ignore user input because "priv_spec=v1.10.0" will be evaluated during
finalize() time, in riscv_cpu_validate_priv_spec(). This change I made was made
with this behavior in mind.

In the case you mentioned, this will happen:

$ ./build/qemu-system-riscv64 -M virt -cpu rv64,priv_spec=v1.10.0,zicbom=on
qemu-system-riscv64: H extension requires priv spec 1.12.0

This happened because, although 'zicbom=true' would bump priv ver to 1.12.0 if needed
(it isn't - rv64 is already set to LATEST), "priv_spec=v1.10.0" is evaluated during
finalize() time and the CPU priv_ver is set to 1.10 before our validation step.

This means that doesn't matter where the 'priv_spec' option is in the command line,
it'll always be honored.


> 
> then, afaict, priv_spec will be silently bumped to 1.12. I think we should
> error out in that case instead. And, we should also error out for
> 
>   -cpu rv64,zicbom=on,priv_spec=v1.10.0
> 
> which means we should know when priv_spec is either
> 
>   - its default value
>   - has been bumped by an extension
>   - has been explicitly set by the user

> 
>> +}
>> +
>>   static void cpu_cfg_ext_auto_update(RISCVCPU *cpu, uint32_t ext_offset,
>>                                       bool value)
>>   {
>> @@ -829,6 +845,10 @@ static void cpu_set_multi_ext_cfg(Object *obj, Visitor *v, const char *name,
>>           return;
>>       }
>>   
>> +    if (value) {
>> +        cpu_validate_multi_ext_priv_ver(&cpu->env, multi_ext_cfg->offset);
>> +    }
> 
> Some misa extensions also have priv spec version dependencies. See
> riscv_cpu_validate_misa_priv()

Yeah. I'll add this same mechanic to RVH, the only MISA bit we have that has a priv_ver
limitation. Thanks,

Daniel

> 
>> +
>>       isa_ext_update_enabled(cpu, multi_ext_cfg->offset, value);
>>   }
>>   
>> -- 
>> 2.41.0
>>
> 
> Thanks,
> drew


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v8 05/19] target/riscv/tcg: update priv_ver on user_set extensions
  2023-11-02 13:42     ` Daniel Henrique Barboza
@ 2023-11-02 13:48       ` Andrew Jones
  0 siblings, 0 replies; 31+ messages in thread
From: Andrew Jones @ 2023-11-02 13:48 UTC (permalink / raw)
  To: Daniel Henrique Barboza
  Cc: qemu-devel, qemu-riscv, alistair.francis, bmeng, liweiwei,
	zhiwei_liu, palmer

On Thu, Nov 02, 2023 at 10:42:25AM -0300, Daniel Henrique Barboza wrote:
> 
> 
> On 11/2/23 06:47, Andrew Jones wrote:
> > On Wed, Nov 01, 2023 at 05:41:50PM -0300, Daniel Henrique Barboza wrote:
> > > We'll add a new bare CPU type that won't have any default priv_ver. This
> > > means that the CPU will default to priv_ver = 0, i.e. 1.10.0.
> > > 
> > > At the same we'll allow these CPUs to enable extensions at will, but
> > > then, if the extension has a priv_ver newer than 1.10, we'll end up
> > > disabling it. Users will then need to manually set priv_ver to something
> > > other than 1.10 to enable the extensions they want, which is not ideal.
> > > 
> > > Change the setter() of multi letter extensions to allow user enabled
> > > extensions to bump the priv_ver of the CPU. This will make it
> > > conveniente for users to enable extensions for CPUs that doesn't set a
> > > default priv_ver.
> > > 
> > > This change does not affect any existing CPU: vendor CPUs does not allow
> > > extensions to be enabled, and generic CPUs are already set to priv_ver
> > > LATEST.
> > > 
> > > Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
> > > ---
> > >   target/riscv/tcg/tcg-cpu.c | 20 ++++++++++++++++++++
> > >   1 file changed, 20 insertions(+)
> > > 
> > > diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
> > > index f54069d06f..b88fce98a4 100644
> > > --- a/target/riscv/tcg/tcg-cpu.c
> > > +++ b/target/riscv/tcg/tcg-cpu.c
> > > @@ -114,6 +114,22 @@ static int cpu_cfg_ext_get_min_version(uint32_t ext_offset)
> > >       g_assert_not_reached();
> > >   }
> > > +static void cpu_validate_multi_ext_priv_ver(CPURISCVState *env,
> > > +                                            uint32_t ext_offset)
> > > +{
> > > +    int ext_priv_ver;
> > > +
> > > +    if (env->priv_ver == PRIV_VERSION_LATEST) {
> > > +        return;
> > > +    }
> > > +
> > > +    ext_priv_ver = cpu_cfg_ext_get_min_version(ext_offset);
> > > +
> > > +    if (env->priv_ver < ext_priv_ver) {
> > > +        env->priv_ver = ext_priv_ver;
> > > +    }
> > 
> > This will ignore user input. If the user, for example, does
> > 
> >   -cpu rv64,priv_spec=v1.10.0,zicbom=on
> 
> 
> This won't ignore user input because "priv_spec=v1.10.0" will be evaluated during
> finalize() time, in riscv_cpu_validate_priv_spec(). This change I made was made
> with this behavior in mind.
> 
> In the case you mentioned, this will happen:
> 
> $ ./build/qemu-system-riscv64 -M virt -cpu rv64,priv_spec=v1.10.0,zicbom=on
> qemu-system-riscv64: H extension requires priv spec 1.12.0
> 
> This happened because, although 'zicbom=true' would bump priv ver to 1.12.0 if needed
> (it isn't - rv64 is already set to LATEST), "priv_spec=v1.10.0" is evaluated during
> finalize() time and the CPU priv_ver is set to 1.10 before our validation step.
> 
> This means that doesn't matter where the 'priv_spec' option is in the command line,
> it'll always be honored.

Oh, good. Sorry for the noise! But maybe a comment above the priv_ver bump
saying something along the lines of what you wrote here would help ease
the minds of those that cross this in the future (including the mind of my
future self after I've forgotten this again)

> 
> 
> > 
> > then, afaict, priv_spec will be silently bumped to 1.12. I think we should
> > error out in that case instead. And, we should also error out for
> > 
> >   -cpu rv64,zicbom=on,priv_spec=v1.10.0
> > 
> > which means we should know when priv_spec is either
> > 
> >   - its default value
> >   - has been bumped by an extension
> >   - has been explicitly set by the user
> 
> > 
> > > +}
> > > +
> > >   static void cpu_cfg_ext_auto_update(RISCVCPU *cpu, uint32_t ext_offset,
> > >                                       bool value)
> > >   {
> > > @@ -829,6 +845,10 @@ static void cpu_set_multi_ext_cfg(Object *obj, Visitor *v, const char *name,
> > >           return;
> > >       }
> > > +    if (value) {
> > > +        cpu_validate_multi_ext_priv_ver(&cpu->env, multi_ext_cfg->offset);
> > > +    }
> > 
> > Some misa extensions also have priv spec version dependencies. See
> > riscv_cpu_validate_misa_priv()
> 
> Yeah. I'll add this same mechanic to RVH, the only MISA bit we have that has a priv_ver
> limitation. Thanks,

Thanks,
drew


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v8 06/19] target/riscv: add rv64i CPU
  2023-11-02  9:59   ` Andrew Jones
@ 2023-11-02 14:23     ` Daniel Henrique Barboza
  0 siblings, 0 replies; 31+ messages in thread
From: Daniel Henrique Barboza @ 2023-11-02 14:23 UTC (permalink / raw)
  To: Andrew Jones
  Cc: qemu-devel, qemu-riscv, alistair.francis, bmeng, liweiwei,
	zhiwei_liu, palmer



On 11/2/23 06:59, Andrew Jones wrote:
> On Wed, Nov 01, 2023 at 05:41:51PM -0300, Daniel Henrique Barboza wrote:
>> We don't have any form of a 'bare bones' CPU. rv64, our default CPUs,
>> comes with a lot of defaults. This is fine for most regular uses but
>> it's not suitable when more control of what is actually loaded in the
>> CPU is required.
>>
>> A bare-bones CPU would be annoying to deal with if not by profile
>> support, a way to load a multitude of extensions with a single flag.
>> Profile support is going to be implemented shortly, so let's add a CPU
>> for it.
>>
>> The new 'rv64i' CPU will have only RVI loaded. It is inspired in the
>> profile specification that dictates, for RVA22U64 [1]:
>>
>> "RVA22U64 Mandatory Base
>>   RV64I is the mandatory base ISA for RVA22U64"
>>
>> And so it seems that RV64I is the mandatory base ISA for all profiles
>> listed in [1], making it an ideal CPU to use with profile support.
>>
>> rv64i is a CPU of type TYPE_RISCV_BARE_CPU. It has a mix of features
>> from pre-existent CPUs:
>>
>> - it allows extensions to be enabled, like generic CPUs;
>> - it will not inherit extension defaults, like vendor CPUs.
>>
>> This is the minimum extension set to boot OpenSBI and buildroot using
>> rv64i:
>>
>> ./build/qemu-system-riscv64 -nographic -M virt \
>>      -cpu rv64i,sv39=true,g=true,c=true,s=true,u=true
>>
>> Our minimal riscv,isa in this case will be:
>>
>>   # cat /proc/device-tree/cpus/cpu@0/riscv,isa
>> rv64imafdc_zicntr_zicsr_zifencei_zihpm_zca_zcd#
>>
>> [1] https://github.com/riscv/riscv-profiles/blob/main/profiles.adoc
>>
>> Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
>> ---
>>   target/riscv/cpu-qom.h |  2 ++
>>   target/riscv/cpu.c     | 23 +++++++++++++++++++++++
>>   2 files changed, 25 insertions(+)
>>
>> diff --git a/target/riscv/cpu-qom.h b/target/riscv/cpu-qom.h
>> index 7831e86d37..ea9a752280 100644
>> --- a/target/riscv/cpu-qom.h
>> +++ b/target/riscv/cpu-qom.h
>> @@ -25,6 +25,7 @@
>>   #define TYPE_RISCV_CPU "riscv-cpu"
>>   #define TYPE_RISCV_DYNAMIC_CPU "riscv-dynamic-cpu"
>>   #define TYPE_RISCV_VENDOR_CPU "riscv-vendor-cpu"
>> +#define TYPE_RISCV_BARE_CPU "riscv-bare-cpu"
>>   
>>   #define RISCV_CPU_TYPE_SUFFIX "-" TYPE_RISCV_CPU
>>   #define RISCV_CPU_TYPE_NAME(name) (name RISCV_CPU_TYPE_SUFFIX)
>> @@ -35,6 +36,7 @@
>>   #define TYPE_RISCV_CPU_BASE32           RISCV_CPU_TYPE_NAME("rv32")
>>   #define TYPE_RISCV_CPU_BASE64           RISCV_CPU_TYPE_NAME("rv64")
>>   #define TYPE_RISCV_CPU_BASE128          RISCV_CPU_TYPE_NAME("x-rv128")
>> +#define TYPE_RISCV_CPU_RV64I            RISCV_CPU_TYPE_NAME("rv64i")
>>   #define TYPE_RISCV_CPU_IBEX             RISCV_CPU_TYPE_NAME("lowrisc-ibex")
>>   #define TYPE_RISCV_CPU_SHAKTI_C         RISCV_CPU_TYPE_NAME("shakti-c")
>>   #define TYPE_RISCV_CPU_SIFIVE_E31       RISCV_CPU_TYPE_NAME("sifive-e31")
>> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
>> index f7c1989d14..4a6e544eaf 100644
>> --- a/target/riscv/cpu.c
>> +++ b/target/riscv/cpu.c
>> @@ -544,6 +544,16 @@ static void rv128_base_cpu_init(Object *obj)
>>       set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV57);
>>   #endif
>>   }
>> +
>> +static void rv64i_bare_cpu_init(Object *obj)
>> +{
>> +    CPURISCVState *env = &RISCV_CPU(obj)->env;
>> +    riscv_cpu_set_misa(env, MXL_RV64, RVI);
>> +
>> +    /* Remove the defaults from the parent class */
>> +    RISCV_CPU(obj)->cfg.ext_zicntr = false;
>> +    RISCV_CPU(obj)->cfg.ext_zihpm = false;
> 
> Good catch since v1, but having to do this is a bit gross. I'd prefer the
> parent class not enable any extensions. Each CPU type that needs these
> can just set them themselves.

It's less work to disable it for bare CPUs than to enable these 2 extensions for every
other existing CPUs. These 2 extensions need to be enabled by default to preserve
existing behavior.

For the future we can, for example, create a new parent device (e.g. TYPE_RISCV_CPU_LEGACY)
that enables these extensions. Current CPUs can inherit from it. TYPE_RISCV_CPU can then
remain pristine, no default extensions.

Thanks,


Daniel

> 
>> +}
>>   #else
>>   static void rv32_base_cpu_init(Object *obj)
>>   {
>> @@ -1753,6 +1763,13 @@ void riscv_cpu_list(void)
>>           .instance_init = initfn              \
>>       }
>>   
>> +#define DEFINE_BARE_CPU(type_name, initfn) \
>> +    {                                      \
>> +        .name = type_name,                 \
>> +        .parent = TYPE_RISCV_BARE_CPU,     \
>> +        .instance_init = initfn            \
>> +    }
>> +
>>   static const TypeInfo riscv_cpu_type_infos[] = {
>>       {
>>           .name = TYPE_RISCV_CPU,
>> @@ -1775,6 +1792,11 @@ static const TypeInfo riscv_cpu_type_infos[] = {
>>           .parent = TYPE_RISCV_CPU,
>>           .abstract = true,
>>       },
>> +    {
>> +        .name = TYPE_RISCV_BARE_CPU,
>> +        .parent = TYPE_RISCV_CPU,
>> +        .abstract = true,
>> +    },
>>       DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_ANY,      riscv_any_cpu_init),
>>       DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_MAX,      riscv_max_cpu_init),
>>   #if defined(TARGET_RISCV32)
>> @@ -1791,6 +1813,7 @@ static const TypeInfo riscv_cpu_type_infos[] = {
>>       DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_THEAD_C906,  rv64_thead_c906_cpu_init),
>>       DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_VEYRON_V1,   rv64_veyron_v1_cpu_init),
>>       DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_BASE128,  rv128_base_cpu_init),
>> +    DEFINE_BARE_CPU(TYPE_RISCV_CPU_RV64I, rv64i_bare_cpu_init),
>>   #endif
>>   };
>>   
>> -- 
>> 2.41.0
>>
> 
> We'll probably need to bring back the satp supported mode setting, as
> suggested on a previous patch, but otherwise
> 
> Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
> 
> Thanks,
> drew


^ permalink raw reply	[flat|nested] 31+ messages in thread

end of thread, other threads:[~2023-11-02 14:24 UTC | newest]

Thread overview: 31+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-11-01 20:41 [PATCH v8 00/19] rv64i CPU, RVA22U64 profile support Daniel Henrique Barboza
2023-11-01 20:41 ` [PATCH v8 01/19] target/riscv: create TYPE_RISCV_VENDOR_CPU Daniel Henrique Barboza
2023-11-02  2:32   ` Alistair Francis
2023-11-01 20:41 ` [PATCH v8 02/19] target/riscv/tcg: do not use "!generic" CPU checks Daniel Henrique Barboza
2023-11-02  2:38   ` Alistair Francis
2023-11-01 20:41 ` [PATCH v8 03/19] target/riscv/cpu.c: set satp_max_supported in cpu_riscv_set_satp() Daniel Henrique Barboza
2023-11-02  9:24   ` Andrew Jones
2023-11-02 12:53     ` Daniel Henrique Barboza
2023-11-02 13:11       ` Andrew Jones
2023-11-01 20:41 ` [PATCH v8 04/19] target/riscv/cpu.c: set satp_mode_max MBARE during satp_finalize() Daniel Henrique Barboza
2023-11-02  9:32   ` Andrew Jones
2023-11-01 20:41 ` [PATCH v8 05/19] target/riscv/tcg: update priv_ver on user_set extensions Daniel Henrique Barboza
2023-11-02  9:47   ` Andrew Jones
2023-11-02 13:42     ` Daniel Henrique Barboza
2023-11-02 13:48       ` Andrew Jones
2023-11-01 20:41 ` [PATCH v8 06/19] target/riscv: add rv64i CPU Daniel Henrique Barboza
2023-11-02  9:59   ` Andrew Jones
2023-11-02 14:23     ` Daniel Henrique Barboza
2023-11-01 20:41 ` [PATCH v8 07/19] target/riscv: add zicbop extension flag Daniel Henrique Barboza
2023-11-01 20:41 ` [PATCH v8 08/19] target/riscv/tcg: add 'zic64b' support Daniel Henrique Barboza
2023-11-01 20:41 ` [PATCH v8 09/19] riscv-qmp-cmds.c: expose named features in cpu_model_expansion Daniel Henrique Barboza
2023-11-01 20:41 ` [PATCH v8 10/19] target/riscv: add rva22u64 profile definition Daniel Henrique Barboza
2023-11-01 20:41 ` [PATCH v8 11/19] target/riscv/kvm: add 'rva22u64' flag as unavailable Daniel Henrique Barboza
2023-11-01 20:41 ` [PATCH v8 12/19] target/riscv/tcg: add user flag for profile support Daniel Henrique Barboza
2023-11-01 20:41 ` [PATCH v8 13/19] target/riscv/tcg: add MISA user options hash Daniel Henrique Barboza
2023-11-01 20:41 ` [PATCH v8 14/19] target/riscv/tcg: add riscv_cpu_write_misa_bit() Daniel Henrique Barboza
2023-11-01 20:42 ` [PATCH v8 15/19] target/riscv/tcg: handle profile MISA bits Daniel Henrique Barboza
2023-11-01 20:42 ` [PATCH v8 16/19] target/riscv/tcg: add hash table insert helpers Daniel Henrique Barboza
2023-11-01 20:42 ` [PATCH v8 17/19] target/riscv/tcg: honor user choice for G MISA bits Daniel Henrique Barboza
2023-11-01 20:42 ` [PATCH v8 18/19] target/riscv/tcg: validate profiles during finalize Daniel Henrique Barboza
2023-11-01 20:42 ` [PATCH v8 19/19] riscv-qmp-cmds.c: add profile flags in cpu-model-expansion Daniel Henrique Barboza

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).