ARM : Kernel : Setting up of MMU in head.S

Dave Hylands dhylands at gmail.com
Wed Mar 30 17:35:03 EDT 2011


Hi Prakash,

On Wed, Mar 30, 2011 at 8:19 AM, Prakash K.B. <prakashk75 at gmail.com> wrote:
> Hello.
>
> Please do not hesitate to let me know if this must be posted elsewhere.
>
> I have been trying to understand the code that sets up the MMU. I do have a
> fair understanding of the way MMU is meant to be setup, but something in the
> kernel code is tripping me.
>
> The code that kickstarts setting up of MMU is __create_page_tables in
> /arch/arm/kernel/head.S.
>
> This code is position independent.
>
> It basically
> - Reserves 16KB of memory in RAM just before the start of the uncompressed
> kernel.
> - Clears the 16KB meant to serve as L1 lookup table containing 4096 entries
> - Creates a section entry in L1 table for the kernel code to be mapped into
> physical memory
>
> It is this creation of section entry code that is puzzling me.
>
> The index used to program this entry is based on physical address of the
> kernel base.
>
> The way it ought to work is this.  When the CPU issues a virtual address,
> the top bits are used as an index into this L1 table and then through a
> couple of table walk throughs, the physical address is arrived at. So the
> index used to program the L1 table ought to have been
>
> Now look at this code.

So the initial mapping is done using a single level table. The top 12
bits (3 nibbles) of the virtual address is used as the index into the
table, and each entry in the table maps 1Mb of memory.

At this stage of the boot, only the kernel direct memory is mapped.

So, if your physical memory starts at 0x80000000 and the kernel
virtual space starts at 0xc0000000 then you should see entries like

0x800xxxxx
0x801xxxxx
0x802xxxxx
0x803xxxxx

starting at 0x80007000.

The first level table starts at an offset of 0x4000 into physical
memory (0x80004000 - 0x80007fff physical or 0xc0004000 - 0xc0007fff
virtual).

If you take the top 3 nibbles of 0xc0000000 you get 0xc00 which when
multipled by 4 (each entry is 4 bytes long), gives 0x3000. 0x80004000
+ 0x3000 = 0x80007000.

Later on, when the kernel is up and running it uses a 2 level table
for memory allocated with get_pages. The 2-level table allows for 4k
pages. The kernel direct memory remains mapped with 1 Mb entries.

If you have access to it (you'll need to register and create an
account), https://silver.arm.com/download/ARM_and_AMBA_Architecture/AR570-DC-11001-r0p0-00rel4/DDI0406B_arm_architecture_reference_manual_errata_markup_8_0.pdf
on page B3-8 shows the layout of the entries which can exist in this
top-level table.

-- 
Dave Hylands
Shuswap, BC, Canada
http://www.davehylands.com



More information about the Kernelnewbies mailing list