From: Sean Christopherson <seanjc@google.com>
To: Paolo Bonzini <pbonzini@redhat.com>
Cc: kvm@vger.kernel.org, Sean Christopherson <seanjc@google.com>,
Jim Mattson <jmattson@google.com>
Subject: [kvm-unit-tests PATCH 2/2] x86: msr: Add tests for MCE bank MSRs
Date: Thu, 12 May 2022 23:30:45 +0000 [thread overview]
Message-ID: <20220512233045.4125471-3-seanjc@google.com> (raw)
In-Reply-To: <20220512233045.4125471-1-seanjc@google.com>
Add tests for MCi_XXX MSRs, a.k.a. CTL, STATUS, ADDR and MISC machine
check MSRs (each tuple of 4 MSRs is referred to as a "bank" of MSRs).
Verify that all MSRs in supported banks, as reported by the hypervsior
(or CPU), follow architecturally defined behavior (thankfully, Intel and
AMD don't diverge), e.g. CTL MSRs allow '0' or all ones, STATUS MSRs only
allow '0', non-existent MSRs #GP on read and write, etc...
Ignore AMD's non-architectural behavior of allowing writes to STATUS MSRs
if bit 18 in MSR_K7_HWCR is set. Aside from the fact that it's not an
architectural bit, sane firmware/software will only set the bit when
stuffing STATUS MSRs, and clear it immediately after, e.g. see Linux's
MCE injection. Neither KVM nor the hypervisor should set the bit by
default as PPRs for CPUs that support McStatusWrEn list its RESET value
as '0'. So unless someone runs KUT with funky firmware, pretending the
bit doesn't exist should Just Work.
MSR_K7_HWCR bit 18 also apparently controls the behavior of AMD-only MISC
MSRs (0xC0000xxx range), but those aren't tested.
For banks that are not supported, but are (unofficially?) reserved for
banks on future CPUs, verify that all accesses #GP fault.
Cc: Jim Mattson <jmattson@google.com>
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
x86/msr.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 64 insertions(+), 2 deletions(-)
diff --git a/x86/msr.c b/x86/msr.c
index 3d48e396..a189991a 100644
--- a/x86/msr.c
+++ b/x86/msr.c
@@ -108,10 +108,11 @@ static void test_msr(struct msr_info *msr, bool is_64bit_host)
int main(int ac, char **av)
{
bool is_64bit_host = this_cpu_has(X86_FEATURE_LM);
+ unsigned int nr_mce_banks;
+ char msr_name[32];
int i;
if (ac == 3) {
- char msr_name[16];
int index = strtoul(av[1], NULL, 0x10);
snprintf(msr_name, sizeof(msr_name), "MSR:0x%x", index);
@@ -122,8 +123,69 @@ int main(int ac, char **av)
};
test_msr(&msr, is_64bit_host);
} else {
- for (i = 0 ; i < ARRAY_SIZE(msr_info); i++) {
+ for (i = 0 ; i < ARRAY_SIZE(msr_info); i++)
test_msr(&msr_info[i], is_64bit_host);
+
+ nr_mce_banks = rdmsr(MSR_IA32_MCG_CAP) & 0xff;
+ for (i = 0; i < nr_mce_banks; i++) {
+ snprintf(msr_name, sizeof(msr_name), "MSR_IA32_MC%u_CTL", i);
+ test_msr_rw(MSR_IA32_MCx_CTL(i), msr_name, 0);
+ test_msr_rw(MSR_IA32_MCx_CTL(i), msr_name, -1ull);
+ test_wrmsr_fault(MSR_IA32_MCx_CTL(i), msr_name, NONCANONICAL);
+
+ snprintf(msr_name, sizeof(msr_name), "MSR_IA32_MC%u_STATUS", i);
+ test_msr_rw(MSR_IA32_MCx_STATUS(i), msr_name, 0);
+ /*
+ * STATUS MSRs can only be written with '0' (to clear
+ * the MSR), except on AMD-based systems with bit 18
+ * set in MSR_K7_HWCR. That bit is not architectural
+ * and should not be set by default by KVM or by the
+ * VMM (though this might fail if run on bare metal).
+ */
+ test_wrmsr_fault(MSR_IA32_MCx_STATUS(i), msr_name, 1);
+
+ snprintf(msr_name, sizeof(msr_name), "MSR_IA32_MC%u_ADDR", i);
+ test_msr_rw(MSR_IA32_MCx_ADDR(i), msr_name, 0);
+ test_msr_rw(MSR_IA32_MCx_ADDR(i), msr_name, -1ull);
+ /*
+ * The ADDR is a physical address, and all bits are
+ * writable on 64-bit hosts. Don't test the negative
+ * case, as KVM doesn't enforce checks on bits 63:36
+ * for 32-bit hosts. The behavior depends on the
+ * underlying hardware, e.g. a 32-bit guest on a 64-bit
+ * host may observe 64-bit values in the ADDR MSRs.
+ */
+ if (is_64bit_host)
+ test_msr_rw(MSR_IA32_MCx_ADDR(i), msr_name, NONCANONICAL);
+
+ snprintf(msr_name, sizeof(msr_name), "MSR_IA32_MC%u_MISC", i);
+ test_msr_rw(MSR_IA32_MCx_MISC(i), msr_name, 0);
+ test_msr_rw(MSR_IA32_MCx_MISC(i), msr_name, -1ull);
+ test_msr_rw(MSR_IA32_MCx_MISC(i), msr_name, NONCANONICAL);
+ }
+
+ /*
+ * The theoretical maximum number of MCE banks is 32 (on Intel
+ * CPUs, without jumping to a new base address), as the last
+ * unclaimed MSR is 0x479; 0x480 begins the VMX MSRs. Verify
+ * accesses to theoretically legal, unsupported MSRs fault.
+ */
+ for (i = nr_mce_banks; i < 32; i++) {
+ snprintf(msr_name, sizeof(msr_name), "MSR_IA32_MC%u_CTL", i);
+ test_rdmsr_fault(MSR_IA32_MCx_CTL(i), msr_name);
+ test_wrmsr_fault(MSR_IA32_MCx_CTL(i), msr_name, 0);
+
+ snprintf(msr_name, sizeof(msr_name), "MSR_IA32_MC%u_STATUS", i);
+ test_rdmsr_fault(MSR_IA32_MCx_STATUS(i), msr_name);
+ test_wrmsr_fault(MSR_IA32_MCx_STATUS(i), msr_name, 0);
+
+ snprintf(msr_name, sizeof(msr_name), "MSR_IA32_MC%u_ADDR", i);
+ test_rdmsr_fault(MSR_IA32_MCx_ADDR(i), msr_name);
+ test_wrmsr_fault(MSR_IA32_MCx_ADDR(i), msr_name, 0);
+
+ snprintf(msr_name, sizeof(msr_name), "MSR_IA32_MC%u_MISC", i);
+ test_rdmsr_fault(MSR_IA32_MCx_MISC(i), msr_name);
+ test_wrmsr_fault(MSR_IA32_MCx_MISC(i), msr_name, 0);
}
}
--
2.36.0.550.gb090851708-goog
prev parent reply other threads:[~2022-05-12 23:31 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-05-12 23:30 [kvm-unit-tests PATCH 0/2] x86: msr: MCi_XXX testcases Sean Christopherson
2022-05-12 23:30 ` [kvm-unit-tests PATCH 1/2] x86: msr: Take the MSR index and name separately in low level helpers Sean Christopherson
2022-05-12 23:30 ` Sean Christopherson [this message]
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=20220512233045.4125471-3-seanjc@google.com \
--to=seanjc@google.com \
--cc=jmattson@google.com \
--cc=kvm@vger.kernel.org \
--cc=pbonzini@redhat.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