summaryrefslogtreecommitdiffstats
path: root/arch/ia64/kernel/pal.S
diff options
context:
space:
mode:
Diffstat (limited to 'arch/ia64/kernel/pal.S')
-rw-r--r--arch/ia64/kernel/pal.S192
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)