On ARM Linux, what is the purpose of several bytes reserved at the "bottom" of the kernel stack for each thread

Question

Why are 8 bytes reserved at the bottom of the kernel stack when it is created?

Background

We know that struct pt_regs and thread_info use the same two consecutive pages (8192 bytes), and pt_reg are located at the upper end and thread_info at the lower end. However, I noticed that 8 bytes are reserved at the highest address of these two pages:

in arch / arm / include / asm / threadinfo.h

 #define THREAD_START_SP (THREAD_SIZE - 8) 
+7
c arm linux-kernel
source share
2 answers

Why are 8 bytes reserved at the bottom of the kernel stack when it is created?

  • If we reserve something on the stack, it must be a multiple of eight.
  • If we look above the stack, we would like to make sure that it is displayed.

Several out of eight

The stack and user register must be aligned with 8 bytes. This only makes things more efficient, since many ARMs have a 64-bit bus, and kernel stack operations (e.g. ldrd and strd ) may have these requirements. You can see the protection in the usr_entry macro . In particular,

 #if defined(CONFIG_AEABI) && (__LINUX_ARM_ARCH__ >= 5) && (S_FRAME_SIZE & 7) #error "sizeof(struct pt_regs) must be a multiple of 8" #endif 

ARMv5 (architecture version 5) adds ldrd and strd . This is also a requirement of the EABI kernel version (compared to OABI). Therefore, if we reserve something on the stack, it must be a multiple of 8.

Peeking on stack

For the topmost frame, we might want to look at the previous data. In order not to constantly check that the stack is in the 8K range, an extra record is reserved. In particular, I think that signals should look at the stack.

+1
source share

Thus, you can access the thread_info structure by simply reading the stack pointer and masking the THREAD_SIZE bits (otherwise SP will initially be in the next THREAD_SIZE block).

 static inline struct thread_info *current_thread_info(void) { register unsigned long sp asm ("sp"); return (struct thread_info *)(sp & ~(THREAD_SIZE - 1)); } 

Eight bytes come from the ARM calling convention, which the SP should be aligned to 8 bytes.

Update: AAPCS 5.2.1.1 status:

A process can only access (read or write) the closed interval of the entire stack, limited by [SP, stack-base-1] (where SP is the value of register r13).

Since the stack is full downward

 THREAD_START_SP (THREAD_SIZE - 8) 

will apply this requirement, probably through illegal access to the next page (segmentation error).

+6
source share

All Articles