73 lines
2.5 KiB
Diff
73 lines
2.5 KiB
Diff
|
References: bnc#805579
|
||
|
|
||
|
# Commit b0583c0e64cc8bb6229c95c3304fdac2051f79b3
|
||
|
# Date 2013-03-12 15:53:30 +0100
|
||
|
# Author Jan Beulich <jbeulich@suse.com>
|
||
|
# Committer Jan Beulich <jbeulich@suse.com>
|
||
|
x86/MCA: suppress bank clearing for certain injected events
|
||
|
|
||
|
As the bits indicating validity of the ADDR and MISC bank MSRs may be
|
||
|
injected in a way that isn't consistent with what the underlying
|
||
|
hardware implements (while the bank must be valid for injection to
|
||
|
work, the auxiliary MSRs may not be implemented - and hence cause #GP
|
||
|
upon access - if the hardware never sets the corresponding valid bits.
|
||
|
|
||
|
Consequently we need to do the clearing writes only if no value was
|
||
|
interposed for the respective MSR (which also makes sense the other way
|
||
|
around: there's no point in clearing a hardware register when all data
|
||
|
read came from software). Of course this all requires the injection
|
||
|
tool to do things in a consistent way (but that had been a requirement
|
||
|
before already).
|
||
|
|
||
|
Signed-off-by: Jan Beulich <jbeulich@suse.com>
|
||
|
Tested-by: Ren Yongjie <yongjie.ren@intel.com>
|
||
|
Acked-by: Liu Jinsong <jinsong.liu@intel.com>
|
||
|
|
||
|
--- a/xen/arch/x86/cpu/mcheck/mce.c
|
||
|
+++ b/xen/arch/x86/cpu/mcheck/mce.c
|
||
|
@@ -1145,13 +1145,15 @@ static void intpose_add(unsigned int cpu
|
||
|
printk("intpose_add: interpose array full - request dropped\n");
|
||
|
}
|
||
|
|
||
|
-void intpose_inval(unsigned int cpu_nr, uint64_t msr)
|
||
|
+bool_t intpose_inval(unsigned int cpu_nr, uint64_t msr)
|
||
|
{
|
||
|
- struct intpose_ent *ent;
|
||
|
+ struct intpose_ent *ent = intpose_lookup(cpu_nr, msr, NULL);
|
||
|
|
||
|
- if ((ent = intpose_lookup(cpu_nr, msr, NULL)) != NULL) {
|
||
|
- ent->cpu_nr = -1;
|
||
|
- }
|
||
|
+ if ( !ent )
|
||
|
+ return 0;
|
||
|
+
|
||
|
+ ent->cpu_nr = -1;
|
||
|
+ return 1;
|
||
|
}
|
||
|
|
||
|
#define IS_MCA_BANKREG(r) \
|
||
|
--- a/xen/arch/x86/cpu/mcheck/mce.h
|
||
|
+++ b/xen/arch/x86/cpu/mcheck/mce.h
|
||
|
@@ -89,7 +89,7 @@ extern void mce_recoverable_register(mce
|
||
|
/* Read an MSR, checking for an interposed value first */
|
||
|
extern struct intpose_ent *intpose_lookup(unsigned int, uint64_t,
|
||
|
uint64_t *);
|
||
|
-extern void intpose_inval(unsigned int, uint64_t);
|
||
|
+extern bool_t intpose_inval(unsigned int, uint64_t);
|
||
|
|
||
|
static inline uint64_t mca_rdmsr(unsigned int msr)
|
||
|
{
|
||
|
@@ -101,9 +101,9 @@ static inline uint64_t mca_rdmsr(unsigne
|
||
|
|
||
|
/* Write an MSR, invalidating any interposed value */
|
||
|
#define mca_wrmsr(msr, val) do { \
|
||
|
- intpose_inval(smp_processor_id(), msr); \
|
||
|
- wrmsrl(msr, val); \
|
||
|
-} while (0)
|
||
|
+ if ( !intpose_inval(smp_processor_id(), msr) ) \
|
||
|
+ wrmsrl(msr, val); \
|
||
|
+} while ( 0 )
|
||
|
|
||
|
|
||
|
/* Utility function to "logout" all architectural MCA telemetry from the MCA
|