/* 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 "efi-header.S"1819__HEAD20SYM_CODE_START(_start)21/*22* Image header expected by Linux boot-loaders. The image header data23* structure is described in asm/image.h.24* Do not modify it without modifying the structure and all bootloaders25* that expects this header format!!26*/27#ifdef CONFIG_EFI28/*29* This instruction decodes to "MZ" ASCII required by UEFI.30*/31c.li s4,-1332j _start_kernel33#else34/* jump to start kernel */35j _start_kernel36/* reserved */37.word 038#endif39.balign 840#ifdef CONFIG_RISCV_M_MODE41/* Image load offset (0MB) from start of RAM for M-mode */42.dword 043#else44#if __riscv_xlen == 6445/* Image load offset(2MB) from start of RAM */46.dword 0x20000047#else48/* Image load offset(4MB) from start of RAM */49.dword 0x40000050#endif51#endif52/* Effective size of kernel image */53.dword _end - _start54.dword __HEAD_FLAGS55.word RISCV_HEADER_VERSION56.word 057.dword 058.ascii RISCV_IMAGE_MAGIC59.balign 460.ascii RISCV_IMAGE_MAGIC261#ifdef CONFIG_EFI62.word pe_head_start - _start63pe_head_start:6465__EFI_PE_HEADER66#else67.word 068#endif6970.align 271#ifdef CONFIG_MMU72.global relocate_enable_mmu73relocate_enable_mmu:74/* Relocate return address */75la a1, kernel_map76XIP_FIXUP_OFFSET a177REG_L a1, KERNEL_MAP_VIRT_ADDR(a1)78la a2, _start79sub a1, a1, a280add ra, ra, a18182/* Point stvec to virtual address of intruction after satp write */83la a2, 1f84add a2, a2, a185csrw CSR_TVEC, a28687/* Compute satp for kernel page tables, but don't load it yet */88srl a2, a0, PAGE_SHIFT89la a1, satp_mode90XIP_FIXUP_OFFSET a191REG_L a1, 0(a1)92or a2, a2, a19394/*95* Load trampoline page directory, which will cause us to trap to96* stvec if VA != PA, or simply fall through if VA == PA. We need a97* full fence here because setup_vm() just wrote these PTEs and we need98* to ensure the new translations are in use.99*/100la a0, trampoline_pg_dir101XIP_FIXUP_OFFSET a0102srl a0, a0, PAGE_SHIFT103or a0, a0, a1104sfence.vma105csrw CSR_SATP, a0106.align 21071:108/* Set trap vector to spin forever to help debug */109la a0, .Lsecondary_park110csrw CSR_TVEC, a0111112/* Reload the global pointer */113load_global_pointer114115/*116* Switch to kernel page tables. A full fence is necessary in order to117* avoid using the trampoline translations, which are only correct for118* the first superpage. Fetching the fence is guaranteed to work119* because that first superpage is translated the same way.120*/121csrw CSR_SATP, a2122sfence.vma123124ret125#endif /* CONFIG_MMU */126#ifdef CONFIG_SMP127.global secondary_start_sbi128secondary_start_sbi:129/* Mask all interrupts */130csrw CSR_IE, zero131csrw CSR_IP, zero132133#ifndef CONFIG_RISCV_M_MODE134/* Enable time CSR */135li t0, 0x2136csrw CSR_SCOUNTEREN, t0137#endif138139/* Load the global pointer */140load_global_pointer141142/*143* Disable FPU & VECTOR to detect illegal usage of144* floating point or vector in kernel space145*/146li t0, SR_FS_VS147csrc CSR_STATUS, t0148149/* Set trap vector to spin forever to help debug */150la a3, .Lsecondary_park151csrw CSR_TVEC, a3152153/* a0 contains the hartid & a1 contains boot data */154li a2, SBI_HART_BOOT_TASK_PTR_OFFSET155XIP_FIXUP_OFFSET a2156add a2, a2, a1157REG_L tp, (a2)158li a3, SBI_HART_BOOT_STACK_PTR_OFFSET159XIP_FIXUP_OFFSET a3160add a3, a3, a1161REG_L sp, (a3)162163.Lsecondary_start_common:164165#ifdef CONFIG_MMU166/* Enable virtual memory and relocate to virtual address */167la a0, swapper_pg_dir168XIP_FIXUP_OFFSET a0169call relocate_enable_mmu170#endif171call .Lsetup_trap_vector172scs_load_current173call smp_callin174#endif /* CONFIG_SMP */175176.align 2177.Lsecondary_park:178/*179* Park this hart if we:180* - have too many harts on CONFIG_RISCV_BOOT_SPINWAIT181* - receive an early trap, before setup_trap_vector finished182* - fail in smp_callin(), as a successful one wouldn't return183*/184wfi185j .Lsecondary_park186187.align 2188.Lsetup_trap_vector:189/* Set trap vector to exception handler */190la a0, handle_exception191csrw CSR_TVEC, a0192193/*194* Set sup0 scratch register to 0, indicating to exception vector that195* we are presently executing in kernel.196*/197csrw CSR_SCRATCH, zero198ret199200SYM_CODE_END(_start)201202SYM_CODE_START(_start_kernel)203/* Mask all interrupts */204csrw CSR_IE, zero205csrw CSR_IP, zero206207#ifdef CONFIG_RISCV_M_MODE208/* flush the instruction cache */209fence.i210211/* Reset all registers except ra, a0, a1 */212call reset_regs213214/*215* Setup a PMP to permit access to all of memory. Some machines may216* not implement PMPs, so we set up a quick trap handler to just skip217* touching the PMPs on any trap.218*/219la a0, .Lpmp_done220csrw CSR_TVEC, a0221222li a0, -1223csrw CSR_PMPADDR0, a0224li a0, (PMP_A_NAPOT | PMP_R | PMP_W | PMP_X)225csrw CSR_PMPCFG0, a0226.align 2227.Lpmp_done:228229/*230* The hartid in a0 is expected later on, and we have no firmware231* to hand it to us.232*/233csrr a0, CSR_MHARTID234#else235/* Enable time CSR */236li t0, 0x2237csrw CSR_SCOUNTEREN, t0238#endif /* CONFIG_RISCV_M_MODE */239240/* Load the global pointer */241load_global_pointer242243/*244* Disable FPU & VECTOR to detect illegal usage of245* floating point or vector in kernel space246*/247li t0, SR_FS_VS248csrc CSR_STATUS, t0249250#ifdef CONFIG_RISCV_BOOT_SPINWAIT251li t0, CONFIG_NR_CPUS252blt a0, t0, .Lgood_cores253tail .Lsecondary_park254.Lgood_cores:255256/* The lottery system is only required for spinwait booting method */257#ifndef CONFIG_XIP_KERNEL258/* Pick one hart to run the main boot sequence */259la a3, hart_lottery260li a2, 1261amoadd.w a3, a2, (a3)262bnez a3, .Lsecondary_start263264#else265/* hart_lottery in flash contains a magic number */266la a3, hart_lottery267mv a2, a3268XIP_FIXUP_OFFSET a2269XIP_FIXUP_FLASH_OFFSET a3270lw t1, (a3)271amoswap.w t0, t1, (a2)272/* first time here if hart_lottery in RAM is not set */273beq t0, t1, .Lsecondary_start274275#endif /* CONFIG_XIP */276#endif /* CONFIG_RISCV_BOOT_SPINWAIT */277278#ifdef CONFIG_XIP_KERNEL279la sp, _end + THREAD_SIZE280XIP_FIXUP_OFFSET sp281mv s0, a0282mv s1, a1283call __copy_data284285/* Restore a0 & a1 copy */286mv a0, s0287mv a1, s1288#endif289290#ifndef CONFIG_XIP_KERNEL291/* Clear BSS for flat non-ELF images */292la a3, __bss_start293la a4, __bss_stop294ble a4, a3, .Lclear_bss_done295.Lclear_bss:296REG_S zero, (a3)297add a3, a3, RISCV_SZPTR298blt a3, a4, .Lclear_bss299.Lclear_bss_done:300#endif301la a2, boot_cpu_hartid302XIP_FIXUP_OFFSET a2303REG_S a0, (a2)304305/* Initialize page tables and relocate to virtual addresses */306la tp, init_task307la sp, init_thread_union + THREAD_SIZE308XIP_FIXUP_OFFSET sp309addi sp, sp, -PT_SIZE_ON_STACK310scs_load_init_stack311#ifdef CONFIG_BUILTIN_DTB312la a0, __dtb_start313XIP_FIXUP_OFFSET a0314#else315mv a0, a1316#endif /* CONFIG_BUILTIN_DTB */317/* Set trap vector to spin forever to help debug */318la a3, .Lsecondary_park319csrw CSR_TVEC, a3320call setup_vm321#ifdef CONFIG_MMU322la a0, early_pg_dir323XIP_FIXUP_OFFSET a0324call relocate_enable_mmu325#endif /* CONFIG_MMU */326327call .Lsetup_trap_vector328/* Restore C environment */329la tp, init_task330la sp, init_thread_union + THREAD_SIZE331addi sp, sp, -PT_SIZE_ON_STACK332scs_load_current333334#ifdef CONFIG_KASAN335call kasan_early_init336#endif337/* Start the kernel */338call soc_early_init339tail start_kernel340341#ifdef CONFIG_RISCV_BOOT_SPINWAIT342.Lsecondary_start:343/* Set trap vector to spin forever to help debug */344la a3, .Lsecondary_park345csrw CSR_TVEC, a3346347slli a3, a0, LGREG348la a1, __cpu_spinwait_stack_pointer349XIP_FIXUP_OFFSET a1350la a2, __cpu_spinwait_task_pointer351XIP_FIXUP_OFFSET a2352add a1, a3, a1353add a2, a3, a2354355/*356* This hart didn't win the lottery, so we wait for the winning hart to357* get far enough along the boot process that it should continue.358*/359.Lwait_for_cpu_up:360/* FIXME: We should WFI to save some energy here. */361REG_L sp, (a1)362REG_L tp, (a2)363beqz sp, .Lwait_for_cpu_up364beqz tp, .Lwait_for_cpu_up365fence366367tail .Lsecondary_start_common368#endif /* CONFIG_RISCV_BOOT_SPINWAIT */369370SYM_CODE_END(_start_kernel)371372#ifdef CONFIG_RISCV_M_MODE373SYM_CODE_START_LOCAL(reset_regs)374li sp, 0375li gp, 0376li tp, 0377li t0, 0378li t1, 0379li t2, 0380li s0, 0381li s1, 0382li a2, 0383li a3, 0384li a4, 0385li a5, 0386li a6, 0387li a7, 0388li s2, 0389li s3, 0390li s4, 0391li s5, 0392li s6, 0393li s7, 0394li s8, 0395li s9, 0396li s10, 0397li s11, 0398li t3, 0399li t4, 0400li t5, 0401li t6, 0402csrw CSR_SCRATCH, 0403404#ifdef CONFIG_FPU405csrr t0, CSR_MISA406andi t0, t0, (COMPAT_HWCAP_ISA_F | COMPAT_HWCAP_ISA_D)407beqz t0, .Lreset_regs_done_fpu408409li t1, SR_FS410csrs CSR_STATUS, t1411fmv.s.x f0, zero412fmv.s.x f1, zero413fmv.s.x f2, zero414fmv.s.x f3, zero415fmv.s.x f4, zero416fmv.s.x f5, zero417fmv.s.x f6, zero418fmv.s.x f7, zero419fmv.s.x f8, zero420fmv.s.x f9, zero421fmv.s.x f10, zero422fmv.s.x f11, zero423fmv.s.x f12, zero424fmv.s.x f13, zero425fmv.s.x f14, zero426fmv.s.x f15, zero427fmv.s.x f16, zero428fmv.s.x f17, zero429fmv.s.x f18, zero430fmv.s.x f19, zero431fmv.s.x f20, zero432fmv.s.x f21, zero433fmv.s.x f22, zero434fmv.s.x f23, zero435fmv.s.x f24, zero436fmv.s.x f25, zero437fmv.s.x f26, zero438fmv.s.x f27, zero439fmv.s.x f28, zero440fmv.s.x f29, zero441fmv.s.x f30, zero442fmv.s.x f31, zero443csrw fcsr, 0444/* note that the caller must clear SR_FS */445.Lreset_regs_done_fpu:446#endif /* CONFIG_FPU */447448#ifdef CONFIG_RISCV_ISA_V449csrr t0, CSR_MISA450li t1, COMPAT_HWCAP_ISA_V451and t0, t0, t1452beqz t0, .Lreset_regs_done_vector453454/*455* Clear vector registers and reset vcsr456* VLMAX has a defined value, VLEN is a constant,457* and this form of vsetvli is defined to set vl to VLMAX.458*/459li t1, SR_VS460csrs CSR_STATUS, t1461csrs CSR_VCSR, x0462vsetvli t1, x0, e8, m8, ta, ma463vmv.v.i v0, 0464vmv.v.i v8, 0465vmv.v.i v16, 0466vmv.v.i v24, 0467/* note that the caller must clear SR_VS */468.Lreset_regs_done_vector:469#endif /* CONFIG_RISCV_ISA_V */470ret471SYM_CODE_END(reset_regs)472#endif /* CONFIG_RISCV_M_MODE */473474475