aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Beulich <jbeulich@suse.com>2013-04-02 10:47:26 +0200
committerJan Beulich <jbeulich@suse.com>2013-04-02 10:47:26 +0200
commit2daa977e4e08b94459b6bfe62cf2c8a381df0903 (patch)
tree5d1000638563e96ef93a2a3c9287f29b2bdcbb9f
parent5c2eb456b376a4a3a6bf9477a5d6577628b68300 (diff)
downloadxen-2daa977e4e08b94459b6bfe62cf2c8a381df0903.tar.gz
xen-2daa977e4e08b94459b6bfe62cf2c8a381df0903.tar.bz2
xen-2daa977e4e08b94459b6bfe62cf2c8a381df0903.zip
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> master changeset: b0583c0e64cc8bb6229c95c3304fdac2051f79b3 master date: 2013-03-12 15:53:30 +0100
-rw-r--r--xen/arch/x86/cpu/mcheck/mce.c12
-rw-r--r--xen/arch/x86/cpu/mcheck/mce.h8
2 files changed, 11 insertions, 9 deletions
diff --git a/xen/arch/x86/cpu/mcheck/mce.c b/xen/arch/x86/cpu/mcheck/mce.c
index c8363203f2..50596e3db5 100644
--- 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_nr, uint64_t msr, uint64_t val)
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) \
diff --git a/xen/arch/x86/cpu/mcheck/mce.h b/xen/arch/x86/cpu/mcheck/mce.h
index 3c773c7450..72b6368713 100644
--- 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_recoverable_t);
/* 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(unsigned int msr)
/* 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