diff --git a/arch/i386/Makefile b/arch/i386/Makefile
index 5b0f06adf4e7842fd67a4d931fa215f395d03d9e..274b4ef91c2e512f3cd057547558664f9a711fbc 100644
--- a/arch/i386/Makefile
+++ b/arch/i386/Makefile
@@ -86,13 +86,25 @@ ifdef CONFIG_MCYRIXIII
 CFLAGS += -march=i586
 endif
 
+ifdef CONFIG_VISWS
+MACHINE	:= visws
+else
+MACHINE	:= generic
+endif
+
 HEAD := arch/i386/kernel/head.o arch/i386/kernel/init_task.o
 
-SUBDIRS += arch/i386/kernel arch/i386/mm arch/i386/lib
+SUBDIRS += arch/i386/kernel arch/i386/mm arch/i386/lib \
+		arch/i386/$(MACHINE)
+
+CORE_FILES := arch/i386/kernel/kernel.o arch/i386/mm/mm.o \
+		arch/i386/$(MACHINE)/$(MACHINE).o $(CORE_FILES)
 
-CORE_FILES := arch/i386/kernel/kernel.o arch/i386/mm/mm.o $(CORE_FILES)
 LIBS := $(TOPDIR)/arch/i386/lib/lib.a $(LIBS) $(TOPDIR)/arch/i386/lib/lib.a
 
+CFLAGS += -I$(TOPDIR)/arch/i386/$(MACHINE)
+AFLAGS += -I$(TOPDIR)/arch/i386/$(MACHINE)
+
 ifdef CONFIG_MATH_EMULATION
 SUBDIRS += arch/i386/math-emu
 DRIVERS += arch/i386/math-emu/math.o
diff --git a/arch/i386/config.in b/arch/i386/config.in
index 1097c6a5e46c514908bd688cba86b9274b700144..38db09a86307cac259b848f14105ccf0af6b06fb 100644
--- a/arch/i386/config.in
+++ b/arch/i386/config.in
@@ -411,6 +411,18 @@ if [ "$CONFIG_DEBUG_KERNEL" != "n" ]; then
    fi
 fi
 
+if [ "$CONFIG_X86_LOCAL_APIC" = "y" ]; then
+   define_bool CONFIG_X86_EXTRA_IRQS y
+   define_bool CONFIG_X86_FIND_SMP_CONFIG y
+fi
+
 endmenu
 
 source lib/Config.in
+
+if [ "$CONFIG_SMP" = "y" ]; then
+   define_bool CONFIG_X86_SMP y
+   define_bool CONFIG_X86_HT y
+fi
+
+define_bool CONFIG_X86_BIOS_REBOOT y
diff --git a/arch/i386/generic/Makefile b/arch/i386/generic/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..8c8c8856d9361dca7cdf5241b77203cd88c68b92
--- /dev/null
+++ b/arch/i386/generic/Makefile
@@ -0,0 +1,24 @@
+#
+# Makefile for the linux kernel.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definitions are now in the main makefile...
+
+.S.o:
+	$(CC) $(AFLAGS) -traditional -c $< -o $*.o
+
+all: generic.o
+
+O_TARGET 	:= generic.o
+EXTRA_CFLAGS	+= -I../kernel
+export-objs     := 
+
+obj-y				:= setup.o
+
+obj-$(CONFIG_PCI)		+= pci-pc.o pci-irq.o
+obj-$(CONFIG_X86_LOCAL_APIC)	+= mpparse.o
+
+include $(TOPDIR)/Rules.make
diff --git a/arch/i386/generic/do_timer.h b/arch/i386/generic/do_timer.h
new file mode 100644
index 0000000000000000000000000000000000000000..8b6be13a9f18049a1becbb86dca0215d93f562d9
--- /dev/null
+++ b/arch/i386/generic/do_timer.h
@@ -0,0 +1,61 @@
+/* defines for inline arch setup functions */
+
+static inline void do_timer_interrupt_hook(struct pt_regs *regs)
+{
+	do_timer(regs);
+/*
+ * In the SMP case we use the local APIC timer interrupt to do the
+ * profiling, except when we simulate SMP mode on a uniprocessor
+ * system, in that case we have to call the local interrupt handler.
+ */
+#ifndef CONFIG_X86_LOCAL_APIC
+	if (!user_mode(regs))
+		x86_do_profile(regs->eip);
+#else
+	if (!using_apic_timer)
+		smp_local_timer_interrupt(regs);
+#endif
+}
+
+
+/* you can safely undefine this if you don't have the Neptune chipset */
+
+#define BUGGY_NEPTUN_TIMER
+
+static inline int do_timer_overflow(int count)
+{
+	int i;
+
+	spin_lock(&i8259A_lock);
+	/*
+	 * This is tricky when I/O APICs are used;
+	 * see do_timer_interrupt().
+	 */
+	i = inb(0x20);
+	spin_unlock(&i8259A_lock);
+	
+	/* assumption about timer being IRQ0 */
+	if (i & 0x01) {
+		/*
+		 * We cannot detect lost timer interrupts ... 
+		 * well, that's why we call them lost, don't we? :)
+		 * [hmm, on the Pentium and Alpha we can ... sort of]
+		 */
+		count -= LATCH;
+	} else {
+#ifdef BUGGY_NEPTUN_TIMER
+		/*
+		 * for the Neptun bug we know that the 'latch'
+		 * command doesnt latch the high and low value
+		 * of the counter atomically. Thus we have to 
+		 * substract 256 from the counter 
+		 * ... funny, isnt it? :)
+		 */
+		
+		count -= 256;
+#else
+		printk("do_slow_gettimeoffset(): hardware timer problem?\n");
+#endif
+	}
+	return count;
+}
diff --git a/arch/i386/generic/entry_arch.h b/arch/i386/generic/entry_arch.h
new file mode 100644
index 0000000000000000000000000000000000000000..7aba091465055f054544258bb27109afc62f8a03
--- /dev/null
+++ b/arch/i386/generic/entry_arch.h
@@ -0,0 +1,28 @@
+/*
+ * 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)
+ */
+#ifdef CONFIG_X86_SMP
+BUILD_INTERRUPT(reschedule_interrupt,RESCHEDULE_VECTOR)
+BUILD_INTERRUPT(invalidate_interrupt,INVALIDATE_TLB_VECTOR)
+BUILD_INTERRUPT(call_function_interrupt,CALL_FUNCTION_VECTOR)
+#endif
+
+/*
+ * every pentium local APIC has two 'local interrupts', with a
+ * soft-definable vector attached to both interrupts, one of
+ * which is a timer interrupt, the other one is error counter
+ * overflow. Linux uses the local APIC timer interrupt to get
+ * a much simpler SMP time architecture:
+ */
+#ifdef CONFIG_X86_LOCAL_APIC
+BUILD_INTERRUPT(apic_timer_interrupt,LOCAL_TIMER_VECTOR)
+BUILD_INTERRUPT(error_interrupt,ERROR_APIC_VECTOR)
+BUILD_INTERRUPT(spurious_interrupt,SPURIOUS_APIC_VECTOR)
+
+#ifdef CONFIG_X86_MCE_P4THERMAL
+BUILD_INTERRUPT(thermal_interrupt,THERMAL_APIC_VECTOR)
+#endif
+
+#endif
diff --git a/include/asm-i386/irq_vectors.h b/arch/i386/generic/irq_vectors.h
similarity index 100%
rename from include/asm-i386/irq_vectors.h
rename to arch/i386/generic/irq_vectors.h
diff --git a/arch/i386/kernel/mpparse.c b/arch/i386/generic/mpparse.c
similarity index 97%
rename from arch/i386/kernel/mpparse.c
rename to arch/i386/generic/mpparse.c
index 2949050f2b243694a4e3af03a592a605f133f3cd..3091aee164833c9fdb7e62933d4c48a6028a9ce0 100644
--- a/arch/i386/kernel/mpparse.c
+++ b/arch/i386/generic/mpparse.c
@@ -73,7 +73,7 @@ unsigned long phys_cpu_present_map;
  * Intel MP BIOS table parsing routines:
  */
 
-#ifndef CONFIG_X86_VISWS_APIC
+
 /*
  * Checksum an MP configuration block.
  */
@@ -775,7 +775,7 @@ static int __init smp_scan_config (unsigned long base, unsigned long length)
 	return 0;
 }
 
-void __init find_intel_smp (void)
+void __init find_smp_config (void)
 {
 	unsigned int address;
 
@@ -815,40 +815,6 @@ void __init find_intel_smp (void)
 		printk(KERN_WARNING "WARNING: MP table in the EBDA can be UNSAFE, contact linux-smp@vger.kernel.org if you experience SMP problems!\n");
 }
 
-#else
-
-/*
- * The Visual Workstation is Intel MP compliant in the hardware
- * sense, but it doesnt have a BIOS(-configuration table).
- * No problem for Linux.
- */
-void __init find_visws_smp(void)
-{
-	smp_found_config = 1;
-
-	phys_cpu_present_map |= 2; /* or in id 1 */
-	apic_version[1] |= 0x10; /* integrated APIC */
-	apic_version[0] |= 0x10;
-
-	mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
-}
-
-#endif
-
-/*
- * - Intel MP Configuration Table
- * - or SGI Visual Workstation configuration
- */
-void __init find_smp_config (void)
-{
-#ifdef CONFIG_X86_LOCAL_APIC
-	find_intel_smp();
-#endif
-#ifdef CONFIG_VISWS
-	find_visws_smp();
-#endif
-}
-
 
 /* --------------------------------------------------------------------------
                             ACPI-based MP Configuration
diff --git a/arch/i386/generic/setup.c b/arch/i386/generic/setup.c
new file mode 100644
index 0000000000000000000000000000000000000000..120baf3280ff1a79ec2d82418007f573217b2893
--- /dev/null
+++ b/arch/i386/generic/setup.c
@@ -0,0 +1,56 @@
+/*
+ *	Machine specific setup for generic
+ */
+
+#include <linux/config.h>
+#include <linux/smp.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <asm/arch_hooks.h>
+
+void __init pre_intr_init_hook(void)
+{
+	init_ISA_irqs();
+}
+
+/*
+ * IRQ2 is cascade interrupt to second interrupt controller
+ */
+static struct irqaction irq2 = { no_action, 0, 0, "cascade", NULL, NULL};
+
+void __init intr_init_hook(void)
+{
+#ifdef CONFIG_X86_LOCAL_APIC
+	apic_intr_init();
+#endif
+
+	setup_irq(2, &irq2);
+}
+
+void __init pre_setup_arch_hook(void)
+{
+}
+
+void __init trap_init_hook(void)
+{
+}
+
+static struct irqaction irq0  = { timer_interrupt, SA_INTERRUPT, 0, "timer", NULL, NULL};
+
+void __init time_init_hook(void)
+{
+	setup_irq(0, &irq0);
+}
+
+#ifdef CONFIG_MCA
+void __init mca_nmi_hook(void)
+{
+	/* If I recall correctly, there's a whole bunch of other things that
+	 * we can do to check for NMI problems, but that's all I know about
+	 * at the moment.
+	 */
+
+	printk("NMI generated from unknown source!\n");
+}
+#endif
diff --git a/arch/i386/generic/setup_arch_post.h b/arch/i386/generic/setup_arch_post.h
new file mode 100644
index 0000000000000000000000000000000000000000..e8611ae44c451b51e702eda7a3e826138823de7d
--- /dev/null
+++ b/arch/i386/generic/setup_arch_post.h
@@ -0,0 +1,37 @@
+/* Hook for machine specific memory setup.
+ *
+ * This is included late in kernel/setup.c so that it can make use of all of
+ * the static functions. */
+
+static inline char * __init machine_specific_memory_setup(void)
+{
+	char *who;
+
+
+	who = "BIOS-e820";
+
+	/*
+	 * Try to copy the BIOS-supplied E820-map.
+	 *
+	 * Otherwise fake a memory map; one section from 0k->640k,
+	 * the next section from 1mb->appropriate_mem_k
+	 */
+	sanitize_e820_map(E820_MAP, &E820_MAP_NR);
+	if (copy_e820_map(E820_MAP, E820_MAP_NR) < 0) {
+		unsigned long mem_size;
+
+		/* compare results from other methods and take the greater */
+		if (ALT_MEM_K < EXT_MEM_K) {
+			mem_size = EXT_MEM_K;
+			who = "BIOS-88";
+		} else {
+			mem_size = ALT_MEM_K;
+			who = "BIOS-e801";
+		}
+
+		e820.nr_map = 0;
+		add_memory_region(0, LOWMEMSIZE(), E820_RAM);
+		add_memory_region(HIGH_MEMORY, mem_size << 10, E820_RAM);
+  	}
+	return who;
+}
diff --git a/arch/i386/generic/setup_arch_pre.h b/arch/i386/generic/setup_arch_pre.h
new file mode 100644
index 0000000000000000000000000000000000000000..fb42099e7bd4eb043ceaaea57d12e5391c40dd7e
--- /dev/null
+++ b/arch/i386/generic/setup_arch_pre.h
@@ -0,0 +1,5 @@
+/* Hook to call BIOS initialisation function */
+
+/* no action for generic */
+
+#define ARCH_SETUP
diff --git a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile
index 9f534753206228f065e3bafb2c111a20373017f7..a34811c54f6955c4075bf8bccf6a20ecaa4c028d 100644
--- a/arch/i386/kernel/Makefile
+++ b/arch/i386/kernel/Makefile
@@ -13,21 +13,16 @@ obj-y	:= process.o semaphore.o signal.o entry.o traps.o irq.o vm86.o \
 		pci-dma.o i386_ksyms.o i387.o bluesmoke.o dmi_scan.o \
 		bootflag.o
 
+obj-$(CONFIG_X86_BIOS_REBOOT)	+= reboot.o
 obj-$(CONFIG_MCA)		+= mca.o
 obj-$(CONFIG_MTRR)		+= mtrr.o
 obj-$(CONFIG_X86_MSR)		+= msr.o
 obj-$(CONFIG_X86_CPUID)		+= cpuid.o
 obj-$(CONFIG_MICROCODE)		+= microcode.o
 obj-$(CONFIG_APM)		+= apm.o
-obj-$(CONFIG_ACPI)		+= acpi.o
-obj-$(CONFIG_ACPI_SLEEP)	+= acpi_wakeup.o
-obj-$(CONFIG_SMP)		+= smp.o smpboot.o trampoline.o
-obj-$(CONFIG_X86_LOCAL_APIC)	+= mpparse.o apic.o nmi.o
+obj-$(CONFIG_X86_SMP)		+= smp.o smpboot.o trampoline.o
+obj-$(CONFIG_X86_LOCAL_APIC)	+= apic.o nmi.o
 obj-$(CONFIG_X86_IO_APIC)	+= io_apic.o
-ifdef CONFIG_VISWS
-obj-y += setup-visws.o
-obj-$(CONFIG_X86_VISWS_APIC)	+= visws_apic.o
-endif
 
 EXTRA_AFLAGS	:= -traditional
 
diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c
index cb9370c0e790aed12ec317a04f1bcddab5b113e4..56be183b369e1edea67ff1e2a37f0ba4fb6e9f99 100644
--- a/arch/i386/kernel/apic.c
+++ b/arch/i386/kernel/apic.c
@@ -29,6 +29,21 @@
 #include <asm/mtrr.h>
 #include <asm/mpspec.h>
 #include <asm/pgalloc.h>
+#include <asm/desc.h>
+#include <asm/arch_hooks.h>
+
+void __init apic_intr_init(void)
+{
+#ifdef CONFIG_SMP
+	smp_intr_init();
+#endif
+	/* self generated IPI for local APIC timer */
+	set_intr_gate(LOCAL_TIMER_VECTOR, apic_timer_interrupt);
+
+	/* IPI vectors for APIC spurious and error interrupts */
+	set_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt);
+	set_intr_gate(ERROR_APIC_VECTOR, error_interrupt);
+}
 
 /* Using APIC to generate smp_local_timer_interrupt? */
 int using_apic_timer = 0;
diff --git a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S
index 375961512766a17ac9ae2b2e89a3b497f31d6f70..49ddc2a98632cf9a6373a88e0c632a274f71840c 100644
--- a/arch/i386/kernel/entry.S
+++ b/arch/i386/kernel/entry.S
@@ -47,7 +47,7 @@
 #include <asm/errno.h>
 #include <asm/segment.h>
 #include <asm/smp.h>
-#include <asm/irq_vectors.h>
+#include "irq_vectors.h"
 
 EBX		= 0x00
 ECX		= 0x04
@@ -373,34 +373,8 @@ ENTRY(name)				\
 	call smp_/**/name;	\
 	jmp ret_from_intr;
 
-/*
- * 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)
- */
-#ifdef CONFIG_SMP
-BUILD_INTERRUPT(reschedule_interrupt,RESCHEDULE_VECTOR)
-BUILD_INTERRUPT(invalidate_interrupt,INVALIDATE_TLB_VECTOR)
-BUILD_INTERRUPT(call_function_interrupt,CALL_FUNCTION_VECTOR)
-#endif
-
-/*
- * every pentium local APIC has two 'local interrupts', with a
- * soft-definable vector attached to both interrupts, one of
- * which is a timer interrupt, the other one is error counter
- * overflow. Linux uses the local APIC timer interrupt to get
- * a much simpler SMP time architecture:
- */
-#ifdef CONFIG_X86_LOCAL_APIC
-BUILD_INTERRUPT(apic_timer_interrupt,LOCAL_TIMER_VECTOR)
-BUILD_INTERRUPT(error_interrupt,ERROR_APIC_VECTOR)
-BUILD_INTERRUPT(spurious_interrupt,SPURIOUS_APIC_VECTOR)
-
-#ifdef CONFIG_X86_MCE_P4THERMAL
-BUILD_INTERRUPT(thermal_interrupt,THERMAL_APIC_VECTOR)
-#endif
-
-#endif
+/* The include is where all of the SMP etc. interrupts come from */
+#include "entry_arch.h"
 
 ENTRY(divide_error)
 	pushl $0			# no error code
diff --git a/arch/i386/kernel/i8259.c b/arch/i386/kernel/i8259.c
index 1cbfe2e706b523eabc00bfdc226b425c42c77ce7..5fc15adb268fa7329a82ca4d549ff32deb5b4c00 100644
--- a/arch/i386/kernel/i8259.c
+++ b/arch/i386/kernel/i8259.c
@@ -22,6 +22,7 @@
 #include <asm/delay.h>
 #include <asm/desc.h>
 #include <asm/apic.h>
+#include <asm/arch_hooks.h>
 
 #include <linux/irq.h>
 
@@ -320,15 +321,6 @@ static void math_error_irq(int cpl, void *dev_id, struct pt_regs *regs)
  */
 static struct irqaction irq13 = { math_error_irq, 0, 0, "fpu", NULL, NULL };
 
-/*
- * IRQ2 is cascade interrupt to second interrupt controller
- */
-
-#ifndef CONFIG_VISWS
-static struct irqaction irq2 = { no_action, 0, 0, "cascade", NULL, NULL};
-#endif
-
-
 void __init init_ISA_irqs (void)
 {
 	int i;
@@ -361,11 +353,9 @@ void __init init_IRQ(void)
 {
 	int i;
 
-#ifndef CONFIG_X86_VISWS_APIC
-	init_ISA_irqs();
-#else
-	init_VISWS_APIC_irqs();
-#endif
+	/* all the set up before the call gates are initialised */
+	pre_intr_init_hook();
+
 	/*
 	 * Cover the whole vector space, no vector can escape
 	 * us. (some of these will be overridden and become
@@ -377,39 +367,9 @@ void __init init_IRQ(void)
 			set_intr_gate(vector, interrupt[i]);
 	}
 
-#ifdef CONFIG_SMP
-	/*
-	 * IRQ0 must be given a fixed assignment and initialized,
-	 * because it's used before the IO-APIC is set up.
-	 */
-	set_intr_gate(FIRST_DEVICE_VECTOR, interrupt[0]);
-
-	/*
-	 * The reschedule interrupt is a CPU-to-CPU reschedule-helper
-	 * IPI, driven by wakeup.
-	 */
-	set_intr_gate(RESCHEDULE_VECTOR, reschedule_interrupt);
-
-	/* IPI for invalidation */
-	set_intr_gate(INVALIDATE_TLB_VECTOR, invalidate_interrupt);
-
-	/* IPI for generic function call */
-	set_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt);
-#endif	
-
-#ifdef CONFIG_X86_LOCAL_APIC
-	/* self generated IPI for local APIC timer */
-	set_intr_gate(LOCAL_TIMER_VECTOR, apic_timer_interrupt);
-
-	/* IPI vectors for APIC spurious and error interrupts */
-	set_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt);
-	set_intr_gate(ERROR_APIC_VECTOR, error_interrupt);
-
-	/* thermal monitor LVT interrupt */
-#ifdef CONFIG_X86_MCE_P4THERMAL
-	set_intr_gate(THERMAL_APIC_VECTOR, thermal_interrupt);
-#endif
-#endif
+	/* setup after call gates are initialised (usually add in
+	 * the architecture specific gates */
+	intr_init_hook();
 
 	/*
 	 * Set the clock to HZ Hz, we already have a valid
@@ -419,10 +379,6 @@ void __init init_IRQ(void)
 	outb_p(LATCH & 0xff , 0x40);	/* LSB */
 	outb(LATCH >> 8 , 0x40);	/* MSB */
 
-#ifndef CONFIG_VISWS
-	setup_irq(2, &irq2);
-#endif
-
 	/*
 	 * External FPU? Set up irq13 if so, for
 	 * original braindamaged IBM FERR coupling.
diff --git a/arch/i386/kernel/mca.c b/arch/i386/kernel/mca.c
index dc7db1cdce4cca2cd52855bf8daddb9f4f3a9dab..ea377ee171d09a1fdec3072a404929b265617b26 100644
--- a/arch/i386/kernel/mca.c
+++ b/arch/i386/kernel/mca.c
@@ -52,6 +52,7 @@
 #include <linux/ioport.h>
 #include <asm/uaccess.h>
 #include <linux/init.h>
+#include <asm/arch_hooks.h>
 
 /* This structure holds MCA information. Each (plug-in) adapter has
  * eight POS registers. Then the machine may have integrated video and
@@ -371,12 +372,7 @@ void mca_handle_nmi(void)
 		}
 	}
 
-	/* If I recall correctly, there's a whole bunch of other things that
-	 * we can do to check for NMI problems, but that's all I know about
-	 * at the moment.
-	 */
-
-	printk("NMI generated from unknown source!\n");
+	mca_nmi_hook();
 } /* mca_handle_nmi */
 
 /*--------------------------------------------------------------------*/
diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
index ad92945381e351ee3bc14cb94f24490964f6017f..0d7585de2eb871c27ce235026316e01dc561cb57 100644
--- a/arch/i386/kernel/process.c
+++ b/arch/i386/kernel/process.c
@@ -67,11 +67,6 @@ unsigned long thread_saved_pc(struct task_struct *tsk)
  */
 void (*pm_idle)(void);
 
-/*
- * Power off function, if any
- */
-void (*pm_power_off)(void);
-
 void disable_hlt(void)
 {
 	hlt_counter++;
@@ -161,287 +156,6 @@ static int __init idle_setup (char *str)
 
 __setup("idle=", idle_setup);
 
-static long no_idt[2];
-static int reboot_mode;
-int reboot_thru_bios;
-
-#ifdef CONFIG_SMP
-int reboot_smp = 0;
-static int reboot_cpu = -1;
-/* shamelessly grabbed from lib/vsprintf.c for readability */
-#define is_digit(c)	((c) >= '0' && (c) <= '9')
-#endif
-static int __init reboot_setup(char *str)
-{
-	while(1) {
-		switch (*str) {
-		case 'w': /* "warm" reboot (no memory testing etc) */
-			reboot_mode = 0x1234;
-			break;
-		case 'c': /* "cold" reboot (with memory testing etc) */
-			reboot_mode = 0x0;
-			break;
-		case 'b': /* "bios" reboot by jumping through the BIOS */
-			reboot_thru_bios = 1;
-			break;
-		case 'h': /* "hard" reboot by toggling RESET and/or crashing the CPU */
-			reboot_thru_bios = 0;
-			break;
-#ifdef CONFIG_SMP
-		case 's': /* "smp" reboot by executing reset on BSP or other CPU*/
-			reboot_smp = 1;
-			if (is_digit(*(str+1))) {
-				reboot_cpu = (int) (*(str+1) - '0');
-				if (is_digit(*(str+2))) 
-					reboot_cpu = reboot_cpu*10 + (int)(*(str+2) - '0');
-			}
-				/* we will leave sorting out the final value 
-				when we are ready to reboot, since we might not
- 				have set up boot_cpu_id or smp_num_cpu */
-			break;
-#endif
-		}
-		if((str = strchr(str,',')) != NULL)
-			str++;
-		else
-			break;
-	}
-	return 1;
-}
-
-__setup("reboot=", reboot_setup);
-
-/* The following code and data reboots the machine by switching to real
-   mode and jumping to the BIOS reset entry point, as if the CPU has
-   really been reset.  The previous version asked the keyboard
-   controller to pulse the CPU reset line, which is more thorough, but
-   doesn't work with at least one type of 486 motherboard.  It is easy
-   to stop this code working; hence the copious comments. */
-
-static unsigned long long
-real_mode_gdt_entries [3] =
-{
-	0x0000000000000000ULL,	/* Null descriptor */
-	0x00009a000000ffffULL,	/* 16-bit real-mode 64k code at 0x00000000 */
-	0x000092000100ffffULL	/* 16-bit real-mode 64k data at 0x00000100 */
-};
-
-static struct
-{
-	unsigned short       size __attribute__ ((packed));
-	unsigned long long * base __attribute__ ((packed));
-}
-real_mode_gdt = { sizeof (real_mode_gdt_entries) - 1, real_mode_gdt_entries },
-real_mode_idt = { 0x3ff, 0 };
-
-/* This is 16-bit protected mode code to disable paging and the cache,
-   switch to real mode and jump to the BIOS reset code.
-
-   The instruction that switches to real mode by writing to CR0 must be
-   followed immediately by a far jump instruction, which set CS to a
-   valid value for real mode, and flushes the prefetch queue to avoid
-   running instructions that have already been decoded in protected
-   mode.
-
-   Clears all the flags except ET, especially PG (paging), PE
-   (protected-mode enable) and TS (task switch for coprocessor state
-   save).  Flushes the TLB after paging has been disabled.  Sets CD and
-   NW, to disable the cache on a 486, and invalidates the cache.  This
-   is more like the state of a 486 after reset.  I don't know if
-   something else should be done for other chips.
-
-   More could be done here to set up the registers as if a CPU reset had
-   occurred; hopefully real BIOSs don't assume much. */
-
-static unsigned char real_mode_switch [] =
-{
-	0x66, 0x0f, 0x20, 0xc0,			/*    movl  %cr0,%eax        */
-	0x66, 0x83, 0xe0, 0x11,			/*    andl  $0x00000011,%eax */
-	0x66, 0x0d, 0x00, 0x00, 0x00, 0x60,	/*    orl   $0x60000000,%eax */
-	0x66, 0x0f, 0x22, 0xc0,			/*    movl  %eax,%cr0        */
-	0x66, 0x0f, 0x22, 0xd8,			/*    movl  %eax,%cr3        */
-	0x66, 0x0f, 0x20, 0xc3,			/*    movl  %cr0,%ebx        */
-	0x66, 0x81, 0xe3, 0x00, 0x00, 0x00, 0x60,	/*    andl  $0x60000000,%ebx */
-	0x74, 0x02,				/*    jz    f                */
-	0x0f, 0x08,				/*    invd                   */
-	0x24, 0x10,				/* f: andb  $0x10,al         */
-	0x66, 0x0f, 0x22, 0xc0			/*    movl  %eax,%cr0        */
-};
-static unsigned char jump_to_bios [] =
-{
-	0xea, 0x00, 0x00, 0xff, 0xff		/*    ljmp  $0xffff,$0x0000  */
-};
-
-static inline void kb_wait(void)
-{
-	int i;
-
-	for (i=0; i<0x10000; i++)
-		if ((inb_p(0x64) & 0x02) == 0)
-			break;
-}
-
-/*
- * Switch to real mode and then execute the code
- * specified by the code and length parameters.
- * We assume that length will aways be less that 100!
- */
-void machine_real_restart(unsigned char *code, int length)
-{
-	unsigned long flags;
-
-	cli();
-
-	/* Write zero to CMOS register number 0x0f, which the BIOS POST
-	   routine will recognize as telling it to do a proper reboot.  (Well
-	   that's what this book in front of me says -- it may only apply to
-	   the Phoenix BIOS though, it's not clear).  At the same time,
-	   disable NMIs by setting the top bit in the CMOS address register,
-	   as we're about to do peculiar things to the CPU.  I'm not sure if
-	   `outb_p' is needed instead of just `outb'.  Use it to be on the
-	   safe side.  (Yes, CMOS_WRITE does outb_p's. -  Paul G.)
-	 */
-
-	spin_lock_irqsave(&rtc_lock, flags);
-	CMOS_WRITE(0x00, 0x8f);
-	spin_unlock_irqrestore(&rtc_lock, flags);
-
-	/* Remap the kernel at virtual address zero, as well as offset zero
-	   from the kernel segment.  This assumes the kernel segment starts at
-	   virtual address PAGE_OFFSET. */
-
-	memcpy (swapper_pg_dir, swapper_pg_dir + USER_PGD_PTRS,
-		sizeof (swapper_pg_dir [0]) * KERNEL_PGD_PTRS);
-
-	/* Make sure the first page is mapped to the start of physical memory.
-	   It is normally not mapped, to trap kernel NULL pointer dereferences. */
-
-	pg0[0] = _PAGE_RW | _PAGE_PRESENT;
-
-	/*
-	 * Use `swapper_pg_dir' as our page directory.
-	 */
-	load_cr3(swapper_pg_dir);
-
-	/* Write 0x1234 to absolute memory location 0x472.  The BIOS reads
-	   this on booting to tell it to "Bypass memory test (also warm
-	   boot)".  This seems like a fairly standard thing that gets set by
-	   REBOOT.COM programs, and the previous reset routine did this
-	   too. */
-
-	*((unsigned short *)0x472) = reboot_mode;
-
-	/* For the switch to real mode, copy some code to low memory.  It has
-	   to be in the first 64k because it is running in 16-bit mode, and it
-	   has to have the same physical and virtual address, because it turns
-	   off paging.  Copy it near the end of the first page, out of the way
-	   of BIOS variables. */
-
-	memcpy ((void *) (0x1000 - sizeof (real_mode_switch) - 100),
-		real_mode_switch, sizeof (real_mode_switch));
-	memcpy ((void *) (0x1000 - 100), code, length);
-
-	/* Set up the IDT for real mode. */
-
-	__asm__ __volatile__ ("lidt %0" : : "m" (real_mode_idt));
-
-	/* Set up a GDT from which we can load segment descriptors for real
-	   mode.  The GDT is not used in real mode; it is just needed here to
-	   prepare the descriptors. */
-
-	__asm__ __volatile__ ("lgdt %0" : : "m" (real_mode_gdt));
-
-	/* Load the data segment registers, and thus the descriptors ready for
-	   real mode.  The base address of each segment is 0x100, 16 times the
-	   selector value being loaded here.  This is so that the segment
-	   registers don't have to be reloaded after switching to real mode:
-	   the values are consistent for real mode operation already. */
-
-	__asm__ __volatile__ ("movl $0x0010,%%eax\n"
-				"\tmovl %%eax,%%ds\n"
-				"\tmovl %%eax,%%es\n"
-				"\tmovl %%eax,%%fs\n"
-				"\tmovl %%eax,%%gs\n"
-				"\tmovl %%eax,%%ss" : : : "eax");
-
-	/* Jump to the 16-bit code that we copied earlier.  It disables paging
-	   and the cache, switches to real mode, and jumps to the BIOS reset
-	   entry point. */
-
-	__asm__ __volatile__ ("ljmp $0x0008,%0"
-				:
-				: "i" ((void *) (0x1000 - sizeof (real_mode_switch) - 100)));
-}
-
-void machine_restart(char * __unused)
-{
-#if CONFIG_SMP
-	int cpuid;
-	
-	cpuid = GET_APIC_ID(apic_read(APIC_ID));
-
-	if (reboot_smp) {
-
-		/* check to see if reboot_cpu is valid 
-		   if its not, default to the BSP */
-		if ((reboot_cpu == -1) ||  
-		      (reboot_cpu > (NR_CPUS -1))  || 
-		      !(phys_cpu_present_map & (1<<cpuid))) 
-			reboot_cpu = boot_cpu_physical_apicid;
-
-		reboot_smp = 0;  /* use this as a flag to only go through this once*/
-		/* re-run this function on the other CPUs
-		   it will fall though this section since we have 
-		   cleared reboot_smp, and do the reboot if it is the
-		   correct CPU, otherwise it halts. */
-		if (reboot_cpu != cpuid)
-			smp_call_function((void *)machine_restart , NULL, 1, 0);
-	}
-
-	/* if reboot_cpu is still -1, then we want a tradional reboot, 
-	   and if we are not running on the reboot_cpu,, halt */
-	if ((reboot_cpu != -1) && (cpuid != reboot_cpu)) {
-		for (;;)
-		__asm__ __volatile__ ("hlt");
-	}
-	/*
-	 * Stop all CPUs and turn off local APICs and the IO-APIC, so
-	 * other OSs see a clean IRQ state.
-	 */
-	smp_send_stop();
-	disable_IO_APIC();
-#endif
-
-	if(!reboot_thru_bios) {
-		/* rebooting needs to touch the page at absolute addr 0 */
-		*((unsigned short *)__va(0x472)) = reboot_mode;
-		for (;;) {
-			int i;
-			for (i=0; i<100; i++) {
-				kb_wait();
-				udelay(50);
-				outb(0xfe,0x64);         /* pulse reset low */
-				udelay(50);
-			}
-			/* That didn't work - force a triple fault.. */
-			__asm__ __volatile__("lidt %0": :"m" (no_idt));
-			__asm__ __volatile__("int3");
-		}
-	}
-
-	machine_real_restart(jump_to_bios, sizeof(jump_to_bios));
-}
-
-void machine_halt(void)
-{
-}
-
-void machine_power_off(void)
-{
-	if (pm_power_off)
-		pm_power_off();
-}
-
 extern void show_trace(unsigned long* esp);
 
 void show_regs(struct pt_regs * regs)
diff --git a/arch/i386/kernel/reboot.c b/arch/i386/kernel/reboot.c
new file mode 100644
index 0000000000000000000000000000000000000000..e50586593622dacbe72b148e6174a3c13f36afa4
--- /dev/null
+++ b/arch/i386/kernel/reboot.c
@@ -0,0 +1,329 @@
+/*
+ *  linux/arch/i386/kernel/reboot.c
+ */
+
+#define __KERNEL_SYSCALLS__
+#include <stdarg.h>
+
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/stddef.h>
+#include <linux/unistd.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/user.h>
+#include <linux/a.out.h>
+#include <linux/interrupt.h>
+#include <linux/config.h>
+#include <linux/delay.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/mc146818rtc.h>
+
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/ldt.h>
+#include <asm/processor.h>
+#include <asm/i387.h>
+#include <asm/desc.h>
+#ifdef CONFIG_MATH_EMULATION
+#include <asm/math_emu.h>
+#endif
+
+#include <linux/irq.h>
+#include <linux/err.h>
+
+/*
+ * Power off function, if any
+ */
+void (*pm_power_off)(void);
+
+static long no_idt[2];
+static int reboot_mode;
+int reboot_thru_bios;
+
+#ifdef CONFIG_SMP
+int reboot_smp = 0;
+static int reboot_cpu = -1;
+/* shamelessly grabbed from lib/vsprintf.c for readability */
+#define is_digit(c)	((c) >= '0' && (c) <= '9')
+#endif
+static int __init reboot_setup(char *str)
+{
+	while(1) {
+		switch (*str) {
+		case 'w': /* "warm" reboot (no memory testing etc) */
+			reboot_mode = 0x1234;
+			break;
+		case 'c': /* "cold" reboot (with memory testing etc) */
+			reboot_mode = 0x0;
+			break;
+		case 'b': /* "bios" reboot by jumping through the BIOS */
+			reboot_thru_bios = 1;
+			break;
+		case 'h': /* "hard" reboot by toggling RESET and/or crashing the CPU */
+			reboot_thru_bios = 0;
+			break;
+#ifdef CONFIG_SMP
+		case 's': /* "smp" reboot by executing reset on BSP or other CPU*/
+			reboot_smp = 1;
+			if (is_digit(*(str+1))) {
+				reboot_cpu = (int) (*(str+1) - '0');
+				if (is_digit(*(str+2))) 
+					reboot_cpu = reboot_cpu*10 + (int)(*(str+2) - '0');
+			}
+				/* we will leave sorting out the final value 
+				when we are ready to reboot, since we might not
+ 				have set up boot_cpu_id or smp_num_cpu */
+			break;
+#endif
+		}
+		if((str = strchr(str,',')) != NULL)
+			str++;
+		else
+			break;
+	}
+	return 1;
+}
+
+__setup("reboot=", reboot_setup);
+
+/* The following code and data reboots the machine by switching to real
+   mode and jumping to the BIOS reset entry point, as if the CPU has
+   really been reset.  The previous version asked the keyboard
+   controller to pulse the CPU reset line, which is more thorough, but
+   doesn't work with at least one type of 486 motherboard.  It is easy
+   to stop this code working; hence the copious comments. */
+
+static unsigned long long
+real_mode_gdt_entries [3] =
+{
+	0x0000000000000000ULL,	/* Null descriptor */
+	0x00009a000000ffffULL,	/* 16-bit real-mode 64k code at 0x00000000 */
+	0x000092000100ffffULL	/* 16-bit real-mode 64k data at 0x00000100 */
+};
+
+static struct
+{
+	unsigned short       size __attribute__ ((packed));
+	unsigned long long * base __attribute__ ((packed));
+}
+real_mode_gdt = { sizeof (real_mode_gdt_entries) - 1, real_mode_gdt_entries },
+real_mode_idt = { 0x3ff, 0 };
+
+/* This is 16-bit protected mode code to disable paging and the cache,
+   switch to real mode and jump to the BIOS reset code.
+
+   The instruction that switches to real mode by writing to CR0 must be
+   followed immediately by a far jump instruction, which set CS to a
+   valid value for real mode, and flushes the prefetch queue to avoid
+   running instructions that have already been decoded in protected
+   mode.
+
+   Clears all the flags except ET, especially PG (paging), PE
+   (protected-mode enable) and TS (task switch for coprocessor state
+   save).  Flushes the TLB after paging has been disabled.  Sets CD and
+   NW, to disable the cache on a 486, and invalidates the cache.  This
+   is more like the state of a 486 after reset.  I don't know if
+   something else should be done for other chips.
+
+   More could be done here to set up the registers as if a CPU reset had
+   occurred; hopefully real BIOSs don't assume much. */
+
+static unsigned char real_mode_switch [] =
+{
+	0x66, 0x0f, 0x20, 0xc0,			/*    movl  %cr0,%eax        */
+	0x66, 0x83, 0xe0, 0x11,			/*    andl  $0x00000011,%eax */
+	0x66, 0x0d, 0x00, 0x00, 0x00, 0x60,	/*    orl   $0x60000000,%eax */
+	0x66, 0x0f, 0x22, 0xc0,			/*    movl  %eax,%cr0        */
+	0x66, 0x0f, 0x22, 0xd8,			/*    movl  %eax,%cr3        */
+	0x66, 0x0f, 0x20, 0xc3,			/*    movl  %cr0,%ebx        */
+	0x66, 0x81, 0xe3, 0x00, 0x00, 0x00, 0x60,	/*    andl  $0x60000000,%ebx */
+	0x74, 0x02,				/*    jz    f                */
+	0x0f, 0x08,				/*    invd                   */
+	0x24, 0x10,				/* f: andb  $0x10,al         */
+	0x66, 0x0f, 0x22, 0xc0			/*    movl  %eax,%cr0        */
+};
+static unsigned char jump_to_bios [] =
+{
+	0xea, 0x00, 0x00, 0xff, 0xff		/*    ljmp  $0xffff,$0x0000  */
+};
+
+static inline void kb_wait(void)
+{
+	int i;
+
+	for (i=0; i<0x10000; i++)
+		if ((inb_p(0x64) & 0x02) == 0)
+			break;
+}
+
+/*
+ * Switch to real mode and then execute the code
+ * specified by the code and length parameters.
+ * We assume that length will aways be less that 100!
+ */
+void machine_real_restart(unsigned char *code, int length)
+{
+	unsigned long flags;
+
+	cli();
+
+	/* Write zero to CMOS register number 0x0f, which the BIOS POST
+	   routine will recognize as telling it to do a proper reboot.  (Well
+	   that's what this book in front of me says -- it may only apply to
+	   the Phoenix BIOS though, it's not clear).  At the same time,
+	   disable NMIs by setting the top bit in the CMOS address register,
+	   as we're about to do peculiar things to the CPU.  I'm not sure if
+	   `outb_p' is needed instead of just `outb'.  Use it to be on the
+	   safe side.  (Yes, CMOS_WRITE does outb_p's. -  Paul G.)
+	 */
+
+	spin_lock_irqsave(&rtc_lock, flags);
+	CMOS_WRITE(0x00, 0x8f);
+	spin_unlock_irqrestore(&rtc_lock, flags);
+
+	/* Remap the kernel at virtual address zero, as well as offset zero
+	   from the kernel segment.  This assumes the kernel segment starts at
+	   virtual address PAGE_OFFSET. */
+
+	memcpy (swapper_pg_dir, swapper_pg_dir + USER_PGD_PTRS,
+		sizeof (swapper_pg_dir [0]) * KERNEL_PGD_PTRS);
+
+	/* Make sure the first page is mapped to the start of physical memory.
+	   It is normally not mapped, to trap kernel NULL pointer dereferences. */
+
+	pg0[0] = _PAGE_RW | _PAGE_PRESENT;
+
+	/*
+	 * Use `swapper_pg_dir' as our page directory.
+	 */
+	load_cr3(swapper_pg_dir);
+
+	/* Write 0x1234 to absolute memory location 0x472.  The BIOS reads
+	   this on booting to tell it to "Bypass memory test (also warm
+	   boot)".  This seems like a fairly standard thing that gets set by
+	   REBOOT.COM programs, and the previous reset routine did this
+	   too. */
+
+	*((unsigned short *)0x472) = reboot_mode;
+
+	/* For the switch to real mode, copy some code to low memory.  It has
+	   to be in the first 64k because it is running in 16-bit mode, and it
+	   has to have the same physical and virtual address, because it turns
+	   off paging.  Copy it near the end of the first page, out of the way
+	   of BIOS variables. */
+
+	memcpy ((void *) (0x1000 - sizeof (real_mode_switch) - 100),
+		real_mode_switch, sizeof (real_mode_switch));
+	memcpy ((void *) (0x1000 - 100), code, length);
+
+	/* Set up the IDT for real mode. */
+
+	__asm__ __volatile__ ("lidt %0" : : "m" (real_mode_idt));
+
+	/* Set up a GDT from which we can load segment descriptors for real
+	   mode.  The GDT is not used in real mode; it is just needed here to
+	   prepare the descriptors. */
+
+	__asm__ __volatile__ ("lgdt %0" : : "m" (real_mode_gdt));
+
+	/* Load the data segment registers, and thus the descriptors ready for
+	   real mode.  The base address of each segment is 0x100, 16 times the
+	   selector value being loaded here.  This is so that the segment
+	   registers don't have to be reloaded after switching to real mode:
+	   the values are consistent for real mode operation already. */
+
+	__asm__ __volatile__ ("movl $0x0010,%%eax\n"
+				"\tmovl %%eax,%%ds\n"
+				"\tmovl %%eax,%%es\n"
+				"\tmovl %%eax,%%fs\n"
+				"\tmovl %%eax,%%gs\n"
+				"\tmovl %%eax,%%ss" : : : "eax");
+
+	/* Jump to the 16-bit code that we copied earlier.  It disables paging
+	   and the cache, switches to real mode, and jumps to the BIOS reset
+	   entry point. */
+
+	__asm__ __volatile__ ("ljmp $0x0008,%0"
+				:
+				: "i" ((void *) (0x1000 - sizeof (real_mode_switch) - 100)));
+}
+
+void machine_restart(char * __unused)
+{
+#if CONFIG_SMP
+	int cpuid;
+	
+	cpuid = GET_APIC_ID(apic_read(APIC_ID));
+
+	if (reboot_smp) {
+
+		/* check to see if reboot_cpu is valid 
+		   if its not, default to the BSP */
+		if ((reboot_cpu == -1) ||  
+		      (reboot_cpu > (NR_CPUS -1))  || 
+		      !(phys_cpu_present_map & (1<<cpuid))) 
+			reboot_cpu = boot_cpu_physical_apicid;
+
+		reboot_smp = 0;  /* use this as a flag to only go through this once*/
+		/* re-run this function on the other CPUs
+		   it will fall though this section since we have 
+		   cleared reboot_smp, and do the reboot if it is the
+		   correct CPU, otherwise it halts. */
+		if (reboot_cpu != cpuid)
+			smp_call_function((void *)machine_restart , NULL, 1, 0);
+	}
+
+	/* if reboot_cpu is still -1, then we want a tradional reboot, 
+	   and if we are not running on the reboot_cpu,, halt */
+	if ((reboot_cpu != -1) && (cpuid != reboot_cpu)) {
+		for (;;)
+		__asm__ __volatile__ ("hlt");
+	}
+	/*
+	 * Stop all CPUs and turn off local APICs and the IO-APIC, so
+	 * other OSs see a clean IRQ state.
+	 */
+	smp_send_stop();
+	disable_IO_APIC();
+#endif
+
+	if(!reboot_thru_bios) {
+		/* rebooting needs to touch the page at absolute addr 0 */
+		*((unsigned short *)__va(0x472)) = reboot_mode;
+		for (;;) {
+			int i;
+			for (i=0; i<100; i++) {
+				kb_wait();
+				udelay(50);
+				outb(0xfe,0x64);         /* pulse reset low */
+				udelay(50);
+			}
+			/* That didn't work - force a triple fault.. */
+			__asm__ __volatile__("lidt %0": :"m" (no_idt));
+			__asm__ __volatile__("int3");
+		}
+	}
+
+	machine_real_restart(jump_to_bios, sizeof(jump_to_bios));
+}
+
+void machine_halt(void)
+{
+}
+
+void machine_power_off(void)
+{
+	if (pm_power_off)
+		pm_power_off();
+}
+
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
index 3f9883be4436660acb25d801feedbac15d96a0b1..f715fc2d11b29911940c0af83dd01f202af9fc4a 100644
--- a/arch/i386/kernel/setup.c
+++ b/arch/i386/kernel/setup.c
@@ -116,6 +116,10 @@
 #include <asm/dma.h>
 #include <asm/mpspec.h>
 #include <asm/mmu_context.h>
+#include <asm/arch_hooks.h>
+#include "setup_arch_pre.h"
+
+static inline char * __init machine_specific_memory_setup(void);
 
 /*
  * Machine setup..
@@ -564,31 +568,8 @@ static int __init copy_e820_map(struct e820entry * biosmap, int nr_map)
 
 static void __init setup_memory_region(void)
 {
-	char *who = "BIOS-e820";
-
-	/*
-	 * Try to copy the BIOS-supplied E820-map.
-	 *
-	 * Otherwise fake a memory map; one section from 0k->640k,
-	 * the next section from 1mb->appropriate_mem_k
-	 */
-	sanitize_e820_map(E820_MAP, &E820_MAP_NR);
-	if (copy_e820_map(E820_MAP, E820_MAP_NR) < 0) {
-		unsigned long mem_size;
-
-		/* compare results from other methods and take the greater */
-		if (ALT_MEM_K < EXT_MEM_K) {
-			mem_size = EXT_MEM_K;
-			who = "BIOS-88";
-		} else {
-			mem_size = ALT_MEM_K;
-			who = "BIOS-e801";
-		}
+	char *who = machine_specific_memory_setup();
 
-		e820.nr_map = 0;
-		add_memory_region(0, LOWMEMSIZE(), E820_RAM);
-		add_memory_region(HIGH_MEMORY, mem_size << 10, E820_RAM);
-  	}
 	printk(KERN_INFO "BIOS-provided physical RAM map:\n");
 	print_memory_map(who);
 } /* setup_memory_region */
@@ -678,14 +659,14 @@ void __init setup_arch(char **cmdline_p)
 	unsigned long start_pfn, max_low_pfn;
 	int i;
 
-#ifdef CONFIG_VISWS
-	visws_get_board_type_and_rev();
-#endif
+	pre_setup_arch_hook();
 
  	ROOT_DEV = to_kdev_t(ORIG_ROOT_DEV);
  	drive_info = DRIVE_INFO;
  	screen_info = SCREEN_INFO;
+#ifdef CONFIG_APM
 	apm_info.bios = APM_BIOS_INFO;
+#endif
 	saved_videomode = VIDEO_MODE;
 	printk("Video mode to be used for restore is %lx\n", saved_videomode);
 	if( SYS_DESC_TABLE.length != 0 ) {
@@ -701,6 +682,7 @@ void __init setup_arch(char **cmdline_p)
 	rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0);
 	rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0);
 #endif
+	ARCH_SETUP
 	setup_memory_region();
 
 	if (!MOUNT_ROOT_RDONLY)
@@ -881,7 +863,7 @@ void __init setup_arch(char **cmdline_p)
 	 */
 	acpi_reserve_bootmem();
 #endif
-#ifdef CONFIG_X86_LOCAL_APIC
+#ifdef CONFIG_X86_FIND_SMP_CONFIG
 	/*
 	 * Find and reserve possible boot-time SMP configuration:
 	 */
@@ -2153,7 +2135,7 @@ static void __init init_intel(struct cpuinfo_x86 *c)
 	if ( p )
 		strcpy(c->x86_model_id, p);
 	
-#ifdef CONFIG_SMP
+#ifdef CONFIG_X86_HT
 	if (cpu_has(c, X86_FEATURE_HT)) {
 		extern	int phys_proc_id[NR_CPUS];
 		
@@ -2937,6 +2919,8 @@ int __init ppro_with_ram_bug(void)
 	printk(KERN_INFO "Your Pentium Pro seems ok.\n");
 	return 0;
 }
+
+#include "setup_arch_post.h"
 	
 /*
  * Local Variables:
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
index e7242a8891be93fb9a949feb470d07691431dcf0..2dac538c6295dc1c6fd705ff989308695a64b4c6 100644
--- a/arch/i386/kernel/smpboot.c
+++ b/arch/i386/kernel/smpboot.c
@@ -49,6 +49,8 @@
 #include <asm/pgalloc.h>
 #include <asm/tlbflush.h>
 #include <asm/smpboot.h>
+#include <asm/desc.h>
+#include <asm/arch_hooks.h>
 
 /* Set if we find a B stepping CPU			*/
 static int smp_b_stepping;
@@ -1253,3 +1255,29 @@ void __init smp_boot_cpus(void)
 smp_done:
 	zap_low_mappings();
 }
+
+void __init smp_intr_init()
+{
+	/*
+	 * IRQ0 must be given a fixed assignment and initialized,
+	 * because it's used before the IO-APIC is set up.
+	 */
+	set_intr_gate(FIRST_DEVICE_VECTOR, interrupt[0]);
+
+	/*
+	 * The reschedule interrupt is a CPU-to-CPU reschedule-helper
+	 * IPI, driven by wakeup.
+	 */
+	set_intr_gate(RESCHEDULE_VECTOR, reschedule_interrupt);
+
+	/* IPI for invalidation */
+	set_intr_gate(INVALIDATE_TLB_VECTOR, invalidate_interrupt);
+
+	/* IPI for generic function call */
+	set_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt);
+
+	/* thermal monitor LVT interrupt */
+#ifdef CONFIG_X86_MCE_P4THERMAL
+	set_intr_gate(THERMAL_APIC_VECTOR, thermal_interrupt);
+#endif
+}
diff --git a/arch/i386/kernel/time.c b/arch/i386/kernel/time.c
index 1e1eb0d3a5f7d446425b8623939ba50587f50ee6..79a65d79a465029f6e1dd089312e95400f347a97 100644
--- a/arch/i386/kernel/time.c
+++ b/arch/i386/kernel/time.c
@@ -57,8 +57,11 @@
 #include <linux/timex.h>
 #include <linux/config.h>
 
-#include <asm/fixmap.h>
-#include <asm/cobalt.h>
+#include <asm/arch_hooks.h>
+
+extern spinlock_t i8259A_lock;
+
+#include "do_timer.h"
 
 /*
  * for x86_do_profile()
@@ -119,8 +122,6 @@ static inline unsigned long do_fast_gettimeoffset(void)
 spinlock_t i8253_lock = SPIN_LOCK_UNLOCKED;
 EXPORT_SYMBOL(i8253_lock);
 
-extern spinlock_t i8259A_lock;
-
 #ifndef CONFIG_X86_TSC
 
 /* This function must be called with interrupts disabled 
@@ -201,47 +202,11 @@ static unsigned long do_slow_gettimeoffset(void)
 	 *     (see c't 95/10 page 335 for Neptun bug.)
 	 */
 
-/* you can safely undefine this if you don't have the Neptune chipset */
-
-#define BUGGY_NEPTUN_TIMER
 
 	if( jiffies_t == jiffies_p ) {
 		if( count > count_p ) {
 			/* the nutcase */
-
-			int i;
-
-			spin_lock(&i8259A_lock);
-			/*
-			 * This is tricky when I/O APICs are used;
-			 * see do_timer_interrupt().
-			 */
-			i = inb(0x20);
-			spin_unlock(&i8259A_lock);
-
-			/* assumption about timer being IRQ0 */
-			if (i & 0x01) {
-				/*
-				 * We cannot detect lost timer interrupts ... 
-				 * well, that's why we call them lost, don't we? :)
-				 * [hmm, on the Pentium and Alpha we can ... sort of]
-				 */
-				count -= LATCH;
-			} else {
-#ifdef BUGGY_NEPTUN_TIMER
-				/*
-				 * for the Neptun bug we know that the 'latch'
-				 * command doesnt latch the high and low value
-				 * of the counter atomically. Thus we have to 
-				 * substract 256 from the counter 
-				 * ... funny, isnt it? :)
-				 */
-
-				count -= 256;
-#else
-				printk("do_slow_gettimeoffset(): hardware timer problem?\n");
-#endif
-			}
+			count = do_timer_overflow(count);
 		}
 	} else
 		jiffies_p = jiffies_t;
@@ -411,23 +376,7 @@ static inline void do_timer_interrupt(int irq, void *dev_id, struct pt_regs *reg
 	}
 #endif
 
-#ifdef CONFIG_VISWS
-	/* Clear the interrupt */
-	co_cpu_write(CO_CPU_STAT,co_cpu_read(CO_CPU_STAT) & ~CO_STAT_TIMEINTR);
-#endif
-	do_timer(regs);
-/*
- * In the SMP case we use the local APIC timer interrupt to do the
- * profiling, except when we simulate SMP mode on a uniprocessor
- * system, in that case we have to call the local interrupt handler.
- */
-#ifndef CONFIG_X86_LOCAL_APIC
-	if (!user_mode(regs))
-		x86_do_profile(regs->eip);
-#else
-	if (!using_apic_timer)
-		smp_local_timer_interrupt(regs);
-#endif
+	do_timer_interrupt_hook(regs);
 
 	/*
 	 * If we have an externally synchronized Linux clock, then update
@@ -468,7 +417,7 @@ static int use_tsc;
  * Time Stamp Counter value at the time of the timer interrupt, so that
  * we later on can estimate the time of day more exactly.
  */
-static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	int count;
 
@@ -558,8 +507,6 @@ unsigned long get_cmos_time(void)
 	return mktime(year, mon, day, hour, min, sec);
 }
 
-static struct irqaction irq0  = { timer_interrupt, SA_INTERRUPT, 0, "timer", NULL, NULL};
-
 /* ------ Calibrate the TSC ------- 
  * Return 2^32 * (1 / (TSC clocks per usec)) for do_fast_gettimeoffset().
  * Too much 64-bit arithmetic here to do this cleanly in C, and for
@@ -572,6 +519,7 @@ static struct irqaction irq0  = { timer_interrupt, SA_INTERRUPT, 0, "timer", NUL
 #define CALIBRATE_LATCH	(5 * LATCH)
 #define CALIBRATE_TIME	(5 * 1000020/HZ)
 
+#ifdef CONFIG_X86_TSC
 static unsigned long __init calibrate_tsc(void)
 {
        /* Set the Gate high, disable speaker */
@@ -636,6 +584,7 @@ static unsigned long __init calibrate_tsc(void)
 bad_ctc:
 	return 0;
 }
+#endif /* CONFIG_X86_TSC */
 
 static struct device device_i8253 = {
 	name:	       	"i8253",
@@ -651,7 +600,9 @@ __initcall(time_init_driverfs);
 
 void __init time_init(void)
 {
+#ifdef CONFIG_X86_TSC
 	extern int x86_udelay_tsc;
+#endif
 	
 	xtime.tv_sec = get_cmos_time();
 	xtime.tv_usec = 0;
@@ -670,6 +621,7 @@ void __init time_init(void)
  * to disk; this won't break the kernel, though, 'cuz we're
  * smart.  See arch/i386/kernel/apm.c.
  */
+#ifdef CONFIG_X86_TSC
  	/*
  	 *	Firstly we have to do a CPU check for chips with
  	 * 	a potentially buggy TSC. At this point we haven't run
@@ -710,22 +662,7 @@ void __init time_init(void)
 			}
 		}
 	}
+#endif /* CONFIG_X86_TSC */
 
-#ifdef CONFIG_VISWS
-	printk("Starting Cobalt Timer system clock\n");
-
-	/* Set the countdown value */
-	co_cpu_write(CO_CPU_TIMEVAL, CO_TIME_HZ/HZ);
-
-	/* Start the timer */
-	co_cpu_write(CO_CPU_CTRL, co_cpu_read(CO_CPU_CTRL) | CO_CTRL_TIMERUN);
-
-	/* Enable (unmask) the timer interrupt */
-	co_cpu_write(CO_CPU_CTRL, co_cpu_read(CO_CPU_CTRL) & ~CO_CTRL_TIMEMASK);
-
-	/* Wire cpu IDT entry to s/w handler (and Cobalt APIC to IDT) */
-	setup_irq(CO_IRQ_TIMER, &irq0);
-#else
-	setup_irq(0, &irq0);
-#endif
+	time_init_hook();
 }
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
index 0d4730c3629b0b7118517a68998c093808da88c3..744aaa052cf1b420c96092320b8a32a021033277 100644
--- a/arch/i386/kernel/traps.c
+++ b/arch/i386/kernel/traps.c
@@ -44,12 +44,7 @@
 
 #include <asm/smp.h>
 #include <asm/pgalloc.h>
-
-#ifdef CONFIG_X86_VISWS_APIC
-#include <asm/fixmap.h>
-#include <asm/cobalt.h>
-#include <asm/lithium.h>
-#endif
+#include <asm/arch_hooks.h>
 
 #include <linux/irq.h>
 #include <linux/module.h>
@@ -864,96 +859,6 @@ void set_ldt_desc(unsigned int n, void *addr, unsigned int size)
 	_set_tssldt_desc(gdt_table+__LDT(n), (int)addr, ((size << 3)-1), 0x82);
 }
 
-#ifdef CONFIG_X86_VISWS_APIC
-
-/*
- * On Rev 005 motherboards legacy device interrupt lines are wired directly
- * to Lithium from the 307.  But the PROM leaves the interrupt type of each
- * 307 logical device set appropriate for the 8259.  Later we'll actually use
- * the 8259, but for now we have to flip the interrupt types to
- * level triggered, active lo as required by Lithium.
- */
-
-#define	REG	0x2e	/* The register to read/write */
-#define	DEV	0x07	/* Register: Logical device select */
-#define	VAL	0x2f	/* The value to read/write */
-
-static void
-superio_outb(int dev, int reg, int val)
-{
-	outb(DEV, REG);
-	outb(dev, VAL);
-	outb(reg, REG);
-	outb(val, VAL);
-}
-
-static int __attribute__ ((unused))
-superio_inb(int dev, int reg)
-{
-	outb(DEV, REG);
-	outb(dev, VAL);
-	outb(reg, REG);
-	return inb(VAL);
-}
-
-#define	FLOP	3	/* floppy logical device */
-#define	PPORT	4	/* parallel logical device */
-#define	UART5	5	/* uart2 logical device (not wired up) */
-#define	UART6	6	/* uart1 logical device (THIS is the serial port!) */
-#define	IDEST	0x70	/* int. destination (which 307 IRQ line) reg. */
-#define	ITYPE	0x71	/* interrupt type register */
-
-/* interrupt type bits */
-#define	LEVEL	0x01	/* bit 0, 0 == edge triggered */
-#define	ACTHI	0x02	/* bit 1, 0 == active lo */
-
-static void
-superio_init(void)
-{
-	if (visws_board_type == VISWS_320 && visws_board_rev == 5) {
-		superio_outb(UART6, IDEST, 0);	/* 0 means no intr propagated */
-		printk("SGI 320 rev 5: disabling 307 uart1 interrupt\n");
-	}
-}
-
-static void
-lithium_init(void)
-{
-	set_fixmap(FIX_LI_PCIA, LI_PCI_A_PHYS);
-	printk("Lithium PCI Bridge A, Bus Number: %d\n",
-				li_pcia_read16(LI_PCI_BUSNUM) & 0xff);
-	set_fixmap(FIX_LI_PCIB, LI_PCI_B_PHYS);
-	printk("Lithium PCI Bridge B (PIIX4), Bus Number: %d\n",
-				li_pcib_read16(LI_PCI_BUSNUM) & 0xff);
-
-	/* XXX blindly enables all interrupts */
-	li_pcia_write16(LI_PCI_INTEN, 0xffff);
-	li_pcib_write16(LI_PCI_INTEN, 0xffff);
-}
-
-static void
-cobalt_init(void)
-{
-	/*
-	 * On normal SMP PC this is used only with SMP, but we have to
-	 * use it and set it up here to start the Cobalt clock
-	 */
-	set_fixmap(FIX_APIC_BASE, APIC_DEFAULT_PHYS_BASE);
-	printk("Local APIC ID %lx\n", apic_read(APIC_ID));
-	printk("Local APIC Version %lx\n", apic_read(APIC_LVR));
-
-	set_fixmap(FIX_CO_CPU, CO_CPU_PHYS);
-	printk("Cobalt Revision %lx\n", co_cpu_read(CO_CPU_REV));
-
-	set_fixmap(FIX_CO_APIC, CO_APIC_PHYS);
-	printk("Cobalt APIC ID %lx\n", co_apic_read(CO_APIC_ID));
-
-	/* Enable Cobalt APIC being careful to NOT change the ID! */
-	co_apic_write(CO_APIC_ID, co_apic_read(CO_APIC_ID)|CO_APIC_ENABLE);
-
-	printk("Cobalt APIC enabled: ID reg %lx\n", co_apic_read(CO_APIC_ID));
-}
-#endif
 
 #ifdef CONFIG_EISA
 int EISA_bus;
@@ -1009,9 +914,5 @@ void __init trap_init(void)
 	 */
 	cpu_init();
 
-#ifdef CONFIG_X86_VISWS_APIC
-	superio_init();
-	lithium_init();
-	cobalt_init();
-#endif
+	trap_init_hook();
 }
diff --git a/arch/i386/pci/Makefile b/arch/i386/pci/Makefile
index 9e5e9cce0a18d5ce10fc20862e28a592566a651a..3d9297c69c1e98b31407936503002c954a99a61b 100644
--- a/arch/i386/pci/Makefile
+++ b/arch/i386/pci/Makefile
@@ -2,10 +2,6 @@ O_TARGET        := pci.o
 
 obj-y		:= i386.o
 
-ifdef	CONFIG_VISWS
-obj-y		+= visws.o
-else
-
 obj-$(CONFIG_PCI_BIOS)		+= pcbios.o
 obj-$(CONFIG_PCI_DIRECT)	+= direct.o
 
@@ -22,6 +18,5 @@ obj-y		+= legacy.o
 
 endif		# CONFIG_MULTIQUAD
 obj-y		+= irq.o common.o
-endif		# CONFIG_VISWS
 
 include $(TOPDIR)/Rules.make
diff --git a/arch/i386/visws/Makefile b/arch/i386/visws/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..471d84f7d32f11029cea148e7621e2354a6589d3
--- /dev/null
+++ b/arch/i386/visws/Makefile
@@ -0,0 +1,25 @@
+#
+# Makefile for the linux kernel.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definitions are now in the main makefile...
+
+.S.o:
+	$(CC) $(AFLAGS) -traditional -c $< -o $*.o
+
+all: visws.o
+
+O_TARGET 	:= visws.o
+EXTRA_CFLAGS	+= -I../kernel
+export-objs     := 
+
+obj-y				:= setup.o traps.o
+
+obj-$(CONFIG_PCI)		+= pci-visws.o
+obj-$(CONFIG_X86_VISWS_APIC)	+= visws_apic.o
+obj-$(CONFIG_X86_LOCAL_APIC)	+= mpparse.o
+
+include $(TOPDIR)/Rules.make
diff --git a/arch/i386/visws/do_timer.h b/arch/i386/visws/do_timer.h
new file mode 100644
index 0000000000000000000000000000000000000000..b2c1cbed5cb9c59ac7b5b4926e61a1f8087fcf3f
--- /dev/null
+++ b/arch/i386/visws/do_timer.h
@@ -0,0 +1,50 @@
+/* defines for inline arch setup functions */
+
+#include <asm/fixmap.h>
+#include <asm/cobalt.h>
+
+static inline void do_timer_interrupt_hook(struct pt_regs *regs)
+{
+	/* Clear the interrupt */
+	co_cpu_write(CO_CPU_STAT,co_cpu_read(CO_CPU_STAT) & ~CO_STAT_TIMEINTR);
+
+	do_timer(regs);
+/*
+ * In the SMP case we use the local APIC timer interrupt to do the
+ * profiling, except when we simulate SMP mode on a uniprocessor
+ * system, in that case we have to call the local interrupt handler.
+ */
+#ifndef CONFIG_X86_LOCAL_APIC
+	if (!user_mode(regs))
+		x86_do_profile(regs->eip);
+#else
+	if (!using_apic_timer)
+		smp_local_timer_interrupt(regs);
+#endif
+}
+
+static inline int do_timer_overflow(int count)
+{
+	int i;
+
+	spin_lock(&i8259A_lock);
+	/*
+	 * This is tricky when I/O APICs are used;
+	 * see do_timer_interrupt().
+	 */
+	i = inb(0x20);
+	spin_unlock(&i8259A_lock);
+	
+	/* assumption about timer being IRQ0 */
+	if (i & 0x01) {
+		/*
+		 * We cannot detect lost timer interrupts ... 
+		 * well, that's why we call them lost, don't we? :)
+		 * [hmm, on the Pentium and Alpha we can ... sort of]
+		 */
+		count -= LATCH;
+	} else {
+		printk("do_slow_gettimeoffset(): hardware timer problem?\n");
+	}
+	return count;
+}
diff --git a/arch/i386/visws/entry_arch.h b/arch/i386/visws/entry_arch.h
new file mode 100644
index 0000000000000000000000000000000000000000..b183fa6d83d99c5eb5e4a1b2752aab37ab4442a3
--- /dev/null
+++ b/arch/i386/visws/entry_arch.h
@@ -0,0 +1,23 @@
+/*
+ * 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)
+ */
+#ifdef CONFIG_X86_SMP
+BUILD_INTERRUPT(reschedule_interrupt,RESCHEDULE_VECTOR)
+BUILD_INTERRUPT(invalidate_interrupt,INVALIDATE_TLB_VECTOR)
+BUILD_INTERRUPT(call_function_interrupt,CALL_FUNCTION_VECTOR)
+#endif
+
+/*
+ * every pentium local APIC has two 'local interrupts', with a
+ * soft-definable vector attached to both interrupts, one of
+ * which is a timer interrupt, the other one is error counter
+ * overflow. Linux uses the local APIC timer interrupt to get
+ * a much simpler SMP time architecture:
+ */
+#ifdef CONFIG_X86_LOCAL_APIC
+BUILD_INTERRUPT(apic_timer_interrupt,LOCAL_TIMER_VECTOR)
+BUILD_INTERRUPT(error_interrupt,ERROR_APIC_VECTOR)
+BUILD_INTERRUPT(spurious_interrupt,SPURIOUS_APIC_VECTOR)
+#endif
diff --git a/arch/i386/visws/irq_vectors.h b/arch/i386/visws/irq_vectors.h
new file mode 100644
index 0000000000000000000000000000000000000000..5c53f00e21a82fb99b03d529da0807b5d20887b6
--- /dev/null
+++ b/arch/i386/visws/irq_vectors.h
@@ -0,0 +1,64 @@
+#ifndef _ASM_IRQ_VECTORS_H
+#define _ASM_IRQ_VECTORS_H
+
+/*
+ * IDT vectors usable for external interrupt sources start
+ * at 0x20:
+ */
+#define FIRST_EXTERNAL_VECTOR	0x20
+
+#define SYSCALL_VECTOR		0x80
+
+/*
+ * Vectors 0x20-0x2f are used for ISA interrupts.
+ */
+
+/*
+ * Special IRQ vectors used by the SMP architecture, 0xf0-0xff
+ *
+ *  some of the following vectors are 'rare', they are merged
+ *  into a single vector (CALL_FUNCTION_VECTOR) to save vector space.
+ *  TLB, reschedule and local APIC vectors are performance-critical.
+ *
+ *  Vectors 0xf0-0xfa are free (reserved for future Linux use).
+ */
+#define SPURIOUS_APIC_VECTOR	0xff
+#define ERROR_APIC_VECTOR	0xfe
+#define INVALIDATE_TLB_VECTOR	0xfd
+#define RESCHEDULE_VECTOR	0xfc
+#define CALL_FUNCTION_VECTOR	0xfb
+
+#define THERMAL_APIC_VECTOR	0xf0
+/*
+ * Local APIC timer IRQ vector is on a different priority level,
+ * to work around the 'lost local interrupt if more than 2 IRQ
+ * sources per level' errata.
+ */
+#define LOCAL_TIMER_VECTOR	0xef
+
+/*
+ * First APIC vector available to drivers: (vectors 0x30-0xee)
+ * we start at 0x31 to spread out vectors evenly between priority
+ * levels. (0x80 is the syscall vector)
+ */
+#define FIRST_DEVICE_VECTOR	0x31
+#define FIRST_SYSTEM_VECTOR	0xef
+
+#define TIMER_IRQ 0
+
+/*
+ * 16 8259A IRQ's, 208 potential APIC interrupt sources.
+ * Right now the APIC is mostly only used for SMP.
+ * 256 vectors is an architectural limit. (we can have
+ * more than 256 devices theoretically, but they will
+ * have to use shared interrupts)
+ * Since vectors 0x00-0x1f are used/reserved for the CPU,
+ * the usable vector space is 0x20-0xff (224 vectors)
+ */
+#ifdef CONFIG_X86_IO_APIC
+#define NR_IRQS 224
+#else
+#define NR_IRQS 16
+#endif
+
+#endif /* _ASM_IRQ_VECTORS_H */
diff --git a/arch/i386/visws/mpparse.c b/arch/i386/visws/mpparse.c
new file mode 100644
index 0000000000000000000000000000000000000000..45de865c5a3f4a382573a10594b30add768aaeb6
--- /dev/null
+++ b/arch/i386/visws/mpparse.c
@@ -0,0 +1,67 @@
+#include <linux/mm.h>
+#include <linux/irq.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/config.h>
+#include <linux/bootmem.h>
+#include <linux/smp_lock.h>
+#include <linux/kernel_stat.h>
+#include <linux/mc146818rtc.h>
+
+#include <asm/smp.h>
+#include <asm/mtrr.h>
+#include <asm/mpspec.h>
+#include <asm/pgalloc.h>
+
+/* Have we found an MP table */
+int smp_found_config;
+
+/*
+ * Various Linux-internal data structures created from the
+ * MP-table.
+ */
+int apic_version [MAX_APICS];
+int mp_bus_id_to_type [MAX_MP_BUSSES];
+int mp_bus_id_to_node [MAX_MP_BUSSES];
+int mp_bus_id_to_pci_bus [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = -1 };
+int mp_current_pci_id;
+
+/* I/O APIC entries */
+struct mpc_config_ioapic mp_ioapics[MAX_IO_APICS];
+
+/* # of MP IRQ source entries */
+struct mpc_config_intsrc mp_irqs[MAX_IRQ_SOURCES];
+
+/* MP IRQ source entries */
+int mp_irq_entries;
+
+int nr_ioapics;
+
+int pic_mode;
+unsigned long mp_lapic_addr;
+
+/* Processor that is doing the boot up */
+unsigned int boot_cpu_physical_apicid = -1U;
+unsigned int boot_cpu_logical_apicid = -1U;
+/* Internal processor count */
+static unsigned int num_processors;
+
+/* Bitmask of physically existing CPUs */
+unsigned long phys_cpu_present_map;
+
+/*
+ * The Visual Workstation is Intel MP compliant in the hardware
+ * sense, but it doesnt have a BIOS(-configuration table).
+ * No problem for Linux.
+ */
+void __init find_smp_config(void)
+{
+	smp_found_config = 1;
+
+	phys_cpu_present_map |= 2; /* or in id 1 */
+	apic_version[1] |= 0x10; /* integrated APIC */
+	apic_version[0] |= 0x10;
+
+	mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
+}
+
diff --git a/arch/i386/pci/visws.c b/arch/i386/visws/pci-visws.c
similarity index 100%
rename from arch/i386/pci/visws.c
rename to arch/i386/visws/pci-visws.c
diff --git a/arch/i386/kernel/setup-visws.c b/arch/i386/visws/setup.c
similarity index 71%
rename from arch/i386/kernel/setup-visws.c
rename to arch/i386/visws/setup.c
index 1c8220b82216587c9d1bef03351c445e19604c82..4ca7ff1113fc8d6eb069cfd17bec17b09e5b6f4e 100644
--- a/arch/i386/kernel/setup-visws.c
+++ b/arch/i386/visws/setup.c
@@ -3,6 +3,16 @@
  *  Split out from setup.c by davej@suse.de
  */
 
+#include <linux/smp.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+
+#include <asm/fixmap.h>
+#include <asm/cobalt.h>
+#include <asm/arch_hooks.h>
+#include <asm/io.h>
+
 char visws_board_type = -1;
 char visws_board_rev = -1;
 
@@ -118,9 +128,43 @@ void __init visws_get_board_type_and_rev(void)
 			visws_board_rev = raw;
 		}
 
-		printk(KERN_INFO "Silicon Graphics %s (rev %d)\n",
-			visws_board_type == VISWS_320 ? "320" :
-			(visws_board_type == VISWS_540 ? "540" :
-					"unknown"), visws_board_rev);
-	}
+	printk(KERN_INFO "Silicon Graphics %s (rev %d)\n",
+	       visws_board_type == VISWS_320 ? "320" :
+	       (visws_board_type == VISWS_540 ? "540" :
+		"unknown"), visws_board_rev);
+}
+
+void __init pre_intr_init_hook(void)
+{
+	init_VISWS_APIC_irqs();
+}
+
+void __init intr_init_hook(void)
+{
+#ifdef CONFIG_X86_LOCAL_APIC
+	apic_intr_init();
+#endif
+}
+
+void __init pre_setup_arch_hook()
+{
+	visws_get_board_type_and_rev();
+}
+static struct irqaction irq0  = { timer_interrupt, SA_INTERRUPT, 0, "timer", NULL, NULL};
+
+void __init time_init_hook(void)
+{
+	printk("Starting Cobalt Timer system clock\n");
+
+	/* Set the countdown value */
+	co_cpu_write(CO_CPU_TIMEVAL, CO_TIME_HZ/HZ);
+
+	/* Start the timer */
+	co_cpu_write(CO_CPU_CTRL, co_cpu_read(CO_CPU_CTRL) | CO_CTRL_TIMERUN);
+
+	/* Enable (unmask) the timer interrupt */
+	co_cpu_write(CO_CPU_CTRL, co_cpu_read(CO_CPU_CTRL) & ~CO_CTRL_TIMEMASK);
+
+	/* Wire cpu IDT entry to s/w handler (and Cobalt APIC to IDT) */
+	setup_irq(CO_IRQ_TIMER, &irq0);
 }
diff --git a/arch/i386/visws/setup_arch_post.h b/arch/i386/visws/setup_arch_post.h
new file mode 100644
index 0000000000000000000000000000000000000000..e8611ae44c451b51e702eda7a3e826138823de7d
--- /dev/null
+++ b/arch/i386/visws/setup_arch_post.h
@@ -0,0 +1,37 @@
+/* Hook for machine specific memory setup.
+ *
+ * This is included late in kernel/setup.c so that it can make use of all of
+ * the static functions. */
+
+static inline char * __init machine_specific_memory_setup(void)
+{
+	char *who;
+
+
+	who = "BIOS-e820";
+
+	/*
+	 * Try to copy the BIOS-supplied E820-map.
+	 *
+	 * Otherwise fake a memory map; one section from 0k->640k,
+	 * the next section from 1mb->appropriate_mem_k
+	 */
+	sanitize_e820_map(E820_MAP, &E820_MAP_NR);
+	if (copy_e820_map(E820_MAP, E820_MAP_NR) < 0) {
+		unsigned long mem_size;
+
+		/* compare results from other methods and take the greater */
+		if (ALT_MEM_K < EXT_MEM_K) {
+			mem_size = EXT_MEM_K;
+			who = "BIOS-88";
+		} else {
+			mem_size = ALT_MEM_K;
+			who = "BIOS-e801";
+		}
+
+		e820.nr_map = 0;
+		add_memory_region(0, LOWMEMSIZE(), E820_RAM);
+		add_memory_region(HIGH_MEMORY, mem_size << 10, E820_RAM);
+  	}
+	return who;
+}
diff --git a/arch/i386/visws/setup_arch_pre.h b/arch/i386/visws/setup_arch_pre.h
new file mode 100644
index 0000000000000000000000000000000000000000..b92d6d9a4d3ced6b7785a9f4d9bdbdf0d124e427
--- /dev/null
+++ b/arch/i386/visws/setup_arch_pre.h
@@ -0,0 +1,5 @@
+/* Hook to call BIOS initialisation function */
+
+/* no action for visws */
+
+#define ARCH_SETUP
diff --git a/arch/i386/visws/traps.c b/arch/i386/visws/traps.c
new file mode 100644
index 0000000000000000000000000000000000000000..2b330bc6f5b7c1f655b0a96edb858f6470887cca
--- /dev/null
+++ b/arch/i386/visws/traps.c
@@ -0,0 +1,134 @@
+/* VISWS traps */
+
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/ptrace.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/highmem.h>
+#include <linux/init.h>
+
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/atomic.h>
+#include <asm/debugreg.h>
+#include <asm/desc.h>
+#include <asm/i387.h>
+
+#include <asm/smp.h>
+#include <asm/pgalloc.h>
+#include <asm/arch_hooks.h>
+
+#ifdef CONFIG_X86_VISWS_APIC
+#include <asm/fixmap.h>
+#include <asm/cobalt.h>
+#include <asm/lithium.h>
+#endif
+
+#ifdef CONFIG_X86_VISWS_APIC
+
+/*
+ * On Rev 005 motherboards legacy device interrupt lines are wired directly
+ * to Lithium from the 307.  But the PROM leaves the interrupt type of each
+ * 307 logical device set appropriate for the 8259.  Later we'll actually use
+ * the 8259, but for now we have to flip the interrupt types to
+ * level triggered, active lo as required by Lithium.
+ */
+
+#define	REG	0x2e	/* The register to read/write */
+#define	DEV	0x07	/* Register: Logical device select */
+#define	VAL	0x2f	/* The value to read/write */
+
+static void
+superio_outb(int dev, int reg, int val)
+{
+	outb(DEV, REG);
+	outb(dev, VAL);
+	outb(reg, REG);
+	outb(val, VAL);
+}
+
+static int __attribute__ ((unused))
+superio_inb(int dev, int reg)
+{
+	outb(DEV, REG);
+	outb(dev, VAL);
+	outb(reg, REG);
+	return inb(VAL);
+}
+
+#define	FLOP	3	/* floppy logical device */
+#define	PPORT	4	/* parallel logical device */
+#define	UART5	5	/* uart2 logical device (not wired up) */
+#define	UART6	6	/* uart1 logical device (THIS is the serial port!) */
+#define	IDEST	0x70	/* int. destination (which 307 IRQ line) reg. */
+#define	ITYPE	0x71	/* interrupt type register */
+
+/* interrupt type bits */
+#define	LEVEL	0x01	/* bit 0, 0 == edge triggered */
+#define	ACTHI	0x02	/* bit 1, 0 == active lo */
+
+static __init void
+superio_init(void)
+{
+	if (visws_board_type == VISWS_320 && visws_board_rev == 5) {
+		superio_outb(UART6, IDEST, 0);	/* 0 means no intr propagated */
+		printk("SGI 320 rev 5: disabling 307 uart1 interrupt\n");
+	}
+}
+
+static __init void
+lithium_init(void)
+{
+	set_fixmap(FIX_LI_PCIA, LI_PCI_A_PHYS);
+	printk("Lithium PCI Bridge A, Bus Number: %d\n",
+				li_pcia_read16(LI_PCI_BUSNUM) & 0xff);
+	set_fixmap(FIX_LI_PCIB, LI_PCI_B_PHYS);
+	printk("Lithium PCI Bridge B (PIIX4), Bus Number: %d\n",
+				li_pcib_read16(LI_PCI_BUSNUM) & 0xff);
+
+	/* XXX blindly enables all interrupts */
+	li_pcia_write16(LI_PCI_INTEN, 0xffff);
+	li_pcib_write16(LI_PCI_INTEN, 0xffff);
+}
+
+static __init void
+cobalt_init(void)
+{
+	/*
+	 * On normal SMP PC this is used only with SMP, but we have to
+	 * use it and set it up here to start the Cobalt clock
+	 */
+	set_fixmap(FIX_APIC_BASE, APIC_DEFAULT_PHYS_BASE);
+	printk("Local APIC ID %lx\n", apic_read(APIC_ID));
+	printk("Local APIC Version %lx\n", apic_read(APIC_LVR));
+
+	set_fixmap(FIX_CO_CPU, CO_CPU_PHYS);
+	printk("Cobalt Revision %lx\n", co_cpu_read(CO_CPU_REV));
+
+	set_fixmap(FIX_CO_APIC, CO_APIC_PHYS);
+	printk("Cobalt APIC ID %lx\n", co_apic_read(CO_APIC_ID));
+
+	/* Enable Cobalt APIC being careful to NOT change the ID! */
+	co_apic_write(CO_APIC_ID, co_apic_read(CO_APIC_ID)|CO_APIC_ENABLE);
+
+	printk("Cobalt APIC enabled: ID reg %lx\n", co_apic_read(CO_APIC_ID));
+}
+#endif
+
+void __init trap_init_hook()
+{
+#ifdef CONFIG_X86_VISWS_APIC
+	superio_init();
+	lithium_init();
+	cobalt_init();
+#endif
+}
diff --git a/arch/i386/kernel/visws_apic.c b/arch/i386/visws/visws_apic.c
similarity index 100%
rename from arch/i386/kernel/visws_apic.c
rename to arch/i386/visws/visws_apic.c
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 992356ef36b1fc8d63a3a082793f36bf60e8930a..e245a5db152bc7d98f8edddcf851d4209555d5ac 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -142,7 +142,7 @@ create_elf_tables(char *p, int argc, int envc,
 	} else
 		u_platform = p;
 
-#if defined(__i386__) && defined(CONFIG_SMP)
+#ifdef CONFIG_X86_HT
 	/*
 	 * In some cases (e.g. Hyper-Threading), we want to avoid L1 evictions
 	 * by the processes running on the same package. One thing we can do
diff --git a/include/asm-i386/arch_hooks.h b/include/asm-i386/arch_hooks.h
new file mode 100644
index 0000000000000000000000000000000000000000..0bf28a32894a7df399b2ead325eefd43bf1a154c
--- /dev/null
+++ b/include/asm-i386/arch_hooks.h
@@ -0,0 +1,25 @@
+#ifndef _ASM_ARCH_HOOKS_H
+#define _ASM_ARCH_HOOKS_H
+
+/*
+ *	linux/include/asm/arch_hooks.h
+ *
+ *	define the architecture specific hooks 
+ */
+
+/* these aren't arch hooks, they are generic routines
+ * that can be used by the hooks */
+extern void init_ISA_irqs(void);
+extern void apic_intr_init(void);
+extern void smp_intr_init(void);
+extern void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+
+/* these are the defined hooks */
+extern void intr_init_hook(void);
+extern void pre_intr_init_hook(void);
+extern void pre_setup_arch_hook(void);
+extern void trap_init_hook(void);
+extern void time_init_hook(void);
+extern void mca_nmi_hook(void);
+
+#endif
diff --git a/include/asm-i386/irq.h b/include/asm-i386/irq.h
index 3fc2c070860ca91bdcca692f60d4b5570b4eb4dc..0a5e1dd662129feb78bd876ae18076a7735bcb40 100644
--- a/include/asm-i386/irq.h
+++ b/include/asm-i386/irq.h
@@ -12,7 +12,8 @@
 
 #include <linux/config.h>
 #include <linux/sched.h>
-#include <asm/irq_vectors.h>
+/* include comes from machine specific directory */
+#include "irq_vectors.h"
 
 static __inline__ int irq_cannonicalize(int irq)
 {