|
[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 |