ping On Thu, Jun 25, 2026 at 9:50 PM Anderson Nascimento <[email protected]> wrote: > > On Tue, Jun 2, 2026 at 11:05 AM Anderson Nascimento > <[email protected]> wrote: > > > > Introduce support for exposing and enabling APERF/MPERF MSR passthrough > > for x86 QEMU guests when running under KVM. > > > > The Linux kernel supports a KVM capability allowing the hypervisor to > > disable read intercepts on the IA32_APERF and IA32_MPERF MSRs, enabling > > guests to track effective frequency directly without VM-exits. QEMU > > currently lacks a native way to request this capability or expose the > > corresponding feature bit to the guest. > > > > This patch adds the `aperfmperf` feature flag via `FEAT_6_ECX` > > (CPUID.06H:ECX[bit 0]). To ensure safe tracking across power states, > > the flag ties into QEMU's existing host power management framework. > > When host CPU power management is explicitly requested by the user > > (via `-overcommit cpu-pm=on`) and the `+aperfmperf` flag is provided > > to the CPU, QEMU will invoke the KVM ioctl to drop the APERF/MPERF > > MSR read intercepts. > > > > This implementation allows guest operating systems (such as FreeBSD > > or Linux) to dynamically calculate CPU utilization and turbo-boost > > metrics without incurring performance overhead from hypervisor trap-and- > > emulate loops. > > > > Signed-off-by: Anderson Nascimento <[email protected]> > > --- > > Changes in v2 > > - Added migration flags > > - Link to v1: > > https://lore.kernel.org/all/[email protected]/ > > > > target/i386/cpu.c | 18 +++++++++++++++++- > > target/i386/cpu.h | 2 ++ > > target/i386/kvm/kvm.c | 5 ++++- > > 3 files changed, 23 insertions(+), 2 deletions(-) > > > > diff --git a/target/i386/cpu.c b/target/i386/cpu.c > > index 8929a75c7c..544738d406 100644 > > --- a/target/i386/cpu.c > > +++ b/target/i386/cpu.c > > @@ -1544,6 +1544,22 @@ FeatureWordInfo feature_word_info[FEATURE_WORDS] = { > > .cpuid = { .eax = 6, .reg = R_EAX, }, > > .tcg_features = TCG_6_EAX_FEATURES, > > }, > > + [FEAT_6_ECX] = { > > + .type = CPUID_FEATURE_WORD, > > + .feat_names = { > > + "aperfmperf", NULL, NULL, NULL, > > + NULL, NULL, NULL, NULL, > > + NULL, NULL, NULL, NULL, > > + NULL, NULL, NULL, NULL, > > + NULL, NULL, NULL, NULL, > > + NULL, NULL, NULL, NULL, > > + NULL, NULL, NULL, NULL, > > + NULL, NULL, NULL, NULL, > > + }, > > + .cpuid = { .eax = 6, .reg = R_ECX, }, > > + .tcg_features = 0, > > + .unmigratable_flags = CPUID_6_ECX_APERFMPERF, > > + }, > > [FEAT_XSAVE_XCR0_LO] = { > > .type = CPUID_FEATURE_WORD, > > .cpuid = { > > @@ -8770,7 +8786,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, > > uint32_t count, > > /* Thermal and Power Leaf */ > > *eax = env->features[FEAT_6_EAX]; > > *ebx = 0; > > - *ecx = 0; > > + *ecx = env->features[FEAT_6_ECX]; > > *edx = 0; > > break; > > case 7: > > diff --git a/target/i386/cpu.h b/target/i386/cpu.h > > index 67e2ecf325..87864969c7 100644 > > --- a/target/i386/cpu.h > > +++ b/target/i386/cpu.h > > @@ -700,6 +700,7 @@ typedef enum FeatureWord { > > FEAT_SVM, /* CPUID[8000_000A].EDX */ > > FEAT_XSAVE, /* CPUID[EAX=0xd,ECX=1].EAX */ > > FEAT_6_EAX, /* CPUID[6].EAX */ > > + FEAT_6_ECX, /* CPUID[6].ECX */ > > FEAT_XSAVE_XCR0_LO, /* CPUID[EAX=0xd,ECX=0].EAX */ > > FEAT_XSAVE_XCR0_HI, /* CPUID[EAX=0xd,ECX=0].EDX */ > > FEAT_ARCH_CAPABILITIES, > > @@ -1232,6 +1233,7 @@ uint64_t x86_cpu_get_supported_feature_word(X86CPU > > *cpu, FeatureWord w); > > #define CPUID_XSAVE_XFD (1U << 4) > > > > #define CPUID_6_EAX_ARAT (1U << 2) > > +#define CPUID_6_ECX_APERFMPERF (1U << 0) > > > > /* CPUID[0x80000007].EDX flags: */ > > #define CPUID_APM_INVTSC (1U << 8) > > diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c > > index 9e352882c8..ca722ff9e9 100644 > > --- a/target/i386/kvm/kvm.c > > +++ b/target/i386/kvm/kvm.c > > @@ -498,6 +498,8 @@ uint32_t kvm_arch_get_supported_cpuid(KVMState *s, > > uint32_t function, > > } > > } else if (function == 6 && reg == R_EAX) { > > ret |= CPUID_6_EAX_ARAT; /* safe to allow because of emulated APIC > > */ > > + } else if (function == 6 && reg == R_ECX) { > > + ret |= CPUID_6_ECX_APERFMPERF; > > } else if (function == 7 && index == 0 && reg == R_EBX) { > > /* Not new instructions, just an optimization. */ > > uint32_t ebx; > > @@ -3291,7 +3293,8 @@ static int kvm_vm_enable_disable_exits(KVMState *s) > > disable_exits &= (KVM_X86_DISABLE_EXITS_MWAIT | > > KVM_X86_DISABLE_EXITS_HLT | > > KVM_X86_DISABLE_EXITS_PAUSE | > > - KVM_X86_DISABLE_EXITS_CSTATE); > > + KVM_X86_DISABLE_EXITS_CSTATE | > > + KVM_X86_DISABLE_EXITS_APERFMPERF); > > } > > > > return kvm_vm_enable_cap(s, KVM_CAP_X86_DISABLE_EXITS, 0, > > -- > > 2.54.0 > > > > ping > > Is there anything I should do to get this patch applied? > > -- > Anderson Nascimento > Allele Security Intelligence > https://www.allelesecurity.com
-- Anderson Nascimento Allele Security Intelligence https://www.allelesecurity.com
