summaryrefslogtreecommitdiffstats
path: root/arch/ppc/kernel
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-02-04 07:40:19 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-02-04 07:40:19 +0000
commit33263fc5f9ac8e8cb2b22d06af3ce5ac1dd815e4 (patch)
tree2d1b86a40bef0958a68cf1a2eafbeb0667a70543 /arch/ppc/kernel
parent216f5f51aa02f8b113aa620ebc14a9631a217a00 (diff)
Merge with Linux 2.3.32.
Diffstat (limited to 'arch/ppc/kernel')
-rw-r--r--arch/ppc/kernel/Makefile72
-rw-r--r--arch/ppc/kernel/align.c52
-rw-r--r--arch/ppc/kernel/entry.S6
-rw-r--r--arch/ppc/kernel/gemini_prom.S1
-rw-r--r--arch/ppc/kernel/gemini_setup.c58
-rw-r--r--arch/ppc/kernel/head.S83
-rw-r--r--arch/ppc/kernel/head_4xx.S600
-rw-r--r--arch/ppc/kernel/misc.S49
-rw-r--r--arch/ppc/kernel/mk_defs.c10
-rw-r--r--arch/ppc/kernel/oak_setup.c84
-rw-r--r--arch/ppc/kernel/oak_setup.h32
-rw-r--r--arch/ppc/kernel/open_pic.c18
-rw-r--r--arch/ppc/kernel/open_pic.h1
-rw-r--r--arch/ppc/kernel/pci.c46
-rw-r--r--arch/ppc/kernel/pmac_nvram.c (renamed from arch/ppc/kernel/pmac_support.c)7
-rw-r--r--arch/ppc/kernel/pmac_pci.c25
-rw-r--r--arch/ppc/kernel/ppc8xx_pic.c2
-rw-r--r--arch/ppc/kernel/ppc8xx_pic.h2
-rw-r--r--arch/ppc/kernel/ppc_asm.h23
-rw-r--r--arch/ppc/kernel/ppc_asm.tmpl18
-rw-r--r--arch/ppc/kernel/ppc_htab.c19
-rw-r--r--arch/ppc/kernel/ppc_ksyms.c16
-rw-r--r--arch/ppc/kernel/prep_setup.c16
-rw-r--r--arch/ppc/kernel/process.c10
-rw-r--r--arch/ppc/kernel/prom.c5
-rw-r--r--arch/ppc/kernel/qspan_pci.c1
-rw-r--r--arch/ppc/kernel/setup.c176
-rw-r--r--arch/ppc/kernel/signal.c1
-rw-r--r--arch/ppc/kernel/smp.c8
-rw-r--r--arch/ppc/kernel/traps.c17
30 files changed, 1190 insertions, 268 deletions
diff --git a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile
index 3677276b5..a41473fa5 100644
--- a/arch/ppc/kernel/Makefile
+++ b/arch/ppc/kernel/Makefile
@@ -12,7 +12,17 @@
O_TARGET := kernel.o
OX_OBJS := ppc_ksyms.o setup.o
-KHEAD := head.o
+
+
+ifeq ($(CONFIG_4xx),y)
+ KHEAD := head_4xx.o
+else
+ ifeq ($(CONFIG_8xx),y)
+ KHEAD := head_8xx.o
+ else
+ KHEAD := head.o
+ endif
+endif
ifdef CONFIG_ALL_PPC
CONFIG_PMAC=y
@@ -47,48 +57,50 @@ ifdef CONFIG_SMP
O_OBJS += smp.o
endif
-ifeq ($(CONFIG_8xx),y)
-KHEAD := head_8xx.o
-O_OBJS += m8xx_setup.o ppc8xx_pic.o
-ifndef CONFIG_MATH_EMULATION
-O_OBJS += softemu8xx.o
-endif
-ifdef CONFIG_PCI
-O_OBJS += qspan_pci.c
+ifeq ($(CONFIG_OAK),y)
+ O_OBJS += oak_setup.o
endif
-ifdef CONFIG_MBX
-O_OBJS += i8259.o
+
+ifeq ($(CONFIG_8xx),y)
+ O_OBJS += m8xx_setup.o ppc8xx_pic.o
+ ifndef CONFIG_MATH_EMULATION
+ O_OBJS += softemu8xx.o
+ endif
+ ifdef CONFIG_PCI
+ O_OBJS += qspan_pci.c
+ endif
+ ifdef CONFIG_MBX
+ O_OBJS += i8259.o
+ endif
endif
-else
-O_OBJS += chrp_setup.o chrp_pci.o chrp_time.o \
- pmac_time.o pmac_pci.o pmac_setup.o \
- prom.o open_pic.o feature.o \
- i8259.o pmac_pic.o indirect_pci.o \
- gemini_pci.o gemini_prom.o gemini_setup.o
ifeq ($(CONFIG_NVRAM),y)
-O_OBJS += pmac_support.o
+ O_OBJS += pmac_nvram.o
endif
-
-ifeq ($(CONFIG_PREP), y)
-O_OBJS += prep_pci.o prep_setup.o prep_nvram.o prep_time.o residual.o
+ifeq ($(CONFIG_6xx),y)
+ O_OBJS += open_pic.o indirect_pci.o
endif
-
-ifeq ($(CONFIG_PMAC), y)
+ifeq ($(CONFIG_APUS),y)
+ O_OBJS += apus_setup.o
endif
-
-ifeq ($(CONFIG_PMAC), y)
+ifeq ($(CONFIG_PMAC),y)
+ O_OBJS += pmac_pic.o pmac_setup.o pmac_time.o feature.o pmac_pci.o prom.o
endif
-
-ifdef CONFIG_APUS
-O_OBJS += apus_setup.o
+ifeq ($(CONFIG_CHRP),y)
+ O_OBJS += chrp_pci.o pmac_pci.o chrp_setup.o i8259.o \
+ chrp_time.o pmac_time.o prom.o
endif
+ifeq ($(CONFIG_PREP),y)
+ O_OBJS += prep_pci.o i8259.o prep_setup.o prep_nvram.o prep_time.o residual.o
+endif
+ifeq ($(CONFIG_GEMINI),y)
+ O_OBJS += gemini_prom.o gemini_pci.o gemini_setup.o
endif
all: $(KHEAD) kernel.o
head.o: head.S ppc_defs.h
-
+head_4xx.o: head_4xx.S ppc_defs.h
head_8xx.o: head_8xx.S ppc_defs.h
ppc_defs.h: mk_defs.c ppc_defs.head \
@@ -98,7 +110,7 @@ ppc_defs.h: mk_defs.c ppc_defs.head \
$(TOPDIR)/include/asm/ptrace.h
$(CC) $(CFLAGS) -S mk_defs.c
cp ppc_defs.head ppc_defs.h
- grep '^#define' mk_defs.s >>ppc_defs.h
+ grep '^#define' mk_defs.s >> ppc_defs.h
rm mk_defs.s
find_name : find_name.c
diff --git a/arch/ppc/kernel/align.c b/arch/ppc/kernel/align.c
index 6a20863c5..7f6340261 100644
--- a/arch/ppc/kernel/align.c
+++ b/arch/ppc/kernel/align.c
@@ -1,9 +1,13 @@
/*
* align.c - handle alignment exceptions for the Power PC.
*
- * Paul Mackerras August 1996.
- * Copyright (C) 1996 Paul Mackerras (paulus@cs.anu.edu.au).
+ * Copyright (c) 1996 Paul Mackerras <paulus@cs.anu.edu.au>
+ * Copyright (c) 1998-1999 TiVo, Inc.
+ * PowerPC 403GCX modifications.
+ * Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
+ * PowerPC 403GCX/405GP modifications.
*/
+#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <asm/ptrace.h>
@@ -16,6 +20,13 @@ struct aligninfo {
unsigned char flags;
};
+#if defined(CONFIG_4xx)
+#define OPCD(inst) (((inst) & 0xFC000000) >> 26)
+#define RS(inst) (((inst) & 0x03E00000) >> 21)
+#define RA(inst) (((inst) & 0x001F0000) >> 16)
+#define IS_DFORM(code) ((code) >= 32 && (code) <= 47)
+#endif
+
#define INVALID { 0, 0 }
#define LD 1 /* load */
@@ -170,6 +181,9 @@ int
fix_alignment(struct pt_regs *regs)
{
int instr, nb, flags;
+#if defined(CONFIG_4xx)
+ int opcode, f1, f2, f3;
+#endif
int i, t;
int reg, areg;
unsigned char *addr;
@@ -180,13 +194,42 @@ fix_alignment(struct pt_regs *regs)
unsigned char v[8];
} data;
+#if defined(CONFIG_4xx)
+ /* The 4xx-family processors have no DSISR register,
+ * so we emulate it.
+ */
+
+ instr = *((unsigned int *)regs->nip);
+ opcode = OPCD(instr);
+ reg = RS(instr);
+ areg = RA(instr);
+
+ if (IS_DFORM(opcode)) {
+ f1 = 0;
+ f2 = (instr & 0x04000000) >> 26;
+ f3 = (instr & 0x78000000) >> 27;
+ } else {
+ f1 = (instr & 0x00000006) >> 1;
+ f2 = (instr & 0x00000040) >> 6;
+ f3 = (instr & 0x00000780) >> 7;
+ }
+
+ instr = ((f1 << 5) | (f2 << 4) | f3);
+#else
+ reg = (regs->dsisr >> 5) & 0x1f; /* source/dest register */
+ areg = regs->dsisr & 0x1f; /* register to update */
instr = (regs->dsisr >> 10) & 0x7f;
+#endif
nb = aligninfo[instr].len;
if (nb == 0)
return 0; /* too hard or invalid instruction bits */
flags = aligninfo[instr].flags;
- addr = (unsigned char *) regs->dar;
- reg = (regs->dsisr >> 5) & 0x1f; /* source/dest register */
+
+ /* For the 4xx-family processors, the 'dar' field of the
+ * pt_regs structure is overloaded and is really from the DEAR.
+ */
+
+ addr = (unsigned char *)regs->dar;
/* Verify the address of the operand */
if (user_mode(regs)) {
@@ -280,7 +323,6 @@ fix_alignment(struct pt_regs *regs)
}
if (flags & U) {
- areg = regs->dsisr & 0x1f; /* register to update */
regs->gpr[areg] = regs->dar;
}
diff --git a/arch/ppc/kernel/entry.S b/arch/ppc/kernel/entry.S
index 6133f32ca..5ed04344e 100644
--- a/arch/ppc/kernel/entry.S
+++ b/arch/ppc/kernel/entry.S
@@ -386,13 +386,13 @@ _GLOBAL(fake_interrupt)
mtlr r0
blr
-#ifndef CONFIG_8xx
+
/*
* PROM code for specific machines follows. Put it
* here so it's easy to add arch-specific sections later.
* -- Cort
*/
-
+#if defined(CONFIG_CHRP) || defined(CONFIG_PMAC) || defined(CONFIG_ALL_PPC)
/*
* On CHRP, the Run-Time Abstraction Services (RTAS) have to be
* called with the MMU off.
@@ -432,4 +432,4 @@ enter_rtas:
mtspr SRR0,r8
mtspr SRR1,r9
rfi /* return to caller */
-#endif /* CONFIG_8xx */
+#endif /* CONFIG_CHRP || CONFIG_PMAC || CONFIG_ALL_PPC */
diff --git a/arch/ppc/kernel/gemini_prom.S b/arch/ppc/kernel/gemini_prom.S
index 095f50e8f..f91e992f4 100644
--- a/arch/ppc/kernel/gemini_prom.S
+++ b/arch/ppc/kernel/gemini_prom.S
@@ -23,6 +23,7 @@
*
*/
+_GLOBAL(prom_init)
_GLOBAL(gemini_prom_init)
#ifdef __SMP__
/* Since the MMU's on, get stuff in rom space that we'll need */
diff --git a/arch/ppc/kernel/gemini_setup.c b/arch/ppc/kernel/gemini_setup.c
index aee01f105..57ea34687 100644
--- a/arch/ppc/kernel/gemini_setup.c
+++ b/arch/ppc/kernel/gemini_setup.c
@@ -36,7 +36,6 @@
void gemini_setup_pci_ptrs(void);
-static int l2_printed = 0;
static unsigned char gemini_switch_map = 0;
static char *gemini_board_families[] = {
"VGM", "VSS", "KGM", "VGR", "KSS"
@@ -178,10 +177,8 @@ void __init gemini_setup_arch(void)
/* take special pains to map the MPIC, since it isn't mapped yet */
gemini_openpic_init();
-
/* start the L2 */
gemini_init_l2();
-
}
@@ -219,7 +216,6 @@ gemini_get_clock_speed(void)
return clock;
}
-
#define L2CR_PIPE_LATEWR (0x01800000) /* late-write SRAM */
#define L2CR_L2CTL (0x00100000) /* RAM control */
#define L2CR_INST_DISABLE (0x00400000) /* disable for insn's */
@@ -259,18 +255,17 @@ void __init gemini_init_l2(void)
probably always going to be late-write". --Dan */
if (reg & 0xc0) {
- if (!l2_printed) {
- printk("Enabling 750 L2 cache: %dKb\n",
- (128 << ((reg & 0xc0)>>6)));
- l2_printed=1;
- }
-
+ printk("Enabling 750 L2 cache: %dKb\n",
+ (128 << ((reg & 0xc0)>>6)));
/* take the size given */
cache = (((reg>>6) & 0x3)<<28);
}
else
+ {
+ printk("Enabling 750 L2 cache: 1M\n");
/* default of 1Mb */
cache = 0x3<<28;
+ }
reg &= 0x3;
@@ -278,6 +273,7 @@ void __init gemini_init_l2(void)
things. If found, tune it down to 1:1.5. -- Dan */
if (!reg) {
+printk("3\n");
speed = gemini_get_clock_speed();
if (speed >= 300) {
@@ -297,7 +293,10 @@ void __init gemini_init_l2(void)
write-through. This is fixed in IBM's 3.1 rev (I'm told), but
for now, always make 2.x versions use L2 write-through. --Dan */
if (((_get_PVR()>>8) & 0xf) <= 2)
+ {
cache |= L2CR_L2WT;
+ printk("L2 cache: Enabling Write-Through due to 750 Errata.\n");
+ }
#endif
cache |= L2CR_PIPE_LATEWR|L2CR_L2CTL|L2CR_INST_DISABLE;
_set_L2CR(0);
@@ -332,7 +331,7 @@ void __init gemini_init_IRQ(void)
/* gemini has no 8259 */
open_pic.irq_offset = 0;
- for( i=0; i < OPENPIC_VEC_SPURIOUS; i++ )
+ for( i=0; i < NR_IRQS; i++ )
irq_desc[i].ctl = &open_pic;
openpic_init(1);
#ifdef __SMP__
@@ -480,6 +479,39 @@ void __init gemini_calibrate_decr(void)
count_period_den = freq / 1000000;
}
+int gemini_get_irq( struct pt_regs *regs )
+{
+ int irq;
+
+ irq = openpic_irq( smp_processor_id() );
+ if (irq == OPENPIC_VEC_SPURIOUS)
+ /*
+ * Spurious interrupts should never be
+ * acknowledged
+ */
+ irq = -1;
+ /*
+ * I would like to openpic_eoi here but there seem to be timing problems
+ * between the openpic ack and the openpic eoi.
+ * -- Cort
+ */
+ return irq;
+}
+
+void gemini_post_irq(int irq)
+{
+ /*
+ * If it's an i8259 irq then we've already done the
+ * openpic irq. So we just check to make sure the controller
+ * is an openpic and if it is then eoi
+ *
+ * We do it this way since our irq_desc[irq].ctl can change
+ * with RTL and no longer be open_pic -- Cort
+ */
+ if ( irq >= open_pic.irq_offset)
+ openpic_eoi( smp_processor_id() );
+}
+
void __init gemini_init(unsigned long r3, unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7)
@@ -506,8 +538,8 @@ void __init gemini_init(unsigned long r3, unsigned long r4, unsigned long r5,
ppc_md.get_cpuinfo = gemini_get_cpuinfo;
ppc_md.irq_cannonicalize = NULL;
ppc_md.init_IRQ = gemini_init_IRQ;
- ppc_md.get_irq = chrp_get_irq;
- ppc_md.post_irq = chrp_post_irq;
+ ppc_md.get_irq = gemini_get_irq;
+ ppc_md.post_irq = gemini_post_irq;
ppc_md.init = NULL;
ppc_md.restart = gemini_restart;
diff --git a/arch/ppc/kernel/head.S b/arch/ppc/kernel/head.S
index 57ff53992..451a1cad4 100644
--- a/arch/ppc/kernel/head.S
+++ b/arch/ppc/kernel/head.S
@@ -137,7 +137,7 @@ __start:
#endif
/*
* We have to do any OF calls before we map ourselves to KERNELBASE,
- * because OF may have I/O devices mapped in in that area
+ * because OF may have I/O devices mapped into that area
* (particularly on CHRP).
*/
mr r31,r3 /* save parameters */
@@ -444,7 +444,9 @@ SystemCall:
STD_EXCEPTION(0xd00, SingleStep, SingleStepException)
STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
+#ifdef CONFIG_ALTIVEC
STD_EXCEPTION(0xf20, AltiVec, AltiVecUnavailable)
+#endif /* CONFIG_ALTIVEC */
/*
* Handle TLB miss for instruction on 603/603e.
@@ -1166,7 +1168,6 @@ __secondary_start:
mtspr SRR0,r3
mtspr SRR1,r4
rfi
-
#endif /* CONFIG_SMP */
/*
@@ -1351,6 +1352,42 @@ _GLOBAL(set_context)
SYNC
blr
+/*
+ * An undocumented "feature" of 604e requires that the v bit
+ * be cleared before changing BAT values.
+ *
+ * Also, newer IBM firmware does not clear bat3 and 4 so
+ * this makes sure it's done.
+ * -- Cort
+ */
+clear_bats:
+#if !defined(CONFIG_GEMINI)
+ li r20,0
+ mfspr r9,PVR
+ rlwinm r9,r9,16,16,31 /* r9 = 1 for 601, 4 for 604 */
+ cmpwi r9, 1
+ beq 1f
+
+ mtspr DBAT0U,r20
+ mtspr DBAT0L,r20
+ mtspr DBAT1U,r20
+ mtspr DBAT1L,r20
+ mtspr DBAT2U,r20
+ mtspr DBAT2L,r20
+ mtspr DBAT3U,r20
+ mtspr DBAT3L,r20
+1:
+ mtspr IBAT0U,r20
+ mtspr IBAT0L,r20
+ mtspr IBAT1U,r20
+ mtspr IBAT1L,r20
+ mtspr IBAT2U,r20
+ mtspr IBAT2L,r20
+ mtspr IBAT3U,r20
+ mtspr IBAT3L,r20
+#endif /* !defined(CONFIG_GEMINI) */
+ blr
+
/*
* We put a few things here that have to be page-aligned.
* This stuff goes at the beginning of the data segment,
@@ -1374,45 +1411,3 @@ swapper_pg_dir:
.globl cmd_line
cmd_line:
.space 512
-
-/*
- * An undocumented "feature" of 604e requires that the v bit
- * be cleared before changing BAT values.
- *
- * Also, newer IBM firmware does not clear bat3 and 4 so
- * this makes sure it's done.
- * -- Cort
- */
-clear_bats:
- mfmsr r20
- andi. r19,r20,MSR_DR
- beqlr
-
- li r20,0
-
- mtspr DBAT0U,r20
- mtspr DBAT0L,r20
- mtspr IBAT0U,r20
- mtspr IBAT0L,r20
- sync
- isync
-
- mtspr DBAT1U,r20
- mtspr DBAT1L,r20
- mtspr IBAT1U,r20
- mtspr IBAT1L,r20
- sync
- isync
-
- mtspr DBAT2U,r20
- mtspr DBAT2L,r20
- mtspr IBAT2U,r20
- mtspr IBAT2L,r20
-
- mtspr DBAT3U,r20
- mtspr DBAT3L,r20
- mtspr IBAT3U,r20
- mtspr IBAT3L,r20
-
- blr
-
diff --git a/arch/ppc/kernel/head_4xx.S b/arch/ppc/kernel/head_4xx.S
new file mode 100644
index 000000000..abc651218
--- /dev/null
+++ b/arch/ppc/kernel/head_4xx.S
@@ -0,0 +1,600 @@
+/*
+ * Copyright (c) 1995-1996 Gary Thomas <gdt@linuxppc.org>
+ * Initial PowerPC version.
+ * Copyright (c) 1996 Cort Dougan <cort@cs.nmt.edu>
+ * Rewritten for PReP
+ * Copyright (c) 1996 Paul Mackerras <paulus@cs.anu.edu.au>
+ * Low-level exception handers, MMU support, and rewrite.
+ * Copyright (c) 1997 Dan Malek <dmalek@jlc.net>
+ * PowerPC 8xx modifications.
+ * Copyright (c) 1998-1999 TiVo, Inc.
+ * PowerPC 403GCX modifications.
+ * Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
+ * PowerPC 403GCX/405GP modifications.
+ *
+ * Module name: head_4xx.S
+ *
+ * Description:
+ * Kernel execution entry point code.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ */
+
+#include <linux/config.h>
+
+#include <asm/processor.h>
+#include <asm/4xx.h>
+#include <asm/403gcx.h>
+#include <asm/405gp.h>
+#include <asm/page.h>
+#include <asm/mmu.h>
+
+#include "ppc_asm.h"
+
+
+/* Preprocessor Defines */
+
+#define STND_EXC 0
+#define CRIT_EXC 1
+
+###
+### Check to make sure the right processor has been defined.
+###
+
+#if !defined(CONFIG_4xx)
+#error "This file is only appropriate for kernels supporting the PPC4xx."
+#endif
+
+###
+### Execution entry point.
+###
+
+###
+### As with the other PowerPC ports, it is expected that when code
+### execution begins here, the following registers contain valid, yet
+### optional, information:
+###
+### r3 - ???
+### r4 - Starting address of the init RAM disk
+### r5 - Ending address of the init RAM disk
+### r6 - Start of kernel command line string (e.g. "mem=96m")
+### r7 - End of kernel command line string
+###
+
+ .text
+_GLOBAL(_stext)
+_GLOBAL(_start)
+ ## Save residual data, init RAM disk, and command line parameters
+
+ mr r31,r3
+ mr r30,r4
+ mr r29,r5
+ mr r28,r6
+ mr r27,r7
+
+ ## Set the ID for this CPU
+
+ li r24,0
+
+ ## Establish exception vector base
+
+ lis r0,KERNELBASE@h
+ mtspr SPRN_EVPR,r0
+
+ ## Jump to the main PowerPC kernel start-up code
+
+1: lis r7,start_here@ha
+ addi r7,r7,start_here@l
+ mtlr r7
+ blr
+
+###
+### Exception vector entry code. This code runs with address translation
+### turned off (i.e. using physical addresses). We assume SPRG3 has the
+### physical address of the current task thread_struct.
+###
+
+ ## Common exception code for all exception types.
+
+#define COMMON_PROLOG \
+0: mtspr SPRN_SPRG0,r20; /* We need r20, move it to SPRG0 */\
+ mtspr SPRN_SPRG1,r21; /* We need r21, move it to SPRG1 */\
+ mfcr r20; /* We need the CR, move it to r20 */\
+ mfspr r21,SPRN_SPRG2; /* Exception stack to use */\
+ cmpwi cr0,r21,0; /* From user mode or RTAS? */\
+ bne 1f; /* Not RTAS, branch */\
+ tophys(r21, r1); /* Convert vka in r1 to pka in r21 */\
+ subi r21,r21,INT_FRAME_SIZE; /* Allocate an exception frame */\
+1: stw r20,_CCR(r21); /* Save CR on the stack */\
+ stw r22,GPR22(r21); /* Save r22 on the stack */\
+ stw r23,GPR23(r21); /* r23 Save on the stack */\
+ mfspr r20,SPRN_SPRG0; /* Get r20 back out of SPRG0 */\
+ stw r20,GPR20(r21); /* Save r20 on the stack */\
+ mfspr r22,SPRN_SPRG1; /* Get r21 back out of SPRG0 */\
+ stw r22,GPR21(r21); /* Save r21 on the stack */\
+ mflr r20; \
+ stw r20,_LINK(r21); /* Save LR on the stack */\
+ mfctr r22; \
+ stw r22,_CTR(r21); /* Save CTR on the stack */\
+ mfspr r20,XER; \
+ stw r20,_XER(r21); /* Save XER on the stack */
+
+#define COMMON_EPILOG \
+ stw r0,GPR0(r21); /* Save r0 on the stack */\
+ stw r1,GPR1(r21); /* Save r1 on the stack */\
+ stw r2,GPR2(r21); /* Save r2 on the stack */\
+ stw r1,0(r21); \
+ tovirt(r1,r21); /* Set-up new kernel stack pointer */\
+ SAVE_4GPRS(3, r21); /* Save r3 through r6 on the stack */
+
+ ## Common exception code for standard (non-critical) exceptions.
+
+#define STND_EXCEPTION_PROLOG \
+ COMMON_PROLOG; \
+ mfspr r22,SPRN_SRR0; /* Faulting instruction address */\
+ mfspr r23,SPRN_SRR1; /* MSR at the time of fault */\
+ COMMON_EPILOG;
+
+ ## Common exception code for critical exceptions.
+
+#define CRIT_EXCEPTION_PROLOG \
+ COMMON_PROLOG; \
+ mfspr r22,SPRN_SRR2; /* Faulting instruction address */\
+ mfspr r23,SPRN_SRR3; /* MSR at the time of fault */\
+ COMMON_EPILOG;
+
+###
+### Macros for specific exception types
+###
+
+#define START_EXCEPTION(n, label) \
+ . = n; \
+label:
+
+
+#define FINISH_EXCEPTION(func) \
+ bl transfer_to_handler; \
+ .long func; \
+ .long ret_from_except
+
+
+#define STND_EXCEPTION(n, label, func) \
+ START_EXCEPTION(n, label); \
+ STND_EXCEPTION_PROLOG; \
+ addi r3,r1,STACK_FRAME_OVERHEAD; \
+ li r0,STND_EXC; \
+ li r20,MSR_KERNEL; \
+ FINISH_EXCEPTION(func)
+
+
+#define CRIT_EXCEPTION(n, label, func) \
+ START_EXCEPTION(n, label); \
+ CRIT_EXCEPTION_PROLOG; \
+ addi r3,r1,STACK_FRAME_OVERHEAD; \
+ li r0,CRIT_EXC; \
+ li r20,MSR_KERNEL; \
+ FINISH_EXCEPTION(func)
+
+
+#define INTR_EXCEPTION(n, label, func) \
+ START_EXCEPTION(n, label); \
+ STND_EXCEPTION_PROLOG; \
+ addi r3,r1,STACK_FRAME_OVERHEAD; \
+ li r0,STND_EXC; \
+ li r20,MSR_KERNEL; \
+ li r4,0; \
+ bl transfer_to_handler; \
+_GLOBAL(do_IRQ_intercept); \
+ .long func; \
+ .long ret_from_except
+
+
+###
+### Exception vectors.
+###
+
+### 0x0100 - Critical Interrupt Exception
+
+ CRIT_EXCEPTION(0x0100, CriticalInterrupt, UnknownException)
+
+### 0x0200 - Machine Check Exception
+
+ CRIT_EXCEPTION(0x0200, MachineCheck, MachineCheckException)
+
+### 0x0300 - Data Storage Exception
+
+ START_EXCEPTION(0x0300, DataAccess)
+ STND_EXCEPTION_PROLOG
+ mfspr r5,SPRN_ESR # Grab the ESR, save it, pass as arg3
+ stw r5,_ESR(r21)
+ mfspr r4,SPRN_DEAR # Grab the DEAR, save it, pass as arg2
+ stw r4,_DEAR(r21)
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ li r0,STND_EXC # This is a standard exception
+ li r20,MSR_KERNEL
+ rlwimi r20,r23,0,16,16 # Copy EE bit from the saved MSR
+ FINISH_EXCEPTION(do_page_fault) # do_page_fault(regs, ESR, DEAR)
+
+### 0x0400 - Instruction Storage Exception
+
+ START_EXCEPTION(0x0400, InstructionAccess)
+ STND_EXCEPTION_PROLOG
+ mr r4,r22 # Pass SRR0 as arg2
+ mr r5,r23 # Pass SRR1 as arg3
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ li r0,STND_EXC # This is a standard exception
+ li r20,MSR_KERNEL
+ rlwimi r20,r23,0,16,16 # Copy EE bit from the saved MSR
+ FINISH_EXCEPTION(do_page_fault) # do_page_fault(regs, SRR0, SRR1)
+
+### 0x0500 - External Interrupt Exception
+
+ INTR_EXCEPTION(0x0500, HardwareInterrupt, do_IRQ)
+
+### 0x0600 - Alignment Exception
+
+ START_EXCEPTION(0x0600, Alignment)
+ STND_EXCEPTION_PROLOG
+ mfspr r4,SPRN_DEAR # Grab the DEAR and save it
+ stw r4,_DEAR(r21)
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ li r0,STND_EXC # This is a standard exception
+ li r20,MSR_KERNEL
+ rlwimi r20,r23,0,16,16 # Copy EE bit from the saved MSR
+ FINISH_EXCEPTION(AlignmentException)
+
+### 0x0700 - Program Exception
+
+ START_EXCEPTION(0x0700, ProgramCheck)
+ STND_EXCEPTION_PROLOG
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ li r0,STND_EXC # This is a standard exception
+ li r20,MSR_KERNEL
+ rlwimi r20,r23,0,16,16 # Copy EE bit from the saved MSR
+ FINISH_EXCEPTION(ProgramCheckException)
+
+ STND_EXCEPTION(0x0800, Trap_08, UnknownException)
+ STND_EXCEPTION(0x0900, Trap_09, UnknownException)
+ STND_EXCEPTION(0x0A00, Trap_0A, UnknownException)
+ STND_EXCEPTION(0x0B00, Trap_0B, UnknownException)
+### 0x0C00 - System Call Exception
+
+ START_EXCEPTION(0x0C00, SystemCall)
+ STND_EXCEPTION_PROLOG
+ stw r3,ORIG_GPR3(r21)
+ li r0,STND_EXC # This is a standard exception
+ li r20,MSR_KERNEL
+ rlwimi r20,r23,0,16,16 # Copy EE bit from the saved MSR
+ FINISH_EXCEPTION(DoSyscall)
+
+ STND_EXCEPTION(0x0D00, Trap_0D, UnknownException)
+ STND_EXCEPTION(0x0E00, Trap_0E, UnknownException)
+ STND_EXCEPTION(0x0F00, Trap_0F, UnknownException)
+
+#if 0
+### 0x1000 - Programmable Interval Timer (PIT) Exception
+
+ STND_EXCEPTION(0x1000, PITException, UnknownException)
+
+### 0x1010 - Fixed Interval Timer (FIT) Exception
+
+ STND_EXCEPTION(0x1010, FITException, UnknownException)
+
+### 0x1020 - Watchdog Timer (WDT) Exception
+
+ CRIT_EXCEPTION(0x1020, WDTException, UnknownException)
+#endif
+
+### 0x1100 - Data TLB Miss Exception
+
+ START_EXCEPTION(0x1100, DTLBMiss)
+ STND_EXCEPTION_PROLOG
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ li r0,STND_EXC
+ li r20,MSR_KERNEL
+ FINISH_EXCEPTION(UnknownException)
+
+### 0x1200 - Instruction TLB Miss Exception
+
+ START_EXCEPTION(0x1200, ITLBMiss)
+ STND_EXCEPTION_PROLOG
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ li r0,STND_EXC
+ li r20,MSR_KERNEL
+ FINISH_EXCEPTION(UnknownException)
+
+ STND_EXCEPTION(0x1300, Trap_13, UnknownException)
+ STND_EXCEPTION(0x1400, Trap_14, UnknownException)
+ STND_EXCEPTION(0x1500, Trap_15, UnknownException)
+ STND_EXCEPTION(0x1600, Trap_16, UnknownException)
+ STND_EXCEPTION(0x1700, Trap_17, UnknownException)
+ STND_EXCEPTION(0x1800, Trap_18, UnknownException)
+ STND_EXCEPTION(0x1900, Trap_19, UnknownException)
+ STND_EXCEPTION(0x1A00, Trap_1A, UnknownException)
+ STND_EXCEPTION(0x1B00, Trap_1B, UnknownException)
+ STND_EXCEPTION(0x1C00, Trap_1C, UnknownException)
+ STND_EXCEPTION(0x1D00, Trap_1D, UnknownException)
+ STND_EXCEPTION(0x1E00, Trap_1E, UnknownException)
+ STND_EXCEPTION(0x1F00, Trap_1F, UnknownException)
+
+### 0x2000 - Debug Exception
+
+ CRIT_EXCEPTION(0x2000, DebugTrap, UnknownException)
+
+###
+### Other PowerPC processors, namely those derived from the 6xx-series
+### have vectors from 0x2100 through 0x2F00 defined, but marked as reserved.
+### However, for the 4xx-series processors these are neither defined nor
+### reserved.
+###
+
+###
+### This code finishes saving the registers to the exception frame
+### and jumps to the appropriate handler for the exception, turning
+### on address translation.
+###
+
+_GLOBAL(transfer_to_handler)
+ stw r22,_NIP(r21) # Save the faulting IP on the stack
+ stw r23,_MSR(r21) # Save the exception MSR on the stack
+ SAVE_GPR(7, r21) # Save r7 on the stack
+ SAVE_4GPRS(8, r21) # Save r8 through r11 on the stack
+ SAVE_8GPRS(12, r21) # Save r12 through r19 on the stack
+ SAVE_8GPRS(24, r21) # Save r24 through r31 on the stack
+ andi. r23,r23,MSR_PR # Is this from user space?
+ mfspr r23,SPRN_SPRG3 # If from user, fix up THREAD.regs
+ beq 2f # No, it is from the kernel; branch.
+ addi r24,r1,STACK_FRAME_OVERHEAD
+ stw r24,PT_REGS(r23) #
+2: addi r2,r23,-THREAD # Set r2 to current thread
+ tovirt(r2,r2)
+ mflr r23
+ andi. r24,r23,0x3f00 # Get vector offset
+ stw r24,TRAP(r21)
+ li r22,RESULT
+ stwcx. r22,r22,r21 # Clear the reservation
+ li r22,0
+ stw r22,RESULT(r21)
+ mtspr SPRN_SPRG2,r22 # r1 is now the kernel stack pointer
+ addi r24,r2,TASK_STRUCT_SIZE # Check for kernel stack overflow
+ cmplw cr0,r1,r2
+ cmplw cr1,r1,r24
+ crand cr1,cr1,cr4
+ bgt- stack_ovf # If r2 < r1 < r2 + TASK_STRUCT_SIZE
+ lwz r24,0(r23) # Virtual address of the handler
+ lwz r23,4(r23) # Handler return pointer
+ cmpwi cr0,r0,STND_EXC # What type of exception is this?
+ bne 3f # It is a critical exception...
+
+ ## Standard exception jump path
+
+ mtspr SPRN_SRR0,r24 # Set up the instruction pointer
+ mtspr SPRN_SRR1,r20 # Set up the machine state register
+ mtlr r23 # Set up the return pointer
+ SYNC
+ rfi # Enable the MMU, jump to the handler
+
+ ## Critical exception jump path
+
+3: mtspr SPRN_SRR2,r24 # Set up the instruction pointer
+ mtspr SPRN_SRR3,r20 # Set up the machine state register
+ mtlr r23 # Set up the return pointer
+ SYNC
+ rfci # Enable the MMU, jump to the handler
+
+###
+### On kernel stack overlow, load up an initial stack pointer and call
+### StackOverflow(regs), which should NOT return.
+###
+
+stack_ovf:
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ lis r1,init_task_union@ha
+ addi r1,r1,init_task_union@l
+ addi r1,r1,TASK_UNION_SIZE - STACK_FRAME_OVERHEAD
+ lis r24,StackOverflow@ha
+ addi r24,r24,StackOverflow@l
+ li r20,MSR_KERNEL
+ mtspr SPRN_SRR0,r24 # Set up the instruction pointer
+ mtspr SPRN_SRR1,r20 # Set up the machine state register
+ SYNC
+ rfi # Enable the MMU, jump to StackOverflow
+
+###
+### extern void giveup_altivec(struct task_struct *prev)
+###
+### The PowerPC 4xx family of processors do not have AltiVec capabilities, so
+### this just returns.
+###
+
+_GLOBAL(giveup_altivec)
+ blr
+
+###
+### extern void giveup_fpu(struct task_struct *prev)
+###
+### The PowerPC 4xx family of processors do not have an FPU, so this just
+### returns.
+###
+
+_GLOBAL(giveup_fpu)
+ blr
+
+###
+### extern void abort(void)
+###
+### At present, this routine just applies a system reset.
+###
+
+_GLOBAL(abort)
+ mfspr r13,SPRN_DBCR
+ ori r13,r13,DBCR_RST(SYSTEM)@h
+ mtspr SPRN_DBCR,r13
+
+
+###
+### This code is jumped-to from the startup code. It copies the kernel
+### image from wherever it happens to be currently running at in physical
+### address space to physical address 0.
+###
+### In general, for a running Linux/PPC system:
+### Kernel Physical Address (KPA) = 0x00000000
+### Kernel Virtual Address (KVA) = 0xC0000000
+###
+
+#if 0
+relocate_kernel:
+ lis r9,0x426f /* if booted from BootX, don't */
+ addi r9,r9,0x6f58 /* translate source addr */
+ cmpw r31,r9 /* (we have to on chrp) */
+ beq 7f
+ rlwinm r4,r4,0,8,31 /* translate source address */
+ add r4,r4,r3 /* to region mapped with BATs */
+7: addis r9,r26,klimit@ha /* fetch klimit */
+ lwz r25,klimit@l(r9)
+ addis r25,r25,-KERNELBASE@h
+ li r6,0 /* Destination offset */
+ li r5,0x4000 /* # bytes of memory to copy */
+ bl copy_and_flush /* copy the first 0x4000 bytes */
+ addi r0,r3,4f@l /* jump to the address of 4f */
+ mtctr r0 /* in copy and do the rest. */
+ bctr /* jump to the copy */
+4: mr r5,r25
+ bl copy_and_flush /* copy the rest */
+ b turn_on_mmu
+
+/*
+ * Copy routine used to copy the kernel to start at physical address 0
+ * and flush and invalidate the caches as needed.
+ * r3 = dest addr, r4 = source addr, r5 = copy limit, r6 = start offset
+ * on exit, r3, r4, r5 are unchanged, r6 is updated to be >= r5.
+ */
+copy_and_flush:
+ addi r5,r5,-4
+ addi r6,r6,-4
+4: li r0,8
+ mtctr r0
+3: addi r6,r6,4 /* copy a cache line */
+ lwzx r0,r6,r4
+ stwx r0,r6,r3
+ bdnz 3b
+ dcbst r6,r3 /* write it to memory */
+ sync
+ icbi r6,r3 /* flush the icache line */
+ cmplw 0,r6,r5
+ blt 4b
+ isync
+ addi r5,r5,4
+ addi r6,r6,4
+ blr
+#endif
+
+###
+### This is where the main kernel code starts.
+###
+
+start_here:
+ ## Establish a pointer to the current task
+
+ lis r2,init_task_union@h
+ ori r2,r2,init_task_union@l
+
+ ## Clear out the BSS as per ANSI C requirements
+
+ lis r7,_end@ha
+ addi r7,r7,_end@l
+ lis r8,__bss_start@ha
+ addi r8,r8,__bss_start@l
+ subf r7,r8,r7
+ addi r7,r7,3
+ srwi. r7,r7,2
+ beq 2f
+ addi r8,r8,-4
+ mtctr r7
+ li r0,0
+3: stwu r0,4(r8)
+ bdnz 3b
+
+ ## Stack
+
+2: addi r1,r2,TASK_UNION_SIZE
+ li r0,0
+ stwu r0,-STACK_FRAME_OVERHEAD(r1)
+
+ ## Determine what type of platform this is.
+
+ mr r3,r31
+ mr r4,r30
+ mr r5,r29
+ mr r6,r28
+ mr r7,r27
+ bl identify_machine
+
+ ## Initialize the memory management unit.
+
+ bl MMU_init
+
+ ## Go back to running unmapped so that we can change to our
+ ## exception vectors.
+
+ lis r4,2f@h
+ ori r4,r4,2f@l
+ tophys(r4,r4)
+ li r3,MSR_KERNEL & ~(MSR_IR|MSR_DR)
+ mtspr SPRN_SRR0,r4 # Set up the instruction pointer
+ mtspr SPRN_SRR1,r3 # Set up the machine state register
+ rfi
+
+ ## Load up the kernel context
+
+2: SYNC # Force all PTE updates to finish
+# tlbia # Clear all TLB entries
+# sync # Wait for tlbia to finish...
+
+ ## Set up for using our exception vectors
+
+ tophys(r4,r2) # Pointer to physical current thread
+ addi r4,r4,THREAD # The init task thread
+ mtspr SPRN_SPRG3,r4 # Save it for exceptions later
+ li r3,0 #
+ mtspr SPRN_SPRG2,r3 # 0 implies r1 has kernel stack pointer
+
+ ## Really turn on the MMU and jump into the kernel
+
+ lis r4,MSR_KERNEL@h
+ ori r4,r4,MSR_KERNEL@l
+ lis r3,start_kernel@h
+ ori r3,r3,start_kernel@l
+ mtspr SPRN_SRR0,r3 # Set up the instruction pointer
+ mtspr SPRN_SRR1,r4 # Set up the machine state register
+ rfi # Enable the MMU, jump to the kernel
+
+_GLOBAL(set_context)
+ mtspr SPRN_PID,r3
+ tlbia
+ SYNC
+ blr
+
+###
+### We put a few things here that have to be page-aligned. This stuff
+### goes at the beginning of the data segment, which is page-aligned.
+###
+
+ .data
+_GLOBAL(sdata)
+_GLOBAL(empty_zero_page)
+ .space 4096
+_GLOBAL(swapper_pg_dir)
+ .space 4096
+
+###
+### This space gets a copy of optional info passed to us by the bootstrap
+### which is used to pass parameters into the kernel like root=/dev/sda1, etc.
+###
+
+_GLOBAL(cmd_line)
+ .space 512
diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S
index 89994881b..444654ec6 100644
--- a/arch/ppc/kernel/misc.S
+++ b/arch/ppc/kernel/misc.S
@@ -103,8 +103,7 @@ _GLOBAL(__no_use_sti)
* We were about to enable interrupts but we have to simulate
* some interrupts that were lost by enable_irq first.
*/
- .globl do_lost_interrupts
-do_lost_interrupts:
+_GLOBAL(do_lost_interrupts)
stwu r1,-16(r1)
mflr r0
stw r0,20(r1)
@@ -405,8 +404,10 @@ _GLOBAL(atomic_set_mask)
* The *_ns versions don't do byte-swapping.
*/
_GLOBAL(_insb)
+ cmpw 0,r5,0
mtctr r5
subi r4,r4,1
+ blelr-
00: lbz r5,0(r3)
eieio
stbu r5,1(r4)
@@ -414,8 +415,10 @@ _GLOBAL(_insb)
blr
_GLOBAL(_outsb)
+ cmpw 0,r5,0
mtctr r5
subi r4,r4,1
+ blelr-
00: lbzu r5,1(r4)
stb r5,0(r3)
eieio
@@ -423,8 +426,10 @@ _GLOBAL(_outsb)
blr
_GLOBAL(_insw)
+ cmpw 0,r5,0
mtctr r5
subi r4,r4,2
+ blelr-
00: lhbrx r5,0,r3
eieio
sthu r5,2(r4)
@@ -432,8 +437,10 @@ _GLOBAL(_insw)
blr
_GLOBAL(_outsw)
+ cmpw 0,r5,0
mtctr r5
subi r4,r4,2
+ blelr-
00: lhzu r5,2(r4)
eieio
sthbrx r5,0,r3
@@ -441,8 +448,10 @@ _GLOBAL(_outsw)
blr
_GLOBAL(_insl)
+ cmpw 0,r5,0
mtctr r5
subi r4,r4,4
+ blelr-
00: lwbrx r5,0,r3
eieio
stwu r5,4(r4)
@@ -450,8 +459,10 @@ _GLOBAL(_insl)
blr
_GLOBAL(_outsl)
+ cmpw 0,r5,0
mtctr r5
subi r4,r4,4
+ blelr-
00: lwzu r5,4(r4)
stwbrx r5,0,r3
eieio
@@ -460,8 +471,10 @@ _GLOBAL(_outsl)
_GLOBAL(ide_insw)
_GLOBAL(_insw_ns)
+ cmpw 0,r5,0
mtctr r5
subi r4,r4,2
+ blelr-
00: lhz r5,0(r3)
eieio
sthu r5,2(r4)
@@ -470,8 +483,10 @@ _GLOBAL(_insw_ns)
_GLOBAL(ide_outsw)
_GLOBAL(_outsw_ns)
+ cmpw 0,r5,0
mtctr r5
subi r4,r4,2
+ blelr-
00: lhzu r5,2(r4)
sth r5,0(r3)
eieio
@@ -479,8 +494,10 @@ _GLOBAL(_outsw_ns)
blr
_GLOBAL(_insl_ns)
+ cmpw 0,r5,0
mtctr r5
subi r4,r4,4
+ blelr-
00: lwz r5,0(r3)
eieio
stwu r5,4(r4)
@@ -488,8 +505,10 @@ _GLOBAL(_insl_ns)
blr
_GLOBAL(_outsl_ns)
+ cmpw 0,r5,0
mtctr r5
subi r4,r4,4
+ blelr-
00: lwzu r5,4(r4)
stw r5,0(r3)
eieio
@@ -758,8 +777,19 @@ _GLOBAL(_set_L2CR)
* We restore and save the fpscr so the task gets the same result
* and exceptions as if the cpu had performed the load or store.
*/
+
+#if defined(CONFIG_4xx)
+_GLOBAL(cvt_fd)
+ lfs 0,0(r3)
+ stfd 0,0(r4)
+ blr
+
+_GLOBAL(cvt_df)
+ lfd 0,0(r3)
+ stfs 0,0(r4)
+ blr
+#else
_GLOBAL(cvt_fd)
-cvt_fd:
lfd 0,-4(r5) /* load up fpscr value */
mtfsf 0xff,0
lfs 0,0(r3)
@@ -769,7 +799,6 @@ cvt_fd:
blr
_GLOBAL(cvt_df)
-cvt_df:
lfd 0,-4(r5) /* load up fpscr value */
mtfsf 0xff,0
lfd 0,0(r3)
@@ -777,9 +806,9 @@ cvt_df:
mffs 0 /* save new fpscr value */
stfd 0,-4(r5)
blr
+#endif
- .globl __clear_msr_me
-__clear_msr_me:
+_GLOBAL(__clear_msr_me)
mfmsr r0 /* Get current interrupt state */
lis r3,0
ori r3,r3,MSR_ME
@@ -843,8 +872,7 @@ SYSCALL(read)
/* Why isn't this a) automatic, b) written in 'C'? */
.data
.align 4
- .globl sys_call_table
-sys_call_table:
+_GLOBAL(sys_call_table)
.long sys_ni_syscall /* 0 - old "setup()" system call */
.long sys_exit
.long sys_fork
@@ -921,7 +949,7 @@ sys_call_table:
.long sys_sigpending
.long sys_sethostname
.long sys_setrlimit /* 75 */
- .long sys_getrlimit
+ .long sys_old_getrlimit
.long sys_getrusage
.long sys_gettimeofday
.long sys_settimeofday
@@ -1039,4 +1067,5 @@ sys_call_table:
.long sys_ni_syscall /* streams1 */
.long sys_ni_syscall /* streams2 */
.long sys_vfork
- .space (NR_syscalls-183)*4
+ .long sys_getrlimit /* 190 */
+ .space (NR_syscalls-190)*4
diff --git a/arch/ppc/kernel/mk_defs.c b/arch/ppc/kernel/mk_defs.c
index 849e268fe..34682bd2a 100644
--- a/arch/ppc/kernel/mk_defs.c
+++ b/arch/ppc/kernel/mk_defs.c
@@ -88,7 +88,9 @@ main(void)
DEFINE(GPR29, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[29]));
DEFINE(GPR30, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[30]));
DEFINE(GPR31, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[31]));
- /* Note: these symbols include _ because they overlap with special register names */
+ /* Note: these symbols include _ because they overlap with special
+ * register names
+ */
DEFINE(_NIP, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, nip));
DEFINE(_MSR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, msr));
DEFINE(_CTR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, ctr));
@@ -97,6 +99,12 @@ main(void)
DEFINE(_XER, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, xer));
DEFINE(_DAR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, dar));
DEFINE(_DSISR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, dsisr));
+ /* The PowerPC 400-class processors have neither the DAR nor the DSISR
+ * SPRs. Hence, we overload them to hold the similar DEAR and ESR SPRs
+ * for such processors.
+ */
+ DEFINE(_DEAR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, dar));
+ DEFINE(_ESR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, dsisr));
DEFINE(ORIG_GPR3, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, orig_gpr3));
DEFINE(RESULT, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, result));
DEFINE(TRAP, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, trap));
diff --git a/arch/ppc/kernel/oak_setup.c b/arch/ppc/kernel/oak_setup.c
new file mode 100644
index 000000000..a9c9137a0
--- /dev/null
+++ b/arch/ppc/kernel/oak_setup.c
@@ -0,0 +1,84 @@
+/*
+ *
+ * Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
+ *
+ * Module name: oak_setup.c
+ *
+ * Description:
+ * Architecture- / platform-specific boot-time initialization code for
+ * the IBM PowerPC 403GCX "Oak" evaluation board. Adapted from original
+ * code by Gary Thomas, Cort Dougan <cort@cs.nmt.edu>, and Dan Malek
+ * <dmalek@jlc.net>.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/string.h>
+
+#include <asm/machdep.h>
+#include <asm/page.h>
+
+#include "oak_setup.h"
+
+
+void __init
+oak_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7)
+{
+#if 0
+#if defined(CONFIG_BLK_DEV_INITRD)
+ /*
+ * If the init RAM disk has been configured in, and there's a valid
+ * starting address for it, set it up.
+ */
+ if (r4) {
+ initrd_start = r4 + KERNELBASE;
+ initrd_end = r5 + KERNELBASE;
+ }
+#endif /* CONFIG_BLK_DEV_INITRD */
+
+ /* Copy the kernel command line arguments to a safe place. */
+
+ if (r6) {
+ *(char *)(r7 + KERNELBASE) = 0;
+ strcpy(cmd_line, (char *)(r6 + KERNELBASE));
+ }
+#endif /* 0 */
+
+ ppc_md.setup_arch = oak_setup_arch;
+ ppc_md.setup_residual = NULL;
+ ppc_md.get_cpuinfo = NULL;
+ ppc_md.irq_cannonicalize = NULL;
+ ppc_md.init_IRQ = NULL;
+ ppc_md.get_irq = NULL;
+ ppc_md.init = NULL;
+
+ ppc_md.restart = NULL;
+ ppc_md.power_off = NULL;
+ ppc_md.halt = NULL;
+
+ ppc_md.time_init = NULL;
+ ppc_md.set_rtc_time = NULL;
+ ppc_md.get_rtc_time = NULL;
+ ppc_md.calibrate_decr = NULL;
+
+ ppc_md.kbd_setkeycode = NULL;
+ ppc_md.kbd_getkeycode = NULL;
+ ppc_md.kbd_translate = NULL;
+ ppc_md.kbd_unexpected_up = NULL;
+ ppc_md.kbd_leds = NULL;
+ ppc_md.kbd_init_hw = NULL;
+
+#if defined(CONFIG_MAGIC_SYSRQ)
+ ppc_md.kbd_sysrq_xlate = NULL;
+#endif
+
+ return;
+}
+
+void __init
+oak_setup_arch(void)
+{
+
+}
diff --git a/arch/ppc/kernel/oak_setup.h b/arch/ppc/kernel/oak_setup.h
new file mode 100644
index 000000000..10f7d7354
--- /dev/null
+++ b/arch/ppc/kernel/oak_setup.h
@@ -0,0 +1,32 @@
+/*
+ *
+ * Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
+ *
+ * Module name: oak_setup.c
+ *
+ * Description:
+ * Architecture- / platform-specific boot-time initialization code for
+ * the IBM PowerPC 403GCX "Oak" evaluation board. Adapted from original
+ * code by Gary Thomas, Cort Dougan <cort@cs.nmt.edu>, and Dan Malek
+ * <dmalek@jlc.net>.
+ *
+ */
+
+#ifndef __OAK_SETUP_H__
+#define __OAK_SETUP_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern void oak_init(unsigned long r3,
+ unsigned long ird_start, unsigned long ird_end,
+ unsigned long cline_start, unsigned long cline_end);
+extern void oak_setup_arch(void);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __OAK_SETUP_H__ */
diff --git a/arch/ppc/kernel/open_pic.c b/arch/ppc/kernel/open_pic.c
index 9f3f58a38..4b0375433 100644
--- a/arch/ppc/kernel/open_pic.c
+++ b/arch/ppc/kernel/open_pic.c
@@ -63,9 +63,15 @@ struct hw_interrupt_type open_pic = {
#define check_arg_pri(pri) \
if (pri < 0 || pri >= OPENPIC_NUM_PRI) \
printk("openpic.c:%d: illegal priority %d\n", __LINE__, pri);
-#define check_arg_irq(irq) \
+/*
+ * Turned this check off since the IPI's are treated as irqs
+ * but they're above NumSources -- Cort
+ */
+#define check_arg_irq(irq)
+#if 0
if (irq < 0 || irq >= (NumSources+open_pic.irq_offset)) \
printk("openpic.c:%d: illegal irq %d\n", __LINE__, irq);
+#endif
#define check_arg_cpu(cpu) \
if (cpu < 0 || cpu >= NumProcessors) \
printk("openpic.c:%d: illegal cpu %d\n", __LINE__, cpu);
@@ -201,15 +207,12 @@ void __init openpic_init(int main_pic)
/* Initialize IPI interrupts */
if ( ppc_md.progress ) ppc_md.progress("openpic ipi",0x3bb);
for (i = 0; i < OPENPIC_NUM_IPI; i++) {
- /* Disabled, Priority 0 */
- openpic_initipi(i, 0, OPENPIC_VEC_IPI+i);
+ /* Disabled, Priority 8 */
+ openpic_initipi(i, 8, OPENPIC_VEC_IPI+i);
}
/* Initialize external interrupts */
if ( ppc_md.progress ) ppc_md.progress("openpic ext",0x3bc);
- /* SIOint (8259 cascade) is special */
- openpic_initirq(0, 8, open_pic.irq_offset, 1, 1);
- openpic_mapirq(0, 1<<0);
for (i = 1; i < NumSources; i++) {
/* Enabled, Priority 8 */
openpic_initirq(i, 8, open_pic.irq_offset+i, 0,
@@ -223,6 +226,9 @@ void __init openpic_init(int main_pic)
openpic_set_spurious(OPENPIC_VEC_SPURIOUS);
if ( _machine != _MACH_gemini )
{
+ /* SIOint (8259 cascade) is special */
+ openpic_initirq(0, 8, open_pic.irq_offset, 1, 1);
+ openpic_mapirq(0, 1<<0);
if (request_irq(IRQ_8259_CASCADE, no_action, SA_INTERRUPT,
"82c59 cascade", NULL))
printk("Unable to get OpenPIC IRQ 0 for cascade\n");
diff --git a/arch/ppc/kernel/open_pic.h b/arch/ppc/kernel/open_pic.h
index ace8590bb..1097c70bf 100644
--- a/arch/ppc/kernel/open_pic.h
+++ b/arch/ppc/kernel/open_pic.h
@@ -4,5 +4,6 @@
extern struct hw_interrupt_type open_pic;
void openpic_ipi_action(int cpl, void *dev_id, struct pt_regs *regs);
+void openpic_enable_IPI(u_int ipi);
#endif /* _PPC_KERNEL_OPEN_PIC_H */
diff --git a/arch/ppc/kernel/pci.c b/arch/ppc/kernel/pci.c
index 0d07c289d..054eee918 100644
--- a/arch/ppc/kernel/pci.c
+++ b/arch/ppc/kernel/pci.c
@@ -8,7 +8,6 @@
#include <linux/delay.h>
#include <linux/string.h>
#include <linux/init.h>
-#include <linux/config.h>
#include <linux/openpic.h>
#include <asm/processor.h>
@@ -77,6 +76,21 @@ void __init pcibios_init(void)
ppc_md.pcibios_fixup();
}
+void __init
+pcibios_fixup_pbus_ranges(struct pci_bus * bus, struct pbus_set_ranges_data * ranges)
+{
+ ranges->io_start -= bus->resource[0]->start;
+ ranges->io_end -= bus->resource[0]->start;
+ ranges->mem_start -= bus->resource[1]->start;
+ ranges->mem_end -= bus->resource[1]->start;
+}
+
+unsigned long resource_fixup(struct pci_dev * dev, struct resource * res,
+ unsigned long start, unsigned long size)
+{
+ return start;
+}
+
static void __init pcibios_claim_resources(struct pci_bus *bus)
{
struct pci_dev *dev;
@@ -117,31 +131,6 @@ char __init *pcibios_setup(char *str)
return str;
}
-#ifndef CONFIG_8xx
-/* Recursively searches any node that is of type PCI-PCI bridge. Without
- * this, the old code would miss children of P2P bridges and hence not
- * fix IRQ's for cards located behind P2P bridges.
- * - Ranjit Deshpande, 01/20/99
- */
-void __init fix_intr(struct device_node *node, struct pci_dev *dev)
-{
- unsigned int *reg, *class_code;
-
- for (; node != 0;node = node->sibling) {
- class_code = (unsigned int *) get_property(node, "class-code", 0);
- if((*class_code >> 8) == PCI_CLASS_BRIDGE_PCI)
- fix_intr(node->child, dev);
- reg = (unsigned int *) get_property(node, "reg", 0);
- if (reg == 0 || ((reg[0] >> 8) & 0xff) != dev->devfn)
- continue;
- /* this is the node, see if it has interrupts */
- if (node->n_intrs > 0)
- dev->irq = node->intrs[0].line;
- break;
- }
-}
-#endif
-
int pcibios_assign_resource(struct pci_dev *pdev, int resource)
{
return 0;
@@ -168,3 +157,8 @@ pcibios_update_irq(struct pci_dev *dev, int irq)
pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
/* XXX FIXME - update OF device tree node interrupt property */
}
+
+void __init
+pcibios_align_resource(void *data, struct resource *res, unsigned long size)
+{
+}
diff --git a/arch/ppc/kernel/pmac_support.c b/arch/ppc/kernel/pmac_nvram.c
index cf3d1711a..99bfa4f8b 100644
--- a/arch/ppc/kernel/pmac_support.c
+++ b/arch/ppc/kernel/pmac_nvram.c
@@ -1,15 +1,13 @@
/*
* Miscellaneous procedures for dealing with the PowerMac hardware.
*/
+#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/stddef.h>
-#include <linux/reboot.h>
#include <linux/nvram.h>
#include <linux/init.h>
#include <asm/init.h>
-#include <asm/ptrace.h>
#include <asm/io.h>
-#include <asm/pgtable.h>
#include <asm/system.h>
#include <asm/prom.h>
#include <linux/adb.h>
@@ -25,7 +23,6 @@ static int nvram_mult;
#define NVRAM_SIZE 0x2000 /* 8kB of non-volatile RAM */
-
__init
void pmac_nvram_init(void)
{
@@ -55,6 +52,7 @@ void pmac_nvram_init(void)
}
}
+__openfirmware
unsigned char nvram_read_byte(int addr)
{
struct adb_request req;
@@ -79,6 +77,7 @@ unsigned char nvram_read_byte(int addr)
return 0;
}
+__openfirmware
void nvram_write_byte(unsigned char val, int addr)
{
struct adb_request req;
diff --git a/arch/ppc/kernel/pmac_pci.c b/arch/ppc/kernel/pmac_pci.c
index 62161f68a..a9166da34 100644
--- a/arch/ppc/kernel/pmac_pci.c
+++ b/arch/ppc/kernel/pmac_pci.c
@@ -21,7 +21,6 @@
#include <asm/init.h>
#include <asm/io.h>
-#include <asm/pgtable.h>
#include <asm/prom.h>
#include <asm/pci-bridge.h>
#include <asm/machdep.h>
@@ -442,6 +441,30 @@ static void __init add_bridges(struct device_node *dev)
}
}
+/* Recursively searches any node that is of type PCI-PCI bridge. Without
+ * this, the old code would miss children of P2P bridges and hence not
+ * fix IRQ's for cards located behind P2P bridges.
+ * - Ranjit Deshpande, 01/20/99
+ */
+void __init
+fix_intr(struct device_node *node, struct pci_dev *dev)
+{
+ unsigned int *reg, *class_code;
+
+ for (; node != 0;node = node->sibling) {
+ class_code = (unsigned int *) get_property(node, "class-code", 0);
+ if((*class_code >> 8) == PCI_CLASS_BRIDGE_PCI)
+ fix_intr(node->child, dev);
+ reg = (unsigned int *) get_property(node, "reg", 0);
+ if (reg == 0 || ((reg[0] >> 8) & 0xff) != dev->devfn)
+ continue;
+ /* this is the node, see if it has interrupts */
+ if (node->n_intrs > 0)
+ dev->irq = node->intrs[0].line;
+ break;
+ }
+}
+
void __init
pmac_pcibios_fixup(void)
{
diff --git a/arch/ppc/kernel/ppc8xx_pic.c b/arch/ppc/kernel/ppc8xx_pic.c
index 96c1e7260..afcda088b 100644
--- a/arch/ppc/kernel/ppc8xx_pic.c
+++ b/arch/ppc/kernel/ppc8xx_pic.c
@@ -1,4 +1,4 @@
-
+#include <linux/config.h>
#include <linux/stddef.h>
#include <linux/init.h>
#include <linux/sched.h>
diff --git a/arch/ppc/kernel/ppc8xx_pic.h b/arch/ppc/kernel/ppc8xx_pic.h
index c4de8f12e..13518bb06 100644
--- a/arch/ppc/kernel/ppc8xx_pic.h
+++ b/arch/ppc/kernel/ppc8xx_pic.h
@@ -1,7 +1,7 @@
-
#ifndef _PPC_KERNEL_PPC8xx_H
#define _PPC_KERNEL_PPC8xx_H
+#include <linux/config.h>
#include "local_irq.h"
extern struct hw_interrupt_type ppc8xx_pic;
diff --git a/arch/ppc/kernel/ppc_asm.h b/arch/ppc/kernel/ppc_asm.h
index 10be7ceab..2b999ab36 100644
--- a/arch/ppc/kernel/ppc_asm.h
+++ b/arch/ppc/kernel/ppc_asm.h
@@ -10,6 +10,9 @@
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
+
+#include <linux/config.h>
+
#include "ppc_asm.tmpl"
#include "ppc_defs.h"
@@ -45,14 +48,20 @@
sync; \
isync
-/* This instruction is not implemented on the PPC 603 or 601 */
-#define tlbia \
- li r4,128; \
- mtctr r4; \
- lis r4,KERNELBASE@h; \
-0: tlbie r4; \
- addi r4,r4,0x1000; \
+/*
+ * This instruction is not implemented on the PPC 603 or 601; however, on
+ * the 403GCX and 405GP tlbia IS defined and tlbie is not.
+ */
+
+#if !defined(CONFIG_4xx)
+#define tlbia \
+ li r4,128; \
+ mtctr r4; \
+ lis r4,KERNELBASE@h; \
+0: tlbie r4; \
+ addi r4,r4,0x1000; \
bdnz 0b
+#endif
/*
* On APUS (Amiga PowerPC cpu upgrade board), we don't know the
diff --git a/arch/ppc/kernel/ppc_asm.tmpl b/arch/ppc/kernel/ppc_asm.tmpl
index e3004c8f6..94a5bd74c 100644
--- a/arch/ppc/kernel/ppc_asm.tmpl
+++ b/arch/ppc/kernel/ppc_asm.tmpl
@@ -1,4 +1,17 @@
-/* Register names */
+/* Condition Register Bit Fields */
+
+#define cr0 0
+#define cr1 1
+#define cr2 2
+#define cr3 3
+#define cr4 4
+#define cr5 5
+#define cr6 6
+#define cr7 7
+
+
+/* General Purpose Registers (GPRs) */
+
#define r0 0
#define r1 1
#define r2 2
@@ -32,6 +45,9 @@
#define r30 30
#define r31 31
+
+/* Floating Point Registers (FPRs) */
+
#define fr0 0
#define fr1 1
#define fr2 2
diff --git a/arch/ppc/kernel/ppc_htab.c b/arch/ppc/kernel/ppc_htab.c
index 0b7c77683..b90fa7a2c 100644
--- a/arch/ppc/kernel/ppc_htab.c
+++ b/arch/ppc/kernel/ppc_htab.c
@@ -63,25 +63,6 @@ static struct file_operations ppc_htab_operations = {
*/
struct inode_operations proc_ppc_htab_inode_operations = {
&ppc_htab_operations, /* default proc file-ops */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* flushpage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL, /* smap */
- NULL /* revalidate */
};
/* these will go into processor.h when I'm done debugging -- Cort */
diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c
index 7bd21c277..11d2cd114 100644
--- a/arch/ppc/kernel/ppc_ksyms.c
+++ b/arch/ppc/kernel/ppc_ksyms.c
@@ -76,7 +76,7 @@ EXPORT_SYMBOL(ppc_local_bh_count);
EXPORT_SYMBOL(kernel_flag);
#endif /* __SMP__ */
-#ifndef CONFIG_8xx
+#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx)
EXPORT_SYMBOL(isa_io_base);
EXPORT_SYMBOL(isa_mem_base);
EXPORT_SYMBOL(pci_dram_offset);
@@ -219,21 +219,22 @@ EXPORT_SYMBOL(pmu_register_sleep_notifier);
EXPORT_SYMBOL(pmu_unregister_sleep_notifier);
EXPORT_SYMBOL(pmu_enable_irled);
#endif CONFIG_PMAC_PBOOK
-EXPORT_SYMBOL(abort);
-#ifndef CONFIG_8xx
+#if defined(CONFIG_PMAC) || defined(CONFIG_ALL_PPC)
EXPORT_SYMBOL(find_devices);
EXPORT_SYMBOL(find_type_devices);
EXPORT_SYMBOL(find_compatible_devices);
EXPORT_SYMBOL(find_path_device);
EXPORT_SYMBOL(find_phandle);
+EXPORT_SYMBOL(device_is_compatible);
+EXPORT_SYMBOL(machine_is_compatible);
EXPORT_SYMBOL(get_property);
EXPORT_SYMBOL(pci_io_base);
EXPORT_SYMBOL(pci_device_loc);
EXPORT_SYMBOL(feature_set);
EXPORT_SYMBOL(feature_clear);
EXPORT_SYMBOL(feature_test);
-#endif
-#ifdef CONFIG_SCSI
+#endif /* defined(CONFIG_PMAC) || defined(CONFIG_ALL_PPC) */
+#if defined(CONFIG_SCSI) && (defined(CONFIG_PMAC) || defined(CONFIG_ALL_PPC))
EXPORT_SYMBOL(note_scsi_host);
#endif
EXPORT_SYMBOL(kd_mksound);
@@ -251,17 +252,16 @@ EXPORT_SYMBOL_NOVERS(memscan);
EXPORT_SYMBOL_NOVERS(memcmp);
EXPORT_SYMBOL(abs);
-#ifndef CONFIG_8xx
-EXPORT_SYMBOL(device_is_compatible);
-#endif
#ifdef CONFIG_VT
EXPORT_SYMBOL(screen_info);
#endif
EXPORT_SYMBOL(int_control);
+#if !defined(CONFIG_4xx)
EXPORT_SYMBOL(timer_interrupt_intercept);
EXPORT_SYMBOL(timer_interrupt);
+#endif
extern unsigned long do_IRQ_intercept;
EXPORT_SYMBOL(do_IRQ_intercept);
EXPORT_SYMBOL(irq_desc);
diff --git a/arch/ppc/kernel/prep_setup.c b/arch/ppc/kernel/prep_setup.c
index 1bfc63c63..e7f62c429 100644
--- a/arch/ppc/kernel/prep_setup.c
+++ b/arch/ppc/kernel/prep_setup.c
@@ -760,22 +760,6 @@ prep_init(unsigned long r3, unsigned long r4, unsigned long r5,
prep_setup_pci_ptrs();
-#ifdef CONFIG_BLK_DEV_INITRD
- /* take care of initrd if we have one */
- if ( r4 )
- {
- initrd_start = r4 + KERNELBASE;
- initrd_end = r5 + KERNELBASE;
- }
-#endif /* CONFIG_BLK_DEV_INITRD */
-
- /* take care of cmd line */
- if ( r6 && (((char *) r6) != '\0'))
- {
- *(char *)(r7+KERNELBASE) = 0;
- strcpy(cmd_line, (char *)(r6+KERNELBASE));
- }
-
ppc_md.setup_arch = prep_setup_arch;
ppc_md.setup_residual = prep_setup_residual;
ppc_md.get_cpuinfo = prep_get_cpuinfo;
diff --git a/arch/ppc/kernel/process.c b/arch/ppc/kernel/process.c
index adeeefe33..403213883 100644
--- a/arch/ppc/kernel/process.c
+++ b/arch/ppc/kernel/process.c
@@ -204,9 +204,15 @@ _switch_to(struct task_struct *prev, struct task_struct *new,
if ( (prev->thread.regs && (prev->thread.regs->msr & MSR_VEC)) &&
prev->thread.vrsave )
giveup_altivec(prev);
- if ( (new->last_processor != NO_PROC_ID) &&
+ /*
+ * The 750 doesn't broadcast invalidates with tlbie's
+ * so flush every processor switch.
+ * -- Cort
+ */
+ if ( ((_get_PVR()>>16) == 8) &&
+ (new->last_processor != NO_PROC_ID) &&
(new->last_processor != new->processor) && new->mm )
- flush_tlb_mm(new->mm);
+ flush_tlb_mm(new->mm);
prev->last_processor = prev->processor;
current_set[smp_processor_id()] = new;
#endif /* __SMP__ */
diff --git a/arch/ppc/kernel/prom.c b/arch/ppc/kernel/prom.c
index 22dcf8cbe..049cde10f 100644
--- a/arch/ppc/kernel/prom.c
+++ b/arch/ppc/kernel/prom.c
@@ -283,11 +283,6 @@ prom_init(int r3, int r4, prom_entry pp)
int l;
char *p, *d;
-#ifdef CONFIG_GEMINI
- gemini_prom_init();
- return;
-#endif /* CONFIG_GEMINI */
-
/* check if we're apus, return if we are */
if ( r3 == 0x61707573 )
return;
diff --git a/arch/ppc/kernel/qspan_pci.c b/arch/ppc/kernel/qspan_pci.c
index 6d331b2b4..860f4f0cc 100644
--- a/arch/ppc/kernel/qspan_pci.c
+++ b/arch/ppc/kernel/qspan_pci.c
@@ -15,6 +15,7 @@
* we have switched the chip select.
*/
+#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/delay.h>
diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c
index 2cf9ee714..caffdcf99 100644
--- a/arch/ppc/kernel/setup.c
+++ b/arch/ppc/kernel/setup.c
@@ -30,6 +30,8 @@
#include <asm/bootx.h>
#include <asm/machdep.h>
+#include "oak_setup.h"
+
extern void pmac_init(unsigned long r3,
unsigned long r4,
unsigned long r5,
@@ -67,11 +69,11 @@ extern void gemini_init(unsigned long r3,
unsigned long r7);
extern boot_infos_t *boot_infos;
-extern char cmd_line[512];
char saved_command_line[256];
unsigned char aux_device_present;
struct int_control_struct int_control;
struct ide_machdep_calls ppc_ide_md;
+int parse_bootinfo(void);
unsigned long ISA_DMA_THRESHOLD;
unsigned long DMA_MODE_READ, DMA_MODE_WRITE;
@@ -84,14 +86,9 @@ int have_of = 0;
#ifdef CONFIG_MAGIC_SYSRQ
unsigned long SYSRQ_KEY;
#endif /* CONFIG_MAGIC_SYSRQ */
-/* For MTX/MVME boards.. with Raven/Falcon Chipset
- Real close to CHRP, but boot like PReP (via PPCbug)
- There's probably a nicer way to do this.. --Troy */
-int is_powerplus = 0;
struct machdep_calls ppc_md;
-
/* copy of the residual data */
#ifndef CONFIG_8xx
extern unsigned char __res[sizeof(RESIDUAL)];
@@ -196,6 +193,7 @@ int get_cpuinfo(char *buffer)
unsigned long len = 0;
unsigned long bogosum = 0;
unsigned long i;
+ unsigned short maj, min;
#ifdef __SMP__
#define CPU_PRESENT(x) (cpu_callin_map[(x)])
@@ -215,8 +213,8 @@ int get_cpuinfo(char *buffer)
if ( i )
len += sprintf(len+buffer,"\n");
len += sprintf(len+buffer,"processor\t: %lu\n",i);
- len += sprintf(len+buffer,"cpu\t\t: ");
-
+ len += sprintf(len+buffer,"cpu\t\t: ");
+
switch (GET_PVR >> 16)
{
case 1:
@@ -254,7 +252,7 @@ int get_cpuinfo(char *buffer)
len += sprintf(len+buffer, "860\n");
break;
default:
- len += sprintf(len+buffer, "unknown (%lu)\n",
+ len += sprintf(len+buffer, "unknown (%lx)\n",
GET_PVR>>16);
break;
}
@@ -294,8 +292,7 @@ int get_cpuinfo(char *buffer)
len += ppc_md.setup_residual(buffer + len);
}
- len += sprintf(len+buffer, "revision\t: %ld.%ld\n",
- (GET_PVR & 0xff00) >> 8, GET_PVR & 0xff);
+ len += sprintf(len+buffer, "revision\t: %hd.%hd\n", maj, min);
len += sprintf(buffer+len, "bogomips\t: %lu.%02lu\n",
(CD(loops_per_sec)+2500)/500000,
@@ -333,6 +330,30 @@ int get_cpuinfo(char *buffer)
return len;
}
+#ifndef CONFIG_MACH_SPECIFIC
+void __init
+intuit_machine_type(void)
+{
+ char *model;
+ struct device_node *root;
+
+ /* ask the OF info if we're a chrp or pmac */
+ root = find_path_device("/");
+ if (root != 0) {
+ /* assume pmac unless proven to be chrp -- Cort */
+ _machine = _MACH_Pmac;
+ model = get_property(root, "device_type", NULL);
+ if (model && !strncmp("chrp", model, 4))
+ _machine = _MACH_chrp;
+ else {
+ model = get_property(root, "model", NULL);
+ if (model && !strncmp(model, "IBM", 3))
+ _machine = _MACH_chrp;
+ }
+ }
+}
+#endif /* CONFIG_MACH_SPECIFIC */
+
/*
* Find out what kind of machine we're on and save any data we need
* from the early boot process (devtree is copied on pmac by prom_init() )
@@ -341,49 +362,31 @@ unsigned long __init
identify_machine(unsigned long r3, unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7)
{
+ int_control.int_sti = __no_use_sti;
+ int_control.int_cli = __no_use_cli;
+ int_control.int_save_flags = __no_use_save_flags;
+ int_control.int_restore_flags = __no_use_restore_flags;
-#ifndef CONFIG_8xx
- if ( ppc_md.progress ) ppc_md.progress("id mach(): start", 0x100);
+ parse_bootinfo();
+ if ( ppc_md.progress ) ppc_md.progress("id mach(): start", 0x100);
+#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx)
#ifndef CONFIG_MACH_SPECIFIC
- /* boot loader will tell us if we're APUS */
- if ( r3 == 0x61707573 )
+ /* if we didn't get any bootinfo telling us what we are... */
+ if ( _machine == 0 )
{
- _machine = _MACH_apus;
- r3 = 0;
- }
- /* prep boot loader tells us if we're prep or not */
- else if ( *(unsigned long *)(KERNELBASE) == (0xdeadc0de) )
- {
- _machine = _MACH_prep;
- } else
- {
- char *model;
- struct device_node *root;
-
- have_of = 1;
-
- /* prom_init has already been called from __start */
- if (boot_infos)
- relocate_nodes();
-
- /* ask the OF info if we're a chrp or pmac */
- /* we need to set _machine before calling finish_device_tree */
- root = find_path_device("/");
- if (root != 0) {
- /* assume pmac unless proven to be chrp -- Cort */
- _machine = _MACH_Pmac;
- model = get_property(root, "device_type", NULL);
- if (model && !strncmp("chrp", model, 4))
- _machine = _MACH_chrp;
- else {
- model = get_property(root, "model", NULL);
- if (model && !strncmp(model, "IBM", 3))
- _machine = _MACH_chrp;
- }
+ /* boot loader will tell us if we're APUS */
+ if ( r3 == 0x61707573 )
+ {
+ _machine = _MACH_apus;
+ r3 = 0;
}
-
- finish_device_tree();
+ /* prep boot loader tells us if we're prep or not */
+ else if ( *(unsigned long *)(KERNELBASE) == (0xdeadc0de) )
+ {
+ _machine = _MACH_prep;
+ } else
+ have_of = 1;
}
#endif /* CONFIG_MACH_SPECIFIC */
@@ -392,7 +395,13 @@ identify_machine(unsigned long r3, unsigned long r4, unsigned long r5,
/* prom_init has already been called from __start */
if (boot_infos)
relocate_nodes();
+#ifndef CONFIG_MACH_SPECIFIC
+ /* we need to set _machine before calling finish_device_tree */
+ if (_machine == 0)
+ intuit_machine_type();
+#endif /* CONFIG_MACH_SPECIFIC */
finish_device_tree();
+
/*
* If we were booted via quik, r3 points to the physical
* address of the command-line parameters.
@@ -444,11 +453,6 @@ identify_machine(unsigned long r3, unsigned long r4, unsigned long r5,
cmd_line[sizeof(cmd_line) - 1] = 0;
}
- int_control.int_sti = __no_use_sti;
- int_control.int_cli = __no_use_cli;
- int_control.int_save_flags = __no_use_save_flags;
- int_control.int_restore_flags = __no_use_restore_flags;
-
switch (_machine)
{
case _MACH_Pmac:
@@ -469,7 +473,7 @@ identify_machine(unsigned long r3, unsigned long r4, unsigned long r5,
case _MACH_gemini:
gemini_init(r3, r4, r5, r6, r7);
break;
-#endif
+#endif
default:
printk("Unknown machine type in identify_machine!\n");
}
@@ -478,14 +482,15 @@ identify_machine(unsigned long r3, unsigned long r4, unsigned long r5,
extern int __map_without_bats;
__map_without_bats = 1;
}
-#else /* CONFIG_8xx */
- int_control.int_sti = __no_use_sti;
- int_control.int_cli = __no_use_cli;
- int_control.int_save_flags = __no_use_save_flags;
- int_control.int_restore_flags = __no_use_restore_flags;
-
+#else
+#if defined(CONFIG_4xx)
+ oak_init(r3, r4, r5, r6, r7);
+#elif defined(CONFIG_8xx)
m8xx_init(r3, r4, r5, r6, r7);
-#endif
+#else
+#error "No board type has been defined for identify_machine()!"
+#endif /* CONFIG_4xx */
+#endif /* !CONFIG_4xx && !CONFIG_8xx */
/* Look for mem= option on command line */
if (strstr(cmd_line, "mem=")) {
@@ -513,6 +518,53 @@ identify_machine(unsigned long r3, unsigned long r4, unsigned long r5,
ppc_md.ppc_machine = _machine;
if ( ppc_md.progress ) ppc_md.progress("id mach(): done", 0x200);
+
+ return 0;
+}
+
+int parse_bootinfo(void)
+{
+ struct bi_record *rec;
+ extern char _end[];
+
+ rec = (struct bi_record *)PAGE_ALIGN((ulong)_end);
+ if ( rec->tag != BI_FIRST )
+ {
+ /*
+ * This 0x10000 offset is a terrible hack but it will go away when
+ * we have the bootloader handle all the relocation and
+ * prom calls -- Cort
+ */
+ rec = (struct bi_record *)PAGE_ALIGN((ulong)_end+0x10000);
+ if ( rec->tag != BI_FIRST )
+ return -1;
+ }
+
+ for ( ; rec->tag != BI_LAST ;
+ rec = (struct bi_record *)((ulong)rec + rec->size) )
+ {
+ ulong *data = rec->data;
+ switch (rec->tag)
+ {
+ case BI_CMD_LINE:
+ memcpy(cmd_line, (void *)data, rec->size);
+ break;
+#ifdef CONFIG_BLK_DEV_INITRD
+ case BI_INITRD:
+ initrd_start = data[0];
+ initrd_end = data[0] + rec->size;
+ break;
+#endif /* CONFIG_BLK_DEV_INITRD */
+#ifndef CONFIG_MACH_SPECIFIC
+ case BI_MACHTYPE:
+ _machine = data[0];
+ have_of = data[1];
+ break;
+#endif /* CONFIG_MACH_SPECIFIC */
+
+ }
+ }
+
return 0;
}
diff --git a/arch/ppc/kernel/signal.c b/arch/ppc/kernel/signal.c
index 0d55bcefc..1ca3a65f8 100644
--- a/arch/ppc/kernel/signal.c
+++ b/arch/ppc/kernel/signal.c
@@ -444,6 +444,7 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
case SIGQUIT: case SIGILL: case SIGTRAP:
case SIGABRT: case SIGFPE: case SIGSEGV:
+ case SIGBUS: case SIGSYS: case SIGXCPU: case SIGXFSZ:
if (do_coredump(signr, regs))
exit_code |= 0x80;
/* FALLTHRU */
diff --git a/arch/ppc/kernel/smp.c b/arch/ppc/kernel/smp.c
index a21361340..fad7c7c1d 100644
--- a/arch/ppc/kernel/smp.c
+++ b/arch/ppc/kernel/smp.c
@@ -39,6 +39,7 @@
#include <asm/gemini.h>
#include "time.h"
+#include "open_pic.h"
int smp_threads_ready = 0;
volatile int smp_commenced = 0;
int smp_num_cpus = 1;
@@ -160,14 +161,15 @@ void smp_message_recv(void)
void smp_send_reschedule(int cpu)
{
/*
+ * This is only used if `cpu' is running an idle task,
+ * so it will reschedule itself anyway...
+ *
* This isn't the case anymore since the other CPU could be
* sleeping and won't reschedule until the next interrupt (such
* as the timer).
* -- Cort
*/
- /* This is only used if `cpu' is running an idle task,
- so it will reschedule itself anyway... */
- /*smp_message_pass(cpu, MSG_RESCHEDULE, 0, 0);*/
+ smp_message_pass(cpu, MSG_RESCHEDULE, 0, 0);
}
void smp_send_stop(void)
diff --git a/arch/ppc/kernel/traps.c b/arch/ppc/kernel/traps.c
index 07e45db6b..47fef50d4 100644
--- a/arch/ppc/kernel/traps.c
+++ b/arch/ppc/kernel/traps.c
@@ -128,6 +128,7 @@ MachineCheckException(struct pt_regs *regs)
_exception(SIGSEGV, regs);
}
+#if defined(CONFIG_ALTIVEC)
void
AltiVecUnavailable(struct pt_regs *regs)
{
@@ -163,6 +164,7 @@ AltiVecUnavailable(struct pt_regs *regs)
/* enable altivec for the task on return */
regs->msr |= MSR_VEC;
}
+#endif /* CONFIG_ALTIVEC */
void
UnknownException(struct pt_regs *regs)
@@ -191,6 +193,20 @@ RunModeException(struct pt_regs *regs)
void
ProgramCheckException(struct pt_regs *regs)
{
+#if defined(CONFIG_4xx)
+ unsigned int instr;
+ unsigned int esr = mfspr(SPRN_ESR);
+
+ if (esr & ESR_PTR) {
+#if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
+ if (debugger_bpt(regs))
+ return;
+#endif
+ _exception(SIGTRAP, regs);
+ } else {
+ _exception(SIGILL, regs);
+ }
+#else
if (regs->msr & 0x100000) {
/* IEEE FP exception */
_exception(SIGFPE, regs);
@@ -204,6 +220,7 @@ ProgramCheckException(struct pt_regs *regs)
} else {
_exception(SIGILL, regs);
}
+#endif
}
void