diff options
Diffstat (limited to 'arch/ia64/kernel/pal.S')
-rw-r--r-- | arch/ia64/kernel/pal.S | 192 |
1 files changed, 134 insertions, 58 deletions
diff --git a/arch/ia64/kernel/pal.S b/arch/ia64/kernel/pal.S index 1506bacc2..e6f44cfb6 100644 --- a/arch/ia64/kernel/pal.S +++ b/arch/ia64/kernel/pal.S @@ -4,9 +4,16 @@ * * Copyright (C) 1999 Don Dugger <don.dugger@intel.com> * Copyright (C) 1999 Walt Drummond <drummond@valinux.com> - * Copyright (C) 1999 David Mosberger <davidm@hpl.hp.com> + * Copyright (C) 1999-2000 David Mosberger <davidm@hpl.hp.com> + * Copyright (C) 2000 Stephane Eranian <eranian@hpl.hp.com> + * + * 05/22/2000 eranian Added support for stacked register calls + * 05/24/2000 eranian Added support for physical mode static calls */ +#include <asm/asmmacro.h> +#include <asm/processor.h> + .text .psr abi64 .psr lsb @@ -24,29 +31,23 @@ pal_entry_point: * * in0 Address of the PAL entry point (text address, NOT a function descriptor). */ - .align 16 - .global ia64_pal_handler_init - .proc ia64_pal_handler_init -ia64_pal_handler_init: +GLOBAL_ENTRY(ia64_pal_handler_init) alloc r3=ar.pfs,1,0,0,0 movl r2=pal_entry_point ;; st8 [r2]=in0 br.ret.sptk.few rp - - .endp ia64_pal_handler_init +END(ia64_pal_handler_init) /* * Default PAL call handler. This needs to be coded in assembly because it uses * the static calling convention, i.e., the RSE may not be used and calls are * done via "br.cond" (not "br.call"). */ - .align 16 - .global ia64_pal_default_handler - .proc ia64_pal_default_handler -ia64_pal_default_handler: +GLOBAL_ENTRY(ia64_pal_default_handler) mov r8=-1 br.cond.sptk.few rp +END(ia64_pal_default_handler) /* * Make a PAL call using the static calling convention. @@ -56,64 +57,139 @@ ia64_pal_default_handler: * in2 - in4 Remaning PAL arguments * */ +GLOBAL_ENTRY(ia64_pal_call_static) + UNW(.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(6)) + alloc loc1 = ar.pfs,6,90,0,0 + movl loc2 = pal_entry_point +1: { + mov r28 = in0 + mov r29 = in1 + mov r8 = ip + } + ;; + ld8 loc2 = [loc2] // loc2 <- entry point + mov r30 = in2 + mov r31 = in3 + ;; + mov loc3 = psr + mov loc0 = rp + UNW(.body) + adds r8 = .ret0-1b,r8 + ;; + rsm psr.i + mov b7 = loc2 + mov rp = r8 + ;; + br.cond.sptk.few b7 +.ret0: mov psr.l = loc3 + mov ar.pfs = loc1 + mov rp = loc0 + ;; + srlz.d // seralize restoration of psr.l + br.ret.sptk.few b0 +END(ia64_pal_call_static) -#ifdef __GCC_MULTIREG_RETVALS__ -# define arg0 in0 -# define arg1 in1 -# define arg2 in2 -# define arg3 in3 -# define arg4 in4 -#else -# define arg0 in1 -# define arg1 in2 -# define arg2 in3 -# define arg3 in4 -# define arg4 in5 -#endif +/* + * Make a PAL call using the stacked registers calling convention. + * + * Inputs: + * in0 Index of PAL service + * in2 - in3 Remaning PAL arguments + */ +GLOBAL_ENTRY(ia64_pal_call_stacked) + UNW(.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(5)) + alloc loc1 = ar.pfs,5,4,87,0 + movl loc2 = pal_entry_point - .text - .psr abi64 - .psr lsb - .lsb + mov r28 = in0 // Index MUST be copied to r28 + mov out0 = in0 // AND in0 of PAL function + mov loc0 = rp + UNW(.body) + ;; + ld8 loc2 = [loc2] // loc2 <- entry point + mov out1 = in1 + mov out2 = in2 + mov out3 = in3 + mov loc3 = psr + ;; + rsm psr.i + mov b7 = loc2 + ;; + br.call.sptk.many rp=b7 // now make the call +.ret2: + mov psr.l = loc3 + mov ar.pfs = loc1 + mov rp = loc0 + ;; + srlz.d // serialize restoration of psr.l + br.ret.sptk.few b0 +END(ia64_pal_call_stacked) + +/* + * Make a physical mode PAL call using the static registers calling convention. + * + * Inputs: + * in0 Index of PAL service + * in2 - in3 Remaning PAL arguments + * + * PSR_DB, PSR_LP, PSR_TB, PSR_ID, PSR_DA are never set by the kernel. + * So we don't need to clear them. + */ +#define PAL_PSR_BITS_TO_CLEAR \ + (IA64_PSR_I | IA64_PSR_IT | IA64_PSR_DT | IA64_PSR_RT | \ + IA64_PSR_DD | IA64_PSR_SS | IA64_PSR_RI | IA64_PSR_ED | \ + IA64_PSR_DFL | IA64_PSR_DFH) + +#define PAL_PSR_BITS_TO_SET \ + (IA64_PSR_BN) - .align 16 - .global ia64_pal_call_static - .proc ia64_pal_call_static -ia64_pal_call_static: - alloc loc0 = ar.pfs,6,90,0,0 - movl loc2 = pal_entry_point + +GLOBAL_ENTRY(ia64_pal_call_phys_static) + UNW(.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(6)) + alloc loc1 = ar.pfs,6,90,0,0 + movl loc2 = pal_entry_point 1: { - mov r28 = arg0 - mov r29 = arg1 - mov r8 = ip + mov r28 = in0 // copy procedure index + mov r8 = ip // save ip to compute branch + mov loc0 = rp // save rp } + UNW(.body) ;; - ld8 loc2 = [loc2] // loc2 <- entry point - mov r30 = arg2 - mov r31 = arg3 + ld8 loc2 = [loc2] // loc2 <- entry point + mov r29 = in1 // first argument + mov r30 = in2 // copy arg2 + mov r31 = in3 // copy arg3 ;; - mov loc3 = psr - mov loc1 = rp - adds r8 = .ret0-1b,r8 - ;; - rsm psr.i - mov b7 = loc2 - mov rp = r8 + mov loc3 = psr // save psr + adds r8 = .ret4-1b,r8 // calculate return address for call ;; - br.cond.sptk.few b7 -.ret0: mov psr.l = loc3 -#ifndef __GCC_MULTIREG_RETVALS__ - st8 [in0] = r8, 8 + mov loc4=ar.rsc // save RSE configuration + dep.z loc2=loc2,0,61 // convert pal entry point to physical + dep.z r8=r8,0,61 // convert rp to physical ;; - st8 [in0] = r9, 8 + mov b7 = loc2 // install target to branch reg + mov ar.rsc=r0 // put RSE in enforced lazy, LE mode + movl r16=PAL_PSR_BITS_TO_CLEAR + movl r17=PAL_PSR_BITS_TO_SET ;; - st8 [in0] = r10, 8 + or loc3=loc3,r17 // add in psr the bits to set ;; - st8 [in0] = r11, 8 -#endif - mov ar.pfs = loc0 - mov rp = loc1 + andcm r16=loc3,r16 // removes bits to clear from psr + br.call.sptk.few rp=ia64_switch_mode +.ret3: + mov rp = r8 // install return address (physical) + br.cond.sptk.few b7 +.ret4: + mov ar.rsc=r0 // put RSE in enforced lazy, LE mode + mov r16=loc3 // r16= original psr + br.call.sptk.few rp=ia64_switch_mode // return to virtual mode + +.ret5: mov psr.l = loc3 // restore init PSR + + mov ar.pfs = loc1 + mov rp = loc0 ;; + mov ar.rsc=loc4 // restore RSE configuration srlz.d // seralize restoration of psr.l br.ret.sptk.few b0 - .endp ia64_pal_call_static +END(ia64_pal_call_phys_static) |