[S390] Convert memory detection into C code.

Hopefully this will make it more maintainable and less error prone.
Code makes use of search_exception_tables(). Since it calls this
function before the kernel exeception table is sorted, there is an
early call to sort_main_extable().

This way it's easy to use the already present infrastructure of fixup
sections. Also this would allows to easily convert the rest of
head[31|64].S into C code.

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 2007-02-05 21:18:37 +01:00 committed by Martin Schwidefsky
parent 31ee4b2f40
commit ab14de6c37
21 changed files with 598 additions and 609 deletions

View file

@ -433,7 +433,6 @@ CONFIG_TN3270_CONSOLE=y
CONFIG_TN3215=y CONFIG_TN3215=y
CONFIG_TN3215_CONSOLE=y CONFIG_TN3215_CONSOLE=y
CONFIG_CCW_CONSOLE=y CONFIG_CCW_CONSOLE=y
CONFIG_SCLP=y
CONFIG_SCLP_TTY=y CONFIG_SCLP_TTY=y
CONFIG_SCLP_CONSOLE=y CONFIG_SCLP_CONSOLE=y
CONFIG_SCLP_VT220_TTY=y CONFIG_SCLP_VT220_TTY=y

View file

@ -4,7 +4,7 @@
EXTRA_AFLAGS := -traditional EXTRA_AFLAGS := -traditional
obj-y := bitmap.o traps.o time.o process.o reset.o \ obj-y := bitmap.o traps.o time.o process.o base.o early.o \
setup.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \ setup.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \
semaphore.o s390_ext.o debug.o irq.o ipl.o semaphore.o s390_ext.o debug.o irq.o ipl.o

150
arch/s390/kernel/base.S Normal file
View file

@ -0,0 +1,150 @@
/*
* arch/s390/kernel/base.S
*
* Copyright IBM Corp. 2006,2007
* Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
* Michael Holzheu <holzheu@de.ibm.com>
*/
#include <asm/ptrace.h>
#include <asm/lowcore.h>
#ifdef CONFIG_64BIT
.globl s390_base_mcck_handler
s390_base_mcck_handler:
basr %r13,0
0: lg %r15,__LC_PANIC_STACK # load panic stack
aghi %r15,-STACK_FRAME_OVERHEAD
larl %r1,s390_base_mcck_handler_fn
lg %r1,0(%r1)
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
.section .bss
.globl s390_base_mcck_handler_fn
s390_base_mcck_handler_fn:
.quad 0
.previous
.globl s390_base_ext_handler
s390_base_ext_handler:
stmg %r0,%r15,__LC_SAVE_AREA
basr %r13,0
0: aghi %r15,-STACK_FRAME_OVERHEAD
larl %r1,s390_base_ext_handler_fn
lg %r1,0(%r1)
ltgr %r1,%r1
jz 1f
basr %r14,%r1
1: lmg %r0,%r15,__LC_SAVE_AREA
ni __LC_EXT_OLD_PSW+1,0xfd # clear wait state bit
lpswe __LC_EXT_OLD_PSW
.section .bss
.globl s390_base_ext_handler_fn
s390_base_ext_handler_fn:
.quad 0
.previous
.globl s390_base_pgm_handler
s390_base_pgm_handler:
stmg %r0,%r15,__LC_SAVE_AREA
basr %r13,0
0: aghi %r15,-STACK_FRAME_OVERHEAD
larl %r1,s390_base_pgm_handler_fn
lg %r1,0(%r1)
ltgr %r1,%r1
jz 1f
basr %r14,%r1
lmg %r0,%r15,__LC_SAVE_AREA
lpswe __LC_PGM_OLD_PSW
1: lpswe disabled_wait_psw-0b(%r13)
.align 8
disabled_wait_psw:
.quad 0x0002000180000000,0x0000000000000000 + s390_base_pgm_handler
.section .bss
.globl s390_base_pgm_handler_fn
s390_base_pgm_handler_fn:
.quad 0
.previous
#else /* CONFIG_64BIT */
.globl s390_base_mcck_handler
s390_base_mcck_handler:
basr %r13,0
0: l %r15,__LC_PANIC_STACK # load panic stack
ahi %r15,-STACK_FRAME_OVERHEAD
l %r1,2f-0b(%r13)
l %r1,0(%r1)
ltr %r1,%r1
jz 1f
basr %r14,%r1
1: lm %r0,%r15,__LC_GPREGS_SAVE_AREA
lpsw __LC_MCK_OLD_PSW
2: .long s390_base_mcck_handler_fn
.section .bss
.globl s390_base_mcck_handler_fn
s390_base_mcck_handler_fn:
.long 0
.previous
.globl s390_base_ext_handler
s390_base_ext_handler:
stm %r0,%r15,__LC_SAVE_AREA
basr %r13,0
0: ahi %r15,-STACK_FRAME_OVERHEAD
l %r1,2f-0b(%r13)
l %r1,0(%r1)
ltr %r1,%r1
jz 1f
basr %r14,%r1
1: lm %r0,%r15,__LC_SAVE_AREA
ni __LC_EXT_OLD_PSW+1,0xfd # clear wait state bit
lpsw __LC_EXT_OLD_PSW
2: .long s390_base_ext_handler_fn
.section .bss
.globl s390_base_ext_handler_fn
s390_base_ext_handler_fn:
.long 0
.previous
.globl s390_base_pgm_handler
s390_base_pgm_handler:
stm %r0,%r15,__LC_SAVE_AREA
basr %r13,0
0: ahi %r15,-STACK_FRAME_OVERHEAD
l %r1,2f-0b(%r13)
l %r1,0(%r1)
ltr %r1,%r1
jz 1f
basr %r14,%r1
lm %r0,%r15,__LC_SAVE_AREA
lpsw __LC_PGM_OLD_PSW
1: lpsw disabled_wait_psw-0b(%r13)
2: .long s390_base_pgm_handler_fn
disabled_wait_psw:
.align 8
.long 0x000a0000,0x00000000 + s390_base_pgm_handler
.section .bss
.globl s390_base_pgm_handler_fn
s390_base_pgm_handler_fn:
.long 0
.previous
#endif /* CONFIG_64BIT */

307
arch/s390/kernel/early.c Normal file
View file

@ -0,0 +1,307 @@
/*
* arch/s390/kernel/early.c
*
* Copyright IBM Corp. 2007
* Author(s): Hongjie Yang <hongjie@us.ibm.com>,
* Heiko Carstens <heiko.carstens@de.ibm.com>
*/
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/ctype.h>
#include <linux/lockdep.h>
#include <linux/module.h>
#include <linux/pfn.h>
#include <linux/uaccess.h>
#include <asm/lowcore.h>
#include <asm/processor.h>
#include <asm/sections.h>
#include <asm/setup.h>
#include <asm/cpcmd.h>
#include <asm/sclp.h>
/*
* Create a Kernel NSS if the SAVESYS= parameter is defined
*/
#define DEFSYS_CMD_SIZE 96
#define SAVESYS_CMD_SIZE 32
extern int _eshared;
char kernel_nss_name[NSS_NAME_SIZE + 1];
#ifdef CONFIG_SHARED_KERNEL
static noinline __init void create_kernel_nss(void)
{
unsigned int i, stext_pfn, eshared_pfn, end_pfn, min_size;
#ifdef CONFIG_BLK_DEV_INITRD
unsigned int sinitrd_pfn, einitrd_pfn;
#endif
int response;
char *savesys_ptr;
char upper_command_line[COMMAND_LINE_SIZE];
char defsys_cmd[DEFSYS_CMD_SIZE];
char savesys_cmd[SAVESYS_CMD_SIZE];
/* Do nothing if we are not running under VM */
if (!MACHINE_IS_VM)
return;
/* Convert COMMAND_LINE to upper case */
for (i = 0; i < strlen(COMMAND_LINE); i++)
upper_command_line[i] = toupper(COMMAND_LINE[i]);
savesys_ptr = strstr(upper_command_line, "SAVESYS=");
if (!savesys_ptr)
return;
savesys_ptr += 8; /* Point to the beginning of the NSS name */
for (i = 0; i < NSS_NAME_SIZE; i++) {
if (savesys_ptr[i] == ' ' || savesys_ptr[i] == '\0')
break;
kernel_nss_name[i] = savesys_ptr[i];
}
stext_pfn = PFN_DOWN(__pa(&_stext));
eshared_pfn = PFN_DOWN(__pa(&_eshared));
end_pfn = PFN_UP(__pa(&_end));
min_size = end_pfn << 2;
sprintf(defsys_cmd, "DEFSYS %s 00000-%.5X EW %.5X-%.5X SR %.5X-%.5X",
kernel_nss_name, stext_pfn - 1, stext_pfn, eshared_pfn - 1,
eshared_pfn, end_pfn);
#ifdef CONFIG_BLK_DEV_INITRD
if (INITRD_START && INITRD_SIZE) {
sinitrd_pfn = PFN_DOWN(__pa(INITRD_START));
einitrd_pfn = PFN_UP(__pa(INITRD_START + INITRD_SIZE));
min_size = einitrd_pfn << 2;
sprintf(defsys_cmd, "%s EW %.5X-%.5X", defsys_cmd,
sinitrd_pfn, einitrd_pfn);
}
#endif
sprintf(defsys_cmd, "%s EW MINSIZE=%.7iK", defsys_cmd, min_size);
sprintf(savesys_cmd, "SAVESYS %s \n IPL %s",
kernel_nss_name, kernel_nss_name);
__cpcmd(defsys_cmd, NULL, 0, &response);
if (response != 0)
return;
__cpcmd(savesys_cmd, NULL, 0, &response);
if (response != strlen(savesys_cmd))
return;
ipl_flags = IPL_NSS_VALID;
}
#else /* CONFIG_SHARED_KERNEL */
static inline void create_kernel_nss(void) { }
#endif /* CONFIG_SHARED_KERNEL */
/*
* Clear bss memory
*/
static noinline __init void clear_bss_section(void)
{
memset(__bss_start, 0, _end - __bss_start);
}
/*
* Initialize storage key for kernel pages
*/
static noinline __init void init_kernel_storage_key(void)
{
unsigned long end_pfn, init_pfn;
end_pfn = PFN_UP(__pa(&_end));
for (init_pfn = 0 ; init_pfn < end_pfn; init_pfn++)
page_set_storage_key(init_pfn << PAGE_SHIFT, PAGE_DEFAULT_KEY);
}
static noinline __init void detect_machine_type(void)
{
struct cpuinfo_S390 *cpuinfo = &S390_lowcore.cpu_data;
asm volatile("stidp %0" : "=m" (S390_lowcore.cpu_data.cpu_id));
/* Running under z/VM ? */
if (cpuinfo->cpu_id.version == 0xff)
machine_flags |= 1;
/* Running on a P/390 ? */
if (cpuinfo->cpu_id.machine == 0x7490)
machine_flags |= 4;
}
static noinline __init int memory_fast_detect(void)
{
unsigned long val0 = 0;
unsigned long val1 = 0xc;
int ret = -ENOSYS;
if (ipl_flags & IPL_NSS_VALID)
return -ENOSYS;
asm volatile(
" diag %1,%2,0x260\n"
"0: lhi %0,0\n"
"1:\n"
EX_TABLE(0b,1b)
: "+d" (ret), "+d" (val0), "+d" (val1) : : "cc");
if (ret || val0 != val1)
return -ENOSYS;
memory_chunk[0].size = val0;
return 0;
}
#define ADDR2G (1UL << 31)
static noinline __init unsigned long sclp_memory_detect(void)
{
struct sclp_readinfo_sccb *sccb;
unsigned long long memsize;
sccb = &s390_readinfo_sccb;
if (sccb->header.response_code != 0x10)
return 0;
if (sccb->rnsize)
memsize = sccb->rnsize << 20;
else
memsize = sccb->rnsize2 << 20;
if (sccb->rnmax)
memsize *= sccb->rnmax;
else
memsize *= sccb->rnmax2;
#ifndef CONFIG_64BIT
/*
* Can't deal with more than 2G in 31 bit addressing mode, so
* limit the value in order to avoid strange side effects.
*/
if (memsize > ADDR2G)
memsize = ADDR2G;
#endif
return (unsigned long) memsize;
}
static inline __init unsigned long __tprot(unsigned long addr)
{
int cc = -1;
asm volatile(
" tprot 0(%1),0\n"
"0: ipm %0\n"
" srl %0,28\n"
"1:\n"
EX_TABLE(0b,1b)
: "+d" (cc) : "a" (addr) : "cc");
return (unsigned long)cc;
}
/* Checking memory in 128KB increments. */
#define CHUNK_INCR (1UL << 17)
static noinline __init void find_memory_chunks(unsigned long memsize)
{
unsigned long addr = 0, old_addr = 0;
unsigned long old_cc = CHUNK_READ_WRITE;
unsigned long cc;
int chunk = 0;
while (chunk < MEMORY_CHUNKS) {
cc = __tprot(addr);
while (cc == old_cc) {
addr += CHUNK_INCR;
cc = __tprot(addr);
#ifndef CONFIG_64BIT
if (addr == ADDR2G)
break;
#endif
}
if (old_addr != addr &&
(old_cc == CHUNK_READ_WRITE || old_cc == CHUNK_READ_ONLY)) {
memory_chunk[chunk].addr = old_addr;
memory_chunk[chunk].size = addr - old_addr;
memory_chunk[chunk].type = old_cc;
chunk++;
}
old_addr = addr;
old_cc = cc;
#ifndef CONFIG_64BIT
if (addr == ADDR2G)
break;
#endif
/*
* Finish memory detection at the first hole, unless
* - we reached the hsa -> skip it.
* - we know there must be more.
*/
if (cc == -1UL && !memsize && old_addr != ADDR2G)
break;
if (memsize && addr >= memsize)
break;
}
}
static __init void early_pgm_check_handler(void)
{
unsigned long addr;
const struct exception_table_entry *fixup;
addr = S390_lowcore.program_old_psw.addr;
fixup = search_exception_tables(addr & PSW_ADDR_INSN);
if (!fixup)
disabled_wait(0);
S390_lowcore.program_old_psw.addr = fixup->fixup | PSW_ADDR_AMODE;
}
static noinline __init void setup_lowcore_early(void)
{
psw_t psw;
psw.mask = PSW_BASE_BITS | PSW_DEFAULT_KEY;
psw.addr = PSW_ADDR_AMODE | (unsigned long) s390_base_ext_handler;
S390_lowcore.external_new_psw = psw;
psw.addr = PSW_ADDR_AMODE | (unsigned long) s390_base_pgm_handler;
S390_lowcore.program_new_psw = psw;
s390_base_pgm_handler_fn = early_pgm_check_handler;
}
/*
* Save ipl parameters, clear bss memory, initialize storage keys
* and create a kernel NSS at startup if the SAVESYS= parm is defined
*/
void __init startup_init(void)
{
unsigned long memsize;
ipl_save_parameters();
clear_bss_section();
init_kernel_storage_key();
lockdep_init();
lockdep_off();
detect_machine_type();
create_kernel_nss();
sort_main_extable();
setup_lowcore_early();
sclp_readinfo_early();
memsize = sclp_memory_detect();
if (memory_fast_detect() < 0)
find_memory_chunks(memsize);
lockdep_on();
}

View file

@ -58,145 +58,6 @@ startup_continue:
l %r14,.Lstartup_init-.LPG1(%r13) l %r14,.Lstartup_init-.LPG1(%r13)
basr %r14,%r14 basr %r14,%r14
l %r2,.Lrcp-.LPG1(%r13) # Read SCP forced command word
.Lservicecall:
stosm .Lpmask-.LPG1(%r13),0x01 # authorize ext interrupts
stctl %r0, %r0,.Lcr-.LPG1(%r13) # get cr0
la %r1,0x200 # set bit 22
o %r1,.Lcr-.LPG1(%r13) # or old cr0 with r1
st %r1,.Lcr-.LPG1(%r13)
lctl %r0, %r0,.Lcr-.LPG1(%r13) # load modified cr0
mvc __LC_EXT_NEW_PSW(8),.Lpcext-.LPG1(%r13) # set postcall psw
la %r1, .Lsclph-.LPG1(%r13)
a %r1,__LC_EXT_NEW_PSW+4 # set handler
st %r1,__LC_EXT_NEW_PSW+4
l %r4,.Lsccbaddr-.LPG1(%r13) # %r4 is our index for sccb stuff
lr %r1,%r4 # our sccb
.insn rre,0xb2200000,%r2,%r1 # service call
ipm %r1
srl %r1,28 # get cc code
xr %r3, %r3
chi %r1,3
be .Lfchunk-.LPG1(%r13) # leave
chi %r1,2
be .Lservicecall-.LPG1(%r13)
lpsw .Lwaitsclp-.LPG1(%r13)
.Lsclph:
lh %r1,.Lsccbr-.Lsccb(%r4)
chi %r1,0x10 # 0x0010 is the sucess code
je .Lprocsccb # let's process the sccb
chi %r1,0x1f0
bne .Lfchunk-.LPG1(%r13) # unhandled error code
c %r2, .Lrcp-.LPG1(%r13) # Did we try Read SCP forced
bne .Lfchunk-.LPG1(%r13) # if no, give up
l %r2, .Lrcp2-.LPG1(%r13) # try with Read SCP
b .Lservicecall-.LPG1(%r13)
.Lprocsccb:
lhi %r1,0
icm %r1,3,.Lscpincr1-.Lsccb(%r4) # use this one if != 0
jnz .Lscnd
lhi %r1,0x800 # otherwise report 2GB
.Lscnd:
lhi %r3,0x800 # limit reported memory size to 2GB
cr %r1,%r3
jl .Lno2gb
lr %r1,%r3
.Lno2gb:
xr %r3,%r3 # same logic
ic %r3,.Lscpa1-.Lsccb(%r4)
chi %r3,0x00
jne .Lcompmem
l %r3,.Lscpa2-.Lsccb(%r4)
.Lcompmem:
mr %r2,%r1 # mem in MB on 128-bit
l %r1,.Lonemb-.LPG1(%r13)
mr %r2,%r1 # mem size in bytes in %r3
b .Lfchunk-.LPG1(%r13)
.align 4
.Linittu:
.long init_thread_union
.Lstartup_init:
.long startup_init
.Lpmask:
.byte 0
.align 8
.Lpcext:.long 0x00080000,0x80000000
.Lcr:
.long 0x00 # place holder for cr0
.align 8
.Lwaitsclp:
.long 0x010a0000,0x80000000 + .Lsclph
.Lrcp:
.int 0x00120001 # Read SCP forced code
.Lrcp2:
.int 0x00020001 # Read SCP code
.Lonemb:
.int 0x100000
.Lfchunk:
#
# find memory chunks.
#
lr %r9,%r3 # end of mem
mvc __LC_PGM_NEW_PSW(8),.Lpcmem-.LPG1(%r13)
la %r1,1 # test in increments of 128KB
sll %r1,17
l %r3,.Lmchunk-.LPG1(%r13) # get pointer to memory_chunk array
slr %r4,%r4 # set start of chunk to zero
slr %r5,%r5 # set end of chunk to zero
slr %r6,%r6 # set access code to zero
la %r10,MEMORY_CHUNKS # number of chunks
.Lloop:
tprot 0(%r5),0 # test protection of first byte
ipm %r7
srl %r7,28
clr %r6,%r7 # compare cc with last access code
be .Lsame-.LPG1(%r13)
lhi %r8,0 # no program checks
b .Lsavchk-.LPG1(%r13)
.Lsame:
ar %r5,%r1 # add 128KB to end of chunk
bno .Lloop-.LPG1(%r13) # r1 < 0x80000000 -> loop
.Lchkmem: # > 2GB or tprot got a program check
lhi %r8,1 # set program check flag
.Lsavchk:
clr %r4,%r5 # chunk size > 0?
be .Lchkloop-.LPG1(%r13)
st %r4,0(%r3) # store start address of chunk
lr %r0,%r5
slr %r0,%r4
st %r0,4(%r3) # store size of chunk
st %r6,8(%r3) # store type of chunk
la %r3,12(%r3)
ahi %r10,-1 # update chunk number
.Lchkloop:
lr %r6,%r7 # set access code to last cc
# we got an exception or we're starting a new
# chunk , we must check if we should
# still try to find valid memory (if we detected
# the amount of available storage), and if we
# have chunks left
xr %r0,%r0
clr %r0,%r9 # did we detect memory?
je .Ldonemem # if not, leave
chi %r10,0 # do we have chunks left?
je .Ldonemem
chi %r8,1 # program check ?
je .Lpgmchk
lr %r4,%r5 # potential new chunk
alr %r5,%r1 # add 128KB to end of chunk
j .Llpcnt
.Lpgmchk:
alr %r5,%r1 # add 128KB to end of chunk
lr %r4,%r5 # potential new chunk
.Llpcnt:
clr %r5,%r9 # should we go on?
jl .Lloop
.Ldonemem:
l %r12,.Lmflags-.LPG1(%r13) # get address of machine_flags l %r12,.Lmflags-.LPG1(%r13) # get address of machine_flags
# #
# find out if we have an IEEE fpu # find out if we have an IEEE fpu
@ -273,7 +134,6 @@ startup_continue:
.long 0 # cr15: linkage stack operations .long 0 # cr15: linkage stack operations
.Lduct: .long 0,0,0,0,0,0,0,0 .Lduct: .long 0,0,0,0,0,0,0,0
.long 0,0,0,0,0,0,0,0 .long 0,0,0,0,0,0,0,0
.Lpcmem:.long 0x00080000,0x80000000 + .Lchkmem
.Lpcfpu:.long 0x00080000,0x80000000 + .Lchkfpu .Lpcfpu:.long 0x00080000,0x80000000 + .Lchkfpu
.Lpccsp:.long 0x00080000,0x80000000 + .Lchkcsp .Lpccsp:.long 0x00080000,0x80000000 + .Lchkcsp
.Lpcmvpg:.long 0x00080000,0x80000000 + .Lchkmvpg .Lpcmvpg:.long 0x00080000,0x80000000 + .Lchkmvpg
@ -284,7 +144,9 @@ startup_continue:
.Lbss_bgn: .long __bss_start .Lbss_bgn: .long __bss_start
.Lbss_end: .long _end .Lbss_end: .long _end
.Lparmaddr: .long PARMAREA .Lparmaddr: .long PARMAREA
.Lsccbaddr: .long .Lsccb .Linittu: .long init_thread_union
.Lstartup_init:
.long startup_init
.globl ipl_schib .globl ipl_schib
ipl_schib: ipl_schib:
@ -300,26 +162,6 @@ ipl_devno:
.word 0 .word 0
.org 0x12000 .org 0x12000
.globl s390_readinfo_sccb
s390_readinfo_sccb:
.Lsccb:
.hword 0x1000 # length, one page
.byte 0x00,0x00,0x00
.byte 0x80 # variable response bit set
.Lsccbr:
.hword 0x00 # response code
.Lscpincr1:
.hword 0x00
.Lscpa1:
.byte 0x00
.fill 89,1,0
.Lscpa2:
.int 0x00
.Lscpincr2:
.quad 0x00
.fill 3984,1,0
.org 0x13000
#ifdef CONFIG_SHARED_KERNEL #ifdef CONFIG_SHARED_KERNEL
.org 0x100000 .org 0x100000
#endif #endif

View file

@ -65,162 +65,6 @@ startup_continue:
brasl %r14,startup_init brasl %r14,startup_init
# set program check new psw mask # set program check new psw mask
mvc __LC_PGM_NEW_PSW(8),.Lpcmsk-.LPG1(%r13) mvc __LC_PGM_NEW_PSW(8),.Lpcmsk-.LPG1(%r13)
larl %r1,.Lslowmemdetect # set program check address
stg %r1,__LC_PGM_NEW_PSW+8
lghi %r1,0xc
diag %r0,%r1,0x260 # get memory size of virtual machine
cgr %r0,%r1 # different? -> old detection routine
jne .Lslowmemdetect
larl %r3,ipl_flags
llgt %r3,0(%r3)
chi %r3,4 # ipled from an kernel NSS
je .Lslowmemdetect
aghi %r1,1 # size is one more than end
larl %r2,memory_chunk
stg %r1,8(%r2) # store size of chunk
.Lslowmemdetect:
l %r2,.Lrcp-.LPG1(%r13) # Read SCP forced command word
.Lservicecall:
stosm .Lpmask-.LPG1(%r13),0x01 # authorize ext interrupts
stctg %r0,%r0,.Lcr-.LPG1(%r13) # get cr0
la %r1,0x200 # set bit 22
og %r1,.Lcr-.LPG1(%r13) # or old cr0 with r1
stg %r1,.Lcr-.LPG1(%r13)
lctlg %r0,%r0,.Lcr-.LPG1(%r13) # load modified cr0
mvc __LC_EXT_NEW_PSW(8),.Lpcmsk-.LPG1(%r13) # set postcall psw
larl %r1,.Lsclph
stg %r1,__LC_EXT_NEW_PSW+8 # set handler
larl %r4,.Lsccb # %r4 is our index for sccb stuff
lgr %r1,%r4 # our sccb
.insn rre,0xb2200000,%r2,%r1 # service call
ipm %r1
srl %r1,28 # get cc code
xr %r3,%r3
chi %r1,3
be .Lfchunk-.LPG1(%r13) # leave
chi %r1,2
be .Lservicecall-.LPG1(%r13)
lpswe .Lwaitsclp-.LPG1(%r13)
.Lsclph:
lh %r1,.Lsccbr-.Lsccb(%r4)
chi %r1,0x10 # 0x0010 is the sucess code
je .Lprocsccb # let's process the sccb
chi %r1,0x1f0
bne .Lfchunk-.LPG1(%r13) # unhandled error code
c %r2,.Lrcp-.LPG1(%r13) # Did we try Read SCP forced
bne .Lfchunk-.LPG1(%r13) # if no, give up
l %r2,.Lrcp2-.LPG1(%r13) # try with Read SCP
b .Lservicecall-.LPG1(%r13)
.Lprocsccb:
lghi %r1,0
icm %r1,3,.Lscpincr1-.Lsccb(%r4) # use this one if != 0
jnz .Lscnd
lg %r1,.Lscpincr2-.Lsccb(%r4) # otherwise use this one
.Lscnd:
xr %r3,%r3 # same logic
ic %r3,.Lscpa1-.Lsccb(%r4)
chi %r3,0x00
jne .Lcompmem
l %r3,.Lscpa2-.Lsccb(%r4)
.Lcompmem:
mlgr %r2,%r1 # mem in MB on 128-bit
l %r1,.Lonemb-.LPG1(%r13)
mlgr %r2,%r1 # mem size in bytes in %r3
b .Lfchunk-.LPG1(%r13)
.align 4
.Lpmask:
.byte 0
.align 8
.Lcr:
.quad 0x00 # place holder for cr0
.Lwaitsclp:
.quad 0x0102000180000000,.Lsclph
.Lrcp:
.int 0x00120001 # Read SCP forced code
.Lrcp2:
.int 0x00020001 # Read SCP code
.Lonemb:
.int 0x100000
.Lfchunk:
#
# find memory chunks.
#
larl %r9,memory_chunk # skip tprot loop if diag260
lg %r9,8(%r9) # memory detection was successful
ltgr %r9,%r9
jne .Ldonemem
lgr %r9,%r3 # end of mem
larl %r1,.Lchkmem # set program check address
stg %r1,__LC_PGM_NEW_PSW+8
la %r1,1 # test in increments of 128KB
sllg %r1,%r1,17
larl %r3,memory_chunk
slgr %r4,%r4 # set start of chunk to zero
slgr %r5,%r5 # set end of chunk to zero
slr %r6,%r6 # set access code to zero
la %r10,MEMORY_CHUNKS # number of chunks
.Lloop:
tprot 0(%r5),0 # test protection of first byte
ipm %r7
srl %r7,28
clr %r6,%r7 # compare cc with last access code
je .Lsame
lghi %r8,0 # no program checks
j .Lsavchk
.Lsame:
algr %r5,%r1 # add 128KB to end of chunk
# no need to check here,
brc 12,.Lloop # this is the same chunk
.Lchkmem: # > 16EB or tprot got a program check
lghi %r8,1 # set program check flag
.Lsavchk:
clgr %r4,%r5 # chunk size > 0?
je .Lchkloop
stg %r4,0(%r3) # store start address of chunk
lgr %r0,%r5
slgr %r0,%r4
stg %r0,8(%r3) # store size of chunk
st %r6,20(%r3) # store type of chunk
la %r3,24(%r3)
ahi %r10,-1 # update chunk number
.Lchkloop:
lr %r6,%r7 # set access code to last cc
# we got an exception or we're starting a new
# chunk , we must check if we should
# still try to find valid memory (if we detected
# the amount of available storage), and if we
# have chunks left
lghi %r4,1
sllg %r4,%r4,31
clgr %r5,%r4
je .Lhsaskip
xr %r0, %r0
clgr %r0, %r9 # did we detect memory?
je .Ldonemem # if not, leave
chi %r10, 0 # do we have chunks left?
je .Ldonemem
.Lhsaskip:
chi %r8,1 # program check ?
je .Lpgmchk
lgr %r4,%r5 # potential new chunk
algr %r5,%r1 # add 128KB to end of chunk
j .Llpcnt
.Lpgmchk:
algr %r5,%r1 # add 128KB to end of chunk
lgr %r4,%r5 # potential new chunk
.Llpcnt:
clgr %r5,%r9 # should we go on?
jl .Lloop
.Ldonemem:
larl %r12,machine_flags larl %r12,machine_flags
# #
# find out if we have the MVPG instruction # find out if we have the MVPG instruction
@ -324,25 +168,6 @@ ipl_devno:
.word 0 .word 0
.org 0x12000 .org 0x12000
.globl s390_readinfo_sccb
s390_readinfo_sccb:
.Lsccb:
.hword 0x1000 # length, one page
.byte 0x00,0x00,0x00
.byte 0x80 # variable response bit set
.Lsccbr:
.hword 0x00 # response code
.Lscpincr1:
.hword 0x00
.Lscpa1:
.byte 0x00
.fill 89,1,0
.Lscpa2:
.int 0x00
.Lscpincr2:
.quad 0x00
.fill 3984,1,0
.org 0x13000
#ifdef CONFIG_SHARED_KERNEL #ifdef CONFIG_SHARED_KERNEL
.org 0x100000 .org 0x100000

View file

@ -20,14 +20,13 @@
#include <asm/cio.h> #include <asm/cio.h>
#include <asm/ebcdic.h> #include <asm/ebcdic.h>
#include <asm/reset.h> #include <asm/reset.h>
#include <asm/sclp.h>
#define IPL_PARM_BLOCK_VERSION 0 #define IPL_PARM_BLOCK_VERSION 0
#define LOADPARM_LEN 8
extern char s390_readinfo_sccb[]; #define SCCB_VALID (s390_readinfo_sccb.header.response_code == 0x10)
#define SCCB_VALID (*((__u16*)&s390_readinfo_sccb[6]) == 0x0010) #define SCCB_LOADPARM (&s390_readinfo_sccb.loadparm)
#define SCCB_LOADPARM (&s390_readinfo_sccb[24]) #define SCCB_FLAG (s390_readinfo_sccb.flags)
#define SCCB_FLAG (s390_readinfo_sccb[91])
enum ipl_type { enum ipl_type {
IPL_TYPE_NONE = 1, IPL_TYPE_NONE = 1,
@ -1080,8 +1079,6 @@ static void do_reset_calls(void)
reset->fn(); reset->fn();
} }
extern void reset_mcck_handler(void);
extern void reset_pgm_handler(void);
extern __u32 dump_prefix_page; extern __u32 dump_prefix_page;
void s390_reset_system(void) void s390_reset_system(void)
@ -1105,12 +1102,12 @@ void s390_reset_system(void)
/* Set new machine check handler */ /* Set new machine check handler */
S390_lowcore.mcck_new_psw.mask = psw_kernel_bits & ~PSW_MASK_MCHECK; S390_lowcore.mcck_new_psw.mask = psw_kernel_bits & ~PSW_MASK_MCHECK;
S390_lowcore.mcck_new_psw.addr = S390_lowcore.mcck_new_psw.addr =
PSW_ADDR_AMODE | (unsigned long) &reset_mcck_handler; PSW_ADDR_AMODE | (unsigned long) s390_base_mcck_handler;
/* Set new program check handler */ /* Set new program check handler */
S390_lowcore.program_new_psw.mask = psw_kernel_bits & ~PSW_MASK_MCHECK; S390_lowcore.program_new_psw.mask = psw_kernel_bits & ~PSW_MASK_MCHECK;
S390_lowcore.program_new_psw.addr = S390_lowcore.program_new_psw.addr =
PSW_ADDR_AMODE | (unsigned long) &reset_pgm_handler; PSW_ADDR_AMODE | (unsigned long) s390_base_pgm_handler;
do_reset_calls(); do_reset_calls();
} }

View file

@ -1,90 +0,0 @@
/*
* arch/s390/kernel/reset.S
*
* Copyright (C) IBM Corp. 2006
* Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
* Michael Holzheu <holzheu@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
.globl reset_pgm_handler
reset_pgm_handler:
stmg %r0,%r15,__LC_SAVE_AREA
basr %r13,0
0: lg %r15,__LC_PANIC_STACK # load panic stack
aghi %r15,-STACK_FRAME_OVERHEAD
lg %r1,s390_reset_pgm_handler-0b(%r13)
ltgr %r1,%r1
jz 1f
basr %r14,%r1
lmg %r0,%r15,__LC_SAVE_AREA
lpswe __LC_PGM_OLD_PSW
1: lpswe disabled_wait_psw-0b(%r13)
.globl s390_reset_pgm_handler
s390_reset_pgm_handler:
.quad 0
.align 8
disabled_wait_psw:
.quad 0x0002000180000000,0x0000000000000000 + reset_pgm_handler
#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
.globl reset_pgm_handler
reset_pgm_handler:
stm %r0,%r15,__LC_SAVE_AREA
basr %r13,0
0: l %r15,__LC_PANIC_STACK # load panic stack
ahi %r15,-STACK_FRAME_OVERHEAD
l %r1,s390_reset_pgm_handler-0b(%r13)
ltr %r1,%r1
jz 1f
basr %r14,%r1
lm %r0,%r15,__LC_SAVE_AREA
lpsw __LC_PGM_OLD_PSW
1: lpsw disabled_wait_psw-0b(%r13)
.globl s390_reset_pgm_handler
s390_reset_pgm_handler:
.long 0
disabled_wait_psw:
.align 8
.long 0x000a0000,0x00000000 + reset_pgm_handler
#endif /* CONFIG_64BIT */

View file

@ -284,140 +284,6 @@ static void __init conmode_default(void)
} }
} }
/*
* Create a Kernel NSS if the SAVESYS= parameter is defined
*/
#define DEFSYS_CMD_SIZE 96
#define SAVESYS_CMD_SIZE 32
extern int _eshared;
char kernel_nss_name[NSS_NAME_SIZE + 1];
#ifdef CONFIG_SHARED_KERNEL
static __init void create_kernel_nss(void)
{
unsigned int i, stext_pfn, eshared_pfn, end_pfn, min_size;
#ifdef CONFIG_BLK_DEV_INITRD
unsigned int sinitrd_pfn, einitrd_pfn;
#endif
int response;
char *savesys_ptr;
char upper_command_line[COMMAND_LINE_SIZE];
char defsys_cmd[DEFSYS_CMD_SIZE];
char savesys_cmd[SAVESYS_CMD_SIZE];
/* Do nothing if we are not running under VM */
if (!MACHINE_IS_VM)
return;
/* Convert COMMAND_LINE to upper case */
for (i = 0; i < strlen(COMMAND_LINE); i++)
upper_command_line[i] = toupper(COMMAND_LINE[i]);
savesys_ptr = strstr(upper_command_line, "SAVESYS=");
if (!savesys_ptr)
return;
savesys_ptr += 8; /* Point to the beginning of the NSS name */
for (i = 0; i < NSS_NAME_SIZE; i++) {
if (savesys_ptr[i] == ' ' || savesys_ptr[i] == '\0')
break;
kernel_nss_name[i] = savesys_ptr[i];
}
stext_pfn = PFN_DOWN(__pa(&_stext));
eshared_pfn = PFN_DOWN(__pa(&_eshared));
end_pfn = PFN_UP(__pa(&_end));
min_size = end_pfn << 2;
sprintf(defsys_cmd, "DEFSYS %s 00000-%.5X EW %.5X-%.5X SR %.5X-%.5X",
kernel_nss_name, stext_pfn - 1, stext_pfn, eshared_pfn - 1,
eshared_pfn, end_pfn);
#ifdef CONFIG_BLK_DEV_INITRD
if (INITRD_START && INITRD_SIZE) {
sinitrd_pfn = PFN_DOWN(__pa(INITRD_START));
einitrd_pfn = PFN_UP(__pa(INITRD_START + INITRD_SIZE));
min_size = einitrd_pfn << 2;
sprintf(defsys_cmd, "%s EW %.5X-%.5X", defsys_cmd,
sinitrd_pfn, einitrd_pfn);
}
#endif
sprintf(defsys_cmd, "%s EW MINSIZE=%.7iK", defsys_cmd, min_size);
sprintf(savesys_cmd, "SAVESYS %s \n IPL %s",
kernel_nss_name, kernel_nss_name);
__cpcmd(defsys_cmd, NULL, 0, &response);
if (response != 0)
return;
__cpcmd(savesys_cmd, NULL, 0, &response);
if (response != strlen(savesys_cmd))
return;
ipl_flags = IPL_NSS_VALID;
}
#else /* CONFIG_SHARED_KERNEL */
static inline void create_kernel_nss(void) { }
#endif /* CONFIG_SHARED_KERNEL */
/*
* Clear bss memory
*/
static __init void clear_bss_section(void)
{
memset(__bss_start, 0, _end - __bss_start);
}
/*
* Initialize storage key for kernel pages
*/
static __init void init_kernel_storage_key(void)
{
unsigned long end_pfn, init_pfn;
end_pfn = PFN_UP(__pa(&_end));
for (init_pfn = 0 ; init_pfn < end_pfn; init_pfn++)
page_set_storage_key(init_pfn << PAGE_SHIFT, PAGE_DEFAULT_KEY);
}
static __init void detect_machine_type(void)
{
struct cpuinfo_S390 *cpuinfo = &S390_lowcore.cpu_data;
asm volatile("stidp %0" : "=m" (S390_lowcore.cpu_data.cpu_id));
/* Running under z/VM ? */
if (cpuinfo->cpu_id.version == 0xff)
machine_flags |= 1;
/* Running on a P/390 ? */
if (cpuinfo->cpu_id.machine == 0x7490)
machine_flags |= 4;
}
/*
* Save ipl parameters, clear bss memory, initialize storage keys
* and create a kernel NSS at startup if the SAVESYS= parm is defined
*/
void __init startup_init(void)
{
ipl_save_parameters();
clear_bss_section();
init_kernel_storage_key();
lockdep_init();
detect_machine_type();
create_kernel_nss();
}
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
void (*_machine_restart)(char *command) = machine_restart_smp; void (*_machine_restart)(char *command) = machine_restart_smp;
void (*_machine_halt)(void) = machine_halt_smp; void (*_machine_halt)(void) = machine_halt_smp;

View file

@ -103,14 +103,8 @@ config CCW_CONSOLE
depends on TN3215_CONSOLE || TN3270_CONSOLE depends on TN3215_CONSOLE || TN3270_CONSOLE
default y default y
config SCLP
bool "Support for SCLP"
help
Include support for the SCLP interface to the service element.
config SCLP_TTY config SCLP_TTY
bool "Support for SCLP line mode terminal" bool "Support for SCLP line mode terminal"
depends on SCLP
help help
Include support for IBM SCLP line-mode terminals. Include support for IBM SCLP line-mode terminals.
@ -123,7 +117,6 @@ config SCLP_CONSOLE
config SCLP_VT220_TTY config SCLP_VT220_TTY
bool "Support for SCLP VT220-compatible terminal" bool "Support for SCLP VT220-compatible terminal"
depends on SCLP
help help
Include support for an IBM SCLP VT220-compatible terminal. Include support for an IBM SCLP VT220-compatible terminal.
@ -136,7 +129,6 @@ config SCLP_VT220_CONSOLE
config SCLP_CPI config SCLP_CPI
tristate "Control-Program Identification" tristate "Control-Program Identification"
depends on SCLP
help help
This option enables the hardware console interface for system This option enables the hardware console interface for system
identification. This is commonly used for workload management and identification. This is commonly used for workload management and

View file

@ -2,7 +2,8 @@
# S/390 character devices # S/390 character devices
# #
obj-y += ctrlchar.o keyboard.o defkeymap.o obj-y += ctrlchar.o keyboard.o defkeymap.o sclp.o sclp_rw.o sclp_quiesce.o \
sclp_info.o
obj-$(CONFIG_TN3270) += raw3270.o obj-$(CONFIG_TN3270) += raw3270.o
obj-$(CONFIG_TN3270_CONSOLE) += con3270.o obj-$(CONFIG_TN3270_CONSOLE) += con3270.o
@ -11,7 +12,6 @@ obj-$(CONFIG_TN3270_FS) += fs3270.o
obj-$(CONFIG_TN3215) += con3215.o obj-$(CONFIG_TN3215) += con3215.o
obj-$(CONFIG_SCLP) += sclp.o sclp_rw.o sclp_quiesce.o
obj-$(CONFIG_SCLP_TTY) += sclp_tty.o obj-$(CONFIG_SCLP_TTY) += sclp_tty.o
obj-$(CONFIG_SCLP_CONSOLE) += sclp_con.o obj-$(CONFIG_SCLP_CONSOLE) += sclp_con.o
obj-$(CONFIG_SCLP_VT220_TTY) += sclp_vt220.o obj-$(CONFIG_SCLP_VT220_TTY) += sclp_vt220.o

View file

@ -96,8 +96,8 @@ static int sclp_init_mask(int calculate);
static int sclp_init(void); static int sclp_init(void);
/* Perform service call. Return 0 on success, non-zero otherwise. */ /* Perform service call. Return 0 on success, non-zero otherwise. */
static int int
service_call(sclp_cmdw_t command, void *sccb) sclp_service_call(sclp_cmdw_t command, void *sccb)
{ {
int cc; int cc;
@ -173,7 +173,7 @@ __sclp_start_request(struct sclp_req *req)
if (sclp_running_state != sclp_running_state_idle) if (sclp_running_state != sclp_running_state_idle)
return 0; return 0;
del_timer(&sclp_request_timer); del_timer(&sclp_request_timer);
rc = service_call(req->command, req->sccb); rc = sclp_service_call(req->command, req->sccb);
req->start_count++; req->start_count++;
if (rc == 0) { if (rc == 0) {
@ -325,7 +325,7 @@ __sclp_make_read_req(void)
sccb = (struct sccb_header *) sclp_read_sccb; sccb = (struct sccb_header *) sclp_read_sccb;
clear_page(sccb); clear_page(sccb);
memset(&sclp_read_req, 0, sizeof(struct sclp_req)); memset(&sclp_read_req, 0, sizeof(struct sclp_req));
sclp_read_req.command = SCLP_CMDW_READDATA; sclp_read_req.command = SCLP_CMDW_READ_EVENT_DATA;
sclp_read_req.status = SCLP_REQ_QUEUED; sclp_read_req.status = SCLP_REQ_QUEUED;
sclp_read_req.start_count = 0; sclp_read_req.start_count = 0;
sclp_read_req.callback = sclp_read_cb; sclp_read_req.callback = sclp_read_cb;
@ -628,7 +628,7 @@ __sclp_make_init_req(u32 receive_mask, u32 send_mask)
sccb = (struct init_sccb *) sclp_init_sccb; sccb = (struct init_sccb *) sclp_init_sccb;
clear_page(sccb); clear_page(sccb);
memset(&sclp_init_req, 0, sizeof(struct sclp_req)); memset(&sclp_init_req, 0, sizeof(struct sclp_req));
sclp_init_req.command = SCLP_CMDW_WRITEMASK; sclp_init_req.command = SCLP_CMDW_WRITE_EVENT_MASK;
sclp_init_req.status = SCLP_REQ_FILLED; sclp_init_req.status = SCLP_REQ_FILLED;
sclp_init_req.start_count = 0; sclp_init_req.start_count = 0;
sclp_init_req.callback = NULL; sclp_init_req.callback = NULL;
@ -831,7 +831,7 @@ sclp_check_interface(void)
for (retry = 0; retry <= SCLP_INIT_RETRY; retry++) { for (retry = 0; retry <= SCLP_INIT_RETRY; retry++) {
__sclp_make_init_req(0, 0); __sclp_make_init_req(0, 0);
sccb = (struct init_sccb *) sclp_init_req.sccb; sccb = (struct init_sccb *) sclp_init_req.sccb;
rc = service_call(sclp_init_req.command, sccb); rc = sclp_service_call(sclp_init_req.command, sccb);
if (rc == -EIO) if (rc == -EIO)
break; break;
sclp_init_req.status = SCLP_REQ_RUNNING; sclp_init_req.status = SCLP_REQ_RUNNING;

View file

@ -12,7 +12,7 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/list.h> #include <linux/list.h>
#include <asm/sclp.h>
#include <asm/ebcdic.h> #include <asm/ebcdic.h>
/* maximum number of pages concerning our own memory management */ /* maximum number of pages concerning our own memory management */
@ -49,9 +49,11 @@
typedef unsigned int sclp_cmdw_t; typedef unsigned int sclp_cmdw_t;
#define SCLP_CMDW_READDATA 0x00770005 #define SCLP_CMDW_READ_EVENT_DATA 0x00770005
#define SCLP_CMDW_WRITEDATA 0x00760005 #define SCLP_CMDW_WRITE_EVENT_DATA 0x00760005
#define SCLP_CMDW_WRITEMASK 0x00780005 #define SCLP_CMDW_WRITE_EVENT_MASK 0x00780005
#define SCLP_CMDW_READ_SCP_INFO 0x00020001
#define SCLP_CMDW_READ_SCP_INFO_FORCED 0x00120001
#define GDS_ID_MDSMU 0x1310 #define GDS_ID_MDSMU 0x1310
#define GDS_ID_MDSRouteInfo 0x1311 #define GDS_ID_MDSRouteInfo 0x1311
@ -66,13 +68,6 @@ typedef unsigned int sclp_cmdw_t;
typedef u32 sccb_mask_t; /* ATTENTION: assumes 32bit mask !!! */ typedef u32 sccb_mask_t; /* ATTENTION: assumes 32bit mask !!! */
struct sccb_header {
u16 length;
u8 function_code;
u8 control_mask[3];
u16 response_code;
} __attribute__((packed));
struct gds_subvector { struct gds_subvector {
u8 length; u8 length;
u8 key; u8 key;
@ -131,6 +126,7 @@ void sclp_unregister(struct sclp_register *reg);
int sclp_remove_processed(struct sccb_header *sccb); int sclp_remove_processed(struct sccb_header *sccb);
int sclp_deactivate(void); int sclp_deactivate(void);
int sclp_reactivate(void); int sclp_reactivate(void);
int sclp_service_call(sclp_cmdw_t command, void *sccb);
/* useful inlines */ /* useful inlines */

View file

@ -169,7 +169,7 @@ cpi_prepare_req(void)
} }
/* prepare request data structure presented to SCLP driver */ /* prepare request data structure presented to SCLP driver */
req->command = SCLP_CMDW_WRITEDATA; req->command = SCLP_CMDW_WRITE_EVENT_DATA;
req->sccb = sccb; req->sccb = sccb;
req->status = SCLP_REQ_FILLED; req->status = SCLP_REQ_FILLED;
req->callback = cpi_callback; req->callback = cpi_callback;

View file

@ -0,0 +1,57 @@
/*
* drivers/s390/char/sclp_info.c
*
* Copyright IBM Corp. 2007
* Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
*/
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <asm/sclp.h>
#include "sclp.h"
struct sclp_readinfo_sccb s390_readinfo_sccb;
void __init sclp_readinfo_early(void)
{
sclp_cmdw_t command;
struct sccb_header *sccb;
int ret;
__ctl_set_bit(0, 9); /* enable service signal subclass mask */
sccb = &s390_readinfo_sccb.header;
command = SCLP_CMDW_READ_SCP_INFO_FORCED;
while (1) {
u16 response;
memset(&s390_readinfo_sccb, 0, sizeof(s390_readinfo_sccb));
sccb->length = sizeof(s390_readinfo_sccb);
sccb->control_mask[2] = 0x80;
ret = sclp_service_call(command, &s390_readinfo_sccb);
if (ret == -EIO)
goto out;
if (ret == -EBUSY)
continue;
__load_psw_mask(PSW_BASE_BITS | PSW_MASK_EXT |
PSW_MASK_WAIT | PSW_DEFAULT_KEY);
local_irq_disable();
barrier();
response = sccb->response_code;
if (response == 0x10)
break;
if (response != 0x1f0 || command == SCLP_CMDW_READ_SCP_INFO)
break;
command = SCLP_CMDW_READ_SCP_INFO;
}
out:
__ctl_clear_bit(0, 9); /* disable service signal subclass mask */
}

View file

@ -460,7 +460,7 @@ sclp_emit_buffer(struct sclp_buffer *buffer,
sccb->msg_buf.header.type = EvTyp_PMsgCmd; sccb->msg_buf.header.type = EvTyp_PMsgCmd;
else else
return -ENOSYS; return -ENOSYS;
buffer->request.command = SCLP_CMDW_WRITEDATA; buffer->request.command = SCLP_CMDW_WRITE_EVENT_DATA;
buffer->request.status = SCLP_REQ_FILLED; buffer->request.status = SCLP_REQ_FILLED;
buffer->request.callback = sclp_writedata_callback; buffer->request.callback = sclp_writedata_callback;
buffer->request.callback_data = buffer; buffer->request.callback_data = buffer;

View file

@ -207,7 +207,7 @@ __sclp_vt220_emit(struct sclp_vt220_request *request)
request->sclp_req.status = SCLP_REQ_FAILED; request->sclp_req.status = SCLP_REQ_FAILED;
return -EIO; return -EIO;
} }
request->sclp_req.command = SCLP_CMDW_WRITEDATA; request->sclp_req.command = SCLP_CMDW_WRITE_EVENT_DATA;
request->sclp_req.status = SCLP_REQ_FILLED; request->sclp_req.status = SCLP_REQ_FILLED;
request->sclp_req.callback = sclp_vt220_callback; request->sclp_req.callback = sclp_vt220_callback;
request->sclp_req.callback_data = (void *) request; request->sclp_req.callback_data = (void *) request;

View file

@ -895,11 +895,11 @@ static int stsch_reset(struct subchannel_id schid, volatile struct schib *addr)
int rc; int rc;
pgm_check_occured = 0; pgm_check_occured = 0;
s390_reset_pgm_handler = cio_reset_pgm_check_handler; s390_base_pgm_handler_fn = cio_reset_pgm_check_handler;
rc = stsch(schid, addr); rc = stsch(schid, addr);
s390_reset_pgm_handler = NULL; s390_base_pgm_handler_fn = NULL;
/* The program check handler could have changed pgm_check_occured */ /* The program check handler could have changed pgm_check_occured. */
barrier(); barrier();
if (pgm_check_occured) if (pgm_check_occured)
@ -957,7 +957,7 @@ static void css_reset(void)
/* Reset subchannels. */ /* Reset subchannels. */
for_each_subchannel(__shutdown_subchannel_easy, NULL); for_each_subchannel(__shutdown_subchannel_easy, NULL);
/* Reset channel paths. */ /* Reset channel paths. */
s390_reset_mcck_handler = s390_reset_chpids_mcck_handler; s390_base_mcck_handler_fn = s390_reset_chpids_mcck_handler;
/* Enable channel report machine checks. */ /* Enable channel report machine checks. */
__ctl_set_bit(14, 28); __ctl_set_bit(14, 28);
/* Temporarily reenable machine checks. */ /* Temporarily reenable machine checks. */
@ -982,7 +982,7 @@ static void css_reset(void)
local_mcck_disable(); local_mcck_disable();
/* Disable channel report machine checks. */ /* Disable channel report machine checks. */
__ctl_clear_bit(14, 28); __ctl_clear_bit(14, 28);
s390_reset_mcck_handler = NULL; s390_base_mcck_handler_fn = NULL;
} }
static struct reset_call css_reset_call = { static struct reset_call css_reset_call = {

View file

@ -330,6 +330,18 @@ static inline void disabled_wait(unsigned long code)
#endif /* __s390x__ */ #endif /* __s390x__ */
} }
/*
* Basic Machine Check/Program Check Handler.
*/
extern void s390_base_mcck_handler(void);
extern void s390_base_pgm_handler(void);
extern void s390_base_ext_handler(void);
extern void (*s390_base_mcck_handler_fn)(void);
extern void (*s390_base_pgm_handler_fn)(void);
extern void (*s390_base_ext_handler_fn)(void);
/* /*
* CPU idle notifier chain. * CPU idle notifier chain.
*/ */

View file

@ -18,7 +18,4 @@ struct reset_call {
extern void register_reset_call(struct reset_call *reset); extern void register_reset_call(struct reset_call *reset);
extern void unregister_reset_call(struct reset_call *reset); extern void unregister_reset_call(struct reset_call *reset);
extern void s390_reset_system(void); extern void s390_reset_system(void);
extern void (*s390_reset_mcck_handler)(void);
extern void (*s390_reset_pgm_handler)(void);
#endif /* _ASM_S390_RESET_H */ #endif /* _ASM_S390_RESET_H */

39
include/asm-s390/sclp.h Normal file
View file

@ -0,0 +1,39 @@
/*
* include/asm-s390/sclp.h
*
* Copyright IBM Corp. 2007
* Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
*/
#ifndef _ASM_S390_SCLP_H
#define _ASM_S390_SCLP_H
#include <linux/types.h>
struct sccb_header {
u16 length;
u8 function_code;
u8 control_mask[3];
u16 response_code;
} __attribute__((packed));
#define LOADPARM_LEN 8
struct sclp_readinfo_sccb {
struct sccb_header header; /* 0-7 */
u16 rnmax; /* 8-9 */
u8 rnsize; /* 10 */
u8 _reserved0[24 - 11]; /* 11-23 */
u8 loadparm[LOADPARM_LEN]; /* 24-31 */
u8 _reserved1[91 - 32]; /* 32-90 */
u8 flags; /* 91 */
u8 _reserved2[100 - 92]; /* 92-99 */
u32 rnsize2; /* 100-103 */
u64 rnmax2; /* 104-111 */
u8 _reserved3[4096 - 112]; /* 112-4095 */
} __attribute__((packed, aligned(4096)));
extern struct sclp_readinfo_sccb s390_readinfo_sccb;
extern void sclp_readinfo_early(void);
#endif /* _ASM_S390_SCLP_H */