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/riscv/riscv/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 /*-
    2  * Copyright (c) 2015-2018 Ruslan Bukin <br@bsdpad.com>
    3  * All rights reserved.
    4  *
    5  * Portions of this software were developed by SRI International and the
    6  * University of Cambridge Computer Laboratory under DARPA/AFRL contract
    7  * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
    8  *
    9  * Portions of this software were developed by the University of Cambridge
   10  * Computer Laboratory as part of the CTSRD Project, with support from the
   11  * UK Higher Education Innovation Fund (HEIF).
   12  *
   13  * Redistribution and use in source and binary forms, with or without
   14  * modification, are permitted provided that the following conditions
   15  * are met:
   16  * 1. Redistributions of source code must retain the above copyright
   17  *    notice, this list of conditions and the following disclaimer.
   18  * 2. Redistributions in binary form must reproduce the above copyright
   19  *    notice, this list of conditions and the following disclaimer in the
   20  *    documentation and/or other materials provided with the distribution.
   21  *
   22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   32  * SUCH DAMAGE.
   33  *
   34  * $FreeBSD$
   35  */
   36 
   37 #include "assym.inc"
   38 
   39 #include <sys/syscall.h>
   40 #include <machine/asm.h>
   41 #include <machine/param.h>
   42 #include <machine/trap.h>
   43 #include <machine/riscvreg.h>
   44 #include <machine/pte.h>
   45 
   46         .globl  kernbase
   47         .set    kernbase, KERNBASE
   48 
   49         .text
   50 /*
   51  * Alternate entry point. Used when booting via SBI firmware. It must be placed
   52  * at the beginning of the .text section. Arguments are as follows:
   53  *  - a0 = hart ID
   54  *  - a1 = dtbp
   55  *
   56  * Multiple CPUs might enter from this point, so we perform a hart lottery and
   57  * send the losers to mpentry.
   58  */
   59         .globl _alt_start
   60 _alt_start:
   61         /* Set the global pointer */
   62 .option push
   63 .option norelax
   64         lla     gp, __global_pointer$
   65 .option pop
   66 
   67         /* Pick a hart to run the boot process. */
   68         lla     t0, hart_lottery
   69         li      t1, 1
   70         amoadd.w t0, t1, 0(t0)
   71 
   72         /*
   73          * We must jump to mpentry in the non-BSP case because the offset is
   74          * too large to fit in a 12-bit branch immediate.
   75          */
   76         beqz    t0, 1f
   77         j       mpentry
   78 1:
   79         /* Store the boot hart */
   80         lla     t0, boot_hart
   81         sw      a0, 0(t0)
   82 
   83         /* Load zero as modulep */
   84         mv      a0, zero
   85         j       pagetables
   86 
   87 /*
   88  * Main entry point. This routine is marked as the ELF entry, and is where
   89  * loader(8) will enter the kernel. Arguments are as follows:
   90  *  - a0 = modulep
   91  *  - a1 = ???
   92  *
   93  * It is expected that only a single CPU will enter here.
   94  */
   95         .globl _start
   96 _start:
   97         /* Set the global pointer */
   98 .option push
   99 .option norelax
  100         lla     gp, __global_pointer$
  101 .option pop
  102 
  103         /*
  104          * Zero a1 to indicate that we have no DTB pointer. It is already
  105          * included in the loader(8) metadata.
  106          */
  107         mv      a1, zero
  108 
  109         /*
  110          * Set up page tables: map a 1GB region starting at KERNBASE using 2MB
  111          * superpages, starting from the first 2MB physical page into which the
  112          * kernel was loaded.  Also reserve an L2 page for the early device map
  113          * and map the DTB, if any, using the second-last entry of that L2
  114          * page.  This is hopefully enough to get us to pmap_bootstrap().
  115          *
  116          * Implementations are required to provide SV39 mode, so we use that
  117          * initially and will optionally enable SV48 mode during kernel pmap
  118          * initialization.
  119          *
  120          *  a0 - modulep or zero
  121          *  a1 - zero or dtbp
  122          */
  123 pagetables:
  124         /* Get the kernel's load address */
  125         jal     get_physmem
  126 
  127         /* Add L1 entry for kernel */
  128         lla     s1, pagetable_l1
  129         lla     s2, pagetable_l2        /* Link to next level PN */
  130         srli    s2, s2, PAGE_SHIFT
  131 
  132         li      a5, KERNBASE
  133         srli    a5, a5, L1_SHIFT        /* >> L1_SHIFT */
  134         andi    a5, a5, Ln_ADDR_MASK    /* & Ln_ADDR_MASK */
  135         li      t4, PTE_V
  136         slli    t5, s2, PTE_PPN0_S      /* (s2 << PTE_PPN0_S) */
  137         or      t6, t4, t5
  138 
  139         /* Store L1 PTE entry to position */
  140         li      a6, PTE_SIZE
  141         mulw    a5, a5, a6
  142         add     t0, s1, a5
  143         sd      t6, (t0)
  144 
  145         /* Level 2 superpages (512 x 2MiB) */
  146         lla     s1, pagetable_l2
  147         srli    t4, s9, L2_SHIFT        /* Div physmem base by 2 MiB */
  148         li      t2, 512                 /* Build 512 entries */
  149         add     t3, t4, t2
  150         li      t0, (PTE_KERN | PTE_X)
  151 1:
  152         slli    t2, t4, PTE_PPN1_S      /* << PTE_PPN1_S */
  153         or      t5, t0, t2
  154         sd      t5, (s1)                /* Store PTE entry to position */
  155         addi    s1, s1, PTE_SIZE
  156 
  157         addi    t4, t4, 1
  158         bltu    t4, t3, 1b
  159 
  160         /* Create an L1 table entry for early devmap */
  161         lla     s1, pagetable_l1
  162         lla     s2, pagetable_l2_devmap /* Link to next level PN */
  163         srli    s2, s2, PAGE_SHIFT
  164 
  165         li      a5, (VM_MAX_KERNEL_ADDRESS - L2_SIZE)
  166         srli    a5, a5, L1_SHIFT        /* >> L1_SHIFT */
  167         andi    a5, a5, Ln_ADDR_MASK    /* & Ln_ADDR_MASK */
  168         li      t4, PTE_V
  169         slli    t5, s2, PTE_PPN0_S      /* (s2 << PTE_PPN0_S) */
  170         or      t6, t4, t5
  171 
  172         /* Store the L1 table entry */
  173         li      a6, PTE_SIZE
  174         mulw    a5, a5, a6
  175         add     t0, s1, a5
  176         sd      t6, (t0)
  177 
  178         /* Check if we have a DTB that needs to be mapped */
  179         beqz    a1, 2f
  180 
  181         /* Create an L2 mapping for the DTB */
  182         lla     s1, pagetable_l2_devmap
  183         mv      s2, a1
  184         srli    s2, s2, PAGE_SHIFT
  185         /* Mask off any bits that aren't aligned */
  186         andi    s2, s2, ~((1 << (PTE_PPN1_S - PTE_PPN0_S)) - 1)
  187 
  188         li      t0, (PTE_KERN)
  189         slli    t2, s2, PTE_PPN0_S      /* << PTE_PPN0_S */
  190         or      t0, t0, t2
  191 
  192         /* Store the L2 table entry for the DTB */
  193         li      a6, PTE_SIZE
  194         li      a5, 510
  195         mulw    a5, a5, a6
  196         add     t1, s1, a5
  197         sd      t0, (t1)
  198 
  199         /* Page tables END */
  200 
  201         /* Setup supervisor trap vector */
  202 2:
  203         lla     t0, va
  204         sub     t0, t0, s9
  205         li      t1, KERNBASE
  206         add     t0, t0, t1
  207         csrw    stvec, t0
  208 
  209         /* Set page tables base register */
  210         lla     s2, pagetable_l1
  211         srli    s2, s2, PAGE_SHIFT
  212         li      t0, SATP_MODE_SV39
  213         or      s2, s2, t0
  214         sfence.vma
  215         csrw    satp, s2
  216 
  217         .align 2
  218 va:
  219         /* Set the global pointer again, this time with the virtual address. */
  220 .option push
  221 .option norelax
  222         lla     gp, __global_pointer$
  223 .option pop
  224 
  225         /* Setup supervisor trap vector */
  226         la      t0, cpu_exception_handler
  227         csrw    stvec, t0
  228 
  229         /* Ensure sscratch is zero */
  230         li      t0, 0
  231         csrw    sscratch, t0
  232 
  233         /* Initialize stack pointer */
  234         la      sp, initstack_end
  235 
  236         /* Clear frame pointer */
  237         mv      s0, zero
  238 
  239         /* Allocate space for thread0 PCB and riscv_bootparams */
  240         addi    sp, sp, -(PCB_SIZE + RISCV_BOOTPARAMS_SIZE) & ~STACKALIGNBYTES
  241 
  242         /* Clear BSS */
  243         la      t0, _C_LABEL(__bss_start)
  244         la      t1, _C_LABEL(_end)
  245 1:
  246         sd      zero, 0(t0)
  247         addi    t0, t0, 8
  248         bltu    t0, t1, 1b
  249 
  250         /* Fill riscv_bootparams */
  251         la      t0, pagetable_l1
  252         sd      t0, RISCV_BOOTPARAMS_KERN_L1PT(sp)
  253         sd      s9, RISCV_BOOTPARAMS_KERN_PHYS(sp)
  254 
  255         la      t0, initstack
  256         sd      t0, RISCV_BOOTPARAMS_KERN_STACK(sp)
  257 
  258         li      t0, (VM_EARLY_DTB_ADDRESS)
  259         /* Add offset of DTB within superpage */
  260         li      t1, (L2_OFFSET)
  261         and     t1, a1, t1
  262         add     t0, t0, t1
  263         sd      t0, RISCV_BOOTPARAMS_DTBP_VIRT(sp)
  264         sd      a1, RISCV_BOOTPARAMS_DTBP_PHYS(sp)
  265 
  266         sd      a0, RISCV_BOOTPARAMS_MODULEP(sp)
  267 
  268         mv      a0, sp
  269         call    _C_LABEL(initriscv)     /* Off we go */
  270         call    _C_LABEL(mi_startup)
  271 
  272         /* We should never reach here, but if so just hang. */
  273 2:
  274         wfi
  275         j       2b
  276 
  277 /*
  278  * Get the physical address the kernel is loaded to. Returned in s9.
  279  */
  280 get_physmem:
  281         lla     t0, virt_map    /* physical address of virt_map */
  282         ld      t1, 0(t0)       /* virtual address of virt_map */
  283         sub     t1, t1, t0      /* calculate phys->virt delta */
  284         li      t2, KERNBASE
  285         sub     s9, t2, t1      /* s9 = physmem base */
  286         ret
  287 
  288         .align  4
  289 initstack:
  290         .space  (PAGE_SIZE * KSTACK_PAGES)
  291 initstack_end:
  292 
  293 ENTRY(sigcode)
  294         mv      a0, sp
  295         addi    a0, a0, SF_UC
  296 
  297 1:
  298         li      t0, SYS_sigreturn
  299         ecall
  300 
  301         /* sigreturn failed, exit */
  302         li      t0, SYS_exit
  303         ecall
  304 
  305         j       1b
  306 END(sigcode)
  307         /* This may be copied to the stack, keep it 16-byte aligned */
  308         .align  3
  309 esigcode:
  310 
  311         .data
  312         .align  3
  313         .global szsigcode
  314 szsigcode:
  315         .quad   esigcode - sigcode
  316 
  317         .align  12
  318 pagetable_l1:
  319         .space  PAGE_SIZE
  320 pagetable_l2:
  321         .space  PAGE_SIZE
  322 pagetable_l2_devmap:
  323         .space  PAGE_SIZE
  324 
  325         .align 3
  326 virt_map:
  327         .quad   virt_map
  328 hart_lottery:
  329         .space  4
  330 
  331         .globl init_pt_va
  332 init_pt_va:
  333         .quad pagetable_l2      /* XXX: Keep page tables VA */
  334 
  335 #ifndef SMP
  336 ENTRY(mpentry)
  337 1:
  338         wfi
  339         j       1b
  340 END(mpentry)
  341 #else
  342 /*
  343  * mpentry(unsigned long)
  344  *
  345  * Called by a core when it is being brought online.
  346  */
  347 ENTRY(mpentry)
  348         /*
  349          * Calculate the offset to __riscv_boot_ap
  350          * for the current core, cpuid is in a0.
  351          */
  352         li      t1, 4
  353         mulw    t1, t1, a0
  354         /* Get the pointer */
  355         lla     t0, __riscv_boot_ap
  356         add     t0, t0, t1
  357 
  358 1:
  359         /* Wait the kernel to be ready */
  360         lw      t1, 0(t0)
  361         beqz    t1, 1b
  362 
  363         /* Setup stack pointer */
  364         lla     t0, bootstack
  365         ld      sp, 0(t0)
  366 
  367         /* Get the kernel's load address */
  368         jal     get_physmem
  369 
  370         /* Setup supervisor trap vector */
  371         lla     t0, mpva
  372         sub     t0, t0, s9
  373         li      t1, KERNBASE
  374         add     t0, t0, t1
  375         csrw    stvec, t0
  376 
  377         /* Set page tables base register */
  378         lla     s2, pagetable_l1
  379         srli    s2, s2, PAGE_SHIFT
  380         li      t0, SATP_MODE_SV39
  381         or      s2, s2, t0
  382         sfence.vma
  383         csrw    satp, s2
  384 
  385         .align 2
  386 mpva:
  387         /* Set the global pointer again, this time with the virtual address. */
  388 .option push
  389 .option norelax
  390         lla     gp, __global_pointer$
  391 .option pop
  392 
  393         /* Setup supervisor trap vector */
  394         la      t0, cpu_exception_handler
  395         csrw    stvec, t0
  396 
  397         /* Ensure sscratch is zero */
  398         li      t0, 0
  399         csrw    sscratch, t0
  400 
  401         call    init_secondary
  402 END(mpentry)
  403 #endif

Cache object: bc7bb94896192bd3c1ccb6443f1e84a6


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