s390/nmi: remove casts

Remove all the casts to and from the machine check interruption code.
This patch changes struct mci to a union, which contains an anonymous
structure with the already known bits and in addition an unsigned
long field, which contains the raw machine check interruption code.

This allows to simply assign and decoce the interruption code value
without the need for all those casts we had all the time.

Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
This commit is contained in:
Heiko Carstens 2015-10-12 13:00:39 +02:00 committed by Martin Schwidefsky
parent 3d68286a43
commit dc6e15556a
3 changed files with 75 additions and 72 deletions

View File

@ -21,49 +21,52 @@
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
struct mci { union mci {
__u32 sd : 1; /* 00 system damage */ unsigned long val;
__u32 pd : 1; /* 01 instruction-processing damage */ struct {
__u32 sr : 1; /* 02 system recovery */ u64 sd : 1; /* 00 system damage */
__u32 : 1; /* 03 */ u64 pd : 1; /* 01 instruction-processing damage */
__u32 cd : 1; /* 04 timing-facility damage */ u64 sr : 1; /* 02 system recovery */
__u32 ed : 1; /* 05 external damage */ u64 : 1; /* 03 */
__u32 : 1; /* 06 */ u64 cd : 1; /* 04 timing-facility damage */
__u32 dg : 1; /* 07 degradation */ u64 ed : 1; /* 05 external damage */
__u32 w : 1; /* 08 warning pending */ u64 : 1; /* 06 */
__u32 cp : 1; /* 09 channel-report pending */ u64 dg : 1; /* 07 degradation */
__u32 sp : 1; /* 10 service-processor damage */ u64 w : 1; /* 08 warning pending */
__u32 ck : 1; /* 11 channel-subsystem damage */ u64 cp : 1; /* 09 channel-report pending */
__u32 : 2; /* 12-13 */ u64 sp : 1; /* 10 service-processor damage */
__u32 b : 1; /* 14 backed up */ u64 ck : 1; /* 11 channel-subsystem damage */
__u32 : 1; /* 15 */ u64 : 2; /* 12-13 */
__u32 se : 1; /* 16 storage error uncorrected */ u64 b : 1; /* 14 backed up */
__u32 sc : 1; /* 17 storage error corrected */ u64 : 1; /* 15 */
__u32 ke : 1; /* 18 storage-key error uncorrected */ u64 se : 1; /* 16 storage error uncorrected */
__u32 ds : 1; /* 19 storage degradation */ u64 sc : 1; /* 17 storage error corrected */
__u32 wp : 1; /* 20 psw mwp validity */ u64 ke : 1; /* 18 storage-key error uncorrected */
__u32 ms : 1; /* 21 psw mask and key validity */ u64 ds : 1; /* 19 storage degradation */
__u32 pm : 1; /* 22 psw program mask and cc validity */ u64 wp : 1; /* 20 psw mwp validity */
__u32 ia : 1; /* 23 psw instruction address validity */ u64 ms : 1; /* 21 psw mask and key validity */
__u32 fa : 1; /* 24 failing storage address validity */ u64 pm : 1; /* 22 psw program mask and cc validity */
__u32 vr : 1; /* 25 vector register validity */ u64 ia : 1; /* 23 psw instruction address validity */
__u32 ec : 1; /* 26 external damage code validity */ u64 fa : 1; /* 24 failing storage address validity */
__u32 fp : 1; /* 27 floating point register validity */ u64 vr : 1; /* 25 vector register validity */
__u32 gr : 1; /* 28 general register validity */ u64 ec : 1; /* 26 external damage code validity */
__u32 cr : 1; /* 29 control register validity */ u64 fp : 1; /* 27 floating point register validity */
__u32 : 1; /* 30 */ u64 gr : 1; /* 28 general register validity */
__u32 st : 1; /* 31 storage logical validity */ u64 cr : 1; /* 29 control register validity */
__u32 ie : 1; /* 32 indirect storage error */ u64 : 1; /* 30 */
__u32 ar : 1; /* 33 access register validity */ u64 st : 1; /* 31 storage logical validity */
__u32 da : 1; /* 34 delayed access exception */ u64 ie : 1; /* 32 indirect storage error */
__u32 : 7; /* 35-41 */ u64 ar : 1; /* 33 access register validity */
__u32 pr : 1; /* 42 tod programmable register validity */ u64 da : 1; /* 34 delayed access exception */
__u32 fc : 1; /* 43 fp control register validity */ u64 : 7; /* 35-41 */
__u32 ap : 1; /* 44 ancillary report */ u64 pr : 1; /* 42 tod programmable register validity */
__u32 : 1; /* 45 */ u64 fc : 1; /* 43 fp control register validity */
__u32 ct : 1; /* 46 cpu timer validity */ u64 ap : 1; /* 44 ancillary report */
__u32 cc : 1; /* 47 clock comparator validity */ u64 : 1; /* 45 */
__u32 : 16; /* 47-63 */ u64 ct : 1; /* 46 cpu timer validity */
u64 cc : 1; /* 47 clock comparator validity */
u64 : 16; /* 47-63 */
};
}; };
struct pt_regs; struct pt_regs;

View File

@ -29,7 +29,7 @@ struct mcck_struct {
int warning; int warning;
unsigned int etr_queue : 1; unsigned int etr_queue : 1;
unsigned int stp_queue : 1; unsigned int stp_queue : 1;
unsigned long long mcck_code; unsigned long mcck_code;
}; };
static DEFINE_PER_CPU(struct mcck_struct, cpu_mcck); static DEFINE_PER_CPU(struct mcck_struct, cpu_mcck);
@ -89,7 +89,7 @@ void s390_handle_mcck(void)
if (mcck.kill_task) { if (mcck.kill_task) {
local_irq_enable(); local_irq_enable();
printk(KERN_EMERG "mcck: Terminating task because of machine " printk(KERN_EMERG "mcck: Terminating task because of machine "
"malfunction (code 0x%016llx).\n", mcck.mcck_code); "malfunction (code 0x%016lx).\n", mcck.mcck_code);
printk(KERN_EMERG "mcck: task: %s, pid: %d.\n", printk(KERN_EMERG "mcck: task: %s, pid: %d.\n",
current->comm, current->pid); current->comm, current->pid);
do_exit(SIGSEGV); do_exit(SIGSEGV);
@ -101,7 +101,7 @@ EXPORT_SYMBOL_GPL(s390_handle_mcck);
* returns 0 if all registers could be validated * returns 0 if all registers could be validated
* returns 1 otherwise * returns 1 otherwise
*/ */
static int notrace s390_revalidate_registers(struct mci *mci) static int notrace s390_revalidate_registers(union mci mci)
{ {
int kill_task; int kill_task;
u64 zero; u64 zero;
@ -110,14 +110,14 @@ static int notrace s390_revalidate_registers(struct mci *mci)
kill_task = 0; kill_task = 0;
zero = 0; zero = 0;
if (!mci->gr) { if (!mci.gr) {
/* /*
* General purpose registers couldn't be restored and have * General purpose registers couldn't be restored and have
* unknown contents. Process needs to be terminated. * unknown contents. Process needs to be terminated.
*/ */
kill_task = 1; kill_task = 1;
} }
if (!mci->fp) { if (!mci.fp) {
/* /*
* Floating point registers can't be restored and * Floating point registers can't be restored and
* therefore the process needs to be terminated. * therefore the process needs to be terminated.
@ -126,7 +126,7 @@ static int notrace s390_revalidate_registers(struct mci *mci)
} }
fpt_save_area = &S390_lowcore.floating_pt_save_area; fpt_save_area = &S390_lowcore.floating_pt_save_area;
fpt_creg_save_area = &S390_lowcore.fpt_creg_save_area; fpt_creg_save_area = &S390_lowcore.fpt_creg_save_area;
if (!mci->fc) { if (!mci.fc) {
/* /*
* Floating point control register can't be restored. * Floating point control register can't be restored.
* Task will be terminated. * Task will be terminated.
@ -160,7 +160,7 @@ static int notrace s390_revalidate_registers(struct mci *mci)
/* Revalidate vector registers */ /* Revalidate vector registers */
union ctlreg0 cr0; union ctlreg0 cr0;
if (!mci->vr) { if (!mci.vr) {
/* /*
* Vector registers can't be restored and therefore * Vector registers can't be restored and therefore
* the process needs to be terminated. * the process needs to be terminated.
@ -182,7 +182,7 @@ static int notrace s390_revalidate_registers(struct mci *mci)
asm volatile( asm volatile(
" lam 0,15,0(%0)" " lam 0,15,0(%0)"
: : "a" (&S390_lowcore.access_regs_save_area)); : : "a" (&S390_lowcore.access_regs_save_area));
if (!mci->ar) { if (!mci.ar) {
/* /*
* Access registers have unknown contents. * Access registers have unknown contents.
* Terminating task. * Terminating task.
@ -190,7 +190,7 @@ static int notrace s390_revalidate_registers(struct mci *mci)
kill_task = 1; kill_task = 1;
} }
/* Revalidate control registers */ /* Revalidate control registers */
if (!mci->cr) { if (!mci.cr) {
/* /*
* Control registers have unknown contents. * Control registers have unknown contents.
* Can't recover and therefore stopping machine. * Can't recover and therefore stopping machine.
@ -209,7 +209,7 @@ static int notrace s390_revalidate_registers(struct mci *mci)
* See if we can revalidate the TOD programmable register with its * See if we can revalidate the TOD programmable register with its
* old contents (should be zero) otherwise set it to zero. * old contents (should be zero) otherwise set it to zero.
*/ */
if (!mci->pr) if (!mci.pr)
asm volatile( asm volatile(
" sr 0,0\n" " sr 0,0\n"
" sckpf" " sckpf"
@ -223,14 +223,14 @@ static int notrace s390_revalidate_registers(struct mci *mci)
/* Revalidate clock comparator register */ /* Revalidate clock comparator register */
set_clock_comparator(S390_lowcore.clock_comparator); set_clock_comparator(S390_lowcore.clock_comparator);
/* Check if old PSW is valid */ /* Check if old PSW is valid */
if (!mci->wp) if (!mci.wp)
/* /*
* Can't tell if we come from user or kernel mode * Can't tell if we come from user or kernel mode
* -> stopping machine. * -> stopping machine.
*/ */
s390_handle_damage(); s390_handle_damage();
if (!mci->ms || !mci->pm || !mci->ia) if (!mci.ms || !mci.pm || !mci.ia)
kill_task = 1; kill_task = 1;
return kill_task; return kill_task;
@ -254,21 +254,21 @@ void notrace s390_do_machine_check(struct pt_regs *regs)
static unsigned long long last_ipd; static unsigned long long last_ipd;
struct mcck_struct *mcck; struct mcck_struct *mcck;
unsigned long long tmp; unsigned long long tmp;
struct mci *mci; union mci mci;
int umode; int umode;
nmi_enter(); nmi_enter();
inc_irq_stat(NMI_NMI); inc_irq_stat(NMI_NMI);
mci = (struct mci *) &S390_lowcore.mcck_interruption_code; mci.val = S390_lowcore.mcck_interruption_code;
mcck = this_cpu_ptr(&cpu_mcck); mcck = this_cpu_ptr(&cpu_mcck);
umode = user_mode(regs); umode = user_mode(regs);
if (mci->sd) { if (mci.sd) {
/* System damage -> stopping machine */ /* System damage -> stopping machine */
s390_handle_damage(); s390_handle_damage();
} }
if (mci->pd) { if (mci.pd) {
if (mci->b) { if (mci.b) {
/* Processing backup -> verify if we can survive this */ /* Processing backup -> verify if we can survive this */
u64 z_mcic, o_mcic, t_mcic; u64 z_mcic, o_mcic, t_mcic;
z_mcic = (1ULL<<63 | 1ULL<<59 | 1ULL<<29); z_mcic = (1ULL<<63 | 1ULL<<59 | 1ULL<<29);
@ -276,7 +276,7 @@ void notrace s390_do_machine_check(struct pt_regs *regs)
1ULL<<36 | 1ULL<<35 | 1ULL<<34 | 1ULL<<32 | 1ULL<<36 | 1ULL<<35 | 1ULL<<34 | 1ULL<<32 |
1ULL<<30 | 1ULL<<21 | 1ULL<<20 | 1ULL<<17 | 1ULL<<30 | 1ULL<<21 | 1ULL<<20 | 1ULL<<17 |
1ULL<<16); 1ULL<<16);
t_mcic = *(u64 *)mci; t_mcic = mci.val;
if (((t_mcic & z_mcic) != 0) || if (((t_mcic & z_mcic) != 0) ||
((t_mcic & o_mcic) != o_mcic)) { ((t_mcic & o_mcic) != o_mcic)) {
@ -309,7 +309,7 @@ void notrace s390_do_machine_check(struct pt_regs *regs)
* user mode -> mark task for termination. * user mode -> mark task for termination.
*/ */
mcck->kill_task = 1; mcck->kill_task = 1;
mcck->mcck_code = *(unsigned long long *) mci; mcck->mcck_code = mci.val;
set_cpu_flag(CIF_MCCK_PENDING); set_cpu_flag(CIF_MCCK_PENDING);
} else { } else {
/* /*
@ -319,11 +319,11 @@ void notrace s390_do_machine_check(struct pt_regs *regs)
s390_handle_damage(); s390_handle_damage();
} }
} }
if (mci->cd) { if (mci.cd) {
/* Timing facility damage */ /* Timing facility damage */
s390_handle_damage(); s390_handle_damage();
} }
if (mci->ed && mci->ec) { if (mci.ed && mci.ec) {
/* External damage */ /* External damage */
if (S390_lowcore.external_damage_code & (1U << ED_ETR_SYNC)) if (S390_lowcore.external_damage_code & (1U << ED_ETR_SYNC))
mcck->etr_queue |= etr_sync_check(); mcck->etr_queue |= etr_sync_check();
@ -336,21 +336,21 @@ void notrace s390_do_machine_check(struct pt_regs *regs)
if (mcck->etr_queue || mcck->stp_queue) if (mcck->etr_queue || mcck->stp_queue)
set_cpu_flag(CIF_MCCK_PENDING); set_cpu_flag(CIF_MCCK_PENDING);
} }
if (mci->se) if (mci.se)
/* Storage error uncorrected */ /* Storage error uncorrected */
s390_handle_damage(); s390_handle_damage();
if (mci->ke) if (mci.ke)
/* Storage key-error uncorrected */ /* Storage key-error uncorrected */
s390_handle_damage(); s390_handle_damage();
if (mci->ds && mci->fa) if (mci.ds && mci.fa)
/* Storage degradation */ /* Storage degradation */
s390_handle_damage(); s390_handle_damage();
if (mci->cp) { if (mci.cp) {
/* Channel report word pending */ /* Channel report word pending */
mcck->channel_report = 1; mcck->channel_report = 1;
set_cpu_flag(CIF_MCCK_PENDING); set_cpu_flag(CIF_MCCK_PENDING);
} }
if (mci->w) { if (mci.w) {
/* Warning pending */ /* Warning pending */
mcck->warning = 1; mcck->warning = 1;
set_cpu_flag(CIF_MCCK_PENDING); set_cpu_flag(CIF_MCCK_PENDING);

View File

@ -826,11 +826,11 @@ static atomic_t chpid_reset_count;
static void s390_reset_chpids_mcck_handler(void) static void s390_reset_chpids_mcck_handler(void)
{ {
struct crw crw; struct crw crw;
struct mci *mci; union mci mci;
/* Check for pending channel report word. */ /* Check for pending channel report word. */
mci = (struct mci *)&S390_lowcore.mcck_interruption_code; mci.val = S390_lowcore.mcck_interruption_code;
if (!mci->cp) if (!mci.cp)
return; return;
/* Process channel report words. */ /* Process channel report words. */
while (stcrw(&crw) == 0) { while (stcrw(&crw) == 0) {