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.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 /*      $NetBSD: locore.S,v 1.14 2003/04/20 16:21:40 thorpej Exp $      */
    2 
    3 /*-
    4  * Copyright (C) 1994-1997 Mark Brinicombe
    5  * Copyright (C) 1994 Brini
    6  * All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  * 3. All advertising materials mentioning features or use of this software
   17  *    must display the following acknowledgement:
   18  *      This product includes software developed by Brini.
   19  * 4. The name of Brini may not be used to endorse or promote products
   20  *    derived from this software without specific prior written permission.
   21  *
   22  * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR
   23  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   24  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   25  * IN NO EVENT SHALL BRINI BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   26  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   27  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
   28  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
   29  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
   30  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
   31  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   32  *
   33  */
   34 
   35 #include "assym.s"
   36 #include <sys/syscall.h>
   37 #include <machine/asm.h>
   38 #include <machine/armreg.h>
   39 #include <machine/pte.h>
   40 __FBSDID("$FreeBSD$");
   41 
   42 /* What size should this really be ? It is only used by init_arm() */
   43 #define INIT_ARM_STACK_SIZE     2048
   44 
   45 /*
   46  * This is for kvm_mkdb, and should be the address of the beginning
   47  * of the kernel text segment (not necessarily the same as kernbase).
   48  */
   49 
   50 
   51 #define CPWAIT_BRANCH                                                    \
   52         sub     pc, pc, #4
   53 
   54 #define CPWAIT(tmp)                                                      \
   55         mrc     p15, 0, tmp, c2, c0, 0  /* arbitrary read of CP15 */    ;\
   56         mov     tmp, tmp                /* wait for it to complete */   ;\
   57         CPWAIT_BRANCH                   /* branch to next insn */
   58 
   59         .text
   60         .align  0
   61 .globl kernbase
   62 .set kernbase,KERNBASE
   63 .globl physaddr
   64 .set physaddr,PHYSADDR
   65 
   66 ENTRY_NP(btext)
   67 
   68 ASENTRY_NP(_start)
   69 #if defined (FLASHADDR) && defined(LOADERRAMADDR)
   70         /* Check if we're running from flash. */
   71         ldr     r7, =FLASHADDR
   72         /* 
   73          * If we're running with MMU disabled, test against the
   74          * physical address instead.
   75          */
   76         mrc     p15, 0, r2, c1, c0, 0
   77         ands    r2, r2, #CPU_CONTROL_MMU_ENABLE
   78         ldreq   r8, =PHYSADDR
   79         ldrne   r8, =LOADERRAMADDR
   80         cmp     r7, r8
   81         bls     flash_lower
   82         cmp     r7, pc
   83         bhi     from_ram
   84         b       do_copy
   85         
   86 flash_lower:
   87         cmp     r8, pc
   88         bls     from_ram
   89 do_copy:
   90         ldr     r9, =KERNBASE
   91         adr     r1, _start 
   92         ldr     r0, Lreal_start
   93         ldr     r2, Lend
   94         sub     r2, r2, r0
   95         sub     r0, r0, r9
   96         add     r0, r0, r8
   97         mov     r4, r0
   98         bl      memcpy
   99         ldr     r0, Lram_offset
  100         add     pc, r4, r0
  101 Lram_offset:    .word from_ram-_C_LABEL(_start)
  102 from_ram:
  103         nop
  104 #endif
  105         adr     r7, Lunmapped
  106         bic     r7, r7, #0xff000000
  107         orr     r7, r7, #PHYSADDR
  108                         
  109 
  110 disable_mmu:
  111         /* Disable MMU for a while */
  112         mrc     p15, 0, r2, c1, c0, 0
  113         bic     r2, r2, #(CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_DC_ENABLE |\
  114             CPU_CONTROL_WBUF_ENABLE)
  115         bic     r2, r2, #(CPU_CONTROL_IC_ENABLE)
  116         bic     r2, r2, #(CPU_CONTROL_BPRD_ENABLE)
  117         mcr     p15, 0, r2, c1, c0, 0
  118 
  119         nop
  120         nop
  121         nop
  122         mov     pc, r7
  123 Lunmapped:
  124 #ifdef STARTUP_PAGETABLE_ADDR
  125         /* build page table from scratch */
  126         ldr     r0, Lstartup_pagetable
  127         adr     r4, mmu_init_table
  128         b       3f
  129 
  130 2:
  131         str     r3, [r0, r2]
  132         add     r2, r2, #4
  133         add     r3, r3, #(L1_S_SIZE)
  134         adds    r1, r1, #-1
  135         bhi     2b
  136 3:
  137         ldmia   r4!, {r1,r2,r3}   /* # of sections, PA|attr, VA */
  138         cmp     r1, #0
  139         adrne   r5, 2b
  140         bicne   r5, r5, #0xff000000
  141         orrne   r5, r5, #PHYSADDR
  142         movne   pc, r5
  143 
  144         mcr     p15, 0, r0, c2, c0, 0   /* Set TTB */
  145         mcr     p15, 0, r0, c8, c7, 0   /* Flush TLB */
  146 
  147         /* Set the Domain Access register.  Very important! */
  148         mov     r0, #((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT)
  149         mcr     p15, 0, r0, c3, c0, 0
  150         /* Enable MMU */
  151         mrc     p15, 0, r0, c1, c0, 0
  152         orr     r0, r0, #CPU_CONTROL_MMU_ENABLE
  153         mcr     p15, 0, r0, c1, c0, 0
  154         nop
  155         nop
  156         nop
  157         CPWAIT(r0)
  158 
  159 #endif
  160 mmu_done:
  161         nop
  162         adr     r1, .Lstart
  163         ldmia   r1, {r1, r2, sp}        /* Set initial stack and */
  164         sub     r2, r2, r1              /* get zero init data */
  165         mov     r3, #0
  166 .L1:
  167         str     r3, [r1], #0x0004       /* get zero init data */
  168         subs    r2, r2, #4
  169         bgt     .L1
  170         ldr     pc, .Lvirt_done
  171 
  172 virt_done:
  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         adr     r0, .Lmainreturned
  182         b       _C_LABEL(panic)
  183         /* NOTEACHED */
  184 #ifdef STARTUP_PAGETABLE_ADDR
  185 #define MMU_INIT(va,pa,n_sec,attr) \
  186         .word   n_sec                                       ; \
  187         .word   4*((va)>>L1_S_SHIFT)                        ; \
  188         .word   (pa)|(attr)                                 ;
  189 
  190 Lvirtaddr:
  191         .word   KERNVIRTADDR
  192 Lphysaddr:
  193         .word   KERNPHYSADDR
  194 Lreal_start:
  195         .word   _start
  196 Lend:   
  197         .word   _edata
  198 Lstartup_pagetable:
  199         .word   STARTUP_PAGETABLE_ADDR
  200 mmu_init_table:
  201         /* fill all table VA==PA */
  202         /* map SDRAM VA==PA, WT cacheable */
  203         MMU_INIT(PHYSADDR, PHYSADDR , 64, L1_TYPE_S|L1_S_C|L1_S_AP(AP_KRW))
  204         /* map VA 0xc0000000..0xc3ffffff to PA */
  205         MMU_INIT(KERNBASE, PHYSADDR, 64, L1_TYPE_S|L1_S_C|L1_S_AP(AP_KRW))
  206 
  207         .word 0 /* end of table */
  208 #endif
  209 .Lstart:
  210         .word   _edata
  211         .word   _end
  212         .word   svcstk + INIT_ARM_STACK_SIZE
  213 
  214 .Lvirt_done:
  215         .word   virt_done
  216 .Lmainreturned:
  217         .asciz  "main() returned"
  218         .align  0
  219 
  220         .bss
  221 svcstk:
  222         .space  INIT_ARM_STACK_SIZE
  223 
  224         .text
  225         .align  0
  226 
  227 #ifndef OFW
  228         /* OFW based systems will used OF_boot() */
  229 
  230 .Lcpufuncs:
  231         .word   _C_LABEL(cpufuncs)
  232 
  233 ENTRY_NP(cpu_halt)
  234         mrs     r2, cpsr
  235         bic     r2, r2, #(PSR_MODE)
  236         orr     r2, r2, #(PSR_SVC32_MODE)
  237         orr     r2, r2, #(I32_bit | F32_bit)
  238         msr     cpsr_all, r2
  239 
  240         ldr     r4, .Lcpu_reset_address
  241         ldr     r4, [r4]
  242 
  243         ldr     r0, .Lcpufuncs
  244         mov     lr, pc
  245         ldr     pc, [r0, #CF_IDCACHE_WBINV_ALL]
  246 
  247         /*
  248          * Load the cpu_reset_needs_v4_MMU_disable flag to determine if it's
  249          * necessary.
  250          */
  251 
  252         ldr     r1, .Lcpu_reset_needs_v4_MMU_disable
  253         ldr     r1, [r1]
  254         cmp     r1, #0
  255         mov     r2, #0
  256 
  257         /*
  258          * MMU & IDC off, 32 bit program & data space
  259          * Hurl ourselves into the ROM
  260          */
  261         mov     r0, #(CPU_CONTROL_32BP_ENABLE | CPU_CONTROL_32BD_ENABLE)
  262         mcr     15, 0, r0, c1, c0, 0
  263         mcrne   15, 0, r2, c8, c7, 0    /* nail I+D TLB on ARMv4 and greater */
  264         mov     pc, r4
  265 
  266         /*
  267          * _cpu_reset_address contains the address to branch to, to complete
  268          * the cpu reset after turning the MMU off
  269          * This variable is provided by the hardware specific code
  270          */
  271 .Lcpu_reset_address:
  272         .word   _C_LABEL(cpu_reset_address)
  273 
  274         /*
  275          * cpu_reset_needs_v4_MMU_disable contains a flag that signals if the
  276          * v4 MMU disable instruction needs executing... it is an illegal instruction
  277          * on f.e. ARM6/7 that locks up the computer in an endless illegal
  278          * instruction / data-abort / reset loop.
  279          */
  280 .Lcpu_reset_needs_v4_MMU_disable:
  281         .word   _C_LABEL(cpu_reset_needs_v4_MMU_disable)
  282 
  283 #endif  /* OFW */
  284 
  285 #ifdef IPKDB
  286 /*
  287  * Execute(inst, psr, args, sp)
  288  *
  289  * Execute INSTruction with PSR and ARGS[0] - ARGS[3] making
  290  * available stack at SP for next undefined instruction trap.
  291  *
  292  * Move the instruction onto the stack and jump to it.
  293  */
  294 ENTRY_NP(Execute)
  295         mov     ip, sp
  296         stmfd   sp!, {r2, r4-r7, fp, ip, lr, pc}
  297         sub     fp, ip, #4
  298         mov     ip, r3
  299         ldr     r7, .Lreturn
  300         stmfd   sp!, {r0, r7}
  301         adr     r7, #.LExec
  302         mov     r5, r1
  303         mrs     r4, cpsr
  304         ldmia   r2, {r0-r3}
  305         mov     r6, sp
  306         mov     sp, ip
  307         msr     cpsr_all, r5
  308         mov     pc, r6
  309 .LExec:
  310         mrs     r5, cpsr
  311 /* XXX Cannot switch thus easily back from user mode */
  312         msr     cpsr_all, r4
  313         add     sp, r6, #8
  314         ldmfd   sp!, {r6}
  315         stmia   r6, {r0-r3}
  316         mov     r0, r5
  317         ldmdb   fp, {r4-r7, fp, sp, pc}
  318 .Lreturn:
  319         mov     pc, r7
  320 #endif
  321 
  322 /*
  323  * setjump + longjmp
  324  */
  325 ENTRY(setjmp)
  326         stmia   r0, {r4-r14}
  327         mov     r0, #0x00000000
  328         RET
  329 
  330 ENTRY(longjmp)
  331         ldmia   r0, {r4-r14}
  332         mov     r0, #0x00000001
  333         RET
  334 
  335         .data
  336         .global _C_LABEL(esym)
  337 _C_LABEL(esym): .word   _C_LABEL(end)
  338 
  339 ENTRY_NP(abort)
  340         b       _C_LABEL(abort)
  341 
  342 ENTRY_NP(sigcode)
  343         mov     r0, sp
  344         swi     SYS_sigreturn
  345 
  346         /* Well if that failed we better exit quick ! */
  347 
  348         swi     SYS_exit
  349         b       . - 8
  350 
  351         .align  0
  352         .global _C_LABEL(esigcode)
  353                 _C_LABEL(esigcode):
  354 
  355         .data
  356         .global szsigcode
  357 szsigcode:
  358         .long esigcode-sigcode
  359 /* End of locore.S */

Cache object: 561f7cc7bac9bb8b5a61630401a16d39


[ 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.