summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Braun <rbraun@sceen.net>2018-08-04 12:00:50 +0200
committerRichard Braun <rbraun@sceen.net>2018-08-04 12:00:50 +0200
commitd6d90a3276a09da65690b019e985392bf77b53b0 (patch)
treeb37303e4926cec7d94b4b736c2851b3872508dd3
parentee60e7d2a87fa92bb2dbc259bfbf87e9c49193f2 (diff)
x86/cpu: fix data/stack alignment
-rw-r--r--arch/x86/machine/cpu.c8
-rw-r--r--arch/x86/machine/cpu.h11
-rw-r--r--arch/x86/machine/cpu_asm.S12
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