[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>
This commit is contained in:
		
							parent
							
								
									1e54622e04
								
							
						
					
					
						commit
						f6649a7e5a
					
				| @ -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; | ||||
|  | ||||
| @ -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)); | ||||
|  | ||||
| @ -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) | ||||
|  | ||||
| @ -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); | ||||
|  | ||||
| @ -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 | ||||
| 
 | ||||
|  | ||||
| @ -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); | ||||
|  | ||||
| @ -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; | ||||
| 
 | ||||
|  | ||||
| @ -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); | ||||
|  | ||||
| @ -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; | ||||
|  | ||||
| @ -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 */ | ||||
|  | ||||
| @ -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); | ||||
| 	} | ||||
| 
 | ||||
|  | ||||
| @ -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 | ||||
| 
 | ||||
|  | ||||
| @ -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; | ||||
|  | ||||
| @ -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: | ||||
|  | ||||
| @ -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; | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user