Skip to content

Commit

Permalink
[S390] Reset infrastructure for re-IPL.
Browse files Browse the repository at this point in the history
In case of re-IPL and diag308 doesn't work we have to reset all devices
manually and wait synchronously that each reset finished.
This patch adds the necessary infrastucture and the first exploiter of it.

Subsystems that need to add a function that needs to be called at re-IPL
may register/unregister this function via

struct reset_call {
	struct reset_call *next;
	void (*fn)(void);
};

void register_reset_call(struct reset_call *reset);
void unregister_reset_call(struct reset_call *reset);

When the registered function get called the context is:

- all cpus beside the current one are stopped
- all machine checks and interrupts are disabled
- prefixing is disabled
- a default machine check handler is available for use

The registered functions may not take any locks are sleep.

For the common I/O layer part of this patch:

Introduce a reset_call css_reset that does the following:
- clear all subchannels
- perform a rchp on all channel paths and wait for the resulting
  machine checks
This replaces the calls to clear_all_subchannels() and
cio_reset_channel_paths() for kexec and ccw reipl. reipl_ccw_dev() now
uses reipl_find_schid() to determine the subchannel id for a given
device id.
Also remove cio_reset_channel_paths() and friends since they are not
needed anymore.

Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
  • Loading branch information
Heiko Carstens authored and Martin Schwidefsky committed Dec 4, 2006
1 parent 2254f5a commit 15e9b58
Show file tree
Hide file tree
Showing 13 changed files with 246 additions and 108 deletions.
2 changes: 1 addition & 1 deletion arch/s390/kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

EXTRA_AFLAGS := -traditional

obj-y := bitmap.o traps.o time.o process.o \
obj-y := bitmap.o traps.o time.o process.o reset.o \
setup.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \
semaphore.o s390_ext.o debug.o profile.o irq.o ipl.o

Expand Down
54 changes: 54 additions & 0 deletions arch/s390/kernel/ipl.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include <asm/cpcmd.h>
#include <asm/cio.h>
#include <asm/ebcdic.h>
#include <asm/reset.h>

#define IPL_PARM_BLOCK_VERSION 0
#define LOADPARM_LEN 8
Expand Down Expand Up @@ -1024,3 +1025,56 @@ static int __init s390_ipl_init(void)
}

__initcall(s390_ipl_init);

static LIST_HEAD(rcall);
static DEFINE_MUTEX(rcall_mutex);

void register_reset_call(struct reset_call *reset)
{
mutex_lock(&rcall_mutex);
list_add(&reset->list, &rcall);
mutex_unlock(&rcall_mutex);
}
EXPORT_SYMBOL_GPL(register_reset_call);

void unregister_reset_call(struct reset_call *reset)
{
mutex_lock(&rcall_mutex);
list_del(&reset->list);
mutex_unlock(&rcall_mutex);
}
EXPORT_SYMBOL_GPL(unregister_reset_call);

static void do_reset_calls(void)
{
struct reset_call *reset;

list_for_each_entry(reset, &rcall, list)
reset->fn();
}

extern void reset_mcck_handler(void);

void s390_reset_system(void)
{
struct _lowcore *lc;

/* Disable all interrupts/machine checks */
__load_psw_mask(PSW_KERNEL_BITS & ~PSW_MASK_MCHECK);

/* Stack for interrupt/machine check handler */
lc = (struct _lowcore *)(unsigned long) store_prefix();
lc->panic_stack = S390_lowcore.panic_stack;

/* Disable prefixing */
set_prefix(0);

/* Disable lowcore protection */
__ctl_clear_bit(0,28);

/* Set new machine check handler */
S390_lowcore.mcck_new_psw.mask = PSW_KERNEL_BITS & ~PSW_MASK_MCHECK;
S390_lowcore.mcck_new_psw.addr =
PSW_ADDR_AMODE | (unsigned long) &reset_mcck_handler;
do_reset_calls();
}
9 changes: 3 additions & 6 deletions arch/s390/kernel/machine_kexec.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <asm/pgalloc.h>
#include <asm/system.h>
#include <asm/smp.h>
#include <asm/reset.h>

static void kexec_halt_all_cpus(void *);

Expand Down Expand Up @@ -62,12 +63,6 @@ machine_shutdown(void)
NORET_TYPE void
machine_kexec(struct kimage *image)
{
clear_all_subchannels();
cio_reset_channel_paths();

/* Disable lowcore protection */
ctl_clear_bit(0,28);

on_each_cpu(kexec_halt_all_cpus, image, 0, 0);
for (;;);
}
Expand Down Expand Up @@ -98,6 +93,8 @@ kexec_halt_all_cpus(void *kernel_image)
cpu_relax();
}

s390_reset_system();

image = (struct kimage *) kernel_image;
data_mover = (relocate_kernel_t)
(page_to_pfn(image->control_code_page) << PAGE_SHIFT);
Expand Down
17 changes: 2 additions & 15 deletions arch/s390/kernel/reipl.S
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,10 @@
.globl do_reipl_asm
do_reipl_asm: basr %r13,0
.Lpg0: lpsw .Lnewpsw-.Lpg0(%r13)

# switch off lowcore protection

.Lpg1: stctl %c0,%c0,.Lctlsave1-.Lpg0(%r13)
stctl %c0,%c0,.Lctlsave2-.Lpg0(%r13)
ni .Lctlsave1-.Lpg0(%r13),0xef
lctl %c0,%c0,.Lctlsave1-.Lpg0(%r13)

# do store status of all registers
.Lpg1: # do store status of all registers

stm %r0,%r15,__LC_GPREGS_SAVE_AREA
stctl %c0,%c15,__LC_CREGS_SAVE_AREA
mvc __LC_CREGS_SAVE_AREA(4),.Lctlsave2-.Lpg0(%r13)
stam %a0,%a15,__LC_AREGS_SAVE_AREA
stpx __LC_PREFIX_SAVE_AREA
stckc .Lclkcmp-.Lpg0(%r13)
Expand Down Expand Up @@ -56,18 +47,14 @@ do_reipl_asm: basr %r13,0
.L002: tm .Liplirb+8-.Lpg0(%r13),0xf3
jz .L003
bas %r14,.Ldisab-.Lpg0(%r13)
.L003: spx .Lnull-.Lpg0(%r13)
st %r1,__LC_SUBCHANNEL_ID
.L003: st %r1,__LC_SUBCHANNEL_ID
lpsw 0
sigp 0,0,0(6)
.Ldisab: st %r14,.Ldispsw+4-.Lpg0(%r13)
lpsw .Ldispsw-.Lpg0(%r13)
.align 8
.Lclkcmp: .quad 0x0000000000000000
.Lall: .long 0xff000000
.Lnull: .long 0x00000000
.Lctlsave1: .long 0x00000000
.Lctlsave2: .long 0x00000000
.align 8
.Lnewpsw: .long 0x00080000,0x80000000+.Lpg1
.Lpcnew: .long 0x00080000,0x80000000+.Lecs
Expand Down
16 changes: 5 additions & 11 deletions arch/s390/kernel/reipl64.S
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@
#include <asm/lowcore.h>
.globl do_reipl_asm
do_reipl_asm: basr %r13,0
.Lpg0: lpswe .Lnewpsw-.Lpg0(%r13)
.Lpg1: # do store status of all registers

# do store status of all registers

.Lpg0: stg %r1,.Lregsave-.Lpg0(%r13)
stg %r1,.Lregsave-.Lpg0(%r13)
lghi %r1,0x1000
stmg %r0,%r15,__LC_GPREGS_SAVE_AREA-0x1000(%r1)
lg %r0,.Lregsave-.Lpg0(%r13)
Expand All @@ -27,11 +27,7 @@ do_reipl_asm: basr %r13,0
stpt __LC_CPU_TIMER_SAVE_AREA-0x1000(%r1)
stg %r13, __LC_PSW_SAVE_AREA-0x1000+8(%r1)

lpswe .Lnewpsw-.Lpg0(%r13)
.Lpg1: lctlg %c6,%c6,.Lall-.Lpg0(%r13)
stctg %c0,%c0,.Lregsave-.Lpg0(%r13)
ni .Lregsave+4-.Lpg0(%r13),0xef
lctlg %c0,%c0,.Lregsave-.Lpg0(%r13)
lctlg %c6,%c6,.Lall-.Lpg0(%r13)
lgr %r1,%r2
mvc __LC_PGM_NEW_PSW(16),.Lpcnew-.Lpg0(%r13)
stsch .Lschib-.Lpg0(%r13)
Expand All @@ -56,8 +52,7 @@ do_reipl_asm: basr %r13,0
.L002: tm .Liplirb+8-.Lpg0(%r13),0xf3
jz .L003
bas %r14,.Ldisab-.Lpg0(%r13)
.L003: spx .Lnull-.Lpg0(%r13)
st %r1,__LC_SUBCHANNEL_ID
.L003: st %r1,__LC_SUBCHANNEL_ID
lhi %r1,0 # mode 0 = esa
slr %r0,%r0 # set cpuid to zero
sigp %r1,%r0,0x12 # switch to esa mode
Expand All @@ -70,7 +65,6 @@ do_reipl_asm: basr %r13,0
.Lclkcmp: .quad 0x0000000000000000
.Lall: .quad 0x00000000ff000000
.Lregsave: .quad 0x0000000000000000
.Lnull: .long 0x0000000000000000
.align 16
/*
* These addresses have to be 31 bit otherwise
Expand Down
5 changes: 1 addition & 4 deletions arch/s390/kernel/relocate_kernel.S
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@
relocate_kernel:
basr %r13,0 # base address
.base:
stnsm sys_msk-.base(%r13),0xf8 # disable DAT and IRQ (external)
spx zero64-.base(%r13) # absolute addressing mode
stnsm sys_msk-.base(%r13),0xfb # disable DAT
stctl %c0,%c15,ctlregs-.base(%r13)
stm %r0,%r15,gprregs-.base(%r13)
la %r1,load_psw-.base(%r13)
Expand Down Expand Up @@ -97,8 +96,6 @@
lpsw 0 # hopefully start new kernel...

.align 8
zero64:
.quad 0
load_psw:
.long 0x00080000,0x80000000
sys_msk:
Expand Down
5 changes: 1 addition & 4 deletions arch/s390/kernel/relocate_kernel64.S
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,7 @@
relocate_kernel:
basr %r13,0 # base address
.base:
stnsm sys_msk-.base(%r13),0xf8 # disable DAT and IRQs
spx zero64-.base(%r13) # absolute addressing mode
stnsm sys_msk-.base(%r13),0xfb # disable DAT
stctg %c0,%c15,ctlregs-.base(%r13)
stmg %r0,%r15,gprregs-.base(%r13)
lghi %r0,3
Expand Down Expand Up @@ -100,8 +99,6 @@
lpsw 0 # hopefully start new kernel...

.align 8
zero64:
.quad 0
load_psw:
.long 0x00080000,0x80000000
sys_msk:
Expand Down
48 changes: 48 additions & 0 deletions arch/s390/kernel/reset.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* arch/s390/kernel/reset.S
*
* Copyright (C) IBM Corp. 2006
* Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
*/

#include <asm/ptrace.h>
#include <asm/lowcore.h>

#ifdef CONFIG_64BIT

.globl reset_mcck_handler
reset_mcck_handler:
basr %r13,0
0: lg %r15,__LC_PANIC_STACK # load panic stack
aghi %r15,-STACK_FRAME_OVERHEAD
lg %r1,s390_reset_mcck_handler-0b(%r13)
ltgr %r1,%r1
jz 1f
basr %r14,%r1
1: la %r1,4095
lmg %r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1)
lpswe __LC_MCK_OLD_PSW

.globl s390_reset_mcck_handler
s390_reset_mcck_handler:
.quad 0

#else /* CONFIG_64BIT */

.globl reset_mcck_handler
reset_mcck_handler:
basr %r13,0
0: l %r15,__LC_PANIC_STACK # load panic stack
ahi %r15,-STACK_FRAME_OVERHEAD
l %r1,s390_reset_mcck_handler-0b(%r13)
ltr %r1,%r1
jz 1f
basr %r14,%r1
1: lm %r0,%r15,__LC_GPREGS_SAVE_AREA
lpsw __LC_MCK_OLD_PSW

.globl s390_reset_mcck_handler
s390_reset_mcck_handler:
.long 0

#endif /* CONFIG_64BIT */
35 changes: 0 additions & 35 deletions drivers/s390/cio/chsc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1465,41 +1465,6 @@ chsc_get_chp_desc(struct subchannel *sch, int chp_no)
return desc;
}

static int reset_channel_path(struct channel_path *chp)
{
int cc;

cc = rchp(chp->id);
switch (cc) {
case 0:
return 0;
case 2:
return -EBUSY;
default:
return -ENODEV;
}
}

static void reset_channel_paths_css(struct channel_subsystem *css)
{
int i;

for (i = 0; i <= __MAX_CHPID; i++) {
if (css->chps[i])
reset_channel_path(css->chps[i]);
}
}

void cio_reset_channel_paths(void)
{
int i;

for (i = 0; i <= __MAX_CSSID; i++) {
if (css[i] && css[i]->valid)
reset_channel_paths_css(css[i]);
}
}

static int __init
chsc_alloc_sei_area(void)
{
Expand Down
Loading

0 comments on commit 15e9b58

Please sign in to comment.