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 /* Trap entries */ 50 .text 51 52 /* Reset vector */ 53 .text 54 .globl _start 55_start: 56 /* Set the global pointer */ 57.option push 58.option norelax 59 lla gp, __global_pointer$ 60.option pop 61 62 /* 63 * a0 = hart id 64 * a1 = dtbp 65 */ 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 79 /* 80 * Page tables 81 */ 821: 83 /* Get the kernel's load address */ 84 jal get_physmem 85 86 /* Add L1 entry for kernel */ 87 lla s1, pagetable_l1 88 lla s2, pagetable_l2 /* Link to next level PN */ 89 srli s2, s2, PAGE_SHIFT 90 91 li a5, KERNBASE 92 srli a5, a5, L1_SHIFT /* >> L1_SHIFT */ 93 andi a5, a5, 0x1ff /* & 0x1ff */ 94 li t4, PTE_V 95 slli t5, s2, PTE_PPN0_S /* (s2 << PTE_PPN0_S) */ 96 or t6, t4, t5 97 98 /* Store L1 PTE entry to position */ 99 li a6, PTE_SIZE 100 mulw a5, a5, a6 101 add t0, s1, a5 102 sd t6, (t0) 103 104 /* Level 2 superpages (512 x 2MiB) */ 105 lla s1, pagetable_l2 106 srli t4, s9, 21 /* Div physmem base by 2 MiB */ 107 li t2, 512 /* Build 512 entries */ 108 add t3, t4, t2 109 li t5, 0 1102: 111 li t0, (PTE_KERN | PTE_X) 112 slli t2, t4, PTE_PPN1_S /* << PTE_PPN1_S */ 113 or t5, t0, t2 114 sd t5, (s1) /* Store PTE entry to position */ 115 addi s1, s1, PTE_SIZE 116 117 addi t4, t4, 1 118 bltu t4, t3, 2b 119 120 /* Create an L1 page for early devmap */ 121 lla s1, pagetable_l1 122 lla s2, pagetable_l2_devmap /* Link to next level PN */ 123 srli s2, s2, PAGE_SHIFT 124 125 li a5, (VM_MAX_KERNEL_ADDRESS - L2_SIZE) 126 srli a5, a5, L1_SHIFT /* >> L1_SHIFT */ 127 andi a5, a5, 0x1ff /* & 0x1ff */ 128 li t4, PTE_V 129 slli t5, s2, PTE_PPN0_S /* (s2 << PTE_PPN0_S) */ 130 or t6, t4, t5 131 132 /* Store single level1 PTE entry to position */ 133 li a6, PTE_SIZE 134 mulw a5, a5, a6 135 add t0, s1, a5 136 sd t6, (t0) 137 138 /* Create an L2 page superpage for DTB */ 139 lla s1, pagetable_l2_devmap 140 mv s2, a1 141 srli s2, s2, PAGE_SHIFT 142 /* Mask off any bits that aren't aligned */ 143 andi s2, s2, ~((1 << (PTE_PPN1_S - PTE_PPN0_S)) - 1) 144 145 li t0, (PTE_KERN) 146 slli t2, s2, PTE_PPN0_S /* << PTE_PPN0_S */ 147 or t0, t0, t2 148 149 /* Store PTE entry to position */ 150 li a6, PTE_SIZE 151 li a5, 510 152 mulw a5, a5, a6 153 add t1, s1, a5 154 sd t0, (t1) 155 156 /* Page tables END */ 157 158 /* Setup supervisor trap vector */ 159 lla t0, va 160 sub t0, t0, s9 161 li t1, KERNBASE 162 add t0, t0, t1 163 csrw stvec, t0 164 165 /* Set page tables base register */ 166 lla s2, pagetable_l1 167 srli s2, s2, PAGE_SHIFT 168 li t0, SATP_MODE_SV39 169 or s2, s2, t0 170 sfence.vma 171 csrw satp, s2 172 173 .align 2 174va: 175 /* Set the global pointer again, this time with the virtual address. */ 176.option push 177.option norelax 178 lla gp, __global_pointer$ 179.option pop 180 181 /* Setup supervisor trap vector */ 182 la t0, cpu_exception_handler 183 csrw stvec, t0 184 185 /* Ensure sscratch is zero */ 186 li t0, 0 187 csrw sscratch, t0 188 189 /* Initialize stack pointer */ 190 la s3, initstack_end 191 mv sp, s3 192 193 /* Allocate space for thread0 PCB and riscv_bootparams */ 194 addi sp, sp, -(PCB_SIZE + RISCV_BOOTPARAMS_SIZE) & ~STACKALIGNBYTES 195 196 /* Clear BSS */ 197 la s0, _C_LABEL(__bss_start) 198 la s1, _C_LABEL(_end) 1991: 200 sd zero, 0(s0) 201 addi s0, s0, 8 202 bltu s0, s1, 1b 203 204#ifdef SMP 205 /* Store boot hart id. */ 206 la t0, boot_hart 207 sw a0, 0(t0) 208#endif 209 210 /* Fill riscv_bootparams */ 211 la t0, pagetable_l1 212 sd t0, RISCV_BOOTPARAMS_KERN_L1PT(sp) 213 sd s9, RISCV_BOOTPARAMS_KERN_PHYS(sp) 214 215 la t0, initstack 216 sd t0, RISCV_BOOTPARAMS_KERN_STACK(sp) 217 218 li t0, (VM_EARLY_DTB_ADDRESS) 219 /* Add offset of DTB within superpage */ 220 li t1, (L2_OFFSET) 221 and t1, a1, t1 222 add t0, t0, t1 223 sd t0, RISCV_BOOTPARAMS_DTBP_VIRT(sp) 224 sd a1, RISCV_BOOTPARAMS_DTBP_PHYS(sp) 225 226 mv a0, sp 227 call _C_LABEL(initriscv) /* Off we go */ 228 call _C_LABEL(mi_startup) 229 230/* 231 * Get the physical address the kernel is loaded to. Returned in s9. 232 */ 233get_physmem: 234 lla t0, virt_map /* physical address of virt_map */ 235 ld t1, 0(t0) /* virtual address of virt_map */ 236 sub t1, t1, t0 /* calculate phys->virt delta */ 237 li t2, KERNBASE 238 sub s9, t2, t1 /* s9 = physmem base */ 239 ret 240 241 .align 4 242initstack: 243 .space (PAGE_SIZE * KSTACK_PAGES) 244initstack_end: 245 246ENTRY(sigcode) 247 mv a0, sp 248 addi a0, a0, SF_UC 249 2501: 251 li t0, SYS_sigreturn 252 ecall 253 254 /* sigreturn failed, exit */ 255 li t0, SYS_exit 256 ecall 257 258 j 1b 259END(sigcode) 260 /* This may be copied to the stack, keep it 16-byte aligned */ 261 .align 3 262esigcode: 263 264 .data 265 .align 3 266 .global szsigcode 267szsigcode: 268 .quad esigcode - sigcode 269 270 .align 12 271pagetable_l1: 272 .space PAGE_SIZE 273pagetable_l2: 274 .space PAGE_SIZE 275pagetable_l2_devmap: 276 .space PAGE_SIZE 277 278 .align 3 279virt_map: 280 .quad virt_map 281hart_lottery: 282 .space 4 283 284 .globl init_pt_va 285init_pt_va: 286 .quad pagetable_l2 /* XXX: Keep page tables VA */ 287 288#ifndef SMP 289ENTRY(mpentry) 2901: 291 wfi 292 j 1b 293END(mpentry) 294#else 295/* 296 * mpentry(unsigned long) 297 * 298 * Called by a core when it is being brought online. 299 */ 300ENTRY(mpentry) 301 /* 302 * Calculate the offset to __riscv_boot_ap 303 * for the current core, cpuid is in a0. 304 */ 305 li t1, 4 306 mulw t1, t1, a0 307 /* Get the pointer */ 308 lla t0, __riscv_boot_ap 309 add t0, t0, t1 310 3111: 312 /* Wait the kernel to be ready */ 313 lw t1, 0(t0) 314 beqz t1, 1b 315 316 /* Setup stack pointer */ 317 lla t0, bootstack 318 ld sp, 0(t0) 319 320 /* Get the kernel's load address */ 321 jal get_physmem 322 323 /* Setup supervisor trap vector */ 324 lla t0, mpva 325 sub t0, t0, s9 326 li t1, KERNBASE 327 add t0, t0, t1 328 csrw stvec, t0 329 330 /* Set page tables base register */ 331 lla s2, pagetable_l1 332 srli s2, s2, PAGE_SHIFT 333 li t0, SATP_MODE_SV39 334 or s2, s2, t0 335 sfence.vma 336 csrw satp, s2 337 338 .align 2 339mpva: 340 /* Set the global pointer again, this time with the virtual address. */ 341.option push 342.option norelax 343 lla gp, __global_pointer$ 344.option pop 345 346 /* Setup supervisor trap vector */ 347 la t0, cpu_exception_handler 348 csrw stvec, t0 349 350 /* Ensure sscratch is zero */ 351 li t0, 0 352 csrw sscratch, t0 353 354 call init_secondary 355END(mpentry) 356#endif 357