From: Dongli Zhang <dongli.zhang@oracle.com>
To: qemu-devel@nongnu.org
Cc: kvm@vger.kernel.org, pbonzini@redhat.com, mtosatti@redhat.com,
dapeng1.mi@linux.intel.com, zhao1.liu@intel.com,
sandipan.das@amd.com, zide.chen@intel.com, joe.jin@oracle.com
Subject: [PATCH 1/1] target/i386/kvm: Use logical counter index for AMD PMU getter
Date: Tue, 24 Mar 2026 19:12:36 -0700 [thread overview]
Message-ID: <20260325021236.14574-1-dongli.zhang@oracle.com> (raw)
For Intel PMU, the counter and selector MSR ranges are disjoint. AMD PMU
behaves the same way when PerfCore is unavailable.
However, once PerfCore is present, AMD PMU switches to an interleaved
layout in which selector and counter MSRs share a single alternating range.
MSR_F15H_PERF_CTL0 = 0xc0010200
MSR_F15H_PERF_CTR0 = 0xc0010201
... ...
... ...
MSR_F15H_PERF_CTL5 = 0xc001020a
MSR_F15H_PERF_CTR5 = 0xc001020b
The commit 4c7f05232c ("target/i386/kvm: reset AMD PMU registers during VM
reset") added the getter/putter pair for AMD PMU MSRs to clear them on
reset, but it ignored that, without PerfCore, AMD reuses alternating MSR
addresses for selectors and counters. env->msr_gp_counters[] holds the raw
counts and env->msr_gp_evtsel[] holds the selectors, so with the
interleaved layout we must translate the MSR address back to the logical
counter index instead of treating the interleaved slot as the array index.
The arrays are sized to MAX_GP_COUNTERS = 18, so the code never writes past
the end. And in the reset path QEMU simply zeroes everything, so that use
case still works.
However, the live migration is broken. The PMU state is stored at the
wrong indices, so the destination VM reloads mismatched selector/counter
pairs. Fix the getter to use the logical counter index rather than the raw
interleaved offset.
Fixes: 4c7f05232c ("target/i386/kvm: reset AMD PMU registers during VM reset")
Signed-off-by: Dongli Zhang <dongli.zhang@oracle.com>
---
target/i386/kvm/kvm.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
index 9e352882c8..b4e549c62b 100644
--- a/target/i386/kvm/kvm.c
+++ b/target/i386/kvm/kvm.c
@@ -5239,9 +5239,9 @@ static int kvm_get_msrs(X86CPU *cpu)
MSR_F15H_PERF_CTL0 + AMD64_NUM_COUNTERS_CORE * 2 - 1:
index = index - MSR_F15H_PERF_CTL0;
if (index & 0x1) {
- env->msr_gp_counters[index] = msrs[i].data;
+ env->msr_gp_counters[index >> 1] = msrs[i].data;
} else {
- env->msr_gp_evtsel[index] = msrs[i].data;
+ env->msr_gp_evtsel[index >> 1] = msrs[i].data;
}
break;
case HV_X64_MSR_HYPERCALL:
--
2.39.3
reply other threads:[~2026-03-25 2:13 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260325021236.14574-1-dongli.zhang@oracle.com \
--to=dongli.zhang@oracle.com \
--cc=dapeng1.mi@linux.intel.com \
--cc=joe.jin@oracle.com \
--cc=kvm@vger.kernel.org \
--cc=mtosatti@redhat.com \
--cc=pbonzini@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=sandipan.das@amd.com \
--cc=zhao1.liu@intel.com \
--cc=zide.chen@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox