target/loongarch/cpu.h | 2 ++ target/loongarch/kvm/kvm.c | 39 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+)
Paravirt preempt feature is OnOffAuto type, it is disabled by default,
also the feature detection is added to check whether it is supported
on KVM host.
Signed-off-by: Bibo Mao <maobibo@loongson.cn>
---
target/loongarch/cpu.h | 2 ++
target/loongarch/kvm/kvm.c | 39 ++++++++++++++++++++++++++++++++++++++
2 files changed, 41 insertions(+)
diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index c592f69885..c6dad2417c 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -302,6 +302,7 @@ enum loongarch_features {
LOONGARCH_FEATURE_STEALTIME,
LOONGARCH_FEATURE_PTW,
LOONGARCH_FEATURE_MSGINT,
+ LOONGARCH_FEATURE_PV_PREEMPT,
};
typedef struct LoongArchBT {
@@ -464,6 +465,7 @@ struct ArchCPU {
OnOffAuto msgint;
OnOffAuto kvm_pv_ipi;
OnOffAuto kvm_steal_time;
+ OnOffAuto kvm_pv_preempt;
int32_t socket_id; /* socket-id of this CPU */
int32_t core_id; /* core-id of this CPU */
int32_t thread_id; /* thread-id of this CPU */
diff --git a/target/loongarch/kvm/kvm.c b/target/loongarch/kvm/kvm.c
index 941142305e..7ca95181a1 100644
--- a/target/loongarch/kvm/kvm.c
+++ b/target/loongarch/kvm/kvm.c
@@ -1039,6 +1039,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_PV_PREEMPT:
+ attr.group = KVM_LOONGARCH_VM_FEAT_CTRL;
+ attr.attr = KVM_LOONGARCH_VM_FEAT_PV_PREEMPT,
+ ret = kvm_vm_ioctl(kvm_state, KVM_HAS_DEVICE_ATTR, &attr);
+ return (ret == 0);
+
default:
return false;
}
@@ -1203,6 +1209,21 @@ static int kvm_cpu_check_pv_features(CPUState *cs, Error **errp)
env->pv_features |= BIT(KVM_FEATURE_STEAL_TIME);
}
+ kvm_supported = kvm_feature_supported(cs, LOONGARCH_FEATURE_PV_PREEMPT);
+ if (cpu->kvm_pv_preempt == ON_OFF_AUTO_ON) {
+ if (!kvm_supported) {
+ error_setg(errp, "'pv preempt' feature not supported by KVM host");
+ return -ENOTSUP;
+ }
+ } else if (cpu->kvm_pv_preempt != ON_OFF_AUTO_AUTO) {
+ kvm_supported = false;
+ }
+
+ /* Feature preempt_hint depends on steal_time */
+ if (kvm_supported && (cpu->kvm_pv_preempt == ON_OFF_AUTO_ON)) {
+ env->pv_features |= BIT(KVM_FEATURE_PREEMPT);
+ }
+
if (object_dynamic_cast(OBJECT(ms), TYPE_LOONGARCH_VIRT_MACHINE)) {
LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(ms);
@@ -1412,6 +1433,18 @@ static void kvm_steal_time_set(Object *obj, bool value, Error **errp)
cpu->kvm_steal_time = value ? ON_OFF_AUTO_ON : ON_OFF_AUTO_OFF;
}
+static bool kvm_pv_preempt_get(Object *obj, Error **errp)
+{
+ return LOONGARCH_CPU(obj)->kvm_pv_preempt != ON_OFF_AUTO_OFF;
+}
+
+static void kvm_pv_preempt_set(Object *obj, bool value, Error **errp)
+{
+ LoongArchCPU *cpu = LOONGARCH_CPU(obj);
+
+ cpu->kvm_pv_preempt = value ? ON_OFF_AUTO_ON : ON_OFF_AUTO_OFF;
+}
+
void kvm_loongarch_cpu_post_init(LoongArchCPU *cpu)
{
cpu->lbt = ON_OFF_AUTO_AUTO;
@@ -1437,6 +1470,12 @@ void kvm_loongarch_cpu_post_init(LoongArchCPU *cpu)
kvm_steal_time_set);
object_property_set_description(OBJECT(cpu), "kvm-steal-time",
"Set off to disable KVM steal time.");
+
+ cpu->kvm_pv_preempt = ON_OFF_AUTO_OFF;
+ object_property_add_bool(OBJECT(cpu), "kvm-pv-preempt", kvm_pv_preempt_get,
+ kvm_pv_preempt_set);
+ object_property_set_description(OBJECT(cpu), "kvm-pv-preempt",
+ "Set off to disable KVM paravirt preempt.");
}
int kvm_arch_destroy_vcpu(CPUState *cs)
base-commit: c1c18d1e640b64292859ce9f30f3c344edfb0294
--
2.54.0
© 2016 - 2026 Red Hat, Inc.