summary refs log tree commit diff
path: root/arch
diff options
context:
space:
mode:
authorMartin Schwidefsky <schwidefsky@de.ibm.com>2010-10-25 16:10:38 +0200
committerMartin Schwidefsky <sky@mschwide.boeblingen.de.ibm.com>2010-10-25 16:10:19 +0200
commitf6649a7e5a9ee99e9623878f4a5579cc2f6cdd51 (patch)
tree183438313c7593565980a1445f208e0ba30162cd /arch
parent1e54622e0403891b10f2105663e0f9dd595a1f17 (diff)
downloadlinux-f6649a7e5a9ee99e9623878f4a5579cc2f6cdd51.tar.gz
[S390] cleanup lowcore access from external interrupts
Read external interrupts parameters from the lowcore in the first
level interrupt handler in entry[64].S.

Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/s390/include/asm/s390_ext.h2
-rw-r--r--arch/s390/kernel/asm-offsets.c2
-rw-r--r--arch/s390/kernel/entry.S3
-rw-r--r--arch/s390/kernel/entry.h2
-rw-r--r--arch/s390/kernel/entry64.S5
-rw-r--r--arch/s390/kernel/s390_ext.c9
-rw-r--r--arch/s390/kernel/smp.c3
-rw-r--r--arch/s390/kernel/time.c17
-rw-r--r--arch/s390/kernel/vtime.c3
-rw-r--r--arch/s390/mm/fault.c11
10 files changed, 35 insertions, 22 deletions
diff --git a/arch/s390/include/asm/s390_ext.h b/arch/s390/include/asm/s390_ext.h
index 2afc060266a2..1a9307e70842 100644
--- a/arch/s390/include/asm/s390_ext.h
+++ b/arch/s390/include/asm/s390_ext.h
@@ -12,7 +12,7 @@
 
 #include <linux/types.h>
 
-typedef void (*ext_int_handler_t)(__u16 code);
+typedef void (*ext_int_handler_t)(unsigned int, unsigned int, unsigned long);
 
 typedef struct ext_int_info_t {
 	struct ext_int_info_t *next;
diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c
index 76328deb31f7..f3c1b823c9a8 100644
--- a/arch/s390/kernel/asm-offsets.c
+++ b/arch/s390/kernel/asm-offsets.c
@@ -143,10 +143,8 @@ int main(void)
 	DEFINE(__LC_GPREGS_SAVE_AREA, offsetof(struct _lowcore, gpregs_save_area));
 	DEFINE(__LC_CREGS_SAVE_AREA, offsetof(struct _lowcore, cregs_save_area));
 #ifdef CONFIG_32BIT
-	DEFINE(__LC_PFAULT_INTPARM, offsetof(struct _lowcore, ext_params));
 	DEFINE(SAVE_AREA_BASE, offsetof(struct _lowcore, extended_save_area_addr));
 #else /* CONFIG_32BIT */
-	DEFINE(__LC_PFAULT_INTPARM, offsetof(struct _lowcore, ext_params2));
 	DEFINE(__LC_EXT_PARAMS2, offsetof(struct _lowcore, ext_params2));
 	DEFINE(SAVE_AREA_BASE, offsetof(struct _lowcore, floating_pt_save_area));
 	DEFINE(__LC_PASTE, offsetof(struct _lowcore, paste));
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index adf25246f72e..736d7010629e 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -722,7 +722,8 @@ ext_no_vtime:
 	l	%r9,__LC_THREAD_INFO	# load pointer to thread_info struct
 	TRACE_IRQS_OFF
 	la	%r2,SP_PTREGS(%r15)	# address of register-save area
-	lh	%r3,__LC_EXT_INT_CODE	# get interruption code
+	l	%r3,__LC_CPU_ADDRESS	# get cpu address + interruption code
+	l	%r4,__LC_EXT_PARAMS	# get external parameters
 	l	%r1,BASED(.Ldo_extint)
 	basr	%r14,%r1
 	b	BASED(io_return)
diff --git a/arch/s390/kernel/entry.h b/arch/s390/kernel/entry.h
index 714ff2e57c6b..95c1dfc4ef31 100644
--- a/arch/s390/kernel/entry.h
+++ b/arch/s390/kernel/entry.h
@@ -19,7 +19,7 @@ void do_signal(struct pt_regs *regs);
 int handle_signal32(unsigned long sig, struct k_sigaction *ka,
 		    siginfo_t *info, sigset_t *oldset, struct pt_regs *regs);
 
-void do_extint(struct pt_regs *regs, unsigned short code);
+void do_extint(struct pt_regs *regs, unsigned int, unsigned int, unsigned long);
 int __cpuinit start_secondary(void *cpuvoid);
 void __init startup_init(void);
 void die(const char * str, struct pt_regs * regs, long err);
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S
index 2d205e4e7bb6..e4038ea4dc57 100644
--- a/arch/s390/kernel/entry64.S
+++ b/arch/s390/kernel/entry64.S
@@ -727,8 +727,11 @@ ext_int_handler:
 ext_no_vtime:
 	HANDLE_SIE_INTERCEPT
 	TRACE_IRQS_OFF
+	lghi	%r1,4096
 	la	%r2,SP_PTREGS(%r15)	# address of register-save area
-	llgh	%r3,__LC_EXT_INT_CODE	# get interruption code
+	llgf	%r3,__LC_CPU_ADDRESS	# get cpu address + interruption code
+	llgf	%r4,__LC_EXT_PARAMS	# get external parameter
+	lg	%r5,__LC_EXT_PARAMS2-4096(%r1)	# get 64 bit external parameter
 	brasl	%r14,do_extint
 	j	io_return
 
diff --git a/arch/s390/kernel/s390_ext.c b/arch/s390/kernel/s390_ext.c
index 9ce641b5291f..bd1db508e8af 100644
--- a/arch/s390/kernel/s390_ext.c
+++ b/arch/s390/kernel/s390_ext.c
@@ -113,12 +113,15 @@ int unregister_early_external_interrupt(__u16 code, ext_int_handler_t handler,
 	return 0;
 }
 
-void __irq_entry do_extint(struct pt_regs *regs, unsigned short code)
+void __irq_entry do_extint(struct pt_regs *regs, unsigned int ext_int_code,
+			   unsigned int param32, unsigned long param64)
 {
+	struct pt_regs *old_regs;
+	unsigned short code;
         ext_int_info_t *p;
         int index;
-	struct pt_regs *old_regs;
 
+	code = (unsigned short) ext_int_code;
 	old_regs = set_irq_regs(regs);
 	s390_idle_check(regs, S390_lowcore.int_clock,
 			S390_lowcore.async_enter_timer);
@@ -132,7 +135,7 @@ void __irq_entry do_extint(struct pt_regs *regs, unsigned short code)
         index = ext_hash(code);
 	for (p = ext_int_hash[index]; p; p = p->next) {
 		if (likely(p->code == code))
-			p->handler(code);
+			p->handler(ext_int_code, param32, param64);
 	}
 	irq_exit();
 	set_irq_regs(old_regs);
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index 8127ebd59c4d..354589d096b1 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -156,7 +156,8 @@ void smp_send_stop(void)
  * cpus are handled.
  */
 
-static void do_ext_call_interrupt(__u16 code)
+static void do_ext_call_interrupt(unsigned int ext_int_code,
+				  unsigned int param32, unsigned long param64)
 {
 	unsigned long bits;
 
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
index 2896cac9c14a..f754a6dc4f94 100644
--- a/arch/s390/kernel/time.c
+++ b/arch/s390/kernel/time.c
@@ -155,7 +155,9 @@ void init_cpu_timer(void)
 	__ctl_set_bit(0, 4);
 }
 
-static void clock_comparator_interrupt(__u16 code)
+static void clock_comparator_interrupt(unsigned int ext_int_code,
+				       unsigned int param32,
+				       unsigned long param64)
 {
 	if (S390_lowcore.clock_comparator == -1ULL)
 		set_clock_comparator(S390_lowcore.clock_comparator);
@@ -164,14 +166,13 @@ static void clock_comparator_interrupt(__u16 code)
 static void etr_timing_alert(struct etr_irq_parm *);
 static void stp_timing_alert(struct stp_irq_parm *);
 
-static void timing_alert_interrupt(__u16 code)
+static void timing_alert_interrupt(unsigned int ext_int_code,
+				   unsigned int param32, unsigned long param64)
 {
-	if (S390_lowcore.ext_params & 0x00c40000)
-		etr_timing_alert((struct etr_irq_parm *)
-				 &S390_lowcore.ext_params);
-	if (S390_lowcore.ext_params & 0x00038000)
-		stp_timing_alert((struct stp_irq_parm *)
-				 &S390_lowcore.ext_params);
+	if (param32 & 0x00c40000)
+		etr_timing_alert((struct etr_irq_parm *) &param32);
+	if (param32 & 0x00038000)
+		stp_timing_alert((struct stp_irq_parm *) &param32);
 }
 
 static void etr_reset(void);
diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c
index 3479f1b0d4e0..56c8687b29b3 100644
--- a/arch/s390/kernel/vtime.c
+++ b/arch/s390/kernel/vtime.c
@@ -314,7 +314,8 @@ static void do_callbacks(struct list_head *cb_list)
 /*
  * Handler for the virtual CPU timer.
  */
-static void do_cpu_timer_interrupt(__u16 error_code)
+static void do_cpu_timer_interrupt(unsigned int ext_int_code,
+				   unsigned int param32, unsigned long param64)
 {
 	struct vtimer_queue *vq;
 	struct vtimer_list *event, *tmp;
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
index b6570069b127..b4aad0c1f562 100644
--- a/arch/s390/mm/fault.c
+++ b/arch/s390/mm/fault.c
@@ -542,7 +542,8 @@ void pfault_fini(void)
 		: : "a" (&refbk), "m" (refbk) : "cc");
 }
 
-static void pfault_interrupt(__u16 int_code)
+static void pfault_interrupt(unsigned int ext_int_code,
+			     unsigned int param32, unsigned long param64)
 {
 	struct task_struct *tsk;
 	__u16 subcode;
@@ -553,14 +554,18 @@ static void pfault_interrupt(__u16 int_code)
 	 * in the 'cpu address' field associated with the
          * external interrupt. 
 	 */
-	subcode = S390_lowcore.cpu_addr;
+	subcode = ext_int_code >> 16;
 	if ((subcode & 0xff00) != __SUBCODE_MASK)
 		return;
 
 	/*
 	 * Get the token (= address of the task structure of the affected task).
 	 */
-	tsk = *(struct task_struct **) __LC_PFAULT_INTPARM;
+#ifdef CONFIG_64BIT
+	tsk = *(struct task_struct **) param64;
+#else
+	tsk = *(struct task_struct **) param32;
+#endif
 
 	if (subcode & 0x0080) {
 		/* signal bit is set -> a page has been swapped in by VM */