All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/20] riscv: split TCG/KVM accelerators from cpu.c
@ 2023-08-25 13:08 Daniel Henrique Barboza
  2023-08-25 13:08 ` [PATCH 01/20] target/riscv: introduce TCG AccelCPUClass Daniel Henrique Barboza
                   ` (19 more replies)
  0 siblings, 20 replies; 51+ messages in thread
From: Daniel Henrique Barboza @ 2023-08-25 13:08 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-riscv, alistair.francis, bmeng, liweiwei, zhiwei_liu,
	palmer, Daniel Henrique Barboza

Based-on: 20230824221440.484675-1-dbarboza@ventanamicro.com
("[PATCH RESEND v8 00/20] riscv: 'max' CPU, detect user choice in TCG")

Hi,

The idea of this work was hinted at during a review [1] where Phil
mentioned that we should handle TCG specific constraints in
AccelCPUClass::cpu_realizefn(). While working on that I came across
the work done in x86 by Claudio Fontana in commit f5cc5a5c1 ("i386:
split cpu accelerators from cpu.c, using AccelCPUClass"). The design
implemented here is heavily inspired by Claudio's work.

An AccelCPUClass is an abstraction used by all QEMU accelerators that
are already streamlined in the init/realize process, doesn't matter if
we use it or not. Using accel classes allow us to split accel-specific
code from cpu.c into their own files, making easier to support
accel-specific builds in the future. It also gives us a template to
follow when adding new accelerators in the future.

The final goal, not entirely reached with this series, is to have cpu.c
hosting only common code for all accelerators, in particular the code
related to extensions support. We should declare extensions in cpu.c
then go to each accelerator class and do what you want with it. We're
not there yet due to how we rely on isa_edata_arr[] for both priv-spec
checks (a tcg only thing) and provide the riscv,isa string (all
accelerators). Trying to untangle priv-spec and isa_str is a fight for
another day.

You'll also notice that I didn't move all TCG related files to the 'tcg'
subdir. The reason is that Phil already did that here [2]:

"[PATCH 00/16] target/riscv: Allow building without TCG (KVM-only so far)"

and I deliberately avoided colliding with what he did. Phil's series focus
in splitting TCG includes and ifdefs in TCG specific files, while this
series focus in decoupling accel-speciic logic inside cpu.c.

The only behavior change implemented is in patch 20 where we block
vendor CPUs from using KVM. Most of the time I'm just juggling code
around to avoid breaking what we already have while trying to keep
patches review-sane.

No other behavior changes were intended with this series.

[1] https://lore.kernel.org/qemu-riscv/3b93823c-3d12-0d67-b814-54a3922d027f@linaro.org/
[2] https://lore.kernel.org/qemu-riscv/20230711121453.59138-1-philmd@linaro.org/


Daniel Henrique Barboza (20):
  target/riscv: introduce TCG AccelCPUClass
  target/riscv: move riscv_cpu_realize_tcg() to TCG::cpu_realizefn()
  target/riscv: move riscv_cpu_validate_set_extensions() to tcg-cpu.c
  target/riscv: move riscv_tcg_ops to tcg-cpu.c
  target/riscv/cpu.c: add 'user_extension_properties' class prop
  target/riscv: add 'max_features' CPU flag
  target/riscv/cpu.c: add .instance_post_init()
  target/riscv: move 'host' CPU declaration to kvm.c
  target/riscv/cpu.c: mark extensions arrays as 'const'
  target/riscv: move riscv_cpu_add_kvm_properties() to kvm.c
  target/riscv: introduce KVM AccelCPUClass
  target/riscv: move KVM only files to kvm subdir
  target/riscv/kvm: refactor kvm_riscv_init_user_properties()
  target/riscv/kvm: do not use riscv_cpu_add_misa_properties()
  target/riscv/tcg: introduce tcg_cpu_instance_init()
  target/riscv/tcg: move riscv_cpu_add_misa_properties() to tcg-cpu.c
  target/riscv/cpu.c: export isa_edata_arr[]
  target/riscv/cpu: move priv spec functions to tcg-cpu.c
  target/riscv: add 'tcg_supported' class property
  target/riscv: add 'kvm_supported' class property

 hw/riscv/virt.c                       |   2 +-
 target/riscv/cpu-qom.h                |   5 +
 target/riscv/cpu.c                    | 999 ++------------------------
 target/riscv/cpu.h                    |  31 +-
 target/riscv/cpu_cfg.h                |   1 +
 target/riscv/csr.c                    |   1 +
 target/riscv/{kvm.c => kvm/kvm-cpu.c} | 153 +++-
 target/riscv/{ => kvm}/kvm-stub.c     |   0
 target/riscv/{ => kvm}/kvm_riscv.h    |   1 -
 target/riscv/kvm/meson.build          |   2 +
 target/riscv/meson.build              |   4 +-
 target/riscv/tcg/meson.build          |   2 +
 target/riscv/tcg/tcg-cpu.c            | 864 ++++++++++++++++++++++
 target/riscv/tcg/tcg-cpu.h            |  28 +
 14 files changed, 1160 insertions(+), 933 deletions(-)
 rename target/riscv/{kvm.c => kvm/kvm-cpu.c} (89%)
 rename target/riscv/{ => kvm}/kvm-stub.c (100%)
 rename target/riscv/{ => kvm}/kvm_riscv.h (95%)
 create mode 100644 target/riscv/kvm/meson.build
 create mode 100644 target/riscv/tcg/meson.build
 create mode 100644 target/riscv/tcg/tcg-cpu.c
 create mode 100644 target/riscv/tcg/tcg-cpu.h

-- 
2.41.0



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

* [PATCH 01/20] target/riscv: introduce TCG AccelCPUClass
  2023-08-25 13:08 [PATCH 00/20] riscv: split TCG/KVM accelerators from cpu.c Daniel Henrique Barboza
@ 2023-08-25 13:08 ` Daniel Henrique Barboza
  2023-08-31 10:17   ` Andrew Jones
  2023-08-25 13:08 ` [PATCH 02/20] target/riscv: move riscv_cpu_realize_tcg() to TCG::cpu_realizefn() Daniel Henrique Barboza
                   ` (18 subsequent siblings)
  19 siblings, 1 reply; 51+ messages in thread
From: Daniel Henrique Barboza @ 2023-08-25 13:08 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-riscv, alistair.francis, bmeng, liweiwei, zhiwei_liu,
	palmer, Daniel Henrique Barboza

target/riscv/cpu.c needs to handle all possible accelerators (TCG and
KVM at this moment) during both init() and realize() time. This forces
us to resort to a lot of "if tcg" and "if kvm" throughout the code,
which isn't wrong, but can get cluttered over time. Splitting
acceleration specific code from cpu.c to its own file will help to
declutter the existing code and it will also make it easier to support
KVM/TCG only builds in the future.

We'll start by adding a new subdir called 'tcg' and a new file called
'tcg-cpu.c'. This file will be used to introduce a new accelerator class
for TCG acceleration in RISC-V, allowing us to center all TCG exclusive
code in its file instead of using 'cpu.c' for everything. This design is
inpired by the work Claudio Fontana did in x86 a few years ago in commit
f5cc5a5c1 ("i386: split cpu accelerators from cpu.c, using
AccelCPUClass").

To avoid moving too much code at once we'll start by adding the new file
and TCG AccelCPUClass declaration. The 'class_init' from the accel class
will init 'tcg_ops', relieving the common riscv_cpu_class_init() from
doing it.

'riscv_tcg_ops' is being exported from 'cpu.c' for now to avoid having
to deal with moving code and files around right now. We'll focus on
decoupling the realize() logic first.

Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
---
 target/riscv/cpu.c           |  5 +---
 target/riscv/cpu.h           |  4 +++
 target/riscv/meson.build     |  2 ++
 target/riscv/tcg/meson.build |  2 ++
 target/riscv/tcg/tcg-cpu.c   | 57 ++++++++++++++++++++++++++++++++++++
 5 files changed, 66 insertions(+), 4 deletions(-)
 create mode 100644 target/riscv/tcg/meson.build
 create mode 100644 target/riscv/tcg/tcg-cpu.c

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 21ebdbf084..38dcbc4dd2 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -2275,9 +2275,7 @@ static const struct SysemuCPUOps riscv_sysemu_ops = {
 };
 #endif
 
-#include "hw/core/tcg-cpu-ops.h"
-
-static const struct TCGCPUOps riscv_tcg_ops = {
+const struct TCGCPUOps riscv_tcg_ops = {
     .initialize = riscv_translate_init,
     .synchronize_from_tb = riscv_cpu_synchronize_from_tb,
     .restore_state_to_opc = riscv_restore_state_to_opc,
@@ -2436,7 +2434,6 @@ static void riscv_cpu_class_init(ObjectClass *c, void *data)
 #endif
     cc->gdb_arch_name = riscv_gdb_arch_name;
     cc->gdb_get_dynamic_xml = riscv_gdb_get_dynamic_xml;
-    cc->tcg_ops = &riscv_tcg_ops;
 
     object_class_property_add(c, "mvendorid", "uint32", cpu_get_mvendorid,
                               cpu_set_mvendorid, NULL, NULL);
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 577abcd724..b84b62f84e 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -707,6 +707,10 @@ enum riscv_pmu_event_idx {
     RISCV_PMU_EVENT_CACHE_ITLB_PREFETCH_MISS = 0x10021,
 };
 
+/* Export tcg_ops until we move everything to tcg/tcg-cpu.c */
+#include "hw/core/tcg-cpu-ops.h"
+extern const struct TCGCPUOps riscv_tcg_ops;
+
 /* CSR function table */
 extern riscv_csr_operations csr_ops[CSR_TABLE_SIZE];
 
diff --git a/target/riscv/meson.build b/target/riscv/meson.build
index 660078bda1..f0486183fa 100644
--- a/target/riscv/meson.build
+++ b/target/riscv/meson.build
@@ -38,5 +38,7 @@ riscv_system_ss.add(files(
   'riscv-qmp-cmds.c',
 ))
 
+subdir('tcg')
+
 target_arch += {'riscv': riscv_ss}
 target_softmmu_arch += {'riscv': riscv_system_ss}
diff --git a/target/riscv/tcg/meson.build b/target/riscv/tcg/meson.build
new file mode 100644
index 0000000000..061df3d74a
--- /dev/null
+++ b/target/riscv/tcg/meson.build
@@ -0,0 +1,2 @@
+riscv_ss.add(when: 'CONFIG_TCG', if_true: files(
+  'tcg-cpu.c'))
diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
new file mode 100644
index 0000000000..1ad27a26aa
--- /dev/null
+++ b/target/riscv/tcg/tcg-cpu.c
@@ -0,0 +1,57 @@
+/*
+ * riscv TCG cpu class initialization
+ *
+ * Copyright (c) 2023 Ventana Micro Systems Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "cpu.h"
+#include "qemu/accel.h"
+#include "hw/core/accel-cpu.h"
+
+static void tcg_cpu_init_ops(AccelCPUClass *accel_cpu, CPUClass *cc)
+{
+    /*
+     * All cpus use the same set of operations.
+     * riscv_tcg_ops is being imported from cpu.c for now.
+     */
+    cc->tcg_ops = &riscv_tcg_ops;
+}
+
+static void tcg_cpu_class_init(CPUClass *cc)
+{
+    cc->init_accel_cpu = tcg_cpu_init_ops;
+}
+
+static void tcg_cpu_accel_class_init(ObjectClass *oc, void *data)
+{
+    AccelCPUClass *acc = ACCEL_CPU_CLASS(oc);
+
+    acc->cpu_class_init = tcg_cpu_class_init;
+}
+
+static const TypeInfo tcg_cpu_accel_type_info = {
+    .name = ACCEL_CPU_NAME("tcg"),
+
+    .parent = TYPE_ACCEL_CPU,
+    .class_init = tcg_cpu_accel_class_init,
+    .abstract = true,
+};
+static void tcg_cpu_accel_register_types(void)
+{
+    type_register_static(&tcg_cpu_accel_type_info);
+}
+type_init(tcg_cpu_accel_register_types);
-- 
2.41.0



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

* [PATCH 02/20] target/riscv: move riscv_cpu_realize_tcg() to TCG::cpu_realizefn()
  2023-08-25 13:08 [PATCH 00/20] riscv: split TCG/KVM accelerators from cpu.c Daniel Henrique Barboza
  2023-08-25 13:08 ` [PATCH 01/20] target/riscv: introduce TCG AccelCPUClass Daniel Henrique Barboza
@ 2023-08-25 13:08 ` Daniel Henrique Barboza
  2023-08-31 10:21   ` Andrew Jones
  2023-08-25 13:08 ` [PATCH 03/20] target/riscv: move riscv_cpu_validate_set_extensions() to tcg-cpu.c Daniel Henrique Barboza
                   ` (17 subsequent siblings)
  19 siblings, 1 reply; 51+ messages in thread
From: Daniel Henrique Barboza @ 2023-08-25 13:08 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-riscv, alistair.francis, bmeng, liweiwei, zhiwei_liu,
	palmer, Daniel Henrique Barboza

riscv_cpu_realize_tcg() was added to allow TCG cpus to have a different
realize() path during the common riscv_cpu_realize(), making it a good
choice to start moving TCG exclusive code to tcg-cpu.c.

Rename it to tcg_cpu_realizefn() and assign it as a implementation of
accel::cpu_realizefn(). tcg_cpu_realizefn() will then be called during
riscv_cpu_realize() via cpu_exec_realizefn(). We'll use a similar
approach with KVM in the near future.

riscv_cpu_validate_set_extensions() is too big and with too many
dependencies to be moved in this same patch. We'll do that next.

Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
---
 target/riscv/cpu.c         | 128 -----------------------------------
 target/riscv/tcg/tcg-cpu.c | 132 +++++++++++++++++++++++++++++++++++++
 2 files changed, 132 insertions(+), 128 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 38dcbc4dd2..36c5c6e579 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -23,9 +23,7 @@
 #include "qemu/log.h"
 #include "cpu.h"
 #include "cpu_vendorid.h"
-#include "pmu.h"
 #include "internals.h"
-#include "time_helper.h"
 #include "exec/exec-all.h"
 #include "qapi/error.h"
 #include "qapi/visitor.h"
@@ -1065,29 +1063,6 @@ static void riscv_cpu_validate_v(CPURISCVState *env, RISCVCPUConfig *cfg,
     }
 }
 
-static void riscv_cpu_validate_priv_spec(RISCVCPU *cpu, Error **errp)
-{
-    CPURISCVState *env = &cpu->env;
-    int priv_version = -1;
-
-    if (cpu->cfg.priv_spec) {
-        if (!g_strcmp0(cpu->cfg.priv_spec, "v1.12.0")) {
-            priv_version = PRIV_VERSION_1_12_0;
-        } else if (!g_strcmp0(cpu->cfg.priv_spec, "v1.11.0")) {
-            priv_version = PRIV_VERSION_1_11_0;
-        } else if (!g_strcmp0(cpu->cfg.priv_spec, "v1.10.0")) {
-            priv_version = PRIV_VERSION_1_10_0;
-        } else {
-            error_setg(errp,
-                       "Unsupported privilege spec version '%s'",
-                       cpu->cfg.priv_spec);
-            return;
-        }
-
-        env->priv_ver = priv_version;
-    }
-}
-
 static void riscv_cpu_disable_priv_spec_isa_exts(RISCVCPU *cpu)
 {
     CPURISCVState *env = &cpu->env;
@@ -1112,33 +1087,6 @@ static void riscv_cpu_disable_priv_spec_isa_exts(RISCVCPU *cpu)
     }
 }
 
-static void riscv_cpu_validate_misa_mxl(RISCVCPU *cpu, Error **errp)
-{
-    RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(cpu);
-    CPUClass *cc = CPU_CLASS(mcc);
-    CPURISCVState *env = &cpu->env;
-
-    /* Validate that MISA_MXL is set properly. */
-    switch (env->misa_mxl_max) {
-#ifdef TARGET_RISCV64
-    case MXL_RV64:
-    case MXL_RV128:
-        cc->gdb_core_xml_file = "riscv-64bit-cpu.xml";
-        break;
-#endif
-    case MXL_RV32:
-        cc->gdb_core_xml_file = "riscv-32bit-cpu.xml";
-        break;
-    default:
-        g_assert_not_reached();
-    }
-
-    if (env->misa_mxl_max != env->misa_mxl) {
-        error_setg(errp, "misa_mxl_max must be equal to misa_mxl");
-        return;
-    }
-}
-
 /*
  * Check consistency between chosen extensions while setting
  * cpu->cfg accordingly.
@@ -1512,74 +1460,6 @@ static void riscv_cpu_finalize_features(RISCVCPU *cpu, Error **errp)
 #endif
 }
 
-static void riscv_cpu_validate_misa_priv(CPURISCVState *env, Error **errp)
-{
-    if (riscv_has_ext(env, RVH) && env->priv_ver < PRIV_VERSION_1_12_0) {
-        error_setg(errp, "H extension requires priv spec 1.12.0");
-        return;
-    }
-}
-
-static void riscv_cpu_realize_tcg(DeviceState *dev, Error **errp)
-{
-    RISCVCPU *cpu = RISCV_CPU(dev);
-    CPURISCVState *env = &cpu->env;
-    Error *local_err = NULL;
-
-    if (object_dynamic_cast(OBJECT(dev), TYPE_RISCV_CPU_HOST)) {
-        error_setg(errp, "'host' CPU is not compatible with TCG acceleration");
-        return;
-    }
-
-    riscv_cpu_validate_misa_mxl(cpu, &local_err);
-    if (local_err != NULL) {
-        error_propagate(errp, local_err);
-        return;
-    }
-
-    riscv_cpu_validate_priv_spec(cpu, &local_err);
-    if (local_err != NULL) {
-        error_propagate(errp, local_err);
-        return;
-    }
-
-    riscv_cpu_validate_misa_priv(env, &local_err);
-    if (local_err != NULL) {
-        error_propagate(errp, local_err);
-        return;
-    }
-
-    if (cpu->cfg.epmp && !cpu->cfg.pmp) {
-        /*
-         * Enhanced PMP should only be available
-         * on harts with PMP support
-         */
-        error_setg(errp, "Invalid configuration: EPMP requires PMP support");
-        return;
-    }
-
-    riscv_cpu_validate_set_extensions(cpu, &local_err);
-    if (local_err != NULL) {
-        error_propagate(errp, local_err);
-        return;
-    }
-
-#ifndef CONFIG_USER_ONLY
-    CPU(dev)->tcg_cflags |= CF_PCREL;
-
-    if (cpu->cfg.ext_sstc) {
-        riscv_timer_init(cpu);
-    }
-
-    if (cpu->cfg.pmu_num) {
-        if (!riscv_pmu_init(cpu, cpu->cfg.pmu_num) && cpu->cfg.ext_sscofpmf) {
-            cpu->pmu_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
-                                          riscv_pmu_timer_cb, cpu);
-        }
-     }
-#endif
-}
-
 static void riscv_cpu_realize(DeviceState *dev, Error **errp)
 {
     CPUState *cs = CPU(dev);
@@ -1598,14 +1478,6 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
         return;
     }
 
-    if (tcg_enabled()) {
-        riscv_cpu_realize_tcg(dev, &local_err);
-        if (local_err != NULL) {
-            error_propagate(errp, local_err);
-            return;
-        }
-    }
-
     riscv_cpu_finalize_features(cpu, &local_err);
     if (local_err != NULL) {
         error_propagate(errp, local_err);
diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
index 1ad27a26aa..b3d3f265d7 100644
--- a/target/riscv/tcg/tcg-cpu.c
+++ b/target/riscv/tcg/tcg-cpu.c
@@ -19,9 +19,140 @@
 
 #include "qemu/osdep.h"
 #include "cpu.h"
+#include "pmu.h"
+#include "time_helper.h"
+#include "qapi/error.h"
 #include "qemu/accel.h"
 #include "hw/core/accel-cpu.h"
 
+
+static void riscv_cpu_validate_misa_priv(CPURISCVState *env, Error **errp)
+{
+    if (riscv_has_ext(env, RVH) && env->priv_ver < PRIV_VERSION_1_12_0) {
+        error_setg(errp, "H extension requires priv spec 1.12.0");
+        return;
+    }
+}
+
+static void riscv_cpu_validate_misa_mxl(RISCVCPU *cpu, Error **errp)
+{
+    RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(cpu);
+    CPUClass *cc = CPU_CLASS(mcc);
+    CPURISCVState *env = &cpu->env;
+
+    /* Validate that MISA_MXL is set properly. */
+    switch (env->misa_mxl_max) {
+#ifdef TARGET_RISCV64
+    case MXL_RV64:
+    case MXL_RV128:
+        cc->gdb_core_xml_file = "riscv-64bit-cpu.xml";
+        break;
+#endif
+    case MXL_RV32:
+        cc->gdb_core_xml_file = "riscv-32bit-cpu.xml";
+        break;
+    default:
+        g_assert_not_reached();
+    }
+
+    if (env->misa_mxl_max != env->misa_mxl) {
+        error_setg(errp, "misa_mxl_max must be equal to misa_mxl");
+        return;
+    }
+}
+
+static void riscv_cpu_validate_priv_spec(RISCVCPU *cpu, Error **errp)
+{
+    CPURISCVState *env = &cpu->env;
+    int priv_version = -1;
+
+    if (cpu->cfg.priv_spec) {
+        if (!g_strcmp0(cpu->cfg.priv_spec, "v1.12.0")) {
+            priv_version = PRIV_VERSION_1_12_0;
+        } else if (!g_strcmp0(cpu->cfg.priv_spec, "v1.11.0")) {
+            priv_version = PRIV_VERSION_1_11_0;
+        } else if (!g_strcmp0(cpu->cfg.priv_spec, "v1.10.0")) {
+            priv_version = PRIV_VERSION_1_10_0;
+        } else {
+            error_setg(errp,
+                       "Unsupported privilege spec version '%s'",
+                       cpu->cfg.priv_spec);
+            return;
+        }
+
+        env->priv_ver = priv_version;
+    }
+}
+
+/*
+ * We'll get here via the following path:
+ *
+ * riscv_cpu_realize()
+ *   -> cpu_exec_realizefn()
+ *      -> tcg_cpu_realizefn() (via accel_cpu_realizefn())
+ */
+static bool tcg_cpu_realizefn(CPUState *cs, Error **errp)
+{
+    RISCVCPU *cpu = RISCV_CPU(cs);
+    CPURISCVState *env = &cpu->env;
+    Error *local_err = NULL;
+
+    if (object_dynamic_cast(OBJECT(cpu), TYPE_RISCV_CPU_HOST)) {
+        error_setg(errp, "'host' CPU is not compatible with TCG acceleration");
+        return false;
+    }
+
+    riscv_cpu_validate_misa_mxl(cpu, &local_err);
+    if (local_err != NULL) {
+        error_propagate(errp, local_err);
+        return false;
+    }
+
+    riscv_cpu_validate_priv_spec(cpu, &local_err);
+    if (local_err != NULL) {
+        error_propagate(errp, local_err);
+        return false;
+    }
+
+    riscv_cpu_validate_misa_priv(env, &local_err);
+    if (local_err != NULL) {
+        error_propagate(errp, local_err);
+        return false;
+    }
+
+    if (cpu->cfg.epmp && !cpu->cfg.pmp) {
+        /*
+         * Enhanced PMP should only be available
+         * on harts with PMP support
+         */
+        error_setg(errp, "Invalid configuration: EPMP requires PMP support");
+        return false;
+    }
+
+    riscv_cpu_validate_set_extensions(cpu, &local_err);
+    if (local_err != NULL) {
+        error_propagate(errp, local_err);
+        return false;
+    }
+
+#ifndef CONFIG_USER_ONLY
+    CPU(cs)->tcg_cflags |= CF_PCREL;
+
+    if (cpu->cfg.ext_sstc) {
+        riscv_timer_init(cpu);
+    }
+
+    if (cpu->cfg.pmu_num) {
+        if (!riscv_pmu_init(cpu, cpu->cfg.pmu_num) && cpu->cfg.ext_sscofpmf) {
+            cpu->pmu_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
+                                          riscv_pmu_timer_cb, cpu);
+        }
+     }
+#endif
+
+    return true;
+}
+
 static void tcg_cpu_init_ops(AccelCPUClass *accel_cpu, CPUClass *cc)
 {
     /*
@@ -41,6 +172,7 @@ static void tcg_cpu_accel_class_init(ObjectClass *oc, void *data)
     AccelCPUClass *acc = ACCEL_CPU_CLASS(oc);
 
     acc->cpu_class_init = tcg_cpu_class_init;
+    acc->cpu_realizefn = tcg_cpu_realizefn;
 }
 
 static const TypeInfo tcg_cpu_accel_type_info = {
-- 
2.41.0



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

* [PATCH 03/20] target/riscv: move riscv_cpu_validate_set_extensions() to tcg-cpu.c
  2023-08-25 13:08 [PATCH 00/20] riscv: split TCG/KVM accelerators from cpu.c Daniel Henrique Barboza
  2023-08-25 13:08 ` [PATCH 01/20] target/riscv: introduce TCG AccelCPUClass Daniel Henrique Barboza
  2023-08-25 13:08 ` [PATCH 02/20] target/riscv: move riscv_cpu_realize_tcg() to TCG::cpu_realizefn() Daniel Henrique Barboza
@ 2023-08-25 13:08 ` Daniel Henrique Barboza
  2023-08-31 10:31   ` Andrew Jones
  2023-08-25 13:08 ` [PATCH 04/20] target/riscv: move riscv_tcg_ops " Daniel Henrique Barboza
                   ` (16 subsequent siblings)
  19 siblings, 1 reply; 51+ messages in thread
From: Daniel Henrique Barboza @ 2023-08-25 13:08 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-riscv, alistair.francis, bmeng, liweiwei, zhiwei_liu,
	palmer, Daniel Henrique Barboza

This function is the core of the RISC-V validations for TCG CPUs, and it
has a lot going on.

Functions in cpu.c were made public to allow them to be used by the KVM
accelerator class later on. 'cpu_cfg_ext_get_min_version()' is notably
hard to move it to another file due to its dependency with isa_edata_arr[]
array, thus make it public and use it as is for now.

riscv_cpu_validate_set_extensions() is kept public because it's used by
csr.c in write_misa().

Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
---
 target/riscv/cpu.c         | 361 +------------------------------------
 target/riscv/cpu.h         |   8 +-
 target/riscv/csr.c         |   1 +
 target/riscv/tcg/tcg-cpu.c | 352 ++++++++++++++++++++++++++++++++++++
 target/riscv/tcg/tcg-cpu.h |  28 +++
 5 files changed, 393 insertions(+), 357 deletions(-)
 create mode 100644 target/riscv/tcg/tcg-cpu.h

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 36c5c6e579..12cea62ee7 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -163,22 +163,21 @@ static const struct isa_ext_data isa_edata_arr[] = {
 /* Hash that stores user set extensions */
 static GHashTable *multi_ext_user_opts;
 
-static bool isa_ext_is_enabled(RISCVCPU *cpu, uint32_t ext_offset)
+bool isa_ext_is_enabled(RISCVCPU *cpu, uint32_t ext_offset)
 {
     bool *ext_enabled = (void *)&cpu->cfg + ext_offset;
 
     return *ext_enabled;
 }
 
-static void isa_ext_update_enabled(RISCVCPU *cpu, uint32_t ext_offset,
-                                   bool en)
+void isa_ext_update_enabled(RISCVCPU *cpu, uint32_t ext_offset, bool en)
 {
     bool *ext_enabled = (void *)&cpu->cfg + ext_offset;
 
     *ext_enabled = en;
 }
 
-static int cpu_cfg_ext_get_min_version(uint32_t ext_offset)
+int cpu_cfg_ext_get_min_version(uint32_t ext_offset)
 {
     int i;
 
@@ -194,38 +193,12 @@ static int cpu_cfg_ext_get_min_version(uint32_t ext_offset)
     return PRIV_VERSION_1_10_0;
 }
 
-static bool cpu_cfg_ext_is_user_set(uint32_t ext_offset)
+bool cpu_cfg_ext_is_user_set(uint32_t ext_offset)
 {
     return g_hash_table_contains(multi_ext_user_opts,
                                  GUINT_TO_POINTER(ext_offset));
 }
 
-static void cpu_cfg_ext_auto_update(RISCVCPU *cpu, uint32_t ext_offset,
-                                    bool value)
-{
-    CPURISCVState *env = &cpu->env;
-    bool prev_val = isa_ext_is_enabled(cpu, ext_offset);
-    int min_version;
-
-    if (prev_val == value) {
-        return;
-    }
-
-    if (cpu_cfg_ext_is_user_set(ext_offset)) {
-        return;
-    }
-
-    if (value && env->priv_ver != PRIV_VERSION_LATEST) {
-        /* Do not enable it if priv_ver is older than min_version */
-        min_version = cpu_cfg_ext_get_min_version(ext_offset);
-        if (env->priv_ver < min_version) {
-            return;
-        }
-    }
-
-    isa_ext_update_enabled(cpu, ext_offset, value);
-}
-
 const char * const riscv_int_regnames[] = {
     "x0/zero", "x1/ra",  "x2/sp",  "x3/gp",  "x4/tp",  "x5/t0",   "x6/t1",
     "x7/t2",   "x8/s0",  "x9/s1",  "x10/a0", "x11/a1", "x12/a2",  "x13/a3",
@@ -1024,46 +997,7 @@ static void riscv_cpu_disas_set_info(CPUState *s, disassemble_info *info)
     }
 }
 
-static void riscv_cpu_validate_v(CPURISCVState *env, RISCVCPUConfig *cfg,
-                                 Error **errp)
-{
-    if (!is_power_of_2(cfg->vlen)) {
-        error_setg(errp, "Vector extension VLEN must be power of 2");
-        return;
-    }
-    if (cfg->vlen > RV_VLEN_MAX || cfg->vlen < 128) {
-        error_setg(errp,
-                   "Vector extension implementation only supports VLEN "
-                   "in the range [128, %d]", RV_VLEN_MAX);
-        return;
-    }
-    if (!is_power_of_2(cfg->elen)) {
-        error_setg(errp, "Vector extension ELEN must be power of 2");
-        return;
-    }
-    if (cfg->elen > 64 || cfg->elen < 8) {
-        error_setg(errp,
-                   "Vector extension implementation only supports ELEN "
-                   "in the range [8, 64]");
-        return;
-    }
-    if (cfg->vext_spec) {
-        if (!g_strcmp0(cfg->vext_spec, "v1.0")) {
-            env->vext_ver = VEXT_VERSION_1_00_0;
-        } else {
-            error_setg(errp, "Unsupported vector spec version '%s'",
-                       cfg->vext_spec);
-            return;
-        }
-    } else if (env->vext_ver == 0) {
-        qemu_log("vector version is not specified, "
-                 "use the default value v1.0\n");
-
-        env->vext_ver = VEXT_VERSION_1_00_0;
-    }
-}
-
-static void riscv_cpu_disable_priv_spec_isa_exts(RISCVCPU *cpu)
+void riscv_cpu_disable_priv_spec_isa_exts(RISCVCPU *cpu)
 {
     CPURISCVState *env = &cpu->env;
     int i;
@@ -1087,291 +1021,6 @@ static void riscv_cpu_disable_priv_spec_isa_exts(RISCVCPU *cpu)
     }
 }
 
-/*
- * Check consistency between chosen extensions while setting
- * cpu->cfg accordingly.
- */
-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_icsr && cpu->cfg.ext_ifencei)) {
-        warn_report("Setting G will also set IMAFD_Zicsr_Zifencei");
-
-        if (cpu_cfg_ext_is_user_set(CPU_CFG_OFFSET(ext_icsr)) &&
-            !cpu->cfg.ext_icsr) {
-            error_setg(errp, "RVG requires Zicsr but user set Zicsr to false");
-            return;
-        }
-
-        if (cpu_cfg_ext_is_user_set(CPU_CFG_OFFSET(ext_ifencei)) &&
-            !cpu->cfg.ext_ifencei) {
-            error_setg(errp, "RVG requires Zifencei but user set "
-                       "Zifencei to false");
-            return;
-        }
-
-        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_icsr), true);
-        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_ifencei), true);
-
-        env->misa_ext |= RVI | RVM | RVA | RVF | RVD;
-        env->misa_ext_mask |= RVI | RVM | RVA | RVF | RVD;
-    }
-
-    if (riscv_has_ext(env, RVI) && riscv_has_ext(env, RVE)) {
-        error_setg(errp,
-                   "I and E extensions are incompatible");
-        return;
-    }
-
-    if (!riscv_has_ext(env, RVI) && !riscv_has_ext(env, RVE)) {
-        error_setg(errp,
-                   "Either I or E extension must be set");
-        return;
-    }
-
-    if (riscv_has_ext(env, RVS) && !riscv_has_ext(env, RVU)) {
-        error_setg(errp,
-                   "Setting S extension without U extension is illegal");
-        return;
-    }
-
-    if (riscv_has_ext(env, RVH) && !riscv_has_ext(env, RVI)) {
-        error_setg(errp,
-                   "H depends on an I base integer ISA with 32 x registers");
-        return;
-    }
-
-    if (riscv_has_ext(env, RVH) && !riscv_has_ext(env, RVS)) {
-        error_setg(errp, "H extension implicitly requires S-mode");
-        return;
-    }
-
-    if (riscv_has_ext(env, RVF) && !cpu->cfg.ext_icsr) {
-        error_setg(errp, "F extension requires Zicsr");
-        return;
-    }
-
-    if ((cpu->cfg.ext_zawrs) && !riscv_has_ext(env, RVA)) {
-        error_setg(errp, "Zawrs extension requires A extension");
-        return;
-    }
-
-    if (cpu->cfg.ext_zfa && !riscv_has_ext(env, RVF)) {
-        error_setg(errp, "Zfa extension requires F extension");
-        return;
-    }
-
-    if (cpu->cfg.ext_zfh) {
-        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zfhmin), true);
-    }
-
-    if (cpu->cfg.ext_zfhmin && !riscv_has_ext(env, RVF)) {
-        error_setg(errp, "Zfh/Zfhmin extensions require F extension");
-        return;
-    }
-
-    if (cpu->cfg.ext_zfbfmin && !riscv_has_ext(env, RVF)) {
-        error_setg(errp, "Zfbfmin extension depends on F extension");
-        return;
-    }
-
-    if (riscv_has_ext(env, RVD) && !riscv_has_ext(env, RVF)) {
-        error_setg(errp, "D extension requires F extension");
-        return;
-    }
-
-    if (riscv_has_ext(env, RVV)) {
-        riscv_cpu_validate_v(env, &cpu->cfg, &local_err);
-        if (local_err != NULL) {
-            error_propagate(errp, local_err);
-            return;
-        }
-
-        /* The V vector extension depends on the Zve64d extension */
-        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zve64d), true);
-    }
-
-    /* The Zve64d extension depends on the Zve64f extension */
-    if (cpu->cfg.ext_zve64d) {
-        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zve64f), true);
-    }
-
-    /* The Zve64f extension depends on the Zve32f extension */
-    if (cpu->cfg.ext_zve64f) {
-        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zve32f), true);
-    }
-
-    if (cpu->cfg.ext_zve64d && !riscv_has_ext(env, RVD)) {
-        error_setg(errp, "Zve64d/V extensions require D extension");
-        return;
-    }
-
-    if (cpu->cfg.ext_zve32f && !riscv_has_ext(env, RVF)) {
-        error_setg(errp, "Zve32f/Zve64f extensions require F extension");
-        return;
-    }
-
-    if (cpu->cfg.ext_zvfh) {
-        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zvfhmin), true);
-    }
-
-    if (cpu->cfg.ext_zvfhmin && !cpu->cfg.ext_zve32f) {
-        error_setg(errp, "Zvfh/Zvfhmin extensions require Zve32f extension");
-        return;
-    }
-
-    if (cpu->cfg.ext_zvfh && !cpu->cfg.ext_zfhmin) {
-        error_setg(errp, "Zvfh extensions requires Zfhmin extension");
-        return;
-    }
-
-    if (cpu->cfg.ext_zvfbfmin && !cpu->cfg.ext_zfbfmin) {
-        error_setg(errp, "Zvfbfmin extension depends on Zfbfmin extension");
-        return;
-    }
-
-    if (cpu->cfg.ext_zvfbfmin && !cpu->cfg.ext_zve32f) {
-        error_setg(errp, "Zvfbfmin extension depends on Zve32f extension");
-        return;
-    }
-
-    if (cpu->cfg.ext_zvfbfwma && !cpu->cfg.ext_zvfbfmin) {
-        error_setg(errp, "Zvfbfwma extension depends on Zvfbfmin extension");
-        return;
-    }
-
-    /* Set the ISA extensions, checks should have happened above */
-    if (cpu->cfg.ext_zhinx) {
-        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zca), true);
-    }
-
-    if ((cpu->cfg.ext_zdinx || cpu->cfg.ext_zhinxmin) && !cpu->cfg.ext_zfinx) {
-        error_setg(errp, "Zdinx/Zhinx/Zhinxmin extensions require Zfinx");
-        return;
-    }
-
-    if (cpu->cfg.ext_zfinx) {
-        if (!cpu->cfg.ext_icsr) {
-            error_setg(errp, "Zfinx extension requires Zicsr");
-            return;
-        }
-        if (riscv_has_ext(env, RVF)) {
-            error_setg(errp,
-                       "Zfinx cannot be supported together with F extension");
-            return;
-        }
-    }
-
-    if (cpu->cfg.ext_zce) {
-        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zca), true);
-        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zcb), true);
-        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zcmp), true);
-        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zcmt), true);
-        if (riscv_has_ext(env, RVF) && env->misa_mxl_max == MXL_RV32) {
-            cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zcf), true);
-        }
-    }
-
-    /* zca, zcd and zcf has a PRIV 1.12.0 restriction */
-    if (riscv_has_ext(env, RVC) && env->priv_ver >= PRIV_VERSION_1_12_0) {
-        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zca), true);
-        if (riscv_has_ext(env, RVF) && env->misa_mxl_max == MXL_RV32) {
-            cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zcf), true);
-        }
-        if (riscv_has_ext(env, RVD)) {
-            cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zcd), true);
-        }
-    }
-
-    if (env->misa_mxl_max != MXL_RV32 && cpu->cfg.ext_zcf) {
-        error_setg(errp, "Zcf extension is only relevant to RV32");
-        return;
-    }
-
-    if (!riscv_has_ext(env, RVF) && cpu->cfg.ext_zcf) {
-        error_setg(errp, "Zcf extension requires F extension");
-        return;
-    }
-
-    if (!riscv_has_ext(env, RVD) && cpu->cfg.ext_zcd) {
-        error_setg(errp, "Zcd extension requires D extension");
-        return;
-    }
-
-    if ((cpu->cfg.ext_zcf || cpu->cfg.ext_zcd || cpu->cfg.ext_zcb ||
-         cpu->cfg.ext_zcmp || cpu->cfg.ext_zcmt) && !cpu->cfg.ext_zca) {
-        error_setg(errp, "Zcf/Zcd/Zcb/Zcmp/Zcmt extensions require Zca "
-                         "extension");
-        return;
-    }
-
-    if (cpu->cfg.ext_zcd && (cpu->cfg.ext_zcmp || cpu->cfg.ext_zcmt)) {
-        error_setg(errp, "Zcmp/Zcmt extensions are incompatible with "
-                         "Zcd extension");
-        return;
-    }
-
-    if (cpu->cfg.ext_zcmt && !cpu->cfg.ext_icsr) {
-        error_setg(errp, "Zcmt extension requires Zicsr extension");
-        return;
-    }
-
-    /*
-     * In principle Zve*x would also suffice here, were they supported
-     * in qemu
-     */
-    if ((cpu->cfg.ext_zvbb || cpu->cfg.ext_zvkg || cpu->cfg.ext_zvkned ||
-         cpu->cfg.ext_zvknha || cpu->cfg.ext_zvksed || cpu->cfg.ext_zvksh) &&
-        !cpu->cfg.ext_zve32f) {
-        error_setg(errp,
-                   "Vector crypto extensions require V or Zve* extensions");
-        return;
-    }
-
-    if ((cpu->cfg.ext_zvbc || cpu->cfg.ext_zvknhb) && !cpu->cfg.ext_zve64f) {
-        error_setg(
-            errp,
-            "Zvbc and Zvknhb extensions require V or Zve64{f,d} extensions");
-        return;
-    }
-
-    if (cpu->cfg.ext_zk) {
-        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zkn), true);
-        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zkr), true);
-        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zkt), true);
-    }
-
-    if (cpu->cfg.ext_zkn) {
-        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zbkb), true);
-        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zbkc), true);
-        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zbkx), true);
-        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zkne), true);
-        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zknd), true);
-        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zknh), true);
-    }
-
-    if (cpu->cfg.ext_zks) {
-        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zbkb), true);
-        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zbkc), true);
-        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zbkx), true);
-        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zksed), true);
-        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zksh), true);
-    }
-
-    /*
-     * Disable isa extensions based on priv spec after we
-     * validated and set everything we need.
-     */
-    riscv_cpu_disable_priv_spec_isa_exts(cpu);
-}
-
 #ifndef CONFIG_USER_ONLY
 static void riscv_cpu_satp_mode_finalize(RISCVCPU *cpu, Error **errp)
 {
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index b84b62f84e..721bd0b119 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -445,7 +445,6 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
                         bool probe, uintptr_t retaddr);
 char *riscv_isa_string(RISCVCPU *cpu);
 void riscv_cpu_list(void);
-void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp);
 
 #define cpu_list riscv_cpu_list
 #define cpu_mmu_index riscv_cpu_mmu_index
@@ -711,6 +710,13 @@ enum riscv_pmu_event_idx {
 #include "hw/core/tcg-cpu-ops.h"
 extern const struct TCGCPUOps riscv_tcg_ops;
 
+/* used by tcg/tcg-cpu.c*/
+void isa_ext_update_enabled(RISCVCPU *cpu, uint32_t ext_offset, bool en);
+bool cpu_cfg_ext_is_user_set(uint32_t ext_offset);
+bool isa_ext_is_enabled(RISCVCPU *cpu, uint32_t ext_offset);
+int cpu_cfg_ext_get_min_version(uint32_t ext_offset);
+void riscv_cpu_disable_priv_spec_isa_exts(RISCVCPU *cpu);
+
 /* CSR function table */
 extern riscv_csr_operations csr_ops[CSR_TABLE_SIZE];
 
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 6145039832..65473b257f 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -21,6 +21,7 @@
 #include "qemu/log.h"
 #include "qemu/timer.h"
 #include "cpu.h"
+#include "tcg/tcg-cpu.h"
 #include "pmu.h"
 #include "time_helper.h"
 #include "qemu/main-loop.h"
diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
index b3d3f265d7..fb17097bb1 100644
--- a/target/riscv/tcg/tcg-cpu.c
+++ b/target/riscv/tcg/tcg-cpu.c
@@ -18,14 +18,42 @@
  */
 
 #include "qemu/osdep.h"
+#include "tcg-cpu.h"
 #include "cpu.h"
 #include "pmu.h"
 #include "time_helper.h"
 #include "qapi/error.h"
 #include "qemu/accel.h"
+#include "qemu/error-report.h"
 #include "hw/core/accel-cpu.h"
 
 
+static void cpu_cfg_ext_auto_update(RISCVCPU *cpu, uint32_t ext_offset,
+                                    bool value)
+{
+    CPURISCVState *env = &cpu->env;
+    bool prev_val = isa_ext_is_enabled(cpu, ext_offset);
+    int min_version;
+
+    if (prev_val == value) {
+        return;
+    }
+
+    if (cpu_cfg_ext_is_user_set(ext_offset)) {
+        return;
+    }
+
+    if (value && env->priv_ver != PRIV_VERSION_LATEST) {
+        /* Do not enable it if priv_ver is older than min_version */
+        min_version = cpu_cfg_ext_get_min_version(ext_offset);
+        if (env->priv_ver < min_version) {
+            return;
+        }
+    }
+
+    isa_ext_update_enabled(cpu, ext_offset, value);
+}
+
 static void riscv_cpu_validate_misa_priv(CPURISCVState *env, Error **errp)
 {
     if (riscv_has_ext(env, RVH) && env->priv_ver < PRIV_VERSION_1_12_0) {
@@ -84,6 +112,330 @@ static void riscv_cpu_validate_priv_spec(RISCVCPU *cpu, Error **errp)
     }
 }
 
+static void riscv_cpu_validate_v(CPURISCVState *env, RISCVCPUConfig *cfg,
+                                 Error **errp)
+{
+    if (!is_power_of_2(cfg->vlen)) {
+        error_setg(errp, "Vector extension VLEN must be power of 2");
+        return;
+    }
+    if (cfg->vlen > RV_VLEN_MAX || cfg->vlen < 128) {
+        error_setg(errp,
+                   "Vector extension implementation only supports VLEN "
+                   "in the range [128, %d]", RV_VLEN_MAX);
+        return;
+    }
+    if (!is_power_of_2(cfg->elen)) {
+        error_setg(errp, "Vector extension ELEN must be power of 2");
+        return;
+    }
+    if (cfg->elen > 64 || cfg->elen < 8) {
+        error_setg(errp,
+                   "Vector extension implementation only supports ELEN "
+                   "in the range [8, 64]");
+        return;
+    }
+    if (cfg->vext_spec) {
+        if (!g_strcmp0(cfg->vext_spec, "v1.0")) {
+            env->vext_ver = VEXT_VERSION_1_00_0;
+        } else {
+            error_setg(errp, "Unsupported vector spec version '%s'",
+                       cfg->vext_spec);
+            return;
+        }
+    } else if (env->vext_ver == 0) {
+        qemu_log("vector version is not specified, "
+                 "use the default value v1.0\n");
+
+        env->vext_ver = VEXT_VERSION_1_00_0;
+    }
+}
+
+/*
+ * Check consistency between chosen extensions while setting
+ * cpu->cfg accordingly.
+ */
+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_icsr && cpu->cfg.ext_ifencei)) {
+        warn_report("Setting G will also set IMAFD_Zicsr_Zifencei");
+
+        if (cpu_cfg_ext_is_user_set(CPU_CFG_OFFSET(ext_icsr)) &&
+            !cpu->cfg.ext_icsr) {
+            error_setg(errp, "RVG requires Zicsr but user set Zicsr to false");
+            return;
+        }
+
+        if (cpu_cfg_ext_is_user_set(CPU_CFG_OFFSET(ext_ifencei)) &&
+            !cpu->cfg.ext_ifencei) {
+            error_setg(errp, "RVG requires Zifencei but user set "
+                       "Zifencei to false");
+            return;
+        }
+
+        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_icsr), true);
+        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_ifencei), true);
+
+        env->misa_ext |= RVI | RVM | RVA | RVF | RVD;
+        env->misa_ext_mask |= RVI | RVM | RVA | RVF | RVD;
+    }
+
+    if (riscv_has_ext(env, RVI) && riscv_has_ext(env, RVE)) {
+        error_setg(errp,
+                   "I and E extensions are incompatible");
+        return;
+    }
+
+    if (!riscv_has_ext(env, RVI) && !riscv_has_ext(env, RVE)) {
+        error_setg(errp,
+                   "Either I or E extension must be set");
+        return;
+    }
+
+    if (riscv_has_ext(env, RVS) && !riscv_has_ext(env, RVU)) {
+        error_setg(errp,
+                   "Setting S extension without U extension is illegal");
+        return;
+    }
+
+    if (riscv_has_ext(env, RVH) && !riscv_has_ext(env, RVI)) {
+        error_setg(errp,
+                   "H depends on an I base integer ISA with 32 x registers");
+        return;
+    }
+
+    if (riscv_has_ext(env, RVH) && !riscv_has_ext(env, RVS)) {
+        error_setg(errp, "H extension implicitly requires S-mode");
+        return;
+    }
+
+    if (riscv_has_ext(env, RVF) && !cpu->cfg.ext_icsr) {
+        error_setg(errp, "F extension requires Zicsr");
+        return;
+    }
+
+    if ((cpu->cfg.ext_zawrs) && !riscv_has_ext(env, RVA)) {
+        error_setg(errp, "Zawrs extension requires A extension");
+        return;
+    }
+
+    if (cpu->cfg.ext_zfa && !riscv_has_ext(env, RVF)) {
+        error_setg(errp, "Zfa extension requires F extension");
+        return;
+    }
+
+    if (cpu->cfg.ext_zfh) {
+        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zfhmin), true);
+    }
+
+    if (cpu->cfg.ext_zfhmin && !riscv_has_ext(env, RVF)) {
+        error_setg(errp, "Zfh/Zfhmin extensions require F extension");
+        return;
+    }
+
+    if (cpu->cfg.ext_zfbfmin && !riscv_has_ext(env, RVF)) {
+        error_setg(errp, "Zfbfmin extension depends on F extension");
+        return;
+    }
+
+    if (riscv_has_ext(env, RVD) && !riscv_has_ext(env, RVF)) {
+        error_setg(errp, "D extension requires F extension");
+        return;
+    }
+
+    if (riscv_has_ext(env, RVV)) {
+        riscv_cpu_validate_v(env, &cpu->cfg, &local_err);
+        if (local_err != NULL) {
+            error_propagate(errp, local_err);
+            return;
+        }
+
+        /* The V vector extension depends on the Zve64d extension */
+        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zve64d), true);
+    }
+
+    /* The Zve64d extension depends on the Zve64f extension */
+    if (cpu->cfg.ext_zve64d) {
+        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zve64f), true);
+    }
+
+    /* The Zve64f extension depends on the Zve32f extension */
+    if (cpu->cfg.ext_zve64f) {
+        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zve32f), true);
+    }
+
+    if (cpu->cfg.ext_zve64d && !riscv_has_ext(env, RVD)) {
+        error_setg(errp, "Zve64d/V extensions require D extension");
+        return;
+    }
+
+    if (cpu->cfg.ext_zve32f && !riscv_has_ext(env, RVF)) {
+        error_setg(errp, "Zve32f/Zve64f extensions require F extension");
+        return;
+    }
+
+    if (cpu->cfg.ext_zvfh) {
+        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zvfhmin), true);
+    }
+
+    if (cpu->cfg.ext_zvfhmin && !cpu->cfg.ext_zve32f) {
+        error_setg(errp, "Zvfh/Zvfhmin extensions require Zve32f extension");
+        return;
+    }
+
+    if (cpu->cfg.ext_zvfh && !cpu->cfg.ext_zfhmin) {
+        error_setg(errp, "Zvfh extensions requires Zfhmin extension");
+        return;
+    }
+
+    if (cpu->cfg.ext_zvfbfmin && !cpu->cfg.ext_zfbfmin) {
+        error_setg(errp, "Zvfbfmin extension depends on Zfbfmin extension");
+        return;
+    }
+
+    if (cpu->cfg.ext_zvfbfmin && !cpu->cfg.ext_zve32f) {
+        error_setg(errp, "Zvfbfmin extension depends on Zve32f extension");
+        return;
+    }
+
+    if (cpu->cfg.ext_zvfbfwma && !cpu->cfg.ext_zvfbfmin) {
+        error_setg(errp, "Zvfbfwma extension depends on Zvfbfmin extension");
+        return;
+    }
+
+    /* Set the ISA extensions, checks should have happened above */
+    if (cpu->cfg.ext_zhinx) {
+        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zca), true);
+    }
+
+    if ((cpu->cfg.ext_zdinx || cpu->cfg.ext_zhinxmin) && !cpu->cfg.ext_zfinx) {
+        error_setg(errp, "Zdinx/Zhinx/Zhinxmin extensions require Zfinx");
+        return;
+    }
+
+    if (cpu->cfg.ext_zfinx) {
+        if (!cpu->cfg.ext_icsr) {
+            error_setg(errp, "Zfinx extension requires Zicsr");
+            return;
+        }
+        if (riscv_has_ext(env, RVF)) {
+            error_setg(errp,
+                       "Zfinx cannot be supported together with F extension");
+            return;
+        }
+    }
+
+    if (cpu->cfg.ext_zce) {
+        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zca), true);
+        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zcb), true);
+        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zcmp), true);
+        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zcmt), true);
+        if (riscv_has_ext(env, RVF) && env->misa_mxl_max == MXL_RV32) {
+            cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zcf), true);
+        }
+    }
+
+    /* zca, zcd and zcf has a PRIV 1.12.0 restriction */
+    if (riscv_has_ext(env, RVC) && env->priv_ver >= PRIV_VERSION_1_12_0) {
+        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zca), true);
+        if (riscv_has_ext(env, RVF) && env->misa_mxl_max == MXL_RV32) {
+            cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zcf), true);
+        }
+        if (riscv_has_ext(env, RVD)) {
+            cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zcd), true);
+        }
+    }
+
+    if (env->misa_mxl_max != MXL_RV32 && cpu->cfg.ext_zcf) {
+        error_setg(errp, "Zcf extension is only relevant to RV32");
+        return;
+    }
+
+    if (!riscv_has_ext(env, RVF) && cpu->cfg.ext_zcf) {
+        error_setg(errp, "Zcf extension requires F extension");
+        return;
+    }
+
+    if (!riscv_has_ext(env, RVD) && cpu->cfg.ext_zcd) {
+        error_setg(errp, "Zcd extension requires D extension");
+        return;
+    }
+
+    if ((cpu->cfg.ext_zcf || cpu->cfg.ext_zcd || cpu->cfg.ext_zcb ||
+         cpu->cfg.ext_zcmp || cpu->cfg.ext_zcmt) && !cpu->cfg.ext_zca) {
+        error_setg(errp, "Zcf/Zcd/Zcb/Zcmp/Zcmt extensions require Zca "
+                         "extension");
+        return;
+    }
+
+    if (cpu->cfg.ext_zcd && (cpu->cfg.ext_zcmp || cpu->cfg.ext_zcmt)) {
+        error_setg(errp, "Zcmp/Zcmt extensions are incompatible with "
+                         "Zcd extension");
+        return;
+    }
+
+    if (cpu->cfg.ext_zcmt && !cpu->cfg.ext_icsr) {
+        error_setg(errp, "Zcmt extension requires Zicsr extension");
+        return;
+    }
+
+    /*
+     * In principle Zve*x would also suffice here, were they supported
+     * in qemu
+     */
+    if ((cpu->cfg.ext_zvbb || cpu->cfg.ext_zvkg || cpu->cfg.ext_zvkned ||
+         cpu->cfg.ext_zvknha || cpu->cfg.ext_zvksed || cpu->cfg.ext_zvksh) &&
+        !cpu->cfg.ext_zve32f) {
+        error_setg(errp,
+                   "Vector crypto extensions require V or Zve* extensions");
+        return;
+    }
+
+    if ((cpu->cfg.ext_zvbc || cpu->cfg.ext_zvknhb) && !cpu->cfg.ext_zve64f) {
+        error_setg(
+            errp,
+            "Zvbc and Zvknhb extensions require V or Zve64{f,d} extensions");
+        return;
+    }
+
+    if (cpu->cfg.ext_zk) {
+        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zkn), true);
+        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zkr), true);
+        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zkt), true);
+    }
+
+    if (cpu->cfg.ext_zkn) {
+        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zbkb), true);
+        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zbkc), true);
+        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zbkx), true);
+        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zkne), true);
+        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zknd), true);
+        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zknh), true);
+    }
+
+    if (cpu->cfg.ext_zks) {
+        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zbkb), true);
+        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zbkc), true);
+        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zbkx), true);
+        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zksed), true);
+        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zksh), true);
+    }
+
+    /*
+     * Disable isa extensions based on priv spec after we
+     * validated and set everything we need.
+     */
+    riscv_cpu_disable_priv_spec_isa_exts(cpu);
+}
+
 /*
  * We'll get here via the following path:
  *
diff --git a/target/riscv/tcg/tcg-cpu.h b/target/riscv/tcg/tcg-cpu.h
new file mode 100644
index 0000000000..4cf35a8015
--- /dev/null
+++ b/target/riscv/tcg/tcg-cpu.h
@@ -0,0 +1,28 @@
+/*
+ * riscv TCG cpu class initialization
+ *
+ * Copyright (c) 2023 Ventana Micro Systems Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef RISCV_TCG_CPU_H
+#define RISCV_TCG_CPU_H
+
+#include "cpu.h"
+
+void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp);
+
+#endif
+
-- 
2.41.0



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

* [PATCH 04/20] target/riscv: move riscv_tcg_ops to tcg-cpu.c
  2023-08-25 13:08 [PATCH 00/20] riscv: split TCG/KVM accelerators from cpu.c Daniel Henrique Barboza
                   ` (2 preceding siblings ...)
  2023-08-25 13:08 ` [PATCH 03/20] target/riscv: move riscv_cpu_validate_set_extensions() to tcg-cpu.c Daniel Henrique Barboza
@ 2023-08-25 13:08 ` Daniel Henrique Barboza
  2023-08-28 16:30   ` Philippe Mathieu-Daudé
  2023-08-31 10:38   ` Andrew Jones
  2023-08-25 13:08 ` [PATCH 05/20] target/riscv/cpu.c: add 'user_extension_properties' class prop Daniel Henrique Barboza
                   ` (15 subsequent siblings)
  19 siblings, 2 replies; 51+ messages in thread
From: Daniel Henrique Barboza @ 2023-08-25 13:08 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-riscv, alistair.francis, bmeng, liweiwei, zhiwei_liu,
	palmer, Daniel Henrique Barboza

Move the remaining of riscv_tcg_ops now that we have a working realize()
implementation.

Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
---
 target/riscv/cpu.c         | 58 -------------------------------------
 target/riscv/cpu.h         |  4 ---
 target/riscv/tcg/tcg-cpu.c | 59 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 59 insertions(+), 62 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 12cea62ee7..839b83e52a 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -839,24 +839,6 @@ static vaddr riscv_cpu_get_pc(CPUState *cs)
     return env->pc;
 }
 
-static void riscv_cpu_synchronize_from_tb(CPUState *cs,
-                                          const TranslationBlock *tb)
-{
-    if (!(tb_cflags(tb) & CF_PCREL)) {
-        RISCVCPU *cpu = RISCV_CPU(cs);
-        CPURISCVState *env = &cpu->env;
-        RISCVMXL xl = FIELD_EX32(tb->flags, TB_FLAGS, XL);
-
-        tcg_debug_assert(!(cs->tcg_cflags & CF_PCREL));
-
-        if (xl == MXL_RV32) {
-            env->pc = (int32_t) tb->pc;
-        } else {
-            env->pc = tb->pc;
-        }
-    }
-}
-
 static bool riscv_cpu_has_work(CPUState *cs)
 {
 #ifndef CONFIG_USER_ONLY
@@ -872,29 +854,6 @@ static bool riscv_cpu_has_work(CPUState *cs)
 #endif
 }
 
-static void riscv_restore_state_to_opc(CPUState *cs,
-                                       const TranslationBlock *tb,
-                                       const uint64_t *data)
-{
-    RISCVCPU *cpu = RISCV_CPU(cs);
-    CPURISCVState *env = &cpu->env;
-    RISCVMXL xl = FIELD_EX32(tb->flags, TB_FLAGS, XL);
-    target_ulong pc;
-
-    if (tb_cflags(tb) & CF_PCREL) {
-        pc = (env->pc & TARGET_PAGE_MASK) | data[0];
-    } else {
-        pc = data[0];
-    }
-
-    if (xl == MXL_RV32) {
-        env->pc = (int32_t)pc;
-    } else {
-        env->pc = pc;
-    }
-    env->bins = data[1];
-}
-
 static void riscv_cpu_reset_hold(Object *obj)
 {
 #ifndef CONFIG_USER_ONLY
@@ -1796,23 +1755,6 @@ static const struct SysemuCPUOps riscv_sysemu_ops = {
 };
 #endif
 
-const struct TCGCPUOps riscv_tcg_ops = {
-    .initialize = riscv_translate_init,
-    .synchronize_from_tb = riscv_cpu_synchronize_from_tb,
-    .restore_state_to_opc = riscv_restore_state_to_opc,
-
-#ifndef CONFIG_USER_ONLY
-    .tlb_fill = riscv_cpu_tlb_fill,
-    .cpu_exec_interrupt = riscv_cpu_exec_interrupt,
-    .do_interrupt = riscv_cpu_do_interrupt,
-    .do_transaction_failed = riscv_cpu_do_transaction_failed,
-    .do_unaligned_access = riscv_cpu_do_unaligned_access,
-    .debug_excp_handler = riscv_cpu_debug_excp_handler,
-    .debug_check_breakpoint = riscv_cpu_debug_check_breakpoint,
-    .debug_check_watchpoint = riscv_cpu_debug_check_watchpoint,
-#endif /* !CONFIG_USER_ONLY */
-};
-
 static bool riscv_cpu_is_dynamic(Object *cpu_obj)
 {
     return object_dynamic_cast(cpu_obj, TYPE_RISCV_DYNAMIC_CPU) != NULL;
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 721bd0b119..2ac00a0304 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -706,10 +706,6 @@ enum riscv_pmu_event_idx {
     RISCV_PMU_EVENT_CACHE_ITLB_PREFETCH_MISS = 0x10021,
 };
 
-/* Export tcg_ops until we move everything to tcg/tcg-cpu.c */
-#include "hw/core/tcg-cpu-ops.h"
-extern const struct TCGCPUOps riscv_tcg_ops;
-
 /* used by tcg/tcg-cpu.c*/
 void isa_ext_update_enabled(RISCVCPU *cpu, uint32_t ext_offset, bool en);
 bool cpu_cfg_ext_is_user_set(uint32_t ext_offset);
diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
index fb17097bb1..2024c98793 100644
--- a/target/riscv/tcg/tcg-cpu.c
+++ b/target/riscv/tcg/tcg-cpu.c
@@ -26,7 +26,66 @@
 #include "qemu/accel.h"
 #include "qemu/error-report.h"
 #include "hw/core/accel-cpu.h"
+#include "hw/core/tcg-cpu-ops.h"
+#include "tcg/tcg.h"
 
+static void riscv_cpu_synchronize_from_tb(CPUState *cs,
+                                          const TranslationBlock *tb)
+{
+    if (!(tb_cflags(tb) & CF_PCREL)) {
+        RISCVCPU *cpu = RISCV_CPU(cs);
+        CPURISCVState *env = &cpu->env;
+        RISCVMXL xl = FIELD_EX32(tb->flags, TB_FLAGS, XL);
+
+        tcg_debug_assert(!(cs->tcg_cflags & CF_PCREL));
+
+        if (xl == MXL_RV32) {
+            env->pc = (int32_t) tb->pc;
+        } else {
+            env->pc = tb->pc;
+        }
+    }
+}
+
+static void riscv_restore_state_to_opc(CPUState *cs,
+                                       const TranslationBlock *tb,
+                                       const uint64_t *data)
+{
+    RISCVCPU *cpu = RISCV_CPU(cs);
+    CPURISCVState *env = &cpu->env;
+    RISCVMXL xl = FIELD_EX32(tb->flags, TB_FLAGS, XL);
+    target_ulong pc;
+
+    if (tb_cflags(tb) & CF_PCREL) {
+        pc = (env->pc & TARGET_PAGE_MASK) | data[0];
+    } else {
+        pc = data[0];
+    }
+
+    if (xl == MXL_RV32) {
+        env->pc = (int32_t)pc;
+    } else {
+        env->pc = pc;
+    }
+    env->bins = data[1];
+}
+
+const struct TCGCPUOps riscv_tcg_ops = {
+    .initialize = riscv_translate_init,
+    .synchronize_from_tb = riscv_cpu_synchronize_from_tb,
+    .restore_state_to_opc = riscv_restore_state_to_opc,
+
+#ifndef CONFIG_USER_ONLY
+    .tlb_fill = riscv_cpu_tlb_fill,
+    .cpu_exec_interrupt = riscv_cpu_exec_interrupt,
+    .do_interrupt = riscv_cpu_do_interrupt,
+    .do_transaction_failed = riscv_cpu_do_transaction_failed,
+    .do_unaligned_access = riscv_cpu_do_unaligned_access,
+    .debug_excp_handler = riscv_cpu_debug_excp_handler,
+    .debug_check_breakpoint = riscv_cpu_debug_check_breakpoint,
+    .debug_check_watchpoint = riscv_cpu_debug_check_watchpoint,
+#endif /* !CONFIG_USER_ONLY */
+};
 
 static void cpu_cfg_ext_auto_update(RISCVCPU *cpu, uint32_t ext_offset,
                                     bool value)
-- 
2.41.0



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

* [PATCH 05/20] target/riscv/cpu.c: add 'user_extension_properties' class prop
  2023-08-25 13:08 [PATCH 00/20] riscv: split TCG/KVM accelerators from cpu.c Daniel Henrique Barboza
                   ` (3 preceding siblings ...)
  2023-08-25 13:08 ` [PATCH 04/20] target/riscv: move riscv_tcg_ops " Daniel Henrique Barboza
@ 2023-08-25 13:08 ` Daniel Henrique Barboza
  2023-08-25 13:08 ` [PATCH 06/20] target/riscv: add 'max_features' CPU flag Daniel Henrique Barboza
                   ` (14 subsequent siblings)
  19 siblings, 0 replies; 51+ messages in thread
From: Daniel Henrique Barboza @ 2023-08-25 13:08 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-riscv, alistair.francis, bmeng, liweiwei, zhiwei_liu,
	palmer, Daniel Henrique Barboza

We want to use a post_init hook to call the cpu_instance_init callback
from each accelerator, moving repetitive code from the cpu_init()
functions to be handled by the accelerator class. But first we need to
ensure that we don't change behavior - vendor CPUs shouldn't expose user
properties, generic CPUs should expose.

Create a new 'user_extension_properties' class property. It'll be
initialized during the class init of each CPU type, where only generic
(dynamic) CPUs will enable it. This new property will be used shortly.

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

diff --git a/target/riscv/cpu-qom.h b/target/riscv/cpu-qom.h
index f3fbe37a2c..7c76dc0dcc 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)
@@ -68,5 +69,7 @@ struct RISCVCPUClass {
     /*< public >*/
     DeviceRealize parent_realize;
     ResettablePhases parent_phases;
+
+    bool user_extension_properties;
 };
 #endif /* RISCV_CPU_QOM_H */
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 839b83e52a..e2e8724dc2 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -1975,6 +1975,20 @@ void riscv_cpu_list(void)
     g_slist_free(list);
 }
 
+static void riscv_dynamic_cpu_class_init(ObjectClass *c, void *data)
+{
+    RISCVCPUClass *rcc = RISCV_CPU_CLASS(c);
+
+    rcc->user_extension_properties = true;
+}
+
+static void riscv_vendor_cpu_class_init(ObjectClass *c, void *data)
+{
+    RISCVCPUClass *rcc = RISCV_CPU_CLASS(c);
+
+    rcc->user_extension_properties = false;
+}
+
 #define DEFINE_CPU(type_name, initfn)      \
     {                                      \
         .name = type_name,                 \
@@ -1989,6 +2003,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,
@@ -2003,6 +2024,13 @@ static const TypeInfo riscv_cpu_type_infos[] = {
     {
         .name = TYPE_RISCV_DYNAMIC_CPU,
         .parent = TYPE_RISCV_CPU,
+        .class_init = riscv_dynamic_cpu_class_init,
+        .abstract = true,
+    },
+    {
+        .name = TYPE_RISCV_VENDOR_CPU,
+        .parent = TYPE_RISCV_CPU,
+        .class_init = riscv_vendor_cpu_class_init,
         .abstract = true,
     },
     DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_ANY,      riscv_any_cpu_init),
@@ -2012,17 +2040,17 @@ static const TypeInfo riscv_cpu_type_infos[] = {
 #endif
 #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] 51+ messages in thread

* [PATCH 06/20] target/riscv: add 'max_features' CPU flag
  2023-08-25 13:08 [PATCH 00/20] riscv: split TCG/KVM accelerators from cpu.c Daniel Henrique Barboza
                   ` (4 preceding siblings ...)
  2023-08-25 13:08 ` [PATCH 05/20] target/riscv/cpu.c: add 'user_extension_properties' class prop Daniel Henrique Barboza
@ 2023-08-25 13:08 ` Daniel Henrique Barboza
  2023-08-25 13:08 ` [PATCH 07/20] target/riscv/cpu.c: add .instance_post_init() Daniel Henrique Barboza
                   ` (13 subsequent siblings)
  19 siblings, 0 replies; 51+ messages in thread
From: Daniel Henrique Barboza @ 2023-08-25 13:08 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-riscv, alistair.francis, bmeng, liweiwei, zhiwei_liu,
	palmer, Daniel Henrique Barboza

The 'max' CPU type is being configured during init() time by enabling
all relevant extensions.

Instead of checking for 'max' CPU to enable all extensions, add a new
CPU cfg flag 'max_features' that can be used by any CPU during its
cpu_init() function. We'll check for it during post_init() time to
decide whether we should enable the maximum amount of features in the
current CPU instance.

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

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index e2e8724dc2..c35d58c64b 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -424,6 +424,8 @@ static void riscv_max_cpu_init(Object *obj)
     CPURISCVState *env = &cpu->env;
     RISCVMXL mlx = MXL_RV64;
 
+    cpu->cfg.max_features = true;
+
 #ifdef TARGET_RISCV32
     mlx = MXL_RV32;
 #endif
diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h
index 0e6a0f245c..df723e697b 100644
--- a/target/riscv/cpu_cfg.h
+++ b/target/riscv/cpu_cfg.h
@@ -137,6 +137,7 @@ struct RISCVCPUConfig {
     bool epmp;
     bool debug;
     bool misa_w;
+    bool max_features;
 
     bool short_isa_string;
 
-- 
2.41.0



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

* [PATCH 07/20] target/riscv/cpu.c: add .instance_post_init()
  2023-08-25 13:08 [PATCH 00/20] riscv: split TCG/KVM accelerators from cpu.c Daniel Henrique Barboza
                   ` (5 preceding siblings ...)
  2023-08-25 13:08 ` [PATCH 06/20] target/riscv: add 'max_features' CPU flag Daniel Henrique Barboza
@ 2023-08-25 13:08 ` Daniel Henrique Barboza
  2023-08-31 11:00   ` Andrew Jones
  2023-08-25 13:08 ` [PATCH 08/20] target/riscv: move 'host' CPU declaration to kvm.c Daniel Henrique Barboza
                   ` (12 subsequent siblings)
  19 siblings, 1 reply; 51+ messages in thread
From: Daniel Henrique Barboza @ 2023-08-25 13:08 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-riscv, alistair.francis, bmeng, liweiwei, zhiwei_liu,
	palmer, Daniel Henrique Barboza

All generic CPUs call riscv_cpu_add_user_properties(). The 'max' CPU
calls riscv_init_max_cpu_extensions(). Both can be moved to a common
instance_post_init() callback, implemented in riscv_cpu_post_init(),
called by all CPUs. The call order then becomes:

riscv_cpu_init() -> cpu_init() of each CPU -> .instance_post_init()

A CPU class that wants to add user flags will let us know via the
'user_extension_properties' property. Likewise, 'cfg.max_features' will
determine if any given CPU, regardless of being the 'max' CPU or not,
wants to enable the maximum amount of extensions.

In the near future riscv_cpu_post_init() will call the init() function
of the current accelerator, providing a hook for KVM and TCG accel
classes to change the init() process of the CPU.

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

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index c35d58c64b..f67b782675 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -430,8 +430,6 @@ static void riscv_max_cpu_init(Object *obj)
     mlx = MXL_RV32;
 #endif
     set_misa(env, mlx, 0);
-    riscv_cpu_add_user_properties(obj);
-    riscv_init_max_cpu_extensions(obj);
     env->priv_ver = PRIV_VERSION_LATEST;
 #ifndef CONFIG_USER_ONLY
     set_satp_mode_max_supported(RISCV_CPU(obj), mlx == MXL_RV32 ?
@@ -445,7 +443,6 @@ static void rv64_base_cpu_init(Object *obj)
     CPURISCVState *env = &RISCV_CPU(obj)->env;
     /* We set this in the realise function */
     set_misa(env, MXL_RV64, 0);
-    riscv_cpu_add_user_properties(obj);
     /* Set latest version of privileged specification */
     env->priv_ver = PRIV_VERSION_LATEST;
 #ifndef CONFIG_USER_ONLY
@@ -569,7 +566,6 @@ static void rv128_base_cpu_init(Object *obj)
     CPURISCVState *env = &RISCV_CPU(obj)->env;
     /* We set this in the realise function */
     set_misa(env, MXL_RV128, 0);
-    riscv_cpu_add_user_properties(obj);
     /* Set latest version of privileged specification */
     env->priv_ver = PRIV_VERSION_LATEST;
 #ifndef CONFIG_USER_ONLY
@@ -582,7 +578,6 @@ static void rv32_base_cpu_init(Object *obj)
     CPURISCVState *env = &RISCV_CPU(obj)->env;
     /* We set this in the realise function */
     set_misa(env, MXL_RV32, 0);
-    riscv_cpu_add_user_properties(obj);
     /* Set latest version of privileged specification */
     env->priv_ver = PRIV_VERSION_LATEST;
 #ifndef CONFIG_USER_ONLY
@@ -1212,6 +1207,20 @@ static void riscv_cpu_set_irq(void *opaque, int irq, int level)
 }
 #endif /* CONFIG_USER_ONLY */
 
+static void riscv_cpu_post_init(Object *obj)
+{
+    RISCVCPU *cpu = RISCV_CPU(obj);
+    RISCVCPUClass *rcc = RISCV_CPU_GET_CLASS(cpu);
+
+    if (rcc->user_extension_properties) {
+        riscv_cpu_add_user_properties(obj);
+    }
+
+    if (cpu->cfg.max_features) {
+        riscv_init_max_cpu_extensions(obj);
+    }
+}
+
 static void riscv_cpu_init(Object *obj)
 {
     RISCVCPU *cpu = RISCV_CPU(obj);
@@ -2019,6 +2028,7 @@ static const TypeInfo riscv_cpu_type_infos[] = {
         .instance_size = sizeof(RISCVCPU),
         .instance_align = __alignof__(RISCVCPU),
         .instance_init = riscv_cpu_init,
+        .instance_post_init = riscv_cpu_post_init,
         .abstract = true,
         .class_size = sizeof(RISCVCPUClass),
         .class_init = riscv_cpu_class_init,
-- 
2.41.0



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

* [PATCH 08/20] target/riscv: move 'host' CPU declaration to kvm.c
  2023-08-25 13:08 [PATCH 00/20] riscv: split TCG/KVM accelerators from cpu.c Daniel Henrique Barboza
                   ` (6 preceding siblings ...)
  2023-08-25 13:08 ` [PATCH 07/20] target/riscv/cpu.c: add .instance_post_init() Daniel Henrique Barboza
@ 2023-08-25 13:08 ` Daniel Henrique Barboza
  2023-08-28 16:35   ` Philippe Mathieu-Daudé
  2023-08-31 11:04   ` Andrew Jones
  2023-08-25 13:08 ` [PATCH 09/20] target/riscv/cpu.c: mark extensions arrays as 'const' Daniel Henrique Barboza
                   ` (11 subsequent siblings)
  19 siblings, 2 replies; 51+ messages in thread
From: Daniel Henrique Barboza @ 2023-08-25 13:08 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-riscv, alistair.francis, bmeng, liweiwei, zhiwei_liu,
	palmer, Daniel Henrique Barboza

This CPU only exists if we're compiling with KVM so move it to the kvm
specific file. While we're at it, change its class_init() to enable the
user_extensions_flag class property, sparing us from having to execute
riscv_cpu_add_user_properties() by hand and letting the post_init() hook
do the work.

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

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index f67b782675..dbf81796d2 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -655,19 +655,6 @@ static void rv32_imafcu_nommu_cpu_init(Object *obj)
 }
 #endif
 
-#if defined(CONFIG_KVM)
-static void riscv_host_cpu_init(Object *obj)
-{
-    CPURISCVState *env = &RISCV_CPU(obj)->env;
-#if defined(TARGET_RISCV32)
-    set_misa(env, MXL_RV32, 0);
-#elif defined(TARGET_RISCV64)
-    set_misa(env, MXL_RV64, 0);
-#endif
-    riscv_cpu_add_user_properties(obj);
-}
-#endif /* CONFIG_KVM */
-
 static ObjectClass *riscv_cpu_class_by_name(const char *cpu_model)
 {
     ObjectClass *oc;
@@ -2000,13 +1987,6 @@ static void riscv_vendor_cpu_class_init(ObjectClass *c, void *data)
     rcc->user_extension_properties = false;
 }
 
-#define DEFINE_CPU(type_name, initfn)      \
-    {                                      \
-        .name = type_name,                 \
-        .parent = TYPE_RISCV_CPU,          \
-        .instance_init = initfn            \
-    }
-
 #define DEFINE_DYNAMIC_CPU(type_name, initfn) \
     {                                         \
         .name = type_name,                    \
@@ -2047,9 +2027,6 @@ static const TypeInfo riscv_cpu_type_infos[] = {
     },
     DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_ANY,      riscv_any_cpu_init),
     DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_MAX,      riscv_max_cpu_init),
-#if defined(CONFIG_KVM)
-    DEFINE_CPU(TYPE_RISCV_CPU_HOST,             riscv_host_cpu_init),
-#endif
 #if defined(TARGET_RISCV32)
     DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_BASE32,   rv32_base_cpu_init),
     DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_IBEX,             rv32_ibex_cpu_init),
diff --git a/target/riscv/kvm.c b/target/riscv/kvm.c
index 7c6dec05e3..59004caa8e 100644
--- a/target/riscv/kvm.c
+++ b/target/riscv/kvm.c
@@ -1217,3 +1217,32 @@ void kvm_riscv_aia_create(MachineState *machine, uint64_t group_shift,
 
     kvm_msi_via_irqfd_allowed = kvm_irqfds_enabled();
 }
+
+static void riscv_host_cpu_init(Object *obj)
+{
+    CPURISCVState *env = &RISCV_CPU(obj)->env;
+
+#if defined(TARGET_RISCV32)
+    env->misa_mxl_max = env->misa_mxl = MXL_RV32;
+#elif defined(TARGET_RISCV64)
+    env->misa_mxl_max = env->misa_mxl = MXL_RV64;
+#endif
+}
+
+static void riscv_kvm_cpu_class_init(ObjectClass *c, void *data)
+{
+    RISCVCPUClass *rcc = RISCV_CPU_CLASS(c);
+
+    rcc->user_extension_properties = true;
+}
+
+static const TypeInfo riscv_kvm_cpu_type_infos[] = {
+    {
+        .name = TYPE_RISCV_CPU_HOST,
+        .parent = TYPE_RISCV_CPU,
+        .instance_init = riscv_host_cpu_init,
+        .class_init = riscv_kvm_cpu_class_init,
+    }
+};
+
+DEFINE_TYPES(riscv_kvm_cpu_type_infos)
-- 
2.41.0



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

* [PATCH 09/20] target/riscv/cpu.c: mark extensions arrays as 'const'
  2023-08-25 13:08 [PATCH 00/20] riscv: split TCG/KVM accelerators from cpu.c Daniel Henrique Barboza
                   ` (7 preceding siblings ...)
  2023-08-25 13:08 ` [PATCH 08/20] target/riscv: move 'host' CPU declaration to kvm.c Daniel Henrique Barboza
@ 2023-08-25 13:08 ` Daniel Henrique Barboza
  2023-08-31 11:10   ` Andrew Jones
  2023-08-25 13:08 ` [PATCH 10/20] target/riscv: move riscv_cpu_add_kvm_properties() to kvm.c Daniel Henrique Barboza
                   ` (10 subsequent siblings)
  19 siblings, 1 reply; 51+ messages in thread
From: Daniel Henrique Barboza @ 2023-08-25 13:08 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-riscv, alistair.francis, bmeng, liweiwei, zhiwei_liu,
	palmer, Daniel Henrique Barboza

We'll need to export these arrays to the accelerator classes in the next
patches. Mark them as 'const' now to minimize changes in the future.

Note that 'riscv_cpu_options' will also be exported, but can't be marked
as 'const', because the properties are changed via
qdev_property_add_static().

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

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index dbf81796d2..4eda853f1d 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -1381,7 +1381,7 @@ typedef struct RISCVCPUMultiExtConfig {
     {.name = _name, .offset = CPU_CFG_OFFSET(_prop), \
      .enabled = _defval}
 
-static RISCVCPUMultiExtConfig riscv_cpu_extensions[] = {
+static const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = {
     /* Defaults for standard extensions */
     MULTI_EXT_CFG_BOOL("sscofpmf", ext_sscofpmf, false),
     MULTI_EXT_CFG_BOOL("Zifencei", ext_ifencei, true),
@@ -1441,7 +1441,7 @@ static RISCVCPUMultiExtConfig riscv_cpu_extensions[] = {
     DEFINE_PROP_END_OF_LIST(),
 };
 
-static RISCVCPUMultiExtConfig riscv_cpu_vendor_exts[] = {
+static const RISCVCPUMultiExtConfig riscv_cpu_vendor_exts[] = {
     MULTI_EXT_CFG_BOOL("xtheadba", ext_xtheadba, false),
     MULTI_EXT_CFG_BOOL("xtheadbb", ext_xtheadbb, false),
     MULTI_EXT_CFG_BOOL("xtheadbs", ext_xtheadbs, false),
@@ -1459,7 +1459,7 @@ static RISCVCPUMultiExtConfig riscv_cpu_vendor_exts[] = {
 };
 
 /* These are experimental so mark with 'x-' */
-static RISCVCPUMultiExtConfig riscv_cpu_experimental_exts[] = {
+static const RISCVCPUMultiExtConfig riscv_cpu_experimental_exts[] = {
     MULTI_EXT_CFG_BOOL("x-zicond", ext_zicond, false),
 
     /* ePMP 0.9.3 */
@@ -1532,7 +1532,7 @@ static void cpu_get_multi_ext_cfg(Object *obj, Visitor *v, const char *name,
 }
 
 static void cpu_add_multi_ext_prop(Object *cpu_obj,
-                                   RISCVCPUMultiExtConfig *multi_cfg)
+                                   const RISCVCPUMultiExtConfig *multi_cfg)
 {
     object_property_add(cpu_obj, multi_cfg->name, "bool",
                         cpu_get_multi_ext_cfg,
@@ -1568,9 +1568,11 @@ static void cpu_set_cfg_unavailable(Object *obj, Visitor *v,
 #endif
 
 static void riscv_cpu_add_multiext_prop_array(Object *obj,
-                                              RISCVCPUMultiExtConfig *array)
+                                        const RISCVCPUMultiExtConfig *array)
 {
-    for (RISCVCPUMultiExtConfig *prop = array; prop && prop->name; prop++) {
+    const RISCVCPUMultiExtConfig *prop;
+
+    for (prop = array; prop && prop->name; prop++) {
         cpu_add_multi_ext_prop(obj, prop);
     }
 }
@@ -1594,9 +1596,11 @@ static void riscv_cpu_add_kvm_unavail_prop(Object *obj, const char *prop_name)
 }
 
 static void riscv_cpu_add_kvm_unavail_prop_array(Object *obj,
-                                                 RISCVCPUMultiExtConfig *array)
+                                        const RISCVCPUMultiExtConfig *array)
 {
-    for (RISCVCPUMultiExtConfig *prop = array; prop && prop->name; prop++) {
+    const RISCVCPUMultiExtConfig *prop;
+
+    for (prop = array; prop && prop->name; prop++) {
         riscv_cpu_add_kvm_unavail_prop(obj, prop->name);
     }
 }
@@ -1659,7 +1663,7 @@ static void riscv_init_max_cpu_extensions(Object *obj)
 {
     RISCVCPU *cpu = RISCV_CPU(obj);
     CPURISCVState *env = &cpu->env;
-    RISCVCPUMultiExtConfig *prop;
+    const RISCVCPUMultiExtConfig *prop;
 
     /* Enable RVG, RVJ and RVV that are disabled by default */
     set_misa(env, env->misa_mxl, env->misa_ext | RVG | RVJ | RVV);
-- 
2.41.0



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

* [PATCH 10/20] target/riscv: move riscv_cpu_add_kvm_properties() to kvm.c
  2023-08-25 13:08 [PATCH 00/20] riscv: split TCG/KVM accelerators from cpu.c Daniel Henrique Barboza
                   ` (8 preceding siblings ...)
  2023-08-25 13:08 ` [PATCH 09/20] target/riscv/cpu.c: mark extensions arrays as 'const' Daniel Henrique Barboza
@ 2023-08-25 13:08 ` Daniel Henrique Barboza
  2023-08-31 11:22   ` Andrew Jones
  2023-08-25 13:08 ` [PATCH 11/20] target/riscv: introduce KVM AccelCPUClass Daniel Henrique Barboza
                   ` (9 subsequent siblings)
  19 siblings, 1 reply; 51+ messages in thread
From: Daniel Henrique Barboza @ 2023-08-25 13:08 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-riscv, alistair.francis, bmeng, liweiwei, zhiwei_liu,
	palmer, Daniel Henrique Barboza

We'll introduce the KVM accelerator class with a 'cpu_instance_init'
implementation that is going to be invoked during the common
riscv_cpu_post_init() (via accel_cpu_instance_init()). This
instance_init will execute KVM exclusive code that TCG doesn't care
about, such as adding KVM specific properties, initing registers using a
KVM scratch CPU and so on.

The core of the forementioned cpu_instance_init impl is the current
riscv_cpu_add_kvm_properties() that is being used by the common code via
riscv_cpu_add_user_properties() in cpu.c. Move it to kvm.c, together
will all the relevant artifacts, exporting and renaming it to
kvm_riscv_cpu_add_kvm_properties() so cpu.c can keep using it for now.

To make this work we'll need to export riscv_cpu_extensions,
riscv_cpu_vendor_exts and riscv_cpu_experimental_exts from cpu.c as
well. The TCG accelerator will also need to access those in the near
future so this export will benefit us in the long run.

Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
---
 target/riscv/cpu.c       | 87 +++-------------------------------------
 target/riscv/cpu.h       | 14 +++++++
 target/riscv/kvm.c       | 66 +++++++++++++++++++++++++++++-
 target/riscv/kvm_riscv.h |  2 +-
 4 files changed, 86 insertions(+), 83 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 4eda853f1d..58b0ef2af8 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -1344,7 +1344,7 @@ static RISCVCPUMisaExtConfig misa_ext_cfgs[] = {
     MISA_CFG(RVG, false),
 };
 
-static void riscv_cpu_add_misa_properties(Object *cpu_obj)
+void riscv_cpu_add_misa_properties(Object *cpu_obj)
 {
     int i;
 
@@ -1371,17 +1371,11 @@ static void riscv_cpu_add_misa_properties(Object *cpu_obj)
     }
 }
 
-typedef struct RISCVCPUMultiExtConfig {
-    const char *name;
-    uint32_t offset;
-    bool enabled;
-} RISCVCPUMultiExtConfig;
-
 #define MULTI_EXT_CFG_BOOL(_name, _prop, _defval) \
     {.name = _name, .offset = CPU_CFG_OFFSET(_prop), \
      .enabled = _defval}
 
-static const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = {
+const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = {
     /* Defaults for standard extensions */
     MULTI_EXT_CFG_BOOL("sscofpmf", ext_sscofpmf, false),
     MULTI_EXT_CFG_BOOL("Zifencei", ext_ifencei, true),
@@ -1441,7 +1435,7 @@ static const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = {
     DEFINE_PROP_END_OF_LIST(),
 };
 
-static const RISCVCPUMultiExtConfig riscv_cpu_vendor_exts[] = {
+const RISCVCPUMultiExtConfig riscv_cpu_vendor_exts[] = {
     MULTI_EXT_CFG_BOOL("xtheadba", ext_xtheadba, false),
     MULTI_EXT_CFG_BOOL("xtheadbb", ext_xtheadbb, false),
     MULTI_EXT_CFG_BOOL("xtheadbs", ext_xtheadbs, false),
@@ -1459,7 +1453,7 @@ static const RISCVCPUMultiExtConfig riscv_cpu_vendor_exts[] = {
 };
 
 /* These are experimental so mark with 'x-' */
-static const RISCVCPUMultiExtConfig riscv_cpu_experimental_exts[] = {
+const RISCVCPUMultiExtConfig riscv_cpu_experimental_exts[] = {
     MULTI_EXT_CFG_BOOL("x-zicond", ext_zicond, false),
 
     /* ePMP 0.9.3 */
@@ -1487,7 +1481,7 @@ static const RISCVCPUMultiExtConfig riscv_cpu_experimental_exts[] = {
     DEFINE_PROP_END_OF_LIST(),
 };
 
-static Property riscv_cpu_options[] = {
+Property riscv_cpu_options[] = {
     DEFINE_PROP_UINT8("pmu-num", RISCVCPU, cfg.pmu_num, 16),
 
     DEFINE_PROP_BOOL("mmu", RISCVCPU, cfg.mmu, true),
@@ -1548,25 +1542,6 @@ static void cpu_add_multi_ext_prop(Object *cpu_obj,
                            multi_cfg->enabled);
 }
 
-#ifndef CONFIG_USER_ONLY
-static void cpu_set_cfg_unavailable(Object *obj, Visitor *v,
-                                    const char *name,
-                                    void *opaque, Error **errp)
-{
-    const char *propname = opaque;
-    bool value;
-
-    if (!visit_type_bool(v, name, &value, errp)) {
-        return;
-    }
-
-    if (value) {
-        error_setg(errp, "extension %s is not available with KVM",
-                   propname);
-    }
-}
-#endif
-
 static void riscv_cpu_add_multiext_prop_array(Object *obj,
                                         const RISCVCPUMultiExtConfig *array)
 {
@@ -1577,56 +1552,6 @@ static void riscv_cpu_add_multiext_prop_array(Object *obj,
     }
 }
 
-#ifndef CONFIG_USER_ONLY
-static void riscv_cpu_add_kvm_unavail_prop(Object *obj, const char *prop_name)
-{
-    /* Check if KVM created the property already */
-    if (object_property_find(obj, prop_name)) {
-        return;
-    }
-
-    /*
-     * Set the default to disabled for every extension
-     * unknown to KVM and error out if the user attempts
-     * to enable any of them.
-     */
-    object_property_add(obj, prop_name, "bool",
-                        NULL, cpu_set_cfg_unavailable,
-                        NULL, (void *)prop_name);
-}
-
-static void riscv_cpu_add_kvm_unavail_prop_array(Object *obj,
-                                        const RISCVCPUMultiExtConfig *array)
-{
-    const RISCVCPUMultiExtConfig *prop;
-
-    for (prop = array; prop && prop->name; prop++) {
-        riscv_cpu_add_kvm_unavail_prop(obj, prop->name);
-    }
-}
-
-static void riscv_cpu_add_kvm_properties(Object *obj)
-{
-    Property *prop;
-    DeviceState *dev = DEVICE(obj);
-
-    kvm_riscv_init_user_properties(obj);
-    riscv_cpu_add_misa_properties(obj);
-
-    riscv_cpu_add_kvm_unavail_prop_array(obj, riscv_cpu_extensions);
-    riscv_cpu_add_kvm_unavail_prop_array(obj, riscv_cpu_vendor_exts);
-    riscv_cpu_add_kvm_unavail_prop_array(obj, riscv_cpu_experimental_exts);
-
-    for (prop = riscv_cpu_options; prop && prop->name; prop++) {
-        /* Check if KVM created the property already */
-        if (object_property_find(obj, prop->name)) {
-            continue;
-        }
-        qdev_property_add_static(dev, prop);
-    }
-}
-#endif
-
 /*
  * Add CPU properties with user-facing flags.
  *
@@ -1639,7 +1564,7 @@ static void riscv_cpu_add_user_properties(Object *obj)
     riscv_add_satp_mode_properties(obj);
 
     if (kvm_enabled()) {
-        riscv_cpu_add_kvm_properties(obj);
+        kvm_riscv_cpu_add_kvm_properties(obj);
         return;
     }
 #endif
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 2ac00a0304..b9c4bea3f7 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -22,6 +22,7 @@
 
 #include "hw/core/cpu.h"
 #include "hw/registerfields.h"
+#include "hw/qdev-properties.h"
 #include "exec/cpu-defs.h"
 #include "qemu/cpu-float.h"
 #include "qom/object.h"
@@ -713,6 +714,19 @@ bool isa_ext_is_enabled(RISCVCPU *cpu, uint32_t ext_offset);
 int cpu_cfg_ext_get_min_version(uint32_t ext_offset);
 void riscv_cpu_disable_priv_spec_isa_exts(RISCVCPU *cpu);
 
+typedef struct RISCVCPUMultiExtConfig {
+    const char *name;
+    uint32_t offset;
+    bool enabled;
+} RISCVCPUMultiExtConfig;
+
+extern const RISCVCPUMultiExtConfig riscv_cpu_extensions[];
+extern const RISCVCPUMultiExtConfig riscv_cpu_vendor_exts[];
+extern const RISCVCPUMultiExtConfig riscv_cpu_experimental_exts[];
+extern Property riscv_cpu_options[];
+
+void riscv_cpu_add_misa_properties(Object *cpu_obj);
+
 /* CSR function table */
 extern riscv_csr_operations csr_ops[CSR_TABLE_SIZE];
 
diff --git a/target/riscv/kvm.c b/target/riscv/kvm.c
index 59004caa8e..7e67121456 100644
--- a/target/riscv/kvm.c
+++ b/target/riscv/kvm.c
@@ -338,6 +338,50 @@ static void kvm_riscv_update_cpu_cfg_isa_ext(RISCVCPU *cpu, CPUState *cs)
     }
 }
 
+static void cpu_set_cfg_unavailable(Object *obj, Visitor *v,
+                                    const char *name,
+                                    void *opaque, Error **errp)
+{
+    const char *propname = opaque;
+    bool value;
+
+    if (!visit_type_bool(v, name, &value, errp)) {
+        return;
+    }
+
+    if (value) {
+        error_setg(errp, "extension %s is not available with KVM",
+                   propname);
+    }
+}
+
+static void riscv_cpu_add_kvm_unavail_prop(Object *obj, const char *prop_name)
+{
+    /* Check if KVM created the property already */
+    if (object_property_find(obj, prop_name)) {
+        return;
+    }
+
+    /*
+     * Set the default to disabled for every extension
+     * unknown to KVM and error out if the user attempts
+     * to enable any of them.
+     */
+    object_property_add(obj, prop_name, "bool",
+                        NULL, cpu_set_cfg_unavailable,
+                        NULL, (void *)prop_name);
+}
+
+static void riscv_cpu_add_kvm_unavail_prop_array(Object *obj,
+                                        const RISCVCPUMultiExtConfig *array)
+{
+    const RISCVCPUMultiExtConfig *prop;
+
+    for (prop = array; prop && prop->name; prop++) {
+        riscv_cpu_add_kvm_unavail_prop(obj, prop->name);
+    }
+}
+
 static void kvm_riscv_add_cpu_user_properties(Object *cpu_obj)
 {
     int i;
@@ -747,7 +791,7 @@ static void kvm_riscv_init_multiext_cfg(RISCVCPU *cpu, KVMScratchCPU *kvmcpu)
     }
 }
 
-void kvm_riscv_init_user_properties(Object *cpu_obj)
+static void riscv_init_user_properties(Object *cpu_obj)
 {
     RISCVCPU *cpu = RISCV_CPU(cpu_obj);
     KVMScratchCPU kvmcpu;
@@ -1218,6 +1262,26 @@ void kvm_riscv_aia_create(MachineState *machine, uint64_t group_shift,
     kvm_msi_via_irqfd_allowed = kvm_irqfds_enabled();
 }
 
+void kvm_riscv_cpu_add_kvm_properties(Object *obj)
+{
+    DeviceState *dev = DEVICE(obj);
+
+    riscv_init_user_properties(obj);
+    riscv_cpu_add_misa_properties(obj);
+
+    riscv_cpu_add_kvm_unavail_prop_array(obj, riscv_cpu_extensions);
+    riscv_cpu_add_kvm_unavail_prop_array(obj, riscv_cpu_vendor_exts);
+    riscv_cpu_add_kvm_unavail_prop_array(obj, riscv_cpu_experimental_exts);
+
+    for (Property *prop = riscv_cpu_options; prop && prop->name; prop++) {
+        /* Check if KVM created the property already */
+        if (object_property_find(obj, prop->name)) {
+            continue;
+        }
+        qdev_property_add_static(dev, prop);
+    }
+}
+
 static void riscv_host_cpu_init(Object *obj)
 {
     CPURISCVState *env = &RISCV_CPU(obj)->env;
diff --git a/target/riscv/kvm_riscv.h b/target/riscv/kvm_riscv.h
index 7d4b7c60e2..81e08b8359 100644
--- a/target/riscv/kvm_riscv.h
+++ b/target/riscv/kvm_riscv.h
@@ -19,7 +19,7 @@
 #ifndef QEMU_KVM_RISCV_H
 #define QEMU_KVM_RISCV_H
 
-void kvm_riscv_init_user_properties(Object *cpu_obj);
+void kvm_riscv_cpu_add_kvm_properties(Object *obj);
 void kvm_riscv_reset_vcpu(RISCVCPU *cpu);
 void kvm_riscv_set_irq(RISCVCPU *cpu, int irq, int level);
 void kvm_riscv_aia_create(MachineState *machine, uint64_t group_shift,
-- 
2.41.0



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

* [PATCH 11/20] target/riscv: introduce KVM AccelCPUClass
  2023-08-25 13:08 [PATCH 00/20] riscv: split TCG/KVM accelerators from cpu.c Daniel Henrique Barboza
                   ` (9 preceding siblings ...)
  2023-08-25 13:08 ` [PATCH 10/20] target/riscv: move riscv_cpu_add_kvm_properties() to kvm.c Daniel Henrique Barboza
@ 2023-08-25 13:08 ` Daniel Henrique Barboza
  2023-08-28 16:38   ` Philippe Mathieu-Daudé
  2023-08-31 11:26   ` Andrew Jones
  2023-08-25 13:08 ` [PATCH 12/20] target/riscv: move KVM only files to kvm subdir Daniel Henrique Barboza
                   ` (8 subsequent siblings)
  19 siblings, 2 replies; 51+ messages in thread
From: Daniel Henrique Barboza @ 2023-08-25 13:08 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-riscv, alistair.francis, bmeng, liweiwei, zhiwei_liu,
	palmer, Daniel Henrique Barboza

Add a KVM accelerator class like we did with TCG. The difference is
that, at least for now, we won't be using a realize() implementation for
this accelerator.

We'll start by assiging kvm_riscv_cpu_add_kvm_properties(), renamed to
kvm_cpu_instance_init(), as a 'cpu_instance_init' implementation. Change
riscv_cpu_post_init() to invoke accel_cpu_instance_init(), which will go
through the 'cpu_instance_init' impl of the current acceleration (if
available) and execute it. The end result is that the KVM initial setup,
i.e. starting registers and adding its specific properties, will be done
via this hook.

riscv_cpu_add_user_properties() is still being called via the common
post_init() function, thus we still need the "if kvm then return" logic
inside it for now. We'll deal with it when TCG accel class get its own
'cpu_instance_init' implementation.

riscv_add_satp_mode_properties() is now being exported from cpu.c since
it's a common helper between KVM and TCG.

Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
---
 target/riscv/cpu.c       |  8 ++---
 target/riscv/cpu.h       |  1 +
 target/riscv/kvm.c       | 64 +++++++++++++++++++++++++++-------------
 target/riscv/kvm_riscv.h |  1 -
 4 files changed, 49 insertions(+), 25 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 58b0ef2af8..04c6bfaeef 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -1112,7 +1112,7 @@ static void cpu_riscv_set_satp(Object *obj, Visitor *v, const char *name,
     satp_map->init |= 1 << satp;
 }
 
-static void riscv_add_satp_mode_properties(Object *obj)
+void riscv_add_satp_mode_properties(Object *obj)
 {
     RISCVCPU *cpu = RISCV_CPU(obj);
 
@@ -1199,6 +1199,8 @@ static void riscv_cpu_post_init(Object *obj)
     RISCVCPU *cpu = RISCV_CPU(obj);
     RISCVCPUClass *rcc = RISCV_CPU_GET_CLASS(cpu);
 
+    accel_cpu_instance_init(CPU(obj));
+
     if (rcc->user_extension_properties) {
         riscv_cpu_add_user_properties(obj);
     }
@@ -1561,12 +1563,10 @@ static void riscv_cpu_add_multiext_prop_array(Object *obj,
 static void riscv_cpu_add_user_properties(Object *obj)
 {
 #ifndef CONFIG_USER_ONLY
-    riscv_add_satp_mode_properties(obj);
-
     if (kvm_enabled()) {
-        kvm_riscv_cpu_add_kvm_properties(obj);
         return;
     }
+    riscv_add_satp_mode_properties(obj);
 #endif
 
     riscv_cpu_add_misa_properties(obj);
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index b9c4bea3f7..950c2301f2 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -726,6 +726,7 @@ extern const RISCVCPUMultiExtConfig riscv_cpu_experimental_exts[];
 extern Property riscv_cpu_options[];
 
 void riscv_cpu_add_misa_properties(Object *cpu_obj);
+void riscv_add_satp_mode_properties(Object *obj);
 
 /* CSR function table */
 extern riscv_csr_operations csr_ops[CSR_TABLE_SIZE];
diff --git a/target/riscv/kvm.c b/target/riscv/kvm.c
index 7e67121456..3c4fa43cee 100644
--- a/target/riscv/kvm.c
+++ b/target/riscv/kvm.c
@@ -31,6 +31,7 @@
 #include "sysemu/kvm_int.h"
 #include "cpu.h"
 #include "trace.h"
+#include "hw/core/accel-cpu.h"
 #include "hw/pci/pci.h"
 #include "exec/memattrs.h"
 #include "exec/address-spaces.h"
@@ -1262,26 +1263,6 @@ void kvm_riscv_aia_create(MachineState *machine, uint64_t group_shift,
     kvm_msi_via_irqfd_allowed = kvm_irqfds_enabled();
 }
 
-void kvm_riscv_cpu_add_kvm_properties(Object *obj)
-{
-    DeviceState *dev = DEVICE(obj);
-
-    riscv_init_user_properties(obj);
-    riscv_cpu_add_misa_properties(obj);
-
-    riscv_cpu_add_kvm_unavail_prop_array(obj, riscv_cpu_extensions);
-    riscv_cpu_add_kvm_unavail_prop_array(obj, riscv_cpu_vendor_exts);
-    riscv_cpu_add_kvm_unavail_prop_array(obj, riscv_cpu_experimental_exts);
-
-    for (Property *prop = riscv_cpu_options; prop && prop->name; prop++) {
-        /* Check if KVM created the property already */
-        if (object_property_find(obj, prop->name)) {
-            continue;
-        }
-        qdev_property_add_static(dev, prop);
-    }
-}
-
 static void riscv_host_cpu_init(Object *obj)
 {
     CPURISCVState *env = &RISCV_CPU(obj)->env;
@@ -1310,3 +1291,46 @@ static const TypeInfo riscv_kvm_cpu_type_infos[] = {
 };
 
 DEFINE_TYPES(riscv_kvm_cpu_type_infos)
+
+static void kvm_cpu_instance_init(CPUState *cs)
+{
+    Object *obj = OBJECT(RISCV_CPU(cs));
+    DeviceState *dev = DEVICE(obj);
+
+    riscv_init_user_properties(obj);
+
+    riscv_add_satp_mode_properties(obj);
+    riscv_cpu_add_misa_properties(obj);
+
+    riscv_cpu_add_kvm_unavail_prop_array(obj, riscv_cpu_extensions);
+    riscv_cpu_add_kvm_unavail_prop_array(obj, riscv_cpu_vendor_exts);
+    riscv_cpu_add_kvm_unavail_prop_array(obj, riscv_cpu_experimental_exts);
+
+    for (Property *prop = riscv_cpu_options; prop && prop->name; prop++) {
+        /* Check if we have a specific KVM handler for the option */
+        if (object_property_find(obj, prop->name)) {
+            continue;
+        }
+        qdev_property_add_static(dev, prop);
+    }
+}
+
+static void kvm_cpu_accel_class_init(ObjectClass *oc, void *data)
+{
+    AccelCPUClass *acc = ACCEL_CPU_CLASS(oc);
+
+    acc->cpu_instance_init = kvm_cpu_instance_init;
+}
+
+static const TypeInfo kvm_cpu_accel_type_info = {
+    .name = ACCEL_CPU_NAME("kvm"),
+
+    .parent = TYPE_ACCEL_CPU,
+    .class_init = kvm_cpu_accel_class_init,
+    .abstract = true,
+};
+static void kvm_cpu_accel_register_types(void)
+{
+    type_register_static(&kvm_cpu_accel_type_info);
+}
+type_init(kvm_cpu_accel_register_types);
diff --git a/target/riscv/kvm_riscv.h b/target/riscv/kvm_riscv.h
index 81e08b8359..a0ea1a7505 100644
--- a/target/riscv/kvm_riscv.h
+++ b/target/riscv/kvm_riscv.h
@@ -19,7 +19,6 @@
 #ifndef QEMU_KVM_RISCV_H
 #define QEMU_KVM_RISCV_H
 
-void kvm_riscv_cpu_add_kvm_properties(Object *obj);
 void kvm_riscv_reset_vcpu(RISCVCPU *cpu);
 void kvm_riscv_set_irq(RISCVCPU *cpu, int irq, int level);
 void kvm_riscv_aia_create(MachineState *machine, uint64_t group_shift,
-- 
2.41.0



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

* [PATCH 12/20] target/riscv: move KVM only files to kvm subdir
  2023-08-25 13:08 [PATCH 00/20] riscv: split TCG/KVM accelerators from cpu.c Daniel Henrique Barboza
                   ` (10 preceding siblings ...)
  2023-08-25 13:08 ` [PATCH 11/20] target/riscv: introduce KVM AccelCPUClass Daniel Henrique Barboza
@ 2023-08-25 13:08 ` Daniel Henrique Barboza
  2023-08-28 16:47   ` Philippe Mathieu-Daudé
  2023-08-31 11:30   ` Andrew Jones
  2023-08-25 13:08 ` [PATCH 13/20] target/riscv/kvm: refactor kvm_riscv_init_user_properties() Daniel Henrique Barboza
                   ` (7 subsequent siblings)
  19 siblings, 2 replies; 51+ messages in thread
From: Daniel Henrique Barboza @ 2023-08-25 13:08 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-riscv, alistair.francis, bmeng, liweiwei, zhiwei_liu,
	palmer, Daniel Henrique Barboza

Move the files to a 'kvm' dir to promote more code separation between
accelerators and making our lives easier supporting build options such
as --disable-tcg.

Rename kvm.c to kvm-cpu.c to keep it in line with its TCG counterpart.

Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
---
 hw/riscv/virt.c                       | 2 +-
 target/riscv/cpu.c                    | 2 +-
 target/riscv/{kvm.c => kvm/kvm-cpu.c} | 0
 target/riscv/{ => kvm}/kvm-stub.c     | 0
 target/riscv/{ => kvm}/kvm_riscv.h    | 0
 target/riscv/kvm/meson.build          | 2 ++
 target/riscv/meson.build              | 2 +-
 7 files changed, 5 insertions(+), 3 deletions(-)
 rename target/riscv/{kvm.c => kvm/kvm-cpu.c} (100%)
 rename target/riscv/{ => kvm}/kvm-stub.c (100%)
 rename target/riscv/{ => kvm}/kvm_riscv.h (100%)
 create mode 100644 target/riscv/kvm/meson.build

diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index 388e52a294..77c384ddc3 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -35,7 +35,7 @@
 #include "hw/riscv/virt.h"
 #include "hw/riscv/boot.h"
 #include "hw/riscv/numa.h"
-#include "kvm_riscv.h"
+#include "kvm/kvm_riscv.h"
 #include "hw/intc/riscv_aclint.h"
 #include "hw/intc/riscv_aplic.h"
 #include "hw/intc/riscv_imsic.h"
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 04c6bfaeef..bf6c8519b1 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -33,7 +33,7 @@
 #include "fpu/softfloat-helpers.h"
 #include "sysemu/kvm.h"
 #include "sysemu/tcg.h"
-#include "kvm_riscv.h"
+#include "kvm/kvm_riscv.h"
 #include "tcg/tcg.h"
 
 /* RISC-V CPU definitions */
diff --git a/target/riscv/kvm.c b/target/riscv/kvm/kvm-cpu.c
similarity index 100%
rename from target/riscv/kvm.c
rename to target/riscv/kvm/kvm-cpu.c
diff --git a/target/riscv/kvm-stub.c b/target/riscv/kvm/kvm-stub.c
similarity index 100%
rename from target/riscv/kvm-stub.c
rename to target/riscv/kvm/kvm-stub.c
diff --git a/target/riscv/kvm_riscv.h b/target/riscv/kvm/kvm_riscv.h
similarity index 100%
rename from target/riscv/kvm_riscv.h
rename to target/riscv/kvm/kvm_riscv.h
diff --git a/target/riscv/kvm/meson.build b/target/riscv/kvm/meson.build
new file mode 100644
index 0000000000..1cd6783894
--- /dev/null
+++ b/target/riscv/kvm/meson.build
@@ -0,0 +1,2 @@
+riscv_ss.add(when: 'CONFIG_KVM', if_true: files('kvm-cpu.c'),
+                                 if_false: files('kvm-stub.c'))
diff --git a/target/riscv/meson.build b/target/riscv/meson.build
index f0486183fa..c53962215f 100644
--- a/target/riscv/meson.build
+++ b/target/riscv/meson.build
@@ -24,7 +24,6 @@ riscv_ss.add(files(
   'zce_helper.c',
   'vcrypto_helper.c'
 ))
-riscv_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c'), if_false: files('kvm-stub.c'))
 
 riscv_system_ss = ss.source_set()
 riscv_system_ss.add(files(
@@ -39,6 +38,7 @@ riscv_system_ss.add(files(
 ))
 
 subdir('tcg')
+subdir('kvm')
 
 target_arch += {'riscv': riscv_ss}
 target_softmmu_arch += {'riscv': riscv_system_ss}
-- 
2.41.0



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

* [PATCH 13/20] target/riscv/kvm: refactor kvm_riscv_init_user_properties()
  2023-08-25 13:08 [PATCH 00/20] riscv: split TCG/KVM accelerators from cpu.c Daniel Henrique Barboza
                   ` (11 preceding siblings ...)
  2023-08-25 13:08 ` [PATCH 12/20] target/riscv: move KVM only files to kvm subdir Daniel Henrique Barboza
@ 2023-08-25 13:08 ` Daniel Henrique Barboza
  2023-08-31 11:34   ` Andrew Jones
  2023-08-25 13:08 ` [PATCH 14/20] target/riscv/kvm: do not use riscv_cpu_add_misa_properties() Daniel Henrique Barboza
                   ` (6 subsequent siblings)
  19 siblings, 1 reply; 51+ messages in thread
From: Daniel Henrique Barboza @ 2023-08-25 13:08 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-riscv, alistair.francis, bmeng, liweiwei, zhiwei_liu,
	palmer, Daniel Henrique Barboza

The function is doing way more than just init user properties. We would
also like to use the 'user_extension_properties' class property, as the
TCG driver is already using, to decide whether KVM should expose user
properties or not.

Rename kvm_riscv_init_user_properties() to riscv_init_kvm_registers()
and leave only the essential, non-optional KVM init functions there. All
functions that deals with property handling is now gated via
rcc->user_extension_properties.

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

diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c
index 3c4fa43cee..85e8b0a927 100644
--- a/target/riscv/kvm/kvm-cpu.c
+++ b/target/riscv/kvm/kvm-cpu.c
@@ -792,7 +792,7 @@ static void kvm_riscv_init_multiext_cfg(RISCVCPU *cpu, KVMScratchCPU *kvmcpu)
     }
 }
 
-static void riscv_init_user_properties(Object *cpu_obj)
+static void riscv_init_kvm_registers(Object *cpu_obj)
 {
     RISCVCPU *cpu = RISCV_CPU(cpu_obj);
     KVMScratchCPU kvmcpu;
@@ -801,7 +801,6 @@ static void riscv_init_user_properties(Object *cpu_obj)
         return;
     }
 
-    kvm_riscv_add_cpu_user_properties(cpu_obj);
     kvm_riscv_init_machine_ids(cpu, &kvmcpu);
     kvm_riscv_init_misa_ext_mask(cpu, &kvmcpu);
     kvm_riscv_init_multiext_cfg(cpu, &kvmcpu);
@@ -1295,16 +1294,20 @@ DEFINE_TYPES(riscv_kvm_cpu_type_infos)
 static void kvm_cpu_instance_init(CPUState *cs)
 {
     Object *obj = OBJECT(RISCV_CPU(cs));
+    RISCVCPUClass *rcc = RISCV_CPU_GET_CLASS(obj);
     DeviceState *dev = DEVICE(obj);
 
-    riscv_init_user_properties(obj);
+    riscv_init_kvm_registers(obj);
 
-    riscv_add_satp_mode_properties(obj);
-    riscv_cpu_add_misa_properties(obj);
+    if (rcc->user_extension_properties) {
+        kvm_riscv_add_cpu_user_properties(obj);
+        riscv_add_satp_mode_properties(obj);
+        riscv_cpu_add_misa_properties(obj);
 
-    riscv_cpu_add_kvm_unavail_prop_array(obj, riscv_cpu_extensions);
-    riscv_cpu_add_kvm_unavail_prop_array(obj, riscv_cpu_vendor_exts);
-    riscv_cpu_add_kvm_unavail_prop_array(obj, riscv_cpu_experimental_exts);
+        riscv_cpu_add_kvm_unavail_prop_array(obj, riscv_cpu_extensions);
+        riscv_cpu_add_kvm_unavail_prop_array(obj, riscv_cpu_vendor_exts);
+        riscv_cpu_add_kvm_unavail_prop_array(obj, riscv_cpu_experimental_exts);
+    }
 
     for (Property *prop = riscv_cpu_options; prop && prop->name; prop++) {
         /* Check if we have a specific KVM handler for the option */
-- 
2.41.0



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

* [PATCH 14/20] target/riscv/kvm: do not use riscv_cpu_add_misa_properties()
  2023-08-25 13:08 [PATCH 00/20] riscv: split TCG/KVM accelerators from cpu.c Daniel Henrique Barboza
                   ` (12 preceding siblings ...)
  2023-08-25 13:08 ` [PATCH 13/20] target/riscv/kvm: refactor kvm_riscv_init_user_properties() Daniel Henrique Barboza
@ 2023-08-25 13:08 ` Daniel Henrique Barboza
  2023-08-31 11:50   ` Andrew Jones
  2023-08-25 13:08 ` [PATCH 15/20] target/riscv/tcg: introduce tcg_cpu_instance_init() Daniel Henrique Barboza
                   ` (5 subsequent siblings)
  19 siblings, 1 reply; 51+ messages in thread
From: Daniel Henrique Barboza @ 2023-08-25 13:08 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-riscv, alistair.francis, bmeng, liweiwei, zhiwei_liu,
	palmer, Daniel Henrique Barboza

riscv_cpu_add_misa_properties() is being used to fill the missing KVM
MISA properties but it is a TCG helper that was adapted to do so. We'll
move it to tcg-cpu.c in the next patches, meaning that KVM needs to fill
the remaining MISA properties on its own.

Do not use riscv_cpu_add_misa_properties(). Let's create a new array
with all available MISA bits we support that can be read by KVM. Then,
inside kvm_riscv_add_cpu_user_properties(), we'll create all KVM MISA
properties as usual and then use this array to add any missing MISA
properties with the riscv_cpu_add_kvm_unavail_prop() helper.

Note that we're creating misa_bits[], and not using the existing
'riscv_single_letter_exts[]', because the latter is tuned for riscv,isa
related functions and it doesn't have all MISA bits we support. Commit
0e2c377023 ("target/riscv: misa to ISA string conversion fix") has the
full context.

While we're at it, move both satp and the multi-letter extension
properties to kvm_riscv_add_cpu_user_properties() as well.

Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
---
 target/riscv/cpu.c         |  2 ++
 target/riscv/cpu.h         |  3 ++-
 target/riscv/kvm/kvm-cpu.c | 17 +++++++++++------
 3 files changed, 15 insertions(+), 7 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index bf6c8519b1..f9aea6a80a 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -38,6 +38,8 @@
 
 /* RISC-V CPU definitions */
 static const char riscv_single_letter_exts[] = "IEMAFDQCPVH";
+const uint32_t misa_bits[] = {RVI, RVE, RVM, RVA, RVF, RVD, RVV,
+                              RVC, RVS, RVU, RVH, RVJ, RVG};
 
 struct isa_ext_data {
     const char *name;
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 950c2301f2..9ec3b98bd2 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -43,7 +43,7 @@
 #define RV(x) ((target_ulong)1 << (x - 'A'))
 
 /*
- * Consider updating misa_ext_info_arr[] and misa_ext_cfgs[]
+ * Update misa_bits[], misa_ext_info_arr[] and misa_ext_cfgs[]
  * when adding new MISA bits here.
  */
 #define RVI RV('I')
@@ -60,6 +60,7 @@
 #define RVJ RV('J')
 #define RVG RV('G')
 
+extern const uint32_t misa_bits[13];
 const char *riscv_get_misa_ext_name(uint32_t bit);
 const char *riscv_get_misa_ext_description(uint32_t bit);
 
diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c
index 85e8b0a927..501384924b 100644
--- a/target/riscv/kvm/kvm-cpu.c
+++ b/target/riscv/kvm/kvm-cpu.c
@@ -387,6 +387,8 @@ static void kvm_riscv_add_cpu_user_properties(Object *cpu_obj)
 {
     int i;
 
+    riscv_add_satp_mode_properties(cpu_obj);
+
     for (i = 0; i < ARRAY_SIZE(kvm_misa_ext_cfgs); i++) {
         KVMCPUConfig *misa_cfg = &kvm_misa_ext_cfgs[i];
         int bit = misa_cfg->offset;
@@ -402,6 +404,11 @@ static void kvm_riscv_add_cpu_user_properties(Object *cpu_obj)
                                         misa_cfg->description);
     }
 
+    for (i = 0; i < ARRAY_SIZE(misa_bits); i++) {
+        const char *ext_name = riscv_get_misa_ext_name(misa_bits[i]);
+        riscv_cpu_add_kvm_unavail_prop(cpu_obj, ext_name);
+    }
+
     for (i = 0; i < ARRAY_SIZE(kvm_multi_ext_cfgs); i++) {
         KVMCPUConfig *multi_cfg = &kvm_multi_ext_cfgs[i];
 
@@ -418,6 +425,10 @@ static void kvm_riscv_add_cpu_user_properties(Object *cpu_obj)
     object_property_add(cpu_obj, "cboz_blocksize", "uint16",
                         NULL, kvm_cpu_set_cbomz_blksize,
                         NULL, &kvm_cboz_blocksize);
+
+    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);
 }
 
 static int kvm_riscv_get_regs_core(CPUState *cs)
@@ -1301,12 +1312,6 @@ static void kvm_cpu_instance_init(CPUState *cs)
 
     if (rcc->user_extension_properties) {
         kvm_riscv_add_cpu_user_properties(obj);
-        riscv_add_satp_mode_properties(obj);
-        riscv_cpu_add_misa_properties(obj);
-
-        riscv_cpu_add_kvm_unavail_prop_array(obj, riscv_cpu_extensions);
-        riscv_cpu_add_kvm_unavail_prop_array(obj, riscv_cpu_vendor_exts);
-        riscv_cpu_add_kvm_unavail_prop_array(obj, riscv_cpu_experimental_exts);
     }
 
     for (Property *prop = riscv_cpu_options; prop && prop->name; prop++) {
-- 
2.41.0



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

* [PATCH 15/20] target/riscv/tcg: introduce tcg_cpu_instance_init()
  2023-08-25 13:08 [PATCH 00/20] riscv: split TCG/KVM accelerators from cpu.c Daniel Henrique Barboza
                   ` (13 preceding siblings ...)
  2023-08-25 13:08 ` [PATCH 14/20] target/riscv/kvm: do not use riscv_cpu_add_misa_properties() Daniel Henrique Barboza
@ 2023-08-25 13:08 ` Daniel Henrique Barboza
  2023-08-31 11:56   ` Andrew Jones
  2023-08-25 13:08 ` [PATCH 16/20] target/riscv/tcg: move riscv_cpu_add_misa_properties() to tcg-cpu.c Daniel Henrique Barboza
                   ` (4 subsequent siblings)
  19 siblings, 1 reply; 51+ messages in thread
From: Daniel Henrique Barboza @ 2023-08-25 13:08 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-riscv, alistair.francis, bmeng, liweiwei, zhiwei_liu,
	palmer, Daniel Henrique Barboza

tcg_cpu_instance_init() will be the 'cpu_instance_init' impl for the TCG
accelerator. It'll be called from within riscv_cpu_post_init(), via
accel_cpu_instance_init(), similar to what happens with KVM. In fact, to
preserve behavior, the implementation will be similar to what
riscv_cpu_post_init() already does.

In this patch we'll move riscv_cpu_add_user_properties() and
riscv_init_max_cpu_extensions() and all their dependencies to tcg-cpu.c.
All multi-extension properties code was moved. The 'multi_ext_user_opts'
hash table was also moved to tcg-cpu.c since it's a TCG only structure,
meaning that we won't have to worry about initializing a TCG hash table
when running a KVM CPU anymore.

riscv_cpu_add_user_properties() will remain in cpu.c for now due to how
much code it requires to be moved at the same time. We'll do that in the
next patch.

Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
---
 target/riscv/cpu.c         | 141 +------------------------------------
 target/riscv/cpu.h         |   2 +-
 target/riscv/tcg/tcg-cpu.c | 138 ++++++++++++++++++++++++++++++++++++
 3 files changed, 140 insertions(+), 141 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index f9aea6a80a..89b09a7e89 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -162,9 +162,6 @@ static const struct isa_ext_data isa_edata_arr[] = {
     ISA_EXT_DATA_ENTRY(xventanacondops, PRIV_VERSION_1_12_0, ext_XVentanaCondOps),
 };
 
-/* Hash that stores user set extensions */
-static GHashTable *multi_ext_user_opts;
-
 bool isa_ext_is_enabled(RISCVCPU *cpu, uint32_t ext_offset)
 {
     bool *ext_enabled = (void *)&cpu->cfg + ext_offset;
@@ -195,12 +192,6 @@ int cpu_cfg_ext_get_min_version(uint32_t ext_offset)
     return PRIV_VERSION_1_10_0;
 }
 
-bool cpu_cfg_ext_is_user_set(uint32_t ext_offset)
-{
-    return g_hash_table_contains(multi_ext_user_opts,
-                                 GUINT_TO_POINTER(ext_offset));
-}
-
 const char * const riscv_int_regnames[] = {
     "x0/zero", "x1/ra",  "x2/sp",  "x3/gp",  "x4/tp",  "x5/t0",   "x6/t1",
     "x7/t2",   "x8/s0",  "x9/s1",  "x10/a0", "x11/a1", "x12/a2",  "x13/a3",
@@ -281,9 +272,6 @@ static const char * const riscv_intr_names[] = {
     "reserved"
 };
 
-static void riscv_cpu_add_user_properties(Object *obj);
-static void riscv_init_max_cpu_extensions(Object *obj);
-
 const char *riscv_cpu_get_trap_name(target_ulong cause, bool async)
 {
     if (async) {
@@ -295,7 +283,7 @@ const char *riscv_cpu_get_trap_name(target_ulong cause, bool async)
     }
 }
 
-static void set_misa(CPURISCVState *env, RISCVMXL mxl, uint32_t ext)
+void set_misa(CPURISCVState *env, RISCVMXL mxl, uint32_t ext)
 {
     env->misa_mxl_max = env->misa_mxl = mxl;
     env->misa_ext_mask = env->misa_ext = ext;
@@ -1198,18 +1186,7 @@ static void riscv_cpu_set_irq(void *opaque, int irq, int level)
 
 static void riscv_cpu_post_init(Object *obj)
 {
-    RISCVCPU *cpu = RISCV_CPU(obj);
-    RISCVCPUClass *rcc = RISCV_CPU_GET_CLASS(cpu);
-
     accel_cpu_instance_init(CPU(obj));
-
-    if (rcc->user_extension_properties) {
-        riscv_cpu_add_user_properties(obj);
-    }
-
-    if (cpu->cfg.max_features) {
-        riscv_init_max_cpu_extensions(obj);
-    }
 }
 
 static void riscv_cpu_init(Object *obj)
@@ -1222,8 +1199,6 @@ static void riscv_cpu_init(Object *obj)
     qdev_init_gpio_in(DEVICE(cpu), riscv_cpu_set_irq,
                       IRQ_LOCAL_MAX + IRQ_LOCAL_GUEST_MAX);
 #endif /* CONFIG_USER_ONLY */
-
-    multi_ext_user_opts = g_hash_table_new(NULL, g_direct_equal);
 }
 
 typedef struct RISCVCPUMisaExtConfig {
@@ -1503,120 +1478,6 @@ Property riscv_cpu_options[] = {
     DEFINE_PROP_END_OF_LIST(),
 };
 
-static void cpu_set_multi_ext_cfg(Object *obj, Visitor *v, const char *name,
-                                  void *opaque, Error **errp)
-{
-    const RISCVCPUMultiExtConfig *multi_ext_cfg = opaque;
-    bool value;
-
-    if (!visit_type_bool(v, name, &value, errp)) {
-        return;
-    }
-
-    isa_ext_update_enabled(RISCV_CPU(obj), multi_ext_cfg->offset, value);
-
-    g_hash_table_insert(multi_ext_user_opts,
-                        GUINT_TO_POINTER(multi_ext_cfg->offset),
-                        (gpointer)value);
-}
-
-static void cpu_get_multi_ext_cfg(Object *obj, Visitor *v, const char *name,
-                                  void *opaque, Error **errp)
-{
-    const RISCVCPUMultiExtConfig *multi_ext_cfg = opaque;
-    bool value = isa_ext_is_enabled(RISCV_CPU(obj), multi_ext_cfg->offset);
-
-    visit_type_bool(v, name, &value, errp);
-}
-
-static void cpu_add_multi_ext_prop(Object *cpu_obj,
-                                   const RISCVCPUMultiExtConfig *multi_cfg)
-{
-    object_property_add(cpu_obj, multi_cfg->name, "bool",
-                        cpu_get_multi_ext_cfg,
-                        cpu_set_multi_ext_cfg,
-                        NULL, (void *)multi_cfg);
-
-    /*
-     * Set def val directly instead of using
-     * object_property_set_bool() to save the set()
-     * callback hash for user inputs.
-     */
-    isa_ext_update_enabled(RISCV_CPU(cpu_obj), multi_cfg->offset,
-                           multi_cfg->enabled);
-}
-
-static void riscv_cpu_add_multiext_prop_array(Object *obj,
-                                        const RISCVCPUMultiExtConfig *array)
-{
-    const RISCVCPUMultiExtConfig *prop;
-
-    for (prop = array; prop && prop->name; prop++) {
-        cpu_add_multi_ext_prop(obj, prop);
-    }
-}
-
-/*
- * Add CPU properties with user-facing flags.
- *
- * This will overwrite existing env->misa_ext values with the
- * defaults set via riscv_cpu_add_misa_properties().
- */
-static void riscv_cpu_add_user_properties(Object *obj)
-{
-#ifndef CONFIG_USER_ONLY
-    if (kvm_enabled()) {
-        return;
-    }
-    riscv_add_satp_mode_properties(obj);
-#endif
-
-    riscv_cpu_add_misa_properties(obj);
-
-    riscv_cpu_add_multiext_prop_array(obj, riscv_cpu_extensions);
-    riscv_cpu_add_multiext_prop_array(obj, riscv_cpu_vendor_exts);
-    riscv_cpu_add_multiext_prop_array(obj, riscv_cpu_experimental_exts);
-
-    for (Property *prop = riscv_cpu_options; prop && prop->name; prop++) {
-        qdev_property_add_static(DEVICE(obj), prop);
-    }
-}
-
-/*
- * The 'max' type CPU will have all possible ratified
- * non-vendor extensions enabled.
- */
-static void riscv_init_max_cpu_extensions(Object *obj)
-{
-    RISCVCPU *cpu = RISCV_CPU(obj);
-    CPURISCVState *env = &cpu->env;
-    const RISCVCPUMultiExtConfig *prop;
-
-    /* Enable RVG, RVJ and RVV that are disabled by default */
-    set_misa(env, env->misa_mxl, env->misa_ext | RVG | RVJ | RVV);
-
-    for (prop = riscv_cpu_extensions; prop && prop->name; prop++) {
-        isa_ext_update_enabled(cpu, prop->offset, true);
-    }
-
-    /* set vector version */
-    env->vext_ver = VEXT_VERSION_1_00_0;
-
-    /* Zfinx is not compatible with F. Disable it */
-    isa_ext_update_enabled(cpu, CPU_CFG_OFFSET(ext_zfinx), false);
-    isa_ext_update_enabled(cpu, CPU_CFG_OFFSET(ext_zdinx), false);
-    isa_ext_update_enabled(cpu, CPU_CFG_OFFSET(ext_zhinx), false);
-    isa_ext_update_enabled(cpu, CPU_CFG_OFFSET(ext_zhinxmin), false);
-
-    isa_ext_update_enabled(cpu, CPU_CFG_OFFSET(ext_zce), false);
-    isa_ext_update_enabled(cpu, CPU_CFG_OFFSET(ext_zcmp), false);
-    isa_ext_update_enabled(cpu, CPU_CFG_OFFSET(ext_zcmt), false);
-
-    if (env->misa_mxl != MXL_RV32) {
-        isa_ext_update_enabled(cpu, CPU_CFG_OFFSET(ext_zcf), false);
-    }
-}
-
 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 9ec3b98bd2..74fbb33e09 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -710,9 +710,9 @@ enum riscv_pmu_event_idx {
 
 /* used by tcg/tcg-cpu.c*/
 void isa_ext_update_enabled(RISCVCPU *cpu, uint32_t ext_offset, bool en);
-bool cpu_cfg_ext_is_user_set(uint32_t ext_offset);
 bool isa_ext_is_enabled(RISCVCPU *cpu, uint32_t ext_offset);
 int cpu_cfg_ext_get_min_version(uint32_t ext_offset);
+void set_misa(CPURISCVState *env, RISCVMXL mxl, uint32_t ext);
 void riscv_cpu_disable_priv_spec_isa_exts(RISCVCPU *cpu);
 
 typedef struct RISCVCPUMultiExtConfig {
diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
index 2024c98793..68ce3cbcb9 100644
--- a/target/riscv/tcg/tcg-cpu.c
+++ b/target/riscv/tcg/tcg-cpu.c
@@ -23,12 +23,22 @@
 #include "pmu.h"
 #include "time_helper.h"
 #include "qapi/error.h"
+#include "qapi/visitor.h"
 #include "qemu/accel.h"
 #include "qemu/error-report.h"
 #include "hw/core/accel-cpu.h"
 #include "hw/core/tcg-cpu-ops.h"
 #include "tcg/tcg.h"
 
+/* Hash that stores user set extensions */
+static GHashTable *multi_ext_user_opts;
+
+static bool cpu_cfg_ext_is_user_set(uint32_t ext_offset)
+{
+    return g_hash_table_contains(multi_ext_user_opts,
+                                 GUINT_TO_POINTER(ext_offset));
+}
+
 static void riscv_cpu_synchronize_from_tb(CPUState *cs,
                                           const TranslationBlock *tb)
 {
@@ -564,6 +574,133 @@ static bool tcg_cpu_realizefn(CPUState *cs, Error **errp)
     return true;
 }
 
+static void cpu_set_multi_ext_cfg(Object *obj, Visitor *v, const char *name,
+                                  void *opaque, Error **errp)
+{
+    const RISCVCPUMultiExtConfig *multi_ext_cfg = opaque;
+    bool value;
+
+    if (!visit_type_bool(v, name, &value, errp)) {
+        return;
+    }
+
+    isa_ext_update_enabled(RISCV_CPU(obj), multi_ext_cfg->offset, value);
+
+    g_hash_table_insert(multi_ext_user_opts,
+                        GUINT_TO_POINTER(multi_ext_cfg->offset),
+                        (gpointer)value);
+}
+
+static void cpu_get_multi_ext_cfg(Object *obj, Visitor *v, const char *name,
+                                  void *opaque, Error **errp)
+{
+    const RISCVCPUMultiExtConfig *multi_ext_cfg = opaque;
+    bool value = isa_ext_is_enabled(RISCV_CPU(obj), multi_ext_cfg->offset);
+
+    visit_type_bool(v, name, &value, errp);
+}
+
+static void cpu_add_multi_ext_prop(Object *cpu_obj,
+                                   const RISCVCPUMultiExtConfig *multi_cfg)
+{
+    object_property_add(cpu_obj, multi_cfg->name, "bool",
+                        cpu_get_multi_ext_cfg,
+                        cpu_set_multi_ext_cfg,
+                        NULL, (void *)multi_cfg);
+
+    /*
+     * Set def val directly instead of using
+     * object_property_set_bool() to save the set()
+     * callback hash for user inputs.
+     */
+    isa_ext_update_enabled(RISCV_CPU(cpu_obj), multi_cfg->offset,
+                           multi_cfg->enabled);
+}
+
+static void riscv_cpu_add_multiext_prop_array(Object *obj,
+                                        const RISCVCPUMultiExtConfig *array)
+{
+    const RISCVCPUMultiExtConfig *prop;
+
+    for (prop = array; prop && prop->name; prop++) {
+        cpu_add_multi_ext_prop(obj, prop);
+    }
+}
+
+/*
+ * Add CPU properties with user-facing flags.
+ *
+ * This will overwrite existing env->misa_ext values with the
+ * defaults set via riscv_cpu_add_misa_properties().
+ */
+static void riscv_cpu_add_user_properties(Object *obj)
+{
+#ifndef CONFIG_USER_ONLY
+    riscv_add_satp_mode_properties(obj);
+#endif
+
+    riscv_cpu_add_misa_properties(obj);
+
+    riscv_cpu_add_multiext_prop_array(obj, riscv_cpu_extensions);
+    riscv_cpu_add_multiext_prop_array(obj, riscv_cpu_vendor_exts);
+    riscv_cpu_add_multiext_prop_array(obj, riscv_cpu_experimental_exts);
+
+    for (Property *prop = riscv_cpu_options; prop && prop->name; prop++) {
+        qdev_property_add_static(DEVICE(obj), prop);
+    }
+}
+
+/*
+ * The 'max' type CPU will have all possible ratified
+ * non-vendor extensions enabled.
+ */
+static void riscv_init_max_cpu_extensions(Object *obj)
+{
+    RISCVCPU *cpu = RISCV_CPU(obj);
+    CPURISCVState *env = &cpu->env;
+    const RISCVCPUMultiExtConfig *prop;
+
+    /* Enable RVG, RVJ and RVV that are disabled by default */
+    set_misa(env, env->misa_mxl, env->misa_ext | RVG | RVJ | RVV);
+
+    for (prop = riscv_cpu_extensions; prop && prop->name; prop++) {
+        isa_ext_update_enabled(cpu, prop->offset, true);
+    }
+
+    /* set vector version */
+    env->vext_ver = VEXT_VERSION_1_00_0;
+
+    /* Zfinx is not compatible with F. Disable it */
+    isa_ext_update_enabled(cpu, CPU_CFG_OFFSET(ext_zfinx), false);
+    isa_ext_update_enabled(cpu, CPU_CFG_OFFSET(ext_zdinx), false);
+    isa_ext_update_enabled(cpu, CPU_CFG_OFFSET(ext_zhinx), false);
+    isa_ext_update_enabled(cpu, CPU_CFG_OFFSET(ext_zhinxmin), false);
+
+    isa_ext_update_enabled(cpu, CPU_CFG_OFFSET(ext_zce), false);
+    isa_ext_update_enabled(cpu, CPU_CFG_OFFSET(ext_zcmp), false);
+    isa_ext_update_enabled(cpu, CPU_CFG_OFFSET(ext_zcmt), false);
+
+    if (env->misa_mxl != MXL_RV32) {
+        isa_ext_update_enabled(cpu, CPU_CFG_OFFSET(ext_zcf), false);
+    }
+}
+
+static void tcg_cpu_instance_init(CPUState *cs)
+{
+    RISCVCPU *cpu = RISCV_CPU(cs);
+    Object *obj = OBJECT(cpu);
+    RISCVCPUClass *rcc = RISCV_CPU_GET_CLASS(obj);
+
+    if (rcc->user_extension_properties) {
+        multi_ext_user_opts = g_hash_table_new(NULL, g_direct_equal);
+        riscv_cpu_add_user_properties(obj);
+    }
+
+    if (cpu->cfg.max_features) {
+        riscv_init_max_cpu_extensions(obj);
+    }
+}
+
 static void tcg_cpu_init_ops(AccelCPUClass *accel_cpu, CPUClass *cc)
 {
     /*
@@ -583,6 +720,7 @@ static void tcg_cpu_accel_class_init(ObjectClass *oc, void *data)
     AccelCPUClass *acc = ACCEL_CPU_CLASS(oc);
 
     acc->cpu_class_init = tcg_cpu_class_init;
+    acc->cpu_instance_init = tcg_cpu_instance_init;
     acc->cpu_realizefn = tcg_cpu_realizefn;
 }
 
-- 
2.41.0



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

* [PATCH 16/20] target/riscv/tcg: move riscv_cpu_add_misa_properties() to tcg-cpu.c
  2023-08-25 13:08 [PATCH 00/20] riscv: split TCG/KVM accelerators from cpu.c Daniel Henrique Barboza
                   ` (14 preceding siblings ...)
  2023-08-25 13:08 ` [PATCH 15/20] target/riscv/tcg: introduce tcg_cpu_instance_init() Daniel Henrique Barboza
@ 2023-08-25 13:08 ` Daniel Henrique Barboza
  2023-08-31 12:01   ` Andrew Jones
  2023-08-25 13:08 ` [PATCH 17/20] target/riscv/cpu.c: export isa_edata_arr[] Daniel Henrique Barboza
                   ` (3 subsequent siblings)
  19 siblings, 1 reply; 51+ messages in thread
From: Daniel Henrique Barboza @ 2023-08-25 13:08 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-riscv, alistair.francis, bmeng, liweiwei, zhiwei_liu,
	palmer, Daniel Henrique Barboza

All code related to MISA TCG properties is also moved.

At this point, all TCG properties handling is done in tcg-cpu.c, all KVM
properties handling is done in kvm-cpu.c.

Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
---
 target/riscv/cpu.c         | 89 --------------------------------------
 target/riscv/cpu.h         |  1 -
 target/riscv/tcg/tcg-cpu.c | 84 +++++++++++++++++++++++++++++++++++
 3 files changed, 84 insertions(+), 90 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 89b09a7e89..3c9db46837 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -1201,49 +1201,6 @@ static void riscv_cpu_init(Object *obj)
 #endif /* CONFIG_USER_ONLY */
 }
 
-typedef struct RISCVCPUMisaExtConfig {
-    const char *name;
-    const char *description;
-    target_ulong misa_bit;
-    bool enabled;
-} RISCVCPUMisaExtConfig;
-
-static void cpu_set_misa_ext_cfg(Object *obj, Visitor *v, const char *name,
-                                 void *opaque, Error **errp)
-{
-    const RISCVCPUMisaExtConfig *misa_ext_cfg = opaque;
-    target_ulong misa_bit = misa_ext_cfg->misa_bit;
-    RISCVCPU *cpu = RISCV_CPU(obj);
-    CPURISCVState *env = &cpu->env;
-    bool value;
-
-    if (!visit_type_bool(v, name, &value, errp)) {
-        return;
-    }
-
-    if (value) {
-        env->misa_ext |= misa_bit;
-        env->misa_ext_mask |= misa_bit;
-    } else {
-        env->misa_ext &= ~misa_bit;
-        env->misa_ext_mask &= ~misa_bit;
-    }
-}
-
-static void cpu_get_misa_ext_cfg(Object *obj, Visitor *v, const char *name,
-                                 void *opaque, Error **errp)
-{
-    const RISCVCPUMisaExtConfig *misa_ext_cfg = opaque;
-    target_ulong misa_bit = misa_ext_cfg->misa_bit;
-    RISCVCPU *cpu = RISCV_CPU(obj);
-    CPURISCVState *env = &cpu->env;
-    bool value;
-
-    value = env->misa_ext & misa_bit;
-
-    visit_type_bool(v, name, &value, errp);
-}
-
 typedef struct misa_ext_info {
     const char *name;
     const char *description;
@@ -1304,52 +1261,6 @@ const char *riscv_get_misa_ext_description(uint32_t bit)
     return val;
 }
 
-#define MISA_CFG(_bit, _enabled) \
-    {.misa_bit = _bit, .enabled = _enabled}
-
-static RISCVCPUMisaExtConfig misa_ext_cfgs[] = {
-    MISA_CFG(RVA, true),
-    MISA_CFG(RVC, true),
-    MISA_CFG(RVD, true),
-    MISA_CFG(RVF, true),
-    MISA_CFG(RVI, true),
-    MISA_CFG(RVE, false),
-    MISA_CFG(RVM, true),
-    MISA_CFG(RVS, true),
-    MISA_CFG(RVU, true),
-    MISA_CFG(RVH, true),
-    MISA_CFG(RVJ, false),
-    MISA_CFG(RVV, false),
-    MISA_CFG(RVG, false),
-};
-
-void riscv_cpu_add_misa_properties(Object *cpu_obj)
-{
-    int i;
-
-    for (i = 0; i < ARRAY_SIZE(misa_ext_cfgs); i++) {
-        RISCVCPUMisaExtConfig *misa_cfg = &misa_ext_cfgs[i];
-        int bit = misa_cfg->misa_bit;
-
-        misa_cfg->name = riscv_get_misa_ext_name(bit);
-        misa_cfg->description = riscv_get_misa_ext_description(bit);
-
-        /* Check if KVM already created the property */
-        if (object_property_find(cpu_obj, misa_cfg->name)) {
-            continue;
-        }
-
-        object_property_add(cpu_obj, misa_cfg->name, "bool",
-                            cpu_get_misa_ext_cfg,
-                            cpu_set_misa_ext_cfg,
-                            NULL, (void *)misa_cfg);
-        object_property_set_description(cpu_obj, misa_cfg->name,
-                                        misa_cfg->description);
-        object_property_set_bool(cpu_obj, misa_cfg->name,
-                                 misa_cfg->enabled, NULL);
-    }
-}
-
 #define MULTI_EXT_CFG_BOOL(_name, _prop, _defval) \
     {.name = _name, .offset = CPU_CFG_OFFSET(_prop), \
      .enabled = _defval}
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 74fbb33e09..4269523e24 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -726,7 +726,6 @@ extern const RISCVCPUMultiExtConfig riscv_cpu_vendor_exts[];
 extern const RISCVCPUMultiExtConfig riscv_cpu_experimental_exts[];
 extern Property riscv_cpu_options[];
 
-void riscv_cpu_add_misa_properties(Object *cpu_obj);
 void riscv_add_satp_mode_properties(Object *obj);
 
 /* CSR function table */
diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
index 68ce3cbcb9..8e3f55d3a6 100644
--- a/target/riscv/tcg/tcg-cpu.c
+++ b/target/riscv/tcg/tcg-cpu.c
@@ -574,6 +574,90 @@ static bool tcg_cpu_realizefn(CPUState *cs, Error **errp)
     return true;
 }
 
+typedef struct RISCVCPUMisaExtConfig {
+    const char *name;
+    const char *description;
+    target_ulong misa_bit;
+    bool enabled;
+} RISCVCPUMisaExtConfig;
+
+static void cpu_set_misa_ext_cfg(Object *obj, Visitor *v, const char *name,
+                                 void *opaque, Error **errp)
+{
+    const RISCVCPUMisaExtConfig *misa_ext_cfg = opaque;
+    target_ulong misa_bit = misa_ext_cfg->misa_bit;
+    RISCVCPU *cpu = RISCV_CPU(obj);
+    CPURISCVState *env = &cpu->env;
+    bool value;
+
+    if (!visit_type_bool(v, name, &value, errp)) {
+        return;
+    }
+
+    if (value) {
+        env->misa_ext |= misa_bit;
+        env->misa_ext_mask |= misa_bit;
+    } else {
+        env->misa_ext &= ~misa_bit;
+        env->misa_ext_mask &= ~misa_bit;
+    }
+}
+
+static void cpu_get_misa_ext_cfg(Object *obj, Visitor *v, const char *name,
+                                 void *opaque, Error **errp)
+{
+    const RISCVCPUMisaExtConfig *misa_ext_cfg = opaque;
+    target_ulong misa_bit = misa_ext_cfg->misa_bit;
+    RISCVCPU *cpu = RISCV_CPU(obj);
+    CPURISCVState *env = &cpu->env;
+    bool value;
+
+    value = env->misa_ext & misa_bit;
+
+    visit_type_bool(v, name, &value, errp);
+}
+
+#define MISA_CFG(_bit, _enabled) \
+    {.misa_bit = _bit, .enabled = _enabled}
+
+static RISCVCPUMisaExtConfig misa_ext_cfgs[] = {
+    MISA_CFG(RVA, true),
+    MISA_CFG(RVC, true),
+    MISA_CFG(RVD, true),
+    MISA_CFG(RVF, true),
+    MISA_CFG(RVI, true),
+    MISA_CFG(RVE, false),
+    MISA_CFG(RVM, true),
+    MISA_CFG(RVS, true),
+    MISA_CFG(RVU, true),
+    MISA_CFG(RVH, true),
+    MISA_CFG(RVJ, false),
+    MISA_CFG(RVV, false),
+    MISA_CFG(RVG, false),
+};
+
+static void riscv_cpu_add_misa_properties(Object *cpu_obj)
+{
+    int i;
+
+    for (i = 0; i < ARRAY_SIZE(misa_ext_cfgs); i++) {
+        RISCVCPUMisaExtConfig *misa_cfg = &misa_ext_cfgs[i];
+        int bit = misa_cfg->misa_bit;
+
+        misa_cfg->name = riscv_get_misa_ext_name(bit);
+        misa_cfg->description = riscv_get_misa_ext_description(bit);
+
+        object_property_add(cpu_obj, misa_cfg->name, "bool",
+                            cpu_get_misa_ext_cfg,
+                            cpu_set_misa_ext_cfg,
+                            NULL, (void *)misa_cfg);
+        object_property_set_description(cpu_obj, misa_cfg->name,
+                                        misa_cfg->description);
+        object_property_set_bool(cpu_obj, misa_cfg->name,
+                                 misa_cfg->enabled, NULL);
+    }
+}
+
 static void cpu_set_multi_ext_cfg(Object *obj, Visitor *v, const char *name,
                                   void *opaque, Error **errp)
 {
-- 
2.41.0



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

* [PATCH 17/20] target/riscv/cpu.c: export isa_edata_arr[]
  2023-08-25 13:08 [PATCH 00/20] riscv: split TCG/KVM accelerators from cpu.c Daniel Henrique Barboza
                   ` (15 preceding siblings ...)
  2023-08-25 13:08 ` [PATCH 16/20] target/riscv/tcg: move riscv_cpu_add_misa_properties() to tcg-cpu.c Daniel Henrique Barboza
@ 2023-08-25 13:08 ` Daniel Henrique Barboza
  2023-08-31 12:06   ` Andrew Jones
  2023-08-25 13:08 ` [PATCH 18/20] target/riscv/cpu: move priv spec functions to tcg-cpu.c Daniel Henrique Barboza
                   ` (2 subsequent siblings)
  19 siblings, 1 reply; 51+ messages in thread
From: Daniel Henrique Barboza @ 2023-08-25 13:08 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-riscv, alistair.francis, bmeng, liweiwei, zhiwei_liu,
	palmer, Daniel Henrique Barboza

This array will be read by the TCG accel class, allowing it to handle
priv spec verifications on its own. The array will remain here in cpu.c
because it's also used by the riscv,isa string function.

To export it we'll make it constant and finish it with an empty element
since ARRAY_SIZE() won't work outside of cpu.c. Get rid of its
ARRAY_SIZE() usage now to alleviate the changes for the next patch.

Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
---
 target/riscv/cpu.c | 47 +++++++++++++++++++++-------------------------
 target/riscv/cpu.h |  7 +++++++
 2 files changed, 28 insertions(+), 26 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 3c9db46837..ac5ad4727c 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -41,15 +41,6 @@ static const char riscv_single_letter_exts[] = "IEMAFDQCPVH";
 const uint32_t misa_bits[] = {RVI, RVE, RVM, RVA, RVF, RVD, RVV,
                               RVC, RVS, RVU, RVH, RVJ, RVG};
 
-struct isa_ext_data {
-    const char *name;
-    int min_version;
-    int ext_enable_offset;
-};
-
-#define ISA_EXT_DATA_ENTRY(_name, _min_ver, _prop) \
-    {#_name, _min_ver, CPU_CFG_OFFSET(_prop)}
-
 /*
  * From vector_helper.c
  * Note that vector data is stored in host-endian 64-bit chunks,
@@ -61,6 +52,9 @@ struct isa_ext_data {
 #define BYTE(x)   (x)
 #endif
 
+#define ISA_EXT_DATA_ENTRY(_name, _min_ver, _prop) \
+    {#_name, _min_ver, CPU_CFG_OFFSET(_prop)}
+
 /*
  * Here are the ordering rules of extension naming defined by RISC-V
  * specification :
@@ -81,7 +75,7 @@ struct isa_ext_data {
  * Single letter extensions are checked in riscv_cpu_validate_misa_priv()
  * instead.
  */
-static const struct isa_ext_data isa_edata_arr[] = {
+const RISCVIsaExtData isa_edata_arr[] = {
     ISA_EXT_DATA_ENTRY(zicbom, PRIV_VERSION_1_12_0, ext_icbom),
     ISA_EXT_DATA_ENTRY(zicboz, PRIV_VERSION_1_12_0, ext_icboz),
     ISA_EXT_DATA_ENTRY(zicond, PRIV_VERSION_1_12_0, ext_zicond),
@@ -160,6 +154,8 @@ static const struct isa_ext_data isa_edata_arr[] = {
     ISA_EXT_DATA_ENTRY(xtheadmempair, PRIV_VERSION_1_11_0, ext_xtheadmempair),
     ISA_EXT_DATA_ENTRY(xtheadsync, PRIV_VERSION_1_11_0, ext_xtheadsync),
     ISA_EXT_DATA_ENTRY(xventanacondops, PRIV_VERSION_1_12_0, ext_XVentanaCondOps),
+
+    DEFINE_PROP_END_OF_LIST(),
 };
 
 bool isa_ext_is_enabled(RISCVCPU *cpu, uint32_t ext_offset)
@@ -178,14 +174,14 @@ void isa_ext_update_enabled(RISCVCPU *cpu, uint32_t ext_offset, bool en)
 
 int cpu_cfg_ext_get_min_version(uint32_t ext_offset)
 {
-    int i;
+    const RISCVIsaExtData *edata;
 
-    for (i = 0; i < ARRAY_SIZE(isa_edata_arr); i++) {
-        if (isa_edata_arr[i].ext_enable_offset != ext_offset) {
+    for (edata = isa_edata_arr; edata && edata->name; edata++) {
+        if (edata->ext_enable_offset != ext_offset) {
             continue;
         }
 
-        return isa_edata_arr[i].min_version;
+        return edata->min_version;
     }
 
     /* Default to oldest priv spec if no match found */
@@ -933,22 +929,21 @@ static void riscv_cpu_disas_set_info(CPUState *s, disassemble_info *info)
 void riscv_cpu_disable_priv_spec_isa_exts(RISCVCPU *cpu)
 {
     CPURISCVState *env = &cpu->env;
-    int i;
+    const RISCVIsaExtData *edata;
 
     /* Force disable extensions if priv spec version does not match */
-    for (i = 0; i < ARRAY_SIZE(isa_edata_arr); i++) {
-        if (isa_ext_is_enabled(cpu, isa_edata_arr[i].ext_enable_offset) &&
-            (env->priv_ver < isa_edata_arr[i].min_version)) {
-            isa_ext_update_enabled(cpu, isa_edata_arr[i].ext_enable_offset,
-                                   false);
+    for (edata = isa_edata_arr; edata && edata->name; edata++) {
+        if (isa_ext_is_enabled(cpu, edata->ext_enable_offset) &&
+            (env->priv_ver < edata->min_version)) {
+            isa_ext_update_enabled(cpu, edata->ext_enable_offset, false);
 #ifndef CONFIG_USER_ONLY
             warn_report("disabling %s extension for hart 0x" TARGET_FMT_lx
                         " because privilege spec version does not match",
-                        isa_edata_arr[i].name, env->mhartid);
+                        edata->name, env->mhartid);
 #else
             warn_report("disabling %s extension because "
                         "privilege spec version does not match",
-                        isa_edata_arr[i].name);
+                        edata->name);
 #endif
         }
     }
@@ -1614,13 +1609,13 @@ static void riscv_cpu_class_init(ObjectClass *c, void *data)
 static void riscv_isa_string_ext(RISCVCPU *cpu, char **isa_str,
                                  int max_str_len)
 {
+    const RISCVIsaExtData *edata;
     char *old = *isa_str;
     char *new = *isa_str;
-    int i;
 
-    for (i = 0; i < ARRAY_SIZE(isa_edata_arr); i++) {
-        if (isa_ext_is_enabled(cpu, isa_edata_arr[i].ext_enable_offset)) {
-            new = g_strconcat(old, "_", isa_edata_arr[i].name, NULL);
+    for (edata = isa_edata_arr; edata && edata->name; edata++) {
+        if (isa_ext_is_enabled(cpu, edata->ext_enable_offset)) {
+            new = g_strconcat(old, "_", edata->name, NULL);
             g_free(old);
             old = new;
         }
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 4269523e24..d9a17df46a 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -726,6 +726,13 @@ extern const RISCVCPUMultiExtConfig riscv_cpu_vendor_exts[];
 extern const RISCVCPUMultiExtConfig riscv_cpu_experimental_exts[];
 extern Property riscv_cpu_options[];
 
+typedef struct isa_ext_data {
+    const char *name;
+    int min_version;
+    int ext_enable_offset;
+} RISCVIsaExtData;
+extern const RISCVIsaExtData isa_edata_arr[];
+
 void riscv_add_satp_mode_properties(Object *obj);
 
 /* CSR function table */
-- 
2.41.0



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

* [PATCH 18/20] target/riscv/cpu: move priv spec functions to tcg-cpu.c
  2023-08-25 13:08 [PATCH 00/20] riscv: split TCG/KVM accelerators from cpu.c Daniel Henrique Barboza
                   ` (16 preceding siblings ...)
  2023-08-25 13:08 ` [PATCH 17/20] target/riscv/cpu.c: export isa_edata_arr[] Daniel Henrique Barboza
@ 2023-08-25 13:08 ` Daniel Henrique Barboza
  2023-08-31 12:07   ` Andrew Jones
  2023-08-25 13:08 ` [PATCH 19/20] target/riscv: add 'tcg_supported' class property Daniel Henrique Barboza
  2023-08-25 13:08 ` [PATCH 20/20] target/riscv: add 'kvm_supported' " Daniel Henrique Barboza
  19 siblings, 1 reply; 51+ messages in thread
From: Daniel Henrique Barboza @ 2023-08-25 13:08 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-riscv, alistair.francis, bmeng, liweiwei, zhiwei_liu,
	palmer, Daniel Henrique Barboza

Priv spec validation is TCG specific. Move it to the TCG accel class.

Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
---
 target/riscv/cpu.c         | 39 --------------------------------------
 target/riscv/cpu.h         |  2 --
 target/riscv/tcg/tcg-cpu.c | 39 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 39 insertions(+), 41 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index ac5ad4727c..6817f94c2c 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -172,22 +172,6 @@ void isa_ext_update_enabled(RISCVCPU *cpu, uint32_t ext_offset, bool en)
     *ext_enabled = en;
 }
 
-int cpu_cfg_ext_get_min_version(uint32_t ext_offset)
-{
-    const RISCVIsaExtData *edata;
-
-    for (edata = isa_edata_arr; edata && edata->name; edata++) {
-        if (edata->ext_enable_offset != ext_offset) {
-            continue;
-        }
-
-        return edata->min_version;
-    }
-
-    /* Default to oldest priv spec if no match found */
-    return PRIV_VERSION_1_10_0;
-}
-
 const char * const riscv_int_regnames[] = {
     "x0/zero", "x1/ra",  "x2/sp",  "x3/gp",  "x4/tp",  "x5/t0",   "x6/t1",
     "x7/t2",   "x8/s0",  "x9/s1",  "x10/a0", "x11/a1", "x12/a2",  "x13/a3",
@@ -926,29 +910,6 @@ static void riscv_cpu_disas_set_info(CPUState *s, disassemble_info *info)
     }
 }
 
-void riscv_cpu_disable_priv_spec_isa_exts(RISCVCPU *cpu)
-{
-    CPURISCVState *env = &cpu->env;
-    const RISCVIsaExtData *edata;
-
-    /* Force disable extensions if priv spec version does not match */
-    for (edata = isa_edata_arr; edata && edata->name; edata++) {
-        if (isa_ext_is_enabled(cpu, edata->ext_enable_offset) &&
-            (env->priv_ver < edata->min_version)) {
-            isa_ext_update_enabled(cpu, edata->ext_enable_offset, false);
-#ifndef CONFIG_USER_ONLY
-            warn_report("disabling %s extension for hart 0x" TARGET_FMT_lx
-                        " because privilege spec version does not match",
-                        edata->name, env->mhartid);
-#else
-            warn_report("disabling %s extension because "
-                        "privilege spec version does not match",
-                        edata->name);
-#endif
-        }
-    }
-}
-
 #ifndef CONFIG_USER_ONLY
 static void riscv_cpu_satp_mode_finalize(RISCVCPU *cpu, Error **errp)
 {
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index d9a17df46a..4254f04684 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -711,9 +711,7 @@ enum riscv_pmu_event_idx {
 /* used by tcg/tcg-cpu.c*/
 void isa_ext_update_enabled(RISCVCPU *cpu, uint32_t ext_offset, bool en);
 bool isa_ext_is_enabled(RISCVCPU *cpu, uint32_t ext_offset);
-int cpu_cfg_ext_get_min_version(uint32_t ext_offset);
 void set_misa(CPURISCVState *env, RISCVMXL mxl, uint32_t ext);
-void riscv_cpu_disable_priv_spec_isa_exts(RISCVCPU *cpu);
 
 typedef struct RISCVCPUMultiExtConfig {
     const char *name;
diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
index 8e3f55d3a6..6c91978920 100644
--- a/target/riscv/tcg/tcg-cpu.c
+++ b/target/riscv/tcg/tcg-cpu.c
@@ -97,6 +97,22 @@ const struct TCGCPUOps riscv_tcg_ops = {
 #endif /* !CONFIG_USER_ONLY */
 };
 
+static int cpu_cfg_ext_get_min_version(uint32_t ext_offset)
+{
+    const RISCVIsaExtData *edata;
+
+    for (edata = isa_edata_arr; edata && edata->name; edata++) {
+        if (edata->ext_enable_offset != ext_offset) {
+            continue;
+        }
+
+        return edata->min_version;
+    }
+
+    /* Default to oldest priv spec if no match found */
+    return PRIV_VERSION_1_10_0;
+}
+
 static void cpu_cfg_ext_auto_update(RISCVCPU *cpu, uint32_t ext_offset,
                                     bool value)
 {
@@ -220,6 +236,29 @@ static void riscv_cpu_validate_v(CPURISCVState *env, RISCVCPUConfig *cfg,
     }
 }
 
+static void riscv_cpu_disable_priv_spec_isa_exts(RISCVCPU *cpu)
+{
+    CPURISCVState *env = &cpu->env;
+    const RISCVIsaExtData *edata;
+
+    /* Force disable extensions if priv spec version does not match */
+    for (edata = isa_edata_arr; edata && edata->name; edata++) {
+        if (isa_ext_is_enabled(cpu, edata->ext_enable_offset) &&
+            (env->priv_ver < edata->min_version)) {
+            isa_ext_update_enabled(cpu, edata->ext_enable_offset, false);
+#ifndef CONFIG_USER_ONLY
+            warn_report("disabling %s extension for hart 0x" TARGET_FMT_lx
+                        " because privilege spec version does not match",
+                        edata->name, env->mhartid);
+#else
+            warn_report("disabling %s extension because "
+                        "privilege spec version does not match",
+                        edata->name);
+#endif
+        }
+    }
+}
+
 /*
  * Check consistency between chosen extensions while setting
  * cpu->cfg accordingly.
-- 
2.41.0



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

* [PATCH 19/20] target/riscv: add 'tcg_supported' class property
  2023-08-25 13:08 [PATCH 00/20] riscv: split TCG/KVM accelerators from cpu.c Daniel Henrique Barboza
                   ` (17 preceding siblings ...)
  2023-08-25 13:08 ` [PATCH 18/20] target/riscv/cpu: move priv spec functions to tcg-cpu.c Daniel Henrique Barboza
@ 2023-08-25 13:08 ` Daniel Henrique Barboza
  2023-08-31 12:25   ` Andrew Jones
  2023-08-25 13:08 ` [PATCH 20/20] target/riscv: add 'kvm_supported' " Daniel Henrique Barboza
  19 siblings, 1 reply; 51+ messages in thread
From: Daniel Henrique Barboza @ 2023-08-25 13:08 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-riscv, alistair.francis, bmeng, liweiwei, zhiwei_liu,
	palmer, Daniel Henrique Barboza

This property indicates if a CPU supports TCG acceleration. All CPUs but
the 'host' CPU supports it.

The error in tcg_cpu_realizefn() can now be made generic in case more
non-TCG CPUs are added in the future.

Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
---
 target/riscv/cpu-qom.h     |  1 +
 target/riscv/cpu.c         | 10 ++++++++++
 target/riscv/cpu.h         |  1 +
 target/riscv/tcg/tcg-cpu.c |  7 +++++--
 4 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/target/riscv/cpu-qom.h b/target/riscv/cpu-qom.h
index 7c76dc0dcc..e86b76f9fe 100644
--- a/target/riscv/cpu-qom.h
+++ b/target/riscv/cpu-qom.h
@@ -71,5 +71,6 @@ struct RISCVCPUClass {
     ResettablePhases parent_phases;
 
     bool user_extension_properties;
+    bool tcg_supported;
 };
 #endif /* RISCV_CPU_QOM_H */
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 6817f94c2c..f749ea2a2e 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -625,6 +625,14 @@ static void rv32_imafcu_nommu_cpu_init(Object *obj)
 }
 #endif
 
+char *riscv_cpu_get_name(RISCVCPUClass *rcc)
+{
+    const char *typename = object_class_get_name(OBJECT_CLASS(rcc));
+
+    return g_strndup(typename,
+                     strlen(typename) - strlen("-" TYPE_RISCV_CPU));
+}
+
 static ObjectClass *riscv_cpu_class_by_name(const char *cpu_model)
 {
     ObjectClass *oc;
@@ -1637,6 +1645,7 @@ static void riscv_dynamic_cpu_class_init(ObjectClass *c, void *data)
     RISCVCPUClass *rcc = RISCV_CPU_CLASS(c);
 
     rcc->user_extension_properties = true;
+    rcc->tcg_supported = true;
 }
 
 static void riscv_vendor_cpu_class_init(ObjectClass *c, void *data)
@@ -1644,6 +1653,7 @@ static void riscv_vendor_cpu_class_init(ObjectClass *c, void *data)
     RISCVCPUClass *rcc = RISCV_CPU_CLASS(c);
 
     rcc->user_extension_properties = false;
+    rcc->tcg_supported = true;
 }
 
 #define DEFINE_DYNAMIC_CPU(type_name, initfn) \
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 4254f04684..1e6ecf52ee 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -732,6 +732,7 @@ typedef struct isa_ext_data {
 extern const RISCVIsaExtData isa_edata_arr[];
 
 void riscv_add_satp_mode_properties(Object *obj);
+char *riscv_cpu_get_name(RISCVCPUClass *rcc);
 
 /* CSR function table */
 extern riscv_csr_operations csr_ops[CSR_TABLE_SIZE];
diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
index 6c91978920..a13796c597 100644
--- a/target/riscv/tcg/tcg-cpu.c
+++ b/target/riscv/tcg/tcg-cpu.c
@@ -554,11 +554,14 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp)
 static bool tcg_cpu_realizefn(CPUState *cs, Error **errp)
 {
     RISCVCPU *cpu = RISCV_CPU(cs);
+    RISCVCPUClass *rcc = RISCV_CPU_GET_CLASS(cpu);
     CPURISCVState *env = &cpu->env;
     Error *local_err = NULL;
 
-    if (object_dynamic_cast(OBJECT(cpu), TYPE_RISCV_CPU_HOST)) {
-        error_setg(errp, "'host' CPU is not compatible with TCG acceleration");
+    if (!rcc->tcg_supported) {
+        g_autofree char *name = riscv_cpu_get_name(rcc);
+        error_setg(errp, "'%s' CPU is not compatible with TCG acceleration",
+                   name);
         return false;
     }
 
-- 
2.41.0



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

* [PATCH 20/20] target/riscv: add 'kvm_supported' class property
  2023-08-25 13:08 [PATCH 00/20] riscv: split TCG/KVM accelerators from cpu.c Daniel Henrique Barboza
                   ` (18 preceding siblings ...)
  2023-08-25 13:08 ` [PATCH 19/20] target/riscv: add 'tcg_supported' class property Daniel Henrique Barboza
@ 2023-08-25 13:08 ` Daniel Henrique Barboza
  2023-08-31 12:47   ` Andrew Jones
  19 siblings, 1 reply; 51+ messages in thread
From: Daniel Henrique Barboza @ 2023-08-25 13:08 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-riscv, alistair.francis, bmeng, liweiwei, zhiwei_liu,
	palmer, Daniel Henrique Barboza

This follows the same idea of 'tcg_support' property added in the
previous patch. Note that we're now implementing the 'cpu_realizefn' for
the KVMAccel class since this verification is done in realize() time.

Supporting vendor CPUs with KVM is not possible. We rely on the
extension support of the KVM module running in the host, making it
impossible to guarantee that a vendor CPU will have all the required
extensions available. The only way to guarantee that a vendor CPU is KVM
compatible is running KVM in a host that has the same vendor CPU, and
for this case we already have the 'host' CPU type.

We're better of declaring that all vendors CPUs are not KVM capable.
After this patch, running KVM accel with a vendor CPU will produce an
error like the following:

$ ./qemu-system-riscv64 -M virt,accel=kvm -cpu veyron-v1
qemu-system-riscv64: 'veyron-v1' CPU is not compatible with KVM acceleration

Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
---
 target/riscv/cpu-qom.h     |  1 +
 target/riscv/cpu.c         |  1 +
 target/riscv/kvm/kvm-cpu.c | 24 ++++++++++++++++++++++++
 3 files changed, 26 insertions(+)

diff --git a/target/riscv/cpu-qom.h b/target/riscv/cpu-qom.h
index e86b76f9fe..32d9bb07b4 100644
--- a/target/riscv/cpu-qom.h
+++ b/target/riscv/cpu-qom.h
@@ -72,5 +72,6 @@ struct RISCVCPUClass {
 
     bool user_extension_properties;
     bool tcg_supported;
+    bool kvm_supported;
 };
 #endif /* RISCV_CPU_QOM_H */
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index f749ea2a2e..73302bb72a 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -1646,6 +1646,7 @@ static void riscv_dynamic_cpu_class_init(ObjectClass *c, void *data)
 
     rcc->user_extension_properties = true;
     rcc->tcg_supported = true;
+    rcc->kvm_supported = true;
 }
 
 static void riscv_vendor_cpu_class_init(ObjectClass *c, void *data)
diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c
index 501384924b..85f3b8c80e 100644
--- a/target/riscv/kvm/kvm-cpu.c
+++ b/target/riscv/kvm/kvm-cpu.c
@@ -1289,6 +1289,7 @@ static void riscv_kvm_cpu_class_init(ObjectClass *c, void *data)
     RISCVCPUClass *rcc = RISCV_CPU_CLASS(c);
 
     rcc->user_extension_properties = true;
+    rcc->kvm_supported = true;
 }
 
 static const TypeInfo riscv_kvm_cpu_type_infos[] = {
@@ -1302,6 +1303,28 @@ static const TypeInfo riscv_kvm_cpu_type_infos[] = {
 
 DEFINE_TYPES(riscv_kvm_cpu_type_infos)
 
+/*
+ * We'll get here via the following path:
+ *
+ * riscv_cpu_realize()
+ *   -> cpu_exec_realizefn()
+ *      -> kvm_cpu_realizefn() (via accel_cpu_realizefn())
+ */
+static bool kvm_cpu_realizefn(CPUState *cs, Error **errp)
+{
+    RISCVCPU *cpu = RISCV_CPU(cs);
+    RISCVCPUClass *rcc = RISCV_CPU_GET_CLASS(cpu);
+
+    if (!rcc->kvm_supported) {
+        g_autofree char *name = riscv_cpu_get_name(rcc);
+        error_setg(errp, "'%s' CPU is not compatible with KVM acceleration",
+                   name);
+        return false;
+    }
+
+    return true;
+}
+
 static void kvm_cpu_instance_init(CPUState *cs)
 {
     Object *obj = OBJECT(RISCV_CPU(cs));
@@ -1328,6 +1351,7 @@ static void kvm_cpu_accel_class_init(ObjectClass *oc, void *data)
     AccelCPUClass *acc = ACCEL_CPU_CLASS(oc);
 
     acc->cpu_instance_init = kvm_cpu_instance_init;
+    acc->cpu_realizefn = kvm_cpu_realizefn;
 }
 
 static const TypeInfo kvm_cpu_accel_type_info = {
-- 
2.41.0



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

* Re: [PATCH 04/20] target/riscv: move riscv_tcg_ops to tcg-cpu.c
  2023-08-25 13:08 ` [PATCH 04/20] target/riscv: move riscv_tcg_ops " Daniel Henrique Barboza
@ 2023-08-28 16:30   ` Philippe Mathieu-Daudé
  2023-08-31 10:38   ` Andrew Jones
  1 sibling, 0 replies; 51+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-08-28 16:30 UTC (permalink / raw)
  To: Daniel Henrique Barboza, qemu-devel
  Cc: qemu-riscv, alistair.francis, bmeng, liweiwei, zhiwei_liu, palmer

On 25/8/23 15:08, Daniel Henrique Barboza wrote:
> Move the remaining of riscv_tcg_ops now that we have a working realize()
> implementation.
> 
> Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
> ---
>   target/riscv/cpu.c         | 58 -------------------------------------
>   target/riscv/cpu.h         |  4 ---
>   target/riscv/tcg/tcg-cpu.c | 59 ++++++++++++++++++++++++++++++++++++++
>   3 files changed, 59 insertions(+), 62 deletions(-)


> +const struct TCGCPUOps riscv_tcg_ops = {
> +    .initialize = riscv_translate_init,
> +    .synchronize_from_tb = riscv_cpu_synchronize_from_tb,
> +    .restore_state_to_opc = riscv_restore_state_to_opc,
> +
> +#ifndef CONFIG_USER_ONLY
> +    .tlb_fill = riscv_cpu_tlb_fill,
> +    .cpu_exec_interrupt = riscv_cpu_exec_interrupt,
> +    .do_interrupt = riscv_cpu_do_interrupt,
> +    .do_transaction_failed = riscv_cpu_do_transaction_failed,
> +    .do_unaligned_access = riscv_cpu_do_unaligned_access,
> +    .debug_excp_handler = riscv_cpu_debug_excp_handler,
> +    .debug_check_breakpoint = riscv_cpu_debug_check_breakpoint,
> +    .debug_check_watchpoint = riscv_cpu_debug_check_watchpoint,
> +#endif /* !CONFIG_USER_ONLY */
> +};

We can remove the "riscv_tcg_ops is being imported from cpu.c for now."
comment in tcg_cpu_init_ops(), otherwise:

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>


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

* Re: [PATCH 08/20] target/riscv: move 'host' CPU declaration to kvm.c
  2023-08-25 13:08 ` [PATCH 08/20] target/riscv: move 'host' CPU declaration to kvm.c Daniel Henrique Barboza
@ 2023-08-28 16:35   ` Philippe Mathieu-Daudé
  2023-08-31 11:04   ` Andrew Jones
  1 sibling, 0 replies; 51+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-08-28 16:35 UTC (permalink / raw)
  To: Daniel Henrique Barboza, qemu-devel
  Cc: qemu-riscv, alistair.francis, bmeng, liweiwei, zhiwei_liu, palmer

On 25/8/23 15:08, Daniel Henrique Barboza wrote:
> This CPU only exists if we're compiling with KVM so move it to the kvm
> specific file. While we're at it, change its class_init() to enable the
> user_extensions_flag class property, sparing us from having to execute
> riscv_cpu_add_user_properties() by hand and letting the post_init() hook
> do the work.
> 
> Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
> ---
>   target/riscv/cpu.c | 23 -----------------------
>   target/riscv/kvm.c | 29 +++++++++++++++++++++++++++++
>   2 files changed, 29 insertions(+), 23 deletions(-)

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>



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

* Re: [PATCH 11/20] target/riscv: introduce KVM AccelCPUClass
  2023-08-25 13:08 ` [PATCH 11/20] target/riscv: introduce KVM AccelCPUClass Daniel Henrique Barboza
@ 2023-08-28 16:38   ` Philippe Mathieu-Daudé
  2023-08-29 13:16     ` Daniel Henrique Barboza
  2023-08-31 11:26   ` Andrew Jones
  1 sibling, 1 reply; 51+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-08-28 16:38 UTC (permalink / raw)
  To: Daniel Henrique Barboza, qemu-devel
  Cc: qemu-riscv, alistair.francis, bmeng, liweiwei, zhiwei_liu, palmer

On 25/8/23 15:08, Daniel Henrique Barboza wrote:
> Add a KVM accelerator class like we did with TCG. The difference is
> that, at least for now, we won't be using a realize() implementation for
> this accelerator.
> 
> We'll start by assiging kvm_riscv_cpu_add_kvm_properties(), renamed to
> kvm_cpu_instance_init(), as a 'cpu_instance_init' implementation. Change
> riscv_cpu_post_init() to invoke accel_cpu_instance_init(), which will go
> through the 'cpu_instance_init' impl of the current acceleration (if
> available) and execute it. The end result is that the KVM initial setup,
> i.e. starting registers and adding its specific properties, will be done
> via this hook.
> 
> riscv_cpu_add_user_properties() is still being called via the common
> post_init() function, thus we still need the "if kvm then return" logic
> inside it for now. We'll deal with it when TCG accel class get its own
> 'cpu_instance_init' implementation.
> 
> riscv_add_satp_mode_properties() is now being exported from cpu.c since
> it's a common helper between KVM and TCG.
> 
> Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
> ---
>   target/riscv/cpu.c       |  8 ++---
>   target/riscv/cpu.h       |  1 +
>   target/riscv/kvm.c       | 64 +++++++++++++++++++++++++++-------------
>   target/riscv/kvm_riscv.h |  1 -
>   4 files changed, 49 insertions(+), 25 deletions(-)


> -static void riscv_add_satp_mode_properties(Object *obj)
> +void riscv_add_satp_mode_properties(Object *obj)
>   {
>       RISCVCPU *cpu = RISCV_CPU(obj);
>   
> @@ -1199,6 +1199,8 @@ static void riscv_cpu_post_init(Object *obj)
>       RISCVCPU *cpu = RISCV_CPU(obj);
>       RISCVCPUClass *rcc = RISCV_CPU_GET_CLASS(cpu);
>   
> +    accel_cpu_instance_init(CPU(obj));
> +
>       if (rcc->user_extension_properties) {
>           riscv_cpu_add_user_properties(obj);
>       }
> @@ -1561,12 +1563,10 @@ static void riscv_cpu_add_multiext_prop_array(Object *obj,
>   static void riscv_cpu_add_user_properties(Object *obj)
>   {
>   #ifndef CONFIG_USER_ONLY
> -    riscv_add_satp_mode_properties(obj);
> -
>       if (kvm_enabled()) {
> -        kvm_riscv_cpu_add_kvm_properties(obj);
>           return;
>       }

Maybe in a preliminary patch:

if (tcg_enabled()) {

> +    riscv_add_satp_mode_properties(obj);

}

then remove the 'if kvm_enabled' in this patch?

>   #endif



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

* Re: [PATCH 12/20] target/riscv: move KVM only files to kvm subdir
  2023-08-25 13:08 ` [PATCH 12/20] target/riscv: move KVM only files to kvm subdir Daniel Henrique Barboza
@ 2023-08-28 16:47   ` Philippe Mathieu-Daudé
  2023-08-30 18:21     ` Daniel Henrique Barboza
  2023-08-31 11:30   ` Andrew Jones
  1 sibling, 1 reply; 51+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-08-28 16:47 UTC (permalink / raw)
  To: Daniel Henrique Barboza, qemu-devel
  Cc: qemu-riscv, alistair.francis, bmeng, liweiwei, zhiwei_liu, palmer

On 25/8/23 15:08, Daniel Henrique Barboza wrote:
> Move the files to a 'kvm' dir to promote more code separation between
> accelerators and making our lives easier supporting build options such
> as --disable-tcg.
> 
> Rename kvm.c to kvm-cpu.c to keep it in line with its TCG counterpart.
> 
> Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
> ---
>   hw/riscv/virt.c                       | 2 +-
>   target/riscv/cpu.c                    | 2 +-
>   target/riscv/{kvm.c => kvm/kvm-cpu.c} | 0
>   target/riscv/{ => kvm}/kvm-stub.c     | 0
>   target/riscv/{ => kvm}/kvm_riscv.h    | 0
>   target/riscv/kvm/meson.build          | 2 ++
>   target/riscv/meson.build              | 2 +-
>   7 files changed, 5 insertions(+), 3 deletions(-)
>   rename target/riscv/{kvm.c => kvm/kvm-cpu.c} (100%)
>   rename target/riscv/{ => kvm}/kvm-stub.c (100%)
>   rename target/riscv/{ => kvm}/kvm_riscv.h (100%)
>   create mode 100644 target/riscv/kvm/meson.build


> +++ b/target/riscv/kvm/meson.build
> @@ -0,0 +1,2 @@
> +riscv_ss.add(when: 'CONFIG_KVM', if_true: files('kvm-cpu.c'),
> +                                 if_false: files('kvm-stub.c'))

Hmm maybe we need to add:

-- >8 --
diff --git a/include/hw/core/accel-cpu.h b/include/hw/core/accel-cpu.h
index 5dbfd79955..65973b6f2e 100644
--- a/include/hw/core/accel-cpu.h
+++ b/include/hw/core/accel-cpu.h
@@ -33,6 +33,7 @@ typedef struct AccelCPUClass {
      void (*cpu_class_init)(CPUClass *cc);
      void (*cpu_instance_init)(CPUState *cpu);
      bool (*cpu_realizefn)(CPUState *cpu, Error **errp);
+    ResettablePhases cpu_reset;
  } AccelCPUClass;
---

and here:

  static void kvm_cpu_accel_class_init(ObjectClass *oc, void *data)
  {
      AccelCPUClass *acc = ACCEL_CPU_CLASS(oc);

      acc->cpu_instance_init = kvm_cpu_instance_init;
+    acc->cpu_reset.hold = kvm_riscv_reset_vcpu;
  }

so then calling some accel_cpu_reset_hold() in riscv_cpu_reset_hold(),
would call kvm_riscv_reset_vcpu() and we can remove kvm-stub.c.





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

* Re: [PATCH 11/20] target/riscv: introduce KVM AccelCPUClass
  2023-08-28 16:38   ` Philippe Mathieu-Daudé
@ 2023-08-29 13:16     ` Daniel Henrique Barboza
  0 siblings, 0 replies; 51+ messages in thread
From: Daniel Henrique Barboza @ 2023-08-29 13:16 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé, qemu-devel
  Cc: qemu-riscv, alistair.francis, bmeng, liweiwei, zhiwei_liu, palmer



On 8/28/23 13:38, Philippe Mathieu-Daudé wrote:
> On 25/8/23 15:08, Daniel Henrique Barboza wrote:
>> Add a KVM accelerator class like we did with TCG. The difference is
>> that, at least for now, we won't be using a realize() implementation for
>> this accelerator.
>>
>> We'll start by assiging kvm_riscv_cpu_add_kvm_properties(), renamed to
>> kvm_cpu_instance_init(), as a 'cpu_instance_init' implementation. Change
>> riscv_cpu_post_init() to invoke accel_cpu_instance_init(), which will go
>> through the 'cpu_instance_init' impl of the current acceleration (if
>> available) and execute it. The end result is that the KVM initial setup,
>> i.e. starting registers and adding its specific properties, will be done
>> via this hook.
>>
>> riscv_cpu_add_user_properties() is still being called via the common
>> post_init() function, thus we still need the "if kvm then return" logic
>> inside it for now. We'll deal with it when TCG accel class get its own
>> 'cpu_instance_init' implementation.
>>
>> riscv_add_satp_mode_properties() is now being exported from cpu.c since
>> it's a common helper between KVM and TCG.
>>
>> Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
>> ---
>>   target/riscv/cpu.c       |  8 ++---
>>   target/riscv/cpu.h       |  1 +
>>   target/riscv/kvm.c       | 64 +++++++++++++++++++++++++++-------------
>>   target/riscv/kvm_riscv.h |  1 -
>>   4 files changed, 49 insertions(+), 25 deletions(-)
> 
> 
>> -static void riscv_add_satp_mode_properties(Object *obj)
>> +void riscv_add_satp_mode_properties(Object *obj)
>>   {
>>       RISCVCPU *cpu = RISCV_CPU(obj);
>> @@ -1199,6 +1199,8 @@ static void riscv_cpu_post_init(Object *obj)
>>       RISCVCPU *cpu = RISCV_CPU(obj);
>>       RISCVCPUClass *rcc = RISCV_CPU_GET_CLASS(cpu);
>> +    accel_cpu_instance_init(CPU(obj));
>> +
>>       if (rcc->user_extension_properties) {
>>           riscv_cpu_add_user_properties(obj);
>>       }
>> @@ -1561,12 +1563,10 @@ static void riscv_cpu_add_multiext_prop_array(Object *obj,
>>   static void riscv_cpu_add_user_properties(Object *obj)
>>   {
>>   #ifndef CONFIG_USER_ONLY
>> -    riscv_add_satp_mode_properties(obj);
>> -
>>       if (kvm_enabled()) {
>> -        kvm_riscv_cpu_add_kvm_properties(obj);
>>           return;
>>       }
> 
> Maybe in a preliminary patch:
> 
> if (tcg_enabled()) {
> 
>> +    riscv_add_satp_mode_properties(obj);
> 
> }
> 
> then remove the 'if kvm_enabled' in this patch?

I'll add a preliminary patch to make kvm_riscv_cpu_add_kvm_properties() call
riscv_add_satp_mode_properties() and change the order they're being called here
(i.e. call kvm_riscv_cpu_add_kvm_properties() first). Then this patch can safely
remove the 'if kvm_enabled' block as you suggested.


Thanks,

Daniel


> 
>>   #endif
> 


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

* Re: [PATCH 12/20] target/riscv: move KVM only files to kvm subdir
  2023-08-28 16:47   ` Philippe Mathieu-Daudé
@ 2023-08-30 18:21     ` Daniel Henrique Barboza
  2023-08-30 20:54       ` Philippe Mathieu-Daudé
  0 siblings, 1 reply; 51+ messages in thread
From: Daniel Henrique Barboza @ 2023-08-30 18:21 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé, qemu-devel
  Cc: qemu-riscv, alistair.francis, bmeng, liweiwei, zhiwei_liu, palmer



On 8/28/23 13:47, Philippe Mathieu-Daudé wrote:
> On 25/8/23 15:08, Daniel Henrique Barboza wrote:
>> Move the files to a 'kvm' dir to promote more code separation between
>> accelerators and making our lives easier supporting build options such
>> as --disable-tcg.
>>
>> Rename kvm.c to kvm-cpu.c to keep it in line with its TCG counterpart.
>>
>> Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
>> ---
>>   hw/riscv/virt.c                       | 2 +-
>>   target/riscv/cpu.c                    | 2 +-
>>   target/riscv/{kvm.c => kvm/kvm-cpu.c} | 0
>>   target/riscv/{ => kvm}/kvm-stub.c     | 0
>>   target/riscv/{ => kvm}/kvm_riscv.h    | 0
>>   target/riscv/kvm/meson.build          | 2 ++
>>   target/riscv/meson.build              | 2 +-
>>   7 files changed, 5 insertions(+), 3 deletions(-)
>>   rename target/riscv/{kvm.c => kvm/kvm-cpu.c} (100%)
>>   rename target/riscv/{ => kvm}/kvm-stub.c (100%)
>>   rename target/riscv/{ => kvm}/kvm_riscv.h (100%)
>>   create mode 100644 target/riscv/kvm/meson.build
> 
> 
>> +++ b/target/riscv/kvm/meson.build
>> @@ -0,0 +1,2 @@
>> +riscv_ss.add(when: 'CONFIG_KVM', if_true: files('kvm-cpu.c'),
>> +                                 if_false: files('kvm-stub.c'))
> 
> Hmm maybe we need to add:
> 
> -- >8 --
> diff --git a/include/hw/core/accel-cpu.h b/include/hw/core/accel-cpu.h
> index 5dbfd79955..65973b6f2e 100644
> --- a/include/hw/core/accel-cpu.h
> +++ b/include/hw/core/accel-cpu.h
> @@ -33,6 +33,7 @@ typedef struct AccelCPUClass {
>       void (*cpu_class_init)(CPUClass *cc);
>       void (*cpu_instance_init)(CPUState *cpu);
>       bool (*cpu_realizefn)(CPUState *cpu, Error **errp);
> +    ResettablePhases cpu_reset;
>   } AccelCPUClass;
> ---
> 
> and here:
> 
>   static void kvm_cpu_accel_class_init(ObjectClass *oc, void *data)
>   {
>       AccelCPUClass *acc = ACCEL_CPU_CLASS(oc);
> 
>       acc->cpu_instance_init = kvm_cpu_instance_init;
> +    acc->cpu_reset.hold = kvm_riscv_reset_vcpu;
>   }
> 
> so then calling some accel_cpu_reset_hold() in riscv_cpu_reset_hold(),
> would call kvm_riscv_reset_vcpu() and we can remove kvm-stub.c.


Or we can just remove kvm-stub.c without doing any other changes :)

Just removing it works fine it seems, even with --enable-debug builds. All functions
implemented in the stub are already wrapped in 'if kvm_enabled()' blocks, so the
stub isn't really being used.

I'll take the opportunity to not just remove kvm-stub.c but also add the non-KVM
stubs of all kvm_riscv.h APIs in the header, like you ARM folks are already doing
in kvm_arm.h.  I'll do that in a preliminary patch.


Oh, and a side note: I took a quick look at target/arm/kvm-stub.c and how
write_kvmstate_to_list() and write_list_to_kvmstate() are being called.

Turns out that this works for me:

[danielhb@grind qemu]$ git diff
diff --git a/target/arm/meson.build b/target/arm/meson.build
index e645e456da..e524e1114b 100644
--- a/target/arm/meson.build
+++ b/target/arm/meson.build
@@ -8,7 +8,7 @@ arm_ss.add(files(
  ))
  arm_ss.add(zlib)
  
-arm_ss.add(when: 'CONFIG_KVM', if_true: files('hyp_gdbstub.c', 'kvm.c', 'kvm64.c'), if_false: files('kvm-stub.c'))
+arm_ss.add(when: 'CONFIG_KVM', if_true: files('hyp_gdbstub.c', 'kvm.c', 'kvm64.c'))
  arm_ss.add(when: 'CONFIG_HVF', if_true: files('hyp_gdbstub.c'))
  
  arm_ss.add(when: 'TARGET_AARCH64', if_true: files(

[danielhb@grind qemu]$ git rm target/arm/kvm-stub.c
rm 'target/arm/kvm-stub.c'

[danielhb@grind qemu]$ cd build
[danielhb@grind build]$ ../configure --target-list=aarch64-softmmu --enable-debug && make -j
(...)
[2724/2725] Generating docs/QEMU manual with a custom command
[2725/2725] Generating docs/QEMU man pages with a custom command
[danielhb@grind build]$


I suggest you take a look into target/arm/kvm-stub.c. Seems like you can just rip it out.


Thanks,


Daniel


> 
> 
> 


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

* Re: [PATCH 12/20] target/riscv: move KVM only files to kvm subdir
  2023-08-30 18:21     ` Daniel Henrique Barboza
@ 2023-08-30 20:54       ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 51+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-08-30 20:54 UTC (permalink / raw)
  To: Daniel Henrique Barboza, qemu-devel
  Cc: qemu-riscv, alistair.francis, bmeng, liweiwei, zhiwei_liu, palmer

On 30/8/23 20:21, Daniel Henrique Barboza wrote:
> 
> 
> On 8/28/23 13:47, Philippe Mathieu-Daudé wrote:
>> On 25/8/23 15:08, Daniel Henrique Barboza wrote:
>>> Move the files to a 'kvm' dir to promote more code separation between
>>> accelerators and making our lives easier supporting build options such
>>> as --disable-tcg.
>>>
>>> Rename kvm.c to kvm-cpu.c to keep it in line with its TCG counterpart.
>>>
>>> Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
>>> ---
>>>   hw/riscv/virt.c                       | 2 +-
>>>   target/riscv/cpu.c                    | 2 +-
>>>   target/riscv/{kvm.c => kvm/kvm-cpu.c} | 0
>>>   target/riscv/{ => kvm}/kvm-stub.c     | 0
>>>   target/riscv/{ => kvm}/kvm_riscv.h    | 0
>>>   target/riscv/kvm/meson.build          | 2 ++
>>>   target/riscv/meson.build              | 2 +-
>>>   7 files changed, 5 insertions(+), 3 deletions(-)
>>>   rename target/riscv/{kvm.c => kvm/kvm-cpu.c} (100%)
>>>   rename target/riscv/{ => kvm}/kvm-stub.c (100%)
>>>   rename target/riscv/{ => kvm}/kvm_riscv.h (100%)
>>>   create mode 100644 target/riscv/kvm/meson.build
>>
>>
>>> +++ b/target/riscv/kvm/meson.build
>>> @@ -0,0 +1,2 @@
>>> +riscv_ss.add(when: 'CONFIG_KVM', if_true: files('kvm-cpu.c'),
>>> +                                 if_false: files('kvm-stub.c'))
>>
>> Hmm maybe we need to add:
>>
>> -- >8 --
>> diff --git a/include/hw/core/accel-cpu.h b/include/hw/core/accel-cpu.h
>> index 5dbfd79955..65973b6f2e 100644
>> --- a/include/hw/core/accel-cpu.h
>> +++ b/include/hw/core/accel-cpu.h
>> @@ -33,6 +33,7 @@ typedef struct AccelCPUClass {
>>       void (*cpu_class_init)(CPUClass *cc);
>>       void (*cpu_instance_init)(CPUState *cpu);
>>       bool (*cpu_realizefn)(CPUState *cpu, Error **errp);
>> +    ResettablePhases cpu_reset;
>>   } AccelCPUClass;
>> ---
>>
>> and here:
>>
>>   static void kvm_cpu_accel_class_init(ObjectClass *oc, void *data)
>>   {
>>       AccelCPUClass *acc = ACCEL_CPU_CLASS(oc);
>>
>>       acc->cpu_instance_init = kvm_cpu_instance_init;
>> +    acc->cpu_reset.hold = kvm_riscv_reset_vcpu;
>>   }
>>
>> so then calling some accel_cpu_reset_hold() in riscv_cpu_reset_hold(),
>> would call kvm_riscv_reset_vcpu() and we can remove kvm-stub.c.
> 
> 
> Or we can just remove kvm-stub.c without doing any other changes :)
> 
> Just removing it works fine it seems, even with --enable-debug builds. 
> All functions
> implemented in the stub are already wrapped in 'if kvm_enabled()' 
> blocks, so the
> stub isn't really being used.
> 
> I'll take the opportunity to not just remove kvm-stub.c but also add the 
> non-KVM
> stubs of all kvm_riscv.h APIs in the header, like you ARM folks are 
> already doing
> in kvm_arm.h.  I'll do that in a preliminary patch.
> 
> 
> Oh, and a side note: I took a quick look at target/arm/kvm-stub.c and how
> write_kvmstate_to_list() and write_list_to_kvmstate() are being called.
> 
> Turns out that this works for me:
> 
> [danielhb@grind qemu]$ git diff
> diff --git a/target/arm/meson.build b/target/arm/meson.build
> index e645e456da..e524e1114b 100644
> --- a/target/arm/meson.build
> +++ b/target/arm/meson.build
> @@ -8,7 +8,7 @@ arm_ss.add(files(
>   ))
>   arm_ss.add(zlib)
> 
> -arm_ss.add(when: 'CONFIG_KVM', if_true: files('hyp_gdbstub.c', 'kvm.c', 
> 'kvm64.c'), if_false: files('kvm-stub.c'))
> +arm_ss.add(when: 'CONFIG_KVM', if_true: files('hyp_gdbstub.c', 'kvm.c', 
> 'kvm64.c'))
>   arm_ss.add(when: 'CONFIG_HVF', if_true: files('hyp_gdbstub.c'))
> 
>   arm_ss.add(when: 'TARGET_AARCH64', if_true: files(
> 
> [danielhb@grind qemu]$ git rm target/arm/kvm-stub.c
> rm 'target/arm/kvm-stub.c'
> 
> [danielhb@grind qemu]$ cd build
> [danielhb@grind build]$ ../configure --target-list=aarch64-softmmu 
> --enable-debug && make -j
> (...)
> [2724/2725] Generating docs/QEMU manual with a custom command
> [2725/2725] Generating docs/QEMU man pages with a custom command
> [danielhb@grind build]$
> 
> 
> I suggest you take a look into target/arm/kvm-stub.c. Seems like you can 
> just rip it out.

Great news, thanks Daniel!



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

* Re: [PATCH 01/20] target/riscv: introduce TCG AccelCPUClass
  2023-08-25 13:08 ` [PATCH 01/20] target/riscv: introduce TCG AccelCPUClass Daniel Henrique Barboza
@ 2023-08-31 10:17   ` Andrew Jones
  0 siblings, 0 replies; 51+ messages in thread
From: Andrew Jones @ 2023-08-31 10:17 UTC (permalink / raw)
  To: Daniel Henrique Barboza
  Cc: qemu-devel, qemu-riscv, alistair.francis, bmeng, liweiwei,
	zhiwei_liu, palmer

On Fri, Aug 25, 2023 at 10:08:34AM -0300, Daniel Henrique Barboza wrote:
> target/riscv/cpu.c needs to handle all possible accelerators (TCG and
> KVM at this moment) during both init() and realize() time. This forces
> us to resort to a lot of "if tcg" and "if kvm" throughout the code,
> which isn't wrong, but can get cluttered over time. Splitting
> acceleration specific code from cpu.c to its own file will help to
> declutter the existing code and it will also make it easier to support
> KVM/TCG only builds in the future.
> 
> We'll start by adding a new subdir called 'tcg' and a new file called
> 'tcg-cpu.c'. This file will be used to introduce a new accelerator class
> for TCG acceleration in RISC-V, allowing us to center all TCG exclusive
> code in its file instead of using 'cpu.c' for everything. This design is
> inpired by the work Claudio Fontana did in x86 a few years ago in commit
> f5cc5a5c1 ("i386: split cpu accelerators from cpu.c, using
> AccelCPUClass").
> 
> To avoid moving too much code at once we'll start by adding the new file
> and TCG AccelCPUClass declaration. The 'class_init' from the accel class
> will init 'tcg_ops', relieving the common riscv_cpu_class_init() from
> doing it.
> 
> 'riscv_tcg_ops' is being exported from 'cpu.c' for now to avoid having
> to deal with moving code and files around right now. We'll focus on
> decoupling the realize() logic first.
> 
> Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
> ---
>  target/riscv/cpu.c           |  5 +---
>  target/riscv/cpu.h           |  4 +++
>  target/riscv/meson.build     |  2 ++
>  target/riscv/tcg/meson.build |  2 ++
>  target/riscv/tcg/tcg-cpu.c   | 57 ++++++++++++++++++++++++++++++++++++
>  5 files changed, 66 insertions(+), 4 deletions(-)
>  create mode 100644 target/riscv/tcg/meson.build
>  create mode 100644 target/riscv/tcg/tcg-cpu.c
> 
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index 21ebdbf084..38dcbc4dd2 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -2275,9 +2275,7 @@ static const struct SysemuCPUOps riscv_sysemu_ops = {
>  };
>  #endif
>  
> -#include "hw/core/tcg-cpu-ops.h"
> -
> -static const struct TCGCPUOps riscv_tcg_ops = {
> +const struct TCGCPUOps riscv_tcg_ops = {
>      .initialize = riscv_translate_init,
>      .synchronize_from_tb = riscv_cpu_synchronize_from_tb,
>      .restore_state_to_opc = riscv_restore_state_to_opc,
> @@ -2436,7 +2434,6 @@ static void riscv_cpu_class_init(ObjectClass *c, void *data)
>  #endif
>      cc->gdb_arch_name = riscv_gdb_arch_name;
>      cc->gdb_get_dynamic_xml = riscv_gdb_get_dynamic_xml;
> -    cc->tcg_ops = &riscv_tcg_ops;
>  
>      object_class_property_add(c, "mvendorid", "uint32", cpu_get_mvendorid,
>                                cpu_set_mvendorid, NULL, NULL);
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index 577abcd724..b84b62f84e 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -707,6 +707,10 @@ enum riscv_pmu_event_idx {
>      RISCV_PMU_EVENT_CACHE_ITLB_PREFETCH_MISS = 0x10021,
>  };
>  
> +/* Export tcg_ops until we move everything to tcg/tcg-cpu.c */
> +#include "hw/core/tcg-cpu-ops.h"
> +extern const struct TCGCPUOps riscv_tcg_ops;
> +
>  /* CSR function table */
>  extern riscv_csr_operations csr_ops[CSR_TABLE_SIZE];
>  
> diff --git a/target/riscv/meson.build b/target/riscv/meson.build
> index 660078bda1..f0486183fa 100644
> --- a/target/riscv/meson.build
> +++ b/target/riscv/meson.build
> @@ -38,5 +38,7 @@ riscv_system_ss.add(files(
>    'riscv-qmp-cmds.c',
>  ))
>  
> +subdir('tcg')
> +
>  target_arch += {'riscv': riscv_ss}
>  target_softmmu_arch += {'riscv': riscv_system_ss}
> diff --git a/target/riscv/tcg/meson.build b/target/riscv/tcg/meson.build
> new file mode 100644
> index 0000000000..061df3d74a
> --- /dev/null
> +++ b/target/riscv/tcg/meson.build
> @@ -0,0 +1,2 @@
> +riscv_ss.add(when: 'CONFIG_TCG', if_true: files(
> +  'tcg-cpu.c'))
> diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
> new file mode 100644
> index 0000000000..1ad27a26aa
> --- /dev/null
> +++ b/target/riscv/tcg/tcg-cpu.c
> @@ -0,0 +1,57 @@
> +/*
> + * riscv TCG cpu class initialization
> + *
> + * Copyright (c) 2023 Ventana Micro Systems Inc.
> + *
> + * This library is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2 of the License, or (at your option) any later version.
> + *
> + * This library is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with this library; if not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include "qemu/osdep.h"
> +#include "cpu.h"
> +#include "qemu/accel.h"
> +#include "hw/core/accel-cpu.h"
> +
> +static void tcg_cpu_init_ops(AccelCPUClass *accel_cpu, CPUClass *cc)
> +{
> +    /*
> +     * All cpus use the same set of operations.
> +     * riscv_tcg_ops is being imported from cpu.c for now.
> +     */
> +    cc->tcg_ops = &riscv_tcg_ops;
> +}
> +
> +static void tcg_cpu_class_init(CPUClass *cc)
> +{
> +    cc->init_accel_cpu = tcg_cpu_init_ops;
> +}
> +
> +static void tcg_cpu_accel_class_init(ObjectClass *oc, void *data)
> +{
> +    AccelCPUClass *acc = ACCEL_CPU_CLASS(oc);
> +
> +    acc->cpu_class_init = tcg_cpu_class_init;
> +}
> +
> +static const TypeInfo tcg_cpu_accel_type_info = {
> +    .name = ACCEL_CPU_NAME("tcg"),
> +
> +    .parent = TYPE_ACCEL_CPU,
> +    .class_init = tcg_cpu_accel_class_init,
> +    .abstract = true,
> +};

need blank line here

> +static void tcg_cpu_accel_register_types(void)
> +{
> +    type_register_static(&tcg_cpu_accel_type_info);
> +}
> +type_init(tcg_cpu_accel_register_types);
> -- 
> 2.41.0
> 
>

Appears to be consistent with target/i386/tcg/tcg-cpu.c, so

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

Thanks,
drew


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

* Re: [PATCH 02/20] target/riscv: move riscv_cpu_realize_tcg() to TCG::cpu_realizefn()
  2023-08-25 13:08 ` [PATCH 02/20] target/riscv: move riscv_cpu_realize_tcg() to TCG::cpu_realizefn() Daniel Henrique Barboza
@ 2023-08-31 10:21   ` Andrew Jones
  0 siblings, 0 replies; 51+ messages in thread
From: Andrew Jones @ 2023-08-31 10:21 UTC (permalink / raw)
  To: Daniel Henrique Barboza
  Cc: qemu-devel, qemu-riscv, alistair.francis, bmeng, liweiwei,
	zhiwei_liu, palmer

On Fri, Aug 25, 2023 at 10:08:35AM -0300, Daniel Henrique Barboza wrote:
> riscv_cpu_realize_tcg() was added to allow TCG cpus to have a different
> realize() path during the common riscv_cpu_realize(), making it a good
> choice to start moving TCG exclusive code to tcg-cpu.c.
> 
> Rename it to tcg_cpu_realizefn() and assign it as a implementation of
> accel::cpu_realizefn(). tcg_cpu_realizefn() will then be called during
> riscv_cpu_realize() via cpu_exec_realizefn(). We'll use a similar
> approach with KVM in the near future.
> 
> riscv_cpu_validate_set_extensions() is too big and with too many
> dependencies to be moved in this same patch. We'll do that next.
> 
> Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
> ---
>  target/riscv/cpu.c         | 128 -----------------------------------
>  target/riscv/tcg/tcg-cpu.c | 132 +++++++++++++++++++++++++++++++++++++
>  2 files changed, 132 insertions(+), 128 deletions(-)
> 
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index 38dcbc4dd2..36c5c6e579 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -23,9 +23,7 @@
>  #include "qemu/log.h"
>  #include "cpu.h"
>  #include "cpu_vendorid.h"
> -#include "pmu.h"
>  #include "internals.h"
> -#include "time_helper.h"
>  #include "exec/exec-all.h"
>  #include "qapi/error.h"
>  #include "qapi/visitor.h"
> @@ -1065,29 +1063,6 @@ static void riscv_cpu_validate_v(CPURISCVState *env, RISCVCPUConfig *cfg,
>      }
>  }
>  
> -static void riscv_cpu_validate_priv_spec(RISCVCPU *cpu, Error **errp)
> -{
> -    CPURISCVState *env = &cpu->env;
> -    int priv_version = -1;
> -
> -    if (cpu->cfg.priv_spec) {
> -        if (!g_strcmp0(cpu->cfg.priv_spec, "v1.12.0")) {
> -            priv_version = PRIV_VERSION_1_12_0;
> -        } else if (!g_strcmp0(cpu->cfg.priv_spec, "v1.11.0")) {
> -            priv_version = PRIV_VERSION_1_11_0;
> -        } else if (!g_strcmp0(cpu->cfg.priv_spec, "v1.10.0")) {
> -            priv_version = PRIV_VERSION_1_10_0;
> -        } else {
> -            error_setg(errp,
> -                       "Unsupported privilege spec version '%s'",
> -                       cpu->cfg.priv_spec);
> -            return;
> -        }
> -
> -        env->priv_ver = priv_version;
> -    }
> -}
> -
>  static void riscv_cpu_disable_priv_spec_isa_exts(RISCVCPU *cpu)
>  {
>      CPURISCVState *env = &cpu->env;
> @@ -1112,33 +1087,6 @@ static void riscv_cpu_disable_priv_spec_isa_exts(RISCVCPU *cpu)
>      }
>  }
>  
> -static void riscv_cpu_validate_misa_mxl(RISCVCPU *cpu, Error **errp)
> -{
> -    RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(cpu);
> -    CPUClass *cc = CPU_CLASS(mcc);
> -    CPURISCVState *env = &cpu->env;
> -
> -    /* Validate that MISA_MXL is set properly. */
> -    switch (env->misa_mxl_max) {
> -#ifdef TARGET_RISCV64
> -    case MXL_RV64:
> -    case MXL_RV128:
> -        cc->gdb_core_xml_file = "riscv-64bit-cpu.xml";
> -        break;
> -#endif
> -    case MXL_RV32:
> -        cc->gdb_core_xml_file = "riscv-32bit-cpu.xml";
> -        break;
> -    default:
> -        g_assert_not_reached();
> -    }
> -
> -    if (env->misa_mxl_max != env->misa_mxl) {
> -        error_setg(errp, "misa_mxl_max must be equal to misa_mxl");
> -        return;
> -    }
> -}
> -
>  /*
>   * Check consistency between chosen extensions while setting
>   * cpu->cfg accordingly.
> @@ -1512,74 +1460,6 @@ static void riscv_cpu_finalize_features(RISCVCPU *cpu, Error **errp)
>  #endif
>  }
>  
> -static void riscv_cpu_validate_misa_priv(CPURISCVState *env, Error **errp)
> -{
> -    if (riscv_has_ext(env, RVH) && env->priv_ver < PRIV_VERSION_1_12_0) {
> -        error_setg(errp, "H extension requires priv spec 1.12.0");
> -        return;
> -    }
> -}
> -
> -static void riscv_cpu_realize_tcg(DeviceState *dev, Error **errp)
> -{
> -    RISCVCPU *cpu = RISCV_CPU(dev);
> -    CPURISCVState *env = &cpu->env;
> -    Error *local_err = NULL;
> -
> -    if (object_dynamic_cast(OBJECT(dev), TYPE_RISCV_CPU_HOST)) {
> -        error_setg(errp, "'host' CPU is not compatible with TCG acceleration");
> -        return;
> -    }
> -
> -    riscv_cpu_validate_misa_mxl(cpu, &local_err);
> -    if (local_err != NULL) {
> -        error_propagate(errp, local_err);
> -        return;
> -    }
> -
> -    riscv_cpu_validate_priv_spec(cpu, &local_err);
> -    if (local_err != NULL) {
> -        error_propagate(errp, local_err);
> -        return;
> -    }
> -
> -    riscv_cpu_validate_misa_priv(env, &local_err);
> -    if (local_err != NULL) {
> -        error_propagate(errp, local_err);
> -        return;
> -    }
> -
> -    if (cpu->cfg.epmp && !cpu->cfg.pmp) {
> -        /*
> -         * Enhanced PMP should only be available
> -         * on harts with PMP support
> -         */
> -        error_setg(errp, "Invalid configuration: EPMP requires PMP support");
> -        return;
> -    }
> -
> -    riscv_cpu_validate_set_extensions(cpu, &local_err);
> -    if (local_err != NULL) {
> -        error_propagate(errp, local_err);
> -        return;
> -    }
> -
> -#ifndef CONFIG_USER_ONLY
> -    CPU(dev)->tcg_cflags |= CF_PCREL;
> -
> -    if (cpu->cfg.ext_sstc) {
> -        riscv_timer_init(cpu);
> -    }
> -
> -    if (cpu->cfg.pmu_num) {
> -        if (!riscv_pmu_init(cpu, cpu->cfg.pmu_num) && cpu->cfg.ext_sscofpmf) {
> -            cpu->pmu_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
> -                                          riscv_pmu_timer_cb, cpu);
> -        }
> -     }
> -#endif
> -}
> -
>  static void riscv_cpu_realize(DeviceState *dev, Error **errp)
>  {
>      CPUState *cs = CPU(dev);
> @@ -1598,14 +1478,6 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
>          return;
>      }
>  
> -    if (tcg_enabled()) {
> -        riscv_cpu_realize_tcg(dev, &local_err);
> -        if (local_err != NULL) {
> -            error_propagate(errp, local_err);
> -            return;
> -        }
> -    }
> -
>      riscv_cpu_finalize_features(cpu, &local_err);
>      if (local_err != NULL) {
>          error_propagate(errp, local_err);
> diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
> index 1ad27a26aa..b3d3f265d7 100644
> --- a/target/riscv/tcg/tcg-cpu.c
> +++ b/target/riscv/tcg/tcg-cpu.c
> @@ -19,9 +19,140 @@
>  
>  #include "qemu/osdep.h"
>  #include "cpu.h"
> +#include "pmu.h"
> +#include "time_helper.h"
> +#include "qapi/error.h"
>  #include "qemu/accel.h"
>  #include "hw/core/accel-cpu.h"
>  
> +
> +static void riscv_cpu_validate_misa_priv(CPURISCVState *env, Error **errp)
> +{
> +    if (riscv_has_ext(env, RVH) && env->priv_ver < PRIV_VERSION_1_12_0) {
> +        error_setg(errp, "H extension requires priv spec 1.12.0");
> +        return;
> +    }
> +}
> +
> +static void riscv_cpu_validate_misa_mxl(RISCVCPU *cpu, Error **errp)
> +{
> +    RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(cpu);
> +    CPUClass *cc = CPU_CLASS(mcc);
> +    CPURISCVState *env = &cpu->env;
> +
> +    /* Validate that MISA_MXL is set properly. */
> +    switch (env->misa_mxl_max) {
> +#ifdef TARGET_RISCV64
> +    case MXL_RV64:
> +    case MXL_RV128:
> +        cc->gdb_core_xml_file = "riscv-64bit-cpu.xml";
> +        break;
> +#endif
> +    case MXL_RV32:
> +        cc->gdb_core_xml_file = "riscv-32bit-cpu.xml";
> +        break;
> +    default:
> +        g_assert_not_reached();
> +    }
> +
> +    if (env->misa_mxl_max != env->misa_mxl) {
> +        error_setg(errp, "misa_mxl_max must be equal to misa_mxl");
> +        return;
> +    }
> +}
> +
> +static void riscv_cpu_validate_priv_spec(RISCVCPU *cpu, Error **errp)
> +{
> +    CPURISCVState *env = &cpu->env;
> +    int priv_version = -1;
> +
> +    if (cpu->cfg.priv_spec) {
> +        if (!g_strcmp0(cpu->cfg.priv_spec, "v1.12.0")) {
> +            priv_version = PRIV_VERSION_1_12_0;
> +        } else if (!g_strcmp0(cpu->cfg.priv_spec, "v1.11.0")) {
> +            priv_version = PRIV_VERSION_1_11_0;
> +        } else if (!g_strcmp0(cpu->cfg.priv_spec, "v1.10.0")) {
> +            priv_version = PRIV_VERSION_1_10_0;
> +        } else {
> +            error_setg(errp,
> +                       "Unsupported privilege spec version '%s'",
> +                       cpu->cfg.priv_spec);
> +            return;
> +        }
> +
> +        env->priv_ver = priv_version;
> +    }
> +}
> +
> +/*
> + * We'll get here via the following path:
> + *
> + * riscv_cpu_realize()
> + *   -> cpu_exec_realizefn()
> + *      -> tcg_cpu_realizefn() (via accel_cpu_realizefn())
> + */
> +static bool tcg_cpu_realizefn(CPUState *cs, Error **errp)
> +{
> +    RISCVCPU *cpu = RISCV_CPU(cs);
> +    CPURISCVState *env = &cpu->env;
> +    Error *local_err = NULL;
> +
> +    if (object_dynamic_cast(OBJECT(cpu), TYPE_RISCV_CPU_HOST)) {
> +        error_setg(errp, "'host' CPU is not compatible with TCG acceleration");
> +        return false;
> +    }
> +
> +    riscv_cpu_validate_misa_mxl(cpu, &local_err);
> +    if (local_err != NULL) {
> +        error_propagate(errp, local_err);
> +        return false;
> +    }
> +
> +    riscv_cpu_validate_priv_spec(cpu, &local_err);
> +    if (local_err != NULL) {
> +        error_propagate(errp, local_err);
> +        return false;
> +    }
> +
> +    riscv_cpu_validate_misa_priv(env, &local_err);
> +    if (local_err != NULL) {
> +        error_propagate(errp, local_err);
> +        return false;
> +    }
> +
> +    if (cpu->cfg.epmp && !cpu->cfg.pmp) {
> +        /*
> +         * Enhanced PMP should only be available
> +         * on harts with PMP support
> +         */
> +        error_setg(errp, "Invalid configuration: EPMP requires PMP support");
> +        return false;
> +    }
> +
> +    riscv_cpu_validate_set_extensions(cpu, &local_err);
> +    if (local_err != NULL) {
> +        error_propagate(errp, local_err);
> +        return false;
> +    }
> +
> +#ifndef CONFIG_USER_ONLY
> +    CPU(cs)->tcg_cflags |= CF_PCREL;
> +
> +    if (cpu->cfg.ext_sstc) {
> +        riscv_timer_init(cpu);
> +    }
> +
> +    if (cpu->cfg.pmu_num) {
> +        if (!riscv_pmu_init(cpu, cpu->cfg.pmu_num) && cpu->cfg.ext_sscofpmf) {
> +            cpu->pmu_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
> +                                          riscv_pmu_timer_cb, cpu);
> +        }
> +     }
> +#endif
> +
> +    return true;
> +}
> +
>  static void tcg_cpu_init_ops(AccelCPUClass *accel_cpu, CPUClass *cc)
>  {
>      /*
> @@ -41,6 +172,7 @@ static void tcg_cpu_accel_class_init(ObjectClass *oc, void *data)
>      AccelCPUClass *acc = ACCEL_CPU_CLASS(oc);
>  
>      acc->cpu_class_init = tcg_cpu_class_init;
> +    acc->cpu_realizefn = tcg_cpu_realizefn;
>  }
>  
>  static const TypeInfo tcg_cpu_accel_type_info = {
> -- 
> 2.41.0
> 
>

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


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

* Re: [PATCH 03/20] target/riscv: move riscv_cpu_validate_set_extensions() to tcg-cpu.c
  2023-08-25 13:08 ` [PATCH 03/20] target/riscv: move riscv_cpu_validate_set_extensions() to tcg-cpu.c Daniel Henrique Barboza
@ 2023-08-31 10:31   ` Andrew Jones
  0 siblings, 0 replies; 51+ messages in thread
From: Andrew Jones @ 2023-08-31 10:31 UTC (permalink / raw)
  To: Daniel Henrique Barboza
  Cc: qemu-devel, qemu-riscv, alistair.francis, bmeng, liweiwei,
	zhiwei_liu, palmer

On Fri, Aug 25, 2023 at 10:08:36AM -0300, Daniel Henrique Barboza wrote:
> This function is the core of the RISC-V validations for TCG CPUs, and it
> has a lot going on.
> 
> Functions in cpu.c were made public to allow them to be used by the KVM
> accelerator class later on. 'cpu_cfg_ext_get_min_version()' is notably
> hard to move it to another file due to its dependency with isa_edata_arr[]
> array, thus make it public and use it as is for now.
> 
> riscv_cpu_validate_set_extensions() is kept public because it's used by
> csr.c in write_misa().
> 
> Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
> ---
>  target/riscv/cpu.c         | 361 +------------------------------------
>  target/riscv/cpu.h         |   8 +-
>  target/riscv/csr.c         |   1 +
>  target/riscv/tcg/tcg-cpu.c | 352 ++++++++++++++++++++++++++++++++++++
>  target/riscv/tcg/tcg-cpu.h |  28 +++
>  5 files changed, 393 insertions(+), 357 deletions(-)
>  create mode 100644 target/riscv/tcg/tcg-cpu.h
> 
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index 36c5c6e579..12cea62ee7 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -163,22 +163,21 @@ static const struct isa_ext_data isa_edata_arr[] = {
>  /* Hash that stores user set extensions */
>  static GHashTable *multi_ext_user_opts;
>  
> -static bool isa_ext_is_enabled(RISCVCPU *cpu, uint32_t ext_offset)
> +bool isa_ext_is_enabled(RISCVCPU *cpu, uint32_t ext_offset)
>  {
>      bool *ext_enabled = (void *)&cpu->cfg + ext_offset;
>  
>      return *ext_enabled;
>  }
>  
> -static void isa_ext_update_enabled(RISCVCPU *cpu, uint32_t ext_offset,
> -                                   bool en)
> +void isa_ext_update_enabled(RISCVCPU *cpu, uint32_t ext_offset, bool en)
>  {
>      bool *ext_enabled = (void *)&cpu->cfg + ext_offset;
>  
>      *ext_enabled = en;
>  }
>  
> -static int cpu_cfg_ext_get_min_version(uint32_t ext_offset)
> +int cpu_cfg_ext_get_min_version(uint32_t ext_offset)
>  {
>      int i;
>  
> @@ -194,38 +193,12 @@ static int cpu_cfg_ext_get_min_version(uint32_t ext_offset)
>      return PRIV_VERSION_1_10_0;
>  }
>  
> -static bool cpu_cfg_ext_is_user_set(uint32_t ext_offset)
> +bool cpu_cfg_ext_is_user_set(uint32_t ext_offset)
>  {
>      return g_hash_table_contains(multi_ext_user_opts,
>                                   GUINT_TO_POINTER(ext_offset));
>  }
>  
> -static void cpu_cfg_ext_auto_update(RISCVCPU *cpu, uint32_t ext_offset,
> -                                    bool value)
> -{
> -    CPURISCVState *env = &cpu->env;
> -    bool prev_val = isa_ext_is_enabled(cpu, ext_offset);
> -    int min_version;
> -
> -    if (prev_val == value) {
> -        return;
> -    }
> -
> -    if (cpu_cfg_ext_is_user_set(ext_offset)) {
> -        return;
> -    }
> -
> -    if (value && env->priv_ver != PRIV_VERSION_LATEST) {
> -        /* Do not enable it if priv_ver is older than min_version */
> -        min_version = cpu_cfg_ext_get_min_version(ext_offset);
> -        if (env->priv_ver < min_version) {
> -            return;
> -        }
> -    }
> -
> -    isa_ext_update_enabled(cpu, ext_offset, value);
> -}
> -
>  const char * const riscv_int_regnames[] = {
>      "x0/zero", "x1/ra",  "x2/sp",  "x3/gp",  "x4/tp",  "x5/t0",   "x6/t1",
>      "x7/t2",   "x8/s0",  "x9/s1",  "x10/a0", "x11/a1", "x12/a2",  "x13/a3",
> @@ -1024,46 +997,7 @@ static void riscv_cpu_disas_set_info(CPUState *s, disassemble_info *info)
>      }
>  }
>  
> -static void riscv_cpu_validate_v(CPURISCVState *env, RISCVCPUConfig *cfg,
> -                                 Error **errp)
> -{
> -    if (!is_power_of_2(cfg->vlen)) {
> -        error_setg(errp, "Vector extension VLEN must be power of 2");
> -        return;
> -    }
> -    if (cfg->vlen > RV_VLEN_MAX || cfg->vlen < 128) {
> -        error_setg(errp,
> -                   "Vector extension implementation only supports VLEN "
> -                   "in the range [128, %d]", RV_VLEN_MAX);
> -        return;
> -    }
> -    if (!is_power_of_2(cfg->elen)) {
> -        error_setg(errp, "Vector extension ELEN must be power of 2");
> -        return;
> -    }
> -    if (cfg->elen > 64 || cfg->elen < 8) {
> -        error_setg(errp,
> -                   "Vector extension implementation only supports ELEN "
> -                   "in the range [8, 64]");
> -        return;
> -    }
> -    if (cfg->vext_spec) {
> -        if (!g_strcmp0(cfg->vext_spec, "v1.0")) {
> -            env->vext_ver = VEXT_VERSION_1_00_0;
> -        } else {
> -            error_setg(errp, "Unsupported vector spec version '%s'",
> -                       cfg->vext_spec);
> -            return;
> -        }
> -    } else if (env->vext_ver == 0) {
> -        qemu_log("vector version is not specified, "
> -                 "use the default value v1.0\n");
> -
> -        env->vext_ver = VEXT_VERSION_1_00_0;
> -    }
> -}
> -
> -static void riscv_cpu_disable_priv_spec_isa_exts(RISCVCPU *cpu)
> +void riscv_cpu_disable_priv_spec_isa_exts(RISCVCPU *cpu)
>  {
>      CPURISCVState *env = &cpu->env;
>      int i;
> @@ -1087,291 +1021,6 @@ static void riscv_cpu_disable_priv_spec_isa_exts(RISCVCPU *cpu)
>      }
>  }
>  
> -/*
> - * Check consistency between chosen extensions while setting
> - * cpu->cfg accordingly.
> - */
> -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_icsr && cpu->cfg.ext_ifencei)) {
> -        warn_report("Setting G will also set IMAFD_Zicsr_Zifencei");
> -
> -        if (cpu_cfg_ext_is_user_set(CPU_CFG_OFFSET(ext_icsr)) &&
> -            !cpu->cfg.ext_icsr) {
> -            error_setg(errp, "RVG requires Zicsr but user set Zicsr to false");
> -            return;
> -        }
> -
> -        if (cpu_cfg_ext_is_user_set(CPU_CFG_OFFSET(ext_ifencei)) &&
> -            !cpu->cfg.ext_ifencei) {
> -            error_setg(errp, "RVG requires Zifencei but user set "
> -                       "Zifencei to false");
> -            return;
> -        }
> -
> -        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_icsr), true);
> -        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_ifencei), true);
> -
> -        env->misa_ext |= RVI | RVM | RVA | RVF | RVD;
> -        env->misa_ext_mask |= RVI | RVM | RVA | RVF | RVD;
> -    }
> -
> -    if (riscv_has_ext(env, RVI) && riscv_has_ext(env, RVE)) {
> -        error_setg(errp,
> -                   "I and E extensions are incompatible");
> -        return;
> -    }
> -
> -    if (!riscv_has_ext(env, RVI) && !riscv_has_ext(env, RVE)) {
> -        error_setg(errp,
> -                   "Either I or E extension must be set");
> -        return;
> -    }
> -
> -    if (riscv_has_ext(env, RVS) && !riscv_has_ext(env, RVU)) {
> -        error_setg(errp,
> -                   "Setting S extension without U extension is illegal");
> -        return;
> -    }
> -
> -    if (riscv_has_ext(env, RVH) && !riscv_has_ext(env, RVI)) {
> -        error_setg(errp,
> -                   "H depends on an I base integer ISA with 32 x registers");
> -        return;
> -    }
> -
> -    if (riscv_has_ext(env, RVH) && !riscv_has_ext(env, RVS)) {
> -        error_setg(errp, "H extension implicitly requires S-mode");
> -        return;
> -    }
> -
> -    if (riscv_has_ext(env, RVF) && !cpu->cfg.ext_icsr) {
> -        error_setg(errp, "F extension requires Zicsr");
> -        return;
> -    }
> -
> -    if ((cpu->cfg.ext_zawrs) && !riscv_has_ext(env, RVA)) {
> -        error_setg(errp, "Zawrs extension requires A extension");
> -        return;
> -    }
> -
> -    if (cpu->cfg.ext_zfa && !riscv_has_ext(env, RVF)) {
> -        error_setg(errp, "Zfa extension requires F extension");
> -        return;
> -    }
> -
> -    if (cpu->cfg.ext_zfh) {
> -        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zfhmin), true);
> -    }
> -
> -    if (cpu->cfg.ext_zfhmin && !riscv_has_ext(env, RVF)) {
> -        error_setg(errp, "Zfh/Zfhmin extensions require F extension");
> -        return;
> -    }
> -
> -    if (cpu->cfg.ext_zfbfmin && !riscv_has_ext(env, RVF)) {
> -        error_setg(errp, "Zfbfmin extension depends on F extension");
> -        return;
> -    }
> -
> -    if (riscv_has_ext(env, RVD) && !riscv_has_ext(env, RVF)) {
> -        error_setg(errp, "D extension requires F extension");
> -        return;
> -    }
> -
> -    if (riscv_has_ext(env, RVV)) {
> -        riscv_cpu_validate_v(env, &cpu->cfg, &local_err);
> -        if (local_err != NULL) {
> -            error_propagate(errp, local_err);
> -            return;
> -        }
> -
> -        /* The V vector extension depends on the Zve64d extension */
> -        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zve64d), true);
> -    }
> -
> -    /* The Zve64d extension depends on the Zve64f extension */
> -    if (cpu->cfg.ext_zve64d) {
> -        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zve64f), true);
> -    }
> -
> -    /* The Zve64f extension depends on the Zve32f extension */
> -    if (cpu->cfg.ext_zve64f) {
> -        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zve32f), true);
> -    }
> -
> -    if (cpu->cfg.ext_zve64d && !riscv_has_ext(env, RVD)) {
> -        error_setg(errp, "Zve64d/V extensions require D extension");
> -        return;
> -    }
> -
> -    if (cpu->cfg.ext_zve32f && !riscv_has_ext(env, RVF)) {
> -        error_setg(errp, "Zve32f/Zve64f extensions require F extension");
> -        return;
> -    }
> -
> -    if (cpu->cfg.ext_zvfh) {
> -        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zvfhmin), true);
> -    }
> -
> -    if (cpu->cfg.ext_zvfhmin && !cpu->cfg.ext_zve32f) {
> -        error_setg(errp, "Zvfh/Zvfhmin extensions require Zve32f extension");
> -        return;
> -    }
> -
> -    if (cpu->cfg.ext_zvfh && !cpu->cfg.ext_zfhmin) {
> -        error_setg(errp, "Zvfh extensions requires Zfhmin extension");
> -        return;
> -    }
> -
> -    if (cpu->cfg.ext_zvfbfmin && !cpu->cfg.ext_zfbfmin) {
> -        error_setg(errp, "Zvfbfmin extension depends on Zfbfmin extension");
> -        return;
> -    }
> -
> -    if (cpu->cfg.ext_zvfbfmin && !cpu->cfg.ext_zve32f) {
> -        error_setg(errp, "Zvfbfmin extension depends on Zve32f extension");
> -        return;
> -    }
> -
> -    if (cpu->cfg.ext_zvfbfwma && !cpu->cfg.ext_zvfbfmin) {
> -        error_setg(errp, "Zvfbfwma extension depends on Zvfbfmin extension");
> -        return;
> -    }
> -
> -    /* Set the ISA extensions, checks should have happened above */
> -    if (cpu->cfg.ext_zhinx) {
> -        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zca), true);
> -    }
> -
> -    if ((cpu->cfg.ext_zdinx || cpu->cfg.ext_zhinxmin) && !cpu->cfg.ext_zfinx) {
> -        error_setg(errp, "Zdinx/Zhinx/Zhinxmin extensions require Zfinx");
> -        return;
> -    }
> -
> -    if (cpu->cfg.ext_zfinx) {
> -        if (!cpu->cfg.ext_icsr) {
> -            error_setg(errp, "Zfinx extension requires Zicsr");
> -            return;
> -        }
> -        if (riscv_has_ext(env, RVF)) {
> -            error_setg(errp,
> -                       "Zfinx cannot be supported together with F extension");
> -            return;
> -        }
> -    }
> -
> -    if (cpu->cfg.ext_zce) {
> -        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zca), true);
> -        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zcb), true);
> -        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zcmp), true);
> -        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zcmt), true);
> -        if (riscv_has_ext(env, RVF) && env->misa_mxl_max == MXL_RV32) {
> -            cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zcf), true);
> -        }
> -    }
> -
> -    /* zca, zcd and zcf has a PRIV 1.12.0 restriction */
> -    if (riscv_has_ext(env, RVC) && env->priv_ver >= PRIV_VERSION_1_12_0) {
> -        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zca), true);
> -        if (riscv_has_ext(env, RVF) && env->misa_mxl_max == MXL_RV32) {
> -            cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zcf), true);
> -        }
> -        if (riscv_has_ext(env, RVD)) {
> -            cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zcd), true);
> -        }
> -    }
> -
> -    if (env->misa_mxl_max != MXL_RV32 && cpu->cfg.ext_zcf) {
> -        error_setg(errp, "Zcf extension is only relevant to RV32");
> -        return;
> -    }
> -
> -    if (!riscv_has_ext(env, RVF) && cpu->cfg.ext_zcf) {
> -        error_setg(errp, "Zcf extension requires F extension");
> -        return;
> -    }
> -
> -    if (!riscv_has_ext(env, RVD) && cpu->cfg.ext_zcd) {
> -        error_setg(errp, "Zcd extension requires D extension");
> -        return;
> -    }
> -
> -    if ((cpu->cfg.ext_zcf || cpu->cfg.ext_zcd || cpu->cfg.ext_zcb ||
> -         cpu->cfg.ext_zcmp || cpu->cfg.ext_zcmt) && !cpu->cfg.ext_zca) {
> -        error_setg(errp, "Zcf/Zcd/Zcb/Zcmp/Zcmt extensions require Zca "
> -                         "extension");
> -        return;
> -    }
> -
> -    if (cpu->cfg.ext_zcd && (cpu->cfg.ext_zcmp || cpu->cfg.ext_zcmt)) {
> -        error_setg(errp, "Zcmp/Zcmt extensions are incompatible with "
> -                         "Zcd extension");
> -        return;
> -    }
> -
> -    if (cpu->cfg.ext_zcmt && !cpu->cfg.ext_icsr) {
> -        error_setg(errp, "Zcmt extension requires Zicsr extension");
> -        return;
> -    }
> -
> -    /*
> -     * In principle Zve*x would also suffice here, were they supported
> -     * in qemu
> -     */
> -    if ((cpu->cfg.ext_zvbb || cpu->cfg.ext_zvkg || cpu->cfg.ext_zvkned ||
> -         cpu->cfg.ext_zvknha || cpu->cfg.ext_zvksed || cpu->cfg.ext_zvksh) &&
> -        !cpu->cfg.ext_zve32f) {
> -        error_setg(errp,
> -                   "Vector crypto extensions require V or Zve* extensions");
> -        return;
> -    }
> -
> -    if ((cpu->cfg.ext_zvbc || cpu->cfg.ext_zvknhb) && !cpu->cfg.ext_zve64f) {
> -        error_setg(
> -            errp,
> -            "Zvbc and Zvknhb extensions require V or Zve64{f,d} extensions");
> -        return;
> -    }
> -
> -    if (cpu->cfg.ext_zk) {
> -        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zkn), true);
> -        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zkr), true);
> -        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zkt), true);
> -    }
> -
> -    if (cpu->cfg.ext_zkn) {
> -        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zbkb), true);
> -        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zbkc), true);
> -        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zbkx), true);
> -        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zkne), true);
> -        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zknd), true);
> -        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zknh), true);
> -    }
> -
> -    if (cpu->cfg.ext_zks) {
> -        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zbkb), true);
> -        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zbkc), true);
> -        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zbkx), true);
> -        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zksed), true);
> -        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zksh), true);
> -    }
> -
> -    /*
> -     * Disable isa extensions based on priv spec after we
> -     * validated and set everything we need.
> -     */
> -    riscv_cpu_disable_priv_spec_isa_exts(cpu);
> -}
> -
>  #ifndef CONFIG_USER_ONLY
>  static void riscv_cpu_satp_mode_finalize(RISCVCPU *cpu, Error **errp)
>  {
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index b84b62f84e..721bd0b119 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -445,7 +445,6 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
>                          bool probe, uintptr_t retaddr);
>  char *riscv_isa_string(RISCVCPU *cpu);
>  void riscv_cpu_list(void);
> -void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp);
>  
>  #define cpu_list riscv_cpu_list
>  #define cpu_mmu_index riscv_cpu_mmu_index
> @@ -711,6 +710,13 @@ enum riscv_pmu_event_idx {
>  #include "hw/core/tcg-cpu-ops.h"
>  extern const struct TCGCPUOps riscv_tcg_ops;
>  
> +/* used by tcg/tcg-cpu.c*/
> +void isa_ext_update_enabled(RISCVCPU *cpu, uint32_t ext_offset, bool en);
> +bool cpu_cfg_ext_is_user_set(uint32_t ext_offset);
> +bool isa_ext_is_enabled(RISCVCPU *cpu, uint32_t ext_offset);
> +int cpu_cfg_ext_get_min_version(uint32_t ext_offset);

Shouldn't we rename the above functions with a 'riscv_cpu_' prefix now
that they're exported?

> +void riscv_cpu_disable_priv_spec_isa_exts(RISCVCPU *cpu);
> +
>  /* CSR function table */
>  extern riscv_csr_operations csr_ops[CSR_TABLE_SIZE];
>  
> diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> index 6145039832..65473b257f 100644
> --- a/target/riscv/csr.c
> +++ b/target/riscv/csr.c
> @@ -21,6 +21,7 @@
>  #include "qemu/log.h"
>  #include "qemu/timer.h"
>  #include "cpu.h"
> +#include "tcg/tcg-cpu.h"
>  #include "pmu.h"
>  #include "time_helper.h"
>  #include "qemu/main-loop.h"
> diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
> index b3d3f265d7..fb17097bb1 100644
> --- a/target/riscv/tcg/tcg-cpu.c
> +++ b/target/riscv/tcg/tcg-cpu.c
> @@ -18,14 +18,42 @@
>   */
>  
>  #include "qemu/osdep.h"
> +#include "tcg-cpu.h"
>  #include "cpu.h"
>  #include "pmu.h"
>  #include "time_helper.h"
>  #include "qapi/error.h"
>  #include "qemu/accel.h"
> +#include "qemu/error-report.h"
>  #include "hw/core/accel-cpu.h"
>  
>  
> +static void cpu_cfg_ext_auto_update(RISCVCPU *cpu, uint32_t ext_offset,
> +                                    bool value)
> +{
> +    CPURISCVState *env = &cpu->env;
> +    bool prev_val = isa_ext_is_enabled(cpu, ext_offset);
> +    int min_version;
> +
> +    if (prev_val == value) {
> +        return;
> +    }
> +
> +    if (cpu_cfg_ext_is_user_set(ext_offset)) {
> +        return;
> +    }
> +
> +    if (value && env->priv_ver != PRIV_VERSION_LATEST) {
> +        /* Do not enable it if priv_ver is older than min_version */
> +        min_version = cpu_cfg_ext_get_min_version(ext_offset);
> +        if (env->priv_ver < min_version) {
> +            return;
> +        }
> +    }
> +
> +    isa_ext_update_enabled(cpu, ext_offset, value);
> +}
> +
>  static void riscv_cpu_validate_misa_priv(CPURISCVState *env, Error **errp)
>  {
>      if (riscv_has_ext(env, RVH) && env->priv_ver < PRIV_VERSION_1_12_0) {
> @@ -84,6 +112,330 @@ static void riscv_cpu_validate_priv_spec(RISCVCPU *cpu, Error **errp)
>      }
>  }
>  
> +static void riscv_cpu_validate_v(CPURISCVState *env, RISCVCPUConfig *cfg,
> +                                 Error **errp)
> +{
> +    if (!is_power_of_2(cfg->vlen)) {
> +        error_setg(errp, "Vector extension VLEN must be power of 2");
> +        return;
> +    }
> +    if (cfg->vlen > RV_VLEN_MAX || cfg->vlen < 128) {
> +        error_setg(errp,
> +                   "Vector extension implementation only supports VLEN "
> +                   "in the range [128, %d]", RV_VLEN_MAX);
> +        return;
> +    }
> +    if (!is_power_of_2(cfg->elen)) {
> +        error_setg(errp, "Vector extension ELEN must be power of 2");
> +        return;
> +    }
> +    if (cfg->elen > 64 || cfg->elen < 8) {
> +        error_setg(errp,
> +                   "Vector extension implementation only supports ELEN "
> +                   "in the range [8, 64]");
> +        return;
> +    }
> +    if (cfg->vext_spec) {
> +        if (!g_strcmp0(cfg->vext_spec, "v1.0")) {
> +            env->vext_ver = VEXT_VERSION_1_00_0;
> +        } else {
> +            error_setg(errp, "Unsupported vector spec version '%s'",
> +                       cfg->vext_spec);
> +            return;
> +        }
> +    } else if (env->vext_ver == 0) {
> +        qemu_log("vector version is not specified, "
> +                 "use the default value v1.0\n");
> +
> +        env->vext_ver = VEXT_VERSION_1_00_0;
> +    }

Normally I wouldn't advocate for any changes to code while moving it, but
I think adding blank lines above each 'if' while moving this would be
fine. (For those that want to diff the code before and after a move, it
can still be done with an ignore-whitespace diff.)

> +}
> +
> +/*
> + * Check consistency between chosen extensions while setting
> + * cpu->cfg accordingly.
> + */
> +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_icsr && cpu->cfg.ext_ifencei)) {
> +        warn_report("Setting G will also set IMAFD_Zicsr_Zifencei");
> +
> +        if (cpu_cfg_ext_is_user_set(CPU_CFG_OFFSET(ext_icsr)) &&
> +            !cpu->cfg.ext_icsr) {
> +            error_setg(errp, "RVG requires Zicsr but user set Zicsr to false");
> +            return;
> +        }
> +
> +        if (cpu_cfg_ext_is_user_set(CPU_CFG_OFFSET(ext_ifencei)) &&
> +            !cpu->cfg.ext_ifencei) {
> +            error_setg(errp, "RVG requires Zifencei but user set "
> +                       "Zifencei to false");
> +            return;
> +        }
> +
> +        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_icsr), true);
> +        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_ifencei), true);
> +
> +        env->misa_ext |= RVI | RVM | RVA | RVF | RVD;
> +        env->misa_ext_mask |= RVI | RVM | RVA | RVF | RVD;
> +    }
> +
> +    if (riscv_has_ext(env, RVI) && riscv_has_ext(env, RVE)) {
> +        error_setg(errp,
> +                   "I and E extensions are incompatible");
> +        return;
> +    }
> +
> +    if (!riscv_has_ext(env, RVI) && !riscv_has_ext(env, RVE)) {
> +        error_setg(errp,
> +                   "Either I or E extension must be set");
> +        return;
> +    }
> +
> +    if (riscv_has_ext(env, RVS) && !riscv_has_ext(env, RVU)) {
> +        error_setg(errp,
> +                   "Setting S extension without U extension is illegal");
> +        return;
> +    }
> +
> +    if (riscv_has_ext(env, RVH) && !riscv_has_ext(env, RVI)) {
> +        error_setg(errp,
> +                   "H depends on an I base integer ISA with 32 x registers");
> +        return;
> +    }
> +
> +    if (riscv_has_ext(env, RVH) && !riscv_has_ext(env, RVS)) {
> +        error_setg(errp, "H extension implicitly requires S-mode");
> +        return;
> +    }
> +
> +    if (riscv_has_ext(env, RVF) && !cpu->cfg.ext_icsr) {
> +        error_setg(errp, "F extension requires Zicsr");
> +        return;
> +    }
> +
> +    if ((cpu->cfg.ext_zawrs) && !riscv_has_ext(env, RVA)) {
> +        error_setg(errp, "Zawrs extension requires A extension");
> +        return;
> +    }
> +
> +    if (cpu->cfg.ext_zfa && !riscv_has_ext(env, RVF)) {
> +        error_setg(errp, "Zfa extension requires F extension");
> +        return;
> +    }
> +
> +    if (cpu->cfg.ext_zfh) {
> +        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zfhmin), true);
> +    }
> +
> +    if (cpu->cfg.ext_zfhmin && !riscv_has_ext(env, RVF)) {
> +        error_setg(errp, "Zfh/Zfhmin extensions require F extension");
> +        return;
> +    }
> +
> +    if (cpu->cfg.ext_zfbfmin && !riscv_has_ext(env, RVF)) {
> +        error_setg(errp, "Zfbfmin extension depends on F extension");
> +        return;
> +    }
> +
> +    if (riscv_has_ext(env, RVD) && !riscv_has_ext(env, RVF)) {
> +        error_setg(errp, "D extension requires F extension");
> +        return;
> +    }
> +
> +    if (riscv_has_ext(env, RVV)) {
> +        riscv_cpu_validate_v(env, &cpu->cfg, &local_err);
> +        if (local_err != NULL) {
> +            error_propagate(errp, local_err);
> +            return;
> +        }
> +
> +        /* The V vector extension depends on the Zve64d extension */
> +        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zve64d), true);
> +    }
> +
> +    /* The Zve64d extension depends on the Zve64f extension */
> +    if (cpu->cfg.ext_zve64d) {
> +        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zve64f), true);
> +    }
> +
> +    /* The Zve64f extension depends on the Zve32f extension */
> +    if (cpu->cfg.ext_zve64f) {
> +        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zve32f), true);
> +    }
> +
> +    if (cpu->cfg.ext_zve64d && !riscv_has_ext(env, RVD)) {
> +        error_setg(errp, "Zve64d/V extensions require D extension");
> +        return;
> +    }
> +
> +    if (cpu->cfg.ext_zve32f && !riscv_has_ext(env, RVF)) {
> +        error_setg(errp, "Zve32f/Zve64f extensions require F extension");
> +        return;
> +    }
> +
> +    if (cpu->cfg.ext_zvfh) {
> +        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zvfhmin), true);
> +    }
> +
> +    if (cpu->cfg.ext_zvfhmin && !cpu->cfg.ext_zve32f) {
> +        error_setg(errp, "Zvfh/Zvfhmin extensions require Zve32f extension");
> +        return;
> +    }
> +
> +    if (cpu->cfg.ext_zvfh && !cpu->cfg.ext_zfhmin) {
> +        error_setg(errp, "Zvfh extensions requires Zfhmin extension");
> +        return;
> +    }
> +
> +    if (cpu->cfg.ext_zvfbfmin && !cpu->cfg.ext_zfbfmin) {
> +        error_setg(errp, "Zvfbfmin extension depends on Zfbfmin extension");
> +        return;
> +    }
> +
> +    if (cpu->cfg.ext_zvfbfmin && !cpu->cfg.ext_zve32f) {
> +        error_setg(errp, "Zvfbfmin extension depends on Zve32f extension");
> +        return;
> +    }
> +
> +    if (cpu->cfg.ext_zvfbfwma && !cpu->cfg.ext_zvfbfmin) {
> +        error_setg(errp, "Zvfbfwma extension depends on Zvfbfmin extension");
> +        return;
> +    }
> +
> +    /* Set the ISA extensions, checks should have happened above */
> +    if (cpu->cfg.ext_zhinx) {
> +        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zca), true);
> +    }
> +
> +    if ((cpu->cfg.ext_zdinx || cpu->cfg.ext_zhinxmin) && !cpu->cfg.ext_zfinx) {
> +        error_setg(errp, "Zdinx/Zhinx/Zhinxmin extensions require Zfinx");
> +        return;
> +    }
> +
> +    if (cpu->cfg.ext_zfinx) {
> +        if (!cpu->cfg.ext_icsr) {
> +            error_setg(errp, "Zfinx extension requires Zicsr");
> +            return;
> +        }
> +        if (riscv_has_ext(env, RVF)) {
> +            error_setg(errp,
> +                       "Zfinx cannot be supported together with F extension");
> +            return;
> +        }
> +    }
> +
> +    if (cpu->cfg.ext_zce) {
> +        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zca), true);
> +        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zcb), true);
> +        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zcmp), true);
> +        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zcmt), true);
> +        if (riscv_has_ext(env, RVF) && env->misa_mxl_max == MXL_RV32) {
> +            cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zcf), true);
> +        }
> +    }
> +
> +    /* zca, zcd and zcf has a PRIV 1.12.0 restriction */
> +    if (riscv_has_ext(env, RVC) && env->priv_ver >= PRIV_VERSION_1_12_0) {
> +        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zca), true);
> +        if (riscv_has_ext(env, RVF) && env->misa_mxl_max == MXL_RV32) {
> +            cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zcf), true);
> +        }
> +        if (riscv_has_ext(env, RVD)) {
> +            cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zcd), true);
> +        }
> +    }
> +
> +    if (env->misa_mxl_max != MXL_RV32 && cpu->cfg.ext_zcf) {
> +        error_setg(errp, "Zcf extension is only relevant to RV32");
> +        return;
> +    }
> +
> +    if (!riscv_has_ext(env, RVF) && cpu->cfg.ext_zcf) {
> +        error_setg(errp, "Zcf extension requires F extension");
> +        return;
> +    }
> +
> +    if (!riscv_has_ext(env, RVD) && cpu->cfg.ext_zcd) {
> +        error_setg(errp, "Zcd extension requires D extension");
> +        return;
> +    }
> +
> +    if ((cpu->cfg.ext_zcf || cpu->cfg.ext_zcd || cpu->cfg.ext_zcb ||
> +         cpu->cfg.ext_zcmp || cpu->cfg.ext_zcmt) && !cpu->cfg.ext_zca) {
> +        error_setg(errp, "Zcf/Zcd/Zcb/Zcmp/Zcmt extensions require Zca "
> +                         "extension");
> +        return;
> +    }
> +
> +    if (cpu->cfg.ext_zcd && (cpu->cfg.ext_zcmp || cpu->cfg.ext_zcmt)) {
> +        error_setg(errp, "Zcmp/Zcmt extensions are incompatible with "
> +                         "Zcd extension");
> +        return;
> +    }
> +
> +    if (cpu->cfg.ext_zcmt && !cpu->cfg.ext_icsr) {
> +        error_setg(errp, "Zcmt extension requires Zicsr extension");
> +        return;
> +    }
> +
> +    /*
> +     * In principle Zve*x would also suffice here, were they supported
> +     * in qemu
> +     */
> +    if ((cpu->cfg.ext_zvbb || cpu->cfg.ext_zvkg || cpu->cfg.ext_zvkned ||
> +         cpu->cfg.ext_zvknha || cpu->cfg.ext_zvksed || cpu->cfg.ext_zvksh) &&
> +        !cpu->cfg.ext_zve32f) {
> +        error_setg(errp,
> +                   "Vector crypto extensions require V or Zve* extensions");
> +        return;
> +    }
> +
> +    if ((cpu->cfg.ext_zvbc || cpu->cfg.ext_zvknhb) && !cpu->cfg.ext_zve64f) {
> +        error_setg(
> +            errp,
> +            "Zvbc and Zvknhb extensions require V or Zve64{f,d} extensions");
> +        return;
> +    }
> +
> +    if (cpu->cfg.ext_zk) {
> +        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zkn), true);
> +        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zkr), true);
> +        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zkt), true);
> +    }
> +
> +    if (cpu->cfg.ext_zkn) {
> +        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zbkb), true);
> +        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zbkc), true);
> +        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zbkx), true);
> +        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zkne), true);
> +        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zknd), true);
> +        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zknh), true);
> +    }
> +
> +    if (cpu->cfg.ext_zks) {
> +        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zbkb), true);
> +        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zbkc), true);
> +        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zbkx), true);
> +        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zksed), true);
> +        cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zksh), true);
> +    }
> +
> +    /*
> +     * Disable isa extensions based on priv spec after we
> +     * validated and set everything we need.
> +     */
> +    riscv_cpu_disable_priv_spec_isa_exts(cpu);
> +}
> +
>  /*
>   * We'll get here via the following path:
>   *
> diff --git a/target/riscv/tcg/tcg-cpu.h b/target/riscv/tcg/tcg-cpu.h
> new file mode 100644
> index 0000000000..4cf35a8015
> --- /dev/null
> +++ b/target/riscv/tcg/tcg-cpu.h
> @@ -0,0 +1,28 @@
> +/*
> + * riscv TCG cpu class initialization
> + *
> + * Copyright (c) 2023 Ventana Micro Systems Inc.
> + *
> + * This library is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2 of the License, or (at your option) any later version.
> + *
> + * This library is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with this library; if not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#ifndef RISCV_TCG_CPU_H
> +#define RISCV_TCG_CPU_H
> +
> +#include "cpu.h"
> +
> +void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp);
> +
> +#endif
> +
> -- 
> 2.41.0
> 
>

Otherwise,

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


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

* Re: [PATCH 04/20] target/riscv: move riscv_tcg_ops to tcg-cpu.c
  2023-08-25 13:08 ` [PATCH 04/20] target/riscv: move riscv_tcg_ops " Daniel Henrique Barboza
  2023-08-28 16:30   ` Philippe Mathieu-Daudé
@ 2023-08-31 10:38   ` Andrew Jones
  1 sibling, 0 replies; 51+ messages in thread
From: Andrew Jones @ 2023-08-31 10:38 UTC (permalink / raw)
  To: Daniel Henrique Barboza
  Cc: qemu-devel, qemu-riscv, alistair.francis, bmeng, liweiwei,
	zhiwei_liu, palmer

On Fri, Aug 25, 2023 at 10:08:37AM -0300, Daniel Henrique Barboza wrote:
> Move the remaining of riscv_tcg_ops now that we have a working realize()
> implementation.
> 
> Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
> ---
>  target/riscv/cpu.c         | 58 -------------------------------------
>  target/riscv/cpu.h         |  4 ---
>  target/riscv/tcg/tcg-cpu.c | 59 ++++++++++++++++++++++++++++++++++++++
>  3 files changed, 59 insertions(+), 62 deletions(-)
> 
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index 12cea62ee7..839b83e52a 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -839,24 +839,6 @@ static vaddr riscv_cpu_get_pc(CPUState *cs)
>      return env->pc;
>  }
>  
> -static void riscv_cpu_synchronize_from_tb(CPUState *cs,
> -                                          const TranslationBlock *tb)
> -{
> -    if (!(tb_cflags(tb) & CF_PCREL)) {
> -        RISCVCPU *cpu = RISCV_CPU(cs);
> -        CPURISCVState *env = &cpu->env;
> -        RISCVMXL xl = FIELD_EX32(tb->flags, TB_FLAGS, XL);
> -
> -        tcg_debug_assert(!(cs->tcg_cflags & CF_PCREL));
> -
> -        if (xl == MXL_RV32) {
> -            env->pc = (int32_t) tb->pc;
> -        } else {
> -            env->pc = tb->pc;
> -        }
> -    }
> -}
> -
>  static bool riscv_cpu_has_work(CPUState *cs)
>  {
>  #ifndef CONFIG_USER_ONLY
> @@ -872,29 +854,6 @@ static bool riscv_cpu_has_work(CPUState *cs)
>  #endif
>  }
>  
> -static void riscv_restore_state_to_opc(CPUState *cs,
> -                                       const TranslationBlock *tb,
> -                                       const uint64_t *data)
> -{
> -    RISCVCPU *cpu = RISCV_CPU(cs);
> -    CPURISCVState *env = &cpu->env;
> -    RISCVMXL xl = FIELD_EX32(tb->flags, TB_FLAGS, XL);
> -    target_ulong pc;
> -
> -    if (tb_cflags(tb) & CF_PCREL) {
> -        pc = (env->pc & TARGET_PAGE_MASK) | data[0];
> -    } else {
> -        pc = data[0];
> -    }
> -
> -    if (xl == MXL_RV32) {
> -        env->pc = (int32_t)pc;
> -    } else {
> -        env->pc = pc;
> -    }
> -    env->bins = data[1];
> -}
> -
>  static void riscv_cpu_reset_hold(Object *obj)
>  {
>  #ifndef CONFIG_USER_ONLY
> @@ -1796,23 +1755,6 @@ static const struct SysemuCPUOps riscv_sysemu_ops = {
>  };
>  #endif
>  
> -const struct TCGCPUOps riscv_tcg_ops = {
> -    .initialize = riscv_translate_init,
> -    .synchronize_from_tb = riscv_cpu_synchronize_from_tb,
> -    .restore_state_to_opc = riscv_restore_state_to_opc,
> -
> -#ifndef CONFIG_USER_ONLY
> -    .tlb_fill = riscv_cpu_tlb_fill,
> -    .cpu_exec_interrupt = riscv_cpu_exec_interrupt,
> -    .do_interrupt = riscv_cpu_do_interrupt,
> -    .do_transaction_failed = riscv_cpu_do_transaction_failed,
> -    .do_unaligned_access = riscv_cpu_do_unaligned_access,
> -    .debug_excp_handler = riscv_cpu_debug_excp_handler,
> -    .debug_check_breakpoint = riscv_cpu_debug_check_breakpoint,
> -    .debug_check_watchpoint = riscv_cpu_debug_check_watchpoint,
> -#endif /* !CONFIG_USER_ONLY */
> -};
> -
>  static bool riscv_cpu_is_dynamic(Object *cpu_obj)
>  {
>      return object_dynamic_cast(cpu_obj, TYPE_RISCV_DYNAMIC_CPU) != NULL;
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index 721bd0b119..2ac00a0304 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -706,10 +706,6 @@ enum riscv_pmu_event_idx {
>      RISCV_PMU_EVENT_CACHE_ITLB_PREFETCH_MISS = 0x10021,
>  };
>  
> -/* Export tcg_ops until we move everything to tcg/tcg-cpu.c */
> -#include "hw/core/tcg-cpu-ops.h"
> -extern const struct TCGCPUOps riscv_tcg_ops;
> -
>  /* used by tcg/tcg-cpu.c*/
>  void isa_ext_update_enabled(RISCVCPU *cpu, uint32_t ext_offset, bool en);
>  bool cpu_cfg_ext_is_user_set(uint32_t ext_offset);
> diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
> index fb17097bb1..2024c98793 100644
> --- a/target/riscv/tcg/tcg-cpu.c
> +++ b/target/riscv/tcg/tcg-cpu.c
> @@ -26,7 +26,66 @@
>  #include "qemu/accel.h"
>  #include "qemu/error-report.h"
>  #include "hw/core/accel-cpu.h"
> +#include "hw/core/tcg-cpu-ops.h"
> +#include "tcg/tcg.h"
>  
> +static void riscv_cpu_synchronize_from_tb(CPUState *cs,
> +                                          const TranslationBlock *tb)
> +{
> +    if (!(tb_cflags(tb) & CF_PCREL)) {
> +        RISCVCPU *cpu = RISCV_CPU(cs);
> +        CPURISCVState *env = &cpu->env;
> +        RISCVMXL xl = FIELD_EX32(tb->flags, TB_FLAGS, XL);
> +
> +        tcg_debug_assert(!(cs->tcg_cflags & CF_PCREL));
> +
> +        if (xl == MXL_RV32) {
> +            env->pc = (int32_t) tb->pc;
> +        } else {
> +            env->pc = tb->pc;
> +        }
> +    }
> +}
> +
> +static void riscv_restore_state_to_opc(CPUState *cs,
> +                                       const TranslationBlock *tb,
> +                                       const uint64_t *data)
> +{
> +    RISCVCPU *cpu = RISCV_CPU(cs);
> +    CPURISCVState *env = &cpu->env;
> +    RISCVMXL xl = FIELD_EX32(tb->flags, TB_FLAGS, XL);
> +    target_ulong pc;
> +
> +    if (tb_cflags(tb) & CF_PCREL) {
> +        pc = (env->pc & TARGET_PAGE_MASK) | data[0];
> +    } else {
> +        pc = data[0];
> +    }
> +
> +    if (xl == MXL_RV32) {
> +        env->pc = (int32_t)pc;
> +    } else {
> +        env->pc = pc;
> +    }
> +    env->bins = data[1];
> +}
> +
> +const struct TCGCPUOps riscv_tcg_ops = {

This can be static again.

> +    .initialize = riscv_translate_init,
> +    .synchronize_from_tb = riscv_cpu_synchronize_from_tb,
> +    .restore_state_to_opc = riscv_restore_state_to_opc,
> +
> +#ifndef CONFIG_USER_ONLY
> +    .tlb_fill = riscv_cpu_tlb_fill,
> +    .cpu_exec_interrupt = riscv_cpu_exec_interrupt,
> +    .do_interrupt = riscv_cpu_do_interrupt,
> +    .do_transaction_failed = riscv_cpu_do_transaction_failed,
> +    .do_unaligned_access = riscv_cpu_do_unaligned_access,
> +    .debug_excp_handler = riscv_cpu_debug_excp_handler,
> +    .debug_check_breakpoint = riscv_cpu_debug_check_breakpoint,
> +    .debug_check_watchpoint = riscv_cpu_debug_check_watchpoint,
> +#endif /* !CONFIG_USER_ONLY */
> +};
>  
>  static void cpu_cfg_ext_auto_update(RISCVCPU *cpu, uint32_t ext_offset,
>                                      bool value)
> -- 
> 2.41.0
> 
>

With the above static change and Phil's remove comment change,

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


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

* Re: [PATCH 07/20] target/riscv/cpu.c: add .instance_post_init()
  2023-08-25 13:08 ` [PATCH 07/20] target/riscv/cpu.c: add .instance_post_init() Daniel Henrique Barboza
@ 2023-08-31 11:00   ` Andrew Jones
  2023-09-01 20:08     ` Daniel Henrique Barboza
  0 siblings, 1 reply; 51+ messages in thread
From: Andrew Jones @ 2023-08-31 11:00 UTC (permalink / raw)
  To: Daniel Henrique Barboza
  Cc: qemu-devel, qemu-riscv, alistair.francis, bmeng, liweiwei,
	zhiwei_liu, palmer

On Fri, Aug 25, 2023 at 10:08:40AM -0300, Daniel Henrique Barboza wrote:
> All generic CPUs call riscv_cpu_add_user_properties(). The 'max' CPU
> calls riscv_init_max_cpu_extensions(). Both can be moved to a common
> instance_post_init() callback, implemented in riscv_cpu_post_init(),
> called by all CPUs. The call order then becomes:
> 
> riscv_cpu_init() -> cpu_init() of each CPU -> .instance_post_init()
> 
> A CPU class that wants to add user flags will let us know via the
> 'user_extension_properties' property. Likewise, 'cfg.max_features' will
> determine if any given CPU, regardless of being the 'max' CPU or not,
> wants to enable the maximum amount of extensions.
> 
> In the near future riscv_cpu_post_init() will call the init() function
> of the current accelerator, providing a hook for KVM and TCG accel
> classes to change the init() process of the CPU.
> 
> Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
> ---
>  target/riscv/cpu.c | 20 +++++++++++++++-----
>  1 file changed, 15 insertions(+), 5 deletions(-)
> 
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index c35d58c64b..f67b782675 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -430,8 +430,6 @@ static void riscv_max_cpu_init(Object *obj)
>      mlx = MXL_RV32;
>  #endif
>      set_misa(env, mlx, 0);
> -    riscv_cpu_add_user_properties(obj);
> -    riscv_init_max_cpu_extensions(obj);
>      env->priv_ver = PRIV_VERSION_LATEST;
>  #ifndef CONFIG_USER_ONLY
>      set_satp_mode_max_supported(RISCV_CPU(obj), mlx == MXL_RV32 ?
> @@ -445,7 +443,6 @@ static void rv64_base_cpu_init(Object *obj)
>      CPURISCVState *env = &RISCV_CPU(obj)->env;
>      /* We set this in the realise function */
>      set_misa(env, MXL_RV64, 0);
> -    riscv_cpu_add_user_properties(obj);
>      /* Set latest version of privileged specification */
>      env->priv_ver = PRIV_VERSION_LATEST;
>  #ifndef CONFIG_USER_ONLY
> @@ -569,7 +566,6 @@ static void rv128_base_cpu_init(Object *obj)
>      CPURISCVState *env = &RISCV_CPU(obj)->env;
>      /* We set this in the realise function */
>      set_misa(env, MXL_RV128, 0);
> -    riscv_cpu_add_user_properties(obj);
>      /* Set latest version of privileged specification */
>      env->priv_ver = PRIV_VERSION_LATEST;
>  #ifndef CONFIG_USER_ONLY
> @@ -582,7 +578,6 @@ static void rv32_base_cpu_init(Object *obj)
>      CPURISCVState *env = &RISCV_CPU(obj)->env;
>      /* We set this in the realise function */
>      set_misa(env, MXL_RV32, 0);
> -    riscv_cpu_add_user_properties(obj);
>      /* Set latest version of privileged specification */
>      env->priv_ver = PRIV_VERSION_LATEST;
>  #ifndef CONFIG_USER_ONLY
> @@ -1212,6 +1207,20 @@ static void riscv_cpu_set_irq(void *opaque, int irq, int level)
>  }
>  #endif /* CONFIG_USER_ONLY */
>  
> +static void riscv_cpu_post_init(Object *obj)
> +{
> +    RISCVCPU *cpu = RISCV_CPU(obj);
> +    RISCVCPUClass *rcc = RISCV_CPU_GET_CLASS(cpu);
> +
> +    if (rcc->user_extension_properties) {

It's not yet clear to me why we need 'user_extension_properties'. Can't we
just do the 'object_dynamic_cast(obj, TYPE_RISCV_DYNAMIC_CPU) != NULL'
check here?

> +        riscv_cpu_add_user_properties(obj);
> +    }
> +
> +    if (cpu->cfg.max_features) {

It's also not yet clear why we need max_features. I can't think of any
other models that want max_features besides 'max'. Checking the cpu type
here should be sufficient, no?

> +        riscv_init_max_cpu_extensions(obj);
> +    }
> +}
> +
>  static void riscv_cpu_init(Object *obj)
>  {
>      RISCVCPU *cpu = RISCV_CPU(obj);
> @@ -2019,6 +2028,7 @@ static const TypeInfo riscv_cpu_type_infos[] = {
>          .instance_size = sizeof(RISCVCPU),
>          .instance_align = __alignof__(RISCVCPU),
>          .instance_init = riscv_cpu_init,
> +        .instance_post_init = riscv_cpu_post_init,
>          .abstract = true,
>          .class_size = sizeof(RISCVCPUClass),
>          .class_init = riscv_cpu_class_init,
> -- 
> 2.41.0
> 
>

Thanks,
drew


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

* Re: [PATCH 08/20] target/riscv: move 'host' CPU declaration to kvm.c
  2023-08-25 13:08 ` [PATCH 08/20] target/riscv: move 'host' CPU declaration to kvm.c Daniel Henrique Barboza
  2023-08-28 16:35   ` Philippe Mathieu-Daudé
@ 2023-08-31 11:04   ` Andrew Jones
  1 sibling, 0 replies; 51+ messages in thread
From: Andrew Jones @ 2023-08-31 11:04 UTC (permalink / raw)
  To: Daniel Henrique Barboza
  Cc: qemu-devel, qemu-riscv, alistair.francis, bmeng, liweiwei,
	zhiwei_liu, palmer

On Fri, Aug 25, 2023 at 10:08:41AM -0300, Daniel Henrique Barboza wrote:
> This CPU only exists if we're compiling with KVM so move it to the kvm
> specific file. While we're at it, change its class_init() to enable the
> user_extensions_flag class property, sparing us from having to execute
> riscv_cpu_add_user_properties() by hand and letting the post_init() hook
> do the work.
> 
> Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
> ---
>  target/riscv/cpu.c | 23 -----------------------
>  target/riscv/kvm.c | 29 +++++++++++++++++++++++++++++
>  2 files changed, 29 insertions(+), 23 deletions(-)
> 
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index f67b782675..dbf81796d2 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -655,19 +655,6 @@ static void rv32_imafcu_nommu_cpu_init(Object *obj)
>  }
>  #endif
>  
> -#if defined(CONFIG_KVM)
> -static void riscv_host_cpu_init(Object *obj)
> -{
> -    CPURISCVState *env = &RISCV_CPU(obj)->env;
> -#if defined(TARGET_RISCV32)
> -    set_misa(env, MXL_RV32, 0);
> -#elif defined(TARGET_RISCV64)
> -    set_misa(env, MXL_RV64, 0);
> -#endif
> -    riscv_cpu_add_user_properties(obj);
> -}
> -#endif /* CONFIG_KVM */
> -
>  static ObjectClass *riscv_cpu_class_by_name(const char *cpu_model)
>  {
>      ObjectClass *oc;
> @@ -2000,13 +1987,6 @@ static void riscv_vendor_cpu_class_init(ObjectClass *c, void *data)
>      rcc->user_extension_properties = false;
>  }
>  
> -#define DEFINE_CPU(type_name, initfn)      \
> -    {                                      \
> -        .name = type_name,                 \
> -        .parent = TYPE_RISCV_CPU,          \
> -        .instance_init = initfn            \
> -    }
> -
>  #define DEFINE_DYNAMIC_CPU(type_name, initfn) \
>      {                                         \
>          .name = type_name,                    \
> @@ -2047,9 +2027,6 @@ static const TypeInfo riscv_cpu_type_infos[] = {
>      },
>      DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_ANY,      riscv_any_cpu_init),
>      DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_MAX,      riscv_max_cpu_init),
> -#if defined(CONFIG_KVM)
> -    DEFINE_CPU(TYPE_RISCV_CPU_HOST,             riscv_host_cpu_init),
> -#endif
>  #if defined(TARGET_RISCV32)
>      DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_BASE32,   rv32_base_cpu_init),
>      DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_IBEX,             rv32_ibex_cpu_init),
> diff --git a/target/riscv/kvm.c b/target/riscv/kvm.c
> index 7c6dec05e3..59004caa8e 100644
> --- a/target/riscv/kvm.c
> +++ b/target/riscv/kvm.c
> @@ -1217,3 +1217,32 @@ void kvm_riscv_aia_create(MachineState *machine, uint64_t group_shift,
>  
>      kvm_msi_via_irqfd_allowed = kvm_irqfds_enabled();
>  }
> +
> +static void riscv_host_cpu_init(Object *obj)
> +{
> +    CPURISCVState *env = &RISCV_CPU(obj)->env;
> +
> +#if defined(TARGET_RISCV32)
> +    env->misa_mxl_max = env->misa_mxl = MXL_RV32;
> +#elif defined(TARGET_RISCV64)
> +    env->misa_mxl_max = env->misa_mxl = MXL_RV64;
> +#endif
> +}
> +
> +static void riscv_kvm_cpu_class_init(ObjectClass *c, void *data)
> +{
> +    RISCVCPUClass *rcc = RISCV_CPU_CLASS(c);
> +
> +    rcc->user_extension_properties = true;
> +}
> +
> +static const TypeInfo riscv_kvm_cpu_type_infos[] = {
> +    {
> +        .name = TYPE_RISCV_CPU_HOST,
> +        .parent = TYPE_RISCV_CPU,
> +        .instance_init = riscv_host_cpu_init,
> +        .class_init = riscv_kvm_cpu_class_init,
> +    }
> +};
> +
> +DEFINE_TYPES(riscv_kvm_cpu_type_infos)
> -- 
> 2.41.0
> 
>

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


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

* Re: [PATCH 09/20] target/riscv/cpu.c: mark extensions arrays as 'const'
  2023-08-25 13:08 ` [PATCH 09/20] target/riscv/cpu.c: mark extensions arrays as 'const' Daniel Henrique Barboza
@ 2023-08-31 11:10   ` Andrew Jones
  0 siblings, 0 replies; 51+ messages in thread
From: Andrew Jones @ 2023-08-31 11:10 UTC (permalink / raw)
  To: Daniel Henrique Barboza
  Cc: qemu-devel, qemu-riscv, alistair.francis, bmeng, liweiwei,
	zhiwei_liu, palmer

On Fri, Aug 25, 2023 at 10:08:42AM -0300, Daniel Henrique Barboza wrote:
> We'll need to export these arrays to the accelerator classes in the next
> patches. Mark them as 'const' now to minimize changes in the future.

Not to "minimize changes in the future", but "because they should
not be modified at runtime".

> 
> Note that 'riscv_cpu_options' will also be exported, but can't be marked
> as 'const', because the properties are changed via
> qdev_property_add_static().
> 
> Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
> ---
>  target/riscv/cpu.c | 22 +++++++++++++---------
>  1 file changed, 13 insertions(+), 9 deletions(-)
> 
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index dbf81796d2..4eda853f1d 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -1381,7 +1381,7 @@ typedef struct RISCVCPUMultiExtConfig {
>      {.name = _name, .offset = CPU_CFG_OFFSET(_prop), \
>       .enabled = _defval}
>  
> -static RISCVCPUMultiExtConfig riscv_cpu_extensions[] = {
> +static const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = {
>      /* Defaults for standard extensions */
>      MULTI_EXT_CFG_BOOL("sscofpmf", ext_sscofpmf, false),
>      MULTI_EXT_CFG_BOOL("Zifencei", ext_ifencei, true),
> @@ -1441,7 +1441,7 @@ static RISCVCPUMultiExtConfig riscv_cpu_extensions[] = {
>      DEFINE_PROP_END_OF_LIST(),
>  };
>  
> -static RISCVCPUMultiExtConfig riscv_cpu_vendor_exts[] = {
> +static const RISCVCPUMultiExtConfig riscv_cpu_vendor_exts[] = {
>      MULTI_EXT_CFG_BOOL("xtheadba", ext_xtheadba, false),
>      MULTI_EXT_CFG_BOOL("xtheadbb", ext_xtheadbb, false),
>      MULTI_EXT_CFG_BOOL("xtheadbs", ext_xtheadbs, false),
> @@ -1459,7 +1459,7 @@ static RISCVCPUMultiExtConfig riscv_cpu_vendor_exts[] = {
>  };
>  
>  /* These are experimental so mark with 'x-' */
> -static RISCVCPUMultiExtConfig riscv_cpu_experimental_exts[] = {
> +static const RISCVCPUMultiExtConfig riscv_cpu_experimental_exts[] = {
>      MULTI_EXT_CFG_BOOL("x-zicond", ext_zicond, false),
>  
>      /* ePMP 0.9.3 */
> @@ -1532,7 +1532,7 @@ static void cpu_get_multi_ext_cfg(Object *obj, Visitor *v, const char *name,
>  }
>  
>  static void cpu_add_multi_ext_prop(Object *cpu_obj,
> -                                   RISCVCPUMultiExtConfig *multi_cfg)
> +                                   const RISCVCPUMultiExtConfig *multi_cfg)
>  {
>      object_property_add(cpu_obj, multi_cfg->name, "bool",
>                          cpu_get_multi_ext_cfg,
> @@ -1568,9 +1568,11 @@ static void cpu_set_cfg_unavailable(Object *obj, Visitor *v,
>  #endif
>  
>  static void riscv_cpu_add_multiext_prop_array(Object *obj,
> -                                              RISCVCPUMultiExtConfig *array)
> +                                        const RISCVCPUMultiExtConfig *array)
>  {
> -    for (RISCVCPUMultiExtConfig *prop = array; prop && prop->name; prop++) {
> +    const RISCVCPUMultiExtConfig *prop;
> +
> +    for (prop = array; prop && prop->name; prop++) {
>          cpu_add_multi_ext_prop(obj, prop);
>      }
>  }
> @@ -1594,9 +1596,11 @@ static void riscv_cpu_add_kvm_unavail_prop(Object *obj, const char *prop_name)
>  }
>  
>  static void riscv_cpu_add_kvm_unavail_prop_array(Object *obj,
> -                                                 RISCVCPUMultiExtConfig *array)
> +                                        const RISCVCPUMultiExtConfig *array)
>  {
> -    for (RISCVCPUMultiExtConfig *prop = array; prop && prop->name; prop++) {
> +    const RISCVCPUMultiExtConfig *prop;
> +
> +    for (prop = array; prop && prop->name; prop++) {
>          riscv_cpu_add_kvm_unavail_prop(obj, prop->name);
>      }
>  }
> @@ -1659,7 +1663,7 @@ static void riscv_init_max_cpu_extensions(Object *obj)
>  {
>      RISCVCPU *cpu = RISCV_CPU(obj);
>      CPURISCVState *env = &cpu->env;
> -    RISCVCPUMultiExtConfig *prop;
> +    const RISCVCPUMultiExtConfig *prop;
>  
>      /* Enable RVG, RVJ and RVV that are disabled by default */
>      set_misa(env, env->misa_mxl, env->misa_ext | RVG | RVJ | RVV);
> -- 
> 2.41.0
> 
>

Other than the commit message change,

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


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

* Re: [PATCH 10/20] target/riscv: move riscv_cpu_add_kvm_properties() to kvm.c
  2023-08-25 13:08 ` [PATCH 10/20] target/riscv: move riscv_cpu_add_kvm_properties() to kvm.c Daniel Henrique Barboza
@ 2023-08-31 11:22   ` Andrew Jones
  0 siblings, 0 replies; 51+ messages in thread
From: Andrew Jones @ 2023-08-31 11:22 UTC (permalink / raw)
  To: Daniel Henrique Barboza
  Cc: qemu-devel, qemu-riscv, alistair.francis, bmeng, liweiwei,
	zhiwei_liu, palmer

On Fri, Aug 25, 2023 at 10:08:43AM -0300, Daniel Henrique Barboza wrote:
> We'll introduce the KVM accelerator class with a 'cpu_instance_init'
> implementation that is going to be invoked during the common
> riscv_cpu_post_init() (via accel_cpu_instance_init()). This
> instance_init will execute KVM exclusive code that TCG doesn't care
> about, such as adding KVM specific properties, initing registers using a
> KVM scratch CPU and so on.
> 
> The core of the forementioned cpu_instance_init impl is the current
> riscv_cpu_add_kvm_properties() that is being used by the common code via
> riscv_cpu_add_user_properties() in cpu.c. Move it to kvm.c, together
> will all the relevant artifacts, exporting and renaming it to
> kvm_riscv_cpu_add_kvm_properties() so cpu.c can keep using it for now.
> 
> To make this work we'll need to export riscv_cpu_extensions,
> riscv_cpu_vendor_exts and riscv_cpu_experimental_exts from cpu.c as
> well. The TCG accelerator will also need to access those in the near
> future so this export will benefit us in the long run.
> 
> Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
> ---
>  target/riscv/cpu.c       | 87 +++-------------------------------------
>  target/riscv/cpu.h       | 14 +++++++
>  target/riscv/kvm.c       | 66 +++++++++++++++++++++++++++++-
>  target/riscv/kvm_riscv.h |  2 +-
>  4 files changed, 86 insertions(+), 83 deletions(-)
> 
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index 4eda853f1d..58b0ef2af8 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -1344,7 +1344,7 @@ static RISCVCPUMisaExtConfig misa_ext_cfgs[] = {
>      MISA_CFG(RVG, false),
>  };
>  
> -static void riscv_cpu_add_misa_properties(Object *cpu_obj)
> +void riscv_cpu_add_misa_properties(Object *cpu_obj)
>  {
>      int i;
>  
> @@ -1371,17 +1371,11 @@ static void riscv_cpu_add_misa_properties(Object *cpu_obj)
>      }
>  }
>  
> -typedef struct RISCVCPUMultiExtConfig {
> -    const char *name;
> -    uint32_t offset;
> -    bool enabled;
> -} RISCVCPUMultiExtConfig;
> -
>  #define MULTI_EXT_CFG_BOOL(_name, _prop, _defval) \
>      {.name = _name, .offset = CPU_CFG_OFFSET(_prop), \
>       .enabled = _defval}
>  
> -static const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = {
> +const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = {
>      /* Defaults for standard extensions */
>      MULTI_EXT_CFG_BOOL("sscofpmf", ext_sscofpmf, false),
>      MULTI_EXT_CFG_BOOL("Zifencei", ext_ifencei, true),
> @@ -1441,7 +1435,7 @@ static const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = {
>      DEFINE_PROP_END_OF_LIST(),
>  };
>  
> -static const RISCVCPUMultiExtConfig riscv_cpu_vendor_exts[] = {
> +const RISCVCPUMultiExtConfig riscv_cpu_vendor_exts[] = {
>      MULTI_EXT_CFG_BOOL("xtheadba", ext_xtheadba, false),
>      MULTI_EXT_CFG_BOOL("xtheadbb", ext_xtheadbb, false),
>      MULTI_EXT_CFG_BOOL("xtheadbs", ext_xtheadbs, false),
> @@ -1459,7 +1453,7 @@ static const RISCVCPUMultiExtConfig riscv_cpu_vendor_exts[] = {
>  };
>  
>  /* These are experimental so mark with 'x-' */
> -static const RISCVCPUMultiExtConfig riscv_cpu_experimental_exts[] = {
> +const RISCVCPUMultiExtConfig riscv_cpu_experimental_exts[] = {
>      MULTI_EXT_CFG_BOOL("x-zicond", ext_zicond, false),
>  
>      /* ePMP 0.9.3 */
> @@ -1487,7 +1481,7 @@ static const RISCVCPUMultiExtConfig riscv_cpu_experimental_exts[] = {
>      DEFINE_PROP_END_OF_LIST(),
>  };
>  
> -static Property riscv_cpu_options[] = {
> +Property riscv_cpu_options[] = {
>      DEFINE_PROP_UINT8("pmu-num", RISCVCPU, cfg.pmu_num, 16),
>  
>      DEFINE_PROP_BOOL("mmu", RISCVCPU, cfg.mmu, true),
> @@ -1548,25 +1542,6 @@ static void cpu_add_multi_ext_prop(Object *cpu_obj,
>                             multi_cfg->enabled);
>  }
>  
> -#ifndef CONFIG_USER_ONLY
> -static void cpu_set_cfg_unavailable(Object *obj, Visitor *v,
> -                                    const char *name,
> -                                    void *opaque, Error **errp)
> -{
> -    const char *propname = opaque;
> -    bool value;
> -
> -    if (!visit_type_bool(v, name, &value, errp)) {
> -        return;
> -    }
> -
> -    if (value) {
> -        error_setg(errp, "extension %s is not available with KVM",
> -                   propname);
> -    }
> -}
> -#endif
> -
>  static void riscv_cpu_add_multiext_prop_array(Object *obj,
>                                          const RISCVCPUMultiExtConfig *array)
>  {
> @@ -1577,56 +1552,6 @@ static void riscv_cpu_add_multiext_prop_array(Object *obj,
>      }
>  }
>  
> -#ifndef CONFIG_USER_ONLY
> -static void riscv_cpu_add_kvm_unavail_prop(Object *obj, const char *prop_name)
> -{
> -    /* Check if KVM created the property already */
> -    if (object_property_find(obj, prop_name)) {
> -        return;
> -    }
> -
> -    /*
> -     * Set the default to disabled for every extension
> -     * unknown to KVM and error out if the user attempts
> -     * to enable any of them.
> -     */
> -    object_property_add(obj, prop_name, "bool",
> -                        NULL, cpu_set_cfg_unavailable,
> -                        NULL, (void *)prop_name);
> -}
> -
> -static void riscv_cpu_add_kvm_unavail_prop_array(Object *obj,
> -                                        const RISCVCPUMultiExtConfig *array)
> -{
> -    const RISCVCPUMultiExtConfig *prop;
> -
> -    for (prop = array; prop && prop->name; prop++) {
> -        riscv_cpu_add_kvm_unavail_prop(obj, prop->name);
> -    }
> -}
> -
> -static void riscv_cpu_add_kvm_properties(Object *obj)
> -{
> -    Property *prop;
> -    DeviceState *dev = DEVICE(obj);
> -
> -    kvm_riscv_init_user_properties(obj);
> -    riscv_cpu_add_misa_properties(obj);
> -
> -    riscv_cpu_add_kvm_unavail_prop_array(obj, riscv_cpu_extensions);
> -    riscv_cpu_add_kvm_unavail_prop_array(obj, riscv_cpu_vendor_exts);
> -    riscv_cpu_add_kvm_unavail_prop_array(obj, riscv_cpu_experimental_exts);
> -
> -    for (prop = riscv_cpu_options; prop && prop->name; prop++) {
> -        /* Check if KVM created the property already */
> -        if (object_property_find(obj, prop->name)) {
> -            continue;
> -        }
> -        qdev_property_add_static(dev, prop);
> -    }
> -}
> -#endif
> -
>  /*
>   * Add CPU properties with user-facing flags.
>   *
> @@ -1639,7 +1564,7 @@ static void riscv_cpu_add_user_properties(Object *obj)
>      riscv_add_satp_mode_properties(obj);
>  
>      if (kvm_enabled()) {
> -        riscv_cpu_add_kvm_properties(obj);
> +        kvm_riscv_cpu_add_kvm_properties(obj);
>          return;
>      }
>  #endif
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index 2ac00a0304..b9c4bea3f7 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -22,6 +22,7 @@
>  
>  #include "hw/core/cpu.h"
>  #include "hw/registerfields.h"
> +#include "hw/qdev-properties.h"
>  #include "exec/cpu-defs.h"
>  #include "qemu/cpu-float.h"
>  #include "qom/object.h"
> @@ -713,6 +714,19 @@ bool isa_ext_is_enabled(RISCVCPU *cpu, uint32_t ext_offset);
>  int cpu_cfg_ext_get_min_version(uint32_t ext_offset);
>  void riscv_cpu_disable_priv_spec_isa_exts(RISCVCPU *cpu);
>  
> +typedef struct RISCVCPUMultiExtConfig {
> +    const char *name;
> +    uint32_t offset;
> +    bool enabled;
> +} RISCVCPUMultiExtConfig;
> +
> +extern const RISCVCPUMultiExtConfig riscv_cpu_extensions[];
> +extern const RISCVCPUMultiExtConfig riscv_cpu_vendor_exts[];
> +extern const RISCVCPUMultiExtConfig riscv_cpu_experimental_exts[];
> +extern Property riscv_cpu_options[];
> +
> +void riscv_cpu_add_misa_properties(Object *cpu_obj);
> +
>  /* CSR function table */
>  extern riscv_csr_operations csr_ops[CSR_TABLE_SIZE];
>  
> diff --git a/target/riscv/kvm.c b/target/riscv/kvm.c
> index 59004caa8e..7e67121456 100644
> --- a/target/riscv/kvm.c
> +++ b/target/riscv/kvm.c
> @@ -338,6 +338,50 @@ static void kvm_riscv_update_cpu_cfg_isa_ext(RISCVCPU *cpu, CPUState *cs)
>      }
>  }
>  
> +static void cpu_set_cfg_unavailable(Object *obj, Visitor *v,
> +                                    const char *name,
> +                                    void *opaque, Error **errp)
> +{
> +    const char *propname = opaque;
> +    bool value;
> +
> +    if (!visit_type_bool(v, name, &value, errp)) {
> +        return;
> +    }
> +
> +    if (value) {
> +        error_setg(errp, "extension %s is not available with KVM",
> +                   propname);
> +    }
> +}
> +
> +static void riscv_cpu_add_kvm_unavail_prop(Object *obj, const char *prop_name)
> +{
> +    /* Check if KVM created the property already */
> +    if (object_property_find(obj, prop_name)) {
> +        return;
> +    }
> +
> +    /*
> +     * Set the default to disabled for every extension
> +     * unknown to KVM and error out if the user attempts
> +     * to enable any of them.
> +     */
> +    object_property_add(obj, prop_name, "bool",
> +                        NULL, cpu_set_cfg_unavailable,
> +                        NULL, (void *)prop_name);
> +}
> +
> +static void riscv_cpu_add_kvm_unavail_prop_array(Object *obj,
> +                                        const RISCVCPUMultiExtConfig *array)
> +{
> +    const RISCVCPUMultiExtConfig *prop;
> +
> +    for (prop = array; prop && prop->name; prop++) {
> +        riscv_cpu_add_kvm_unavail_prop(obj, prop->name);
> +    }
> +}
> +
>  static void kvm_riscv_add_cpu_user_properties(Object *cpu_obj)
>  {
>      int i;
> @@ -747,7 +791,7 @@ static void kvm_riscv_init_multiext_cfg(RISCVCPU *cpu, KVMScratchCPU *kvmcpu)
>      }
>  }
>  
> -void kvm_riscv_init_user_properties(Object *cpu_obj)
> +static void riscv_init_user_properties(Object *cpu_obj)
>  {
>      RISCVCPU *cpu = RISCV_CPU(cpu_obj);
>      KVMScratchCPU kvmcpu;
> @@ -1218,6 +1262,26 @@ void kvm_riscv_aia_create(MachineState *machine, uint64_t group_shift,
>      kvm_msi_via_irqfd_allowed = kvm_irqfds_enabled();
>  }
>  
> +void kvm_riscv_cpu_add_kvm_properties(Object *obj)
> +{
> +    DeviceState *dev = DEVICE(obj);
> +
> +    riscv_init_user_properties(obj);
> +    riscv_cpu_add_misa_properties(obj);
> +
> +    riscv_cpu_add_kvm_unavail_prop_array(obj, riscv_cpu_extensions);
> +    riscv_cpu_add_kvm_unavail_prop_array(obj, riscv_cpu_vendor_exts);
> +    riscv_cpu_add_kvm_unavail_prop_array(obj, riscv_cpu_experimental_exts);
> +
> +    for (Property *prop = riscv_cpu_options; prop && prop->name; prop++) {
> +        /* Check if KVM created the property already */
> +        if (object_property_find(obj, prop->name)) {
> +            continue;
> +        }
> +        qdev_property_add_static(dev, prop);
> +    }
> +}
> +
>  static void riscv_host_cpu_init(Object *obj)
>  {
>      CPURISCVState *env = &RISCV_CPU(obj)->env;
> diff --git a/target/riscv/kvm_riscv.h b/target/riscv/kvm_riscv.h
> index 7d4b7c60e2..81e08b8359 100644
> --- a/target/riscv/kvm_riscv.h
> +++ b/target/riscv/kvm_riscv.h
> @@ -19,7 +19,7 @@
>  #ifndef QEMU_KVM_RISCV_H
>  #define QEMU_KVM_RISCV_H
>  
> -void kvm_riscv_init_user_properties(Object *cpu_obj);
> +void kvm_riscv_cpu_add_kvm_properties(Object *obj);
>  void kvm_riscv_reset_vcpu(RISCVCPU *cpu);
>  void kvm_riscv_set_irq(RISCVCPU *cpu, int irq, int level);
>  void kvm_riscv_aia_create(MachineState *machine, uint64_t group_shift,
> -- 
> 2.41.0
> 
>

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


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

* Re: [PATCH 11/20] target/riscv: introduce KVM AccelCPUClass
  2023-08-25 13:08 ` [PATCH 11/20] target/riscv: introduce KVM AccelCPUClass Daniel Henrique Barboza
  2023-08-28 16:38   ` Philippe Mathieu-Daudé
@ 2023-08-31 11:26   ` Andrew Jones
  1 sibling, 0 replies; 51+ messages in thread
From: Andrew Jones @ 2023-08-31 11:26 UTC (permalink / raw)
  To: Daniel Henrique Barboza
  Cc: qemu-devel, qemu-riscv, alistair.francis, bmeng, liweiwei,
	zhiwei_liu, palmer

On Fri, Aug 25, 2023 at 10:08:44AM -0300, Daniel Henrique Barboza wrote:
> Add a KVM accelerator class like we did with TCG. The difference is
> that, at least for now, we won't be using a realize() implementation for
> this accelerator.
> 
> We'll start by assiging kvm_riscv_cpu_add_kvm_properties(), renamed to
> kvm_cpu_instance_init(), as a 'cpu_instance_init' implementation. Change
> riscv_cpu_post_init() to invoke accel_cpu_instance_init(), which will go
> through the 'cpu_instance_init' impl of the current acceleration (if
> available) and execute it. The end result is that the KVM initial setup,
> i.e. starting registers and adding its specific properties, will be done
> via this hook.
> 
> riscv_cpu_add_user_properties() is still being called via the common
> post_init() function, thus we still need the "if kvm then return" logic
> inside it for now. We'll deal with it when TCG accel class get its own
> 'cpu_instance_init' implementation.
> 
> riscv_add_satp_mode_properties() is now being exported from cpu.c since
> it's a common helper between KVM and TCG.
> 
> Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
> ---
>  target/riscv/cpu.c       |  8 ++---
>  target/riscv/cpu.h       |  1 +
>  target/riscv/kvm.c       | 64 +++++++++++++++++++++++++++-------------
>  target/riscv/kvm_riscv.h |  1 -
>  4 files changed, 49 insertions(+), 25 deletions(-)
> 
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index 58b0ef2af8..04c6bfaeef 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -1112,7 +1112,7 @@ static void cpu_riscv_set_satp(Object *obj, Visitor *v, const char *name,
>      satp_map->init |= 1 << satp;
>  }
>  
> -static void riscv_add_satp_mode_properties(Object *obj)
> +void riscv_add_satp_mode_properties(Object *obj)
>  {
>      RISCVCPU *cpu = RISCV_CPU(obj);
>  
> @@ -1199,6 +1199,8 @@ static void riscv_cpu_post_init(Object *obj)
>      RISCVCPU *cpu = RISCV_CPU(obj);
>      RISCVCPUClass *rcc = RISCV_CPU_GET_CLASS(cpu);
>  
> +    accel_cpu_instance_init(CPU(obj));
> +
>      if (rcc->user_extension_properties) {
>          riscv_cpu_add_user_properties(obj);
>      }
> @@ -1561,12 +1563,10 @@ static void riscv_cpu_add_multiext_prop_array(Object *obj,
>  static void riscv_cpu_add_user_properties(Object *obj)
>  {
>  #ifndef CONFIG_USER_ONLY
> -    riscv_add_satp_mode_properties(obj);
> -
>      if (kvm_enabled()) {
> -        kvm_riscv_cpu_add_kvm_properties(obj);
>          return;
>      }
> +    riscv_add_satp_mode_properties(obj);
>  #endif
>  
>      riscv_cpu_add_misa_properties(obj);
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index b9c4bea3f7..950c2301f2 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -726,6 +726,7 @@ extern const RISCVCPUMultiExtConfig riscv_cpu_experimental_exts[];
>  extern Property riscv_cpu_options[];
>  
>  void riscv_cpu_add_misa_properties(Object *cpu_obj);
> +void riscv_add_satp_mode_properties(Object *obj);
>  
>  /* CSR function table */
>  extern riscv_csr_operations csr_ops[CSR_TABLE_SIZE];
> diff --git a/target/riscv/kvm.c b/target/riscv/kvm.c
> index 7e67121456..3c4fa43cee 100644
> --- a/target/riscv/kvm.c
> +++ b/target/riscv/kvm.c
> @@ -31,6 +31,7 @@
>  #include "sysemu/kvm_int.h"
>  #include "cpu.h"
>  #include "trace.h"
> +#include "hw/core/accel-cpu.h"
>  #include "hw/pci/pci.h"
>  #include "exec/memattrs.h"
>  #include "exec/address-spaces.h"
> @@ -1262,26 +1263,6 @@ void kvm_riscv_aia_create(MachineState *machine, uint64_t group_shift,
>      kvm_msi_via_irqfd_allowed = kvm_irqfds_enabled();
>  }
>  
> -void kvm_riscv_cpu_add_kvm_properties(Object *obj)
> -{
> -    DeviceState *dev = DEVICE(obj);
> -
> -    riscv_init_user_properties(obj);
> -    riscv_cpu_add_misa_properties(obj);
> -
> -    riscv_cpu_add_kvm_unavail_prop_array(obj, riscv_cpu_extensions);
> -    riscv_cpu_add_kvm_unavail_prop_array(obj, riscv_cpu_vendor_exts);
> -    riscv_cpu_add_kvm_unavail_prop_array(obj, riscv_cpu_experimental_exts);
> -
> -    for (Property *prop = riscv_cpu_options; prop && prop->name; prop++) {
> -        /* Check if KVM created the property already */
> -        if (object_property_find(obj, prop->name)) {
> -            continue;
> -        }
> -        qdev_property_add_static(dev, prop);
> -    }
> -}
> -
>  static void riscv_host_cpu_init(Object *obj)
>  {
>      CPURISCVState *env = &RISCV_CPU(obj)->env;
> @@ -1310,3 +1291,46 @@ static const TypeInfo riscv_kvm_cpu_type_infos[] = {
>  };
>  
>  DEFINE_TYPES(riscv_kvm_cpu_type_infos)
> +
> +static void kvm_cpu_instance_init(CPUState *cs)
> +{
> +    Object *obj = OBJECT(RISCV_CPU(cs));
> +    DeviceState *dev = DEVICE(obj);
> +
> +    riscv_init_user_properties(obj);
> +
> +    riscv_add_satp_mode_properties(obj);
> +    riscv_cpu_add_misa_properties(obj);
> +
> +    riscv_cpu_add_kvm_unavail_prop_array(obj, riscv_cpu_extensions);
> +    riscv_cpu_add_kvm_unavail_prop_array(obj, riscv_cpu_vendor_exts);
> +    riscv_cpu_add_kvm_unavail_prop_array(obj, riscv_cpu_experimental_exts);
> +
> +    for (Property *prop = riscv_cpu_options; prop && prop->name; prop++) {
> +        /* Check if we have a specific KVM handler for the option */
> +        if (object_property_find(obj, prop->name)) {
> +            continue;
> +        }
> +        qdev_property_add_static(dev, prop);
> +    }
> +}
> +
> +static void kvm_cpu_accel_class_init(ObjectClass *oc, void *data)
> +{
> +    AccelCPUClass *acc = ACCEL_CPU_CLASS(oc);
> +
> +    acc->cpu_instance_init = kvm_cpu_instance_init;
> +}
> +
> +static const TypeInfo kvm_cpu_accel_type_info = {
> +    .name = ACCEL_CPU_NAME("kvm"),
> +
> +    .parent = TYPE_ACCEL_CPU,
> +    .class_init = kvm_cpu_accel_class_init,
> +    .abstract = true,
> +};

blank line here

> +static void kvm_cpu_accel_register_types(void)
> +{
> +    type_register_static(&kvm_cpu_accel_type_info);
> +}
> +type_init(kvm_cpu_accel_register_types);
> diff --git a/target/riscv/kvm_riscv.h b/target/riscv/kvm_riscv.h
> index 81e08b8359..a0ea1a7505 100644
> --- a/target/riscv/kvm_riscv.h
> +++ b/target/riscv/kvm_riscv.h
> @@ -19,7 +19,6 @@
>  #ifndef QEMU_KVM_RISCV_H
>  #define QEMU_KVM_RISCV_H
>  
> -void kvm_riscv_cpu_add_kvm_properties(Object *obj);
>  void kvm_riscv_reset_vcpu(RISCVCPU *cpu);
>  void kvm_riscv_set_irq(RISCVCPU *cpu, int irq, int level);
>  void kvm_riscv_aia_create(MachineState *machine, uint64_t group_shift,
> -- 
> 2.41.0
> 
>

I'll wait for v2 to complete the review of this one.

Thanks,
drew


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

* Re: [PATCH 12/20] target/riscv: move KVM only files to kvm subdir
  2023-08-25 13:08 ` [PATCH 12/20] target/riscv: move KVM only files to kvm subdir Daniel Henrique Barboza
  2023-08-28 16:47   ` Philippe Mathieu-Daudé
@ 2023-08-31 11:30   ` Andrew Jones
  2023-09-01 17:19     ` Daniel Henrique Barboza
  1 sibling, 1 reply; 51+ messages in thread
From: Andrew Jones @ 2023-08-31 11:30 UTC (permalink / raw)
  To: Daniel Henrique Barboza
  Cc: qemu-devel, qemu-riscv, alistair.francis, bmeng, liweiwei,
	zhiwei_liu, palmer

On Fri, Aug 25, 2023 at 10:08:45AM -0300, Daniel Henrique Barboza wrote:
> Move the files to a 'kvm' dir to promote more code separation between
> accelerators and making our lives easier supporting build options such
> as --disable-tcg.
> 
> Rename kvm.c to kvm-cpu.c to keep it in line with its TCG counterpart.

Now that we have 'kvm' and 'tcg' subdirectories, it seems like we should
be removing prefixes from files, i.e. 'kvm/cpu.c' and 'tcg/cpu.c' would be
less verbose and just as easy to identify, but whatever people like...

> 
> Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
> ---
>  hw/riscv/virt.c                       | 2 +-
>  target/riscv/cpu.c                    | 2 +-
>  target/riscv/{kvm.c => kvm/kvm-cpu.c} | 0
>  target/riscv/{ => kvm}/kvm-stub.c     | 0
>  target/riscv/{ => kvm}/kvm_riscv.h    | 0
>  target/riscv/kvm/meson.build          | 2 ++
>  target/riscv/meson.build              | 2 +-
>  7 files changed, 5 insertions(+), 3 deletions(-)
>  rename target/riscv/{kvm.c => kvm/kvm-cpu.c} (100%)
>  rename target/riscv/{ => kvm}/kvm-stub.c (100%)
>  rename target/riscv/{ => kvm}/kvm_riscv.h (100%)
>  create mode 100644 target/riscv/kvm/meson.build
> 
> diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
> index 388e52a294..77c384ddc3 100644
> --- a/hw/riscv/virt.c
> +++ b/hw/riscv/virt.c
> @@ -35,7 +35,7 @@
>  #include "hw/riscv/virt.h"
>  #include "hw/riscv/boot.h"
>  #include "hw/riscv/numa.h"
> -#include "kvm_riscv.h"
> +#include "kvm/kvm_riscv.h"
>  #include "hw/intc/riscv_aclint.h"
>  #include "hw/intc/riscv_aplic.h"
>  #include "hw/intc/riscv_imsic.h"
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index 04c6bfaeef..bf6c8519b1 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -33,7 +33,7 @@
>  #include "fpu/softfloat-helpers.h"
>  #include "sysemu/kvm.h"
>  #include "sysemu/tcg.h"
> -#include "kvm_riscv.h"
> +#include "kvm/kvm_riscv.h"
>  #include "tcg/tcg.h"
>  
>  /* RISC-V CPU definitions */
> diff --git a/target/riscv/kvm.c b/target/riscv/kvm/kvm-cpu.c
> similarity index 100%
> rename from target/riscv/kvm.c
> rename to target/riscv/kvm/kvm-cpu.c
> diff --git a/target/riscv/kvm-stub.c b/target/riscv/kvm/kvm-stub.c
> similarity index 100%
> rename from target/riscv/kvm-stub.c
> rename to target/riscv/kvm/kvm-stub.c
> diff --git a/target/riscv/kvm_riscv.h b/target/riscv/kvm/kvm_riscv.h
> similarity index 100%
> rename from target/riscv/kvm_riscv.h
> rename to target/riscv/kvm/kvm_riscv.h
> diff --git a/target/riscv/kvm/meson.build b/target/riscv/kvm/meson.build
> new file mode 100644
> index 0000000000..1cd6783894
> --- /dev/null
> +++ b/target/riscv/kvm/meson.build
> @@ -0,0 +1,2 @@
> +riscv_ss.add(when: 'CONFIG_KVM', if_true: files('kvm-cpu.c'),
> +                                 if_false: files('kvm-stub.c'))
> diff --git a/target/riscv/meson.build b/target/riscv/meson.build
> index f0486183fa..c53962215f 100644
> --- a/target/riscv/meson.build
> +++ b/target/riscv/meson.build
> @@ -24,7 +24,6 @@ riscv_ss.add(files(
>    'zce_helper.c',
>    'vcrypto_helper.c'
>  ))
> -riscv_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c'), if_false: files('kvm-stub.c'))
>  
>  riscv_system_ss = ss.source_set()
>  riscv_system_ss.add(files(
> @@ -39,6 +38,7 @@ riscv_system_ss.add(files(
>  ))
>  
>  subdir('tcg')
> +subdir('kvm')
>  
>  target_arch += {'riscv': riscv_ss}
>  target_softmmu_arch += {'riscv': riscv_system_ss}
> -- 
> 2.41.0
> 
>

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


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

* Re: [PATCH 13/20] target/riscv/kvm: refactor kvm_riscv_init_user_properties()
  2023-08-25 13:08 ` [PATCH 13/20] target/riscv/kvm: refactor kvm_riscv_init_user_properties() Daniel Henrique Barboza
@ 2023-08-31 11:34   ` Andrew Jones
  0 siblings, 0 replies; 51+ messages in thread
From: Andrew Jones @ 2023-08-31 11:34 UTC (permalink / raw)
  To: Daniel Henrique Barboza
  Cc: qemu-devel, qemu-riscv, alistair.francis, bmeng, liweiwei,
	zhiwei_liu, palmer

On Fri, Aug 25, 2023 at 10:08:46AM -0300, Daniel Henrique Barboza wrote:
> The function is doing way more than just init user properties. We would
> also like to use the 'user_extension_properties' class property, as the
> TCG driver is already using, to decide whether KVM should expose user
> properties or not.
> 
> Rename kvm_riscv_init_user_properties() to riscv_init_kvm_registers()
> and leave only the essential, non-optional KVM init functions there. All
> functions that deals with property handling is now gated via
> rcc->user_extension_properties.
> 
> Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
> ---
>  target/riscv/kvm/kvm-cpu.c | 19 +++++++++++--------
>  1 file changed, 11 insertions(+), 8 deletions(-)
> 
> diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c
> index 3c4fa43cee..85e8b0a927 100644
> --- a/target/riscv/kvm/kvm-cpu.c
> +++ b/target/riscv/kvm/kvm-cpu.c
> @@ -792,7 +792,7 @@ static void kvm_riscv_init_multiext_cfg(RISCVCPU *cpu, KVMScratchCPU *kvmcpu)
>      }
>  }
>  
> -static void riscv_init_user_properties(Object *cpu_obj)
> +static void riscv_init_kvm_registers(Object *cpu_obj)
>  {
>      RISCVCPU *cpu = RISCV_CPU(cpu_obj);
>      KVMScratchCPU kvmcpu;
> @@ -801,7 +801,6 @@ static void riscv_init_user_properties(Object *cpu_obj)
>          return;
>      }
>  
> -    kvm_riscv_add_cpu_user_properties(cpu_obj);
>      kvm_riscv_init_machine_ids(cpu, &kvmcpu);
>      kvm_riscv_init_misa_ext_mask(cpu, &kvmcpu);
>      kvm_riscv_init_multiext_cfg(cpu, &kvmcpu);
> @@ -1295,16 +1294,20 @@ DEFINE_TYPES(riscv_kvm_cpu_type_infos)
>  static void kvm_cpu_instance_init(CPUState *cs)
>  {
>      Object *obj = OBJECT(RISCV_CPU(cs));
> +    RISCVCPUClass *rcc = RISCV_CPU_GET_CLASS(obj);
>      DeviceState *dev = DEVICE(obj);
>  
> -    riscv_init_user_properties(obj);
> +    riscv_init_kvm_registers(obj);
>  
> -    riscv_add_satp_mode_properties(obj);
> -    riscv_cpu_add_misa_properties(obj);
> +    if (rcc->user_extension_properties) {
> +        kvm_riscv_add_cpu_user_properties(obj);
> +        riscv_add_satp_mode_properties(obj);
> +        riscv_cpu_add_misa_properties(obj);
>  
> -    riscv_cpu_add_kvm_unavail_prop_array(obj, riscv_cpu_extensions);
> -    riscv_cpu_add_kvm_unavail_prop_array(obj, riscv_cpu_vendor_exts);
> -    riscv_cpu_add_kvm_unavail_prop_array(obj, riscv_cpu_experimental_exts);
> +        riscv_cpu_add_kvm_unavail_prop_array(obj, riscv_cpu_extensions);
> +        riscv_cpu_add_kvm_unavail_prop_array(obj, riscv_cpu_vendor_exts);
> +        riscv_cpu_add_kvm_unavail_prop_array(obj, riscv_cpu_experimental_exts);
> +    }
>  
>      for (Property *prop = riscv_cpu_options; prop && prop->name; prop++) {
>          /* Check if we have a specific KVM handler for the option */
> -- 
> 2.41.0
> 
>

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


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

* Re: [PATCH 14/20] target/riscv/kvm: do not use riscv_cpu_add_misa_properties()
  2023-08-25 13:08 ` [PATCH 14/20] target/riscv/kvm: do not use riscv_cpu_add_misa_properties() Daniel Henrique Barboza
@ 2023-08-31 11:50   ` Andrew Jones
  0 siblings, 0 replies; 51+ messages in thread
From: Andrew Jones @ 2023-08-31 11:50 UTC (permalink / raw)
  To: Daniel Henrique Barboza
  Cc: qemu-devel, qemu-riscv, alistair.francis, bmeng, liweiwei,
	zhiwei_liu, palmer

On Fri, Aug 25, 2023 at 10:08:47AM -0300, Daniel Henrique Barboza wrote:
> riscv_cpu_add_misa_properties() is being used to fill the missing KVM
> MISA properties but it is a TCG helper that was adapted to do so. We'll
> move it to tcg-cpu.c in the next patches, meaning that KVM needs to fill
> the remaining MISA properties on its own.
> 
> Do not use riscv_cpu_add_misa_properties(). Let's create a new array
> with all available MISA bits we support that can be read by KVM. Then,
> inside kvm_riscv_add_cpu_user_properties(), we'll create all KVM MISA
> properties as usual and then use this array to add any missing MISA
> properties with the riscv_cpu_add_kvm_unavail_prop() helper.
> 
> Note that we're creating misa_bits[], and not using the existing
> 'riscv_single_letter_exts[]', because the latter is tuned for riscv,isa
> related functions and it doesn't have all MISA bits we support. Commit
> 0e2c377023 ("target/riscv: misa to ISA string conversion fix") has the
> full context.
> 
> While we're at it, move both satp and the multi-letter extension
> properties to kvm_riscv_add_cpu_user_properties() as well.
> 
> Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
> ---
>  target/riscv/cpu.c         |  2 ++
>  target/riscv/cpu.h         |  3 ++-
>  target/riscv/kvm/kvm-cpu.c | 17 +++++++++++------
>  3 files changed, 15 insertions(+), 7 deletions(-)
> 
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index bf6c8519b1..f9aea6a80a 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -38,6 +38,8 @@
>  
>  /* RISC-V CPU definitions */
>  static const char riscv_single_letter_exts[] = "IEMAFDQCPVH";
> +const uint32_t misa_bits[] = {RVI, RVE, RVM, RVA, RVF, RVD, RVV,
> +                              RVC, RVS, RVU, RVH, RVJ, RVG};
>  
>  struct isa_ext_data {
>      const char *name;
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index 950c2301f2..9ec3b98bd2 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -43,7 +43,7 @@
>  #define RV(x) ((target_ulong)1 << (x - 'A'))
>  
>  /*
> - * Consider updating misa_ext_info_arr[] and misa_ext_cfgs[]
> + * Update misa_bits[], misa_ext_info_arr[] and misa_ext_cfgs[]
>   * when adding new MISA bits here.
>   */
>  #define RVI RV('I')
> @@ -60,6 +60,7 @@
>  #define RVJ RV('J')
>  #define RVG RV('G')
>  
> +extern const uint32_t misa_bits[13];
                                   ^ maintaining this will be a PITA

I suggest misa_bits either have a terminating zero (zero is an invalid bit
number) or that a const nr_misa_bits is also exported from riscv/cpu.c
which be set to ARRAY_SIZE(misa_bits) and would be used for the loop
condition.

>  const char *riscv_get_misa_ext_name(uint32_t bit);
>  const char *riscv_get_misa_ext_description(uint32_t bit);
>  
> diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c
> index 85e8b0a927..501384924b 100644
> --- a/target/riscv/kvm/kvm-cpu.c
> +++ b/target/riscv/kvm/kvm-cpu.c
> @@ -387,6 +387,8 @@ static void kvm_riscv_add_cpu_user_properties(Object *cpu_obj)
>  {
>      int i;
>  
> +    riscv_add_satp_mode_properties(cpu_obj);
> +
>      for (i = 0; i < ARRAY_SIZE(kvm_misa_ext_cfgs); i++) {
>          KVMCPUConfig *misa_cfg = &kvm_misa_ext_cfgs[i];
>          int bit = misa_cfg->offset;
> @@ -402,6 +404,11 @@ static void kvm_riscv_add_cpu_user_properties(Object *cpu_obj)
>                                          misa_cfg->description);
>      }
>  
> +    for (i = 0; i < ARRAY_SIZE(misa_bits); i++) {
> +        const char *ext_name = riscv_get_misa_ext_name(misa_bits[i]);
> +        riscv_cpu_add_kvm_unavail_prop(cpu_obj, ext_name);
> +    }
> +
>      for (i = 0; i < ARRAY_SIZE(kvm_multi_ext_cfgs); i++) {
>          KVMCPUConfig *multi_cfg = &kvm_multi_ext_cfgs[i];
>  
> @@ -418,6 +425,10 @@ static void kvm_riscv_add_cpu_user_properties(Object *cpu_obj)
>      object_property_add(cpu_obj, "cboz_blocksize", "uint16",
>                          NULL, kvm_cpu_set_cbomz_blksize,
>                          NULL, &kvm_cboz_blocksize);
> +
> +    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);
>  }
>  
>  static int kvm_riscv_get_regs_core(CPUState *cs)
> @@ -1301,12 +1312,6 @@ static void kvm_cpu_instance_init(CPUState *cs)
>  
>      if (rcc->user_extension_properties) {
>          kvm_riscv_add_cpu_user_properties(obj);
> -        riscv_add_satp_mode_properties(obj);
> -        riscv_cpu_add_misa_properties(obj);
> -
> -        riscv_cpu_add_kvm_unavail_prop_array(obj, riscv_cpu_extensions);
> -        riscv_cpu_add_kvm_unavail_prop_array(obj, riscv_cpu_vendor_exts);
> -        riscv_cpu_add_kvm_unavail_prop_array(obj, riscv_cpu_experimental_exts);
>      }
>  
>      for (Property *prop = riscv_cpu_options; prop && prop->name; prop++) {
> -- 
> 2.41.0
> 
> 

Otherwise,

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


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

* Re: [PATCH 15/20] target/riscv/tcg: introduce tcg_cpu_instance_init()
  2023-08-25 13:08 ` [PATCH 15/20] target/riscv/tcg: introduce tcg_cpu_instance_init() Daniel Henrique Barboza
@ 2023-08-31 11:56   ` Andrew Jones
  0 siblings, 0 replies; 51+ messages in thread
From: Andrew Jones @ 2023-08-31 11:56 UTC (permalink / raw)
  To: Daniel Henrique Barboza
  Cc: qemu-devel, qemu-riscv, alistair.francis, bmeng, liweiwei,
	zhiwei_liu, palmer

On Fri, Aug 25, 2023 at 10:08:48AM -0300, Daniel Henrique Barboza wrote:
> tcg_cpu_instance_init() will be the 'cpu_instance_init' impl for the TCG
> accelerator. It'll be called from within riscv_cpu_post_init(), via
> accel_cpu_instance_init(), similar to what happens with KVM. In fact, to
> preserve behavior, the implementation will be similar to what
> riscv_cpu_post_init() already does.
> 
> In this patch we'll move riscv_cpu_add_user_properties() and
> riscv_init_max_cpu_extensions() and all their dependencies to tcg-cpu.c.
> All multi-extension properties code was moved. The 'multi_ext_user_opts'
> hash table was also moved to tcg-cpu.c since it's a TCG only structure,
> meaning that we won't have to worry about initializing a TCG hash table
> when running a KVM CPU anymore.
> 
> riscv_cpu_add_user_properties() will remain in cpu.c for now due to how
> much code it requires to be moved at the same time. We'll do that in the
> next patch.
> 
> Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
> ---
>  target/riscv/cpu.c         | 141 +------------------------------------
>  target/riscv/cpu.h         |   2 +-
>  target/riscv/tcg/tcg-cpu.c | 138 ++++++++++++++++++++++++++++++++++++
>  3 files changed, 140 insertions(+), 141 deletions(-)
> 
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index f9aea6a80a..89b09a7e89 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -162,9 +162,6 @@ static const struct isa_ext_data isa_edata_arr[] = {
>      ISA_EXT_DATA_ENTRY(xventanacondops, PRIV_VERSION_1_12_0, ext_XVentanaCondOps),
>  };
>  
> -/* Hash that stores user set extensions */
> -static GHashTable *multi_ext_user_opts;
> -
>  bool isa_ext_is_enabled(RISCVCPU *cpu, uint32_t ext_offset)
>  {
>      bool *ext_enabled = (void *)&cpu->cfg + ext_offset;
> @@ -195,12 +192,6 @@ int cpu_cfg_ext_get_min_version(uint32_t ext_offset)
>      return PRIV_VERSION_1_10_0;
>  }
>  
> -bool cpu_cfg_ext_is_user_set(uint32_t ext_offset)
> -{
> -    return g_hash_table_contains(multi_ext_user_opts,
> -                                 GUINT_TO_POINTER(ext_offset));
> -}
> -
>  const char * const riscv_int_regnames[] = {
>      "x0/zero", "x1/ra",  "x2/sp",  "x3/gp",  "x4/tp",  "x5/t0",   "x6/t1",
>      "x7/t2",   "x8/s0",  "x9/s1",  "x10/a0", "x11/a1", "x12/a2",  "x13/a3",
> @@ -281,9 +272,6 @@ static const char * const riscv_intr_names[] = {
>      "reserved"
>  };
>  
> -static void riscv_cpu_add_user_properties(Object *obj);
> -static void riscv_init_max_cpu_extensions(Object *obj);
> -
>  const char *riscv_cpu_get_trap_name(target_ulong cause, bool async)
>  {
>      if (async) {
> @@ -295,7 +283,7 @@ const char *riscv_cpu_get_trap_name(target_ulong cause, bool async)
>      }
>  }
>  
> -static void set_misa(CPURISCVState *env, RISCVMXL mxl, uint32_t ext)
> +void set_misa(CPURISCVState *env, RISCVMXL mxl, uint32_t ext)
>  {
>      env->misa_mxl_max = env->misa_mxl = mxl;
>      env->misa_ext_mask = env->misa_ext = ext;
> @@ -1198,18 +1186,7 @@ static void riscv_cpu_set_irq(void *opaque, int irq, int level)
>  
>  static void riscv_cpu_post_init(Object *obj)
>  {
> -    RISCVCPU *cpu = RISCV_CPU(obj);
> -    RISCVCPUClass *rcc = RISCV_CPU_GET_CLASS(cpu);
> -
>      accel_cpu_instance_init(CPU(obj));
> -
> -    if (rcc->user_extension_properties) {
> -        riscv_cpu_add_user_properties(obj);
> -    }
> -
> -    if (cpu->cfg.max_features) {
> -        riscv_init_max_cpu_extensions(obj);
> -    }
>  }
>  
>  static void riscv_cpu_init(Object *obj)
> @@ -1222,8 +1199,6 @@ static void riscv_cpu_init(Object *obj)
>      qdev_init_gpio_in(DEVICE(cpu), riscv_cpu_set_irq,
>                        IRQ_LOCAL_MAX + IRQ_LOCAL_GUEST_MAX);
>  #endif /* CONFIG_USER_ONLY */
> -
> -    multi_ext_user_opts = g_hash_table_new(NULL, g_direct_equal);
>  }
>  
>  typedef struct RISCVCPUMisaExtConfig {
> @@ -1503,120 +1478,6 @@ Property riscv_cpu_options[] = {
>      DEFINE_PROP_END_OF_LIST(),
>  };
>  
> -static void cpu_set_multi_ext_cfg(Object *obj, Visitor *v, const char *name,
> -                                  void *opaque, Error **errp)
> -{
> -    const RISCVCPUMultiExtConfig *multi_ext_cfg = opaque;
> -    bool value;
> -
> -    if (!visit_type_bool(v, name, &value, errp)) {
> -        return;
> -    }
> -
> -    isa_ext_update_enabled(RISCV_CPU(obj), multi_ext_cfg->offset, value);
> -
> -    g_hash_table_insert(multi_ext_user_opts,
> -                        GUINT_TO_POINTER(multi_ext_cfg->offset),
> -                        (gpointer)value);
> -}
> -
> -static void cpu_get_multi_ext_cfg(Object *obj, Visitor *v, const char *name,
> -                                  void *opaque, Error **errp)
> -{
> -    const RISCVCPUMultiExtConfig *multi_ext_cfg = opaque;
> -    bool value = isa_ext_is_enabled(RISCV_CPU(obj), multi_ext_cfg->offset);
> -
> -    visit_type_bool(v, name, &value, errp);
> -}
> -
> -static void cpu_add_multi_ext_prop(Object *cpu_obj,
> -                                   const RISCVCPUMultiExtConfig *multi_cfg)
> -{
> -    object_property_add(cpu_obj, multi_cfg->name, "bool",
> -                        cpu_get_multi_ext_cfg,
> -                        cpu_set_multi_ext_cfg,
> -                        NULL, (void *)multi_cfg);
> -
> -    /*
> -     * Set def val directly instead of using
> -     * object_property_set_bool() to save the set()
> -     * callback hash for user inputs.
> -     */
> -    isa_ext_update_enabled(RISCV_CPU(cpu_obj), multi_cfg->offset,
> -                           multi_cfg->enabled);
> -}
> -
> -static void riscv_cpu_add_multiext_prop_array(Object *obj,
> -                                        const RISCVCPUMultiExtConfig *array)
> -{
> -    const RISCVCPUMultiExtConfig *prop;
> -
> -    for (prop = array; prop && prop->name; prop++) {
> -        cpu_add_multi_ext_prop(obj, prop);
> -    }
> -}
> -
> -/*
> - * Add CPU properties with user-facing flags.
> - *
> - * This will overwrite existing env->misa_ext values with the
> - * defaults set via riscv_cpu_add_misa_properties().
> - */
> -static void riscv_cpu_add_user_properties(Object *obj)
> -{
> -#ifndef CONFIG_USER_ONLY
> -    if (kvm_enabled()) {
> -        return;
> -    }
> -    riscv_add_satp_mode_properties(obj);
> -#endif
> -
> -    riscv_cpu_add_misa_properties(obj);
> -
> -    riscv_cpu_add_multiext_prop_array(obj, riscv_cpu_extensions);
> -    riscv_cpu_add_multiext_prop_array(obj, riscv_cpu_vendor_exts);
> -    riscv_cpu_add_multiext_prop_array(obj, riscv_cpu_experimental_exts);
> -
> -    for (Property *prop = riscv_cpu_options; prop && prop->name; prop++) {
> -        qdev_property_add_static(DEVICE(obj), prop);
> -    }
> -}
> -
> -/*
> - * The 'max' type CPU will have all possible ratified
> - * non-vendor extensions enabled.
> - */
> -static void riscv_init_max_cpu_extensions(Object *obj)
> -{
> -    RISCVCPU *cpu = RISCV_CPU(obj);
> -    CPURISCVState *env = &cpu->env;
> -    const RISCVCPUMultiExtConfig *prop;
> -
> -    /* Enable RVG, RVJ and RVV that are disabled by default */
> -    set_misa(env, env->misa_mxl, env->misa_ext | RVG | RVJ | RVV);
> -
> -    for (prop = riscv_cpu_extensions; prop && prop->name; prop++) {
> -        isa_ext_update_enabled(cpu, prop->offset, true);
> -    }
> -
> -    /* set vector version */
> -    env->vext_ver = VEXT_VERSION_1_00_0;
> -
> -    /* Zfinx is not compatible with F. Disable it */
> -    isa_ext_update_enabled(cpu, CPU_CFG_OFFSET(ext_zfinx), false);
> -    isa_ext_update_enabled(cpu, CPU_CFG_OFFSET(ext_zdinx), false);
> -    isa_ext_update_enabled(cpu, CPU_CFG_OFFSET(ext_zhinx), false);
> -    isa_ext_update_enabled(cpu, CPU_CFG_OFFSET(ext_zhinxmin), false);
> -
> -    isa_ext_update_enabled(cpu, CPU_CFG_OFFSET(ext_zce), false);
> -    isa_ext_update_enabled(cpu, CPU_CFG_OFFSET(ext_zcmp), false);
> -    isa_ext_update_enabled(cpu, CPU_CFG_OFFSET(ext_zcmt), false);
> -
> -    if (env->misa_mxl != MXL_RV32) {
> -        isa_ext_update_enabled(cpu, CPU_CFG_OFFSET(ext_zcf), false);
> -    }
> -}
> -
>  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 9ec3b98bd2..74fbb33e09 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -710,9 +710,9 @@ enum riscv_pmu_event_idx {
>  
>  /* used by tcg/tcg-cpu.c*/
>  void isa_ext_update_enabled(RISCVCPU *cpu, uint32_t ext_offset, bool en);
> -bool cpu_cfg_ext_is_user_set(uint32_t ext_offset);
>  bool isa_ext_is_enabled(RISCVCPU *cpu, uint32_t ext_offset);
>  int cpu_cfg_ext_get_min_version(uint32_t ext_offset);
> +void set_misa(CPURISCVState *env, RISCVMXL mxl, uint32_t ext);

riscv_cpu_set_misa() ?

>  void riscv_cpu_disable_priv_spec_isa_exts(RISCVCPU *cpu);
>  
>  typedef struct RISCVCPUMultiExtConfig {
> diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
> index 2024c98793..68ce3cbcb9 100644
> --- a/target/riscv/tcg/tcg-cpu.c
> +++ b/target/riscv/tcg/tcg-cpu.c
> @@ -23,12 +23,22 @@
>  #include "pmu.h"
>  #include "time_helper.h"
>  #include "qapi/error.h"
> +#include "qapi/visitor.h"
>  #include "qemu/accel.h"
>  #include "qemu/error-report.h"
>  #include "hw/core/accel-cpu.h"
>  #include "hw/core/tcg-cpu-ops.h"
>  #include "tcg/tcg.h"
>  
> +/* Hash that stores user set extensions */
> +static GHashTable *multi_ext_user_opts;
> +
> +static bool cpu_cfg_ext_is_user_set(uint32_t ext_offset)
> +{
> +    return g_hash_table_contains(multi_ext_user_opts,
> +                                 GUINT_TO_POINTER(ext_offset));
> +}
> +
>  static void riscv_cpu_synchronize_from_tb(CPUState *cs,
>                                            const TranslationBlock *tb)
>  {
> @@ -564,6 +574,133 @@ static bool tcg_cpu_realizefn(CPUState *cs, Error **errp)
>      return true;
>  }
>  
> +static void cpu_set_multi_ext_cfg(Object *obj, Visitor *v, const char *name,
> +                                  void *opaque, Error **errp)
> +{
> +    const RISCVCPUMultiExtConfig *multi_ext_cfg = opaque;
> +    bool value;
> +
> +    if (!visit_type_bool(v, name, &value, errp)) {
> +        return;
> +    }
> +
> +    isa_ext_update_enabled(RISCV_CPU(obj), multi_ext_cfg->offset, value);
> +
> +    g_hash_table_insert(multi_ext_user_opts,
> +                        GUINT_TO_POINTER(multi_ext_cfg->offset),
> +                        (gpointer)value);
> +}
> +
> +static void cpu_get_multi_ext_cfg(Object *obj, Visitor *v, const char *name,
> +                                  void *opaque, Error **errp)
> +{
> +    const RISCVCPUMultiExtConfig *multi_ext_cfg = opaque;
> +    bool value = isa_ext_is_enabled(RISCV_CPU(obj), multi_ext_cfg->offset);
> +
> +    visit_type_bool(v, name, &value, errp);
> +}
> +
> +static void cpu_add_multi_ext_prop(Object *cpu_obj,
> +                                   const RISCVCPUMultiExtConfig *multi_cfg)
> +{
> +    object_property_add(cpu_obj, multi_cfg->name, "bool",
> +                        cpu_get_multi_ext_cfg,
> +                        cpu_set_multi_ext_cfg,
> +                        NULL, (void *)multi_cfg);
> +
> +    /*
> +     * Set def val directly instead of using
> +     * object_property_set_bool() to save the set()
> +     * callback hash for user inputs.
> +     */
> +    isa_ext_update_enabled(RISCV_CPU(cpu_obj), multi_cfg->offset,
> +                           multi_cfg->enabled);
> +}
> +
> +static void riscv_cpu_add_multiext_prop_array(Object *obj,
> +                                        const RISCVCPUMultiExtConfig *array)
> +{
> +    const RISCVCPUMultiExtConfig *prop;
> +
> +    for (prop = array; prop && prop->name; prop++) {
> +        cpu_add_multi_ext_prop(obj, prop);
> +    }
> +}
> +
> +/*
> + * Add CPU properties with user-facing flags.
> + *
> + * This will overwrite existing env->misa_ext values with the
> + * defaults set via riscv_cpu_add_misa_properties().
> + */
> +static void riscv_cpu_add_user_properties(Object *obj)
> +{
> +#ifndef CONFIG_USER_ONLY
> +    riscv_add_satp_mode_properties(obj);
> +#endif
> +
> +    riscv_cpu_add_misa_properties(obj);
> +
> +    riscv_cpu_add_multiext_prop_array(obj, riscv_cpu_extensions);
> +    riscv_cpu_add_multiext_prop_array(obj, riscv_cpu_vendor_exts);
> +    riscv_cpu_add_multiext_prop_array(obj, riscv_cpu_experimental_exts);
> +
> +    for (Property *prop = riscv_cpu_options; prop && prop->name; prop++) {
> +        qdev_property_add_static(DEVICE(obj), prop);
> +    }
> +}
> +
> +/*
> + * The 'max' type CPU will have all possible ratified
> + * non-vendor extensions enabled.
> + */
> +static void riscv_init_max_cpu_extensions(Object *obj)
> +{
> +    RISCVCPU *cpu = RISCV_CPU(obj);
> +    CPURISCVState *env = &cpu->env;
> +    const RISCVCPUMultiExtConfig *prop;
> +
> +    /* Enable RVG, RVJ and RVV that are disabled by default */
> +    set_misa(env, env->misa_mxl, env->misa_ext | RVG | RVJ | RVV);
> +
> +    for (prop = riscv_cpu_extensions; prop && prop->name; prop++) {
> +        isa_ext_update_enabled(cpu, prop->offset, true);
> +    }
> +
> +    /* set vector version */
> +    env->vext_ver = VEXT_VERSION_1_00_0;
> +
> +    /* Zfinx is not compatible with F. Disable it */
> +    isa_ext_update_enabled(cpu, CPU_CFG_OFFSET(ext_zfinx), false);
> +    isa_ext_update_enabled(cpu, CPU_CFG_OFFSET(ext_zdinx), false);
> +    isa_ext_update_enabled(cpu, CPU_CFG_OFFSET(ext_zhinx), false);
> +    isa_ext_update_enabled(cpu, CPU_CFG_OFFSET(ext_zhinxmin), false);
> +
> +    isa_ext_update_enabled(cpu, CPU_CFG_OFFSET(ext_zce), false);
> +    isa_ext_update_enabled(cpu, CPU_CFG_OFFSET(ext_zcmp), false);
> +    isa_ext_update_enabled(cpu, CPU_CFG_OFFSET(ext_zcmt), false);
> +
> +    if (env->misa_mxl != MXL_RV32) {
> +        isa_ext_update_enabled(cpu, CPU_CFG_OFFSET(ext_zcf), false);
> +    }
> +}
> +
> +static void tcg_cpu_instance_init(CPUState *cs)
> +{
> +    RISCVCPU *cpu = RISCV_CPU(cs);
> +    Object *obj = OBJECT(cpu);
> +    RISCVCPUClass *rcc = RISCV_CPU_GET_CLASS(obj);
> +
> +    if (rcc->user_extension_properties) {
> +        multi_ext_user_opts = g_hash_table_new(NULL, g_direct_equal);
> +        riscv_cpu_add_user_properties(obj);
> +    }
> +
> +    if (cpu->cfg.max_features) {
> +        riscv_init_max_cpu_extensions(obj);
> +    }
> +}
> +
>  static void tcg_cpu_init_ops(AccelCPUClass *accel_cpu, CPUClass *cc)
>  {
>      /*
> @@ -583,6 +720,7 @@ static void tcg_cpu_accel_class_init(ObjectClass *oc, void *data)
>      AccelCPUClass *acc = ACCEL_CPU_CLASS(oc);
>  
>      acc->cpu_class_init = tcg_cpu_class_init;
> +    acc->cpu_instance_init = tcg_cpu_instance_init;
>      acc->cpu_realizefn = tcg_cpu_realizefn;
>  }
>  
> -- 
> 2.41.0
> 
>

Otherwise,

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


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

* Re: [PATCH 16/20] target/riscv/tcg: move riscv_cpu_add_misa_properties() to tcg-cpu.c
  2023-08-25 13:08 ` [PATCH 16/20] target/riscv/tcg: move riscv_cpu_add_misa_properties() to tcg-cpu.c Daniel Henrique Barboza
@ 2023-08-31 12:01   ` Andrew Jones
  2023-09-04 14:21     ` Daniel Henrique Barboza
  0 siblings, 1 reply; 51+ messages in thread
From: Andrew Jones @ 2023-08-31 12:01 UTC (permalink / raw)
  To: Daniel Henrique Barboza
  Cc: qemu-devel, qemu-riscv, alistair.francis, bmeng, liweiwei,
	zhiwei_liu, palmer

On Fri, Aug 25, 2023 at 10:08:49AM -0300, Daniel Henrique Barboza wrote:
> All code related to MISA TCG properties is also moved.
> 
> At this point, all TCG properties handling is done in tcg-cpu.c, all KVM
> properties handling is done in kvm-cpu.c.
> 
> Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
> ---
>  target/riscv/cpu.c         | 89 --------------------------------------
>  target/riscv/cpu.h         |  1 -
>  target/riscv/tcg/tcg-cpu.c | 84 +++++++++++++++++++++++++++++++++++
>  3 files changed, 84 insertions(+), 90 deletions(-)
> 
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index 89b09a7e89..3c9db46837 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -1201,49 +1201,6 @@ static void riscv_cpu_init(Object *obj)
>  #endif /* CONFIG_USER_ONLY */
>  }
>  
> -typedef struct RISCVCPUMisaExtConfig {
> -    const char *name;
> -    const char *description;
> -    target_ulong misa_bit;
> -    bool enabled;
> -} RISCVCPUMisaExtConfig;
> -
> -static void cpu_set_misa_ext_cfg(Object *obj, Visitor *v, const char *name,
> -                                 void *opaque, Error **errp)
> -{
> -    const RISCVCPUMisaExtConfig *misa_ext_cfg = opaque;
> -    target_ulong misa_bit = misa_ext_cfg->misa_bit;
> -    RISCVCPU *cpu = RISCV_CPU(obj);
> -    CPURISCVState *env = &cpu->env;
> -    bool value;
> -
> -    if (!visit_type_bool(v, name, &value, errp)) {
> -        return;
> -    }
> -
> -    if (value) {
> -        env->misa_ext |= misa_bit;
> -        env->misa_ext_mask |= misa_bit;
> -    } else {
> -        env->misa_ext &= ~misa_bit;
> -        env->misa_ext_mask &= ~misa_bit;
> -    }
> -}
> -
> -static void cpu_get_misa_ext_cfg(Object *obj, Visitor *v, const char *name,
> -                                 void *opaque, Error **errp)
> -{
> -    const RISCVCPUMisaExtConfig *misa_ext_cfg = opaque;
> -    target_ulong misa_bit = misa_ext_cfg->misa_bit;
> -    RISCVCPU *cpu = RISCV_CPU(obj);
> -    CPURISCVState *env = &cpu->env;
> -    bool value;
> -
> -    value = env->misa_ext & misa_bit;
> -
> -    visit_type_bool(v, name, &value, errp);
> -}
> -
>  typedef struct misa_ext_info {
>      const char *name;
>      const char *description;
> @@ -1304,52 +1261,6 @@ const char *riscv_get_misa_ext_description(uint32_t bit)
>      return val;
>  }
>  
> -#define MISA_CFG(_bit, _enabled) \
> -    {.misa_bit = _bit, .enabled = _enabled}
> -
> -static RISCVCPUMisaExtConfig misa_ext_cfgs[] = {
> -    MISA_CFG(RVA, true),
> -    MISA_CFG(RVC, true),
> -    MISA_CFG(RVD, true),
> -    MISA_CFG(RVF, true),
> -    MISA_CFG(RVI, true),
> -    MISA_CFG(RVE, false),
> -    MISA_CFG(RVM, true),
> -    MISA_CFG(RVS, true),
> -    MISA_CFG(RVU, true),
> -    MISA_CFG(RVH, true),
> -    MISA_CFG(RVJ, false),
> -    MISA_CFG(RVV, false),
> -    MISA_CFG(RVG, false),
> -};
> -
> -void riscv_cpu_add_misa_properties(Object *cpu_obj)
> -{
> -    int i;
> -
> -    for (i = 0; i < ARRAY_SIZE(misa_ext_cfgs); i++) {
> -        RISCVCPUMisaExtConfig *misa_cfg = &misa_ext_cfgs[i];
> -        int bit = misa_cfg->misa_bit;
> -
> -        misa_cfg->name = riscv_get_misa_ext_name(bit);
> -        misa_cfg->description = riscv_get_misa_ext_description(bit);
> -
> -        /* Check if KVM already created the property */
> -        if (object_property_find(cpu_obj, misa_cfg->name)) {
> -            continue;
> -        }
> -
> -        object_property_add(cpu_obj, misa_cfg->name, "bool",
> -                            cpu_get_misa_ext_cfg,
> -                            cpu_set_misa_ext_cfg,
> -                            NULL, (void *)misa_cfg);
> -        object_property_set_description(cpu_obj, misa_cfg->name,
> -                                        misa_cfg->description);
> -        object_property_set_bool(cpu_obj, misa_cfg->name,
> -                                 misa_cfg->enabled, NULL);
> -    }
> -}
> -
>  #define MULTI_EXT_CFG_BOOL(_name, _prop, _defval) \
>      {.name = _name, .offset = CPU_CFG_OFFSET(_prop), \
>       .enabled = _defval}
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index 74fbb33e09..4269523e24 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -726,7 +726,6 @@ extern const RISCVCPUMultiExtConfig riscv_cpu_vendor_exts[];
>  extern const RISCVCPUMultiExtConfig riscv_cpu_experimental_exts[];
>  extern Property riscv_cpu_options[];
>  
> -void riscv_cpu_add_misa_properties(Object *cpu_obj);
>  void riscv_add_satp_mode_properties(Object *obj);
>  
>  /* CSR function table */
> diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
> index 68ce3cbcb9..8e3f55d3a6 100644
> --- a/target/riscv/tcg/tcg-cpu.c
> +++ b/target/riscv/tcg/tcg-cpu.c
> @@ -574,6 +574,90 @@ static bool tcg_cpu_realizefn(CPUState *cs, Error **errp)
>      return true;
>  }
>  
> +typedef struct RISCVCPUMisaExtConfig {
> +    const char *name;
> +    const char *description;
> +    target_ulong misa_bit;
> +    bool enabled;
> +} RISCVCPUMisaExtConfig;
> +
> +static void cpu_set_misa_ext_cfg(Object *obj, Visitor *v, const char *name,
> +                                 void *opaque, Error **errp)
> +{
> +    const RISCVCPUMisaExtConfig *misa_ext_cfg = opaque;
> +    target_ulong misa_bit = misa_ext_cfg->misa_bit;
> +    RISCVCPU *cpu = RISCV_CPU(obj);
> +    CPURISCVState *env = &cpu->env;
> +    bool value;
> +
> +    if (!visit_type_bool(v, name, &value, errp)) {
> +        return;
> +    }
> +
> +    if (value) {
> +        env->misa_ext |= misa_bit;
> +        env->misa_ext_mask |= misa_bit;
> +    } else {
> +        env->misa_ext &= ~misa_bit;
> +        env->misa_ext_mask &= ~misa_bit;
> +    }
> +}
> +
> +static void cpu_get_misa_ext_cfg(Object *obj, Visitor *v, const char *name,
> +                                 void *opaque, Error **errp)
> +{
> +    const RISCVCPUMisaExtConfig *misa_ext_cfg = opaque;
> +    target_ulong misa_bit = misa_ext_cfg->misa_bit;
> +    RISCVCPU *cpu = RISCV_CPU(obj);
> +    CPURISCVState *env = &cpu->env;
> +    bool value;
> +
> +    value = env->misa_ext & misa_bit;
> +
> +    visit_type_bool(v, name, &value, errp);
> +}
> +
> +#define MISA_CFG(_bit, _enabled) \
> +    {.misa_bit = _bit, .enabled = _enabled}
> +
> +static RISCVCPUMisaExtConfig misa_ext_cfgs[] = {

Can this be const?

> +    MISA_CFG(RVA, true),
> +    MISA_CFG(RVC, true),
> +    MISA_CFG(RVD, true),
> +    MISA_CFG(RVF, true),
> +    MISA_CFG(RVI, true),
> +    MISA_CFG(RVE, false),
> +    MISA_CFG(RVM, true),
> +    MISA_CFG(RVS, true),
> +    MISA_CFG(RVU, true),
> +    MISA_CFG(RVH, true),
> +    MISA_CFG(RVJ, false),
> +    MISA_CFG(RVV, false),
> +    MISA_CFG(RVG, false),
> +};
> +
> +static void riscv_cpu_add_misa_properties(Object *cpu_obj)
> +{
> +    int i;
> +
> +    for (i = 0; i < ARRAY_SIZE(misa_ext_cfgs); i++) {
> +        RISCVCPUMisaExtConfig *misa_cfg = &misa_ext_cfgs[i];
> +        int bit = misa_cfg->misa_bit;
> +
> +        misa_cfg->name = riscv_get_misa_ext_name(bit);
> +        misa_cfg->description = riscv_get_misa_ext_description(bit);
> +
> +        object_property_add(cpu_obj, misa_cfg->name, "bool",
> +                            cpu_get_misa_ext_cfg,
> +                            cpu_set_misa_ext_cfg,
> +                            NULL, (void *)misa_cfg);
> +        object_property_set_description(cpu_obj, misa_cfg->name,
> +                                        misa_cfg->description);
> +        object_property_set_bool(cpu_obj, misa_cfg->name,
> +                                 misa_cfg->enabled, NULL);
> +    }
> +}
> +
>  static void cpu_set_multi_ext_cfg(Object *obj, Visitor *v, const char *name,
>                                    void *opaque, Error **errp)
>  {
> -- 
> 2.41.0
> 
>

Otherwise,

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


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

* Re: [PATCH 17/20] target/riscv/cpu.c: export isa_edata_arr[]
  2023-08-25 13:08 ` [PATCH 17/20] target/riscv/cpu.c: export isa_edata_arr[] Daniel Henrique Barboza
@ 2023-08-31 12:06   ` Andrew Jones
  0 siblings, 0 replies; 51+ messages in thread
From: Andrew Jones @ 2023-08-31 12:06 UTC (permalink / raw)
  To: Daniel Henrique Barboza
  Cc: qemu-devel, qemu-riscv, alistair.francis, bmeng, liweiwei,
	zhiwei_liu, palmer

On Fri, Aug 25, 2023 at 10:08:50AM -0300, Daniel Henrique Barboza wrote:
> This array will be read by the TCG accel class, allowing it to handle
> priv spec verifications on its own. The array will remain here in cpu.c
> because it's also used by the riscv,isa string function.
> 
> To export it we'll make it constant and finish it with an empty element
                             ^ it's already constant

> since ARRAY_SIZE() won't work outside of cpu.c. Get rid of its
> ARRAY_SIZE() usage now to alleviate the changes for the next patch.
> 
> Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
> ---
>  target/riscv/cpu.c | 47 +++++++++++++++++++++-------------------------
>  target/riscv/cpu.h |  7 +++++++
>  2 files changed, 28 insertions(+), 26 deletions(-)
> 
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index 3c9db46837..ac5ad4727c 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -41,15 +41,6 @@ static const char riscv_single_letter_exts[] = "IEMAFDQCPVH";
>  const uint32_t misa_bits[] = {RVI, RVE, RVM, RVA, RVF, RVD, RVV,
>                                RVC, RVS, RVU, RVH, RVJ, RVG};
>  
> -struct isa_ext_data {
> -    const char *name;
> -    int min_version;
> -    int ext_enable_offset;
> -};
> -
> -#define ISA_EXT_DATA_ENTRY(_name, _min_ver, _prop) \
> -    {#_name, _min_ver, CPU_CFG_OFFSET(_prop)}
> -
>  /*
>   * From vector_helper.c
>   * Note that vector data is stored in host-endian 64-bit chunks,
> @@ -61,6 +52,9 @@ struct isa_ext_data {
>  #define BYTE(x)   (x)
>  #endif
>  
> +#define ISA_EXT_DATA_ENTRY(_name, _min_ver, _prop) \
> +    {#_name, _min_ver, CPU_CFG_OFFSET(_prop)}
> +
>  /*
>   * Here are the ordering rules of extension naming defined by RISC-V
>   * specification :
> @@ -81,7 +75,7 @@ struct isa_ext_data {
>   * Single letter extensions are checked in riscv_cpu_validate_misa_priv()
>   * instead.
>   */
> -static const struct isa_ext_data isa_edata_arr[] = {
> +const RISCVIsaExtData isa_edata_arr[] = {
>      ISA_EXT_DATA_ENTRY(zicbom, PRIV_VERSION_1_12_0, ext_icbom),
>      ISA_EXT_DATA_ENTRY(zicboz, PRIV_VERSION_1_12_0, ext_icboz),
>      ISA_EXT_DATA_ENTRY(zicond, PRIV_VERSION_1_12_0, ext_zicond),
> @@ -160,6 +154,8 @@ static const struct isa_ext_data isa_edata_arr[] = {
>      ISA_EXT_DATA_ENTRY(xtheadmempair, PRIV_VERSION_1_11_0, ext_xtheadmempair),
>      ISA_EXT_DATA_ENTRY(xtheadsync, PRIV_VERSION_1_11_0, ext_xtheadsync),
>      ISA_EXT_DATA_ENTRY(xventanacondops, PRIV_VERSION_1_12_0, ext_XVentanaCondOps),
> +
> +    DEFINE_PROP_END_OF_LIST(),
>  };
>  
>  bool isa_ext_is_enabled(RISCVCPU *cpu, uint32_t ext_offset)
> @@ -178,14 +174,14 @@ void isa_ext_update_enabled(RISCVCPU *cpu, uint32_t ext_offset, bool en)
>  
>  int cpu_cfg_ext_get_min_version(uint32_t ext_offset)
>  {
> -    int i;
> +    const RISCVIsaExtData *edata;
>  
> -    for (i = 0; i < ARRAY_SIZE(isa_edata_arr); i++) {
> -        if (isa_edata_arr[i].ext_enable_offset != ext_offset) {
> +    for (edata = isa_edata_arr; edata && edata->name; edata++) {

Just checking edata->name is sufficient.

> +        if (edata->ext_enable_offset != ext_offset) {
>              continue;
>          }
>  
> -        return isa_edata_arr[i].min_version;
> +        return edata->min_version;
>      }
>  
>      /* Default to oldest priv spec if no match found */
> @@ -933,22 +929,21 @@ static void riscv_cpu_disas_set_info(CPUState *s, disassemble_info *info)
>  void riscv_cpu_disable_priv_spec_isa_exts(RISCVCPU *cpu)
>  {
>      CPURISCVState *env = &cpu->env;
> -    int i;
> +    const RISCVIsaExtData *edata;
>  
>      /* Force disable extensions if priv spec version does not match */
> -    for (i = 0; i < ARRAY_SIZE(isa_edata_arr); i++) {
> -        if (isa_ext_is_enabled(cpu, isa_edata_arr[i].ext_enable_offset) &&
> -            (env->priv_ver < isa_edata_arr[i].min_version)) {
> -            isa_ext_update_enabled(cpu, isa_edata_arr[i].ext_enable_offset,
> -                                   false);
> +    for (edata = isa_edata_arr; edata && edata->name; edata++) {
> +        if (isa_ext_is_enabled(cpu, edata->ext_enable_offset) &&
> +            (env->priv_ver < edata->min_version)) {
> +            isa_ext_update_enabled(cpu, edata->ext_enable_offset, false);
>  #ifndef CONFIG_USER_ONLY
>              warn_report("disabling %s extension for hart 0x" TARGET_FMT_lx
>                          " because privilege spec version does not match",
> -                        isa_edata_arr[i].name, env->mhartid);
> +                        edata->name, env->mhartid);
>  #else
>              warn_report("disabling %s extension because "
>                          "privilege spec version does not match",
> -                        isa_edata_arr[i].name);
> +                        edata->name);
>  #endif
>          }
>      }
> @@ -1614,13 +1609,13 @@ static void riscv_cpu_class_init(ObjectClass *c, void *data)
>  static void riscv_isa_string_ext(RISCVCPU *cpu, char **isa_str,
>                                   int max_str_len)
>  {
> +    const RISCVIsaExtData *edata;
>      char *old = *isa_str;
>      char *new = *isa_str;
> -    int i;
>  
> -    for (i = 0; i < ARRAY_SIZE(isa_edata_arr); i++) {
> -        if (isa_ext_is_enabled(cpu, isa_edata_arr[i].ext_enable_offset)) {
> -            new = g_strconcat(old, "_", isa_edata_arr[i].name, NULL);
> +    for (edata = isa_edata_arr; edata && edata->name; edata++) {
> +        if (isa_ext_is_enabled(cpu, edata->ext_enable_offset)) {
> +            new = g_strconcat(old, "_", edata->name, NULL);
>              g_free(old);
>              old = new;
>          }
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index 4269523e24..d9a17df46a 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -726,6 +726,13 @@ extern const RISCVCPUMultiExtConfig riscv_cpu_vendor_exts[];
>  extern const RISCVCPUMultiExtConfig riscv_cpu_experimental_exts[];
>  extern Property riscv_cpu_options[];
>  
> +typedef struct isa_ext_data {
> +    const char *name;
> +    int min_version;
> +    int ext_enable_offset;
> +} RISCVIsaExtData;
> +extern const RISCVIsaExtData isa_edata_arr[];
> +
>  void riscv_add_satp_mode_properties(Object *obj);
>  
>  /* CSR function table */
> -- 
> 2.41.0
> 
>

Otherwise,

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



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

* Re: [PATCH 18/20] target/riscv/cpu: move priv spec functions to tcg-cpu.c
  2023-08-25 13:08 ` [PATCH 18/20] target/riscv/cpu: move priv spec functions to tcg-cpu.c Daniel Henrique Barboza
@ 2023-08-31 12:07   ` Andrew Jones
  0 siblings, 0 replies; 51+ messages in thread
From: Andrew Jones @ 2023-08-31 12:07 UTC (permalink / raw)
  To: Daniel Henrique Barboza
  Cc: qemu-devel, qemu-riscv, alistair.francis, bmeng, liweiwei,
	zhiwei_liu, palmer

On Fri, Aug 25, 2023 at 10:08:51AM -0300, Daniel Henrique Barboza wrote:
> Priv spec validation is TCG specific. Move it to the TCG accel class.
> 
> Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
> ---
>  target/riscv/cpu.c         | 39 --------------------------------------
>  target/riscv/cpu.h         |  2 --
>  target/riscv/tcg/tcg-cpu.c | 39 ++++++++++++++++++++++++++++++++++++++
>  3 files changed, 39 insertions(+), 41 deletions(-)
> 
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index ac5ad4727c..6817f94c2c 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -172,22 +172,6 @@ void isa_ext_update_enabled(RISCVCPU *cpu, uint32_t ext_offset, bool en)
>      *ext_enabled = en;
>  }
>  
> -int cpu_cfg_ext_get_min_version(uint32_t ext_offset)
> -{
> -    const RISCVIsaExtData *edata;
> -
> -    for (edata = isa_edata_arr; edata && edata->name; edata++) {
> -        if (edata->ext_enable_offset != ext_offset) {
> -            continue;
> -        }
> -
> -        return edata->min_version;
> -    }
> -
> -    /* Default to oldest priv spec if no match found */
> -    return PRIV_VERSION_1_10_0;
> -}
> -
>  const char * const riscv_int_regnames[] = {
>      "x0/zero", "x1/ra",  "x2/sp",  "x3/gp",  "x4/tp",  "x5/t0",   "x6/t1",
>      "x7/t2",   "x8/s0",  "x9/s1",  "x10/a0", "x11/a1", "x12/a2",  "x13/a3",
> @@ -926,29 +910,6 @@ static void riscv_cpu_disas_set_info(CPUState *s, disassemble_info *info)
>      }
>  }
>  
> -void riscv_cpu_disable_priv_spec_isa_exts(RISCVCPU *cpu)
> -{
> -    CPURISCVState *env = &cpu->env;
> -    const RISCVIsaExtData *edata;
> -
> -    /* Force disable extensions if priv spec version does not match */
> -    for (edata = isa_edata_arr; edata && edata->name; edata++) {
> -        if (isa_ext_is_enabled(cpu, edata->ext_enable_offset) &&
> -            (env->priv_ver < edata->min_version)) {
> -            isa_ext_update_enabled(cpu, edata->ext_enable_offset, false);
> -#ifndef CONFIG_USER_ONLY
> -            warn_report("disabling %s extension for hart 0x" TARGET_FMT_lx
> -                        " because privilege spec version does not match",
> -                        edata->name, env->mhartid);
> -#else
> -            warn_report("disabling %s extension because "
> -                        "privilege spec version does not match",
> -                        edata->name);
> -#endif
> -        }
> -    }
> -}
> -
>  #ifndef CONFIG_USER_ONLY
>  static void riscv_cpu_satp_mode_finalize(RISCVCPU *cpu, Error **errp)
>  {
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index d9a17df46a..4254f04684 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -711,9 +711,7 @@ enum riscv_pmu_event_idx {
>  /* used by tcg/tcg-cpu.c*/
>  void isa_ext_update_enabled(RISCVCPU *cpu, uint32_t ext_offset, bool en);
>  bool isa_ext_is_enabled(RISCVCPU *cpu, uint32_t ext_offset);
> -int cpu_cfg_ext_get_min_version(uint32_t ext_offset);
>  void set_misa(CPURISCVState *env, RISCVMXL mxl, uint32_t ext);
> -void riscv_cpu_disable_priv_spec_isa_exts(RISCVCPU *cpu);
>  
>  typedef struct RISCVCPUMultiExtConfig {
>      const char *name;
> diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
> index 8e3f55d3a6..6c91978920 100644
> --- a/target/riscv/tcg/tcg-cpu.c
> +++ b/target/riscv/tcg/tcg-cpu.c
> @@ -97,6 +97,22 @@ const struct TCGCPUOps riscv_tcg_ops = {
>  #endif /* !CONFIG_USER_ONLY */
>  };
>  
> +static int cpu_cfg_ext_get_min_version(uint32_t ext_offset)
> +{
> +    const RISCVIsaExtData *edata;
> +
> +    for (edata = isa_edata_arr; edata && edata->name; edata++) {
> +        if (edata->ext_enable_offset != ext_offset) {
> +            continue;
> +        }
> +
> +        return edata->min_version;
> +    }
> +
> +    /* Default to oldest priv spec if no match found */
> +    return PRIV_VERSION_1_10_0;
> +}
> +
>  static void cpu_cfg_ext_auto_update(RISCVCPU *cpu, uint32_t ext_offset,
>                                      bool value)
>  {
> @@ -220,6 +236,29 @@ static void riscv_cpu_validate_v(CPURISCVState *env, RISCVCPUConfig *cfg,
>      }
>  }
>  
> +static void riscv_cpu_disable_priv_spec_isa_exts(RISCVCPU *cpu)
> +{
> +    CPURISCVState *env = &cpu->env;
> +    const RISCVIsaExtData *edata;
> +
> +    /* Force disable extensions if priv spec version does not match */
> +    for (edata = isa_edata_arr; edata && edata->name; edata++) {
> +        if (isa_ext_is_enabled(cpu, edata->ext_enable_offset) &&
> +            (env->priv_ver < edata->min_version)) {
> +            isa_ext_update_enabled(cpu, edata->ext_enable_offset, false);
> +#ifndef CONFIG_USER_ONLY
> +            warn_report("disabling %s extension for hart 0x" TARGET_FMT_lx
> +                        " because privilege spec version does not match",
> +                        edata->name, env->mhartid);
> +#else
> +            warn_report("disabling %s extension because "
> +                        "privilege spec version does not match",
> +                        edata->name);
> +#endif
> +        }
> +    }
> +}
> +
>  /*
>   * Check consistency between chosen extensions while setting
>   * cpu->cfg accordingly.
> -- 
> 2.41.0
> 
>

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


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

* Re: [PATCH 19/20] target/riscv: add 'tcg_supported' class property
  2023-08-25 13:08 ` [PATCH 19/20] target/riscv: add 'tcg_supported' class property Daniel Henrique Barboza
@ 2023-08-31 12:25   ` Andrew Jones
  0 siblings, 0 replies; 51+ messages in thread
From: Andrew Jones @ 2023-08-31 12:25 UTC (permalink / raw)
  To: Daniel Henrique Barboza
  Cc: qemu-devel, qemu-riscv, alistair.francis, bmeng, liweiwei,
	zhiwei_liu, palmer

On Fri, Aug 25, 2023 at 10:08:52AM -0300, Daniel Henrique Barboza wrote:
> This property indicates if a CPU supports TCG acceleration. All CPUs but
> the 'host' CPU supports it.
> 
> The error in tcg_cpu_realizefn() can now be made generic in case more
> non-TCG CPUs are added in the future.
> 
> Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
> ---
>  target/riscv/cpu-qom.h     |  1 +
>  target/riscv/cpu.c         | 10 ++++++++++
>  target/riscv/cpu.h         |  1 +
>  target/riscv/tcg/tcg-cpu.c |  7 +++++--
>  4 files changed, 17 insertions(+), 2 deletions(-)
> 
> diff --git a/target/riscv/cpu-qom.h b/target/riscv/cpu-qom.h
> index 7c76dc0dcc..e86b76f9fe 100644
> --- a/target/riscv/cpu-qom.h
> +++ b/target/riscv/cpu-qom.h
> @@ -71,5 +71,6 @@ struct RISCVCPUClass {
>      ResettablePhases parent_phases;
>  
>      bool user_extension_properties;
> +    bool tcg_supported;
>  };
>  #endif /* RISCV_CPU_QOM_H */
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index 6817f94c2c..f749ea2a2e 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -625,6 +625,14 @@ static void rv32_imafcu_nommu_cpu_init(Object *obj)
>  }
>  #endif
>  
> +char *riscv_cpu_get_name(RISCVCPUClass *rcc)
> +{
> +    const char *typename = object_class_get_name(OBJECT_CLASS(rcc));
> +
> +    return g_strndup(typename,
> +                     strlen(typename) - strlen("-" TYPE_RISCV_CPU));
                                                  RISCV_CPU_TYPE_SUFFIX

Could also add the assert like x86 has in x86_cpu_class_get_model_name()

> +}
> +
>  static ObjectClass *riscv_cpu_class_by_name(const char *cpu_model)
>  {
>      ObjectClass *oc;
> @@ -1637,6 +1645,7 @@ static void riscv_dynamic_cpu_class_init(ObjectClass *c, void *data)
>      RISCVCPUClass *rcc = RISCV_CPU_CLASS(c);
>  
>      rcc->user_extension_properties = true;
> +    rcc->tcg_supported = true;

Rather than add this tcg_supported to most (all but 'host'?) cpus, what
about doing what x86 does and create an 'accel_uses_host_cpuid()' function
which is checked in realize?

>  }
>  
>  static void riscv_vendor_cpu_class_init(ObjectClass *c, void *data)
> @@ -1644,6 +1653,7 @@ static void riscv_vendor_cpu_class_init(ObjectClass *c, void *data)
>      RISCVCPUClass *rcc = RISCV_CPU_CLASS(c);
>  
>      rcc->user_extension_properties = false;
> +    rcc->tcg_supported = true;
>  }
>  
>  #define DEFINE_DYNAMIC_CPU(type_name, initfn) \
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index 4254f04684..1e6ecf52ee 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -732,6 +732,7 @@ typedef struct isa_ext_data {
>  extern const RISCVIsaExtData isa_edata_arr[];
>  
>  void riscv_add_satp_mode_properties(Object *obj);
> +char *riscv_cpu_get_name(RISCVCPUClass *rcc);
>  
>  /* CSR function table */
>  extern riscv_csr_operations csr_ops[CSR_TABLE_SIZE];
> diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
> index 6c91978920..a13796c597 100644
> --- a/target/riscv/tcg/tcg-cpu.c
> +++ b/target/riscv/tcg/tcg-cpu.c
> @@ -554,11 +554,14 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp)
>  static bool tcg_cpu_realizefn(CPUState *cs, Error **errp)
>  {
>      RISCVCPU *cpu = RISCV_CPU(cs);
> +    RISCVCPUClass *rcc = RISCV_CPU_GET_CLASS(cpu);
>      CPURISCVState *env = &cpu->env;
>      Error *local_err = NULL;
>  
> -    if (object_dynamic_cast(OBJECT(cpu), TYPE_RISCV_CPU_HOST)) {
> -        error_setg(errp, "'host' CPU is not compatible with TCG acceleration");
> +    if (!rcc->tcg_supported) {
> +        g_autofree char *name = riscv_cpu_get_name(rcc);
> +        error_setg(errp, "'%s' CPU is not compatible with TCG acceleration",
> +                   name);
>          return false;
>      }
>  
> -- 
> 2.41.0
> 
>

Thanks,
drew


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

* Re: [PATCH 20/20] target/riscv: add 'kvm_supported' class property
  2023-08-25 13:08 ` [PATCH 20/20] target/riscv: add 'kvm_supported' " Daniel Henrique Barboza
@ 2023-08-31 12:47   ` Andrew Jones
  2023-09-01 20:57     ` Daniel Henrique Barboza
  0 siblings, 1 reply; 51+ messages in thread
From: Andrew Jones @ 2023-08-31 12:47 UTC (permalink / raw)
  To: Daniel Henrique Barboza
  Cc: qemu-devel, qemu-riscv, alistair.francis, bmeng, liweiwei,
	zhiwei_liu, palmer

On Fri, Aug 25, 2023 at 10:08:53AM -0300, Daniel Henrique Barboza wrote:
> This follows the same idea of 'tcg_support' property added in the
> previous patch. Note that we're now implementing the 'cpu_realizefn' for
> the KVMAccel class since this verification is done in realize() time.
> 
> Supporting vendor CPUs with KVM is not possible. We rely on the
> extension support of the KVM module running in the host, making it
> impossible to guarantee that a vendor CPU will have all the required
> extensions available. The only way to guarantee that a vendor CPU is KVM
> compatible is running KVM in a host that has the same vendor CPU, and

Or to attempt to enable each extension which the vendor CPU expects and
to attempt to disable everything else. If all those actions succeed, then
we can override the ID registers with those of the CPU we want to model
and go for it. There's still risk, though, that the guest kernel will see
the ID registers of the model and attempt to apply some errata workaround
which may or may not work and/or crash the guest.

> for this case we already have the 'host' CPU type.
> 
> We're better of declaring that all vendors CPUs are not KVM capable.
> After this patch, running KVM accel with a vendor CPU will produce an
> error like the following:
> 
> $ ./qemu-system-riscv64 -M virt,accel=kvm -cpu veyron-v1
> qemu-system-riscv64: 'veyron-v1' CPU is not compatible with KVM acceleration

Shouldn't we at least check if the host matches the requested CPU first?
So, if we happen to be on a veyron-v1, then the veyron-v1 model should
be equivalent to 'host'. (They may not be 100% equivalent in practice, but
theoretically they should be, which means trying it and debugging the bugs
should improve the CPU models on both sides.)

> 
> Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
> ---
>  target/riscv/cpu-qom.h     |  1 +
>  target/riscv/cpu.c         |  1 +
>  target/riscv/kvm/kvm-cpu.c | 24 ++++++++++++++++++++++++
>  3 files changed, 26 insertions(+)
> 
> diff --git a/target/riscv/cpu-qom.h b/target/riscv/cpu-qom.h
> index e86b76f9fe..32d9bb07b4 100644
> --- a/target/riscv/cpu-qom.h
> +++ b/target/riscv/cpu-qom.h
> @@ -72,5 +72,6 @@ struct RISCVCPUClass {
>  
>      bool user_extension_properties;
>      bool tcg_supported;
> +    bool kvm_supported;
>  };
>  #endif /* RISCV_CPU_QOM_H */
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index f749ea2a2e..73302bb72a 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -1646,6 +1646,7 @@ static void riscv_dynamic_cpu_class_init(ObjectClass *c, void *data)
>  
>      rcc->user_extension_properties = true;
>      rcc->tcg_supported = true;
> +    rcc->kvm_supported = true;
>  }
>  
>  static void riscv_vendor_cpu_class_init(ObjectClass *c, void *data)
> diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c
> index 501384924b..85f3b8c80e 100644
> --- a/target/riscv/kvm/kvm-cpu.c
> +++ b/target/riscv/kvm/kvm-cpu.c
> @@ -1289,6 +1289,7 @@ static void riscv_kvm_cpu_class_init(ObjectClass *c, void *data)
>      RISCVCPUClass *rcc = RISCV_CPU_CLASS(c);
>  
>      rcc->user_extension_properties = true;
> +    rcc->kvm_supported = true;
>  }
>  
>  static const TypeInfo riscv_kvm_cpu_type_infos[] = {
> @@ -1302,6 +1303,28 @@ static const TypeInfo riscv_kvm_cpu_type_infos[] = {
>  
>  DEFINE_TYPES(riscv_kvm_cpu_type_infos)
>  
> +/*
> + * We'll get here via the following path:
> + *
> + * riscv_cpu_realize()
> + *   -> cpu_exec_realizefn()
> + *      -> kvm_cpu_realizefn() (via accel_cpu_realizefn())
> + */
> +static bool kvm_cpu_realizefn(CPUState *cs, Error **errp)
> +{
> +    RISCVCPU *cpu = RISCV_CPU(cs);
> +    RISCVCPUClass *rcc = RISCV_CPU_GET_CLASS(cpu);
> +
> +    if (!rcc->kvm_supported) {
> +        g_autofree char *name = riscv_cpu_get_name(rcc);
> +        error_setg(errp, "'%s' CPU is not compatible with KVM acceleration",
> +                   name);
> +        return false;
> +    }
> +
> +    return true;
> +}
> +
>  static void kvm_cpu_instance_init(CPUState *cs)
>  {
>      Object *obj = OBJECT(RISCV_CPU(cs));
> @@ -1328,6 +1351,7 @@ static void kvm_cpu_accel_class_init(ObjectClass *oc, void *data)
>      AccelCPUClass *acc = ACCEL_CPU_CLASS(oc);
>  
>      acc->cpu_instance_init = kvm_cpu_instance_init;
> +    acc->cpu_realizefn = kvm_cpu_realizefn;
>  }
>  
>  static const TypeInfo kvm_cpu_accel_type_info = {
> -- 
> 2.41.0
> 
>

I don't think we want kvm_supported nor tcg_supported as they necessarily
bring accelerator knowledge into target/riscv/cpu.c, where the booleans
have to be set. It would be better if the decisions as to what is
supported or not are made in the accelerator's respective files. So, we
try to realize some model with some accel and let that accel do some
checks and error out when it can't. If riscv kvm only supports 'host',
then it's check would simply be "is the model host?" and the inverse for
tcg.

Thanks,
drew


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

* Re: [PATCH 12/20] target/riscv: move KVM only files to kvm subdir
  2023-08-31 11:30   ` Andrew Jones
@ 2023-09-01 17:19     ` Daniel Henrique Barboza
  0 siblings, 0 replies; 51+ messages in thread
From: Daniel Henrique Barboza @ 2023-09-01 17:19 UTC (permalink / raw)
  To: Andrew Jones
  Cc: qemu-devel, qemu-riscv, alistair.francis, bmeng, liweiwei,
	zhiwei_liu, palmer



On 8/31/23 08:30, Andrew Jones wrote:
> On Fri, Aug 25, 2023 at 10:08:45AM -0300, Daniel Henrique Barboza wrote:
>> Move the files to a 'kvm' dir to promote more code separation between
>> accelerators and making our lives easier supporting build options such
>> as --disable-tcg.
>>
>> Rename kvm.c to kvm-cpu.c to keep it in line with its TCG counterpart.
> 
> Now that we have 'kvm' and 'tcg' subdirectories, it seems like we should
> be removing prefixes from files, i.e. 'kvm/cpu.c' and 'tcg/cpu.c' would be
> less verbose and just as easy to identify, but whatever people like...

I don't mind shortening the names. I chose these because x86 names it that
way.

It's also easier to identify in the editor which file I'm editing at that
moment via the filename alone, e.g. tcg-cpu.c is easier to identify than
seeing 'cpu.c' and having to check the rest of the path.

Yes, VSCode user here, too old for vim/emacs :D



Thanks,

Daniel


> 
>>
>> Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
>> ---
>>   hw/riscv/virt.c                       | 2 +-
>>   target/riscv/cpu.c                    | 2 +-
>>   target/riscv/{kvm.c => kvm/kvm-cpu.c} | 0
>>   target/riscv/{ => kvm}/kvm-stub.c     | 0
>>   target/riscv/{ => kvm}/kvm_riscv.h    | 0
>>   target/riscv/kvm/meson.build          | 2 ++
>>   target/riscv/meson.build              | 2 +-
>>   7 files changed, 5 insertions(+), 3 deletions(-)
>>   rename target/riscv/{kvm.c => kvm/kvm-cpu.c} (100%)
>>   rename target/riscv/{ => kvm}/kvm-stub.c (100%)
>>   rename target/riscv/{ => kvm}/kvm_riscv.h (100%)
>>   create mode 100644 target/riscv/kvm/meson.build
>>
>> diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
>> index 388e52a294..77c384ddc3 100644
>> --- a/hw/riscv/virt.c
>> +++ b/hw/riscv/virt.c
>> @@ -35,7 +35,7 @@
>>   #include "hw/riscv/virt.h"
>>   #include "hw/riscv/boot.h"
>>   #include "hw/riscv/numa.h"
>> -#include "kvm_riscv.h"
>> +#include "kvm/kvm_riscv.h"
>>   #include "hw/intc/riscv_aclint.h"
>>   #include "hw/intc/riscv_aplic.h"
>>   #include "hw/intc/riscv_imsic.h"
>> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
>> index 04c6bfaeef..bf6c8519b1 100644
>> --- a/target/riscv/cpu.c
>> +++ b/target/riscv/cpu.c
>> @@ -33,7 +33,7 @@
>>   #include "fpu/softfloat-helpers.h"
>>   #include "sysemu/kvm.h"
>>   #include "sysemu/tcg.h"
>> -#include "kvm_riscv.h"
>> +#include "kvm/kvm_riscv.h"
>>   #include "tcg/tcg.h"
>>   
>>   /* RISC-V CPU definitions */
>> diff --git a/target/riscv/kvm.c b/target/riscv/kvm/kvm-cpu.c
>> similarity index 100%
>> rename from target/riscv/kvm.c
>> rename to target/riscv/kvm/kvm-cpu.c
>> diff --git a/target/riscv/kvm-stub.c b/target/riscv/kvm/kvm-stub.c
>> similarity index 100%
>> rename from target/riscv/kvm-stub.c
>> rename to target/riscv/kvm/kvm-stub.c
>> diff --git a/target/riscv/kvm_riscv.h b/target/riscv/kvm/kvm_riscv.h
>> similarity index 100%
>> rename from target/riscv/kvm_riscv.h
>> rename to target/riscv/kvm/kvm_riscv.h
>> diff --git a/target/riscv/kvm/meson.build b/target/riscv/kvm/meson.build
>> new file mode 100644
>> index 0000000000..1cd6783894
>> --- /dev/null
>> +++ b/target/riscv/kvm/meson.build
>> @@ -0,0 +1,2 @@
>> +riscv_ss.add(when: 'CONFIG_KVM', if_true: files('kvm-cpu.c'),
>> +                                 if_false: files('kvm-stub.c'))
>> diff --git a/target/riscv/meson.build b/target/riscv/meson.build
>> index f0486183fa..c53962215f 100644
>> --- a/target/riscv/meson.build
>> +++ b/target/riscv/meson.build
>> @@ -24,7 +24,6 @@ riscv_ss.add(files(
>>     'zce_helper.c',
>>     'vcrypto_helper.c'
>>   ))
>> -riscv_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c'), if_false: files('kvm-stub.c'))
>>   
>>   riscv_system_ss = ss.source_set()
>>   riscv_system_ss.add(files(
>> @@ -39,6 +38,7 @@ riscv_system_ss.add(files(
>>   ))
>>   
>>   subdir('tcg')
>> +subdir('kvm')
>>   
>>   target_arch += {'riscv': riscv_ss}
>>   target_softmmu_arch += {'riscv': riscv_system_ss}
>> -- 
>> 2.41.0
>>
>>
> 
> Reviewed-by: Andrew Jones <ajones@ventanamicro.com>


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

* Re: [PATCH 07/20] target/riscv/cpu.c: add .instance_post_init()
  2023-08-31 11:00   ` Andrew Jones
@ 2023-09-01 20:08     ` Daniel Henrique Barboza
  0 siblings, 0 replies; 51+ messages in thread
From: Daniel Henrique Barboza @ 2023-09-01 20:08 UTC (permalink / raw)
  To: Andrew Jones
  Cc: qemu-devel, qemu-riscv, alistair.francis, bmeng, liweiwei,
	zhiwei_liu, palmer



On 8/31/23 08:00, Andrew Jones wrote:
> On Fri, Aug 25, 2023 at 10:08:40AM -0300, Daniel Henrique Barboza wrote:
>> All generic CPUs call riscv_cpu_add_user_properties(). The 'max' CPU
>> calls riscv_init_max_cpu_extensions(). Both can be moved to a common
>> instance_post_init() callback, implemented in riscv_cpu_post_init(),
>> called by all CPUs. The call order then becomes:
>>
>> riscv_cpu_init() -> cpu_init() of each CPU -> .instance_post_init()
>>
>> A CPU class that wants to add user flags will let us know via the
>> 'user_extension_properties' property. Likewise, 'cfg.max_features' will
>> determine if any given CPU, regardless of being the 'max' CPU or not,
>> wants to enable the maximum amount of extensions.
>>
>> In the near future riscv_cpu_post_init() will call the init() function
>> of the current accelerator, providing a hook for KVM and TCG accel
>> classes to change the init() process of the CPU.
>>
>> Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
>> ---
>>   target/riscv/cpu.c | 20 +++++++++++++++-----
>>   1 file changed, 15 insertions(+), 5 deletions(-)
>>
>> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
>> index c35d58c64b..f67b782675 100644
>> --- a/target/riscv/cpu.c
>> +++ b/target/riscv/cpu.c
>> @@ -430,8 +430,6 @@ static void riscv_max_cpu_init(Object *obj)
>>       mlx = MXL_RV32;
>>   #endif
>>       set_misa(env, mlx, 0);
>> -    riscv_cpu_add_user_properties(obj);
>> -    riscv_init_max_cpu_extensions(obj);
>>       env->priv_ver = PRIV_VERSION_LATEST;
>>   #ifndef CONFIG_USER_ONLY
>>       set_satp_mode_max_supported(RISCV_CPU(obj), mlx == MXL_RV32 ?
>> @@ -445,7 +443,6 @@ static void rv64_base_cpu_init(Object *obj)
>>       CPURISCVState *env = &RISCV_CPU(obj)->env;
>>       /* We set this in the realise function */
>>       set_misa(env, MXL_RV64, 0);
>> -    riscv_cpu_add_user_properties(obj);
>>       /* Set latest version of privileged specification */
>>       env->priv_ver = PRIV_VERSION_LATEST;
>>   #ifndef CONFIG_USER_ONLY
>> @@ -569,7 +566,6 @@ static void rv128_base_cpu_init(Object *obj)
>>       CPURISCVState *env = &RISCV_CPU(obj)->env;
>>       /* We set this in the realise function */
>>       set_misa(env, MXL_RV128, 0);
>> -    riscv_cpu_add_user_properties(obj);
>>       /* Set latest version of privileged specification */
>>       env->priv_ver = PRIV_VERSION_LATEST;
>>   #ifndef CONFIG_USER_ONLY
>> @@ -582,7 +578,6 @@ static void rv32_base_cpu_init(Object *obj)
>>       CPURISCVState *env = &RISCV_CPU(obj)->env;
>>       /* We set this in the realise function */
>>       set_misa(env, MXL_RV32, 0);
>> -    riscv_cpu_add_user_properties(obj);
>>       /* Set latest version of privileged specification */
>>       env->priv_ver = PRIV_VERSION_LATEST;
>>   #ifndef CONFIG_USER_ONLY
>> @@ -1212,6 +1207,20 @@ static void riscv_cpu_set_irq(void *opaque, int irq, int level)
>>   }
>>   #endif /* CONFIG_USER_ONLY */
>>   
>> +static void riscv_cpu_post_init(Object *obj)
>> +{
>> +    RISCVCPU *cpu = RISCV_CPU(obj);
>> +    RISCVCPUClass *rcc = RISCV_CPU_GET_CLASS(cpu);
>> +
>> +    if (rcc->user_extension_properties) {
> 
> It's not yet clear to me why we need 'user_extension_properties'. Can't we
> just do the 'object_dynamic_cast(obj, TYPE_RISCV_DYNAMIC_CPU) != NULL'
> check here?

I'll answer here but this also applies for patches 19 and 20.

The idea in my head was to create a flexible way of defining new CPU types in
the future that doesn't necessarily fits the 3 big molds we have: generic CPUs
(I'm considering 'max' CPU as a generic CPU on steroids), vendor CPUs and the
KVM only 'host' CPU. For example, it would be possible to create a vendor-style
CPU that has all extensions enabled and runs KVM.

This idea is probably better in my head than in reality, and there's a very high
chance that I'm adding extra stuff in the CPU class and we won't add any new
'funky' CPU type in the future to justify it.

I'll drop patches 5 and 6 with 'user_extension_properties' and 'max_features'
flag and do a regular CPU type check in post_init().'tcg_supported' in patch 19
is indeed a bit silly today since every CPU but 'host' will enable it, so we can
do a 'cpu is host' kind of check and live without it. We can still throw generic
errors in all these checks regardless of how we're doing the validation.

Patch 20 has another underlying discussion that I'd rather have there. Thanks,


Daniel





> 
>> +        riscv_cpu_add_user_properties(obj);
>> +    }
>> +
>> +    if (cpu->cfg.max_features) {
> 
> It's also not yet clear why we need max_features. I can't think of any
> other models that want max_features besides 'max'. Checking the cpu type
> here should be sufficient, no?
> 
>> +        riscv_init_max_cpu_extensions(obj);
>> +    }
>> +}
>> +
>>   static void riscv_cpu_init(Object *obj)
>>   {
>>       RISCVCPU *cpu = RISCV_CPU(obj);
>> @@ -2019,6 +2028,7 @@ static const TypeInfo riscv_cpu_type_infos[] = {
>>           .instance_size = sizeof(RISCVCPU),
>>           .instance_align = __alignof__(RISCVCPU),
>>           .instance_init = riscv_cpu_init,
>> +        .instance_post_init = riscv_cpu_post_init,
>>           .abstract = true,
>>           .class_size = sizeof(RISCVCPUClass),
>>           .class_init = riscv_cpu_class_init,
>> -- 
>> 2.41.0
>>
>>
> 
> Thanks,
> drew


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

* Re: [PATCH 20/20] target/riscv: add 'kvm_supported' class property
  2023-08-31 12:47   ` Andrew Jones
@ 2023-09-01 20:57     ` Daniel Henrique Barboza
  2023-09-04  9:05       ` Andrew Jones
  0 siblings, 1 reply; 51+ messages in thread
From: Daniel Henrique Barboza @ 2023-09-01 20:57 UTC (permalink / raw)
  To: Andrew Jones
  Cc: qemu-devel, qemu-riscv, alistair.francis, bmeng, liweiwei,
	zhiwei_liu, palmer



On 8/31/23 09:47, Andrew Jones wrote:
> On Fri, Aug 25, 2023 at 10:08:53AM -0300, Daniel Henrique Barboza wrote:
>> This follows the same idea of 'tcg_support' property added in the
>> previous patch. Note that we're now implementing the 'cpu_realizefn' for
>> the KVMAccel class since this verification is done in realize() time.
>>
>> Supporting vendor CPUs with KVM is not possible. We rely on the
>> extension support of the KVM module running in the host, making it
>> impossible to guarantee that a vendor CPU will have all the required
>> extensions available. The only way to guarantee that a vendor CPU is KVM
>> compatible is running KVM in a host that has the same vendor CPU, and
> 
> Or to attempt to enable each extension which the vendor CPU expects and
> to attempt to disable everything else. If all those actions succeed, then
> we can override the ID registers with those of the CPU we want to model
> and go for it. There's still risk, though, that the guest kernel will see
> the ID registers of the model and attempt to apply some errata workaround
> which may or may not work and/or crash the guest.

This can also happen when migrating the guest from a host that happens to have
an errata to one that doesn't have, regardless of the CPU type the guest
is using (host CPU vs vendor CPU). The guest would need a power cycle to
identify the current model ID.

We don't have the tooling needed to mitigate this risk in QEMU I'm afraid. Upper
layers like libvirt are more able to deal with it.

> 
>> for this case we already have the 'host' CPU type.
>>
>> We're better of declaring that all vendors CPUs are not KVM capable.
>> After this patch, running KVM accel with a vendor CPU will produce an
>> error like the following:
>>
>> $ ./qemu-system-riscv64 -M virt,accel=kvm -cpu veyron-v1
>> qemu-system-riscv64: 'veyron-v1' CPU is not compatible with KVM acceleration
> 
> Shouldn't we at least check if the host matches the requested CPU first?
> So, if we happen to be on a veyron-v1, then the veyron-v1 model should
> be equivalent to 'host'. (They may not be 100% equivalent in practice, but
> theoretically they should be, which means trying it and debugging the bugs
> should improve the CPU models on both sides.)

If we're really going this route we would need to match host and vendor CPU
in the extension level, matching each vendor CPU extension with what the
CPU can provide, failing if the host can't provide all extensions the vendor
CPU requires. I wouldn't even bother checking for things like machine ID since
they can be easily impersonated (e.g. use a rv64 emulated host, edit mvendorid)
and can't be trusted.

TBH I am not thrilled with the idea of supporting vendor CPUs with KVM. The user
can pick the 'host' CPU to have the most capable KVM CPU available in the host,
and that is already not trivial to support in cases like live migration and so
on. Vendor CPU KVM support will promote things like:

"I tried to use a veyron-v2 KVM CPU in a veyron-v1 host, why is that not possible
it should be it's not fair"

"why can't I use a vendor X KVM CPU A into a vendor Y CPU B host it surely should
work since CPU A is older than CPU B right"

And then, even if we decide to support vendor CPUs with KVM in a feasible way, with
a lot of conditions and training wheels, we'll be so restrictive that the user will
be better of using the 'host' CPU anyway.


All this said, there's a lot going on in this series already and this vendor CPU + KVM
discussion might deserve its own RFC/thread. I'll drop this patch from the series to
give us time to discuss this properly. Let's leave it as is for now.


Thanks,

Daniel


> 
>>
>> Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
>> ---
>>   target/riscv/cpu-qom.h     |  1 +
>>   target/riscv/cpu.c         |  1 +
>>   target/riscv/kvm/kvm-cpu.c | 24 ++++++++++++++++++++++++
>>   3 files changed, 26 insertions(+)
>>
>> diff --git a/target/riscv/cpu-qom.h b/target/riscv/cpu-qom.h
>> index e86b76f9fe..32d9bb07b4 100644
>> --- a/target/riscv/cpu-qom.h
>> +++ b/target/riscv/cpu-qom.h
>> @@ -72,5 +72,6 @@ struct RISCVCPUClass {
>>   
>>       bool user_extension_properties;
>>       bool tcg_supported;
>> +    bool kvm_supported;
>>   };
>>   #endif /* RISCV_CPU_QOM_H */
>> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
>> index f749ea2a2e..73302bb72a 100644
>> --- a/target/riscv/cpu.c
>> +++ b/target/riscv/cpu.c
>> @@ -1646,6 +1646,7 @@ static void riscv_dynamic_cpu_class_init(ObjectClass *c, void *data)
>>   
>>       rcc->user_extension_properties = true;
>>       rcc->tcg_supported = true;
>> +    rcc->kvm_supported = true;
>>   }
>>   
>>   static void riscv_vendor_cpu_class_init(ObjectClass *c, void *data)
>> diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c
>> index 501384924b..85f3b8c80e 100644
>> --- a/target/riscv/kvm/kvm-cpu.c
>> +++ b/target/riscv/kvm/kvm-cpu.c
>> @@ -1289,6 +1289,7 @@ static void riscv_kvm_cpu_class_init(ObjectClass *c, void *data)
>>       RISCVCPUClass *rcc = RISCV_CPU_CLASS(c);
>>   
>>       rcc->user_extension_properties = true;
>> +    rcc->kvm_supported = true;
>>   }
>>   
>>   static const TypeInfo riscv_kvm_cpu_type_infos[] = {
>> @@ -1302,6 +1303,28 @@ static const TypeInfo riscv_kvm_cpu_type_infos[] = {
>>   
>>   DEFINE_TYPES(riscv_kvm_cpu_type_infos)
>>   
>> +/*
>> + * We'll get here via the following path:
>> + *
>> + * riscv_cpu_realize()
>> + *   -> cpu_exec_realizefn()
>> + *      -> kvm_cpu_realizefn() (via accel_cpu_realizefn())
>> + */
>> +static bool kvm_cpu_realizefn(CPUState *cs, Error **errp)
>> +{
>> +    RISCVCPU *cpu = RISCV_CPU(cs);
>> +    RISCVCPUClass *rcc = RISCV_CPU_GET_CLASS(cpu);
>> +
>> +    if (!rcc->kvm_supported) {
>> +        g_autofree char *name = riscv_cpu_get_name(rcc);
>> +        error_setg(errp, "'%s' CPU is not compatible with KVM acceleration",
>> +                   name);
>> +        return false;
>> +    }
>> +
>> +    return true;
>> +}
>> +
>>   static void kvm_cpu_instance_init(CPUState *cs)
>>   {
>>       Object *obj = OBJECT(RISCV_CPU(cs));
>> @@ -1328,6 +1351,7 @@ static void kvm_cpu_accel_class_init(ObjectClass *oc, void *data)
>>       AccelCPUClass *acc = ACCEL_CPU_CLASS(oc);
>>   
>>       acc->cpu_instance_init = kvm_cpu_instance_init;
>> +    acc->cpu_realizefn = kvm_cpu_realizefn;
>>   }
>>   
>>   static const TypeInfo kvm_cpu_accel_type_info = {
>> -- 
>> 2.41.0
>>
>>
> 
> I don't think we want kvm_supported nor tcg_supported as they necessarily
> bring accelerator knowledge into target/riscv/cpu.c, where the booleans
> have to be set. It would be better if the decisions as to what is
> supported or not are made in the accelerator's respective files. So, we
> try to realize some model with some accel and let that accel do some
> checks and error out when it can't. If riscv kvm only supports 'host',
> then it's check would simply be "is the model host?" and the inverse for
> tcg.
> 
> Thanks,
> drew


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

* Re: [PATCH 20/20] target/riscv: add 'kvm_supported' class property
  2023-09-01 20:57     ` Daniel Henrique Barboza
@ 2023-09-04  9:05       ` Andrew Jones
  0 siblings, 0 replies; 51+ messages in thread
From: Andrew Jones @ 2023-09-04  9:05 UTC (permalink / raw)
  To: Daniel Henrique Barboza
  Cc: qemu-devel, qemu-riscv, alistair.francis, bmeng, liweiwei,
	zhiwei_liu, palmer

On Fri, Sep 01, 2023 at 05:57:46PM -0300, Daniel Henrique Barboza wrote:
> 
> 
> On 8/31/23 09:47, Andrew Jones wrote:
> > On Fri, Aug 25, 2023 at 10:08:53AM -0300, Daniel Henrique Barboza wrote:
> > > This follows the same idea of 'tcg_support' property added in the
> > > previous patch. Note that we're now implementing the 'cpu_realizefn' for
> > > the KVMAccel class since this verification is done in realize() time.
> > > 
> > > Supporting vendor CPUs with KVM is not possible. We rely on the
> > > extension support of the KVM module running in the host, making it
> > > impossible to guarantee that a vendor CPU will have all the required
> > > extensions available. The only way to guarantee that a vendor CPU is KVM
> > > compatible is running KVM in a host that has the same vendor CPU, and
> > 
> > Or to attempt to enable each extension which the vendor CPU expects and
> > to attempt to disable everything else. If all those actions succeed, then
> > we can override the ID registers with those of the CPU we want to model
> > and go for it. There's still risk, though, that the guest kernel will see
> > the ID registers of the model and attempt to apply some errata workaround
> > which may or may not work and/or crash the guest.
> 
> This can also happen when migrating the guest from a host that happens to have
> an errata to one that doesn't have, regardless of the CPU type the guest
> is using (host CPU vs vendor CPU). The guest would need a power cycle to
> identify the current model ID.

We shouldn't migrate a 'host' CPU model anywhere other than to an exactly
identical host (same ID registers, same errata). Also, migration must
consider the host kernel. The aim is to support "ping-pong" migration,
i.e. migrate A->B->A, where B has a host kernel which is the same or more
recent than A. This is a reasonable level of support, as it supports host
upgrades with rollback. B cannot be older than A, as it may not handle
errata in the same way.

> 
> We don't have the tooling needed to mitigate this risk in QEMU I'm afraid. Upper
> layers like libvirt are more able to deal with it.

And higher layers yet, libvirt daemons capture all the information of the
hosts they run on. Layers above libvirt compare information from all hosts
under their control to create sets of possible migration destinations for
each VM, considering the VM configurations.

> 
> > 
> > > for this case we already have the 'host' CPU type.
> > > 
> > > We're better of declaring that all vendors CPUs are not KVM capable.
> > > After this patch, running KVM accel with a vendor CPU will produce an
> > > error like the following:
> > > 
> > > $ ./qemu-system-riscv64 -M virt,accel=kvm -cpu veyron-v1
> > > qemu-system-riscv64: 'veyron-v1' CPU is not compatible with KVM acceleration
> > 
> > Shouldn't we at least check if the host matches the requested CPU first?
> > So, if we happen to be on a veyron-v1, then the veyron-v1 model should
> > be equivalent to 'host'. (They may not be 100% equivalent in practice, but
> > theoretically they should be, which means trying it and debugging the bugs
> > should improve the CPU models on both sides.)
> 
> If we're really going this route we would need to match host and vendor CPU
> in the extension level, matching each vendor CPU extension with what the
> CPU can provide, failing if the host can't provide all extensions the vendor
> CPU requires.

We can't support arbitrary vendor CPU models on arbitrary hosts. I'm only
advocating for supporting CPU model XYZ when KVM is running on XYZ CPUs
or compatible CPUs (more on the compatible CPUs later).

To elaborate, I don't really see a problem with expecting KVM to provide a
VCPU which matches the CPU model of the physical CPU which KVM is running
on (minus M-mode). KVM should be steadily learning how to expose all
extensions of the CPUs it runs on to its guests. So, while it may not be
possible now to enable all extensions of a particular model, it should be
eventually. If there are extensions in the CPU model which cannot be
virtualized, then it may be tolerable for QEMU to just warn about them,
rather than abort the whole thing (hopefully we don't have any of those
anyway). And, the "VCPU only almost matching the CPU model" problem isn't
much different than the "VCPU not actually matching the host CPU when
using '-cpu host'" problem. In both cases, a user may not be pleased that
they didn't get exactly what they asked for. At least with the CPU model,
QEMU will be aware of the differences and can warn about them.

> I wouldn't even bother checking for things like machine ID since
> they can be easily impersonated (e.g. use a rv64 emulated host, edit mvendorid)
> and can't be trusted.

We should definitely check the ID registers. If KVM says it's running on
XYZ CPUs, then we should consider allowing the XYZ model to be used with
KVM guests. If the host is emulated and the user configured things in
a strange way, then, when things blow up, they can keep the pieces.

> 
> TBH I am not thrilled with the idea of supporting vendor CPUs with KVM. The user
> can pick the 'host' CPU to have the most capable KVM CPU available in the host,
> and that is already not trivial to support in cases like live migration and so
> on.

(And now back to compatible CPUs.)

The user may not want the most capable VCPU. The user may want the most
compatible for their datacenter. If the datacenter is a bunch of XYZ
revision 1 CPUs which are slowly getting replaced with XYZ revision 2
CPUs, and revision 2 is compatible with revision 1, then it should be
safe to use the XYZ revision 1 CPU model for KVM VCPUs. Using '-cpu host'
would require that the guests only migrate to other hosts of the exact
same type (either revision 1 or revision 2, depending on where they were
launched first).

> Vendor CPU KVM support will promote things like:
> 
> "I tried to use a veyron-v2 KVM CPU in a veyron-v1 host, why is that not possible
> it should be it's not fair"
> 
> "why can't I use a vendor X KVM CPU A into a vendor Y CPU B host it surely should
> work since CPU A is older than CPU B right"

If KVM and QEMU decide a CPU model is compatible with the host they're
running on, then the model will be allowed. If not, then the model will
error out. Documentation about what is possible and not for RISC-V KVM
CPU models is the best we can do to educate users.

> 
> And then, even if we decide to support vendor CPUs with KVM in a feasible way, with
> a lot of conditions and training wheels, we'll be so restrictive that the user will
> be better of using the 'host' CPU anyway.

Whether 'host' is the better choice or not depends on the use case. Being
able to migrate a less capable VM to similar hardware in a datacenter
could be a higher priority than extension support. The admins deploying
VMs will need to collect the requirements from their users and make those
choices. We should try to provide support for both.

There could be an argument made that the set of compatible CPUs is too
small to bother with supporting CPU models at all. (That's basically the
argument we have in the Arm KVM world where only '-cpu host' is
supported since errata mitigations are installed based on ID registers.)
I'm a bit more optimistic with RISC-V, because the base of the RISC-V
instruction set is small and I hope vendors will conform to the specs for
it (there are already examples to the contrary, but let's stay optimistic
a bit longer :-). So, if we assume the size and spec compliance of the
base keeps errata out of the base, then the errata will only be in
extensions. This means that the mitigations, which will still use ID
registers to install, would only apply to extensions. Then, it's easy to
avoid those mitigations by simply disabling the affected extensions
altogether.

Now, one might state, if we're disabling extensions to avoid errata, then
we're no longer properly providing the model. That statement is correct,
which is why we also need to provide a bare minimal base CPU model where
each extension that should be enabled is explicitly enabled on the QEMU
command line. This base CPU model would use zero for the ID registers,
which is a legal value and indicates that the CPU "is a non-commercial
implementation". Actually, I could be convinced to not support XYZ VCPUs
on XYZ CPU hosts at all, as long as we have this base CPU model working
with KVM, since the base CPU model can satisfy those that prioritize
migration over capabilities even better than CPU models can.

> 
> 
> All this said, there's a lot going on in this series already and this vendor CPU + KVM
> discussion might deserve its own RFC/thread. I'll drop this patch from the series to
> give us time to discuss this properly. Let's leave it as is for now.

Works for me.

Thanks,
drew


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

* Re: [PATCH 16/20] target/riscv/tcg: move riscv_cpu_add_misa_properties() to tcg-cpu.c
  2023-08-31 12:01   ` Andrew Jones
@ 2023-09-04 14:21     ` Daniel Henrique Barboza
  0 siblings, 0 replies; 51+ messages in thread
From: Daniel Henrique Barboza @ 2023-09-04 14:21 UTC (permalink / raw)
  To: Andrew Jones
  Cc: qemu-devel, qemu-riscv, alistair.francis, bmeng, liweiwei,
	zhiwei_liu, palmer



On 8/31/23 09:01, Andrew Jones wrote:
> On Fri, Aug 25, 2023 at 10:08:49AM -0300, Daniel Henrique Barboza wrote:
>> All code related to MISA TCG properties is also moved.
>>
>> At this point, all TCG properties handling is done in tcg-cpu.c, all KVM
>> properties handling is done in kvm-cpu.c.
>>
>> Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
>> ---
>>   target/riscv/cpu.c         | 89 --------------------------------------
>>   target/riscv/cpu.h         |  1 -
>>   target/riscv/tcg/tcg-cpu.c | 84 +++++++++++++++++++++++++++++++++++
>>   3 files changed, 84 insertions(+), 90 deletions(-)
>>
>> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
>> index 89b09a7e89..3c9db46837 100644
>> --- a/target/riscv/cpu.c
>> +++ b/target/riscv/cpu.c
>> @@ -1201,49 +1201,6 @@ static void riscv_cpu_init(Object *obj)
>>   #endif /* CONFIG_USER_ONLY */
>>   }
>>   
>> -typedef struct RISCVCPUMisaExtConfig {
>> -    const char *name;
>> -    const char *description;
>> -    target_ulong misa_bit;
>> -    bool enabled;
>> -} RISCVCPUMisaExtConfig;
>> -
>> -static void cpu_set_misa_ext_cfg(Object *obj, Visitor *v, const char *name,
>> -                                 void *opaque, Error **errp)
>> -{
>> -    const RISCVCPUMisaExtConfig *misa_ext_cfg = opaque;
>> -    target_ulong misa_bit = misa_ext_cfg->misa_bit;
>> -    RISCVCPU *cpu = RISCV_CPU(obj);
>> -    CPURISCVState *env = &cpu->env;
>> -    bool value;
>> -
>> -    if (!visit_type_bool(v, name, &value, errp)) {
>> -        return;
>> -    }
>> -
>> -    if (value) {
>> -        env->misa_ext |= misa_bit;
>> -        env->misa_ext_mask |= misa_bit;
>> -    } else {
>> -        env->misa_ext &= ~misa_bit;
>> -        env->misa_ext_mask &= ~misa_bit;
>> -    }
>> -}
>> -
>> -static void cpu_get_misa_ext_cfg(Object *obj, Visitor *v, const char *name,
>> -                                 void *opaque, Error **errp)
>> -{
>> -    const RISCVCPUMisaExtConfig *misa_ext_cfg = opaque;
>> -    target_ulong misa_bit = misa_ext_cfg->misa_bit;
>> -    RISCVCPU *cpu = RISCV_CPU(obj);
>> -    CPURISCVState *env = &cpu->env;
>> -    bool value;
>> -
>> -    value = env->misa_ext & misa_bit;
>> -
>> -    visit_type_bool(v, name, &value, errp);
>> -}
>> -
>>   typedef struct misa_ext_info {
>>       const char *name;
>>       const char *description;
>> @@ -1304,52 +1261,6 @@ const char *riscv_get_misa_ext_description(uint32_t bit)
>>       return val;
>>   }
>>   
>> -#define MISA_CFG(_bit, _enabled) \
>> -    {.misa_bit = _bit, .enabled = _enabled}
>> -
>> -static RISCVCPUMisaExtConfig misa_ext_cfgs[] = {
>> -    MISA_CFG(RVA, true),
>> -    MISA_CFG(RVC, true),
>> -    MISA_CFG(RVD, true),
>> -    MISA_CFG(RVF, true),
>> -    MISA_CFG(RVI, true),
>> -    MISA_CFG(RVE, false),
>> -    MISA_CFG(RVM, true),
>> -    MISA_CFG(RVS, true),
>> -    MISA_CFG(RVU, true),
>> -    MISA_CFG(RVH, true),
>> -    MISA_CFG(RVJ, false),
>> -    MISA_CFG(RVV, false),
>> -    MISA_CFG(RVG, false),
>> -};
>> -
>> -void riscv_cpu_add_misa_properties(Object *cpu_obj)
>> -{
>> -    int i;
>> -
>> -    for (i = 0; i < ARRAY_SIZE(misa_ext_cfgs); i++) {
>> -        RISCVCPUMisaExtConfig *misa_cfg = &misa_ext_cfgs[i];
>> -        int bit = misa_cfg->misa_bit;
>> -
>> -        misa_cfg->name = riscv_get_misa_ext_name(bit);
>> -        misa_cfg->description = riscv_get_misa_ext_description(bit);
>> -
>> -        /* Check if KVM already created the property */
>> -        if (object_property_find(cpu_obj, misa_cfg->name)) {
>> -            continue;
>> -        }
>> -
>> -        object_property_add(cpu_obj, misa_cfg->name, "bool",
>> -                            cpu_get_misa_ext_cfg,
>> -                            cpu_set_misa_ext_cfg,
>> -                            NULL, (void *)misa_cfg);
>> -        object_property_set_description(cpu_obj, misa_cfg->name,
>> -                                        misa_cfg->description);
>> -        object_property_set_bool(cpu_obj, misa_cfg->name,
>> -                                 misa_cfg->enabled, NULL);
>> -    }
>> -}
>> -
>>   #define MULTI_EXT_CFG_BOOL(_name, _prop, _defval) \
>>       {.name = _name, .offset = CPU_CFG_OFFSET(_prop), \
>>        .enabled = _defval}
>> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
>> index 74fbb33e09..4269523e24 100644
>> --- a/target/riscv/cpu.h
>> +++ b/target/riscv/cpu.h
>> @@ -726,7 +726,6 @@ extern const RISCVCPUMultiExtConfig riscv_cpu_vendor_exts[];
>>   extern const RISCVCPUMultiExtConfig riscv_cpu_experimental_exts[];
>>   extern Property riscv_cpu_options[];
>>   
>> -void riscv_cpu_add_misa_properties(Object *cpu_obj);
>>   void riscv_add_satp_mode_properties(Object *obj);
>>   
>>   /* CSR function table */
>> diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
>> index 68ce3cbcb9..8e3f55d3a6 100644
>> --- a/target/riscv/tcg/tcg-cpu.c
>> +++ b/target/riscv/tcg/tcg-cpu.c
>> @@ -574,6 +574,90 @@ static bool tcg_cpu_realizefn(CPUState *cs, Error **errp)
>>       return true;
>>   }
>>   
>> +typedef struct RISCVCPUMisaExtConfig {
>> +    const char *name;
>> +    const char *description;
>> +    target_ulong misa_bit;
>> +    bool enabled;
>> +} RISCVCPUMisaExtConfig;
>> +
>> +static void cpu_set_misa_ext_cfg(Object *obj, Visitor *v, const char *name,
>> +                                 void *opaque, Error **errp)
>> +{
>> +    const RISCVCPUMisaExtConfig *misa_ext_cfg = opaque;
>> +    target_ulong misa_bit = misa_ext_cfg->misa_bit;
>> +    RISCVCPU *cpu = RISCV_CPU(obj);
>> +    CPURISCVState *env = &cpu->env;
>> +    bool value;
>> +
>> +    if (!visit_type_bool(v, name, &value, errp)) {
>> +        return;
>> +    }
>> +
>> +    if (value) {
>> +        env->misa_ext |= misa_bit;
>> +        env->misa_ext_mask |= misa_bit;
>> +    } else {
>> +        env->misa_ext &= ~misa_bit;
>> +        env->misa_ext_mask &= ~misa_bit;
>> +    }
>> +}
>> +
>> +static void cpu_get_misa_ext_cfg(Object *obj, Visitor *v, const char *name,
>> +                                 void *opaque, Error **errp)
>> +{
>> +    const RISCVCPUMisaExtConfig *misa_ext_cfg = opaque;
>> +    target_ulong misa_bit = misa_ext_cfg->misa_bit;
>> +    RISCVCPU *cpu = RISCV_CPU(obj);
>> +    CPURISCVState *env = &cpu->env;
>> +    bool value;
>> +
>> +    value = env->misa_ext & misa_bit;
>> +
>> +    visit_type_bool(v, name, &value, errp);
>> +}
>> +
>> +#define MISA_CFG(_bit, _enabled) \
>> +    {.misa_bit = _bit, .enabled = _enabled}
>> +
>> +static RISCVCPUMisaExtConfig misa_ext_cfgs[] = {
> 
> Can this be const?

At this moment it can't because we're setting 'name' and 'description' for
each element down there in riscv_cpu_add_misa_properties().

However, in a quick look it seems that we don't need these fields because we
don't access 'name' or 'description' using the struct after the property is
created.

I'll take another look and, if that's indeed the case, I'll do a prep patch
to make these changes before moving code in this patch. Thanks,


Daniel

> 
>> +    MISA_CFG(RVA, true),
>> +    MISA_CFG(RVC, true),
>> +    MISA_CFG(RVD, true),
>> +    MISA_CFG(RVF, true),
>> +    MISA_CFG(RVI, true),
>> +    MISA_CFG(RVE, false),
>> +    MISA_CFG(RVM, true),
>> +    MISA_CFG(RVS, true),
>> +    MISA_CFG(RVU, true),
>> +    MISA_CFG(RVH, true),
>> +    MISA_CFG(RVJ, false),
>> +    MISA_CFG(RVV, false),
>> +    MISA_CFG(RVG, false),
>> +};
>> +
>> +static void riscv_cpu_add_misa_properties(Object *cpu_obj)
>> +{
>> +    int i;
>> +
>> +    for (i = 0; i < ARRAY_SIZE(misa_ext_cfgs); i++) {
>> +        RISCVCPUMisaExtConfig *misa_cfg = &misa_ext_cfgs[i];
>> +        int bit = misa_cfg->misa_bit;
>> +
>> +        misa_cfg->name = riscv_get_misa_ext_name(bit);
>> +        misa_cfg->description = riscv_get_misa_ext_description(bit);
>> +
>> +        object_property_add(cpu_obj, misa_cfg->name, "bool",
>> +                            cpu_get_misa_ext_cfg,
>> +                            cpu_set_misa_ext_cfg,
>> +                            NULL, (void *)misa_cfg);
>> +        object_property_set_description(cpu_obj, misa_cfg->name,
>> +                                        misa_cfg->description);
>> +        object_property_set_bool(cpu_obj, misa_cfg->name,
>> +                                 misa_cfg->enabled, NULL);
>> +    }
>> +}
>> +
>>   static void cpu_set_multi_ext_cfg(Object *obj, Visitor *v, const char *name,
>>                                     void *opaque, Error **errp)
>>   {
>> -- 
>> 2.41.0
>>
>>
> 
> Otherwise,
> 
> Reviewed-by: Andrew Jones <ajones@ventanamicro.com>


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

end of thread, other threads:[~2023-09-04 14:22 UTC | newest]

Thread overview: 51+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-08-25 13:08 [PATCH 00/20] riscv: split TCG/KVM accelerators from cpu.c Daniel Henrique Barboza
2023-08-25 13:08 ` [PATCH 01/20] target/riscv: introduce TCG AccelCPUClass Daniel Henrique Barboza
2023-08-31 10:17   ` Andrew Jones
2023-08-25 13:08 ` [PATCH 02/20] target/riscv: move riscv_cpu_realize_tcg() to TCG::cpu_realizefn() Daniel Henrique Barboza
2023-08-31 10:21   ` Andrew Jones
2023-08-25 13:08 ` [PATCH 03/20] target/riscv: move riscv_cpu_validate_set_extensions() to tcg-cpu.c Daniel Henrique Barboza
2023-08-31 10:31   ` Andrew Jones
2023-08-25 13:08 ` [PATCH 04/20] target/riscv: move riscv_tcg_ops " Daniel Henrique Barboza
2023-08-28 16:30   ` Philippe Mathieu-Daudé
2023-08-31 10:38   ` Andrew Jones
2023-08-25 13:08 ` [PATCH 05/20] target/riscv/cpu.c: add 'user_extension_properties' class prop Daniel Henrique Barboza
2023-08-25 13:08 ` [PATCH 06/20] target/riscv: add 'max_features' CPU flag Daniel Henrique Barboza
2023-08-25 13:08 ` [PATCH 07/20] target/riscv/cpu.c: add .instance_post_init() Daniel Henrique Barboza
2023-08-31 11:00   ` Andrew Jones
2023-09-01 20:08     ` Daniel Henrique Barboza
2023-08-25 13:08 ` [PATCH 08/20] target/riscv: move 'host' CPU declaration to kvm.c Daniel Henrique Barboza
2023-08-28 16:35   ` Philippe Mathieu-Daudé
2023-08-31 11:04   ` Andrew Jones
2023-08-25 13:08 ` [PATCH 09/20] target/riscv/cpu.c: mark extensions arrays as 'const' Daniel Henrique Barboza
2023-08-31 11:10   ` Andrew Jones
2023-08-25 13:08 ` [PATCH 10/20] target/riscv: move riscv_cpu_add_kvm_properties() to kvm.c Daniel Henrique Barboza
2023-08-31 11:22   ` Andrew Jones
2023-08-25 13:08 ` [PATCH 11/20] target/riscv: introduce KVM AccelCPUClass Daniel Henrique Barboza
2023-08-28 16:38   ` Philippe Mathieu-Daudé
2023-08-29 13:16     ` Daniel Henrique Barboza
2023-08-31 11:26   ` Andrew Jones
2023-08-25 13:08 ` [PATCH 12/20] target/riscv: move KVM only files to kvm subdir Daniel Henrique Barboza
2023-08-28 16:47   ` Philippe Mathieu-Daudé
2023-08-30 18:21     ` Daniel Henrique Barboza
2023-08-30 20:54       ` Philippe Mathieu-Daudé
2023-08-31 11:30   ` Andrew Jones
2023-09-01 17:19     ` Daniel Henrique Barboza
2023-08-25 13:08 ` [PATCH 13/20] target/riscv/kvm: refactor kvm_riscv_init_user_properties() Daniel Henrique Barboza
2023-08-31 11:34   ` Andrew Jones
2023-08-25 13:08 ` [PATCH 14/20] target/riscv/kvm: do not use riscv_cpu_add_misa_properties() Daniel Henrique Barboza
2023-08-31 11:50   ` Andrew Jones
2023-08-25 13:08 ` [PATCH 15/20] target/riscv/tcg: introduce tcg_cpu_instance_init() Daniel Henrique Barboza
2023-08-31 11:56   ` Andrew Jones
2023-08-25 13:08 ` [PATCH 16/20] target/riscv/tcg: move riscv_cpu_add_misa_properties() to tcg-cpu.c Daniel Henrique Barboza
2023-08-31 12:01   ` Andrew Jones
2023-09-04 14:21     ` Daniel Henrique Barboza
2023-08-25 13:08 ` [PATCH 17/20] target/riscv/cpu.c: export isa_edata_arr[] Daniel Henrique Barboza
2023-08-31 12:06   ` Andrew Jones
2023-08-25 13:08 ` [PATCH 18/20] target/riscv/cpu: move priv spec functions to tcg-cpu.c Daniel Henrique Barboza
2023-08-31 12:07   ` Andrew Jones
2023-08-25 13:08 ` [PATCH 19/20] target/riscv: add 'tcg_supported' class property Daniel Henrique Barboza
2023-08-31 12:25   ` Andrew Jones
2023-08-25 13:08 ` [PATCH 20/20] target/riscv: add 'kvm_supported' " Daniel Henrique Barboza
2023-08-31 12:47   ` Andrew Jones
2023-09-01 20:57     ` Daniel Henrique Barboza
2023-09-04  9:05       ` 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.