From: Martin Schwidefsky Date: Mon, 25 Oct 2010 14:10:38 +0000 (+0200) Subject: [S390] cleanup lowcore access from external interrupts X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=f6649a7e5a9ee99e9623878f4a5579cc2f6cdd51;p=GitHub%2FLineageOS%2Fandroid_kernel_samsung_universal7580.git [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 --- diff --git a/arch/s390/include/asm/s390_ext.h b/arch/s390/include/asm/s390_ext.h index 2afc060266a..1a9307e7084 100644 --- a/arch/s390/include/asm/s390_ext.h +++ b/arch/s390/include/asm/s390_ext.h @@ -12,7 +12,7 @@ #include -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 76328deb31f..f3c1b823c9a 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 adf25246f72..736d7010629 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 714ff2e57c6..95c1dfc4ef3 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 2d205e4e7bb..e4038ea4dc5 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 9ce641b5291..bd1db508e8a 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 8127ebd59c4..354589d096b 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 2896cac9c14..f754a6dc4f9 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 *) ¶m32); + if (param32 & 0x00038000) + stp_timing_alert((struct stp_irq_parm *) ¶m32); } static void etr_reset(void); diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c index 3479f1b0d4e..56c8687b29b 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 b6570069b12..b4aad0c1f56 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 */ diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c index 2b3bc3ec054..266b34b5540 100644 --- a/drivers/s390/block/dasd_diag.c +++ b/drivers/s390/block/dasd_diag.c @@ -228,25 +228,22 @@ dasd_diag_term_IO(struct dasd_ccw_req * cqr) } /* Handle external interruption. */ -static void -dasd_ext_handler(__u16 code) +static void dasd_ext_handler(unsigned int ext_int_code, + unsigned int param32, unsigned long param64) { struct dasd_ccw_req *cqr, *next; struct dasd_device *device; unsigned long long expires; unsigned long flags; - u8 int_code, status; addr_t ip; int rc; - int_code = *((u8 *) DASD_DIAG_LC_INT_CODE); - status = *((u8 *) DASD_DIAG_LC_INT_STATUS); - switch (int_code) { + switch (ext_int_code >> 24) { case DASD_DIAG_CODE_31BIT: - ip = (addr_t) *((u32 *) DASD_DIAG_LC_INT_PARM_31BIT); + ip = (addr_t) param32; break; case DASD_DIAG_CODE_64BIT: - ip = (addr_t) *((u64 *) DASD_DIAG_LC_INT_PARM_64BIT); + ip = (addr_t) param64; break; default: return; @@ -281,7 +278,7 @@ dasd_ext_handler(__u16 code) cqr->stopclk = get_clock(); expires = 0; - if (status == 0) { + if ((ext_int_code & 0xff0000) == 0) { cqr->status = DASD_CQR_SUCCESS; /* Start first request on queue if possible -> fast_io. */ if (!list_empty(&device->ccw_queue)) { @@ -296,8 +293,8 @@ dasd_ext_handler(__u16 code) } else { cqr->status = DASD_CQR_QUEUED; DBF_DEV_EVENT(DBF_DEBUG, device, "interrupt status for " - "request %p was %d (%d retries left)", cqr, status, - cqr->retries); + "request %p was %d (%d retries left)", cqr, + (ext_int_code >> 16) & 0xff, cqr->retries); dasd_diag_erp(device); } diff --git a/drivers/s390/block/dasd_diag.h b/drivers/s390/block/dasd_diag.h index b8c78267ff3..4f71fbe60c8 100644 --- a/drivers/s390/block/dasd_diag.h +++ b/drivers/s390/block/dasd_diag.h @@ -18,10 +18,6 @@ #define DEV_CLASS_FBA 0x01 #define DEV_CLASS_ECKD 0x04 -#define DASD_DIAG_LC_INT_CODE 132 -#define DASD_DIAG_LC_INT_STATUS 133 -#define DASD_DIAG_LC_INT_PARM_31BIT 128 -#define DASD_DIAG_LC_INT_PARM_64BIT 4536 #define DASD_DIAG_CODE_31BIT 0x03 #define DASD_DIAG_CODE_64BIT 0x07 diff --git a/drivers/s390/char/sclp.c b/drivers/s390/char/sclp.c index 5707a80b96b..35cc4686b99 100644 --- a/drivers/s390/char/sclp.c +++ b/drivers/s390/char/sclp.c @@ -395,16 +395,16 @@ __sclp_find_req(u32 sccb) /* Handler for external interruption. Perform request post-processing. * Prepare read event data request if necessary. Start processing of next * request on queue. */ -static void -sclp_interrupt_handler(__u16 code) +static void sclp_interrupt_handler(unsigned int ext_int_code, + unsigned int param32, unsigned long param64) { struct sclp_req *req; u32 finished_sccb; u32 evbuf_pending; spin_lock(&sclp_lock); - finished_sccb = S390_lowcore.ext_params & 0xfffffff8; - evbuf_pending = S390_lowcore.ext_params & 0x3; + finished_sccb = param32 & 0xfffffff8; + evbuf_pending = param32 & 0x3; if (finished_sccb) { del_timer(&sclp_request_timer); sclp_running_state = sclp_running_state_reset_pending; @@ -819,12 +819,12 @@ EXPORT_SYMBOL(sclp_reactivate); /* Handler for external interruption used during initialization. Modify * request state to done. */ -static void -sclp_check_handler(__u16 code) +static void sclp_check_handler(unsigned int ext_int_code, + unsigned int param32, unsigned long param64) { u32 finished_sccb; - finished_sccb = S390_lowcore.ext_params & 0xfffffff8; + finished_sccb = param32 & 0xfffffff8; /* Is this the interrupt we are waiting for? */ if (finished_sccb == 0) return; diff --git a/drivers/s390/kvm/kvm_virtio.c b/drivers/s390/kvm/kvm_virtio.c index 5a46b8c5d68..375aeeaf9ea 100644 --- a/drivers/s390/kvm/kvm_virtio.c +++ b/drivers/s390/kvm/kvm_virtio.c @@ -372,21 +372,22 @@ static void hotplug_devices(struct work_struct *dummy) /* * we emulate the request_irq behaviour on top of s390 extints */ -static void kvm_extint_handler(u16 code) +static void kvm_extint_handler(unsigned int ext_int_code, + unsigned int param32, unsigned long param64) { struct virtqueue *vq; u16 subcode; u32 param; - subcode = S390_lowcore.cpu_addr; + subcode = ext_int_code >> 16; if ((subcode & 0xff00) != VIRTIO_SUBCODE_64) return; /* The LSB might be overloaded, we have to mask it */ - vq = (struct virtqueue *)(S390_lowcore.ext_params2 & ~1UL); + vq = (struct virtqueue *)(param64 & ~1UL); /* We use ext_params to decide what this interrupt means */ - param = S390_lowcore.ext_params & VIRTIO_PARAM_MASK; + param = param32 & VIRTIO_PARAM_MASK; switch (param) { case VIRTIO_PARAM_CONFIG_CHANGED: diff --git a/net/iucv/iucv.c b/net/iucv/iucv.c index 499c045d691..f7db676de77 100644 --- a/net/iucv/iucv.c +++ b/net/iucv/iucv.c @@ -1798,7 +1798,8 @@ static void iucv_work_fn(struct work_struct *work) * Handles external interrupts coming in from CP. * Places the interrupt buffer on a queue and schedules iucv_tasklet_fn(). */ -static void iucv_external_interrupt(u16 code) +static void iucv_external_interrupt(unsigned int ext_int_code, + unsigned int param32, unsigned long param64) { struct iucv_irq_data *p; struct iucv_irq_list *work;