cpu->ptw = value ? ON_OFF_AUTO_ON : ON_OFF_AUTO_OFF;
if (kvm_enabled()) {
- /* PTW feature is only support in TCG mode now */
+ /* kvm feature detection in function kvm_arch_init_vcpu */
return;
}
static void loongarch_max_initfn(Object *obj)
{
LoongArchCPU *cpu = LOONGARCH_CPU(obj);
- /* '-cpu max' for TCG: we use cpu la464. */
+ /* '-cpu max': use it for max supported CPU features */
loongarch_la464_initfn(obj);
+ cpu->ptw = ON_OFF_AUTO_AUTO;
if (tcg_enabled()) {
cpu->env.cpucfg[1] = FIELD_DP32(cpu->env.cpucfg[1], CPUCFG1, MSG_INT, 1);
cpu->msgint = ON_OFF_AUTO_AUTO;
cpu->env.cpucfg[2] = FIELD_DP32(cpu->env.cpucfg[2], CPUCFG2, HPTW, 1);
- cpu->ptw = ON_OFF_AUTO_AUTO;
}
}
ret = kvm_vm_ioctl(kvm_state, KVM_HAS_DEVICE_ATTR, &attr);
return (ret == 0);
+ case LOONGARCH_FEATURE_PTW:
+ attr.group = KVM_LOONGARCH_VM_FEAT_CTRL;
+ attr.attr = KVM_LOONGARCH_VM_FEAT_PTW;
+ ret = kvm_vm_ioctl(kvm_state, KVM_HAS_DEVICE_ATTR, &attr);
+ return (ret == 0);
+
default:
return false;
}
return 0;
}
+static int kvm_cpu_check_ptw(CPUState *cs, Error **errp)
+{
+ LoongArchCPU *cpu = LOONGARCH_CPU(cs);
+ CPULoongArchState *env = cpu_env(cs);
+ bool kvm_supported;
+
+ kvm_supported = kvm_feature_supported(cs, LOONGARCH_FEATURE_PTW);
+ if (cpu->ptw == ON_OFF_AUTO_ON) {
+ if (!kvm_supported) {
+ error_setg(errp, "'ptw' feature not supported by KVM on the host");
+ return -ENOTSUP;
+ }
+ } else if (cpu->ptw != ON_OFF_AUTO_AUTO) {
+ /* disable pmu if ON_OFF_AUTO_OFF is set */
+ kvm_supported = false;
+ }
+
+ if (kvm_supported) {
+ env->cpucfg[2] = FIELD_DP32(env->cpucfg[2], CPUCFG2, HPTW, 1);
+ }
+ return 0;
+}
+
static int kvm_cpu_check_pv_features(CPUState *cs, Error **errp)
{
MachineState *ms = MACHINE(qdev_get_machine());
return ret;
}
+ ret = kvm_cpu_check_ptw(cs, &local_err);
+ if (ret < 0) {
+ error_report_err(local_err);
+ return ret;
+ }
+
return 0;
}