Messages in this thread Patch in this message | | | From | Andy Lutomirski <> | Subject | [RFC 5/7] x86/asm: Rearrange struct cpu_tss to enlarge SYSENTER_stack and fix alignment | Date | Fri, 10 Nov 2017 20:05:24 -0800 |
| |
The Intel SDM says (Volume 3, 7.2.1):
Avoid placing a page boundary in the part of the TSS that the processor reads during a task switch (the first 104 bytes). The processor may not correctly perform address translations if a boundary occurs in this area. During a task switch, the processor reads and writes into the first 104 bytes of each TSS (using contiguous physical addresses beginning with the physical address of the first byte of the TSS). So, after TSS access begins, if part of the 104 bytes is not physically contiguous, the processor will access incorrect information without generating a page-fault exception.
Merely cacheline-aligning the TSS doesn't actually guarantee that the hardware TSS doesn't span a page. Instead, page-align the structure that contains it.
Signed-off-by: Andy Lutomirski <luto@kernel.org> --- arch/x86/include/asm/processor.h | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-)
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index 301d41ca1fa1..97ded6e3edd3 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -326,6 +326,16 @@ struct x86_hw_tss { struct tss_struct { /* + * Space for the temporary SYSENTER stack. Used for the entry + * trampoline as well. Size it such that tss_struct ends up + * as a multiple of PAGE_SIZE. This calculation assumes that + * io_bitmap is a multiple of PAGE_SIZE (8192 bytes) plus one + * long. + */ + unsigned long SYSENTER_stack_canary; + unsigned long SYSENTER_stack[(PAGE_SIZE - sizeof(struct x86_hw_tss)) / sizeof(unsigned long) - 2]; + + /* * The hardware state: */ struct x86_hw_tss x86_tss; @@ -337,15 +347,9 @@ struct tss_struct { * be within the limit. */ unsigned long io_bitmap[IO_BITMAP_LONGS + 1]; - - /* - * Space for the temporary SYSENTER stack. - */ - unsigned long SYSENTER_stack_canary; - unsigned long SYSENTER_stack[64]; } ____cacheline_aligned; -DECLARE_PER_CPU_SHARED_ALIGNED(struct tss_struct, cpu_tss); +DECLARE_PER_CPU_PAGE_ALIGNED(struct tss_struct, cpu_tss); /* * sizeof(unsigned long) coming from an extra "long" at the end -- 2.13.6
| |