diff options
author | Richard Braun <rbraun@sceen.net> | 2018-08-04 12:00:50 +0200 |
---|---|---|
committer | Richard Braun <rbraun@sceen.net> | 2018-08-04 12:00:50 +0200 |
commit | d6d90a3276a09da65690b019e985392bf77b53b0 (patch) | |
tree | b37303e4926cec7d94b4b736c2851b3872508dd3 | |
parent | ee60e7d2a87fa92bb2dbc259bfbf87e9c49193f2 (diff) |
x86/cpu: fix data/stack alignment
-rw-r--r-- | arch/x86/machine/cpu.c | 8 | ||||
-rw-r--r-- | arch/x86/machine/cpu.h | 11 | ||||
-rw-r--r-- | arch/x86/machine/cpu_asm.S | 12 |
3 files changed, 28 insertions, 3 deletions
diff --git a/arch/x86/machine/cpu.c b/arch/x86/machine/cpu.c index 350c7c49..4ceb5e7f 100644 --- a/arch/x86/machine/cpu.c +++ b/arch/x86/machine/cpu.c @@ -118,9 +118,15 @@ struct cpu_pseudo_desc { uintptr_t address; } __packed; +#ifdef __LP64__ +#define cpu_exc_frame_attrs +#else /* __LP64__ */ +#define cpu_exc_frame_attrs __packed +#endif /* __LP64__ */ + struct cpu_exc_frame { unsigned long words[CPU_EXC_FRAME_SIZE]; -}; +} cpu_exc_frame_attrs; /* * Type for low level exception handlers. diff --git a/arch/x86/machine/cpu.h b/arch/x86/machine/cpu.h index 01d1d39f..2ce14028 100644 --- a/arch/x86/machine/cpu.h +++ b/arch/x86/machine/cpu.h @@ -90,9 +90,16 @@ #define CPU_WORD_SIZE (LONG_BIT / 8) /* - * Data alignment, normally the word size. + * Data alignment. + * + * This is used to align regions of memory that can store any type of + * data, such as stacks and sections. The modern i386 as well as the + * amd64 System V ABIs both mandate 16 byte data alignment. Kernel + * software could use smaller alignments, but this one is meant to + * be linked against static libraries, and in particular libgcc, which + * are built for standard ABIs. */ -#define CPU_DATA_ALIGN CPU_WORD_SIZE +#define CPU_DATA_ALIGN 16 /* * Function alignment. diff --git a/arch/x86/machine/cpu_asm.S b/arch/x86/machine/cpu_asm.S index ff9c6e9a..24d44797 100644 --- a/arch/x86/machine/cpu_asm.S +++ b/arch/x86/machine/cpu_asm.S @@ -120,6 +120,10 @@ .endr .endm +/* + * Note that, unlike i386, the CPU aligns the stack frame to 16 bytes, + * and skipping the red zone keeps the stack pointer correctly aligned. + */ .macro cpu_ll_exc_enter vector pushq %rbx /* save registers used for */ pushq %rax /* stack switching */ @@ -146,6 +150,7 @@ .macro cpu_ll_exc_handle vector cpu_ll_exc_enter \vector movq %rbx, %rdi + andq $(~(CPU_DATA_ALIGN - 1)), %rsp call cpu_exc_main cpu_ll_exc_leave .endm @@ -201,6 +206,11 @@ movl %esp, %ebx /* save frame */ .endm +.macro cpu_ll_exc_align_stack nr_args + andl $(~(CPU_DATA_ALIGN - 1)), %esp + addl $((\nr_args * CPU_WORD_SIZE) % CPU_DATA_ALIGN), %esp +.endm + .macro cpu_ll_exc_leave movl %ebx, %esp /* restore stack */ call thread_schedule /* schedule threads */ @@ -210,6 +220,7 @@ .macro cpu_ll_exc_handle vector cpu_ll_exc_enter \vector + cpu_ll_exc_align_stack 1 pushl %ebx call cpu_exc_main cpu_ll_exc_leave @@ -219,6 +230,7 @@ cpu_ll_exc_enter \vector call cpu_get_intr_stack_ptr movl %eax, %esp /* switch to interrupt stack */ + cpu_ll_exc_align_stack 1 pushl %ebx call cpu_intr_main cpu_ll_exc_leave |