mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH] 2.5.40 s390 (1/27): arch.
@ 2002-10-04 14:24 Martin Schwidefsky
  0 siblings, 0 replies; only message in thread
From: Martin Schwidefsky @ 2002-10-04 14:24 UTC (permalink / raw)
  To: linux-kernel, torvalds

s390 arch file changes for 2.5.39. 

diff -urN linux-2.5.40/arch/s390/kernel/Makefile linux-2.5.40-s390/arch/s390/kernel/Makefile
--- linux-2.5.40/arch/s390/kernel/Makefile	Tue Oct  1 09:07:43 2002
+++ linux-2.5.40-s390/arch/s390/kernel/Makefile	Fri Oct  4 16:14:27 2002
@@ -5,8 +5,8 @@
 EXTRA_TARGETS	:= head.o init_task.o
 EXTRA_AFLAGS	:= -traditional
 
-export-objs	:= debug.o ebcdic.o irq.o s390_ext.o smp.o s390_ksyms.o
-obj-y	:= entry.o bitmap.o traps.o time.o process.o irq.o \
+export-objs	:= debug.o ebcdic.o s390_ext.o smp.o s390_ksyms.o
+obj-y	:= entry.o bitmap.o traps.o time.o process.o \
             setup.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \
             semaphore.o s390fpu.o reipl.o s390_ext.o debug.o
 
diff -urN linux-2.5.40/arch/s390/kernel/entry.S linux-2.5.40-s390/arch/s390/kernel/entry.S
--- linux-2.5.40/arch/s390/kernel/entry.S	Tue Oct  1 09:06:21 2002
+++ linux-2.5.40-s390/arch/s390/kernel/entry.S	Fri Oct  4 16:14:27 2002
@@ -15,7 +15,6 @@
 #include <asm/cache.h>
 #include <asm/lowcore.h>
 #include <asm/errno.h>
-#include <asm/smp.h>
 #include <asm/ptrace.h>
 #include <asm/thread_info.h>
 
diff -urN linux-2.5.40/arch/s390/kernel/head.S linux-2.5.40-s390/arch/s390/kernel/head.S
--- linux-2.5.40/arch/s390/kernel/head.S	Tue Oct  1 09:06:26 2002
+++ linux-2.5.40-s390/arch/s390/kernel/head.S	Fri Oct  4 16:14:27 2002
@@ -653,5 +653,5 @@
 .Lstart:    .long  start_kernel
 .Lbss_bgn:  .long  __bss_start
 .Lbss_end:  .long  _end
-.Laregs:    .long  0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0
+.Laregs:    .long  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
 
diff -urN linux-2.5.40/arch/s390/kernel/init_task.c linux-2.5.40-s390/arch/s390/kernel/init_task.c
--- linux-2.5.40/arch/s390/kernel/init_task.c	Tue Oct  1 09:07:09 2002
+++ linux-2.5.40-s390/arch/s390/kernel/init_task.c	Fri Oct  4 16:14:27 2002
@@ -15,7 +15,7 @@
 
 static struct fs_struct init_fs = INIT_FS;
 static struct files_struct init_files = INIT_FILES;
-static struct signal_struct init_signals = INIT_SIGNALS;
+static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
 struct mm_struct init_mm = INIT_MM(init_mm);
 
 /*
diff -urN linux-2.5.40/arch/s390/kernel/irq.c linux-2.5.40-s390/arch/s390/kernel/irq.c
--- linux-2.5.40/arch/s390/kernel/irq.c	Tue Oct  1 09:07:00 2002
+++ linux-2.5.40-s390/arch/s390/kernel/irq.c	Thu Jan  1 01:00:00 1970
@@ -1,360 +0,0 @@
-/*
- *  arch/s390/kernel/irq.c
- *
- *  S390 version
- *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
- *    Author(s): Ingo Adlung (adlung@de.ibm.com)
- *
- *  Derived from "arch/i386/kernel/irq.c"
- *    Copyright (C) 1992, 1999 Linus Torvalds, Ingo Molnar
- *
- *  S/390 I/O interrupt processing and I/O request processing is
- *   implemented in arch/s390/kernel/s390io.c
- */
-#include <linux/module.h>
-#include <linux/config.h>
-#include <linux/ptrace.h>
-#include <linux/errno.h>
-#include <linux/kernel_stat.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/ioport.h>
-#include <linux/interrupt.h>
-#include <linux/timex.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/random.h>
-#include <linux/smp.h>
-#include <linux/threads.h>
-#include <linux/smp_lock.h>
-#include <linux/init.h>
-#include <linux/seq_file.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/bitops.h>
-#include <asm/smp.h>
-#include <asm/pgtable.h>
-#include <asm/delay.h>
-#include <asm/lowcore.h>
-
-void          s390_init_IRQ   ( void );
-void          s390_free_irq   ( unsigned int irq, void *dev_id);
-int           s390_request_irq( unsigned int irq,
-                     void           (*handler)(int, void *, struct pt_regs *),
-                     unsigned long  irqflags,
-                     const char    *devname,
-                     void          *dev_id);
-
-#if 0
-/*
- * The following vectors are part of the Linux architecture, there
- * is no hardware IRQ pin equivalent for them, they are triggered
- * through the ICC by us (IPIs), via smp_message_pass():
- */
-BUILD_SMP_INTERRUPT(reschedule_interrupt)
-BUILD_SMP_INTERRUPT(invalidate_interrupt)
-BUILD_SMP_INTERRUPT(stop_cpu_interrupt)
-BUILD_SMP_INTERRUPT(mtrr_interrupt)
-BUILD_SMP_INTERRUPT(spurious_interrupt)
-#endif
-
-int show_interrupts(struct seq_file *p, void *v)
-{
-	int i, j;
-
-	seq_puts(p, "           ");
-
-	for (j=0; j<smp_num_cpus; j++)
-		seq_printf(p, "CPU%d       ",j);
-
-	seq_putc(p, '\n');
-
-	for (i = 0 ; i < NR_IRQS ; i++) {
-		if (ioinfo[i] == INVALID_STORAGE_AREA)
-			continue;
-
-		seq_printf(p, "%3d: ",i);
-		seq_printf(p, "  %s", ioinfo[i]->irq_desc.name);
-
-		seq_putc(p, '\n');
-	
-	} /* endfor */
-
-	return 0;
-}
-
-/*
- * Global interrupt locks for SMP. Allow interrupts to come in on any
- * CPU, yet make cli/sti act globally to protect critical regions..
- */
-#ifdef CONFIG_SMP
-atomic_t global_irq_holder = ATOMIC_INIT(NO_PROC_ID);
-atomic_t global_irq_lock = ATOMIC_INIT(0);
-atomic_t global_irq_count = ATOMIC_INIT(0);
-atomic_t global_bh_count;
-
-/*
- * "global_cli()" is a special case, in that it can hold the
- * interrupts disabled for a longish time, and also because
- * we may be doing TLB invalidates when holding the global
- * IRQ lock for historical reasons. Thus we may need to check
- * SMP invalidate events specially by hand here (but not in
- * any normal spinlocks)
- *
- * Thankfully we don't need this as we can deliver flush tlbs with
- * interrupts disabled DJB :-)
- */
-#define check_smp_invalidate(cpu)
-
-extern void show_stack(unsigned long* esp);
-
-static void show(char * str)
-{
-	int cpu = smp_processor_id();
-
-	printk("\n%s, CPU %d:\n", str, cpu);
-	printk("irq:  %d [%d]\n",
-	       atomic_read(&global_irq_count),local_irq_count(smp_processor_id()));
-	printk("bh:   %d [%d]\n",
-	       atomic_read(&global_bh_count),local_bh_count(smp_processor_id()));
-	show_stack(NULL);
-}
-
-#define MAXCOUNT 100000000
-
-static inline void wait_on_bh(void)
-{
-	int count = MAXCOUNT;
-	do {
-		if (!--count) {
-			show("wait_on_bh");
-			count = ~0;
-		}
-		/* nothing .. wait for the other bh's to go away */
-	} while (atomic_read(&global_bh_count) != 0);
-}
-
-static inline void wait_on_irq(int cpu)
-{
-	int count = MAXCOUNT;
-
-	for (;;) {
-
-		/*
-		 * Wait until all interrupts are gone. Wait
-		 * for bottom half handlers unless we're
-		 * already executing in one..
-		 */
-		if (!atomic_read(&global_irq_count)) {
-			if (local_bh_count(cpu)||
-			    !atomic_read(&global_bh_count))
-				break;
-		}
-
-		/* Duh, we have to loop. Release the lock to avoid deadlocks */
-		atomic_set(&global_irq_lock, 0);
-
-		for (;;) {
-			if (!--count) {
-				show("wait_on_irq");
-				count = ~0;
-			}
-			local_irq_enable();
-			SYNC_OTHER_CORES(cpu);
-			local_irq_disable();
-			check_smp_invalidate(cpu);
-			if (atomic_read(&global_irq_count))
-				continue;
-			if (atomic_read(&global_irq_lock))
-				continue;
-			if (!local_bh_count(cpu)
-			    && atomic_read(&global_bh_count))
-				continue;
-			if (!atomic_compare_and_swap(0, 1, &global_irq_lock))
-				 break;
-		}
-	}
-}
-
-/*
- * This is called when we want to synchronize with
- * bottom half handlers. We need to wait until
- * no other CPU is executing any bottom half handler.
- *
- * Don't wait if we're already running in an interrupt
- * context or are inside a bh handler.
- */
-void synchronize_bh(void)
-{
-	if (atomic_read(&global_bh_count) && !in_interrupt())
-		wait_on_bh();
-}
-
-/*
- * This is called when we want to synchronize with
- * interrupts. We may for example tell a device to
- * stop sending interrupts: but to make sure there
- * are no interrupts that are executing on another
- * CPU we need to call this function.
- */
-void synchronize_irq(void)
-{
-	if (atomic_read(&global_irq_count)) {
-		/* Stupid approach */
-		cli();
-		sti();
-	}
-}
-
-static inline void get_irqlock(int cpu)
-{
-	if (atomic_compare_and_swap(0, 1, &global_irq_lock) != 0) {
-		/* do we already hold the lock? */
-		if ( cpu == atomic_read(&global_irq_holder))
-			return;
-		/* Uhhuh.. Somebody else got it. Wait.. */
-		do {
-			check_smp_invalidate(cpu);
-		} while (atomic_compare_and_swap(0, 1, &global_irq_lock) != 0);
-	}
-	/*
-	 * We also to make sure that nobody else is running
-	 * in an interrupt context.
-	 */
-	wait_on_irq(cpu);
-
-	/*
-	 * Ok, finally..
-	 */
-	atomic_set(&global_irq_holder,cpu);
-}
-
-#define EFLAGS_I_SHIFT 25
-
-/*
- * A global "cli()" while in an interrupt context
- * turns into just a local cli(). Interrupts
- * should use spinlocks for the (very unlikely)
- * case that they ever want to protect against
- * each other.
- *
- * If we already have local interrupts disabled,
- * this will not turn a local disable into a
- * global one (problems with spinlocks: this makes
- * save_flags+cli+sti usable inside a spinlock).
- */
-void __global_cli(void)
-{
-	unsigned long flags;
-
-	local_save_flags(flags);
-	if (flags & (1 << EFLAGS_I_SHIFT)) {
-		int cpu = smp_processor_id();
-		local_irq_disable();
-		if (!in_irq())
-			get_irqlock(cpu);
-	}
-}
-
-void __global_sti(void)
-{
-
-	if (!in_irq())
-		release_irqlock(smp_processor_id());
-	local_irq_enable();
-}
-
-/*
- * SMP flags value to restore to:
- * 0 - global cli
- * 1 - global sti
- * 2 - local cli
- * 3 - local sti
- */
-unsigned long __global_save_flags(void)
-{
-	int retval;
-	int local_enabled;
-	unsigned long flags;
-
-	local_save_flags(flags);
-	local_enabled = (flags >> EFLAGS_I_SHIFT) & 1;
-	/* default to local */
-	retval = 2 + local_enabled;
-
-	/* check for global flags if we're not in an interrupt */
-	if (!in_irq())
-	{
-		if (local_enabled)
-			retval = 1;
-		if (atomic_read(&global_irq_holder)== smp_processor_id())
-			retval = 0;
-	}
-	return retval;
-}
-
-void __global_restore_flags(unsigned long flags)
-{
-	switch (flags) {
-	case 0:
-		__global_cli();
-		break;
-	case 1:
-		__global_sti();
-		break;
-	case 2:
-		local_irq_disable();
-		break;
-	case 3:
-		local_irq_enable();
-		break;
-	default:
-		printk("global_restore_flags: %08lx (%08lx)\n",
-		       flags, (&flags)[-1]);
-	}
-}
-
-#endif
-
-
-void __init init_IRQ(void)
-{
-        s390_init_IRQ();
-}
-
-
-void free_irq(unsigned int irq, void *dev_id)
-{
-   s390_free_irq( irq, dev_id);
-}
-
-
-int request_irq( unsigned int   irq,
-                 void           (*handler)(int, void *, struct pt_regs *),
-                 unsigned long  irqflags,
-                 const char    *devname,
-                 void          *dev_id)
-{
-   return( s390_request_irq( irq, handler, irqflags, devname, dev_id ) );
-
-}
-
-void init_irq_proc(void)
-{
-        /* For now, nothing... */
-}
-
-#ifdef CONFIG_SMP
-EXPORT_SYMBOL(__global_cli);
-EXPORT_SYMBOL(__global_sti);
-EXPORT_SYMBOL(__global_save_flags);
-EXPORT_SYMBOL(__global_restore_flags);
-EXPORT_SYMBOL(global_irq_holder);
-EXPORT_SYMBOL(global_irq_lock);
-EXPORT_SYMBOL(global_irq_count);
-EXPORT_SYMBOL(global_bh_count);
-#endif
-
-EXPORT_SYMBOL(global_bh_lock);
diff -urN linux-2.5.40/arch/s390/kernel/process.c linux-2.5.40-s390/arch/s390/kernel/process.c
--- linux-2.5.40/arch/s390/kernel/process.c	Tue Oct  1 09:07:34 2002
+++ linux-2.5.40-s390/arch/s390/kernel/process.c	Fri Oct  4 16:14:28 2002
@@ -15,9 +15,6 @@
  * This file handles the architecture-dependent parts of process handling..
  */
 
-#define __KERNEL_SYSCALLS__
-#include <stdarg.h>
-
 #include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
@@ -121,31 +118,35 @@
 		show_trace((unsigned long *) regs->gprs[15]);
 }
 
+extern void kernel_thread_starter(void);
+__asm__(".align 4\n"
+	"kernel_thread_starter:\n"
+	"    l     15,0(8)\n"
+	"    sr    15,7\n"
+	"    stosm 24(15),3\n"
+	"    lr    2,10\n"
+	"    basr  14,9\n"
+	"    sr    2,2\n"
+	"    br    11\n");
+
 int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
 {
-        int clone_arg = flags | CLONE_VM;
-        int retval;
+	struct task_struct *p;
+	struct pt_regs regs;
 
-        __asm__ __volatile__(
-                "     sr    2,2\n"
-                "     lr    3,%1\n"
-                "     l     4,%6\n"     /* load kernel stack ptr of parent */
-                "     svc   %b2\n"                     /* Linux system call*/
-                "     cl    4,%6\n"    /* compare ksp's: child or parent ? */
-                "     je    0f\n"                          /* parent - jump*/
-                "     l     15,%6\n"            /* fix kernel stack pointer*/
-                "     ahi   15,%7\n"
-                "     xc    0(96,15),0(15)\n"           /* clear save area */
-                "     lr    2,%4\n"                        /* load argument*/
-                "     lr    14,%5\n"                      /* get fn-pointer*/
-                "     basr  14,14\n"                             /* call fn*/
-                "     svc   %b3\n"                     /* Linux system call*/
-                "0:   lr    %0,2"
-                : "=a" (retval)
-                : "d" (clone_arg), "i" (__NR_clone), "i" (__NR_exit),
-                  "d" (arg), "d" (fn), "i" (__LC_KERNEL_STACK) , "i" (-STACK_FRAME_OVERHEAD)
-                : "2", "3", "4" );
-        return retval;
+	memset(&regs, 0, sizeof(regs));
+	regs.psw.mask = _SVC_PSW_MASK;
+	regs.psw.addr = (__u32) kernel_thread_starter | _ADDR_31;
+	regs.gprs[7] = STACK_FRAME_OVERHEAD;
+	regs.gprs[8] = __LC_KERNEL_STACK;
+	regs.gprs[9] = (unsigned long) fn;
+	regs.gprs[10] = (unsigned long) arg;
+	regs.gprs[11] = (unsigned long) do_exit;
+	regs.orig_gpr2 = -1;
+
+	/* Ok, create the new process.. */
+	p = do_fork(flags | CLONE_VM, 0, &regs, 0, NULL);
+	return IS_ERR(p) ? PTR_ERR(p) : p->pid;
 }
 
 /*
@@ -186,12 +187,13 @@
         frame = ((struct stack_frame *)
 		 (THREAD_SIZE + (unsigned long) p->thread_info)) - 1;
         p->thread.ksp = (unsigned long) frame;
-        memcpy(&frame->childregs,regs,sizeof(struct pt_regs));
+        frame->childregs = *regs;
+	frame->childregs.gprs[2] = 0;	/* child returns 0 on fork. */
         frame->childregs.gprs[15] = new_stackp;
         frame->back_chain = frame->eos = 0;
 
-        /* new return point is ret_from_sys_call */
-        frame->gprs[8] = ((unsigned long) &ret_from_fork) | 0x80000000;
+        /* new return point is ret_from_fork */
+        frame->gprs[8] = (unsigned long) ret_from_fork;
 	/* start disabled because of schedule_tick and rq->lock being held */
 	frame->childregs.psw.mask &= ~0x03000000;
 
@@ -200,6 +202,8 @@
         /* save fprs, if used in last task */
 	save_fp_regs(&p->thread.fp_regs);
         p->thread.user_seg = __pa((unsigned long) p->mm->pgd) | _SEGMENT_TABLE;
+	/* start process with ar4 pointing to the correct address space */
+	p->thread.ar4 = get_fs().ar4;
         /* Don't copy debug registers */
         memset(&p->thread.per_info,0,sizeof(p->thread.per_info));
         return 0;
@@ -208,7 +212,7 @@
 asmlinkage int sys_fork(struct pt_regs regs)
 {
 	struct task_struct *p;
-        p = do_fork(SIGCHLD, regs.gprs[15], &regs, 0);
+        p = do_fork(SIGCHLD, regs.gprs[15], &regs, 0, NULL);
 	return IS_ERR(p) ? PTR_ERR(p) : p->pid;
 }
 
@@ -217,12 +221,14 @@
         unsigned long clone_flags;
         unsigned long newsp;
 	struct task_struct *p;
+	int *user_tid;
 
         clone_flags = regs.gprs[3];
         newsp = regs.orig_gpr2;
+	user_tid = (int *) regs.gprs[4];
         if (!newsp)
                 newsp = regs.gprs[15];
-        p = do_fork(clone_flags & ~CLONE_IDLETASK, newsp, &regs, 0);
+        p = do_fork(clone_flags & ~CLONE_IDLETASK, newsp, &regs, 0, user_tid);
 	return IS_ERR(p) ? PTR_ERR(p) : p->pid;
 }
 
@@ -239,7 +245,8 @@
 asmlinkage int sys_vfork(struct pt_regs regs)
 {
 	struct task_struct *p;
-	p = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.gprs[15], &regs, 0);
+	p = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD,
+		    regs.gprs[15], &regs, 0, NULL);
 	return IS_ERR(p) ? PTR_ERR(p) : p->pid;
 }
 
diff -urN linux-2.5.40/arch/s390/kernel/setup.c linux-2.5.40-s390/arch/s390/kernel/setup.c
--- linux-2.5.40/arch/s390/kernel/setup.c	Tue Oct  1 09:06:17 2002
+++ linux-2.5.40-s390/arch/s390/kernel/setup.c	Fri Oct  4 16:14:28 2002
@@ -524,7 +524,7 @@
 		seq_printf(m, "vendor_id       : IBM/S390\n"
 			       "# processors    : %i\n"
 			       "bogomips per cpu: %lu.%02lu\n",
-			       smp_num_cpus, loops_per_jiffy/(500000/HZ),
+			       num_online_cpus(), loops_per_jiffy/(500000/HZ),
 			       (loops_per_jiffy/(5000/HZ))%100);
 	}
 	if (cpu_online_map & (1 << n)) {
diff -urN linux-2.5.40/arch/s390/kernel/signal.c linux-2.5.40-s390/arch/s390/kernel/signal.c
--- linux-2.5.40/arch/s390/kernel/signal.c	Tue Oct  1 09:06:25 2002
+++ linux-2.5.40-s390/arch/s390/kernel/signal.c	Fri Oct  4 16:14:28 2002
@@ -60,11 +60,11 @@
 	sigset_t saveset;
 
 	mask &= _BLOCKABLE;
-	spin_lock_irq(&current->sigmask_lock);
+	spin_lock_irq(&current->sig->siglock);
 	saveset = current->blocked;
 	siginitset(&current->blocked, mask);
 	recalc_sigpending();
-	spin_unlock_irq(&current->sigmask_lock);
+	spin_unlock_irq(&current->sig->siglock);
 	regs->gprs[2] = -EINTR;
 
 	while (1) {
@@ -88,11 +88,11 @@
 		return -EFAULT;
 	sigdelsetmask(&newset, ~_BLOCKABLE);
 
-	spin_lock_irq(&current->sigmask_lock);
+	spin_lock_irq(&current->sig->siglock);
 	saveset = current->blocked;
 	current->blocked = newset;
 	recalc_sigpending();
-	spin_unlock_irq(&current->sigmask_lock);
+	spin_unlock_irq(&current->sig->siglock);
 	regs->gprs[2] = -EINTR;
 
 	while (1) {
@@ -191,10 +191,10 @@
 		goto badframe;
 
 	sigdelsetmask(&set, ~_BLOCKABLE);
-	spin_lock_irq(&current->sigmask_lock);
+	spin_lock_irq(&current->sig->siglock);
 	current->blocked = set;
 	recalc_sigpending();
-	spin_unlock_irq(&current->sigmask_lock);
+	spin_unlock_irq(&current->sig->siglock);
 
 	if (restore_sigregs(regs, &frame->sregs))
 		goto badframe;
@@ -217,10 +217,10 @@
 		goto badframe;
 
 	sigdelsetmask(&set, ~_BLOCKABLE);
-	spin_lock_irq(&current->sigmask_lock);
+	spin_lock_irq(&current->sig->siglock);
 	current->blocked = set;
 	recalc_sigpending();
-	spin_unlock_irq(&current->sigmask_lock);
+	spin_unlock_irq(&current->sig->siglock);
 
 	if (restore_sigregs(regs, &frame->uc.uc_mcontext))
 		goto badframe;
@@ -420,11 +420,11 @@
 		ka->sa.sa_handler = SIG_DFL;
 
 	if (!(ka->sa.sa_flags & SA_NODEFER)) {
-		spin_lock_irq(&current->sigmask_lock);
+		spin_lock_irq(&current->sig->siglock);
 		sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
 		sigaddset(&current->blocked,sig);
 		recalc_sigpending();
-		spin_unlock_irq(&current->sigmask_lock);
+		spin_unlock_irq(&current->sig->siglock);
 	}
 }
 
diff -urN linux-2.5.40/arch/s390/kernel/smp.c linux-2.5.40-s390/arch/s390/kernel/smp.c
--- linux-2.5.40/arch/s390/kernel/smp.c	Tue Oct  1 09:05:47 2002
+++ linux-2.5.40-s390/arch/s390/kernel/smp.c	Fri Oct  4 16:14:28 2002
@@ -47,45 +47,16 @@
 /*
  * An array with a pointer the lowcore of every CPU.
  */
-static int       max_cpus = NR_CPUS;	  /* Setup configured maximum number of CPUs to activate	*/
-int              smp_num_cpus;
+
 struct _lowcore *lowcore_ptr[NR_CPUS];
 cycles_t         cacheflush_time=0;
 int              smp_threads_ready=0;      /* Set when the idlers are all forked. */
-static atomic_t  smp_commenced = ATOMIC_INIT(0);
 
-volatile unsigned long phys_cpu_present_map;
 volatile unsigned long cpu_online_map;
+volatile unsigned long cpu_possible_map;
 unsigned long    cache_decay_ticks = 0;
 
 /*
- *      Setup routine for controlling SMP activation
- *
- *      Command-line option of "nosmp" or "maxcpus=0" will disable SMP
- *      activation entirely (the MPS table probe still happens, though).
- *
- *      Command-line option of "maxcpus=<NUM>", where <NUM> is an integer
- *      greater than 0, limits the maximum number of CPUs activated in
- *      SMP mode to <NUM>.
- */
-
-static int __init nosmp(char *str)
-{
-	max_cpus = 0;
-	return 1;
-}
-
-__setup("nosmp", nosmp);
-
-static int __init maxcpus(char *str)
-{
-	get_option(&str, &max_cpus);
-	return 1;
-}
-
-__setup("maxcpus=", maxcpus);
-
-/*
  * Reboot, halt and power_off routines for SMP.
  */
 extern char vmhalt_cmd[];
@@ -148,9 +119,10 @@
  */
 {
 	struct call_data_struct data;
-	int cpus = smp_num_cpus-1;
+	int cpus = num_online_cpus()-1;
 
-	if (!cpus || !atomic_read(&smp_commenced))
+	/* FIXME: get cpu lock -hc */
+	if (cpus <= 0)
 		return 0;
 
 	data.func = func;
@@ -183,8 +155,8 @@
         int i, rc;
 
         /* stop all processors */
-        for (i =  0; i < smp_num_cpus; i++) {
-                if (smp_processor_id() == i)
+        for (i =  0; i < NR_CPUS; i++) {
+                if (!cpu_online(i) || smp_processor_id() == i)
 			continue;
 		do {
 			rc = signal_processor_ps(&dummy, 0, i, sigp_stop);
@@ -199,8 +171,8 @@
         int i, rc;
 
         /* store status of all processors in their lowcores (real 0) */
-        for (i =  0; i < smp_num_cpus; i++) {
-                if (smp_processor_id() == i)
+        for (i =  0; i < NR_CPUS; i++) {
+                if (!cpu_online(i) || smp_processor_id() == i)
 			continue;
 		low_core_addr = (unsigned long)get_cpu_lowcore(i);
 		do {
@@ -345,8 +317,8 @@
         struct _lowcore *lowcore;
         int i;
 
-        for (i = 0; i < smp_num_cpus; i++) {
-                if (smp_processor_id() == i)
+        for (i = 0; i < NR_CPUS; i++) {
+                if (!cpu_online(i) || smp_processor_id() == i)
                         continue;
                 lowcore = get_cpu_lowcore(i);
                 /*
@@ -425,13 +397,11 @@
 void smp_ctl_set_bit(int cr, int bit) {
         ec_creg_mask_parms parms;
 
-        if (atomic_read(&smp_commenced) != 0) {
-                parms.start_ctl = cr;
-                parms.end_ctl = cr;
-                parms.orvals[cr] = 1 << bit;
-                parms.andvals[cr] = 0xFFFFFFFF;
-                smp_call_function(smp_ctl_bit_callback, &parms, 0, 1);
-        }
+	parms.start_ctl = cr;
+	parms.end_ctl = cr;
+	parms.orvals[cr] = 1 << bit;
+	parms.andvals[cr] = 0xFFFFFFFF;
+	smp_call_function(smp_ctl_bit_callback, &parms, 0, 1);
         __ctl_set_bit(cr, bit);
 }
 
@@ -441,13 +411,11 @@
 void smp_ctl_clear_bit(int cr, int bit) {
         ec_creg_mask_parms parms;
 
-        if (atomic_read(&smp_commenced) != 0) {
-                parms.start_ctl = cr;
-                parms.end_ctl = cr;
-                parms.orvals[cr] = 0x00000000;
-                parms.andvals[cr] = ~(1 << bit);
-                smp_call_function(smp_ctl_bit_callback, &parms, 0, 1);
-        }
+	parms.start_ctl = cr;
+	parms.end_ctl = cr;
+	parms.orvals[cr] = 0x00000000;
+	parms.andvals[cr] = ~(1 << bit);
+	smp_call_function(smp_ctl_bit_callback, &parms, 0, 1);
         __ctl_clear_bit(cr, bit);
 }
 
@@ -455,30 +423,30 @@
  * Lets check how many CPUs we have.
  */
 
-void smp_count_cpus(void)
+void __init smp_check_cpus(unsigned int max_cpus)
 {
-        int curr_cpu;
+        int curr_cpu, num_cpus;
 
+	boot_cpu_addr = S390_lowcore.cpu_data.cpu_addr;
         current_thread_info()->cpu = 0;
-        smp_num_cpus = 1;
-	phys_cpu_present_map = 1;
+        num_cpus = 1;
+	cpu_possible_map = 1;
 	cpu_online_map = 1;
         for (curr_cpu = 0;
-             curr_cpu <= 65535 && smp_num_cpus < max_cpus; curr_cpu++) {
+             curr_cpu <= 65535 && num_cpus < max_cpus; curr_cpu++) {
                 if ((__u16) curr_cpu == boot_cpu_addr)
                         continue;
-                __cpu_logical_map[smp_num_cpus] = (__u16) curr_cpu;
-                if (signal_processor(smp_num_cpus, sigp_sense) ==
+                __cpu_logical_map[num_cpus] = (__u16) curr_cpu;
+                if (signal_processor(num_cpus, sigp_sense) ==
                     sigp_not_operational)
                         continue;
-		set_bit(smp_num_cpus, &phys_cpu_present_map);
-                smp_num_cpus++;
+		set_bit(num_cpus, &cpu_possible_map);
+                num_cpus++;
         }
-        printk("Detected %d CPU's\n",(int) smp_num_cpus);
+        printk("Detected %d CPU's\n",(int) num_cpus);
         printk("Boot cpu address %2X\n", boot_cpu_addr);
 }
 
-
 /*
  *      Activate a secondary processor.
  */
@@ -490,19 +458,18 @@
 {
         /* Setup the cpu */
         cpu_init();
-	/* Mark this cpu as online */
-	set_bit(smp_processor_id(), &cpu_online_map);
-        /* Print info about this processor */
-        print_cpu_info(&safe_get_cpu_lowcore(smp_processor_id())->cpu_data);
-        /* Wait for completion of smp startup */
-        while (!atomic_read(&smp_commenced))
-                /* nothing */ ;
         /* init per CPU timer */
         init_cpu_timer();
 #ifdef CONFIG_PFAULT
 	/* Enable pfault pseudo page faults on this cpu. */
 	pfault_init();
 #endif
+	/* Mark this cpu as online */
+	set_bit(smp_processor_id(), &cpu_online_map);
+	/* Switch on interrupts */
+	local_irq_enable();
+        /* Print info about this processor */
+        print_cpu_info(&S390_lowcore.cpu_data);
         /* cpu_idle will call schedule for us */
         return cpu_idle(NULL);
 }
@@ -513,19 +480,36 @@
        /* don't care about the psw and regs settings since we'll never
           reschedule the forked task. */
        memset(&regs,0,sizeof(struct pt_regs));
-       return do_fork(CLONE_VM|CLONE_IDLETASK, 0, &regs, 0);
+       return do_fork(CLONE_VM|CLONE_IDLETASK, 0, &regs, 0, NULL);
 }
 
-static void __init do_boot_cpu(int cpu)
+int __cpu_up(unsigned int cpu)
 {
         struct task_struct *idle;
         struct _lowcore    *cpu_lowcore;
+        sigp_ccode          ccode;
+
+	/*
+	 *  Set prefix page for new cpu
+	 */
+
+	ccode = signal_processor_p((u32)(lowcore_ptr[cpu]),
+				   cpu, sigp_set_prefix);
+	if (ccode){
+		printk("sigp_set_prefix failed for cpu %d "
+		       "with condition code %d\n",
+		       (int) cpu, (int) ccode);
+		return -EIO;
+	}
+
 
         /* We can't use kernel_thread since we must _avoid_ to reschedule
            the child. */
         idle = fork_by_hand();
-	if (IS_ERR(idle))
-                panic("failed fork for CPU %d", cpu);
+	if (IS_ERR(idle)){
+                printk("failed fork for CPU %d", cpu);
+		return -EIO;
+	}
 
         /*
          * We remove it from the pidhash and the runqueue
@@ -537,7 +521,7 @@
 
         cpu_lowcore = get_cpu_lowcore(cpu);
 	cpu_lowcore->save_area[15] = idle->thread.ksp;
-	cpu_lowcore->kernel_stack = (__u32) idle->thread_info + 8192;
+	cpu_lowcore->kernel_stack = (__u32) idle->thread_info + (2*PAGE_SIZE);
         __asm__ __volatile__("la    1,%0\n\t"
 			     "stctl 0,15,0(1)\n\t"
 			     "la    1,%1\n\t"
@@ -548,48 +532,34 @@
 
         eieio();
         signal_processor(cpu,sigp_restart);
-}
-
-/*
- *      Architecture specific routine called by the kernel just before init is
- *      fired off. This allows the BP to have everything in order [we hope].
- *      At the end of this all the APs will hit the system scheduling and off
- *      we go. Each AP will load the system gdt's and jump through the kernel
- *      init into idle(). At this point the scheduler will one day take over
- *      and give them jobs to do. smp_callin is a standard routine
- *      we use to track CPUs as they power up.
- */
 
-void __init smp_commence(void)
-{
-        /*
-         *      Lets the callins below out of their loop.
-         */
-        atomic_set(&smp_commenced,1);
+	while (!cpu_online(cpu));
+	return 0;
 }
 
 /*
- *	Cycle through the processors sending sigp_restart to boot each.
+ *	Cycle through the processors and setup structures.
  */
 
-void __init smp_boot_cpus(void)
+void __init smp_prepare_cpus(unsigned int max_cpus)
 {
 	unsigned long async_stack;
-        sigp_ccode   ccode;
         int i;
 
         /* request the 0x1202 external interrupt */
         if (register_external_interrupt(0x1202, do_ext_call_interrupt) != 0)
                 panic("Couldn't request external interrupt 0x1202");
-        smp_count_cpus();
+        smp_check_cpus(max_cpus);
         memset(lowcore_ptr,0,sizeof(lowcore_ptr));  
-        
+
         /*
-         *      Initialize the logical to physical CPU number mapping
+         *  Initialize prefix pages and stacks for all possible cpus
          */
         print_cpu_info(&safe_get_cpu_lowcore(0)->cpu_data);
 
-        for(i = 0; i < smp_num_cpus; i++) {
+        for(i = 0; i < NR_CPUS; i++) {
+		if (!cpu_possible(i))
+			continue;
 		lowcore_ptr[i] = (struct _lowcore *)
 			__get_free_page(GFP_KERNEL|GFP_DMA);
 		async_stack = __get_free_pages(GFP_KERNEL,1);
@@ -598,26 +568,12 @@
 
                 memcpy(lowcore_ptr[i], &S390_lowcore, sizeof(struct _lowcore));
 		lowcore_ptr[i]->async_stack = async_stack + (2 * PAGE_SIZE);
-                /*
-                 * Most of the parameters are set up when the cpu is
-                 * started up.
-                 */
-		if (smp_processor_id() == i) {
-			set_prefix((u32) lowcore_ptr[i]);
-			continue;
-		}
-		ccode = signal_processor_p((u32)(lowcore_ptr[i]),
-					   i, sigp_set_prefix);
-		if (ccode)
-			panic("sigp_set_prefix failed for cpu %d "
-			      "with condition code %d\n",
-			      (int) i, (int) ccode);
-		do_boot_cpu(i);
 	}
-	/*
-	 * Now wait until all of the cpus are online.
-	 */
-	while (phys_cpu_present_map != cpu_online_map);
+	set_prefix((u32) lowcore_ptr[smp_processor_id()]);
+}
+
+void smp_cpus_done(unsigned int max_cpus)
+{
 }
 
 /*
@@ -634,5 +590,4 @@
 EXPORT_SYMBOL(lowcore_ptr);
 EXPORT_SYMBOL(smp_ctl_set_bit);
 EXPORT_SYMBOL(smp_ctl_clear_bit);
-EXPORT_SYMBOL(smp_num_cpus);
 EXPORT_SYMBOL(smp_call_function);
diff -urN linux-2.5.40/arch/s390/kernel/time.c linux-2.5.40-s390/arch/s390/kernel/time.c
--- linux-2.5.40/arch/s390/kernel/time.c	Tue Oct  1 09:05:47 2002
+++ linux-2.5.40-s390/arch/s390/kernel/time.c	Fri Oct  4 16:14:28 2002
@@ -27,6 +27,7 @@
 #include <asm/uaccess.h>
 #include <asm/delay.h>
 #include <asm/s390_ext.h>
+#include <asm/div64.h>
 
 #include <linux/timex.h>
 #include <linux/config.h>
@@ -47,45 +48,22 @@
 extern rwlock_t xtime_lock;
 extern unsigned long wall_jiffies;
 
-void tod_to_timeval(__u64 todval, struct timeval *xtime)
+void tod_to_timeval(__u64 todval, struct timespec *xtime)
 {
-        const int high_bit = 0x80000000L;
-        const int c_f4240 = 0xf4240L;
-        const int c_7a120 = 0x7a120;
-	/* We have to divide the 64 bit value todval by 4096
-	 * (because the 2^12 bit is the one that changes every 
-         * microsecond) and then split it into seconds and
-         * microseconds. A value of max (2^52-1) divided by
-         * the value 0xF4240 can yield a max result of approx
-         * (2^32.068). Thats to big to fit into a signed int
-	 *   ... hacking time!
-         */
-	asm volatile ("L     2,%1\n\t"
-		      "LR    3,2\n\t"
-		      "SRL   2,12\n\t"
-		      "SLL   3,20\n\t"
-		      "L     4,%O1+4(%R1)\n\t"
-		      "SRL   4,12\n\t"
-		      "OR    3,4\n\t"  /* now R2/R3 contain (todval >> 12) */
-		      "SR    4,4\n\t"
-		      "CL    2,%2\n\t"
-		      "JL    .+12\n\t"
-		      "S     2,%2\n\t"
-		      "L     4,%3\n\t"
-                      "D     2,%4\n\t"
-		      "OR    3,4\n\t"
-		      "ST    2,%O0+4(%R0)\n\t"
-		      "ST    3,%0"
-		      : "=m" (*xtime) : "m" (todval),
-		        "m" (c_7a120), "m" (high_bit), "m" (c_f4240)
-		      : "cc", "memory", "2", "3", "4" );
+	unsigned long long sec;
+
+	sec = todval >> 12;
+	do_div(sec, 1000000);
+	xtime->tv_sec = sec;
+	todval -= (sec * 1000000) << 12;
+	xtime->tv_nsec = ((todval * 1000) >> 12);
 }
 
 static inline unsigned long do_gettimeoffset(void) 
 {
 	__u64 now;
 
-	asm ("STCK 0(%0)" : : "a" (&now) : "memory", "cc");
+	asm volatile ("STCK 0(%0)" : : "a" (&now) : "memory", "cc");
         now = (now - init_timer_cc) >> 12;
 	/* We require the offset from the latest update of xtime */
 	now -= (__u64) wall_jiffies*USECS_PER_JIFFY;
@@ -102,7 +80,7 @@
 
 	read_lock_irqsave(&xtime_lock, flags);
 	sec = xtime.tv_sec;
-	usec = xtime.tv_usec + do_gettimeoffset();
+	usec = xtime.tv_nsec / 1000 + do_gettimeoffset();
 	read_unlock_irqrestore(&xtime_lock, flags);
 
 	while (usec >= 1000000) {
@@ -118,7 +96,7 @@
 {
 
 	write_lock_irq(&xtime_lock);
-	/* This is revolting. We need to set the xtime.tv_usec
+	/* This is revolting. We need to set the xtime.tv_nsec
 	 * correctly. However, the value in this location is
 	 * is value at the last tick.
 	 * Discover what correction gettimeofday
@@ -131,7 +109,8 @@
 		tv->tv_sec--;
 	}
 
-	xtime = *tv;
+	xtime.tv_sec = tv->tv_sec;
+	xtime.tv_nsec = tv->tv_usec * 1000;
 	time_adjust = 0;		/* stop active adjtime() */
 	time_status |= STA_UNSYNC;
 	time_maxerror = NTP_PHASE_LIMIT;
@@ -152,7 +131,7 @@
 {
 	int cpu = smp_processor_id();
 
-	irq_enter(cpu, 0);
+	irq_enter();
 
 	/*
 	 * set clock comparator for next tick
@@ -174,7 +153,7 @@
 	do_timer(regs);
 #endif
 
-	irq_exit(cpu, 0);
+	irq_exit();
 }
 
 /*
diff -urN linux-2.5.40/arch/s390/kernel/traps.c linux-2.5.40-s390/arch/s390/kernel/traps.c
--- linux-2.5.40/arch/s390/kernel/traps.c	Tue Oct  1 09:06:29 2002
+++ linux-2.5.40-s390/arch/s390/kernel/traps.c	Fri Oct  4 16:14:28 2002
@@ -170,6 +170,14 @@
 	show_trace(sp);
 }
 
+/*
+ * The architecture-independent dump_stack generator
+ */
+void dump_stack(void)
+{
+	show_stack(0);
+}
+
 void show_registers(struct pt_regs *regs)
 {
 	mm_segment_t old_fs;
diff -urN linux-2.5.40/arch/s390/mm/fault.c linux-2.5.40-s390/arch/s390/mm/fault.c
--- linux-2.5.40/arch/s390/mm/fault.c	Tue Oct  1 09:07:34 2002
+++ linux-2.5.40-s390/arch/s390/mm/fault.c	Fri Oct  4 16:14:28 2002
@@ -46,7 +46,6 @@
  */
 void bust_spinlocks(int yes)
 {
-	spin_lock_init(&timerlist_lock);
 	if (yes) {
 		oops_in_progress = 1;
 	} else {
diff -urN linux-2.5.40/arch/s390x/kernel/Makefile linux-2.5.40-s390/arch/s390x/kernel/Makefile
--- linux-2.5.40/arch/s390x/kernel/Makefile	Tue Oct  1 09:06:55 2002
+++ linux-2.5.40-s390/arch/s390x/kernel/Makefile	Fri Oct  4 16:14:28 2002
@@ -5,10 +5,10 @@
 EXTRA_TARGETS	:= head.o init_task.o
 EXTRA_AFLAGS	:= -traditional
 
-export-objs	:= debug.o ebcdic.o irq.o s390_ext.o smp.o s390_ksyms.o \
+export-objs	:= debug.o ebcdic.o s390_ext.o smp.o s390_ksyms.o \
 		   exec32.o
 
-obj-y		:= entry.o bitmap.o traps.o time.o process.o irq.o \
+obj-y		:= entry.o bitmap.o traps.o time.o process.o \
 		   setup.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \
 		   semaphore.o s390fpu.o reipl.o s390_ext.o debug.o
 
diff -urN linux-2.5.40/arch/s390x/kernel/entry.S linux-2.5.40-s390/arch/s390x/kernel/entry.S
--- linux-2.5.40/arch/s390x/kernel/entry.S	Tue Oct  1 09:06:25 2002
+++ linux-2.5.40-s390/arch/s390x/kernel/entry.S	Fri Oct  4 16:14:28 2002
@@ -15,7 +15,6 @@
 #include <asm/cache.h>
 #include <asm/lowcore.h>
 #include <asm/errno.h>
-#include <asm/smp.h>
 #include <asm/ptrace.h>
 #include <asm/thread_info.h>
 
@@ -551,8 +550,8 @@
         .long  SYSCALL(sys_rt_sigtimedwait,sys32_rt_sigtimedwait_wrapper)
         .long  SYSCALL(sys_rt_sigqueueinfo,sys32_rt_sigqueueinfo_wrapper)
         .long  SYSCALL(sys_rt_sigsuspend_glue,sys32_rt_sigsuspend_glue)
-        .long  SYSCALL(sys_pread,sys32_pread_wrapper)           /* 180 */
-        .long  SYSCALL(sys_pwrite,sys32_pwrite_wrapper)
+        .long  SYSCALL(sys_pread64,sys32_pread_wrapper)           /* 180 */
+        .long  SYSCALL(sys_pwrite64,sys32_pwrite_wrapper)
         .long  SYSCALL(sys_ni_syscall,sys32_chown16_wrapper)    /* old chown16 syscall */
         .long  SYSCALL(sys_getcwd,sys32_getcwd_wrapper)
         .long  SYSCALL(sys_capget,sys32_capget_wrapper)
diff -urN linux-2.5.40/arch/s390x/kernel/head.S linux-2.5.40-s390/arch/s390x/kernel/head.S
--- linux-2.5.40/arch/s390x/kernel/head.S	Tue Oct  1 09:06:17 2002
+++ linux-2.5.40-s390/arch/s390x/kernel/head.S	Fri Oct  4 16:14:28 2002
@@ -645,5 +645,5 @@
 #
             .align 8
 .Ldw:       .quad  0x0002000180000000,0x0000000000000000
-.Laregs:    .long  0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0
+.Laregs:    .long  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
 
diff -urN linux-2.5.40/arch/s390x/kernel/init_task.c linux-2.5.40-s390/arch/s390x/kernel/init_task.c
--- linux-2.5.40/arch/s390x/kernel/init_task.c	Tue Oct  1 09:06:30 2002
+++ linux-2.5.40-s390/arch/s390x/kernel/init_task.c	Fri Oct  4 16:14:28 2002
@@ -15,7 +15,7 @@
 
 static struct fs_struct init_fs = INIT_FS;
 static struct files_struct init_files = INIT_FILES;
-static struct signal_struct init_signals = INIT_SIGNALS;
+static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
 struct mm_struct init_mm = INIT_MM(init_mm);
 
 /*
diff -urN linux-2.5.40/arch/s390x/kernel/irq.c linux-2.5.40-s390/arch/s390x/kernel/irq.c
--- linux-2.5.40/arch/s390x/kernel/irq.c	Tue Oct  1 09:07:50 2002
+++ linux-2.5.40-s390/arch/s390x/kernel/irq.c	Thu Jan  1 01:00:00 1970
@@ -1,361 +0,0 @@
-/*
- *  arch/s390/kernel/irq.c
- *
- *  S390 version
- *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
- *    Author(s): Ingo Adlung (adlung@de.ibm.com)
- *
- *  Derived from "arch/i386/kernel/irq.c"
- *    Copyright (C) 1992, 1999 Linus Torvalds, Ingo Molnar
- *
- *  S/390 I/O interrupt processing and I/O request processing is
- *   implemented in arch/s390/kernel/s390io.c
- */
-#include <linux/module.h>
-#include <linux/config.h>
-#include <linux/ptrace.h>
-#include <linux/errno.h>
-#include <linux/kernel_stat.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/ioport.h>
-#include <linux/interrupt.h>
-#include <linux/timex.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/random.h>
-#include <linux/smp.h>
-#include <linux/threads.h>
-#include <linux/smp_lock.h>
-#include <linux/init.h>
-#include <linux/seq_file.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/bitops.h>
-#include <asm/smp.h>
-#include <asm/pgtable.h>
-#include <asm/delay.h>
-#include <asm/lowcore.h>
-
-void          s390_init_IRQ   ( void );
-void          s390_free_irq   ( unsigned int irq, void *dev_id);
-int           s390_request_irq( unsigned int irq,
-                     void           (*handler)(int, void *, struct pt_regs *),
-                     unsigned long  irqflags,
-                     const char    *devname,
-                     void          *dev_id);
-
-#if 0
-/*
- * The following vectors are part of the Linux architecture, there
- * is no hardware IRQ pin equivalent for them, they are triggered
- * through the ICC by us (IPIs), via smp_message_pass():
- */
-BUILD_SMP_INTERRUPT(reschedule_interrupt)
-BUILD_SMP_INTERRUPT(invalidate_interrupt)
-BUILD_SMP_INTERRUPT(stop_cpu_interrupt)
-BUILD_SMP_INTERRUPT(mtrr_interrupt)
-BUILD_SMP_INTERRUPT(spurious_interrupt)
-#endif
-
-int show_interrupts(struct seq_file *p, void *v)
-{
-	int i, j;
-
-	seq_puts(p, "           ");
-
-	for (j=0; j<smp_num_cpus; j++)
-		seq_printf(p, "CPU%d       ",j);
-
-	seq_putc(p, '\n');
-
-	for (i = 0 ; i < NR_IRQS ; i++)
-	{
-		if (ioinfo[i] == INVALID_STORAGE_AREA)
-			continue;
-
-		seq_printf(p, "%3d: ",i);
-		seq_printf(p, "  %s", ioinfo[i]->irq_desc.name);
-
-		seq_putc(p, '\n');
-	
-	} /* endfor */
-
-	return 0;
-}
-
-/*
- * Global interrupt locks for SMP. Allow interrupts to come in on any
- * CPU, yet make cli/sti act globally to protect critical regions..
- */
-#ifdef CONFIG_SMP
-atomic_t global_irq_holder = ATOMIC_INIT(NO_PROC_ID);
-atomic_t global_irq_lock = ATOMIC_INIT(0);
-atomic_t global_irq_count = ATOMIC_INIT(0);
-atomic_t global_bh_count;
-
-/*
- * "global_cli()" is a special case, in that it can hold the
- * interrupts disabled for a longish time, and also because
- * we may be doing TLB invalidates when holding the global
- * IRQ lock for historical reasons. Thus we may need to check
- * SMP invalidate events specially by hand here (but not in
- * any normal spinlocks)
- *
- * Thankfully we don't need this as we can deliver flush tlbs with
- * interrupts disabled DJB :-)
- */
-#define check_smp_invalidate(cpu)
-
-extern void show_stack(unsigned long* esp);
-
-static void show(char * str)
-{
-	int cpu = smp_processor_id();
-
-	printk("\n%s, CPU %d:\n", str, cpu);
-	printk("irq:  %d [%d]\n",
-	       atomic_read(&global_irq_count),local_irq_count(smp_processor_id()));
-	printk("bh:   %d [%d]\n",
-	       atomic_read(&global_bh_count),local_bh_count(smp_processor_id()));
-	show_stack(NULL);
-}
-
-#define MAXCOUNT 100000000
-
-static inline void wait_on_bh(void)
-{
-	int count = MAXCOUNT;
-	do {
-		if (!--count) {
-			show("wait_on_bh");
-			count = ~0;
-		}
-		/* nothing .. wait for the other bh's to go away */
-	} while (atomic_read(&global_bh_count) != 0);
-}
-
-static inline void wait_on_irq(int cpu)
-{
-	int count = MAXCOUNT;
-
-	for (;;) {
-
-		/*
-		 * Wait until all interrupts are gone. Wait
-		 * for bottom half handlers unless we're
-		 * already executing in one..
-		 */
-		if (!atomic_read(&global_irq_count)) {
-			if (local_bh_count(cpu)||
-			    !atomic_read(&global_bh_count))
-				break;
-		}
-
-		/* Duh, we have to loop. Release the lock to avoid deadlocks */
-                atomic_set(&global_irq_lock, 0);
-
-		for (;;) {
-			if (!--count) {
-				show("wait_on_irq");
-				count = ~0;
-			}
-			local_irq_enable();
-			SYNC_OTHER_CORES(cpu);
-			local_irq_disable();
-			check_smp_invalidate(cpu);
-			if (atomic_read(&global_irq_count))
-				continue;
-			if (atomic_read(&global_irq_lock))
-				continue;
-			if (!local_bh_count(cpu)
-			    && atomic_read(&global_bh_count))
-				continue;
-                        if (!atomic_compare_and_swap(0, 1, &global_irq_lock))
-				break;
-		}
-	}
-}
-
-/*
- * This is called when we want to synchronize with
- * bottom half handlers. We need to wait until
- * no other CPU is executing any bottom half handler.
- *
- * Don't wait if we're already running in an interrupt
- * context or are inside a bh handler.
- */
-void synchronize_bh(void)
-{
-	if (atomic_read(&global_bh_count) && !in_interrupt())
-		wait_on_bh();
-}
-
-/*
- * This is called when we want to synchronize with
- * interrupts. We may for example tell a device to
- * stop sending interrupts: but to make sure there
- * are no interrupts that are executing on another
- * CPU we need to call this function.
- */
-void synchronize_irq(void)
-{
-	if (atomic_read(&global_irq_count)) {
-		/* Stupid approach */
-		cli();
-		sti();
-	}
-}
-
-static inline void get_irqlock(int cpu)
-{
-	if (atomic_compare_and_swap(0,1,&global_irq_lock) != 0) {
-		/* do we already hold the lock? */
-		if ( cpu == atomic_read(&global_irq_holder))
-			return;
-		/* Uhhuh.. Somebody else got it. Wait.. */
-		do {
-			check_smp_invalidate(cpu);
-		} while (atomic_compare_and_swap(0,1,&global_irq_lock) != 0);
-	}
-	/*
-	 * We also to make sure that nobody else is running
-	 * in an interrupt context.
-	 */
-	wait_on_irq(cpu);
-
-	/*
-	 * Ok, finally..
-	 */
-	atomic_set(&global_irq_holder,cpu);
-}
-
-#define EFLAGS_I_SHIFT 57
-
-/*
- * A global "cli()" while in an interrupt context
- * turns into just a local cli(). Interrupts
- * should use spinlocks for the (very unlikely)
- * case that they ever want to protect against
- * each other.
- *
- * If we already have local interrupts disabled,
- * this will not turn a local disable into a
- * global one (problems with spinlocks: this makes
- * save_flags+cli+sti usable inside a spinlock).
- */
-void __global_cli(void)
-{
-	unsigned long flags;
-
-	local_save_flags(flags);
-	if (flags & (1UL << EFLAGS_I_SHIFT)) {
-		int cpu = smp_processor_id();
-		local_irq_disable();
-		if (!in_irq())
-			get_irqlock(cpu);
-	}
-}
-
-void __global_sti(void)
-{
-
-	if (!in_irq())
-		release_irqlock(smp_processor_id());
-	local_irq_enable();
-}
-
-/*
- * SMP flags value to restore to:
- * 0 - global cli
- * 1 - global sti
- * 2 - local cli
- * 3 - local sti
- */
-unsigned long __global_save_flags(void)
-{
-	int retval;
-	int local_enabled;
-	unsigned long flags;
-
-	local_save_flags(flags);
-	local_enabled = (flags >> EFLAGS_I_SHIFT) & 1;
-	/* default to local */
-	retval = 2 + local_enabled;
-
-	/* check for global flags if we're not in an interrupt */
-	if (!in_irq())
-	{
-		if (local_enabled)
-			retval = 1;
-		if (atomic_read(&global_irq_holder)== smp_processor_id())
-			retval = 0;
-	}
-	return retval;
-}
-
-void __global_restore_flags(unsigned long flags)
-{
-	switch (flags) {
-	case 0:
-		__global_cli();
-		break;
-	case 1:
-		__global_sti();
-		break;
-	case 2:
-		local_irq_disable();
-		break;
-	case 3:
-		local_irq_enable();
-		break;
-	default:
-		printk("global_restore_flags: %08lx (%08lx)\n",
-		       flags, (&flags)[-1]);
-	}
-}
-
-#endif
-
-
-void __init init_IRQ(void)
-{
-   s390_init_IRQ();
-}
-
-
-void free_irq(unsigned int irq, void *dev_id)
-{
-   s390_free_irq( irq, dev_id);
-}
-
-
-int request_irq( unsigned int   irq,
-                 void           (*handler)(int, void *, struct pt_regs *),
-                 unsigned long  irqflags,
-                 const char    *devname,
-                 void          *dev_id)
-{
-   return( s390_request_irq( irq, handler, irqflags, devname, dev_id ) );
-
-}
-
-void init_irq_proc(void)
-{
-        /* For now, nothing... */
-}
-
-#ifdef CONFIG_SMP
-EXPORT_SYMBOL(__global_cli);
-EXPORT_SYMBOL(__global_sti);
-EXPORT_SYMBOL(__global_save_flags);
-EXPORT_SYMBOL(__global_restore_flags);
-EXPORT_SYMBOL(global_irq_holder);
-EXPORT_SYMBOL(global_irq_lock);
-EXPORT_SYMBOL(global_irq_count);
-EXPORT_SYMBOL(global_bh_count);
-#endif
-
-EXPORT_SYMBOL(global_bh_lock);
diff -urN linux-2.5.40/arch/s390x/kernel/linux32.c linux-2.5.40-s390/arch/s390x/kernel/linux32.c
--- linux-2.5.40/arch/s390x/kernel/linux32.c	Tue Oct  1 09:06:21 2002
+++ linux-2.5.40-s390/arch/s390x/kernel/linux32.c	Fri Oct  4 16:14:28 2002
@@ -1953,15 +1953,17 @@
 			return -EINVAL;
 	}
 
-	spin_lock_irq(&current->sigmask_lock);
-	sig = dequeue_signal(&these, &info);
+	spin_lock_irq(&current->sig->siglock);
+	sig = dequeue_signal(&current->sig->shared_pending, &these, &info);
+	if (!sig)
+		sig = dequeue_signal(&current->pending, &these, &info);
 	if (!sig) {
 		/* None ready -- temporarily unblock those we're interested
 		   in so that we'll be awakened when they arrive.  */
-		sigset_t oldblocked = current->blocked;
+		current->real_blocked = current->blocked;
 		sigandsets(&current->blocked, &current->blocked, &these);
 		recalc_sigpending();
-		spin_unlock_irq(&current->sigmask_lock);
+		spin_unlock_irq(&current->sig->siglock);
 
 		timeout = MAX_SCHEDULE_TIMEOUT;
 		if (uts)
@@ -1971,12 +1973,15 @@
 		current->state = TASK_INTERRUPTIBLE;
 		timeout = schedule_timeout(timeout);
 
-		spin_lock_irq(&current->sigmask_lock);
-		sig = dequeue_signal(&these, &info);
-		current->blocked = oldblocked;
+		spin_lock_irq(&current->sig->siglock);
+		sig = dequeue_signal(&current->sig->shared_pending, &these, &info);
+		if (!sig)
+			sig = dequeue_signal(&current->pending, &these, &info);
+		current->blocked = current->real_blocked;
+		siginitset(&current->real_blocked, 0);
 		recalc_sigpending();
 	}
-	spin_unlock_irq(&current->sigmask_lock);
+	spin_unlock_irq(&current->sig->siglock);
 
 	if (sig) {
 		ret = sig;
diff -urN linux-2.5.40/arch/s390x/kernel/process.c linux-2.5.40-s390/arch/s390x/kernel/process.c
--- linux-2.5.40/arch/s390x/kernel/process.c	Tue Oct  1 09:06:21 2002
+++ linux-2.5.40-s390/arch/s390x/kernel/process.c	Fri Oct  4 16:14:28 2002
@@ -15,9 +15,6 @@
  * This file handles the architecture-dependent parts of process handling..
  */
 
-#define __KERNEL_SYSCALLS__
-#include <stdarg.h>
-
 #include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
@@ -118,31 +115,35 @@
 		show_trace((unsigned long *) regs->gprs[15]);
 }
 
+extern void kernel_thread_starter(void);
+__asm__(".align 4\n"
+	"kernel_thread_starter:\n"
+	"    lg    15,0(8)\n"
+	"    sgr   15,7\n"
+	"    stosm 48(15),3\n"
+	"    lgr   2,10\n"
+	"    basr  14,9\n"
+	"    sgr   2,2\n"
+	"    br    11\n");
+
 int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
 {
-        int clone_arg = flags | CLONE_VM;
-        int retval;
+	struct task_struct *p;
+	struct pt_regs regs;
 
-        __asm__ __volatile__(
-                "     slgr  2,2\n"
-                "     lgr   3,%1\n"
-                "     lg    4,%6\n"     /* load kernel stack ptr of parent */
-                "     svc   %b2\n"                     /* Linux system call*/
-                "     clg   4,%6\n"    /* compare ksp's: child or parent ? */
-                "     je    0f\n"                          /* parent - jump*/
-                "     lg    15,%6\n"            /* fix kernel stack pointer*/
-                "     aghi  15,%7\n"
-                "     xc    0(160,15),0(15)\n"          /* clear save area */
-                "     lgr   2,%4\n"                        /* load argument*/
-                "     basr  14,%5\n"                             /* call fn*/
-                "     svc   %b3\n"                     /* Linux system call*/
-                "0:   lgr   %0,2"
-                : "=a" (retval)
-                : "d" (clone_arg), "i" (__NR_clone), "i" (__NR_exit),
-                  "d" (arg), "a" (fn), "i" (__LC_KERNEL_STACK) ,
-                  "i" (-STACK_FRAME_OVERHEAD)
-                : "2", "3", "4" );
-        return retval;
+	memset(&regs, 0, sizeof(regs));
+	regs.psw.mask = _SVC_PSW_MASK;
+	regs.psw.addr = (__u64) kernel_thread_starter;
+	regs.gprs[7] = STACK_FRAME_OVERHEAD;
+	regs.gprs[8] = __LC_KERNEL_STACK;
+	regs.gprs[9] = (unsigned long) fn;
+	regs.gprs[10] = (unsigned long) arg;
+	regs.gprs[11] = (unsigned long) do_exit;
+	regs.orig_gpr2 = -1;
+
+	/* Ok, create the new process.. */
+	p = do_fork(flags | CLONE_VM, 0, &regs, 0, NULL);
+	return IS_ERR(p) ? PTR_ERR(p) : p->pid;
 }
 
 /*
@@ -184,17 +185,20 @@
 		 (THREAD_SIZE + (unsigned long) p->thread_info)) - 1;
         p->thread.ksp = (unsigned long) frame;
         frame->childregs = *regs;
+	frame->childregs.gprs[2] = 0;	/* child returns 0 on fork. */
         frame->childregs.gprs[15] = new_stackp;
         frame->back_chain = frame->eos = 0;
 
-        /* new return point is ret_from_sys_call */
-        frame->gprs[8] = (unsigned long) &ret_from_fork;
+        /* new return point is ret_from_fork */
+        frame->gprs[8] = (unsigned long) ret_from_fork;
 
         /* fake return stack for resume(), don't go back to schedule */
         frame->gprs[9] = (unsigned long) frame;
-        /* save fprs, if used in last task */
+        /* save fprs */
 	save_fp_regs(&p->thread.fp_regs);
         p->thread.user_seg = __pa((unsigned long) p->mm->pgd) | _REGION_TABLE;
+	/* start new process with ar4 pointing to the correct address space */
+	p->thread.ar4 = get_fs().ar4;
         /* Don't copy debug registers */
         memset(&p->thread.per_info,0,sizeof(p->thread.per_info));
         return 0;
@@ -203,7 +207,7 @@
 asmlinkage int sys_fork(struct pt_regs regs)
 {
 	struct task_struct *p;
-        p = do_fork(SIGCHLD, regs.gprs[15], &regs, 0);
+        p = do_fork(SIGCHLD, regs.gprs[15], &regs, 0, NULL);
 	return IS_ERR(p) ? PTR_ERR(p) : p->pid;
 }
 
@@ -212,12 +216,14 @@
         unsigned long clone_flags;
         unsigned long newsp;
 	struct task_struct *p;
+	int *user_tid;
 
         clone_flags = regs.gprs[3];
         newsp = regs.orig_gpr2;
+	user_tid = (int *) regs.gprs[4];
         if (!newsp)
                 newsp = regs.gprs[15];
-        p = do_fork(clone_flags & ~CLONE_IDLETASK, newsp, &regs, 0);
+        p = do_fork(clone_flags & ~CLONE_IDLETASK, newsp, &regs, 0, user_tid);
 	return IS_ERR(p) ? PTR_ERR(p) : p->pid;
 }
 
@@ -234,7 +240,8 @@
 asmlinkage int sys_vfork(struct pt_regs regs)
 {
 	struct task_struct *p;
-	p = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.gprs[15], &regs, 0);
+	p = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD,
+		    regs.gprs[15], &regs, 0, NULL);
 	return IS_ERR(p) ? PTR_ERR(p) : p->pid;
 }
 
diff -urN linux-2.5.40/arch/s390x/kernel/setup.c linux-2.5.40-s390/arch/s390x/kernel/setup.c
--- linux-2.5.40/arch/s390x/kernel/setup.c	Tue Oct  1 09:06:55 2002
+++ linux-2.5.40-s390/arch/s390x/kernel/setup.c	Fri Oct  4 16:14:28 2002
@@ -514,7 +514,7 @@
 		seq_printf(m, "vendor_id       : IBM/S390\n"
 				"# processors    : %i\n"
 				"bogomips per cpu: %lu.%02lu\n",
-				smp_num_cpus, loops_per_jiffy/(500000/HZ),
+				num_online_cpus(), loops_per_jiffy/(500000/HZ),
 				(loops_per_jiffy/(5000/HZ))%100);
 	}
 	if (cpu_online_map & (1 << n)) {
diff -urN linux-2.5.40/arch/s390x/kernel/signal.c linux-2.5.40-s390/arch/s390x/kernel/signal.c
--- linux-2.5.40/arch/s390x/kernel/signal.c	Tue Oct  1 09:07:08 2002
+++ linux-2.5.40-s390/arch/s390x/kernel/signal.c	Fri Oct  4 16:14:28 2002
@@ -60,11 +60,11 @@
 	sigset_t saveset;
 
 	mask &= _BLOCKABLE;
-	spin_lock_irq(&current->sigmask_lock);
+	spin_lock_irq(&current->sig->siglock);
 	saveset = current->blocked;
 	siginitset(&current->blocked, mask);
 	recalc_sigpending();
-	spin_unlock_irq(&current->sigmask_lock);
+	spin_unlock_irq(&current->sig->siglock);
 	regs->gprs[2] = -EINTR;
 
 	while (1) {
@@ -88,11 +88,11 @@
 		return -EFAULT;
 	sigdelsetmask(&newset, ~_BLOCKABLE);
 
-	spin_lock_irq(&current->sigmask_lock);
+	spin_lock_irq(&current->sig->siglock);
 	saveset = current->blocked;
 	current->blocked = newset;
 	recalc_sigpending();
-	spin_unlock_irq(&current->sigmask_lock);
+	spin_unlock_irq(&current->sig->siglock);
 	regs->gprs[2] = -EINTR;
 
 	while (1) {
@@ -191,10 +191,10 @@
 		goto badframe;
 
 	sigdelsetmask(&set, ~_BLOCKABLE);
-	spin_lock_irq(&current->sigmask_lock);
+	spin_lock_irq(&current->sig->siglock);
 	current->blocked = set;
 	recalc_sigpending();
-	spin_unlock_irq(&current->sigmask_lock);
+	spin_unlock_irq(&current->sig->siglock);
 
 	if (restore_sigregs(regs, &frame->sregs))
 		goto badframe;
@@ -217,10 +217,10 @@
 		goto badframe;
 
 	sigdelsetmask(&set, ~_BLOCKABLE);
-	spin_lock_irq(&current->sigmask_lock);
+	spin_lock_irq(&current->sig->siglock);
 	current->blocked = set;
 	recalc_sigpending();
-	spin_unlock_irq(&current->sigmask_lock);
+	spin_unlock_irq(&current->sig->siglock);
 
 	if (restore_sigregs(regs, &frame->uc.uc_mcontext))
 		goto badframe;
@@ -420,11 +420,11 @@
 		ka->sa.sa_handler = SIG_DFL;
 
 	if (!(ka->sa.sa_flags & SA_NODEFER)) {
-		spin_lock_irq(&current->sigmask_lock);
+		spin_lock_irq(&current->sig->siglock);
 		sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
 		sigaddset(&current->blocked,sig);
 		recalc_sigpending();
-		spin_unlock_irq(&current->sigmask_lock);
+		spin_unlock_irq(&current->sig->siglock);
 	}
 }
 
diff -urN linux-2.5.40/arch/s390x/kernel/signal32.c linux-2.5.40-s390/arch/s390x/kernel/signal32.c
--- linux-2.5.40/arch/s390x/kernel/signal32.c	Tue Oct  1 09:06:58 2002
+++ linux-2.5.40-s390/arch/s390x/kernel/signal32.c	Fri Oct  4 16:14:28 2002
@@ -112,11 +112,11 @@
 	sigset_t saveset;
 
 	mask &= _BLOCKABLE;
-	spin_lock_irq(&current->sigmask_lock);
+	spin_lock_irq(&current->sig->siglock);
 	saveset = current->blocked;
 	siginitset(&current->blocked, mask);
 	recalc_sigpending();
-	spin_unlock_irq(&current->sigmask_lock);
+	spin_unlock_irq(&current->sig->siglock);
 	regs->gprs[2] = -EINTR;
 
 	while (1) {
@@ -147,11 +147,11 @@
 	}
         sigdelsetmask(&newset, ~_BLOCKABLE);
 
-        spin_lock_irq(&current->sigmask_lock);
+        spin_lock_irq(&current->sig->siglock);
         saveset = current->blocked;
         current->blocked = newset;
         recalc_sigpending();
-        spin_unlock_irq(&current->sigmask_lock);
+        spin_unlock_irq(&current->sig->siglock);
         regs->gprs[2] = -EINTR;
 
         while (1) {
@@ -352,10 +352,10 @@
 		goto badframe;
 
 	sigdelsetmask(&set, ~_BLOCKABLE);
-	spin_lock_irq(&current->sigmask_lock);
+	spin_lock_irq(&current->sig->siglock);
 	current->blocked = set;
 	recalc_sigpending();
-	spin_unlock_irq(&current->sigmask_lock);
+	spin_unlock_irq(&current->sig->siglock);
 
 	if (restore_sigregs32(regs, &frame->sregs))
 		goto badframe;
@@ -382,10 +382,10 @@
 		goto badframe;
 
 	sigdelsetmask(&set, ~_BLOCKABLE);
-	spin_lock_irq(&current->sigmask_lock);
+	spin_lock_irq(&current->sig->siglock);
 	current->blocked = set;
 	recalc_sigpending();
-	spin_unlock_irq(&current->sigmask_lock);
+	spin_unlock_irq(&current->sig->siglock);
 
 	if (restore_sigregs32(regs, &frame->uc.uc_mcontext))
 		goto badframe;
@@ -595,11 +595,11 @@
 		ka->sa.sa_handler = SIG_DFL;
 
 	if (!(ka->sa.sa_flags & SA_NODEFER)) {
-		spin_lock_irq(&current->sigmask_lock);
+		spin_lock_irq(&current->sig->siglock);
 		sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
 		sigaddset(&current->blocked,sig);
 		recalc_sigpending();
-		spin_unlock_irq(&current->sigmask_lock);
+		spin_unlock_irq(&current->sig->siglock);
 	}
 }
 
diff -urN linux-2.5.40/arch/s390x/kernel/smp.c linux-2.5.40-s390/arch/s390x/kernel/smp.c
--- linux-2.5.40/arch/s390x/kernel/smp.c	Tue Oct  1 09:07:01 2002
+++ linux-2.5.40-s390/arch/s390x/kernel/smp.c	Fri Oct  4 16:14:28 2002
@@ -46,45 +46,16 @@
 /*
  * An array with a pointer the lowcore of every CPU.
  */
-static int       max_cpus = NR_CPUS;	  /* Setup configured maximum number of CPUs to activate	*/
-int              smp_num_cpus;
+
 struct _lowcore *lowcore_ptr[NR_CPUS];
 cycles_t         cacheflush_time=0;
 int              smp_threads_ready=0;      /* Set when the idlers are all forked. */
-static atomic_t  smp_commenced = ATOMIC_INIT(0);
 
-volatile unsigned long phys_cpu_present_map;
 volatile unsigned long cpu_online_map;
+volatile unsigned long cpu_possible_map;
 unsigned long    cache_decay_ticks = 0;
 
 /*
- *      Setup routine for controlling SMP activation
- *
- *      Command-line option of "nosmp" or "maxcpus=0" will disable SMP
- *      activation entirely (the MPS table probe still happens, though).
- *
- *      Command-line option of "maxcpus=<NUM>", where <NUM> is an integer
- *      greater than 0, limits the maximum number of CPUs activated in
- *      SMP mode to <NUM>.
- */
-
-static int __init nosmp(char *str)
-{
-	max_cpus = 0;
-	return 1;
-}
-
-__setup("nosmp", nosmp);
-
-static int __init maxcpus(char *str)
-{
-	get_option(&str, &max_cpus);
-	return 1;
-}
-
-__setup("maxcpus=", maxcpus);
-
-/*
  * Reboot, halt and power_off routines for SMP.
  */
 extern char vmhalt_cmd[];
@@ -147,9 +118,10 @@
  */
 {
 	struct call_data_struct data;
-	int cpus = smp_num_cpus-1;
+	int cpus = num_online_cpus()-1;
 
-	if (!cpus || !atomic_read(&smp_commenced))
+	/* FIXME: get cpu lock -hc */
+	if (cpus <= 0)
 		return 0;
 
 	data.func = func;
@@ -182,8 +154,8 @@
         int i, rc;
 
         /* stop all processors */
-        for (i =  0; i < smp_num_cpus; i++) {
-                if (smp_processor_id() == i)
+        for (i =  0; i < NR_CPUS; i++) {
+                if (!cpu_online(i) || smp_processor_id() == i)
 			continue;
 		do {
 			rc = signal_processor_ps(&dummy, 0, i, sigp_stop);
@@ -198,8 +170,8 @@
         int i, rc;
 
         /* store status of all processors in their lowcores (real 0) */
-        for (i =  0; i < smp_num_cpus; i++) {
-                if (smp_processor_id() == i) 
+        for (i =  0; i < NR_CPUS; i++) {
+                if (!cpu_online(i) || smp_processor_id() == i) 
 			continue;
 		low_core_addr = (unsigned long)get_cpu_lowcore(i);
 		do {
@@ -340,8 +312,8 @@
 {
         int i;
 
-        for (i = 0; i < smp_num_cpus; i++) {
-                if (smp_processor_id() == i)
+        for (i = 0; i < NR_CPUS; i++) {
+                if (!cpu_online(i) || smp_processor_id() == i)
                         continue;
                 /*
                  * Set signaling bit in lowcore of target cpu and kick it
@@ -405,13 +377,11 @@
 void smp_ctl_set_bit(int cr, int bit) {
         ec_creg_mask_parms parms;
 
-        if (atomic_read(&smp_commenced) != 0) {
-                parms.start_ctl = cr;
-                parms.end_ctl = cr;
-                parms.orvals[cr] = 1 << bit;
-                parms.andvals[cr] = -1L;
-                smp_call_function(smp_ctl_bit_callback, &parms, 0, 1);
-        }
+	parms.start_ctl = cr;
+	parms.end_ctl = cr;
+	parms.orvals[cr] = 1 << bit;
+	parms.andvals[cr] = -1L;
+	smp_call_function(smp_ctl_bit_callback, &parms, 0, 1);
         __ctl_set_bit(cr, bit);
 }
 
@@ -421,13 +391,11 @@
 void smp_ctl_clear_bit(int cr, int bit) {
         ec_creg_mask_parms parms;
 
-        if (atomic_read(&smp_commenced) != 0) {
-                parms.start_ctl = cr;
-                parms.end_ctl = cr;
-                parms.orvals[cr] = 0;
-                parms.andvals[cr] = ~(1L << bit);
-                smp_call_function(smp_ctl_bit_callback, &parms, 0, 1);
-        }
+	parms.start_ctl = cr;
+	parms.end_ctl = cr;
+	parms.orvals[cr] = 0;
+	parms.andvals[cr] = ~(1L << bit);
+	smp_call_function(smp_ctl_bit_callback, &parms, 0, 1);
         __ctl_clear_bit(cr, bit);
 }
 
@@ -436,26 +404,27 @@
  * Lets check how many CPUs we have.
  */
 
-void smp_count_cpus(void)
+void __init smp_check_cpus(unsigned int max_cpus)
 {
-        int curr_cpu;
+        int curr_cpu, num_cpus;
 
+	boot_cpu_addr = S390_lowcore.cpu_data.cpu_addr;
         current_thread_info()->cpu = 0;
-        smp_num_cpus = 1;
-	phys_cpu_present_map = 1;
+        num_cpus = 1;
+	cpu_possible_map = 1;
         cpu_online_map = 1;
         for (curr_cpu = 0;
-             curr_cpu <= 65535 && smp_num_cpus < max_cpus; curr_cpu++) {
+             curr_cpu <= 65535 && num_cpus < max_cpus; curr_cpu++) {
                 if ((__u16) curr_cpu == boot_cpu_addr)
                         continue;
-                __cpu_logical_map[smp_num_cpus] = (__u16) curr_cpu;
-                if (signal_processor(smp_num_cpus, sigp_sense) ==
+                __cpu_logical_map[num_cpus] = (__u16) curr_cpu;
+                if (signal_processor(num_cpus, sigp_sense) ==
                     sigp_not_operational)
                         continue;
-		set_bit(smp_num_cpus, &phys_cpu_present_map);
-                smp_num_cpus++;
+		set_bit(num_cpus, &cpu_possible_map);
+                num_cpus++;
         }
-        printk("Detected %d CPU's\n",(int) smp_num_cpus);
+        printk("Detected %d CPU's\n",(int) num_cpus);
         printk("Boot cpu address %2X\n", boot_cpu_addr);
 }
 
@@ -470,19 +439,18 @@
 {
         /* Setup the cpu */
         cpu_init();
-	/* Mark this cpu as online. */
-	set_bit(smp_processor_id(), &cpu_online_map);
-        /* Print info about this processor */
-        print_cpu_info(&safe_get_cpu_lowcore(smp_processor_id())->cpu_data);
-        /* Wait for completion of smp startup */
-        while (!atomic_read(&smp_commenced))
-                /* nothing */ ;
         /* init per CPU timer */
         init_cpu_timer();
 #ifdef CONFIG_PFAULT
 	/* Enable pfault pseudo page faults on this cpu. */
 	pfault_init();
 #endif
+	/* Mark this cpu as online. */
+	set_bit(smp_processor_id(), &cpu_online_map);
+	/* Switch on interrupts */
+	local_irq_enable();
+        /* Print info about this processor */
+        print_cpu_info(&S390_lowcore.cpu_data);
         /* cpu_idle will call schedule for us */
         return cpu_idle(NULL);
 }
@@ -493,19 +461,35 @@
        /* don't care about the psw and regs settings since we'll never
           reschedule the forked task. */
        memset(&regs,0,sizeof(struct pt_regs));
-       return do_fork(CLONE_VM|CLONE_IDLETASK, 0, &regs, 0);
+       return do_fork(CLONE_VM|CLONE_IDLETASK, 0, &regs, 0, NULL);
 }
 
-static void __init do_boot_cpu(int cpu)
+int __cpu_up(unsigned int cpu)
 {
         struct task_struct *idle;
         struct _lowcore    *cpu_lowcore;
+	sigp_ccode          ccode;
+
+	/*
+	 * Set prefix page for new cpu
+	 */
+
+	ccode = signal_processor_p((u64) lowcore_ptr[cpu],
+				   cpu, sigp_set_prefix);
+	if(ccode){
+		printk("sigp_set_prefix failed for cpu %d "
+		       "with condition code %d\n",
+		       (int) cpu, (int) ccode);
+		return -EIO;
+	}
 
         /* We can't use kernel_thread since we must _avoid_ to reschedule
            the child. */
         idle = fork_by_hand();
-	if (IS_ERR(idle))
-                panic("failed fork for CPU %d", cpu);
+	if (IS_ERR(idle)){
+                printk("failed fork for CPU %d", cpu);
+		return -EIO;
+	}
 
         /*
          * We remove it from the pidhash and the runqueue
@@ -517,7 +501,7 @@
 
         cpu_lowcore = get_cpu_lowcore(cpu);
 	cpu_lowcore->save_area[15] = idle->thread.ksp;
-	cpu_lowcore->kernel_stack = (__u64) idle->thread_info + 16384;
+	cpu_lowcore->kernel_stack = (__u64) idle->thread_info + (4*PAGE_SIZE);
         __asm__ __volatile__("la    1,%0\n\t"
 			     "stctg 0,15,0(1)\n\t"
 			     "la    1,%1\n\t"
@@ -528,75 +512,47 @@
 
         eieio();
         signal_processor(cpu,sigp_restart);
-}
-
-/*
- *      Architecture specific routine called by the kernel just before init is
- *      fired off. This allows the BP to have everything in order [we hope].
- *      At the end of this all the APs will hit the system scheduling and off
- *      we go. Each AP will load the system gdt's and jump through the kernel
- *      init into idle(). At this point the scheduler will one day take over
- *      and give them jobs to do. smp_callin is a standard routine
- *      we use to track CPUs as they power up.
- */
 
-void __init smp_commence(void)
-{
-        /*
-         *      Lets the callins below out of their loop.
-         */
-        atomic_set(&smp_commenced,1);
+	while (!cpu_online(cpu));
+	return 0;
 }
 
 /*
- *	Cycle through the processors sending restart sigps to boot each.
+ *	Cycle through the processors and setup structures.
  */
 
-void __init smp_boot_cpus(void)
+void __init smp_prepare_cpus(unsigned int max_cpus)
 {
 	unsigned long async_stack;
-        sigp_ccode   ccode;
         int i;
 
         /* request the 0x1202 external interrupt */
         if (register_external_interrupt(0x1202, do_ext_call_interrupt) != 0)
                 panic("Couldn't request external interrupt 0x1202");
-        smp_count_cpus();
+        smp_check_cpus(max_cpus);
         memset(lowcore_ptr,0,sizeof(lowcore_ptr));  
         
         /*
-         *      Initialize the logical to physical CPU number mapping
+         *  Initialize prefix pages and stacks for all possible cpus
          */
         print_cpu_info(&safe_get_cpu_lowcore(0)->cpu_data);
 
-        for(i = 0; i < smp_num_cpus; i++) {
-                lowcore_ptr[i] = (struct _lowcore *)
-                                    __get_free_pages(GFP_KERNEL|GFP_DMA, 1);
+        for(i = 0; i < NR_CPUS; i++) {
+		if (!cpu_possible(i))
+			continue;
+		lowcore_ptr[i] = (struct _lowcore *)
+			__get_free_pages(GFP_KERNEL|GFP_DMA, 1);
 		async_stack = __get_free_pages(GFP_KERNEL,2);
 		if (lowcore_ptr[i] == NULL || async_stack == 0ULL)
 			panic("smp_boot_cpus failed to allocate memory\n");
                 memcpy(lowcore_ptr[i], &S390_lowcore, sizeof(struct _lowcore));
 		lowcore_ptr[i]->async_stack = async_stack + (4 * PAGE_SIZE);
-                /*
-                 * Most of the parameters are set up when the cpu is
-                 * started up.
-                 */
-                if (smp_processor_id() == i) {
-                        set_prefix((u32)(u64) lowcore_ptr[i]);
-			continue;
-		}
-		ccode = signal_processor_p((u64) lowcore_ptr[i],
-					   i, sigp_set_prefix);
-		if(ccode)
-			panic("sigp_set_prefix failed for cpu %d "
-			      "with condition code %d\n",
-			      (int) i, (int) ccode);
-		do_boot_cpu(i);
-        }
-	/*
-	 * Now wait until all of the cpus are online.
-	 */
-	while (phys_cpu_present_map != cpu_online_map);
+	}
+	set_prefix((u32)(u64) lowcore_ptr[smp_processor_id()]);
+}
+
+void smp_cpus_done(unsigned int max_cpis)
+{
 }
 
 /*
@@ -613,5 +569,4 @@
 EXPORT_SYMBOL(lowcore_ptr);
 EXPORT_SYMBOL(smp_ctl_set_bit);
 EXPORT_SYMBOL(smp_ctl_clear_bit);
-EXPORT_SYMBOL(smp_num_cpus);
 EXPORT_SYMBOL(smp_call_function);
diff -urN linux-2.5.40/arch/s390x/kernel/time.c linux-2.5.40-s390/arch/s390x/kernel/time.c
--- linux-2.5.40/arch/s390x/kernel/time.c	Tue Oct  1 09:07:35 2002
+++ linux-2.5.40-s390/arch/s390x/kernel/time.c	Fri Oct  4 16:14:28 2002
@@ -47,18 +47,18 @@
 extern rwlock_t xtime_lock;
 extern unsigned long wall_jiffies;
 
-void tod_to_timeval(__u64 todval, struct timeval *xtime)
+void tod_to_timeval(__u64 todval, struct timespec *xtime)
 {
-        todval >>= 12;
-        xtime->tv_sec = todval / 1000000;
-        xtime->tv_usec = todval % 1000000;
+        xtime->tv_sec = (todval >> 12) / 1000000;
+	todval -= (xtime->tv_sec * 1000000) << 12;
+	xtime->tv_nsec = ((todval * 1000) >> 12);
 }
 
 static inline unsigned long do_gettimeoffset(void) 
 {
 	__u64 now;
 
-	asm ("STCK 0(%0)" : : "a" (&now) : "memory", "cc");
+	asm volatile ("STCK 0(%0)" : : "a" (&now) : "memory", "cc");
         now = (now - init_timer_cc) >> 12;
 	/* We require the offset from the latest update of xtime */
 	now -= (__u64) wall_jiffies*USECS_PER_JIFFY;
@@ -75,7 +75,7 @@
 
 	read_lock_irqsave(&xtime_lock, flags);
 	sec = xtime.tv_sec;
-	usec = xtime.tv_usec + do_gettimeoffset();
+	usec = xtime.tv_nsec + do_gettimeoffset();
 	read_unlock_irqrestore(&xtime_lock, flags);
 
 	while (usec >= 1000000) {
@@ -104,7 +104,8 @@
 		tv->tv_sec--;
 	}
 
-	xtime = *tv;
+	xtime.tv_sec = tv->tv_sec;
+	xtime.tv_nsec = tv->tv_usec * 1000;
 	time_adjust = 0;		/* stop active adjtime() */
 	time_status |= STA_UNSYNC;
 	time_maxerror = NTP_PHASE_LIMIT;
@@ -125,7 +126,7 @@
 {
 	int cpu = smp_processor_id();
 
-	irq_enter(cpu, 0);
+	irq_enter();
 
 	/*
 	 * set clock comparator for next tick
@@ -147,7 +148,7 @@
 	do_timer(regs);
 #endif
 
-	irq_exit(cpu, 0);
+	irq_exit();
 }
 
 /*
diff -urN linux-2.5.40/arch/s390x/kernel/traps.c linux-2.5.40-s390/arch/s390x/kernel/traps.c
--- linux-2.5.40/arch/s390x/kernel/traps.c	Tue Oct  1 09:07:34 2002
+++ linux-2.5.40-s390/arch/s390x/kernel/traps.c	Fri Oct  4 16:14:28 2002
@@ -172,6 +172,14 @@
 	show_trace(sp);
 }
 
+/*
+ * The architecture-independent dump_stack generator
+ */
+void dump_stack(void)
+{
+	show_stack(0);
+}
+
 void show_registers(struct pt_regs *regs)
 {
 	mm_segment_t old_fs;
diff -urN linux-2.5.40/arch/s390x/mm/fault.c linux-2.5.40-s390/arch/s390x/mm/fault.c
--- linux-2.5.40/arch/s390x/mm/fault.c	Tue Oct  1 09:06:29 2002
+++ linux-2.5.40-s390/arch/s390x/mm/fault.c	Fri Oct  4 16:14:28 2002
@@ -45,7 +45,6 @@
  */
 void bust_spinlocks(int yes)
 {
-	spin_lock_init(&timerlist_lock);
 	if (yes) {
 		oops_in_progress = 1;
 	} else {


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2002-10-04 14:39 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-10-04 14:24 [PATCH] 2.5.40 s390 (1/27): arch Martin Schwidefsky

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®