From 33263fc5f9ac8e8cb2b22d06af3ce5ac1dd815e4 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Fri, 4 Feb 2000 07:40:19 +0000 Subject: Merge with Linux 2.3.32. --- arch/ppc/kernel/Makefile | 72 ++--- arch/ppc/kernel/align.c | 52 +++- arch/ppc/kernel/entry.S | 6 +- arch/ppc/kernel/gemini_prom.S | 1 + arch/ppc/kernel/gemini_setup.c | 58 +++- arch/ppc/kernel/head.S | 83 +++--- arch/ppc/kernel/head_4xx.S | 600 +++++++++++++++++++++++++++++++++++++++++ arch/ppc/kernel/misc.S | 49 +++- arch/ppc/kernel/mk_defs.c | 10 +- arch/ppc/kernel/oak_setup.c | 84 ++++++ arch/ppc/kernel/oak_setup.h | 32 +++ arch/ppc/kernel/open_pic.c | 18 +- arch/ppc/kernel/open_pic.h | 1 + arch/ppc/kernel/pci.c | 46 ++-- arch/ppc/kernel/pmac_nvram.c | 105 ++++++++ arch/ppc/kernel/pmac_pci.c | 25 +- arch/ppc/kernel/pmac_support.c | 106 -------- arch/ppc/kernel/ppc8xx_pic.c | 2 +- arch/ppc/kernel/ppc8xx_pic.h | 2 +- arch/ppc/kernel/ppc_asm.h | 23 +- arch/ppc/kernel/ppc_asm.tmpl | 18 +- arch/ppc/kernel/ppc_htab.c | 19 -- arch/ppc/kernel/ppc_ksyms.c | 16 +- arch/ppc/kernel/prep_setup.c | 16 -- arch/ppc/kernel/process.c | 10 +- arch/ppc/kernel/prom.c | 5 - arch/ppc/kernel/qspan_pci.c | 1 + arch/ppc/kernel/setup.c | 176 +++++++----- arch/ppc/kernel/signal.c | 1 + arch/ppc/kernel/smp.c | 8 +- arch/ppc/kernel/traps.c | 17 ++ 31 files changed, 1292 insertions(+), 370 deletions(-) create mode 100644 arch/ppc/kernel/head_4xx.S create mode 100644 arch/ppc/kernel/oak_setup.c create mode 100644 arch/ppc/kernel/oak_setup.h create mode 100644 arch/ppc/kernel/pmac_nvram.c delete mode 100644 arch/ppc/kernel/pmac_support.c (limited to 'arch/ppc/kernel') 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 + * Copyright (c) 1998-1999 TiVo, Inc. + * PowerPC 403GCX modifications. + * Copyright (c) 1999 Grant Erickson + * PowerPC 403GCX/405GP modifications. */ +#include #include #include #include @@ -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 + * Initial PowerPC version. + * Copyright (c) 1996 Cort Dougan + * Rewritten for PReP + * Copyright (c) 1996 Paul Mackerras + * Low-level exception handers, MMU support, and rewrite. + * Copyright (c) 1997 Dan Malek + * PowerPC 8xx modifications. + * Copyright (c) 1998-1999 TiVo, Inc. + * PowerPC 403GCX modifications. + * Copyright (c) 1999 Grant Erickson + * 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 + +#include +#include +#include +#include +#include +#include + +#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 + * + * 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 , and Dan Malek + * . + * + */ + +#include +#include +#include + +#include +#include + +#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 + * + * 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 , and Dan Malek + * . + * + */ + +#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 #include #include -#include #include #include @@ -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_nvram.c b/arch/ppc/kernel/pmac_nvram.c new file mode 100644 index 000000000..99bfa4f8b --- /dev/null +++ b/arch/ppc/kernel/pmac_nvram.c @@ -0,0 +1,105 @@ +/* + * Miscellaneous procedures for dealing with the PowerMac hardware. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Read and write the non-volatile RAM on PowerMacs and CHRP machines. + */ +static int nvram_naddrs; +static volatile unsigned char *nvram_addr; +static volatile unsigned char *nvram_data; +static int nvram_mult; + +#define NVRAM_SIZE 0x2000 /* 8kB of non-volatile RAM */ + +__init +void pmac_nvram_init(void) +{ + struct device_node *dp; + + dp = find_devices("nvram"); + if (dp == NULL) { + printk(KERN_ERR "Can't find NVRAM device\n"); + nvram_naddrs = 0; + return; + } + nvram_naddrs = dp->n_addrs; + if (_machine == _MACH_chrp && nvram_naddrs == 1) { + nvram_data = ioremap(dp->addrs[0].address, dp->addrs[0].size); + nvram_mult = 1; + } else if (nvram_naddrs == 1) { + nvram_data = ioremap(dp->addrs[0].address, dp->addrs[0].size); + nvram_mult = (dp->addrs[0].size + NVRAM_SIZE - 1) / NVRAM_SIZE; + } else if (nvram_naddrs == 2) { + nvram_addr = ioremap(dp->addrs[0].address, dp->addrs[0].size); + nvram_data = ioremap(dp->addrs[1].address, dp->addrs[1].size); + } else if (nvram_naddrs == 0 && sys_ctrler == SYS_CTRLER_PMU) { + nvram_naddrs = -1; + } else { + printk(KERN_ERR "Don't know how to access NVRAM with %d addresses\n", + nvram_naddrs); + } +} + +__openfirmware +unsigned char nvram_read_byte(int addr) +{ + struct adb_request req; + + switch (nvram_naddrs) { +#ifdef CONFIG_ADB_PMU + case -1: + if (pmu_request(&req, NULL, 3, PMU_READ_NVRAM, + (addr >> 8) & 0xff, addr & 0xff)) + break; + while (!req.complete) + pmu_poll(); + return req.reply[1]; +#endif + case 1: + return nvram_data[(addr & (NVRAM_SIZE - 1)) * nvram_mult]; + case 2: + *nvram_addr = addr >> 5; + eieio(); + return nvram_data[(addr & 0x1f) << 4]; + } + return 0; +} + +__openfirmware +void nvram_write_byte(unsigned char val, int addr) +{ + struct adb_request req; + + switch (nvram_naddrs) { +#ifdef CONFIG_ADB_PMU + case -1: + if (pmu_request(&req, NULL, 4, PMU_WRITE_NVRAM, + (addr >> 8) & 0xff, addr & 0xff, val)) + break; + while (!req.complete) + pmu_poll(); + break; +#endif + case 1: + nvram_data[(addr & (NVRAM_SIZE - 1)) * nvram_mult] = val; + break; + case 2: + *nvram_addr = addr >> 5; + eieio(); + nvram_data[(addr & 0x1f) << 4] = val; + break; + } + eieio(); +} 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 #include -#include #include #include #include @@ -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/pmac_support.c b/arch/ppc/kernel/pmac_support.c deleted file mode 100644 index cf3d1711a..000000000 --- a/arch/ppc/kernel/pmac_support.c +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Miscellaneous procedures for dealing with the PowerMac hardware. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * Read and write the non-volatile RAM on PowerMacs and CHRP machines. - */ -static int nvram_naddrs; -static volatile unsigned char *nvram_addr; -static volatile unsigned char *nvram_data; -static int nvram_mult; - -#define NVRAM_SIZE 0x2000 /* 8kB of non-volatile RAM */ - - -__init -void pmac_nvram_init(void) -{ - struct device_node *dp; - - dp = find_devices("nvram"); - if (dp == NULL) { - printk(KERN_ERR "Can't find NVRAM device\n"); - nvram_naddrs = 0; - return; - } - nvram_naddrs = dp->n_addrs; - if (_machine == _MACH_chrp && nvram_naddrs == 1) { - nvram_data = ioremap(dp->addrs[0].address, dp->addrs[0].size); - nvram_mult = 1; - } else if (nvram_naddrs == 1) { - nvram_data = ioremap(dp->addrs[0].address, dp->addrs[0].size); - nvram_mult = (dp->addrs[0].size + NVRAM_SIZE - 1) / NVRAM_SIZE; - } else if (nvram_naddrs == 2) { - nvram_addr = ioremap(dp->addrs[0].address, dp->addrs[0].size); - nvram_data = ioremap(dp->addrs[1].address, dp->addrs[1].size); - } else if (nvram_naddrs == 0 && sys_ctrler == SYS_CTRLER_PMU) { - nvram_naddrs = -1; - } else { - printk(KERN_ERR "Don't know how to access NVRAM with %d addresses\n", - nvram_naddrs); - } -} - -unsigned char nvram_read_byte(int addr) -{ - struct adb_request req; - - switch (nvram_naddrs) { -#ifdef CONFIG_ADB_PMU - case -1: - if (pmu_request(&req, NULL, 3, PMU_READ_NVRAM, - (addr >> 8) & 0xff, addr & 0xff)) - break; - while (!req.complete) - pmu_poll(); - return req.reply[1]; -#endif - case 1: - return nvram_data[(addr & (NVRAM_SIZE - 1)) * nvram_mult]; - case 2: - *nvram_addr = addr >> 5; - eieio(); - return nvram_data[(addr & 0x1f) << 4]; - } - return 0; -} - -void nvram_write_byte(unsigned char val, int addr) -{ - struct adb_request req; - - switch (nvram_naddrs) { -#ifdef CONFIG_ADB_PMU - case -1: - if (pmu_request(&req, NULL, 4, PMU_WRITE_NVRAM, - (addr >> 8) & 0xff, addr & 0xff, val)) - break; - while (!req.complete) - pmu_poll(); - break; -#endif - case 1: - nvram_data[(addr & (NVRAM_SIZE - 1)) * nvram_mult] = val; - break; - case 2: - *nvram_addr = addr >> 5; - eieio(); - nvram_data[(addr & 0x1f) << 4] = val; - break; - } - eieio(); -} 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 #include #include #include 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 #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 + #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 #include #include #include 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 #include +#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 #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 -- cgit v1.2.3