]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/arm64/arm64/locore.S
Merge libxo 0.4.6
[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.s"
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/vmparam.h>
38
39 #define VIRT_BITS       48
40
41         .globl  kernbase
42         .set    kernbase, KERNBASE
43
44 #define DEVICE_MEM      0
45 #define NORMAL_UNCACHED 1
46 #define NORMAL_MEM      2
47
48 /*
49  * We assume:
50  *  MMU      on with an identity map, or off
51  *  D-Cache: off
52  *  I-Cache: on or off
53  *  We are loaded at a 2MiB aligned address
54  */
55
56         .text
57         .globl _start
58 _start:
59         /* Drop to EL1 */
60         bl      drop_to_el1
61
62         /*
63          * Disable the MMU. We may have entered the kernel with it on and
64          * will need to update the tables later. If this has been set up
65          * with anything other than a VA == PA map then this will fail,
66          * but in this case the code to find where we are running from
67          * would have also failed.
68          */
69         dsb     sy
70         mrs     x2, sctlr_el1
71         bic     x2, x2, SCTLR_M
72         msr     sctlr_el1, x2
73         isb
74
75         /* Set the context id */
76         msr     contextidr_el1, xzr
77
78         /* Get the virt -> phys offset */
79         bl      get_virt_delta
80
81         /*
82          * At this point:
83          * x29 = PA - VA
84          * x28 = Our physical load address
85          */
86
87         /* Create the page tables */
88         bl      create_pagetables
89
90         /*
91          * At this point:
92          * x27 = TTBR0 table
93          * x26 = Kernel L1 table
94          * x24 = TTBR1 table
95          */
96
97         /* Enable the mmu */
98         bl      start_mmu
99
100         /* Jump to the virtual address space */
101         ldr     x15, .Lvirtdone
102         br      x15
103
104 virtdone:
105         /* Set up the stack */
106         adr     x25, 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         /* Backup the module pointer */
119         mov     x1, x0
120
121         /* Make the page table base a virtual address */
122         sub     x26, x26, x29
123         sub     x24, x24, x29
124
125         sub     sp, sp, #(64 * 4)
126         mov     x0, sp
127
128         /* Degate the delda so it is VA -> PA */
129         neg     x29, x29
130
131         str     x1,  [x0]       /* modulep */
132         str     x26, [x0, 8]    /* kern_l1pt */
133         str     x29, [x0, 16]   /* kern_delta */
134         str     x25, [x0, 24]   /* kern_stack */
135         str     x24, [x0, 32]   /* kern_l0pt */
136
137         /* trace back starts here */
138         mov     fp, #0
139         /* Branch to C code */
140         bl      initarm
141         bl      mi_startup
142
143         /* We should not get here */
144         brk     0
145
146         .align 3
147 .Lvirtdone:
148         .quad   virtdone
149 .Lbss:
150         .quad   __bss_start
151 .Lend:
152         .quad   _end
153
154 #ifdef SMP
155 /*
156  * mpentry(unsigned long)
157  *
158  * Called by a core when it is being brought online.
159  * The data in x0 is passed straight to init_secondary.
160  */
161 ENTRY(mpentry)
162         /* Disable interrupts */
163         msr     daifset, #2
164
165         /* Drop to EL1 */
166         bl      drop_to_el1
167
168         /* Set the context id */
169         msr     contextidr_el1, x1
170
171         /* Load the kernel page table */
172         adr     x24, pagetable_l0_ttbr1
173         /* Load the identity page table */
174         adr     x27, pagetable_l0_ttbr0
175
176         /* Enable the mmu */
177         bl      start_mmu
178
179         /* Jump to the virtual address space */
180         ldr     x15, =mp_virtdone
181         br      x15
182
183 mp_virtdone:
184         ldr     x4, =secondary_stacks
185         mov     x5, #(PAGE_SIZE * KSTACK_PAGES)
186         mul     x5, x0, x5
187         add     sp, x4, x5
188
189         b       init_secondary
190 END(mpentry)
191 #endif
192
193 /*
194  * If we are started in EL2, configure the required hypervisor
195  * registers and drop to EL1.
196  */
197 drop_to_el1:
198         mrs     x1, CurrentEL
199         lsr     x1, x1, #2
200         cmp     x1, #0x2
201         b.eq    1f
202         ret
203 1:
204         /* Configure the Hypervisor */
205         mov     x2, #(HCR_RW)
206         msr     hcr_el2, x2
207
208         /* Load the Virtualization Process ID Register */
209         mrs     x2, midr_el1
210         msr     vpidr_el2, x2
211
212         /* Load the Virtualization Multiprocess ID Register */
213         mrs     x2, mpidr_el1
214         msr     vmpidr_el2, x2
215
216         /* Set the bits that need to be 1 in sctlr_el1 */
217         ldr     x2, .Lsctlr_res1
218         msr     sctlr_el1, x2
219
220         /* Don't trap to EL2 for exceptions */
221         mov     x2, #CPTR_RES1
222         msr     cptr_el2, x2
223
224         /* Don't trap to EL2 for CP15 traps */
225         msr     hstr_el2, xzr
226
227         /* Enable access to the physical timers at EL1 */
228         mrs     x2, cnthctl_el2
229         orr     x2, x2, #(CNTHCTL_EL1PCTEN | CNTHCTL_EL1PCEN)
230         msr     cnthctl_el2, x2
231
232         /* Set the counter offset to a known value */
233         msr     cntvoff_el2, xzr
234
235         /* Hypervisor trap functions */
236         adr     x2, hyp_vectors
237         msr     vbar_el2, x2
238
239         mov     x2, #(PSR_F | PSR_I | PSR_A | PSR_D | PSR_M_EL1h)
240         msr     spsr_el2, x2
241
242         /* Configure GICv3 CPU interface */
243         mrs     x2, id_aa64pfr0_el1
244         /* Extract GIC bits from the register */
245         ubfx    x2, x2, #ID_AA64PFR0_GIC_SHIFT, #ID_AA64PFR0_GIC_BITS
246         /* GIC[3:0] == 0001 - GIC CPU interface via special regs. supported */
247         cmp     x2, #(ID_AA64PFR0_GIC_CPUIF_EN >> ID_AA64PFR0_GIC_SHIFT)
248         b.ne    2f
249
250         mrs     x2, icc_sre_el2
251         orr     x2, x2, #ICC_SRE_EL2_EN /* Enable access from insecure EL1 */
252         orr     x2, x2, #ICC_SRE_EL2_SRE        /* Enable system registers */
253         msr     icc_sre_el2, x2
254 2:
255
256         /* Set the address to return to our return address */
257         msr     elr_el2, x30
258         isb
259
260         eret
261
262         .align 3
263 .Lsctlr_res1:
264         .quad SCTLR_RES1
265
266 #define VECT_EMPTY      \
267         .align 7;       \
268         1:      b       1b
269
270         .align 11
271 hyp_vectors:
272         VECT_EMPTY      /* Synchronous EL2t */
273         VECT_EMPTY      /* IRQ EL2t */
274         VECT_EMPTY      /* FIQ EL2t */
275         VECT_EMPTY      /* Error EL2t */
276
277         VECT_EMPTY      /* Synchronous EL2h */
278         VECT_EMPTY      /* IRQ EL2h */
279         VECT_EMPTY      /* FIQ EL2h */
280         VECT_EMPTY      /* Error EL2h */
281
282         VECT_EMPTY      /* Synchronous 64-bit EL1 */
283         VECT_EMPTY      /* IRQ 64-bit EL1 */
284         VECT_EMPTY      /* FIQ 64-bit EL1 */
285         VECT_EMPTY      /* Error 64-bit EL1 */
286
287         VECT_EMPTY      /* Synchronous 32-bit EL1 */
288         VECT_EMPTY      /* IRQ 32-bit EL1 */
289         VECT_EMPTY      /* FIQ 32-bit EL1 */
290         VECT_EMPTY      /* Error 32-bit EL1 */
291
292 /*
293  * Get the delta between the physical address we were loaded to and the
294  * virtual address we expect to run from. This is used when building the
295  * initial page table.
296  */
297 get_virt_delta:
298         /* Load the physical address of virt_map */
299         adr     x29, virt_map
300         /* Load the virtual address of virt_map stored in virt_map */
301         ldr     x28, [x29]
302         /* Find PA - VA as PA' = VA' - VA + PA = VA' + (PA - VA) = VA' + x29 */
303         sub     x29, x29, x28
304         /* Find the load address for the kernel */
305         mov     x28, #(KERNBASE)
306         add     x28, x28, x29
307         ret
308
309         .align 3
310 virt_map:
311         .quad   virt_map
312
313 /*
314  * This builds the page tables containing the identity map, and the kernel
315  * virtual map.
316  *
317  * It relys on:
318  *  We were loaded to an address that is on a 2MiB boundary
319  *  All the memory must not cross a 1GiB boundaty
320  *  x28 contains the physical address we were loaded from
321  *
322  * TODO: This is out of date.
323  *  There are at least 5 pages before that address for the page tables
324  *   The pages used are:
325  *    - The identity (PA = VA) table (TTBR0)
326  *    - The Kernel L1 table          (TTBR1)(not yet)
327  *    -  The PA != VA L2 table to jump into (not yet)
328  *    -  The FDT L2 table                   (not yet)
329  */
330 create_pagetables:
331         /* Save the Link register */
332         mov     x5, x30
333
334         /* Clean the page table */
335         adr     x6, pagetable
336         mov     x26, x6
337         adr     x27, pagetable_end
338 1:
339         stp     xzr, xzr, [x6], #16
340         stp     xzr, xzr, [x6], #16
341         stp     xzr, xzr, [x6], #16
342         stp     xzr, xzr, [x6], #16
343         cmp     x6, x27
344         b.lo    1b
345
346         /*
347          * Build the TTBR1 maps.
348          */
349
350         /* Find the size of the kernel */
351         mov     x6, #(KERNBASE)
352         ldr     x7, .Lend
353         /* Find the end - begin */
354         sub     x8, x7, x6
355         /* Get the number of l2 pages to allocate, rounded down */
356         lsr     x10, x8, #(L2_SHIFT)
357         /* Add 8 MiB for any rounding above and the module data */
358         add     x10, x10, #4
359
360         /* Create the kernel space L2 table */
361         mov     x6, x26
362         mov     x7, #NORMAL_MEM
363         mov     x8, #(KERNBASE & L2_BLOCK_MASK)
364         mov     x9, x28
365         bl      build_l2_block_pagetable
366
367         /* Move to the l1 table */
368         add     x26, x26, #PAGE_SIZE
369
370         /* Link the l1 -> l2 table */
371         mov     x9, x6
372         mov     x6, x26
373         bl      link_l1_pagetable
374
375         /* Move to the l0 table */
376         add     x24, x26, #PAGE_SIZE
377
378         /* Link the l0 -> l1 table */
379         mov     x9, x6
380         mov     x6, x24
381         mov     x10, #1
382         bl      link_l0_pagetable
383
384         /*
385          * Build the TTBR0 maps.
386          */
387         add     x27, x24, #PAGE_SIZE
388
389         mov     x6, x27         /* The initial page table */
390 #if defined(SOCDEV_PA) && defined(SOCDEV_VA)
391         /* Create a table for the UART */
392         mov     x7, #DEVICE_MEM
393         mov     x8, #(SOCDEV_VA)        /* VA start */
394         mov     x9, #(SOCDEV_PA)        /* PA start */
395         mov     x10, #1
396         bl      build_l1_block_pagetable
397 #endif
398
399         /* Create the VA = PA map */
400         mov     x7, #NORMAL_UNCACHED /* Uncached as it's only needed early on */
401         mov     x9, x27
402         mov     x8, x9          /* VA start (== PA start) */
403         mov     x10, #1
404         bl      build_l1_block_pagetable
405
406         /* Move to the l0 table */
407         add     x27, x27, #PAGE_SIZE
408
409         /* Link the l0 -> l1 table */
410         mov     x9, x6
411         mov     x6, x27
412         mov     x10, #1
413         bl      link_l0_pagetable
414
415         /* Restore the Link register */
416         mov     x30, x5
417         ret
418
419 /*
420  * Builds an L0 -> L1 table descriptor
421  *
422  * This is a link for a 512GiB block of memory with up to 1GiB regions mapped
423  * within it by build_l1_block_pagetable.
424  *
425  *  x6  = L0 table
426  *  x8  = Virtual Address
427  *  x9  = L1 PA (trashed)
428  *  x10 = Entry count
429  *  x11, x12 and x13 are trashed
430  */
431 link_l0_pagetable:
432         /*
433          * Link an L0 -> L1 table entry.
434          */
435         /* Find the table index */
436         lsr     x11, x8, #L0_SHIFT
437         and     x11, x11, #L0_ADDR_MASK
438
439         /* Build the L0 block entry */
440         mov     x12, #L0_TABLE
441
442         /* Only use the output address bits */
443         lsr     x9, x9, #PAGE_SHIFT
444 1:      orr     x13, x12, x9, lsl #PAGE_SHIFT
445
446         /* Store the entry */
447         str     x13, [x6, x11, lsl #3]
448
449         sub     x10, x10, #1
450         add     x11, x11, #1
451         add     x9, x9, #1
452         cbnz    x10, 1b
453
454         ret
455
456 /*
457  * Builds an L1 -> L2 table descriptor
458  *
459  * This is a link for a 1GiB block of memory with up to 2MiB regions mapped
460  * within it by build_l2_block_pagetable.
461  *
462  *  x6  = L1 table
463  *  x8  = Virtual Address
464  *  x9  = L2 PA (trashed)
465  *  x11, x12 and x13 are trashed
466  */
467 link_l1_pagetable:
468         /*
469          * Link an L1 -> L2 table entry.
470          */
471         /* Find the table index */
472         lsr     x11, x8, #L1_SHIFT
473         and     x11, x11, #Ln_ADDR_MASK
474
475         /* Build the L1 block entry */
476         mov     x12, #L1_TABLE
477
478         /* Only use the output address bits */
479         lsr     x9, x9, #PAGE_SHIFT
480         orr     x13, x12, x9, lsl #PAGE_SHIFT
481
482         /* Store the entry */
483         str     x13, [x6, x11, lsl #3]
484
485         ret
486
487 /*
488  * Builds count 1 GiB page table entry
489  *  x6  = L1 table
490  *  x7  = Type (0 = Device, 1 = Normal)
491  *  x8  = VA start
492  *  x9  = PA start (trashed)
493  *  x10 = Entry count
494  *  x11, x12 and x13 are trashed
495  */
496 build_l1_block_pagetable:
497         /*
498          * Build the L1 table entry.
499          */
500         /* Find the table index */
501         lsr     x11, x8, #L1_SHIFT
502         and     x11, x11, #Ln_ADDR_MASK
503
504         /* Build the L1 block entry */
505         lsl     x12, x7, #2
506         orr     x12, x12, #L1_BLOCK
507         orr     x12, x12, #(ATTR_AF)
508 #ifdef SMP
509         orr     x12, x12, ATTR_SH(ATTR_SH_IS)
510 #endif
511
512         /* Only use the output address bits */
513         lsr     x9, x9, #L1_SHIFT
514
515         /* Set the physical address for this virtual address */
516 1:      orr     x13, x12, x9, lsl #L1_SHIFT
517
518         /* Store the entry */
519         str     x13, [x6, x11, lsl #3]
520
521         sub     x10, x10, #1
522         add     x11, x11, #1
523         add     x9, x9, #1
524         cbnz    x10, 1b
525
526         ret
527
528 /*
529  * Builds count 2 MiB page table entry
530  *  x6  = L2 table
531  *  x7  = Type (0 = Device, 1 = Normal)
532  *  x8  = VA start
533  *  x9  = PA start (trashed)
534  *  x10 = Entry count
535  *  x11, x12 and x13 are trashed
536  */
537 build_l2_block_pagetable:
538         /*
539          * Build the L2 table entry.
540          */
541         /* Find the table index */
542         lsr     x11, x8, #L2_SHIFT
543         and     x11, x11, #Ln_ADDR_MASK
544
545         /* Build the L2 block entry */
546         lsl     x12, x7, #2
547         orr     x12, x12, #L2_BLOCK
548         orr     x12, x12, #(ATTR_AF)
549 #ifdef SMP
550         orr     x12, x12, ATTR_SH(ATTR_SH_IS)
551 #endif
552
553         /* Only use the output address bits */
554         lsr     x9, x9, #L2_SHIFT
555
556         /* Set the physical address for this virtual address */
557 1:      orr     x13, x12, x9, lsl #L2_SHIFT
558
559         /* Store the entry */
560         str     x13, [x6, x11, lsl #3]
561
562         sub     x10, x10, #1
563         add     x11, x11, #1
564         add     x9, x9, #1
565         cbnz    x10, 1b
566
567         ret
568
569 start_mmu:
570         dsb     sy
571
572         /* Load the exception vectors */
573         ldr     x2, =exception_vectors
574         msr     vbar_el1, x2
575
576         /* Load ttbr0 and ttbr1 */
577         msr     ttbr0_el1, x27
578         msr     ttbr1_el1, x24
579         isb
580
581         /* Clear the Monitor Debug System control register */
582         msr     mdscr_el1, xzr
583
584         /* Invalidate the TLB */
585         tlbi    vmalle1is
586
587         ldr     x2, mair
588         msr     mair_el1, x2
589
590         /*
591          * Setup TCR according to PARange bits from ID_AA64MMFR0_EL1.
592          */
593         ldr     x2, tcr
594         mrs     x3, id_aa64mmfr0_el1
595         bfi     x2, x3, #32, #3
596         msr     tcr_el1, x2
597
598         /* Setup SCTLR */
599         ldr     x2, sctlr_set
600         ldr     x3, sctlr_clear
601         mrs     x1, sctlr_el1
602         bic     x1, x1, x3      /* Clear the required bits */
603         orr     x1, x1, x2      /* Set the required bits */
604         msr     sctlr_el1, x1
605         isb
606
607         ret
608
609         .align 3
610 mair:
611                 /* Device            Normal, no cache     Normal, write-back */
612         .quad   MAIR_ATTR(0x00, 0) | MAIR_ATTR(0x44, 1) | MAIR_ATTR(0xff, 2)
613 tcr:
614         .quad (TCR_TxSZ(64 - VIRT_BITS) | TCR_ASID_16 | TCR_TG1_4K | \
615             TCR_CACHE_ATTRS | TCR_SMP_ATTRS)
616 sctlr_set:
617         /* Bits to set */
618         .quad (SCTLR_UCI | SCTLR_nTWE | SCTLR_nTWI | SCTLR_UCT | SCTLR_DZE | \
619             SCTLR_I | SCTLR_SED | SCTLR_SA0 | SCTLR_SA | SCTLR_C | SCTLR_M)
620 sctlr_clear:
621         /* Bits to clear */
622         .quad (SCTLR_EE | SCTLR_EOE | SCTLR_WXN | SCTLR_UMA | SCTLR_ITD | \
623             SCTLR_THEE | SCTLR_CP15BEN | SCTLR_A)
624
625         .globl abort
626 abort:
627         b abort
628
629         //.section .init_pagetable
630         .align 12 /* 4KiB aligned */
631         /*
632          * 3 initial tables (in the following order):
633          *           L2 for kernel (High addresses)
634          *           L1 for kernel
635          *           L1 for user   (Low addresses)
636          */
637 pagetable:
638         .space  PAGE_SIZE
639 pagetable_l1_ttbr1:
640         .space  PAGE_SIZE
641 pagetable_l0_ttbr1:
642         .space  PAGE_SIZE
643 pagetable_l1_ttbr0:
644         .space  PAGE_SIZE
645 pagetable_l0_ttbr0:
646         .space  PAGE_SIZE
647 pagetable_end:
648
649 el2_pagetable:
650         .space  PAGE_SIZE
651
652         .globl init_pt_va
653 init_pt_va:
654         .quad pagetable         /* XXX: Keep page tables VA */
655
656         .align  4
657 initstack:
658         .space  (PAGE_SIZE * KSTACK_PAGES)
659 initstack_end:
660
661
662 ENTRY(sigcode)
663         mov     x0, sp
664         add     x0, x0, #SF_UC
665
666 1:
667         mov     x8, #SYS_sigreturn
668         svc     0
669
670         /* sigreturn failed, exit */
671         mov     x8, #SYS_exit
672         svc     0
673
674         b       1b
675 END(sigcode)
676         /* This may be copied to the stack, keep it 16-byte aligned */
677         .align  3
678 esigcode:
679
680         .data
681         .align  3
682         .global szsigcode
683 szsigcode:
684         .quad   esigcode - sigcode