mmu - Page table in Linux kernel space during boot -
i feel confuse in page table management in linux kernel ?
in linux kernel space, before page table turned on. kernel run in virtual memory 1-1 mapping mechanism. after page table turned on, kernel has consult page tables translate virtual address physical memory address. questions are:
at time, after turning on page table, kernel space still 1gb (from 0xc0000000 - 0xffffffff ) ?
and in page tables of kernel process, page table entries (pte) in range 0xc0000000 - 0xffffffff mapped ?. ptes out of range not mapped because kernel code never jump there ?
mapping address before , after turning on page table same ?
eg. before turning on page table, virtual address 0xc00000ff mapped physical address 0x000000ff, after turning on page table, above mapping not change. virtual address 0xc00000ff still mapped physical address 0x000000ff. different thing after turning on page table, cpu has consult page table translate virtual address physical address no need before.the page table in kernel space global , shared across process in system including user process ?
this mechanism same in x86 32bit , arm ?
the following discussion based on 32-bit arm linux, , version of kernel source code 3.9
questions can addressed if go through procedure of setting initial page table(which overwitten later function paging_init
) , turning on mmu.
when kernel first launched bootloader, assembly function stext
(in arch\arm\kernel\head.s) first function run. note mmu has not been turned on yet @ moment.
among other things, 2 import jobs done function stext
is:
- create initial page tabel(which overwitten later function
paging_init
) - turn on mmu
- jump c part of kernel initialization code , carry on
before delving questions, benificial know:
- before mmu turned on, every address issued cpu physical address
- after mmu turned on, every address issued cpu virtual address
- a proper page table should set before turning on mmu, otherwise code "be blown away"
- by convention, linux kernel uses higher 1gb part of virtual address , user land uses lower 3gb part
now tricky part:
first trick: using position-independent code. assembly function stext linked address "page_offset + text_offset
"(0xcxxxxxxx), virtual address, however, since mmu has not been turned on yet, actual address assembly function stext running "phys_offset + text_offset
"(the actual value depends on actual hardware), physical address.
so, here thing: program of function stext
"thinks" running in address 0xcxxxxxxx running in address (0x00000000 + some_offeset)(say hardware configures 0x00000000 starting point of ram). before turning on mmu, assembly code need written make sure nothing goes wrong during execution procedure. in fact techinque called position-independent code(pic) used.
to further explain above, extract several assembly code snippets:
ldr r13, =__mmap_switched @ address jump after mmu has been enabled b __enable_mmu @ jump function "__enable_mmu" turn on mmu
note above "ldr" instruction pseudo instruction means "get (virtual) address of function __mmap_switched , put r13"
and function __enable_mmu in turn calls function __turn_mmu_on: (note removed several instructions function __turn_mmu_on essential instructions function not of our interest)
entry(__turn_mmu_on) mcr p15, 0, r0, c1, c0, 0 @ write control reg enable mmu====> mmu turned on, after instruction, every address issued cpu "virtual address" translated mmu mov r3, r13 @ r13 stores (virtual) address jump after mmu has been enabled, (0xc0000000 + some_offset) mov pc, r3 @ long jump endproc(__turn_mmu_on)
second trick: identical mapping when setting initial page table before turning on mmu. more specifically, same address range kernel code running mapped twice.
- the first mapping, expected, maps address range 0x00000000(again, address depends on hardware config) through (0x00000000 + offset) 0xcxxxxxxx through (0xcxxxxxxx + offset)
- the second mapping, interestingly, maps address range 0x00000000 through (0x00000000 + offset) itself(i.e.: 0x00000000 --> (0x00000000 + offset))
why doing that? remember before mmu turned on, every address issued cpu physical address(starting @ 0x00000000) , after mmu turned on, every address issued cpu virtual address(starting @ 0xc0000000).
because arm pipeline structure, @ moment mmu turned on, there still instructions in arm's pipeine using (physical) addresses generated cpu before mmu turned on! avoid these instructions blown up, identical mapping has set cater them.
now returning questions:
- at time, after turning on page table, kernel space still 1gb (from 0xc0000000 - 0xffffffff ) ?
a: guess mean turning on mmu. answer yes, kernel space 1gb(actually occupies several mega bytes below 0xc0000000, not of our interest)
- and in page tables of kernel process, page table entries (pte) in range 0xc0000000 - 0xffffffff mapped ?. ptes out of range not mapped because kernel code never jump there ?
a: while answer question quite complicated because involves lot of details regarding specific kernel configurations.
answer question, need read part of kernel source code set initial page table(assembly function __create_page_tables
) , function sets final page table(c function paging_init).
put simple, there 2 levels of page table in arm, first page table pgd, occupies 16kb. kernel first zeros out pgd during initialization process , initial mapping in assembly function __create_page_tables
. in function __create_page_tables
, small portion of address space mapped.
after that, final page table set in function paging_init
, , in function, quite large portion of address space mapped. if have 512m ram, common configurations, 512m-ram mapping kernel code section section(1 section 1mb). if ram quite large(say 2gb), portion of ram directly mapped. (i stop here because there many details regarding question 2)
- mapping address before , after turning on page table same ?
a: think i've answered question in explanation of "second trick: identical mapping when setting initial page table before turning on mmu."
4 . page table in kernel space global , shared across process in system including user process ?
a: yes , no. yes because processes share same copy(content) of kernel page table(higher 1gb part). no because each process uses own 16kb memory store kernel page table(although content of page table higher 1gb part identical every process).
5 . mechanism same in x86 32bit , arm ?
different architectures use different mechanism
Comments
Post a Comment