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

real2.S (6525B)


      1/*
      2 *
      3 * This file is subject to the terms and conditions of the GNU General Public
      4 * License.  See the file "COPYING" in the main directory of this archive
      5 * for more details.
      6 *
      7 * Copyright (C) 2000 Hewlett Packard (Paul Bame bame@puffin.external.hp.com)
      8 *
      9 */
     10
     11#include <asm/pdc.h>
     12#include <asm/psw.h>
     13#include <asm/assembly.h>
     14#include <asm/asm-offsets.h>
     15
     16#include <linux/linkage.h>
     17
     18
     19	.section	.bss
     20
     21	.export pdc_result
     22	.export pdc_result2
     23	.align 8
     24pdc_result:
     25	.block	ASM_PDC_RESULT_SIZE
     26pdc_result2:
     27	.block	ASM_PDC_RESULT_SIZE
     28
     29	.export real_stack
     30	.export real32_stack
     31	.export real64_stack
     32	.align	64
     33real_stack:
     34real32_stack:
     35real64_stack:
     36	.block	8192
     37
     38#define N_SAVED_REGS 9
     39
     40save_cr_space:
     41	.block	REG_SZ * N_SAVED_REGS
     42save_cr_end:
     43
     44
     45/************************ 32-bit real-mode calls ***********************/
     46/* This can be called in both narrow and wide kernels */
     47
     48	.text
     49
     50	/* unsigned long real32_call_asm(unsigned int *sp,
     51	 *		unsigned int *arg0p,
     52	 *		unsigned int iodc_fn)
     53	 *	sp is value of stack pointer to adopt before calling PDC (virt)
     54	 *	arg0p points to where saved arg values may be found
     55	 *	iodc_fn is the IODC function to call
     56	 */
     57
     58ENTRY_CFI(real32_call_asm)
     59	STREG	%rp, -RP_OFFSET(%sp)	/* save RP */
     60#ifdef CONFIG_64BIT
     61	callee_save
     62	ldo	2*REG_SZ(%sp), %sp	/* room for a couple more saves */
     63	STREG	%r27, -1*REG_SZ(%sp)
     64	STREG	%r29, -2*REG_SZ(%sp)
     65#endif
     66	STREG	%sp, -REG_SZ(%arg0)	/* save SP on real-mode stack */
     67	copy	%arg0, %sp		/* adopt the real-mode SP */
     68
     69	/* save iodc_fn */
     70	copy	%arg2, %r31
     71
     72	/* load up the arg registers from the saved arg area */
     73	/* 32-bit calling convention passes first 4 args in registers */
     74	ldw	0(%arg1), %arg0		/* note overwriting arg0 */
     75	ldw	-8(%arg1), %arg2
     76	ldw	-12(%arg1), %arg3
     77	ldw	-4(%arg1), %arg1	/* obviously must do this one last! */
     78
     79	tophys_r1  %sp
     80
     81	b,l	rfi_virt2real,%r2
     82	nop
     83
     84	b,l	save_control_regs,%r2		/* modifies r1, r2, r28 */
     85	nop
     86
     87#ifdef CONFIG_64BIT
     88	rsm	PSW_SM_W, %r0		/* go narrow */
     89#endif
     90
     91	load32	PA(ric_ret), %r2
     92	bv	0(%r31)
     93	nop
     94ric_ret:
     95#ifdef CONFIG_64BIT
     96	ssm	PSW_SM_W, %r0		/* go wide */
     97#endif
     98	/* restore CRs before going virtual in case we page fault */
     99	b,l	restore_control_regs, %r2	/* modifies r1, r2, r26 */
    100	nop
    101
    102	b,l	rfi_real2virt,%r2
    103	nop
    104
    105	tovirt_r1 %sp
    106	LDREG	-REG_SZ(%sp), %sp	/* restore SP */
    107#ifdef CONFIG_64BIT
    108	LDREG	-1*REG_SZ(%sp), %r27
    109	LDREG	-2*REG_SZ(%sp), %r29
    110	ldo	-2*REG_SZ(%sp), %sp
    111	callee_rest
    112#endif
    113	LDREG	-RP_OFFSET(%sp), %rp	/* restore RP */
    114	bv	0(%rp)
    115	nop
    116ENDPROC_CFI(real32_call_asm)
    117
    118
    119#  define PUSH_CR(r, where) mfctl r, %r1 ! STREG,ma %r1, REG_SZ(where)
    120#  define POP_CR(r, where) LDREG,mb -REG_SZ(where), %r1 ! mtctl %r1, r
    121
    122	.text
    123ENTRY_CFI(save_control_regs)
    124	load32	PA(save_cr_space), %r28
    125	PUSH_CR(%cr24, %r28)
    126	PUSH_CR(%cr25, %r28)
    127	PUSH_CR(%cr26, %r28)
    128	PUSH_CR(%cr27, %r28)
    129	PUSH_CR(%cr28, %r28)
    130	PUSH_CR(%cr29, %r28)
    131	PUSH_CR(%cr30, %r28)
    132	PUSH_CR(%cr31, %r28)
    133	PUSH_CR(%cr15, %r28)
    134	bv 0(%r2)
    135	nop
    136ENDPROC_CFI(save_control_regs)
    137
    138ENTRY_CFI(restore_control_regs)
    139	load32	PA(save_cr_end), %r26
    140	POP_CR(%cr15, %r26)
    141	POP_CR(%cr31, %r26)
    142	POP_CR(%cr30, %r26)
    143	POP_CR(%cr29, %r26)
    144	POP_CR(%cr28, %r26)
    145	POP_CR(%cr27, %r26)
    146	POP_CR(%cr26, %r26)
    147	POP_CR(%cr25, %r26)
    148	POP_CR(%cr24, %r26)
    149	bv 0(%r2)
    150	nop
    151ENDPROC_CFI(restore_control_regs)
    152
    153/* rfi_virt2real() and rfi_real2virt() could perhaps be adapted for
    154 * more general-purpose use by the several places which need RFIs
    155 */
    156	.text
    157	.align 128
    158ENTRY_CFI(rfi_virt2real)
    159#if !defined(BOOTLOADER)
    160	/* switch to real mode... */
    161	rsm		PSW_SM_I,%r0
    162	load32		PA(rfi_v2r_1), %r1
    163	nop
    164	nop
    165	nop
    166	nop
    167	nop
    168	
    169	rsm             PSW_SM_Q,%r0  /* disable Q & I bits to load iia queue */
    170	mtctl		%r0, %cr17	/* Clear IIASQ tail */
    171	mtctl		%r0, %cr17	/* Clear IIASQ head */
    172	mtctl		%r1, %cr18	/* IIAOQ head */
    173	ldo		4(%r1), %r1
    174	mtctl		%r1, %cr18	/* IIAOQ tail */
    175	load32          REAL_MODE_PSW, %r1
    176	mtctl		%r1, %cr22
    177	rfi
    178	
    179	nop
    180	nop
    181	nop
    182	nop
    183	nop
    184	nop
    185	nop
    186	nop
    187rfi_v2r_1:
    188	tophys_r1 %r2
    189#endif /* defined(BOOTLOADER) */
    190	bv	0(%r2)
    191	nop
    192ENDPROC_CFI(rfi_virt2real)
    193
    194	.text
    195	.align 128
    196ENTRY_CFI(rfi_real2virt)
    197#if !defined(BOOTLOADER)
    198	rsm		PSW_SM_I,%r0
    199	load32		(rfi_r2v_1), %r1
    200	nop
    201	nop
    202	nop
    203	nop
    204	nop
    205	
    206	rsm             PSW_SM_Q,%r0    /* disable Q bit to load iia queue */
    207	mtctl		%r0, %cr17	/* Clear IIASQ tail */
    208	mtctl		%r0, %cr17	/* Clear IIASQ head */
    209	mtctl		%r1, %cr18	/* IIAOQ head */
    210	ldo		4(%r1), %r1
    211	mtctl		%r1, %cr18	/* IIAOQ tail */
    212	load32		KERNEL_PSW, %r1
    213	mtctl		%r1, %cr22
    214	rfi
    215	
    216	nop
    217	nop
    218	nop
    219	nop
    220	nop
    221	nop
    222	nop
    223	nop
    224rfi_r2v_1:
    225	tovirt_r1 %r2
    226#endif /* defined(BOOTLOADER) */
    227	bv	0(%r2)
    228	nop
    229ENDPROC_CFI(rfi_real2virt)
    230
    231#ifdef CONFIG_64BIT
    232
    233/************************ 64-bit real-mode calls ***********************/
    234/* This is only usable in wide kernels right now and will probably stay so */
    235	.text
    236	/* unsigned long real64_call_asm(unsigned long *sp,
    237	 *		unsigned long *arg0p,
    238	 *		unsigned long fn)
    239	 *	sp is value of stack pointer to adopt before calling PDC (virt)
    240	 *	arg0p points to where saved arg values may be found
    241	 *	iodc_fn is the IODC function to call
    242	 */
    243ENTRY_CFI(real64_call_asm)
    244	std	%rp, -0x10(%sp)		/* save RP */
    245	std	%sp, -8(%arg0)		/* save SP on real-mode stack */
    246	copy	%arg0, %sp		/* adopt the real-mode SP */
    247
    248	/* save fn */
    249	copy	%arg2, %r31
    250
    251	/* set up the new ap */
    252	ldo	64(%arg1), %r29
    253
    254	/* load up the arg registers from the saved arg area */
    255	/* 32-bit calling convention passes first 4 args in registers */
    256	ldd	0*REG_SZ(%arg1), %arg0		/* note overwriting arg0 */
    257	ldd	2*REG_SZ(%arg1), %arg2
    258	ldd	3*REG_SZ(%arg1), %arg3
    259	ldd	4*REG_SZ(%arg1), %r22
    260	ldd	5*REG_SZ(%arg1), %r21
    261	ldd	6*REG_SZ(%arg1), %r20
    262	ldd	7*REG_SZ(%arg1), %r19
    263	ldd	1*REG_SZ(%arg1), %arg1		/* do this one last! */
    264
    265	tophys_r1 %sp
    266
    267	b,l	rfi_virt2real,%r2
    268	nop
    269
    270	b,l	save_control_regs,%r2		/* modifies r1, r2, r28 */
    271	nop
    272
    273	load32	PA(r64_ret), %r2
    274	bv	0(%r31)
    275	nop
    276r64_ret:
    277	/* restore CRs before going virtual in case we page fault */
    278	b,l	restore_control_regs, %r2	/* modifies r1, r2, r26 */
    279	nop
    280
    281	b,l	rfi_real2virt,%r2
    282	nop
    283
    284	tovirt_r1 %sp
    285	ldd	-8(%sp), %sp		/* restore SP */
    286	ldd	-0x10(%sp), %rp		/* restore RP */
    287	bv	0(%rp)
    288	nop
    289ENDPROC_CFI(real64_call_asm)
    290
    291#endif
    292
    293	.text
    294	/* http://lists.parisc-linux.org/hypermail/parisc-linux/10916.html
    295	**	GCC 3.3 and later has a new function in libgcc.a for
    296	**	comparing function pointers.
    297	*/
    298ENTRY_CFI(__canonicalize_funcptr_for_compare)
    299#ifdef CONFIG_64BIT
    300	bve (%r2)
    301#else
    302	bv %r0(%r2)
    303#endif
    304	copy %r26,%r28
    305ENDPROC_CFI(__canonicalize_funcptr_for_compare)
    306