[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>
diff --git a/arch/s390/defconfig b/arch/s390/defconfig
index dbe3df4..7c621b8 100644
--- a/arch/s390/defconfig
+++ b/arch/s390/defconfig
@@ -433,7 +433,6 @@
 CONFIG_TN3215=y
 CONFIG_TN3215_CONSOLE=y
 CONFIG_CCW_CONSOLE=y
-CONFIG_SCLP=y
 CONFIG_SCLP_TTY=y
 CONFIG_SCLP_CONSOLE=y
 CONFIG_SCLP_VT220_TTY=y
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile
index 2de811a..5492d25 100644
--- a/arch/s390/kernel/Makefile
+++ b/arch/s390/kernel/Makefile
@@ -4,7 +4,7 @@
 
 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 \
 	    semaphore.o s390_ext.o debug.o irq.o ipl.o
 
diff --git a/arch/s390/kernel/base.S b/arch/s390/kernel/base.S
new file mode 100644
index 0000000..dc7e525
--- /dev/null
+++ b/arch/s390/kernel/base.S
@@ -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 */
diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c
new file mode 100644
index 0000000..40dd479
--- /dev/null
+++ b/arch/s390/kernel/early.c
@@ -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();
+}
diff --git a/arch/s390/kernel/head31.S b/arch/s390/kernel/head31.S
index b3dcdcd..453fd3b 100644
--- a/arch/s390/kernel/head31.S
+++ b/arch/s390/kernel/head31.S
@@ -58,145 +58,6 @@
 	l	%r14,.Lstartup_init-.LPG1(%r13)
 	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
 #
 # find out if we have an IEEE fpu
@@ -273,7 +134,6 @@
 	.long	0			# cr15: linkage stack operations
 .Lduct:	.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
 .Lpccsp:.long	0x00080000,0x80000000 + .Lchkcsp
 .Lpcmvpg:.long	0x00080000,0x80000000 + .Lchkmvpg
@@ -284,7 +144,9 @@
 .Lbss_bgn:  .long __bss_start
 .Lbss_end:  .long _end
 .Lparmaddr: .long PARMAREA
-.Lsccbaddr: .long .Lsccb
+.Linittu:   .long init_thread_union
+.Lstartup_init:
+	    .long startup_init
 
 	.globl ipl_schib
 ipl_schib:
@@ -300,26 +162,6 @@
 	.word 0
 
 	.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
 	.org	0x100000
 #endif
diff --git a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S
index 030a1c9..b8fec4e 100644
--- a/arch/s390/kernel/head64.S
+++ b/arch/s390/kernel/head64.S
@@ -65,162 +65,6 @@
 	brasl	%r14,startup_init
 					# set program check new psw mask
 	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
 #
 # find out if we have the MVPG instruction
@@ -324,25 +168,6 @@
 	.word 0
 
 	.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
 	.org	0x100000
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c
index 13eacce..0522595 100644
--- a/arch/s390/kernel/ipl.c
+++ b/arch/s390/kernel/ipl.c
@@ -20,14 +20,13 @@
 #include <asm/cio.h>
 #include <asm/ebcdic.h>
 #include <asm/reset.h>
+#include <asm/sclp.h>
 
 #define IPL_PARM_BLOCK_VERSION 0
-#define LOADPARM_LEN 8
 
-extern char s390_readinfo_sccb[];
-#define SCCB_VALID (*((__u16*)&s390_readinfo_sccb[6]) == 0x0010)
-#define SCCB_LOADPARM (&s390_readinfo_sccb[24])
-#define SCCB_FLAG (s390_readinfo_sccb[91])
+#define SCCB_VALID (s390_readinfo_sccb.header.response_code == 0x10)
+#define SCCB_LOADPARM (&s390_readinfo_sccb.loadparm)
+#define SCCB_FLAG (s390_readinfo_sccb.flags)
 
 enum ipl_type {
 	IPL_TYPE_NONE	 = 1,
@@ -1080,8 +1079,6 @@
 		reset->fn();
 }
 
-extern void reset_mcck_handler(void);
-extern void reset_pgm_handler(void);
 extern __u32 dump_prefix_page;
 
 void s390_reset_system(void)
@@ -1105,12 +1102,12 @@
 	/* 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;
+		PSW_ADDR_AMODE | (unsigned long) s390_base_mcck_handler;
 
 	/* Set new program check handler */
 	S390_lowcore.program_new_psw.mask = psw_kernel_bits & ~PSW_MASK_MCHECK;
 	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();
 }
diff --git a/arch/s390/kernel/reset.S b/arch/s390/kernel/reset.S
deleted file mode 100644
index 8a87355..0000000
--- a/arch/s390/kernel/reset.S
+++ /dev/null
@@ -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 */
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index 2fa866f..f73a115 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -284,140 +284,6 @@
 	}
 }
 
-/*
- * 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
 void (*_machine_restart)(char *command) = machine_restart_smp;
 void (*_machine_halt)(void) = machine_halt_smp;