@@ -1726,6 +1726,11 @@ static void riscv_cpu_add_misa_properties(Object *cpu_obj)
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,
@@ -22,8 +22,10 @@
#include <linux/kvm.h>
#include "qemu/timer.h"
+#include "qapi/error.h"
#include "qemu/error-report.h"
#include "qemu/main-loop.h"
+#include "qapi/visitor.h"
#include "sysemu/sysemu.h"
#include "sysemu/kvm.h"
#include "sysemu/kvm_int.h"
@@ -105,6 +107,81 @@ static uint64_t kvm_riscv_reg_id(CPURISCVState *env, uint64_t type,
} \
} while (0)
+typedef struct KVMCPUConfig {
+ const char *name;
+ const char *description;
+ target_ulong offset;
+ int kvm_reg_id;
+ bool user_set;
+} KVMCPUConfig;
+
+#define KVM_MISA_CFG(_bit, _reg_id) \
+ {.offset = _bit, .kvm_reg_id = _reg_id}
+
+/* KVM ISA extensions */
+static KVMCPUConfig kvm_misa_ext_cfgs[] = {
+ KVM_MISA_CFG(RVA, KVM_RISCV_ISA_EXT_A),
+ KVM_MISA_CFG(RVC, KVM_RISCV_ISA_EXT_C),
+ KVM_MISA_CFG(RVD, KVM_RISCV_ISA_EXT_D),
+ KVM_MISA_CFG(RVF, KVM_RISCV_ISA_EXT_F),
+ KVM_MISA_CFG(RVH, KVM_RISCV_ISA_EXT_H),
+ KVM_MISA_CFG(RVI, KVM_RISCV_ISA_EXT_I),
+ KVM_MISA_CFG(RVM, KVM_RISCV_ISA_EXT_M),
+};
+
+static void kvm_cpu_set_misa_ext_cfg(Object *obj, Visitor *v,
+ const char *name,
+ void *opaque, Error **errp)
+{
+ KVMCPUConfig *misa_ext_cfg = opaque;
+ target_ulong misa_bit = misa_ext_cfg->offset;
+ RISCVCPU *cpu = RISCV_CPU(obj);
+ CPURISCVState *env = &cpu->env;
+ bool value, host_bit;
+
+ if (!visit_type_bool(v, name, &value, errp)) {
+ return;
+ }
+
+ host_bit = env->misa_ext_mask & misa_bit;
+
+ if (value == host_bit) {
+ return;
+ }
+
+ if (!value) {
+ misa_ext_cfg->user_set = true;
+ return;
+ }
+
+ /*
+ * Forbid users to enable extensions that aren't
+ * available in the hart.
+ */
+ error_setg(errp, "Enabling MISA bit '%s' is not allowed: it's not "
+ "enabled in the host", misa_ext_cfg->name);
+}
+
+static void kvm_riscv_add_cpu_user_properties(Object *cpu_obj)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(kvm_misa_ext_cfgs); i++) {
+ KVMCPUConfig *misa_cfg = &kvm_misa_ext_cfgs[i];
+ int bit = misa_cfg->offset;
+
+ 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",
+ NULL,
+ kvm_cpu_set_misa_ext_cfg,
+ NULL, misa_cfg);
+ object_property_set_description(cpu_obj, misa_cfg->name,
+ misa_cfg->description);
+ }
+}
+
static int kvm_riscv_get_regs_core(CPUState *cs)
{
int ret = 0;
@@ -427,6 +504,7 @@ void kvm_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);