1/*
2 * Copyright 2017, Data61
3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO)
4 * ABN 41 687 119 230.
5 *
6 * This software may be distributed and modified according to the terms of
7 * the GNU General Public License version 2. Note that NO WARRANTY is provided.
8 * See "LICENSE_GPLv2.txt" for details.
9 *
10 * @TAG(DATA61_GPL)
11 */
12
13#include <config.h>
14#include <machine/assembler.h>
15#include <arch/machine/hardware.h>
16#include <arch/machine/registerset.h>
17#include <util.h>
18
19#ifndef ALLOW_UNALIGNED_ACCESS
20#define ALLOW_UNALIGNED_ACCESS 1
21#endif
22
23#if ALLOW_UNALIGNED_ACCESS
24#define CR_ALIGN_SET     0
25#define CR_ALIGN_CLEAR   BIT(CONTROL_A)
26#else
27#define CR_ALIGN_SET     BIT(CONTROL_A)
28#define CR_ALIGN_CLEAR   0
29#endif
30
31#ifndef CONFIG_DEBUG_DISABLE_L1_ICACHE
32    #define CR_L1_ICACHE_SET   BIT(CONTROL_I)
33    #define CR_L1_ICACHE_CLEAR 0
34#else
35    #define CR_L1_ICACHE_SET   0
36    #define CR_L1_ICACHE_CLEAR BIT(CONTROL_I)
37#endif
38
39#ifndef CONFIG_DEBUG_DISABLE_L1_DCACHE
40    #define CR_L1_DCACHE_SET   BIT(CONTROL_C)
41    #define CR_L1_DCACHE_CLEAR 0
42#else
43    #define CR_L1_DCACHE_SET   0
44    #define CR_L1_DCACHE_CLEAR BIT(CONTROL_C)
45#endif
46
47#define CR_BITS_SET    (CR_ALIGN_SET | \
48                        CR_L1_ICACHE_SET | \
49                        CR_L1_DCACHE_SET | \
50                        BIT(CONTROL_M))
51
52#define CR_BITS_CLEAR  (CR_ALIGN_CLEAR | \
53                        CR_L1_ICACHE_CLEAR | \
54                        CR_L1_DCACHE_CLEAR | \
55                        BIT(CONTROL_SA0) | \
56                        BIT(CONTROL_EE) | \
57                        BIT(CONTROL_E0E))
58
59/*
60 * Entry point of the kernel ELF image.
61 * X0-X3 contain parameters that are passed to init_kernel().
62 *
63 * Note that for SMP kernel, the tpidr_el1 is used to pass
64 * the logical core ID.
65 */
66
67#ifdef CONFIG_ARM_HYPERVISOR_SUPPORT
68#define SCTLR   sctlr_el2
69#else
70#define SCTLR   sctlr_el1
71#endif
72
73.section .boot.text
74BEGIN_FUNC(_start)
75    /* Make sure interrupts are disable */
76    msr daifset, #DAIFSET_MASK
77
78    /* Initialise sctlr_el1 or sctlr_el2 register */
79    msr     spsel, #1
80    mrs     x4, SCTLR
81    ldr     x19, =CR_BITS_SET
82    ldr     x20, =CR_BITS_CLEAR
83    orr     x4, x4, x19
84    bic     x4, x4, x20
85    msr     SCTLR, x4
86
87#ifdef ENABLE_SMP_SUPPORT
88    /* tpidr_el1 has the logic ID of the core, starting from 0 */
89    mrs     x6, tpidr_el1
90    /* Set the sp for each core assuming linear indices */
91    ldr     x5, =BIT(CONFIG_KERNEL_STACK_BITS)
92    mul     x5, x5, x6
93    ldr     x4, =kernel_stack_alloc + BIT(CONFIG_KERNEL_STACK_BITS)
94    add     x4, x4, x5
95    mov     sp, x4
96    /* the kernel stack must be 4-KiB aligned since we use the
97       lowest 12 bits to store the logical core ID. */
98    orr     x6, x6, x4
99#ifdef CONFIG_ARM_HYPERVISOR_SUPPORT
100    msr     tpidr_el2, x6
101#else
102    msr     tpidr_el1, x6
103#endif
104#else
105    ldr    x4, =kernel_stack_alloc + BIT(CONFIG_KERNEL_STACK_BITS)
106    mov    sp, x4
107#endif /* ENABLE_SMP_SUPPORT */
108
109    /* Attempt to workaround any known ARM errata. */
110    stp     x0, x1, [sp, #-16]!
111    stp     x2, x3, [sp, #-16]!
112    bl arm_errata
113    ldp     x2, x3, [sp], #16
114    ldp     x0, x1, [sp], #16
115
116    /* Call bootstrapping implemented in C */
117    bl      init_kernel
118
119    /* Restore the initial thread */
120    b restore_user_context
121END_FUNC(_start)
122