mmu.c (2751B)
1 /* aarch64 stage-1 MMU setup for QEMU virt. */ 2 3 typedef unsigned long u64; 4 typedef unsigned int u32; 5 typedef unsigned char u8; 6 7 #include "arch.h" 8 9 __attribute__((aligned(4096))) static u64 l1_pt[512]; 10 __attribute__((aligned(4096))) static u64 l2_user[512]; 11 12 static u64 pool_pa(int which) { 13 return which ? ARCH_USER_POOL_B_PA : ARCH_USER_POOL_A_PA; 14 } 15 16 void arch_setup_mmu(void) { 17 /* Block-descriptor attribute bits (block at L1 = bit[1]=0). 18 * V(0)=1, block(1)=0, AttrIdx[4:2]=Attr0(Normal)/Attr1(Device), 19 * NS(5)=0, AP[7:6]=00 (RW EL1 only), SH[9:8]=11 (ISH), AF(10)=1, 20 * nG(11)=0 -> 0x701 (Normal) / 0x705 (Device-nGnRnE). 21 * Block descriptors at L2 use the same bit layout. */ 22 u64 normal = 0x701; 23 u64 device = 0x705; 24 25 for (int i = 0; i < 512; i++) l1_pt[i] = 0; 26 27 l2_user[0] = 0; 28 for (int i = ARCH_USER_POOL_FIRST_SLOT; i <= ARCH_USER_POOL_LAST_SLOT; i++) { 29 u64 pa = ARCH_USER_POOL_A_PA + (u64)(i - ARCH_USER_POOL_FIRST_SLOT) * 0x200000UL; 30 l2_user[i] = pa | normal; 31 } 32 for (int i = ARCH_USER_POOL_LAST_SLOT + 1; i < 512; i++) { 33 u64 pa = (u64)i * 0x200000UL; 34 l2_user[i] = pa | device; 35 } 36 37 l1_pt[0] = (u64)l2_user | 0x3UL; 38 l1_pt[1] = 0x40000000UL | normal; 39 l1_pt[2] = 0x80000000UL | normal; 40 l1_pt[3] = 0xc0000000UL | normal; 41 l1_pt[4] = 0x00000000UL | device; 42 43 sysreg_write(SR_MAIR_EL1, 0x00000000000000ffUL); 44 45 u64 tcr = (u64)25 /* T0SZ: 39-bit VA */ 46 | ((u64)1 << 8) /* IRGN0 = WBWA */ 47 | ((u64)1 << 10) /* ORGN0 = WBWA */ 48 | ((u64)3 << 12) /* SH0 = inner shareable */ 49 | ((u64)0 << 14) /* TG0 = 4KB */ 50 | ((u64)1 << 23) /* EPD1 = disable TTBR1 walks */ 51 | ((u64)2 << 32); /* IPS = 40-bit phys */ 52 sysreg_write(SR_TCR_EL1, tcr); 53 sysreg_write(SR_TTBR0_EL1, (u64)l1_pt); 54 55 arm64_ic_iallu(); 56 arm64_barrier(BAR_DSB_ISH); 57 arm64_tlbi_vmalle1(); 58 arm64_barrier(BAR_DSB_ISH); 59 arm64_barrier(BAR_ISB); 60 61 u64 sctlr = sysreg_read(SR_SCTLR_EL1); 62 sctlr &= ~(u64)((1 << 1) | (1 << 19)); 63 sctlr |= (u64)((1 << 0) | (1 << 2) | (1 << 12)); 64 sysreg_write(SR_SCTLR_EL1, sctlr); 65 arm64_barrier(BAR_ISB); 66 67 sysreg_write(SR_CPACR_EL1, (u64)3 << 20); 68 arm64_barrier(BAR_ISB); 69 } 70 71 void arch_swap_user_pool(int which) { 72 u64 normal = 0x701; 73 u64 base = pool_pa(which); 74 for (int i = ARCH_USER_POOL_FIRST_SLOT; i <= ARCH_USER_POOL_LAST_SLOT; i++) { 75 l2_user[i] = (base + (u64)(i - ARCH_USER_POOL_FIRST_SLOT) * 0x200000UL) | normal; 76 } 77 arm64_barrier(BAR_DSB_ISH); 78 arm64_tlbi_vmalle1(); 79 arm64_barrier(BAR_DSB_ISH); 80 arm64_barrier(BAR_ISB); 81 }