Skip to content

Commit

Permalink
[S390] cleanup lowcore access from external interrupts
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Martin Schwidefsky authored and Martin Schwidefsky committed Oct 25, 2010
1 parent 1e54622 commit f6649a7
Show file tree
Hide file tree
Showing 15 changed files with 57 additions and 49 deletions.
2 changes: 1 addition & 1 deletion arch/s390/include/asm/s390_ext.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 0 additions & 2 deletions arch/s390/kernel/asm-offsets.c
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down
3 changes: 2 additions & 1 deletion arch/s390/kernel/entry.S
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion arch/s390/kernel/entry.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
5 changes: 4 additions & 1 deletion arch/s390/kernel/entry64.S
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
9 changes: 6 additions & 3 deletions arch/s390/kernel/s390_ext.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand Down
3 changes: 2 additions & 1 deletion arch/s390/kernel/smp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
17 changes: 9 additions & 8 deletions arch/s390/kernel/time.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand Down
3 changes: 2 additions & 1 deletion arch/s390/kernel/vtime.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
11 changes: 8 additions & 3 deletions arch/s390/mm/fault.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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 */
Expand Down
19 changes: 8 additions & 11 deletions drivers/s390/block/dasd_diag.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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)) {
Expand All @@ -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);
}

Expand Down
4 changes: 0 additions & 4 deletions drivers/s390/block/dasd_diag.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
14 changes: 7 additions & 7 deletions drivers/s390/char/sclp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
9 changes: 5 additions & 4 deletions drivers/s390/kvm/kvm_virtio.c
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
3 changes: 2 additions & 1 deletion net/iucv/iucv.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit f6649a7

Please sign in to comment.