pagetable_init() --> kernel_physical_mapping_init()
static void __init kernel_physical_mapping_init(pgd_t *pgd_base)
{
unsigned long pfn;
pgd_t *pgd;
pmd_t *pmd;
pte_t *pte;
int pgd_idx, pmd_idx, pte_ofs;
定位主内核页全局目录(master kernel page global directory)的起始项pgd=768:
|--------------------------------------|
| pgd_idx = pgd_index(PAGE_OFFSET); |
| pgd = pgd_base + pgd_idx; |
|--------------------------------------|
物理地址从0x0000 0000开始,起始页框号(page frame number)为pfn;
|-----------------|
| pfn = 0; |
|-----------------|
for (; pgd_idx < PTRS_PER_PGD; pgd++, pgd_idx++) {
直接返回pgd(pmd和pgd指向同一个页目录项)
|-------------------------------------|
| pmd = one_md_table_init(pgd); |
|-------------------------------------|
if (pfn >= max_low_pfn)
continue;
for (pmd_idx = 0; pmd_idx < PTRS_PER_PMD && pfn < max_low_pfn; pmd++, pmd_idx++) {
计算第pfn个页框对应的内核空间的线性地址:
|-----------------------------------------------------------------|
| unsigned int address = pfn * PAGE_SIZE + PAGE_OFFSET; |
|-----------------------------------------------------------------|
if (cpu_has_pse) {
unsigned int address2 = (pfn + PTRS_PER_PTE - 1)
* PAGE_SIZE + PAGE_OFFSET + PAGE_SIZE-1;
if (is_kernel_text(address) || is_kernel_text(address2))
set_pmd(pmd, pfn_pmd(pfn, PAGE_KERNEL_LARGE_EXEC));
else
set_pmd(pmd, pfn_pmd(pfn, PAGE_KERNEL_LARGE));
pfn += PTRS_PER_PTE;
填写一个页目录项pmd(pgd),并填写该目录项所对应的页表的所有项
为页目录项pmd分配页表pte,将该页表pte的物理地址写入pmd中,并初始化页表pte的每个页表项;
|--------------------------------------------------------------------------|
| } else { |
| pte = one_page_table_init(pmd); |
| for (pte_ofs = 0; |
| pte_ofs < PTRS_PER_PTE && pfn < max_low_pfn; |
| pte++, pfn++, pte_ofs++) { |
| if ( is_kernel_text(address)) |
| set_pte(pte, pfn_pte(pfn, PAGE_KERNEL_EXEC)); |
| else |
| set_pte(pte, pfn_pte(pfn, PAGE_KERNEL)); |
| } |
| } |
|--------------------------------------------------------------------------|
}
}
}
static void __init kernel_physical_mapping_init(pgd_t *pgd_base)
{
unsigned long pfn;
pgd_t *pgd;
pmd_t *pmd;
pte_t *pte;
int pgd_idx, pmd_idx, pte_ofs;
定位主内核页全局目录(master kernel page global directory)的起始项pgd=768:
|--------------------------------------|
| pgd_idx = pgd_index(PAGE_OFFSET); |
| pgd = pgd_base + pgd_idx; |
|--------------------------------------|
物理地址从0x0000 0000开始,起始页框号(page frame number)为pfn;
|-----------------|
| pfn = 0; |
|-----------------|
for (; pgd_idx < PTRS_PER_PGD; pgd++, pgd_idx++) {
直接返回pgd(pmd和pgd指向同一个页目录项)
|-------------------------------------|
| pmd = one_md_table_init(pgd); |
|-------------------------------------|
if (pfn >= max_low_pfn)
continue;
for (pmd_idx = 0; pmd_idx < PTRS_PER_PMD && pfn < max_low_pfn; pmd++, pmd_idx++) {
计算第pfn个页框对应的内核空间的线性地址:
|-----------------------------------------------------------------|
| unsigned int address = pfn * PAGE_SIZE + PAGE_OFFSET; |
|-----------------------------------------------------------------|
if (cpu_has_pse) {
unsigned int address2 = (pfn + PTRS_PER_PTE - 1)
* PAGE_SIZE + PAGE_OFFSET + PAGE_SIZE-1;
if (is_kernel_text(address) || is_kernel_text(address2))
set_pmd(pmd, pfn_pmd(pfn, PAGE_KERNEL_LARGE_EXEC));
else
set_pmd(pmd, pfn_pmd(pfn, PAGE_KERNEL_LARGE));
pfn += PTRS_PER_PTE;
填写一个页目录项pmd(pgd),并填写该目录项所对应的页表的所有项
为页目录项pmd分配页表pte,将该页表pte的物理地址写入pmd中,并初始化页表pte的每个页表项;
|--------------------------------------------------------------------------|
| } else { |
| pte = one_page_table_init(pmd); |
| for (pte_ofs = 0; |
| pte_ofs < PTRS_PER_PTE && pfn < max_low_pfn; |
| pte++, pfn++, pte_ofs++) { |
| if ( is_kernel_text(address)) |
| set_pte(pte, pfn_pte(pfn, PAGE_KERNEL_EXEC)); |
| else |
| set_pte(pte, pfn_pte(pfn, PAGE_KERNEL)); |
| } |
| } |
|--------------------------------------------------------------------------|
}
}
}