CodingNow
CodingNow

Reputation: 1028

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

Question:

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

Background:

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

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

#define THREAD_START_SP     (THREAD_SIZE - 8)

Upvotes: 8

Views: 887

Answers (2)

auselen
auselen

Reputation: 28087

This way you can access to thread_info structure just by reading stack pointer and masking out THREAD_SIZE bits (otherwise SP initially would be on 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 that SP needs to be 8-byte aligned.

Update: AAPCS 5.2.1.1 states:

A process may only access (for reading or writing) the closed interval of the entire stack delimited by [SP, stack-base – 1] (where SP is the value of register r13).

Since stack is full-descending

THREAD_START_SP (THREAD_SIZE - 8)

would enforce this requirement probably by illegal access to next page (segmentation fault).

Upvotes: 6

artless-noise-bye-due2AI
artless-noise-bye-due2AI

Reputation: 22440

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

  1. If we reserve anything on the stack, it must be a multiple of eight.
  2. If we peek above the stack, we like to make sure it is mapped.

Multiple of eight

The stack and user register needs to be aligned to 8 bytes. This just makes things more efficient as many ARMs have a 64bit bus and operations on the kernel stack (such as ldrd and strd) may have these requirements. You can see the protection in usr_entry macro. Specifically,

#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 the ldrd and strd instructions. It is also a requirement of the EABI version of the kernel (versus OABI). So if we reserve anything on the stack, it must be a multiple of 8.

Peeking on stack

For the very top frame, we may want to take a peek at previous data. In order not to constantly check that the stack is in the 8K range an extra entry is reserved. Specifically, I think that signals need to peek at the stack.

Upvotes: 1

Related Questions