target/i386: support KVM_FEATURE_ASYNC_PF_INT

Linux-5.8 introduced interrupt based mechanism for 'page ready' events
delivery and disabled the old, #PF based one (see commit 2635b5c4a0e4
"KVM: x86: interrupt based APF 'page ready' event delivery"). Linux
guest switches to using in in 5.9 (see commit b1d405751cd5 "KVM: x86:
Switch KVM guest to using interrupts for page ready APF delivery").
The feature has a new KVM_FEATURE_ASYNC_PF_INT bit assigned and
the interrupt vector is set in MSR_KVM_ASYNC_PF_INT MSR. Support this
in QEMU.

Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
Message-Id: <20200908141206.357450-1-vkuznets@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Vitaly Kuznetsov 2020-09-08 16:12:06 +02:00 committed by Paolo Bonzini
parent 1b7e01d008
commit db5daafab2
4 changed files with 32 additions and 1 deletions

View File

@ -799,7 +799,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
"kvmclock", "kvm-nopiodelay", "kvm-mmu", "kvmclock", "kvmclock", "kvm-nopiodelay", "kvm-mmu", "kvmclock",
"kvm-asyncpf", "kvm-steal-time", "kvm-pv-eoi", "kvm-pv-unhalt", "kvm-asyncpf", "kvm-steal-time", "kvm-pv-eoi", "kvm-pv-unhalt",
NULL, "kvm-pv-tlb-flush", NULL, "kvm-pv-ipi", NULL, "kvm-pv-tlb-flush", NULL, "kvm-pv-ipi",
"kvm-poll-control", "kvm-pv-sched-yield", NULL, NULL, "kvm-poll-control", "kvm-pv-sched-yield", "kvm-asyncpf-int", NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
"kvmclock-stable-bit", NULL, NULL, NULL, "kvmclock-stable-bit", NULL, NULL, NULL,
@ -6988,6 +6988,7 @@ static void x86_cpu_initfn(Object *obj)
object_property_add_alias(obj, "kvm_nopiodelay", obj, "kvm-nopiodelay"); object_property_add_alias(obj, "kvm_nopiodelay", obj, "kvm-nopiodelay");
object_property_add_alias(obj, "kvm_mmu", obj, "kvm-mmu"); object_property_add_alias(obj, "kvm_mmu", obj, "kvm-mmu");
object_property_add_alias(obj, "kvm_asyncpf", obj, "kvm-asyncpf"); object_property_add_alias(obj, "kvm_asyncpf", obj, "kvm-asyncpf");
object_property_add_alias(obj, "kvm_asyncpf_int", obj, "kvm-asyncpf-int");
object_property_add_alias(obj, "kvm_steal_time", obj, "kvm-steal-time"); object_property_add_alias(obj, "kvm_steal_time", obj, "kvm-steal-time");
object_property_add_alias(obj, "kvm_pv_eoi", obj, "kvm-pv-eoi"); object_property_add_alias(obj, "kvm_pv_eoi", obj, "kvm-pv-eoi");
object_property_add_alias(obj, "kvm_pv_unhalt", obj, "kvm-pv-unhalt"); object_property_add_alias(obj, "kvm_pv_unhalt", obj, "kvm-pv-unhalt");

View File

@ -1492,6 +1492,7 @@ typedef struct CPUX86State {
uint64_t wall_clock_msr; uint64_t wall_clock_msr;
uint64_t steal_time_msr; uint64_t steal_time_msr;
uint64_t async_pf_en_msr; uint64_t async_pf_en_msr;
uint64_t async_pf_int_msr;
uint64_t pv_eoi_en_msr; uint64_t pv_eoi_en_msr;
uint64_t poll_control_msr; uint64_t poll_control_msr;

View File

@ -287,6 +287,7 @@ static const struct kvm_para_features {
{ KVM_CAP_NOP_IO_DELAY, KVM_FEATURE_NOP_IO_DELAY }, { KVM_CAP_NOP_IO_DELAY, KVM_FEATURE_NOP_IO_DELAY },
{ KVM_CAP_PV_MMU, KVM_FEATURE_MMU_OP }, { KVM_CAP_PV_MMU, KVM_FEATURE_MMU_OP },
{ KVM_CAP_ASYNC_PF, KVM_FEATURE_ASYNC_PF }, { KVM_CAP_ASYNC_PF, KVM_FEATURE_ASYNC_PF },
{ KVM_CAP_ASYNC_PF_INT, KVM_FEATURE_ASYNC_PF_INT },
}; };
static int get_para_features(KVMState *s) static int get_para_features(KVMState *s)
@ -2821,6 +2822,9 @@ static int kvm_put_msrs(X86CPU *cpu, int level)
if (env->features[FEAT_KVM] & (1 << KVM_FEATURE_ASYNC_PF)) { if (env->features[FEAT_KVM] & (1 << KVM_FEATURE_ASYNC_PF)) {
kvm_msr_entry_add(cpu, MSR_KVM_ASYNC_PF_EN, env->async_pf_en_msr); kvm_msr_entry_add(cpu, MSR_KVM_ASYNC_PF_EN, env->async_pf_en_msr);
} }
if (env->features[FEAT_KVM] & (1 << KVM_FEATURE_ASYNC_PF_INT)) {
kvm_msr_entry_add(cpu, MSR_KVM_ASYNC_PF_EN, env->async_pf_int_msr);
}
if (env->features[FEAT_KVM] & (1 << KVM_FEATURE_PV_EOI)) { if (env->features[FEAT_KVM] & (1 << KVM_FEATURE_PV_EOI)) {
kvm_msr_entry_add(cpu, MSR_KVM_PV_EOI_EN, env->pv_eoi_en_msr); kvm_msr_entry_add(cpu, MSR_KVM_PV_EOI_EN, env->pv_eoi_en_msr);
} }
@ -3206,6 +3210,9 @@ static int kvm_get_msrs(X86CPU *cpu)
if (env->features[FEAT_KVM] & (1 << KVM_FEATURE_ASYNC_PF)) { if (env->features[FEAT_KVM] & (1 << KVM_FEATURE_ASYNC_PF)) {
kvm_msr_entry_add(cpu, MSR_KVM_ASYNC_PF_EN, 0); kvm_msr_entry_add(cpu, MSR_KVM_ASYNC_PF_EN, 0);
} }
if (env->features[FEAT_KVM] & (1 << KVM_FEATURE_ASYNC_PF_INT)) {
kvm_msr_entry_add(cpu, MSR_KVM_ASYNC_PF_INT, 0);
}
if (env->features[FEAT_KVM] & (1 << KVM_FEATURE_PV_EOI)) { if (env->features[FEAT_KVM] & (1 << KVM_FEATURE_PV_EOI)) {
kvm_msr_entry_add(cpu, MSR_KVM_PV_EOI_EN, 0); kvm_msr_entry_add(cpu, MSR_KVM_PV_EOI_EN, 0);
} }
@ -3446,6 +3453,9 @@ static int kvm_get_msrs(X86CPU *cpu)
case MSR_KVM_ASYNC_PF_EN: case MSR_KVM_ASYNC_PF_EN:
env->async_pf_en_msr = msrs[i].data; env->async_pf_en_msr = msrs[i].data;
break; break;
case MSR_KVM_ASYNC_PF_INT:
env->async_pf_int_msr = msrs[i].data;
break;
case MSR_KVM_PV_EOI_EN: case MSR_KVM_PV_EOI_EN:
env->pv_eoi_en_msr = msrs[i].data; env->pv_eoi_en_msr = msrs[i].data;
break; break;

View File

@ -394,6 +394,13 @@ static bool async_pf_msr_needed(void *opaque)
return cpu->env.async_pf_en_msr != 0; return cpu->env.async_pf_en_msr != 0;
} }
static bool async_pf_int_msr_needed(void *opaque)
{
X86CPU *cpu = opaque;
return cpu->env.async_pf_int_msr != 0;
}
static bool pv_eoi_msr_needed(void *opaque) static bool pv_eoi_msr_needed(void *opaque)
{ {
X86CPU *cpu = opaque; X86CPU *cpu = opaque;
@ -467,6 +474,17 @@ static const VMStateDescription vmstate_async_pf_msr = {
} }
}; };
static const VMStateDescription vmstate_async_pf_int_msr = {
.name = "cpu/async_pf_int_msr",
.version_id = 1,
.minimum_version_id = 1,
.needed = async_pf_int_msr_needed,
.fields = (VMStateField[]) {
VMSTATE_UINT64(env.async_pf_int_msr, X86CPU),
VMSTATE_END_OF_LIST()
}
};
static const VMStateDescription vmstate_pv_eoi_msr = { static const VMStateDescription vmstate_pv_eoi_msr = {
.name = "cpu/async_pv_eoi_msr", .name = "cpu/async_pv_eoi_msr",
.version_id = 1, .version_id = 1,
@ -1438,6 +1456,7 @@ VMStateDescription vmstate_x86_cpu = {
.subsections = (const VMStateDescription*[]) { .subsections = (const VMStateDescription*[]) {
&vmstate_exception_info, &vmstate_exception_info,
&vmstate_async_pf_msr, &vmstate_async_pf_msr,
&vmstate_async_pf_int_msr,
&vmstate_pv_eoi_msr, &vmstate_pv_eoi_msr,
&vmstate_steal_time_msr, &vmstate_steal_time_msr,
&vmstate_poll_control_msr, &vmstate_poll_control_msr,