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

pal.S (7880B)


      1/* SPDX-License-Identifier: GPL-2.0 */
      2/*
      3 * PAL Firmware support
      4 * IA-64 Processor Programmers Reference Vol 2
      5 *
      6 * Copyright (C) 1999 Don Dugger <don.dugger@intel.com>
      7 * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
      8 * Copyright (C) 1999-2001, 2003 Hewlett-Packard Co
      9 *	David Mosberger <davidm@hpl.hp.com>
     10 *	Stephane Eranian <eranian@hpl.hp.com>
     11 *
     12 * 05/22/2000 eranian Added support for stacked register calls
     13 * 05/24/2000 eranian Added support for physical mode static calls
     14 */
     15
     16#include <asm/asmmacro.h>
     17#include <asm/processor.h>
     18#include <asm/export.h>
     19
     20	.data
     21pal_entry_point:
     22	data8 ia64_pal_default_handler
     23	.text
     24
     25/*
     26 * Set the PAL entry point address.  This could be written in C code, but we
     27 * do it here to keep it all in one module (besides, it's so trivial that it's
     28 * not a big deal).
     29 *
     30 * in0		Address of the PAL entry point (text address, NOT a function
     31 *		descriptor).
     32 */
     33GLOBAL_ENTRY(ia64_pal_handler_init)
     34	alloc r3=ar.pfs,1,0,0,0
     35	movl r2=pal_entry_point
     36	;;
     37	st8 [r2]=in0
     38	br.ret.sptk.many rp
     39END(ia64_pal_handler_init)
     40
     41/*
     42 * Default PAL call handler.  This needs to be coded in assembly because it
     43 * uses the static calling convention, i.e., the RSE may not be used and
     44 * calls are done via "br.cond" (not "br.call").
     45 */
     46GLOBAL_ENTRY(ia64_pal_default_handler)
     47	mov r8=-1
     48	br.cond.sptk.many rp
     49END(ia64_pal_default_handler)
     50
     51/*
     52 * Make a PAL call using the static calling convention.
     53 *
     54 * in0         Index of PAL service
     55 * in1 - in3   Remaining PAL arguments
     56 */
     57GLOBAL_ENTRY(ia64_pal_call_static)
     58	.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(4)
     59	alloc loc1 = ar.pfs,4,5,0,0
     60	movl loc2 = pal_entry_point
     611:	{
     62	  mov r28 = in0
     63	  mov r29 = in1
     64	  mov r8 = ip
     65	}
     66	;;
     67	ld8 loc2 = [loc2]		// loc2 <- entry point
     68	adds r8 = 1f-1b,r8
     69	mov loc4=ar.rsc			// save RSE configuration
     70	;;
     71	mov ar.rsc=0			// put RSE in enforced lazy, LE mode
     72	mov loc3 = psr
     73	mov loc0 = rp
     74	.body
     75	mov r30 = in2
     76
     77	mov r31 = in3
     78	mov b7 = loc2
     79
     80	rsm psr.i
     81	;;
     82	mov rp = r8
     83	br.cond.sptk.many b7
     841:	mov psr.l = loc3
     85	mov ar.rsc = loc4		// restore RSE configuration
     86	mov ar.pfs = loc1
     87	mov rp = loc0
     88	;;
     89	srlz.d				// serialize restoration of psr.l
     90	br.ret.sptk.many b0
     91END(ia64_pal_call_static)
     92EXPORT_SYMBOL(ia64_pal_call_static)
     93
     94/*
     95 * Make a PAL call using the stacked registers calling convention.
     96 *
     97 * Inputs:
     98 *	in0         Index of PAL service
     99 *	in2 - in3   Remaining PAL arguments
    100 */
    101GLOBAL_ENTRY(ia64_pal_call_stacked)
    102	.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(4)
    103	alloc loc1 = ar.pfs,4,4,4,0
    104	movl loc2 = pal_entry_point
    105
    106	mov r28  = in0			// Index MUST be copied to r28
    107	mov out0 = in0			// AND in0 of PAL function
    108	mov loc0 = rp
    109	.body
    110	;;
    111	ld8 loc2 = [loc2]		// loc2 <- entry point
    112	mov out1 = in1
    113	mov out2 = in2
    114	mov out3 = in3
    115	mov loc3 = psr
    116	;;
    117	rsm psr.i
    118	mov b7 = loc2
    119	;;
    120	br.call.sptk.many rp=b7		// now make the call
    121.ret0:	mov psr.l  = loc3
    122	mov ar.pfs = loc1
    123	mov rp = loc0
    124	;;
    125	srlz.d				// serialize restoration of psr.l
    126	br.ret.sptk.many b0
    127END(ia64_pal_call_stacked)
    128EXPORT_SYMBOL(ia64_pal_call_stacked)
    129
    130/*
    131 * Make a physical mode PAL call using the static registers calling convention.
    132 *
    133 * Inputs:
    134 *	in0         Index of PAL service
    135 *	in2 - in3   Remaining PAL arguments
    136 *
    137 * PSR_LP, PSR_TB, PSR_ID, PSR_DA are never set by the kernel.
    138 * So we don't need to clear them.
    139 */
    140#define PAL_PSR_BITS_TO_CLEAR						      \
    141	(IA64_PSR_I | IA64_PSR_IT | IA64_PSR_DT  | IA64_PSR_DB | IA64_PSR_RT |\
    142	 IA64_PSR_DD | IA64_PSR_SS | IA64_PSR_RI | IA64_PSR_ED |	      \
    143	 IA64_PSR_DFL | IA64_PSR_DFH)
    144
    145#define PAL_PSR_BITS_TO_SET						      \
    146	(IA64_PSR_BN)
    147
    148
    149GLOBAL_ENTRY(ia64_pal_call_phys_static)
    150	.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(4)
    151	alloc loc1 = ar.pfs,4,7,0,0
    152	movl loc2 = pal_entry_point
    1531:	{
    154	  mov r28  = in0		// copy procedure index
    155	  mov r8   = ip			// save ip to compute branch
    156	  mov loc0 = rp			// save rp
    157	}
    158	.body
    159	;;
    160	ld8 loc2 = [loc2]		// loc2 <- entry point
    161	mov r29  = in1			// first argument
    162	mov r30  = in2			// copy arg2
    163	mov r31  = in3			// copy arg3
    164	;;
    165	mov loc3 = psr			// save psr
    166	adds r8  = 1f-1b,r8		// calculate return address for call
    167	;;
    168	mov loc4=ar.rsc			// save RSE configuration
    169	dep.z loc2=loc2,0,61		// convert pal entry point to physical
    170	tpa r8=r8			// convert rp to physical
    171	;;
    172	mov b7 = loc2			// install target to branch reg
    173	mov ar.rsc=0			// put RSE in enforced lazy, LE mode
    174	movl r16=PAL_PSR_BITS_TO_CLEAR
    175	movl r17=PAL_PSR_BITS_TO_SET
    176	;;
    177	or loc3=loc3,r17		// add in psr the bits to set
    178	;;
    179	andcm r16=loc3,r16		// removes bits to clear from psr
    180	br.call.sptk.many rp=ia64_switch_mode_phys
    181	mov rp = r8			// install return address (physical)
    182	mov loc5 = r19
    183	mov loc6 = r20
    184	br.cond.sptk.many b7
    1851:
    186	mov ar.rsc=0			// put RSE in enforced lazy, LE mode
    187	mov r16=loc3			// r16= original psr
    188	mov r19=loc5
    189	mov r20=loc6
    190	br.call.sptk.many rp=ia64_switch_mode_virt // return to virtual mode
    191	mov psr.l = loc3		// restore init PSR
    192
    193	mov ar.pfs = loc1
    194	mov rp = loc0
    195	;;
    196	mov ar.rsc=loc4			// restore RSE configuration
    197	srlz.d				// serialize restoration of psr.l
    198	br.ret.sptk.many b0
    199END(ia64_pal_call_phys_static)
    200EXPORT_SYMBOL(ia64_pal_call_phys_static)
    201
    202/*
    203 * Make a PAL call using the stacked registers in physical mode.
    204 *
    205 * Inputs:
    206 *	in0         Index of PAL service
    207 *	in2 - in3   Remaining PAL arguments
    208 */
    209GLOBAL_ENTRY(ia64_pal_call_phys_stacked)
    210	.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(5)
    211	alloc	loc1 = ar.pfs,5,7,4,0
    212	movl	loc2 = pal_entry_point
    2131:	{
    214	  mov r28  = in0		// copy procedure index
    215	  mov loc0 = rp			// save rp
    216	}
    217	.body
    218	;;
    219	ld8 loc2 = [loc2]		// loc2 <- entry point
    220	mov loc3 = psr			// save psr
    221	;;
    222	mov loc4=ar.rsc			// save RSE configuration
    223	dep.z loc2=loc2,0,61		// convert pal entry point to physical
    224	;;
    225	mov ar.rsc=0			// put RSE in enforced lazy, LE mode
    226	movl r16=PAL_PSR_BITS_TO_CLEAR
    227	movl r17=PAL_PSR_BITS_TO_SET
    228	;;
    229	or loc3=loc3,r17		// add in psr the bits to set
    230	mov b7 = loc2			// install target to branch reg
    231	;;
    232	andcm r16=loc3,r16		// removes bits to clear from psr
    233	br.call.sptk.many rp=ia64_switch_mode_phys
    234
    235	mov out0 = in0			// first argument
    236	mov out1 = in1			// copy arg2
    237	mov out2 = in2			// copy arg3
    238	mov out3 = in3			// copy arg3
    239	mov loc5 = r19
    240	mov loc6 = r20
    241
    242	br.call.sptk.many rp=b7		// now make the call
    243
    244	mov ar.rsc=0			// put RSE in enforced lazy, LE mode
    245	mov r16=loc3			// r16= original psr
    246	mov r19=loc5
    247	mov r20=loc6
    248	br.call.sptk.many rp=ia64_switch_mode_virt // return to virtual mode
    249
    250	mov psr.l  = loc3		// restore init PSR
    251	mov ar.pfs = loc1
    252	mov rp = loc0
    253	;;
    254	mov ar.rsc=loc4			// restore RSE configuration
    255	srlz.d				// serialize restoration of psr.l
    256	br.ret.sptk.many b0
    257END(ia64_pal_call_phys_stacked)
    258EXPORT_SYMBOL(ia64_pal_call_phys_stacked)
    259
    260/*
    261 * Save scratch fp scratch regs which aren't saved in pt_regs already
    262 * (fp10-fp15).
    263 *
    264 * NOTE: We need to do this since firmware (SAL and PAL) may use any of the
    265 * scratch regs fp-low partition.
    266 *
    267 * Inputs:
    268 *      in0	Address of stack storage for fp regs
    269 */
    270GLOBAL_ENTRY(ia64_save_scratch_fpregs)
    271	alloc r3=ar.pfs,1,0,0,0
    272	add r2=16,in0
    273	;;
    274	stf.spill [in0] = f10,32
    275	stf.spill [r2]  = f11,32
    276	;;
    277	stf.spill [in0] = f12,32
    278	stf.spill [r2]  = f13,32
    279	;;
    280	stf.spill [in0] = f14,32
    281	stf.spill [r2]  = f15,32
    282	br.ret.sptk.many rp
    283END(ia64_save_scratch_fpregs)
    284EXPORT_SYMBOL(ia64_save_scratch_fpregs)
    285
    286/*
    287 * Load scratch fp scratch regs (fp10-fp15)
    288 *
    289 * Inputs:
    290 *      in0	Address of stack storage for fp regs
    291 */
    292GLOBAL_ENTRY(ia64_load_scratch_fpregs)
    293	alloc r3=ar.pfs,1,0,0,0
    294	add r2=16,in0
    295	;;
    296	ldf.fill  f10 = [in0],32
    297	ldf.fill  f11 = [r2],32
    298	;;
    299	ldf.fill  f12 = [in0],32
    300	ldf.fill  f13 = [r2],32
    301	;;
    302	ldf.fill  f14 = [in0],32
    303	ldf.fill  f15 = [r2],32
    304	br.ret.sptk.many rp
    305END(ia64_load_scratch_fpregs)
    306EXPORT_SYMBOL(ia64_load_scratch_fpregs)