[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Minios-devel] [UNIKRAFT PATCHv6 19/37] plat/kvm: Enable MMU for Arm64
From: Wei Chen <Wei.Chen@xxxxxxx> QEMU/KVM provides a 1TB physical address for Arm64. In this case, we should use 40-bit virtual address to map physical address. In this patch, we enable the MMU to access memory with virtual address. Signed-off-by: Wei Chen <Wei.Chen@xxxxxxx> --- plat/common/include/arm/arm64/cpu_defs.h | 134 +++++++++++++++++++++++ plat/kvm/arm/entry64.S | 25 ++++- plat/kvm/arm/pagetable.S | 60 ++++++++++ 3 files changed, 218 insertions(+), 1 deletion(-) diff --git a/plat/common/include/arm/arm64/cpu_defs.h b/plat/common/include/arm/arm64/cpu_defs.h index 3d78647..71ba307 100644 --- a/plat/common/include/arm/arm64/cpu_defs.h +++ b/plat/common/include/arm/arm64/cpu_defs.h @@ -34,6 +34,13 @@ #ifndef __CPU_ARM_64_DEFS_H__ #define __CPU_ARM_64_DEFS_H__ +/* + * The supported virtual address bits. + * We will do 1:1 VA to PA Mapping, so we define the same address size + * for VA and PA. 1TB size for Virtual and Physical Address Space. + */ +#define VIRT_BITS 40 + /* * CTR_EL0, Cache Type Register * Provides information about the architecture of the caches. @@ -43,6 +50,24 @@ #define CTR_IMINLINE_MASK 0xf #define CTR_BYTES_PER_WORD 4 +/* Registers and Bits definitions for MMU */ +/* MAIR_EL1 - Memory Attribute Indirection Register */ +#define MAIR_ATTR_MASK(idx) (0xff << ((n)* 8)) +#define MAIR_ATTR(attr, idx) ((attr) << ((idx) * 8)) + +/* Device-nGnRnE memory */ +#define MAIR_DEVICE_nGnRnE 0x00 +/* Device-nGnRE memory */ +#define MAIR_DEVICE_nGnRE 0x04 +/* Device-GRE memory */ +#define MAIR_DEVICE_GRE 0x0C +/* Outer Non-cacheable + Inner Non-cacheable */ +#define MAIR_NORMAL_NC 0x44 +/* Outer + Inner Write-through non-transient */ +#define MAIR_NORMAL_WT 0xbb +/* Outer + Inner Write-back non-transient */ +#define MAIR_NORMAL_WB 0xff + /* * Memory types, these values are the indexs of the attributes * that defined in MAIR_EL1. @@ -54,6 +79,115 @@ #define NORMAL_WT 4 #define NORMAL_WB 5 +#define MAIR_INIT_ATTR \ + (MAIR_ATTR(MAIR_DEVICE_nGnRnE, DEVICE_nGnRnE) | \ + MAIR_ATTR(MAIR_DEVICE_nGnRE, DEVICE_nGnRE) | \ + MAIR_ATTR(MAIR_DEVICE_GRE, DEVICE_GRE) | \ + MAIR_ATTR(MAIR_NORMAL_NC, NORMAL_NC) | \ + MAIR_ATTR(MAIR_NORMAL_WB, NORMAL_WT) | \ + MAIR_ATTR(MAIR_NORMAL_WT, NORMAL_WB)) + +/* TCR_EL1 - Translation Control Register */ +#define TCR_ASID_16 (1 << 36) + +#define TCR_IPS_SHIFT 32 +#define TCR_IPS_32BIT (0 << TCR_IPS_SHIFT) +#define TCR_IPS_36BIT (1 << TCR_IPS_SHIFT) +#define TCR_IPS_40BIT (2 << TCR_IPS_SHIFT) +#define TCR_IPS_42BIT (3 << TCR_IPS_SHIFT) +#define TCR_IPS_44BIT (4 << TCR_IPS_SHIFT) +#define TCR_IPS_48BIT (5 << TCR_IPS_SHIFT) + +#define TCR_TG1_SHIFT 30 +#define TCR_TG1_16K (1 << TCR_TG1_SHIFT) +#define TCR_TG1_4K (2 << TCR_TG1_SHIFT) +#define TCR_TG1_64K (3 << TCR_TG1_SHIFT) + +#define TCR_TG0_SHIFT 14 +#define TCR_TG0_4K (0 << TCR_TG0_SHIFT) +#define TCR_TG0_64K (1 << TCR_TG0_SHIFT) +#define TCR_TG0_16K (2 << TCR_TG0_SHIFT) + +#define TCR_SH1_SHIFT 28 +#define TCR_SH1_IS (0x3 << TCR_SH1_SHIFT) +#define TCR_ORGN1_SHIFT 26 +#define TCR_ORGN1_WBWA (0x1 << TCR_ORGN1_SHIFT) +#define TCR_IRGN1_SHIFT 24 +#define TCR_IRGN1_WBWA (0x1 << TCR_IRGN1_SHIFT) +#define TCR_SH0_SHIFT 12 +#define TCR_SH0_IS (0x3 << TCR_SH0_SHIFT) +#define TCR_ORGN0_SHIFT 10 +#define TCR_ORGN0_WBWA (0x1 << TCR_ORGN0_SHIFT) +#define TCR_IRGN0_SHIFT 8 +#define TCR_IRGN0_WBWA (0x1 << TCR_IRGN0_SHIFT) + +#define TCR_CACHE_ATTRS ((TCR_IRGN0_WBWA | TCR_IRGN1_WBWA) | \ + (TCR_ORGN0_WBWA | TCR_ORGN1_WBWA)) + +#define TCR_SMP_ATTRS (TCR_SH0_IS | TCR_SH1_IS) + +#define TCR_T1SZ_SHIFT 16 +#define TCR_T0SZ_SHIFT 0 +#define TCR_T1SZ(x) ((x) << TCR_T1SZ_SHIFT) +#define TCR_T0SZ(x) ((x) << TCR_T0SZ_SHIFT) +#define TCR_TxSZ(x) (TCR_T1SZ(x) | TCR_T0SZ(x)) + +#define TCR_INIT_FLAGS (TCR_TxSZ(64 - VIRT_BITS) | TCR_ASID_16 | \ + TCR_TG0_4K | TCR_CACHE_ATTRS | TCR_SMP_ATTRS) + +/* SCTLR_EL1 - System Control Register */ +#define SCTLR_M (_AC(1, UL) << 0) /* MMU enable */ +#define SCTLR_A (_AC(1, UL) << 1) /* Alignment check enable */ +#define SCTLR_C (_AC(1, UL) << 2) /* Data/unified cache enable */ +#define SCTLR_SA (_AC(1, UL) << 3) /* Stack alignment check enable */ +#define SCTLR_SA0 (_AC(1, UL) << 4) /* Stack Alignment Check Enable for EL0 */ +#define SCTLR_CP15BEN (_AC(1, UL) << 5) /* System instruction memory barrier enable */ +#define SCTLR_ITD (_AC(1, UL) << 7) /* IT disable */ +#define SCTLR_SED (_AC(1, UL) << 8) /* SETEND instruction disable */ +#define SCTLR_UMA (_AC(1, UL) << 9) /* User mask access */ +#define SCTLR_I (_AC(1, UL) << 12) /* Instruction access Cacheability control */ +#define SCTLR_DZE (_AC(1, UL) << 14) /* Traps EL0 DC ZVA instructions to EL1 */ +#define SCTLR_UCT (_AC(1, UL) << 15) /* Traps EL0 accesses to the CTR_EL0 to EL1 */ +#define SCTLR_nTWI (_AC(1, UL) << 16) /* Don't trap EL0 WFI to EL1 */ +#define SCTLR_nTWE (_AC(1, UL) << 18) /* Don't trap EL0 WFE to EL1 */ +#define SCTLR_WXN (_AC(1, UL) << 19) /* Write permission implies XN */ +#define SCTLR_EOE (_AC(1, UL) << 24) /* Endianness of data accesses at EL0 */ +#define SCTLR_EE (_AC(1, UL) << 25) /* Endianness of data accesses at EL1 */ +#define SCTLR_UCI (_AC(1, UL) << 26) /* Traps EL0 cache instructions to EL1 */ + +/* Reserve to 1 */ +#define SCTLR_RES1_B11 (_AC(1, UL) << 11) +#define SCTLR_RES1_B20 (_AC(1, UL) << 20) +#define SCTLR_RES1_B22 (_AC(1, UL) << 22) +#define SCTLR_RES1_B23 (_AC(1, UL) << 23) +#define SCTLR_RES1_B28 (_AC(1, UL) << 28) +#define SCTLR_RES1_B29 (_AC(1, UL) << 29) + +/* Reserve to 0 */ +#define SCTLR_RES0_B6 (_AC(1, UL) << 6) +#define SCTLR_RES0_B10 (_AC(1, UL) << 10) +#define SCTLR_RES0_B13 (_AC(1, UL) << 13) +#define SCTLR_RES0_B17 (_AC(1, UL) << 17) +#define SCTLR_RES0_B21 (_AC(1, UL) << 21) +#define SCTLR_RES0_B27 (_AC(1, UL) << 27) +#define SCTLR_RES0_B30 (_AC(1, UL) << 30) +#define SCTLR_RES0_B31 (_AC(1, UL) << 31) + +/* Bits to set */ +#define SCTLR_SET_BITS \ + (SCTLR_UCI | SCTLR_nTWE | SCTLR_nTWI | SCTLR_UCT | \ + SCTLR_DZE | SCTLR_I | SCTLR_SED | SCTLR_SA0 | SCTLR_SA | \ + SCTLR_C | SCTLR_M | SCTLR_CP15BEN | SCTLR_RES1_B11 | \ + SCTLR_RES1_B20 | SCTLR_RES1_B22 | SCTLR_RES1_B23 | \ + SCTLR_RES1_B28 | SCTLR_RES1_B29) + +/* Bits to clear */ +#define SCTLR_CLEAR_BITS \ + (SCTLR_EE | SCTLR_EOE | SCTLR_WXN | SCTLR_UMA | \ + SCTLR_ITD | SCTLR_A | SCTLR_RES0_B6 | SCTLR_RES0_B10 | \ + SCTLR_RES0_B13 | SCTLR_RES0_B17 | SCTLR_RES0_B21 | \ + SCTLR_RES0_B27 | SCTLR_RES0_B30 | SCTLR_RES0_B31) + /* * Definitions for Block and Page descriptor attributes */ diff --git a/plat/kvm/arm/entry64.S b/plat/kvm/arm/entry64.S index 2aecbec..850b7e8 100644 --- a/plat/kvm/arm/entry64.S +++ b/plat/kvm/arm/entry64.S @@ -34,6 +34,7 @@ #include <uk/arch/limits.h> #include <uk/asm.h> #include <kvm-arm/mm.h> +#include <arm/cpu_defs.h> /* * The registers used by _libkvmplat_start: @@ -63,10 +64,32 @@ ENTRY(_libkvmplat_entry) mov sp, x27 - /* Setup excetpion vector table address before enable MMU */ + /* + * Disable the MMU. We may have entered the kernel with it on and + * will need to update the tables later. If this has been set up + * with anything other than a VA == PA map then this will fail, + * but in this case the code to find where we are running from + * would have also failed. + */ + dsb sy + mrs x2, sctlr_el1 + bic x2, x2, #SCTLR_M + msr sctlr_el1, x2 + isb + + /* Set the context id */ + msr contextidr_el1, xzr + + /* Create a pagetable to do PA == VA mapping */ + bl create_pagetables + + /* Setup exception vector table address before enable MMU */ ldr x29, =vector_table msr VBAR_EL1, x29 + /* Enable the mmu */ + bl start_mmu + /* Load dtb address to x0 as a parameter */ ldr x0, =_dtb b _libkvmplat_start diff --git a/plat/kvm/arm/pagetable.S b/plat/kvm/arm/pagetable.S index e876195..9120c4e 100644 --- a/plat/kvm/arm/pagetable.S +++ b/plat/kvm/arm/pagetable.S @@ -188,6 +188,66 @@ ENTRY(create_pagetables) ret END(create_pagetables) +ENTRY(start_mmu) + /* + * Using dsb here to guarantee the create_pagetables has + * been done. + */ + dsb sy + + /* Load ttbr0, pagetable starts from _end */ + ldr x27, =_end + msr ttbr0_el1, x27 + isb + + /* Clear the Monitor Debug System control register */ + msr mdscr_el1, xzr + + /* Invalidate the TLB to avoid stale one */ + tlbi vmalle1 + dsb nsh + + ldr x2, =MAIR_INIT_ATTR + msr mair_el1, x2 + + /* + * Setup TCR according to PARange bits from ID_AA64MMFR0_EL1. + */ + ldr x2, =TCR_INIT_FLAGS + mrs x3, id_aa64mmfr0_el1 + bfi x2, x3, #32, #3 + msr tcr_el1, x2 + + /* save lr */ + mov x22, x30 + + /* + * Invalidate the I/D cache to avoid using invalid data that existed + * in I/D cache. Invalidate ranges: DTB, TEXT, DATA, BSS, PAGETABLE + * and BOOTSTACK. + */ + ldr x0, =_dtb + ldr x1, =_end + add x1, x1, #PAGE_TABLE_SIZE + add x1, x1, #__STACK_SIZE + sub x1, x1, x0 + bl invalidate_idcache_range + + /* Setup SCTLR */ + ldr x2, =SCTLR_SET_BITS + ldr x3, =SCTLR_CLEAR_BITS + mrs x1, sctlr_el1 + bic x1, x1, x3 /* Clear the required bits */ + orr x1, x1, x2 /* Set the required bits */ + msr sctlr_el1, x1 + isb + + /* restore lr */ + mov x30, x22 + + ret +END(start_mmu) + /* * Builds an L0 -> L1 table descriptor * -- 2.17.1 _______________________________________________ Minios-devel mailing list Minios-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/mailman/listinfo/minios-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |