[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:
Martin Schwidefsky 2010-10-25 16:10:38 +02:00 committed by Martin Schwidefsky
parent 1e54622e04
commit f6649a7e5a
15 changed files with 57 additions and 49 deletions

View file

@ -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;

View file

@ -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));

View file

@ -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)

View file

@ -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);

View file

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

View file

@ -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);

View file

@ -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;

View file

@ -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);

View file

@ -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;

View file

@ -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 */

View file

@ -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);
}

View file

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

View file

@ -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;

View file

@ -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:

View file

@ -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;