Overview
In this article, only first stage address translation is discussed.
Memory layout
AArch64 allowing 39-bit (512GB) or 48-bit (256TB) virtual addresses,respectively, for both user and kernel. Assume virtual address space is 48-bit, user addresses have bits [63:48] set to 0 while the kernel addresses have the same bits set to 1. TTBRx selection is given by bit 63 of the virtual address, thus, memory layout is show as following figure.
Below is the composition of virtual address.
Index bits | 9 | 9 | 9 | 9 | 12 |
---|---|---|---|---|---|
Entries in page table | 512 | 512 | 512 | 512 | offset |
Address translation using translation tables is shown in the following figure:
TTBR1_EL1 register store the value of swapper_pg_dir.
AArch64 descriptor format
The AArch64 descriptor format is used in all levels of table, from Level 0 to Level 3. Level 0 descriptors can only output the address of a Level 1 table. Level 3 descriptors cannot point to another table and can only output block addresses. The format of the table is therefore slightly different for Level 3.
The following figure shows that the table descriptor type is identified by bits 1:0 of the entry and can refer to either(Below figure is a little bit confused, actually Table descriptor is a abstract name of Block entry, Table entry, Invalid entry):
- The address of a next level table, in which case memory can be further subdivided into smaller blocks.
- The address of a variable sized block of memory.
- Table entries, which can be marked Fault, or Invalid.
Block descriptor means the virtual address is translated by variable sized block memory, such as 1G, 2M.
Translation flow
Because of AArch64 is a 64 bit system, and 8 bytes alignment, [2:0] bits is 0.
Here is an example:
/*
* Macro to create a table entry to the next page.
*
* tbl: page table address
* virt: virtual address
* shift: #imm page table shift
* ptrs: #imm pointers per table page
*
* Preserves: virt
* Corrupts: tmp1, tmp2
* Returns: tbl -> next level table page address
*/
.macro create_table_entry, tbl, virt, shift, ptrs, tmp1, tmp2
lsr \tmp1, \virt, #\shift
and \tmp1, \tmp1, #\ptrs - 1 // table index
add \tmp2, \tbl, #PAGE_SIZE
orr \tmp2, \tmp2, #PMD_TYPE_TABLE // address of next table and entry type
str \tmp2, [\tbl, \tmp1, lsl #3]
add \tbl, \tbl, #PAGE_SIZE // next level table page
.endm
/*example*/
create_table_entry \tbl, \virt, PGDIR_SHIFT, PTRS_PER_PGD, \tmp1, \tmp2
Reference:
- ARM® Architecture Reference Manual ARMv8, for ARMv8-A architecture profile
- ARMv8-A Address Translation Version 1.0
- Documentation/arm64/memory.txt