Merge pull request #610 from tkyymmt/mypatch

Update descriptions related to initial_stack
pull/616/head
0xAX 6 years ago committed by GitHub
commit 617e1e360d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -358,7 +358,7 @@ The most interesting thing here is the `initial_stack`. This symbol is defined i
```assembly ```assembly
GLOBAL(initial_stack) GLOBAL(initial_stack)
.quad init_thread_union+THREAD_SIZE-8 .quad init_thread_union + THREAD_SIZE - SIZEOF_PTREGS
``` ```
The `GLOBAL` is already familiar to us from. It defined in the [arch/x86/include/asm/linkage.h](https://github.com/torvalds/linux/blob/16f73eb02d7e1765ccab3d2018e0bd98eb93d973/arch/x86/include/asm/linkage.h) header file expands to the `global` symbol definition: The `GLOBAL` is already familiar to us from. It defined in the [arch/x86/include/asm/linkage.h](https://github.com/torvalds/linux/blob/16f73eb02d7e1765ccab3d2018e0bd98eb93d973/arch/x86/include/asm/linkage.h) header file expands to the `global` symbol definition:
@ -378,19 +378,13 @@ The `THREAD_SIZE` macro is defined in the [arch/x86/include/asm/page_64_types.h]
We consider when the [kasan](http://lxr.free-electrons.com/source/Documentation/kasan.txt) is disabled and the `PAGE_SIZE` is `4096` bytes. So the `THREAD_SIZE` will expands to `16` kilobytes and represents size of the stack of a thread. Why is `thread`? You may already know that each [process](https://en.wikipedia.org/wiki/Process_%28computing%29) may have parent [processes](https://en.wikipedia.org/wiki/Parent_process) and [child](https://en.wikipedia.org/wiki/Child_process) processes. Actually, a parent process and child process differ in stack. A new kernel stack is allocated for a new process. In the Linux kernel this stack is represented by the [union](https://en.wikipedia.org/wiki/Union_type#C.2FC.2B.2B) with the `thread_info` structure. We consider when the [kasan](http://lxr.free-electrons.com/source/Documentation/kasan.txt) is disabled and the `PAGE_SIZE` is `4096` bytes. So the `THREAD_SIZE` will expands to `16` kilobytes and represents size of the stack of a thread. Why is `thread`? You may already know that each [process](https://en.wikipedia.org/wiki/Process_%28computing%29) may have parent [processes](https://en.wikipedia.org/wiki/Parent_process) and [child](https://en.wikipedia.org/wiki/Child_process) processes. Actually, a parent process and child process differ in stack. A new kernel stack is allocated for a new process. In the Linux kernel this stack is represented by the [union](https://en.wikipedia.org/wiki/Union_type#C.2FC.2B.2B) with the `thread_info` structure.
And as we can see the `init_thread_union` is represented by the `thread_union` [union](https://en.wikipedia.org/wiki/Union_type#C.2FC.2B.2B). Earlier this union looked like: The `init_thread_union` is represented by the `thread_union`. And the `thread_union` is defined in the [include/linux/sched.h](https://github.com/torvalds/linux/blob/0500871f21b237b2bea2d9db405eadf78e5aab05/include/linux/sched.h) file like the following:
```C
union thread_union {
struct thread_info thread_info;
unsigned long stack[THREAD_SIZE/sizeof(long)];
};
```
but from the Linux kernel `4.9-rc1` release, `thread_info` was moved to the `task_struct` structure which represents a thread. So, for now `thread_union` looks like:
```C ```C
union thread_union { union thread_union {
#ifndef CONFIG_ARCH_TASK_STRUCT_ON_STACK
struct task_struct task;
#endif
#ifndef CONFIG_THREAD_INFO_IN_TASK #ifndef CONFIG_THREAD_INFO_IN_TASK
struct thread_info thread_info; struct thread_info thread_info;
#endif #endif
@ -398,27 +392,36 @@ union thread_union {
}; };
``` ```
where the `CONFIG_THREAD_INFO_IN_TASK` kernel configuration option is enabled for `x86_64` architecture. So, as we consider only `x86_64` architecture in this book, an instance of `thread_union` will contain only stack and `thread_info` structure will be placed in the `task_struct`. The `CONFIG_ARCH_TASK_STRUCT_ON_STACK` kernel configuration option is only enabled for `ia64` architecture, and the `CONFIG_THREAD_INFO_IN_TASK` kernel configuration option is enabled for `x86_64` architecture. Thus the `thread_info` structure will be placed in `task_struct` structure instead of the `thread_union` union. So, as we consider only `x86_64` architecture in this book, an instance of `thread_union` will contain only stack and task.
The `init_thread_union` is defined in the [include/asm-generic/vmlinux.lds.h](https://github.com/torvalds/blob/a6214385005333202c8cc1744c7075a9e1a26b9a/include/asm-generic/vmlinux.lds.h) file as part of the `INIT_TASK_DATA` macro like the following:
```C
#define INIT_TASK_DATA(align) \
... \
init_thread_union = .; \
...
```
The `init_thread_union` looks like: This macro is used in the [arch/x86/kernel/vmlinux.lds.S](https://github.com/torvalds/linux/blob/c62e43202e7cf50ca24bce58b255df7bf5de69d0/arch/x86/kernel/vmlinux.lds.S) file like the following:
``` ```
union thread_union init_thread_union __init_task_data = { .data : AT(ADDR(.data) - LOAD_OFFSET) {
#ifndef CONFIG_THREAD_INFO_IN_TASK ...
INIT_THREAD_INFO(init_task) /* init_task */
#endif INIT_TASK_DATA(THREAD_SIZE)
}; ...
} :data
``` ```
which represents just thread stack. Now we may understand this expression: Now we may understand this expression:
```assembly ```assembly
GLOBAL(initial_stack) GLOBAL(initial_stack)
.quad init_thread_union+THREAD_SIZE-8 .quad init_thread_union + THREAD_SIZE - SIZEOF_PTREGS
``` ```
that `initial_stack` symbol points to the start of the `thread_union.stack` array + `THREAD_SIZE` which is 16 killobytes and - `SIZEOF_PTREGS` which is 168 bytes. Here we need to subtract `168` bytes at the top of stack. This is necessary to guarantee illegal access of the next page memory.
that `initial_stack` symbol points to the start of the `thread_union.stack` array + `THREAD_SIZE` which is 16 killobytes and - 8 bytes. Here we need to subtract `8` bytes at the top of stack. This is necessary to guarantee illegal access of the next page memory.
After the early boot stack is set, to update the [Global Descriptor Table](https://en.wikipedia.org/wiki/Global_Descriptor_Table) with the `lgdt` instruction: After the early boot stack is set, to update the [Global Descriptor Table](https://en.wikipedia.org/wiki/Global_Descriptor_Table) with the `lgdt` instruction:

@ -120,3 +120,4 @@ Thank you to all contributors:
* [Horace Heaven](https://github.com/horaceheaven) * [Horace Heaven](https://github.com/horaceheaven)
* [Miha Zidar](https://github.com/zidarsk8) * [Miha Zidar](https://github.com/zidarsk8)
* [Ivan Kovnatsky](https://github.com/sevenfourk) * [Ivan Kovnatsky](https://github.com/sevenfourk)
* [Takuya Yamamoto](https://github.com/tkyymmt)

Loading…
Cancel
Save