Commit 85fe9359 authored by James Bottomley's avatar James Bottomley

Enable Voyager in current kernel

parent 58acbf38
...@@ -38,6 +38,33 @@ source "init/Kconfig" ...@@ -38,6 +38,33 @@ source "init/Kconfig"
menu "Processor type and features" menu "Processor type and features"
choice
prompt "Subarchitecture Type"
default PC
config PC
bool PC
help
Choose this option if your computer is a standard PC or compatible.
config VOYAGER
bool "NCR Voyager Architecture"
---help---
Voyager is a MCA based 32 way capable SMP architecture proprietary
to NCR Corp. Machine classes 345x/35xx/4100/51xx are voyager based.
*** WARNING ***
If you do not specifically know you have a Voyager based machine,
say N here otherwise the kernel you build will not be bootable.
# Visual Workstation support is utterly broken.
# If you want to see it working mail an VW540 to hch@infradead.org 8)
#bool 'SGI Visual Workstation support' CONFIG_VISWS
endchoice
choice choice
prompt "Processor family" prompt "Processor family"
default M686 default M686
...@@ -337,6 +364,7 @@ config PREEMPT ...@@ -337,6 +364,7 @@ config PREEMPT
config X86_UP_APIC config X86_UP_APIC
bool "Local APIC support on uniprocessors" if !SMP bool "Local APIC support on uniprocessors" if !SMP
depends on !VOYAGER
---help--- ---help---
A local APIC (Advanced Programmable Interrupt Controller) is an A local APIC (Advanced Programmable Interrupt Controller) is an
integrated interrupt controller in the CPU. If you have a single-CPU integrated interrupt controller in the CPU. If you have a single-CPU
...@@ -690,6 +718,7 @@ endmenu ...@@ -690,6 +718,7 @@ endmenu
menu "Power management options (ACPI, APM)" menu "Power management options (ACPI, APM)"
depends on !VOYAGER
config PM config PM
bool "Power Management support" bool "Power Management support"
...@@ -990,9 +1019,6 @@ endmenu ...@@ -990,9 +1019,6 @@ endmenu
menu "Bus options (PCI, PCMCIA, EISA, MCA, ISA)" menu "Bus options (PCI, PCMCIA, EISA, MCA, ISA)"
# Visual Workstation support is utterly broken.
# If you want to see it working mail an VW540 to hch@infradead.org 8)
#bool 'SGI Visual Workstation support' CONFIG_VISWS
config X86_VISWS_APIC config X86_VISWS_APIC
bool bool
depends on VISWS depends on VISWS
...@@ -1000,11 +1026,12 @@ config X86_VISWS_APIC ...@@ -1000,11 +1026,12 @@ config X86_VISWS_APIC
config X86_LOCAL_APIC config X86_LOCAL_APIC
bool bool
depends on !VISWS && SMP || VISWS depends on ((!VISWS && SMP) || VISWS) && !VOYAGER
default y default y
config PCI config PCI
bool "PCI support" if !VISWS bool "PCI support" if !VISWS
depends on !VOYAGER
default y if VISWS default y if VISWS
help help
Find out whether you have a PCI motherboard. PCI is the name of a Find out whether you have a PCI motherboard. PCI is the name of a
...@@ -1019,7 +1046,7 @@ config PCI ...@@ -1019,7 +1046,7 @@ config PCI
config X86_IO_APIC config X86_IO_APIC
bool bool
depends on !VISWS && SMP depends on !VISWS && SMP && !VOYAGER
default y default y
choice choice
...@@ -1063,6 +1090,7 @@ config PCI_DIRECT ...@@ -1063,6 +1090,7 @@ config PCI_DIRECT
config SCx200 config SCx200
tristate "NatSemi SCx200 support" tristate "NatSemi SCx200 support"
depends on !VOYAGER
help help
This provides basic support for the National Semiconductor SCx200 This provides basic support for the National Semiconductor SCx200
processor. Right now this is just a driver for the GPIO pins. processor. Right now this is just a driver for the GPIO pins.
...@@ -1076,6 +1104,7 @@ source "drivers/pci/Kconfig" ...@@ -1076,6 +1104,7 @@ source "drivers/pci/Kconfig"
config ISA config ISA
bool "ISA support" bool "ISA support"
depends on !VOYAGER
help help
Find out whether you have ISA slots on your motherboard. ISA is the Find out whether you have ISA slots on your motherboard. ISA is the
name of a bus system, i.e. the way the CPU talks to the other stuff name of a bus system, i.e. the way the CPU talks to the other stuff
...@@ -1101,13 +1130,17 @@ config EISA ...@@ -1101,13 +1130,17 @@ config EISA
config MCA config MCA
bool "MCA support" bool "MCA support"
depends on !VISWS depends on !VISWS && !VOYAGER
help help
MicroChannel Architecture is found in some IBM PS/2 machines and MicroChannel Architecture is found in some IBM PS/2 machines and
laptops. It is a bus system similar to PCI or ISA. See laptops. It is a bus system similar to PCI or ISA. See
<file:Documentation/mca.txt> (and especially the web page given <file:Documentation/mca.txt> (and especially the web page given
there) before attempting to build an MCA bus kernel. there) before attempting to build an MCA bus kernel.
config MCA
depends on VOYAGER
default y if VOYAGER
source "drivers/mca/Kconfig" source "drivers/mca/Kconfig"
config HOTPLUG config HOTPLUG
...@@ -1574,12 +1607,12 @@ config FRAME_POINTER ...@@ -1574,12 +1607,12 @@ config FRAME_POINTER
config X86_EXTRA_IRQS config X86_EXTRA_IRQS
bool bool
depends on X86_LOCAL_APIC depends on X86_LOCAL_APIC || VOYAGER
default y default y
config X86_FIND_SMP_CONFIG config X86_FIND_SMP_CONFIG
bool bool
depends on X86_LOCAL_APIC depends on X86_LOCAL_APIC || VOYAGER
default y default y
config X86_MPPARSE config X86_MPPARSE
...@@ -1597,15 +1630,16 @@ source "lib/Kconfig" ...@@ -1597,15 +1630,16 @@ source "lib/Kconfig"
config X86_SMP config X86_SMP
bool bool
depends on SMP depends on SMP && !VOYAGER
default y default y
config X86_HT config X86_HT
bool bool
depends on SMP depends on SMP && !VOYAGER
default y default y
config X86_BIOS_REBOOT config X86_BIOS_REBOOT
bool bool
depends on !VOYAGER
default y default y
...@@ -51,6 +51,10 @@ CFLAGS += $(cflags-y) ...@@ -51,6 +51,10 @@ CFLAGS += $(cflags-y)
#default subarch .c files #default subarch .c files
mcore-y := mach-default mcore-y := mach-default
#Voyager subarch support
mflags-$(CONFIG_VOYAGER) := -Iinclude/asm-i386/mach-voyager
mcore-$(CONFIG_VOYAGER) := mach-voyager
#VISWS subarch support #VISWS subarch support
mflags-$(CONFIG_VISWS) := -Iinclude/asm-i386/mach-visws mflags-$(CONFIG_VISWS) := -Iinclude/asm-i386/mach-visws
mcore-$(CONFIG_VISWS) := mach-visws mcore-$(CONFIG_VISWS) := mach-visws
......
...@@ -476,6 +476,24 @@ sysdesc_ok: ...@@ -476,6 +476,24 @@ sysdesc_ok:
movsb movsb
popw %ds popw %ds
no_mca: no_mca:
#ifdef CONFIG_VOYAGER
movb $0xff, 0x40 # flag on config found
movb $0xc0, %al
mov $0xff, %ah
int $0x15 # put voyager config info at es:di
jc no_voyager
movw $0x40, %si # place voyager info in apm table
cld
movw $7, %cx
voyager_rep:
movb %es:(%di), %al
movb %al,(%si)
incw %di
incw %si
decw %cx
jnz voyager_rep
no_voyager:
#endif
# Check for PS/2 pointing device # Check for PS/2 pointing device
movw %cs, %ax # aka SETUPSEG movw %cs, %ax # aka SETUPSEG
subw $DELTA_INITSEG, %ax # aka INITSEG subw $DELTA_INITSEG, %ax # aka INITSEG
...@@ -740,6 +758,7 @@ A20_TEST_LOOPS = 32 # Iterations per wait ...@@ -740,6 +758,7 @@ A20_TEST_LOOPS = 32 # Iterations per wait
A20_ENABLE_LOOPS = 255 # Total loops to try A20_ENABLE_LOOPS = 255 # Total loops to try
#ifndef CONFIG_VOYAGER
a20_try_loop: a20_try_loop:
# First, see if we are on a system with no A20 gate. # First, see if we are on a system with no A20 gate.
...@@ -758,11 +777,14 @@ a20_bios: ...@@ -758,11 +777,14 @@ a20_bios:
jnz a20_done jnz a20_done
# Try enabling A20 through the keyboard controller # Try enabling A20 through the keyboard controller
#endif /* CONFIG_VOYAGER */
a20_kbc: a20_kbc:
call empty_8042 call empty_8042
#ifndef CONFIG_VOYAGER
call a20_test # Just in case the BIOS worked call a20_test # Just in case the BIOS worked
jnz a20_done # but had a delayed reaction. jnz a20_done # but had a delayed reaction.
#endif
movb $0xD1, %al # command write movb $0xD1, %al # command write
outb %al, $0x64 outb %al, $0x64
...@@ -772,6 +794,7 @@ a20_kbc: ...@@ -772,6 +794,7 @@ a20_kbc:
outb %al, $0x60 outb %al, $0x60
call empty_8042 call empty_8042
#ifndef CONFIG_VOYAGER
# Wait until a20 really *is* enabled; it can take a fair amount of # Wait until a20 really *is* enabled; it can take a fair amount of
# time on certain systems; Toshiba Tecras are known to have this # time on certain systems; Toshiba Tecras are known to have this
# problem. # problem.
...@@ -819,6 +842,7 @@ a20_err_msg: ...@@ -819,6 +842,7 @@ a20_err_msg:
# If we get here, all is good # If we get here, all is good
a20_done: a20_done:
#endif /* CONFIG_VOYAGER */
# set up gdt and idt # set up gdt and idt
lidt idt_48 # load idt with 0,0 lidt idt_48 # load idt with 0,0
xorl %eax, %eax # Compute gdt_base xorl %eax, %eax # Compute gdt_base
...@@ -985,6 +1009,7 @@ bootsect_panic_mess: ...@@ -985,6 +1009,7 @@ bootsect_panic_mess:
.string "INT15 refuses to access high mem, giving up." .string "INT15 refuses to access high mem, giving up."
#ifndef CONFIG_VOYAGER
# This routine tests whether or not A20 is enabled. If so, it # This routine tests whether or not A20 is enabled. If so, it
# exits with zf = 0. # exits with zf = 0.
# #
...@@ -1015,6 +1040,8 @@ a20_test_wait: ...@@ -1015,6 +1040,8 @@ a20_test_wait:
popw %cx popw %cx
ret ret
#endif /* CONFIG_VOYAGER */
# This routine checks that the keyboard command queue is empty # This routine checks that the keyboard command queue is empty
# (after emptying the output buffers) # (after emptying the output buffers)
# #
......
...@@ -50,11 +50,6 @@ int smp_threads_ready = 0; ...@@ -50,11 +50,6 @@ int smp_threads_ready = 0;
* indexed physically */ * indexed physically */
struct cpuinfo_x86 cpu_data[NR_CPUS] __cacheline_aligned; struct cpuinfo_x86 cpu_data[NR_CPUS] __cacheline_aligned;
/* Per CPU interrupt stacks */
extern union thread_union init_irq_union;
union thread_union *irq_stacks[NR_CPUS] __cacheline_aligned =
{ &init_irq_union, };
/* physical ID of the CPU used to boot the system */ /* physical ID of the CPU used to boot the system */
unsigned char boot_cpu_id; unsigned char boot_cpu_id;
...@@ -450,6 +445,7 @@ smp_store_cpu_info(int id) ...@@ -450,6 +445,7 @@ smp_store_cpu_info(int id)
struct cpuinfo_x86 *c=&cpu_data[id]; struct cpuinfo_x86 *c=&cpu_data[id];
*c = boot_cpu_data; *c = boot_cpu_data;
identify_cpu(c); identify_cpu(c);
} }
...@@ -512,6 +508,11 @@ start_secondary(void *unused) ...@@ -512,6 +508,11 @@ start_secondary(void *unused)
/* if we're a quad, we may need to bootstrap other CPUs */ /* if we're a quad, we may need to bootstrap other CPUs */
do_quad_bootstrap(); do_quad_bootstrap();
/* FIXME: this is rather a poor hack to prevent the CPU
* activating softirqs while it's supposed to be waiting for
* permission to proceed. Without this, the new per CPU stuff
* in the softirqs will fail */
local_irq_disable();
set_bit(cpuid, &cpu_callin_map); set_bit(cpuid, &cpu_callin_map);
/* signal that we're done */ /* signal that we're done */
...@@ -519,6 +520,7 @@ start_secondary(void *unused) ...@@ -519,6 +520,7 @@ start_secondary(void *unused)
while (!test_bit(cpuid, &smp_commenced_mask)) while (!test_bit(cpuid, &smp_commenced_mask))
rep_nop(); rep_nop();
local_irq_enable();
local_flush_tlb(); local_flush_tlb();
...@@ -533,29 +535,7 @@ fork_by_hand(void) ...@@ -533,29 +535,7 @@ fork_by_hand(void)
struct pt_regs regs; struct pt_regs regs;
/* don't care about the eip and regs settings since we'll /* don't care about the eip and regs settings since we'll
* never reschedule the forked task. */ * never reschedule the forked task. */
return do_fork(CLONE_VM|CLONE_IDLETASK, 0, &regs, 0, NULL); return do_fork(CLONE_VM|CLONE_IDLETASK, 0, &regs, 0, NULL, NULL);
}
static void __init setup_irq_stack(struct task_struct *p, int cpu)
{
unsigned long stk;
stk = __get_free_pages(GFP_KERNEL, THREAD_ORDER+1);
if (!stk)
panic("I can't seem to allocate my irq stack. Oh well, giving up.");
irq_stacks[cpu] = (void *)stk;
memset(irq_stacks[cpu], 0, THREAD_SIZE);
irq_stacks[cpu]->thread_info.cpu = cpu;
irq_stacks[cpu]->thread_info.preempt_count = 1;
/* interrupts are not preemptable */
p->thread_info->irq_stack = irq_stacks[cpu];
/* If we want to make the irq stack more than one unit
* deep, we can chain then off of the irq_stack pointer
* here.
*/
} }
...@@ -617,20 +597,17 @@ do_boot_cpu(__u8 cpu) ...@@ -617,20 +597,17 @@ do_boot_cpu(__u8 cpu)
if(IS_ERR(idle)) if(IS_ERR(idle))
panic("failed fork for CPU%d", cpu); panic("failed fork for CPU%d", cpu);
setup_irq_stack(idle, cpu);
init_idle(idle, cpu); init_idle(idle, cpu);
idle->thread.eip = (unsigned long) start_secondary; idle->thread.eip = (unsigned long) start_secondary;
unhash_process(idle); unhash_process(idle);
/* init_tasks (in sched.c) is indexed logically */
/* The -4 is to correct for the fact that the stack pointer #if 0
* is used to find the location of the thread_info structure // for AC kernels
* by masking off several of the LSBs. Without the -4, esp stack_start.esp = (THREAD_SIZE + (__u8 *)TSK_TO_KSTACK(idle));
* is pointing to the page after the one the stack is on. #else
*/ stack_start.esp = (void *) (1024 + PAGE_SIZE + (char *)idle->thread_info);
stack_start.esp = (void *)(THREAD_SIZE - 4 + (char *)idle->thread_info); #endif
/* Note: Don't modify initial ss override */ /* Note: Don't modify initial ss override */
VDEBUG(("VOYAGER SMP: Booting CPU%d at 0x%lx[%x:%x], stack %p\n", cpu, VDEBUG(("VOYAGER SMP: Booting CPU%d at 0x%lx[%x:%x], stack %p\n", cpu,
(unsigned long)hijack_source.val, hijack_source.idt.Segment, (unsigned long)hijack_source.val, hijack_source.idt.Segment,
...@@ -764,6 +741,9 @@ smp_boot_cpus(void) ...@@ -764,6 +741,9 @@ smp_boot_cpus(void)
/* enable our own CPIs */ /* enable our own CPIs */
vic_enable_cpi(); vic_enable_cpi();
set_bit(boot_cpu_id, &cpu_online_map);
set_bit(boot_cpu_id, &cpu_callout_map);
/* loop over all the extended VIC CPUs and boot them. The /* loop over all the extended VIC CPUs and boot them. The
* Quad CPUs must be bootstrapped by their extended VIC cpu */ * Quad CPUs must be bootstrapped by their extended VIC cpu */
...@@ -1312,12 +1292,9 @@ smp_vic_timer_interrupt(struct pt_regs *regs) ...@@ -1312,12 +1292,9 @@ smp_vic_timer_interrupt(struct pt_regs *regs)
static inline void static inline void
wrapper_smp_local_timer_interrupt(struct pt_regs *regs) wrapper_smp_local_timer_interrupt(struct pt_regs *regs)
{ {
__u8 cpu = smp_processor_id();
irq_enter(); irq_enter();
smp_local_timer_interrupt(regs); smp_local_timer_interrupt(regs);
irq_exit(); irq_exit();
} }
/* local (per CPU) timer interrupt. It does both profiling and /* local (per CPU) timer interrupt. It does both profiling and
......
...@@ -131,7 +131,7 @@ static inline int unregister_profile_notifier(struct notifier_block * nb) ...@@ -131,7 +131,7 @@ static inline int unregister_profile_notifier(struct notifier_block * nb)
#endif /* CONFIG_PROFILING */ #endif /* CONFIG_PROFILING */
#ifdef CONFIG_SMP /*more of this file should probably be ifdefed SMP */ #if defined(CONFIG_SMP) && !defined(CONFIG_VOYAGER) /*more of this file should probably be ifdefed SMP */
static inline void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i) { static inline void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i) {
if (IO_APIC_IRQ(i)) if (IO_APIC_IRQ(i))
send_IPI_self(IO_APIC_VECTOR(i)); send_IPI_self(IO_APIC_VECTOR(i));
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
*/ */
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
#include <linux/config.h> #include <linux/config.h>
#include <linux/kernel.h>
#include <linux/threads.h> #include <linux/threads.h>
#endif #endif
...@@ -83,11 +84,22 @@ extern volatile unsigned long cpu_callout_map; ...@@ -83,11 +84,22 @@ extern volatile unsigned long cpu_callout_map;
#define cpu_possible(cpu) (cpu_callout_map & (1<<(cpu))) #define cpu_possible(cpu) (cpu_callout_map & (1<<(cpu)))
#define cpu_online(cpu) (cpu_online_map & (1<<(cpu))) #define cpu_online(cpu) (cpu_online_map & (1<<(cpu)))
#define for_each_cpu(cpu, mask) \
for(mask = cpu_online_map; \
cpu = __ffs(mask), mask != 0; \
mask &= ~(1<<cpu))
extern inline unsigned int num_online_cpus(void) extern inline unsigned int num_online_cpus(void)
{ {
return hweight32(cpu_online_map); return hweight32(cpu_online_map);
} }
/* We don't mark CPUs online until __cpu_up(), so we need another measure */
static inline int num_booting_cpus(void)
{
return hweight32(cpu_callout_map);
}
extern inline int any_online_cpu(unsigned int mask) extern inline int any_online_cpu(unsigned int mask)
{ {
if (mask & cpu_online_map) if (mask & cpu_online_map)
...@@ -95,7 +107,7 @@ extern inline int any_online_cpu(unsigned int mask) ...@@ -95,7 +107,7 @@ extern inline int any_online_cpu(unsigned int mask)
return -1; return -1;
} }
#ifdef CONFIG_X86_LOCAL_APIC
static __inline int hard_smp_processor_id(void) static __inline int hard_smp_processor_id(void)
{ {
/* we don't want to mark this access volatile - bad code generation */ /* we don't want to mark this access volatile - bad code generation */
...@@ -108,12 +120,7 @@ static __inline int logical_smp_processor_id(void) ...@@ -108,12 +120,7 @@ static __inline int logical_smp_processor_id(void)
return GET_APIC_LOGICAL_ID(*(unsigned long *)(APIC_BASE+APIC_LDR)); return GET_APIC_LOGICAL_ID(*(unsigned long *)(APIC_BASE+APIC_LDR));
} }
/* We don't mark CPUs online until __cpu_up(), so we need another measure */ #endif
static inline int num_booting_cpus(void)
{
return hweight32(cpu_callout_map);
}
#endif /* !__ASSEMBLY__ */ #endif /* !__ASSEMBLY__ */
#define NO_PROC_ID 0xFF /* No processor magic marker */ #define NO_PROC_ID 0xFF /* No processor magic marker */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment