[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

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.