So I'm working with QEMU and AArch64 mode and using the MMU. I've succesfully mapped 4K blocks, but I'm having trouble mapping 2M blocks. My configuration is such that the L1 entries are 1GB blocks, L2 entries are 2M blocks, and L3 entries are 4K, or at least that's my understanding of how I've configured it. My assumption is that if I have a block entry in a L2 table that it will map that VA from [va, va+2M) starting at the given PA in the entry in the range [pa, pa+2M). See example below for what I'm expecting. My configuration:TCR_EL1 = 0x120192019
TTBR0_EL1 = 0x43496000VA = 0x201000--> L1 Index = 0--> L2 Index = 1--> L3 Index = 1 (not needed, unused) First couple of entries:0x43496000: 0x43497003 0x43496008: 0x0 0x43496010: 0x00x43497003 is value at L1_TABLE[0] and points to an L2 Table at 0x43497000.First few entries at 0x43497000 which is the L2_TABLE:0x43497000: 0x434980030x43497008: 0x438976490x43497010: 0x43a976490x43497018: 0x43c976490x43497020: 0x43e976490x43497028: 0x440976490x43497030: 0x442976490x43497038: 0x444976490x43497040: 0x44697649Entry L2_TABLE[1] is 0x43897649 and represents a 2MB block at [0x43897000, 0x43a97000). Given this configuration, I expect that VA 0x201000 maps to PA 0x43898000, but in QEMU I see that every 4K is mapped again starting at 0x43897000. See below for some examples.(qemu) gva2gpa 0x200000gpa: 0x43897000 ---> this is expected(qemu) gva2gpa 0x200100gpa: 0x43897100 ---> this is expected (qemu) gva2gpa 0x201000gpa: 0x43897000 ---> this is NOT expected, expected 0x43898000(qemu) gva2gpa 0x202000gpa: 0x43897000 ---> this is NOT expected, expected 0x43899000(qemu) gva2gpa 0x202500gpa: 0x43897500 ---> this is NOT expected, expected 0x43899500(qemu) gva2gpa 0x203000gpa: 0x43897000 ---> this is NOT expected, expected 0x4389a000What am I missing?
After a few days of searching, I've found my answer. I mistakenly thought only the VA had to be aligned to the block size (2M for example), but that the PA could be aligned to the granularity (4K). For example, I mistakenly believed that a 2MB entry such as 0x43897649 would map from [0x43897000, 0x43A97000), which is 2MB aligned to a 4K boundary. This is not how the MMU operates. It does not add to the base address, it takes the least N sig-bits and "copies" them directly to the output address.