The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/arm/arm/locore-v6.S

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright 2004-2014 Olivier Houchard <cognet@FreeBSD.org>
    3  * Copyright 2012-2014 Ian Lepore <ian@FreeBSD.org>
    4  * Copyright 2013-2014 Andrew Turner <andrew@FreeBSD.org>
    5  * Copyright 2014 Svatopluk Kraus <onwahe@gmail.com>
    6  * Copyright 2014 Michal Meloun <meloun@miracle.cz>
    7  * All rights reserved.
    8  *
    9  * Redistribution and use in source and binary forms, with or without
   10  * modification, are permitted provided that the following conditions
   11  * are met:
   12  * 1. Redistributions of source code must retain the above copyright
   13  *    notice, this list of conditions and the following disclaimer.
   14  * 2. Redistributions in binary form must reproduce the above copyright
   15  *    notice, this list of conditions and the following disclaimer in the
   16  *    documentation and/or other materials provided with the distribution.
   17  *
   18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   28  * SUCH DAMAGE.
   29  */
   30 
   31 #include "assym.s"
   32 #include <sys/syscall.h>
   33 #include <machine/asm.h>
   34 #include <machine/asmacros.h>
   35 #include <machine/armreg.h>
   36 #include <machine/sysreg.h>
   37 #include <machine/cpuconf.h>
   38 #include <machine/pte.h>
   39 
   40 __FBSDID("$FreeBSD: releng/10.2/sys/arm/arm/locore-v6.S 278702 2015-02-13 20:23:06Z ian $");
   41 
   42 #ifndef ARM_NEW_PMAP
   43 #define PTE1_OFFSET     L1_S_OFFSET
   44 #define PTE1_SHIFT      L1_S_SHIFT
   45 #define PTE1_SIZE       L1_S_SIZE
   46 #endif
   47 
   48 /* A small statically-allocated stack used only during initarm() and AP startup. */
   49 #define INIT_ARM_STACK_SIZE     2048
   50 
   51         .text
   52         .align  2
   53 
   54 /*
   55  * On entry for FreeBSD boot ABI:
   56  *      r0 - metadata pointer or 0 (boothowto on AT91's boot2)
   57  *      r1 - if (r0 == 0) then metadata pointer
   58  * On entry for Linux boot ABI:
   59  *      r0 - 0
   60  *      r1 - machine type (passed as arg2 to initarm)
   61  *      r2 - Pointer to a tagged list or dtb image (phys addr) (passed as arg1 initarm)
   62  *
   63  * For both types of boot we gather up the args, put them in a struct arm_boot_params
   64  * structure and pass that to initarm.
   65  */
   66         .globl  btext
   67 btext:
   68 ASENTRY_NP(_start)
   69         STOP_UNWINDING          /* Can't unwind into the bootloader! */
   70 
   71         /* Make sure interrupts are disabled. */
   72         cpsid   ifa
   73 
   74         mov     r8, r0          /* 0 or boot mode from boot2 */
   75         mov     r9, r1          /* Save Machine type */
   76         mov     r10, r2         /* Save meta data */
   77         mov     r11, r3         /* Future expansion */
   78 
   79         /* 
   80          * Check whether data cache is enabled.  If it is, then we know
   81          * current tags are valid (not power-on garbage values) and there
   82          * might be dirty lines that need cleaning.  Disable cache to prevent
   83          * new lines being allocated, then call wbinv_poc_all to clean it.
   84          */
   85         mrc     CP15_SCTLR(r7)
   86         tst     r7, #CPU_CONTROL_DC_ENABLE
   87         blne    dcache_wbinv_poc_all
   88 
   89         /* ! Do not write to memory between wbinv and disabling cache ! */
   90 
   91         /*
   92          * Now there are no dirty lines, but there may still be lines marked
   93          * valid.  Disable all caches and the MMU, and invalidate everything
   94          * before setting up new page tables and re-enabling the mmu.
   95          */
   96 1:      
   97         bic     r7, #CPU_CONTROL_DC_ENABLE
   98         bic     r7, #CPU_CONTROL_MMU_ENABLE
   99         bic     r7, #CPU_CONTROL_IC_ENABLE
  100         bic     r7, #CPU_CONTROL_UNAL_ENABLE
  101         bic     r7, #CPU_CONTROL_BPRD_ENABLE
  102         bic     r7, #CPU_CONTROL_SW_ENABLE
  103         orr     r7, #CPU_CONTROL_AFLT_ENABLE
  104         orr     r7, #CPU_CONTROL_VECRELOC
  105         mcr     CP15_SCTLR(r7)
  106         ISB
  107         bl      dcache_inv_poc_all
  108         mcr     CP15_ICIALLU
  109         ISB
  110 
  111         /*
  112          * Build page table from scratch.
  113          */
  114 
  115         /* Calculate the physical address of the startup pagetable. */
  116         adr     r0, Lpagetable
  117         bl      translate_va_to_pa
  118 
  119         /*
  120          * Map PA == VA
  121          */
  122         /* Find the start kernels load address */
  123         adr     r5, _start
  124         ldr     r2, =(PTE1_OFFSET)
  125         bic     r5, r2
  126         mov     r1, r5
  127         mov     r2, r5
  128         /* Map 64MiB, preserved over calls to build_pagetables */
  129         mov     r3, #64
  130         bl      build_pagetables
  131 
  132         /* Create the kernel map to jump to */
  133         mov     r1, r5
  134         ldr     r2, =(KERNVIRTADDR)
  135         bl      build_pagetables
  136 
  137 #if defined(SOCDEV_PA) && defined(SOCDEV_VA)
  138         /* Create the custom map used for early_printf(). */
  139         ldr     r1, =SOCDEV_PA
  140         ldr     r2, =SOCDEV_VA
  141         bl      build_pagetables
  142 #endif
  143         bl      init_mmu
  144 
  145         /* Switch to virtual addresses. */
  146         ldr     pc, =1f
  147 1:
  148 
  149         /* Setup stack, clear BSS */
  150         ldr     r1, =.Lstart
  151         ldmia   r1, {r1, r2, sp}        /* Set initial stack and */
  152         add     sp, sp, #INIT_ARM_STACK_SIZE
  153         sub     r2, r2, r1              /* get zero init data */
  154         mov     r3, #0
  155 2:
  156         str     r3, [r1], #0x0004       /* get zero init data */
  157         subs    r2, r2, #4
  158         bgt     2b
  159 
  160         mov     r1, #28                 /* loader info size is 28 bytes also second arg */
  161         subs    sp, sp, r1              /* allocate arm_boot_params struct on stack */
  162         mov     r0, sp                  /* loader info pointer is first arg */
  163         bic     sp, sp, #7              /* align stack to 8 bytes */
  164         str     r1, [r0]                /* Store length of loader info */
  165         str     r8, [r0, #4]            /* Store r0 from boot loader */
  166         str     r9, [r0, #8]            /* Store r1 from boot loader */
  167         str     r10, [r0, #12]          /* store r2 from boot loader */
  168         str     r11, [r0, #16]          /* store r3 from boot loader */
  169         str     r5, [r0, #20]           /* store the physical address */
  170         adr     r4, Lpagetable          /* load the pagetable address */
  171         ldr     r5, [r4, #4]
  172         str     r5, [r0, #24]           /* store the pagetable address */
  173         mov     fp, #0                  /* trace back starts here */
  174         bl      _C_LABEL(initarm)       /* Off we go */
  175 
  176         /* init arm will return the new stack pointer. */
  177         mov     sp, r0
  178 
  179         bl      _C_LABEL(mi_startup)    /* call mi_startup()! */
  180 
  181         ldr     r0, =.Lmainreturned
  182         b       _C_LABEL(panic)
  183         /* NOTREACHED */
  184 END(_start)
  185 
  186 #define VA_TO_PA_POINTER(name, table)    \
  187 name:                                   ;\
  188         .word   .                       ;\
  189         .word   table
  190 
  191 /*
  192  * Returns the physical address of a magic va to pa pointer.
  193  * r0     - The pagetable data pointer. This must be built using the
  194  *          VA_TO_PA_POINTER macro.
  195  *          e.g.
  196  *            VA_TO_PA_POINTER(Lpagetable, pagetable)
  197  *            ...
  198  *            adr  r0, Lpagetable
  199  *            bl   translate_va_to_pa
  200  *            r0 will now contain the physical address of pagetable
  201  * r1, r2 - Trashed
  202  */
  203 translate_va_to_pa:
  204         ldr     r1, [r0]
  205         sub     r2, r1, r0
  206         /* At this point: r2 = VA - PA */
  207 
  208         /*
  209          * Find the physical address of the table. After these two
  210          * instructions:
  211          * r1 = va(pagetable)
  212          *
  213          * r0 = va(pagetable) - (VA - PA)
  214          *    = va(pagetable) - VA + PA
  215          *    = pa(pagetable)
  216          */
  217         ldr     r1, [r0, #4]
  218         sub     r0, r1, r2
  219         mov     pc, lr
  220 
  221 /*
  222  * Init MMU
  223  * r0 - The table base address
  224  */
  225 
  226 ASENTRY_NP(init_mmu)
  227 
  228         /* Setup TLB and MMU registers */
  229         mcr     CP15_TTBR0(r0)          /* Set TTB */
  230         mov     r0, #0
  231         mcr     CP15_CONTEXTIDR(r0)     /* Set ASID to 0 */
  232 
  233         /* Set the Domain Access register */
  234         mov     r0, #((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT)
  235         mcr     CP15_DACR(r0)
  236 
  237 #ifdef ARM_NEW_PMAP
  238         /*
  239          * Set TEX remap registers
  240          *  - All is set to uncacheable memory
  241          */
  242         ldr     r0, =0xAAAAA
  243         mrc     CP15_PRRR(r0)
  244         mov     r0, #0
  245         mcr     CP15_NMRR(r0)
  246 #endif
  247         mcr     CP15_TLBIALL            /* Flush TLB */
  248         DSB
  249         ISB
  250 
  251         /* Enable MMU */
  252         mrc     CP15_SCTLR(r0)
  253         orr     r0, r0, #CPU_CONTROL_MMU_ENABLE
  254         orr     r0, r0, #CPU_CONTROL_V6_EXTPAGE
  255 #ifdef ARM_NEW_PMAP
  256         orr     r0, r0, #CPU_CONTROL_TR_ENABLE
  257 #endif
  258         orr     r0, r0, #CPU_CONTROL_AF_ENABLE
  259         mcr     CP15_SCTLR(r0)
  260         DSB
  261         ISB
  262         mcr     CP15_TLBIALL            /* Flush TLB */
  263         mcr     CP15_BPIALL             /* Flush Branch predictor */
  264         ISB
  265         mov     pc, lr
  266 END(init_mmu)
  267 
  268 
  269 /*
  270  * Init SMP coherent mode, enable caching and switch to final MMU table.
  271  * Called with disabled caches
  272  * r0 - The table base address
  273  * r1 - clear bits for aux register
  274  * r2 - set bits for aux register
  275  */
  276 ASENTRY_NP(reinit_mmu)
  277         push    {r4-r11, lr}
  278         mov     r4, r0
  279         mov     r5, r1
  280         mov     r6, r2
  281 
  282         /* !! Be very paranoid here !! */
  283         /* !! We cannot write single bit here !! */
  284 
  285 #if 0   /* XXX writeback shouldn't be necessary */
  286         /* Write back and invalidate all integrated caches */
  287         bl      dcache_wbinv_poc_all
  288 #else
  289         bl      dcache_inv_pou_all
  290 #endif
  291         mcr     CP15_ICIALLU
  292         ISB
  293 
  294         /* Set auxiliary register */
  295         mrc     CP15_ACTLR(r7)
  296         bic     r8, r7, r5              /* Mask bits */
  297         eor     r8, r8, r6              /* Set bits */
  298         teq     r7, r8
  299         mcrne   CP15_ACTLR(r8)
  300         ISB
  301 
  302         /* Enable caches. */
  303         mrc     CP15_SCTLR(r7)
  304         orr     r7, #CPU_CONTROL_DC_ENABLE
  305         orr     r7, #CPU_CONTROL_IC_ENABLE
  306         orr     r7, #CPU_CONTROL_BPRD_ENABLE
  307         mcr     CP15_SCTLR(r7)
  308         DSB
  309 
  310         mcr     CP15_TTBR0(r4)          /* Set new TTB */
  311         DSB
  312         ISB
  313 
  314         /* Flush all TLBs */
  315         mcr     CP15_TLBIALL
  316         DSB
  317         ISB
  318 
  319 #if 0 /* XXX writeback shouldn't be necessary */
  320         /* Write back and invalidate all integrated caches */
  321         bl      dcache_wbinv_poc_all
  322 #else
  323         bl      dcache_inv_pou_all
  324 #endif
  325         mcr     CP15_ICIALLU
  326         ISB
  327 
  328         pop     {r4-r11, pc}
  329 END(reinit_mmu)
  330 
  331 
  332 /*
  333  * Builds the page table
  334  * r0 - The table base address
  335  * r1 - The physical address (trashed)
  336  * r2 - The virtual address (trashed)
  337  * r3 - The number of 1MiB sections
  338  * r4 - Trashed
  339  *
  340  * Addresses must be 1MiB aligned
  341  */
  342 build_pagetables:
  343         /* Set the required page attributed */
  344 #if defined(ARM_NEW_PMAP)
  345         ldr     r4, =PTE1_V|PTE1_A|PTE1_AP_KRW|TEX1_CLASS_0
  346 #elif defined(SMP)
  347         ldr     r4, =(L1_TYPE_S|L1_S_C|L1_S_AP(AP_KRW)|L1_SHARED)
  348 #else
  349         ldr     r4, =(L1_TYPE_S|L1_S_C|L1_S_AP(AP_KRW))
  350 #endif
  351         orr     r1, r4
  352 
  353         /* Move the virtual address to the correct bit location */
  354         lsr     r2, #(PTE1_SHIFT - 2)
  355 
  356         mov     r4, r3
  357 1:
  358         str     r1, [r0, r2]
  359         add     r2, r2, #4
  360         add     r1, r1, #(PTE1_SIZE)
  361         adds    r4, r4, #-1
  362         bhi     1b
  363 
  364         mov     pc, lr
  365 
  366 VA_TO_PA_POINTER(Lpagetable, boot_pt1)
  367 
  368 
  369 .Lstart:
  370         .word   _edata                  /* Note that these three items are */
  371         .word   _ebss                   /* loaded with a single ldmia and */
  372         .word   svcstk                  /* must remain in order together. */
  373 
  374 .Lmainreturned:
  375         .asciz  "main() returned"
  376         .align  2
  377 
  378         .bss
  379 svcstk:
  380         .space  INIT_ARM_STACK_SIZE * MAXCPU
  381 
  382 /*
  383  * Memory for the initial pagetable. We are unable to place this in
  384  * the bss as this will be cleared after the table is loaded.
  385  */
  386         .section ".init_pagetable"
  387         .align  14 /* 16KiB aligned */
  388         .globl  boot_pt1
  389 boot_pt1:
  390         .space  L1_TABLE_SIZE
  391 
  392         .text
  393         .align  2
  394 
  395 .Lcpufuncs:
  396         .word   _C_LABEL(cpufuncs)
  397 
  398 #if defined(SMP)
  399 
  400 ASENTRY_NP(mpentry)
  401         /* Make sure interrupts are disabled. */
  402         cpsid   ifa
  403 
  404         /* Setup core, disable all caches. */
  405         mrc     CP15_SCTLR(r0)
  406         bic     r0, #CPU_CONTROL_MMU_ENABLE
  407         bic     r0, #CPU_CONTROL_DC_ENABLE
  408         bic     r0, #CPU_CONTROL_IC_ENABLE
  409         bic     r0, #CPU_CONTROL_UNAL_ENABLE
  410         bic     r0, #CPU_CONTROL_BPRD_ENABLE
  411         bic     r0, #CPU_CONTROL_SW_ENABLE
  412         orr     r0, #CPU_CONTROL_AFLT_ENABLE
  413         orr     r0, #CPU_CONTROL_VECRELOC
  414         mcr     CP15_SCTLR(r0)
  415         ISB
  416 
  417         /* Invalidate L1 cache I+D cache */
  418         bl      dcache_inv_pou_all
  419         mcr     CP15_ICIALLU
  420         ISB
  421 
  422         /* Find the delta between VA and PA */
  423         adr     r0, Lpagetable
  424         bl      translate_va_to_pa
  425         
  426         bl      init_mmu
  427 
  428         adr     r1, .Lstart+8           /* Get initstack pointer from */
  429         ldr     sp, [r1]                /* startup data. */
  430         mrc     CP15_MPIDR(r0)          /* Get processor id number. */
  431         and     r0, r0, #0x0f
  432         mov     r1, #INIT_ARM_STACK_SIZE
  433         mul     r2, r1, r0              /* Point sp to initstack */
  434         add     sp, sp, r2              /* area for this processor. */
  435 
  436         /* Switch to virtual addresses. */
  437         ldr     pc, =1f
  438 1:
  439         mov     fp, #0                  /* trace back starts here */
  440         bl      _C_LABEL(init_secondary)/* Off we go, cpu id in r0. */
  441 
  442         adr     r0, .Lmpreturned
  443         b       _C_LABEL(panic)
  444         /* NOTREACHED */
  445 END(mpentry)
  446 
  447 .Lmpreturned:
  448         .asciz  "init_secondary() returned"
  449         .align  2
  450 #endif
  451 
  452 ENTRY_NP(cpu_halt)
  453 
  454         /* XXX re-implement !!! */
  455         cpsid   ifa
  456         bl      dcache_wbinv_poc_all
  457 
  458         ldr     r4, .Lcpu_reset_address
  459         ldr     r4, [r4]
  460         teq     r4, #0
  461         movne   pc, r4
  462 1:      
  463         WFI
  464         b       1b
  465 
  466         /*
  467          * _cpu_reset_address contains the address to branch to, to complete
  468          * the cpu reset after turning the MMU off
  469          * This variable is provided by the hardware specific code
  470          */
  471 .Lcpu_reset_address:
  472         .word   _C_LABEL(cpu_reset_address)
  473 END(cpu_halt)
  474 
  475 
  476 /*
  477  * setjump + longjmp
  478  */
  479 ENTRY(setjmp)
  480         stmia   r0, {r4-r14}
  481         mov     r0, #0x00000000
  482         RET
  483 END(setjmp)
  484 
  485 ENTRY(longjmp)
  486         ldmia   r0, {r4-r14}
  487         mov     r0, #0x00000001
  488         RET
  489 END(longjmp)
  490 
  491         .data
  492         .global _C_LABEL(esym)
  493 _C_LABEL(esym): .word   _C_LABEL(end)
  494 
  495 ENTRY_NP(abort)
  496         b       _C_LABEL(abort)
  497 END(abort)
  498 
  499 ENTRY_NP(sigcode)
  500         mov     r0, sp
  501         add     r0, r0, #SIGF_UC
  502 
  503         /*
  504          * Call the sigreturn system call.
  505          *
  506          * We have to load r7 manually rather than using
  507          * "ldr r7, =SYS_sigreturn" to ensure the value of szsigcode is
  508          * correct. Using the alternative places esigcode at the address
  509          * of the data rather than the address one past the data.
  510          */
  511 
  512         ldr     r7, [pc, #12]   /* Load SYS_sigreturn */
  513         swi     SYS_sigreturn
  514 
  515         /* Well if that failed we better exit quick ! */
  516 
  517         ldr     r7, [pc, #8]    /* Load SYS_exit */
  518         swi     SYS_exit
  519 
  520         /* Branch back to retry SYS_sigreturn */
  521         b       . - 16
  522 END(sigcode)
  523 
  524         .word   SYS_sigreturn
  525         .word   SYS_exit
  526 
  527         .align  2
  528         .global _C_LABEL(esigcode)
  529                 _C_LABEL(esigcode):
  530 
  531         .data
  532         .global szsigcode
  533 szsigcode:
  534         .long esigcode-sigcode
  535 
  536 /* End of locore.S */

Cache object: 1f1db19e428c3b178c92fc53549bb0f6


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.