Commit f6649a7e5a9ee99e9623878f4a5579cc2f6cdd51
Committed by
Martin Schwidefsky
1 parent
1e54622e04
Exists in
master
and in
39 other branches
[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
- arch/s390/kernel/asm-offsets.c
- arch/s390/kernel/entry.S
- arch/s390/kernel/entry.h
- arch/s390/kernel/entry64.S
- arch/s390/kernel/s390_ext.c
- arch/s390/kernel/smp.c
- arch/s390/kernel/time.c
- arch/s390/kernel/vtime.c
- arch/s390/mm/fault.c
- drivers/s390/block/dasd_diag.c
- drivers/s390/block/dasd_diag.h
- drivers/s390/char/sclp.c
- drivers/s390/kvm/kvm_virtio.c
- net/iucv/iucv.c
arch/s390/include/asm/s390_ext.h
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
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 *) ¶m32); | |
174 | + if (param32 & 0x00038000) | |
175 | + stp_timing_alert((struct stp_irq_parm *) ¶m32); | |
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: |
net/iucv/iucv.c
... | ... | @@ -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; |