1
0
Fork 0

[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>
wifi-calibration
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> #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 { typedef struct ext_int_info_t {
struct ext_int_info_t *next; 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_GPREGS_SAVE_AREA, offsetof(struct _lowcore, gpregs_save_area));
DEFINE(__LC_CREGS_SAVE_AREA, offsetof(struct _lowcore, cregs_save_area)); DEFINE(__LC_CREGS_SAVE_AREA, offsetof(struct _lowcore, cregs_save_area));
#ifdef CONFIG_32BIT #ifdef CONFIG_32BIT
DEFINE(__LC_PFAULT_INTPARM, offsetof(struct _lowcore, ext_params));
DEFINE(SAVE_AREA_BASE, offsetof(struct _lowcore, extended_save_area_addr)); DEFINE(SAVE_AREA_BASE, offsetof(struct _lowcore, extended_save_area_addr));
#else /* CONFIG_32BIT */ #else /* CONFIG_32BIT */
DEFINE(__LC_PFAULT_INTPARM, offsetof(struct _lowcore, ext_params2));
DEFINE(__LC_EXT_PARAMS2, 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(SAVE_AREA_BASE, offsetof(struct _lowcore, floating_pt_save_area));
DEFINE(__LC_PASTE, offsetof(struct _lowcore, paste)); 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 l %r9,__LC_THREAD_INFO # load pointer to thread_info struct
TRACE_IRQS_OFF TRACE_IRQS_OFF
la %r2,SP_PTREGS(%r15) # address of register-save area 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) l %r1,BASED(.Ldo_extint)
basr %r14,%r1 basr %r14,%r1
b BASED(io_return) 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, int handle_signal32(unsigned long sig, struct k_sigaction *ka,
siginfo_t *info, sigset_t *oldset, struct pt_regs *regs); 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); int __cpuinit start_secondary(void *cpuvoid);
void __init startup_init(void); void __init startup_init(void);
void die(const char * str, struct pt_regs * regs, long err); void die(const char * str, struct pt_regs * regs, long err);

View File

@ -727,8 +727,11 @@ ext_int_handler:
ext_no_vtime: ext_no_vtime:
HANDLE_SIE_INTERCEPT HANDLE_SIE_INTERCEPT
TRACE_IRQS_OFF TRACE_IRQS_OFF
lghi %r1,4096
la %r2,SP_PTREGS(%r15) # address of register-save area 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 brasl %r14,do_extint
j io_return j io_return

View File

@ -113,12 +113,15 @@ int unregister_early_external_interrupt(__u16 code, ext_int_handler_t handler,
return 0; 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; ext_int_info_t *p;
int index; int index;
struct pt_regs *old_regs;
code = (unsigned short) ext_int_code;
old_regs = set_irq_regs(regs); old_regs = set_irq_regs(regs);
s390_idle_check(regs, S390_lowcore.int_clock, s390_idle_check(regs, S390_lowcore.int_clock,
S390_lowcore.async_enter_timer); 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); index = ext_hash(code);
for (p = ext_int_hash[index]; p; p = p->next) { for (p = ext_int_hash[index]; p; p = p->next) {
if (likely(p->code == code)) if (likely(p->code == code))
p->handler(code); p->handler(ext_int_code, param32, param64);
} }
irq_exit(); irq_exit();
set_irq_regs(old_regs); set_irq_regs(old_regs);

View File

@ -156,7 +156,8 @@ void smp_send_stop(void)
* cpus are handled. * 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; unsigned long bits;

View File

@ -155,7 +155,9 @@ void init_cpu_timer(void)
__ctl_set_bit(0, 4); __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) if (S390_lowcore.clock_comparator == -1ULL)
set_clock_comparator(S390_lowcore.clock_comparator); 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 etr_timing_alert(struct etr_irq_parm *);
static void stp_timing_alert(struct stp_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) if (param32 & 0x00c40000)
etr_timing_alert((struct etr_irq_parm *) etr_timing_alert((struct etr_irq_parm *) &param32);
&S390_lowcore.ext_params); if (param32 & 0x00038000)
if (S390_lowcore.ext_params & 0x00038000) stp_timing_alert((struct stp_irq_parm *) &param32);
stp_timing_alert((struct stp_irq_parm *)
&S390_lowcore.ext_params);
} }
static void etr_reset(void); 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. * 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_queue *vq;
struct vtimer_list *event, *tmp; struct vtimer_list *event, *tmp;

View File

@ -542,7 +542,8 @@ void pfault_fini(void)
: : "a" (&refbk), "m" (refbk) : "cc"); : : "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; struct task_struct *tsk;
__u16 subcode; __u16 subcode;
@ -553,14 +554,18 @@ static void pfault_interrupt(__u16 int_code)
* in the 'cpu address' field associated with the * in the 'cpu address' field associated with the
* external interrupt. * external interrupt.
*/ */
subcode = S390_lowcore.cpu_addr; subcode = ext_int_code >> 16;
if ((subcode & 0xff00) != __SUBCODE_MASK) if ((subcode & 0xff00) != __SUBCODE_MASK)
return; return;
/* /*
* Get the token (= address of the task structure of the affected task). * 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) { if (subcode & 0x0080) {
/* signal bit is set -> a page has been swapped in by VM */ /* 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. */ /* Handle external interruption. */
static void static void dasd_ext_handler(unsigned int ext_int_code,
dasd_ext_handler(__u16 code) unsigned int param32, unsigned long param64)
{ {
struct dasd_ccw_req *cqr, *next; struct dasd_ccw_req *cqr, *next;
struct dasd_device *device; struct dasd_device *device;
unsigned long long expires; unsigned long long expires;
unsigned long flags; unsigned long flags;
u8 int_code, status;
addr_t ip; addr_t ip;
int rc; int rc;
int_code = *((u8 *) DASD_DIAG_LC_INT_CODE); switch (ext_int_code >> 24) {
status = *((u8 *) DASD_DIAG_LC_INT_STATUS);
switch (int_code) {
case DASD_DIAG_CODE_31BIT: case DASD_DIAG_CODE_31BIT:
ip = (addr_t) *((u32 *) DASD_DIAG_LC_INT_PARM_31BIT); ip = (addr_t) param32;
break; break;
case DASD_DIAG_CODE_64BIT: case DASD_DIAG_CODE_64BIT:
ip = (addr_t) *((u64 *) DASD_DIAG_LC_INT_PARM_64BIT); ip = (addr_t) param64;
break; break;
default: default:
return; return;
@ -281,7 +278,7 @@ dasd_ext_handler(__u16 code)
cqr->stopclk = get_clock(); cqr->stopclk = get_clock();
expires = 0; expires = 0;
if (status == 0) { if ((ext_int_code & 0xff0000) == 0) {
cqr->status = DASD_CQR_SUCCESS; cqr->status = DASD_CQR_SUCCESS;
/* Start first request on queue if possible -> fast_io. */ /* Start first request on queue if possible -> fast_io. */
if (!list_empty(&device->ccw_queue)) { if (!list_empty(&device->ccw_queue)) {
@ -296,8 +293,8 @@ dasd_ext_handler(__u16 code)
} else { } else {
cqr->status = DASD_CQR_QUEUED; cqr->status = DASD_CQR_QUEUED;
DBF_DEV_EVENT(DBF_DEBUG, device, "interrupt status for " DBF_DEV_EVENT(DBF_DEBUG, device, "interrupt status for "
"request %p was %d (%d retries left)", cqr, status, "request %p was %d (%d retries left)", cqr,
cqr->retries); (ext_int_code >> 16) & 0xff, cqr->retries);
dasd_diag_erp(device); dasd_diag_erp(device);
} }

View File

@ -18,10 +18,6 @@
#define DEV_CLASS_FBA 0x01 #define DEV_CLASS_FBA 0x01
#define DEV_CLASS_ECKD 0x04 #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_31BIT 0x03
#define DASD_DIAG_CODE_64BIT 0x07 #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. /* Handler for external interruption. Perform request post-processing.
* Prepare read event data request if necessary. Start processing of next * Prepare read event data request if necessary. Start processing of next
* request on queue. */ * request on queue. */
static void static void sclp_interrupt_handler(unsigned int ext_int_code,
sclp_interrupt_handler(__u16 code) unsigned int param32, unsigned long param64)
{ {
struct sclp_req *req; struct sclp_req *req;
u32 finished_sccb; u32 finished_sccb;
u32 evbuf_pending; u32 evbuf_pending;
spin_lock(&sclp_lock); spin_lock(&sclp_lock);
finished_sccb = S390_lowcore.ext_params & 0xfffffff8; finished_sccb = param32 & 0xfffffff8;
evbuf_pending = S390_lowcore.ext_params & 0x3; evbuf_pending = param32 & 0x3;
if (finished_sccb) { if (finished_sccb) {
del_timer(&sclp_request_timer); del_timer(&sclp_request_timer);
sclp_running_state = sclp_running_state_reset_pending; sclp_running_state = sclp_running_state_reset_pending;
@ -819,12 +819,12 @@ EXPORT_SYMBOL(sclp_reactivate);
/* Handler for external interruption used during initialization. Modify /* Handler for external interruption used during initialization. Modify
* request state to done. */ * request state to done. */
static void static void sclp_check_handler(unsigned int ext_int_code,
sclp_check_handler(__u16 code) unsigned int param32, unsigned long param64)
{ {
u32 finished_sccb; u32 finished_sccb;
finished_sccb = S390_lowcore.ext_params & 0xfffffff8; finished_sccb = param32 & 0xfffffff8;
/* Is this the interrupt we are waiting for? */ /* Is this the interrupt we are waiting for? */
if (finished_sccb == 0) if (finished_sccb == 0)
return; 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 * 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; struct virtqueue *vq;
u16 subcode; u16 subcode;
u32 param; u32 param;
subcode = S390_lowcore.cpu_addr; subcode = ext_int_code >> 16;
if ((subcode & 0xff00) != VIRTIO_SUBCODE_64) if ((subcode & 0xff00) != VIRTIO_SUBCODE_64)
return; return;
/* The LSB might be overloaded, we have to mask it */ /* 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 */ /* 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) { switch (param) {
case VIRTIO_PARAM_CONFIG_CHANGED: 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. * Handles external interrupts coming in from CP.
* Places the interrupt buffer on a queue and schedules iucv_tasklet_fn(). * 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_data *p;
struct iucv_irq_list *work; struct iucv_irq_list *work;