diff options
| author | Tony Luck <tony.luck@intel.com> | 2012-05-23 17:14:22 -0400 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-06-01 03:13:00 -0400 |
| commit | 1c4f53ca32463a742583976f40444ce4485f3cf9 (patch) | |
| tree | 68dcbed29e197bf61c0265d1091778bddd32f7ec /arch/x86/kernel/cpu | |
| parent | c179c9851c1b009faf3ec15b2af5042431a5a2ca (diff) | |
x86/mce: Fix check for processor context when machine check was taken.
commit 875e26648cf9b6db9d8dc07b7959d7c61fb3f49c upstream.
Linus pointed out that there was no value is checking whether m->ip
was zero - because zero is a legimate value. If we have a reliable
(or faked in the VM86 case) "m->cs" we can use it to tell whether we
were in user mode or kernelwhen the machine check hit.
Reported-by: Linus Torvalds <torvalds@linuxfoundation.org>
Signed-off-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'arch/x86/kernel/cpu')
| -rw-r--r-- | arch/x86/kernel/cpu/mcheck/mce-severity.c | 16 |
1 files changed, 10 insertions, 6 deletions
diff --git a/arch/x86/kernel/cpu/mcheck/mce-severity.c b/arch/x86/kernel/cpu/mcheck/mce-severity.c index 1e8d66c1336..362190bd9e1 100644 --- a/arch/x86/kernel/cpu/mcheck/mce-severity.c +++ b/arch/x86/kernel/cpu/mcheck/mce-severity.c | |||
| @@ -101,15 +101,19 @@ static struct severity { | |||
| 101 | }; | 101 | }; |
| 102 | 102 | ||
| 103 | /* | 103 | /* |
| 104 | * If the EIPV bit is set, it means the saved IP is the | 104 | * If mcgstatus indicated that ip/cs on the stack were |
| 105 | * instruction which caused the MCE. | 105 | * no good, then "m->cs" will be zero and we will have |
| 106 | * to assume the worst case (IN_KERNEL) as we actually | ||
| 107 | * have no idea what we were executing when the machine | ||
| 108 | * check hit. | ||
| 109 | * If we do have a good "m->cs" (or a faked one in the | ||
| 110 | * case we were executing in VM86 mode) we can use it to | ||
| 111 | * distinguish an exception taken in user from from one | ||
| 112 | * taken in the kernel. | ||
| 106 | */ | 113 | */ |
| 107 | static int error_context(struct mce *m) | 114 | static int error_context(struct mce *m) |
| 108 | { | 115 | { |
| 109 | if (m->mcgstatus & MCG_STATUS_EIPV) | 116 | return ((m->cs & 3) == 3) ? IN_USER : IN_KERNEL; |
| 110 | return (m->ip && (m->cs & 3) == 3) ? IN_USER : IN_KERNEL; | ||
| 111 | /* Unknown, assume kernel */ | ||
| 112 | return IN_KERNEL; | ||
| 113 | } | 117 | } |
| 114 | 118 | ||
| 115 | int mce_severity(struct mce *a, int tolerant, char **msg) | 119 | int mce_severity(struct mce *a, int tolerant, char **msg) |
