locore.S revision 295972
1295041Sbr/*- 2295972Sbr * Copyright (c) 2015-2016 Ruslan Bukin <br@bsdpad.com> 3295041Sbr * All rights reserved. 4295041Sbr * 5295041Sbr * Portions of this software were developed by SRI International and the 6295041Sbr * University of Cambridge Computer Laboratory under DARPA/AFRL contract 7295041Sbr * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme. 8295041Sbr * 9295041Sbr * Portions of this software were developed by the University of Cambridge 10295041Sbr * Computer Laboratory as part of the CTSRD Project, with support from the 11295041Sbr * UK Higher Education Innovation Fund (HEIF). 12295041Sbr * 13295041Sbr * Redistribution and use in source and binary forms, with or without 14295041Sbr * modification, are permitted provided that the following conditions 15295041Sbr * are met: 16295041Sbr * 1. Redistributions of source code must retain the above copyright 17295041Sbr * notice, this list of conditions and the following disclaimer. 18295041Sbr * 2. Redistributions in binary form must reproduce the above copyright 19295041Sbr * notice, this list of conditions and the following disclaimer in the 20295041Sbr * documentation and/or other materials provided with the distribution. 21295041Sbr * 22295041Sbr * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 23295041Sbr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24295041Sbr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25295041Sbr * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 26295041Sbr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27295041Sbr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28295041Sbr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29295041Sbr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30295041Sbr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31295041Sbr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32295041Sbr * SUCH DAMAGE. 33295041Sbr * 34295041Sbr * $FreeBSD: head/sys/riscv/riscv/locore.S 295972 2016-02-24 16:50:34Z br $ 35295041Sbr */ 36295041Sbr 37295041Sbr#include "assym.s" 38295041Sbr 39295041Sbr#include <sys/syscall.h> 40295041Sbr#include <machine/asm.h> 41295041Sbr#include <machine/param.h> 42295041Sbr#include <machine/trap.h> 43295041Sbr#include <machine/riscvreg.h> 44295041Sbr#include <machine/pte.h> 45295041Sbr 46295972Sbr#define HTIF_RING_NENTRIES (512) 47295972Sbr#define HTIF_RING_ENTRY_SZ (24) 48295972Sbr#define HTIF_RING_SIZE (HTIF_RING_ENTRY_SZ * HTIF_RING_NENTRIES) 49295972Sbr#define HW_STACK_SIZE (96) 50295041Sbr 51295972Sbr/* 52295972Sbr * Event queue for each CPU core: 53295972Sbr * 54295972Sbr * struct htif_ring { 55295972Sbr * uint64_t data; 56295972Sbr * uint64_t used; 57295972Sbr * uint64_t next; 58295972Sbr * } htif_ring[HTIF_RING_NENTRIES]; 59295972Sbr * uint64_t htif_ring_cursor; 60295972Sbr * uint64_t htif_ring_last; 61295972Sbr */ 62295972Sbr 63295972Sbr.macro build_ring 64295972Sbr la t0, htif_ring 65295972Sbr#ifdef SMP 66295972Sbr csrr a0, mhartid 67295972Sbr li s0, (HTIF_RING_SIZE + 16) 68295972Sbr mulw s0, a0, s0 69295972Sbr add t0, t0, s0 70295972Sbr#endif 71295972Sbr li t1, 0 72295972Sbr sd t1, 0(t0) /* zero data */ 73295972Sbr sd t1, 8(t0) /* zero used */ 74295972Sbr mv t2, t0 75295972Sbr mv t3, t0 76295972Sbr li t5, (HTIF_RING_SIZE - HTIF_RING_ENTRY_SZ) 77295972Sbr li t6, 0 78295972Sbr add t4, t0, t5 79295972Sbr1: 80295972Sbr addi t3, t3, 24 /* pointer to next */ 81295972Sbr beq t3, t4, 2f /* finish */ 82295972Sbr sd t3, 16(t2) /* store pointer */ 83295972Sbr addi t2, t2, 24 /* next entry */ 84295972Sbr addi t6, t6, 1 /* counter */ 85295972Sbr j 1b 86295972Sbr2: 87295972Sbr sd t0, 16(t3) /* last -> first */ 88295972Sbr 89295972Sbr li t2, (HTIF_RING_SIZE) 90295972Sbr add s0, t0, t2 91295972Sbr sd t0, 0(s0) /* cursor */ 92295972Sbr sd t0, 8(s0) /* last */ 93295972Sbr /* finish building ring */ 94295972Sbr.endm 95295972Sbr 96295041Sbr .globl kernbase 97295041Sbr .set kernbase, KERNBASE 98295041Sbr 99295041Sbr /* Trap entries */ 100295041Sbr .text 101295041Sbr 102295041Sbrmentry: 103295041Sbr /* User mode entry point (mtvec + 0x000) */ 104295041Sbr .align 6 105295041Sbr j user_trap 106295041Sbr 107295041Sbr /* Supervisor mode entry point (mtvec + 0x040) */ 108295041Sbr .align 6 109295041Sbr j supervisor_trap 110295041Sbr 111295041Sbr /* Hypervisor mode entry point (mtvec + 0x080) */ 112295041Sbr .align 6 113295041Sbr j bad_trap 114295041Sbr 115295041Sbr /* Machine mode entry point (mtvec + 0x0C0) */ 116295041Sbr .align 6 117295041Sbr j bad_trap 118295041Sbr 119295041Sbr /* Reset vector */ 120295041Sbr .text 121295041Sbr .align 8 122295041Sbr .globl _start 123295041Sbr_start: 124295972Sbr /* Direct secondary cores to mpentry */ 125295972Sbr csrr a0, mhartid 126295972Sbr bnez a0, mpentry 127295041Sbr 128295972Sbr /* Build event queue for current core */ 129295972Sbr build_ring 130295041Sbr 131295972Sbr /* Setup machine-mode stack for CPU 0 */ 132295041Sbr la t0, hardstack_end 133295041Sbr csrw mscratch, t0 134295041Sbr 135295041Sbr la t0, mentry 136295041Sbr csrw mtvec, t0 137295041Sbr 138295041Sbr li t0, 0 139295041Sbr csrw sscratch, t0 140295041Sbr 141295041Sbr li s10, PAGE_SIZE 142295041Sbr li s9, (PAGE_SIZE * KSTACK_PAGES) 143295041Sbr 144295041Sbr /* Page tables */ 145295041Sbr 146295041Sbr /* Level 0 */ 147295041Sbr la s1, pagetable_l0 148295041Sbr la s2, pagetable_l1 /* Link to next level PN */ 149295041Sbr srli s2, s2, PAGE_SHIFT 150295041Sbr 151295041Sbr li t4, (PTE_VALID | (PTE_TYPE_PTR << PTE_TYPE_S)) 152295041Sbr slli t5, s2, PTE_PPN0_S /* (s2 << PTE_PPN0_S) */ 153295041Sbr or t6, t4, t5 154295041Sbr 155295041Sbr /* Store single level0 PTE entry to position */ 156295041Sbr li a5, 0x1ff 157295041Sbr li a6, PTE_SIZE 158295041Sbr mulw a5, a5, a6 159295041Sbr add t0, s1, a5 160295972Sbr /* Store it to pagetable_l0 for each cpu */ 161295972Sbr li t1, MAXCPU 162295972Sbr li t2, PAGE_SIZE 163295972Sbr1: 164295041Sbr sd t6, 0(t0) 165295972Sbr add t0, t0, t2 166295972Sbr addi t1, t1, -1 167295972Sbr bnez t1, 1b 168295041Sbr 169295041Sbr /* Level 1 */ 170295041Sbr la s1, pagetable_l1 171295041Sbr la s2, pagetable_l2 /* Link to next level PN */ 172295041Sbr srli s2, s2, PAGE_SHIFT 173295041Sbr 174295041Sbr li a5, KERNBASE 175295041Sbr srli a5, a5, 0x1e /* >> 30 */ 176295041Sbr andi a5, a5, 0x1ff /* & 0x1ff */ 177295041Sbr li t4, (PTE_VALID | (PTE_TYPE_PTR << PTE_TYPE_S)) 178295041Sbr slli t5, s2, PTE_PPN0_S /* (s2 << PTE_PPN0_S) */ 179295041Sbr or t6, t4, t5 180295041Sbr 181295041Sbr /* Store single level1 PTE entry to position */ 182295041Sbr li a6, PTE_SIZE 183295041Sbr mulw a5, a5, a6 184295041Sbr add t0, s1, a5 185295041Sbr sd t6, (t0) 186295041Sbr 187295041Sbr /* Level 2 superpages (512 x 2MiB) */ 188295041Sbr la s1, pagetable_l2 189295041Sbr li t3, 512 /* Build 512 entries */ 190295041Sbr li t4, 0 /* Counter */ 191295041Sbr li t5, 0 192295041Sbr2: 193295041Sbr li t0, (PTE_VALID | (PTE_TYPE_SRWX << PTE_TYPE_S)) 194295041Sbr slli t2, t4, PTE_PPN1_S /* << PTE_PPN1_S */ 195295041Sbr or t5, t0, t2 196295041Sbr sd t5, (s1) /* Store PTE entry to position */ 197295041Sbr addi s1, s1, PTE_SIZE 198295041Sbr 199295041Sbr addi t4, t4, 1 200295041Sbr bltu t4, t3, 2b 201295041Sbr 202295041Sbr /* Set page tables base register */ 203295041Sbr la s1, pagetable_l0 204295041Sbr csrw sptbr, s1 205295041Sbr 206295041Sbr /* Page tables END */ 207295041Sbr 208295041Sbr /* Enter supervisor mode */ 209295041Sbr li s0, ((MSTATUS_VM_SV48 << MSTATUS_VM_SHIFT) | \ 210295041Sbr (MSTATUS_PRV_M << MSTATUS_PRV_SHIFT) | \ 211295041Sbr (MSTATUS_PRV_S << MSTATUS_PRV1_SHIFT) | \ 212295041Sbr (MSTATUS_PRV_U << MSTATUS_PRV2_SHIFT)); 213295041Sbr csrw mstatus, s0 214295041Sbr 215295972Sbr /* 216295972Sbr * Enable machine-mode software interrupts 217295972Sbr * so we can deliver IPI to this core. 218295972Sbr */ 219295972Sbr li t0, MIE_MSIE 220295972Sbr csrs mie, t0 221295972Sbr 222295041Sbr /* Exit from machine mode */ 223295041Sbr la t0, .Lmmu_on 224295972Sbr li s11, KERNBASE 225295041Sbr add t0, t0, s11 226295041Sbr csrw mepc, t0 227295041Sbr eret 228295041Sbr 229295041Sbr.Lmmu_on: 230295041Sbr /* Initialize stack pointer */ 231295041Sbr la s3, initstack_end 232295041Sbr mv sp, s3 233295041Sbr addi sp, sp, -PCB_SIZE 234295041Sbr 235295041Sbr /* Clear BSS */ 236295041Sbr la a0, _C_LABEL(__bss_start) 237295041Sbr la s1, _C_LABEL(_end) 238295041Sbr1: 239295041Sbr sd zero, 0(a0) 240295041Sbr addi a0, a0, 8 241295041Sbr bltu a0, s1, 1b 242295041Sbr 243295041Sbr /* Fill riscv_bootparams */ 244295041Sbr addi sp, sp, -16 245295041Sbr la t0, pagetable_l1 246295041Sbr sd t0, 0(sp) /* kern_l1pt */ 247295041Sbr la t0, initstack_end 248295041Sbr sd t0, 8(sp) /* kern_stack */ 249295041Sbr 250295041Sbr mv a0, sp 251295041Sbr call _C_LABEL(initriscv) /* Off we go */ 252295041Sbr call _C_LABEL(mi_startup) 253295041Sbr 254295041Sbr .align 4 255295041Sbrinitstack: 256295041Sbr .space (PAGE_SIZE * KSTACK_PAGES) 257295041Sbrinitstack_end: 258295041Sbrhardstack: 259295972Sbr .space (HW_STACK_SIZE * MAXCPU) 260295041Sbrhardstack_end: 261295041Sbr 262295041Sbr .globl htif_ring 263295041Sbrhtif_ring: 264295972Sbr .space ((HTIF_RING_SIZE + 16) * MAXCPU) 265295041Sbr 266295041Sbr .globl console_intr 267295041Sbrconsole_intr: 268295972Sbr .space (8) 269295041Sbr 270295041SbrENTRY(sigcode) 271295041Sbr mv a0, sp 272295041Sbr addi a0, a0, SF_UC 273295041Sbr 274295041Sbr1: 275295041Sbr li t0, SYS_sigreturn 276295041Sbr ecall 277295041Sbr 278295041Sbr /* sigreturn failed, exit */ 279295041Sbr li t0, SYS_exit 280295041Sbr ecall 281295041Sbr 282295041Sbr j 1b 283295041SbrEND(sigcode) 284295041Sbr /* This may be copied to the stack, keep it 16-byte aligned */ 285295041Sbr .align 3 286295041Sbresigcode: 287295041Sbr 288295041Sbr .data 289295041Sbr .align 3 290295041Sbr .global szsigcode 291295041Sbrszsigcode: 292295041Sbr .quad esigcode - sigcode 293295041Sbr 294295041Sbr .align 12 295295041Sbr .globl pagetable_l0 296295041Sbrpagetable_l0: 297295972Sbr .space (PAGE_SIZE * MAXCPU) 298295041Sbrpagetable_l1: 299295041Sbr .space PAGE_SIZE 300295041Sbrpagetable_l2: 301295041Sbr .space PAGE_SIZE 302295041Sbrpagetable_end: 303295041Sbr 304295041Sbr .globl init_pt_va 305295041Sbrinit_pt_va: 306295041Sbr .quad pagetable_l2 /* XXX: Keep page tables VA */ 307295041Sbr 308295972Sbr#ifndef SMP 309295972SbrENTRY(mpentry) 310295972Sbr1: 311295972Sbr wfi 312295972Sbr j 1b 313295972SbrEND(mpentry) 314295972Sbr#else 315295972Sbr/* 316295972Sbr * mpentry(unsigned long) 317295972Sbr * 318295972Sbr * Called by a core when it is being brought online. 319295972Sbr * The data in x0 is passed straight to init_secondary. 320295972Sbr */ 321295972SbrENTRY(mpentry) 322295972Sbr /* 323295972Sbr * Calculate the offset to __riscv_boot_ap 324295972Sbr * for current core, cpuid in a0. 325295972Sbr */ 326295972Sbr li t1, 4 327295972Sbr mulw t1, t1, a0 328295972Sbr /* Get pointer */ 329295972Sbr la t0, __riscv_boot_ap 330295972Sbr add t0, t0, t1 331295972Sbr 332295972Sbr1: 333295972Sbr /* Wait the kernel to be ready */ 334295972Sbr lw t1, 0(t0) 335295972Sbr beqz t1, 1b 336295972Sbr 337295972Sbr /* Setup machine exception vector */ 338295972Sbr la t0, mentry 339295972Sbr csrw mtvec, t0 340295972Sbr 341295972Sbr /* Build event queue ring for this core */ 342295972Sbr build_ring 343295972Sbr 344295972Sbr /* Set page tables base register */ 345295972Sbr la t0, pagetable_l0 346295972Sbr li t1, PAGE_SIZE 347295972Sbr mulw t1, t1, a0 348295972Sbr add t0, t0, t1 349295972Sbr csrw sptbr, t0 350295972Sbr /* Page tables END */ 351295972Sbr 352295972Sbr /* Configure mstatus */ 353295972Sbr li s0, ((MSTATUS_VM_SV48 << MSTATUS_VM_SHIFT) | \ 354295972Sbr (MSTATUS_PRV_M << MSTATUS_PRV_SHIFT) | \ 355295972Sbr (MSTATUS_PRV_S << MSTATUS_PRV1_SHIFT) | \ 356295972Sbr (MSTATUS_PRV_U << MSTATUS_PRV2_SHIFT)); 357295972Sbr csrw mstatus, s0 358295972Sbr 359295972Sbr /* Setup stack for machine mode exceptions */ 360295972Sbr la t0, hardstack_end 361295972Sbr li t1, HW_STACK_SIZE 362295972Sbr mulw t1, t1, a0 363295972Sbr sub t0, t0, t1 364295972Sbr csrw mscratch, t0 365295972Sbr 366295972Sbr li t0, 0 367295972Sbr csrw sscratch, t0 368295972Sbr 369295972Sbr /* 370295972Sbr * Enable machine-mode software interrupts 371295972Sbr * so we can deliver IPI to this core. 372295972Sbr */ 373295972Sbr li t0, MIE_MSIE 374295972Sbr csrs mie, t0 375295972Sbr 376295972Sbr /* 377295972Sbr * Exit from machine mode and go to 378295972Sbr * the virtual address space. 379295972Sbr */ 380295972Sbr la t0, mp_virtdone 381295972Sbr li s11, KERNBASE 382295972Sbr add t0, t0, s11 383295972Sbr csrw mepc, t0 384295972Sbr eret 385295972Sbr 386295972Sbrmp_virtdone: 387295972Sbr /* We are now in virtual address space */ 388295972Sbr 389295972Sbr /* Setup stack pointer */ 390295972Sbr la t0, secondary_stacks 391295972Sbr li t1, (PAGE_SIZE * KSTACK_PAGES) 392295972Sbr mulw t1, t1, a0 393295972Sbr add sp, t0, t1 394295972Sbr 395295972Sbr call init_secondary 396295972SbrEND(mpentry) 397295972Sbr#endif 398295972Sbr 399295041Sbr#include "exception.S" 400