From 3ea041e4d989c74b3a72cf386034a22218e80013 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ciro=20Santilli=20=E5=85=AD=E5=9B=9B=E4=BA=8B=E4=BB=B6=20?= =?UTF-8?q?=E6=B3=95=E8=BD=AE=E5=8A=9F?= Date: Thu, 18 Jul 2019 00:00:00 +0000 Subject: [PATCH] arm: start documenting paging --- README.adoc | 20 ++++++++++++++++++++ baremetal/arch/aarch64/dump_regs.c | 14 ++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/README.adoc b/README.adoc index ed86d4b..23dddd0 100644 --- a/README.adoc +++ b/README.adoc @@ -15096,6 +15096,26 @@ Bibliography: * https://stackoverflow.com/questions/51094092/how-to-make-timer-irq-work-on-qemu-machine-virt-cpu-cortex-a57 * https://stackoverflow.com/questions/44198483/arm-timers-and-interrupts +==== ARM paging + +TODO create a minimal working aarch64 example analogous to the x86 one at: https://github.com/cirosantilli/x86-bare-metal-examples/blob/6dc9a73830fc05358d8d66128f740ef9906f7677/paging.S + +A general introduction to paging with x86 examples can be found at: https://cirosantilli.com/x86-paging[]. + +ARM paging is documented at <> Chapter D5 and is mostly called VMSAv8 in the ARMv8 manual (Virtual Memory System Architecture). + +Paging is enabled by the `SCTLR_EL1.M` bit. + +The base table address is selected by the register documented at <> D12.2.111 "TTBR0_EL1, Translation Table Base Register 0 (EL1)". + +There is also a `TTBR1_EL1` register, which is for the second translation stage to speed up virtualization: https://en.wikipedia.org/wiki/Second_Level_Address_Translation and will not be used in this section. + +The translation types are described at: <> D5.2.4 "Memory translation granule size". + +From this we can see that the translation scheme uses up to 4 levels (0 to 3) and has possible granule sizes 4KiB, 16KiB and 64KiB. + +Page table formats are described at <> D5.3.1 "VMSAv8-64 translation table level 0, level 1, and level 2 descriptor formats". + ==== ARM baremetal bibliography First, also consider the userland bibliography: <>. diff --git a/baremetal/arch/aarch64/dump_regs.c b/baremetal/arch/aarch64/dump_regs.c index 0ca116a..d9ab7ca 100644 --- a/baremetal/arch/aarch64/dump_regs.c +++ b/baremetal/arch/aarch64/dump_regs.c @@ -8,11 +8,25 @@ int main(void) { __asm__ ("mrs %0, sctlr_el1" : "=r" (sctlr_el1) : :); printf("SCTLR_EL1 0x%" PRIX32 "\n", sctlr_el1); printf("SCTLR_EL1.A 0x%" PRIX32 "\n", (sctlr_el1 >> 1) & 1); + /* https://cirosantilli.com/linux-kernel-module-cheat#arm-paging */ + printf("SCTLR_EL1.M 0x%" PRIX32 "\n", (sctlr_el1 >> 0) & 1); uint64_t CurrentEL; __asm__ ("mrs %0, CurrentEL;" : "=r" (CurrentEL) : :); printf("CurrentEL 0x%" PRIX64 "\n", CurrentEL); /* https://cirosantilli.com/linux-kernel-module-cheat#arm-exception-levels */ printf("CurrentEL.EL 0x%" PRIX64 "\n", CurrentEL >> 2); + + /* https://cirosantilli.com/linux-kernel-module-cheat#arm-paging */ + { + uint64_t tcr_el1; + __asm__ ("mrs %0, tcr_el1;" : "=r" (tcr_el1) : :); + printf("TCR_EL1 0x%" PRIX64 "\n", tcr_el1); + + uint64_t ttbr0_el1; + __asm__ ("mrs %0, ttbr0_el1;" : "=r" (ttbr0_el1) : :); + printf("TTBR0_EL1 0x%" PRIX64 "\n", ttbr0_el1); + } + return 0; }