18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * linux/arch/arm/kernel/head.S 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 1994-2002 Russell King 68c2ecf20Sopenharmony_ci * Copyright (c) 2003 ARM Limited 78c2ecf20Sopenharmony_ci * All Rights Reserved 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * Kernel startup code for all 32-bit CPUs 108c2ecf20Sopenharmony_ci */ 118c2ecf20Sopenharmony_ci#include <linux/linkage.h> 128c2ecf20Sopenharmony_ci#include <linux/init.h> 138c2ecf20Sopenharmony_ci#include <linux/pgtable.h> 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#include <asm/assembler.h> 168c2ecf20Sopenharmony_ci#include <asm/cp15.h> 178c2ecf20Sopenharmony_ci#include <asm/domain.h> 188c2ecf20Sopenharmony_ci#include <asm/ptrace.h> 198c2ecf20Sopenharmony_ci#include <asm/asm-offsets.h> 208c2ecf20Sopenharmony_ci#include <asm/memory.h> 218c2ecf20Sopenharmony_ci#include <asm/thread_info.h> 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci#if defined(CONFIG_DEBUG_LL) && !defined(CONFIG_DEBUG_SEMIHOSTING) 248c2ecf20Sopenharmony_ci#include CONFIG_DEBUG_LL_INCLUDE 258c2ecf20Sopenharmony_ci#endif 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci/* 288c2ecf20Sopenharmony_ci * swapper_pg_dir is the virtual address of the initial page table. 298c2ecf20Sopenharmony_ci * We place the page tables 16K below KERNEL_RAM_VADDR. Therefore, we must 308c2ecf20Sopenharmony_ci * make sure that KERNEL_RAM_VADDR is correctly set. Currently, we expect 318c2ecf20Sopenharmony_ci * the least significant 16 bits to be 0x8000, but we could probably 328c2ecf20Sopenharmony_ci * relax this restriction to KERNEL_RAM_VADDR >= PAGE_OFFSET + 0x4000. 338c2ecf20Sopenharmony_ci */ 348c2ecf20Sopenharmony_ci#define KERNEL_RAM_VADDR (PAGE_OFFSET + TEXT_OFFSET) 358c2ecf20Sopenharmony_ci#if (KERNEL_RAM_VADDR & 0xffff) != 0x8000 368c2ecf20Sopenharmony_ci#error KERNEL_RAM_VADDR must start at 0xXXXX8000 378c2ecf20Sopenharmony_ci#endif 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci#ifdef CONFIG_ARM_LPAE 408c2ecf20Sopenharmony_ci /* LPAE requires an additional page for the PGD */ 418c2ecf20Sopenharmony_ci#define PG_DIR_SIZE 0x5000 428c2ecf20Sopenharmony_ci#define PMD_ORDER 3 438c2ecf20Sopenharmony_ci#else 448c2ecf20Sopenharmony_ci#define PG_DIR_SIZE 0x4000 458c2ecf20Sopenharmony_ci#define PMD_ORDER 2 468c2ecf20Sopenharmony_ci#endif 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci .macro get_kaslr_offset, reg 498c2ecf20Sopenharmony_ci#ifdef CONFIG_RANDOMIZE_BASE 508c2ecf20Sopenharmony_ci ldr_l \reg, __kaslr_offset 518c2ecf20Sopenharmony_ci#else 528c2ecf20Sopenharmony_ci mov \reg, #0 538c2ecf20Sopenharmony_ci#endif 548c2ecf20Sopenharmony_ci .endm 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci .macro add_kaslr_offset, reg, tmp 578c2ecf20Sopenharmony_ci#ifdef CONFIG_RANDOMIZE_BASE 588c2ecf20Sopenharmony_ci get_kaslr_offset \tmp 598c2ecf20Sopenharmony_ci add \reg, \reg, \tmp 608c2ecf20Sopenharmony_ci#endif 618c2ecf20Sopenharmony_ci .endm 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci .macro sub_kaslr_offset, reg, tmp 648c2ecf20Sopenharmony_ci#ifdef CONFIG_RANDOMIZE_BASE 658c2ecf20Sopenharmony_ci get_kaslr_offset \tmp 668c2ecf20Sopenharmony_ci sub \reg, \reg, \tmp 678c2ecf20Sopenharmony_ci#endif 688c2ecf20Sopenharmony_ci .endm 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci/* 718c2ecf20Sopenharmony_ci * Kernel startup entry point. 728c2ecf20Sopenharmony_ci * --------------------------- 738c2ecf20Sopenharmony_ci * 748c2ecf20Sopenharmony_ci * This is normally called from the decompressor code. The requirements 758c2ecf20Sopenharmony_ci * are: MMU = off, D-cache = off, I-cache = dont care, r0 = 0, 768c2ecf20Sopenharmony_ci * r1 = machine nr, r2 = atags or dtb pointer. 778c2ecf20Sopenharmony_ci * 788c2ecf20Sopenharmony_ci * This code is mostly position independent, so if you link the kernel at 798c2ecf20Sopenharmony_ci * 0xc0008000, you call this at __pa(0xc0008000). 808c2ecf20Sopenharmony_ci * 818c2ecf20Sopenharmony_ci * See linux/arch/arm/tools/mach-types for the complete list of machine 828c2ecf20Sopenharmony_ci * numbers for r1. 838c2ecf20Sopenharmony_ci * 848c2ecf20Sopenharmony_ci * We're trying to keep crap to a minimum; DO NOT add any machine specific 858c2ecf20Sopenharmony_ci * crap here - that's what the boot loader (or in extreme, well justified 868c2ecf20Sopenharmony_ci * circumstances, zImage) is for. 878c2ecf20Sopenharmony_ci */ 888c2ecf20Sopenharmony_ci .arm 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci __HEAD 918c2ecf20Sopenharmony_ci .globl swapper_pg_dir 928c2ecf20Sopenharmony_ci .equ swapper_pg_dir, . - PG_DIR_SIZE 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ciENTRY(stext) 958c2ecf20Sopenharmony_ci mov r3, #0 @ normal entry point - clear r3 968c2ecf20Sopenharmony_ci ARM_BE8(setend be ) @ ensure we are in BE8 mode 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci THUMB( badr r9, 1f ) @ Kernel is always entered in ARM. 998c2ecf20Sopenharmony_ci THUMB( bx r9 ) @ If this is a Thumb-2 kernel, 1008c2ecf20Sopenharmony_ci THUMB( .thumb ) @ switch to Thumb now. 1018c2ecf20Sopenharmony_ci THUMB(1: ) 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci#ifdef CONFIG_RANDOMIZE_BASE 1048c2ecf20Sopenharmony_ci str_l r3, __kaslr_offset, r9 @ offset in r3 if entered via kaslr ep 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci .pushsection .data @ data in bss will be cleared 1078c2ecf20Sopenharmony_ci .align 2 1088c2ecf20Sopenharmony_ciENTRY(__kaslr_offset) 1098c2ecf20Sopenharmony_ci .long 0 @ will be wiped before entering C code 1108c2ecf20Sopenharmony_ci .popsection 1118c2ecf20Sopenharmony_ci#endif 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci#ifdef CONFIG_ARM_VIRT_EXT 1148c2ecf20Sopenharmony_ci bl __hyp_stub_install 1158c2ecf20Sopenharmony_ci#endif 1168c2ecf20Sopenharmony_ci @ ensure svc mode and all interrupts masked 1178c2ecf20Sopenharmony_ci safe_svcmode_maskall r9 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci mrc p15, 0, r9, c0, c0 @ get processor id 1208c2ecf20Sopenharmony_ci bl __lookup_processor_type @ r5=procinfo r9=cpuid 1218c2ecf20Sopenharmony_ci movs r10, r5 @ invalid processor (r5=0)? 1228c2ecf20Sopenharmony_ci THUMB( it eq ) @ force fixup-able long branch encoding 1238c2ecf20Sopenharmony_ci beq __error_p @ yes, error 'p' 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci#ifdef CONFIG_ARM_LPAE 1268c2ecf20Sopenharmony_ci mrc p15, 0, r3, c0, c1, 4 @ read ID_MMFR0 1278c2ecf20Sopenharmony_ci and r3, r3, #0xf @ extract VMSA support 1288c2ecf20Sopenharmony_ci cmp r3, #5 @ long-descriptor translation table format? 1298c2ecf20Sopenharmony_ci THUMB( it lo ) @ force fixup-able long branch encoding 1308c2ecf20Sopenharmony_ci blo __error_lpae @ only classic page table format 1318c2ecf20Sopenharmony_ci#endif 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci#ifndef CONFIG_XIP_KERNEL 1348c2ecf20Sopenharmony_ci adr_l r8, _text @ __pa(_text) 1358c2ecf20Sopenharmony_ci sub r8, r8, #TEXT_OFFSET @ PHYS_OFFSET 1368c2ecf20Sopenharmony_ci sub_kaslr_offset r8, r12 1378c2ecf20Sopenharmony_ci#else 1388c2ecf20Sopenharmony_ci ldr r8, =PLAT_PHYS_OFFSET @ always constant in this case 1398c2ecf20Sopenharmony_ci#endif 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci /* 1428c2ecf20Sopenharmony_ci * r1 = machine no, r2 = atags or dtb, 1438c2ecf20Sopenharmony_ci * r8 = phys_offset, r9 = cpuid, r10 = procinfo 1448c2ecf20Sopenharmony_ci */ 1458c2ecf20Sopenharmony_ci bl __vet_atags 1468c2ecf20Sopenharmony_ci#ifdef CONFIG_SMP_ON_UP 1478c2ecf20Sopenharmony_ci bl __fixup_smp 1488c2ecf20Sopenharmony_ci#endif 1498c2ecf20Sopenharmony_ci#ifdef CONFIG_ARM_PATCH_PHYS_VIRT 1508c2ecf20Sopenharmony_ci bl __fixup_pv_table 1518c2ecf20Sopenharmony_ci#endif 1528c2ecf20Sopenharmony_ci bl __create_page_tables 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci /* 1558c2ecf20Sopenharmony_ci * The following calls CPU specific code in a position independent 1568c2ecf20Sopenharmony_ci * manner. See arch/arm/mm/proc-*.S for details. r10 = base of 1578c2ecf20Sopenharmony_ci * xxx_proc_info structure selected by __lookup_processor_type 1588c2ecf20Sopenharmony_ci * above. 1598c2ecf20Sopenharmony_ci * 1608c2ecf20Sopenharmony_ci * The processor init function will be called with: 1618c2ecf20Sopenharmony_ci * r1 - machine type 1628c2ecf20Sopenharmony_ci * r2 - boot data (atags/dt) pointer 1638c2ecf20Sopenharmony_ci * r4 - translation table base (low word) 1648c2ecf20Sopenharmony_ci * r5 - translation table base (high word, if LPAE) 1658c2ecf20Sopenharmony_ci * r8 - translation table base 1 (pfn if LPAE) 1668c2ecf20Sopenharmony_ci * r9 - cpuid 1678c2ecf20Sopenharmony_ci * r13 - virtual address for __enable_mmu -> __turn_mmu_on 1688c2ecf20Sopenharmony_ci * 1698c2ecf20Sopenharmony_ci * On return, the CPU will be ready for the MMU to be turned on, 1708c2ecf20Sopenharmony_ci * r0 will hold the CPU control register value, r1, r2, r4, and 1718c2ecf20Sopenharmony_ci * r9 will be preserved. r5 will also be preserved if LPAE. 1728c2ecf20Sopenharmony_ci */ 1738c2ecf20Sopenharmony_ci adr_l lr, __primary_switch @ address to jump to after 1748c2ecf20Sopenharmony_ci mov r13, lr @ mmu has been enabled 1758c2ecf20Sopenharmony_ci badr lr, 1f @ return (PIC) address 1768c2ecf20Sopenharmony_ci#ifdef CONFIG_ARM_LPAE 1778c2ecf20Sopenharmony_ci mov r5, #0 @ high TTBR0 1788c2ecf20Sopenharmony_ci mov r8, r4, lsr #12 @ TTBR1 is swapper_pg_dir pfn 1798c2ecf20Sopenharmony_ci#else 1808c2ecf20Sopenharmony_ci mov r8, r4 @ set TTBR1 to swapper_pg_dir 1818c2ecf20Sopenharmony_ci#endif 1828c2ecf20Sopenharmony_ci ldr r12, [r10, #PROCINFO_INITFUNC] 1838c2ecf20Sopenharmony_ci add r12, r12, r10 1848c2ecf20Sopenharmony_ci ret r12 1858c2ecf20Sopenharmony_ci1: get_kaslr_offset r12 @ get before turning MMU on 1868c2ecf20Sopenharmony_ci b __enable_mmu 1878c2ecf20Sopenharmony_ciENDPROC(stext) 1888c2ecf20Sopenharmony_ci .ltorg 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci/* 1918c2ecf20Sopenharmony_ci * Setup the initial page tables. We only setup the barest 1928c2ecf20Sopenharmony_ci * amount which are required to get the kernel running, which 1938c2ecf20Sopenharmony_ci * generally means mapping in the kernel code. 1948c2ecf20Sopenharmony_ci * 1958c2ecf20Sopenharmony_ci * r8 = phys_offset, r9 = cpuid, r10 = procinfo 1968c2ecf20Sopenharmony_ci * 1978c2ecf20Sopenharmony_ci * Returns: 1988c2ecf20Sopenharmony_ci * r0, r3, r5-r7 corrupted 1998c2ecf20Sopenharmony_ci * r4 = physical page table address 2008c2ecf20Sopenharmony_ci */ 2018c2ecf20Sopenharmony_ci__create_page_tables: 2028c2ecf20Sopenharmony_ci adr_l r4, swapper_pg_dir @ page table address 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci /* 2058c2ecf20Sopenharmony_ci * Clear the swapper page table 2068c2ecf20Sopenharmony_ci */ 2078c2ecf20Sopenharmony_ci mov r0, r4 2088c2ecf20Sopenharmony_ci mov r3, #0 2098c2ecf20Sopenharmony_ci add r6, r0, #PG_DIR_SIZE 2108c2ecf20Sopenharmony_ci1: str r3, [r0], #4 2118c2ecf20Sopenharmony_ci str r3, [r0], #4 2128c2ecf20Sopenharmony_ci str r3, [r0], #4 2138c2ecf20Sopenharmony_ci str r3, [r0], #4 2148c2ecf20Sopenharmony_ci teq r0, r6 2158c2ecf20Sopenharmony_ci bne 1b 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ci#ifdef CONFIG_ARM_LPAE 2188c2ecf20Sopenharmony_ci /* 2198c2ecf20Sopenharmony_ci * Build the PGD table (first level) to point to the PMD table. A PGD 2208c2ecf20Sopenharmony_ci * entry is 64-bit wide. 2218c2ecf20Sopenharmony_ci */ 2228c2ecf20Sopenharmony_ci mov r0, r4 2238c2ecf20Sopenharmony_ci add r3, r4, #0x1000 @ first PMD table address 2248c2ecf20Sopenharmony_ci orr r3, r3, #3 @ PGD block type 2258c2ecf20Sopenharmony_ci mov r6, #4 @ PTRS_PER_PGD 2268c2ecf20Sopenharmony_ci mov r7, #1 << (55 - 32) @ L_PGD_SWAPPER 2278c2ecf20Sopenharmony_ci1: 2288c2ecf20Sopenharmony_ci#ifdef CONFIG_CPU_ENDIAN_BE8 2298c2ecf20Sopenharmony_ci str r7, [r0], #4 @ set top PGD entry bits 2308c2ecf20Sopenharmony_ci str r3, [r0], #4 @ set bottom PGD entry bits 2318c2ecf20Sopenharmony_ci#else 2328c2ecf20Sopenharmony_ci str r3, [r0], #4 @ set bottom PGD entry bits 2338c2ecf20Sopenharmony_ci str r7, [r0], #4 @ set top PGD entry bits 2348c2ecf20Sopenharmony_ci#endif 2358c2ecf20Sopenharmony_ci add r3, r3, #0x1000 @ next PMD table 2368c2ecf20Sopenharmony_ci subs r6, r6, #1 2378c2ecf20Sopenharmony_ci bne 1b 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci add r4, r4, #0x1000 @ point to the PMD tables 2408c2ecf20Sopenharmony_ci#ifdef CONFIG_CPU_ENDIAN_BE8 2418c2ecf20Sopenharmony_ci add r4, r4, #4 @ we only write the bottom word 2428c2ecf20Sopenharmony_ci#endif 2438c2ecf20Sopenharmony_ci#endif 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ci ldr r7, [r10, #PROCINFO_MM_MMUFLAGS] @ mm_mmuflags 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci /* 2488c2ecf20Sopenharmony_ci * Create identity mapping to cater for __enable_mmu. 2498c2ecf20Sopenharmony_ci * This identity mapping will be removed by paging_init(). 2508c2ecf20Sopenharmony_ci */ 2518c2ecf20Sopenharmony_ci adr_l r5, __turn_mmu_on @ _pa(__turn_mmu_on) 2528c2ecf20Sopenharmony_ci adr_l r6, __turn_mmu_on_end @ _pa(__turn_mmu_on_end) 2538c2ecf20Sopenharmony_ci mov r5, r5, lsr #SECTION_SHIFT 2548c2ecf20Sopenharmony_ci mov r6, r6, lsr #SECTION_SHIFT 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci1: orr r3, r7, r5, lsl #SECTION_SHIFT @ flags + kernel base 2578c2ecf20Sopenharmony_ci str r3, [r4, r5, lsl #PMD_ORDER] @ identity mapping 2588c2ecf20Sopenharmony_ci cmp r5, r6 2598c2ecf20Sopenharmony_ci addlo r5, r5, #1 @ next section 2608c2ecf20Sopenharmony_ci blo 1b 2618c2ecf20Sopenharmony_ci 2628c2ecf20Sopenharmony_ci /* 2638c2ecf20Sopenharmony_ci * Map our RAM from the start to the end of the kernel .bss section. 2648c2ecf20Sopenharmony_ci */ 2658c2ecf20Sopenharmony_ci get_kaslr_offset r3 2668c2ecf20Sopenharmony_ci add r0, r3, #PAGE_OFFSET 2678c2ecf20Sopenharmony_ci add r0, r4, r0, lsr #(SECTION_SHIFT - PMD_ORDER) 2688c2ecf20Sopenharmony_ci adr_l r6, _end - 1 2698c2ecf20Sopenharmony_ci sub r6, r6, r8 2708c2ecf20Sopenharmony_ci add r6, r6, #PAGE_OFFSET 2718c2ecf20Sopenharmony_ci add r3, r3, r8 2728c2ecf20Sopenharmony_ci orr r3, r3, r7 2738c2ecf20Sopenharmony_ci add r6, r4, r6, lsr #(SECTION_SHIFT - PMD_ORDER) 2748c2ecf20Sopenharmony_ci1: str r3, [r0], #1 << PMD_ORDER 2758c2ecf20Sopenharmony_ci add r3, r3, #1 << SECTION_SHIFT 2768c2ecf20Sopenharmony_ci cmp r0, r6 2778c2ecf20Sopenharmony_ci bls 1b 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci#ifdef CONFIG_XIP_KERNEL 2808c2ecf20Sopenharmony_ci /* 2818c2ecf20Sopenharmony_ci * Map the kernel image separately as it is not located in RAM. 2828c2ecf20Sopenharmony_ci */ 2838c2ecf20Sopenharmony_ci#define XIP_START XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR) 2848c2ecf20Sopenharmony_ci mov r3, pc 2858c2ecf20Sopenharmony_ci mov r3, r3, lsr #SECTION_SHIFT 2868c2ecf20Sopenharmony_ci orr r3, r7, r3, lsl #SECTION_SHIFT 2878c2ecf20Sopenharmony_ci add r0, r4, #(XIP_START & 0xff000000) >> (SECTION_SHIFT - PMD_ORDER) 2888c2ecf20Sopenharmony_ci str r3, [r0, #((XIP_START & 0x00f00000) >> SECTION_SHIFT) << PMD_ORDER]! 2898c2ecf20Sopenharmony_ci ldr r6, =(_edata_loc - 1) 2908c2ecf20Sopenharmony_ci add r0, r0, #1 << PMD_ORDER 2918c2ecf20Sopenharmony_ci add r6, r4, r6, lsr #(SECTION_SHIFT - PMD_ORDER) 2928c2ecf20Sopenharmony_ci1: cmp r0, r6 2938c2ecf20Sopenharmony_ci add r3, r3, #1 << SECTION_SHIFT 2948c2ecf20Sopenharmony_ci strls r3, [r0], #1 << PMD_ORDER 2958c2ecf20Sopenharmony_ci bls 1b 2968c2ecf20Sopenharmony_ci#endif 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci /* 2998c2ecf20Sopenharmony_ci * Then map boot params address in r2 if specified. 3008c2ecf20Sopenharmony_ci * We map 2 sections in case the ATAGs/DTB crosses a section boundary. 3018c2ecf20Sopenharmony_ci */ 3028c2ecf20Sopenharmony_ci mov r0, r2, lsr #SECTION_SHIFT 3038c2ecf20Sopenharmony_ci cmp r2, #0 3048c2ecf20Sopenharmony_ci ldrne r3, =FDT_FIXED_BASE >> (SECTION_SHIFT - PMD_ORDER) 3058c2ecf20Sopenharmony_ci addne r3, r3, r4 3068c2ecf20Sopenharmony_ci orrne r6, r7, r0, lsl #SECTION_SHIFT 3078c2ecf20Sopenharmony_ci strne r6, [r3], #1 << PMD_ORDER 3088c2ecf20Sopenharmony_ci addne r6, r6, #1 << SECTION_SHIFT 3098c2ecf20Sopenharmony_ci strne r6, [r3] 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci#if defined(CONFIG_ARM_LPAE) && defined(CONFIG_CPU_ENDIAN_BE8) 3128c2ecf20Sopenharmony_ci sub r4, r4, #4 @ Fixup page table pointer 3138c2ecf20Sopenharmony_ci @ for 64-bit descriptors 3148c2ecf20Sopenharmony_ci#endif 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_ci#ifdef CONFIG_DEBUG_LL 3178c2ecf20Sopenharmony_ci#if !defined(CONFIG_DEBUG_ICEDCC) && !defined(CONFIG_DEBUG_SEMIHOSTING) 3188c2ecf20Sopenharmony_ci /* 3198c2ecf20Sopenharmony_ci * Map in IO space for serial debugging. 3208c2ecf20Sopenharmony_ci * This allows debug messages to be output 3218c2ecf20Sopenharmony_ci * via a serial console before paging_init. 3228c2ecf20Sopenharmony_ci */ 3238c2ecf20Sopenharmony_ci addruart r7, r3, r0 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ci mov r3, r3, lsr #SECTION_SHIFT 3268c2ecf20Sopenharmony_ci mov r3, r3, lsl #PMD_ORDER 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci add r0, r4, r3 3298c2ecf20Sopenharmony_ci mov r3, r7, lsr #SECTION_SHIFT 3308c2ecf20Sopenharmony_ci ldr r7, [r10, #PROCINFO_IO_MMUFLAGS] @ io_mmuflags 3318c2ecf20Sopenharmony_ci orr r3, r7, r3, lsl #SECTION_SHIFT 3328c2ecf20Sopenharmony_ci#ifdef CONFIG_ARM_LPAE 3338c2ecf20Sopenharmony_ci mov r7, #1 << (54 - 32) @ XN 3348c2ecf20Sopenharmony_ci#ifdef CONFIG_CPU_ENDIAN_BE8 3358c2ecf20Sopenharmony_ci str r7, [r0], #4 3368c2ecf20Sopenharmony_ci str r3, [r0], #4 3378c2ecf20Sopenharmony_ci#else 3388c2ecf20Sopenharmony_ci str r3, [r0], #4 3398c2ecf20Sopenharmony_ci str r7, [r0], #4 3408c2ecf20Sopenharmony_ci#endif 3418c2ecf20Sopenharmony_ci#else 3428c2ecf20Sopenharmony_ci orr r3, r3, #PMD_SECT_XN 3438c2ecf20Sopenharmony_ci str r3, [r0], #4 3448c2ecf20Sopenharmony_ci#endif 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_ci#else /* CONFIG_DEBUG_ICEDCC || CONFIG_DEBUG_SEMIHOSTING */ 3478c2ecf20Sopenharmony_ci /* we don't need any serial debugging mappings */ 3488c2ecf20Sopenharmony_ci ldr r7, [r10, #PROCINFO_IO_MMUFLAGS] @ io_mmuflags 3498c2ecf20Sopenharmony_ci#endif 3508c2ecf20Sopenharmony_ci 3518c2ecf20Sopenharmony_ci#if defined(CONFIG_ARCH_NETWINDER) || defined(CONFIG_ARCH_CATS) 3528c2ecf20Sopenharmony_ci /* 3538c2ecf20Sopenharmony_ci * If we're using the NetWinder or CATS, we also need to map 3548c2ecf20Sopenharmony_ci * in the 16550-type serial port for the debug messages 3558c2ecf20Sopenharmony_ci */ 3568c2ecf20Sopenharmony_ci add r0, r4, #0xff000000 >> (SECTION_SHIFT - PMD_ORDER) 3578c2ecf20Sopenharmony_ci orr r3, r7, #0x7c000000 3588c2ecf20Sopenharmony_ci str r3, [r0] 3598c2ecf20Sopenharmony_ci#endif 3608c2ecf20Sopenharmony_ci#ifdef CONFIG_ARCH_RPC 3618c2ecf20Sopenharmony_ci /* 3628c2ecf20Sopenharmony_ci * Map in screen at 0x02000000 & SCREEN2_BASE 3638c2ecf20Sopenharmony_ci * Similar reasons here - for debug. This is 3648c2ecf20Sopenharmony_ci * only for Acorn RiscPC architectures. 3658c2ecf20Sopenharmony_ci */ 3668c2ecf20Sopenharmony_ci add r0, r4, #0x02000000 >> (SECTION_SHIFT - PMD_ORDER) 3678c2ecf20Sopenharmony_ci orr r3, r7, #0x02000000 3688c2ecf20Sopenharmony_ci str r3, [r0] 3698c2ecf20Sopenharmony_ci add r0, r4, #0xd8000000 >> (SECTION_SHIFT - PMD_ORDER) 3708c2ecf20Sopenharmony_ci str r3, [r0] 3718c2ecf20Sopenharmony_ci#endif 3728c2ecf20Sopenharmony_ci#endif 3738c2ecf20Sopenharmony_ci#ifdef CONFIG_ARM_LPAE 3748c2ecf20Sopenharmony_ci sub r4, r4, #0x1000 @ point to the PGD table 3758c2ecf20Sopenharmony_ci#endif 3768c2ecf20Sopenharmony_ci ret lr 3778c2ecf20Sopenharmony_ciENDPROC(__create_page_tables) 3788c2ecf20Sopenharmony_ci .ltorg 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_ci#if defined(CONFIG_SMP) 3818c2ecf20Sopenharmony_ci .text 3828c2ecf20Sopenharmony_ci .arm 3838c2ecf20Sopenharmony_ciENTRY(secondary_startup_arm) 3848c2ecf20Sopenharmony_ci THUMB( badr r9, 1f ) @ Kernel is entered in ARM. 3858c2ecf20Sopenharmony_ci THUMB( bx r9 ) @ If this is a Thumb-2 kernel, 3868c2ecf20Sopenharmony_ci THUMB( .thumb ) @ switch to Thumb now. 3878c2ecf20Sopenharmony_ci THUMB(1: ) 3888c2ecf20Sopenharmony_ciENTRY(secondary_startup) 3898c2ecf20Sopenharmony_ci /* 3908c2ecf20Sopenharmony_ci * Common entry point for secondary CPUs. 3918c2ecf20Sopenharmony_ci * 3928c2ecf20Sopenharmony_ci * Ensure that we're in SVC mode, and IRQs are disabled. Lookup 3938c2ecf20Sopenharmony_ci * the processor type - there is no need to check the machine type 3948c2ecf20Sopenharmony_ci * as it has already been validated by the primary processor. 3958c2ecf20Sopenharmony_ci */ 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_ci ARM_BE8(setend be) @ ensure we are in BE8 mode 3988c2ecf20Sopenharmony_ci 3998c2ecf20Sopenharmony_ci#ifdef CONFIG_ARM_VIRT_EXT 4008c2ecf20Sopenharmony_ci bl __hyp_stub_install_secondary 4018c2ecf20Sopenharmony_ci#endif 4028c2ecf20Sopenharmony_ci safe_svcmode_maskall r9 4038c2ecf20Sopenharmony_ci 4048c2ecf20Sopenharmony_ci mrc p15, 0, r9, c0, c0 @ get processor id 4058c2ecf20Sopenharmony_ci bl __lookup_processor_type 4068c2ecf20Sopenharmony_ci movs r10, r5 @ invalid processor? 4078c2ecf20Sopenharmony_ci moveq r0, #'p' @ yes, error 'p' 4088c2ecf20Sopenharmony_ci THUMB( it eq ) @ force fixup-able long branch encoding 4098c2ecf20Sopenharmony_ci beq __error_p 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_ci /* 4128c2ecf20Sopenharmony_ci * Use the page tables supplied from __cpu_up. 4138c2ecf20Sopenharmony_ci */ 4148c2ecf20Sopenharmony_ci adr_l r3, secondary_data 4158c2ecf20Sopenharmony_ci mov_l r12, __secondary_switch 4168c2ecf20Sopenharmony_ci ldrd r4, r5, [r3, #0] @ get secondary_data.pgdir 4178c2ecf20Sopenharmony_ciARM_BE8(eor r4, r4, r5) @ Swap r5 and r4 in BE: 4188c2ecf20Sopenharmony_ciARM_BE8(eor r5, r4, r5) @ it can be done in 3 steps 4198c2ecf20Sopenharmony_ciARM_BE8(eor r4, r4, r5) @ without using a temp reg. 4208c2ecf20Sopenharmony_ci ldr r8, [r3, #8] @ get secondary_data.swapper_pg_dir 4218c2ecf20Sopenharmony_ci badr lr, __enable_mmu @ return address 4228c2ecf20Sopenharmony_ci mov r13, r12 @ __secondary_switched address 4238c2ecf20Sopenharmony_ci ldr r12, [r10, #PROCINFO_INITFUNC] 4248c2ecf20Sopenharmony_ci add r12, r12, r10 @ initialise processor 4258c2ecf20Sopenharmony_ci @ (return control reg) 4268c2ecf20Sopenharmony_ci ret r12 4278c2ecf20Sopenharmony_ciENDPROC(secondary_startup) 4288c2ecf20Sopenharmony_ciENDPROC(secondary_startup_arm) 4298c2ecf20Sopenharmony_ci 4308c2ecf20Sopenharmony_ciENTRY(__secondary_switched) 4318c2ecf20Sopenharmony_ci ldr_l r7, secondary_data + 12 @ get secondary_data.stack 4328c2ecf20Sopenharmony_ci mov sp, r7 4338c2ecf20Sopenharmony_ci mov fp, #0 4348c2ecf20Sopenharmony_ci b secondary_start_kernel 4358c2ecf20Sopenharmony_ciENDPROC(__secondary_switched) 4368c2ecf20Sopenharmony_ci 4378c2ecf20Sopenharmony_ci#endif /* defined(CONFIG_SMP) */ 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_ci 4408c2ecf20Sopenharmony_ci 4418c2ecf20Sopenharmony_ci/* 4428c2ecf20Sopenharmony_ci * Setup common bits before finally enabling the MMU. Essentially 4438c2ecf20Sopenharmony_ci * this is just loading the page table pointer and domain access 4448c2ecf20Sopenharmony_ci * registers. All these registers need to be preserved by the 4458c2ecf20Sopenharmony_ci * processor setup function (or set in the case of r0) 4468c2ecf20Sopenharmony_ci * 4478c2ecf20Sopenharmony_ci * r0 = cp#15 control register 4488c2ecf20Sopenharmony_ci * r1 = machine ID 4498c2ecf20Sopenharmony_ci * r2 = atags or dtb pointer 4508c2ecf20Sopenharmony_ci * r4 = TTBR pointer (low word) 4518c2ecf20Sopenharmony_ci * r5 = TTBR pointer (high word if LPAE) 4528c2ecf20Sopenharmony_ci * r9 = processor ID 4538c2ecf20Sopenharmony_ci * r12 = KASLR offset 4548c2ecf20Sopenharmony_ci * r13 = *virtual* address to jump to upon completion 4558c2ecf20Sopenharmony_ci */ 4568c2ecf20Sopenharmony_ci__enable_mmu: 4578c2ecf20Sopenharmony_ci#if defined(CONFIG_ALIGNMENT_TRAP) && __LINUX_ARM_ARCH__ < 6 4588c2ecf20Sopenharmony_ci orr r0, r0, #CR_A 4598c2ecf20Sopenharmony_ci#else 4608c2ecf20Sopenharmony_ci bic r0, r0, #CR_A 4618c2ecf20Sopenharmony_ci#endif 4628c2ecf20Sopenharmony_ci#ifdef CONFIG_CPU_DCACHE_DISABLE 4638c2ecf20Sopenharmony_ci bic r0, r0, #CR_C 4648c2ecf20Sopenharmony_ci#endif 4658c2ecf20Sopenharmony_ci#ifdef CONFIG_CPU_BPREDICT_DISABLE 4668c2ecf20Sopenharmony_ci bic r0, r0, #CR_Z 4678c2ecf20Sopenharmony_ci#endif 4688c2ecf20Sopenharmony_ci#ifdef CONFIG_CPU_ICACHE_DISABLE 4698c2ecf20Sopenharmony_ci bic r0, r0, #CR_I 4708c2ecf20Sopenharmony_ci#endif 4718c2ecf20Sopenharmony_ci#ifdef CONFIG_ARM_LPAE 4728c2ecf20Sopenharmony_ci mcrr p15, 0, r4, r5, c2 @ load TTBR0 4738c2ecf20Sopenharmony_ci#else 4748c2ecf20Sopenharmony_ci mov r5, #DACR_INIT 4758c2ecf20Sopenharmony_ci mcr p15, 0, r5, c3, c0, 0 @ load domain access register 4768c2ecf20Sopenharmony_ci mcr p15, 0, r4, c2, c0, 0 @ load page table pointer 4778c2ecf20Sopenharmony_ci#endif 4788c2ecf20Sopenharmony_ci b __turn_mmu_on 4798c2ecf20Sopenharmony_ciENDPROC(__enable_mmu) 4808c2ecf20Sopenharmony_ci 4818c2ecf20Sopenharmony_ci/* 4828c2ecf20Sopenharmony_ci * Enable the MMU. This completely changes the structure of the visible 4838c2ecf20Sopenharmony_ci * memory space. You will not be able to trace execution through this. 4848c2ecf20Sopenharmony_ci * If you have an enquiry about this, *please* check the linux-arm-kernel 4858c2ecf20Sopenharmony_ci * mailing list archives BEFORE sending another post to the list. 4868c2ecf20Sopenharmony_ci * 4878c2ecf20Sopenharmony_ci * r0 = cp#15 control register 4888c2ecf20Sopenharmony_ci * r1 = machine ID 4898c2ecf20Sopenharmony_ci * r2 = atags or dtb pointer 4908c2ecf20Sopenharmony_ci * r9 = processor ID 4918c2ecf20Sopenharmony_ci * r12 = KASLR offset 4928c2ecf20Sopenharmony_ci * r13 = *virtual* address to jump to upon completion 4938c2ecf20Sopenharmony_ci * 4948c2ecf20Sopenharmony_ci * other registers depend on the function called upon completion 4958c2ecf20Sopenharmony_ci */ 4968c2ecf20Sopenharmony_ci .align 5 4978c2ecf20Sopenharmony_ci .pushsection .idmap.text, "ax" 4988c2ecf20Sopenharmony_ciENTRY(__turn_mmu_on) 4998c2ecf20Sopenharmony_ci mov r0, r0 5008c2ecf20Sopenharmony_ci instr_sync 5018c2ecf20Sopenharmony_ci mcr p15, 0, r0, c1, c0, 0 @ write control reg 5028c2ecf20Sopenharmony_ci mrc p15, 0, r3, c0, c0, 0 @ read id reg 5038c2ecf20Sopenharmony_ci instr_sync 5048c2ecf20Sopenharmony_ci mov r3, r3 5058c2ecf20Sopenharmony_ci mov r3, r13 5068c2ecf20Sopenharmony_ci ret r3 5078c2ecf20Sopenharmony_ciENDPROC(__turn_mmu_on) 5088c2ecf20Sopenharmony_ci 5098c2ecf20Sopenharmony_ci__primary_switch: 5108c2ecf20Sopenharmony_ci#ifdef CONFIG_RELOCATABLE 5118c2ecf20Sopenharmony_ci adr_l r7, _text @ r7 := __pa(_text) 5128c2ecf20Sopenharmony_ci sub r7, r7, #TEXT_OFFSET @ r7 := PHYS_OFFSET 5138c2ecf20Sopenharmony_ci 5148c2ecf20Sopenharmony_ci adr_l r5, __rel_begin 5158c2ecf20Sopenharmony_ci adr_l r6, __rel_end 5168c2ecf20Sopenharmony_ci sub r5, r5, r7 5178c2ecf20Sopenharmony_ci sub r6, r6, r7 5188c2ecf20Sopenharmony_ci 5198c2ecf20Sopenharmony_ci add r5, r5, #PAGE_OFFSET 5208c2ecf20Sopenharmony_ci add r6, r6, #PAGE_OFFSET 5218c2ecf20Sopenharmony_ci add r5, r5, r12 5228c2ecf20Sopenharmony_ci add r6, r6, r12 5238c2ecf20Sopenharmony_ci 5248c2ecf20Sopenharmony_ci adr_l r3, __stubs_start @ __pa(__stubs_start) 5258c2ecf20Sopenharmony_ci sub r3, r3, r7 @ offset of __stubs_start 5268c2ecf20Sopenharmony_ci add r3, r3, #PAGE_OFFSET @ __va(__stubs_start) 5278c2ecf20Sopenharmony_ci sub r3, r3, #0xffff1000 @ subtract VA of stubs section 5288c2ecf20Sopenharmony_ci 5298c2ecf20Sopenharmony_ci0: cmp r5, r6 5308c2ecf20Sopenharmony_ci bge 1f 5318c2ecf20Sopenharmony_ci ldm r5!, {r7, r8} @ load next relocation entry 5328c2ecf20Sopenharmony_ci cmp r8, #23 @ R_ARM_RELATIVE 5338c2ecf20Sopenharmony_ci bne 0b 5348c2ecf20Sopenharmony_ci cmp r7, #0xff000000 @ vector page? 5358c2ecf20Sopenharmony_ci addgt r7, r7, r3 @ fix up VA offset 5368c2ecf20Sopenharmony_ci ldr r8, [r7, r12] 5378c2ecf20Sopenharmony_ci add r8, r8, r12 5388c2ecf20Sopenharmony_ci str r8, [r7, r12] 5398c2ecf20Sopenharmony_ci b 0b 5408c2ecf20Sopenharmony_ci1: 5418c2ecf20Sopenharmony_ci#endif 5428c2ecf20Sopenharmony_ci ldr pc, =__mmap_switched 5438c2ecf20Sopenharmony_ciENDPROC(__primary_switch) 5448c2ecf20Sopenharmony_ci 5458c2ecf20Sopenharmony_ci#ifdef CONFIG_SMP 5468c2ecf20Sopenharmony_ci__secondary_switch: 5478c2ecf20Sopenharmony_ci ldr pc, =__secondary_switched 5488c2ecf20Sopenharmony_ciENDPROC(__secondary_switch) 5498c2ecf20Sopenharmony_ci#endif 5508c2ecf20Sopenharmony_ci .ltorg 5518c2ecf20Sopenharmony_ci__turn_mmu_on_end: 5528c2ecf20Sopenharmony_ci .popsection 5538c2ecf20Sopenharmony_ci 5548c2ecf20Sopenharmony_ci#ifdef CONFIG_SMP_ON_UP 5558c2ecf20Sopenharmony_ci __HEAD 5568c2ecf20Sopenharmony_ci__fixup_smp: 5578c2ecf20Sopenharmony_ci and r3, r9, #0x000f0000 @ architecture version 5588c2ecf20Sopenharmony_ci teq r3, #0x000f0000 @ CPU ID supported? 5598c2ecf20Sopenharmony_ci bne __fixup_smp_on_up @ no, assume UP 5608c2ecf20Sopenharmony_ci 5618c2ecf20Sopenharmony_ci bic r3, r9, #0x00ff0000 5628c2ecf20Sopenharmony_ci bic r3, r3, #0x0000000f @ mask 0xff00fff0 5638c2ecf20Sopenharmony_ci mov r4, #0x41000000 5648c2ecf20Sopenharmony_ci orr r4, r4, #0x0000b000 5658c2ecf20Sopenharmony_ci orr r4, r4, #0x00000020 @ val 0x4100b020 5668c2ecf20Sopenharmony_ci teq r3, r4 @ ARM 11MPCore? 5678c2ecf20Sopenharmony_ci reteq lr @ yes, assume SMP 5688c2ecf20Sopenharmony_ci 5698c2ecf20Sopenharmony_ci mrc p15, 0, r0, c0, c0, 5 @ read MPIDR 5708c2ecf20Sopenharmony_ci and r0, r0, #0xc0000000 @ multiprocessing extensions and 5718c2ecf20Sopenharmony_ci teq r0, #0x80000000 @ not part of a uniprocessor system? 5728c2ecf20Sopenharmony_ci bne __fixup_smp_on_up @ no, assume UP 5738c2ecf20Sopenharmony_ci 5748c2ecf20Sopenharmony_ci @ Core indicates it is SMP. Check for Aegis SOC where a single 5758c2ecf20Sopenharmony_ci @ Cortex-A9 CPU is present but SMP operations fault. 5768c2ecf20Sopenharmony_ci mov r4, #0x41000000 5778c2ecf20Sopenharmony_ci orr r4, r4, #0x0000c000 5788c2ecf20Sopenharmony_ci orr r4, r4, #0x00000090 5798c2ecf20Sopenharmony_ci teq r3, r4 @ Check for ARM Cortex-A9 5808c2ecf20Sopenharmony_ci retne lr @ Not ARM Cortex-A9, 5818c2ecf20Sopenharmony_ci 5828c2ecf20Sopenharmony_ci @ If a future SoC *does* use 0x0 as the PERIPH_BASE, then the 5838c2ecf20Sopenharmony_ci @ below address check will need to be #ifdef'd or equivalent 5848c2ecf20Sopenharmony_ci @ for the Aegis platform. 5858c2ecf20Sopenharmony_ci mrc p15, 4, r0, c15, c0 @ get SCU base address 5868c2ecf20Sopenharmony_ci teq r0, #0x0 @ '0' on actual UP A9 hardware 5878c2ecf20Sopenharmony_ci beq __fixup_smp_on_up @ So its an A9 UP 5888c2ecf20Sopenharmony_ci ldr r0, [r0, #4] @ read SCU Config 5898c2ecf20Sopenharmony_ciARM_BE8(rev r0, r0) @ byteswap if big endian 5908c2ecf20Sopenharmony_ci and r0, r0, #0x3 @ number of CPUs 5918c2ecf20Sopenharmony_ci teq r0, #0x0 @ is 1? 5928c2ecf20Sopenharmony_ci retne lr 5938c2ecf20Sopenharmony_ci 5948c2ecf20Sopenharmony_ci__fixup_smp_on_up: 5958c2ecf20Sopenharmony_ci adr_l r4, __smpalt_begin 5968c2ecf20Sopenharmony_ci adr_l r5, __smpalt_end 5978c2ecf20Sopenharmony_ci b __do_fixup_smp_on_up 5988c2ecf20Sopenharmony_ciENDPROC(__fixup_smp) 5998c2ecf20Sopenharmony_ci 6008c2ecf20Sopenharmony_ci .pushsection .data 6018c2ecf20Sopenharmony_ci .align 2 6028c2ecf20Sopenharmony_ci .globl smp_on_up 6038c2ecf20Sopenharmony_cismp_on_up: 6048c2ecf20Sopenharmony_ci ALT_SMP(.long 1) 6058c2ecf20Sopenharmony_ci ALT_UP(.long 0) 6068c2ecf20Sopenharmony_ci .popsection 6078c2ecf20Sopenharmony_ci#endif 6088c2ecf20Sopenharmony_ci 6098c2ecf20Sopenharmony_ci .text 6108c2ecf20Sopenharmony_ci__do_fixup_smp_on_up: 6118c2ecf20Sopenharmony_ci cmp r4, r5 6128c2ecf20Sopenharmony_ci reths lr 6138c2ecf20Sopenharmony_ci ldmia r4, {r0, r6} 6148c2ecf20Sopenharmony_ci ARM( str r6, [r0, r4] ) 6158c2ecf20Sopenharmony_ci THUMB( add r0, r0, r4 ) 6168c2ecf20Sopenharmony_ci add r4, r4, #8 6178c2ecf20Sopenharmony_ci#ifdef __ARMEB__ 6188c2ecf20Sopenharmony_ci THUMB( mov r6, r6, ror #16 ) @ Convert word order for big-endian. 6198c2ecf20Sopenharmony_ci#endif 6208c2ecf20Sopenharmony_ci THUMB( strh r6, [r0], #2 ) @ For Thumb-2, store as two halfwords 6218c2ecf20Sopenharmony_ci THUMB( mov r6, r6, lsr #16 ) @ to be robust against misaligned r0. 6228c2ecf20Sopenharmony_ci THUMB( strh r6, [r0] ) 6238c2ecf20Sopenharmony_ci b __do_fixup_smp_on_up 6248c2ecf20Sopenharmony_ciENDPROC(__do_fixup_smp_on_up) 6258c2ecf20Sopenharmony_ci 6268c2ecf20Sopenharmony_ciENTRY(fixup_smp) 6278c2ecf20Sopenharmony_ci stmfd sp!, {r4 - r6, lr} 6288c2ecf20Sopenharmony_ci mov r4, r0 6298c2ecf20Sopenharmony_ci add r5, r0, r1 6308c2ecf20Sopenharmony_ci bl __do_fixup_smp_on_up 6318c2ecf20Sopenharmony_ci ldmfd sp!, {r4 - r6, pc} 6328c2ecf20Sopenharmony_ciENDPROC(fixup_smp) 6338c2ecf20Sopenharmony_ci 6348c2ecf20Sopenharmony_ci#include "head-common.S" 635