cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

iwmmxt.S (8427B)


      1/* SPDX-License-Identifier: GPL-2.0-only */
      2/*
      3 *  linux/arch/arm/kernel/iwmmxt.S
      4 *
      5 *  XScale iWMMXt (Concan) context switching and handling
      6 *
      7 *  Initial code:
      8 *  Copyright (c) 2003, Intel Corporation
      9 *
     10 *  Full lazy switching support, optimizations and more, by Nicolas Pitre
     11*   Copyright (c) 2003-2004, MontaVista Software, Inc.
     12 */
     13
     14#include <linux/linkage.h>
     15#include <asm/ptrace.h>
     16#include <asm/thread_info.h>
     17#include <asm/asm-offsets.h>
     18#include <asm/assembler.h>
     19#include "iwmmxt.h"
     20
     21#if defined(CONFIG_CPU_PJ4) || defined(CONFIG_CPU_PJ4B)
     22#define PJ4(code...)		code
     23#define XSC(code...)
     24#elif defined(CONFIG_CPU_MOHAWK) || \
     25	defined(CONFIG_CPU_XSC3) || \
     26	defined(CONFIG_CPU_XSCALE)
     27#define PJ4(code...)
     28#define XSC(code...)		code
     29#else
     30#error "Unsupported iWMMXt architecture"
     31#endif
     32
     33#define MMX_WR0		 	(0x00)
     34#define MMX_WR1		 	(0x08)
     35#define MMX_WR2		 	(0x10)
     36#define MMX_WR3			(0x18)
     37#define MMX_WR4		 	(0x20)
     38#define MMX_WR5		 	(0x28)
     39#define MMX_WR6		 	(0x30)
     40#define MMX_WR7		 	(0x38)
     41#define MMX_WR8		 	(0x40)
     42#define MMX_WR9		 	(0x48)
     43#define MMX_WR10		(0x50)
     44#define MMX_WR11		(0x58)
     45#define MMX_WR12		(0x60)
     46#define MMX_WR13		(0x68)
     47#define MMX_WR14		(0x70)
     48#define MMX_WR15		(0x78)
     49#define MMX_WCSSF		(0x80)
     50#define MMX_WCASF		(0x84)
     51#define MMX_WCGR0		(0x88)
     52#define MMX_WCGR1		(0x8C)
     53#define MMX_WCGR2		(0x90)
     54#define MMX_WCGR3		(0x94)
     55
     56#define MMX_SIZE		(0x98)
     57
     58	.text
     59	.arm
     60
     61/*
     62 * Lazy switching of Concan coprocessor context
     63 *
     64 * r10 = struct thread_info pointer
     65 * r9  = ret_from_exception
     66 * lr  = undefined instr exit
     67 *
     68 * called from prefetch exception handler with interrupts enabled
     69 */
     70
     71ENTRY(iwmmxt_task_enable)
     72	inc_preempt_count r10, r3
     73
     74	XSC(mrc	p15, 0, r2, c15, c1, 0)
     75	PJ4(mrc p15, 0, r2, c1, c0, 2)
     76	@ CP0 and CP1 accessible?
     77	XSC(tst	r2, #0x3)
     78	PJ4(tst	r2, #0xf)
     79	bne	4f				@ if so no business here
     80	@ enable access to CP0 and CP1
     81	XSC(orr	r2, r2, #0x3)
     82	XSC(mcr	p15, 0, r2, c15, c1, 0)
     83	PJ4(orr	r2, r2, #0xf)
     84	PJ4(mcr	p15, 0, r2, c1, c0, 2)
     85
     86	ldr	r3, =concan_owner
     87	add	r0, r10, #TI_IWMMXT_STATE	@ get task Concan save area
     88	ldr	r2, [sp, #60]			@ current task pc value
     89	ldr	r1, [r3]			@ get current Concan owner
     90	str	r0, [r3]			@ this task now owns Concan regs
     91	sub	r2, r2, #4			@ adjust pc back
     92	str	r2, [sp, #60]
     93
     94	mrc	p15, 0, r2, c2, c0, 0
     95	mov	r2, r2				@ cpwait
     96	bl	concan_save
     97
     98#ifdef CONFIG_PREEMPT_COUNT
     99	get_thread_info r10
    100#endif
    1014:	dec_preempt_count r10, r3
    102	ret	r9				@ normal exit from exception
    103
    104concan_save:
    105
    106	teq	r1, #0				@ test for last ownership
    107	beq	concan_load			@ no owner, skip save
    108
    109	tmrc	r2, wCon
    110
    111	@ CUP? wCx
    112	tst	r2, #0x1
    113	beq 	1f
    114
    115concan_dump:
    116
    117	wstrw	wCSSF, r1, MMX_WCSSF
    118	wstrw	wCASF, r1, MMX_WCASF
    119	wstrw	wCGR0, r1, MMX_WCGR0
    120	wstrw	wCGR1, r1, MMX_WCGR1
    121	wstrw	wCGR2, r1, MMX_WCGR2
    122	wstrw	wCGR3, r1, MMX_WCGR3
    123
    1241:	@ MUP? wRn
    125	tst	r2, #0x2
    126	beq	2f
    127
    128	wstrd	wR0,  r1, MMX_WR0
    129	wstrd	wR1,  r1, MMX_WR1
    130	wstrd	wR2,  r1, MMX_WR2
    131	wstrd	wR3,  r1, MMX_WR3
    132	wstrd	wR4,  r1, MMX_WR4
    133	wstrd	wR5,  r1, MMX_WR5
    134	wstrd	wR6,  r1, MMX_WR6
    135	wstrd	wR7,  r1, MMX_WR7
    136	wstrd	wR8,  r1, MMX_WR8
    137	wstrd	wR9,  r1, MMX_WR9
    138	wstrd	wR10, r1, MMX_WR10
    139	wstrd	wR11, r1, MMX_WR11
    140	wstrd	wR12, r1, MMX_WR12
    141	wstrd	wR13, r1, MMX_WR13
    142	wstrd	wR14, r1, MMX_WR14
    143	wstrd	wR15, r1, MMX_WR15
    144
    1452:	teq	r0, #0				@ anything to load?
    146	reteq	lr				@ if not, return
    147
    148concan_load:
    149
    150	@ Load wRn
    151	wldrd	wR0,  r0, MMX_WR0
    152	wldrd	wR1,  r0, MMX_WR1
    153	wldrd	wR2,  r0, MMX_WR2
    154	wldrd	wR3,  r0, MMX_WR3
    155	wldrd	wR4,  r0, MMX_WR4
    156	wldrd	wR5,  r0, MMX_WR5
    157	wldrd	wR6,  r0, MMX_WR6
    158	wldrd	wR7,  r0, MMX_WR7
    159	wldrd	wR8,  r0, MMX_WR8
    160	wldrd	wR9,  r0, MMX_WR9
    161	wldrd	wR10, r0, MMX_WR10
    162	wldrd	wR11, r0, MMX_WR11
    163	wldrd	wR12, r0, MMX_WR12
    164	wldrd	wR13, r0, MMX_WR13
    165	wldrd	wR14, r0, MMX_WR14
    166	wldrd	wR15, r0, MMX_WR15
    167
    168	@ Load wCx
    169	wldrw	wCSSF, r0, MMX_WCSSF
    170	wldrw	wCASF, r0, MMX_WCASF
    171	wldrw	wCGR0, r0, MMX_WCGR0
    172	wldrw	wCGR1, r0, MMX_WCGR1
    173	wldrw	wCGR2, r0, MMX_WCGR2
    174	wldrw	wCGR3, r0, MMX_WCGR3
    175
    176	@ clear CUP/MUP (only if r1 != 0)
    177	teq	r1, #0
    178	mov 	r2, #0
    179	reteq	lr
    180
    181	tmcr	wCon, r2
    182	ret	lr
    183
    184ENDPROC(iwmmxt_task_enable)
    185
    186/*
    187 * Back up Concan regs to save area and disable access to them
    188 * (mainly for gdb or sleep mode usage)
    189 *
    190 * r0 = struct thread_info pointer of target task or NULL for any
    191 */
    192
    193ENTRY(iwmmxt_task_disable)
    194
    195	stmfd	sp!, {r4, lr}
    196
    197	mrs	ip, cpsr
    198	orr	r2, ip, #PSR_I_BIT		@ disable interrupts
    199	msr	cpsr_c, r2
    200
    201	ldr	r3, =concan_owner
    202	add	r2, r0, #TI_IWMMXT_STATE	@ get task Concan save area
    203	ldr	r1, [r3]			@ get current Concan owner
    204	teq	r1, #0				@ any current owner?
    205	beq	1f				@ no: quit
    206	teq	r0, #0				@ any owner?
    207	teqne	r1, r2				@ or specified one?
    208	bne	1f				@ no: quit
    209
    210	@ enable access to CP0 and CP1
    211	XSC(mrc	p15, 0, r4, c15, c1, 0)
    212	XSC(orr	r4, r4, #0x3)
    213	XSC(mcr	p15, 0, r4, c15, c1, 0)
    214	PJ4(mrc p15, 0, r4, c1, c0, 2)
    215	PJ4(orr	r4, r4, #0xf)
    216	PJ4(mcr	p15, 0, r4, c1, c0, 2)
    217
    218	mov	r0, #0				@ nothing to load
    219	str	r0, [r3]			@ no more current owner
    220	mrc	p15, 0, r2, c2, c0, 0
    221	mov	r2, r2				@ cpwait
    222	bl	concan_save
    223
    224	@ disable access to CP0 and CP1
    225	XSC(bic	r4, r4, #0x3)
    226	XSC(mcr	p15, 0, r4, c15, c1, 0)
    227	PJ4(bic	r4, r4, #0xf)
    228	PJ4(mcr	p15, 0, r4, c1, c0, 2)
    229
    230	mrc	p15, 0, r2, c2, c0, 0
    231	mov	r2, r2				@ cpwait
    232
    2331:	msr	cpsr_c, ip			@ restore interrupt mode
    234	ldmfd	sp!, {r4, pc}
    235
    236ENDPROC(iwmmxt_task_disable)
    237
    238/*
    239 * Copy Concan state to given memory address
    240 *
    241 * r0 = struct thread_info pointer of target task
    242 * r1 = memory address where to store Concan state
    243 *
    244 * this is called mainly in the creation of signal stack frames
    245 */
    246
    247ENTRY(iwmmxt_task_copy)
    248
    249	mrs	ip, cpsr
    250	orr	r2, ip, #PSR_I_BIT		@ disable interrupts
    251	msr	cpsr_c, r2
    252
    253	ldr	r3, =concan_owner
    254	add	r2, r0, #TI_IWMMXT_STATE	@ get task Concan save area
    255	ldr	r3, [r3]			@ get current Concan owner
    256	teq	r2, r3				@ does this task own it...
    257	beq	1f
    258
    259	@ current Concan values are in the task save area
    260	msr	cpsr_c, ip			@ restore interrupt mode
    261	mov	r0, r1
    262	mov	r1, r2
    263	mov	r2, #MMX_SIZE
    264	b	memcpy
    265
    2661:	@ this task owns Concan regs -- grab a copy from there
    267	mov	r0, #0				@ nothing to load
    268	mov	r2, #3				@ save all regs
    269	mov	r3, lr				@ preserve return address
    270	bl	concan_dump
    271	msr	cpsr_c, ip			@ restore interrupt mode
    272	ret	r3
    273
    274ENDPROC(iwmmxt_task_copy)
    275
    276/*
    277 * Restore Concan state from given memory address
    278 *
    279 * r0 = struct thread_info pointer of target task
    280 * r1 = memory address where to get Concan state from
    281 *
    282 * this is used to restore Concan state when unwinding a signal stack frame
    283 */
    284
    285ENTRY(iwmmxt_task_restore)
    286
    287	mrs	ip, cpsr
    288	orr	r2, ip, #PSR_I_BIT		@ disable interrupts
    289	msr	cpsr_c, r2
    290
    291	ldr	r3, =concan_owner
    292	add	r2, r0, #TI_IWMMXT_STATE	@ get task Concan save area
    293	ldr	r3, [r3]			@ get current Concan owner
    294	bic	r2, r2, #0x7			@ 64-bit alignment
    295	teq	r2, r3				@ does this task own it...
    296	beq	1f
    297
    298	@ this task doesn't own Concan regs -- use its save area
    299	msr	cpsr_c, ip			@ restore interrupt mode
    300	mov	r0, r2
    301	mov	r2, #MMX_SIZE
    302	b	memcpy
    303
    3041:	@ this task owns Concan regs -- load them directly
    305	mov	r0, r1
    306	mov	r1, #0				@ don't clear CUP/MUP
    307	mov	r3, lr				@ preserve return address
    308	bl	concan_load
    309	msr	cpsr_c, ip			@ restore interrupt mode
    310	ret	r3
    311
    312ENDPROC(iwmmxt_task_restore)
    313
    314/*
    315 * Concan handling on task switch
    316 *
    317 * r0 = next thread_info pointer
    318 *
    319 * Called only from the iwmmxt notifier with task preemption disabled.
    320 */
    321ENTRY(iwmmxt_task_switch)
    322
    323	XSC(mrc	p15, 0, r1, c15, c1, 0)
    324	PJ4(mrc	p15, 0, r1, c1, c0, 2)
    325	@ CP0 and CP1 accessible?
    326	XSC(tst	r1, #0x3)
    327	PJ4(tst	r1, #0xf)
    328	bne	1f				@ yes: block them for next task
    329
    330	ldr	r2, =concan_owner
    331	add	r3, r0, #TI_IWMMXT_STATE	@ get next task Concan save area
    332	ldr	r2, [r2]			@ get current Concan owner
    333	teq	r2, r3				@ next task owns it?
    334	retne	lr				@ no: leave Concan disabled
    335
    3361:	@ flip Concan access
    337	XSC(eor	r1, r1, #0x3)
    338	XSC(mcr	p15, 0, r1, c15, c1, 0)
    339	PJ4(eor r1, r1, #0xf)
    340	PJ4(mcr	p15, 0, r1, c1, c0, 2)
    341
    342	mrc	p15, 0, r1, c2, c0, 0
    343	sub	pc, lr, r1, lsr #32		@ cpwait and return
    344
    345ENDPROC(iwmmxt_task_switch)
    346
    347/*
    348 * Remove Concan ownership of given task
    349 *
    350 * r0 = struct thread_info pointer
    351 */
    352ENTRY(iwmmxt_task_release)
    353
    354	mrs	r2, cpsr
    355	orr	ip, r2, #PSR_I_BIT		@ disable interrupts
    356	msr	cpsr_c, ip
    357	ldr	r3, =concan_owner
    358	add	r0, r0, #TI_IWMMXT_STATE	@ get task Concan save area
    359	ldr	r1, [r3]			@ get current Concan owner
    360	eors	r0, r0, r1			@ if equal...
    361	streq	r0, [r3]			@ then clear ownership
    362	msr	cpsr_c, r2			@ restore interrupts
    363	ret	lr
    364
    365ENDPROC(iwmmxt_task_release)
    366
    367	.data
    368	.align	2
    369concan_owner:
    370	.word	0
    371