]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/arm64/arm64/locore.S
zfs: merge openzfs/zfs@21bd76613 (zfs-2.1-release) into stable/13
[FreeBSD/FreeBSD.git] / sys / arm64 / arm64 / locore.S
1 /*-
2  * Copyright (c) 2012-2014 Andrew Turner
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  * $FreeBSD$
27  */
28
29 #include "assym.inc"
30 #include "opt_kstack_pages.h"
31 #include <sys/syscall.h>
32 #include <machine/asm.h>
33 #include <machine/armreg.h>
34 #include <machine/hypervisor.h>
35 #include <machine/param.h>
36 #include <machine/pte.h>
37 #include <machine/vm.h>
38 #include <machine/vmparam.h>
39
40 #define VIRT_BITS       48
41
42         .globl  kernbase
43         .set    kernbase, KERNBASE
44
45 /*
46  * We assume:
47  *  MMU      on with an identity map, or off
48  *  D-Cache: off
49  *  I-Cache: on or off
50  *  We are loaded at a 2MiB aligned address
51  */
52
53 ENTRY(_start)
54         /* Drop to EL1 */
55         bl      drop_to_el1
56
57         /*
58          * Disable the MMU. We may have entered the kernel with it on and
59          * will need to update the tables later. If this has been set up
60          * with anything other than a VA == PA map then this will fail,
61          * but in this case the code to find where we are running from
62          * would have also failed.
63          */
64         dsb     sy
65         mrs     x2, sctlr_el1
66         bic     x2, x2, SCTLR_M
67         msr     sctlr_el1, x2
68         isb
69
70         /* Set the context id */
71         msr     contextidr_el1, xzr
72
73         /* Get the virt -> phys offset */
74         bl      get_virt_delta
75
76         /*
77          * At this point:
78          * x29 = PA - VA
79          * x28 = Our physical load address
80          */
81
82         /* Create the page tables */
83         bl      create_pagetables
84
85         /*
86          * At this point:
87          * x27 = TTBR0 table
88          * x26 = Kernel L1 table
89          * x24 = TTBR1 table
90          */
91
92         /* Enable the mmu */
93         bl      start_mmu
94
95         /* Load the new ttbr0 pagetable */
96         adrp    x27, pagetable_l0_ttbr0
97         add     x27, x27, :lo12:pagetable_l0_ttbr0
98
99         /* Jump to the virtual address space */
100         ldr     x15, .Lvirtdone
101         br      x15
102
103 virtdone:
104         /* Set up the stack */
105         adrp    x25, initstack_end
106         add     x25, x25, :lo12:initstack_end
107         mov     sp, x25
108         sub     sp, sp, #PCB_SIZE
109
110         /* Zero the BSS */
111         ldr     x15, .Lbss
112         ldr     x14, .Lend
113 1:
114         str     xzr, [x15], #8
115         cmp     x15, x14
116         b.lo    1b
117
118 #if defined(PERTHREAD_SSP)
119         /* Set sp_el0 to the boot canary for early per-thread SSP to work */
120         adrp    x15, boot_canary
121         add     x15, x15, :lo12:boot_canary
122         msr     sp_el0, x15
123 #endif
124
125         /* Backup the module pointer */
126         mov     x1, x0
127
128         /* Make the page table base a virtual address */
129         sub     x26, x26, x29
130         sub     x24, x24, x29
131
132         sub     sp, sp, #BOOTPARAMS_SIZE
133         mov     x0, sp
134
135         /* Degate the delda so it is VA -> PA */
136         neg     x29, x29
137
138         str     x1,  [x0, #BP_MODULEP]
139         str     x26, [x0, #BP_KERN_L1PT]
140         str     x29, [x0, #BP_KERN_DELTA]
141         adrp    x25, initstack
142         add     x25, x25, :lo12:initstack
143         str     x25, [x0, #BP_KERN_STACK]
144         str     x24, [x0, #BP_KERN_L0PT]
145         str     x27, [x0, #BP_KERN_TTBR0]
146         str     x23, [x0, #BP_BOOT_EL]
147
148         /* trace back starts here */
149         mov     fp, #0
150         /* Branch to C code */
151         bl      initarm
152         /* We are done with the boot params */
153         add     sp, sp, #BOOTPARAMS_SIZE
154         bl      mi_startup
155
156         /* We should not get here */
157         brk     0
158
159         .align 3
160 .Lvirtdone:
161         .quad   virtdone
162 .Lbss:
163         .quad   __bss_start
164 .Lend:
165         .quad   __bss_end
166 END(_start)
167
168 #ifdef SMP
169 /*
170  * mpentry(unsigned long)
171  *
172  * Called by a core when it is being brought online.
173  * The data in x0 is passed straight to init_secondary.
174  */
175 ENTRY(mpentry)
176         /* Disable interrupts */
177         msr     daifset, #DAIF_INTR
178
179         /* Drop to EL1 */
180         bl      drop_to_el1
181
182         /* Set the context id */
183         msr     contextidr_el1, xzr
184
185         /* Load the kernel page table */
186         adrp    x24, pagetable_l0_ttbr1
187         add     x24, x24, :lo12:pagetable_l0_ttbr1
188         /* Load the identity page table */
189         adrp    x27, pagetable_l0_ttbr0_boostrap
190         add     x27, x27, :lo12:pagetable_l0_ttbr0_boostrap
191
192         /* Enable the mmu */
193         bl      start_mmu
194
195         /* Load the new ttbr0 pagetable */
196         adrp    x27, pagetable_l0_ttbr0
197         add     x27, x27, :lo12:pagetable_l0_ttbr0
198
199         /* Jump to the virtual address space */
200         ldr     x15, =mp_virtdone
201         br      x15
202
203 mp_virtdone:
204         /* Start using the AP boot stack */
205         ldr     x4, =bootstack
206         ldr     x4, [x4]
207         mov     sp, x4
208
209 #if defined(PERTHREAD_SSP)
210         /* Set sp_el0 to the boot canary for early per-thread SSP to work */
211         adrp    x15, boot_canary
212         add     x15, x15, :lo12:boot_canary
213         msr     sp_el0, x15
214 #endif
215
216         /* Load the kernel ttbr0 pagetable */
217         msr     ttbr0_el1, x27
218         isb
219
220         /* Invalidate the TLB */
221         tlbi    vmalle1
222         dsb     sy
223         isb
224
225         b       init_secondary
226 END(mpentry)
227 #endif
228
229 /*
230  * If we are started in EL2, configure the required hypervisor
231  * registers and drop to EL1.
232  */
233 LENTRY(drop_to_el1)
234         mrs     x23, CurrentEL
235         lsr     x23, x23, #2
236         cmp     x23, #0x2
237         b.eq    1f
238         ret
239 1:
240         /*
241          * Disable the MMU. If the HCR_EL2.E2H field is set we will clear it
242          * which may break address translation.
243          */
244         dsb     sy
245         mrs     x2, sctlr_el2
246         bic     x2, x2, SCTLR_M
247         msr     sctlr_el2, x2
248         isb
249
250         /* Configure the Hypervisor */
251         mov     x2, #(HCR_RW)
252         msr     hcr_el2, x2
253
254         /* Load the Virtualization Process ID Register */
255         mrs     x2, midr_el1
256         msr     vpidr_el2, x2
257
258         /* Load the Virtualization Multiprocess ID Register */
259         mrs     x2, mpidr_el1
260         msr     vmpidr_el2, x2
261
262         /* Set the bits that need to be 1 in sctlr_el1 */
263         ldr     x2, .Lsctlr_res1
264         msr     sctlr_el1, x2
265
266         /* Don't trap to EL2 for exceptions */
267         mov     x2, #CPTR_RES1
268         msr     cptr_el2, x2
269
270         /* Don't trap to EL2 for CP15 traps */
271         msr     hstr_el2, xzr
272
273         /* Enable access to the physical timers at EL1 */
274         mrs     x2, cnthctl_el2
275         orr     x2, x2, #(CNTHCTL_EL1PCTEN | CNTHCTL_EL1PCEN)
276         msr     cnthctl_el2, x2
277
278         /* Set the counter offset to a known value */
279         msr     cntvoff_el2, xzr
280
281         /* Hypervisor trap functions */
282         adrp    x2, hyp_vectors
283         add     x2, x2, :lo12:hyp_vectors
284         msr     vbar_el2, x2
285
286         mov     x2, #(PSR_F | PSR_I | PSR_A | PSR_D | PSR_M_EL1h)
287         msr     spsr_el2, x2
288
289         /* Configure GICv3 CPU interface */
290         mrs     x2, id_aa64pfr0_el1
291         /* Extract GIC bits from the register */
292         ubfx    x2, x2, #ID_AA64PFR0_GIC_SHIFT, #ID_AA64PFR0_GIC_BITS
293         /* GIC[3:0] == 0001 - GIC CPU interface via special regs. supported */
294         cmp     x2, #(ID_AA64PFR0_GIC_CPUIF_EN >> ID_AA64PFR0_GIC_SHIFT)
295         b.ne    2f
296
297         mrs     x2, icc_sre_el2
298         orr     x2, x2, #ICC_SRE_EL2_EN /* Enable access from insecure EL1 */
299         orr     x2, x2, #ICC_SRE_EL2_SRE        /* Enable system registers */
300         msr     icc_sre_el2, x2
301 2:
302
303         /* Set the address to return to our return address */
304         msr     elr_el2, x30
305         isb
306
307         eret
308
309         .align 3
310 .Lsctlr_res1:
311         .quad SCTLR_RES1
312 LEND(drop_to_el1)
313
314 #define VECT_EMPTY      \
315         .align 7;       \
316         1:      b       1b
317
318         .align 11
319 hyp_vectors:
320         VECT_EMPTY      /* Synchronous EL2t */
321         VECT_EMPTY      /* IRQ EL2t */
322         VECT_EMPTY      /* FIQ EL2t */
323         VECT_EMPTY      /* Error EL2t */
324
325         VECT_EMPTY      /* Synchronous EL2h */
326         VECT_EMPTY      /* IRQ EL2h */
327         VECT_EMPTY      /* FIQ EL2h */
328         VECT_EMPTY      /* Error EL2h */
329
330         VECT_EMPTY      /* Synchronous 64-bit EL1 */
331         VECT_EMPTY      /* IRQ 64-bit EL1 */
332         VECT_EMPTY      /* FIQ 64-bit EL1 */
333         VECT_EMPTY      /* Error 64-bit EL1 */
334
335         VECT_EMPTY      /* Synchronous 32-bit EL1 */
336         VECT_EMPTY      /* IRQ 32-bit EL1 */
337         VECT_EMPTY      /* FIQ 32-bit EL1 */
338         VECT_EMPTY      /* Error 32-bit EL1 */
339
340 /*
341  * Get the delta between the physical address we were loaded to and the
342  * virtual address we expect to run from. This is used when building the
343  * initial page table.
344  */
345 LENTRY(get_virt_delta)
346         /* Load the physical address of virt_map */
347         adrp    x29, virt_map
348         add     x29, x29, :lo12:virt_map
349         /* Load the virtual address of virt_map stored in virt_map */
350         ldr     x28, [x29]
351         /* Find PA - VA as PA' = VA' - VA + PA = VA' + (PA - VA) = VA' + x29 */
352         sub     x29, x29, x28
353         /* Find the load address for the kernel */
354         mov     x28, #(KERNBASE)
355         add     x28, x28, x29
356         ret
357
358         .align 3
359 virt_map:
360         .quad   virt_map
361 LEND(get_virt_delta)
362
363 /*
364  * This builds the page tables containing the identity map, and the kernel
365  * virtual map.
366  *
367  * It relys on:
368  *  We were loaded to an address that is on a 2MiB boundary
369  *  All the memory must not cross a 1GiB boundaty
370  *  x28 contains the physical address we were loaded from
371  *
372  * TODO: This is out of date.
373  *  There are at least 5 pages before that address for the page tables
374  *   The pages used are:
375  *    - The Kernel L2 table
376  *    - The Kernel L1 table
377  *    - The Kernel L0 table             (TTBR1)
378  *    - The identity (PA = VA) L1 table
379  *    - The identity (PA = VA) L0 table (TTBR0)
380  */
381 LENTRY(create_pagetables)
382         /* Save the Link register */
383         mov     x5, x30
384
385         /* Clean the page table */
386         adrp    x6, pagetable
387         add     x6, x6, :lo12:pagetable
388         mov     x26, x6
389         adrp    x27, pagetable_end
390         add     x27, x27, :lo12:pagetable_end
391 1:
392         stp     xzr, xzr, [x6], #16
393         stp     xzr, xzr, [x6], #16
394         stp     xzr, xzr, [x6], #16
395         stp     xzr, xzr, [x6], #16
396         cmp     x6, x27
397         b.lo    1b
398
399         /*
400          * Build the TTBR1 maps.
401          */
402
403         /* Find the size of the kernel */
404         mov     x6, #(KERNBASE)
405
406 #if defined(LINUX_BOOT_ABI)
407         /* X19 is used as 'map FDT data' flag */
408         mov     x19, xzr
409
410         /* No modules or FDT pointer ? */
411         cbz     x0, booti_no_fdt
412
413         /*
414          * Test if x0 points to modules descriptor(virtual address) or
415          * to FDT (physical address)
416          */
417         cmp     x0, x6          /* x6 is #(KERNBASE) */
418         b.lo    booti_fdt
419 #endif
420
421         /* Booted with modules pointer */
422         /* Find modulep - begin */
423         sub     x8, x0, x6
424         /* Add two 2MiB pages for the module data and round up */
425         ldr     x7, =(3 * L2_SIZE - 1)
426         add     x8, x8, x7
427         b       common
428
429 #if defined(LINUX_BOOT_ABI)
430 booti_fdt:
431         /* Booted by U-Boot booti with FDT data */
432         /* Set 'map FDT data' flag */
433         mov     x19, #1
434
435 booti_no_fdt:
436         /* Booted by U-Boot booti without FTD data */
437         /* Find the end - begin */
438         ldr     x7, .Lend
439         sub     x8, x7, x6
440
441         /*
442          * Add one 2MiB page for copy of FDT data (maximum FDT size),
443          * one for metadata and round up
444          */
445         ldr     x7, =(3 * L2_SIZE - 1)
446         add     x8, x8, x7
447 #endif
448
449 common:
450         /* Get the number of l2 pages to allocate, rounded down */
451         lsr     x10, x8, #(L2_SHIFT)
452
453         /* Create the kernel space L2 table */
454         mov     x6, x26
455         mov     x7, #VM_MEMATTR_WRITE_BACK
456         mov     x8, #(KERNBASE & L2_BLOCK_MASK)
457         mov     x9, x28
458         bl      build_l2_block_pagetable
459
460         /* Move to the l1 table */
461         add     x26, x26, #PAGE_SIZE
462
463         /* Link the l1 -> l2 table */
464         mov     x9, x6
465         mov     x6, x26
466         bl      link_l1_pagetable
467
468         /* Move to the l0 table */
469         add     x24, x26, #PAGE_SIZE
470
471         /* Link the l0 -> l1 table */
472         mov     x9, x6
473         mov     x6, x24
474         mov     x10, #1
475         bl      link_l0_pagetable
476
477         /*
478          * Build the TTBR0 maps.  As TTBR0 maps, they must specify ATTR_S1_nG.
479          * They are only needed early on, so the VA = PA map is uncached.
480          */
481         add     x27, x24, #PAGE_SIZE
482
483         mov     x6, x27         /* The initial page table */
484 #if defined(SOCDEV_PA) && defined(SOCDEV_VA)
485         /* Create a table for the UART */
486         mov     x7, #(ATTR_S1_nG | ATTR_S1_IDX(VM_MEMATTR_DEVICE))
487         mov     x8, #(SOCDEV_VA)        /* VA start */
488         mov     x9, #(SOCDEV_PA)        /* PA start */
489         mov     x10, #1
490         bl      build_l1_block_pagetable
491 #endif
492
493 #if defined(LINUX_BOOT_ABI)
494         /* Map FDT data ? */
495         cbz     x19, 1f
496
497         /* Create the identity mapping for FDT data (2 MiB max) */
498         mov     x7, #(ATTR_S1_nG | ATTR_S1_IDX(VM_MEMATTR_WRITE_BACK))
499         mov     x9, x0
500         mov     x8, x0          /* VA start (== PA start) */
501         mov     x10, #1
502         bl      build_l1_block_pagetable
503
504 1:
505 #endif
506
507         /* Create the VA = PA map */
508         mov     x7, #(ATTR_S1_nG | ATTR_S1_IDX(VM_MEMATTR_WRITE_BACK))
509         mov     x9, x28
510         mov     x8, x9          /* VA start (== PA start) */
511         mov     x10, #1
512         bl      build_l1_block_pagetable
513
514         /* Move to the l0 table */
515         add     x27, x27, #PAGE_SIZE
516
517         /* Link the l0 -> l1 table */
518         mov     x9, x6
519         mov     x6, x27
520         mov     x10, #1
521         bl      link_l0_pagetable
522
523         /* Restore the Link register */
524         mov     x30, x5
525         ret
526 LEND(create_pagetables)
527
528 /*
529  * Builds an L0 -> L1 table descriptor
530  *
531  * This is a link for a 512GiB block of memory with up to 1GiB regions mapped
532  * within it by build_l1_block_pagetable.
533  *
534  *  x6  = L0 table
535  *  x8  = Virtual Address
536  *  x9  = L1 PA (trashed)
537  *  x10 = Entry count
538  *  x11, x12 and x13 are trashed
539  */
540 LENTRY(link_l0_pagetable)
541         /*
542          * Link an L0 -> L1 table entry.
543          */
544         /* Find the table index */
545         lsr     x11, x8, #L0_SHIFT
546         and     x11, x11, #L0_ADDR_MASK
547
548         /* Build the L0 block entry */
549         mov     x12, #L0_TABLE
550         orr     x12, x12, #(TATTR_UXN_TABLE | TATTR_AP_TABLE_NO_EL0)
551
552         /* Only use the output address bits */
553         lsr     x9, x9, #PAGE_SHIFT
554 1:      orr     x13, x12, x9, lsl #PAGE_SHIFT
555
556         /* Store the entry */
557         str     x13, [x6, x11, lsl #3]
558
559         sub     x10, x10, #1
560         add     x11, x11, #1
561         add     x9, x9, #1
562         cbnz    x10, 1b
563
564         ret
565 LEND(link_l0_pagetable)
566
567 /*
568  * Builds an L1 -> L2 table descriptor
569  *
570  * This is a link for a 1GiB block of memory with up to 2MiB regions mapped
571  * within it by build_l2_block_pagetable.
572  *
573  *  x6  = L1 table
574  *  x8  = Virtual Address
575  *  x9  = L2 PA (trashed)
576  *  x11, x12 and x13 are trashed
577  */
578 LENTRY(link_l1_pagetable)
579         /*
580          * Link an L1 -> L2 table entry.
581          */
582         /* Find the table index */
583         lsr     x11, x8, #L1_SHIFT
584         and     x11, x11, #Ln_ADDR_MASK
585
586         /* Build the L1 block entry */
587         mov     x12, #L1_TABLE
588
589         /* Only use the output address bits */
590         lsr     x9, x9, #PAGE_SHIFT
591         orr     x13, x12, x9, lsl #PAGE_SHIFT
592
593         /* Store the entry */
594         str     x13, [x6, x11, lsl #3]
595
596         ret
597 LEND(link_l1_pagetable)
598
599 /*
600  * Builds count 1 GiB page table entry
601  *  x6  = L1 table
602  *  x7  = Variable lower block attributes
603  *  x8  = VA start
604  *  x9  = PA start (trashed)
605  *  x10 = Entry count
606  *  x11, x12 and x13 are trashed
607  */
608 LENTRY(build_l1_block_pagetable)
609         /*
610          * Build the L1 table entry.
611          */
612         /* Find the table index */
613         lsr     x11, x8, #L1_SHIFT
614         and     x11, x11, #Ln_ADDR_MASK
615
616         /* Build the L1 block entry */
617         orr     x12, x7, #L1_BLOCK
618         orr     x12, x12, #(ATTR_DEFAULT)
619
620         /* Only use the output address bits */
621         lsr     x9, x9, #L1_SHIFT
622
623         /* Set the physical address for this virtual address */
624 1:      orr     x13, x12, x9, lsl #L1_SHIFT
625
626         /* Store the entry */
627         str     x13, [x6, x11, lsl #3]
628
629         sub     x10, x10, #1
630         add     x11, x11, #1
631         add     x9, x9, #1
632         cbnz    x10, 1b
633
634         ret
635 LEND(build_l1_block_pagetable)
636
637 /*
638  * Builds count 2 MiB page table entry
639  *  x6  = L2 table
640  *  x7  = Type (0 = Device, 1 = Normal)
641  *  x8  = VA start
642  *  x9  = PA start (trashed)
643  *  x10 = Entry count
644  *  x11, x12 and x13 are trashed
645  */
646 LENTRY(build_l2_block_pagetable)
647         /*
648          * Build the L2 table entry.
649          */
650         /* Find the table index */
651         lsr     x11, x8, #L2_SHIFT
652         and     x11, x11, #Ln_ADDR_MASK
653
654         /* Build the L2 block entry */
655         lsl     x12, x7, #2
656         orr     x12, x12, #L2_BLOCK
657         orr     x12, x12, #(ATTR_DEFAULT)
658         orr     x12, x12, #(ATTR_S1_UXN)
659
660         /* Only use the output address bits */
661         lsr     x9, x9, #L2_SHIFT
662
663         /* Set the physical address for this virtual address */
664 1:      orr     x13, x12, x9, lsl #L2_SHIFT
665
666         /* Store the entry */
667         str     x13, [x6, x11, lsl #3]
668
669         sub     x10, x10, #1
670         add     x11, x11, #1
671         add     x9, x9, #1
672         cbnz    x10, 1b
673
674         ret
675 LEND(build_l2_block_pagetable)
676
677 LENTRY(start_mmu)
678         dsb     sy
679
680         /* Load the exception vectors */
681         ldr     x2, =exception_vectors
682         msr     vbar_el1, x2
683
684         /* Load ttbr0 and ttbr1 */
685         msr     ttbr0_el1, x27
686         msr     ttbr1_el1, x24
687         isb
688
689         /* Clear the Monitor Debug System control register */
690         msr     mdscr_el1, xzr
691
692         /* Invalidate the TLB */
693         tlbi    vmalle1is
694         dsb     ish
695         isb
696
697         ldr     x2, mair
698         msr     mair_el1, x2
699
700         /*
701          * Setup TCR according to the PARange and ASIDBits fields
702          * from ID_AA64MMFR0_EL1 and the HAFDBS field from the
703          * ID_AA64MMFR1_EL1.  More precisely, set TCR_EL1.AS
704          * to 1 only if the ASIDBits field equals 0b0010.
705          */
706         ldr     x2, tcr
707         mrs     x3, id_aa64mmfr0_el1
708
709         /* Copy the bottom 3 bits from id_aa64mmfr0_el1 into TCR.IPS */
710         bfi     x2, x3, #(TCR_IPS_SHIFT), #(TCR_IPS_WIDTH)
711         and     x3, x3, #(ID_AA64MMFR0_ASIDBits_MASK)
712
713         /* Check if the HW supports 16 bit ASIDS */
714         cmp     x3, #(ID_AA64MMFR0_ASIDBits_16)
715         /* If so x3 == 1, else x3 == 0 */
716         cset    x3, eq
717         /* Set TCR.AS with x3 */
718         bfi     x2, x3, #(TCR_ASID_SHIFT), #(TCR_ASID_WIDTH)
719
720         /*
721          * Check if the HW supports access flag and dirty state updates,
722          * and set TCR_EL1.HA and TCR_EL1.HD accordingly.
723          */
724         mrs     x3, id_aa64mmfr1_el1
725         and     x3, x3, #(ID_AA64MMFR1_HAFDBS_MASK)
726         cmp     x3, #1
727         b.ne    1f
728         orr     x2, x2, #(TCR_HA)
729         b       2f
730 1:
731         cmp     x3, #2
732         b.ne    2f
733         orr     x2, x2, #(TCR_HA | TCR_HD)
734 2:
735         msr     tcr_el1, x2
736
737         /*
738          * Setup SCTLR.
739          */
740         ldr     x2, sctlr_set
741         ldr     x3, sctlr_clear
742         mrs     x1, sctlr_el1
743         bic     x1, x1, x3      /* Clear the required bits */
744         orr     x1, x1, x2      /* Set the required bits */
745         msr     sctlr_el1, x1
746         isb
747
748         ret
749
750         .align 3
751 mair:
752         .quad   MAIR_ATTR(MAIR_DEVICE_nGnRnE, VM_MEMATTR_DEVICE_nGnRnE) | \
753                 MAIR_ATTR(MAIR_NORMAL_NC, VM_MEMATTR_UNCACHEABLE)   |   \
754                 MAIR_ATTR(MAIR_NORMAL_WB, VM_MEMATTR_WRITE_BACK)    |   \
755                 MAIR_ATTR(MAIR_NORMAL_WT, VM_MEMATTR_WRITE_THROUGH) |   \
756                 MAIR_ATTR(MAIR_DEVICE_nGnRE, VM_MEMATTR_DEVICE_nGnRE)
757 tcr:
758         .quad (TCR_TxSZ(64 - VIRT_BITS) | TCR_TG1_4K | TCR_TG0_4K | \
759             TCR_CACHE_ATTRS | TCR_SMP_ATTRS)
760 sctlr_set:
761         /* Bits to set */
762         .quad (SCTLR_LSMAOE | SCTLR_nTLSMD | SCTLR_UCI | SCTLR_SPAN | \
763             SCTLR_nTWE | SCTLR_nTWI | SCTLR_UCT | SCTLR_DZE | \
764             SCTLR_I | SCTLR_SED | SCTLR_SA0 | SCTLR_SA | SCTLR_C | \
765             SCTLR_M | SCTLR_CP15BEN)
766 sctlr_clear:
767         /* Bits to clear */
768         .quad (SCTLR_EE | SCTLR_E0E | SCTLR_IESB | SCTLR_WXN | SCTLR_UMA | \
769             SCTLR_ITD | SCTLR_A)
770 LEND(start_mmu)
771
772 ENTRY(abort)
773         b abort
774 END(abort)
775
776         .section .init_pagetable, "aw", %nobits
777         .align PAGE_SHIFT
778         /*
779          * 6 initial tables (in the following order):
780          *           L2 for kernel (High addresses)
781          *           L1 for kernel
782          *           L0 for kernel
783          *           L1 bootstrap for user   (Low addresses)
784          *           L0 bootstrap for user
785          *           L0 for user
786          */
787         .globl pagetable_l0_ttbr1
788 pagetable:
789         .space  PAGE_SIZE
790 pagetable_l1_ttbr1:
791         .space  PAGE_SIZE
792 pagetable_l0_ttbr1:
793         .space  PAGE_SIZE
794 pagetable_l1_ttbr0_bootstrap:
795         .space  PAGE_SIZE
796 pagetable_l0_ttbr0_boostrap:
797         .space  PAGE_SIZE
798 pagetable_l0_ttbr0:
799         .space  PAGE_SIZE
800
801 pagetable_end:
802
803 el2_pagetable:
804         .space  PAGE_SIZE
805
806         .align  4
807 initstack:
808         .space  (PAGE_SIZE * KSTACK_PAGES)
809 initstack_end:
810
811
812 .text
813 EENTRY(aarch32_sigcode)
814         .word 0xe1a0000d        // mov r0, sp
815         .word 0xe2800040        // add r0, r0, #SIGF_UC
816         .word 0xe59f700c        // ldr r7, [pc, #12]
817         .word 0xef000000        // swi #0
818         .word 0xe59f7008        // ldr r7, [pc, #8]
819         .word 0xef000000        // swi #0
820         .word 0xeafffffa        // b . - 16
821 EEND(aarch32_sigcode)
822         .word SYS_sigreturn
823         .word SYS_exit
824         .align  3
825 aarch32_esigcode:
826         .data
827         .global sz_aarch32_sigcode
828 sz_aarch32_sigcode:
829         .quad aarch32_esigcode - aarch32_sigcode