Understanding getting the task_struct pointer from the process kernel stack

Right now I am reading Robert Love's Linux Kernel Development 3d Edition. There he writes about the thread_info structure, which contains a pointer to a struct task_struct and, as I understand it, is located at the bottom or at the top of the process kernel stack (depending on architecture). Until recently, I was not familiar with the Linux kernel API, and I did not know about the existence of the current () method. There is an excerpt from the book related to how the current () method works:

In x86, current is computed by masking the 13 least significant bits of the pointer stack to get the thread_info structure. This is done using current_thread_info (). The assembly is shown here: movl $ -8192,% eax andl% esp,% eax It is assumed that the stack size is 8 KB. When 4K blocks are enabled, 4096 is used in place of 8192.

My questions:

  • As far as I know, if we have a decimal value represented as a set of bits, then there is only one low-order bit in the set, right?
  • What is magic number 13?

For thousands who read this topic, the questions that I have voiced may lead to the conclusion that the author does not properly understand the process of allocating and administering memory. Well, that might be right because, in my opinion, I can think of the memory allocated for the stack as a tape full of bits (or bytes). All of these bytes available at a specific memory address are represented as some decimal value. The stack source is the smallest memory address, and the edge of the stack is the highest memory address. But HOW can we get a pointer to the thread_info structure located, for example, at the end of the stack, only by masking the 13 least significant bits of ARBITRARY located by the stack pointer (if I understand correctly, we mask the bits of the ADDRESS stack pointer, represented as a decimal value).

+4
linux linux-kernel
Aug 14 2018-12-12T00:
source share
4 answers

The kernel stack contains a special structure at the top - thread_info :

26 struct thread_info { 27 struct task_struct *task; /* main task structure */ 28 struct exec_domain *exec_domain; /* execution domain */ 29 __u32 flags; /* low level flags */ 30 __u32 status; /* thread synchronous flags */ 31 __u32 cpu; /* current CPU */ 32 int preempt_count; /* 0 => preemptable, 33 <0 => BUG */ 34 mm_segment_t addr_limit; 35 struct restart_block restart_block; 36 void __user *sysenter_return; 37 #ifdef CONFIG_X86_32 38 unsigned long previous_esp; /* ESP of the previous stack in 39 case of nested (IRQ) stacks 40 */ 41 __u8 supervisor_stack[0]; 42 #endif 43 unsigned int sig_on_uaccess_error:1; 44 unsigned int uaccess_err:1; /* uaccess failed */ 45 }; 

So, to get task_struct , you need to get the thread_info pointer with GET_THREAD_INFO from the ASM code:

 183 /* how to get the thread information struct from ASM */ 184 #define GET_THREAD_INFO(reg) \ 185 movl $-THREAD_SIZE, reg; \ 186 andl %esp, reg 

... or current_thread_info from C code:

 174 /* how to get the thread information struct from C */ 175 static inline struct thread_info *current_thread_info(void) 176 { 177 return (struct thread_info *) 178 (current_stack_pointer & ~(THREAD_SIZE - 1)); 179 } 

Note that THREAD_SIZE , defined as (PAGE_SIZE << THREAD_SIZE_ORDER) and THREAD_SIZE_ORDER , is 1 for x86_32 and x86_64, so THREAD_SIZE results in 8192 (2 ^ 13 or 1 <13).

+3
Aug 16 '12 at 23:00
source share

Each process receives only 8192 bytes of the kernel stack aligned at the boundary of 8192 bytes, so when the stack pointer is changed by pressing or pop, the low 13 bits are the only part that changes. 2 ** 13 == 8192.

+4
Aug 14 '12 at 10:13
source share

But HOW can we get a pointer to the thread_info structure, located, say, at the end of the stack, only by masking the 13 least significant bits of the ARBITRARY located on the stack pointer

Please note that both the lower and the limiting (upper) addresses (provided that there is a bottom-up stack with a higher address located below) MUST BE a multiple of the stack size. For example, if the stack size is 8192 (= 2 ^ 13), the 13 least significant bits should be 0 for both the lower and the limit address. The least significant 13 bits is not an ARBITRAGER in a sense that it gives an offset between the bottom address and the limit address that ends with 13 0. Thus, masking the least significant 13 bits gives you the address of the limit address where the thread_info structure is located.

0
Sep 17 '15 at 15:33
source share

My 2 bits: note that the implementation of "current" depends on the form. Answers are still focused on x86; different ways of getting to thread_info and therefore task_struct are used by another arch in Linux.

For example, apparently, PPC uses a register (it is RISC, remember, with a lot of GPR) to save the value of the current effect, displaying part of the hardware context! It will be very fast.

The modern x86 port (I was looking for the source code for 4.1.0) uses per-cpu data for quick implementation and inaction. And so on...

0
Nov 10 '15 at 7:35
source share



All Articles