[patch 2/5] physical mode SAL calls

From: Horms <horms_at_verge.net.au>
Date: 2006-10-23 18:48:42
Currently the EFI code will fall back to making real mode calls
if the call to map the EFI code fails. Unfortunately this only
takes into account EFI calls, but if EFI calls are made in physical
mode SAL calls also need to be made in physical mode. On a Tiger2 at least,
forcing EFI to stay in physical mode caues the boot to oops in a SAL call.

This patch changes things around by adding code to allow SAL calls to
be made in physical mode. I then makes this the path that is allways
followed - that is SAL calls are always physical with this patch.

A small patch will follow that will make physical SAL calls when
physical EFI calls are in operation, and virtual SAL calls when
virtual EFI calls are in poration. However, again a Tiger2, it seems
that having SAL always physical does actually work. So although this
patch seems like it should break stuff, it doesn't.

Signed-Off-By: Simon Horman <horms@verge.net.au>

 arch/ia64/kernel/Makefile   |    2 
 arch/ia64/kernel/sal_stub.S |   92 +++++++++++++++++++++++++++++++++++++++++++
 include/asm-ia64/sal.h      |    4 +
 3 files changed, 96 insertions(+), 2 deletions(-)

Index: kexec-ia64-2.6/ia64/kernel/sal_stub.S
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ kexec-ia64-2.6/arch/ia64/kernel/sal_stub.S	2006-10-05 13:22:14.000000000 +0900
@@ -0,0 +1,92 @@
+/*
+ * SAL call stub.
+ *
+ * Copyright (C) 2006 Horms <horms@verge.net.au>
+ *
+ * Based heavily on arch/ia64/kernel/efi_stub.S
+ *
+ * Copyright (C) 1999-2001 Hewlett-Packard Co
+ *	David Mosberger <davidm@hpl.hp.com>
+ *
+ * This stub allows us to make PAL calls in physical mode with interrupts
+ * turned off. This is needed to make PAL calls if EFI has not been
+ * maped using SetVirtualMap() for one reason or another
+ */
+
+/*
+ * PSR settings as per SAL spec (Chapter 8 in the "IA-64 System
+ * Abstraction Layer Specification", revision 2.6e).  Note that
+ * psr.dfl and psr.dfh MUST be cleared, despite what this manual says.
+ * Otherwise, SAL dies whenever it's trying to do an IA-32 BIOS call
+ * (the br.ia instruction fails unless psr.dfl and psr.dfh are
+ * cleared).  Fortunately, SAL promises not to touch the floating
+ * point regs, so at least we don't have to save f2-f127.
+ */
+#define 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 PSR_BITS_TO_SET							\
+	(IA64_PSR_BN)
+
+#include <asm/processor.h>
+#include <asm/asmmacro.h>
+
+/*
+ * Inputs:
+ *	in0 = address of function descriptor of EFI routine to call
+ *	in1..in8 = arguments to routine
+ *
+ * Outputs:
+ *	r8..r11 = return
+ */
+
+GLOBAL_ENTRY(sal_call_phys)
+	.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(9)
+	alloc loc1=ar.pfs,9,8,8,0
+	ld8 r2=[in0],8			// load SAL function's entry point
+	mov loc0=rp			// save return pointer
+	.body
+	;;
+	mov loc2=gp			// save global pointer
+	mov loc4=ar.rsc			// save RSE configuration
+	mov ar.rsc=0			// put RSE in enforced lazy, LE mode
+	;;
+	dep r2=0,r2,61,3		// __pa
+	ld8 gp=[in0]			// load EFI function's global pointer
+	movl r16=PSR_BITS_TO_CLEAR
+	mov loc3=psr
+	movl r17=PSR_BITS_TO_SET
+	;;
+	or loc3=loc3,r17
+	mov b6=r2
+	;;
+	dep gp=0,gp,61,3		// __pa
+	andcm r16=loc3,r16
+	br.call.sptk.many rp=ia64_switch_mode_phys
+.ret0:	mov out0=in1
+	mov out1=in2
+	mov out2=in3
+	mov out3=in4
+	mov out4=in5
+	mov out5=in6
+	mov out6=in7
+	mov out7=in8
+	mov loc5=r19
+	mov loc6=r20
+	;;
+	br.call.sptk.many rp=b6		// call the SAL function
+	;;
+	mov ar.rsc=0                    // put RSE in enforced lazy, LE mode
+	mov r16=loc3
+	mov r19=loc5
+	mov r20=loc6
+.ret1:	br.call.sptk.many rp=ia64_switch_mode_virt // return to virtual 	;;
+.ret2:	mov ar.rsc=loc4                 // restore RSE configuration
+	mov ar.pfs = loc1		// restore register stack
+	mov rp=loc0			// retore return pointer
+	mov gp=loc2			// retore global pointer
+	br.ret.sptk.many rp
+END(sal_call_phys)
+
Index: kexec-ia64-2.6/arch/ia64/kernel/Makefile
===================================================================
--- kexec-ia64-2.6.orig/arch/ia64/kernel/Makefile	2006-10-05 13:22:05.000000000 +0900
+++ kexec-ia64-2.6/arch/ia64/kernel/Makefile	2006-10-05 13:22:14.000000000 +0900
@@ -7,7 +7,7 @@
 obj-y := acpi.o entry.o efi.o efi_stub.o gate-data.o fsys.o ia64_ksyms.o irq.o irq_ia64.o	\
 	 irq_lsapic.o ivt.o machvec.o pal.o patch.o process.o perfmon.o ptrace.o sal.o		\
 	 salinfo.o semaphore.o setup.o signal.o sys_ia64.o time.o traps.o unaligned.o \
-	 unwind.o mca.o mca_asm.o topology.o
+	 unwind.o mca.o mca_asm.o topology.o sal_stub.o
 
 obj-$(CONFIG_IA64_BRL_EMU)	+= brl_emu.o
 obj-$(CONFIG_IA64_GENERIC)	+= acpi-ext.o
Index: kexec-ia64-2.6/include/asm-ia64/sal.h
===================================================================
--- kexec-ia64-2.6.orig/include/asm-ia64/sal.h	2006-10-05 13:22:14.000000000 +0900
+++ kexec-ia64-2.6/include/asm-ia64/sal.h	2006-10-05 13:26:42.000000000 +0900
@@ -62,8 +62,10 @@
 typedef struct ia64_sal_retval (*ia64_sal_handler) (u64, ...);
 
 /* SAL spec _requires_ eight args for each call. */
+struct ia64_sal_retval sal_call_phys(ia64_sal_handler ia64_sal, ...);
+
 #define __SAL_CALL(result,a0,a1,a2,a3,a4,a5,a6,a7)	\
-	result = (*ia64_sal)(a0,a1,a2,a3,a4,a5,a6,a7)
+	result = sal_call_phys(ia64_sal,a0,a1,a2,a3,a4,a5,a6,a7);
 
 # define SAL_CALL(result,args...) do {				\
 	unsigned long __ia64_sc_flags;				\

--

-- 
Horms
  H: http://www.vergenet.net/~horms/
  W: http://www.valinux.co.jp/en/

-
To unsubscribe from this list: send the line "unsubscribe linux-ia64" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Received on Mon Oct 23 19:05:57 2006

This archive was generated by hypermail 2.1.8 : 2006-10-23 19:10:13 EST