root/arch/riscv/kernel/head.S

/* [<][>][^][v][top][bottom][index][help] */
   1 /* SPDX-License-Identifier: GPL-2.0-only */
   2 /*
   3  * Copyright (C) 2012 Regents of the University of California
   4  */
   5 
   6 #include <asm/thread_info.h>
   7 #include <asm/asm-offsets.h>
   8 #include <asm/asm.h>
   9 #include <linux/init.h>
  10 #include <linux/linkage.h>
  11 #include <asm/thread_info.h>
  12 #include <asm/page.h>
  13 #include <asm/csr.h>
  14 #include <asm/image.h>
  15 
  16 __INIT
  17 ENTRY(_start)
  18         /*
  19          * Image header expected by Linux boot-loaders. The image header data
  20          * structure is described in asm/image.h.
  21          * Do not modify it without modifying the structure and all bootloaders
  22          * that expects this header format!!
  23          */
  24         /* jump to start kernel */
  25         j _start_kernel
  26         /* reserved */
  27         .word 0
  28         .balign 8
  29 #if __riscv_xlen == 64
  30         /* Image load offset(2MB) from start of RAM */
  31         .dword 0x200000
  32 #else
  33         /* Image load offset(4MB) from start of RAM */
  34         .dword 0x400000
  35 #endif
  36         /* Effective size of kernel image */
  37         .dword _end - _start
  38         .dword __HEAD_FLAGS
  39         .word RISCV_HEADER_VERSION
  40         .word 0
  41         .dword 0
  42         .ascii RISCV_IMAGE_MAGIC
  43         .balign 4
  44         .ascii RISCV_IMAGE_MAGIC2
  45         .word 0
  46 
  47 .global _start_kernel
  48 _start_kernel:
  49         /* Mask all interrupts */
  50         csrw CSR_SIE, zero
  51         csrw CSR_SIP, zero
  52 
  53         /* Load the global pointer */
  54 .option push
  55 .option norelax
  56         la gp, __global_pointer$
  57 .option pop
  58 
  59         /*
  60          * Disable FPU to detect illegal usage of
  61          * floating point in kernel space
  62          */
  63         li t0, SR_FS
  64         csrc CSR_SSTATUS, t0
  65 
  66 #ifdef CONFIG_SMP
  67         li t0, CONFIG_NR_CPUS
  68         bgeu a0, t0, .Lsecondary_park
  69 #endif
  70 
  71         /* Pick one hart to run the main boot sequence */
  72         la a3, hart_lottery
  73         li a2, 1
  74         amoadd.w a3, a2, (a3)
  75         bnez a3, .Lsecondary_start
  76 
  77         /* Clear BSS for flat non-ELF images */
  78         la a3, __bss_start
  79         la a4, __bss_stop
  80         ble a4, a3, clear_bss_done
  81 clear_bss:
  82         REG_S zero, (a3)
  83         add a3, a3, RISCV_SZPTR
  84         blt a3, a4, clear_bss
  85 clear_bss_done:
  86 
  87         /* Save hart ID and DTB physical address */
  88         mv s0, a0
  89         mv s1, a1
  90         la a2, boot_cpu_hartid
  91         REG_S a0, (a2)
  92 
  93         /* Initialize page tables and relocate to virtual addresses */
  94         la sp, init_thread_union + THREAD_SIZE
  95         mv a0, s1
  96         call setup_vm
  97         la a0, early_pg_dir
  98         call relocate
  99 
 100         /* Restore C environment */
 101         la tp, init_task
 102         sw zero, TASK_TI_CPU(tp)
 103         la sp, init_thread_union + THREAD_SIZE
 104 
 105         /* Start the kernel */
 106         call parse_dtb
 107         tail start_kernel
 108 
 109 relocate:
 110         /* Relocate return address */
 111         li a1, PAGE_OFFSET
 112         la a2, _start
 113         sub a1, a1, a2
 114         add ra, ra, a1
 115 
 116         /* Point stvec to virtual address of intruction after satp write */
 117         la a2, 1f
 118         add a2, a2, a1
 119         csrw CSR_STVEC, a2
 120 
 121         /* Compute satp for kernel page tables, but don't load it yet */
 122         srl a2, a0, PAGE_SHIFT
 123         li a1, SATP_MODE
 124         or a2, a2, a1
 125 
 126         /*
 127          * Load trampoline page directory, which will cause us to trap to
 128          * stvec if VA != PA, or simply fall through if VA == PA.  We need a
 129          * full fence here because setup_vm() just wrote these PTEs and we need
 130          * to ensure the new translations are in use.
 131          */
 132         la a0, trampoline_pg_dir
 133         srl a0, a0, PAGE_SHIFT
 134         or a0, a0, a1
 135         sfence.vma
 136         csrw CSR_SATP, a0
 137 .align 2
 138 1:
 139         /* Set trap vector to spin forever to help debug */
 140         la a0, .Lsecondary_park
 141         csrw CSR_STVEC, a0
 142 
 143         /* Reload the global pointer */
 144 .option push
 145 .option norelax
 146         la gp, __global_pointer$
 147 .option pop
 148 
 149         /*
 150          * Switch to kernel page tables.  A full fence is necessary in order to
 151          * avoid using the trampoline translations, which are only correct for
 152          * the first superpage.  Fetching the fence is guarnteed to work
 153          * because that first superpage is translated the same way.
 154          */
 155         csrw CSR_SATP, a2
 156         sfence.vma
 157 
 158         ret
 159 
 160 .Lsecondary_start:
 161 #ifdef CONFIG_SMP
 162         /* Set trap vector to spin forever to help debug */
 163         la a3, .Lsecondary_park
 164         csrw CSR_STVEC, a3
 165 
 166         slli a3, a0, LGREG
 167         la a1, __cpu_up_stack_pointer
 168         la a2, __cpu_up_task_pointer
 169         add a1, a3, a1
 170         add a2, a3, a2
 171 
 172         /*
 173          * This hart didn't win the lottery, so we wait for the winning hart to
 174          * get far enough along the boot process that it should continue.
 175          */
 176 .Lwait_for_cpu_up:
 177         /* FIXME: We should WFI to save some energy here. */
 178         REG_L sp, (a1)
 179         REG_L tp, (a2)
 180         beqz sp, .Lwait_for_cpu_up
 181         beqz tp, .Lwait_for_cpu_up
 182         fence
 183 
 184         /* Enable virtual memory and relocate to virtual address */
 185         la a0, swapper_pg_dir
 186         call relocate
 187 
 188         tail smp_callin
 189 #endif
 190 
 191 .align 2
 192 .Lsecondary_park:
 193         /* We lack SMP support or have too many harts, so park this hart */
 194         wfi
 195         j .Lsecondary_park
 196 END(_start)
 197 
 198 __PAGE_ALIGNED_BSS
 199         /* Empty zero page */
 200         .balign PAGE_SIZE

/* [<][>][^][v][top][bottom][index][help] */