18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * arch/arm/include/asm/assembler.h 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 1996-2000 Russell King 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * This file contains arm architecture specific defines 88c2ecf20Sopenharmony_ci * for the different processors. 98c2ecf20Sopenharmony_ci * 108c2ecf20Sopenharmony_ci * Do not include any C declarations in this file - it is included by 118c2ecf20Sopenharmony_ci * assembler source. 128c2ecf20Sopenharmony_ci */ 138c2ecf20Sopenharmony_ci#ifndef __ASM_ASSEMBLER_H__ 148c2ecf20Sopenharmony_ci#define __ASM_ASSEMBLER_H__ 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci#ifndef __ASSEMBLY__ 178c2ecf20Sopenharmony_ci#error "Only include this from assembly code" 188c2ecf20Sopenharmony_ci#endif 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci#include <asm/ptrace.h> 218c2ecf20Sopenharmony_ci#include <asm/extable.h> 228c2ecf20Sopenharmony_ci#include <asm/opcodes-virt.h> 238c2ecf20Sopenharmony_ci#include <asm/asm-offsets.h> 248c2ecf20Sopenharmony_ci#include <asm/page.h> 258c2ecf20Sopenharmony_ci#include <asm/thread_info.h> 268c2ecf20Sopenharmony_ci#include <asm/uaccess-asm.h> 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci#define IOMEM(x) (x) 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci/* 318c2ecf20Sopenharmony_ci * Endian independent macros for shifting bytes within registers. 328c2ecf20Sopenharmony_ci */ 338c2ecf20Sopenharmony_ci#ifndef __ARMEB__ 348c2ecf20Sopenharmony_ci#define lspull lsr 358c2ecf20Sopenharmony_ci#define lspush lsl 368c2ecf20Sopenharmony_ci#define get_byte_0 lsl #0 378c2ecf20Sopenharmony_ci#define get_byte_1 lsr #8 388c2ecf20Sopenharmony_ci#define get_byte_2 lsr #16 398c2ecf20Sopenharmony_ci#define get_byte_3 lsr #24 408c2ecf20Sopenharmony_ci#define put_byte_0 lsl #0 418c2ecf20Sopenharmony_ci#define put_byte_1 lsl #8 428c2ecf20Sopenharmony_ci#define put_byte_2 lsl #16 438c2ecf20Sopenharmony_ci#define put_byte_3 lsl #24 448c2ecf20Sopenharmony_ci#else 458c2ecf20Sopenharmony_ci#define lspull lsl 468c2ecf20Sopenharmony_ci#define lspush lsr 478c2ecf20Sopenharmony_ci#define get_byte_0 lsr #24 488c2ecf20Sopenharmony_ci#define get_byte_1 lsr #16 498c2ecf20Sopenharmony_ci#define get_byte_2 lsr #8 508c2ecf20Sopenharmony_ci#define get_byte_3 lsl #0 518c2ecf20Sopenharmony_ci#define put_byte_0 lsl #24 528c2ecf20Sopenharmony_ci#define put_byte_1 lsl #16 538c2ecf20Sopenharmony_ci#define put_byte_2 lsl #8 548c2ecf20Sopenharmony_ci#define put_byte_3 lsl #0 558c2ecf20Sopenharmony_ci#endif 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci/* Select code for any configuration running in BE8 mode */ 588c2ecf20Sopenharmony_ci#ifdef CONFIG_CPU_ENDIAN_BE8 598c2ecf20Sopenharmony_ci#define ARM_BE8(code...) code 608c2ecf20Sopenharmony_ci#else 618c2ecf20Sopenharmony_ci#define ARM_BE8(code...) 628c2ecf20Sopenharmony_ci#endif 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci/* 658c2ecf20Sopenharmony_ci * Data preload for architectures that support it 668c2ecf20Sopenharmony_ci */ 678c2ecf20Sopenharmony_ci#if __LINUX_ARM_ARCH__ >= 5 688c2ecf20Sopenharmony_ci#define PLD(code...) code 698c2ecf20Sopenharmony_ci#else 708c2ecf20Sopenharmony_ci#define PLD(code...) 718c2ecf20Sopenharmony_ci#endif 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci/* 748c2ecf20Sopenharmony_ci * This can be used to enable code to cacheline align the destination 758c2ecf20Sopenharmony_ci * pointer when bulk writing to memory. Experiments on StrongARM and 768c2ecf20Sopenharmony_ci * XScale didn't show this a worthwhile thing to do when the cache is not 778c2ecf20Sopenharmony_ci * set to write-allocate (this would need further testing on XScale when WA 788c2ecf20Sopenharmony_ci * is used). 798c2ecf20Sopenharmony_ci * 808c2ecf20Sopenharmony_ci * On Feroceon there is much to gain however, regardless of cache mode. 818c2ecf20Sopenharmony_ci */ 828c2ecf20Sopenharmony_ci#ifdef CONFIG_CPU_FEROCEON 838c2ecf20Sopenharmony_ci#define CALGN(code...) code 848c2ecf20Sopenharmony_ci#else 858c2ecf20Sopenharmony_ci#define CALGN(code...) 868c2ecf20Sopenharmony_ci#endif 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci#define IMM12_MASK 0xfff 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci/* 918c2ecf20Sopenharmony_ci * Enable and disable interrupts 928c2ecf20Sopenharmony_ci */ 938c2ecf20Sopenharmony_ci#if __LINUX_ARM_ARCH__ >= 6 948c2ecf20Sopenharmony_ci .macro disable_irq_notrace 958c2ecf20Sopenharmony_ci cpsid i 968c2ecf20Sopenharmony_ci .endm 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci .macro enable_irq_notrace 998c2ecf20Sopenharmony_ci cpsie i 1008c2ecf20Sopenharmony_ci .endm 1018c2ecf20Sopenharmony_ci#else 1028c2ecf20Sopenharmony_ci .macro disable_irq_notrace 1038c2ecf20Sopenharmony_ci msr cpsr_c, #PSR_I_BIT | SVC_MODE 1048c2ecf20Sopenharmony_ci .endm 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci .macro enable_irq_notrace 1078c2ecf20Sopenharmony_ci msr cpsr_c, #SVC_MODE 1088c2ecf20Sopenharmony_ci .endm 1098c2ecf20Sopenharmony_ci#endif 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci#if __LINUX_ARM_ARCH__ < 7 1128c2ecf20Sopenharmony_ci .macro dsb, args 1138c2ecf20Sopenharmony_ci mcr p15, 0, r0, c7, c10, 4 1148c2ecf20Sopenharmony_ci .endm 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci .macro isb, args 1178c2ecf20Sopenharmony_ci mcr p15, 0, r0, c7, c5, 4 1188c2ecf20Sopenharmony_ci .endm 1198c2ecf20Sopenharmony_ci#endif 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci .macro asm_trace_hardirqs_off, save=1 1228c2ecf20Sopenharmony_ci#if defined(CONFIG_TRACE_IRQFLAGS) 1238c2ecf20Sopenharmony_ci .if \save 1248c2ecf20Sopenharmony_ci stmdb sp!, {r0-r3, ip, lr} 1258c2ecf20Sopenharmony_ci .endif 1268c2ecf20Sopenharmony_ci bl trace_hardirqs_off 1278c2ecf20Sopenharmony_ci .if \save 1288c2ecf20Sopenharmony_ci ldmia sp!, {r0-r3, ip, lr} 1298c2ecf20Sopenharmony_ci .endif 1308c2ecf20Sopenharmony_ci#endif 1318c2ecf20Sopenharmony_ci .endm 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci .macro asm_trace_hardirqs_on, cond=al, save=1 1348c2ecf20Sopenharmony_ci#if defined(CONFIG_TRACE_IRQFLAGS) 1358c2ecf20Sopenharmony_ci /* 1368c2ecf20Sopenharmony_ci * actually the registers should be pushed and pop'd conditionally, but 1378c2ecf20Sopenharmony_ci * after bl the flags are certainly clobbered 1388c2ecf20Sopenharmony_ci */ 1398c2ecf20Sopenharmony_ci .if \save 1408c2ecf20Sopenharmony_ci stmdb sp!, {r0-r3, ip, lr} 1418c2ecf20Sopenharmony_ci .endif 1428c2ecf20Sopenharmony_ci bl\cond trace_hardirqs_on 1438c2ecf20Sopenharmony_ci .if \save 1448c2ecf20Sopenharmony_ci ldmia sp!, {r0-r3, ip, lr} 1458c2ecf20Sopenharmony_ci .endif 1468c2ecf20Sopenharmony_ci#endif 1478c2ecf20Sopenharmony_ci .endm 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci .macro disable_irq, save=1 1508c2ecf20Sopenharmony_ci disable_irq_notrace 1518c2ecf20Sopenharmony_ci asm_trace_hardirqs_off \save 1528c2ecf20Sopenharmony_ci .endm 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci .macro enable_irq 1558c2ecf20Sopenharmony_ci asm_trace_hardirqs_on 1568c2ecf20Sopenharmony_ci enable_irq_notrace 1578c2ecf20Sopenharmony_ci .endm 1588c2ecf20Sopenharmony_ci/* 1598c2ecf20Sopenharmony_ci * Save the current IRQ state and disable IRQs. Note that this macro 1608c2ecf20Sopenharmony_ci * assumes FIQs are enabled, and that the processor is in SVC mode. 1618c2ecf20Sopenharmony_ci */ 1628c2ecf20Sopenharmony_ci .macro save_and_disable_irqs, oldcpsr 1638c2ecf20Sopenharmony_ci#ifdef CONFIG_CPU_V7M 1648c2ecf20Sopenharmony_ci mrs \oldcpsr, primask 1658c2ecf20Sopenharmony_ci#else 1668c2ecf20Sopenharmony_ci mrs \oldcpsr, cpsr 1678c2ecf20Sopenharmony_ci#endif 1688c2ecf20Sopenharmony_ci disable_irq 1698c2ecf20Sopenharmony_ci .endm 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci .macro save_and_disable_irqs_notrace, oldcpsr 1728c2ecf20Sopenharmony_ci#ifdef CONFIG_CPU_V7M 1738c2ecf20Sopenharmony_ci mrs \oldcpsr, primask 1748c2ecf20Sopenharmony_ci#else 1758c2ecf20Sopenharmony_ci mrs \oldcpsr, cpsr 1768c2ecf20Sopenharmony_ci#endif 1778c2ecf20Sopenharmony_ci disable_irq_notrace 1788c2ecf20Sopenharmony_ci .endm 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci/* 1818c2ecf20Sopenharmony_ci * Restore interrupt state previously stored in a register. We don't 1828c2ecf20Sopenharmony_ci * guarantee that this will preserve the flags. 1838c2ecf20Sopenharmony_ci */ 1848c2ecf20Sopenharmony_ci .macro restore_irqs_notrace, oldcpsr 1858c2ecf20Sopenharmony_ci#ifdef CONFIG_CPU_V7M 1868c2ecf20Sopenharmony_ci msr primask, \oldcpsr 1878c2ecf20Sopenharmony_ci#else 1888c2ecf20Sopenharmony_ci msr cpsr_c, \oldcpsr 1898c2ecf20Sopenharmony_ci#endif 1908c2ecf20Sopenharmony_ci .endm 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_ci .macro restore_irqs, oldcpsr 1938c2ecf20Sopenharmony_ci tst \oldcpsr, #PSR_I_BIT 1948c2ecf20Sopenharmony_ci asm_trace_hardirqs_on cond=eq 1958c2ecf20Sopenharmony_ci restore_irqs_notrace \oldcpsr 1968c2ecf20Sopenharmony_ci .endm 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci/* 1998c2ecf20Sopenharmony_ci * Assembly version of "adr rd, BSYM(sym)". This should only be used to 2008c2ecf20Sopenharmony_ci * reference local symbols in the same assembly file which are to be 2018c2ecf20Sopenharmony_ci * resolved by the assembler. Other usage is undefined. 2028c2ecf20Sopenharmony_ci */ 2038c2ecf20Sopenharmony_ci .irp c,,eq,ne,cs,cc,mi,pl,vs,vc,hi,ls,ge,lt,gt,le,hs,lo 2048c2ecf20Sopenharmony_ci .macro badr\c, rd, sym 2058c2ecf20Sopenharmony_ci#ifdef CONFIG_THUMB2_KERNEL 2068c2ecf20Sopenharmony_ci adr\c \rd, \sym + 1 2078c2ecf20Sopenharmony_ci#else 2088c2ecf20Sopenharmony_ci adr\c \rd, \sym 2098c2ecf20Sopenharmony_ci#endif 2108c2ecf20Sopenharmony_ci .endm 2118c2ecf20Sopenharmony_ci .endr 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_ci/* 2148c2ecf20Sopenharmony_ci * Get current thread_info. 2158c2ecf20Sopenharmony_ci */ 2168c2ecf20Sopenharmony_ci .macro get_thread_info, rd 2178c2ecf20Sopenharmony_ci ARM( mov \rd, sp, lsr #THREAD_SIZE_ORDER + PAGE_SHIFT ) 2188c2ecf20Sopenharmony_ci THUMB( mov \rd, sp ) 2198c2ecf20Sopenharmony_ci THUMB( lsr \rd, \rd, #THREAD_SIZE_ORDER + PAGE_SHIFT ) 2208c2ecf20Sopenharmony_ci mov \rd, \rd, lsl #THREAD_SIZE_ORDER + PAGE_SHIFT 2218c2ecf20Sopenharmony_ci .endm 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci/* 2248c2ecf20Sopenharmony_ci * Increment/decrement the preempt count. 2258c2ecf20Sopenharmony_ci */ 2268c2ecf20Sopenharmony_ci#ifdef CONFIG_PREEMPT_COUNT 2278c2ecf20Sopenharmony_ci .macro inc_preempt_count, ti, tmp 2288c2ecf20Sopenharmony_ci ldr \tmp, [\ti, #TI_PREEMPT] @ get preempt count 2298c2ecf20Sopenharmony_ci add \tmp, \tmp, #1 @ increment it 2308c2ecf20Sopenharmony_ci str \tmp, [\ti, #TI_PREEMPT] 2318c2ecf20Sopenharmony_ci .endm 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_ci .macro dec_preempt_count, ti, tmp 2348c2ecf20Sopenharmony_ci ldr \tmp, [\ti, #TI_PREEMPT] @ get preempt count 2358c2ecf20Sopenharmony_ci sub \tmp, \tmp, #1 @ decrement it 2368c2ecf20Sopenharmony_ci str \tmp, [\ti, #TI_PREEMPT] 2378c2ecf20Sopenharmony_ci .endm 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci .macro dec_preempt_count_ti, ti, tmp 2408c2ecf20Sopenharmony_ci get_thread_info \ti 2418c2ecf20Sopenharmony_ci dec_preempt_count \ti, \tmp 2428c2ecf20Sopenharmony_ci .endm 2438c2ecf20Sopenharmony_ci#else 2448c2ecf20Sopenharmony_ci .macro inc_preempt_count, ti, tmp 2458c2ecf20Sopenharmony_ci .endm 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci .macro dec_preempt_count, ti, tmp 2488c2ecf20Sopenharmony_ci .endm 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci .macro dec_preempt_count_ti, ti, tmp 2518c2ecf20Sopenharmony_ci .endm 2528c2ecf20Sopenharmony_ci#endif 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_ci#define USERL(l, x...) \ 2558c2ecf20Sopenharmony_ci9999: x; \ 2568c2ecf20Sopenharmony_ci ex_entry 9999b,l; 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci#define USER(x...) USERL(9001f, x) 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci#ifdef CONFIG_SMP 2618c2ecf20Sopenharmony_ci#define ALT_SMP(instr...) \ 2628c2ecf20Sopenharmony_ci9998: instr 2638c2ecf20Sopenharmony_ci/* 2648c2ecf20Sopenharmony_ci * Note: if you get assembler errors from ALT_UP() when building with 2658c2ecf20Sopenharmony_ci * CONFIG_THUMB2_KERNEL, you almost certainly need to use 2668c2ecf20Sopenharmony_ci * ALT_SMP( W(instr) ... ) 2678c2ecf20Sopenharmony_ci */ 2688c2ecf20Sopenharmony_ci#define ALT_UP(instr...) \ 2698c2ecf20Sopenharmony_ci .pushsection ".alt.smp.init", "a" ;\ 2708c2ecf20Sopenharmony_ci .long 9998b - . ;\ 2718c2ecf20Sopenharmony_ci9997: instr ;\ 2728c2ecf20Sopenharmony_ci .if . - 9997b == 2 ;\ 2738c2ecf20Sopenharmony_ci nop ;\ 2748c2ecf20Sopenharmony_ci .endif ;\ 2758c2ecf20Sopenharmony_ci .if . - 9997b != 4 ;\ 2768c2ecf20Sopenharmony_ci .error "ALT_UP() content must assemble to exactly 4 bytes";\ 2778c2ecf20Sopenharmony_ci .endif ;\ 2788c2ecf20Sopenharmony_ci .popsection 2798c2ecf20Sopenharmony_ci#define ALT_UP_B(label) \ 2808c2ecf20Sopenharmony_ci .pushsection ".alt.smp.init", "a" ;\ 2818c2ecf20Sopenharmony_ci .long 9998b - . ;\ 2828c2ecf20Sopenharmony_ci W(b) . + (label - 9998b) ;\ 2838c2ecf20Sopenharmony_ci .popsection 2848c2ecf20Sopenharmony_ci#else 2858c2ecf20Sopenharmony_ci#define ALT_SMP(instr...) 2868c2ecf20Sopenharmony_ci#define ALT_UP(instr...) instr 2878c2ecf20Sopenharmony_ci#define ALT_UP_B(label) b label 2888c2ecf20Sopenharmony_ci#endif 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci/* 2918c2ecf20Sopenharmony_ci * Instruction barrier 2928c2ecf20Sopenharmony_ci */ 2938c2ecf20Sopenharmony_ci .macro instr_sync 2948c2ecf20Sopenharmony_ci#if __LINUX_ARM_ARCH__ >= 7 2958c2ecf20Sopenharmony_ci isb 2968c2ecf20Sopenharmony_ci#elif __LINUX_ARM_ARCH__ == 6 2978c2ecf20Sopenharmony_ci mcr p15, 0, r0, c7, c5, 4 2988c2ecf20Sopenharmony_ci#endif 2998c2ecf20Sopenharmony_ci .endm 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_ci/* 3028c2ecf20Sopenharmony_ci * SMP data memory barrier 3038c2ecf20Sopenharmony_ci */ 3048c2ecf20Sopenharmony_ci .macro smp_dmb mode 3058c2ecf20Sopenharmony_ci#ifdef CONFIG_SMP 3068c2ecf20Sopenharmony_ci#if __LINUX_ARM_ARCH__ >= 7 3078c2ecf20Sopenharmony_ci .ifeqs "\mode","arm" 3088c2ecf20Sopenharmony_ci ALT_SMP(dmb ish) 3098c2ecf20Sopenharmony_ci .else 3108c2ecf20Sopenharmony_ci ALT_SMP(W(dmb) ish) 3118c2ecf20Sopenharmony_ci .endif 3128c2ecf20Sopenharmony_ci#elif __LINUX_ARM_ARCH__ == 6 3138c2ecf20Sopenharmony_ci ALT_SMP(mcr p15, 0, r0, c7, c10, 5) @ dmb 3148c2ecf20Sopenharmony_ci#else 3158c2ecf20Sopenharmony_ci#error Incompatible SMP platform 3168c2ecf20Sopenharmony_ci#endif 3178c2ecf20Sopenharmony_ci .ifeqs "\mode","arm" 3188c2ecf20Sopenharmony_ci ALT_UP(nop) 3198c2ecf20Sopenharmony_ci .else 3208c2ecf20Sopenharmony_ci ALT_UP(W(nop)) 3218c2ecf20Sopenharmony_ci .endif 3228c2ecf20Sopenharmony_ci#endif 3238c2ecf20Sopenharmony_ci .endm 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ci#if defined(CONFIG_CPU_V7M) 3268c2ecf20Sopenharmony_ci /* 3278c2ecf20Sopenharmony_ci * setmode is used to assert to be in svc mode during boot. For v7-M 3288c2ecf20Sopenharmony_ci * this is done in __v7m_setup, so setmode can be empty here. 3298c2ecf20Sopenharmony_ci */ 3308c2ecf20Sopenharmony_ci .macro setmode, mode, reg 3318c2ecf20Sopenharmony_ci .endm 3328c2ecf20Sopenharmony_ci#elif defined(CONFIG_THUMB2_KERNEL) 3338c2ecf20Sopenharmony_ci .macro setmode, mode, reg 3348c2ecf20Sopenharmony_ci mov \reg, #\mode 3358c2ecf20Sopenharmony_ci msr cpsr_c, \reg 3368c2ecf20Sopenharmony_ci .endm 3378c2ecf20Sopenharmony_ci#else 3388c2ecf20Sopenharmony_ci .macro setmode, mode, reg 3398c2ecf20Sopenharmony_ci msr cpsr_c, #\mode 3408c2ecf20Sopenharmony_ci .endm 3418c2ecf20Sopenharmony_ci#endif 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_ci/* 3448c2ecf20Sopenharmony_ci * Helper macro to enter SVC mode cleanly and mask interrupts. reg is 3458c2ecf20Sopenharmony_ci * a scratch register for the macro to overwrite. 3468c2ecf20Sopenharmony_ci * 3478c2ecf20Sopenharmony_ci * This macro is intended for forcing the CPU into SVC mode at boot time. 3488c2ecf20Sopenharmony_ci * you cannot return to the original mode. 3498c2ecf20Sopenharmony_ci */ 3508c2ecf20Sopenharmony_ci.macro safe_svcmode_maskall reg:req 3518c2ecf20Sopenharmony_ci#if __LINUX_ARM_ARCH__ >= 6 && !defined(CONFIG_CPU_V7M) 3528c2ecf20Sopenharmony_ci mrs \reg , cpsr 3538c2ecf20Sopenharmony_ci eor \reg, \reg, #HYP_MODE 3548c2ecf20Sopenharmony_ci tst \reg, #MODE_MASK 3558c2ecf20Sopenharmony_ci bic \reg , \reg , #MODE_MASK 3568c2ecf20Sopenharmony_ci orr \reg , \reg , #PSR_I_BIT | PSR_F_BIT | SVC_MODE 3578c2ecf20Sopenharmony_ciTHUMB( orr \reg , \reg , #PSR_T_BIT ) 3588c2ecf20Sopenharmony_ci bne 1f 3598c2ecf20Sopenharmony_ci orr \reg, \reg, #PSR_A_BIT 3608c2ecf20Sopenharmony_ci badr lr, 2f 3618c2ecf20Sopenharmony_ci msr spsr_cxsf, \reg 3628c2ecf20Sopenharmony_ci __MSR_ELR_HYP(14) 3638c2ecf20Sopenharmony_ci __ERET 3648c2ecf20Sopenharmony_ci1: msr cpsr_c, \reg 3658c2ecf20Sopenharmony_ci2: 3668c2ecf20Sopenharmony_ci#else 3678c2ecf20Sopenharmony_ci/* 3688c2ecf20Sopenharmony_ci * workaround for possibly broken pre-v6 hardware 3698c2ecf20Sopenharmony_ci * (akita, Sharp Zaurus C-1000, PXA270-based) 3708c2ecf20Sopenharmony_ci */ 3718c2ecf20Sopenharmony_ci setmode PSR_F_BIT | PSR_I_BIT | SVC_MODE, \reg 3728c2ecf20Sopenharmony_ci#endif 3738c2ecf20Sopenharmony_ci.endm 3748c2ecf20Sopenharmony_ci 3758c2ecf20Sopenharmony_ci/* 3768c2ecf20Sopenharmony_ci * STRT/LDRT access macros with ARM and Thumb-2 variants 3778c2ecf20Sopenharmony_ci */ 3788c2ecf20Sopenharmony_ci#ifdef CONFIG_THUMB2_KERNEL 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_ci .macro usraccoff, instr, reg, ptr, inc, off, cond, abort, t=TUSER() 3818c2ecf20Sopenharmony_ci9999: 3828c2ecf20Sopenharmony_ci .if \inc == 1 3838c2ecf20Sopenharmony_ci \instr\()b\t\cond\().w \reg, [\ptr, #\off] 3848c2ecf20Sopenharmony_ci .elseif \inc == 4 3858c2ecf20Sopenharmony_ci \instr\t\cond\().w \reg, [\ptr, #\off] 3868c2ecf20Sopenharmony_ci .else 3878c2ecf20Sopenharmony_ci .error "Unsupported inc macro argument" 3888c2ecf20Sopenharmony_ci .endif 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_ci ex_entry 9999b, \abort 3918c2ecf20Sopenharmony_ci .endm 3928c2ecf20Sopenharmony_ci 3938c2ecf20Sopenharmony_ci .macro usracc, instr, reg, ptr, inc, cond, rept, abort 3948c2ecf20Sopenharmony_ci @ explicit IT instruction needed because of the label 3958c2ecf20Sopenharmony_ci @ introduced by the USER macro 3968c2ecf20Sopenharmony_ci .ifnc \cond,al 3978c2ecf20Sopenharmony_ci .if \rept == 1 3988c2ecf20Sopenharmony_ci itt \cond 3998c2ecf20Sopenharmony_ci .elseif \rept == 2 4008c2ecf20Sopenharmony_ci ittt \cond 4018c2ecf20Sopenharmony_ci .else 4028c2ecf20Sopenharmony_ci .error "Unsupported rept macro argument" 4038c2ecf20Sopenharmony_ci .endif 4048c2ecf20Sopenharmony_ci .endif 4058c2ecf20Sopenharmony_ci 4068c2ecf20Sopenharmony_ci @ Slightly optimised to avoid incrementing the pointer twice 4078c2ecf20Sopenharmony_ci usraccoff \instr, \reg, \ptr, \inc, 0, \cond, \abort 4088c2ecf20Sopenharmony_ci .if \rept == 2 4098c2ecf20Sopenharmony_ci usraccoff \instr, \reg, \ptr, \inc, \inc, \cond, \abort 4108c2ecf20Sopenharmony_ci .endif 4118c2ecf20Sopenharmony_ci 4128c2ecf20Sopenharmony_ci add\cond \ptr, #\rept * \inc 4138c2ecf20Sopenharmony_ci .endm 4148c2ecf20Sopenharmony_ci 4158c2ecf20Sopenharmony_ci#else /* !CONFIG_THUMB2_KERNEL */ 4168c2ecf20Sopenharmony_ci 4178c2ecf20Sopenharmony_ci .macro usracc, instr, reg, ptr, inc, cond, rept, abort, t=TUSER() 4188c2ecf20Sopenharmony_ci .rept \rept 4198c2ecf20Sopenharmony_ci9999: 4208c2ecf20Sopenharmony_ci .if \inc == 1 4218c2ecf20Sopenharmony_ci \instr\()b\t\cond \reg, [\ptr], #\inc 4228c2ecf20Sopenharmony_ci .elseif \inc == 4 4238c2ecf20Sopenharmony_ci \instr\t\cond \reg, [\ptr], #\inc 4248c2ecf20Sopenharmony_ci .else 4258c2ecf20Sopenharmony_ci .error "Unsupported inc macro argument" 4268c2ecf20Sopenharmony_ci .endif 4278c2ecf20Sopenharmony_ci 4288c2ecf20Sopenharmony_ci ex_entry 9999b, \abort 4298c2ecf20Sopenharmony_ci .endr 4308c2ecf20Sopenharmony_ci .endm 4318c2ecf20Sopenharmony_ci 4328c2ecf20Sopenharmony_ci#endif /* CONFIG_THUMB2_KERNEL */ 4338c2ecf20Sopenharmony_ci 4348c2ecf20Sopenharmony_ci .macro strusr, reg, ptr, inc, cond=al, rept=1, abort=9001f 4358c2ecf20Sopenharmony_ci usracc str, \reg, \ptr, \inc, \cond, \rept, \abort 4368c2ecf20Sopenharmony_ci .endm 4378c2ecf20Sopenharmony_ci 4388c2ecf20Sopenharmony_ci .macro ldrusr, reg, ptr, inc, cond=al, rept=1, abort=9001f 4398c2ecf20Sopenharmony_ci usracc ldr, \reg, \ptr, \inc, \cond, \rept, \abort 4408c2ecf20Sopenharmony_ci .endm 4418c2ecf20Sopenharmony_ci 4428c2ecf20Sopenharmony_ci/* Utility macro for declaring string literals */ 4438c2ecf20Sopenharmony_ci .macro string name:req, string 4448c2ecf20Sopenharmony_ci .type \name , #object 4458c2ecf20Sopenharmony_ci\name: 4468c2ecf20Sopenharmony_ci .asciz "\string" 4478c2ecf20Sopenharmony_ci .size \name , . - \name 4488c2ecf20Sopenharmony_ci .endm 4498c2ecf20Sopenharmony_ci 4508c2ecf20Sopenharmony_ci .irp c,,eq,ne,cs,cc,mi,pl,vs,vc,hi,ls,ge,lt,gt,le,hs,lo 4518c2ecf20Sopenharmony_ci .macro ret\c, reg 4528c2ecf20Sopenharmony_ci#if __LINUX_ARM_ARCH__ < 6 4538c2ecf20Sopenharmony_ci mov\c pc, \reg 4548c2ecf20Sopenharmony_ci#else 4558c2ecf20Sopenharmony_ci .ifeqs "\reg", "lr" 4568c2ecf20Sopenharmony_ci bx\c \reg 4578c2ecf20Sopenharmony_ci .else 4588c2ecf20Sopenharmony_ci mov\c pc, \reg 4598c2ecf20Sopenharmony_ci .endif 4608c2ecf20Sopenharmony_ci#endif 4618c2ecf20Sopenharmony_ci .endm 4628c2ecf20Sopenharmony_ci .endr 4638c2ecf20Sopenharmony_ci 4648c2ecf20Sopenharmony_ci .macro ret.w, reg 4658c2ecf20Sopenharmony_ci ret \reg 4668c2ecf20Sopenharmony_ci#ifdef CONFIG_THUMB2_KERNEL 4678c2ecf20Sopenharmony_ci nop 4688c2ecf20Sopenharmony_ci#endif 4698c2ecf20Sopenharmony_ci .endm 4708c2ecf20Sopenharmony_ci 4718c2ecf20Sopenharmony_ci .macro bug, msg, line 4728c2ecf20Sopenharmony_ci#ifdef CONFIG_THUMB2_KERNEL 4738c2ecf20Sopenharmony_ci1: .inst 0xde02 4748c2ecf20Sopenharmony_ci#else 4758c2ecf20Sopenharmony_ci1: .inst 0xe7f001f2 4768c2ecf20Sopenharmony_ci#endif 4778c2ecf20Sopenharmony_ci#ifdef CONFIG_DEBUG_BUGVERBOSE 4788c2ecf20Sopenharmony_ci .pushsection .rodata.str, "aMS", %progbits, 1 4798c2ecf20Sopenharmony_ci2: .asciz "\msg" 4808c2ecf20Sopenharmony_ci .popsection 4818c2ecf20Sopenharmony_ci .pushsection __bug_table, "aw" 4828c2ecf20Sopenharmony_ci .align 2 4838c2ecf20Sopenharmony_ci .word 1b, 2b 4848c2ecf20Sopenharmony_ci .hword \line 4858c2ecf20Sopenharmony_ci .popsection 4868c2ecf20Sopenharmony_ci#endif 4878c2ecf20Sopenharmony_ci .endm 4888c2ecf20Sopenharmony_ci 4898c2ecf20Sopenharmony_ci#ifdef CONFIG_KPROBES 4908c2ecf20Sopenharmony_ci#define _ASM_NOKPROBE(entry) \ 4918c2ecf20Sopenharmony_ci .pushsection "_kprobe_blacklist", "aw" ; \ 4928c2ecf20Sopenharmony_ci .balign 4 ; \ 4938c2ecf20Sopenharmony_ci .long entry; \ 4948c2ecf20Sopenharmony_ci .popsection 4958c2ecf20Sopenharmony_ci#else 4968c2ecf20Sopenharmony_ci#define _ASM_NOKPROBE(entry) 4978c2ecf20Sopenharmony_ci#endif 4988c2ecf20Sopenharmony_ci 4998c2ecf20Sopenharmony_ci .macro __adldst_l, op, reg, sym, tmp, c 5008c2ecf20Sopenharmony_ci .if __LINUX_ARM_ARCH__ < 7 5018c2ecf20Sopenharmony_ci ldr\c \tmp, .La\@ 5028c2ecf20Sopenharmony_ci .subsection 1 5038c2ecf20Sopenharmony_ci .align 2 5048c2ecf20Sopenharmony_ci.La\@: .long \sym - .Lpc\@ 5058c2ecf20Sopenharmony_ci .previous 5068c2ecf20Sopenharmony_ci .else 5078c2ecf20Sopenharmony_ci .ifnb \c 5088c2ecf20Sopenharmony_ci THUMB( ittt \c ) 5098c2ecf20Sopenharmony_ci .endif 5108c2ecf20Sopenharmony_ci movw\c \tmp, #:lower16:\sym - .Lpc\@ 5118c2ecf20Sopenharmony_ci movt\c \tmp, #:upper16:\sym - .Lpc\@ 5128c2ecf20Sopenharmony_ci .endif 5138c2ecf20Sopenharmony_ci 5148c2ecf20Sopenharmony_ci#ifndef CONFIG_THUMB2_KERNEL 5158c2ecf20Sopenharmony_ci .set .Lpc\@, . + 8 // PC bias 5168c2ecf20Sopenharmony_ci .ifc \op, add 5178c2ecf20Sopenharmony_ci add\c \reg, \tmp, pc 5188c2ecf20Sopenharmony_ci .else 5198c2ecf20Sopenharmony_ci \op\c \reg, [pc, \tmp] 5208c2ecf20Sopenharmony_ci .endif 5218c2ecf20Sopenharmony_ci#else 5228c2ecf20Sopenharmony_ci.Lb\@: add\c \tmp, \tmp, pc 5238c2ecf20Sopenharmony_ci /* 5248c2ecf20Sopenharmony_ci * In Thumb-2 builds, the PC bias depends on whether we are currently 5258c2ecf20Sopenharmony_ci * emitting into a .arm or a .thumb section. The size of the add opcode 5268c2ecf20Sopenharmony_ci * above will be 2 bytes when emitting in Thumb mode and 4 bytes when 5278c2ecf20Sopenharmony_ci * emitting in ARM mode, so let's use this to account for the bias. 5288c2ecf20Sopenharmony_ci */ 5298c2ecf20Sopenharmony_ci .set .Lpc\@, . + (. - .Lb\@) 5308c2ecf20Sopenharmony_ci 5318c2ecf20Sopenharmony_ci .ifnc \op, add 5328c2ecf20Sopenharmony_ci \op\c \reg, [\tmp] 5338c2ecf20Sopenharmony_ci .endif 5348c2ecf20Sopenharmony_ci#endif 5358c2ecf20Sopenharmony_ci .endm 5368c2ecf20Sopenharmony_ci 5378c2ecf20Sopenharmony_ci /* 5388c2ecf20Sopenharmony_ci * mov_l - move a constant value or [relocated] address into a register 5398c2ecf20Sopenharmony_ci */ 5408c2ecf20Sopenharmony_ci .macro mov_l, dst:req, imm:req 5418c2ecf20Sopenharmony_ci .if CONFIG_RELOCATABLE == 1 || __LINUX_ARM_ARCH__ < 7 5428c2ecf20Sopenharmony_ci ldr \dst, =\imm 5438c2ecf20Sopenharmony_ci .else 5448c2ecf20Sopenharmony_ci movw \dst, #:lower16:\imm 5458c2ecf20Sopenharmony_ci movt \dst, #:upper16:\imm 5468c2ecf20Sopenharmony_ci .endif 5478c2ecf20Sopenharmony_ci .endm 5488c2ecf20Sopenharmony_ci 5498c2ecf20Sopenharmony_ci /* 5508c2ecf20Sopenharmony_ci * adr_l - adr pseudo-op with unlimited range 5518c2ecf20Sopenharmony_ci * 5528c2ecf20Sopenharmony_ci * @dst: destination register 5538c2ecf20Sopenharmony_ci * @sym: name of the symbol 5548c2ecf20Sopenharmony_ci * @cond: conditional opcode suffix 5558c2ecf20Sopenharmony_ci */ 5568c2ecf20Sopenharmony_ci .macro adr_l, dst:req, sym:req, cond 5578c2ecf20Sopenharmony_ci __adldst_l add, \dst, \sym, \dst, \cond 5588c2ecf20Sopenharmony_ci .endm 5598c2ecf20Sopenharmony_ci 5608c2ecf20Sopenharmony_ci /* 5618c2ecf20Sopenharmony_ci * ldr_l - ldr <literal> pseudo-op with unlimited range 5628c2ecf20Sopenharmony_ci * 5638c2ecf20Sopenharmony_ci * @dst: destination register 5648c2ecf20Sopenharmony_ci * @sym: name of the symbol 5658c2ecf20Sopenharmony_ci * @cond: conditional opcode suffix 5668c2ecf20Sopenharmony_ci */ 5678c2ecf20Sopenharmony_ci .macro ldr_l, dst:req, sym:req, cond 5688c2ecf20Sopenharmony_ci __adldst_l ldr, \dst, \sym, \dst, \cond 5698c2ecf20Sopenharmony_ci .endm 5708c2ecf20Sopenharmony_ci 5718c2ecf20Sopenharmony_ci /* 5728c2ecf20Sopenharmony_ci * str_l - str <literal> pseudo-op with unlimited range 5738c2ecf20Sopenharmony_ci * 5748c2ecf20Sopenharmony_ci * @src: source register 5758c2ecf20Sopenharmony_ci * @sym: name of the symbol 5768c2ecf20Sopenharmony_ci * @tmp: mandatory scratch register 5778c2ecf20Sopenharmony_ci * @cond: conditional opcode suffix 5788c2ecf20Sopenharmony_ci */ 5798c2ecf20Sopenharmony_ci .macro str_l, src:req, sym:req, tmp:req, cond 5808c2ecf20Sopenharmony_ci __adldst_l str, \src, \sym, \tmp, \cond 5818c2ecf20Sopenharmony_ci .endm 5828c2ecf20Sopenharmony_ci 5838c2ecf20Sopenharmony_ci#endif /* __ASM_ASSEMBLER_H__ */ 584