[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 13/16] target/riscv/kvm.c: add multi-letter extension KVM propert
From: |
Daniel Henrique Barboza |
Subject: |
[PATCH 13/16] target/riscv/kvm.c: add multi-letter extension KVM properties |
Date: |
Tue, 30 May 2023 16:46:20 -0300 |
Let's add KVM user properties for the multi-letter extensions that KVM
currently supports: zicbom, zicboz, zihintpause, zbb, ssaia, sstc,
svinval and svpbmt.
As with the recently added MISA properties we're also going to add a
'user_set' flag in each of them. The flag will be set only if the user
chose an option that's different from the host and will require extra
handling from the KVM driver.
However, multi-letter CPUs have more cases to cover than MISA
extensions, so we're adding an extra 'supported' flag as well. This flag
will reflect if a given extension is supported by KVM, i.e. KVM knows
how to handle it. This is determined during KVM extension discovery in
kvm_riscv_init_multiext_cfg(), where we test for EINVAL errors. Any
other error different from EINVAL will cause an abort.
The 'supported' flag will then be used later on to give an exception for
users that are disabling multi-letter extensions that are unknown to
KVM.
Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
---
target/riscv/kvm.c | 136 +++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 136 insertions(+)
diff --git a/target/riscv/kvm.c b/target/riscv/kvm.c
index bb1dafe263..b4193a10d8 100644
--- a/target/riscv/kvm.c
+++ b/target/riscv/kvm.c
@@ -202,6 +202,99 @@ static void kvm_riscv_update_cpu_misa_ext(RISCVCPU *cpu,
CPUState *cs)
}
}
+typedef struct RISCVCPUMultiExtConfig {
+ const char *name;
+ int kvm_reg_id;
+ int cpu_cfg_offset;
+ bool supported;
+ bool user_set;
+} RISCVCPUMultiExtConfig;
+
+#define CPUCFG(_prop) offsetof(struct RISCVCPUConfig, _prop)
+
+/*
+ * KVM ISA Multi-letter extensions. We care about the order
+ * since it'll be used to create the ISA string later on.
+ * We follow the same ordering rules of isa_edata_arr[]
+ * from target/riscv/cpu.c.
+ */
+static RISCVCPUMultiExtConfig kvm_multi_ext_cfgs[] = {
+ {.name = "zicbom", .kvm_reg_id = KVM_RISCV_ISA_EXT_ZICBOM,
+ .cpu_cfg_offset = CPUCFG(ext_icbom)},
+ {.name = "zicboz", .kvm_reg_id = KVM_RISCV_ISA_EXT_ZICBOZ,
+ .cpu_cfg_offset = CPUCFG(ext_icboz)},
+ {.name = "zihintpause", .kvm_reg_id = KVM_RISCV_ISA_EXT_ZIHINTPAUSE,
+ .cpu_cfg_offset = CPUCFG(ext_zihintpause)},
+ {.name = "zbb", .kvm_reg_id = KVM_RISCV_ISA_EXT_ZBB,
+ .cpu_cfg_offset = CPUCFG(ext_zbb)},
+ {.name = "ssaia", .kvm_reg_id = KVM_RISCV_ISA_EXT_SSAIA,
+ .cpu_cfg_offset = CPUCFG(ext_ssaia)},
+ {.name = "sstc", .kvm_reg_id = KVM_RISCV_ISA_EXT_SSTC,
+ .cpu_cfg_offset = CPUCFG(ext_sstc)},
+ {.name = "svinval", .kvm_reg_id = KVM_RISCV_ISA_EXT_SVINVAL,
+ .cpu_cfg_offset = CPUCFG(ext_svinval)},
+ {.name = "svpbmt", .kvm_reg_id = KVM_RISCV_ISA_EXT_SVPBMT,
+ .cpu_cfg_offset = CPUCFG(ext_svpbmt)},
+};
+
+static void kvm_cpu_cfg_set(RISCVCPU *cpu, RISCVCPUMultiExtConfig *multi_ext,
+ uint32_t val)
+{
+ int cpu_cfg_offset = multi_ext->cpu_cfg_offset;
+ bool *ext_enabled = (void *)&cpu->cfg + cpu_cfg_offset;
+
+ *ext_enabled = val;
+}
+
+static uint32_t kvm_cpu_cfg_get(RISCVCPU *cpu,
+ RISCVCPUMultiExtConfig *multi_ext)
+{
+ int cpu_cfg_offset = multi_ext->cpu_cfg_offset;
+ bool *ext_enabled = (void *)&cpu->cfg + cpu_cfg_offset;
+
+ return *ext_enabled;
+}
+
+static void kvm_cpu_set_multi_ext_cfg(Object *obj, Visitor *v,
+ const char *name,
+ void *opaque, Error **errp)
+{
+ RISCVCPUMultiExtConfig *multi_ext_cfg = opaque;
+ RISCVCPU *cpu = RISCV_CPU(obj);
+ bool value, host_val;
+
+ if (!visit_type_bool(v, name, &value, errp)) {
+ return;
+ }
+
+ host_val = kvm_cpu_cfg_get(cpu, multi_ext_cfg);
+
+ /*
+ * Ignore if the user is setting the same value
+ * as the host.
+ */
+ if (value == host_val) {
+ return;
+ }
+
+ if (!multi_ext_cfg->supported) {
+ /*
+ * Error out if the user is trying to enable an
+ * extension that KVM doesn't support. Ignore
+ * option otherwise.
+ */
+ if (value) {
+ error_setg(errp, "KVM does not support disabling extension %s",
+ multi_ext_cfg->name);
+ }
+
+ return;
+ }
+
+ multi_ext_cfg->user_set = true;
+ kvm_cpu_cfg_set(cpu, multi_ext_cfg, value);
+}
+
static void kvm_riscv_add_cpu_user_properties(Object *cpu_obj)
{
int i;
@@ -216,6 +309,15 @@ static void kvm_riscv_add_cpu_user_properties(Object
*cpu_obj)
object_property_set_description(cpu_obj, misa_cfg->name,
misa_cfg->description);
}
+
+ for (i = 0; i < ARRAY_SIZE(kvm_multi_ext_cfgs); i++) {
+ RISCVCPUMultiExtConfig *multi_cfg = &kvm_multi_ext_cfgs[i];
+
+ object_property_add(cpu_obj, multi_cfg->name, "bool",
+ NULL,
+ kvm_cpu_set_multi_ext_cfg,
+ NULL, multi_cfg);
+ }
}
static int kvm_riscv_get_regs_core(CPUState *cs)
@@ -531,6 +633,39 @@ static void kvm_riscv_init_misa_ext_mask(RISCVCPU *cpu,
env->misa_ext = env->misa_ext_mask;
}
+static void kvm_riscv_init_multiext_cfg(RISCVCPU *cpu, KVMScratchCPU *kvmcpu)
+{
+ CPURISCVState *env = &cpu->env;
+ uint64_t val;
+ int i, ret;
+
+ for (i = 0; i < ARRAY_SIZE(kvm_multi_ext_cfgs); i++) {
+ RISCVCPUMultiExtConfig *multi_ext_cfg = &kvm_multi_ext_cfgs[i];
+ struct kvm_one_reg reg;
+
+ reg.id = kvm_riscv_reg_id(env, KVM_REG_RISCV_ISA_EXT,
+ multi_ext_cfg->kvm_reg_id);
+ reg.addr = (uint64_t)&val;
+ ret = ioctl(kvmcpu->cpufd, KVM_GET_ONE_REG, ®);
+ if (ret != 0) {
+ if (ret == -EINVAL) {
+ /* Silently default to 'false' if KVM does not support it. */
+ multi_ext_cfg->supported = false;
+ val = false;
+ } else {
+ error_report("Unable to read ISA_EXT KVM register %s, "
+ "error %d", multi_ext_cfg->name, ret);
+ kvm_riscv_destroy_scratch_vcpu(kvmcpu);
+ exit(EXIT_FAILURE);
+ }
+ } else {
+ multi_ext_cfg->supported = true;
+ }
+
+ kvm_cpu_cfg_set(cpu, multi_ext_cfg, val);
+ }
+}
+
void kvm_riscv_init_user_properties(Object *cpu_obj)
{
RISCVCPU *cpu = RISCV_CPU(cpu_obj);
@@ -543,6 +678,7 @@ void kvm_riscv_init_user_properties(Object *cpu_obj)
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);
kvm_riscv_destroy_scratch_vcpu(&kvmcpu);
}
--
2.40.1
- [PATCH 03/16] target/riscv/cpu.c: restrict 'mvendorid' value, (continued)
- [PATCH 03/16] target/riscv/cpu.c: restrict 'mvendorid' value, Daniel Henrique Barboza, 2023/05/30
- [PATCH 04/16] target/riscv/cpu.c: restrict 'mimpid' value, Daniel Henrique Barboza, 2023/05/30
- [PATCH 05/16] target/riscv/cpu.c: restrict 'marchid' value, Daniel Henrique Barboza, 2023/05/30
- [PATCH 06/16] target/riscv: use KVM scratch CPUs to init KVM properties, Daniel Henrique Barboza, 2023/05/30
- [PATCH 07/16] target/riscv: read marchid/mimpid in kvm_riscv_init_machine_ids(), Daniel Henrique Barboza, 2023/05/30
- [PATCH 08/16] target/riscv: handle mvendorid/marchid/mimpid for KVM CPUs, Daniel Henrique Barboza, 2023/05/30
- [PATCH 09/16] linux-headers: Update to v6.4-rc1, Daniel Henrique Barboza, 2023/05/30
- [PATCH 11/16] target/riscv: add KVM specific MISA properties, Daniel Henrique Barboza, 2023/05/30
- [PATCH 12/16] target/riscv/kvm.c: update KVM MISA bits, Daniel Henrique Barboza, 2023/05/30
- [PATCH 10/16] target/riscv/kvm.c: init 'misa_ext_mask' with scratch CPU, Daniel Henrique Barboza, 2023/05/30
- [PATCH 13/16] target/riscv/kvm.c: add multi-letter extension KVM properties,
Daniel Henrique Barboza <=
- [PATCH 14/16] target/riscv: adapt 'riscv_isa_string' for KVM, Daniel Henrique Barboza, 2023/05/30
- [PATCH 15/16] target/riscv: update multi-letter extension KVM properties, Daniel Henrique Barboza, 2023/05/30
- [PATCH 16/16] target/riscv/kvm.c: read/write (cbom|cboz)_blocksize in KVM, Daniel Henrique Barboza, 2023/05/30