From 1b719bb8b093c418372a58bbc7aabd3e00882d0b Mon Sep 17 00:00:00 2001 From: Andrew Cooper Date: Thu, 9 Nov 2017 12:09:06 +0000 Subject: [PATCH] x86/msr: Introduce xtf_msr_consistency_test() To help with testing the correctness of MSRs which may be passed directly through to a guest. Signed-off-by: Andrew Cooper --- arch/x86/include/arch/msr.h | 34 ++++++++++++++ arch/x86/msr.c | 91 +++++++++++++++++++++++++++++++++++++ build/files.mk | 1 + 3 files changed, 126 insertions(+) create mode 100644 arch/x86/msr.c diff --git a/arch/x86/include/arch/msr.h b/arch/x86/include/arch/msr.h index 3c58eaf..9fdc236 100644 --- a/arch/x86/include/arch/msr.h +++ b/arch/x86/include/arch/msr.h @@ -107,6 +107,40 @@ typedef union msr_vmx_basic { }; } msr_vmx_basic_t; +/* + * Library logic for MSRs. + */ +struct xtf_msr_consistency_test_data +{ + uint32_t msr; + + const struct xtf_msr_consistency_test_vals + { + uint64_t val; + bool pred; + } *vals; + + size_t nr_vals; +}; + +/** + * Run consistency tests as described by @p t + * + * Some MSRs may be passed directly through to guests for performance reasons. + * This introduces an extra level of complexity for context switching an + * emulation purposes. + * + * To check that synchronisation is working properly, @p t describes an MSR + * and an array of predicated values. For each value where the predicate is + * true, mix regular and forced reads and writes to check that values written + * via one mechanism become visible via the other. + * + * This logic is only applicable to read/write MSRs which expect to retain + * their written values on subsequent reads, and for values which will succeed + * when written. + */ +void xtf_msr_consistency_test(const struct xtf_msr_consistency_test_data *t); + #endif /* XTF_X86_MSR_H */ /* diff --git a/arch/x86/msr.c b/arch/x86/msr.c new file mode 100644 index 0000000..321fab2 --- /dev/null +++ b/arch/x86/msr.c @@ -0,0 +1,91 @@ +/** + * @file arch/x86/msr.c + * + * Library logic for MSRs. + */ +#include +#include + +#include + +static uint64_t force_rdmsr(uint32_t idx) +{ + uint32_t lo, hi; + + asm volatile (_ASM_XEN_FEP "rdmsr" + : "=a" (lo), "=d" (hi) + : "c" (idx)); + + return (((uint64_t)hi) << 32) | lo; +} + +static void force_wrmsr(uint32_t idx, uint64_t val) +{ + asm volatile (_ASM_XEN_FEP "wrmsr": + : "c" (idx), "a" ((uint32_t)val), + "d" ((uint32_t)(val >> 32))); +} + +void xtf_msr_consistency_test(const struct xtf_msr_consistency_test_data *t) +{ + size_t i; + uint64_t val; + + for ( i = 0; i < t->nr_vals; ++i ) + { + if ( !t->vals[i].pred ) + continue; + + wrmsr(t->msr, t->vals[i].val); + val = rdmsr(t->msr); + + if ( val != t->vals[i].val ) + xtf_failure("Fail: MSR %08x, real write, real read\n" + " Got %016"PRIx64", Expected %016"PRIx64"\n", + t->msr, val, t->vals[i].val); + + if ( !xtf_has_fep ) + continue; + + val = force_rdmsr(t->msr); + + if ( val != t->vals[i].val ) + xtf_failure("Fail: MSR %08x, real write, emul read\n" + " Got %016"PRIx64", Expected %016"PRIx64"\n", + t->msr, val, t->vals[i].val); + } + + if ( !xtf_has_fep ) + return; + + for ( i = 0; i < t->nr_vals; ++i ) + { + if ( !t->vals[i].pred ) + continue; + + force_wrmsr(t->msr, t->vals[i].val); + val = rdmsr(t->msr); + + if ( val != t->vals[i].val ) + xtf_failure("Fail: MSR %08x, emul write, real read\n" + " Got %016"PRIx64", Expected %016"PRIx64"\n", + t->msr, val, t->vals[i].val); + + val = force_rdmsr(t->msr); + + if ( val != t->vals[i].val ) + xtf_failure("Fail: MSR %08x, emul write, emul read\n" + " Got %016"PRIx64", Expected %016"PRIx64"\n", + t->msr, val, t->vals[i].val); + } +} + +/* + * Local variables: + * mode: C + * c-file-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/build/files.mk b/build/files.mk index f9bb3b4..46b42d6 100644 --- a/build/files.mk +++ b/build/files.mk @@ -22,6 +22,7 @@ obj-perenv += $(ROOT)/arch/x86/desc.o obj-perenv += $(ROOT)/arch/x86/extable.o obj-perenv += $(ROOT)/arch/x86/grant_table.o obj-perenv += $(ROOT)/arch/x86/hypercall_page.o +obj-perenv += $(ROOT)/arch/x86/msr.o obj-perenv += $(ROOT)/arch/x86/setup.o obj-perenv += $(ROOT)/arch/x86/traps.o -- 2.39.5