Commit f6649a7e5a9ee99e9623878f4a5579cc2f6cdd51

Authored by Martin Schwidefsky
Committed by Martin Schwidefsky
1 parent 1e54622e04

[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>

Showing 15 changed files with 57 additions and 49 deletions Side-by-side Diff

arch/s390/include/asm/s390_ext.h
... ... @@ -12,7 +12,7 @@
12 12  
13 13 #include <linux/types.h>
14 14  
15   -typedef void (*ext_int_handler_t)(__u16 code);
  15 +typedef void (*ext_int_handler_t)(unsigned int, unsigned int, unsigned long);
16 16  
17 17 typedef struct ext_int_info_t {
18 18 struct ext_int_info_t *next;
arch/s390/kernel/asm-offsets.c
... ... @@ -143,10 +143,8 @@
143 143 DEFINE(__LC_GPREGS_SAVE_AREA, offsetof(struct _lowcore, gpregs_save_area));
144 144 DEFINE(__LC_CREGS_SAVE_AREA, offsetof(struct _lowcore, cregs_save_area));
145 145 #ifdef CONFIG_32BIT
146   - DEFINE(__LC_PFAULT_INTPARM, offsetof(struct _lowcore, ext_params));
147 146 DEFINE(SAVE_AREA_BASE, offsetof(struct _lowcore, extended_save_area_addr));
148 147 #else /* CONFIG_32BIT */
149   - DEFINE(__LC_PFAULT_INTPARM, offsetof(struct _lowcore, ext_params2));
150 148 DEFINE(__LC_EXT_PARAMS2, offsetof(struct _lowcore, ext_params2));
151 149 DEFINE(SAVE_AREA_BASE, offsetof(struct _lowcore, floating_pt_save_area));
152 150 DEFINE(__LC_PASTE, offsetof(struct _lowcore, paste));
arch/s390/kernel/entry.S
... ... @@ -722,7 +722,8 @@
722 722 l %r9,__LC_THREAD_INFO # load pointer to thread_info struct
723 723 TRACE_IRQS_OFF
724 724 la %r2,SP_PTREGS(%r15) # address of register-save area
725   - lh %r3,__LC_EXT_INT_CODE # get interruption code
  725 + l %r3,__LC_CPU_ADDRESS # get cpu address + interruption code
  726 + l %r4,__LC_EXT_PARAMS # get external parameters
726 727 l %r1,BASED(.Ldo_extint)
727 728 basr %r14,%r1
728 729 b BASED(io_return)
arch/s390/kernel/entry.h
... ... @@ -19,7 +19,7 @@
19 19 int handle_signal32(unsigned long sig, struct k_sigaction *ka,
20 20 siginfo_t *info, sigset_t *oldset, struct pt_regs *regs);
21 21  
22   -void do_extint(struct pt_regs *regs, unsigned short code);
  22 +void do_extint(struct pt_regs *regs, unsigned int, unsigned int, unsigned long);
23 23 int __cpuinit start_secondary(void *cpuvoid);
24 24 void __init startup_init(void);
25 25 void die(const char * str, struct pt_regs * regs, long err);
arch/s390/kernel/entry64.S
... ... @@ -727,8 +727,11 @@
727 727 ext_no_vtime:
728 728 HANDLE_SIE_INTERCEPT
729 729 TRACE_IRQS_OFF
  730 + lghi %r1,4096
730 731 la %r2,SP_PTREGS(%r15) # address of register-save area
731   - llgh %r3,__LC_EXT_INT_CODE # get interruption code
  732 + llgf %r3,__LC_CPU_ADDRESS # get cpu address + interruption code
  733 + llgf %r4,__LC_EXT_PARAMS # get external parameter
  734 + lg %r5,__LC_EXT_PARAMS2-4096(%r1) # get 64 bit external parameter
732 735 brasl %r14,do_extint
733 736 j io_return
734 737  
arch/s390/kernel/s390_ext.c
... ... @@ -113,12 +113,15 @@
113 113 return 0;
114 114 }
115 115  
116   -void __irq_entry do_extint(struct pt_regs *regs, unsigned short code)
  116 +void __irq_entry do_extint(struct pt_regs *regs, unsigned int ext_int_code,
  117 + unsigned int param32, unsigned long param64)
117 118 {
  119 + struct pt_regs *old_regs;
  120 + unsigned short code;
118 121 ext_int_info_t *p;
119 122 int index;
120   - struct pt_regs *old_regs;
121 123  
  124 + code = (unsigned short) ext_int_code;
122 125 old_regs = set_irq_regs(regs);
123 126 s390_idle_check(regs, S390_lowcore.int_clock,
124 127 S390_lowcore.async_enter_timer);
... ... @@ -132,7 +135,7 @@
132 135 index = ext_hash(code);
133 136 for (p = ext_int_hash[index]; p; p = p->next) {
134 137 if (likely(p->code == code))
135   - p->handler(code);
  138 + p->handler(ext_int_code, param32, param64);
136 139 }
137 140 irq_exit();
138 141 set_irq_regs(old_regs);
arch/s390/kernel/smp.c
... ... @@ -156,7 +156,8 @@
156 156 * cpus are handled.
157 157 */
158 158  
159   -static void do_ext_call_interrupt(__u16 code)
  159 +static void do_ext_call_interrupt(unsigned int ext_int_code,
  160 + unsigned int param32, unsigned long param64)
160 161 {
161 162 unsigned long bits;
162 163  
arch/s390/kernel/time.c
... ... @@ -155,7 +155,9 @@
155 155 __ctl_set_bit(0, 4);
156 156 }
157 157  
158   -static void clock_comparator_interrupt(__u16 code)
  158 +static void clock_comparator_interrupt(unsigned int ext_int_code,
  159 + unsigned int param32,
  160 + unsigned long param64)
159 161 {
160 162 if (S390_lowcore.clock_comparator == -1ULL)
161 163 set_clock_comparator(S390_lowcore.clock_comparator);
162 164  
... ... @@ -164,14 +166,13 @@
164 166 static void etr_timing_alert(struct etr_irq_parm *);
165 167 static void stp_timing_alert(struct stp_irq_parm *);
166 168  
167   -static void timing_alert_interrupt(__u16 code)
  169 +static void timing_alert_interrupt(unsigned int ext_int_code,
  170 + unsigned int param32, unsigned long param64)
168 171 {
169   - if (S390_lowcore.ext_params & 0x00c40000)
170   - etr_timing_alert((struct etr_irq_parm *)
171   - &S390_lowcore.ext_params);
172   - if (S390_lowcore.ext_params & 0x00038000)
173   - stp_timing_alert((struct stp_irq_parm *)
174   - &S390_lowcore.ext_params);
  172 + if (param32 & 0x00c40000)
  173 + etr_timing_alert((struct etr_irq_parm *) &param32);
  174 + if (param32 & 0x00038000)
  175 + stp_timing_alert((struct stp_irq_parm *) &param32);
175 176 }
176 177  
177 178 static void etr_reset(void);
arch/s390/kernel/vtime.c
... ... @@ -314,7 +314,8 @@
314 314 /*
315 315 * Handler for the virtual CPU timer.
316 316 */
317   -static void do_cpu_timer_interrupt(__u16 error_code)
  317 +static void do_cpu_timer_interrupt(unsigned int ext_int_code,
  318 + unsigned int param32, unsigned long param64)
318 319 {
319 320 struct vtimer_queue *vq;
320 321 struct vtimer_list *event, *tmp;
arch/s390/mm/fault.c
... ... @@ -542,7 +542,8 @@
542 542 : : "a" (&refbk), "m" (refbk) : "cc");
543 543 }
544 544  
545   -static void pfault_interrupt(__u16 int_code)
  545 +static void pfault_interrupt(unsigned int ext_int_code,
  546 + unsigned int param32, unsigned long param64)
546 547 {
547 548 struct task_struct *tsk;
548 549 __u16 subcode;
549 550  
... ... @@ -553,14 +554,18 @@
553 554 * in the 'cpu address' field associated with the
554 555 * external interrupt.
555 556 */
556   - subcode = S390_lowcore.cpu_addr;
  557 + subcode = ext_int_code >> 16;
557 558 if ((subcode & 0xff00) != __SUBCODE_MASK)
558 559 return;
559 560  
560 561 /*
561 562 * Get the token (= address of the task structure of the affected task).
562 563 */
563   - tsk = *(struct task_struct **) __LC_PFAULT_INTPARM;
  564 +#ifdef CONFIG_64BIT
  565 + tsk = *(struct task_struct **) param64;
  566 +#else
  567 + tsk = *(struct task_struct **) param32;
  568 +#endif
564 569  
565 570 if (subcode & 0x0080) {
566 571 /* signal bit is set -> a page has been swapped in by VM */
drivers/s390/block/dasd_diag.c
... ... @@ -228,25 +228,22 @@
228 228 }
229 229  
230 230 /* Handle external interruption. */
231   -static void
232   -dasd_ext_handler(__u16 code)
  231 +static void dasd_ext_handler(unsigned int ext_int_code,
  232 + unsigned int param32, unsigned long param64)
233 233 {
234 234 struct dasd_ccw_req *cqr, *next;
235 235 struct dasd_device *device;
236 236 unsigned long long expires;
237 237 unsigned long flags;
238   - u8 int_code, status;
239 238 addr_t ip;
240 239 int rc;
241 240  
242   - int_code = *((u8 *) DASD_DIAG_LC_INT_CODE);
243   - status = *((u8 *) DASD_DIAG_LC_INT_STATUS);
244   - switch (int_code) {
  241 + switch (ext_int_code >> 24) {
245 242 case DASD_DIAG_CODE_31BIT:
246   - ip = (addr_t) *((u32 *) DASD_DIAG_LC_INT_PARM_31BIT);
  243 + ip = (addr_t) param32;
247 244 break;
248 245 case DASD_DIAG_CODE_64BIT:
249   - ip = (addr_t) *((u64 *) DASD_DIAG_LC_INT_PARM_64BIT);
  246 + ip = (addr_t) param64;
250 247 break;
251 248 default:
252 249 return;
... ... @@ -281,7 +278,7 @@
281 278 cqr->stopclk = get_clock();
282 279  
283 280 expires = 0;
284   - if (status == 0) {
  281 + if ((ext_int_code & 0xff0000) == 0) {
285 282 cqr->status = DASD_CQR_SUCCESS;
286 283 /* Start first request on queue if possible -> fast_io. */
287 284 if (!list_empty(&device->ccw_queue)) {
... ... @@ -296,8 +293,8 @@
296 293 } else {
297 294 cqr->status = DASD_CQR_QUEUED;
298 295 DBF_DEV_EVENT(DBF_DEBUG, device, "interrupt status for "
299   - "request %p was %d (%d retries left)", cqr, status,
300   - cqr->retries);
  296 + "request %p was %d (%d retries left)", cqr,
  297 + (ext_int_code >> 16) & 0xff, cqr->retries);
301 298 dasd_diag_erp(device);
302 299 }
303 300  
drivers/s390/block/dasd_diag.h
... ... @@ -18,10 +18,6 @@
18 18 #define DEV_CLASS_FBA 0x01
19 19 #define DEV_CLASS_ECKD 0x04
20 20  
21   -#define DASD_DIAG_LC_INT_CODE 132
22   -#define DASD_DIAG_LC_INT_STATUS 133
23   -#define DASD_DIAG_LC_INT_PARM_31BIT 128
24   -#define DASD_DIAG_LC_INT_PARM_64BIT 4536
25 21 #define DASD_DIAG_CODE_31BIT 0x03
26 22 #define DASD_DIAG_CODE_64BIT 0x07
27 23  
drivers/s390/char/sclp.c
... ... @@ -395,16 +395,16 @@
395 395 /* Handler for external interruption. Perform request post-processing.
396 396 * Prepare read event data request if necessary. Start processing of next
397 397 * request on queue. */
398   -static void
399   -sclp_interrupt_handler(__u16 code)
  398 +static void sclp_interrupt_handler(unsigned int ext_int_code,
  399 + unsigned int param32, unsigned long param64)
400 400 {
401 401 struct sclp_req *req;
402 402 u32 finished_sccb;
403 403 u32 evbuf_pending;
404 404  
405 405 spin_lock(&sclp_lock);
406   - finished_sccb = S390_lowcore.ext_params & 0xfffffff8;
407   - evbuf_pending = S390_lowcore.ext_params & 0x3;
  406 + finished_sccb = param32 & 0xfffffff8;
  407 + evbuf_pending = param32 & 0x3;
408 408 if (finished_sccb) {
409 409 del_timer(&sclp_request_timer);
410 410 sclp_running_state = sclp_running_state_reset_pending;
411 411  
... ... @@ -819,12 +819,12 @@
819 819  
820 820 /* Handler for external interruption used during initialization. Modify
821 821 * request state to done. */
822   -static void
823   -sclp_check_handler(__u16 code)
  822 +static void sclp_check_handler(unsigned int ext_int_code,
  823 + unsigned int param32, unsigned long param64)
824 824 {
825 825 u32 finished_sccb;
826 826  
827   - finished_sccb = S390_lowcore.ext_params & 0xfffffff8;
  827 + finished_sccb = param32 & 0xfffffff8;
828 828 /* Is this the interrupt we are waiting for? */
829 829 if (finished_sccb == 0)
830 830 return;
drivers/s390/kvm/kvm_virtio.c
... ... @@ -372,21 +372,22 @@
372 372 /*
373 373 * we emulate the request_irq behaviour on top of s390 extints
374 374 */
375   -static void kvm_extint_handler(u16 code)
  375 +static void kvm_extint_handler(unsigned int ext_int_code,
  376 + unsigned int param32, unsigned long param64)
376 377 {
377 378 struct virtqueue *vq;
378 379 u16 subcode;
379 380 u32 param;
380 381  
381   - subcode = S390_lowcore.cpu_addr;
  382 + subcode = ext_int_code >> 16;
382 383 if ((subcode & 0xff00) != VIRTIO_SUBCODE_64)
383 384 return;
384 385  
385 386 /* The LSB might be overloaded, we have to mask it */
386   - vq = (struct virtqueue *)(S390_lowcore.ext_params2 & ~1UL);
  387 + vq = (struct virtqueue *)(param64 & ~1UL);
387 388  
388 389 /* We use ext_params to decide what this interrupt means */
389   - param = S390_lowcore.ext_params & VIRTIO_PARAM_MASK;
  390 + param = param32 & VIRTIO_PARAM_MASK;
390 391  
391 392 switch (param) {
392 393 case VIRTIO_PARAM_CONFIG_CHANGED:
... ... @@ -1798,7 +1798,8 @@
1798 1798 * Handles external interrupts coming in from CP.
1799 1799 * Places the interrupt buffer on a queue and schedules iucv_tasklet_fn().
1800 1800 */
1801   -static void iucv_external_interrupt(u16 code)
  1801 +static void iucv_external_interrupt(unsigned int ext_int_code,
  1802 + unsigned int param32, unsigned long param64)
1802 1803 {
1803 1804 struct iucv_irq_data *p;
1804 1805 struct iucv_irq_list *work;