Dans ARM Linux, à quoi servent les quelques octets réservés au bas de la stack du kernel pour chaque thread

Question :

Pourquoi 8 octets sont-ils réservés au “bas” de la stack du kernel lors de sa création?

Contexte

Nous soaps que struct pt_regs et thread_info partagent les mêmes 2 pages consécutives (8 192 octets), avec pt_reg situé à l’extrémité supérieure et thread_info à l’extrémité inférieure. Cependant, j’ai remarqué que 8 octets sont réservés à l’adresse la plus élevée de ces 2 pages:

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

 #define THREAD_START_SP (THREAD_SIZE - 8) 

Pourquoi 8 octets sont-ils réservés au “bas” de la stack du kernel lors de sa création?

  1. Si nous réservons quelque chose sur la stack, il doit s’agir d’un multiple de huit.
  2. Si nous jetons un coup d’œil au-dessus de la stack, nous voulons nous assurer qu’elle est cartographiée.

Multiple de huit

La stack et le registre d’utilisateurs doivent être alignés sur 8 octets. Cela rend simplement les choses plus efficaces car de nombreux ARM ont un bus 64 bits et les opérations sur la stack du kernel (telles que ldrd et strd ) peuvent avoir ces exigences. Vous pouvez voir la protection dans la macro usr_entry . Plus précisément,

 #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) ajoute les instructions ldrd et strd . C’est également une exigence de la version EABI du kernel (versus OABI). Donc, si nous réservons quelque chose sur la stack, il doit s’agir d’un multiple de 8.

Jeter un coup d’oeil sur la stack

Pour le cadre tout en haut, nous voudrons peut-être jeter un coup d’œil aux données précédentes. Afin de ne pas vérifier en permanence que la stack est dans la plage de 8 Ko, une entrée supplémentaire est réservée. Plus précisément, je pense que les signaux doivent jeter un coup d’œil à la stack.

De cette façon, vous pouvez accéder à la structure thread_info simplement en lisant le pointeur de stack et en masquant les bits THREAD_SIZE (sinon, SP se trouverait initialement dans le bloc THREAD_SIZE suivant).

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

Huit octets proviennent de la convention d’appel ARM selon laquelle SP doit être aligné sur 8 octets.

Mise à jour: AAPCS 5.2.1.1 déclare:

Un processus peut uniquement accéder (en lecture ou en écriture) à l’intervalle fermé de la stack entière délimitée par [SP, stack-base – 1] (où SP est la valeur du registre r13).

Puisque la stack est complètement décroissante

 THREAD_START_SP (THREAD_SIZE - 8) 

appliquerait probablement cette exigence par un access illégal à la page suivante (erreur de segmentation).