diff mbox series

[5/6] target/riscv/tcg-cpu.c: enable profile support for vendor CPUs

Message ID 20230926194951.183767-6-dbarboza@ventanamicro.com
State New
Headers show
Series riscv: RVA22U64 profile support | expand

Commit Message

Daniel Henrique Barboza Sept. 26, 2023, 7:49 p.m. UTC
Vendor CPUs can implement any profile they want as long as all required
extensions are being set in their respective cpu_init().

We do not enable extensions for vendor CPUs and that will still be true
with profile support. The idea then is to enable the profile option for
vendor CPUs and  let users try to enable it. In case the vendor CPU
do not implement all mandatory extensions of the profile, error out.
Proceed as usual otherwise.

Here's an example of what happens if we try to enable the rva22u64
profile with the veyron-v1 CPU:

./qemu-system-riscv64 -M virt -cpu veyron-v1,rva22u64=true

qemu-system-riscv64: can't apply global veyron-v1-riscv-cpu.rva22u64=true:
  Setting profile 'rva22u64' failed: CPU veyron-v1 does not support extension 'Zihintpause'

Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
---
 target/riscv/tcg/tcg-cpu.c | 43 ++++++++++++++++++++++++++++++++++----
 1 file changed, 39 insertions(+), 4 deletions(-)
diff mbox series

Patch

diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
index 03435521c9..c8f688292e 100644
--- a/target/riscv/tcg/tcg-cpu.c
+++ b/target/riscv/tcg/tcg-cpu.c
@@ -99,6 +99,31 @@  static const struct TCGCPUOps riscv_tcg_ops = {
 #endif /* !CONFIG_USER_ONLY */
 };
 
+static const char *cpu_get_multi_ext_cfg_name(uint32_t ext_offset)
+{
+    const RISCVCPUMultiExtConfig *prop;
+
+    for (prop = riscv_cpu_extensions; prop && prop->name; prop++) {
+        if (prop->offset == ext_offset) {
+            return prop->name;
+        }
+    }
+
+    for (prop = riscv_cpu_experimental_exts; prop && prop->name; prop++) {
+        if (prop->offset == ext_offset) {
+            return prop->name;
+        }
+    }
+
+    for (prop = riscv_cpu_vendor_exts; prop && prop->name; prop++) {
+        if (prop->offset == ext_offset) {
+            return prop->name;
+        }
+    }
+
+    return NULL;
+}
+
 static int cpu_cfg_ext_get_min_version(uint32_t ext_offset)
 {
     const RISCVIsaExtData *edata;
@@ -747,7 +772,7 @@  static void cpu_set_profile(Object *obj, Visitor *v, const char *name,
     RISCVCPU *cpu = RISCV_CPU(obj);
     CPURISCVState *env = &cpu->env;
     int i = 0;
-    bool value;
+    bool value, generic_cpu;
 
     if (!visit_type_bool(v, name, &value, errp)) {
         return;
@@ -758,16 +783,28 @@  static void cpu_set_profile(Object *obj, Visitor *v, const char *name,
         return;
     }
 
+    generic_cpu = object_dynamic_cast(obj, TYPE_RISCV_DYNAMIC_CPU) != NULL;
+
     env->misa_ext |= profile->misa_ext;
     env->misa_ext_mask |= profile->misa_ext;
 
     for (i = 0;; i++) {
         int ext_offset = profile->ext_offsets[i];
+        bool prev_val = isa_ext_is_enabled(cpu, ext_offset);
 
         if (ext_offset == RISCV_PROFILE_EXT_LIST_END) {
             break;
         }
 
+        if (!prev_val && !generic_cpu) {
+            const char *ext_name = cpu_get_multi_ext_cfg_name(ext_offset);
+            const char *cpu_name = riscv_cpu_get_name(cpu);
+
+            error_setg(errp, "Setting profile '%s' failed: CPU %s does not "
+                       "support extension '%s'", name, cpu_name, ext_name);
+            return;
+        }
+
         isa_ext_update_enabled(cpu, ext_offset, true);
         g_hash_table_insert(multi_ext_user_opts,
                             GUINT_TO_POINTER(ext_offset),
@@ -885,9 +922,7 @@  static void riscv_cpu_add_user_properties(Object *obj)
     riscv_cpu_add_multiext_prop_array(obj, riscv_cpu_vendor_exts);
     riscv_cpu_add_multiext_prop_array(obj, riscv_cpu_experimental_exts);
 
-    if (object_dynamic_cast(obj, TYPE_RISCV_DYNAMIC_CPU) != NULL) {
-        riscv_cpu_add_profile_prop(obj, &RVA22U64);
-    }
+    riscv_cpu_add_profile_prop(obj, &RVA22U64);
 
     for (Property *prop = riscv_cpu_options; prop && prop->name; prop++) {
         qdev_property_add_static(DEVICE(obj), prop);