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