x86/asm/32: Make pt_regs's segment registers be 16 bits
Many 32-bit x86 CPUs do 16-bit writes when storing segment registers to memory. This can cause the high word of regs->[cdefgs]s to occasionally contain garbage. Rather than making the entry code more complicated to fix up the garbage, just change pt_regs to reflect reality. Signed-off-by: Andy Lutomirski <luto@kernel.org> Cc: Borislav Petkov <bp@alien8.de> Cc: Borislav Petkov <bpetkov@suse.de> Cc: Brian Gerst <brgerst@gmail.com> Cc: Denys Vlasenko <dvlasenk@redhat.com> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Josh Poimboeuf <jpoimboe@redhat.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
parent
21ec3bf6ae
commit
385eca8f27
@ -9,6 +9,20 @@
|
||||
#ifdef __i386__
|
||||
|
||||
struct pt_regs {
|
||||
/*
|
||||
* NB: 32-bit x86 CPUs are inconsistent as what happens in the
|
||||
* following cases (where %seg represents a segment register):
|
||||
*
|
||||
* - pushl %seg: some do a 16-bit write and leave the high
|
||||
* bits alone
|
||||
* - movl %seg, [mem]: some do a 16-bit write despite the movl
|
||||
* - IDT entry: some (e.g. 486) will leave the high bits of CS
|
||||
* and (if applicable) SS undefined.
|
||||
*
|
||||
* Fortunately, x86-32 doesn't read the high bits on POP or IRET,
|
||||
* so we can just treat all of the segment registers as 16-bit
|
||||
* values.
|
||||
*/
|
||||
unsigned long bx;
|
||||
unsigned long cx;
|
||||
unsigned long dx;
|
||||
@ -16,16 +30,22 @@ struct pt_regs {
|
||||
unsigned long di;
|
||||
unsigned long bp;
|
||||
unsigned long ax;
|
||||
unsigned long ds;
|
||||
unsigned long es;
|
||||
unsigned long fs;
|
||||
unsigned long gs;
|
||||
unsigned short ds;
|
||||
unsigned short __dsh;
|
||||
unsigned short es;
|
||||
unsigned short __esh;
|
||||
unsigned short fs;
|
||||
unsigned short __fsh;
|
||||
unsigned short gs;
|
||||
unsigned short __gsh;
|
||||
unsigned long orig_ax;
|
||||
unsigned long ip;
|
||||
unsigned long cs;
|
||||
unsigned short cs;
|
||||
unsigned short __csh;
|
||||
unsigned long flags;
|
||||
unsigned long sp;
|
||||
unsigned long ss;
|
||||
unsigned short ss;
|
||||
unsigned short __ssh;
|
||||
};
|
||||
|
||||
#else /* __i386__ */
|
||||
|
Loading…
Reference in New Issue
Block a user