Implement Hardware page table walker(PTW for short) feature in KVM mode.
Use OnOffAuto type variable ptw to check the PTW feature. If the PTW
feature is not supported with KVM host, it reports error if there is
ptw=on option.
Signed-off-by: Bibo Mao <maobibo@loongson.cn>
---
target/loongarch/cpu.c | 5 +++--
target/loongarch/cpu.h | 1 +
target/loongarch/kvm/kvm.c | 35 +++++++++++++++++++++++++++++++++++
3 files changed, 39 insertions(+), 2 deletions(-)
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index b7b61ff877..9aa8f863e9 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -233,12 +233,13 @@ static void loongarch_set_ptw(Object *obj, bool value, Error **errp)
{
LoongArchCPU *cpu = LOONGARCH_CPU(obj);
+ 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;
}
- cpu->ptw = value ? ON_OFF_AUTO_ON : ON_OFF_AUTO_OFF;
cpu->env.cpucfg[2] = FIELD_DP32(cpu->env.cpucfg[2], CPUCFG2, HPTW, value);
}
diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index b1d6799222..1a14469b3b 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -279,6 +279,7 @@ enum loongarch_features {
LOONGARCH_FEATURE_PMU,
LOONGARCH_FEATURE_PV_IPI,
LOONGARCH_FEATURE_STEALTIME,
+ LOONGARCH_FEATURE_PTW,
};
typedef struct LoongArchBT {
diff --git a/target/loongarch/kvm/kvm.c b/target/loongarch/kvm/kvm.c
index 4e4f4e79f6..26e40c9bdc 100644
--- a/target/loongarch/kvm/kvm.c
+++ b/target/loongarch/kvm/kvm.c
@@ -931,6 +931,12 @@ static bool kvm_feature_supported(CPUState *cs, enum loongarch_features feature)
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;
}
@@ -1029,6 +1035,29 @@ static int kvm_cpu_check_pmu(CPUState *cs, Error **errp)
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());
@@ -1123,6 +1152,12 @@ int kvm_arch_init_vcpu(CPUState *cs)
return ret;
}
+ ret = kvm_cpu_check_ptw(cs, &local_err);
+ if (ret < 0) {
+ error_report_err(local_err);
+ return ret;
+ }
+
return 0;
}
--
2.39.3
© 2016 - 2025 Red Hat, Inc.