All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v7 00/16] rv64i CPU, RVA22U64 profile support
@ 2023-10-31 20:39 Daniel Henrique Barboza
  2023-10-31 20:39 ` [PATCH v7 01/16] target/riscv: create TYPE_RISCV_VENDOR_CPU Daniel Henrique Barboza
                   ` (15 more replies)
  0 siblings, 16 replies; 25+ messages in thread
From: Daniel Henrique Barboza @ 2023-10-31 20:39 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-riscv, alistair.francis, bmeng, liweiwei, zhiwei_liu,
	palmer, ajones, Daniel Henrique Barboza

Hi,

As discussed in v6, all our problems with the profile implementation
cames from the rv64 CPU and how to deal with its defaults. Enabling a
profile on top of it is straightforward, but disabling it (either via a
script trying to undo a profile enablement, or users doing something
silly) makes things complicated - disabling all the mandatory extensions
will overwrite the CPU defaults, but doing nothing is weird considering
how QEMU options work. And therein lies the rub: we didn't have any
other way of consuming profiles, so we were stuck dancing around rv64
defaults and what to do with them.

In this v7 we're adding a new CPU called 'rv64i'. This is a new type of
CPUs, called 'bare', that doesn't inherit any defaults and allows users
to enable/disable extensions at will. This CPU is implementing bare
RV64I for a reason: this is the mandatory ISA for profiles support.

All the design around profile support is now made on top of how rv64i
works.  Other non-vendor CPUs (like rv64) can still use profiles, but
now we're not concerned about what happens if an user does '-cpu
rv64,rva22u64=false'. In short, we recommend using profiles with rv64i
but we won't forbid using it with rv64 (in particular because stock rv64
does not implement rva22u64, which is surprising giving it has a lot of
defaults ...). Patches 1, 2 and 3 implements rv64i. 

Another noticeable change was made in patches 15 and 16. We're now
exposing the profile flag to all CPUs. In the end a profile is just a
set of mandatory extensions and conditions that must be met. If the
conditions are met we should enable the flag, regardless of user input.
This is done by changes in patch 15. Patch 16 changes
query-cpu-model-expansion to show profile flags.

Patches based on top of Alistair's riscv-to-apply.next.

Patches missing acks: 1, 2, 3, 5, 15, 16

Changes from v6:
- patch 1 (new):
  - create vendor CPU type
- patch 2 (new):
  - check for 'if vendorCPU' instead of 'if !genericCPU'
- patch 3 (new):
  - add rv64i CPU
- patch 5 (former patch 2 from v6):
  - drop the CB_DEF_VALUE define
- patch 6 (fomer patch 3 from v6):
  - mention cbop block size in commit msg
- patch 9 (former patch 6 from v6):
  - removed the "no-op" when disabling a profile
  - rewrote the commit msg to reflect that the design is made on top of the rv64i CPU
- patch 12 (fomer patch 9 from v6):
  - do not disable RVI when disabling a profile
- patch 15 (patch 12 from v6):
  - previous acks revoked due to the amount of changes made
  - disable profile flags if there are missing mandatory extensions during finalize()
  - enable profile flags if all its preconditions are met during
    finalize()
- patch 16 (new):
  - add profile flags to query-cpu-model-expansion
- v6 link: https://lore.kernel.org/qemu-riscv/20231028085427.707060-1-dbarboza@ventanamicro.com/

Daniel Henrique Barboza (16):
  target/riscv: create TYPE_RISCV_VENDOR_CPU
  target/riscv/tcg: do not use "!generic" CPU checks
  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            |  96 ++++++++++-
 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    | 301 +++++++++++++++++++++++++++++-----
 8 files changed, 412 insertions(+), 60 deletions(-)

-- 
2.41.0



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

* [PATCH v7 01/16] target/riscv: create TYPE_RISCV_VENDOR_CPU
  2023-10-31 20:39 [PATCH v7 00/16] rv64i CPU, RVA22U64 profile support Daniel Henrique Barboza
@ 2023-10-31 20:39 ` Daniel Henrique Barboza
  2023-11-01  9:19   ` Andrew Jones
  2023-10-31 20:39 ` [PATCH v7 02/16] target/riscv/tcg: do not use "!generic" CPU checks Daniel Henrique Barboza
                   ` (14 subsequent siblings)
  15 siblings, 1 reply; 25+ messages in thread
From: Daniel Henrique Barboza @ 2023-10-31 20:39 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>
---
 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] 25+ messages in thread

* [PATCH v7 02/16] target/riscv/tcg: do not use "!generic" CPU checks
  2023-10-31 20:39 [PATCH v7 00/16] rv64i CPU, RVA22U64 profile support Daniel Henrique Barboza
  2023-10-31 20:39 ` [PATCH v7 01/16] target/riscv: create TYPE_RISCV_VENDOR_CPU Daniel Henrique Barboza
@ 2023-10-31 20:39 ` Daniel Henrique Barboza
  2023-11-01  9:20   ` Andrew Jones
  2023-10-31 20:39 ` [PATCH v7 03/16] target/riscv: add rv64i CPU Daniel Henrique Barboza
                   ` (13 subsequent siblings)
  15 siblings, 1 reply; 25+ messages in thread
From: Daniel Henrique Barboza @ 2023-10-31 20:39 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>
---
 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] 25+ messages in thread

* [PATCH v7 03/16] target/riscv: add rv64i CPU
  2023-10-31 20:39 [PATCH v7 00/16] rv64i CPU, RVA22U64 profile support Daniel Henrique Barboza
  2023-10-31 20:39 ` [PATCH v7 01/16] target/riscv: create TYPE_RISCV_VENDOR_CPU Daniel Henrique Barboza
  2023-10-31 20:39 ` [PATCH v7 02/16] target/riscv/tcg: do not use "!generic" CPU checks Daniel Henrique Barboza
@ 2023-10-31 20:39 ` Daniel Henrique Barboza
  2023-11-01  9:02   ` Andrew Jones
  2023-10-31 20:39 ` [PATCH v7 04/16] target/riscv: add zicbop extension flag Daniel Henrique Barboza
                   ` (12 subsequent siblings)
  15 siblings, 1 reply; 25+ messages in thread
From: Daniel Henrique Barboza @ 2023-10-31 20:39 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,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     | 25 +++++++++++++++++++++++++
 2 files changed, 27 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 822970345c..98b2a4061a 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -544,6 +544,18 @@ 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);
+
+    /* Set latest version of privileged specification */
+    env->priv_ver = PRIV_VERSION_LATEST;
+#ifndef CONFIG_USER_ONLY
+    set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV57);
+#endif
+}
 #else
 static void rv32_base_cpu_init(Object *obj)
 {
@@ -1732,6 +1744,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,
@@ -1754,6 +1773,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)
@@ -1770,6 +1794,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] 25+ messages in thread

* [PATCH v7 04/16] target/riscv: add zicbop extension flag
  2023-10-31 20:39 [PATCH v7 00/16] rv64i CPU, RVA22U64 profile support Daniel Henrique Barboza
                   ` (2 preceding siblings ...)
  2023-10-31 20:39 ` [PATCH v7 03/16] target/riscv: add rv64i CPU Daniel Henrique Barboza
@ 2023-10-31 20:39 ` Daniel Henrique Barboza
  2023-10-31 20:39 ` [PATCH v7 05/16] target/riscv/tcg: add 'zic64b' support Daniel Henrique Barboza
                   ` (11 subsequent siblings)
  15 siblings, 0 replies; 25+ messages in thread
From: Daniel Henrique Barboza @ 2023-10-31 20:39 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 98b2a4061a..7e5ad76eff 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),
@@ -1348,6 +1349,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),
@@ -1436,6 +1438,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] 25+ messages in thread

* [PATCH v7 05/16] target/riscv/tcg: add 'zic64b' support
  2023-10-31 20:39 [PATCH v7 00/16] rv64i CPU, RVA22U64 profile support Daniel Henrique Barboza
                   ` (3 preceding siblings ...)
  2023-10-31 20:39 ` [PATCH v7 04/16] target/riscv: add zicbop extension flag Daniel Henrique Barboza
@ 2023-10-31 20:39 ` Daniel Henrique Barboza
  2023-11-01  9:04   ` Andrew Jones
  2023-10-31 20:39 ` [PATCH v7 06/16] riscv-qmp-cmds.c: expose named features in cpu_model_expansion Daniel Henrique Barboza
                   ` (10 subsequent siblings)
  15 siblings, 1 reply; 25+ messages in thread
From: Daniel Henrique Barboza @ 2023-10-31 20:39 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>
---
 target/riscv/cpu.c         |  6 ++++++
 target/riscv/cpu.h         |  1 +
 target/riscv/cpu_cfg.h     |  1 +
 target/riscv/tcg/tcg-cpu.c | 14 ++++++++++++++
 4 files changed, 22 insertions(+)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 7e5ad76eff..f284604857 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -1408,6 +1408,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 f54069d06f..8aa17ffaa2 100644
--- a/target/riscv/tcg/tcg-cpu.c
+++ b/target/riscv/tcg/tcg-cpu.c
@@ -264,6 +264,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.
@@ -586,6 +598,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] 25+ messages in thread

* [PATCH v7 06/16] riscv-qmp-cmds.c: expose named features in cpu_model_expansion
  2023-10-31 20:39 [PATCH v7 00/16] rv64i CPU, RVA22U64 profile support Daniel Henrique Barboza
                   ` (4 preceding siblings ...)
  2023-10-31 20:39 ` [PATCH v7 05/16] target/riscv/tcg: add 'zic64b' support Daniel Henrique Barboza
@ 2023-10-31 20:39 ` Daniel Henrique Barboza
  2023-10-31 20:39 ` [PATCH v7 07/16] target/riscv: add rva22u64 profile definition Daniel Henrique Barboza
                   ` (9 subsequent siblings)
  15 siblings, 0 replies; 25+ messages in thread
From: Daniel Henrique Barboza @ 2023-10-31 20:39 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] 25+ messages in thread

* [PATCH v7 07/16] target/riscv: add rva22u64 profile definition
  2023-10-31 20:39 [PATCH v7 00/16] rv64i CPU, RVA22U64 profile support Daniel Henrique Barboza
                   ` (5 preceding siblings ...)
  2023-10-31 20:39 ` [PATCH v7 06/16] riscv-qmp-cmds.c: expose named features in cpu_model_expansion Daniel Henrique Barboza
@ 2023-10-31 20:39 ` Daniel Henrique Barboza
  2023-10-31 20:39 ` [PATCH v7 08/16] target/riscv/kvm: add 'rva22u64' flag as unavailable Daniel Henrique Barboza
                   ` (8 subsequent siblings)
  15 siblings, 0 replies; 25+ messages in thread
From: Daniel Henrique Barboza @ 2023-10-31 20:39 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 f284604857..5f0089a01f 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -1450,6 +1450,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] 25+ messages in thread

* [PATCH v7 08/16] target/riscv/kvm: add 'rva22u64' flag as unavailable
  2023-10-31 20:39 [PATCH v7 00/16] rv64i CPU, RVA22U64 profile support Daniel Henrique Barboza
                   ` (6 preceding siblings ...)
  2023-10-31 20:39 ` [PATCH v7 07/16] target/riscv: add rva22u64 profile definition Daniel Henrique Barboza
@ 2023-10-31 20:39 ` Daniel Henrique Barboza
  2023-10-31 20:39 ` [PATCH v7 09/16] target/riscv/tcg: add user flag for profile support Daniel Henrique Barboza
                   ` (7 subsequent siblings)
  15 siblings, 0 replies; 25+ messages in thread
From: Daniel Henrique Barboza @ 2023-10-31 20:39 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] 25+ messages in thread

* [PATCH v7 09/16] target/riscv/tcg: add user flag for profile support
  2023-10-31 20:39 [PATCH v7 00/16] rv64i CPU, RVA22U64 profile support Daniel Henrique Barboza
                   ` (7 preceding siblings ...)
  2023-10-31 20:39 ` [PATCH v7 08/16] target/riscv/kvm: add 'rva22u64' flag as unavailable Daniel Henrique Barboza
@ 2023-10-31 20:39 ` Daniel Henrique Barboza
  2023-10-31 20:39 ` [PATCH v7 10/16] target/riscv/tcg: add MISA user options hash Daniel Henrique Barboza
                   ` (6 subsequent siblings)
  15 siblings, 0 replies; 25+ messages in thread
From: Daniel Henrique Barboza @ 2023-10-31 20:39 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,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 | 59 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 59 insertions(+)

diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
index 8aa17ffaa2..3e31a41859 100644
--- a/target/riscv/tcg/tcg-cpu.c
+++ b/target/riscv/tcg/tcg-cpu.c
@@ -788,6 +788,63 @@ 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];
+
+        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]);
@@ -911,6 +968,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] 25+ messages in thread

* [PATCH v7 10/16] target/riscv/tcg: add MISA user options hash
  2023-10-31 20:39 [PATCH v7 00/16] rv64i CPU, RVA22U64 profile support Daniel Henrique Barboza
                   ` (8 preceding siblings ...)
  2023-10-31 20:39 ` [PATCH v7 09/16] target/riscv/tcg: add user flag for profile support Daniel Henrique Barboza
@ 2023-10-31 20:39 ` Daniel Henrique Barboza
  2023-10-31 20:39 ` [PATCH v7 11/16] target/riscv/tcg: add riscv_cpu_write_misa_bit() Daniel Henrique Barboza
                   ` (5 subsequent siblings)
  15 siblings, 0 replies; 25+ messages in thread
From: Daniel Henrique Barboza @ 2023-10-31 20:39 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 3e31a41859..70cd07efd7 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)
 {
@@ -700,6 +701,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) {
@@ -763,6 +768,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;
 
@@ -783,7 +789,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;
+            }
         }
     }
 }
@@ -1020,6 +1032,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] 25+ messages in thread

* [PATCH v7 11/16] target/riscv/tcg: add riscv_cpu_write_misa_bit()
  2023-10-31 20:39 [PATCH v7 00/16] rv64i CPU, RVA22U64 profile support Daniel Henrique Barboza
                   ` (9 preceding siblings ...)
  2023-10-31 20:39 ` [PATCH v7 10/16] target/riscv/tcg: add MISA user options hash Daniel Henrique Barboza
@ 2023-10-31 20:39 ` Daniel Henrique Barboza
  2023-10-31 20:39 ` [PATCH v7 12/16] target/riscv/tcg: handle profile MISA bits Daniel Henrique Barboza
                   ` (4 subsequent siblings)
  15 siblings, 0 replies; 25+ messages in thread
From: Daniel Henrique Barboza @ 2023-10-31 20:39 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 70cd07efd7..b62890e568 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)
 {
@@ -711,20 +725,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,
@@ -768,7 +776,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;
 
@@ -789,13 +796,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] 25+ messages in thread

* [PATCH v7 12/16] target/riscv/tcg: handle profile MISA bits
  2023-10-31 20:39 [PATCH v7 00/16] rv64i CPU, RVA22U64 profile support Daniel Henrique Barboza
                   ` (10 preceding siblings ...)
  2023-10-31 20:39 ` [PATCH v7 11/16] target/riscv/tcg: add riscv_cpu_write_misa_bit() Daniel Henrique Barboza
@ 2023-10-31 20:39 ` Daniel Henrique Barboza
  2023-10-31 20:39 ` [PATCH v7 13/16] target/riscv/tcg: add hash table insert helpers Daniel Henrique Barboza
                   ` (3 subsequent siblings)
  15 siblings, 0 replies; 25+ messages in thread
From: Daniel Henrique Barboza @ 2023-10-31 20:39 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,s=true,zifencei=true

In the near future, when rva22s64 (where both 's' and 'zifencei' are
mandatory) support is added, 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 b62890e568..4a915acff4 100644
--- a/target/riscv/tcg/tcg-cpu.c
+++ b/target/riscv/tcg/tcg-cpu.c
@@ -829,6 +829,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] 25+ messages in thread

* [PATCH v7 13/16] target/riscv/tcg: add hash table insert helpers
  2023-10-31 20:39 [PATCH v7 00/16] rv64i CPU, RVA22U64 profile support Daniel Henrique Barboza
                   ` (11 preceding siblings ...)
  2023-10-31 20:39 ` [PATCH v7 12/16] target/riscv/tcg: handle profile MISA bits Daniel Henrique Barboza
@ 2023-10-31 20:39 ` Daniel Henrique Barboza
  2023-10-31 20:39 ` [PATCH v7 14/16] target/riscv/tcg: honor user choice for G MISA bits Daniel Henrique Barboza
                   ` (2 subsequent siblings)
  15 siblings, 0 replies; 25+ messages in thread
From: Daniel Henrique Barboza @ 2023-10-31 20:39 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 4a915acff4..9127249f85 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)
 {
@@ -715,9 +727,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;
 
@@ -844,18 +854,14 @@ 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);
     }
 
     for (i = 0; profile->ext_offsets[i] != RISCV_PROFILE_EXT_LIST_END; i++) {
         ext_offset = profile->ext_offsets[i];
 
-        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);
     }
 }
@@ -918,9 +924,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] 25+ messages in thread

* [PATCH v7 14/16] target/riscv/tcg: honor user choice for G MISA bits
  2023-10-31 20:39 [PATCH v7 00/16] rv64i CPU, RVA22U64 profile support Daniel Henrique Barboza
                   ` (12 preceding siblings ...)
  2023-10-31 20:39 ` [PATCH v7 13/16] target/riscv/tcg: add hash table insert helpers Daniel Henrique Barboza
@ 2023-10-31 20:39 ` Daniel Henrique Barboza
  2023-10-31 20:39 ` [PATCH v7 15/16] target/riscv/tcg: validate profiles during finalize Daniel Henrique Barboza
  2023-10-31 20:39 ` [PATCH v7 16/16] riscv-qmp-cmds.c: add profile flags in cpu-model-expansion Daniel Henrique Barboza
  15 siblings, 0 replies; 25+ messages in thread
From: Daniel Henrique Barboza @ 2023-10-31 20:39 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 9127249f85..544f6dd01d 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),
@@ -303,6 +309,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.
@@ -312,31 +358,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] 25+ messages in thread

* [PATCH v7 15/16] target/riscv/tcg: validate profiles during finalize
  2023-10-31 20:39 [PATCH v7 00/16] rv64i CPU, RVA22U64 profile support Daniel Henrique Barboza
                   ` (13 preceding siblings ...)
  2023-10-31 20:39 ` [PATCH v7 14/16] target/riscv/tcg: honor user choice for G MISA bits Daniel Henrique Barboza
@ 2023-10-31 20:39 ` Daniel Henrique Barboza
  2023-11-01  9:17   ` Andrew Jones
  2023-10-31 20:39 ` [PATCH v7 16/16] riscv-qmp-cmds.c: add profile flags in cpu-model-expansion Daniel Henrique Barboza
  15 siblings, 1 reply; 25+ messages in thread
From: Daniel Henrique Barboza @ 2023-10-31 20:39 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>
---
 target/riscv/tcg/tcg-cpu.c | 70 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 70 insertions(+)

diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
index 544f6dd01d..23007b19e4 100644
--- a/target/riscv/tcg/tcg-cpu.c
+++ b/target/riscv/tcg/tcg-cpu.c
@@ -147,6 +147,27 @@ 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 && edata->name; 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 void cpu_cfg_ext_auto_update(RISCVCPU *cpu, uint32_t ext_offset,
                                     bool value)
 {
@@ -631,6 +652,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;
@@ -649,6 +718,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] 25+ messages in thread

* [PATCH v7 16/16] riscv-qmp-cmds.c: add profile flags in cpu-model-expansion
  2023-10-31 20:39 [PATCH v7 00/16] rv64i CPU, RVA22U64 profile support Daniel Henrique Barboza
                   ` (14 preceding siblings ...)
  2023-10-31 20:39 ` [PATCH v7 15/16] target/riscv/tcg: validate profiles during finalize Daniel Henrique Barboza
@ 2023-10-31 20:39 ` Daniel Henrique Barboza
  2023-11-01  9:19   ` Andrew Jones
  15 siblings, 1 reply; 25+ messages in thread
From: Daniel Henrique Barboza @ 2023-10-31 20:39 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>
---
 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] 25+ messages in thread

* Re: [PATCH v7 03/16] target/riscv: add rv64i CPU
  2023-10-31 20:39 ` [PATCH v7 03/16] target/riscv: add rv64i CPU Daniel Henrique Barboza
@ 2023-11-01  9:02   ` Andrew Jones
  2023-11-01  9:27     ` Daniel Henrique Barboza
  0 siblings, 1 reply; 25+ messages in thread
From: Andrew Jones @ 2023-11-01  9:02 UTC (permalink / raw)
  To: Daniel Henrique Barboza
  Cc: qemu-devel, qemu-riscv, alistair.francis, bmeng, liweiwei,
	zhiwei_liu, palmer

On Tue, Oct 31, 2023 at 05:39:03PM -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,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     | 25 +++++++++++++++++++++++++
>  2 files changed, 27 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 822970345c..98b2a4061a 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -544,6 +544,18 @@ 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);
> +
> +    /* Set latest version of privileged specification */
> +    env->priv_ver = PRIV_VERSION_LATEST;

The beauty of rv64i is we'll finally know exactly what we're configuring
when we select it and some set of extensions. With that in mind I think
we should also be explicit about which version of the priv spec is
implemented, but we can't just pick a version now, since we may need to
update it later. I think we have the following options:

 1. Expose priv version properties (v1_10_0, ...) and either require the
    user to select one or default to the latest. (Any versions we don't
    want to support for rv64i would error out if selected.)

 2. Add multiple rv64i base cpu types where the version is also specified
    in the name, e.g. rv64i_1_12_0, and then maybe have an rv64i alias
    which always points at the latest.

A nice thing about (1) is that we can expose the boolean version
properties in cpu model expansion. A nice thing about (2) is that the user
will either be forced to select an explicit version or, if we have the
alias, libvirt will convert 'rv64i' into its full name when storing it
in the XML. But, we can force the user to select a version with (1) too by
not providing a default. While that adds a burden of always having to
provide a version, it's not a big deal for a barebones cpu, since all
extensions necessary to create a useful cpu are also required. And,
profiles alleviate the burden. For example, rva22s64 mandates Ss1p12, so
that profile will automatically set the v1_12_0 property.

I think we should implement (1) without a default.

> +#ifndef CONFIG_USER_ONLY
> +    set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV57);

I think we should require the user provide one of sv39, sv48, ... rather
than have a default for this too. S-mode profiles will again automatically
set this to what it mandates, relieving the burden.

> +#endif
> +}
>  #else
>  static void rv32_base_cpu_init(Object *obj)
>  {
> @@ -1732,6 +1744,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,
> @@ -1754,6 +1773,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)
> @@ -1770,6 +1794,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
>

Thanks,
drew


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

* Re: [PATCH v7 05/16] target/riscv/tcg: add 'zic64b' support
  2023-10-31 20:39 ` [PATCH v7 05/16] target/riscv/tcg: add 'zic64b' support Daniel Henrique Barboza
@ 2023-11-01  9:04   ` Andrew Jones
  0 siblings, 0 replies; 25+ messages in thread
From: Andrew Jones @ 2023-11-01  9:04 UTC (permalink / raw)
  To: Daniel Henrique Barboza
  Cc: qemu-devel, qemu-riscv, alistair.francis, bmeng, liweiwei,
	zhiwei_liu, palmer

On Tue, Oct 31, 2023 at 05:39:05PM -0300, Daniel Henrique Barboza wrote:
> 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>
> ---
>  target/riscv/cpu.c         |  6 ++++++
>  target/riscv/cpu.h         |  1 +
>  target/riscv/cpu_cfg.h     |  1 +
>  target/riscv/tcg/tcg-cpu.c | 14 ++++++++++++++
>  4 files changed, 22 insertions(+)
>

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


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

* Re: [PATCH v7 15/16] target/riscv/tcg: validate profiles during finalize
  2023-10-31 20:39 ` [PATCH v7 15/16] target/riscv/tcg: validate profiles during finalize Daniel Henrique Barboza
@ 2023-11-01  9:17   ` Andrew Jones
  0 siblings, 0 replies; 25+ messages in thread
From: Andrew Jones @ 2023-11-01  9:17 UTC (permalink / raw)
  To: Daniel Henrique Barboza
  Cc: qemu-devel, qemu-riscv, alistair.francis, bmeng, liweiwei,
	zhiwei_liu, palmer

On Tue, Oct 31, 2023 at 05:39:15PM -0300, Daniel Henrique Barboza wrote:
> 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>
> ---
>  target/riscv/tcg/tcg-cpu.c | 70 ++++++++++++++++++++++++++++++++++++++
>  1 file changed, 70 insertions(+)
> 
> diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
> index 544f6dd01d..23007b19e4 100644
> --- a/target/riscv/tcg/tcg-cpu.c
> +++ b/target/riscv/tcg/tcg-cpu.c
> @@ -147,6 +147,27 @@ 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 && edata->name; edata++) {

No need to check edata isn't null since we have the end-of-list, just like
feat isn't checked below.

> +        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();
> +}
> +
> +

extra blank line here

>  static void cpu_cfg_ext_auto_update(RISCVCPU *cpu, uint32_t ext_offset,
>                                      bool value)
>  {
> @@ -631,6 +652,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;
> @@ -649,6 +718,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
>

Other than the nits,

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


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

* Re: [PATCH v7 16/16] riscv-qmp-cmds.c: add profile flags in cpu-model-expansion
  2023-10-31 20:39 ` [PATCH v7 16/16] riscv-qmp-cmds.c: add profile flags in cpu-model-expansion Daniel Henrique Barboza
@ 2023-11-01  9:19   ` Andrew Jones
  0 siblings, 0 replies; 25+ messages in thread
From: Andrew Jones @ 2023-11-01  9:19 UTC (permalink / raw)
  To: Daniel Henrique Barboza
  Cc: qemu-devel, qemu-riscv, alistair.francis, bmeng, liweiwei,
	zhiwei_liu, palmer

On Tue, Oct 31, 2023 at 05:39:16PM -0300, Daniel Henrique Barboza wrote:
> 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, ...}}}}

Nice!

> 
> 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>
> ---
>  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
>

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


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

* Re: [PATCH v7 01/16] target/riscv: create TYPE_RISCV_VENDOR_CPU
  2023-10-31 20:39 ` [PATCH v7 01/16] target/riscv: create TYPE_RISCV_VENDOR_CPU Daniel Henrique Barboza
@ 2023-11-01  9:19   ` Andrew Jones
  0 siblings, 0 replies; 25+ messages in thread
From: Andrew Jones @ 2023-11-01  9:19 UTC (permalink / raw)
  To: Daniel Henrique Barboza
  Cc: qemu-devel, qemu-riscv, alistair.francis, bmeng, liweiwei,
	zhiwei_liu, palmer

On Tue, Oct 31, 2023 at 05:39:01PM -0300, Daniel Henrique Barboza 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>
> ---
>  target/riscv/cpu-qom.h |  1 +
>  target/riscv/cpu.c     | 30 +++++++++++++++++++++---------
>  2 files changed, 22 insertions(+), 9 deletions(-)
>

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


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

* Re: [PATCH v7 02/16] target/riscv/tcg: do not use "!generic" CPU checks
  2023-10-31 20:39 ` [PATCH v7 02/16] target/riscv/tcg: do not use "!generic" CPU checks Daniel Henrique Barboza
@ 2023-11-01  9:20   ` Andrew Jones
  0 siblings, 0 replies; 25+ messages in thread
From: Andrew Jones @ 2023-11-01  9:20 UTC (permalink / raw)
  To: Daniel Henrique Barboza
  Cc: qemu-devel, qemu-riscv, alistair.francis, bmeng, liweiwei,
	zhiwei_liu, palmer

On Tue, Oct 31, 2023 at 05:39:02PM -0300, Daniel Henrique Barboza 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>
> ---
>  target/riscv/tcg/tcg-cpu.c | 13 +++++++++----
>  1 file changed, 9 insertions(+), 4 deletions(-)
>

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


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

* Re: [PATCH v7 03/16] target/riscv: add rv64i CPU
  2023-11-01  9:02   ` Andrew Jones
@ 2023-11-01  9:27     ` Daniel Henrique Barboza
  2023-11-01  9:47       ` Andrew Jones
  0 siblings, 1 reply; 25+ messages in thread
From: Daniel Henrique Barboza @ 2023-11-01  9:27 UTC (permalink / raw)
  To: Andrew Jones
  Cc: qemu-devel, qemu-riscv, alistair.francis, bmeng, liweiwei,
	zhiwei_liu, palmer



On 11/1/23 06:02, Andrew Jones wrote:
> On Tue, Oct 31, 2023 at 05:39:03PM -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,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     | 25 +++++++++++++++++++++++++
>>   2 files changed, 27 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 822970345c..98b2a4061a 100644
>> --- a/target/riscv/cpu.c
>> +++ b/target/riscv/cpu.c
>> @@ -544,6 +544,18 @@ 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);
>> +
>> +    /* Set latest version of privileged specification */
>> +    env->priv_ver = PRIV_VERSION_LATEST;
> 
> The beauty of rv64i is we'll finally know exactly what we're configuring
> when we select it and some set of extensions. With that in mind I think
> we should also be explicit about which version of the priv spec is
> implemented, but we can't just pick a version now, since we may need to
> update it later. I think we have the following options:
> 
>   1. Expose priv version properties (v1_10_0, ...) and either require the
>      user to select one or default to the latest. (Any versions we don't
>      want to support for rv64i would error out if selected.)

This is already the case but it's a string property instead of booleans:

$ ./build/qemu-system-riscv64 -M virt -cpu rv64i,priv_spec="v1.11.0"
$ ./build/qemu-system-riscv64 -M virt -cpu rv64i,priv_spec="v1.10.0"
$ ./build/qemu-system-riscv64 -M virt -cpu rv64i,priv_spec="not_valid"
qemu-system-riscv64: Unsupported privilege spec version 'not_valid'

If users set 'priv_spec' we'll use it, otherwise rv64i will default to 'latest'.

In case we do not want string values (and yeah, it's extra work to parse it, check
if it's the right val and so on) then we can add priv spec bools that users would
set on or off. We would need to deprecate "priv_spec" as it is.

This can be done outside of this work (we would need a RFC first probably).

> 
>   2. Add multiple rv64i base cpu types where the version is also specified
>      in the name, e.g. rv64i_1_12_0, and then maybe have an rv64i alias
>      which always points at the latest.
> 
> A nice thing about (1) is that we can expose the boolean version
> properties in cpu model expansion. A nice thing about (2) is that the user
> will either be forced to select an explicit version or, if we have the
> alias, libvirt will convert 'rv64i' into its full name when storing it
> in the XML. But, we can force the user to select a version with (1) too by
> not providing a default. While that adds a burden of always having to
> provide a version, it's not a big deal for a barebones cpu, since all
> extensions necessary to create a useful cpu are also required. And,
> profiles alleviate the burden. For example, rva22s64 mandates Ss1p12, so
> that profile will automatically set the v1_12_0 property.
> 
> I think we should implement (1) without a default.
> 
>> +#ifndef CONFIG_USER_ONLY
>> +    set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV57);
> 
> I think we should require the user provide one of sv39, sv48, ... rather
> than have a default for this too. S-mode profiles will again automatically
> set this to what it mandates, relieving the burden.

Makes sense. I'll remove this default.


Thanks,


Daniel

> 
>> +#endif
>> +}
>>   #else
>>   static void rv32_base_cpu_init(Object *obj)
>>   {
>> @@ -1732,6 +1744,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,
>> @@ -1754,6 +1773,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)
>> @@ -1770,6 +1794,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
>>
> 
> Thanks,
> drew


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

* Re: [PATCH v7 03/16] target/riscv: add rv64i CPU
  2023-11-01  9:27     ` Daniel Henrique Barboza
@ 2023-11-01  9:47       ` Andrew Jones
  0 siblings, 0 replies; 25+ messages in thread
From: Andrew Jones @ 2023-11-01  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 06:27:02AM -0300, Daniel Henrique Barboza wrote:
> 
> 
> On 11/1/23 06:02, Andrew Jones wrote:
> > On Tue, Oct 31, 2023 at 05:39:03PM -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,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     | 25 +++++++++++++++++++++++++
> > >   2 files changed, 27 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 822970345c..98b2a4061a 100644
> > > --- a/target/riscv/cpu.c
> > > +++ b/target/riscv/cpu.c
> > > @@ -544,6 +544,18 @@ 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);
> > > +
> > > +    /* Set latest version of privileged specification */
> > > +    env->priv_ver = PRIV_VERSION_LATEST;
> > 
> > The beauty of rv64i is we'll finally know exactly what we're configuring
> > when we select it and some set of extensions. With that in mind I think
> > we should also be explicit about which version of the priv spec is
> > implemented, but we can't just pick a version now, since we may need to
> > update it later. I think we have the following options:
> > 
> >   1. Expose priv version properties (v1_10_0, ...) and either require the
> >      user to select one or default to the latest. (Any versions we don't
> >      want to support for rv64i would error out if selected.)
> 
> This is already the case but it's a string property instead of booleans:
> 
> $ ./build/qemu-system-riscv64 -M virt -cpu rv64i,priv_spec="v1.11.0"
> $ ./build/qemu-system-riscv64 -M virt -cpu rv64i,priv_spec="v1.10.0"
> $ ./build/qemu-system-riscv64 -M virt -cpu rv64i,priv_spec="not_valid"
> qemu-system-riscv64: Unsupported privilege spec version 'not_valid'
> 
> If users set 'priv_spec' we'll use it, otherwise rv64i will default to 'latest'.

I think I'd prefer we don't have a default, but maybe in practice it'll be
OK, since once we have S-mode profiles (which will most likely always be
used with rv64i) then they'll override the default anyway.

> 
> In case we do not want string values (and yeah, it's extra work to parse it, check
> if it's the right val and so on) then we can add priv spec bools that users would
> set on or off. We would need to deprecate "priv_spec" as it is.

Yes, we should switch to booleans for cpu-model-expansion. I suppose we
should keep the priv_ver default until we switch to booleans, though, in
order to avoid encouraging more deprecated priv_spec usage in the
meantime.

> 
> This can be done outside of this work (we would need a RFC first probably).

I can live with that.

Thanks,
drew


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

end of thread, other threads:[~2023-11-01  9:48 UTC | newest]

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

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.