@@ -68,6 +68,11 @@ static void cpu_option_add_user_setting(const char *optname, uint32_t value)
GUINT_TO_POINTER(value));
}
+bool riscv_cpu_option_set(const char *optname)
+{
+ return g_hash_table_contains(general_user_opts, optname);
+}
+
#define ISA_EXT_DATA_ENTRY(_name, _min_ver, _prop) \
{#_name, _min_ver, CPU_CFG_OFFSET(_prop)}
@@ -1109,17 +1114,18 @@ void riscv_cpu_finalize_features(RISCVCPU *cpu, Error **errp)
}
#endif
- /*
- * KVM accel does not have a specialized finalize()
- * callback because its extensions are validated
- * in the get()/set() callbacks of each property.
- */
if (tcg_enabled()) {
riscv_tcg_cpu_finalize_features(cpu, &local_err);
if (local_err != NULL) {
error_propagate(errp, local_err);
return;
}
+ } else if (kvm_enabled()) {
+ riscv_kvm_cpu_finalize_features(cpu, &local_err);
+ if (local_err != NULL) {
+ error_propagate(errp, local_err);
+ return;
+ }
}
}
@@ -510,6 +510,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
MMUAccessType access_type, int mmu_idx,
bool probe, uintptr_t retaddr);
char *riscv_isa_string(RISCVCPU *cpu);
+bool riscv_cpu_option_set(const char *optname);
#define cpu_mmu_index riscv_cpu_mmu_index
@@ -1598,6 +1598,65 @@ static bool kvm_cpu_realize(CPUState *cs, Error **errp)
return true;
}
+void riscv_kvm_cpu_finalize_features(RISCVCPU *cpu, Error **errp)
+{
+ CPURISCVState *env = &cpu->env;
+ KVMScratchCPU kvmcpu;
+ struct kvm_one_reg reg;
+ uint64_t val;
+ int ret;
+
+ /* short-circuit without spinning the scratch CPU */
+ if (!cpu->cfg.ext_zicbom && !cpu->cfg.ext_zicboz) {
+ return;
+ }
+
+ if (!kvm_riscv_create_scratch_vcpu(&kvmcpu)) {
+ error_setg(errp, "Unable to create scratch KVM cpu");
+ return;
+ }
+
+ if (cpu->cfg.ext_zicbom &&
+ riscv_cpu_option_set(kvm_cbom_blocksize.name)) {
+
+ reg.id = kvm_riscv_reg_id_ulong(env, KVM_REG_RISCV_CONFIG,
+ kvm_cbom_blocksize.kvm_reg_id);
+ reg.addr = (uint64_t)&val;
+ ret = ioctl(kvmcpu.cpufd, KVM_GET_ONE_REG, ®);
+ if (ret != 0) {
+ error_setg(errp, "Unable to read cbom_blocksize, error %d", errno);
+ return;
+ }
+
+ if (cpu->cfg.cbom_blocksize != val) {
+ error_setg(errp, "Unable to set cbom_blocksize to a different "
+ "value than the host (%lu)", val);
+ return;
+ }
+ }
+
+ if (cpu->cfg.ext_zicboz &&
+ riscv_cpu_option_set(kvm_cboz_blocksize.name)) {
+
+ reg.id = kvm_riscv_reg_id_ulong(env, KVM_REG_RISCV_CONFIG,
+ kvm_cboz_blocksize.kvm_reg_id);
+ reg.addr = (uint64_t)&val;
+ ret = ioctl(kvmcpu.cpufd, KVM_GET_ONE_REG, ®);
+ if (ret != 0) {
+ error_setg(errp, "Unable to read cboz_blocksize, error %d", errno);
+ return;
+ }
+
+ if (cpu->cfg.cboz_blocksize != val) {
+ error_setg(errp, "Unable to set cboz_blocksize to a different "
+ "value than the host (%lu)", val);
+ return;
+ }
+ }
+
+ kvm_riscv_destroy_scratch_vcpu(&kvmcpu);
+}
+
static void kvm_cpu_accel_class_init(ObjectClass *oc, void *data)
{
AccelCPUClass *acc = ACCEL_CPU_CLASS(oc);
@@ -27,5 +27,6 @@ void kvm_riscv_aia_create(MachineState *machine, uint64_t group_shift,
uint64_t guest_num);
void riscv_kvm_aplic_request(void *opaque, int irq, int level);
int kvm_riscv_sync_mpstate_to_kvm(RISCVCPU *cpu, int state);
+void riscv_kvm_cpu_finalize_features(RISCVCPU *cpu, Error **errp);
#endif