/* SPDX-License-Identifier: GPL-2.0-only */1/*2* Copyright (C) 2012 Regents of the University of California3*/45#include <asm/asm-offsets.h>6#include <asm/asm.h>7#include <linux/init.h>8#include <linux/linkage.h>9#include <asm/thread_info.h>10#include <asm/page.h>11#include <asm/pgtable.h>12#include <asm/csr.h>13#include <asm/hwcap.h>14#include <asm/image.h>15#include <asm/scs.h>16#include <asm/xip_fixup.h>17#include <asm/usercfi.h>18#include "efi-header.S"1920__HEAD21SYM_CODE_START(_start)22/*23* Image header expected by Linux boot-loaders. The image header data24* structure is described in asm/image.h.25* Do not modify it without modifying the structure and all bootloaders26* that expects this header format!!27*/28#ifdef CONFIG_EFI29/*30* This instruction decodes to "MZ" ASCII required by UEFI.31*/32c.li s4,-1333j _start_kernel34#else35/* jump to start kernel */36j _start_kernel37/* reserved */38.word 039#endif40.balign 841#ifdef CONFIG_RISCV_M_MODE42/* Image load offset (0MB) from start of RAM for M-mode */43.dword 044#else45#if __riscv_xlen == 6446/* Image load offset(2MB) from start of RAM */47.dword 0x20000048#else49/* Image load offset(4MB) from start of RAM */50.dword 0x40000051#endif52#endif53/* Effective size of kernel image */54.dword _end - _start55.dword __HEAD_FLAGS56.word RISCV_HEADER_VERSION57.word 058.dword 059.ascii RISCV_IMAGE_MAGIC60.balign 461.ascii RISCV_IMAGE_MAGIC262#ifdef CONFIG_EFI63.word pe_head_start - _start64pe_head_start:6566__EFI_PE_HEADER67#else68.word 069#endif7071.align 272#ifdef CONFIG_MMU73.global relocate_enable_mmu74relocate_enable_mmu:75/* Relocate return address */76la a1, kernel_map77XIP_FIXUP_OFFSET a178REG_L a1, KERNEL_MAP_VIRT_ADDR(a1)79la a2, _start80sub a1, a1, a281add ra, ra, a18283/* Point stvec to virtual address of intruction after satp write */84la a2, 1f85add a2, a2, a186csrw CSR_TVEC, a28788/* Compute satp for kernel page tables, but don't load it yet */89srl a2, a0, PAGE_SHIFT90la a1, satp_mode91XIP_FIXUP_OFFSET a192REG_L a1, 0(a1)93or a2, a2, a19495/*96* Load trampoline page directory, which will cause us to trap to97* stvec if VA != PA, or simply fall through if VA == PA. We need a98* full fence here because setup_vm() just wrote these PTEs and we need99* to ensure the new translations are in use.100*/101la a0, trampoline_pg_dir102XIP_FIXUP_OFFSET a0103srl a0, a0, PAGE_SHIFT104or a0, a0, a1105sfence.vma106csrw CSR_SATP, a0107.align 21081:109/* Set trap vector to spin forever to help debug */110la a0, .Lsecondary_park111csrw CSR_TVEC, a0112113/* Reload the global pointer */114load_global_pointer115116/*117* Switch to kernel page tables. A full fence is necessary in order to118* avoid using the trampoline translations, which are only correct for119* the first superpage. Fetching the fence is guaranteed to work120* because that first superpage is translated the same way.121*/122csrw CSR_SATP, a2123sfence.vma124125ret126#endif /* CONFIG_MMU */127#ifdef CONFIG_SMP128.global secondary_start_sbi129secondary_start_sbi:130/* Mask all interrupts */131csrw CSR_IE, zero132csrw CSR_IP, zero133134#ifndef CONFIG_RISCV_M_MODE135/* Enable time CSR */136li t0, 0x2137csrw CSR_SCOUNTEREN, t0138#endif139140/* Load the global pointer */141load_global_pointer142143/*144* Disable FPU & VECTOR to detect illegal usage of145* floating point or vector in kernel space146*/147li t0, SR_FS_VS148csrc CSR_STATUS, t0149150/* Set trap vector to spin forever to help debug */151la a3, .Lsecondary_park152csrw CSR_TVEC, a3153154/* a0 contains the hartid & a1 contains boot data */155li a2, SBI_HART_BOOT_TASK_PTR_OFFSET156XIP_FIXUP_OFFSET a2157add a2, a2, a1158REG_L tp, (a2)159li a3, SBI_HART_BOOT_STACK_PTR_OFFSET160XIP_FIXUP_OFFSET a3161add a3, a3, a1162REG_L sp, (a3)163164.Lsecondary_start_common:165166#ifdef CONFIG_MMU167/* Enable virtual memory and relocate to virtual address */168la a0, swapper_pg_dir169XIP_FIXUP_OFFSET a0170call relocate_enable_mmu171#endif172call .Lsetup_trap_vector173#if defined(CONFIG_RISCV_SBI) && defined(CONFIG_RISCV_USER_CFI)174li a7, SBI_EXT_FWFT175li a6, SBI_EXT_FWFT_SET176li a0, SBI_FWFT_SHADOW_STACK177li a1, 1 /* enable supervisor to access shadow stack access */178li a2, SBI_FWFT_SET_FLAG_LOCK179ecall180beqz a0, 1f181la a1, riscv_nousercfi182li a0, CMDLINE_DISABLE_RISCV_USERCFI_BCFI183REG_S a0, (a1)1841:185#endif186scs_load_current187call smp_callin188#endif /* CONFIG_SMP */189190.align 2191.Lsecondary_park:192/*193* Park this hart if we:194* - have too many harts on CONFIG_RISCV_BOOT_SPINWAIT195* - receive an early trap, before setup_trap_vector finished196* - fail in smp_callin(), as a successful one wouldn't return197*/198wfi199j .Lsecondary_park200201.align 2202.Lsetup_trap_vector:203/* Set trap vector to exception handler */204la a0, handle_exception205csrw CSR_TVEC, a0206207/*208* Set sup0 scratch register to 0, indicating to exception vector that209* we are presently executing in kernel.210*/211csrw CSR_SCRATCH, zero212ret213214SYM_CODE_END(_start)215216SYM_CODE_START(_start_kernel)217/* Mask all interrupts */218csrw CSR_IE, zero219csrw CSR_IP, zero220221#ifdef CONFIG_RISCV_M_MODE222/* flush the instruction cache */223fence.i224225/* Reset all registers except ra, a0, a1 */226call reset_regs227228/*229* Setup a PMP to permit access to all of memory. Some machines may230* not implement PMPs, so we set up a quick trap handler to just skip231* touching the PMPs on any trap.232*/233la a0, .Lpmp_done234csrw CSR_TVEC, a0235236li a0, -1237csrw CSR_PMPADDR0, a0238li a0, (PMP_A_NAPOT | PMP_R | PMP_W | PMP_X)239csrw CSR_PMPCFG0, a0240.align 2241.Lpmp_done:242243/*244* The hartid in a0 is expected later on, and we have no firmware245* to hand it to us.246*/247csrr a0, CSR_MHARTID248#else249/* Enable time CSR */250li t0, 0x2251csrw CSR_SCOUNTEREN, t0252#endif /* CONFIG_RISCV_M_MODE */253254/* Load the global pointer */255load_global_pointer256257/*258* Disable FPU & VECTOR to detect illegal usage of259* floating point or vector in kernel space260*/261li t0, SR_FS_VS262csrc CSR_STATUS, t0263264#ifdef CONFIG_RISCV_BOOT_SPINWAIT265li t0, CONFIG_NR_CPUS266blt a0, t0, .Lgood_cores267tail .Lsecondary_park268.Lgood_cores:269270/* The lottery system is only required for spinwait booting method */271#ifndef CONFIG_XIP_KERNEL272/* Pick one hart to run the main boot sequence */273la a3, hart_lottery274li a2, 1275amoadd.w a3, a2, (a3)276bnez a3, .Lsecondary_start277278#else279/* hart_lottery in flash contains a magic number */280la a3, hart_lottery281mv a2, a3282XIP_FIXUP_OFFSET a2283XIP_FIXUP_FLASH_OFFSET a3284lw t1, (a3)285amoswap.w t0, t1, (a2)286/* first time here if hart_lottery in RAM is not set */287beq t0, t1, .Lsecondary_start288289#endif /* CONFIG_XIP */290#endif /* CONFIG_RISCV_BOOT_SPINWAIT */291292#ifdef CONFIG_XIP_KERNEL293la sp, _end + THREAD_SIZE294XIP_FIXUP_OFFSET sp295mv s0, a0296mv s1, a1297call __copy_data298299/* Restore a0 & a1 copy */300mv a0, s0301mv a1, s1302#endif303304#ifndef CONFIG_XIP_KERNEL305/* Clear BSS for flat non-ELF images */306la a3, __bss_start307la a4, __bss_stop308ble a4, a3, .Lclear_bss_done309.Lclear_bss:310REG_S zero, (a3)311add a3, a3, RISCV_SZPTR312blt a3, a4, .Lclear_bss313.Lclear_bss_done:314#endif315la a2, boot_cpu_hartid316XIP_FIXUP_OFFSET a2317REG_S a0, (a2)318319/* Initialize page tables and relocate to virtual addresses */320la tp, init_task321la sp, init_thread_union + THREAD_SIZE322XIP_FIXUP_OFFSET sp323addi sp, sp, -PT_SIZE_ON_STACK324scs_load_init_stack325#ifdef CONFIG_BUILTIN_DTB326la a0, __dtb_start327XIP_FIXUP_OFFSET a0328#else329mv a0, a1330#endif /* CONFIG_BUILTIN_DTB */331/* Set trap vector to spin forever to help debug */332la a3, .Lsecondary_park333csrw CSR_TVEC, a3334call setup_vm335#ifdef CONFIG_MMU336la a0, early_pg_dir337XIP_FIXUP_OFFSET a0338call relocate_enable_mmu339#endif /* CONFIG_MMU */340341call .Lsetup_trap_vector342/* Restore C environment */343la tp, init_task344la sp, init_thread_union + THREAD_SIZE345addi sp, sp, -PT_SIZE_ON_STACK346#if defined(CONFIG_RISCV_SBI) && defined(CONFIG_RISCV_USER_CFI)347li a7, SBI_EXT_FWFT348li a6, SBI_EXT_FWFT_SET349li a0, SBI_FWFT_SHADOW_STACK350li a1, 1 /* enable supervisor to access shadow stack access */351li a2, SBI_FWFT_SET_FLAG_LOCK352ecall353beqz a0, 1f354la a1, riscv_nousercfi355li a0, CMDLINE_DISABLE_RISCV_USERCFI_BCFI356REG_S a0, (a1)3571:358#endif359scs_load_current360361#ifdef CONFIG_KASAN362call kasan_early_init363#endif364/* Start the kernel */365call soc_early_init366tail start_kernel367368#ifdef CONFIG_RISCV_BOOT_SPINWAIT369.Lsecondary_start:370/* Set trap vector to spin forever to help debug */371la a3, .Lsecondary_park372csrw CSR_TVEC, a3373374slli a3, a0, LGREG375la a1, __cpu_spinwait_stack_pointer376XIP_FIXUP_OFFSET a1377la a2, __cpu_spinwait_task_pointer378XIP_FIXUP_OFFSET a2379add a1, a3, a1380add a2, a3, a2381382/*383* This hart didn't win the lottery, so we wait for the winning hart to384* get far enough along the boot process that it should continue.385*/386.Lwait_for_cpu_up:387/* FIXME: We should WFI to save some energy here. */388REG_L sp, (a1)389REG_L tp, (a2)390beqz sp, .Lwait_for_cpu_up391beqz tp, .Lwait_for_cpu_up392fence393394tail .Lsecondary_start_common395#endif /* CONFIG_RISCV_BOOT_SPINWAIT */396397SYM_CODE_END(_start_kernel)398399#ifdef CONFIG_RISCV_M_MODE400SYM_CODE_START_LOCAL(reset_regs)401li sp, 0402li gp, 0403li tp, 0404li t0, 0405li t1, 0406li t2, 0407li s0, 0408li s1, 0409li a2, 0410li a3, 0411li a4, 0412li a5, 0413li a6, 0414li a7, 0415li s2, 0416li s3, 0417li s4, 0418li s5, 0419li s6, 0420li s7, 0421li s8, 0422li s9, 0423li s10, 0424li s11, 0425li t3, 0426li t4, 0427li t5, 0428li t6, 0429csrw CSR_SCRATCH, 0430431#ifdef CONFIG_FPU432csrr t0, CSR_MISA433andi t0, t0, (COMPAT_HWCAP_ISA_F | COMPAT_HWCAP_ISA_D)434beqz t0, .Lreset_regs_done_fpu435436li t1, SR_FS437csrs CSR_STATUS, t1438fmv.s.x f0, zero439fmv.s.x f1, zero440fmv.s.x f2, zero441fmv.s.x f3, zero442fmv.s.x f4, zero443fmv.s.x f5, zero444fmv.s.x f6, zero445fmv.s.x f7, zero446fmv.s.x f8, zero447fmv.s.x f9, zero448fmv.s.x f10, zero449fmv.s.x f11, zero450fmv.s.x f12, zero451fmv.s.x f13, zero452fmv.s.x f14, zero453fmv.s.x f15, zero454fmv.s.x f16, zero455fmv.s.x f17, zero456fmv.s.x f18, zero457fmv.s.x f19, zero458fmv.s.x f20, zero459fmv.s.x f21, zero460fmv.s.x f22, zero461fmv.s.x f23, zero462fmv.s.x f24, zero463fmv.s.x f25, zero464fmv.s.x f26, zero465fmv.s.x f27, zero466fmv.s.x f28, zero467fmv.s.x f29, zero468fmv.s.x f30, zero469fmv.s.x f31, zero470csrw fcsr, 0471/* note that the caller must clear SR_FS */472.Lreset_regs_done_fpu:473#endif /* CONFIG_FPU */474475#ifdef CONFIG_RISCV_ISA_V476csrr t0, CSR_MISA477li t1, COMPAT_HWCAP_ISA_V478and t0, t0, t1479beqz t0, .Lreset_regs_done_vector480481/*482* Clear vector registers and reset vcsr483* VLMAX has a defined value, VLEN is a constant,484* and this form of vsetvli is defined to set vl to VLMAX.485*/486li t1, SR_VS487csrs CSR_STATUS, t1488csrs CSR_VCSR, x0489vsetvli t1, x0, e8, m8, ta, ma490vmv.v.i v0, 0491vmv.v.i v8, 0492vmv.v.i v16, 0493vmv.v.i v24, 0494/* note that the caller must clear SR_VS */495.Lreset_regs_done_vector:496#endif /* CONFIG_RISCV_ISA_V */497ret498SYM_CODE_END(reset_regs)499#endif /* CONFIG_RISCV_M_MODE */500501502