[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Minios-devel] [PATCH v3 06/43] 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 48 bit virtual address. 2.) setup the page table for the code section. 3.) enable the MMU This patch refers to Chen Baozi's patch: "Initial codes for arm64" Signed-off-by: Huang Shijie <shijie.huang@xxxxxxx> --- arch/arm/arm64/arm64.S | 286 ++++++++++++++++++++++++++++++++++++++++++ arch/arm/arm64/asm.h | 18 +++ include/arm/arm64/pagetable.h | 108 ++++++++++++++++ 3 files changed, 412 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..b454cc6 --- /dev/null +++ b/arch/arm/arm64/arm64.S @@ -0,0 +1,286 @@ +#include "asm.h" +#include <arch_limits.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: \ + + .data + .globl _boot_stack + .globl boot_l0_pgtable + .globl boot_l1_pgtable + .globl boot_l2_pgtable + .globl idmap_l0_pgtable + .globl idmap_l1_pgtable + + .align 12 +boot_l0_pgtable: + .fill PAGE_SIZE,1,0 +boot_l1_pgtable: + .fill PAGE_SIZE,1,0 +boot_l2_pgtable: + .fill PAGE_SIZE,1,0 +idmap_l0_pgtable: + .fill PAGE_SIZE,1,0 +idmap_l1_pgtable: + .fill PAGE_SIZE,1,0 + + .align 12 +_boot_stack: + .fill __STACK_SIZE,1,0 +stack_end: + +/* + * Kernel startup entry point. + * + * Please refer to linux 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 flags: 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 + mov x19, x0 + + /* Setup the identity mapping */ + bl _setup_idmap_pgtable + + /* Load TTBRx */ + msr ttbr1_el1, x19 + msr ttbr0_el1, x0 + 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: + /* Do not use the TTBR0_EL1 any more */ + mrs x19, tcr_el1 + add x19, x19, TCR_EPD0 + msr tcr_el1, x19 + + /* Setup stack */ + PRINT("- Setup stack -\n") + ldr x1, =stack_end + mov sp, x1 + + PRINT("- Jumping to C entry -\n") + mov x0, x20 /* x0 <- device tree (physical address) */ + mov x1, x22 /* x1 <- phys_offset */ + + b arch_init +ENDPROC(_start) + +/* + * Get the phys-offset, and save it in x22 + */ +_calc_offset: + ldr x22, =_start /* x0 := vaddr(_start) */ + adr x21, _start /* x21 := paddr(_start) */ + sub x22, x21, x22 /* x22 := phys-offset (paddr - vaddr) */ + ret + +/* + * Setup the memory region attribute; + * Setup the TCR. + */ +_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_IRGN_WBWA | TCR_ORGN_WBWA | TCR_SHARED | TCR_IPS_48BIT) + msr tcr_el1, x0 + + ret + +/* + * Setup the page table mapping for @addr at @level with @prot. + * + * Note: x22 stores the offset between virtual address and physical address. + */ +.macro set_page_table, addr, level, prot + /* Find the table index in @level, save it in x3 */ +.if \level == 0 + lsr x3, \addr, #L0_SHIFT + adr x8, boot_l1_pgtable + adr x11, boot_l0_pgtable +.endif + +.if \level == 1 + lsr x3, \addr, #L1_SHIFT + adr x8, boot_l2_pgtable + adr x11, boot_l1_pgtable +.endif + +.if \level == 2 + lsr x3, \addr, #L2_SHIFT + adr x11, boot_l2_pgtable + /* Get the physical address, the @addr should be 2M aligned. */ + add x8, \addr, x22 +.endif + + and x3, x3, #Ln_ADDR_MASK + + /* Build the page table entry */ + ldr x7, = \prot + lsr x9, x8, #PAGE_SHIFT + orr x7, x7, x9, lsl #PAGE_SHIFT + + /* Store entry */ + str x7, [x11, x3, lsl #3] +.endm + +/* + * Setup the mapping for code section + * + * => null + * <= x0 -> for TTBR1_EL1 + */ +_setup_initial_pgtable: + /* Start to map the code */ + ldr x0, =_text /* x0 := vaddr(_text) */ + ldr x1, =_end /* x1 := vaddr(_end) */ + + set_page_table x0, 0, PT_PT + set_page_table x0, 1, PT_PT +1: + set_page_table x0, 2, PT_MEM + + add x0, x0, L2_SIZE + cmp x1, x0 + b.gt 1b + + adr x0, boot_l0_pgtable + dsb sy + ret + +/* + * Setup the page table mapping for @addr at @level with @prot. + * + * Only used for identity mapping. + */ +.macro set_ident_page_table, addr, level, prot + /* Find the table index in @level, save it in x3 */ +.if \level == 0 + lsr x3, \addr, #L0_SHIFT + adr x8, idmap_l1_pgtable + adr x11, idmap_l0_pgtable +.endif + +.if \level == 1 + lsr x3, \addr, #L1_SHIFT + mov x8, \addr + adr x11, idmap_l1_pgtable +.endif + + and x3, x3, #Ln_ADDR_MASK + + /* Build the page table entry */ + ldr x7, = \prot + lsr x9, x8, #PAGE_SHIFT + orr x7, x7, x9, lsl #PAGE_SHIFT + + /* Store entry */ + str x7, [x11, x3, lsl #3] +.endm + +/* + * Setup the page table for TTBR0_EL1: + * Mapping the page table for the code section. + * We use 48bit address, and just use level 0/1 + * for the mapping (we do not use level 2 and level 3). + * + * => none + * <= x0 : save the page table pointer for TTBR0_EL1. + */ +_setup_idmap_pgtable: + /* Create the VA = PA map */ + adr x0, _text + + set_ident_page_table x0, 0, PT_PT + set_ident_page_table x0, 1, PT_MEM + + adr x0, idmap_l0_pgtable + dsb sy + ret 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..8e2384f --- /dev/null +++ b/include/arm/arm64/pagetable.h @@ -0,0 +1,108 @@ +#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_48BIT ((5) << 32) +#define TCR_TG1_4K ((2) << 30) +#define TCR_EPD0 (1 << 7) + +/* Max virtual address */ +#define VM_MAX_ADDRESS (0xffffffffffffffff) + +/* Number of virtual address bits */ +#define VA_BITS 48 + +/* + * 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 (1 << 0) +#define SCTLR_C (1 << 2) +#define SCTLR_I (1 << 12) + +/* Level 0 table, 512GiB per entry */ +#define L0_SHIFT 39 +#define L0_SIZE (1UL << L0_SHIFT) +#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 l0_pgt_idx(va) (((va) >> L0_SHIFT) & Ln_ADDR_MASK) +#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 MEM_DEF_ATTR (ATTR_AF|ATTR_SH(ATTR_SH_IS)|ATTR_IDX(MEM_NORMAL)) +#define MEM_NC_ATTR (ATTR_AF|ATTR_SH(ATTR_SH_IS)|ATTR_IDX(MEM_NORMAL_NC)) +#define MEM_DEV_ATTR (ATTR_AF|ATTR_SH(ATTR_SH_IS)|ATTR_IDX(MEM_DEVICE_nGnRnE)) + +#define MEM_RO_ATTR (MEM_DEF_ATTR|ATTR_AP(ATTR_AP_RO)) + +#define PT_PT (L0_TABLE) +#define PT_MEM (MEM_DEF_ATTR | L1_BLOCK) + +#endif -- 2.7.4 _______________________________________________ Minios-devel mailing list Minios-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/mailman/listinfo/minios-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |