[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Minios-devel] [PATCH 03/40] arm64: add the boot code
This patch adds the boot code for arm64: 0.) add the header which contains all the macros to setup the page table 1.) init the MAIR/TCR for 39 bit virtual address. 2.) setup the page table. 3.) enable the MMU This patch refers to Chen Baozi's patch: "Initial codes for arm64" Change-Id: I5371640c3f58d2659b31a1009352fdb7b1b02833 Jira: ENTOS-247 Signed-off-by: Huang Shijie <shijie.huang@xxxxxxx> --- arch/arm/arm64/arm64.S | 307 ++++++++++++++++++++++++++++++++++++++++++ arch/arm/arm64/asm.h | 18 +++ include/arm/arm64/pagetable.h | 106 +++++++++++++++ 3 files changed, 431 insertions(+) create mode 100644 arch/arm/arm64/arm64.S create mode 100644 arch/arm/arm64/asm.h create mode 100644 include/arm/arm64/pagetable.h diff --git a/arch/arm/arm64/arm64.S b/arch/arm/arm64/arm64.S new file mode 100644 index 0000000..61c14a6 --- /dev/null +++ b/arch/arm/arm64/arm64.S @@ -0,0 +1,307 @@ +#include "asm.h" +#include <arm64/pagetable.h> +#include <xen/xen.h> + +/* This macro will use the x0/x1/x2/x16 */ +#define PRINT(_s) \ + adr x2, 97f; \ + adr x1, 98f; \ + sub x1, x1, x2; \ + mov x0, #CONSOLEIO_write; \ + mov x16, #__HYPERVISOR_console_io; \ + hvc #XEN_HYPERCALL_TAG; \ + b 99f; \ +97: .asciz _s; \ +98: ; \ + .align 2; \ +99: \ + + .macro mem_clear, addr, len + adr x0, \addr + add x1, x0, \len +1: stp xzr, xzr, [x0], #16 + stp xzr, xzr, [x0], #16 + stp xzr, xzr, [x0], #16 + stp xzr, xzr, [x0], #16 + cmp x0, x1 + b.lo 1b + .endm + + .data + .globl _boot_stack + .globl boot_l1_pgtable, boot_l2_pgtable, boot_l2_pgtable1 + .globl idmap_pgtable + + .align 12 +boot_l1_pgtable: + .space PAGE_SIZE +boot_l2_pgtable: + .space PAGE_SIZE +boot_l2_pgtable1: + .space PAGE_SIZE +idmap_pgtable: + .space PAGE_SIZE + + .align 12 +_boot_stack: + .space (4 * PAGE_SIZE) +stack_end: + +/* + * Kernel startup entry point. + * + * Please refer to kernel file Documentation/arm64/booting.txt + * for the header format. + */ + .text + + b _start /* branch to kernel start, magic */ + .long 0 /* reserved */ + .quad 0x0 /* Image load offset from start of RAM */ + .quad _end - _start /* Effective Image size */ + .quad 2 /* kernel flages: LE, 4K page size */ + .quad 0 /* reserved */ + .quad 0 /* reserved */ + .quad 0 /* reserved */ + .byte 0x41 /* Magic number, "ARM\x64" */ + .byte 0x52 + .byte 0x4d + .byte 0x64 + .long 0 /* reserved */ + +/* + * Primary CPU general-purpose register settings + * x0 = physical address of device tree blob (dtb) in system RAM. + * x1 = 0 (reserved for future use) + * x2 = 0 (reserved for future use) + * x3 = 0 (reserved for future use) + * + * The registers used by _start: + * x20 - FDT pointer + * x22 - offset between PA and VA + */ +ENTRY(_start) + /* Save the FDT pointer */ + mov x20, x0 + + /* Calculate where we are */ + bl _calc_offset + + PRINT("- Mini-OS booting -\n") + + PRINT("- Setup CPU -\n") + /* Setup CPU for turning on the MMU. */ + bl _setup_cpu + + PRINT("- Setup booting pagetable -\n") + /* Setup the initial page table. */ + bl _setup_initial_pgtable + + /* Setup the identity mapping */ + bl _setup_idmap_pgtable + + /* Load TTBRx */ + msr ttbr1_el1, x4 + msr ttbr0_el1, x5 + isb + + /* Turning on MMU */ + tlbi vmalle1 + dsb nsh + isb + ldr x1, =(SCTLR_M | SCTLR_C | SCTLR_I) + msr sctlr_el1, x1 + isb + + PRINT("- MMU on -\n") + ldr x0, =mmu_on + br x0 + +mmu_on: + /* Setup stack */ + PRINT("- Setup stack -\n") + mem_clear _boot_stack,#(4*PAGE_SIZE) + + ldr x1, =stack_end + mov sp, x1 + + PRINT("- Jumping to C entry -\n") + add x20, x20, x22 + mov x0, x20 /* x0 <- device tree (virtual address) */ + mov x1, x22 /* x1 <- phys_offset */ + + b arch_init +ENDPROC(_start) + +/* + * Get the phys-offset, and save it in x22 + */ +ENTRY(_calc_offset) + ldr x22, =_start /* x0 := vaddr(_start) */ + adr x21, _start /* x21 := paddr(_start) */ + sub x22, x22, x21 /* x22 := phys-offset (vaddr - paddr) */ + ret +ENDPROC(_calc_offset) + +/* + * Setup the memory region attribute; + * Setup the TCR. + */ +ENTRY(_setup_cpu) + /* + * Setup memory attribute type tables + * + * Memory region attributes for LPAE: + * + * n = AttrIndx[2:0] + * n MAIR + * DEVICE_nGnRnE 000 00000000 (0x00) + * DEVICE_nGnRE 001 00000100 (0x04) + * DEVICE_GRE 010 00001100 (0x0c) + * NORMAL_NC 011 01000100 (0x44) + * NORMAL 100 11111111 (0xff) + */ + ldr x0, =(SET_MAIR(0x00, MEM_DEVICE_nGnRnE) | \ + SET_MAIR(0x04, MEM_DEVICE_nGnRE) | \ + SET_MAIR(0x0c, MEM_DEVICE_GRE) | \ + SET_MAIR(0x44, MEM_NORMAL_NC) | \ + SET_MAIR(0xff, MEM_NORMAL)) + msr mair_el1, x0 + + /* + * Setup translation control register (TCR) + */ + ldr x0, =(TCR_TxSZ(VA_BITS) | TCR_ASID16 | TCR_TG1_4K | TCR_FLAGS ) + msr tcr_el1, x0 + + ret +ENDPROC(_setup_cpu) + + +/* + * Setup the mapping for code section and device tree + * + * => x20 = device tree address + * <= x4 -> for TTBR1_EL1 + */ +ENTRY(_setup_initial_pgtable) + /* Clear page tables */ + mem_clear boot_l1_pgtable,#PAGE_SIZE + mem_clear boot_l2_pgtable,#PAGE_SIZE + mem_clear boot_l2_pgtable1,#PAGE_SIZE + + adr x4, boot_l1_pgtable /* x4 := paddr (boot_l1_pgtable) */ + adr x5, boot_l2_pgtable /* x5 := paddr (boot_l2_pgtable) */ + + /* Find the size of the kernel */ + ldr x0, =_text /* x0 := vaddr(_text) */ + ldr x1, =_end /* x1 := vaddr(_end) */ + sub x2, x1, x0 + /* Get the number of l2 pages to allocate, rounded down */ + lsr x2, x2, #L2_SHIFT + /* Add 2 MiB for rounding above */ + add x2, x2, #1 /* x2 := total number of entries */ + + /* Find the table index */ + lsr x3, x0, #L2_SHIFT /* L2_SHIFT = 21 */ + and x3, x3, #Ln_ADDR_MASK /* x3 := index of l2 table */ + + + /* Build the L2 block entries */ + sub x6, x0, x22 /* x6 := paddr(_text) */ + lsr x6, x6, #L2_SHIFT /* L2_SHIFT = 21 */ + mov x7, #PT_MEM +1: orr x7, x7, x6, lsl #L2_SHIFT /* x7 := l2 pgtbl entry content */ + + /* Store the entry */ + str x7, [x5, x3, lsl #3] + + /* Clear the address bits */ + and x7, x7, #ATTR_MASK_L + + sub x2, x2, #1 + add x3, x3, #1 + add x6, x6, #1 + cbnz x2, 1b + + /* Link the l1 -> l2 table */ + /* Find the table index */ + lsr x3, x0, #L1_SHIFT + and x3, x3, #Ln_ADDR_MASK /* x3 := index of l1 table */ + + /* Build the L1 page table entry */ + ldr x7, =PT_PT + lsr x9, x5, #12 + orr x7, x7, x9, lsl #12 + + /* Store the L1 entry */ + str x7, [x4, x3, lsl #3] + + /* Start to map the Device-Tree */ + lsr x3, x20, #L1_SHIFT + and x3, x3, #Ln_ADDR_MASK /* x3 := index of l1 table */ + ldr x0, [x4, x3, lsl #3] + cbz x0, 2f + + /* Setup the new l2 page table */ + ldr x7, =PT_PT + adr x6, boot_l2_pgtable1 + lsr x9, x6, #12 + orr x7, x7, x9, lsl #12 + + /* Store the L1 entry */ + str x7, [x4, x3, lsl #3] + + mov x5, x6 +2: + mov x8, x5 /* x8 := the l2 page table */ + + lsr x3, x20, #L2_SHIFT + and x3, x3, #Ln_ADDR_MASK /* x3 := index of l2 table */ + + /* Build the L2 block entries */ + mov x6, x20 + lsr x6, x6, #L2_SHIFT + mov x7, #PT_MEM + orr x7, x7, x6, lsl #L2_SHIFT /* x7 := l2 pgtbl entry content */ + + /* Store the entry */ + str x7, [x8, x3, lsl #3] + + dsb sy + ret +ENDPROC(_setup_initial_pgtable) + +/* + * Setup the page table for TTBR0_EL1: + * Mapping the page table for the code section. + * We use 39bit address, and just use level 1 + * for the mapping (we do not use level 0, level 2 and level 3). + * + * => none + * <= x5 : save the page table pointer for TTBR0_EL1. + */ +ENTRY(_setup_idmap_pgtable) + /* Clear identity mapping page table */ + mem_clear idmap_pgtable,#PAGE_SIZE + + adr x5, idmap_pgtable + + /* Create the VA = PA map */ + adr x6, _text + + /* Find the table index */ + lsr x0, x6, #L1_SHIFT + and x0, x0, #Ln_ADDR_MASK /* x0 := index of l1 table */ + + /* Build the L1 block entry */ + ldr x1, =PT_MEM + lsr x2, x6, #L1_SHIFT + orr x1, x1, x2, lsl #L1_SHIFT + + /* Store the entry */ + str x1, [x5, x0, lsl #3] + + dsb sy + ret +ENDPROC(_setup_idmap_pgtable) diff --git a/arch/arm/arm64/asm.h b/arch/arm/arm64/asm.h new file mode 100644 index 0000000..3a498c4 --- /dev/null +++ b/arch/arm/arm64/asm.h @@ -0,0 +1,18 @@ +#ifndef __ASM_H__ +#define __ASM_H__ + +#define ALIGN .align 4 + +#define ENTRY(name) \ + .globl name; \ + ALIGN; \ + name: + +#define END(name) \ + .size name, .-name + +#define ENDPROC(name) \ + .type name, @function; \ + END(name) + +#endif /* __ASM_H__ */ diff --git a/include/arm/arm64/pagetable.h b/include/arm/arm64/pagetable.h new file mode 100644 index 0000000..1e3a472 --- /dev/null +++ b/include/arm/arm64/pagetable.h @@ -0,0 +1,106 @@ +#ifndef __ARM64_PAGE_TABLE__ + +#define __ARM64_PAGE_TABLE__ + +/* TCR flags */ +#define TCR_TxSZ(x) ((((64) - (x)) << 16) | (((64) - (x)) << 0)) +#define TCR_IRGN_WBWA (((1) << 8) | ((1) << 24)) +#define TCR_ORGN_WBWA (((1) << 10) | ((1) << 26)) +#define TCR_SHARED (((3) << 12) | ((3) << 28)) +#define TCR_ASID16 ((1) << 36) +#define TCR_IPS_40BIT ((2) << 32) +#define TCR_TG1_4K ((2) << 30) + +#define TCR_FLAGS (TCR_IRGN_WBWA | TCR_ORGN_WBWA | TCR_SHARED | TCR_IPS_40BIT) + +/* Number of virtual address bits */ +#define VA_BITS 39 + +/* + * Memory types available. + */ +#define MEM_DEVICE_nGnRnE 0 +#define MEM_DEVICE_nGnRE 1 +#define MEM_DEVICE_GRE 2 +#define MEM_NORMAL_NC 3 +#define MEM_NORMAL 4 + +#define SET_MAIR(attr, mt) ((attr) << ((mt) * 8)) + +/* SCTLR_EL1 - System Control Register */ +#define SCTLR_M 0x00000001 +#define SCTLR_C 0x00000004 +#define SCTLR_I 0x00001000 + +/* Level 0 table, 512GiB per entry */ +#define L0_SHIFT 39 +#define L0_INVAL 0x0 /* An invalid address */ +#define L0_TABLE 0x3 /* A next-level table */ + +/* Level 1 table, 1GiB per entry */ +#define L1_SHIFT 30 +#define L1_SIZE (1 << L1_SHIFT) +#define L1_OFFSET (L1_SIZE - 1) +#define L1_INVAL L0_INVAL +#define L1_BLOCK 0x1 +#define L1_TABLE L0_TABLE +#define L1_MASK (~(L1_SIZE-1)) + +/* Level 2 table, 2MiB per entry */ +#define L2_SHIFT 21 +#define L2_SIZE (1 << L2_SHIFT) +#define L2_OFFSET (L2_SIZE - 1) +#define L2_INVAL L0_INVAL +#define L2_BLOCK L1_BLOCK +#define L2_TABLE L0_TABLE +#define L2_MASK (~(L2_SIZE-1)) + +/* Level 3 table, 4KiB per entry */ +#define L3_SHIFT 12 +#define L3_SIZE (1 << L3_SHIFT) +#define L3_OFFSET (L3_SIZE - 1) +#define L3_INVAL 0x0 +#define L3_PAGE 0x3 +#define L3_MASK (~(L3_SIZE-1)) + +#define Ln_ENTRIES (1 << 9) +#define Ln_ADDR_MASK (Ln_ENTRIES - 1) + +#define ATTR_MASK_L 0xfff + +#define l1_pgt_idx(va) (((va) >> L1_SHIFT) & Ln_ADDR_MASK) +#define l2_pgt_idx(va) (((va) >> L2_SHIFT) & Ln_ADDR_MASK) +#define l3_pgt_idx(va) (((va) >> L3_SHIFT) & Ln_ADDR_MASK) + +/* + * Lower attributes fields in Stage 1 VMSAv8-A Block and Page descriptor + */ +#define ATTR_nG (1 << 11) +#define ATTR_AF (1 << 10) +#define ATTR_SH(x) ((x) << 8) +#define ATTR_SH_MASK ATTR_SH(3) +#define ATTR_SH_NS 0 /* Non-shareable */ +#define ATTR_SH_OS 2 /* Outer-shareable */ +#define ATTR_SH_IS 3 /* Inner-shareable */ +#define ATTR_AP_RW_BIT (1 << 7) +#define ATTR_AP(x) ((x) << 6) +#define ATTR_AP_MASK ATTR_AP(3) +#define ATTR_AP_RW (0 << 1) +#define ATTR_AP_RO (1 << 1) +#define ATTR_AP_USER (1 << 0) +#define ATTR_NS (1 << 5) +#define ATTR_IDX(x) ((x) << 2) +#define ATTR_IDX_MASK (7 << 2) + +#define BLOCK_DEF_ATTR (ATTR_AF|ATTR_SH(ATTR_SH_IS)|ATTR_IDX(MEM_NORMAL)) +#define BLOCK_NC_ATTR (ATTR_AF|ATTR_SH(ATTR_SH_IS)|ATTR_IDX(MEM_NORMAL_NC)) +#define BLOCK_DEV_ATTR (ATTR_AF|ATTR_SH(ATTR_SH_IS)|ATTR_IDX(MEM_DEVICE_nGnRnE)) + +#define PT_PT (L0_TABLE) +#define PT_MEM (BLOCK_DEF_ATTR | L1_BLOCK) + +#ifndef PAGE_SIZE +#define PAGE_SIZE L3_SIZE +#endif + +#endif -- 2.7.4 _______________________________________________ Minios-devel mailing list Minios-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/cgi-bin/mailman/listinfo/minios-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |