1/* 2 * Copyright (C) 2012 Regents of the University of California 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation, version 2. 7 * 8 * This program is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU General Public License for more details. 12 */ 13 14#include <asm/thread_info.h> 15#include <asm/asm-offsets.h> 16#include <asm/asm.h> 17#include <linux/init.h> 18#include <linux/linkage.h> 19#include <asm/thread_info.h> 20#include <asm/page.h> 21#include <asm/csr.h> 22 23__INIT 24ENTRY(_start) 25 /* Mask all interrupts */ 26 csrw sie, zero 27 28 /* Load the global pointer */ 29.option push 30.option norelax 31 la gp, __global_pointer$ 32.option pop 33 34 /* 35 * Disable FPU to detect illegal usage of 36 * floating point in kernel space 37 */ 38 li t0, SR_FS 39 csrc sstatus, t0 40 41 /* Pick one hart to run the main boot sequence */ 42 la a3, hart_lottery 43 li a2, 1 44 amoadd.w a3, a2, (a3) 45 bnez a3, .Lsecondary_start 46 47 /* Save hart ID and DTB physical address */ 48 mv s0, a0 49 mv s1, a1 50 51 /* Initialize page tables and relocate to virtual addresses */ 52 la sp, init_thread_union + THREAD_SIZE 53 call setup_vm 54 call relocate 55 56 /* Restore C environment */ 57 la tp, init_task 58 sw s0, TASK_TI_CPU(tp) 59 60 la sp, init_thread_union 61 li a0, ASM_THREAD_SIZE 62 add sp, sp, a0 63 64 /* Start the kernel */ 65 mv a0, s0 66 mv a1, s1 67 call parse_dtb 68 tail start_kernel 69 70relocate: 71 /* Relocate return address */ 72 li a1, PAGE_OFFSET 73 la a0, _start 74 sub a1, a1, a0 75 add ra, ra, a1 76 77 /* Point stvec to virtual address of intruction after satp write */ 78 la a0, 1f 79 add a0, a0, a1 80 csrw stvec, a0 81 82 /* Compute satp for kernel page tables, but don't load it yet */ 83 la a2, swapper_pg_dir 84 srl a2, a2, PAGE_SHIFT 85 li a1, SATP_MODE 86 or a2, a2, a1 87 88 /* 89 * Load trampoline page directory, which will cause us to trap to 90 * stvec if VA != PA, or simply fall through if VA == PA 91 */ 92 la a0, trampoline_pg_dir 93 srl a0, a0, PAGE_SHIFT 94 or a0, a0, a1 95 sfence.vma 96 csrw sptbr, a0 97.align 2 981: 99 /* Set trap vector to spin forever to help debug */ 100 la a0, .Lsecondary_park 101 csrw stvec, a0 102 103 /* Reload the global pointer */ 104.option push 105.option norelax 106 la gp, __global_pointer$ 107.option pop 108 109 /* Switch to kernel page tables */ 110 csrw sptbr, a2 111 112 ret 113 114.Lsecondary_start: 115#ifdef CONFIG_SMP 116 li a1, CONFIG_NR_CPUS 117 bgeu a0, a1, .Lsecondary_park 118 119 /* Set trap vector to spin forever to help debug */ 120 la a3, .Lsecondary_park 121 csrw stvec, a3 122 123 slli a3, a0, LGREG 124 la a1, __cpu_up_stack_pointer 125 la a2, __cpu_up_task_pointer 126 add a1, a3, a1 127 add a2, a3, a2 128 129 /* 130 * This hart didn't win the lottery, so we wait for the winning hart to 131 * get far enough along the boot process that it should continue. 132 */ 133.Lwait_for_cpu_up: 134 /* FIXME: We should WFI to save some energy here. */ 135 REG_L sp, (a1) 136 REG_L tp, (a2) 137 beqz sp, .Lwait_for_cpu_up 138 beqz tp, .Lwait_for_cpu_up 139 fence 140 141 /* Enable virtual memory and relocate to virtual address */ 142 call relocate 143 144 tail smp_callin 145#endif 146 147.align 2 148.Lsecondary_park: 149 /* We lack SMP support or have too many harts, so park this hart */ 150 wfi 151 j .Lsecondary_park 152END(_start) 153 154__PAGE_ALIGNED_BSS 155 /* Empty zero page */ 156 .balign PAGE_SIZE 157