void SECTION(".init.cpu")These codes are located in glue/v4_x86/idt.cc. It fill the value into IDTR. However, what more interesting is how IDT is initialized. The initialization filled each exception handler, by default, exc_catch_common. The codes for initialization follows the above codes and reside in class constructor idt_t(). The most confused codes is the first loop in idt_t().
idt_t::activate()
{
x86_descreg_t ide((word_t)descriptors,sizeof(descriptors));
idt.setdescreg(x86_descreg_t::idtr);
}
exc_catch_all[i] =
((sizeof(exc_catch_all)-i*sizeof(u64_t)-5)<<8)|0xe8;
add_int_gate(i, (func_exc) &exc_catch_all[i]);
In order to understand this loop, it is necessary to read three files, i.e. exception.cc, linker-pc99.lds under directory glue/v4-x86/x32 and glue/v4-x86/exception.cc. In the linker-pc99.lds you will find that exc_catch_all[] array and exc_catch_common handler are put side by side. I describe this situation as follow,
________________
| |
| |
| |
| |
| |
. .
. exc_catch_all .
. .
. .
| |
| |
| |
| |
| |
|________________|
| |
|exc_catch_common|
|________________|
from the above figure you may understand where sizeof(exc_catch_all) - i*sizeof(u64_t) comes from. Closer the entry is to exc_catch_common, smaller is the offset that should be filled into entry. I don't know if I clearly explained this stuff... Hope you understand. 0xe8 represents the "near call with 4 byte offset (5 byte)", this is the reason for existence of "-5". After each entry is initialized, they are put into the descriptor table as interrupt gate. The rest code fills special entry in descriptor table with special values, e.g. replace the entry for handling pagefault with the function pointer exc_pagefault.
After IDT is activated, an initializing routine for KIP is called. The initializing routine sets the system call variables to their proper value, the function pointer of each system call routine. I am not very sure what ARCH_SYSCALL is, I will investigate them later. Then more memory will be grabbed for kernel through add_more_kmem(). It looks for the reserved contiguous memory region in KIP's memory descriptors. If there is one, it is reserved for our kernel. add_more_kmem() will put into free memory list in kernel memory manager. If there is not, add_more_kmem() continues to see if special memory descriptor reserved_mem1 is set and put the memory described by reserved_mem1 into free memory list. Then init_meminfo() will reconstruct the memory descriptor map in KIP. init_meminfo() is located in glue/v4-x86/x32/init.cc. The next step is initializing the mapping database in L4 pistachio. I will discuss it in next post.
0 comments:
Post a Comment