1
votes

I'm having some doubts about how kernel physical and logical addresses are handled by the MMU. I'll try to explain my question doing an example. Let's doing the assumption that we are on an ARM architecture.

The system starts with the MMU off, so all the addresses which pass inside the CPU are physical. Before we enable the MMU we make a page table where we say that all our physical addresses are mapped at the virtual addresses physical address + 0xC0000000. After this we turn on the MMU. All of this is clear. But now questions start:

Since we are in a pipeline architecture let's say that the instruction after is a load from the address 0x8000. Now for my knowledge here we should have a page fault since the MMU doesn't find this address anywhere inside the page table, so it's invoked a page fault for handle the situation. But also if we've set the interrupt vector, inside it there's a branch to another physical address, so the MMU doesn't find this address and we fall unavoidably in an endless loop. What am I missing?

1

1 Answers

1
votes

You miss that all used virtual addresses should be mapped even if in fact they match the same physical memory regions. Let's elaborate.

Say there is startup code (for primary initialisation and enabling MMU) and other main code (only to work with MMU enabled) with a following layout.

  • startup - phys: 0x4000-0x7FFFF, virt: 0x4000-0x7FFFF
  • main - phys: 0x8000-0xBFFF, virt: 0xC0008000-0xC000BFFF

Such a layout is linker job and your job is to feed it with a right script. CPU entry point in this example is supposed to be 0x4000. That pretty much is a hardware specific address.

CPU starts with MMU disabled and 'PC=0x4000', and it continues till say 0x4800 when MMU is enabled.

So before enabling MMU there have to be maps for a 0x4000-0x7FFFF (startup) and 0xC0008000-0xC000BFFF (all other code).

Now MMU is enabled. PC has 0x4804 (assuming 32b CPU). 0x4804 is a virtual address now and it's mapped on 0x4804 physical address. CPU proceeds with 0x4804, 0x4808, 0x480C etc.

At some point you should jump into a main. For ARM that would be something like

ldr r0, =0xC0008000
bx r0

Note, that virtual address of main entry is used. So after branching PC=0xC0008000 which is resolved into 0x8000 in physical memory.

0x4000-0x7FFFF mapping could be removed after that.