summaryrefslogtreecommitdiffstats
path: root/arch/ppc/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/ppc/kernel')
-rw-r--r--arch/ppc/kernel/Makefile21
-rw-r--r--arch/ppc/kernel/asm-offsets.c164
-rw-r--r--arch/ppc/kernel/cpu_setup_power4.S197
-rw-r--r--arch/ppc/kernel/entry.S960
-rw-r--r--arch/ppc/kernel/head.S1220
-rw-r--r--arch/ppc/kernel/head_44x.S769
-rw-r--r--arch/ppc/kernel/head_4xx.S1021
-rw-r--r--arch/ppc/kernel/head_8xx.S959
-rw-r--r--arch/ppc/kernel/head_booke.h308
-rw-r--r--arch/ppc/kernel/machine_kexec.c118
-rw-r--r--arch/ppc/kernel/misc.S868
-rw-r--r--arch/ppc/kernel/pci.c1233
-rw-r--r--arch/ppc/kernel/ppc-stub.c866
-rw-r--r--arch/ppc/kernel/ppc_htab.c464
-rw-r--r--arch/ppc/kernel/ppc_ksyms.c258
-rw-r--r--arch/ppc/kernel/relocate_kernel.S123
-rw-r--r--arch/ppc/kernel/setup.c572
-rw-r--r--arch/ppc/kernel/smp-tbsync.c180
-rw-r--r--arch/ppc/kernel/smp.c414
-rw-r--r--arch/ppc/kernel/softemu8xx.c147
-rw-r--r--arch/ppc/kernel/time.c445
-rw-r--r--arch/ppc/kernel/traps.c826
-rw-r--r--arch/ppc/kernel/vmlinux.lds.S164
23 files changed, 0 insertions, 12297 deletions
diff --git a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile
deleted file mode 100644
index 7b739054968f..000000000000
--- a/arch/ppc/kernel/Makefile
+++ /dev/null
@@ -1,21 +0,0 @@
-#
-# Makefile for the linux kernel.
-#
-extra-$(CONFIG_PPC_STD_MMU) := head.o
-extra-$(CONFIG_40x) := head_4xx.o
-extra-$(CONFIG_44x) := head_44x.o
-extra-$(CONFIG_8xx) := head_8xx.o
-extra-y += vmlinux.lds
-
-obj-y := entry.o traps.o time.o misc.o \
- setup.o \
- ppc_htab.o
-obj-$(CONFIG_MODULES) += ppc_ksyms.o
-obj-$(CONFIG_PCI) += pci.o
-obj-$(CONFIG_KGDB) += ppc-stub.o
-obj-$(CONFIG_SMP) += smp.o smp-tbsync.o
-obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
-
-ifndef CONFIG_MATH_EMULATION
-obj-$(CONFIG_8xx) += softemu8xx.o
-endif
diff --git a/arch/ppc/kernel/asm-offsets.c b/arch/ppc/kernel/asm-offsets.c
deleted file mode 100644
index 8dcbdd6c2d2c..000000000000
--- a/arch/ppc/kernel/asm-offsets.c
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * This program is used to generate definitions needed by
- * assembly language modules.
- *
- * We use the technique used in the OSF Mach kernel code:
- * generate asm statements containing #defines,
- * compile this file to assembler, and then extract the
- * #defines from the assembly-language output.
- */
-
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/types.h>
-#include <linux/ptrace.h>
-#include <linux/suspend.h>
-#include <linux/mman.h>
-#include <linux/mm.h>
-#include <linux/kbuild.h>
-
-#include <asm/io.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#include <asm/processor.h>
-#include <asm/cputable.h>
-#include <asm/thread_info.h>
-#include <asm/vdso_datapage.h>
-
-int
-main(void)
-{
- DEFINE(THREAD, offsetof(struct task_struct, thread));
- DEFINE(THREAD_INFO, offsetof(struct task_struct, stack));
- DEFINE(MM, offsetof(struct task_struct, mm));
- DEFINE(PTRACE, offsetof(struct task_struct, ptrace));
- DEFINE(KSP, offsetof(struct thread_struct, ksp));
- DEFINE(PGDIR, offsetof(struct thread_struct, pgdir));
- DEFINE(PT_REGS, offsetof(struct thread_struct, regs));
- DEFINE(THREAD_FPEXC_MODE, offsetof(struct thread_struct, fpexc_mode));
- DEFINE(THREAD_FPR0, offsetof(struct thread_struct, fpr[0]));
- DEFINE(THREAD_FPSCR, offsetof(struct thread_struct, fpscr));
-#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
- DEFINE(THREAD_DBCR0, offsetof(struct thread_struct, dbcr0));
- DEFINE(PT_PTRACED, PT_PTRACED);
-#endif
-#ifdef CONFIG_ALTIVEC
- DEFINE(THREAD_VR0, offsetof(struct thread_struct, vr[0]));
- DEFINE(THREAD_VRSAVE, offsetof(struct thread_struct, vrsave));
- DEFINE(THREAD_VSCR, offsetof(struct thread_struct, vscr));
- DEFINE(THREAD_USED_VR, offsetof(struct thread_struct, used_vr));
-#endif /* CONFIG_ALTIVEC */
- /* Interrupt register frame */
- DEFINE(STACK_FRAME_OVERHEAD, STACK_FRAME_OVERHEAD);
- DEFINE(INT_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs));
- /* in fact we only use gpr0 - gpr9 and gpr20 - gpr23 */
- DEFINE(GPR0, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[0]));
- DEFINE(GPR1, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[1]));
- DEFINE(GPR2, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[2]));
- DEFINE(GPR3, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[3]));
- DEFINE(GPR4, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[4]));
- DEFINE(GPR5, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[5]));
- DEFINE(GPR6, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[6]));
- DEFINE(GPR7, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[7]));
- DEFINE(GPR8, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[8]));
- DEFINE(GPR9, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[9]));
- DEFINE(GPR10, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[10]));
- DEFINE(GPR11, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[11]));
- DEFINE(GPR12, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[12]));
- DEFINE(GPR13, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[13]));
- DEFINE(GPR14, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[14]));
- DEFINE(GPR15, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[15]));
- DEFINE(GPR16, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[16]));
- DEFINE(GPR17, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[17]));
- DEFINE(GPR18, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[18]));
- DEFINE(GPR19, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[19]));
- DEFINE(GPR20, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[20]));
- DEFINE(GPR21, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[21]));
- DEFINE(GPR22, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[22]));
- DEFINE(GPR23, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[23]));
- DEFINE(GPR24, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[24]));
- DEFINE(GPR25, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[25]));
- DEFINE(GPR26, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[26]));
- DEFINE(GPR27, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[27]));
- DEFINE(GPR28, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[28]));
- 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
- */
- 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));
- DEFINE(_LINK, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, link));
- DEFINE(_CCR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, ccr));
- DEFINE(_MQ, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, mq));
- 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 & Book-E processors have neither the DAR nor the DSISR
- * SPRs. Hence, we overload them to hold the similar DEAR and ESR SPRs
- * for such processors. For critical interrupts we use them to
- * hold SRR0 and SRR1.
- */
- 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));
- DEFINE(CLONE_VM, CLONE_VM);
- DEFINE(CLONE_UNTRACED, CLONE_UNTRACED);
- DEFINE(MM_PGD, offsetof(struct mm_struct, pgd));
-
- /* About the CPU features table */
- DEFINE(CPU_SPEC_ENTRY_SIZE, sizeof(struct cpu_spec));
- DEFINE(CPU_SPEC_PVR_MASK, offsetof(struct cpu_spec, pvr_mask));
- DEFINE(CPU_SPEC_PVR_VALUE, offsetof(struct cpu_spec, pvr_value));
- DEFINE(CPU_SPEC_FEATURES, offsetof(struct cpu_spec, cpu_features));
- DEFINE(CPU_SPEC_SETUP, offsetof(struct cpu_spec, cpu_setup));
-
- DEFINE(TI_TASK, offsetof(struct thread_info, task));
- DEFINE(TI_EXECDOMAIN, offsetof(struct thread_info, exec_domain));
- DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
- DEFINE(TI_LOCAL_FLAGS, offsetof(struct thread_info, local_flags));
- DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
- DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count));
-
- DEFINE(pbe_address, offsetof(struct pbe, address));
- DEFINE(pbe_orig_address, offsetof(struct pbe, orig_address));
- DEFINE(pbe_next, offsetof(struct pbe, next));
-
- DEFINE(TASK_SIZE, TASK_SIZE);
- DEFINE(NUM_USER_SEGMENTS, TASK_SIZE>>28);
-
- /* datapage offsets for use by vdso */
- DEFINE(CFG_TB_ORIG_STAMP, offsetof(struct vdso_data, tb_orig_stamp));
- DEFINE(CFG_TB_TICKS_PER_SEC, offsetof(struct vdso_data, tb_ticks_per_sec));
- DEFINE(CFG_TB_TO_XS, offsetof(struct vdso_data, tb_to_xs));
- DEFINE(CFG_STAMP_XSEC, offsetof(struct vdso_data, stamp_xsec));
- DEFINE(CFG_TB_UPDATE_COUNT, offsetof(struct vdso_data, tb_update_count));
- DEFINE(CFG_TZ_MINUTEWEST, offsetof(struct vdso_data, tz_minuteswest));
- DEFINE(CFG_TZ_DSTTIME, offsetof(struct vdso_data, tz_dsttime));
- DEFINE(CFG_SYSCALL_MAP32, offsetof(struct vdso_data, syscall_map_32));
- DEFINE(WTOM_CLOCK_SEC, offsetof(struct vdso_data, wtom_clock_sec));
- DEFINE(WTOM_CLOCK_NSEC, offsetof(struct vdso_data, wtom_clock_nsec));
- DEFINE(TVAL32_TV_SEC, offsetof(struct timeval, tv_sec));
- DEFINE(TVAL32_TV_USEC, offsetof(struct timeval, tv_usec));
- DEFINE(TSPEC32_TV_SEC, offsetof(struct timespec, tv_sec));
- DEFINE(TSPEC32_TV_NSEC, offsetof(struct timespec, tv_nsec));
-
- /* timeval/timezone offsets for use by vdso */
- DEFINE(TZONE_TZ_MINWEST, offsetof(struct timezone, tz_minuteswest));
- DEFINE(TZONE_TZ_DSTTIME, offsetof(struct timezone, tz_dsttime));
-
- /* Other bits used by the vdso */
- DEFINE(CLOCK_REALTIME, CLOCK_REALTIME);
- DEFINE(CLOCK_MONOTONIC, CLOCK_MONOTONIC);
- DEFINE(NSEC_PER_SEC, NSEC_PER_SEC);
- DEFINE(CLOCK_REALTIME_RES, TICK_NSEC);
-
- return 0;
-}
diff --git a/arch/ppc/kernel/cpu_setup_power4.S b/arch/ppc/kernel/cpu_setup_power4.S
deleted file mode 100644
index 6a674e834eeb..000000000000
--- a/arch/ppc/kernel/cpu_setup_power4.S
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * This file contains low level CPU setup functions.
- * Copyright (C) 2003 Benjamin Herrenschmidt (benh@kernel.crashing.org)
- *
- * 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 <asm/processor.h>
-#include <asm/page.h>
-#include <asm/ppc_asm.h>
-#include <asm/cputable.h>
-#include <asm/asm-offsets.h>
-#include <asm/cache.h>
-
-_GLOBAL(__970_cpu_preinit)
- /*
- * Deal only with PPC970 and PPC970FX.
- */
- mfspr r0,SPRN_PVR
- srwi r0,r0,16
- cmpwi cr0,r0,0x39
- cmpwi cr1,r0,0x3c
- cror 4*cr0+eq,4*cr0+eq,4*cr1+eq
- bnelr
-
- /* Make sure HID4:rm_ci is off before MMU is turned off, that large
- * pages are enabled with HID4:61 and clear HID5:DCBZ_size and
- * HID5:DCBZ32_ill
- */
- li r0,0
- mfspr r11,SPRN_HID4
- rldimi r11,r0,40,23 /* clear bit 23 (rm_ci) */
- rldimi r11,r0,2,61 /* clear bit 61 (lg_pg_en) */
- sync
- mtspr SPRN_HID4,r11
- isync
- sync
- mfspr r11,SPRN_HID5
- rldimi r11,r0,6,56 /* clear bits 56 & 57 (DCBZ*) */
- sync
- mtspr SPRN_HID5,r11
- isync
- sync
-
- /* Setup some basic HID1 features */
- mfspr r0,SPRN_HID1
- li r11,0x1200 /* enable i-fetch cacheability */
- sldi r11,r11,44 /* and prefetch */
- or r0,r0,r11
- mtspr SPRN_HID1,r0
- mtspr SPRN_HID1,r0
- isync
-
- /* Clear HIOR */
- li r0,0
- sync
- mtspr SPRN_HIOR,0 /* Clear interrupt prefix */
- isync
- blr
-
-_GLOBAL(__setup_cpu_ppc970)
- mfspr r0,SPRN_HID0
- li r11,5 /* clear DOZE and SLEEP */
- rldimi r0,r11,52,8 /* set NAP and DPM */
- mtspr SPRN_HID0,r0
- mfspr r0,SPRN_HID0
- mfspr r0,SPRN_HID0
- mfspr r0,SPRN_HID0
- mfspr r0,SPRN_HID0
- mfspr r0,SPRN_HID0
- mfspr r0,SPRN_HID0
- sync
- isync
- blr
-
-/* Definitions for the table use to save CPU states */
-#define CS_HID0 0
-#define CS_HID1 8
-#define CS_HID4 16
-#define CS_HID5 24
-#define CS_SIZE 32
-
- .data
- .balign L1_CACHE_BYTES
-cpu_state_storage:
- .space CS_SIZE
- .balign L1_CACHE_BYTES,0
- .text
-
-/* Called in normal context to backup CPU 0 state. This
- * does not include cache settings. This function is also
- * called for machine sleep. This does not include the MMU
- * setup, BATs, etc... but rather the "special" registers
- * like HID0, HID1, HID4, etc...
- */
-_GLOBAL(__save_cpu_setup)
- /* Some CR fields are volatile, we back it up all */
- mfcr r7
-
- /* Get storage ptr */
- lis r5,cpu_state_storage@h
- ori r5,r5,cpu_state_storage@l
-
- /* We only deal with 970 for now */
- mfspr r0,SPRN_PVR
- srwi r0,r0,16
- cmpwi cr0,r0,0x39
- cmpwi cr1,r0,0x3c
- cror 4*cr0+eq,4*cr0+eq,4*cr1+eq
- bne 1f
-
- /* Save HID0,1,4 and 5 */
- mfspr r3,SPRN_HID0
- std r3,CS_HID0(r5)
- mfspr r3,SPRN_HID1
- std r3,CS_HID1(r5)
- mfspr r3,SPRN_HID4
- std r3,CS_HID4(r5)
- mfspr r3,SPRN_HID5
- std r3,CS_HID5(r5)
-
-1:
- mtcr r7
- blr
-
-/* Called with no MMU context (typically MSR:IR/DR off) to
- * restore CPU state as backed up by the previous
- * function. This does not include cache setting
- */
-_GLOBAL(__restore_cpu_setup)
- /* Some CR fields are volatile, we back it up all */
- mfcr r7
-
- /* Get storage ptr */
- lis r5,(cpu_state_storage-KERNELBASE)@h
- ori r5,r5,cpu_state_storage@l
-
- /* We only deal with 970 for now */
- mfspr r0,SPRN_PVR
- srwi r0,r0,16
- cmpwi cr0,r0,0x39
- cmpwi cr1,r0,0x3c
- cror 4*cr0+eq,4*cr0+eq,4*cr1+eq
- bne 1f
-
- /* Clear interrupt prefix */
- li r0,0
- sync
- mtspr SPRN_HIOR,0
- isync
-
- /* Restore HID0 */
- ld r3,CS_HID0(r5)
- sync
- isync
- mtspr SPRN_HID0,r3
- mfspr r3,SPRN_HID0
- mfspr r3,SPRN_HID0
- mfspr r3,SPRN_HID0
- mfspr r3,SPRN_HID0
- mfspr r3,SPRN_HID0
- mfspr r3,SPRN_HID0
- sync
- isync
-
- /* Restore HID1 */
- ld r3,CS_HID1(r5)
- sync
- isync
- mtspr SPRN_HID1,r3
- mtspr SPRN_HID1,r3
- sync
- isync
-
- /* Restore HID4 */
- ld r3,CS_HID4(r5)
- sync
- isync
- mtspr SPRN_HID4,r3
- sync
- isync
-
- /* Restore HID5 */
- ld r3,CS_HID5(r5)
- sync
- isync
- mtspr SPRN_HID5,r3
- sync
- isync
-1:
- mtcr r7
- blr
-
diff --git a/arch/ppc/kernel/entry.S b/arch/ppc/kernel/entry.S
deleted file mode 100644
index 5f3a5d068a5c..000000000000
--- a/arch/ppc/kernel/entry.S
+++ /dev/null
@@ -1,960 +0,0 @@
-/*
- * PowerPC version
- * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
- * Rewritten by Cort Dougan (cort@fsmlabs.com) for PReP
- * Copyright (C) 1996 Cort Dougan <cort@fsmlabs.com>
- * Adapted for Power Macintosh by Paul Mackerras.
- * Low-level exception handlers and MMU support
- * rewritten by Paul Mackerras.
- * Copyright (C) 1996 Paul Mackerras.
- * MPC8xx modifications Copyright (C) 1997 Dan Malek (dmalek@jlc.net).
- *
- * This file contains the system call entry code, context switch
- * code, and exception/interrupt return code for PowerPC.
- *
- * 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/errno.h>
-#include <linux/sys.h>
-#include <linux/threads.h>
-#include <asm/processor.h>
-#include <asm/page.h>
-#include <asm/mmu.h>
-#include <asm/cputable.h>
-#include <asm/thread_info.h>
-#include <asm/ppc_asm.h>
-#include <asm/asm-offsets.h>
-#include <asm/unistd.h>
-
-#undef SHOW_SYSCALLS
-#undef SHOW_SYSCALLS_TASK
-
-/*
- * MSR_KERNEL is > 0x10000 on 4xx/Book-E since it include MSR_CE.
- */
-#if MSR_KERNEL >= 0x10000
-#define LOAD_MSR_KERNEL(r, x) lis r,(x)@h; ori r,r,(x)@l
-#else
-#define LOAD_MSR_KERNEL(r, x) li r,(x)
-#endif
-
-#ifdef CONFIG_BOOKE
-#include "head_booke.h"
-#define TRANSFER_TO_HANDLER_EXC_LEVEL(exc_level) \
- mtspr exc_level##_SPRG,r8; \
- BOOKE_LOAD_EXC_LEVEL_STACK(exc_level); \
- lwz r0,GPR10-INT_FRAME_SIZE(r8); \
- stw r0,GPR10(r11); \
- lwz r0,GPR11-INT_FRAME_SIZE(r8); \
- stw r0,GPR11(r11); \
- mfspr r8,exc_level##_SPRG
-
- .globl mcheck_transfer_to_handler
-mcheck_transfer_to_handler:
- TRANSFER_TO_HANDLER_EXC_LEVEL(MCHECK)
- b transfer_to_handler_full
-
- .globl debug_transfer_to_handler
-debug_transfer_to_handler:
- TRANSFER_TO_HANDLER_EXC_LEVEL(DEBUG)
- b transfer_to_handler_full
-
- .globl crit_transfer_to_handler
-crit_transfer_to_handler:
- TRANSFER_TO_HANDLER_EXC_LEVEL(CRIT)
- /* fall through */
-#endif
-
-#ifdef CONFIG_40x
- .globl crit_transfer_to_handler
-crit_transfer_to_handler:
- lwz r0,crit_r10@l(0)
- stw r0,GPR10(r11)
- lwz r0,crit_r11@l(0)
- stw r0,GPR11(r11)
- /* fall through */
-#endif
-
-/*
- * This code finishes saving the registers to the exception frame
- * and jumps to the appropriate handler for the exception, turning
- * on address translation.
- * Note that we rely on the caller having set cr0.eq iff the exception
- * occurred in kernel mode (i.e. MSR:PR = 0).
- */
- .globl transfer_to_handler_full
-transfer_to_handler_full:
- SAVE_NVGPRS(r11)
- /* fall through */
-
- .globl transfer_to_handler
-transfer_to_handler:
- stw r2,GPR2(r11)
- stw r12,_NIP(r11)
- stw r9,_MSR(r11)
- andi. r2,r9,MSR_PR
- mfctr r12
- mfspr r2,SPRN_XER
- stw r12,_CTR(r11)
- stw r2,_XER(r11)
- mfspr r12,SPRN_SPRG3
- addi r2,r12,-THREAD
- tovirt(r2,r2) /* set r2 to current */
- beq 2f /* if from user, fix up THREAD.regs */
- addi r11,r1,STACK_FRAME_OVERHEAD
- stw r11,PT_REGS(r12)
-#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
- /* Check to see if the dbcr0 register is set up to debug. Use the
- single-step bit to do this. */
- lwz r12,THREAD_DBCR0(r12)
- andis. r12,r12,DBCR0_IC@h
- beq+ 3f
- /* From user and task is ptraced - load up global dbcr0 */
- li r12,-1 /* clear all pending debug events */
- mtspr SPRN_DBSR,r12
- lis r11,global_dbcr0@ha
- tophys(r11,r11)
- addi r11,r11,global_dbcr0@l
- lwz r12,0(r11)
- mtspr SPRN_DBCR0,r12
- lwz r12,4(r11)
- addi r12,r12,-1
- stw r12,4(r11)
-#endif
- b 3f
-
-2: /* if from kernel, check interrupted DOZE/NAP mode and
- * check for stack overflow
- */
- lwz r9,THREAD_INFO-THREAD(r12)
- cmplw r1,r9 /* if r1 <= current->thread_info */
- ble- stack_ovf /* then the kernel stack overflowed */
-5:
-#ifdef CONFIG_6xx
- tophys(r9,r9) /* check local flags */
- lwz r12,TI_LOCAL_FLAGS(r9)
- mtcrf 0x01,r12
- bt- 31-TLF_NAPPING,4f
-#endif /* CONFIG_6xx */
- .globl transfer_to_handler_cont
-transfer_to_handler_cont:
-3:
- mflr r9
- lwz r11,0(r9) /* virtual address of handler */
- lwz r9,4(r9) /* where to go when done */
- mtspr SPRN_SRR0,r11
- mtspr SPRN_SRR1,r10
- mtlr r9
- SYNC
- RFI /* jump to handler, enable MMU */
-
-#ifdef CONFIG_6xx
-4: rlwinm r12,r12,0,~_TLF_NAPPING
- stw r12,TI_LOCAL_FLAGS(r9)
- b power_save_6xx_restore
-#endif
-
-/*
- * On kernel stack overflow, load up an initial stack pointer
- * and call StackOverflow(regs), which should not return.
- */
-stack_ovf:
- /* sometimes we use a statically-allocated stack, which is OK. */
- lis r12,_end@h
- ori r12,r12,_end@l
- cmplw r1,r12
- ble 5b /* r1 <= &_end is OK */
- SAVE_NVGPRS(r11)
- addi r3,r1,STACK_FRAME_OVERHEAD
- lis r1,init_thread_union@ha
- addi r1,r1,init_thread_union@l
- addi r1,r1,THREAD_SIZE-STACK_FRAME_OVERHEAD
- lis r9,StackOverflow@ha
- addi r9,r9,StackOverflow@l
- LOAD_MSR_KERNEL(r10,MSR_KERNEL)
- FIX_SRR1(r10,r12)
- mtspr SPRN_SRR0,r9
- mtspr SPRN_SRR1,r10
- SYNC
- RFI
-
-/*
- * Handle a system call.
- */
- .stabs "arch/ppc/kernel/",N_SO,0,0,0f
- .stabs "entry.S",N_SO,0,0,0f
-0:
-
-_GLOBAL(DoSyscall)
- stw r3,ORIG_GPR3(r1)
- li r12,0
- stw r12,RESULT(r1)
- lwz r11,_CCR(r1) /* Clear SO bit in CR */
- rlwinm r11,r11,0,4,2
- stw r11,_CCR(r1)
-#ifdef SHOW_SYSCALLS
- bl do_show_syscall
-#endif /* SHOW_SYSCALLS */
- rlwinm r10,r1,0,0,18 /* current_thread_info() */
- lwz r11,TI_FLAGS(r10)
- andi. r11,r11,_TIF_SYSCALL_T_OR_A
- bne- syscall_dotrace
-syscall_dotrace_cont:
- cmplwi 0,r0,NR_syscalls
- lis r10,sys_call_table@h
- ori r10,r10,sys_call_table@l
- slwi r0,r0,2
- bge- 66f
- lwzx r10,r10,r0 /* Fetch system call handler [ptr] */
- mtlr r10
- addi r9,r1,STACK_FRAME_OVERHEAD
- PPC440EP_ERR42
- blrl /* Call handler */
- .globl ret_from_syscall
-ret_from_syscall:
-#ifdef SHOW_SYSCALLS
- bl do_show_syscall_exit
-#endif
- mr r6,r3
- rlwinm r12,r1,0,0,18 /* current_thread_info() */
- /* disable interrupts so current_thread_info()->flags can't change */
- LOAD_MSR_KERNEL(r10,MSR_KERNEL) /* doesn't include MSR_EE */
- SYNC
- MTMSRD(r10)
- lwz r9,TI_FLAGS(r12)
- li r8,-_LAST_ERRNO
- andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP|_TIF_USER_WORK_MASK|_TIF_PERSYSCALL_MASK)
- bne- syscall_exit_work
- cmplw 0,r3,r8
- blt+ syscall_exit_cont
- lwz r11,_CCR(r1) /* Load CR */
- neg r3,r3
- oris r11,r11,0x1000 /* Set SO bit in CR */
- stw r11,_CCR(r1)
-syscall_exit_cont:
-#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
- /* If the process has its own DBCR0 value, load it up. The single
- step bit tells us that dbcr0 should be loaded. */
- lwz r0,THREAD+THREAD_DBCR0(r2)
- andis. r10,r0,DBCR0_IC@h
- bnel- load_dbcr0
-#endif
-#ifdef CONFIG_44x
- lis r4,icache_44x_need_flush@ha
- lwz r5,icache_44x_need_flush@l(r4)
- cmplwi cr0,r5,0
- bne- 2f
-1:
-#endif /* CONFIG_44x */
-BEGIN_FTR_SECTION
- lwarx r7,0,r1
-END_FTR_SECTION_IFSET(CPU_FTR_NEED_PAIRED_STWCX)
- stwcx. r0,0,r1 /* to clear the reservation */
- lwz r4,_LINK(r1)
- lwz r5,_CCR(r1)
- mtlr r4
- mtcr r5
- lwz r7,_NIP(r1)
- lwz r8,_MSR(r1)
- FIX_SRR1(r8, r0)
- lwz r2,GPR2(r1)
- lwz r1,GPR1(r1)
- mtspr SPRN_SRR0,r7
- mtspr SPRN_SRR1,r8
- SYNC
- RFI
-#ifdef CONFIG_44x
-2: li r7,0
- iccci r0,r0
- stw r7,icache_44x_need_flush@l(r4)
- b 1b
-#endif /* CONFIG_44x */
-
-66: li r3,-ENOSYS
- b ret_from_syscall
-
- .globl ret_from_fork
-ret_from_fork:
- REST_NVGPRS(r1)
- bl schedule_tail
- li r3,0
- b ret_from_syscall
-
-/* Traced system call support */
-syscall_dotrace:
- SAVE_NVGPRS(r1)
- li r0,0xc00
- stw r0,TRAP(r1)
- addi r3,r1,STACK_FRAME_OVERHEAD
- bl do_syscall_trace_enter
- lwz r0,GPR0(r1) /* Restore original registers */
- lwz r3,GPR3(r1)
- lwz r4,GPR4(r1)
- lwz r5,GPR5(r1)
- lwz r6,GPR6(r1)
- lwz r7,GPR7(r1)
- lwz r8,GPR8(r1)
- REST_NVGPRS(r1)
- b syscall_dotrace_cont
-
-syscall_exit_work:
- andi. r0,r9,_TIF_RESTOREALL
- beq+ 0f
- REST_NVGPRS(r1)
- b 2f
-0: cmplw 0,r3,r8
- blt+ 1f
- andi. r0,r9,_TIF_NOERROR
- bne- 1f
- lwz r11,_CCR(r1) /* Load CR */
- neg r3,r3
- oris r11,r11,0x1000 /* Set SO bit in CR */
- stw r11,_CCR(r1)
-
-1: stw r6,RESULT(r1) /* Save result */
- stw r3,GPR3(r1) /* Update return value */
-2: andi. r0,r9,(_TIF_PERSYSCALL_MASK)
- beq 4f
-
- /* Clear per-syscall TIF flags if any are set. */
-
- li r11,_TIF_PERSYSCALL_MASK
- addi r12,r12,TI_FLAGS
-3: lwarx r8,0,r12
- andc r8,r8,r11
-#ifdef CONFIG_IBM405_ERR77
- dcbt 0,r12
-#endif
- stwcx. r8,0,r12
- bne- 3b
- subi r12,r12,TI_FLAGS
-
-4: /* Anything which requires enabling interrupts? */
- andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP)
- beq ret_from_except
-
- /* Re-enable interrupts */
- ori r10,r10,MSR_EE
- SYNC
- MTMSRD(r10)
-
- /* Save NVGPRS if they're not saved already */
- lwz r4,TRAP(r1)
- andi. r4,r4,1
- beq 5f
- SAVE_NVGPRS(r1)
- li r4,0xc00
- stw r4,TRAP(r1)
-5:
- addi r3,r1,STACK_FRAME_OVERHEAD
- bl do_syscall_trace_leave
- b ret_from_except_full
-
-#ifdef SHOW_SYSCALLS
-do_show_syscall:
-#ifdef SHOW_SYSCALLS_TASK
- lis r11,show_syscalls_task@ha
- lwz r11,show_syscalls_task@l(r11)
- cmp 0,r2,r11
- bnelr
-#endif
- stw r31,GPR31(r1)
- mflr r31
- lis r3,7f@ha
- addi r3,r3,7f@l
- lwz r4,GPR0(r1)
- lwz r5,GPR3(r1)
- lwz r6,GPR4(r1)
- lwz r7,GPR5(r1)
- lwz r8,GPR6(r1)
- lwz r9,GPR7(r1)
- bl printk
- lis r3,77f@ha
- addi r3,r3,77f@l
- lwz r4,GPR8(r1)
- mr r5,r2
- bl printk
- lwz r0,GPR0(r1)
- lwz r3,GPR3(r1)
- lwz r4,GPR4(r1)
- lwz r5,GPR5(r1)
- lwz r6,GPR6(r1)
- lwz r7,GPR7(r1)
- lwz r8,GPR8(r1)
- mtlr r31
- lwz r31,GPR31(r1)
- blr
-
-do_show_syscall_exit:
-#ifdef SHOW_SYSCALLS_TASK
- lis r11,show_syscalls_task@ha
- lwz r11,show_syscalls_task@l(r11)
- cmp 0,r2,r11
- bnelr
-#endif
- stw r31,GPR31(r1)
- mflr r31
- stw r3,RESULT(r1) /* Save result */
- mr r4,r3
- lis r3,79f@ha
- addi r3,r3,79f@l
- bl printk
- lwz r3,RESULT(r1)
- mtlr r31
- lwz r31,GPR31(r1)
- blr
-
-7: .string "syscall %d(%x, %x, %x, %x, %x, "
-77: .string "%x), current=%p\n"
-79: .string " -> %x\n"
- .align 2,0
-
-#ifdef SHOW_SYSCALLS_TASK
- .data
- .globl show_syscalls_task
-show_syscalls_task:
- .long -1
- .text
-#endif
-#endif /* SHOW_SYSCALLS */
-
-/*
- * The fork/clone functions need to copy the full register set into
- * the child process. Therefore we need to save all the nonvolatile
- * registers (r13 - r31) before calling the C code.
- */
- .globl ppc_fork
-ppc_fork:
- SAVE_NVGPRS(r1)
- lwz r0,TRAP(r1)
- rlwinm r0,r0,0,0,30 /* clear LSB to indicate full */
- stw r0,TRAP(r1) /* register set saved */
- b sys_fork
-
- .globl ppc_vfork
-ppc_vfork:
- SAVE_NVGPRS(r1)
- lwz r0,TRAP(r1)
- rlwinm r0,r0,0,0,30 /* clear LSB to indicate full */
- stw r0,TRAP(r1) /* register set saved */
- b sys_vfork
-
- .globl ppc_clone
-ppc_clone:
- SAVE_NVGPRS(r1)
- lwz r0,TRAP(r1)
- rlwinm r0,r0,0,0,30 /* clear LSB to indicate full */
- stw r0,TRAP(r1) /* register set saved */
- b sys_clone
-
- .globl ppc_swapcontext
-ppc_swapcontext:
- SAVE_NVGPRS(r1)
- lwz r0,TRAP(r1)
- rlwinm r0,r0,0,0,30 /* clear LSB to indicate full */
- stw r0,TRAP(r1) /* register set saved */
- b sys_swapcontext
-
-/*
- * Top-level page fault handling.
- * This is in assembler because if do_page_fault tells us that
- * it is a bad kernel page fault, we want to save the non-volatile
- * registers before calling bad_page_fault.
- */
- .globl handle_page_fault
-handle_page_fault:
- stw r4,_DAR(r1)
- addi r3,r1,STACK_FRAME_OVERHEAD
- bl do_page_fault
- cmpwi r3,0
- beq+ ret_from_except
- SAVE_NVGPRS(r1)
- lwz r0,TRAP(r1)
- clrrwi r0,r0,1
- stw r0,TRAP(r1)
- mr r5,r3
- addi r3,r1,STACK_FRAME_OVERHEAD
- lwz r4,_DAR(r1)
- bl bad_page_fault
- b ret_from_except_full
-
-/*
- * This routine switches between two different tasks. The process
- * state of one is saved on its kernel stack. Then the state
- * of the other is restored from its kernel stack. The memory
- * management hardware is updated to the second process's state.
- * Finally, we can return to the second process.
- * On entry, r3 points to the THREAD for the current task, r4
- * points to the THREAD for the new task.
- *
- * This routine is always called with interrupts disabled.
- *
- * Note: there are two ways to get to the "going out" portion
- * of this code; either by coming in via the entry (_switch)
- * or via "fork" which must set up an environment equivalent
- * to the "_switch" path. If you change this , you'll have to
- * change the fork code also.
- *
- * The code which creates the new task context is in 'copy_thread'
- * in arch/ppc/kernel/process.c
- */
-_GLOBAL(_switch)
- stwu r1,-INT_FRAME_SIZE(r1)
- mflr r0
- stw r0,INT_FRAME_SIZE+4(r1)
- /* r3-r12 are caller saved -- Cort */
- SAVE_NVGPRS(r1)
- stw r0,_NIP(r1) /* Return to switch caller */
- mfmsr r11
- li r0,MSR_FP /* Disable floating-point */
-#ifdef CONFIG_ALTIVEC
-BEGIN_FTR_SECTION
- oris r0,r0,MSR_VEC@h /* Disable altivec */
- mfspr r12,SPRN_VRSAVE /* save vrsave register value */
- stw r12,THREAD+THREAD_VRSAVE(r2)
-END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
-#endif /* CONFIG_ALTIVEC */
- and. r0,r0,r11 /* FP or altivec enabled? */
- beq+ 1f
- andc r11,r11,r0
- MTMSRD(r11)
- isync
-1: stw r11,_MSR(r1)
- mfcr r10
- stw r10,_CCR(r1)
- stw r1,KSP(r3) /* Set old stack pointer */
-
-#ifdef CONFIG_SMP
- /* We need a sync somewhere here to make sure that if the
- * previous task gets rescheduled on another CPU, it sees all
- * stores it has performed on this one.
- */
- sync
-#endif /* CONFIG_SMP */
-
- tophys(r0,r4)
- CLR_TOP32(r0)
- mtspr SPRN_SPRG3,r0 /* Update current THREAD phys addr */
- lwz r1,KSP(r4) /* Load new stack pointer */
-
- /* save the old current 'last' for return value */
- mr r3,r2
- addi r2,r4,-THREAD /* Update current */
-
-#ifdef CONFIG_ALTIVEC
-BEGIN_FTR_SECTION
- lwz r0,THREAD+THREAD_VRSAVE(r2)
- mtspr SPRN_VRSAVE,r0 /* if G4, restore VRSAVE reg */
-END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
-#endif /* CONFIG_ALTIVEC */
- lwz r0,_CCR(r1)
- mtcrf 0xFF,r0
- /* r3-r12 are destroyed -- Cort */
- REST_NVGPRS(r1)
-
- lwz r4,_NIP(r1) /* Return to _switch caller in new task */
- mtlr r4
- addi r1,r1,INT_FRAME_SIZE
- blr
-
- .globl fast_exception_return
-fast_exception_return:
-#if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE))
- andi. r10,r9,MSR_RI /* check for recoverable interrupt */
- beq 1f /* if not, we've got problems */
-#endif
-
-2: REST_4GPRS(3, r11)
- lwz r10,_CCR(r11)
- REST_GPR(1, r11)
- mtcr r10
- lwz r10,_LINK(r11)
- mtlr r10
- REST_GPR(10, r11)
- mtspr SPRN_SRR1,r9
- mtspr SPRN_SRR0,r12
- REST_GPR(9, r11)
- REST_GPR(12, r11)
- lwz r11,GPR11(r11)
- SYNC
- RFI
-
-#if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE))
-/* check if the exception happened in a restartable section */
-1: lis r3,exc_exit_restart_end@ha
- addi r3,r3,exc_exit_restart_end@l
- cmplw r12,r3
- bge 3f
- lis r4,exc_exit_restart@ha
- addi r4,r4,exc_exit_restart@l
- cmplw r12,r4
- blt 3f
- lis r3,fee_restarts@ha
- tophys(r3,r3)
- lwz r5,fee_restarts@l(r3)
- addi r5,r5,1
- stw r5,fee_restarts@l(r3)
- mr r12,r4 /* restart at exc_exit_restart */
- b 2b
-
- .section .bss
- .align 2
-fee_restarts:
- .space 4
- .previous
-
-/* aargh, a nonrecoverable interrupt, panic */
-/* aargh, we don't know which trap this is */
-/* but the 601 doesn't implement the RI bit, so assume it's OK */
-3:
-BEGIN_FTR_SECTION
- b 2b
-END_FTR_SECTION_IFSET(CPU_FTR_601)
- li r10,-1
- stw r10,TRAP(r11)
- addi r3,r1,STACK_FRAME_OVERHEAD
- lis r10,MSR_KERNEL@h
- ori r10,r10,MSR_KERNEL@l
- bl transfer_to_handler_full
- .long nonrecoverable_exception
- .long ret_from_except
-#endif
-
- .globl ret_from_except_full
-ret_from_except_full:
- REST_NVGPRS(r1)
- /* fall through */
-
- .globl ret_from_except
-ret_from_except:
- /* Hard-disable interrupts so that current_thread_info()->flags
- * can't change between when we test it and when we return
- * from the interrupt. */
- LOAD_MSR_KERNEL(r10,MSR_KERNEL)
- SYNC /* Some chip revs have problems here... */
- MTMSRD(r10) /* disable interrupts */
-
- lwz r3,_MSR(r1) /* Returning to user mode? */
- andi. r0,r3,MSR_PR
- beq resume_kernel
-
-user_exc_return: /* r10 contains MSR_KERNEL here */
- /* Check current_thread_info()->flags */
- rlwinm r9,r1,0,0,18
- lwz r9,TI_FLAGS(r9)
- andi. r0,r9,(_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK|_TIF_NEED_RESCHED)
- bne do_work
-
-restore_user:
-#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
- /* Check whether this process has its own DBCR0 value. The single
- step bit tells us that dbcr0 should be loaded. */
- lwz r0,THREAD+THREAD_DBCR0(r2)
- andis. r10,r0,DBCR0_IC@h
- bnel- load_dbcr0
-#endif
-
-#ifdef CONFIG_PREEMPT
- b restore
-
-/* N.B. the only way to get here is from the beq following ret_from_except. */
-resume_kernel:
- /* check current_thread_info->preempt_count */
- rlwinm r9,r1,0,0,18
- lwz r0,TI_PREEMPT(r9)
- cmpwi 0,r0,0 /* if non-zero, just restore regs and return */
- bne restore
- lwz r0,TI_FLAGS(r9)
- andi. r0,r0,_TIF_NEED_RESCHED
- beq+ restore
- andi. r0,r3,MSR_EE /* interrupts off? */
- beq restore /* don't schedule if so */
-1: bl preempt_schedule_irq
- rlwinm r9,r1,0,0,18
- lwz r3,TI_FLAGS(r9)
- andi. r0,r3,_TIF_NEED_RESCHED
- bne- 1b
-#else
-resume_kernel:
-#endif /* CONFIG_PREEMPT */
-
- /* interrupts are hard-disabled at this point */
-restore:
-#ifdef CONFIG_44x
- lis r4,icache_44x_need_flush@ha
- lwz r5,icache_44x_need_flush@l(r4)
- cmplwi cr0,r5,0
- beq+ 1f
- li r6,0
- iccci r0,r0
- stw r6,icache_44x_need_flush@l(r4)
-1:
-#endif /* CONFIG_44x */
- lwz r0,GPR0(r1)
- lwz r2,GPR2(r1)
- REST_4GPRS(3, r1)
- REST_2GPRS(7, r1)
-
- lwz r10,_XER(r1)
- lwz r11,_CTR(r1)
- mtspr SPRN_XER,r10
- mtctr r11
-
- PPC405_ERR77(0,r1)
-BEGIN_FTR_SECTION
- lwarx r11,0,r1
-END_FTR_SECTION_IFSET(CPU_FTR_NEED_PAIRED_STWCX)
- stwcx. r0,0,r1 /* to clear the reservation */
-
-#if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE))
- lwz r9,_MSR(r1)
- andi. r10,r9,MSR_RI /* check if this exception occurred */
- beql nonrecoverable /* at a bad place (MSR:RI = 0) */
-
- lwz r10,_CCR(r1)
- lwz r11,_LINK(r1)
- mtcrf 0xFF,r10
- mtlr r11
-
- /*
- * Once we put values in SRR0 and SRR1, we are in a state
- * where exceptions are not recoverable, since taking an
- * exception will trash SRR0 and SRR1. Therefore we clear the
- * MSR:RI bit to indicate this. If we do take an exception,
- * we can't return to the point of the exception but we
- * can restart the exception exit path at the label
- * exc_exit_restart below. -- paulus
- */
- LOAD_MSR_KERNEL(r10,MSR_KERNEL & ~MSR_RI)
- SYNC
- MTMSRD(r10) /* clear the RI bit */
- .globl exc_exit_restart
-exc_exit_restart:
- lwz r9,_MSR(r1)
- lwz r12,_NIP(r1)
- FIX_SRR1(r9,r10)
- mtspr SPRN_SRR0,r12
- mtspr SPRN_SRR1,r9
- REST_4GPRS(9, r1)
- lwz r1,GPR1(r1)
- .globl exc_exit_restart_end
-exc_exit_restart_end:
- SYNC
- RFI
-
-#else /* !(CONFIG_4xx || CONFIG_BOOKE) */
- /*
- * This is a bit different on 4xx/Book-E because it doesn't have
- * the RI bit in the MSR.
- * The TLB miss handler checks if we have interrupted
- * the exception exit path and restarts it if so
- * (well maybe one day it will... :).
- */
- lwz r11,_LINK(r1)
- mtlr r11
- lwz r10,_CCR(r1)
- mtcrf 0xff,r10
- REST_2GPRS(9, r1)
- .globl exc_exit_restart
-exc_exit_restart:
- lwz r11,_NIP(r1)
- lwz r12,_MSR(r1)
-exc_exit_start:
- mtspr SPRN_SRR0,r11
- mtspr SPRN_SRR1,r12
- REST_2GPRS(11, r1)
- lwz r1,GPR1(r1)
- .globl exc_exit_restart_end
-exc_exit_restart_end:
- PPC405_ERR77_SYNC
- rfi
- b . /* prevent prefetch past rfi */
-
-/*
- * Returning from a critical interrupt in user mode doesn't need
- * to be any different from a normal exception. For a critical
- * interrupt in the kernel, we just return (without checking for
- * preemption) since the interrupt may have happened at some crucial
- * place (e.g. inside the TLB miss handler), and because we will be
- * running with r1 pointing into critical_stack, not the current
- * process's kernel stack (and therefore current_thread_info() will
- * give the wrong answer).
- * We have to restore various SPRs that may have been in use at the
- * time of the critical interrupt.
- *
- */
-#ifdef CONFIG_40x
-#define PPC_40x_TURN_OFF_MSR_DR \
- /* avoid any possible TLB misses here by turning off MSR.DR, we \
- * assume the instructions here are mapped by a pinned TLB entry */ \
- li r10,MSR_IR; \
- mtmsr r10; \
- isync; \
- tophys(r1, r1);
-#else
-#define PPC_40x_TURN_OFF_MSR_DR
-#endif
-
-#define RET_FROM_EXC_LEVEL(exc_lvl_srr0, exc_lvl_srr1, exc_lvl_rfi) \
- REST_NVGPRS(r1); \
- lwz r3,_MSR(r1); \
- andi. r3,r3,MSR_PR; \
- LOAD_MSR_KERNEL(r10,MSR_KERNEL); \
- bne user_exc_return; \
- lwz r0,GPR0(r1); \
- lwz r2,GPR2(r1); \
- REST_4GPRS(3, r1); \
- REST_2GPRS(7, r1); \
- lwz r10,_XER(r1); \
- lwz r11,_CTR(r1); \
- mtspr SPRN_XER,r10; \
- mtctr r11; \
- PPC405_ERR77(0,r1); \
- stwcx. r0,0,r1; /* to clear the reservation */ \
- lwz r11,_LINK(r1); \
- mtlr r11; \
- lwz r10,_CCR(r1); \
- mtcrf 0xff,r10; \
- PPC_40x_TURN_OFF_MSR_DR; \
- lwz r9,_DEAR(r1); \
- lwz r10,_ESR(r1); \
- mtspr SPRN_DEAR,r9; \
- mtspr SPRN_ESR,r10; \
- lwz r11,_NIP(r1); \
- lwz r12,_MSR(r1); \
- mtspr exc_lvl_srr0,r11; \
- mtspr exc_lvl_srr1,r12; \
- lwz r9,GPR9(r1); \
- lwz r12,GPR12(r1); \
- lwz r10,GPR10(r1); \
- lwz r11,GPR11(r1); \
- lwz r1,GPR1(r1); \
- PPC405_ERR77_SYNC; \
- exc_lvl_rfi; \
- b .; /* prevent prefetch past exc_lvl_rfi */
-
- .globl ret_from_crit_exc
-ret_from_crit_exc:
- RET_FROM_EXC_LEVEL(SPRN_CSRR0, SPRN_CSRR1, RFCI)
-
-#ifdef CONFIG_BOOKE
- .globl ret_from_debug_exc
-ret_from_debug_exc:
- RET_FROM_EXC_LEVEL(SPRN_DSRR0, SPRN_DSRR1, RFDI)
-
- .globl ret_from_mcheck_exc
-ret_from_mcheck_exc:
- RET_FROM_EXC_LEVEL(SPRN_MCSRR0, SPRN_MCSRR1, RFMCI)
-#endif /* CONFIG_BOOKE */
-
-/*
- * Load the DBCR0 value for a task that is being ptraced,
- * having first saved away the global DBCR0. Note that r0
- * has the dbcr0 value to set upon entry to this.
- */
-load_dbcr0:
- mfmsr r10 /* first disable debug exceptions */
- rlwinm r10,r10,0,~MSR_DE
- mtmsr r10
- isync
- mfspr r10,SPRN_DBCR0
- lis r11,global_dbcr0@ha
- addi r11,r11,global_dbcr0@l
- stw r10,0(r11)
- mtspr SPRN_DBCR0,r0
- lwz r10,4(r11)
- addi r10,r10,1
- stw r10,4(r11)
- li r11,-1
- mtspr SPRN_DBSR,r11 /* clear all pending debug events */
- blr
-
- .section .bss
- .align 4
-global_dbcr0:
- .space 8
- .previous
-#endif /* !(CONFIG_4xx || CONFIG_BOOKE) */
-
-do_work: /* r10 contains MSR_KERNEL here */
- andi. r0,r9,_TIF_NEED_RESCHED
- beq do_user_signal
-
-do_resched: /* r10 contains MSR_KERNEL here */
- ori r10,r10,MSR_EE
- SYNC
- MTMSRD(r10) /* hard-enable interrupts */
- bl schedule
-recheck:
- LOAD_MSR_KERNEL(r10,MSR_KERNEL)
- SYNC
- MTMSRD(r10) /* disable interrupts */
- rlwinm r9,r1,0,0,18
- lwz r9,TI_FLAGS(r9)
- andi. r0,r9,_TIF_NEED_RESCHED
- bne- do_resched
- andi. r0,r9,_TIF_SIGPENDING
- beq restore_user
-do_user_signal: /* r10 contains MSR_KERNEL here */
- ori r10,r10,MSR_EE
- SYNC
- MTMSRD(r10) /* hard-enable interrupts */
- /* save r13-r31 in the exception frame, if not already done */
- lwz r3,TRAP(r1)
- andi. r0,r3,1
- beq 2f
- SAVE_NVGPRS(r1)
- rlwinm r3,r3,0,0,30
- stw r3,TRAP(r1)
-2: li r3,0
- addi r4,r1,STACK_FRAME_OVERHEAD
- bl do_signal
- REST_NVGPRS(r1)
- b recheck
-
-/*
- * We come here when we are at the end of handling an exception
- * that occurred at a place where taking an exception will lose
- * state information, such as the contents of SRR0 and SRR1.
- */
-nonrecoverable:
- lis r10,exc_exit_restart_end@ha
- addi r10,r10,exc_exit_restart_end@l
- cmplw r12,r10
- bge 3f
- lis r11,exc_exit_restart@ha
- addi r11,r11,exc_exit_restart@l
- cmplw r12,r11
- blt 3f
- lis r10,ee_restarts@ha
- lwz r12,ee_restarts@l(r10)
- addi r12,r12,1
- stw r12,ee_restarts@l(r10)
- mr r12,r11 /* restart at exc_exit_restart */
- blr
-3: /* OK, we can't recover, kill this process */
- /* but the 601 doesn't implement the RI bit, so assume it's OK */
-BEGIN_FTR_SECTION
- blr
-END_FTR_SECTION_IFSET(CPU_FTR_601)
- lwz r3,TRAP(r1)
- andi. r0,r3,1
- beq 4f
- SAVE_NVGPRS(r1)
- rlwinm r3,r3,0,0,30
- stw r3,TRAP(r1)
-4: addi r3,r1,STACK_FRAME_OVERHEAD
- bl nonrecoverable_exception
- /* shouldn't return */
- b 4b
-
- .section .bss
- .align 2
-ee_restarts:
- .space 4
- .previous
diff --git a/arch/ppc/kernel/head.S b/arch/ppc/kernel/head.S
deleted file mode 100644
index e7e642b95138..000000000000
--- a/arch/ppc/kernel/head.S
+++ /dev/null
@@ -1,1220 +0,0 @@
-/*
- * PowerPC version
- * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
- *
- * Rewritten by Cort Dougan (cort@cs.nmt.edu) for PReP
- * Copyright (C) 1996 Cort Dougan <cort@cs.nmt.edu>
- * Adapted for Power Macintosh by Paul Mackerras.
- * Low-level exception handlers and MMU support
- * rewritten by Paul Mackerras.
- * Copyright (C) 1996 Paul Mackerras.
- * MPC8xx modifications Copyright (C) 1997 Dan Malek (dmalek@jlc.net).
- * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
- *
- * This file contains the low-level support and setup for the
- * PowerPC platform, including trap and interrupt dispatch.
- * (The PPC 8xx embedded CPUs use head_8xx.S instead.)
- *
- * 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 <asm/processor.h>
-#include <asm/page.h>
-#include <asm/mmu.h>
-#include <asm/pgtable.h>
-#include <asm/cputable.h>
-#include <asm/cache.h>
-#include <asm/thread_info.h>
-#include <asm/ppc_asm.h>
-#include <asm/asm-offsets.h>
-
-/* 601 only have IBAT; cr0.eq is set on 601 when using this macro */
-#define LOAD_BAT(n, reg, RA, RB) \
- /* see the comment for clear_bats() -- Cort */ \
- li RA,0; \
- mtspr SPRN_IBAT##n##U,RA; \
- mtspr SPRN_DBAT##n##U,RA; \
- lwz RA,(n*16)+0(reg); \
- lwz RB,(n*16)+4(reg); \
- mtspr SPRN_IBAT##n##U,RA; \
- mtspr SPRN_IBAT##n##L,RB; \
- beq 1f; \
- lwz RA,(n*16)+8(reg); \
- lwz RB,(n*16)+12(reg); \
- mtspr SPRN_DBAT##n##U,RA; \
- mtspr SPRN_DBAT##n##L,RB; \
-1:
-
- .text
- .stabs "arch/ppc/kernel/",N_SO,0,0,0f
- .stabs "head.S",N_SO,0,0,0f
-0:
- .globl _stext
-_stext:
-
-/*
- * _start is defined this way because the XCOFF loader in the OpenFirmware
- * on the powermac expects the entry point to be a procedure descriptor.
- */
- .text
- .globl _start
-_start:
- /*
- * These are here for legacy reasons, the kernel used to
- * need to look like a coff function entry for the pmac
- * but we're always started by some kind of bootloader now.
- * -- Cort
- */
- nop /* used by __secondary_hold on prep (mtx) and chrp smp */
- nop /* used by __secondary_hold on prep (mtx) and chrp smp */
- nop
-
-/* PMAC
- * Enter here with the kernel text, data and bss loaded starting at
- * 0, running with virtual == physical mapping.
- * r5 points to the prom entry point (the client interface handler
- * address). Address translation is turned on, with the prom
- * managing the hash table. Interrupts are disabled. The stack
- * pointer (r1) points to just below the end of the half-meg region
- * from 0x380000 - 0x400000, which is mapped in already.
- *
- * If we are booted from MacOS via BootX, we enter with the kernel
- * image loaded somewhere, and the following values in registers:
- * r3: 'BooX' (0x426f6f58)
- * r4: virtual address of boot_infos_t
- * r5: 0
- *
- * APUS
- * r3: 'APUS'
- * r4: physical address of memory base
- * Linux/m68k style BootInfo structure at &_end.
- *
- * PREP
- * This is jumped to on prep systems right after the kernel is relocated
- * to its proper place in memory by the boot loader. The expected layout
- * of the regs is:
- * r3: ptr to residual data
- * r4: initrd_start or if no initrd then 0
- * r5: initrd_end - unused if r4 is 0
- * r6: Start of command line string
- * r7: End of command line string
- *
- * This just gets a minimal mmu environment setup so we can call
- * start_here() to do the real work.
- * -- Cort
- */
-
- .globl __start
-__start:
- mr r31,r3 /* save parameters */
- mr r30,r4
- mr r29,r5
- mr r28,r6
- mr r27,r7
- li r24,0 /* cpu # */
-
-/*
- * early_init() does the early machine identification and does
- * the necessary low-level setup and clears the BSS
- * -- Cort <cort@fsmlabs.com>
- */
- bl early_init
-
-/* Switch MMU off, clear BATs and flush TLB. At this point, r3 contains
- * the physical address we are running at, returned by early_init()
- */
- bl mmu_off
-__after_mmu_off:
- bl clear_bats
- bl flush_tlbs
-
- bl initial_bats
-#ifdef CONFIG_BOOTX_TEXT
- bl setup_disp_bat
-#endif
-
-/*
- * Call setup_cpu for CPU 0 and initialize 6xx Idle
- */
- bl reloc_offset
- li r24,0 /* cpu# */
- bl call_setup_cpu /* Call setup_cpu for this CPU */
-#ifdef CONFIG_6xx
- bl reloc_offset
- bl init_idle_6xx
-#endif /* CONFIG_6xx */
-
-
-/*
- * We need to run with _start at physical address 0.
- * If the MMU is already turned on, we copy stuff to KERNELBASE,
- * otherwise we copy it to 0.
- */
- bl reloc_offset
- mr r26,r3
- addis r4,r3,KERNELBASE@h /* current address of _start */
- cmpwi 0,r4,0 /* are we already running at 0? */
- bne relocate_kernel
-
-/*
- * we now have the 1st 16M of ram mapped with the bats.
- * prep needs the mmu to be turned on here, but pmac already has it on.
- * this shouldn't bother the pmac since it just gets turned on again
- * as we jump to our code at KERNELBASE. -- Cort
- * Actually no, pmac doesn't have it on any more. BootX enters with MMU
- * off, and in other cases, we now turn it off before changing BATs above.
- */
-turn_on_mmu:
- mfmsr r0
- ori r0,r0,MSR_DR|MSR_IR
- mtspr SPRN_SRR1,r0
- lis r0,start_here@h
- ori r0,r0,start_here@l
- mtspr SPRN_SRR0,r0
- SYNC
- RFI /* enables MMU */
-
-/*
- * We need __secondary_hold as a place to hold the other cpus on
- * an SMP machine, even when we are running a UP kernel.
- */
- . = 0xc0 /* for prep bootloader */
- li r3,1 /* MTX only has 1 cpu */
- .globl __secondary_hold
-__secondary_hold:
- /* tell the master we're here */
- stw r3,4(0)
-#ifdef CONFIG_SMP
-100: lwz r4,0(0)
- /* wait until we're told to start */
- cmpw 0,r4,r3
- bne 100b
- /* our cpu # was at addr 0 - go */
- mr r24,r3 /* cpu # */
- b __secondary_start
-#else
- b .
-#endif /* CONFIG_SMP */
-
-/*
- * Exception 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's thread_struct.
- */
-#define EXCEPTION_PROLOG \
- mtspr SPRN_SPRG0,r10; \
- mtspr SPRN_SPRG1,r11; \
- mfcr r10; \
- EXCEPTION_PROLOG_1; \
- EXCEPTION_PROLOG_2
-
-#define EXCEPTION_PROLOG_1 \
- mfspr r11,SPRN_SRR1; /* check whether user or kernel */ \
- andi. r11,r11,MSR_PR; \
- tophys(r11,r1); /* use tophys(r1) if kernel */ \
- beq 1f; \
- mfspr r11,SPRN_SPRG3; \
- lwz r11,THREAD_INFO-THREAD(r11); \
- addi r11,r11,THREAD_SIZE; \
- tophys(r11,r11); \
-1: subi r11,r11,INT_FRAME_SIZE /* alloc exc. frame */
-
-
-#define EXCEPTION_PROLOG_2 \
- CLR_TOP32(r11); \
- stw r10,_CCR(r11); /* save registers */ \
- stw r12,GPR12(r11); \
- stw r9,GPR9(r11); \
- mfspr r10,SPRN_SPRG0; \
- stw r10,GPR10(r11); \
- mfspr r12,SPRN_SPRG1; \
- stw r12,GPR11(r11); \
- mflr r10; \
- stw r10,_LINK(r11); \
- mfspr r12,SPRN_SRR0; \
- mfspr r9,SPRN_SRR1; \
- stw r1,GPR1(r11); \
- stw r1,0(r11); \
- tovirt(r1,r11); /* set new kernel sp */ \
- li r10,MSR_KERNEL & ~(MSR_IR|MSR_DR); /* can take exceptions */ \
- MTMSRD(r10); /* (except for mach check in rtas) */ \
- stw r0,GPR0(r11); \
- SAVE_4GPRS(3, r11); \
- SAVE_2GPRS(7, r11)
-
-/*
- * Note: code which follows this uses cr0.eq (set if from kernel),
- * r11, r12 (SRR0), and r9 (SRR1).
- *
- * Note2: once we have set r1 we are in a position to take exceptions
- * again, and we could thus set MSR:RI at that point.
- */
-
-/*
- * Exception vectors.
- */
-#define EXCEPTION(n, label, hdlr, xfer) \
- . = n; \
-label: \
- EXCEPTION_PROLOG; \
- addi r3,r1,STACK_FRAME_OVERHEAD; \
- xfer(n, hdlr)
-
-#define EXC_XFER_TEMPLATE(n, hdlr, trap, copyee, tfer, ret) \
- li r10,trap; \
- stw r10,TRAP(r11); \
- li r10,MSR_KERNEL; \
- copyee(r10, r9); \
- bl tfer; \
-i##n: \
- .long hdlr; \
- .long ret
-
-#define COPY_EE(d, s) rlwimi d,s,0,16,16
-#define NOCOPY(d, s)
-
-#define EXC_XFER_STD(n, hdlr) \
- EXC_XFER_TEMPLATE(n, hdlr, n, NOCOPY, transfer_to_handler_full, \
- ret_from_except_full)
-
-#define EXC_XFER_LITE(n, hdlr) \
- EXC_XFER_TEMPLATE(n, hdlr, n+1, NOCOPY, transfer_to_handler, \
- ret_from_except)
-
-#define EXC_XFER_EE(n, hdlr) \
- EXC_XFER_TEMPLATE(n, hdlr, n, COPY_EE, transfer_to_handler_full, \
- ret_from_except_full)
-
-#define EXC_XFER_EE_LITE(n, hdlr) \
- EXC_XFER_TEMPLATE(n, hdlr, n+1, COPY_EE, transfer_to_handler, \
- ret_from_except)
-
-/* System reset */
-/* core99 pmac starts the seconary here by changing the vector, and
- putting it back to what it was (unknown_exception) when done. */
- EXCEPTION(0x100, Reset, unknown_exception, EXC_XFER_STD)
-
-/* Machine check */
- . = 0x200
- mtspr SPRN_SPRG0,r10
- mtspr SPRN_SPRG1,r11
- mfcr r10
- EXCEPTION_PROLOG_1
-7: EXCEPTION_PROLOG_2
- addi r3,r1,STACK_FRAME_OVERHEAD
- EXC_XFER_STD(0x200, machine_check_exception)
-
-/* Data access exception. */
- . = 0x300
-DataAccess:
- EXCEPTION_PROLOG
- mfspr r10,SPRN_DSISR
- andis. r0,r10,0xa470 /* weird error? */
- bne 1f /* if not, try to put a PTE */
- mfspr r4,SPRN_DAR /* into the hash table */
- rlwinm r3,r10,32-15,21,21 /* DSISR_STORE -> _PAGE_RW */
- bl hash_page
-1: stw r10,_DSISR(r11)
- mr r5,r10
- mfspr r4,SPRN_DAR
- EXC_XFER_EE_LITE(0x300, handle_page_fault)
-
-/* Instruction access exception. */
- . = 0x400
-InstructionAccess:
- EXCEPTION_PROLOG
- andis. r0,r9,0x4000 /* no pte found? */
- beq 1f /* if so, try to put a PTE */
- li r3,0 /* into the hash table */
- mr r4,r12 /* SRR0 is fault address */
- bl hash_page
-1: mr r4,r12
- mr r5,r9
- EXC_XFER_EE_LITE(0x400, handle_page_fault)
-
-/* External interrupt */
- EXCEPTION(0x500, HardwareInterrupt, do_IRQ, EXC_XFER_LITE)
-
-/* Alignment exception */
- . = 0x600
-Alignment:
- EXCEPTION_PROLOG
- mfspr r4,SPRN_DAR
- stw r4,_DAR(r11)
- mfspr r5,SPRN_DSISR
- stw r5,_DSISR(r11)
- addi r3,r1,STACK_FRAME_OVERHEAD
- EXC_XFER_EE(0x600, alignment_exception)
-
-/* Program check exception */
- EXCEPTION(0x700, ProgramCheck, program_check_exception, EXC_XFER_STD)
-
-/* Floating-point unavailable */
- . = 0x800
-FPUnavailable:
- EXCEPTION_PROLOG
- bne load_up_fpu /* if from user, just load it up */
- addi r3,r1,STACK_FRAME_OVERHEAD
- EXC_XFER_EE_LITE(0x800, kernel_fp_unavailable_exception)
-
-/* Decrementer */
- EXCEPTION(0x900, Decrementer, timer_interrupt, EXC_XFER_LITE)
-
- EXCEPTION(0xa00, Trap_0a, unknown_exception, EXC_XFER_EE)
- EXCEPTION(0xb00, Trap_0b, unknown_exception, EXC_XFER_EE)
-
-/* System call */
- . = 0xc00
-SystemCall:
- EXCEPTION_PROLOG
- EXC_XFER_EE_LITE(0xc00, DoSyscall)
-
-/* Single step - not used on 601 */
- EXCEPTION(0xd00, SingleStep, single_step_exception, EXC_XFER_STD)
- EXCEPTION(0xe00, Trap_0e, unknown_exception, EXC_XFER_EE)
-
-/*
- * The Altivec unavailable trap is at 0x0f20. Foo.
- * We effectively remap it to 0x3000.
- * We include an altivec unavailable exception vector even if
- * not configured for Altivec, so that you can't panic a
- * non-altivec kernel running on a machine with altivec just
- * by executing an altivec instruction.
- */
- . = 0xf00
- b Trap_0f
-
- . = 0xf20
- b AltiVecUnavailable
-
-Trap_0f:
- EXCEPTION_PROLOG
- addi r3,r1,STACK_FRAME_OVERHEAD
- EXC_XFER_EE(0xf00, unknown_exception)
-
-/*
- * Handle TLB miss for instruction on 603/603e.
- * Note: we get an alternate set of r0 - r3 to use automatically.
- */
- . = 0x1000
-InstructionTLBMiss:
-/*
- * r0: stored ctr
- * r1: linux style pte ( later becomes ppc hardware pte )
- * r2: ptr to linux-style pte
- * r3: scratch
- */
- mfctr r0
- /* Get PTE (linux-style) and check access */
- mfspr r3,SPRN_IMISS
- lis r1,KERNELBASE@h /* check if kernel address */
- cmplw 0,r3,r1
- mfspr r2,SPRN_SPRG3
- li r1,_PAGE_USER|_PAGE_PRESENT /* low addresses tested as user */
- lwz r2,PGDIR(r2)
- blt+ 112f
- lis r2,swapper_pg_dir@ha /* if kernel address, use */
- addi r2,r2,swapper_pg_dir@l /* kernel page table */
- mfspr r1,SPRN_SRR1 /* and MSR_PR bit from SRR1 */
- rlwinm r1,r1,32-12,29,29 /* shift MSR_PR to _PAGE_USER posn */
-112: tophys(r2,r2)
- rlwimi r2,r3,12,20,29 /* insert top 10 bits of address */
- lwz r2,0(r2) /* get pmd entry */
- rlwinm. r2,r2,0,0,19 /* extract address of pte page */
- beq- InstructionAddressInvalid /* return if no mapping */
- rlwimi r2,r3,22,20,29 /* insert next 10 bits of address */
- lwz r3,0(r2) /* get linux-style pte */
- andc. r1,r1,r3 /* check access & ~permission */
- bne- InstructionAddressInvalid /* return if access not permitted */
- ori r3,r3,_PAGE_ACCESSED /* set _PAGE_ACCESSED in pte */
- /*
- * NOTE! We are assuming this is not an SMP system, otherwise
- * we would need to update the pte atomically with lwarx/stwcx.
- */
- stw r3,0(r2) /* update PTE (accessed bit) */
- /* Convert linux-style PTE to low word of PPC-style PTE */
- rlwinm r1,r3,32-10,31,31 /* _PAGE_RW -> PP lsb */
- rlwinm r2,r3,32-7,31,31 /* _PAGE_DIRTY -> PP lsb */
- and r1,r1,r2 /* writable if _RW and _DIRTY */
- rlwimi r3,r3,32-1,30,30 /* _PAGE_USER -> PP msb */
- rlwimi r3,r3,32-1,31,31 /* _PAGE_USER -> PP lsb */
- ori r1,r1,0xe14 /* clear out reserved bits and M */
- andc r1,r3,r1 /* PP = user? (rw&dirty? 2: 3): 0 */
- mtspr SPRN_RPA,r1
- mfspr r3,SPRN_IMISS
- tlbli r3
- mfspr r3,SPRN_SRR1 /* Need to restore CR0 */
- mtcrf 0x80,r3
- rfi
-InstructionAddressInvalid:
- mfspr r3,SPRN_SRR1
- rlwinm r1,r3,9,6,6 /* Get load/store bit */
-
- addis r1,r1,0x2000
- mtspr SPRN_DSISR,r1 /* (shouldn't be needed) */
- mtctr r0 /* Restore CTR */
- andi. r2,r3,0xFFFF /* Clear upper bits of SRR1 */
- or r2,r2,r1
- mtspr SPRN_SRR1,r2
- mfspr r1,SPRN_IMISS /* Get failing address */
- rlwinm. r2,r2,0,31,31 /* Check for little endian access */
- rlwimi r2,r2,1,30,30 /* change 1 -> 3 */
- xor r1,r1,r2
- mtspr SPRN_DAR,r1 /* Set fault address */
- mfmsr r0 /* Restore "normal" registers */
- xoris r0,r0,MSR_TGPR>>16
- mtcrf 0x80,r3 /* Restore CR0 */
- mtmsr r0
- b InstructionAccess
-
-/*
- * Handle TLB miss for DATA Load operation on 603/603e
- */
- . = 0x1100
-DataLoadTLBMiss:
-/*
- * r0: stored ctr
- * r1: linux style pte ( later becomes ppc hardware pte )
- * r2: ptr to linux-style pte
- * r3: scratch
- */
- mfctr r0
- /* Get PTE (linux-style) and check access */
- mfspr r3,SPRN_DMISS
- lis r1,KERNELBASE@h /* check if kernel address */
- cmplw 0,r3,r1
- mfspr r2,SPRN_SPRG3
- li r1,_PAGE_USER|_PAGE_PRESENT /* low addresses tested as user */
- lwz r2,PGDIR(r2)
- blt+ 112f
- lis r2,swapper_pg_dir@ha /* if kernel address, use */
- addi r2,r2,swapper_pg_dir@l /* kernel page table */
- mfspr r1,SPRN_SRR1 /* and MSR_PR bit from SRR1 */
- rlwinm r1,r1,32-12,29,29 /* shift MSR_PR to _PAGE_USER posn */
-112: tophys(r2,r2)
- rlwimi r2,r3,12,20,29 /* insert top 10 bits of address */
- lwz r2,0(r2) /* get pmd entry */
- rlwinm. r2,r2,0,0,19 /* extract address of pte page */
- beq- DataAddressInvalid /* return if no mapping */
- rlwimi r2,r3,22,20,29 /* insert next 10 bits of address */
- lwz r3,0(r2) /* get linux-style pte */
- andc. r1,r1,r3 /* check access & ~permission */
- bne- DataAddressInvalid /* return if access not permitted */
- ori r3,r3,_PAGE_ACCESSED /* set _PAGE_ACCESSED in pte */
- /*
- * NOTE! We are assuming this is not an SMP system, otherwise
- * we would need to update the pte atomically with lwarx/stwcx.
- */
- stw r3,0(r2) /* update PTE (accessed bit) */
- /* Convert linux-style PTE to low word of PPC-style PTE */
- rlwinm r1,r3,32-10,31,31 /* _PAGE_RW -> PP lsb */
- rlwinm r2,r3,32-7,31,31 /* _PAGE_DIRTY -> PP lsb */
- and r1,r1,r2 /* writable if _RW and _DIRTY */
- rlwimi r3,r3,32-1,30,30 /* _PAGE_USER -> PP msb */
- rlwimi r3,r3,32-1,31,31 /* _PAGE_USER -> PP lsb */
- ori r1,r1,0xe14 /* clear out reserved bits and M */
- andc r1,r3,r1 /* PP = user? (rw&dirty? 2: 3): 0 */
- mtspr SPRN_RPA,r1
- mfspr r3,SPRN_DMISS
- tlbld r3
- mfspr r3,SPRN_SRR1 /* Need to restore CR0 */
- mtcrf 0x80,r3
- rfi
-DataAddressInvalid:
- mfspr r3,SPRN_SRR1
- rlwinm r1,r3,9,6,6 /* Get load/store bit */
- addis r1,r1,0x2000
- mtspr SPRN_DSISR,r1
- mtctr r0 /* Restore CTR */
- andi. r2,r3,0xFFFF /* Clear upper bits of SRR1 */
- mtspr SPRN_SRR1,r2
- mfspr r1,SPRN_DMISS /* Get failing address */
- rlwinm. r2,r2,0,31,31 /* Check for little endian access */
- beq 20f /* Jump if big endian */
- xori r1,r1,3
-20: mtspr SPRN_DAR,r1 /* Set fault address */
- mfmsr r0 /* Restore "normal" registers */
- xoris r0,r0,MSR_TGPR>>16
- mtcrf 0x80,r3 /* Restore CR0 */
- mtmsr r0
- b DataAccess
-
-/*
- * Handle TLB miss for DATA Store on 603/603e
- */
- . = 0x1200
-DataStoreTLBMiss:
-/*
- * r0: stored ctr
- * r1: linux style pte ( later becomes ppc hardware pte )
- * r2: ptr to linux-style pte
- * r3: scratch
- */
- mfctr r0
- /* Get PTE (linux-style) and check access */
- mfspr r3,SPRN_DMISS
- lis r1,KERNELBASE@h /* check if kernel address */
- cmplw 0,r3,r1
- mfspr r2,SPRN_SPRG3
- li r1,_PAGE_RW|_PAGE_USER|_PAGE_PRESENT /* access flags */
- lwz r2,PGDIR(r2)
- blt+ 112f
- lis r2,swapper_pg_dir@ha /* if kernel address, use */
- addi r2,r2,swapper_pg_dir@l /* kernel page table */
- mfspr r1,SPRN_SRR1 /* and MSR_PR bit from SRR1 */
- rlwinm r1,r1,32-12,29,29 /* shift MSR_PR to _PAGE_USER posn */
-112: tophys(r2,r2)
- rlwimi r2,r3,12,20,29 /* insert top 10 bits of address */
- lwz r2,0(r2) /* get pmd entry */
- rlwinm. r2,r2,0,0,19 /* extract address of pte page */
- beq- DataAddressInvalid /* return if no mapping */
- rlwimi r2,r3,22,20,29 /* insert next 10 bits of address */
- lwz r3,0(r2) /* get linux-style pte */
- andc. r1,r1,r3 /* check access & ~permission */
- bne- DataAddressInvalid /* return if access not permitted */
- ori r3,r3,_PAGE_ACCESSED|_PAGE_DIRTY
- /*
- * NOTE! We are assuming this is not an SMP system, otherwise
- * we would need to update the pte atomically with lwarx/stwcx.
- */
- stw r3,0(r2) /* update PTE (accessed/dirty bits) */
- /* Convert linux-style PTE to low word of PPC-style PTE */
- rlwimi r3,r3,32-1,30,30 /* _PAGE_USER -> PP msb */
- li r1,0xe15 /* clear out reserved bits and M */
- andc r1,r3,r1 /* PP = user? 2: 0 */
- mtspr SPRN_RPA,r1
- mfspr r3,SPRN_DMISS
- tlbld r3
- mfspr r3,SPRN_SRR1 /* Need to restore CR0 */
- mtcrf 0x80,r3
- rfi
-
-#ifndef CONFIG_ALTIVEC
-#define altivec_assist_exception unknown_exception
-#endif
-
- EXCEPTION(0x1300, Trap_13, instruction_breakpoint_exception, EXC_XFER_EE)
- EXCEPTION(0x1400, SMI, SMIException, EXC_XFER_EE)
- EXCEPTION(0x1500, Trap_15, unknown_exception, EXC_XFER_EE)
- EXCEPTION(0x1600, Trap_16, altivec_assist_exception, EXC_XFER_EE)
- EXCEPTION(0x1700, Trap_17, TAUException, EXC_XFER_STD)
- EXCEPTION(0x1800, Trap_18, unknown_exception, EXC_XFER_EE)
- EXCEPTION(0x1900, Trap_19, unknown_exception, EXC_XFER_EE)
- EXCEPTION(0x1a00, Trap_1a, unknown_exception, EXC_XFER_EE)
- EXCEPTION(0x1b00, Trap_1b, unknown_exception, EXC_XFER_EE)
- EXCEPTION(0x1c00, Trap_1c, unknown_exception, EXC_XFER_EE)
- EXCEPTION(0x1d00, Trap_1d, unknown_exception, EXC_XFER_EE)
- EXCEPTION(0x1e00, Trap_1e, unknown_exception, EXC_XFER_EE)
- EXCEPTION(0x1f00, Trap_1f, unknown_exception, EXC_XFER_EE)
- EXCEPTION(0x2000, RunMode, RunModeException, EXC_XFER_EE)
- EXCEPTION(0x2100, Trap_21, unknown_exception, EXC_XFER_EE)
- EXCEPTION(0x2200, Trap_22, unknown_exception, EXC_XFER_EE)
- EXCEPTION(0x2300, Trap_23, unknown_exception, EXC_XFER_EE)
- EXCEPTION(0x2400, Trap_24, unknown_exception, EXC_XFER_EE)
- EXCEPTION(0x2500, Trap_25, unknown_exception, EXC_XFER_EE)
- EXCEPTION(0x2600, Trap_26, unknown_exception, EXC_XFER_EE)
- EXCEPTION(0x2700, Trap_27, unknown_exception, EXC_XFER_EE)
- EXCEPTION(0x2800, Trap_28, unknown_exception, EXC_XFER_EE)
- EXCEPTION(0x2900, Trap_29, unknown_exception, EXC_XFER_EE)
- EXCEPTION(0x2a00, Trap_2a, unknown_exception, EXC_XFER_EE)
- EXCEPTION(0x2b00, Trap_2b, unknown_exception, EXC_XFER_EE)
- EXCEPTION(0x2c00, Trap_2c, unknown_exception, EXC_XFER_EE)
- EXCEPTION(0x2d00, Trap_2d, unknown_exception, EXC_XFER_EE)
- EXCEPTION(0x2e00, Trap_2e, unknown_exception, EXC_XFER_EE)
- EXCEPTION(0x2f00, MOLTrampoline, unknown_exception, EXC_XFER_EE_LITE)
-
- .globl mol_trampoline
- .set mol_trampoline, i0x2f00
-
- . = 0x3000
-
-AltiVecUnavailable:
- EXCEPTION_PROLOG
-#ifdef CONFIG_ALTIVEC
- bne load_up_altivec /* if from user, just load it up */
-#endif /* CONFIG_ALTIVEC */
- addi r3,r1,STACK_FRAME_OVERHEAD
- EXC_XFER_EE_LITE(0xf20, altivec_unavailable_exception)
-
-#ifdef CONFIG_ALTIVEC
-/* Note that the AltiVec support is closely modeled after the FP
- * support. Changes to one are likely to be applicable to the
- * other! */
-load_up_altivec:
-/*
- * Disable AltiVec for the task which had AltiVec previously,
- * and save its AltiVec registers in its thread_struct.
- * Enables AltiVec for use in the kernel on return.
- * On SMP we know the AltiVec units are free, since we give it up every
- * switch. -- Kumar
- */
- mfmsr r5
- oris r5,r5,MSR_VEC@h
- MTMSRD(r5) /* enable use of AltiVec now */
- isync
-/*
- * For SMP, we don't do lazy AltiVec switching because it just gets too
- * horrendously complex, especially when a task switches from one CPU
- * to another. Instead we call giveup_altivec in switch_to.
- */
-#ifndef CONFIG_SMP
- tophys(r6,0)
- addis r3,r6,last_task_used_altivec@ha
- lwz r4,last_task_used_altivec@l(r3)
- cmpwi 0,r4,0
- beq 1f
- add r4,r4,r6
- addi r4,r4,THREAD /* want THREAD of last_task_used_altivec */
- SAVE_32VRS(0,r10,r4)
- mfvscr vr0
- li r10,THREAD_VSCR
- stvx vr0,r10,r4
- lwz r5,PT_REGS(r4)
- add r5,r5,r6
- lwz r4,_MSR-STACK_FRAME_OVERHEAD(r5)
- lis r10,MSR_VEC@h
- andc r4,r4,r10 /* disable altivec for previous task */
- stw r4,_MSR-STACK_FRAME_OVERHEAD(r5)
-1:
-#endif /* CONFIG_SMP */
- /* enable use of AltiVec after return */
- oris r9,r9,MSR_VEC@h
- mfspr r5,SPRN_SPRG3 /* current task's THREAD (phys) */
- li r4,1
- li r10,THREAD_VSCR
- stw r4,THREAD_USED_VR(r5)
- lvx vr0,r10,r5
- mtvscr vr0
- REST_32VRS(0,r10,r5)
-#ifndef CONFIG_SMP
- subi r4,r5,THREAD
- sub r4,r4,r6
- stw r4,last_task_used_altivec@l(r3)
-#endif /* CONFIG_SMP */
- /* restore registers and return */
- /* we haven't used ctr or xer or lr */
- b fast_exception_return
-
-/*
- * giveup_altivec(tsk)
- * Disable AltiVec for the task given as the argument,
- * and save the AltiVec registers in its thread_struct.
- * Enables AltiVec for use in the kernel on return.
- */
-
- .globl giveup_altivec
-giveup_altivec:
- mfmsr r5
- oris r5,r5,MSR_VEC@h
- SYNC
- MTMSRD(r5) /* enable use of AltiVec now */
- isync
- cmpwi 0,r3,0
- beqlr- /* if no previous owner, done */
- addi r3,r3,THREAD /* want THREAD of task */
- lwz r5,PT_REGS(r3)
- cmpwi 0,r5,0
- SAVE_32VRS(0, r4, r3)
- mfvscr vr0
- li r4,THREAD_VSCR
- stvx vr0,r4,r3
- beq 1f
- lwz r4,_MSR-STACK_FRAME_OVERHEAD(r5)
- lis r3,MSR_VEC@h
- andc r4,r4,r3 /* disable AltiVec for previous task */
- stw r4,_MSR-STACK_FRAME_OVERHEAD(r5)
-1:
-#ifndef CONFIG_SMP
- li r5,0
- lis r4,last_task_used_altivec@ha
- stw r5,last_task_used_altivec@l(r4)
-#endif /* CONFIG_SMP */
- blr
-#endif /* CONFIG_ALTIVEC */
-
-/*
- * This code is jumped to from the startup code to copy
- * the kernel image to physical address 0.
- */
-relocate_kernel:
- addis r9,r26,klimit@ha /* fetch klimit */
- lwz r25,klimit@l(r9)
- addis r25,r25,-KERNELBASE@h
- li r3,0 /* Destination base address */
- 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,L1_CACHE_BYTES/4
- 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
- sync /* additional sync needed on g4 */
- isync
- addi r5,r5,4
- addi r6,r6,4
- blr
-
-#ifdef CONFIG_SMP
- .globl __secondary_start_pmac_0
-__secondary_start_pmac_0:
- /* NB the entries for cpus 0, 1, 2 must each occupy 8 bytes. */
- li r24,0
- b 1f
- li r24,1
- b 1f
- li r24,2
- b 1f
- li r24,3
-1:
- /* on powersurge, we come in here with IR=0 and DR=1, and DBAT 0
- set to map the 0xf0000000 - 0xffffffff region */
- mfmsr r0
- rlwinm r0,r0,0,28,26 /* clear DR (0x10) */
- SYNC
- mtmsr r0
- isync
-
- .globl __secondary_start
-__secondary_start:
- /* Copy some CPU settings from CPU 0 */
- bl __restore_cpu_setup
-
- lis r3,-KERNELBASE@h
- mr r4,r24
- bl call_setup_cpu /* Call setup_cpu for this CPU */
-#ifdef CONFIG_6xx
- lis r3,-KERNELBASE@h
- bl init_idle_6xx
-#endif /* CONFIG_6xx */
-
- /* get current_thread_info and current */
- lis r1,secondary_ti@ha
- tophys(r1,r1)
- lwz r1,secondary_ti@l(r1)
- tophys(r2,r1)
- lwz r2,TI_TASK(r2)
-
- /* stack */
- addi r1,r1,THREAD_SIZE-STACK_FRAME_OVERHEAD
- li r0,0
- tophys(r3,r1)
- stw r0,0(r3)
-
- /* load up the MMU */
- bl load_up_mmu
-
- /* ptr to phys current thread */
- tophys(r4,r2)
- addi r4,r4,THREAD /* phys address of our thread_struct */
- CLR_TOP32(r4)
- mtspr SPRN_SPRG3,r4
- li r3,0
- mtspr SPRN_SPRG2,r3 /* 0 => not in RTAS */
-
- /* enable MMU and jump to start_secondary */
- li r4,MSR_KERNEL
- FIX_SRR1(r4,r5)
- lis r3,start_secondary@h
- ori r3,r3,start_secondary@l
- mtspr SPRN_SRR0,r3
- mtspr SPRN_SRR1,r4
- SYNC
- RFI
-#endif /* CONFIG_SMP */
-
-/*
- * Those generic dummy functions are kept for CPUs not
- * included in CONFIG_6xx
- */
-#if !defined(CONFIG_6xx)
-_GLOBAL(__save_cpu_setup)
- blr
-_GLOBAL(__restore_cpu_setup)
- blr
-#endif /* !defined(CONFIG_6xx) */
-
-
-/*
- * Load stuff into the MMU. Intended to be called with
- * IR=0 and DR=0.
- */
-load_up_mmu:
- sync /* Force all PTE updates to finish */
- isync
- tlbia /* Clear all TLB entries */
- sync /* wait for tlbia/tlbie to finish */
- TLBSYNC /* ... on all CPUs */
- /* Load the SDR1 register (hash table base & size) */
- lis r6,_SDR1@ha
- tophys(r6,r6)
- lwz r6,_SDR1@l(r6)
- mtspr SPRN_SDR1,r6
- li r0,16 /* load up segment register values */
- mtctr r0 /* for context 0 */
- lis r3,0x2000 /* Ku = 1, VSID = 0 */
- li r4,0
-3: mtsrin r3,r4
- addi r3,r3,0x111 /* increment VSID */
- addis r4,r4,0x1000 /* address of next segment */
- bdnz 3b
-
-/* Load the BAT registers with the values set up by MMU_init.
- MMU_init takes care of whether we're on a 601 or not. */
- mfpvr r3
- srwi r3,r3,16
- cmpwi r3,1
- lis r3,BATS@ha
- addi r3,r3,BATS@l
- tophys(r3,r3)
- LOAD_BAT(0,r3,r4,r5)
- LOAD_BAT(1,r3,r4,r5)
- LOAD_BAT(2,r3,r4,r5)
- LOAD_BAT(3,r3,r4,r5)
-
- blr
-
-/*
- * This is where the main kernel code starts.
- */
-start_here:
- /* ptr to current */
- lis r2,init_task@h
- ori r2,r2,init_task@l
- /* Set up for using our exception vectors */
- /* ptr to phys current thread */
- tophys(r4,r2)
- addi r4,r4,THREAD /* init task's THREAD */
- CLR_TOP32(r4)
- mtspr SPRN_SPRG3,r4
- li r3,0
- mtspr SPRN_SPRG2,r3 /* 0 => not in RTAS */
-
- /* stack */
- lis r1,init_thread_union@ha
- addi r1,r1,init_thread_union@l
- li r0,0
- stwu r0,THREAD_SIZE-STACK_FRAME_OVERHEAD(r1)
-/*
- * Do early bootinfo parsing, platform-specific initialization,
- * and set up the MMU.
- */
- mr r3,r31
- mr r4,r30
- mr r5,r29
- mr r6,r28
- mr r7,r27
- bl machine_init
- bl MMU_init
-
-/*
- * Go back to running unmapped so we can load up new values
- * for SDR1 (hash table pointer) and the segment registers
- * and change to using our exception vectors.
- */
- lis r4,2f@h
- ori r4,r4,2f@l
- tophys(r4,r4)
- li r3,MSR_KERNEL & ~(MSR_IR|MSR_DR)
- FIX_SRR1(r3,r5)
- mtspr SPRN_SRR0,r4
- mtspr SPRN_SRR1,r3
- SYNC
- RFI
-/* Load up the kernel context */
-2: bl load_up_mmu
-
-#ifdef CONFIG_BDI_SWITCH
- /* Add helper information for the Abatron bdiGDB debugger.
- * We do this here because we know the mmu is disabled, and
- * will be enabled for real in just a few instructions.
- */
- lis r5, abatron_pteptrs@h
- ori r5, r5, abatron_pteptrs@l
- stw r5, 0xf0(r0) /* This much match your Abatron config */
- lis r6, swapper_pg_dir@h
- ori r6, r6, swapper_pg_dir@l
- tophys(r5, r5)
- stw r6, 0(r5)
-#endif /* CONFIG_BDI_SWITCH */
-
-/* Now turn on the MMU for real! */
- li r4,MSR_KERNEL
- FIX_SRR1(r4,r5)
- lis r3,start_kernel@h
- ori r3,r3,start_kernel@l
- mtspr SPRN_SRR0,r3
- mtspr SPRN_SRR1,r4
- SYNC
- RFI
-
-/*
- * Set up the segment registers for a new context.
- */
-_GLOBAL(set_context)
- mulli r3,r3,897 /* multiply context by skew factor */
- rlwinm r3,r3,4,8,27 /* VSID = (context & 0xfffff) << 4 */
- addis r3,r3,0x6000 /* Set Ks, Ku bits */
- li r0,NUM_USER_SEGMENTS
- mtctr r0
-
-#ifdef CONFIG_BDI_SWITCH
- /* Context switch the PTE pointer for the Abatron BDI2000.
- * The PGDIR is passed as second argument.
- */
- lis r5, KERNELBASE@h
- lwz r5, 0xf0(r5)
- stw r4, 0x4(r5)
-#endif
- li r4,0
- isync
-3:
- mtsrin r3,r4
- addi r3,r3,0x111 /* next VSID */
- rlwinm r3,r3,0,8,3 /* clear out any overflow from VSID field */
- addis r4,r4,0x1000 /* address of next segment */
- bdnz 3b
- sync
- isync
- 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:
- li r10,0
- mfspr r9,SPRN_PVR
- rlwinm r9,r9,16,16,31 /* r9 = 1 for 601, 4 for 604 */
- cmpwi r9, 1
- beq 1f
-
- mtspr SPRN_DBAT0U,r10
- mtspr SPRN_DBAT0L,r10
- mtspr SPRN_DBAT1U,r10
- mtspr SPRN_DBAT1L,r10
- mtspr SPRN_DBAT2U,r10
- mtspr SPRN_DBAT2L,r10
- mtspr SPRN_DBAT3U,r10
- mtspr SPRN_DBAT3L,r10
-1:
- mtspr SPRN_IBAT0U,r10
- mtspr SPRN_IBAT0L,r10
- mtspr SPRN_IBAT1U,r10
- mtspr SPRN_IBAT1L,r10
- mtspr SPRN_IBAT2U,r10
- mtspr SPRN_IBAT2L,r10
- mtspr SPRN_IBAT3U,r10
- mtspr SPRN_IBAT3L,r10
-BEGIN_FTR_SECTION
- /* Here's a tweak: at this point, CPU setup have
- * not been called yet, so HIGH_BAT_EN may not be
- * set in HID0 for the 745x processors. However, it
- * seems that doesn't affect our ability to actually
- * write to these SPRs.
- */
- mtspr SPRN_DBAT4U,r10
- mtspr SPRN_DBAT4L,r10
- mtspr SPRN_DBAT5U,r10
- mtspr SPRN_DBAT5L,r10
- mtspr SPRN_DBAT6U,r10
- mtspr SPRN_DBAT6L,r10
- mtspr SPRN_DBAT7U,r10
- mtspr SPRN_DBAT7L,r10
- mtspr SPRN_IBAT4U,r10
- mtspr SPRN_IBAT4L,r10
- mtspr SPRN_IBAT5U,r10
- mtspr SPRN_IBAT5L,r10
- mtspr SPRN_IBAT6U,r10
- mtspr SPRN_IBAT6L,r10
- mtspr SPRN_IBAT7U,r10
- mtspr SPRN_IBAT7L,r10
-END_FTR_SECTION_IFSET(CPU_FTR_HAS_HIGH_BATS)
- blr
-
-flush_tlbs:
- lis r10, 0x40
-1: addic. r10, r10, -0x1000
- tlbie r10
- blt 1b
- sync
- blr
-
-mmu_off:
- addi r4, r3, __after_mmu_off - _start
- mfmsr r3
- andi. r0,r3,MSR_DR|MSR_IR /* MMU enabled? */
- beqlr
- andc r3,r3,r0
- mtspr SPRN_SRR0,r4
- mtspr SPRN_SRR1,r3
- sync
- RFI
-
-/*
- * Use the first pair of BAT registers to map the 1st 16MB
- * of RAM to KERNELBASE. From this point on we can't safely
- * call OF any more.
- */
-initial_bats:
- lis r11,KERNELBASE@h
- mfspr r9,SPRN_PVR
- rlwinm r9,r9,16,16,31 /* r9 = 1 for 601, 4 for 604 */
- cmpwi 0,r9,1
- bne 4f
- ori r11,r11,4 /* set up BAT registers for 601 */
- li r8,0x7f /* valid, block length = 8MB */
- oris r9,r11,0x800000@h /* set up BAT reg for 2nd 8M */
- oris r10,r8,0x800000@h /* set up BAT reg for 2nd 8M */
- mtspr SPRN_IBAT0U,r11 /* N.B. 601 has valid bit in */
- mtspr SPRN_IBAT0L,r8 /* lower BAT register */
- mtspr SPRN_IBAT1U,r9
- mtspr SPRN_IBAT1L,r10
- isync
- blr
-
-4: tophys(r8,r11)
-#ifdef CONFIG_SMP
- ori r8,r8,0x12 /* R/W access, M=1 */
-#else
- ori r8,r8,2 /* R/W access */
-#endif /* CONFIG_SMP */
- ori r11,r11,BL_256M<<2|0x2 /* set up BAT registers for 604 */
-
- mtspr SPRN_DBAT0L,r8 /* N.B. 6xx (not 601) have valid */
- mtspr SPRN_DBAT0U,r11 /* bit in upper BAT register */
- mtspr SPRN_IBAT0L,r8
- mtspr SPRN_IBAT0U,r11
- isync
- blr
-
-#ifdef CONFIG_BOOTX_TEXT
-setup_disp_bat:
- /*
- * setup the display bat prepared for us in prom.c
- */
- mflr r8
- bl reloc_offset
- mtlr r8
- addis r8,r3,disp_BAT@ha
- addi r8,r8,disp_BAT@l
- lwz r11,0(r8)
- lwz r8,4(r8)
- mfspr r9,SPRN_PVR
- rlwinm r9,r9,16,16,31 /* r9 = 1 for 601, 4 for 604 */
- cmpwi 0,r9,1
- beq 1f
- mtspr SPRN_DBAT3L,r8
- mtspr SPRN_DBAT3U,r11
- blr
-1: mtspr SPRN_IBAT3L,r8
- mtspr SPRN_IBAT3U,r11
- blr
-
-#endif /* defined(CONFIG_BOOTX_TEXT) */
-
-#ifdef CONFIG_8260
-/* Jump into the system reset for the rom.
- * We first disable the MMU, and then jump to the ROM reset address.
- *
- * r3 is the board info structure, r4 is the location for starting.
- * I use this for building a small kernel that can load other kernels,
- * rather than trying to write or rely on a rom monitor that can tftp load.
- */
- .globl m8260_gorom
-m8260_gorom:
- mfmsr r0
- rlwinm r0,r0,0,17,15 /* clear MSR_EE in r0 */
- sync
- mtmsr r0
- sync
- mfspr r11, SPRN_HID0
- lis r10, 0
- ori r10,r10,HID0_ICE|HID0_DCE
- andc r11, r11, r10
- mtspr SPRN_HID0, r11
- isync
- li r5, MSR_ME|MSR_RI
- lis r6,2f@h
- addis r6,r6,-KERNELBASE@h
- ori r6,r6,2f@l
- mtspr SPRN_SRR0,r6
- mtspr SPRN_SRR1,r5
- isync
- sync
- rfi
-2:
- mtlr r4
- blr
-#endif
-
-
-/*
- * 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
- .globl sdata
-sdata:
- .globl empty_zero_page
-empty_zero_page:
- .space 4096
-
- .globl swapper_pg_dir
-swapper_pg_dir:
- .space 4096
-
-/*
- * This space gets a copy of optional info passed to us by the bootstrap
- * Used to pass parameters into the kernel like root=/dev/sda1, etc.
- */
- .globl cmd_line
-cmd_line:
- .space 512
-
- .globl intercept_table
-intercept_table:
- .long 0, 0, i0x200, i0x300, i0x400, 0, i0x600, i0x700
- .long i0x800, 0, 0, 0, 0, i0xd00, 0, 0
- .long 0, 0, 0, i0x1300, 0, 0, 0, 0
- .long 0, 0, 0, 0, 0, 0, 0, 0
- .long 0, 0, 0, 0, 0, 0, 0, 0
- .long 0, 0, 0, 0, 0, 0, 0, 0
-
-/* Room for two PTE pointers, usually the kernel and current user pointers
- * to their respective root page table.
- */
-abatron_pteptrs:
- .space 8
diff --git a/arch/ppc/kernel/head_44x.S b/arch/ppc/kernel/head_44x.S
deleted file mode 100644
index ebb5a403829f..000000000000
--- a/arch/ppc/kernel/head_44x.S
+++ /dev/null
@@ -1,769 +0,0 @@
-/*
- * Kernel execution entry point code.
- *
- * 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.
- * Copyright 2000 MontaVista Software Inc.
- * PPC405 modifications
- * PowerPC 403GCX/405GP modifications.
- * Author: MontaVista Software, Inc.
- * frank_rowand@mvista.com or source@mvista.com
- * debbie_chu@mvista.com
- * Copyright 2002-2005 MontaVista Software, Inc.
- * PowerPC 44x support, Matt Porter <mporter@kernel.crashing.org>
- *
- * 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 <asm/processor.h>
-#include <asm/page.h>
-#include <asm/mmu.h>
-#include <asm/pgtable.h>
-#include <asm/ibm4xx.h>
-#include <asm/ibm44x.h>
-#include <asm/cputable.h>
-#include <asm/thread_info.h>
-#include <asm/ppc_asm.h>
-#include <asm/asm-offsets.h>
-#include "head_booke.h"
-
-
-/* As with the other PowerPC ports, it is expected that when code
- * execution begins here, the following registers contain valid, yet
- * optional, information:
- *
- * r3 - Board info structure pointer (DRAM, frequency, MAC address, etc.)
- * 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=128")
- * r7 - End of kernel command line string
- *
- */
- .text
-_GLOBAL(_stext)
-_GLOBAL(_start)
- /*
- * Reserve a word at a fixed location to store the address
- * of abatron_pteptrs
- */
- nop
-/*
- * Save parameters we are passed
- */
- mr r31,r3
- mr r30,r4
- mr r29,r5
- mr r28,r6
- mr r27,r7
- li r24,0 /* CPU number */
-
-/*
- * Set up the initial MMU state
- *
- * We are still executing code at the virtual address
- * mappings set by the firmware for the base of RAM.
- *
- * We first invalidate all TLB entries but the one
- * we are running from. We then load the KERNELBASE
- * mappings so we can begin to use kernel addresses
- * natively and so the interrupt vector locations are
- * permanently pinned (necessary since Book E
- * implementations always have translation enabled).
- *
- * TODO: Use the known TLB entry we are running from to
- * determine which physical region we are located
- * in. This can be used to determine where in RAM
- * (on a shared CPU system) or PCI memory space
- * (on a DRAMless system) we are located.
- * For now, we assume a perfect world which means
- * we are located at the base of DRAM (physical 0).
- */
-
-/*
- * Search TLB for entry that we are currently using.
- * Invalidate all entries but the one we are using.
- */
- /* Load our current PID->MMUCR TID and MSR IS->MMUCR STS */
- mfspr r3,SPRN_PID /* Get PID */
- mfmsr r4 /* Get MSR */
- andi. r4,r4,MSR_IS@l /* TS=1? */
- beq wmmucr /* If not, leave STS=0 */
- oris r3,r3,PPC44x_MMUCR_STS@h /* Set STS=1 */
-wmmucr: mtspr SPRN_MMUCR,r3 /* Put MMUCR */
- sync
-
- bl invstr /* Find our address */
-invstr: mflr r5 /* Make it accessible */
- tlbsx r23,0,r5 /* Find entry we are in */
- li r4,0 /* Start at TLB entry 0 */
- li r3,0 /* Set PAGEID inval value */
-1: cmpw r23,r4 /* Is this our entry? */
- beq skpinv /* If so, skip the inval */
- tlbwe r3,r4,PPC44x_TLB_PAGEID /* If not, inval the entry */
-skpinv: addi r4,r4,1 /* Increment */
- cmpwi r4,64 /* Are we done? */
- bne 1b /* If not, repeat */
- isync /* If so, context change */
-
-/*
- * Configure and load pinned entry into TLB slot 63.
- */
-
- lis r3,KERNELBASE@h /* Load the kernel virtual address */
- ori r3,r3,KERNELBASE@l
-
- /* Kernel is at the base of RAM */
- li r4, 0 /* Load the kernel physical address */
-
- /* Load the kernel PID = 0 */
- li r0,0
- mtspr SPRN_PID,r0
- sync
-
- /* Initialize MMUCR */
- li r5,0
- mtspr SPRN_MMUCR,r5
- sync
-
- /* pageid fields */
- clrrwi r3,r3,10 /* Mask off the effective page number */
- ori r3,r3,PPC44x_TLB_VALID | PPC44x_TLB_256M
-
- /* xlat fields */
- clrrwi r4,r4,10 /* Mask off the real page number */
- /* ERPN is 0 for first 4GB page */
-
- /* attrib fields */
- /* Added guarded bit to protect against speculative loads/stores */
- li r5,0
- ori r5,r5,(PPC44x_TLB_SW | PPC44x_TLB_SR | PPC44x_TLB_SX | PPC44x_TLB_G)
-
- li r0,63 /* TLB slot 63 */
-
- tlbwe r3,r0,PPC44x_TLB_PAGEID /* Load the pageid fields */
- tlbwe r4,r0,PPC44x_TLB_XLAT /* Load the translation fields */
- tlbwe r5,r0,PPC44x_TLB_ATTRIB /* Load the attrib/access fields */
-
- /* Force context change */
- mfmsr r0
- mtspr SPRN_SRR1, r0
- lis r0,3f@h
- ori r0,r0,3f@l
- mtspr SPRN_SRR0,r0
- sync
- rfi
-
- /* If necessary, invalidate original entry we used */
-3: cmpwi r23,63
- beq 4f
- li r6,0
- tlbwe r6,r23,PPC44x_TLB_PAGEID
- isync
-
-4:
-#ifdef CONFIG_SERIAL_TEXT_DEBUG
- /*
- * Add temporary UART mapping for early debug.
- * We can map UART registers wherever we want as long as they don't
- * interfere with other system mappings (e.g. with pinned entries).
- * For an example of how we handle this - see ocotea.h. --ebs
- */
- /* pageid fields */
- lis r3,UART0_IO_BASE@h
- ori r3,r3,PPC44x_TLB_VALID | PPC44x_TLB_4K
-
- /* xlat fields */
- lis r4,UART0_PHYS_IO_BASE@h /* RPN depends on SoC */
-#ifdef UART0_PHYS_ERPN
- ori r4,r4,UART0_PHYS_ERPN /* Add ERPN if above 4GB */
-#endif
-
- /* attrib fields */
- li r5,0
- ori r5,r5,(PPC44x_TLB_SW | PPC44x_TLB_SR | PPC44x_TLB_I | PPC44x_TLB_G)
-
- li r0,62 /* TLB slot 62 */
-
- tlbwe r3,r0,PPC44x_TLB_PAGEID /* Load the pageid fields */
- tlbwe r4,r0,PPC44x_TLB_XLAT /* Load the translation fields */
- tlbwe r5,r0,PPC44x_TLB_ATTRIB /* Load the attrib/access fields */
-
- /* Force context change */
- isync
-#endif /* CONFIG_SERIAL_TEXT_DEBUG */
-
- /* Establish the interrupt vector offsets */
- SET_IVOR(0, CriticalInput);
- SET_IVOR(1, MachineCheck);
- SET_IVOR(2, DataStorage);
- SET_IVOR(3, InstructionStorage);
- SET_IVOR(4, ExternalInput);
- SET_IVOR(5, Alignment);
- SET_IVOR(6, Program);
- SET_IVOR(7, FloatingPointUnavailable);
- SET_IVOR(8, SystemCall);
- SET_IVOR(9, AuxillaryProcessorUnavailable);
- SET_IVOR(10, Decrementer);
- SET_IVOR(11, FixedIntervalTimer);
- SET_IVOR(12, WatchdogTimer);
- SET_IVOR(13, DataTLBError);
- SET_IVOR(14, InstructionTLBError);
- SET_IVOR(15, Debug);
-
- /* Establish the interrupt vector base */
- lis r4,interrupt_base@h /* IVPR only uses the high 16-bits */
- mtspr SPRN_IVPR,r4
-
- /*
- * This is where the main kernel code starts.
- */
-
- /* ptr to current */
- lis r2,init_task@h
- ori r2,r2,init_task@l
-
- /* ptr to current thread */
- addi r4,r2,THREAD /* init task's THREAD */
- mtspr SPRN_SPRG3,r4
-
- /* stack */
- lis r1,init_thread_union@h
- ori r1,r1,init_thread_union@l
- li r0,0
- stwu r0,THREAD_SIZE-STACK_FRAME_OVERHEAD(r1)
-
- bl early_init
-
-/*
- * Decide what sort of machine this is and initialize the MMU.
- */
- mr r3,r31
- mr r4,r30
- mr r5,r29
- mr r6,r28
- mr r7,r27
- bl machine_init
- bl MMU_init
-
- /* Setup PTE pointers for the Abatron bdiGDB */
- lis r6, swapper_pg_dir@h
- ori r6, r6, swapper_pg_dir@l
- lis r5, abatron_pteptrs@h
- ori r5, r5, abatron_pteptrs@l
- lis r4, KERNELBASE@h
- ori r4, r4, KERNELBASE@l
- stw r5, 0(r4) /* Save abatron_pteptrs at a fixed location */
- stw r6, 0(r5)
-
- /* Let's move on */
- lis r4,start_kernel@h
- ori r4,r4,start_kernel@l
- lis r3,MSR_KERNEL@h
- ori r3,r3,MSR_KERNEL@l
- mtspr SPRN_SRR0,r4
- mtspr SPRN_SRR1,r3
- rfi /* change context and jump to start_kernel */
-
-/*
- * Interrupt vector entry code
- *
- * The Book E MMUs are always on so we don't need to handle
- * interrupts in real mode as with previous PPC processors. In
- * this case we handle interrupts in the kernel virtual address
- * space.
- *
- * Interrupt vectors are dynamically placed relative to the
- * interrupt prefix as determined by the address of interrupt_base.
- * The interrupt vectors offsets are programmed using the labels
- * for each interrupt vector entry.
- *
- * Interrupt vectors must be aligned on a 16 byte boundary.
- * We align on a 32 byte cache line boundary for good measure.
- */
-
-interrupt_base:
- /* Critical Input Interrupt */
- CRITICAL_EXCEPTION(0x0100, CriticalInput, unknown_exception)
-
- /* Machine Check Interrupt */
-#ifdef CONFIG_440A
- MCHECK_EXCEPTION(0x0200, MachineCheck, machine_check_exception)
-#else
- CRITICAL_EXCEPTION(0x0200, MachineCheck, machine_check_exception)
-#endif
-
- /* Data Storage Interrupt */
- START_EXCEPTION(DataStorage)
- mtspr SPRN_SPRG0, r10 /* Save some working registers */
- mtspr SPRN_SPRG1, r11
- mtspr SPRN_SPRG4W, r12
- mtspr SPRN_SPRG5W, r13
- mfcr r11
- mtspr SPRN_SPRG7W, r11
-
- /*
- * Check if it was a store fault, if not then bail
- * because a user tried to access a kernel or
- * read-protected page. Otherwise, get the
- * offending address and handle it.
- */
- mfspr r10, SPRN_ESR
- andis. r10, r10, ESR_ST@h
- beq 2f
-
- mfspr r10, SPRN_DEAR /* Get faulting address */
-
- /* If we are faulting a kernel address, we have to use the
- * kernel page tables.
- */
- lis r11, TASK_SIZE@h
- cmplw r10, r11
- blt+ 3f
- lis r11, swapper_pg_dir@h
- ori r11, r11, swapper_pg_dir@l
-
- mfspr r12,SPRN_MMUCR
- rlwinm r12,r12,0,0,23 /* Clear TID */
-
- b 4f
-
- /* Get the PGD for the current thread */
-3:
- mfspr r11,SPRN_SPRG3
- lwz r11,PGDIR(r11)
-
- /* Load PID into MMUCR TID */
- mfspr r12,SPRN_MMUCR /* Get MMUCR */
- mfspr r13,SPRN_PID /* Get PID */
- rlwimi r12,r13,0,24,31 /* Set TID */
-
-4:
- mtspr SPRN_MMUCR,r12
-
- rlwinm r12, r10, 13, 19, 29 /* Compute pgdir/pmd offset */
- lwzx r11, r12, r11 /* Get pgd/pmd entry */
- rlwinm. r12, r11, 0, 0, 20 /* Extract pt base address */
- beq 2f /* Bail if no table */
-
- rlwimi r12, r10, 23, 20, 28 /* Compute pte address */
- lwz r11, 4(r12) /* Get pte entry */
-
- andi. r13, r11, _PAGE_RW /* Is it writeable? */
- beq 2f /* Bail if not */
-
- /* Update 'changed'.
- */
- ori r11, r11, _PAGE_DIRTY|_PAGE_ACCESSED|_PAGE_HWWRITE
- stw r11, 4(r12) /* Update Linux page table */
-
- li r13, PPC44x_TLB_SR@l /* Set SR */
- rlwimi r13, r11, 29, 29, 29 /* SX = _PAGE_HWEXEC */
- rlwimi r13, r11, 0, 30, 30 /* SW = _PAGE_RW */
- rlwimi r13, r11, 29, 28, 28 /* UR = _PAGE_USER */
- rlwimi r12, r11, 31, 26, 26 /* (_PAGE_USER>>1)->r12 */
- rlwimi r12, r11, 29, 30, 30 /* (_PAGE_USER>>3)->r12 */
- and r12, r12, r11 /* HWEXEC/RW & USER */
- rlwimi r13, r12, 0, 26, 26 /* UX = HWEXEC & USER */
- rlwimi r13, r12, 3, 27, 27 /* UW = RW & USER */
-
- rlwimi r11,r13,0,26,31 /* Insert static perms */
-
- rlwinm r11,r11,0,20,15 /* Clear U0-U3 */
-
- /* find the TLB index that caused the fault. It has to be here. */
- tlbsx r10, 0, r10
-
- tlbwe r11, r10, PPC44x_TLB_ATTRIB /* Write ATTRIB */
-
- /* Done...restore registers and get out of here.
- */
- mfspr r11, SPRN_SPRG7R
- mtcr r11
- mfspr r13, SPRN_SPRG5R
- mfspr r12, SPRN_SPRG4R
-
- mfspr r11, SPRN_SPRG1
- mfspr r10, SPRN_SPRG0
- rfi /* Force context change */
-
-2:
- /*
- * The bailout. Restore registers to pre-exception conditions
- * and call the heavyweights to help us out.
- */
- mfspr r11, SPRN_SPRG7R
- mtcr r11
- mfspr r13, SPRN_SPRG5R
- mfspr r12, SPRN_SPRG4R
-
- mfspr r11, SPRN_SPRG1
- mfspr r10, SPRN_SPRG0
- b data_access
-
- /* Instruction Storage Interrupt */
- INSTRUCTION_STORAGE_EXCEPTION
-
- /* External Input Interrupt */
- EXCEPTION(0x0500, ExternalInput, do_IRQ, EXC_XFER_LITE)
-
- /* Alignment Interrupt */
- ALIGNMENT_EXCEPTION
-
- /* Program Interrupt */
- PROGRAM_EXCEPTION
-
- /* Floating Point Unavailable Interrupt */
-#ifdef CONFIG_PPC_FPU
- FP_UNAVAILABLE_EXCEPTION
-#else
- EXCEPTION(0x2010, FloatingPointUnavailable, unknown_exception, EXC_XFER_EE)
-#endif
-
- /* System Call Interrupt */
- START_EXCEPTION(SystemCall)
- NORMAL_EXCEPTION_PROLOG
- EXC_XFER_EE_LITE(0x0c00, DoSyscall)
-
- /* Auxillary Processor Unavailable Interrupt */
- EXCEPTION(0x2020, AuxillaryProcessorUnavailable, unknown_exception, EXC_XFER_EE)
-
- /* Decrementer Interrupt */
- DECREMENTER_EXCEPTION
-
- /* Fixed Internal Timer Interrupt */
- /* TODO: Add FIT support */
- EXCEPTION(0x1010, FixedIntervalTimer, unknown_exception, EXC_XFER_EE)
-
- /* Watchdog Timer Interrupt */
- /* TODO: Add watchdog support */
-#ifdef CONFIG_BOOKE_WDT
- CRITICAL_EXCEPTION(0x1020, WatchdogTimer, WatchdogException)
-#else
- CRITICAL_EXCEPTION(0x1020, WatchdogTimer, unknown_exception)
-#endif
-
- /* Data TLB Error Interrupt */
- START_EXCEPTION(DataTLBError)
- mtspr SPRN_SPRG0, r10 /* Save some working registers */
- mtspr SPRN_SPRG1, r11
- mtspr SPRN_SPRG4W, r12
- mtspr SPRN_SPRG5W, r13
- mfcr r11
- mtspr SPRN_SPRG7W, r11
- mfspr r10, SPRN_DEAR /* Get faulting address */
-
- /* If we are faulting a kernel address, we have to use the
- * kernel page tables.
- */
- lis r11, TASK_SIZE@h
- cmplw r10, r11
- blt+ 3f
- lis r11, swapper_pg_dir@h
- ori r11, r11, swapper_pg_dir@l
-
- mfspr r12,SPRN_MMUCR
- rlwinm r12,r12,0,0,23 /* Clear TID */
-
- b 4f
-
- /* Get the PGD for the current thread */
-3:
- mfspr r11,SPRN_SPRG3
- lwz r11,PGDIR(r11)
-
- /* Load PID into MMUCR TID */
- mfspr r12,SPRN_MMUCR
- mfspr r13,SPRN_PID /* Get PID */
- rlwimi r12,r13,0,24,31 /* Set TID */
-
-4:
- mtspr SPRN_MMUCR,r12
-
- rlwinm r12, r10, 13, 19, 29 /* Compute pgdir/pmd offset */
- lwzx r11, r12, r11 /* Get pgd/pmd entry */
- rlwinm. r12, r11, 0, 0, 20 /* Extract pt base address */
- beq 2f /* Bail if no table */
-
- rlwimi r12, r10, 23, 20, 28 /* Compute pte address */
- lwz r11, 4(r12) /* Get pte entry */
- andi. r13, r11, _PAGE_PRESENT /* Is the page present? */
- beq 2f /* Bail if not present */
-
- ori r11, r11, _PAGE_ACCESSED
- stw r11, 4(r12)
-
- /* Jump to common tlb load */
- b finish_tlb_load
-
-2:
- /* The bailout. Restore registers to pre-exception conditions
- * and call the heavyweights to help us out.
- */
- mfspr r11, SPRN_SPRG7R
- mtcr r11
- mfspr r13, SPRN_SPRG5R
- mfspr r12, SPRN_SPRG4R
- mfspr r11, SPRN_SPRG1
- mfspr r10, SPRN_SPRG0
- b data_access
-
- /* Instruction TLB Error Interrupt */
- /*
- * Nearly the same as above, except we get our
- * information from different registers and bailout
- * to a different point.
- */
- START_EXCEPTION(InstructionTLBError)
- mtspr SPRN_SPRG0, r10 /* Save some working registers */
- mtspr SPRN_SPRG1, r11
- mtspr SPRN_SPRG4W, r12
- mtspr SPRN_SPRG5W, r13
- mfcr r11
- mtspr SPRN_SPRG7W, r11
- mfspr r10, SPRN_SRR0 /* Get faulting address */
-
- /* If we are faulting a kernel address, we have to use the
- * kernel page tables.
- */
- lis r11, TASK_SIZE@h
- cmplw r10, r11
- blt+ 3f
- lis r11, swapper_pg_dir@h
- ori r11, r11, swapper_pg_dir@l
-
- mfspr r12,SPRN_MMUCR
- rlwinm r12,r12,0,0,23 /* Clear TID */
-
- b 4f
-
- /* Get the PGD for the current thread */
-3:
- mfspr r11,SPRN_SPRG3
- lwz r11,PGDIR(r11)
-
- /* Load PID into MMUCR TID */
- mfspr r12,SPRN_MMUCR
- mfspr r13,SPRN_PID /* Get PID */
- rlwimi r12,r13,0,24,31 /* Set TID */
-
-4:
- mtspr SPRN_MMUCR,r12
-
- rlwinm r12, r10, 13, 19, 29 /* Compute pgdir/pmd offset */
- lwzx r11, r12, r11 /* Get pgd/pmd entry */
- rlwinm. r12, r11, 0, 0, 20 /* Extract pt base address */
- beq 2f /* Bail if no table */
-
- rlwimi r12, r10, 23, 20, 28 /* Compute pte address */
- lwz r11, 4(r12) /* Get pte entry */
- andi. r13, r11, _PAGE_PRESENT /* Is the page present? */
- beq 2f /* Bail if not present */
-
- ori r11, r11, _PAGE_ACCESSED
- stw r11, 4(r12)
-
- /* Jump to common TLB load point */
- b finish_tlb_load
-
-2:
- /* The bailout. Restore registers to pre-exception conditions
- * and call the heavyweights to help us out.
- */
- mfspr r11, SPRN_SPRG7R
- mtcr r11
- mfspr r13, SPRN_SPRG5R
- mfspr r12, SPRN_SPRG4R
- mfspr r11, SPRN_SPRG1
- mfspr r10, SPRN_SPRG0
- b InstructionStorage
-
- /* Debug Interrupt */
- DEBUG_EXCEPTION
-
-/*
- * Local functions
- */
- /*
- * Data TLB exceptions will bail out to this point
- * if they can't resolve the lightweight TLB fault.
- */
-data_access:
- NORMAL_EXCEPTION_PROLOG
- mfspr r5,SPRN_ESR /* Grab the ESR, save it, pass arg3 */
- stw r5,_ESR(r11)
- mfspr r4,SPRN_DEAR /* Grab the DEAR, save it, pass arg2 */
- EXC_XFER_EE_LITE(0x0300, handle_page_fault)
-
-/*
-
- * Both the instruction and data TLB miss get to this
- * point to load the TLB.
- * r10 - EA of fault
- * r11 - available to use
- * r12 - Pointer to the 64-bit PTE
- * r13 - available to use
- * MMUCR - loaded with proper value when we get here
- * Upon exit, we reload everything and RFI.
- */
-finish_tlb_load:
- /*
- * We set execute, because we don't have the granularity to
- * properly set this at the page level (Linux problem).
- * If shared is set, we cause a zero PID->TID load.
- * Many of these bits are software only. Bits we don't set
- * here we (properly should) assume have the appropriate value.
- */
-
- /* Load the next available TLB index */
- lis r13, tlb_44x_index@ha
- lwz r13, tlb_44x_index@l(r13)
- /* Load the TLB high watermark */
- lis r11, tlb_44x_hwater@ha
- lwz r11, tlb_44x_hwater@l(r11)
-
- /* Increment, rollover, and store TLB index */
- addi r13, r13, 1
- cmpw 0, r13, r11 /* reserve entries */
- ble 7f
- li r13, 0
-7:
- /* Store the next available TLB index */
- lis r11, tlb_44x_index@ha
- stw r13, tlb_44x_index@l(r11)
-
- lwz r11, 0(r12) /* Get MS word of PTE */
- lwz r12, 4(r12) /* Get LS word of PTE */
- rlwimi r11, r12, 0, 0 , 19 /* Insert RPN */
- tlbwe r11, r13, PPC44x_TLB_XLAT /* Write XLAT */
-
- /*
- * Create PAGEID. This is the faulting address,
- * page size, and valid flag.
- */
- li r11, PPC44x_TLB_VALID | PPC44x_TLB_4K
- rlwimi r10, r11, 0, 20, 31 /* Insert valid and page size */
- tlbwe r10, r13, PPC44x_TLB_PAGEID /* Write PAGEID */
-
- li r10, PPC44x_TLB_SR@l /* Set SR */
- rlwimi r10, r12, 0, 30, 30 /* Set SW = _PAGE_RW */
- rlwimi r10, r12, 29, 29, 29 /* SX = _PAGE_HWEXEC */
- rlwimi r10, r12, 29, 28, 28 /* UR = _PAGE_USER */
- rlwimi r11, r12, 31, 26, 26 /* (_PAGE_USER>>1)->r12 */
- and r11, r12, r11 /* HWEXEC & USER */
- rlwimi r10, r11, 0, 26, 26 /* UX = HWEXEC & USER */
-
- rlwimi r12, r10, 0, 26, 31 /* Insert static perms */
- rlwinm r12, r12, 0, 20, 15 /* Clear U0-U3 */
- tlbwe r12, r13, PPC44x_TLB_ATTRIB /* Write ATTRIB */
-
- /* Done...restore registers and get out of here.
- */
- mfspr r11, SPRN_SPRG7R
- mtcr r11
- mfspr r13, SPRN_SPRG5R
- mfspr r12, SPRN_SPRG4R
- mfspr r11, SPRN_SPRG1
- mfspr r10, SPRN_SPRG0
- rfi /* Force context change */
-
-/*
- * Global functions
- */
-
-/*
- * extern void giveup_altivec(struct task_struct *prev)
- *
- * The 44x core does not have an AltiVec unit.
- */
-_GLOBAL(giveup_altivec)
- blr
-
-/*
- * extern void giveup_fpu(struct task_struct *prev)
- *
- * The 44x core does not have an FPU.
- */
-#ifndef CONFIG_PPC_FPU
-_GLOBAL(giveup_fpu)
- blr
-#endif
-
-/*
- * extern void abort(void)
- *
- * At present, this routine just applies a system reset.
- */
-_GLOBAL(abort)
- mfspr r13,SPRN_DBCR0
- oris r13,r13,DBCR0_RST_SYSTEM@h
- mtspr SPRN_DBCR0,r13
-
-_GLOBAL(set_context)
-
-#ifdef CONFIG_BDI_SWITCH
- /* Context switch the PTE pointer for the Abatron BDI2000.
- * The PGDIR is the second parameter.
- */
- lis r5, abatron_pteptrs@h
- ori r5, r5, abatron_pteptrs@l
- stw r4, 0x4(r5)
-#endif
- mtspr SPRN_PID,r3
- isync /* Force context change */
- 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
- .align 12
- .globl sdata
-sdata:
- .globl empty_zero_page
-empty_zero_page:
- .space 4096
-
-/*
- * To support >32-bit physical addresses, we use an 8KB pgdir.
- */
- .globl swapper_pg_dir
-swapper_pg_dir:
- .space 8192
-
-/* Reserved 4k for the critical exception stack & 4k for the machine
- * check stack per CPU for kernel mode exceptions */
- .section .bss
- .align 12
-exception_stack_bottom:
- .space BOOKE_EXCEPTION_STACK_SIZE
- .globl exception_stack_top
-exception_stack_top:
-
-/*
- * 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.
- */
- .globl cmd_line
-cmd_line:
- .space 512
-
-/*
- * Room for two PTE pointers, usually the kernel and current user pointers
- * to their respective root page table.
- */
-abatron_pteptrs:
- .space 8
diff --git a/arch/ppc/kernel/head_4xx.S b/arch/ppc/kernel/head_4xx.S
deleted file mode 100644
index 51da157a629e..000000000000
--- a/arch/ppc/kernel/head_4xx.S
+++ /dev/null
@@ -1,1021 +0,0 @@
-/*
- * 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.
- * Copyright 2000 MontaVista Software Inc.
- * PPC405 modifications
- * PowerPC 403GCX/405GP modifications.
- * Author: MontaVista Software, Inc.
- * frank_rowand@mvista.com or source@mvista.com
- * debbie_chu@mvista.com
- *
- *
- * 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 <asm/processor.h>
-#include <asm/page.h>
-#include <asm/mmu.h>
-#include <asm/pgtable.h>
-#include <asm/ibm4xx.h>
-#include <asm/cputable.h>
-#include <asm/thread_info.h>
-#include <asm/ppc_asm.h>
-#include <asm/asm-offsets.h>
-
-/* As with the other PowerPC ports, it is expected that when code
- * execution begins here, the following registers contain valid, yet
- * optional, information:
- *
- * r3 - Board info structure pointer (DRAM, frequency, MAC address, etc.)
- * 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
- *
- * This is all going to change RSN when we add bi_recs....... -- Dan
- */
- .text
-_GLOBAL(_stext)
-_GLOBAL(_start)
-
- /* Save parameters we are passed.
- */
- mr r31,r3
- mr r30,r4
- mr r29,r5
- mr r28,r6
- mr r27,r7
-
- /* We have to turn on the MMU right away so we get cache modes
- * set correctly.
- */
- bl initial_mmu
-
-/* We now have the lower 16 Meg mapped into TLB entries, and the caches
- * ready to work.
- */
-turn_on_mmu:
- lis r0,MSR_KERNEL@h
- ori r0,r0,MSR_KERNEL@l
- mtspr SPRN_SRR1,r0
- lis r0,start_here@h
- ori r0,r0,start_here@l
- mtspr SPRN_SRR0,r0
- SYNC
- rfi /* enables MMU */
- b . /* prevent prefetch past rfi */
-
-/*
- * This area is used for temporarily saving registers during the
- * critical exception prolog.
- */
- . = 0xc0
-crit_save:
-_GLOBAL(crit_r10)
- .space 4
-_GLOBAL(crit_r11)
- .space 4
-
-/*
- * 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.
- * Note that we have to have decremented r1 before we write to any fields
- * of the exception frame, since a critical interrupt could occur at any
- * time, and it will write to the area immediately below the current r1.
- */
-#define NORMAL_EXCEPTION_PROLOG \
- mtspr SPRN_SPRG0,r10; /* save two registers to work with */\
- mtspr SPRN_SPRG1,r11; \
- mtspr SPRN_SPRG2,r1; \
- mfcr r10; /* save CR in r10 for now */\
- mfspr r11,SPRN_SRR1; /* check whether user or kernel */\
- andi. r11,r11,MSR_PR; \
- beq 1f; \
- mfspr r1,SPRN_SPRG3; /* if from user, start at top of */\
- lwz r1,THREAD_INFO-THREAD(r1); /* this thread's kernel stack */\
- addi r1,r1,THREAD_SIZE; \
-1: subi r1,r1,INT_FRAME_SIZE; /* Allocate an exception frame */\
- tophys(r11,r1); \
- stw r10,_CCR(r11); /* save various registers */\
- stw r12,GPR12(r11); \
- stw r9,GPR9(r11); \
- mfspr r10,SPRN_SPRG0; \
- stw r10,GPR10(r11); \
- mfspr r12,SPRN_SPRG1; \
- stw r12,GPR11(r11); \
- mflr r10; \
- stw r10,_LINK(r11); \
- mfspr r10,SPRN_SPRG2; \
- mfspr r12,SPRN_SRR0; \
- stw r10,GPR1(r11); \
- mfspr r9,SPRN_SRR1; \
- stw r10,0(r11); \
- rlwinm r9,r9,0,14,12; /* clear MSR_WE (necessary?) */\
- stw r0,GPR0(r11); \
- SAVE_4GPRS(3, r11); \
- SAVE_2GPRS(7, r11)
-
-/*
- * Exception prolog for critical exceptions. This is a little different
- * from the normal exception prolog above since a critical exception
- * can potentially occur at any point during normal exception processing.
- * Thus we cannot use the same SPRG registers as the normal prolog above.
- * Instead we use a couple of words of memory at low physical addresses.
- * This is OK since we don't support SMP on these processors.
- */
-#define CRITICAL_EXCEPTION_PROLOG \
- stw r10,crit_r10@l(0); /* save two registers to work with */\
- stw r11,crit_r11@l(0); \
- mfcr r10; /* save CR in r10 for now */\
- mfspr r11,SPRN_SRR3; /* check whether user or kernel */\
- andi. r11,r11,MSR_PR; \
- lis r11,critical_stack_top@h; \
- ori r11,r11,critical_stack_top@l; \
- beq 1f; \
- /* COMING FROM USER MODE */ \
- mfspr r11,SPRN_SPRG3; /* if from user, start at top of */\
- lwz r11,THREAD_INFO-THREAD(r11); /* this thread's kernel stack */\
- addi r11,r11,THREAD_SIZE; \
-1: subi r11,r11,INT_FRAME_SIZE; /* Allocate an exception frame */\
- tophys(r11,r11); \
- stw r10,_CCR(r11); /* save various registers */\
- stw r12,GPR12(r11); \
- stw r9,GPR9(r11); \
- mflr r10; \
- stw r10,_LINK(r11); \
- mfspr r12,SPRN_DEAR; /* save DEAR and ESR in the frame */\
- stw r12,_DEAR(r11); /* since they may have had stuff */\
- mfspr r9,SPRN_ESR; /* in them at the point where the */\
- stw r9,_ESR(r11); /* exception was taken */\
- mfspr r12,SPRN_SRR2; \
- stw r1,GPR1(r11); \
- mfspr r9,SPRN_SRR3; \
- stw r1,0(r11); \
- tovirt(r1,r11); \
- rlwinm r9,r9,0,14,12; /* clear MSR_WE (necessary?) */\
- stw r0,GPR0(r11); \
- SAVE_4GPRS(3, r11); \
- SAVE_2GPRS(7, r11)
-
- /*
- * State at this point:
- * r9 saved in stack frame, now saved SRR3 & ~MSR_WE
- * r10 saved in crit_r10 and in stack frame, trashed
- * r11 saved in crit_r11 and in stack frame,
- * now phys stack/exception frame pointer
- * r12 saved in stack frame, now saved SRR2
- * CR saved in stack frame, CR0.EQ = !SRR3.PR
- * LR, DEAR, ESR in stack frame
- * r1 saved in stack frame, now virt stack/excframe pointer
- * r0, r3-r8 saved in stack frame
- */
-
-/*
- * Exception vectors.
- */
-#define START_EXCEPTION(n, label) \
- . = n; \
-label:
-
-#define EXCEPTION(n, label, hdlr, xfer) \
- START_EXCEPTION(n, label); \
- NORMAL_EXCEPTION_PROLOG; \
- addi r3,r1,STACK_FRAME_OVERHEAD; \
- xfer(n, hdlr)
-
-#define CRITICAL_EXCEPTION(n, label, hdlr) \
- START_EXCEPTION(n, label); \
- CRITICAL_EXCEPTION_PROLOG; \
- addi r3,r1,STACK_FRAME_OVERHEAD; \
- EXC_XFER_TEMPLATE(hdlr, n+2, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \
- NOCOPY, crit_transfer_to_handler, \
- ret_from_crit_exc)
-
-#define EXC_XFER_TEMPLATE(hdlr, trap, msr, copyee, tfer, ret) \
- li r10,trap; \
- stw r10,TRAP(r11); \
- lis r10,msr@h; \
- ori r10,r10,msr@l; \
- copyee(r10, r9); \
- bl tfer; \
- .long hdlr; \
- .long ret
-
-#define COPY_EE(d, s) rlwimi d,s,0,16,16
-#define NOCOPY(d, s)
-
-#define EXC_XFER_STD(n, hdlr) \
- EXC_XFER_TEMPLATE(hdlr, n, MSR_KERNEL, NOCOPY, transfer_to_handler_full, \
- ret_from_except_full)
-
-#define EXC_XFER_LITE(n, hdlr) \
- EXC_XFER_TEMPLATE(hdlr, n+1, MSR_KERNEL, NOCOPY, transfer_to_handler, \
- ret_from_except)
-
-#define EXC_XFER_EE(n, hdlr) \
- EXC_XFER_TEMPLATE(hdlr, n, MSR_KERNEL, COPY_EE, transfer_to_handler_full, \
- ret_from_except_full)
-
-#define EXC_XFER_EE_LITE(n, hdlr) \
- EXC_XFER_TEMPLATE(hdlr, n+1, MSR_KERNEL, COPY_EE, transfer_to_handler, \
- ret_from_except)
-
-
-/*
- * 0x0100 - Critical Interrupt Exception
- */
- CRITICAL_EXCEPTION(0x0100, CriticalInterrupt, unknown_exception)
-
-/*
- * 0x0200 - Machine Check Exception
- */
- CRITICAL_EXCEPTION(0x0200, MachineCheck, machine_check_exception)
-
-/*
- * 0x0300 - Data Storage Exception
- * This happens for just a few reasons. U0 set (but we don't do that),
- * or zone protection fault (user violation, write to protected page).
- * If this is just an update of modified status, we do that quickly
- * and exit. Otherwise, we call heavywight functions to do the work.
- */
- START_EXCEPTION(0x0300, DataStorage)
- mtspr SPRN_SPRG0, r10 /* Save some working registers */
- mtspr SPRN_SPRG1, r11
-#ifdef CONFIG_403GCX
- stw r12, 0(r0)
- stw r9, 4(r0)
- mfcr r11
- mfspr r12, SPRN_PID
- stw r11, 8(r0)
- stw r12, 12(r0)
-#else
- mtspr SPRN_SPRG4, r12
- mtspr SPRN_SPRG5, r9
- mfcr r11
- mfspr r12, SPRN_PID
- mtspr SPRN_SPRG7, r11
- mtspr SPRN_SPRG6, r12
-#endif
-
- /* First, check if it was a zone fault (which means a user
- * tried to access a kernel or read-protected page - always
- * a SEGV). All other faults here must be stores, so no
- * need to check ESR_DST as well. */
- mfspr r10, SPRN_ESR
- andis. r10, r10, ESR_DIZ@h
- bne 2f
-
- mfspr r10, SPRN_DEAR /* Get faulting address */
-
- /* If we are faulting a kernel address, we have to use the
- * kernel page tables.
- */
- lis r11, TASK_SIZE@h
- cmplw r10, r11
- blt+ 3f
- lis r11, swapper_pg_dir@h
- ori r11, r11, swapper_pg_dir@l
- li r9, 0
- mtspr SPRN_PID, r9 /* TLB will have 0 TID */
- b 4f
-
- /* Get the PGD for the current thread.
- */
-3:
- mfspr r11,SPRN_SPRG3
- lwz r11,PGDIR(r11)
-4:
- tophys(r11, r11)
- rlwimi r11, r10, 12, 20, 29 /* Create L1 (pgdir/pmd) address */
- lwz r11, 0(r11) /* Get L1 entry */
- rlwinm. r12, r11, 0, 0, 19 /* Extract L2 (pte) base address */
- beq 2f /* Bail if no table */
-
- rlwimi r12, r10, 22, 20, 29 /* Compute PTE address */
- lwz r11, 0(r12) /* Get Linux PTE */
-
- andi. r9, r11, _PAGE_RW /* Is it writeable? */
- beq 2f /* Bail if not */
-
- /* Update 'changed'.
- */
- ori r11, r11, _PAGE_DIRTY|_PAGE_ACCESSED|_PAGE_HWWRITE
- stw r11, 0(r12) /* Update Linux page table */
-
- /* Most of the Linux PTE is ready to load into the TLB LO.
- * We set ZSEL, where only the LS-bit determines user access.
- * We set execute, because we don't have the granularity to
- * properly set this at the page level (Linux problem).
- * If shared is set, we cause a zero PID->TID load.
- * Many of these bits are software only. Bits we don't set
- * here we (properly should) assume have the appropriate value.
- */
- li r12, 0x0ce2
- andc r11, r11, r12 /* Make sure 20, 21 are zero */
-
- /* find the TLB index that caused the fault. It has to be here.
- */
- tlbsx r9, 0, r10
-
- tlbwe r11, r9, TLB_DATA /* Load TLB LO */
-
- /* Done...restore registers and get out of here.
- */
-#ifdef CONFIG_403GCX
- lwz r12, 12(r0)
- lwz r11, 8(r0)
- mtspr SPRN_PID, r12
- mtcr r11
- lwz r9, 4(r0)
- lwz r12, 0(r0)
-#else
- mfspr r12, SPRN_SPRG6
- mfspr r11, SPRN_SPRG7
- mtspr SPRN_PID, r12
- mtcr r11
- mfspr r9, SPRN_SPRG5
- mfspr r12, SPRN_SPRG4
-#endif
- mfspr r11, SPRN_SPRG1
- mfspr r10, SPRN_SPRG0
- PPC405_ERR77_SYNC
- rfi /* Should sync shadow TLBs */
- b . /* prevent prefetch past rfi */
-
-2:
- /* The bailout. Restore registers to pre-exception conditions
- * and call the heavyweights to help us out.
- */
-#ifdef CONFIG_403GCX
- lwz r12, 12(r0)
- lwz r11, 8(r0)
- mtspr SPRN_PID, r12
- mtcr r11
- lwz r9, 4(r0)
- lwz r12, 0(r0)
-#else
- mfspr r12, SPRN_SPRG6
- mfspr r11, SPRN_SPRG7
- mtspr SPRN_PID, r12
- mtcr r11
- mfspr r9, SPRN_SPRG5
- mfspr r12, SPRN_SPRG4
-#endif
- mfspr r11, SPRN_SPRG1
- mfspr r10, SPRN_SPRG0
- b DataAccess
-
-/*
- * 0x0400 - Instruction Storage Exception
- * This is caused by a fetch from non-execute or guarded pages.
- */
- START_EXCEPTION(0x0400, InstructionAccess)
- NORMAL_EXCEPTION_PROLOG
- mr r4,r12 /* Pass SRR0 as arg2 */
- li r5,0 /* Pass zero as arg3 */
- EXC_XFER_EE_LITE(0x400, handle_page_fault)
-
-/* 0x0500 - External Interrupt Exception */
- EXCEPTION(0x0500, HardwareInterrupt, do_IRQ, EXC_XFER_LITE)
-
-/* 0x0600 - Alignment Exception */
- START_EXCEPTION(0x0600, Alignment)
- NORMAL_EXCEPTION_PROLOG
- mfspr r4,SPRN_DEAR /* Grab the DEAR and save it */
- stw r4,_DEAR(r11)
- addi r3,r1,STACK_FRAME_OVERHEAD
- EXC_XFER_EE(0x600, alignment_exception)
-
-/* 0x0700 - Program Exception */
- START_EXCEPTION(0x0700, ProgramCheck)
- NORMAL_EXCEPTION_PROLOG
- mfspr r4,SPRN_ESR /* Grab the ESR and save it */
- stw r4,_ESR(r11)
- addi r3,r1,STACK_FRAME_OVERHEAD
- EXC_XFER_STD(0x700, program_check_exception)
-
- EXCEPTION(0x0800, Trap_08, unknown_exception, EXC_XFER_EE)
- EXCEPTION(0x0900, Trap_09, unknown_exception, EXC_XFER_EE)
- EXCEPTION(0x0A00, Trap_0A, unknown_exception, EXC_XFER_EE)
- EXCEPTION(0x0B00, Trap_0B, unknown_exception, EXC_XFER_EE)
-
-/* 0x0C00 - System Call Exception */
- START_EXCEPTION(0x0C00, SystemCall)
- NORMAL_EXCEPTION_PROLOG
- EXC_XFER_EE_LITE(0xc00, DoSyscall)
-
- EXCEPTION(0x0D00, Trap_0D, unknown_exception, EXC_XFER_EE)
- EXCEPTION(0x0E00, Trap_0E, unknown_exception, EXC_XFER_EE)
- EXCEPTION(0x0F00, Trap_0F, unknown_exception, EXC_XFER_EE)
-
-/* 0x1000 - Programmable Interval Timer (PIT) Exception */
- START_EXCEPTION(0x1000, Decrementer)
- NORMAL_EXCEPTION_PROLOG
- lis r0,TSR_PIS@h
- mtspr SPRN_TSR,r0 /* Clear the PIT exception */
- addi r3,r1,STACK_FRAME_OVERHEAD
- EXC_XFER_LITE(0x1000, timer_interrupt)
-
-#if 0
-/* NOTE:
- * FIT and WDT handlers are not implemented yet.
- */
-
-/* 0x1010 - Fixed Interval Timer (FIT) Exception
-*/
- STND_EXCEPTION(0x1010, FITException, unknown_exception)
-
-/* 0x1020 - Watchdog Timer (WDT) Exception
-*/
-#ifdef CONFIG_BOOKE_WDT
- CRITICAL_EXCEPTION(0x1020, WDTException, WatchdogException)
-#else
- CRITICAL_EXCEPTION(0x1020, WDTException, unknown_exception)
-#endif
-#endif
-
-/* 0x1100 - Data TLB Miss Exception
- * As the name implies, translation is not in the MMU, so search the
- * page tables and fix it. The only purpose of this function is to
- * load TLB entries from the page table if they exist.
- */
- START_EXCEPTION(0x1100, DTLBMiss)
- mtspr SPRN_SPRG0, r10 /* Save some working registers */
- mtspr SPRN_SPRG1, r11
-#ifdef CONFIG_403GCX
- stw r12, 0(r0)
- stw r9, 4(r0)
- mfcr r11
- mfspr r12, SPRN_PID
- stw r11, 8(r0)
- stw r12, 12(r0)
-#else
- mtspr SPRN_SPRG4, r12
- mtspr SPRN_SPRG5, r9
- mfcr r11
- mfspr r12, SPRN_PID
- mtspr SPRN_SPRG7, r11
- mtspr SPRN_SPRG6, r12
-#endif
- mfspr r10, SPRN_DEAR /* Get faulting address */
-
- /* If we are faulting a kernel address, we have to use the
- * kernel page tables.
- */
- lis r11, TASK_SIZE@h
- cmplw r10, r11
- blt+ 3f
- lis r11, swapper_pg_dir@h
- ori r11, r11, swapper_pg_dir@l
- li r9, 0
- mtspr SPRN_PID, r9 /* TLB will have 0 TID */
- b 4f
-
- /* Get the PGD for the current thread.
- */
-3:
- mfspr r11,SPRN_SPRG3
- lwz r11,PGDIR(r11)
-4:
- tophys(r11, r11)
- rlwimi r11, r10, 12, 20, 29 /* Create L1 (pgdir/pmd) address */
- lwz r12, 0(r11) /* Get L1 entry */
- andi. r9, r12, _PMD_PRESENT /* Check if it points to a PTE page */
- beq 2f /* Bail if no table */
-
- rlwimi r12, r10, 22, 20, 29 /* Compute PTE address */
- lwz r11, 0(r12) /* Get Linux PTE */
- andi. r9, r11, _PAGE_PRESENT
- beq 5f
-
- ori r11, r11, _PAGE_ACCESSED
- stw r11, 0(r12)
-
- /* Create TLB tag. This is the faulting address plus a static
- * set of bits. These are size, valid, E, U0.
- */
- li r12, 0x00c0
- rlwimi r10, r12, 0, 20, 31
-
- b finish_tlb_load
-
-2: /* Check for possible large-page pmd entry */
- rlwinm. r9, r12, 2, 22, 24
- beq 5f
-
- /* Create TLB tag. This is the faulting address, plus a static
- * set of bits (valid, E, U0) plus the size from the PMD.
- */
- ori r9, r9, 0x40
- rlwimi r10, r9, 0, 20, 31
- mr r11, r12
-
- b finish_tlb_load
-
-5:
- /* The bailout. Restore registers to pre-exception conditions
- * and call the heavyweights to help us out.
- */
-#ifdef CONFIG_403GCX
- lwz r12, 12(r0)
- lwz r11, 8(r0)
- mtspr SPRN_PID, r12
- mtcr r11
- lwz r9, 4(r0)
- lwz r12, 0(r0)
-#else
- mfspr r12, SPRN_SPRG6
- mfspr r11, SPRN_SPRG7
- mtspr SPRN_PID, r12
- mtcr r11
- mfspr r9, SPRN_SPRG5
- mfspr r12, SPRN_SPRG4
-#endif
- mfspr r11, SPRN_SPRG1
- mfspr r10, SPRN_SPRG0
- b DataAccess
-
-/* 0x1200 - Instruction TLB Miss Exception
- * Nearly the same as above, except we get our information from different
- * registers and bailout to a different point.
- */
- START_EXCEPTION(0x1200, ITLBMiss)
- mtspr SPRN_SPRG0, r10 /* Save some working registers */
- mtspr SPRN_SPRG1, r11
-#ifdef CONFIG_403GCX
- stw r12, 0(r0)
- stw r9, 4(r0)
- mfcr r11
- mfspr r12, SPRN_PID
- stw r11, 8(r0)
- stw r12, 12(r0)
-#else
- mtspr SPRN_SPRG4, r12
- mtspr SPRN_SPRG5, r9
- mfcr r11
- mfspr r12, SPRN_PID
- mtspr SPRN_SPRG7, r11
- mtspr SPRN_SPRG6, r12
-#endif
- mfspr r10, SPRN_SRR0 /* Get faulting address */
-
- /* If we are faulting a kernel address, we have to use the
- * kernel page tables.
- */
- lis r11, TASK_SIZE@h
- cmplw r10, r11
- blt+ 3f
- lis r11, swapper_pg_dir@h
- ori r11, r11, swapper_pg_dir@l
- li r9, 0
- mtspr SPRN_PID, r9 /* TLB will have 0 TID */
- b 4f
-
- /* Get the PGD for the current thread.
- */
-3:
- mfspr r11,SPRN_SPRG3
- lwz r11,PGDIR(r11)
-4:
- tophys(r11, r11)
- rlwimi r11, r10, 12, 20, 29 /* Create L1 (pgdir/pmd) address */
- lwz r12, 0(r11) /* Get L1 entry */
- andi. r9, r12, _PMD_PRESENT /* Check if it points to a PTE page */
- beq 2f /* Bail if no table */
-
- rlwimi r12, r10, 22, 20, 29 /* Compute PTE address */
- lwz r11, 0(r12) /* Get Linux PTE */
- andi. r9, r11, _PAGE_PRESENT
- beq 5f
-
- ori r11, r11, _PAGE_ACCESSED
- stw r11, 0(r12)
-
- /* Create TLB tag. This is the faulting address plus a static
- * set of bits. These are size, valid, E, U0.
- */
- li r12, 0x00c0
- rlwimi r10, r12, 0, 20, 31
-
- b finish_tlb_load
-
-2: /* Check for possible large-page pmd entry */
- rlwinm. r9, r12, 2, 22, 24
- beq 5f
-
- /* Create TLB tag. This is the faulting address, plus a static
- * set of bits (valid, E, U0) plus the size from the PMD.
- */
- ori r9, r9, 0x40
- rlwimi r10, r9, 0, 20, 31
- mr r11, r12
-
- b finish_tlb_load
-
-5:
- /* The bailout. Restore registers to pre-exception conditions
- * and call the heavyweights to help us out.
- */
-#ifdef CONFIG_403GCX
- lwz r12, 12(r0)
- lwz r11, 8(r0)
- mtspr SPRN_PID, r12
- mtcr r11
- lwz r9, 4(r0)
- lwz r12, 0(r0)
-#else
- mfspr r12, SPRN_SPRG6
- mfspr r11, SPRN_SPRG7
- mtspr SPRN_PID, r12
- mtcr r11
- mfspr r9, SPRN_SPRG5
- mfspr r12, SPRN_SPRG4
-#endif
- mfspr r11, SPRN_SPRG1
- mfspr r10, SPRN_SPRG0
- b InstructionAccess
-
- EXCEPTION(0x1300, Trap_13, unknown_exception, EXC_XFER_EE)
- EXCEPTION(0x1400, Trap_14, unknown_exception, EXC_XFER_EE)
- EXCEPTION(0x1500, Trap_15, unknown_exception, EXC_XFER_EE)
- EXCEPTION(0x1600, Trap_16, unknown_exception, EXC_XFER_EE)
-#ifdef CONFIG_IBM405_ERR51
- /* 405GP errata 51 */
- START_EXCEPTION(0x1700, Trap_17)
- b DTLBMiss
-#else
- EXCEPTION(0x1700, Trap_17, unknown_exception, EXC_XFER_EE)
-#endif
- EXCEPTION(0x1800, Trap_18, unknown_exception, EXC_XFER_EE)
- EXCEPTION(0x1900, Trap_19, unknown_exception, EXC_XFER_EE)
- EXCEPTION(0x1A00, Trap_1A, unknown_exception, EXC_XFER_EE)
- EXCEPTION(0x1B00, Trap_1B, unknown_exception, EXC_XFER_EE)
- EXCEPTION(0x1C00, Trap_1C, unknown_exception, EXC_XFER_EE)
- EXCEPTION(0x1D00, Trap_1D, unknown_exception, EXC_XFER_EE)
- EXCEPTION(0x1E00, Trap_1E, unknown_exception, EXC_XFER_EE)
- EXCEPTION(0x1F00, Trap_1F, unknown_exception, EXC_XFER_EE)
-
-/* Check for a single step debug exception while in an exception
- * handler before state has been saved. This is to catch the case
- * where an instruction that we are trying to single step causes
- * an exception (eg ITLB/DTLB miss) and thus the first instruction of
- * the exception handler generates a single step debug exception.
- *
- * If we get a debug trap on the first instruction of an exception handler,
- * we reset the MSR_DE in the _exception handler's_ MSR (the debug trap is
- * a critical exception, so we are using SPRN_CSRR1 to manipulate the MSR).
- * The exception handler was handling a non-critical interrupt, so it will
- * save (and later restore) the MSR via SPRN_SRR1, which will still have
- * the MSR_DE bit set.
- */
- /* 0x2000 - Debug Exception */
- START_EXCEPTION(0x2000, DebugTrap)
- CRITICAL_EXCEPTION_PROLOG
-
- /*
- * If this is a single step or branch-taken exception in an
- * exception entry sequence, it was probably meant to apply to
- * the code where the exception occurred (since exception entry
- * doesn't turn off DE automatically). We simulate the effect
- * of turning off DE on entry to an exception handler by turning
- * off DE in the SRR3 value and clearing the debug status.
- */
- mfspr r10,SPRN_DBSR /* check single-step/branch taken */
- andis. r10,r10,DBSR_IC@h
- beq+ 2f
-
- andi. r10,r9,MSR_IR|MSR_PR /* check supervisor + MMU off */
- beq 1f /* branch and fix it up */
-
- mfspr r10,SPRN_SRR2 /* Faulting instruction address */
- cmplwi r10,0x2100
- bgt+ 2f /* address above exception vectors */
-
- /* here it looks like we got an inappropriate debug exception. */
-1: rlwinm r9,r9,0,~MSR_DE /* clear DE in the SRR3 value */
- lis r10,DBSR_IC@h /* clear the IC event */
- mtspr SPRN_DBSR,r10
- /* restore state and get out */
- lwz r10,_CCR(r11)
- lwz r0,GPR0(r11)
- lwz r1,GPR1(r11)
- mtcrf 0x80,r10
- mtspr SPRN_SRR2,r12
- mtspr SPRN_SRR3,r9
- lwz r9,GPR9(r11)
- lwz r12,GPR12(r11)
- lwz r10,crit_r10@l(0)
- lwz r11,crit_r11@l(0)
- PPC405_ERR77_SYNC
- rfci
- b .
-
- /* continue normal handling for a critical exception... */
-2: mfspr r4,SPRN_DBSR
- addi r3,r1,STACK_FRAME_OVERHEAD
- EXC_XFER_TEMPLATE(DebugException, 0x2002, \
- (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \
- NOCOPY, crit_transfer_to_handler, ret_from_crit_exc)
-
-/*
- * The other Data TLB exceptions bail out to this point
- * if they can't resolve the lightweight TLB fault.
- */
-DataAccess:
- NORMAL_EXCEPTION_PROLOG
- mfspr r5,SPRN_ESR /* Grab the ESR, save it, pass arg3 */
- stw r5,_ESR(r11)
- mfspr r4,SPRN_DEAR /* Grab the DEAR, save it, pass arg2 */
- EXC_XFER_EE_LITE(0x300, handle_page_fault)
-
-/* 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.
- */
-
- /* Damn, I came up one instruction too many to fit into the
- * exception space :-). Both the instruction and data TLB
- * miss get to this point to load the TLB.
- * r10 - TLB_TAG value
- * r11 - Linux PTE
- * r12, r9 - avilable to use
- * PID - loaded with proper value when we get here
- * Upon exit, we reload everything and RFI.
- * Actually, it will fit now, but oh well.....a common place
- * to load the TLB.
- */
-tlb_4xx_index:
- .long 0
-finish_tlb_load:
- /* load the next available TLB index.
- */
- lwz r9, tlb_4xx_index@l(0)
- addi r9, r9, 1
- andi. r9, r9, (PPC4XX_TLB_SIZE-1)
- stw r9, tlb_4xx_index@l(0)
-
-6:
- /*
- * Clear out the software-only bits in the PTE to generate the
- * TLB_DATA value. These are the bottom 2 bits of the RPM, the
- * top 3 bits of the zone field, and M.
- */
- li r12, 0x0ce2
- andc r11, r11, r12
-
- tlbwe r11, r9, TLB_DATA /* Load TLB LO */
- tlbwe r10, r9, TLB_TAG /* Load TLB HI */
-
- /* Done...restore registers and get out of here.
- */
-#ifdef CONFIG_403GCX
- lwz r12, 12(r0)
- lwz r11, 8(r0)
- mtspr SPRN_PID, r12
- mtcr r11
- lwz r9, 4(r0)
- lwz r12, 0(r0)
-#else
- mfspr r12, SPRN_SPRG6
- mfspr r11, SPRN_SPRG7
- mtspr SPRN_PID, r12
- mtcr r11
- mfspr r9, SPRN_SPRG5
- mfspr r12, SPRN_SPRG4
-#endif
- mfspr r11, SPRN_SPRG1
- mfspr r10, SPRN_SPRG0
- PPC405_ERR77_SYNC
- rfi /* Should sync shadow TLBs */
- b . /* prevent prefetch past rfi */
-
-/* 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
-
-/* This is where the main kernel code starts.
- */
-start_here:
-
- /* ptr to current */
- lis r2,init_task@h
- ori r2,r2,init_task@l
-
- /* ptr to phys current thread */
- tophys(r4,r2)
- addi r4,r4,THREAD /* init task's THREAD */
- mtspr SPRN_SPRG3,r4
-
- /* stack */
- lis r1,init_thread_union@ha
- addi r1,r1,init_thread_union@l
- li r0,0
- stwu r0,THREAD_SIZE-STACK_FRAME_OVERHEAD(r1)
-
- bl early_init /* We have to do this with MMU on */
-
-/*
- * Decide what sort of machine this is and initialize the MMU.
- */
- mr r3,r31
- mr r4,r30
- mr r5,r29
- mr r6,r28
- mr r7,r27
- bl machine_init
- bl MMU_init
-
-/* Go back to running unmapped so we can load up new values
- * and change to using our exception vectors.
- * On the 4xx, all we have to do is invalidate the TLB to clear
- * the old 16M byte TLB mappings.
- */
- lis r4,2f@h
- ori r4,r4,2f@l
- tophys(r4,r4)
- lis r3,(MSR_KERNEL & ~(MSR_IR|MSR_DR))@h
- ori r3,r3,(MSR_KERNEL & ~(MSR_IR|MSR_DR))@l
- mtspr SPRN_SRR0,r4
- mtspr SPRN_SRR1,r3
- rfi
- b . /* prevent prefetch past rfi */
-
-/* Load up the kernel context */
-2:
- sync /* Flush to memory before changing TLB */
- tlbia
- isync /* Flush shadow TLBs */
-
- /* set up the PTE pointers for the Abatron bdiGDB.
- */
- lis r6, swapper_pg_dir@h
- ori r6, r6, swapper_pg_dir@l
- lis r5, abatron_pteptrs@h
- ori r5, r5, abatron_pteptrs@l
- stw r5, 0xf0(r0) /* Must match your Abatron config file */
- tophys(r5,r5)
- stw r6, 0(r5)
-
-/* Now turn on the MMU for real! */
- 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
- mtspr SPRN_SRR1,r4
- rfi /* enable MMU and jump to start_kernel */
- b . /* prevent prefetch past rfi */
-
-/* Set up the initial MMU state so we can do the first level of
- * kernel initialization. This maps the first 16 MBytes of memory 1:1
- * virtual to physical and more importantly sets the cache mode.
- */
-initial_mmu:
- tlbia /* Invalidate all TLB entries */
- isync
-
- /* We should still be executing code at physical address 0x0000xxxx
- * at this point. However, start_here is at virtual address
- * 0xC000xxxx. So, set up a TLB mapping to cover this once
- * translation is enabled.
- */
-
- lis r3,KERNELBASE@h /* Load the kernel virtual address */
- ori r3,r3,KERNELBASE@l
- tophys(r4,r3) /* Load the kernel physical address */
-
- iccci r0,r3 /* Invalidate the i-cache before use */
-
- /* Load the kernel PID.
- */
- li r0,0
- mtspr SPRN_PID,r0
- sync
-
- /* Configure and load two entries into TLB slots 62 and 63.
- * In case we are pinning TLBs, these are reserved in by the
- * other TLB functions. If not reserving, then it doesn't
- * matter where they are loaded.
- */
- clrrwi r4,r4,10 /* Mask off the real page number */
- ori r4,r4,(TLB_WR | TLB_EX) /* Set the write and execute bits */
-
- clrrwi r3,r3,10 /* Mask off the effective page number */
- ori r3,r3,(TLB_VALID | TLB_PAGESZ(PAGESZ_16M))
-
- li r0,63 /* TLB slot 63 */
-
- tlbwe r4,r0,TLB_DATA /* Load the data portion of the entry */
- tlbwe r3,r0,TLB_TAG /* Load the tag portion of the entry */
-
-#if defined(CONFIG_SERIAL_TEXT_DEBUG) && defined(SERIAL_DEBUG_IO_BASE)
-
- /* Load a TLB entry for the UART, so that ppc4xx_progress() can use
- * the UARTs nice and early. We use a 4k real==virtual mapping. */
-
- lis r3,SERIAL_DEBUG_IO_BASE@h
- ori r3,r3,SERIAL_DEBUG_IO_BASE@l
- mr r4,r3
- clrrwi r4,r4,12
- ori r4,r4,(TLB_WR|TLB_I|TLB_M|TLB_G)
-
- clrrwi r3,r3,12
- ori r3,r3,(TLB_VALID | TLB_PAGESZ(PAGESZ_4K))
-
- li r0,0 /* TLB slot 0 */
- tlbwe r4,r0,TLB_DATA
- tlbwe r3,r0,TLB_TAG
-#endif /* CONFIG_SERIAL_DEBUG_TEXT && SERIAL_DEBUG_IO_BASE */
-
- isync
-
- /* Establish the exception vector base
- */
- lis r4,KERNELBASE@h /* EVPR only uses the high 16-bits */
- tophys(r0,r4) /* Use the physical address */
- mtspr SPRN_EVPR,r0
-
- blr
-
-_GLOBAL(abort)
- mfspr r13,SPRN_DBCR0
- oris r13,r13,DBCR0_RST_SYSTEM@h
- mtspr SPRN_DBCR0,r13
-
-_GLOBAL(set_context)
-
-#ifdef CONFIG_BDI_SWITCH
- /* Context switch the PTE pointer for the Abatron BDI2000.
- * The PGDIR is the second parameter.
- */
- lis r5, KERNELBASE@h
- lwz r5, 0xf0(r5)
- stw r4, 0x4(r5)
-#endif
- sync
- mtspr SPRN_PID,r3
- isync /* Need an isync to flush shadow */
- /* TLBs after changing PID */
- 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
- .align 12
- .globl sdata
-sdata:
- .globl empty_zero_page
-empty_zero_page:
- .space 4096
- .globl swapper_pg_dir
-swapper_pg_dir:
- .space 4096
-
-
-/* Stack for handling critical exceptions from kernel mode */
- .section .bss
- .align 12
-exception_stack_bottom:
- .space 4096
-critical_stack_top:
- .globl exception_stack_top
-exception_stack_top:
-
-/* 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.
- */
- .globl cmd_line
-cmd_line:
- .space 512
-
-/* Room for two PTE pointers, usually the kernel and current user pointers
- * to their respective root page table.
- */
-abatron_pteptrs:
- .space 8
diff --git a/arch/ppc/kernel/head_8xx.S b/arch/ppc/kernel/head_8xx.S
deleted file mode 100644
index 321bda2de2cb..000000000000
--- a/arch/ppc/kernel/head_8xx.S
+++ /dev/null
@@ -1,959 +0,0 @@
-/*
- * PowerPC version
- * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
- * Rewritten by Cort Dougan (cort@cs.nmt.edu) for PReP
- * Copyright (C) 1996 Cort Dougan <cort@cs.nmt.edu>
- * Low-level exception handlers and MMU support
- * rewritten by Paul Mackerras.
- * Copyright (C) 1996 Paul Mackerras.
- * MPC8xx modifications by Dan Malek
- * Copyright (C) 1997 Dan Malek (dmalek@jlc.net).
- *
- * This file contains low-level support and setup for PowerPC 8xx
- * embedded processors, including trap and interrupt dispatch.
- *
- * 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 <asm/processor.h>
-#include <asm/page.h>
-#include <asm/mmu.h>
-#include <asm/cache.h>
-#include <asm/pgtable.h>
-#include <asm/cputable.h>
-#include <asm/thread_info.h>
-#include <asm/ppc_asm.h>
-#include <asm/asm-offsets.h>
-
-/* Macro to make the code more readable. */
-#ifdef CONFIG_8xx_CPU6
-#define DO_8xx_CPU6(val, reg) \
- li reg, val; \
- stw reg, 12(r0); \
- lwz reg, 12(r0);
-#else
-#define DO_8xx_CPU6(val, reg)
-#endif
- .text
- .globl _stext
-_stext:
- .text
- .globl _start
-_start:
-
-/* MPC8xx
- * This port was done on an MBX board with an 860. Right now I only
- * support an ELF compressed (zImage) boot from EPPC-Bug because the
- * code there loads up some registers before calling us:
- * r3: ptr to board info data
- * r4: initrd_start or if no initrd then 0
- * r5: initrd_end - unused if r4 is 0
- * r6: Start of command line string
- * r7: End of command line string
- *
- * I decided to use conditional compilation instead of checking PVR and
- * adding more processor specific branches around code I don't need.
- * Since this is an embedded processor, I also appreciate any memory
- * savings I can get.
- *
- * The MPC8xx does not have any BATs, but it supports large page sizes.
- * We first initialize the MMU to support 8M byte pages, then load one
- * entry into each of the instruction and data TLBs to map the first
- * 8M 1:1. I also mapped an additional I/O space 1:1 so we can get to
- * the "internal" processor registers before MMU_init is called.
- *
- * The TLB code currently contains a major hack. Since I use the condition
- * code register, I have to save and restore it. I am out of registers, so
- * I just store it in memory location 0 (the TLB handlers are not reentrant).
- * To avoid making any decisions, I need to use the "segment" valid bit
- * in the first level table, but that would require many changes to the
- * Linux page directory/table functions that I don't want to do right now.
- *
- * I used to use SPRG2 for a temporary register in the TLB handler, but it
- * has since been put to other uses. I now use a hack to save a register
- * and the CCR at memory location 0.....Someday I'll fix this.....
- * -- Dan
- */
- .globl __start
-__start:
- mr r31,r3 /* save parameters */
- mr r30,r4
- mr r29,r5
- mr r28,r6
- mr r27,r7
-
- /* We have to turn on the MMU right away so we get cache modes
- * set correctly.
- */
- bl initial_mmu
-
-/* We now have the lower 8 Meg mapped into TLB entries, and the caches
- * ready to work.
- */
-
-turn_on_mmu:
- mfmsr r0
- ori r0,r0,MSR_DR|MSR_IR
- mtspr SPRN_SRR1,r0
- lis r0,start_here@h
- ori r0,r0,start_here@l
- mtspr SPRN_SRR0,r0
- SYNC
- rfi /* enables MMU */
-
-/*
- * Exception 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's thread_struct.
- */
-#define EXCEPTION_PROLOG \
- mtspr SPRN_SPRG0,r10; \
- mtspr SPRN_SPRG1,r11; \
- mfcr r10; \
- EXCEPTION_PROLOG_1; \
- EXCEPTION_PROLOG_2
-
-#define EXCEPTION_PROLOG_1 \
- mfspr r11,SPRN_SRR1; /* check whether user or kernel */ \
- andi. r11,r11,MSR_PR; \
- tophys(r11,r1); /* use tophys(r1) if kernel */ \
- beq 1f; \
- mfspr r11,SPRN_SPRG3; \
- lwz r11,THREAD_INFO-THREAD(r11); \
- addi r11,r11,THREAD_SIZE; \
- tophys(r11,r11); \
-1: subi r11,r11,INT_FRAME_SIZE /* alloc exc. frame */
-
-
-#define EXCEPTION_PROLOG_2 \
- CLR_TOP32(r11); \
- stw r10,_CCR(r11); /* save registers */ \
- stw r12,GPR12(r11); \
- stw r9,GPR9(r11); \
- mfspr r10,SPRN_SPRG0; \
- stw r10,GPR10(r11); \
- mfspr r12,SPRN_SPRG1; \
- stw r12,GPR11(r11); \
- mflr r10; \
- stw r10,_LINK(r11); \
- mfspr r12,SPRN_SRR0; \
- mfspr r9,SPRN_SRR1; \
- stw r1,GPR1(r11); \
- stw r1,0(r11); \
- tovirt(r1,r11); /* set new kernel sp */ \
- li r10,MSR_KERNEL & ~(MSR_IR|MSR_DR); /* can take exceptions */ \
- MTMSRD(r10); /* (except for mach check in rtas) */ \
- stw r0,GPR0(r11); \
- SAVE_4GPRS(3, r11); \
- SAVE_2GPRS(7, r11)
-
-/*
- * Note: code which follows this uses cr0.eq (set if from kernel),
- * r11, r12 (SRR0), and r9 (SRR1).
- *
- * Note2: once we have set r1 we are in a position to take exceptions
- * again, and we could thus set MSR:RI at that point.
- */
-
-/*
- * Exception vectors.
- */
-#define EXCEPTION(n, label, hdlr, xfer) \
- . = n; \
-label: \
- EXCEPTION_PROLOG; \
- addi r3,r1,STACK_FRAME_OVERHEAD; \
- xfer(n, hdlr)
-
-#define EXC_XFER_TEMPLATE(n, hdlr, trap, copyee, tfer, ret) \
- li r10,trap; \
- stw r10,TRAP(r11); \
- li r10,MSR_KERNEL; \
- copyee(r10, r9); \
- bl tfer; \
-i##n: \
- .long hdlr; \
- .long ret
-
-#define COPY_EE(d, s) rlwimi d,s,0,16,16
-#define NOCOPY(d, s)
-
-#define EXC_XFER_STD(n, hdlr) \
- EXC_XFER_TEMPLATE(n, hdlr, n, NOCOPY, transfer_to_handler_full, \
- ret_from_except_full)
-
-#define EXC_XFER_LITE(n, hdlr) \
- EXC_XFER_TEMPLATE(n, hdlr, n+1, NOCOPY, transfer_to_handler, \
- ret_from_except)
-
-#define EXC_XFER_EE(n, hdlr) \
- EXC_XFER_TEMPLATE(n, hdlr, n, COPY_EE, transfer_to_handler_full, \
- ret_from_except_full)
-
-#define EXC_XFER_EE_LITE(n, hdlr) \
- EXC_XFER_TEMPLATE(n, hdlr, n+1, COPY_EE, transfer_to_handler, \
- ret_from_except)
-
-/* System reset */
- EXCEPTION(0x100, Reset, unknown_exception, EXC_XFER_STD)
-
-/* Machine check */
- . = 0x200
-MachineCheck:
- EXCEPTION_PROLOG
- mfspr r4,SPRN_DAR
- stw r4,_DAR(r11)
- mfspr r5,SPRN_DSISR
- stw r5,_DSISR(r11)
- addi r3,r1,STACK_FRAME_OVERHEAD
- EXC_XFER_STD(0x200, machine_check_exception)
-
-/* Data access exception.
- * This is "never generated" by the MPC8xx. We jump to it for other
- * translation errors.
- */
- . = 0x300
-DataAccess:
- EXCEPTION_PROLOG
- mfspr r10,SPRN_DSISR
- stw r10,_DSISR(r11)
- mr r5,r10
- mfspr r4,SPRN_DAR
- EXC_XFER_EE_LITE(0x300, handle_page_fault)
-
-/* Instruction access exception.
- * This is "never generated" by the MPC8xx. We jump to it for other
- * translation errors.
- */
- . = 0x400
-InstructionAccess:
- EXCEPTION_PROLOG
- mr r4,r12
- mr r5,r9
- EXC_XFER_EE_LITE(0x400, handle_page_fault)
-
-/* External interrupt */
- EXCEPTION(0x500, HardwareInterrupt, do_IRQ, EXC_XFER_LITE)
-
-/* Alignment exception */
- . = 0x600
-Alignment:
- EXCEPTION_PROLOG
- mfspr r4,SPRN_DAR
- stw r4,_DAR(r11)
- mfspr r5,SPRN_DSISR
- stw r5,_DSISR(r11)
- addi r3,r1,STACK_FRAME_OVERHEAD
- EXC_XFER_EE(0x600, alignment_exception)
-
-/* Program check exception */
- EXCEPTION(0x700, ProgramCheck, program_check_exception, EXC_XFER_STD)
-
-/* No FPU on MPC8xx. This exception is not supposed to happen.
-*/
- EXCEPTION(0x800, FPUnavailable, unknown_exception, EXC_XFER_STD)
-
-/* Decrementer */
- EXCEPTION(0x900, Decrementer, timer_interrupt, EXC_XFER_LITE)
-
- EXCEPTION(0xa00, Trap_0a, unknown_exception, EXC_XFER_EE)
- EXCEPTION(0xb00, Trap_0b, unknown_exception, EXC_XFER_EE)
-
-/* System call */
- . = 0xc00
-SystemCall:
- EXCEPTION_PROLOG
- EXC_XFER_EE_LITE(0xc00, DoSyscall)
-
-/* Single step - not used on 601 */
- EXCEPTION(0xd00, SingleStep, single_step_exception, EXC_XFER_STD)
- EXCEPTION(0xe00, Trap_0e, unknown_exception, EXC_XFER_EE)
- EXCEPTION(0xf00, Trap_0f, unknown_exception, EXC_XFER_EE)
-
-/* On the MPC8xx, this is a software emulation interrupt. It occurs
- * for all unimplemented and illegal instructions.
- */
- EXCEPTION(0x1000, SoftEmu, SoftwareEmulation, EXC_XFER_STD)
-
- . = 0x1100
-/*
- * For the MPC8xx, this is a software tablewalk to load the instruction
- * TLB. It is modelled after the example in the Motorola manual. The task
- * switch loads the M_TWB register with the pointer to the first level table.
- * If we discover there is no second level table (value is zero) or if there
- * is an invalid pte, we load that into the TLB, which causes another fault
- * into the TLB Error interrupt where we can handle such problems.
- * We have to use the MD_xxx registers for the tablewalk because the
- * equivalent MI_xxx registers only perform the attribute functions.
- */
-InstructionTLBMiss:
-#ifdef CONFIG_8xx_CPU6
- stw r3, 8(r0)
-#endif
- DO_8xx_CPU6(0x3f80, r3)
- mtspr SPRN_M_TW, r10 /* Save a couple of working registers */
- mfcr r10
- stw r10, 0(r0)
- stw r11, 4(r0)
- mfspr r10, SPRN_SRR0 /* Get effective address of fault */
- DO_8xx_CPU6(0x3780, r3)
- mtspr SPRN_MD_EPN, r10 /* Have to use MD_EPN for walk, MI_EPN can't */
- mfspr r10, SPRN_M_TWB /* Get level 1 table entry address */
-
- /* If we are faulting a kernel address, we have to use the
- * kernel page tables.
- */
- andi. r11, r10, 0x0800 /* Address >= 0x80000000 */
- beq 3f
- lis r11, swapper_pg_dir@h
- ori r11, r11, swapper_pg_dir@l
- rlwimi r10, r11, 0, 2, 19
-3:
- lwz r11, 0(r10) /* Get the level 1 entry */
- rlwinm. r10, r11,0,0,19 /* Extract page descriptor page address */
- beq 2f /* If zero, don't try to find a pte */
-
- /* We have a pte table, so load the MI_TWC with the attributes
- * for this "segment."
- */
- ori r11,r11,1 /* Set valid bit */
- DO_8xx_CPU6(0x2b80, r3)
- mtspr SPRN_MI_TWC, r11 /* Set segment attributes */
- DO_8xx_CPU6(0x3b80, r3)
- mtspr SPRN_MD_TWC, r11 /* Load pte table base address */
- mfspr r11, SPRN_MD_TWC /* ....and get the pte address */
- lwz r10, 0(r11) /* Get the pte */
-
-#ifdef CONFIG_SWAP
- /* do not set the _PAGE_ACCESSED bit of a non-present page */
- andi. r11, r10, _PAGE_PRESENT
- beq 4f
- ori r10, r10, _PAGE_ACCESSED
- mfspr r11, SPRN_MD_TWC /* get the pte address again */
- stw r10, 0(r11)
-4:
-#else
- ori r10, r10, _PAGE_ACCESSED
- stw r10, 0(r11)
-#endif
-
- /* The Linux PTE won't go exactly into the MMU TLB.
- * Software indicator bits 21, 22 and 28 must be clear.
- * Software indicator bits 24, 25, 26, and 27 must be
- * set. All other Linux PTE bits control the behavior
- * of the MMU.
- */
-2: li r11, 0x00f0
- rlwimi r10, r11, 0, 24, 28 /* Set 24-27, clear 28 */
- DO_8xx_CPU6(0x2d80, r3)
- mtspr SPRN_MI_RPN, r10 /* Update TLB entry */
-
- mfspr r10, SPRN_M_TW /* Restore registers */
- lwz r11, 0(r0)
- mtcr r11
- lwz r11, 4(r0)
-#ifdef CONFIG_8xx_CPU6
- lwz r3, 8(r0)
-#endif
- rfi
-
- . = 0x1200
-DataStoreTLBMiss:
- stw r3, 8(r0)
- DO_8xx_CPU6(0x3f80, r3)
- mtspr SPRN_M_TW, r10 /* Save a couple of working registers */
- mfcr r10
- stw r10, 0(r0)
- stw r11, 4(r0)
- mfspr r10, SPRN_M_TWB /* Get level 1 table entry address */
-
- /* If we are faulting a kernel address, we have to use the
- * kernel page tables.
- */
- andi. r11, r10, 0x0800
- beq 3f
- lis r11, swapper_pg_dir@h
- ori r11, r11, swapper_pg_dir@l
- rlwimi r10, r11, 0, 2, 19
- stw r12, 16(r0)
- b LoadLargeDTLB
-3:
- lwz r11, 0(r10) /* Get the level 1 entry */
- rlwinm. r10, r11,0,0,19 /* Extract page descriptor page address */
- beq 2f /* If zero, don't try to find a pte */
-
- /* We have a pte table, so load fetch the pte from the table.
- */
- ori r11, r11, 1 /* Set valid bit in physical L2 page */
- DO_8xx_CPU6(0x3b80, r3)
- mtspr SPRN_MD_TWC, r11 /* Load pte table base address */
- mfspr r10, SPRN_MD_TWC /* ....and get the pte address */
- lwz r10, 0(r10) /* Get the pte */
-
- /* Insert the Guarded flag into the TWC from the Linux PTE.
- * It is bit 27 of both the Linux PTE and the TWC (at least
- * I got that right :-). It will be better when we can put
- * this into the Linux pgd/pmd and load it in the operation
- * above.
- */
- rlwimi r11, r10, 0, 27, 27
- DO_8xx_CPU6(0x3b80, r3)
- mtspr SPRN_MD_TWC, r11
-
-#ifdef CONFIG_SWAP
- /* do not set the _PAGE_ACCESSED bit of a non-present page */
- andi. r11, r10, _PAGE_PRESENT
- beq 4f
- ori r10, r10, _PAGE_ACCESSED
-4:
- /* and update pte in table */
-#else
- ori r10, r10, _PAGE_ACCESSED
-#endif
- mfspr r11, SPRN_MD_TWC /* get the pte address again */
- stw r10, 0(r11)
-
- /* The Linux PTE won't go exactly into the MMU TLB.
- * Software indicator bits 21, 22 and 28 must be clear.
- * Software indicator bits 24, 25, 26, and 27 must be
- * set. All other Linux PTE bits control the behavior
- * of the MMU.
- */
-2: li r11, 0x00f0
- rlwimi r10, r11, 0, 24, 28 /* Set 24-27, clear 28 */
- DO_8xx_CPU6(0x3d80, r3)
- mtspr SPRN_MD_RPN, r10 /* Update TLB entry */
-
- mfspr r10, SPRN_M_TW /* Restore registers */
- lwz r11, 0(r0)
- mtcr r11
- lwz r11, 4(r0)
- lwz r3, 8(r0)
- rfi
-
-/* This is an instruction TLB error on the MPC8xx. This could be due
- * to many reasons, such as executing guarded memory or illegal instruction
- * addresses. There is nothing to do but handle a big time error fault.
- */
- . = 0x1300
-InstructionTLBError:
- b InstructionAccess
-
-LoadLargeDTLB:
- li r12, 0
- lwz r11, 0(r10) /* Get the level 1 entry */
- rlwinm. r10, r11,0,0,19 /* Extract page descriptor page address */
- beq 3f /* If zero, don't try to find a pte */
-
- /* We have a pte table, so load fetch the pte from the table.
- */
- ori r11, r11, 1 /* Set valid bit in physical L2 page */
- DO_8xx_CPU6(0x3b80, r3)
- mtspr SPRN_MD_TWC, r11 /* Load pte table base address */
- mfspr r10, SPRN_MD_TWC /* ....and get the pte address */
- lwz r10, 0(r10) /* Get the pte */
-
- /* Insert the Guarded flag into the TWC from the Linux PTE.
- * It is bit 27 of both the Linux PTE and the TWC (at least
- * I got that right :-). It will be better when we can put
- * this into the Linux pgd/pmd and load it in the operation
- * above.
- */
- rlwimi r11, r10, 0, 27, 27
-
- rlwimi r12, r10, 0, 0, 9 /* extract phys. addr */
- mfspr r3, SPRN_MD_EPN
- rlwinm r3, r3, 0, 0, 9 /* extract virtual address */
- tophys(r3, r3)
- cmpw r3, r12 /* only use 8M page if it is a direct
- kernel mapping */
- bne 1f
- ori r11, r11, MD_PS8MEG
- li r12, 1
- b 2f
-1:
- li r12, 0 /* can't use 8MB TLB, so zero r12. */
-2:
- DO_8xx_CPU6(0x3b80, r3)
- mtspr SPRN_MD_TWC, r11
-
- /* The Linux PTE won't go exactly into the MMU TLB.
- * Software indicator bits 21, 22 and 28 must be clear.
- * Software indicator bits 24, 25, 26, and 27 must be
- * set. All other Linux PTE bits control the behavior
- * of the MMU.
- */
-3: li r11, 0x00f0
- rlwimi r10, r11, 0, 24, 28 /* Set 24-27, clear 28 */
- cmpwi r12, 1
- bne 4f
- ori r10, r10, 0x8
-
- mfspr r12, SPRN_MD_EPN
- lis r3, 0xff80 /* 10-19 must be clear for 8MB TLB */
- ori r3, r3, 0x0fff
- and r12, r3, r12
- DO_8xx_CPU6(0x3780, r3)
- mtspr SPRN_MD_EPN, r12
-
- lis r3, 0xff80 /* 10-19 must be clear for 8MB TLB */
- ori r3, r3, 0x0fff
- and r10, r3, r10
-4:
- DO_8xx_CPU6(0x3d80, r3)
- mtspr SPRN_MD_RPN, r10 /* Update TLB entry */
-
- mfspr r10, SPRN_M_TW /* Restore registers */
- lwz r11, 0(r0)
- mtcr r11
- lwz r11, 4(r0)
-
- lwz r12, 16(r0)
- lwz r3, 8(r0)
- rfi
-
-/* This is the data TLB error on the MPC8xx. This could be due to
- * many reasons, including a dirty update to a pte. We can catch that
- * one here, but anything else is an error. First, we track down the
- * Linux pte. If it is valid, write access is allowed, but the
- * page dirty bit is not set, we will set it and reload the TLB. For
- * any other case, we bail out to a higher level function that can
- * handle it.
- */
- . = 0x1400
-DataTLBError:
-#ifdef CONFIG_8xx_CPU6
- stw r3, 8(r0)
-#endif
- DO_8xx_CPU6(0x3f80, r3)
- mtspr SPRN_M_TW, r10 /* Save a couple of working registers */
- mfcr r10
- stw r10, 0(r0)
- stw r11, 4(r0)
-
- /* First, make sure this was a store operation.
- */
- mfspr r10, SPRN_DSISR
- andis. r11, r10, 0x0200 /* If set, indicates store op */
- beq 2f
-
- /* The EA of a data TLB miss is automatically stored in the MD_EPN
- * register. The EA of a data TLB error is automatically stored in
- * the DAR, but not the MD_EPN register. We must copy the 20 most
- * significant bits of the EA from the DAR to MD_EPN before we
- * start walking the page tables. We also need to copy the CASID
- * value from the M_CASID register.
- * Addendum: The EA of a data TLB error is _supposed_ to be stored
- * in DAR, but it seems that this doesn't happen in some cases, such
- * as when the error is due to a dcbi instruction to a page with a
- * TLB that doesn't have the changed bit set. In such cases, there
- * does not appear to be any way to recover the EA of the error
- * since it is neither in DAR nor MD_EPN. As a workaround, the
- * _PAGE_HWWRITE bit is set for all kernel data pages when the PTEs
- * are initialized in mapin_ram(). This will avoid the problem,
- * assuming we only use the dcbi instruction on kernel addresses.
- */
- mfspr r10, SPRN_DAR
- rlwinm r11, r10, 0, 0, 19
- ori r11, r11, MD_EVALID
- mfspr r10, SPRN_M_CASID
- rlwimi r11, r10, 0, 28, 31
- DO_8xx_CPU6(0x3780, r3)
- mtspr SPRN_MD_EPN, r11
-
- mfspr r10, SPRN_M_TWB /* Get level 1 table entry address */
-
- /* If we are faulting a kernel address, we have to use the
- * kernel page tables.
- */
- andi. r11, r10, 0x0800
- beq 3f
- lis r11, swapper_pg_dir@h
- ori r11, r11, swapper_pg_dir@l
- rlwimi r10, r11, 0, 2, 19
-3:
- lwz r11, 0(r10) /* Get the level 1 entry */
- rlwinm. r10, r11,0,0,19 /* Extract page descriptor page address */
- beq 2f /* If zero, bail */
-
- /* We have a pte table, so fetch the pte from the table.
- */
- ori r11, r11, 1 /* Set valid bit in physical L2 page */
- DO_8xx_CPU6(0x3b80, r3)
- mtspr SPRN_MD_TWC, r11 /* Load pte table base address */
- mfspr r11, SPRN_MD_TWC /* ....and get the pte address */
- lwz r10, 0(r11) /* Get the pte */
-
- andi. r11, r10, _PAGE_RW /* Is it writeable? */
- beq 2f /* Bail out if not */
-
- /* Update 'changed', among others.
- */
-#ifdef CONFIG_SWAP
- ori r10, r10, _PAGE_DIRTY|_PAGE_HWWRITE
- /* do not set the _PAGE_ACCESSED bit of a non-present page */
- andi. r11, r10, _PAGE_PRESENT
- beq 4f
- ori r10, r10, _PAGE_ACCESSED
-4:
-#else
- ori r10, r10, _PAGE_DIRTY|_PAGE_ACCESSED|_PAGE_HWWRITE
-#endif
- mfspr r11, SPRN_MD_TWC /* Get pte address again */
- stw r10, 0(r11) /* and update pte in table */
-
- /* The Linux PTE won't go exactly into the MMU TLB.
- * Software indicator bits 21, 22 and 28 must be clear.
- * Software indicator bits 24, 25, 26, and 27 must be
- * set. All other Linux PTE bits control the behavior
- * of the MMU.
- */
- li r11, 0x00f0
- rlwimi r10, r11, 0, 24, 28 /* Set 24-27, clear 28 */
- DO_8xx_CPU6(0x3d80, r3)
- mtspr SPRN_MD_RPN, r10 /* Update TLB entry */
-
- mfspr r10, SPRN_M_TW /* Restore registers */
- lwz r11, 0(r0)
- mtcr r11
- lwz r11, 4(r0)
-#ifdef CONFIG_8xx_CPU6
- lwz r3, 8(r0)
-#endif
- rfi
-2:
- mfspr r10, SPRN_M_TW /* Restore registers */
- lwz r11, 0(r0)
- mtcr r11
- lwz r11, 4(r0)
-#ifdef CONFIG_8xx_CPU6
- lwz r3, 8(r0)
-#endif
- b DataAccess
-
- EXCEPTION(0x1500, Trap_15, unknown_exception, EXC_XFER_EE)
- EXCEPTION(0x1600, Trap_16, unknown_exception, EXC_XFER_EE)
- EXCEPTION(0x1700, Trap_17, unknown_exception, EXC_XFER_EE)
- EXCEPTION(0x1800, Trap_18, unknown_exception, EXC_XFER_EE)
- EXCEPTION(0x1900, Trap_19, unknown_exception, EXC_XFER_EE)
- EXCEPTION(0x1a00, Trap_1a, unknown_exception, EXC_XFER_EE)
- EXCEPTION(0x1b00, Trap_1b, unknown_exception, EXC_XFER_EE)
-
-/* On the MPC8xx, these next four traps are used for development
- * support of breakpoints and such. Someday I will get around to
- * using them.
- */
- EXCEPTION(0x1c00, Trap_1c, unknown_exception, EXC_XFER_EE)
- EXCEPTION(0x1d00, Trap_1d, unknown_exception, EXC_XFER_EE)
- EXCEPTION(0x1e00, Trap_1e, unknown_exception, EXC_XFER_EE)
- EXCEPTION(0x1f00, Trap_1f, unknown_exception, EXC_XFER_EE)
-
- . = 0x2000
-
- .globl giveup_fpu
-giveup_fpu:
- blr
-
-/*
- * This is where the main kernel code starts.
- */
-start_here:
- /* ptr to current */
- lis r2,init_task@h
- ori r2,r2,init_task@l
-
- /* ptr to phys current thread */
- tophys(r4,r2)
- addi r4,r4,THREAD /* init task's THREAD */
- mtspr SPRN_SPRG3,r4
- li r3,0
- mtspr SPRN_SPRG2,r3 /* 0 => r1 has kernel sp */
-
- /* stack */
- lis r1,init_thread_union@ha
- addi r1,r1,init_thread_union@l
- li r0,0
- stwu r0,THREAD_SIZE-STACK_FRAME_OVERHEAD(r1)
-
- bl early_init /* We have to do this with MMU on */
-
-/*
- * Decide what sort of machine this is and initialize the MMU.
- */
- mr r3,r31
- mr r4,r30
- mr r5,r29
- mr r6,r28
- mr r7,r27
- bl machine_init
- bl MMU_init
-
-/*
- * Go back to running unmapped so we can load up new values
- * and change to using our exception vectors.
- * On the 8xx, all we have to do is invalidate the TLB to clear
- * the old 8M byte TLB mappings and load the page table base register.
- */
- /* The right way to do this would be to track it down through
- * init's THREAD like the context switch code does, but this is
- * easier......until someone changes init's static structures.
- */
- lis r6, swapper_pg_dir@h
- ori r6, r6, swapper_pg_dir@l
- tophys(r6,r6)
-#ifdef CONFIG_8xx_CPU6
- lis r4, cpu6_errata_word@h
- ori r4, r4, cpu6_errata_word@l
- li r3, 0x3980
- stw r3, 12(r4)
- lwz r3, 12(r4)
-#endif
- mtspr SPRN_M_TWB, r6
- lis r4,2f@h
- ori r4,r4,2f@l
- tophys(r4,r4)
- li r3,MSR_KERNEL & ~(MSR_IR|MSR_DR)
- mtspr SPRN_SRR0,r4
- mtspr SPRN_SRR1,r3
- rfi
-/* Load up the kernel context */
-2:
- SYNC /* Force all PTE updates to finish */
- tlbia /* Clear all TLB entries */
- sync /* wait for tlbia/tlbie to finish */
- TLBSYNC /* ... on all CPUs */
-
- /* set up the PTE pointers for the Abatron bdiGDB.
- */
- tovirt(r6,r6)
- lis r5, abatron_pteptrs@h
- ori r5, r5, abatron_pteptrs@l
- stw r5, 0xf0(r0) /* Must match your Abatron config file */
- tophys(r5,r5)
- stw r6, 0(r5)
-
-/* Now turn on the MMU for real! */
- li r4,MSR_KERNEL
- lis r3,start_kernel@h
- ori r3,r3,start_kernel@l
- mtspr SPRN_SRR0,r3
- mtspr SPRN_SRR1,r4
- rfi /* enable MMU and jump to start_kernel */
-
-/* Set up the initial MMU state so we can do the first level of
- * kernel initialization. This maps the first 8 MBytes of memory 1:1
- * virtual to physical. Also, set the cache mode since that is defined
- * by TLB entries and perform any additional mapping (like of the IMMR).
- * If configured to pin some TLBs, we pin the first 8 Mbytes of kernel,
- * 24 Mbytes of data, and the 8M IMMR space. Anything not covered by
- * these mappings is mapped by page tables.
- */
-initial_mmu:
- tlbia /* Invalidate all TLB entries */
-#ifdef CONFIG_PIN_TLB
- lis r8, MI_RSV4I@h
- ori r8, r8, 0x1c00
-#else
- li r8, 0
-#endif
- mtspr SPRN_MI_CTR, r8 /* Set instruction MMU control */
-
-#ifdef CONFIG_PIN_TLB
- lis r10, (MD_RSV4I | MD_RESETVAL)@h
- ori r10, r10, 0x1c00
- mr r8, r10
-#else
- lis r10, MD_RESETVAL@h
-#endif
-#ifndef CONFIG_8xx_COPYBACK
- oris r10, r10, MD_WTDEF@h
-#endif
- mtspr SPRN_MD_CTR, r10 /* Set data TLB control */
-
- /* Now map the lower 8 Meg into the TLBs. For this quick hack,
- * we can load the instruction and data TLB registers with the
- * same values.
- */
- lis r8, KERNELBASE@h /* Create vaddr for TLB */
- ori r8, r8, MI_EVALID /* Mark it valid */
- mtspr SPRN_MI_EPN, r8
- mtspr SPRN_MD_EPN, r8
- li r8, MI_PS8MEG /* Set 8M byte page */
- ori r8, r8, MI_SVALID /* Make it valid */
- mtspr SPRN_MI_TWC, r8
- mtspr SPRN_MD_TWC, r8
- li r8, MI_BOOTINIT /* Create RPN for address 0 */
- mtspr SPRN_MI_RPN, r8 /* Store TLB entry */
- mtspr SPRN_MD_RPN, r8
- lis r8, MI_Kp@h /* Set the protection mode */
- mtspr SPRN_MI_AP, r8
- mtspr SPRN_MD_AP, r8
-
- /* Map another 8 MByte at the IMMR to get the processor
- * internal registers (among other things).
- */
-#ifdef CONFIG_PIN_TLB
- addi r10, r10, 0x0100
- mtspr SPRN_MD_CTR, r10
-#endif
- mfspr r9, 638 /* Get current IMMR */
- andis. r9, r9, 0xff80 /* Get 8Mbyte boundary */
-
- mr r8, r9 /* Create vaddr for TLB */
- ori r8, r8, MD_EVALID /* Mark it valid */
- mtspr SPRN_MD_EPN, r8
- li r8, MD_PS8MEG /* Set 8M byte page */
- ori r8, r8, MD_SVALID /* Make it valid */
- mtspr SPRN_MD_TWC, r8
- mr r8, r9 /* Create paddr for TLB */
- ori r8, r8, MI_BOOTINIT|0x2 /* Inhibit cache -- Cort */
- mtspr SPRN_MD_RPN, r8
-
-#ifdef CONFIG_PIN_TLB
- /* Map two more 8M kernel data pages.
- */
- addi r10, r10, 0x0100
- mtspr SPRN_MD_CTR, r10
-
- lis r8, KERNELBASE@h /* Create vaddr for TLB */
- addis r8, r8, 0x0080 /* Add 8M */
- ori r8, r8, MI_EVALID /* Mark it valid */
- mtspr SPRN_MD_EPN, r8
- li r9, MI_PS8MEG /* Set 8M byte page */
- ori r9, r9, MI_SVALID /* Make it valid */
- mtspr SPRN_MD_TWC, r9
- li r11, MI_BOOTINIT /* Create RPN for address 0 */
- addis r11, r11, 0x0080 /* Add 8M */
- mtspr SPRN_MD_RPN, r11
-
- addi r10, r10, 0x0100
- mtspr SPRN_MD_CTR, r10
-
- addis r8, r8, 0x0080 /* Add 8M */
- mtspr SPRN_MD_EPN, r8
- mtspr SPRN_MD_TWC, r9
- addis r11, r11, 0x0080 /* Add 8M */
- mtspr SPRN_MD_RPN, r11
-#endif
-
- /* Since the cache is enabled according to the information we
- * just loaded into the TLB, invalidate and enable the caches here.
- * We should probably check/set other modes....later.
- */
- lis r8, IDC_INVALL@h
- mtspr SPRN_IC_CST, r8
- mtspr SPRN_DC_CST, r8
- lis r8, IDC_ENABLE@h
- mtspr SPRN_IC_CST, r8
-#ifdef CONFIG_8xx_COPYBACK
- mtspr SPRN_DC_CST, r8
-#else
- /* For a debug option, I left this here to easily enable
- * the write through cache mode
- */
- lis r8, DC_SFWT@h
- mtspr SPRN_DC_CST, r8
- lis r8, IDC_ENABLE@h
- mtspr SPRN_DC_CST, r8
-#endif
- blr
-
-
-/*
- * Set up to use a given MMU context.
- * r3 is context number, r4 is PGD pointer.
- *
- * We place the physical address of the new task page directory loaded
- * into the MMU base register, and set the ASID compare register with
- * the new "context."
- */
-_GLOBAL(set_context)
-
-#ifdef CONFIG_BDI_SWITCH
- /* Context switch the PTE pointer for the Abatron BDI2000.
- * The PGDIR is passed as second argument.
- */
- lis r5, KERNELBASE@h
- lwz r5, 0xf0(r5)
- stw r4, 0x4(r5)
-#endif
-
-#ifdef CONFIG_8xx_CPU6
- lis r6, cpu6_errata_word@h
- ori r6, r6, cpu6_errata_word@l
- tophys (r4, r4)
- li r7, 0x3980
- stw r7, 12(r6)
- lwz r7, 12(r6)
- mtspr SPRN_M_TWB, r4 /* Update MMU base address */
- li r7, 0x3380
- stw r7, 12(r6)
- lwz r7, 12(r6)
- mtspr SPRN_M_CASID, r3 /* Update context */
-#else
- mtspr SPRN_M_CASID,r3 /* Update context */
- tophys (r4, r4)
- mtspr SPRN_M_TWB, r4 /* and pgd */
-#endif
- SYNC
- blr
-
-#ifdef CONFIG_8xx_CPU6
-/* It's here because it is unique to the 8xx.
- * It is important we get called with interrupts disabled. I used to
- * do that, but it appears that all code that calls this already had
- * interrupt disabled.
- */
- .globl set_dec_cpu6
-set_dec_cpu6:
- lis r7, cpu6_errata_word@h
- ori r7, r7, cpu6_errata_word@l
- li r4, 0x2c00
- stw r4, 8(r7)
- lwz r4, 8(r7)
- mtspr 22, r3 /* Update Decrementer */
- SYNC
- blr
-#endif
-
-/*
- * 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
- .globl sdata
-sdata:
- .globl empty_zero_page
-empty_zero_page:
- .space 4096
-
- .globl swapper_pg_dir
-swapper_pg_dir:
- .space 4096
-
-/*
- * This space gets a copy of optional info passed to us by the bootstrap
- * Used to pass parameters into the kernel like root=/dev/sda1, etc.
- */
- .globl cmd_line
-cmd_line:
- .space 512
-
-/* Room for two PTE table poiners, usually the kernel and current user
- * pointer to their respective root page table (pgdir).
- */
-abatron_pteptrs:
- .space 8
-
-#ifdef CONFIG_8xx_CPU6
- .globl cpu6_errata_word
-cpu6_errata_word:
- .space 16
-#endif
-
diff --git a/arch/ppc/kernel/head_booke.h b/arch/ppc/kernel/head_booke.h
deleted file mode 100644
index 166d597b6db2..000000000000
--- a/arch/ppc/kernel/head_booke.h
+++ /dev/null
@@ -1,308 +0,0 @@
-#ifndef __HEAD_BOOKE_H__
-#define __HEAD_BOOKE_H__
-
-/*
- * Macros used for common Book-e exception handling
- */
-
-#define SET_IVOR(vector_number, vector_label) \
- li r26,vector_label@l; \
- mtspr SPRN_IVOR##vector_number,r26; \
- sync
-
-#define NORMAL_EXCEPTION_PROLOG \
- mtspr SPRN_SPRG0,r10; /* save two registers to work with */\
- mtspr SPRN_SPRG1,r11; \
- mtspr SPRN_SPRG4W,r1; \
- mfcr r10; /* save CR in r10 for now */\
- mfspr r11,SPRN_SRR1; /* check whether user or kernel */\
- andi. r11,r11,MSR_PR; \
- beq 1f; \
- mfspr r1,SPRN_SPRG3; /* if from user, start at top of */\
- lwz r1,THREAD_INFO-THREAD(r1); /* this thread's kernel stack */\
- addi r1,r1,THREAD_SIZE; \
-1: subi r1,r1,INT_FRAME_SIZE; /* Allocate an exception frame */\
- mr r11,r1; \
- stw r10,_CCR(r11); /* save various registers */\
- stw r12,GPR12(r11); \
- stw r9,GPR9(r11); \
- mfspr r10,SPRN_SPRG0; \
- stw r10,GPR10(r11); \
- mfspr r12,SPRN_SPRG1; \
- stw r12,GPR11(r11); \
- mflr r10; \
- stw r10,_LINK(r11); \
- mfspr r10,SPRN_SPRG4R; \
- mfspr r12,SPRN_SRR0; \
- stw r10,GPR1(r11); \
- mfspr r9,SPRN_SRR1; \
- stw r10,0(r11); \
- rlwinm r9,r9,0,14,12; /* clear MSR_WE (necessary?) */\
- stw r0,GPR0(r11); \
- SAVE_4GPRS(3, r11); \
- SAVE_2GPRS(7, r11)
-
-/* To handle the additional exception priority levels on 40x and Book-E
- * processors we allocate a 4k stack per additional priority level. The various
- * head_xxx.S files allocate space (exception_stack_top) for each priority's
- * stack times the number of CPUs
- *
- * On 40x critical is the only additional level
- * On 44x/e500 we have critical and machine check
- * On e200 we have critical and debug (machine check occurs via critical)
- *
- * Additionally we reserve a SPRG for each priority level so we can free up a
- * GPR to use as the base for indirect access to the exception stacks. This
- * is necessary since the MMU is always on, for Book-E parts, and the stacks
- * are offset from KERNELBASE.
- *
- */
-#define BOOKE_EXCEPTION_STACK_SIZE (8192)
-
-/* CRIT_SPRG only used in critical exception handling */
-#define CRIT_SPRG SPRN_SPRG2
-/* MCHECK_SPRG only used in machine check exception handling */
-#define MCHECK_SPRG SPRN_SPRG6W
-
-#define MCHECK_STACK_TOP (exception_stack_top - 4096)
-#define CRIT_STACK_TOP (exception_stack_top)
-
-/* only on e200 for now */
-#define DEBUG_STACK_TOP (exception_stack_top - 4096)
-#define DEBUG_SPRG SPRN_SPRG6W
-
-#ifdef CONFIG_SMP
-#define BOOKE_LOAD_EXC_LEVEL_STACK(level) \
- mfspr r8,SPRN_PIR; \
- mulli r8,r8,BOOKE_EXCEPTION_STACK_SIZE; \
- neg r8,r8; \
- addis r8,r8,level##_STACK_TOP@ha; \
- addi r8,r8,level##_STACK_TOP@l
-#else
-#define BOOKE_LOAD_EXC_LEVEL_STACK(level) \
- lis r8,level##_STACK_TOP@h; \
- ori r8,r8,level##_STACK_TOP@l
-#endif
-
-/*
- * Exception prolog for critical/machine check exceptions. This is a
- * little different from the normal exception prolog above since a
- * critical/machine check exception can potentially occur at any point
- * during normal exception processing. Thus we cannot use the same SPRG
- * registers as the normal prolog above. Instead we use a portion of the
- * critical/machine check exception stack at low physical addresses.
- */
-#define EXC_LEVEL_EXCEPTION_PROLOG(exc_level, exc_level_srr0, exc_level_srr1) \
- mtspr exc_level##_SPRG,r8; \
- BOOKE_LOAD_EXC_LEVEL_STACK(exc_level);/* r8 points to the exc_level stack*/ \
- stw r10,GPR10-INT_FRAME_SIZE(r8); \
- stw r11,GPR11-INT_FRAME_SIZE(r8); \
- mfcr r10; /* save CR in r10 for now */\
- mfspr r11,exc_level_srr1; /* check whether user or kernel */\
- andi. r11,r11,MSR_PR; \
- mr r11,r8; \
- mfspr r8,exc_level##_SPRG; \
- beq 1f; \
- /* COMING FROM USER MODE */ \
- mfspr r11,SPRN_SPRG3; /* if from user, start at top of */\
- lwz r11,THREAD_INFO-THREAD(r11); /* this thread's kernel stack */\
- addi r11,r11,THREAD_SIZE; \
-1: subi r11,r11,INT_FRAME_SIZE; /* Allocate an exception frame */\
- stw r10,_CCR(r11); /* save various registers */\
- stw r12,GPR12(r11); \
- stw r9,GPR9(r11); \
- mflr r10; \
- stw r10,_LINK(r11); \
- mfspr r12,SPRN_DEAR; /* save DEAR and ESR in the frame */\
- stw r12,_DEAR(r11); /* since they may have had stuff */\
- mfspr r9,SPRN_ESR; /* in them at the point where the */\
- stw r9,_ESR(r11); /* exception was taken */\
- mfspr r12,exc_level_srr0; \
- stw r1,GPR1(r11); \
- mfspr r9,exc_level_srr1; \
- stw r1,0(r11); \
- mr r1,r11; \
- rlwinm r9,r9,0,14,12; /* clear MSR_WE (necessary?) */\
- stw r0,GPR0(r11); \
- SAVE_4GPRS(3, r11); \
- SAVE_2GPRS(7, r11)
-
-#define CRITICAL_EXCEPTION_PROLOG \
- EXC_LEVEL_EXCEPTION_PROLOG(CRIT, SPRN_CSRR0, SPRN_CSRR1)
-#define DEBUG_EXCEPTION_PROLOG \
- EXC_LEVEL_EXCEPTION_PROLOG(DEBUG, SPRN_DSRR0, SPRN_DSRR1)
-#define MCHECK_EXCEPTION_PROLOG \
- EXC_LEVEL_EXCEPTION_PROLOG(MCHECK, SPRN_MCSRR0, SPRN_MCSRR1)
-
-/*
- * Exception vectors.
- */
-#define START_EXCEPTION(label) \
- .align 5; \
-label:
-
-#define FINISH_EXCEPTION(func) \
- bl transfer_to_handler_full; \
- .long func; \
- .long ret_from_except_full
-
-#define EXCEPTION(n, label, hdlr, xfer) \
- START_EXCEPTION(label); \
- NORMAL_EXCEPTION_PROLOG; \
- addi r3,r1,STACK_FRAME_OVERHEAD; \
- xfer(n, hdlr)
-
-#define CRITICAL_EXCEPTION(n, label, hdlr) \
- START_EXCEPTION(label); \
- CRITICAL_EXCEPTION_PROLOG; \
- addi r3,r1,STACK_FRAME_OVERHEAD; \
- EXC_XFER_TEMPLATE(hdlr, n+2, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \
- NOCOPY, crit_transfer_to_handler, \
- ret_from_crit_exc)
-
-#define MCHECK_EXCEPTION(n, label, hdlr) \
- START_EXCEPTION(label); \
- MCHECK_EXCEPTION_PROLOG; \
- mfspr r5,SPRN_ESR; \
- stw r5,_ESR(r11); \
- addi r3,r1,STACK_FRAME_OVERHEAD; \
- EXC_XFER_TEMPLATE(hdlr, n+2, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \
- NOCOPY, mcheck_transfer_to_handler, \
- ret_from_mcheck_exc)
-
-#define EXC_XFER_TEMPLATE(hdlr, trap, msr, copyee, tfer, ret) \
- li r10,trap; \
- stw r10,TRAP(r11); \
- lis r10,msr@h; \
- ori r10,r10,msr@l; \
- copyee(r10, r9); \
- bl tfer; \
- .long hdlr; \
- .long ret
-
-#define COPY_EE(d, s) rlwimi d,s,0,16,16
-#define NOCOPY(d, s)
-
-#define EXC_XFER_STD(n, hdlr) \
- EXC_XFER_TEMPLATE(hdlr, n, MSR_KERNEL, NOCOPY, transfer_to_handler_full, \
- ret_from_except_full)
-
-#define EXC_XFER_LITE(n, hdlr) \
- EXC_XFER_TEMPLATE(hdlr, n+1, MSR_KERNEL, NOCOPY, transfer_to_handler, \
- ret_from_except)
-
-#define EXC_XFER_EE(n, hdlr) \
- EXC_XFER_TEMPLATE(hdlr, n, MSR_KERNEL, COPY_EE, transfer_to_handler_full, \
- ret_from_except_full)
-
-#define EXC_XFER_EE_LITE(n, hdlr) \
- EXC_XFER_TEMPLATE(hdlr, n+1, MSR_KERNEL, COPY_EE, transfer_to_handler, \
- ret_from_except)
-
-/* Check for a single step debug exception while in an exception
- * handler before state has been saved. This is to catch the case
- * where an instruction that we are trying to single step causes
- * an exception (eg ITLB/DTLB miss) and thus the first instruction of
- * the exception handler generates a single step debug exception.
- *
- * If we get a debug trap on the first instruction of an exception handler,
- * we reset the MSR_DE in the _exception handler's_ MSR (the debug trap is
- * a critical exception, so we are using SPRN_CSRR1 to manipulate the MSR).
- * The exception handler was handling a non-critical interrupt, so it will
- * save (and later restore) the MSR via SPRN_CSRR1, which will still have
- * the MSR_DE bit set.
- */
-#define DEBUG_EXCEPTION \
- START_EXCEPTION(Debug); \
- CRITICAL_EXCEPTION_PROLOG; \
- \
- /* \
- * If there is a single step or branch-taken exception in an \
- * exception entry sequence, it was probably meant to apply to \
- * the code where the exception occurred (since exception entry \
- * doesn't turn off DE automatically). We simulate the effect \
- * of turning off DE on entry to an exception handler by turning \
- * off DE in the CSRR1 value and clearing the debug status. \
- */ \
- mfspr r10,SPRN_DBSR; /* check single-step/branch taken */ \
- andis. r10,r10,DBSR_IC@h; \
- beq+ 2f; \
- \
- lis r10,KERNELBASE@h; /* check if exception in vectors */ \
- ori r10,r10,KERNELBASE@l; \
- cmplw r12,r10; \
- blt+ 2f; /* addr below exception vectors */ \
- \
- lis r10,Debug@h; \
- ori r10,r10,Debug@l; \
- cmplw r12,r10; \
- bgt+ 2f; /* addr above exception vectors */ \
- \
- /* here it looks like we got an inappropriate debug exception. */ \
-1: rlwinm r9,r9,0,~MSR_DE; /* clear DE in the CSRR1 value */ \
- lis r10,DBSR_IC@h; /* clear the IC event */ \
- mtspr SPRN_DBSR,r10; \
- /* restore state and get out */ \
- lwz r10,_CCR(r11); \
- lwz r0,GPR0(r11); \
- lwz r1,GPR1(r11); \
- mtcrf 0x80,r10; \
- mtspr SPRN_CSRR0,r12; \
- mtspr SPRN_CSRR1,r9; \
- lwz r9,GPR9(r11); \
- lwz r12,GPR12(r11); \
- mtspr CRIT_SPRG,r8; \
- BOOKE_LOAD_EXC_LEVEL_STACK(CRIT); /* r8 points to the debug stack */ \
- lwz r10,GPR10-INT_FRAME_SIZE(r8); \
- lwz r11,GPR11-INT_FRAME_SIZE(r8); \
- mfspr r8,CRIT_SPRG; \
- \
- rfci; \
- b .; \
- \
- /* continue normal handling for a critical exception... */ \
-2: mfspr r4,SPRN_DBSR; \
- addi r3,r1,STACK_FRAME_OVERHEAD; \
- EXC_XFER_TEMPLATE(DebugException, 0x2002, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), NOCOPY, crit_transfer_to_handler, ret_from_crit_exc)
-
-#define INSTRUCTION_STORAGE_EXCEPTION \
- START_EXCEPTION(InstructionStorage) \
- NORMAL_EXCEPTION_PROLOG; \
- mfspr r5,SPRN_ESR; /* Grab the ESR and save it */ \
- stw r5,_ESR(r11); \
- mr r4,r12; /* Pass SRR0 as arg2 */ \
- li r5,0; /* Pass zero as arg3 */ \
- EXC_XFER_EE_LITE(0x0400, handle_page_fault)
-
-#define ALIGNMENT_EXCEPTION \
- START_EXCEPTION(Alignment) \
- NORMAL_EXCEPTION_PROLOG; \
- mfspr r4,SPRN_DEAR; /* Grab the DEAR and save it */ \
- stw r4,_DEAR(r11); \
- addi r3,r1,STACK_FRAME_OVERHEAD; \
- EXC_XFER_EE(0x0600, alignment_exception)
-
-#define PROGRAM_EXCEPTION \
- START_EXCEPTION(Program) \
- NORMAL_EXCEPTION_PROLOG; \
- mfspr r4,SPRN_ESR; /* Grab the ESR and save it */ \
- stw r4,_ESR(r11); \
- addi r3,r1,STACK_FRAME_OVERHEAD; \
- EXC_XFER_STD(0x0700, program_check_exception)
-
-#define DECREMENTER_EXCEPTION \
- START_EXCEPTION(Decrementer) \
- NORMAL_EXCEPTION_PROLOG; \
- lis r0,TSR_DIS@h; /* Setup the DEC interrupt mask */ \
- mtspr SPRN_TSR,r0; /* Clear the DEC interrupt */ \
- addi r3,r1,STACK_FRAME_OVERHEAD; \
- EXC_XFER_LITE(0x0900, timer_interrupt)
-
-#define FP_UNAVAILABLE_EXCEPTION \
- START_EXCEPTION(FloatingPointUnavailable) \
- NORMAL_EXCEPTION_PROLOG; \
- bne load_up_fpu; /* if from user, just load it up */ \
- addi r3,r1,STACK_FRAME_OVERHEAD; \
- EXC_XFER_EE_LITE(0x800, kernel_fp_unavailable_exception)
-
-#endif /* __HEAD_BOOKE_H__ */
diff --git a/arch/ppc/kernel/machine_kexec.c b/arch/ppc/kernel/machine_kexec.c
deleted file mode 100644
index a469ba438cbe..000000000000
--- a/arch/ppc/kernel/machine_kexec.c
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * machine_kexec.c - handle transition of Linux booting another kernel
- * Copyright (C) 2002-2003 Eric Biederman <ebiederm@xmission.com>
- *
- * GameCube/ppc32 port Copyright (C) 2004 Albert Herranz
- *
- * This source code is licensed under the GNU General Public License,
- * Version 2. See the file COPYING for more details.
- */
-
-#include <linux/mm.h>
-#include <linux/kexec.h>
-#include <linux/delay.h>
-#include <linux/reboot.h>
-#include <asm/pgtable.h>
-#include <asm/pgalloc.h>
-#include <asm/mmu_context.h>
-#include <asm/io.h>
-#include <asm/hw_irq.h>
-#include <asm/cacheflush.h>
-#include <asm/machdep.h>
-
-typedef NORET_TYPE void (*relocate_new_kernel_t)(
- unsigned long indirection_page,
- unsigned long reboot_code_buffer,
- unsigned long start_address) ATTRIB_NORET;
-
-extern const unsigned char relocate_new_kernel[];
-extern const unsigned int relocate_new_kernel_size;
-
-void machine_shutdown(void)
-{
- if (ppc_md.machine_shutdown)
- ppc_md.machine_shutdown();
-}
-
-void machine_crash_shutdown(struct pt_regs *regs)
-{
- if (ppc_md.machine_crash_shutdown)
- ppc_md.machine_crash_shutdown();
-}
-
-/*
- * Do what every setup is needed on image and the
- * reboot code buffer to allow us to avoid allocations
- * later.
- */
-int machine_kexec_prepare(struct kimage *image)
-{
- if (ppc_md.machine_kexec_prepare)
- return ppc_md.machine_kexec_prepare(image);
- /*
- * Fail if platform doesn't provide its own machine_kexec_prepare
- * implementation.
- */
- return -ENOSYS;
-}
-
-void machine_kexec_cleanup(struct kimage *image)
-{
- if (ppc_md.machine_kexec_cleanup)
- ppc_md.machine_kexec_cleanup(image);
-}
-
-/*
- * Do not allocate memory (or fail in any way) in machine_kexec().
- * We are past the point of no return, committed to rebooting now.
- */
-NORET_TYPE void machine_kexec(struct kimage *image)
-{
- if (ppc_md.machine_kexec)
- ppc_md.machine_kexec(image);
- else {
- /*
- * Fall back to normal restart if platform doesn't provide
- * its own kexec function, and user insist to kexec...
- */
- machine_restart(NULL);
- }
- for(;;);
-}
-
-/*
- * This is a generic machine_kexec function suitable at least for
- * non-OpenFirmware embedded platforms.
- * It merely copies the image relocation code to the control page and
- * jumps to it.
- * A platform specific function may just call this one.
- */
-void machine_kexec_simple(struct kimage *image)
-{
- unsigned long page_list;
- unsigned long reboot_code_buffer, reboot_code_buffer_phys;
- relocate_new_kernel_t rnk;
-
- /* Interrupts aren't acceptable while we reboot */
- local_irq_disable();
-
- page_list = image->head;
-
- /* we need both effective and real address here */
- reboot_code_buffer =
- (unsigned long)page_address(image->control_code_page);
- reboot_code_buffer_phys = virt_to_phys((void *)reboot_code_buffer);
-
- /* copy our kernel relocation code to the control code page */
- memcpy((void *)reboot_code_buffer, relocate_new_kernel,
- relocate_new_kernel_size);
-
- flush_icache_range(reboot_code_buffer,
- reboot_code_buffer + KEXEC_CONTROL_CODE_SIZE);
- printk(KERN_INFO "Bye!\n");
-
- /* now call it */
- rnk = (relocate_new_kernel_t) reboot_code_buffer;
- (*rnk)(page_list, reboot_code_buffer_phys, image->start);
-}
-
diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S
deleted file mode 100644
index d5e0dfc9ffec..000000000000
--- a/arch/ppc/kernel/misc.S
+++ /dev/null
@@ -1,868 +0,0 @@
-/*
- * This file contains miscellaneous low-level functions.
- * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
- *
- * Largely rewritten by Cort Dougan (cort@cs.nmt.edu)
- * and Paul Mackerras.
- *
- * 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/sys.h>
-#include <asm/unistd.h>
-#include <asm/errno.h>
-#include <asm/processor.h>
-#include <asm/page.h>
-#include <asm/cache.h>
-#include <asm/cputable.h>
-#include <asm/mmu.h>
-#include <asm/ppc_asm.h>
-#include <asm/thread_info.h>
-#include <asm/asm-offsets.h>
-
-#ifdef CONFIG_8xx
-#define ISYNC_8xx isync
-#else
-#define ISYNC_8xx
-#endif
- .text
-
- .align 5
-_GLOBAL(__delay)
- cmpwi 0,r3,0
- mtctr r3
- beqlr
-1: bdnz 1b
- blr
-
-/*
- * Returns (address we're running at) - (address we were linked at)
- * for use before the text and data are mapped to KERNELBASE.
- */
-_GLOBAL(reloc_offset)
- mflr r0
- bl 1f
-1: mflr r3
- lis r4,1b@ha
- addi r4,r4,1b@l
- subf r3,r4,r3
- mtlr r0
- blr
-
-/*
- * add_reloc_offset(x) returns x + reloc_offset().
- */
-_GLOBAL(add_reloc_offset)
- mflr r0
- bl 1f
-1: mflr r5
- lis r4,1b@ha
- addi r4,r4,1b@l
- subf r5,r4,r5
- add r3,r3,r5
- mtlr r0
- blr
-
-/*
- * sub_reloc_offset(x) returns x - reloc_offset().
- */
-_GLOBAL(sub_reloc_offset)
- mflr r0
- bl 1f
-1: mflr r5
- lis r4,1b@ha
- addi r4,r4,1b@l
- subf r5,r4,r5
- subf r3,r5,r3
- mtlr r0
- blr
-
-/*
- * reloc_got2 runs through the .got2 section adding an offset
- * to each entry.
- */
-_GLOBAL(reloc_got2)
- mflr r11
- lis r7,__got2_start@ha
- addi r7,r7,__got2_start@l
- lis r8,__got2_end@ha
- addi r8,r8,__got2_end@l
- subf r8,r7,r8
- srwi. r8,r8,2
- beqlr
- mtctr r8
- bl 1f
-1: mflr r0
- lis r4,1b@ha
- addi r4,r4,1b@l
- subf r0,r4,r0
- add r7,r0,r7
-2: lwz r0,0(r7)
- add r0,r0,r3
- stw r0,0(r7)
- addi r7,r7,4
- bdnz 2b
- mtlr r11
- blr
-
-/*
- * call_setup_cpu - call the setup_cpu function for this cpu
- * r3 = data offset, r24 = cpu number
- *
- * Setup function is called with:
- * r3 = data offset
- * r4 = ptr to CPU spec (relocated)
- */
-_GLOBAL(call_setup_cpu)
- addis r4,r3,cur_cpu_spec@ha
- addi r4,r4,cur_cpu_spec@l
- lwz r4,0(r4)
- add r4,r4,r3
- lwz r5,CPU_SPEC_SETUP(r4)
- cmpi 0,r5,0
- add r5,r5,r3
- beqlr
- mtctr r5
- bctr
-
-/*
- * complement mask on the msr then "or" some values on.
- * _nmask_and_or_msr(nmask, value_to_or)
- */
-_GLOBAL(_nmask_and_or_msr)
- mfmsr r0 /* Get current msr */
- andc r0,r0,r3 /* And off the bits set in r3 (first parm) */
- or r0,r0,r4 /* Or on the bits in r4 (second parm) */
- SYNC /* Some chip revs have problems here... */
- mtmsr r0 /* Update machine state */
- isync
- blr /* Done */
-
-
-/*
- * Flush MMU TLB
- */
-_GLOBAL(_tlbia)
-#if defined(CONFIG_40x)
- sync /* Flush to memory before changing mapping */
- tlbia
- isync /* Flush shadow TLB */
-#elif defined(CONFIG_44x)
- li r3,0
- sync
-
- /* Load high watermark */
- lis r4,tlb_44x_hwater@ha
- lwz r5,tlb_44x_hwater@l(r4)
-
-1: tlbwe r3,r3,PPC44x_TLB_PAGEID
- addi r3,r3,1
- cmpw 0,r3,r5
- ble 1b
-
- isync
-#else /* !(CONFIG_40x || CONFIG_44x) */
-#if defined(CONFIG_SMP)
- rlwinm r8,r1,0,0,18
- lwz r8,TI_CPU(r8)
- oris r8,r8,10
- mfmsr r10
- SYNC
- rlwinm r0,r10,0,17,15 /* clear bit 16 (MSR_EE) */
- rlwinm r0,r0,0,28,26 /* clear DR */
- mtmsr r0
- SYNC_601
- isync
- lis r9,mmu_hash_lock@h
- ori r9,r9,mmu_hash_lock@l
- tophys(r9,r9)
-10: lwarx r7,0,r9
- cmpwi 0,r7,0
- bne- 10b
- stwcx. r8,0,r9
- bne- 10b
- sync
- tlbia
- sync
- TLBSYNC
- li r0,0
- stw r0,0(r9) /* clear mmu_hash_lock */
- mtmsr r10
- SYNC_601
- isync
-#else /* CONFIG_SMP */
- sync
- tlbia
- sync
-#endif /* CONFIG_SMP */
-#endif /* ! defined(CONFIG_40x) */
- blr
-
-/*
- * Flush MMU TLB for a particular address
- */
-_GLOBAL(_tlbie)
-#if defined(CONFIG_40x)
- /* We run the search with interrupts disabled because we have to change
- * the PID and I don't want to preempt when that happens.
- */
- mfmsr r5
- mfspr r6,SPRN_PID
- wrteei 0
- mtspr SPRN_PID,r4
- tlbsx. r3, 0, r3
- mtspr SPRN_PID,r6
- wrtee r5
- bne 10f
- sync
- /* There are only 64 TLB entries, so r3 < 64, which means bit 25 is clear.
- * Since 25 is the V bit in the TLB_TAG, loading this value will invalidate
- * the TLB entry. */
- tlbwe r3, r3, TLB_TAG
- isync
-10:
-#elif defined(CONFIG_44x)
- mfspr r5,SPRN_MMUCR
- rlwimi r5,r4,0,24,31 /* Set TID */
-
- /* We have to run the search with interrupts disabled, even critical
- * and debug interrupts (in fact the only critical exceptions we have
- * are debug and machine check). Otherwise an interrupt which causes
- * a TLB miss can clobber the MMUCR between the mtspr and the tlbsx. */
- mfmsr r4
- lis r6,(MSR_EE|MSR_CE|MSR_ME|MSR_DE)@ha
- addi r6,r6,(MSR_EE|MSR_CE|MSR_ME|MSR_DE)@l
- andc r6,r4,r6
- mtmsr r6
- mtspr SPRN_MMUCR,r5
- tlbsx. r3, 0, r3
- mtmsr r4
- bne 10f
- sync
- /* There are only 64 TLB entries, so r3 < 64,
- * which means bit 22, is clear. Since 22 is
- * the V bit in the TLB_PAGEID, loading this
- * value will invalidate the TLB entry.
- */
- tlbwe r3, r3, PPC44x_TLB_PAGEID
- isync
-10:
-#else /* !(CONFIG_40x || CONFIG_44x) */
-#if defined(CONFIG_SMP)
- rlwinm r8,r1,0,0,18
- lwz r8,TI_CPU(r8)
- oris r8,r8,11
- mfmsr r10
- SYNC
- rlwinm r0,r10,0,17,15 /* clear bit 16 (MSR_EE) */
- rlwinm r0,r0,0,28,26 /* clear DR */
- mtmsr r0
- SYNC_601
- isync
- lis r9,mmu_hash_lock@h
- ori r9,r9,mmu_hash_lock@l
- tophys(r9,r9)
-10: lwarx r7,0,r9
- cmpwi 0,r7,0
- bne- 10b
- stwcx. r8,0,r9
- bne- 10b
- eieio
- tlbie r3
- sync
- TLBSYNC
- li r0,0
- stw r0,0(r9) /* clear mmu_hash_lock */
- mtmsr r10
- SYNC_601
- isync
-#else /* CONFIG_SMP */
- tlbie r3
- sync
-#endif /* CONFIG_SMP */
-#endif /* ! CONFIG_40x */
- blr
-
-/*
- * Flush instruction cache.
- * This is a no-op on the 601.
- */
-_GLOBAL(flush_instruction_cache)
-#if defined(CONFIG_8xx)
- isync
- lis r5, IDC_INVALL@h
- mtspr SPRN_IC_CST, r5
-#elif defined(CONFIG_4xx)
-#ifdef CONFIG_403GCX
- li r3, 512
- mtctr r3
- lis r4, KERNELBASE@h
-1: iccci 0, r4
- addi r4, r4, 16
- bdnz 1b
-#else
- lis r3, KERNELBASE@h
- iccci 0,r3
-#endif
-#else
- mfspr r3,SPRN_PVR
- rlwinm r3,r3,16,16,31
- cmpwi 0,r3,1
- beqlr /* for 601, do nothing */
- /* 603/604 processor - use invalidate-all bit in HID0 */
- mfspr r3,SPRN_HID0
- ori r3,r3,HID0_ICFI
- mtspr SPRN_HID0,r3
-#endif /* CONFIG_8xx/4xx */
- isync
- blr
-
-/*
- * Write any modified data cache blocks out to memory
- * and invalidate the corresponding instruction cache blocks.
- * This is a no-op on the 601.
- *
- * __flush_icache_range(unsigned long start, unsigned long stop)
- */
-_GLOBAL(__flush_icache_range)
-BEGIN_FTR_SECTION
- blr /* for 601, do nothing */
-END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
- li r5,L1_CACHE_BYTES-1
- andc r3,r3,r5
- subf r4,r3,r4
- add r4,r4,r5
- srwi. r4,r4,L1_CACHE_SHIFT
- beqlr
- mtctr r4
- mr r6,r3
-1: dcbst 0,r3
- addi r3,r3,L1_CACHE_BYTES
- bdnz 1b
- sync /* wait for dcbst's to get to ram */
- mtctr r4
-2: icbi 0,r6
- addi r6,r6,L1_CACHE_BYTES
- bdnz 2b
- sync /* additional sync needed on g4 */
- isync
- blr
-/*
- * Write any modified data cache blocks out to memory.
- * Does not invalidate the corresponding cache lines (especially for
- * any corresponding instruction cache).
- *
- * clean_dcache_range(unsigned long start, unsigned long stop)
- */
-_GLOBAL(clean_dcache_range)
- li r5,L1_CACHE_BYTES-1
- andc r3,r3,r5
- subf r4,r3,r4
- add r4,r4,r5
- srwi. r4,r4,L1_CACHE_SHIFT
- beqlr
- mtctr r4
-
-1: dcbst 0,r3
- addi r3,r3,L1_CACHE_BYTES
- bdnz 1b
- sync /* wait for dcbst's to get to ram */
- blr
-
-/*
- * Write any modified data cache blocks out to memory and invalidate them.
- * Does not invalidate the corresponding instruction cache blocks.
- *
- * flush_dcache_range(unsigned long start, unsigned long stop)
- */
-_GLOBAL(flush_dcache_range)
- li r5,L1_CACHE_BYTES-1
- andc r3,r3,r5
- subf r4,r3,r4
- add r4,r4,r5
- srwi. r4,r4,L1_CACHE_SHIFT
- beqlr
- mtctr r4
-
-1: dcbf 0,r3
- addi r3,r3,L1_CACHE_BYTES
- bdnz 1b
- sync /* wait for dcbst's to get to ram */
- blr
-
-/*
- * Like above, but invalidate the D-cache. This is used by the 8xx
- * to invalidate the cache so the PPC core doesn't get stale data
- * from the CPM (no cache snooping here :-).
- *
- * invalidate_dcache_range(unsigned long start, unsigned long stop)
- */
-_GLOBAL(invalidate_dcache_range)
- li r5,L1_CACHE_BYTES-1
- andc r3,r3,r5
- subf r4,r3,r4
- add r4,r4,r5
- srwi. r4,r4,L1_CACHE_SHIFT
- beqlr
- mtctr r4
-
-1: dcbi 0,r3
- addi r3,r3,L1_CACHE_BYTES
- bdnz 1b
- sync /* wait for dcbi's to get to ram */
- blr
-
-#ifdef CONFIG_NOT_COHERENT_CACHE
-/*
- * 40x cores have 8K or 16K dcache and 32 byte line size.
- * 44x has a 32K dcache and 32 byte line size.
- * 8xx has 1, 2, 4, 8K variants.
- * For now, cover the worst case of the 44x.
- * Must be called with external interrupts disabled.
- */
-#define CACHE_NWAYS 64
-#define CACHE_NLINES 16
-
-_GLOBAL(flush_dcache_all)
- li r4, (2 * CACHE_NWAYS * CACHE_NLINES)
- mtctr r4
- lis r5, KERNELBASE@h
-1: lwz r3, 0(r5) /* Load one word from every line */
- addi r5, r5, L1_CACHE_BYTES
- bdnz 1b
- blr
-#endif /* CONFIG_NOT_COHERENT_CACHE */
-
-/*
- * Flush a particular page from the data cache to RAM.
- * Note: this is necessary because the instruction cache does *not*
- * snoop from the data cache.
- * This is a no-op on the 601 which has a unified cache.
- *
- * void __flush_dcache_icache(void *page)
- */
-_GLOBAL(__flush_dcache_icache)
-BEGIN_FTR_SECTION
- blr /* for 601, do nothing */
-END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
- rlwinm r3,r3,0,0,19 /* Get page base address */
- li r4,4096/L1_CACHE_BYTES /* Number of lines in a page */
- mtctr r4
- mr r6,r3
-0: dcbst 0,r3 /* Write line to ram */
- addi r3,r3,L1_CACHE_BYTES
- bdnz 0b
- sync
-#ifndef CONFIG_44x
- /* We don't flush the icache on 44x. Those have a virtual icache
- * and we don't have access to the virtual address here (it's
- * not the page vaddr but where it's mapped in user space). The
- * flushing of the icache on these is handled elsewhere, when
- * a change in the address space occurs, before returning to
- * user space
- */
- mtctr r4
-1: icbi 0,r6
- addi r6,r6,L1_CACHE_BYTES
- bdnz 1b
- sync
- isync
-#endif /* CONFIG_44x */
- blr
-
-/*
- * Flush a particular page from the data cache to RAM, identified
- * by its physical address. We turn off the MMU so we can just use
- * the physical address (this may be a highmem page without a kernel
- * mapping).
- *
- * void __flush_dcache_icache_phys(unsigned long physaddr)
- */
-_GLOBAL(__flush_dcache_icache_phys)
-BEGIN_FTR_SECTION
- blr /* for 601, do nothing */
-END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
- mfmsr r10
- rlwinm r0,r10,0,28,26 /* clear DR */
- mtmsr r0
- isync
- rlwinm r3,r3,0,0,19 /* Get page base address */
- li r4,4096/L1_CACHE_BYTES /* Number of lines in a page */
- mtctr r4
- mr r6,r3
-0: dcbst 0,r3 /* Write line to ram */
- addi r3,r3,L1_CACHE_BYTES
- bdnz 0b
- sync
- mtctr r4
-1: icbi 0,r6
- addi r6,r6,L1_CACHE_BYTES
- bdnz 1b
- sync
- mtmsr r10 /* restore DR */
- isync
- blr
-
-/*
- * Clear pages using the dcbz instruction, which doesn't cause any
- * memory traffic (except to write out any cache lines which get
- * displaced). This only works on cacheable memory.
- *
- * void clear_pages(void *page, int order) ;
- */
-_GLOBAL(clear_pages)
- li r0,4096/L1_CACHE_BYTES
- slw r0,r0,r4
- mtctr r0
-#ifdef CONFIG_8xx
- li r4, 0
-1: stw r4, 0(r3)
- stw r4, 4(r3)
- stw r4, 8(r3)
- stw r4, 12(r3)
-#else
-1: dcbz 0,r3
-#endif
- addi r3,r3,L1_CACHE_BYTES
- bdnz 1b
- blr
-
-/*
- * Copy a whole page. We use the dcbz instruction on the destination
- * to reduce memory traffic (it eliminates the unnecessary reads of
- * the destination into cache). This requires that the destination
- * is cacheable.
- */
-#define COPY_16_BYTES \
- lwz r6,4(r4); \
- lwz r7,8(r4); \
- lwz r8,12(r4); \
- lwzu r9,16(r4); \
- stw r6,4(r3); \
- stw r7,8(r3); \
- stw r8,12(r3); \
- stwu r9,16(r3)
-
-_GLOBAL(copy_page)
- addi r3,r3,-4
- addi r4,r4,-4
-
-#ifdef CONFIG_8xx
- /* don't use prefetch on 8xx */
- li r0,4096/L1_CACHE_BYTES
- mtctr r0
-1: COPY_16_BYTES
- bdnz 1b
- blr
-
-#else /* not 8xx, we can prefetch */
- li r5,4
-
-#if MAX_COPY_PREFETCH > 1
- li r0,MAX_COPY_PREFETCH
- li r11,4
- mtctr r0
-11: dcbt r11,r4
- addi r11,r11,L1_CACHE_BYTES
- bdnz 11b
-#else /* MAX_COPY_PREFETCH == 1 */
- dcbt r5,r4
- li r11,L1_CACHE_BYTES+4
-#endif /* MAX_COPY_PREFETCH */
- li r0,4096/L1_CACHE_BYTES - MAX_COPY_PREFETCH
- crclr 4*cr0+eq
-2:
- mtctr r0
-1:
- dcbt r11,r4
- dcbz r5,r3
- COPY_16_BYTES
-#if L1_CACHE_BYTES >= 32
- COPY_16_BYTES
-#if L1_CACHE_BYTES >= 64
- COPY_16_BYTES
- COPY_16_BYTES
-#if L1_CACHE_BYTES >= 128
- COPY_16_BYTES
- COPY_16_BYTES
- COPY_16_BYTES
- COPY_16_BYTES
-#endif
-#endif
-#endif
- bdnz 1b
- beqlr
- crnot 4*cr0+eq,4*cr0+eq
- li r0,MAX_COPY_PREFETCH
- li r11,4
- b 2b
-#endif /* CONFIG_8xx */
-
-/*
- * void atomic_clear_mask(atomic_t mask, atomic_t *addr)
- * void atomic_set_mask(atomic_t mask, atomic_t *addr);
- */
-_GLOBAL(atomic_clear_mask)
-10: lwarx r5,0,r4
- andc r5,r5,r3
- PPC405_ERR77(0,r4)
- stwcx. r5,0,r4
- bne- 10b
- blr
-_GLOBAL(atomic_set_mask)
-10: lwarx r5,0,r4
- or r5,r5,r3
- PPC405_ERR77(0,r4)
- stwcx. r5,0,r4
- bne- 10b
- blr
-
-/*
- * I/O string operations
- *
- * insb(port, buf, len)
- * outsb(port, buf, len)
- * insw(port, buf, len)
- * outsw(port, buf, len)
- * insl(port, buf, len)
- * outsl(port, buf, len)
- * insw_ns(port, buf, len)
- * outsw_ns(port, buf, len)
- * insl_ns(port, buf, len)
- * outsl_ns(port, buf, len)
- *
- * The *_ns versions don't do byte-swapping.
- */
-_GLOBAL(_insb)
- cmpwi 0,r5,0
- mtctr r5
- subi r4,r4,1
- blelr-
-00: lbz r5,0(r3)
-01: eieio
-02: stbu r5,1(r4)
- ISYNC_8xx
- .section .fixup,"ax"
-03: blr
- .text
- .section __ex_table, "a"
- .align 2
- .long 00b, 03b
- .long 01b, 03b
- .long 02b, 03b
- .text
- bdnz 00b
- blr
-
-_GLOBAL(_outsb)
- cmpwi 0,r5,0
- mtctr r5
- subi r4,r4,1
- blelr-
-00: lbzu r5,1(r4)
-01: stb r5,0(r3)
-02: eieio
- ISYNC_8xx
- .section .fixup,"ax"
-03: blr
- .text
- .section __ex_table, "a"
- .align 2
- .long 00b, 03b
- .long 01b, 03b
- .long 02b, 03b
- .text
- bdnz 00b
- blr
-
-_GLOBAL(_insw_ns)
- cmpwi 0,r5,0
- mtctr r5
- subi r4,r4,2
- blelr-
-00: lhz r5,0(r3)
-01: eieio
-02: sthu r5,2(r4)
- ISYNC_8xx
- .section .fixup,"ax"
-03: blr
- .text
- .section __ex_table, "a"
- .align 2
- .long 00b, 03b
- .long 01b, 03b
- .long 02b, 03b
- .text
- bdnz 00b
- blr
-
-_GLOBAL(_outsw_ns)
- cmpwi 0,r5,0
- mtctr r5
- subi r4,r4,2
- blelr-
-00: lhzu r5,2(r4)
-01: sth r5,0(r3)
-02: eieio
- ISYNC_8xx
- .section .fixup,"ax"
-03: blr
- .text
- .section __ex_table, "a"
- .align 2
- .long 00b, 03b
- .long 01b, 03b
- .long 02b, 03b
- .text
- bdnz 00b
- blr
-
-_GLOBAL(_insl_ns)
- cmpwi 0,r5,0
- mtctr r5
- subi r4,r4,4
- blelr-
-00: lwz r5,0(r3)
-01: eieio
-02: stwu r5,4(r4)
- ISYNC_8xx
- .section .fixup,"ax"
-03: blr
- .text
- .section __ex_table, "a"
- .align 2
- .long 00b, 03b
- .long 01b, 03b
- .long 02b, 03b
- .text
- bdnz 00b
- blr
-
-_GLOBAL(_outsl_ns)
- cmpwi 0,r5,0
- mtctr r5
- subi r4,r4,4
- blelr-
-00: lwzu r5,4(r4)
-01: stw r5,0(r3)
-02: eieio
- ISYNC_8xx
- .section .fixup,"ax"
-03: blr
- .text
- .section __ex_table, "a"
- .align 2
- .long 00b, 03b
- .long 01b, 03b
- .long 02b, 03b
- .text
- bdnz 00b
- blr
-
-/*
- * Extended precision shifts.
- *
- * Updated to be valid for shift counts from 0 to 63 inclusive.
- * -- Gabriel
- *
- * R3/R4 has 64 bit value
- * R5 has shift count
- * result in R3/R4
- *
- * ashrdi3: arithmetic right shift (sign propagation)
- * lshrdi3: logical right shift
- * ashldi3: left shift
- */
-_GLOBAL(__ashrdi3)
- subfic r6,r5,32
- srw r4,r4,r5 # LSW = count > 31 ? 0 : LSW >> count
- addi r7,r5,32 # could be xori, or addi with -32
- slw r6,r3,r6 # t1 = count > 31 ? 0 : MSW << (32-count)
- rlwinm r8,r7,0,32 # t3 = (count < 32) ? 32 : 0
- sraw r7,r3,r7 # t2 = MSW >> (count-32)
- or r4,r4,r6 # LSW |= t1
- slw r7,r7,r8 # t2 = (count < 32) ? 0 : t2
- sraw r3,r3,r5 # MSW = MSW >> count
- or r4,r4,r7 # LSW |= t2
- blr
-
-_GLOBAL(__ashldi3)
- subfic r6,r5,32
- slw r3,r3,r5 # MSW = count > 31 ? 0 : MSW << count
- addi r7,r5,32 # could be xori, or addi with -32
- srw r6,r4,r6 # t1 = count > 31 ? 0 : LSW >> (32-count)
- slw r7,r4,r7 # t2 = count < 32 ? 0 : LSW << (count-32)
- or r3,r3,r6 # MSW |= t1
- slw r4,r4,r5 # LSW = LSW << count
- or r3,r3,r7 # MSW |= t2
- blr
-
-_GLOBAL(__lshrdi3)
- subfic r6,r5,32
- srw r4,r4,r5 # LSW = count > 31 ? 0 : LSW >> count
- addi r7,r5,32 # could be xori, or addi with -32
- slw r6,r3,r6 # t1 = count > 31 ? 0 : MSW << (32-count)
- srw r7,r3,r7 # t2 = count < 32 ? 0 : MSW >> (count-32)
- or r4,r4,r6 # LSW |= t1
- srw r3,r3,r5 # MSW = MSW >> count
- or r4,r4,r7 # LSW |= t2
- blr
-
-_GLOBAL(abs)
- srawi r4,r3,31
- xor r3,r3,r4
- sub r3,r3,r4
- blr
-
-_GLOBAL(_get_SP)
- mr r3,r1 /* Close enough */
- blr
-
-/*
- * Create a kernel thread
- * kernel_thread(fn, arg, flags)
- */
-_GLOBAL(kernel_thread)
- stwu r1,-16(r1)
- stw r30,8(r1)
- stw r31,12(r1)
- mr r30,r3 /* function */
- mr r31,r4 /* argument */
- ori r3,r5,CLONE_VM /* flags */
- oris r3,r3,CLONE_UNTRACED>>16
- li r4,0 /* new sp (unused) */
- li r0,__NR_clone
- sc
- cmpwi 0,r3,0 /* parent or child? */
- bne 1f /* return if parent */
- li r0,0 /* make top-level stack frame */
- stwu r0,-16(r1)
- mtlr r30 /* fn addr in lr */
- mr r3,r31 /* load arg and call fn */
- PPC440EP_ERR42
- blrl
- li r0,__NR_exit /* exit if function returns */
- li r3,0
- sc
-1: lwz r30,8(r1)
- lwz r31,12(r1)
- addi r1,r1,16
- blr
-
-_GLOBAL(kernel_execve)
- li r0,__NR_execve
- sc
- bnslr
- neg r3,r3
- blr
-
-/*
- * This routine is just here to keep GCC happy - sigh...
- */
-_GLOBAL(__main)
- blr
-
diff --git a/arch/ppc/kernel/pci.c b/arch/ppc/kernel/pci.c
deleted file mode 100644
index df3ef6db072c..000000000000
--- a/arch/ppc/kernel/pci.c
+++ /dev/null
@@ -1,1233 +0,0 @@
-/*
- * Common prep/chrp pci routines. -- Cort
- */
-
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/string.h>
-#include <linux/init.h>
-#include <linux/capability.h>
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/bootmem.h>
-
-#include <asm/processor.h>
-#include <asm/io.h>
-#include <asm/prom.h>
-#include <asm/sections.h>
-#include <asm/pci-bridge.h>
-#include <asm/byteorder.h>
-#include <asm/irq.h>
-#include <asm/uaccess.h>
-#include <asm/machdep.h>
-
-#undef DEBUG
-
-#ifdef DEBUG
-#define DBG(x...) printk(x)
-#else
-#define DBG(x...)
-#endif
-
-unsigned long isa_io_base = 0;
-unsigned long isa_mem_base = 0;
-unsigned long pci_dram_offset = 0;
-int pcibios_assign_bus_offset = 1;
-
-void pcibios_make_OF_bus_map(void);
-
-static int pci_relocate_bridge_resource(struct pci_bus *bus, int i);
-static int probe_resource(struct pci_bus *parent, struct resource *pr,
- struct resource *res, struct resource **conflict);
-static void update_bridge_base(struct pci_bus *bus, int i);
-static void pcibios_fixup_resources(struct pci_dev* dev);
-static void fixup_broken_pcnet32(struct pci_dev* dev);
-static int reparent_resources(struct resource *parent, struct resource *res);
-static void fixup_cpc710_pci64(struct pci_dev* dev);
-
-/* By default, we don't re-assign bus numbers.
- */
-int pci_assign_all_buses;
-
-struct pci_controller* hose_head;
-struct pci_controller** hose_tail = &hose_head;
-
-static int pci_bus_count;
-
-static void
-fixup_broken_pcnet32(struct pci_dev* dev)
-{
- if ((dev->class>>8 == PCI_CLASS_NETWORK_ETHERNET)) {
- dev->vendor = PCI_VENDOR_ID_AMD;
- pci_write_config_word(dev, PCI_VENDOR_ID, PCI_VENDOR_ID_AMD);
- }
-}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TRIDENT, PCI_ANY_ID, fixup_broken_pcnet32);
-
-static void
-fixup_cpc710_pci64(struct pci_dev* dev)
-{
- /* Hide the PCI64 BARs from the kernel as their content doesn't
- * fit well in the resource management
- */
- dev->resource[0].start = dev->resource[0].end = 0;
- dev->resource[0].flags = 0;
- dev->resource[1].start = dev->resource[1].end = 0;
- dev->resource[1].flags = 0;
-}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CPC710_PCI64, fixup_cpc710_pci64);
-
-static void
-pcibios_fixup_resources(struct pci_dev *dev)
-{
- struct pci_controller* hose = (struct pci_controller *)dev->sysdata;
- int i;
- unsigned long offset;
-
- if (!hose) {
- printk(KERN_ERR "No hose for PCI dev %s!\n", pci_name(dev));
- return;
- }
- for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
- struct resource *res = dev->resource + i;
- if (!res->flags)
- continue;
- if (res->end == 0xffffffff) {
- DBG("PCI:%s Resource %d [%016llx-%016llx] is unassigned\n",
- pci_name(dev), i,
- (unsigned long long)res->start,
- (unsigned long long)res->end);
- res->end -= res->start;
- res->start = 0;
- res->flags |= IORESOURCE_UNSET;
- continue;
- }
- offset = 0;
- if (res->flags & IORESOURCE_MEM) {
- offset = hose->pci_mem_offset;
- } else if (res->flags & IORESOURCE_IO) {
- offset = (unsigned long) hose->io_base_virt
- - isa_io_base;
- }
- if (offset != 0) {
- res->start += offset;
- res->end += offset;
-#ifdef DEBUG
- printk("Fixup res %d (%lx) of dev %s: %lx -> %lx\n",
- i, res->flags, pci_name(dev),
- res->start - offset, res->start);
-#endif
- }
- }
-
- /* Call machine specific resource fixup */
- if (ppc_md.pcibios_fixup_resources)
- ppc_md.pcibios_fixup_resources(dev);
-}
-DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pcibios_fixup_resources);
-
-void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
- struct resource *res)
-{
- unsigned long offset = 0;
- struct pci_controller *hose = dev->sysdata;
-
- if (hose && res->flags & IORESOURCE_IO)
- offset = (unsigned long)hose->io_base_virt - isa_io_base;
- else if (hose && res->flags & IORESOURCE_MEM)
- offset = hose->pci_mem_offset;
- region->start = res->start - offset;
- region->end = res->end - offset;
-}
-EXPORT_SYMBOL(pcibios_resource_to_bus);
-
-void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
- struct pci_bus_region *region)
-{
- unsigned long offset = 0;
- struct pci_controller *hose = dev->sysdata;
-
- if (hose && res->flags & IORESOURCE_IO)
- offset = (unsigned long)hose->io_base_virt - isa_io_base;
- else if (hose && res->flags & IORESOURCE_MEM)
- offset = hose->pci_mem_offset;
- res->start = region->start + offset;
- res->end = region->end + offset;
-}
-EXPORT_SYMBOL(pcibios_bus_to_resource);
-
-/*
- * We need to avoid collisions with `mirrored' VGA ports
- * and other strange ISA hardware, so we always want the
- * addresses to be allocated in the 0x000-0x0ff region
- * modulo 0x400.
- *
- * Why? Because some silly external IO cards only decode
- * the low 10 bits of the IO address. The 0x00-0xff region
- * is reserved for motherboard devices that decode all 16
- * bits, so it's ok to allocate at, say, 0x2800-0x28ff,
- * but we want to try to avoid allocating at 0x2900-0x2bff
- * which might have be mirrored at 0x0100-0x03ff..
- */
-void pcibios_align_resource(void *data, struct resource *res,
- resource_size_t size, resource_size_t align)
-{
- struct pci_dev *dev = data;
-
- if (res->flags & IORESOURCE_IO) {
- resource_size_t start = res->start;
-
- if (size > 0x100) {
- printk(KERN_ERR "PCI: I/O Region %s/%d too large"
- " (%lld bytes)\n", pci_name(dev),
- dev->resource - res, (unsigned long long)size);
- }
-
- if (start & 0x300) {
- start = (start + 0x3ff) & ~0x3ff;
- res->start = start;
- }
- }
-}
-EXPORT_SYMBOL(pcibios_align_resource);
-
-/*
- * Handle resources of PCI devices. If the world were perfect, we could
- * just allocate all the resource regions and do nothing more. It isn't.
- * On the other hand, we cannot just re-allocate all devices, as it would
- * require us to know lots of host bridge internals. So we attempt to
- * keep as much of the original configuration as possible, but tweak it
- * when it's found to be wrong.
- *
- * Known BIOS problems we have to work around:
- * - I/O or memory regions not configured
- * - regions configured, but not enabled in the command register
- * - bogus I/O addresses above 64K used
- * - expansion ROMs left enabled (this may sound harmless, but given
- * the fact the PCI specs explicitly allow address decoders to be
- * shared between expansion ROMs and other resource regions, it's
- * at least dangerous)
- *
- * Our solution:
- * (1) Allocate resources for all buses behind PCI-to-PCI bridges.
- * This gives us fixed barriers on where we can allocate.
- * (2) Allocate resources for all enabled devices. If there is
- * a collision, just mark the resource as unallocated. Also
- * disable expansion ROMs during this step.
- * (3) Try to allocate resources for disabled devices. If the
- * resources were assigned correctly, everything goes well,
- * if they weren't, they won't disturb allocation of other
- * resources.
- * (4) Assign new addresses to resources which were either
- * not configured at all or misconfigured. If explicitly
- * requested by the user, configure expansion ROM address
- * as well.
- */
-
-static void __init
-pcibios_allocate_bus_resources(struct list_head *bus_list)
-{
- struct pci_bus *bus;
- int i;
- struct resource *res, *pr;
-
- /* Depth-First Search on bus tree */
- list_for_each_entry(bus, bus_list, node) {
- for (i = 0; i < 4; ++i) {
- if ((res = bus->resource[i]) == NULL || !res->flags
- || res->start > res->end)
- continue;
- if (bus->parent == NULL)
- pr = (res->flags & IORESOURCE_IO)?
- &ioport_resource: &iomem_resource;
- else {
- pr = pci_find_parent_resource(bus->self, res);
- if (pr == res) {
- /* this happens when the generic PCI
- * code (wrongly) decides that this
- * bridge is transparent -- paulus
- */
- continue;
- }
- }
-
- DBG("PCI: bridge rsrc %llx..%llx (%lx), parent %p\n",
- (unsigned long long)res->start,
- (unsigned long long)res->end, res->flags, pr);
- if (pr) {
- if (request_resource(pr, res) == 0)
- continue;
- /*
- * Must be a conflict with an existing entry.
- * Move that entry (or entries) under the
- * bridge resource and try again.
- */
- if (reparent_resources(pr, res) == 0)
- continue;
- }
- printk(KERN_ERR "PCI: Cannot allocate resource region "
- "%d of PCI bridge %d\n", i, bus->number);
- if (pci_relocate_bridge_resource(bus, i))
- bus->resource[i] = NULL;
- }
- pcibios_allocate_bus_resources(&bus->children);
- }
-}
-
-/*
- * Reparent resource children of pr that conflict with res
- * under res, and make res replace those children.
- */
-static int __init
-reparent_resources(struct resource *parent, struct resource *res)
-{
- struct resource *p, **pp;
- struct resource **firstpp = NULL;
-
- for (pp = &parent->child; (p = *pp) != NULL; pp = &p->sibling) {
- if (p->end < res->start)
- continue;
- if (res->end < p->start)
- break;
- if (p->start < res->start || p->end > res->end)
- return -1; /* not completely contained */
- if (firstpp == NULL)
- firstpp = pp;
- }
- if (firstpp == NULL)
- return -1; /* didn't find any conflicting entries? */
- res->parent = parent;
- res->child = *firstpp;
- res->sibling = *pp;
- *firstpp = res;
- *pp = NULL;
- for (p = res->child; p != NULL; p = p->sibling) {
- p->parent = res;
- DBG(KERN_INFO "PCI: reparented %s [%llx..%llx] under %s\n",
- p->name, (unsigned long long)p->start,
- (unsigned long long)p->end, res->name);
- }
- return 0;
-}
-
-/*
- * A bridge has been allocated a range which is outside the range
- * of its parent bridge, so it needs to be moved.
- */
-static int __init
-pci_relocate_bridge_resource(struct pci_bus *bus, int i)
-{
- struct resource *res, *pr, *conflict;
- unsigned long try, size;
- int j;
- struct pci_bus *parent = bus->parent;
-
- if (parent == NULL) {
- /* shouldn't ever happen */
- printk(KERN_ERR "PCI: can't move host bridge resource\n");
- return -1;
- }
- res = bus->resource[i];
- if (res == NULL)
- return -1;
- pr = NULL;
- for (j = 0; j < 4; j++) {
- struct resource *r = parent->resource[j];
- if (!r)
- continue;
- if ((res->flags ^ r->flags) & (IORESOURCE_IO | IORESOURCE_MEM))
- continue;
- if (!((res->flags ^ r->flags) & IORESOURCE_PREFETCH)) {
- pr = r;
- break;
- }
- if (res->flags & IORESOURCE_PREFETCH)
- pr = r;
- }
- if (pr == NULL)
- return -1;
- size = res->end - res->start;
- if (pr->start > pr->end || size > pr->end - pr->start)
- return -1;
- try = pr->end;
- for (;;) {
- res->start = try - size;
- res->end = try;
- if (probe_resource(bus->parent, pr, res, &conflict) == 0)
- break;
- if (conflict->start <= pr->start + size)
- return -1;
- try = conflict->start - 1;
- }
- if (request_resource(pr, res)) {
- DBG(KERN_ERR "PCI: huh? couldn't move to %llx..%llx\n",
- (unsigned long long)res->start,
- (unsigned long long)res->end);
- return -1; /* "can't happen" */
- }
- update_bridge_base(bus, i);
- printk(KERN_INFO "PCI: bridge %d resource %d moved to %llx..%llx\n",
- bus->number, i, (unsigned long long)res->start,
- (unsigned long long)res->end);
- return 0;
-}
-
-static int __init
-probe_resource(struct pci_bus *parent, struct resource *pr,
- struct resource *res, struct resource **conflict)
-{
- struct pci_bus *bus;
- struct pci_dev *dev;
- struct resource *r;
- int i;
-
- for (r = pr->child; r != NULL; r = r->sibling) {
- if (r->end >= res->start && res->end >= r->start) {
- *conflict = r;
- return 1;
- }
- }
- list_for_each_entry(bus, &parent->children, node) {
- for (i = 0; i < 4; ++i) {
- if ((r = bus->resource[i]) == NULL)
- continue;
- if (!r->flags || r->start > r->end || r == res)
- continue;
- if (pci_find_parent_resource(bus->self, r) != pr)
- continue;
- if (r->end >= res->start && res->end >= r->start) {
- *conflict = r;
- return 1;
- }
- }
- }
- list_for_each_entry(dev, &parent->devices, bus_list) {
- for (i = 0; i < 6; ++i) {
- r = &dev->resource[i];
- if (!r->flags || (r->flags & IORESOURCE_UNSET))
- continue;
- if (pci_find_parent_resource(dev, r) != pr)
- continue;
- if (r->end >= res->start && res->end >= r->start) {
- *conflict = r;
- return 1;
- }
- }
- }
- return 0;
-}
-
-static void __init
-update_bridge_base(struct pci_bus *bus, int i)
-{
- struct resource *res = bus->resource[i];
- u8 io_base_lo, io_limit_lo;
- u16 mem_base, mem_limit;
- u16 cmd;
- unsigned long start, end, off;
- struct pci_dev *dev = bus->self;
- struct pci_controller *hose = dev->sysdata;
-
- if (!hose) {
- printk("update_bridge_base: no hose?\n");
- return;
- }
- pci_read_config_word(dev, PCI_COMMAND, &cmd);
- pci_write_config_word(dev, PCI_COMMAND,
- cmd & ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY));
- if (res->flags & IORESOURCE_IO) {
- off = (unsigned long) hose->io_base_virt - isa_io_base;
- start = res->start - off;
- end = res->end - off;
- io_base_lo = (start >> 8) & PCI_IO_RANGE_MASK;
- io_limit_lo = (end >> 8) & PCI_IO_RANGE_MASK;
- if (end > 0xffff) {
- pci_write_config_word(dev, PCI_IO_BASE_UPPER16,
- start >> 16);
- pci_write_config_word(dev, PCI_IO_LIMIT_UPPER16,
- end >> 16);
- io_base_lo |= PCI_IO_RANGE_TYPE_32;
- } else
- io_base_lo |= PCI_IO_RANGE_TYPE_16;
- pci_write_config_byte(dev, PCI_IO_BASE, io_base_lo);
- pci_write_config_byte(dev, PCI_IO_LIMIT, io_limit_lo);
-
- } else if ((res->flags & (IORESOURCE_MEM | IORESOURCE_PREFETCH))
- == IORESOURCE_MEM) {
- off = hose->pci_mem_offset;
- mem_base = ((res->start - off) >> 16) & PCI_MEMORY_RANGE_MASK;
- mem_limit = ((res->end - off) >> 16) & PCI_MEMORY_RANGE_MASK;
- pci_write_config_word(dev, PCI_MEMORY_BASE, mem_base);
- pci_write_config_word(dev, PCI_MEMORY_LIMIT, mem_limit);
-
- } else if ((res->flags & (IORESOURCE_MEM | IORESOURCE_PREFETCH))
- == (IORESOURCE_MEM | IORESOURCE_PREFETCH)) {
- off = hose->pci_mem_offset;
- mem_base = ((res->start - off) >> 16) & PCI_PREF_RANGE_MASK;
- mem_limit = ((res->end - off) >> 16) & PCI_PREF_RANGE_MASK;
- pci_write_config_word(dev, PCI_PREF_MEMORY_BASE, mem_base);
- pci_write_config_word(dev, PCI_PREF_MEMORY_LIMIT, mem_limit);
-
- } else {
- DBG(KERN_ERR "PCI: ugh, bridge %s res %d has flags=%lx\n",
- pci_name(dev), i, res->flags);
- }
- pci_write_config_word(dev, PCI_COMMAND, cmd);
-}
-
-static inline void alloc_resource(struct pci_dev *dev, int idx)
-{
- struct resource *pr, *r = &dev->resource[idx];
-
- DBG("PCI:%s: Resource %d: %016llx-%016llx (f=%lx)\n",
- pci_name(dev), idx, (unsigned long long)r->start,
- (unsigned long long)r->end, r->flags);
- pr = pci_find_parent_resource(dev, r);
- if (!pr || request_resource(pr, r) < 0) {
- printk(KERN_ERR "PCI: Cannot allocate resource region %d"
- " of device %s\n", idx, pci_name(dev));
- if (pr)
- DBG("PCI: parent is %p: %016llx-%016llx (f=%lx)\n",
- pr, (unsigned long long)pr->start,
- (unsigned long long)pr->end, pr->flags);
- /* We'll assign a new address later */
- r->flags |= IORESOURCE_UNSET;
- r->end -= r->start;
- r->start = 0;
- }
-}
-
-static void __init
-pcibios_allocate_resources(int pass)
-{
- struct pci_dev *dev = NULL;
- int idx, disabled;
- u16 command;
- struct resource *r;
-
- for_each_pci_dev(dev) {
- pci_read_config_word(dev, PCI_COMMAND, &command);
- for (idx = 0; idx < 6; idx++) {
- r = &dev->resource[idx];
- if (r->parent) /* Already allocated */
- continue;
- if (!r->flags || (r->flags & IORESOURCE_UNSET))
- continue; /* Not assigned at all */
- if (r->flags & IORESOURCE_IO)
- disabled = !(command & PCI_COMMAND_IO);
- else
- disabled = !(command & PCI_COMMAND_MEMORY);
- if (pass == disabled)
- alloc_resource(dev, idx);
- }
- if (pass)
- continue;
- r = &dev->resource[PCI_ROM_RESOURCE];
- if (r->flags & IORESOURCE_ROM_ENABLE) {
- /* Turn the ROM off, leave the resource region, but keep it unregistered. */
- u32 reg;
- DBG("PCI: Switching off ROM of %s\n", pci_name(dev));
- r->flags &= ~IORESOURCE_ROM_ENABLE;
- pci_read_config_dword(dev, dev->rom_base_reg, &reg);
- pci_write_config_dword(dev, dev->rom_base_reg,
- reg & ~PCI_ROM_ADDRESS_ENABLE);
- }
- }
-}
-
-static void __init
-pcibios_assign_resources(void)
-{
- struct pci_dev *dev = NULL;
- int idx;
- struct resource *r;
-
- for_each_pci_dev(dev) {
- int class = dev->class >> 8;
-
- /* Don't touch classless devices and host bridges */
- if (!class || class == PCI_CLASS_BRIDGE_HOST)
- continue;
-
- for (idx = 0; idx < 6; idx++) {
- r = &dev->resource[idx];
-
- /*
- * We shall assign a new address to this resource,
- * either because the BIOS (sic) forgot to do so
- * or because we have decided the old address was
- * unusable for some reason.
- */
- if ((r->flags & IORESOURCE_UNSET) && r->end &&
- (!ppc_md.pcibios_enable_device_hook ||
- !ppc_md.pcibios_enable_device_hook(dev, 1))) {
- r->flags &= ~IORESOURCE_UNSET;
- pci_assign_resource(dev, idx);
- }
- }
-
-#if 0 /* don't assign ROMs */
- r = &dev->resource[PCI_ROM_RESOURCE];
- r->end -= r->start;
- r->start = 0;
- if (r->end)
- pci_assign_resource(dev, PCI_ROM_RESOURCE);
-#endif
- }
-}
-
-
-static int next_controller_index;
-
-struct pci_controller * __init
-pcibios_alloc_controller(void)
-{
- struct pci_controller *hose;
-
- hose = (struct pci_controller *)alloc_bootmem(sizeof(*hose));
- memset(hose, 0, sizeof(struct pci_controller));
-
- *hose_tail = hose;
- hose_tail = &hose->next;
-
- hose->index = next_controller_index++;
-
- return hose;
-}
-
-void pcibios_make_OF_bus_map(void)
-{
-}
-
-static int __init
-pcibios_init(void)
-{
- struct pci_controller *hose;
- struct pci_bus *bus;
- int next_busno;
-
- printk(KERN_INFO "PCI: Probing PCI hardware\n");
-
- /* Scan all of the recorded PCI controllers. */
- for (next_busno = 0, hose = hose_head; hose; hose = hose->next) {
- if (pci_assign_all_buses)
- hose->first_busno = next_busno;
- hose->last_busno = 0xff;
- bus = pci_scan_bus(hose->first_busno, hose->ops, hose);
- hose->last_busno = bus->subordinate;
- if (pci_assign_all_buses || next_busno <= hose->last_busno)
- next_busno = hose->last_busno + pcibios_assign_bus_offset;
- }
- pci_bus_count = next_busno;
-
- /* OpenFirmware based machines need a map of OF bus
- * numbers vs. kernel bus numbers since we may have to
- * remap them.
- */
- if (pci_assign_all_buses && have_of)
- pcibios_make_OF_bus_map();
-
- /* Do machine dependent PCI interrupt routing */
- if (ppc_md.pci_swizzle && ppc_md.pci_map_irq)
- pci_fixup_irqs(ppc_md.pci_swizzle, ppc_md.pci_map_irq);
-
- /* Call machine dependent fixup */
- if (ppc_md.pcibios_fixup)
- ppc_md.pcibios_fixup();
-
- /* Allocate and assign resources */
- pcibios_allocate_bus_resources(&pci_root_buses);
- pcibios_allocate_resources(0);
- pcibios_allocate_resources(1);
- pcibios_assign_resources();
-
- /* Call machine dependent post-init code */
- if (ppc_md.pcibios_after_init)
- ppc_md.pcibios_after_init();
-
- return 0;
-}
-
-subsys_initcall(pcibios_init);
-
-unsigned char __init
-common_swizzle(struct pci_dev *dev, unsigned char *pinp)
-{
- struct pci_controller *hose = dev->sysdata;
-
- if (dev->bus->number != hose->first_busno) {
- u8 pin = *pinp;
- do {
- pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
- /* Move up the chain of bridges. */
- dev = dev->bus->self;
- } while (dev->bus->self);
- *pinp = pin;
-
- /* The slot is the idsel of the last bridge. */
- }
- return PCI_SLOT(dev->devfn);
-}
-
-unsigned long resource_fixup(struct pci_dev * dev, struct resource * res,
- unsigned long start, unsigned long size)
-{
- return start;
-}
-
-void __init pcibios_fixup_bus(struct pci_bus *bus)
-{
- struct pci_controller *hose = (struct pci_controller *) bus->sysdata;
- unsigned long io_offset;
- struct resource *res;
- int i;
-
- io_offset = (unsigned long)hose->io_base_virt - isa_io_base;
- if (bus->parent == NULL) {
- /* This is a host bridge - fill in its resources */
- hose->bus = bus;
-
- bus->resource[0] = res = &hose->io_resource;
- if (!res->flags) {
- if (io_offset)
- printk(KERN_ERR "I/O resource not set for host"
- " bridge %d\n", hose->index);
- res->start = 0;
- res->end = IO_SPACE_LIMIT;
- res->flags = IORESOURCE_IO;
- }
- res->start += io_offset;
- res->end += io_offset;
-
- for (i = 0; i < 3; ++i) {
- res = &hose->mem_resources[i];
- if (!res->flags) {
- if (i > 0)
- continue;
- printk(KERN_ERR "Memory resource not set for "
- "host bridge %d\n", hose->index);
- res->start = hose->pci_mem_offset;
- res->end = ~0U;
- res->flags = IORESOURCE_MEM;
- }
- bus->resource[i+1] = res;
- }
- } else {
- /* This is a subordinate bridge */
- pci_read_bridge_bases(bus);
-
- for (i = 0; i < 4; ++i) {
- if ((res = bus->resource[i]) == NULL)
- continue;
- if (!res->flags)
- continue;
- if (io_offset && (res->flags & IORESOURCE_IO)) {
- res->start += io_offset;
- res->end += io_offset;
- } else if (hose->pci_mem_offset
- && (res->flags & IORESOURCE_MEM)) {
- res->start += hose->pci_mem_offset;
- res->end += hose->pci_mem_offset;
- }
- }
- }
-
- if (ppc_md.pcibios_fixup_bus)
- ppc_md.pcibios_fixup_bus(bus);
-}
-
-char __init *pcibios_setup(char *str)
-{
- return str;
-}
-
-/* the next one is stolen from the alpha port... */
-void __init
-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 */
-}
-
-int pcibios_enable_device(struct pci_dev *dev, int mask)
-{
- if (ppc_md.pcibios_enable_device_hook)
- if (ppc_md.pcibios_enable_device_hook(dev, 0))
- return -EINVAL;
-
- return pci_enable_resources(dev, mask);
-}
-
-struct pci_controller*
-pci_bus_to_hose(int bus)
-{
- struct pci_controller* hose = hose_head;
-
- for (; hose; hose = hose->next)
- if (bus >= hose->first_busno && bus <= hose->last_busno)
- return hose;
- return NULL;
-}
-
-void __iomem *
-pci_bus_io_base(unsigned int bus)
-{
- struct pci_controller *hose;
-
- hose = pci_bus_to_hose(bus);
- if (!hose)
- return NULL;
- return hose->io_base_virt;
-}
-
-unsigned long
-pci_bus_io_base_phys(unsigned int bus)
-{
- struct pci_controller *hose;
-
- hose = pci_bus_to_hose(bus);
- if (!hose)
- return 0;
- return hose->io_base_phys;
-}
-
-unsigned long
-pci_bus_mem_base_phys(unsigned int bus)
-{
- struct pci_controller *hose;
-
- hose = pci_bus_to_hose(bus);
- if (!hose)
- return 0;
- return hose->pci_mem_offset;
-}
-
-unsigned long
-pci_resource_to_bus(struct pci_dev *pdev, struct resource *res)
-{
- /* Hack alert again ! See comments in chrp_pci.c
- */
- struct pci_controller* hose =
- (struct pci_controller *)pdev->sysdata;
- if (hose && res->flags & IORESOURCE_MEM)
- return res->start - hose->pci_mem_offset;
- /* We may want to do something with IOs here... */
- return res->start;
-}
-
-
-static struct resource *__pci_mmap_make_offset(struct pci_dev *dev,
- resource_size_t *offset,
- enum pci_mmap_state mmap_state)
-{
- struct pci_controller *hose = pci_bus_to_hose(dev->bus->number);
- unsigned long io_offset = 0;
- int i, res_bit;
-
- if (hose == 0)
- return NULL; /* should never happen */
-
- /* If memory, add on the PCI bridge address offset */
- if (mmap_state == pci_mmap_mem) {
-#if 0 /* See comment in pci_resource_to_user() for why this is disabled */
- *offset += hose->pci_mem_offset;
-#endif
- res_bit = IORESOURCE_MEM;
- } else {
- io_offset = hose->io_base_virt - ___IO_BASE;
- *offset += io_offset;
- res_bit = IORESOURCE_IO;
- }
-
- /*
- * Check that the offset requested corresponds to one of the
- * resources of the device.
- */
- for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
- struct resource *rp = &dev->resource[i];
- int flags = rp->flags;
-
- /* treat ROM as memory (should be already) */
- if (i == PCI_ROM_RESOURCE)
- flags |= IORESOURCE_MEM;
-
- /* Active and same type? */
- if ((flags & res_bit) == 0)
- continue;
-
- /* In the range of this resource? */
- if (*offset < (rp->start & PAGE_MASK) || *offset > rp->end)
- continue;
-
- /* found it! construct the final physical address */
- if (mmap_state == pci_mmap_io)
- *offset += hose->io_base_phys - io_offset;
- return rp;
- }
-
- return NULL;
-}
-
-/*
- * Set vm_page_prot of VMA, as appropriate for this architecture, for a pci
- * device mapping.
- */
-static pgprot_t __pci_mmap_set_pgprot(struct pci_dev *dev, struct resource *rp,
- pgprot_t protection,
- enum pci_mmap_state mmap_state,
- int write_combine)
-{
- unsigned long prot = pgprot_val(protection);
-
- /* Write combine is always 0 on non-memory space mappings. On
- * memory space, if the user didn't pass 1, we check for a
- * "prefetchable" resource. This is a bit hackish, but we use
- * this to workaround the inability of /sysfs to provide a write
- * combine bit
- */
- if (mmap_state != pci_mmap_mem)
- write_combine = 0;
- else if (write_combine == 0) {
- if (rp->flags & IORESOURCE_PREFETCH)
- write_combine = 1;
- }
-
- /* XXX would be nice to have a way to ask for write-through */
- prot |= _PAGE_NO_CACHE;
- if (write_combine)
- prot &= ~_PAGE_GUARDED;
- else
- prot |= _PAGE_GUARDED;
-
- printk("PCI map for %s:%llx, prot: %lx\n", pci_name(dev),
- (unsigned long long)rp->start, prot);
-
- return __pgprot(prot);
-}
-
-/*
- * This one is used by /dev/mem and fbdev who have no clue about the
- * PCI device, it tries to find the PCI device first and calls the
- * above routine
- */
-pgprot_t pci_phys_mem_access_prot(struct file *file,
- unsigned long pfn,
- unsigned long size,
- pgprot_t protection)
-{
- struct pci_dev *pdev = NULL;
- struct resource *found = NULL;
- unsigned long prot = pgprot_val(protection);
- unsigned long offset = pfn << PAGE_SHIFT;
- int i;
-
- if (page_is_ram(pfn))
- return prot;
-
- prot |= _PAGE_NO_CACHE | _PAGE_GUARDED;
-
- for_each_pci_dev(pdev) {
- for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
- struct resource *rp = &pdev->resource[i];
- int flags = rp->flags;
-
- /* Active and same type? */
- if ((flags & IORESOURCE_MEM) == 0)
- continue;
- /* In the range of this resource? */
- if (offset < (rp->start & PAGE_MASK) ||
- offset > rp->end)
- continue;
- found = rp;
- break;
- }
- if (found)
- break;
- }
- if (found) {
- if (found->flags & IORESOURCE_PREFETCH)
- prot &= ~_PAGE_GUARDED;
- pci_dev_put(pdev);
- }
-
- DBG("non-PCI map for %lx, prot: %lx\n", offset, prot);
-
- return __pgprot(prot);
-}
-
-
-/*
- * Perform the actual remap of the pages for a PCI device mapping, as
- * appropriate for this architecture. The region in the process to map
- * is described by vm_start and vm_end members of VMA, the base physical
- * address is found in vm_pgoff.
- * The pci device structure is provided so that architectures may make mapping
- * decisions on a per-device or per-bus basis.
- *
- * Returns a negative error code on failure, zero on success.
- */
-int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
- enum pci_mmap_state mmap_state,
- int write_combine)
-{
- resource_size_t offset = vma->vm_pgoff << PAGE_SHIFT;
- struct resource *rp;
- int ret;
-
- rp = __pci_mmap_make_offset(dev, &offset, mmap_state);
- if (rp == NULL)
- return -EINVAL;
-
- vma->vm_pgoff = offset >> PAGE_SHIFT;
- vma->vm_page_prot = __pci_mmap_set_pgprot(dev, rp,
- vma->vm_page_prot,
- mmap_state, write_combine);
-
- ret = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
- vma->vm_end - vma->vm_start, vma->vm_page_prot);
-
- return ret;
-}
-
-/* Obsolete functions. Should be removed once the symbios driver
- * is fixed
- */
-unsigned long
-phys_to_bus(unsigned long pa)
-{
- struct pci_controller *hose;
- int i;
-
- for (hose = hose_head; hose; hose = hose->next) {
- for (i = 0; i < 3; ++i) {
- if (pa >= hose->mem_resources[i].start
- && pa <= hose->mem_resources[i].end) {
- /*
- * XXX the hose->pci_mem_offset really
- * only applies to mem_resources[0].
- * We need a way to store an offset for
- * the others. -- paulus
- */
- if (i == 0)
- pa -= hose->pci_mem_offset;
- return pa;
- }
- }
- }
- /* hmmm, didn't find it */
- return 0;
-}
-
-unsigned long
-pci_phys_to_bus(unsigned long pa, int busnr)
-{
- struct pci_controller* hose = pci_bus_to_hose(busnr);
- if (!hose)
- return pa;
- return pa - hose->pci_mem_offset;
-}
-
-unsigned long
-pci_bus_to_phys(unsigned int ba, int busnr)
-{
- struct pci_controller* hose = pci_bus_to_hose(busnr);
- if (!hose)
- return ba;
- return ba + hose->pci_mem_offset;
-}
-
-/* Provide information on locations of various I/O regions in physical
- * memory. Do this on a per-card basis so that we choose the right
- * root bridge.
- * Note that the returned IO or memory base is a physical address
- */
-
-long sys_pciconfig_iobase(long which, unsigned long bus, unsigned long devfn)
-{
- struct pci_controller* hose;
- long result = -EOPNOTSUPP;
-
- hose = pci_bus_to_hose(bus);
- if (!hose)
- return -ENODEV;
-
- switch (which) {
- case IOBASE_BRIDGE_NUMBER:
- return (long)hose->first_busno;
- case IOBASE_MEMORY:
- return (long)hose->pci_mem_offset;
- case IOBASE_IO:
- return (long)hose->io_base_phys;
- case IOBASE_ISA_IO:
- return (long)isa_io_base;
- case IOBASE_ISA_MEM:
- return (long)isa_mem_base;
- }
-
- return result;
-}
-
-void pci_resource_to_user(const struct pci_dev *dev, int bar,
- const struct resource *rsrc,
- resource_size_t *start, resource_size_t *end)
-{
- struct pci_controller *hose = pci_bus_to_hose(dev->bus->number);
- resource_size_t offset = 0;
-
- if (hose == NULL)
- return;
-
- if (rsrc->flags & IORESOURCE_IO)
- offset = (unsigned long)hose->io_base_virt - _IO_BASE;
-
- /* We pass a fully fixed up address to userland for MMIO instead of
- * a BAR value because X is lame and expects to be able to use that
- * to pass to /dev/mem !
- *
- * That means that we'll have potentially 64 bits values where some
- * userland apps only expect 32 (like X itself since it thinks only
- * Sparc has 64 bits MMIO) but if we don't do that, we break it on
- * 32 bits CHRPs :-(
- *
- * Hopefully, the sysfs insterface is immune to that gunk. Once X
- * has been fixed (and the fix spread enough), we can re-enable the
- * 2 lines below and pass down a BAR value to userland. In that case
- * we'll also have to re-enable the matching code in
- * __pci_mmap_make_offset().
- *
- * BenH.
- */
-#if 0
- else if (rsrc->flags & IORESOURCE_MEM)
- offset = hose->pci_mem_offset;
-#endif
-
- *start = rsrc->start - offset;
- *end = rsrc->end - offset;
-}
-
-void __init pci_init_resource(struct resource *res, resource_size_t start,
- resource_size_t end, int flags, char *name)
-{
- res->start = start;
- res->end = end;
- res->flags = flags;
- res->name = name;
- res->parent = NULL;
- res->sibling = NULL;
- res->child = NULL;
-}
-
-void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max)
-{
- resource_size_t start = pci_resource_start(dev, bar);
- resource_size_t len = pci_resource_len(dev, bar);
- unsigned long flags = pci_resource_flags(dev, bar);
-
- if (!len)
- return NULL;
- if (max && len > max)
- len = max;
- if (flags & IORESOURCE_IO)
- return ioport_map(start, len);
- if (flags & IORESOURCE_MEM)
- /* Not checking IORESOURCE_CACHEABLE because PPC does
- * not currently distinguish between ioremap and
- * ioremap_nocache.
- */
- return ioremap(start, len);
- /* What? */
- return NULL;
-}
-
-void pci_iounmap(struct pci_dev *dev, void __iomem *addr)
-{
- /* Nothing to do */
-}
-EXPORT_SYMBOL(pci_iomap);
-EXPORT_SYMBOL(pci_iounmap);
-
-unsigned long pci_address_to_pio(phys_addr_t address)
-{
- struct pci_controller* hose = hose_head;
-
- for (; hose; hose = hose->next) {
- unsigned int size = hose->io_resource.end -
- hose->io_resource.start + 1;
- if (address >= hose->io_base_phys &&
- address < (hose->io_base_phys + size)) {
- unsigned long base =
- (unsigned long)hose->io_base_virt - _IO_BASE;
- return base + (address - hose->io_base_phys);
- }
- }
- return (unsigned int)-1;
-}
-EXPORT_SYMBOL(pci_address_to_pio);
-
-/*
- * Null PCI config access functions, for the case when we can't
- * find a hose.
- */
-#define NULL_PCI_OP(rw, size, type) \
-static int \
-null_##rw##_config_##size(struct pci_dev *dev, int offset, type val) \
-{ \
- return PCIBIOS_DEVICE_NOT_FOUND; \
-}
-
-static int
-null_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
- int len, u32 *val)
-{
- return PCIBIOS_DEVICE_NOT_FOUND;
-}
-
-static int
-null_write_config(struct pci_bus *bus, unsigned int devfn, int offset,
- int len, u32 val)
-{
- return PCIBIOS_DEVICE_NOT_FOUND;
-}
-
-static struct pci_ops null_pci_ops =
-{
- null_read_config,
- null_write_config
-};
-
-/*
- * These functions are used early on before PCI scanning is done
- * and all of the pci_dev and pci_bus structures have been created.
- */
-static struct pci_bus *
-fake_pci_bus(struct pci_controller *hose, int busnr)
-{
- static struct pci_bus bus;
-
- if (hose == 0) {
- hose = pci_bus_to_hose(busnr);
- if (hose == 0)
- printk(KERN_ERR "Can't find hose for PCI bus %d!\n", busnr);
- }
- bus.number = busnr;
- bus.sysdata = hose;
- bus.ops = hose? hose->ops: &null_pci_ops;
- return &bus;
-}
-
-#define EARLY_PCI_OP(rw, size, type) \
-int early_##rw##_config_##size(struct pci_controller *hose, int bus, \
- int devfn, int offset, type value) \
-{ \
- return pci_bus_##rw##_config_##size(fake_pci_bus(hose, bus), \
- devfn, offset, value); \
-}
-
-EARLY_PCI_OP(read, byte, u8 *)
-EARLY_PCI_OP(read, word, u16 *)
-EARLY_PCI_OP(read, dword, u32 *)
-EARLY_PCI_OP(write, byte, u8)
-EARLY_PCI_OP(write, word, u16)
-EARLY_PCI_OP(write, dword, u32)
diff --git a/arch/ppc/kernel/ppc-stub.c b/arch/ppc/kernel/ppc-stub.c
deleted file mode 100644
index 5f9ee7bb67ec..000000000000
--- a/arch/ppc/kernel/ppc-stub.c
+++ /dev/null
@@ -1,866 +0,0 @@
-/*
- * ppc-stub.c: KGDB support for the Linux kernel.
- *
- * adapted from arch/sparc/kernel/sparc-stub.c for the PowerPC
- * some stuff borrowed from Paul Mackerras' xmon
- * Copyright (C) 1998 Michael AK Tesch (tesch@cs.wisc.edu)
- *
- * Modifications to run under Linux
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
- *
- * This file originally came from the gdb sources, and the
- * copyright notices have been retained below.
- */
-
-/****************************************************************************
-
- THIS SOFTWARE IS NOT COPYRIGHTED
-
- HP offers the following for use in the public domain. HP makes no
- warranty with regard to the software or its performance and the
- user accepts the software "AS IS" with all faults.
-
- HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD
- TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
-
-****************************************************************************/
-
-/****************************************************************************
- * Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $
- *
- * Module name: remcom.c $
- * Revision: 1.34 $
- * Date: 91/03/09 12:29:49 $
- * Contributor: Lake Stevens Instrument Division$
- *
- * Description: low level support for gdb debugger. $
- *
- * Considerations: only works on target hardware $
- *
- * Written by: Glenn Engel $
- * ModuleState: Experimental $
- *
- * NOTES: See Below $
- *
- * Modified for SPARC by Stu Grossman, Cygnus Support.
- *
- * This code has been extensively tested on the Fujitsu SPARClite demo board.
- *
- * To enable debugger support, two things need to happen. One, a
- * call to set_debug_traps() is necessary in order to allow any breakpoints
- * or error conditions to be properly intercepted and reported to gdb.
- * Two, a breakpoint needs to be generated to begin communication. This
- * is most easily accomplished by a call to breakpoint(). Breakpoint()
- * simulates a breakpoint by executing a trap #1.
- *
- *************
- *
- * The following gdb commands are supported:
- *
- * command function Return value
- *
- * g return the value of the CPU registers hex data or ENN
- * G set the value of the CPU registers OK or ENN
- * qOffsets Get section offsets. Reply is Text=xxx;Data=yyy;Bss=zzz
- *
- * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN
- * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN
- *
- * c Resume at current address SNN ( signal NN)
- * cAA..AA Continue at address AA..AA SNN
- *
- * s Step one instruction SNN
- * sAA..AA Step one instruction from AA..AA SNN
- *
- * k kill
- *
- * ? What was the last sigval ? SNN (signal NN)
- *
- * bBB..BB Set baud rate to BB..BB OK or BNN, then sets
- * baud rate
- *
- * All commands and responses are sent with a packet which includes a
- * checksum. A packet consists of
- *
- * $<packet info>#<checksum>.
- *
- * where
- * <packet info> :: <characters representing the command or response>
- * <checksum> :: <two hex digits computed as modulo 256 sum of <packetinfo>>
- *
- * When a packet is received, it is first acknowledged with either '+' or '-'.
- * '+' indicates a successful transfer. '-' indicates a failed transfer.
- *
- * Example:
- *
- * Host: Reply:
- * $m0,10#2a +$00010203040506070809101112131415#42
- *
- ****************************************************************************/
-
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/smp.h>
-#include <linux/smp_lock.h>
-#include <linux/init.h>
-#include <linux/sysrq.h>
-
-#include <asm/cacheflush.h>
-#include <asm/system.h>
-#include <asm/signal.h>
-#include <asm/kgdb.h>
-#include <asm/pgtable.h>
-#include <asm/ptrace.h>
-
-void breakinst(void);
-
-/*
- * BUFMAX defines the maximum number of characters in inbound/outbound buffers
- * at least NUMREGBYTES*2 are needed for register packets
- */
-#define BUFMAX 2048
-static char remcomInBuffer[BUFMAX];
-static char remcomOutBuffer[BUFMAX];
-
-static int initialized;
-static int kgdb_active;
-static int kgdb_started;
-static u_int fault_jmp_buf[100];
-static int kdebug;
-
-
-static const char hexchars[]="0123456789abcdef";
-
-/* Place where we save old trap entries for restoration - sparc*/
-/* struct tt_entry kgdb_savettable[256]; */
-/* typedef void (*trapfunc_t)(void); */
-
-static void kgdb_fault_handler(struct pt_regs *regs);
-static int handle_exception (struct pt_regs *regs);
-
-#if 0
-/* Install an exception handler for kgdb */
-static void exceptionHandler(int tnum, unsigned int *tfunc)
-{
- /* We are dorking with a live trap table, all irqs off */
-}
-#endif
-
-int
-kgdb_setjmp(long *buf)
-{
- asm ("mflr 0; stw 0,0(%0);"
- "stw 1,4(%0); stw 2,8(%0);"
- "mfcr 0; stw 0,12(%0);"
- "stmw 13,16(%0)"
- : : "r" (buf));
- /* XXX should save fp regs as well */
- return 0;
-}
-void
-kgdb_longjmp(long *buf, int val)
-{
- if (val == 0)
- val = 1;
- asm ("lmw 13,16(%0);"
- "lwz 0,12(%0); mtcrf 0x38,0;"
- "lwz 0,0(%0); lwz 1,4(%0); lwz 2,8(%0);"
- "mtlr 0; mr 3,%1"
- : : "r" (buf), "r" (val));
-}
-/* Convert ch from a hex digit to an int */
-static int
-hex(unsigned char ch)
-{
- if (ch >= 'a' && ch <= 'f')
- return ch-'a'+10;
- if (ch >= '0' && ch <= '9')
- return ch-'0';
- if (ch >= 'A' && ch <= 'F')
- return ch-'A'+10;
- return -1;
-}
-
-/* Convert the memory pointed to by mem into hex, placing result in buf.
- * Return a pointer to the last char put in buf (null), in case of mem fault,
- * return 0.
- */
-static unsigned char *
-mem2hex(const char *mem, char *buf, int count)
-{
- unsigned char ch;
- unsigned short tmp_s;
- unsigned long tmp_l;
-
- if (kgdb_setjmp((long*)fault_jmp_buf) == 0) {
- debugger_fault_handler = kgdb_fault_handler;
-
- /* Accessing 16 bit and 32 bit objects in a single
- ** load instruction is required to avoid bad side
- ** effects for some IO registers.
- */
-
- if ((count == 2) && (((long)mem & 1) == 0)) {
- tmp_s = *(unsigned short *)mem;
- mem += 2;
- *buf++ = hexchars[(tmp_s >> 12) & 0xf];
- *buf++ = hexchars[(tmp_s >> 8) & 0xf];
- *buf++ = hexchars[(tmp_s >> 4) & 0xf];
- *buf++ = hexchars[tmp_s & 0xf];
-
- } else if ((count == 4) && (((long)mem & 3) == 0)) {
- tmp_l = *(unsigned int *)mem;
- mem += 4;
- *buf++ = hexchars[(tmp_l >> 28) & 0xf];
- *buf++ = hexchars[(tmp_l >> 24) & 0xf];
- *buf++ = hexchars[(tmp_l >> 20) & 0xf];
- *buf++ = hexchars[(tmp_l >> 16) & 0xf];
- *buf++ = hexchars[(tmp_l >> 12) & 0xf];
- *buf++ = hexchars[(tmp_l >> 8) & 0xf];
- *buf++ = hexchars[(tmp_l >> 4) & 0xf];
- *buf++ = hexchars[tmp_l & 0xf];
-
- } else {
- while (count-- > 0) {
- ch = *mem++;
- *buf++ = hexchars[ch >> 4];
- *buf++ = hexchars[ch & 0xf];
- }
- }
-
- } else {
- /* error condition */
- }
- debugger_fault_handler = NULL;
- *buf = 0;
- return buf;
-}
-
-/* convert the hex array pointed to by buf into binary to be placed in mem
- * return a pointer to the character AFTER the last byte written.
-*/
-static char *
-hex2mem(char *buf, char *mem, int count)
-{
- unsigned char ch;
- int i;
- char *orig_mem;
- unsigned short tmp_s;
- unsigned long tmp_l;
-
- orig_mem = mem;
-
- if (kgdb_setjmp((long*)fault_jmp_buf) == 0) {
- debugger_fault_handler = kgdb_fault_handler;
-
- /* Accessing 16 bit and 32 bit objects in a single
- ** store instruction is required to avoid bad side
- ** effects for some IO registers.
- */
-
- if ((count == 2) && (((long)mem & 1) == 0)) {
- tmp_s = hex(*buf++) << 12;
- tmp_s |= hex(*buf++) << 8;
- tmp_s |= hex(*buf++) << 4;
- tmp_s |= hex(*buf++);
-
- *(unsigned short *)mem = tmp_s;
- mem += 2;
-
- } else if ((count == 4) && (((long)mem & 3) == 0)) {
- tmp_l = hex(*buf++) << 28;
- tmp_l |= hex(*buf++) << 24;
- tmp_l |= hex(*buf++) << 20;
- tmp_l |= hex(*buf++) << 16;
- tmp_l |= hex(*buf++) << 12;
- tmp_l |= hex(*buf++) << 8;
- tmp_l |= hex(*buf++) << 4;
- tmp_l |= hex(*buf++);
-
- *(unsigned long *)mem = tmp_l;
- mem += 4;
-
- } else {
- for (i=0; i<count; i++) {
- ch = hex(*buf++) << 4;
- ch |= hex(*buf++);
- *mem++ = ch;
- }
- }
-
-
- /*
- ** Flush the data cache, invalidate the instruction cache.
- */
- flush_icache_range((int)orig_mem, (int)orig_mem + count - 1);
-
- } else {
- /* error condition */
- }
- debugger_fault_handler = NULL;
- return mem;
-}
-
-/*
- * While we find nice hex chars, build an int.
- * Return number of chars processed.
- */
-static int
-hexToInt(char **ptr, int *intValue)
-{
- int numChars = 0;
- int hexValue;
-
- *intValue = 0;
-
- if (kgdb_setjmp((long*)fault_jmp_buf) == 0) {
- debugger_fault_handler = kgdb_fault_handler;
- while (**ptr) {
- hexValue = hex(**ptr);
- if (hexValue < 0)
- break;
-
- *intValue = (*intValue << 4) | hexValue;
- numChars ++;
-
- (*ptr)++;
- }
- } else {
- /* error condition */
- }
- debugger_fault_handler = NULL;
-
- return (numChars);
-}
-
-/* scan for the sequence $<data>#<checksum> */
-static void
-getpacket(char *buffer)
-{
- unsigned char checksum;
- unsigned char xmitcsum;
- int i;
- int count;
- unsigned char ch;
-
- do {
- /* wait around for the start character, ignore all other
- * characters */
- while ((ch = (getDebugChar() & 0x7f)) != '$') ;
-
- checksum = 0;
- xmitcsum = -1;
-
- count = 0;
-
- /* now, read until a # or end of buffer is found */
- while (count < BUFMAX) {
- ch = getDebugChar() & 0x7f;
- if (ch == '#')
- break;
- checksum = checksum + ch;
- buffer[count] = ch;
- count = count + 1;
- }
-
- if (count >= BUFMAX)
- continue;
-
- buffer[count] = 0;
-
- if (ch == '#') {
- xmitcsum = hex(getDebugChar() & 0x7f) << 4;
- xmitcsum |= hex(getDebugChar() & 0x7f);
- if (checksum != xmitcsum)
- putDebugChar('-'); /* failed checksum */
- else {
- putDebugChar('+'); /* successful transfer */
- /* if a sequence char is present, reply the ID */
- if (buffer[2] == ':') {
- putDebugChar(buffer[0]);
- putDebugChar(buffer[1]);
- /* remove sequence chars from buffer */
- count = strlen(buffer);
- for (i=3; i <= count; i++)
- buffer[i-3] = buffer[i];
- }
- }
- }
- } while (checksum != xmitcsum);
-}
-
-/* send the packet in buffer. */
-static void putpacket(unsigned char *buffer)
-{
- unsigned char checksum;
- int count;
- unsigned char ch, recv;
-
- /* $<packet info>#<checksum>. */
- do {
- putDebugChar('$');
- checksum = 0;
- count = 0;
-
- while ((ch = buffer[count])) {
- putDebugChar(ch);
- checksum += ch;
- count += 1;
- }
-
- putDebugChar('#');
- putDebugChar(hexchars[checksum >> 4]);
- putDebugChar(hexchars[checksum & 0xf]);
- recv = getDebugChar();
- } while ((recv & 0x7f) != '+');
-}
-
-static void kgdb_flush_cache_all(void)
-{
- flush_instruction_cache();
-}
-
-/* Set up exception handlers for tracing and breakpoints
- * [could be called kgdb_init()]
- */
-void set_debug_traps(void)
-{
-#if 0
- unsigned char c;
-
- save_and_cli(flags);
-
- /* In case GDB is started before us, ack any packets (presumably
- * "$?#xx") sitting there.
- *
- * I've found this code causes more problems than it solves,
- * so that's why it's commented out. GDB seems to work fine
- * now starting either before or after the kernel -bwb
- */
-
- while((c = getDebugChar()) != '$');
- while((c = getDebugChar()) != '#');
- c = getDebugChar(); /* eat first csum byte */
- c = getDebugChar(); /* eat second csum byte */
- putDebugChar('+'); /* ack it */
-#endif
- debugger = kgdb;
- debugger_bpt = kgdb_bpt;
- debugger_sstep = kgdb_sstep;
- debugger_iabr_match = kgdb_iabr_match;
- debugger_dabr_match = kgdb_dabr_match;
-
- initialized = 1;
-}
-
-static void kgdb_fault_handler(struct pt_regs *regs)
-{
- kgdb_longjmp((long*)fault_jmp_buf, 1);
-}
-
-int kgdb_bpt(struct pt_regs *regs)
-{
- return handle_exception(regs);
-}
-
-int kgdb_sstep(struct pt_regs *regs)
-{
- return handle_exception(regs);
-}
-
-void kgdb(struct pt_regs *regs)
-{
- handle_exception(regs);
-}
-
-int kgdb_iabr_match(struct pt_regs *regs)
-{
- printk(KERN_ERR "kgdb doesn't support iabr, what?!?\n");
- return handle_exception(regs);
-}
-
-int kgdb_dabr_match(struct pt_regs *regs)
-{
- printk(KERN_ERR "kgdb doesn't support dabr, what?!?\n");
- return handle_exception(regs);
-}
-
-/* Convert the hardware trap type code to a unix signal number. */
-/*
- * This table contains the mapping between PowerPC hardware trap types, and
- * signals, which are primarily what GDB understands.
- */
-static struct hard_trap_info
-{
- unsigned int tt; /* Trap type code for powerpc */
- unsigned char signo; /* Signal that we map this trap into */
-} hard_trap_info[] = {
-#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
- { 0x100, SIGINT }, /* critical input interrupt */
- { 0x200, SIGSEGV }, /* machine check */
- { 0x300, SIGSEGV }, /* data storage */
- { 0x400, SIGBUS }, /* instruction storage */
- { 0x500, SIGINT }, /* interrupt */
- { 0x600, SIGBUS }, /* alignment */
- { 0x700, SIGILL }, /* program */
- { 0x800, SIGILL }, /* reserved */
- { 0x900, SIGILL }, /* reserved */
- { 0xa00, SIGILL }, /* reserved */
- { 0xb00, SIGILL }, /* reserved */
- { 0xc00, SIGCHLD }, /* syscall */
- { 0xd00, SIGILL }, /* reserved */
- { 0xe00, SIGILL }, /* reserved */
- { 0xf00, SIGILL }, /* reserved */
- /*
- ** 0x1000 PIT
- ** 0x1010 FIT
- ** 0x1020 watchdog
- ** 0x1100 data TLB miss
- ** 0x1200 instruction TLB miss
- */
- { 0x2002, SIGTRAP}, /* debug */
-#else
- { 0x200, SIGSEGV }, /* machine check */
- { 0x300, SIGSEGV }, /* address error (store) */
- { 0x400, SIGBUS }, /* instruction bus error */
- { 0x500, SIGINT }, /* interrupt */
- { 0x600, SIGBUS }, /* alingment */
- { 0x700, SIGTRAP }, /* breakpoint trap */
- { 0x800, SIGFPE }, /* fpu unavail */
- { 0x900, SIGALRM }, /* decrementer */
- { 0xa00, SIGILL }, /* reserved */
- { 0xb00, SIGILL }, /* reserved */
- { 0xc00, SIGCHLD }, /* syscall */
- { 0xd00, SIGTRAP }, /* single-step/watch */
- { 0xe00, SIGFPE }, /* fp assist */
-#endif
- { 0, 0} /* Must be last */
-
-};
-
-static int computeSignal(unsigned int tt)
-{
- struct hard_trap_info *ht;
-
- for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
- if (ht->tt == tt)
- return ht->signo;
-
- return SIGHUP; /* default for things we don't know about */
-}
-
-#define PC_REGNUM 64
-#define SP_REGNUM 1
-
-/*
- * This function does all command processing for interfacing to gdb.
- */
-static int
-handle_exception (struct pt_regs *regs)
-{
- int sigval;
- int addr;
- int length;
- char *ptr;
- unsigned int msr;
-
- /* We don't handle user-mode breakpoints. */
- if (user_mode(regs))
- return 0;
-
- if (debugger_fault_handler) {
- debugger_fault_handler(regs);
- panic("kgdb longjump failed!\n");
- }
- if (kgdb_active) {
- printk(KERN_ERR "interrupt while in kgdb, returning\n");
- return 0;
- }
-
- kgdb_active = 1;
- kgdb_started = 1;
-
-#ifdef KGDB_DEBUG
- printk("kgdb: entering handle_exception; trap [0x%x]\n",
- (unsigned int)regs->trap);
-#endif
-
- kgdb_interruptible(0);
- lock_kernel();
- msr = mfmsr();
- mtmsr(msr & ~MSR_EE); /* disable interrupts */
-
- if (regs->nip == (unsigned long)breakinst) {
- /* Skip over breakpoint trap insn */
- regs->nip += 4;
- }
-
- /* reply to host that an exception has occurred */
- sigval = computeSignal(regs->trap);
- ptr = remcomOutBuffer;
-
- *ptr++ = 'T';
- *ptr++ = hexchars[sigval >> 4];
- *ptr++ = hexchars[sigval & 0xf];
- *ptr++ = hexchars[PC_REGNUM >> 4];
- *ptr++ = hexchars[PC_REGNUM & 0xf];
- *ptr++ = ':';
- ptr = mem2hex((char *)&regs->nip, ptr, 4);
- *ptr++ = ';';
- *ptr++ = hexchars[SP_REGNUM >> 4];
- *ptr++ = hexchars[SP_REGNUM & 0xf];
- *ptr++ = ':';
- ptr = mem2hex(((char *)regs) + SP_REGNUM*4, ptr, 4);
- *ptr++ = ';';
- *ptr++ = 0;
-
- putpacket(remcomOutBuffer);
- if (kdebug)
- printk("remcomOutBuffer: %s\n", remcomOutBuffer);
-
- /* XXX We may want to add some features dealing with poking the
- * XXX page tables, ... (look at sparc-stub.c for more info)
- * XXX also required hacking to the gdb sources directly...
- */
-
- while (1) {
- remcomOutBuffer[0] = 0;
-
- getpacket(remcomInBuffer);
- switch (remcomInBuffer[0]) {
- case '?': /* report most recent signal */
- remcomOutBuffer[0] = 'S';
- remcomOutBuffer[1] = hexchars[sigval >> 4];
- remcomOutBuffer[2] = hexchars[sigval & 0xf];
- remcomOutBuffer[3] = 0;
- break;
-#if 0
- case 'q': /* this screws up gdb for some reason...*/
- {
- extern long _start, sdata, __bss_start;
-
- ptr = &remcomInBuffer[1];
- if (strncmp(ptr, "Offsets", 7) != 0)
- break;
-
- ptr = remcomOutBuffer;
- sprintf(ptr, "Text=%8.8x;Data=%8.8x;Bss=%8.8x",
- &_start, &sdata, &__bss_start);
- break;
- }
-#endif
- case 'd':
- /* toggle debug flag */
- kdebug ^= 1;
- break;
-
- case 'g': /* return the value of the CPU registers.
- * some of them are non-PowerPC names :(
- * they are stored in gdb like:
- * struct {
- * u32 gpr[32];
- * f64 fpr[32];
- * u32 pc, ps, cnd, lr; (ps=msr)
- * u32 cnt, xer, mq;
- * }
- */
- {
- int i;
- ptr = remcomOutBuffer;
- /* General Purpose Regs */
- ptr = mem2hex((char *)regs, ptr, 32 * 4);
- /* Floating Point Regs - FIXME */
- /*ptr = mem2hex((char *), ptr, 32 * 8);*/
- for(i=0; i<(32*8*2); i++) { /* 2chars/byte */
- ptr[i] = '0';
- }
- ptr += 32*8*2;
- /* pc, msr, cr, lr, ctr, xer, (mq is unused) */
- ptr = mem2hex((char *)&regs->nip, ptr, 4);
- ptr = mem2hex((char *)&regs->msr, ptr, 4);
- ptr = mem2hex((char *)&regs->ccr, ptr, 4);
- ptr = mem2hex((char *)&regs->link, ptr, 4);
- ptr = mem2hex((char *)&regs->ctr, ptr, 4);
- ptr = mem2hex((char *)&regs->xer, ptr, 4);
- }
- break;
-
- case 'G': /* set the value of the CPU registers */
- {
- ptr = &remcomInBuffer[1];
-
- /*
- * If the stack pointer has moved, you should pray.
- * (cause only god can help you).
- */
-
- /* General Purpose Regs */
- hex2mem(ptr, (char *)regs, 32 * 4);
-
- /* Floating Point Regs - FIXME?? */
- /*ptr = hex2mem(ptr, ??, 32 * 8);*/
- ptr += 32*8*2;
-
- /* pc, msr, cr, lr, ctr, xer, (mq is unused) */
- ptr = hex2mem(ptr, (char *)&regs->nip, 4);
- ptr = hex2mem(ptr, (char *)&regs->msr, 4);
- ptr = hex2mem(ptr, (char *)&regs->ccr, 4);
- ptr = hex2mem(ptr, (char *)&regs->link, 4);
- ptr = hex2mem(ptr, (char *)&regs->ctr, 4);
- ptr = hex2mem(ptr, (char *)&regs->xer, 4);
-
- strcpy(remcomOutBuffer,"OK");
- }
- break;
- case 'H':
- /* don't do anything, yet, just acknowledge */
- hexToInt(&ptr, &addr);
- strcpy(remcomOutBuffer,"OK");
- break;
-
- case 'm': /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */
- /* Try to read %x,%x. */
-
- ptr = &remcomInBuffer[1];
-
- if (hexToInt(&ptr, &addr) && *ptr++ == ','
- && hexToInt(&ptr, &length)) {
- if (mem2hex((char *)addr, remcomOutBuffer,
- length))
- break;
- strcpy(remcomOutBuffer, "E03");
- } else
- strcpy(remcomOutBuffer, "E01");
- break;
-
- case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
- /* Try to read '%x,%x:'. */
-
- ptr = &remcomInBuffer[1];
-
- if (hexToInt(&ptr, &addr) && *ptr++ == ','
- && hexToInt(&ptr, &length)
- && *ptr++ == ':') {
- if (hex2mem(ptr, (char *)addr, length))
- strcpy(remcomOutBuffer, "OK");
- else
- strcpy(remcomOutBuffer, "E03");
- flush_icache_range(addr, addr+length);
- } else
- strcpy(remcomOutBuffer, "E02");
- break;
-
-
- case 'k': /* kill the program, actually just continue */
- case 'c': /* cAA..AA Continue; address AA..AA optional */
- /* try to read optional parameter, pc unchanged if no parm */
-
- ptr = &remcomInBuffer[1];
- if (hexToInt(&ptr, &addr))
- regs->nip = addr;
-
-/* Need to flush the instruction cache here, as we may have deposited a
- * breakpoint, and the icache probably has no way of knowing that a data ref to
- * some location may have changed something that is in the instruction cache.
- */
- kgdb_flush_cache_all();
- mtmsr(msr);
-
- kgdb_interruptible(1);
- unlock_kernel();
- kgdb_active = 0;
- if (kdebug) {
- printk("remcomInBuffer: %s\n", remcomInBuffer);
- printk("remcomOutBuffer: %s\n", remcomOutBuffer);
- }
- return 1;
-
- case 's':
- kgdb_flush_cache_all();
-#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
- mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) | DBCR0_IC);
- regs->msr |= MSR_DE;
-#else
- regs->msr |= MSR_SE;
-#endif
- unlock_kernel();
- kgdb_active = 0;
- if (kdebug) {
- printk("remcomInBuffer: %s\n", remcomInBuffer);
- printk("remcomOutBuffer: %s\n", remcomOutBuffer);
- }
- return 1;
-
- case 'r': /* Reset (if user process..exit ???)*/
- panic("kgdb reset.");
- break;
- } /* switch */
- if (remcomOutBuffer[0] && kdebug) {
- printk("remcomInBuffer: %s\n", remcomInBuffer);
- printk("remcomOutBuffer: %s\n", remcomOutBuffer);
- }
- /* reply to the request */
- putpacket(remcomOutBuffer);
- } /* while(1) */
-}
-
-/* This function will generate a breakpoint exception. It is used at the
- beginning of a program to sync up with a debugger and can be used
- otherwise as a quick means to stop program execution and "break" into
- the debugger. */
-
-void
-breakpoint(void)
-{
- if (!initialized) {
- printk("breakpoint() called b4 kgdb init\n");
- return;
- }
-
- asm(" .globl breakinst \n\
- breakinst: .long 0x7d821008");
-}
-
-#ifdef CONFIG_KGDB_CONSOLE
-/* Output string in GDB O-packet format if GDB has connected. If nothing
- output, returns 0 (caller must then handle output). */
-int
-kgdb_output_string (const char* s, unsigned int count)
-{
- char buffer[512];
-
- if (!kgdb_started)
- return 0;
-
- count = (count <= (sizeof(buffer) / 2 - 2))
- ? count : (sizeof(buffer) / 2 - 2);
-
- buffer[0] = 'O';
- mem2hex (s, &buffer[1], count);
- putpacket(buffer);
-
- return 1;
-}
-#endif
-
-static void sysrq_handle_gdb(int key, struct pt_regs *pt_regs,
- struct tty_struct *tty)
-{
- printk("Entering GDB stub\n");
- breakpoint();
-}
-static struct sysrq_key_op sysrq_gdb_op = {
- .handler = sysrq_handle_gdb,
- .help_msg = "Gdb",
- .action_msg = "GDB",
-};
-
-static int gdb_register_sysrq(void)
-{
- printk("Registering GDB sysrq handler\n");
- register_sysrq_key('g', &sysrq_gdb_op);
- return 0;
-}
-module_init(gdb_register_sysrq);
diff --git a/arch/ppc/kernel/ppc_htab.c b/arch/ppc/kernel/ppc_htab.c
deleted file mode 100644
index 9ed36dd9cbff..000000000000
--- a/arch/ppc/kernel/ppc_htab.c
+++ /dev/null
@@ -1,464 +0,0 @@
-/*
- * PowerPC hash table management proc entry. Will show information
- * about the current hash table and will allow changes to it.
- *
- * Written by Cort Dougan (cort@cs.nmt.edu)
- *
- * 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/errno.h>
-#include <linux/sched.h>
-#include <linux/proc_fs.h>
-#include <linux/stat.h>
-#include <linux/sysctl.h>
-#include <linux/capability.h>
-#include <linux/ctype.h>
-#include <linux/threads.h>
-#include <linux/seq_file.h>
-#include <linux/init.h>
-#include <linux/bitops.h>
-
-#include <asm/uaccess.h>
-#include <asm/mmu.h>
-#include <asm/residual.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/cputable.h>
-#include <asm/system.h>
-#include <asm/reg.h>
-
-static int ppc_htab_show(struct seq_file *m, void *v);
-static ssize_t ppc_htab_write(struct file * file, const char __user * buffer,
- size_t count, loff_t *ppos);
-extern PTE *Hash, *Hash_end;
-extern unsigned long Hash_size, Hash_mask;
-extern unsigned long _SDR1;
-extern unsigned long htab_reloads;
-extern unsigned long htab_preloads;
-extern unsigned long htab_evicts;
-extern unsigned long pte_misses;
-extern unsigned long pte_errors;
-extern unsigned int primary_pteg_full;
-extern unsigned int htab_hash_searches;
-
-static int ppc_htab_open(struct inode *inode, struct file *file)
-{
- return single_open(file, ppc_htab_show, NULL);
-}
-
-const struct file_operations ppc_htab_operations = {
- .open = ppc_htab_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .write = ppc_htab_write,
- .release = single_release,
-};
-
-static char *pmc1_lookup(unsigned long mmcr0)
-{
- switch ( mmcr0 & (0x7f<<7) )
- {
- case 0x0:
- return "none";
- case MMCR0_PMC1_CYCLES:
- return "cycles";
- case MMCR0_PMC1_ICACHEMISS:
- return "ic miss";
- case MMCR0_PMC1_DTLB:
- return "dtlb miss";
- default:
- return "unknown";
- }
-}
-
-static char *pmc2_lookup(unsigned long mmcr0)
-{
- switch ( mmcr0 & 0x3f )
- {
- case 0x0:
- return "none";
- case MMCR0_PMC2_CYCLES:
- return "cycles";
- case MMCR0_PMC2_DCACHEMISS:
- return "dc miss";
- case MMCR0_PMC2_ITLB:
- return "itlb miss";
- case MMCR0_PMC2_LOADMISSTIME:
- return "load miss time";
- default:
- return "unknown";
- }
-}
-
-/*
- * print some useful info about the hash table. This function
- * is _REALLY_ slow (see the nested for loops below) but nothing
- * in here should be really timing critical. -- Cort
- */
-static int ppc_htab_show(struct seq_file *m, void *v)
-{
- unsigned long mmcr0 = 0, pmc1 = 0, pmc2 = 0;
-#if defined(CONFIG_PPC_STD_MMU)
- unsigned int kptes = 0, uptes = 0;
- PTE *ptr;
-#endif /* CONFIG_PPC_STD_MMU */
-
- if (cpu_has_feature(CPU_FTR_604_PERF_MON)) {
- mmcr0 = mfspr(SPRN_MMCR0);
- pmc1 = mfspr(SPRN_PMC1);
- pmc2 = mfspr(SPRN_PMC2);
- seq_printf(m,
- "604 Performance Monitoring\n"
- "MMCR0\t\t: %08lx %s%s ",
- mmcr0,
- ( mmcr0>>28 & 0x2 ) ? "(user mode counted)" : "",
- ( mmcr0>>28 & 0x4 ) ? "(kernel mode counted)" : "");
- seq_printf(m,
- "\nPMC1\t\t: %08lx (%s)\n"
- "PMC2\t\t: %08lx (%s)\n",
- pmc1, pmc1_lookup(mmcr0),
- pmc2, pmc2_lookup(mmcr0));
- }
-
-#ifdef CONFIG_PPC_STD_MMU
- /* if we don't have a htab */
- if ( Hash_size == 0 ) {
- seq_printf(m, "No Hash Table used\n");
- return 0;
- }
-
- for (ptr = Hash; ptr < Hash_end; ptr++) {
- unsigned int mctx, vsid;
-
- if (!ptr->v)
- continue;
- /* undo the esid skew */
- vsid = ptr->vsid;
- mctx = ((vsid - (vsid & 0xf) * 0x111) >> 4) & 0xfffff;
- if (mctx == 0)
- kptes++;
- else
- uptes++;
- }
-
- seq_printf(m,
- "PTE Hash Table Information\n"
- "Size\t\t: %luKb\n"
- "Buckets\t\t: %lu\n"
- "Address\t\t: %08lx\n"
- "Entries\t\t: %lu\n"
- "User ptes\t: %u\n"
- "Kernel ptes\t: %u\n"
- "Percent full\t: %lu%%\n"
- , (unsigned long)(Hash_size>>10),
- (Hash_size/(sizeof(PTE)*8)),
- (unsigned long)Hash,
- Hash_size/sizeof(PTE)
- , uptes,
- kptes,
- ((kptes+uptes)*100) / (Hash_size/sizeof(PTE))
- );
-
- seq_printf(m,
- "Reloads\t\t: %lu\n"
- "Preloads\t: %lu\n"
- "Searches\t: %u\n"
- "Overflows\t: %u\n"
- "Evicts\t\t: %lu\n",
- htab_reloads, htab_preloads, htab_hash_searches,
- primary_pteg_full, htab_evicts);
-#endif /* CONFIG_PPC_STD_MMU */
-
- seq_printf(m,
- "Non-error misses: %lu\n"
- "Error misses\t: %lu\n",
- pte_misses, pte_errors);
- return 0;
-}
-
-/*
- * Allow user to define performance counters and resize the hash table
- */
-static ssize_t ppc_htab_write(struct file * file, const char __user * ubuffer,
- size_t count, loff_t *ppos)
-{
-#ifdef CONFIG_PPC_STD_MMU
- unsigned long tmp;
- char buffer[16];
-
- if (!capable(CAP_SYS_ADMIN))
- return -EACCES;
- if (strncpy_from_user(buffer, ubuffer, 15))
- return -EFAULT;
- buffer[15] = 0;
-
- /* don't set the htab size for now */
- if ( !strncmp( buffer, "size ", 5) )
- return -EBUSY;
-
- if ( !strncmp( buffer, "reset", 5) )
- {
- if (cpu_has_feature(CPU_FTR_604_PERF_MON)) {
- /* reset PMC1 and PMC2 */
- mtspr(SPRN_PMC1, 0);
- mtspr(SPRN_PMC2, 0);
- }
- htab_reloads = 0;
- htab_evicts = 0;
- pte_misses = 0;
- pte_errors = 0;
- }
-
- /* Everything below here requires the performance monitor feature. */
- if (!cpu_has_feature(CPU_FTR_604_PERF_MON))
- return count;
-
- /* turn off performance monitoring */
- if ( !strncmp( buffer, "off", 3) )
- {
- mtspr(SPRN_MMCR0, 0);
- mtspr(SPRN_PMC1, 0);
- mtspr(SPRN_PMC2, 0);
- }
-
- if ( !strncmp( buffer, "user", 4) )
- {
- /* setup mmcr0 and clear the correct pmc */
- tmp = (mfspr(SPRN_MMCR0) & ~(0x60000000)) | 0x20000000;
- mtspr(SPRN_MMCR0, tmp);
- mtspr(SPRN_PMC1, 0);
- mtspr(SPRN_PMC2, 0);
- }
-
- if ( !strncmp( buffer, "kernel", 6) )
- {
- /* setup mmcr0 and clear the correct pmc */
- tmp = (mfspr(SPRN_MMCR0) & ~(0x60000000)) | 0x40000000;
- mtspr(SPRN_MMCR0, tmp);
- mtspr(SPRN_PMC1, 0);
- mtspr(SPRN_PMC2, 0);
- }
-
- /* PMC1 values */
- if ( !strncmp( buffer, "dtlb", 4) )
- {
- /* setup mmcr0 and clear the correct pmc */
- tmp = (mfspr(SPRN_MMCR0) & ~(0x7F << 7)) | MMCR0_PMC1_DTLB;
- mtspr(SPRN_MMCR0, tmp);
- mtspr(SPRN_PMC1, 0);
- }
-
- if ( !strncmp( buffer, "ic miss", 7) )
- {
- /* setup mmcr0 and clear the correct pmc */
- tmp = (mfspr(SPRN_MMCR0) & ~(0x7F<<7)) | MMCR0_PMC1_ICACHEMISS;
- mtspr(SPRN_MMCR0, tmp);
- mtspr(SPRN_PMC1, 0);
- }
-
- /* PMC2 values */
- if ( !strncmp( buffer, "load miss time", 14) )
- {
- /* setup mmcr0 and clear the correct pmc */
- asm volatile(
- "mfspr %0,%1\n\t" /* get current mccr0 */
- "rlwinm %0,%0,0,0,31-6\n\t" /* clear bits [26-31] */
- "ori %0,%0,%2 \n\t" /* or in mmcr0 settings */
- "mtspr %1,%0 \n\t" /* set new mccr0 */
- "mtspr %3,%4 \n\t" /* reset the pmc */
- : "=r" (tmp)
- : "i" (SPRN_MMCR0),
- "i" (MMCR0_PMC2_LOADMISSTIME),
- "i" (SPRN_PMC2), "r" (0) );
- }
-
- if ( !strncmp( buffer, "itlb", 4) )
- {
- /* setup mmcr0 and clear the correct pmc */
- asm volatile(
- "mfspr %0,%1\n\t" /* get current mccr0 */
- "rlwinm %0,%0,0,0,31-6\n\t" /* clear bits [26-31] */
- "ori %0,%0,%2 \n\t" /* or in mmcr0 settings */
- "mtspr %1,%0 \n\t" /* set new mccr0 */
- "mtspr %3,%4 \n\t" /* reset the pmc */
- : "=r" (tmp)
- : "i" (SPRN_MMCR0), "i" (MMCR0_PMC2_ITLB),
- "i" (SPRN_PMC2), "r" (0) );
- }
-
- if ( !strncmp( buffer, "dc miss", 7) )
- {
- /* setup mmcr0 and clear the correct pmc */
- asm volatile(
- "mfspr %0,%1\n\t" /* get current mccr0 */
- "rlwinm %0,%0,0,0,31-6\n\t" /* clear bits [26-31] */
- "ori %0,%0,%2 \n\t" /* or in mmcr0 settings */
- "mtspr %1,%0 \n\t" /* set new mccr0 */
- "mtspr %3,%4 \n\t" /* reset the pmc */
- : "=r" (tmp)
- : "i" (SPRN_MMCR0), "i" (MMCR0_PMC2_DCACHEMISS),
- "i" (SPRN_PMC2), "r" (0) );
- }
-
- return count;
-#else /* CONFIG_PPC_STD_MMU */
- return 0;
-#endif /* CONFIG_PPC_STD_MMU */
-}
-
-int proc_dol2crvec(ctl_table *table, int write, struct file *filp,
- void __user *buffer_arg, size_t *lenp, loff_t *ppos)
-{
- int vleft, first=1, len, left, val;
- char __user *buffer = (char __user *) buffer_arg;
- #define TMPBUFLEN 256
- char buf[TMPBUFLEN], *p;
- static const char *sizestrings[4] = {
- "2MB", "256KB", "512KB", "1MB"
- };
- static const char *clockstrings[8] = {
- "clock disabled", "+1 clock", "+1.5 clock", "reserved(3)",
- "+2 clock", "+2.5 clock", "+3 clock", "reserved(7)"
- };
- static const char *typestrings[4] = {
- "flow-through burst SRAM", "reserved SRAM",
- "pipelined burst SRAM", "pipelined late-write SRAM"
- };
- static const char *holdstrings[4] = {
- "0.5", "1.0", "(reserved2)", "(reserved3)"
- };
-
- if (!cpu_has_feature(CPU_FTR_L2CR))
- return -EFAULT;
-
- if ( /*!table->maxlen ||*/ (*ppos && !write)) {
- *lenp = 0;
- return 0;
- }
-
- vleft = table->maxlen / sizeof(int);
- left = *lenp;
-
- for (; left /*&& vleft--*/; first=0) {
- if (write) {
- while (left) {
- char c;
- if(get_user(c, buffer))
- return -EFAULT;
- if (!isspace(c))
- break;
- left--;
- buffer++;
- }
- if (!left)
- break;
- len = left;
- if (len > TMPBUFLEN-1)
- len = TMPBUFLEN-1;
- if(copy_from_user(buf, buffer, len))
- return -EFAULT;
- buf[len] = 0;
- p = buf;
- if (*p < '0' || *p > '9')
- break;
- val = simple_strtoul(p, &p, 0);
- len = p-buf;
- if ((len < left) && *p && !isspace(*p))
- break;
- buffer += len;
- left -= len;
- _set_L2CR(val);
- } else {
- p = buf;
- if (!first)
- *p++ = '\t';
- val = _get_L2CR();
- p += sprintf(p, "0x%08x: ", val);
- p += sprintf(p, " %s", (val >> 31) & 1 ? "enabled" :
- "disabled");
- p += sprintf(p, ", %sparity", (val>>30)&1 ? "" : "no ");
- p += sprintf(p, ", %s", sizestrings[(val >> 28) & 3]);
- p += sprintf(p, ", %s", clockstrings[(val >> 25) & 7]);
- p += sprintf(p, ", %s", typestrings[(val >> 23) & 2]);
- p += sprintf(p, "%s", (val>>22)&1 ? ", data only" : "");
- p += sprintf(p, "%s", (val>>20)&1 ? ", ZZ enabled": "");
- p += sprintf(p, ", %s", (val>>19)&1 ? "write-through" :
- "copy-back");
- p += sprintf(p, "%s", (val>>18)&1 ? ", testing" : "");
- p += sprintf(p, ", %sns hold",holdstrings[(val>>16)&3]);
- p += sprintf(p, "%s", (val>>15)&1 ? ", DLL slow" : "");
- p += sprintf(p, "%s", (val>>14)&1 ? ", diff clock" :"");
- p += sprintf(p, "%s", (val>>13)&1 ? ", DLL bypass" :"");
-
- p += sprintf(p,"\n");
-
- len = strlen(buf);
- if (len > left)
- len = left;
- if (copy_to_user(buffer, buf, len))
- return -EFAULT;
- left -= len;
- buffer += len;
- break;
- }
- }
-
- if (!write && !first && left) {
- if(put_user('\n', (char __user *) buffer))
- return -EFAULT;
- left--, buffer++;
- }
- if (write) {
- char __user *s = (char __user *) buffer;
- while (left) {
- char c;
- if(get_user(c, s++))
- return -EFAULT;
- if (!isspace(c))
- break;
- left--;
- }
- }
- if (write && first)
- return -EINVAL;
- *lenp -= left;
- *ppos += *lenp;
- return 0;
-}
-
-#ifdef CONFIG_SYSCTL
-/*
- * Register our sysctl.
- */
-static ctl_table htab_ctl_table[]={
- {
- .procname = "l2cr",
- .mode = 0644,
- .proc_handler = &proc_dol2crvec,
- },
- {}
-};
-static ctl_table htab_sysctl_root[] = {
- {
- .ctl_name = CTL_KERN,
- .procname = "kernel",
- .mode = 0555,
- .child = htab_ctl_table,
- },
- {}
-};
-
-static int __init
-register_ppc_htab_sysctl(void)
-{
- register_sysctl_table(htab_sysctl_root);
-
- return 0;
-}
-
-__initcall(register_ppc_htab_sysctl);
-#endif
diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c
deleted file mode 100644
index 5d529bcbeee9..000000000000
--- a/arch/ppc/kernel/ppc_ksyms.c
+++ /dev/null
@@ -1,258 +0,0 @@
-#include <linux/module.h>
-#include <linux/threads.h>
-#include <linux/smp.h>
-#include <linux/sched.h>
-#include <linux/elfcore.h>
-#include <linux/string.h>
-#include <linux/interrupt.h>
-#include <linux/screen_info.h>
-#include <linux/vt_kern.h>
-#include <linux/nvram.h>
-#include <linux/console.h>
-#include <linux/irq.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/pm.h>
-#include <linux/bitops.h>
-
-#include <asm/page.h>
-#include <asm/processor.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/ide.h>
-#include <asm/atomic.h>
-#include <asm/checksum.h>
-#include <asm/pgtable.h>
-#include <asm/tlbflush.h>
-#include <asm/cacheflush.h>
-#include <linux/adb.h>
-#include <linux/cuda.h>
-#include <linux/pmu.h>
-#include <asm/system.h>
-#include <asm/pci-bridge.h>
-#include <asm/irq.h>
-#include <asm/dma.h>
-#include <asm/machdep.h>
-#include <asm/hw_irq.h>
-#include <asm/nvram.h>
-#include <asm/mmu_context.h>
-#include <asm/backlight.h>
-#include <asm/time.h>
-#include <asm/cputable.h>
-#include <asm/btext.h>
-#include <asm/xmon.h>
-#include <asm/signal.h>
-#include <asm/dcr.h>
-
-#ifdef CONFIG_8xx
-#include <asm/cpm1.h>
-#endif
-
-extern void transfer_to_handler(void);
-extern void do_IRQ(struct pt_regs *regs);
-extern void machine_check_exception(struct pt_regs *regs);
-extern void alignment_exception(struct pt_regs *regs);
-extern void program_check_exception(struct pt_regs *regs);
-extern void single_step_exception(struct pt_regs *regs);
-extern int sys_sigreturn(struct pt_regs *regs);
-
-long long __ashrdi3(long long, int);
-long long __ashldi3(long long, int);
-long long __lshrdi3(long long, int);
-
-EXPORT_SYMBOL(empty_zero_page);
-EXPORT_SYMBOL(clear_pages);
-EXPORT_SYMBOL(clear_user_page);
-EXPORT_SYMBOL(copy_page);
-EXPORT_SYMBOL(transfer_to_handler);
-EXPORT_SYMBOL(do_IRQ);
-EXPORT_SYMBOL(machine_check_exception);
-EXPORT_SYMBOL(alignment_exception);
-EXPORT_SYMBOL(program_check_exception);
-EXPORT_SYMBOL(single_step_exception);
-EXPORT_SYMBOL(sys_sigreturn);
-EXPORT_SYMBOL(ppc_n_lost_interrupts);
-
-EXPORT_SYMBOL(ISA_DMA_THRESHOLD);
-EXPORT_SYMBOL(DMA_MODE_READ);
-EXPORT_SYMBOL(DMA_MODE_WRITE);
-
-#if !defined(__INLINE_BITOPS)
-EXPORT_SYMBOL(set_bit);
-EXPORT_SYMBOL(clear_bit);
-EXPORT_SYMBOL(change_bit);
-EXPORT_SYMBOL(test_and_set_bit);
-EXPORT_SYMBOL(test_and_clear_bit);
-EXPORT_SYMBOL(test_and_change_bit);
-#endif /* __INLINE_BITOPS */
-
-EXPORT_SYMBOL(strcpy);
-EXPORT_SYMBOL(strncpy);
-EXPORT_SYMBOL(strcat);
-EXPORT_SYMBOL(strlen);
-EXPORT_SYMBOL(strcmp);
-EXPORT_SYMBOL(strncmp);
-
-EXPORT_SYMBOL(csum_partial);
-EXPORT_SYMBOL(csum_partial_copy_generic);
-EXPORT_SYMBOL(ip_fast_csum);
-EXPORT_SYMBOL(csum_tcpudp_magic);
-
-EXPORT_SYMBOL(__copy_tofrom_user);
-EXPORT_SYMBOL(__clear_user);
-EXPORT_SYMBOL(__strncpy_from_user);
-EXPORT_SYMBOL(__strnlen_user);
-
-/*
-EXPORT_SYMBOL(inb);
-EXPORT_SYMBOL(inw);
-EXPORT_SYMBOL(inl);
-EXPORT_SYMBOL(outb);
-EXPORT_SYMBOL(outw);
-EXPORT_SYMBOL(outl);
-EXPORT_SYMBOL(outsl);*/
-
-EXPORT_SYMBOL(_insb);
-EXPORT_SYMBOL(_outsb);
-EXPORT_SYMBOL(_insw_ns);
-EXPORT_SYMBOL(_outsw_ns);
-EXPORT_SYMBOL(_insl_ns);
-EXPORT_SYMBOL(_outsl_ns);
-EXPORT_SYMBOL(iopa);
-EXPORT_SYMBOL(ioremap);
-#ifdef CONFIG_44x
-EXPORT_SYMBOL(ioremap64);
-#endif
-EXPORT_SYMBOL(__ioremap);
-EXPORT_SYMBOL(iounmap);
-EXPORT_SYMBOL(ioremap_bot); /* aka VMALLOC_END */
-
-#ifdef CONFIG_PCI
-EXPORT_SYMBOL(isa_io_base);
-EXPORT_SYMBOL(isa_mem_base);
-EXPORT_SYMBOL(pci_dram_offset);
-EXPORT_SYMBOL(pci_alloc_consistent);
-EXPORT_SYMBOL(pci_free_consistent);
-EXPORT_SYMBOL(pci_bus_io_base);
-EXPORT_SYMBOL(pci_bus_io_base_phys);
-EXPORT_SYMBOL(pci_bus_mem_base_phys);
-EXPORT_SYMBOL(pci_bus_to_hose);
-EXPORT_SYMBOL(pci_resource_to_bus);
-EXPORT_SYMBOL(pci_phys_to_bus);
-EXPORT_SYMBOL(pci_bus_to_phys);
-#endif /* CONFIG_PCI */
-
-#ifdef CONFIG_NOT_COHERENT_CACHE
-extern void flush_dcache_all(void);
-EXPORT_SYMBOL(flush_dcache_all);
-#endif
-
-EXPORT_SYMBOL(start_thread);
-EXPORT_SYMBOL(kernel_thread);
-
-EXPORT_SYMBOL(flush_instruction_cache);
-EXPORT_SYMBOL(giveup_fpu);
-EXPORT_SYMBOL(__flush_icache_range);
-EXPORT_SYMBOL(flush_dcache_range);
-EXPORT_SYMBOL(flush_icache_user_range);
-EXPORT_SYMBOL(flush_dcache_page);
-EXPORT_SYMBOL(flush_tlb_kernel_range);
-EXPORT_SYMBOL(flush_tlb_page);
-EXPORT_SYMBOL(_tlbie);
-#ifdef CONFIG_ALTIVEC
-#ifndef CONFIG_SMP
-EXPORT_SYMBOL(last_task_used_altivec);
-#endif
-EXPORT_SYMBOL(giveup_altivec);
-#endif /* CONFIG_ALTIVEC */
-#ifdef CONFIG_SMP
-EXPORT_SYMBOL(smp_call_function);
-EXPORT_SYMBOL(smp_hw_index);
-#endif
-
-EXPORT_SYMBOL(ppc_md);
-
-#ifdef CONFIG_ADB
-EXPORT_SYMBOL(adb_request);
-EXPORT_SYMBOL(adb_register);
-EXPORT_SYMBOL(adb_unregister);
-EXPORT_SYMBOL(adb_poll);
-EXPORT_SYMBOL(adb_try_handler_change);
-#endif /* CONFIG_ADB */
-#ifdef CONFIG_ADB_CUDA
-EXPORT_SYMBOL(cuda_request);
-EXPORT_SYMBOL(cuda_poll);
-#endif /* CONFIG_ADB_CUDA */
-#if defined(CONFIG_BOOTX_TEXT)
-EXPORT_SYMBOL(btext_update_display);
-#endif
-EXPORT_SYMBOL(to_tm);
-
-EXPORT_SYMBOL(pm_power_off);
-
-EXPORT_SYMBOL(__ashrdi3);
-EXPORT_SYMBOL(__ashldi3);
-EXPORT_SYMBOL(__lshrdi3);
-EXPORT_SYMBOL(memcpy);
-EXPORT_SYMBOL(cacheable_memcpy);
-EXPORT_SYMBOL(memset);
-EXPORT_SYMBOL(memmove);
-EXPORT_SYMBOL(memcmp);
-EXPORT_SYMBOL(memchr);
-
-#if defined(CONFIG_FB_VGA16_MODULE)
-EXPORT_SYMBOL(screen_info);
-#endif
-
-EXPORT_SYMBOL(__delay);
-EXPORT_SYMBOL(timer_interrupt);
-EXPORT_SYMBOL(irq_desc);
-EXPORT_SYMBOL(tb_ticks_per_jiffy);
-EXPORT_SYMBOL(console_drivers);
-#ifdef CONFIG_XMON
-EXPORT_SYMBOL(xmon);
-EXPORT_SYMBOL(xmon_printf);
-#endif
-
-#if defined(CONFIG_KGDB) || defined(CONFIG_XMON)
-extern void (*debugger)(struct pt_regs *regs);
-extern int (*debugger_bpt)(struct pt_regs *regs);
-extern int (*debugger_sstep)(struct pt_regs *regs);
-extern int (*debugger_iabr_match)(struct pt_regs *regs);
-extern int (*debugger_dabr_match)(struct pt_regs *regs);
-extern void (*debugger_fault_handler)(struct pt_regs *regs);
-
-EXPORT_SYMBOL(debugger);
-EXPORT_SYMBOL(debugger_bpt);
-EXPORT_SYMBOL(debugger_sstep);
-EXPORT_SYMBOL(debugger_iabr_match);
-EXPORT_SYMBOL(debugger_dabr_match);
-EXPORT_SYMBOL(debugger_fault_handler);
-#endif
-
-#ifdef CONFIG_8xx
-EXPORT_SYMBOL(cpm_install_handler);
-EXPORT_SYMBOL(cpm_free_handler);
-#endif /* CONFIG_8xx */
-#if defined(CONFIG_8xx) || defined(CONFIG_40x)
-EXPORT_SYMBOL(__res);
-#endif
-
-EXPORT_SYMBOL(next_mmu_context);
-EXPORT_SYMBOL(set_context);
-EXPORT_SYMBOL(disarm_decr);
-#ifdef CONFIG_PPC_STD_MMU
-extern long mol_trampoline;
-EXPORT_SYMBOL(mol_trampoline); /* For MOL */
-EXPORT_SYMBOL(flush_hash_pages); /* For MOL */
-#ifdef CONFIG_SMP
-extern int mmu_hash_lock;
-EXPORT_SYMBOL(mmu_hash_lock); /* For MOL */
-#endif /* CONFIG_SMP */
-extern long *intercept_table;
-EXPORT_SYMBOL(intercept_table);
-#endif /* CONFIG_PPC_STD_MMU */
-#ifdef CONFIG_PPC_DCR_NATIVE
-EXPORT_SYMBOL(__mtdcr);
-EXPORT_SYMBOL(__mfdcr);
-#endif
diff --git a/arch/ppc/kernel/relocate_kernel.S b/arch/ppc/kernel/relocate_kernel.S
deleted file mode 100644
index 9b2ad48e988c..000000000000
--- a/arch/ppc/kernel/relocate_kernel.S
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * relocate_kernel.S - put the kernel image in place to boot
- * Copyright (C) 2002-2003 Eric Biederman <ebiederm@xmission.com>
- *
- * GameCube/ppc32 port Copyright (C) 2004 Albert Herranz
- *
- * This source code is licensed under the GNU General Public License,
- * Version 2. See the file COPYING for more details.
- */
-
-#include <asm/reg.h>
-#include <asm/ppc_asm.h>
-#include <asm/processor.h>
-
-#include <asm/kexec.h>
-
-#define PAGE_SIZE 4096 /* must be same value as in <asm/page.h> */
-
- /*
- * Must be relocatable PIC code callable as a C function.
- */
- .globl relocate_new_kernel
-relocate_new_kernel:
- /* r3 = page_list */
- /* r4 = reboot_code_buffer */
- /* r5 = start_address */
-
- li r0, 0
-
- /*
- * Set Machine Status Register to a known status,
- * switch the MMU off and jump to 1: in a single step.
- */
-
- mr r8, r0
- ori r8, r8, MSR_RI|MSR_ME
- mtspr SPRN_SRR1, r8
- addi r8, r4, 1f - relocate_new_kernel
- mtspr SPRN_SRR0, r8
- sync
- rfi
-
-1:
- /* from this point address translation is turned off */
- /* and interrupts are disabled */
-
- /* set a new stack at the bottom of our page... */
- /* (not really needed now) */
- addi r1, r4, KEXEC_CONTROL_CODE_SIZE - 8 /* for LR Save+Back Chain */
- stw r0, 0(r1)
-
- /* Do the copies */
- li r6, 0 /* checksum */
- mr r0, r3
- b 1f
-
-0: /* top, read another word for the indirection page */
- lwzu r0, 4(r3)
-
-1:
- /* is it a destination page? (r8) */
- rlwinm. r7, r0, 0, 31, 31 /* IND_DESTINATION (1<<0) */
- beq 2f
-
- rlwinm r8, r0, 0, 0, 19 /* clear kexec flags, page align */
- b 0b
-
-2: /* is it an indirection page? (r3) */
- rlwinm. r7, r0, 0, 30, 30 /* IND_INDIRECTION (1<<1) */
- beq 2f
-
- rlwinm r3, r0, 0, 0, 19 /* clear kexec flags, page align */
- subi r3, r3, 4
- b 0b
-
-2: /* are we done? */
- rlwinm. r7, r0, 0, 29, 29 /* IND_DONE (1<<2) */
- beq 2f
- b 3f
-
-2: /* is it a source page? (r9) */
- rlwinm. r7, r0, 0, 28, 28 /* IND_SOURCE (1<<3) */
- beq 0b
-
- rlwinm r9, r0, 0, 0, 19 /* clear kexec flags, page align */
-
- li r7, PAGE_SIZE / 4
- mtctr r7
- subi r9, r9, 4
- subi r8, r8, 4
-9:
- lwzu r0, 4(r9) /* do the copy */
- xor r6, r6, r0
- stwu r0, 4(r8)
- dcbst 0, r8
- sync
- icbi 0, r8
- bdnz 9b
-
- addi r9, r9, 4
- addi r8, r8, 4
- b 0b
-
-3:
-
- /* To be certain of avoiding problems with self-modifying code
- * execute a serializing instruction here.
- */
- isync
- sync
-
- /* jump to the entry point, usually the setup routine */
- mtlr r5
- blrl
-
-1: b 1b
-
-relocate_new_kernel_end:
-
- .globl relocate_new_kernel_size
-relocate_new_kernel_size:
- .long relocate_new_kernel_end - relocate_new_kernel
-
diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c
deleted file mode 100644
index 51e8094f52d6..000000000000
--- a/arch/ppc/kernel/setup.c
+++ /dev/null
@@ -1,572 +0,0 @@
-/*
- * Common prep boot and setup code.
- */
-
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/sched.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/reboot.h>
-#include <linux/delay.h>
-#include <linux/initrd.h>
-#include <linux/screen_info.h>
-#include <linux/bootmem.h>
-#include <linux/seq_file.h>
-#include <linux/root_dev.h>
-#include <linux/cpu.h>
-#include <linux/console.h>
-
-#include <asm/residual.h>
-#include <asm/io.h>
-#include <asm/prom.h>
-#include <asm/processor.h>
-#include <asm/pgtable.h>
-#include <asm/bootinfo.h>
-#include <asm/setup.h>
-#include <asm/smp.h>
-#include <asm/elf.h>
-#include <asm/cputable.h>
-#include <asm/bootx.h>
-#include <asm/btext.h>
-#include <asm/machdep.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <asm/sections.h>
-#include <asm/nvram.h>
-#include <asm/xmon.h>
-#include <asm/ocp.h>
-#include <asm/irq.h>
-
-#define USES_PPC_SYS (defined(CONFIG_MPC10X_BRIDGE) || defined(CONFIG_8260) || \
- defined(CONFIG_PPC_MPC52xx))
-
-#if USES_PPC_SYS
-#include <asm/ppc_sys.h>
-#endif
-
-#if defined CONFIG_KGDB
-#include <asm/kgdb.h>
-#endif
-
-extern void platform_init(unsigned long r3, unsigned long r4,
- unsigned long r5, unsigned long r6, unsigned long r7);
-extern void reloc_got2(unsigned long offset);
-
-extern void ppc6xx_idle(void);
-extern void power4_idle(void);
-
-extern boot_infos_t *boot_infos;
-
-/* Used with the BI_MEMSIZE bootinfo parameter to store the memory
- size value reported by the boot loader. */
-unsigned long boot_mem_size;
-
-unsigned long ISA_DMA_THRESHOLD;
-unsigned int DMA_MODE_READ;
-unsigned int DMA_MODE_WRITE;
-
-#ifdef CONFIG_PPC_PREP
-extern void prep_init(unsigned long r3, unsigned long r4,
- unsigned long r5, unsigned long r6, unsigned long r7);
-
-dev_t boot_dev;
-#endif /* CONFIG_PPC_PREP */
-
-int have_of;
-EXPORT_SYMBOL(have_of);
-
-#ifdef __DO_IRQ_CANON
-int ppc_do_canonicalize_irqs;
-EXPORT_SYMBOL(ppc_do_canonicalize_irqs);
-#endif
-
-#ifdef CONFIG_VGA_CONSOLE
-unsigned long vgacon_remap_base;
-#endif
-
-struct machdep_calls ppc_md;
-
-/*
- * These are used in binfmt_elf.c to put aux entries on the stack
- * for each elf executable being started.
- */
-int dcache_bsize;
-int icache_bsize;
-int ucache_bsize;
-
-#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_FB_VGA16) || \
- defined(CONFIG_FB_VGA16_MODULE) || defined(CONFIG_FB_VESA)
-struct screen_info screen_info = {
- 0, 25, /* orig-x, orig-y */
- 0, /* unused */
- 0, /* orig-video-page */
- 0, /* orig-video-mode */
- 80, /* orig-video-cols */
- 0,0,0, /* ega_ax, ega_bx, ega_cx */
- 25, /* orig-video-lines */
- 1, /* orig-video-isVGA */
- 16 /* orig-video-points */
-};
-#endif /* CONFIG_VGA_CONSOLE || CONFIG_FB_VGA16 || CONFIG_FB_VESA */
-
-void machine_restart(char *cmd)
-{
-#ifdef CONFIG_NVRAM
- nvram_sync();
-#endif
- ppc_md.restart(cmd);
-}
-
-static void ppc_generic_power_off(void)
-{
- ppc_md.power_off();
-}
-
-void machine_halt(void)
-{
-#ifdef CONFIG_NVRAM
- nvram_sync();
-#endif
- ppc_md.halt();
-}
-
-void (*pm_power_off)(void) = ppc_generic_power_off;
-
-void machine_power_off(void)
-{
-#ifdef CONFIG_NVRAM
- nvram_sync();
-#endif
- if (pm_power_off)
- pm_power_off();
- ppc_generic_power_off();
-}
-
-#ifdef CONFIG_TAU
-extern u32 cpu_temp(unsigned long cpu);
-extern u32 cpu_temp_both(unsigned long cpu);
-#endif /* CONFIG_TAU */
-
-int show_cpuinfo(struct seq_file *m, void *v)
-{
- int i = (int) v - 1;
- int err = 0;
- unsigned int pvr;
- unsigned short maj, min;
- unsigned long lpj;
-
- if (i >= NR_CPUS) {
- /* Show summary information */
-#ifdef CONFIG_SMP
- unsigned long bogosum = 0;
- for_each_online_cpu(i)
- bogosum += cpu_data[i].loops_per_jiffy;
- seq_printf(m, "total bogomips\t: %lu.%02lu\n",
- bogosum/(500000/HZ), bogosum/(5000/HZ) % 100);
-#endif /* CONFIG_SMP */
-
- if (ppc_md.show_cpuinfo != NULL)
- err = ppc_md.show_cpuinfo(m);
- return err;
- }
-
-#ifdef CONFIG_SMP
- if (!cpu_online(i))
- return 0;
- pvr = cpu_data[i].pvr;
- lpj = cpu_data[i].loops_per_jiffy;
-#else
- pvr = mfspr(SPRN_PVR);
- lpj = loops_per_jiffy;
-#endif
-
- seq_printf(m, "processor\t: %d\n", i);
- seq_printf(m, "cpu\t\t: ");
-
- if (cur_cpu_spec->pvr_mask)
- seq_printf(m, "%s", cur_cpu_spec->cpu_name);
- else
- seq_printf(m, "unknown (%08x)", pvr);
-#ifdef CONFIG_ALTIVEC
- if (cur_cpu_spec->cpu_features & CPU_FTR_ALTIVEC)
- seq_printf(m, ", altivec supported");
-#endif
- seq_printf(m, "\n");
-
-#ifdef CONFIG_TAU
- if (cur_cpu_spec->cpu_features & CPU_FTR_TAU) {
-#ifdef CONFIG_TAU_AVERAGE
- /* more straightforward, but potentially misleading */
- seq_printf(m, "temperature \t: %u C (uncalibrated)\n",
- cpu_temp(i));
-#else
- /* show the actual temp sensor range */
- u32 temp;
- temp = cpu_temp_both(i);
- seq_printf(m, "temperature \t: %u-%u C (uncalibrated)\n",
- temp & 0xff, temp >> 16);
-#endif
- }
-#endif /* CONFIG_TAU */
-
- if (ppc_md.show_percpuinfo != NULL) {
- err = ppc_md.show_percpuinfo(m, i);
- if (err)
- return err;
- }
-
- /* If we are a Freescale core do a simple check so
- * we dont have to keep adding cases in the future */
- if ((PVR_VER(pvr) & 0x8000) == 0x8000) {
- maj = PVR_MAJ(pvr);
- min = PVR_MIN(pvr);
- } else {
- switch (PVR_VER(pvr)) {
- case 0x0020: /* 403 family */
- maj = PVR_MAJ(pvr) + 1;
- min = PVR_MIN(pvr);
- break;
- case 0x1008: /* 740P/750P ?? */
- maj = ((pvr >> 8) & 0xFF) - 1;
- min = pvr & 0xFF;
- break;
- default:
- maj = (pvr >> 8) & 0xFF;
- min = pvr & 0xFF;
- break;
- }
- }
-
- seq_printf(m, "revision\t: %hd.%hd (pvr %04x %04x)\n",
- maj, min, PVR_VER(pvr), PVR_REV(pvr));
-
- seq_printf(m, "bogomips\t: %lu.%02lu\n",
- lpj / (500000/HZ), (lpj / (5000/HZ)) % 100);
-
-#if USES_PPC_SYS
- if (cur_ppc_sys_spec->ppc_sys_name)
- seq_printf(m, "chipset\t\t: %s\n",
- cur_ppc_sys_spec->ppc_sys_name);
-#endif
-
-#ifdef CONFIG_SMP
- seq_printf(m, "\n");
-#endif
-
- return 0;
-}
-
-static void *c_start(struct seq_file *m, loff_t *pos)
-{
- int i = *pos;
-
- return i <= NR_CPUS? (void *) (i + 1): NULL;
-}
-
-static void *c_next(struct seq_file *m, void *v, loff_t *pos)
-{
- ++*pos;
- return c_start(m, pos);
-}
-
-static void c_stop(struct seq_file *m, void *v)
-{
-}
-
-const struct seq_operations cpuinfo_op = {
- .start =c_start,
- .next = c_next,
- .stop = c_stop,
- .show = show_cpuinfo,
-};
-
-/*
- * We're called here very early in the boot. We determine the machine
- * type and call the appropriate low-level setup functions.
- * -- Cort <cort@fsmlabs.com>
- *
- * Note that the kernel may be running at an address which is different
- * from the address that it was linked at, so we must use RELOC/PTRRELOC
- * to access static data (including strings). -- paulus
- */
-__init
-unsigned long
-early_init(int r3, int r4, int r5)
-{
- unsigned long phys;
- unsigned long offset = reloc_offset();
- struct cpu_spec *spec;
-
- /* Default */
- phys = offset + KERNELBASE;
-
- /* First zero the BSS -- use memset, some arches don't have
- * caches on yet */
- memset_io(PTRRELOC(&__bss_start), 0, _end - __bss_start);
-
- /*
- * Identify the CPU type and fix up code sections
- * that depend on which cpu we have.
- */
-#if defined(CONFIG_440EP) && defined(CONFIG_PPC_FPU)
- /* We pass the virtual PVR here for 440EP as 440EP and 440GR have
- * identical PVRs and there is no reliable way to check for the FPU
- */
- spec = identify_cpu(offset, (mfspr(SPRN_PVR) | 0x8));
-#else
- spec = identify_cpu(offset, mfspr(SPRN_PVR));
-#endif
- do_feature_fixups(spec->cpu_features,
- PTRRELOC(&__start___ftr_fixup),
- PTRRELOC(&__stop___ftr_fixup));
-
- return phys;
-}
-
-#ifdef CONFIG_PPC_PREP
-/*
- * The PPC_PREP version of platform_init...
- */
-void __init
-platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
- unsigned long r6, unsigned long r7)
-{
-#ifdef CONFIG_BOOTX_TEXT
- if (boot_text_mapped) {
- btext_clearscreen();
- btext_welcome();
- }
-#endif
-
- parse_bootinfo(find_bootinfo());
-
- prep_init(r3, r4, r5, r6, r7);
-}
-#endif /* CONFIG_PPC_PREP */
-
-struct bi_record *find_bootinfo(void)
-{
- struct bi_record *rec;
-
- rec = (struct bi_record *)_ALIGN((ulong)__bss_start+(1<<20)-1,(1<<20));
- 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 *)_ALIGN((ulong)__bss_start+0x10000+(1<<20)-1,(1<<20));
- if ( rec->tag != BI_FIRST )
- return NULL;
- }
- return rec;
-}
-
-void parse_bootinfo(struct bi_record *rec)
-{
- if (rec == NULL || rec->tag != BI_FIRST)
- return;
- while (rec->tag != BI_LAST) {
- ulong *data = rec->data;
- switch (rec->tag) {
- case BI_CMD_LINE:
- strlcpy(cmd_line, (void *)data, sizeof(cmd_line));
- break;
-#ifdef CONFIG_BLK_DEV_INITRD
- case BI_INITRD:
- initrd_start = data[0] + KERNELBASE;
- initrd_end = data[0] + data[1] + KERNELBASE;
- break;
-#endif /* CONFIG_BLK_DEV_INITRD */
- case BI_MEMSIZE:
- boot_mem_size = data[0];
- break;
- }
- rec = (struct bi_record *)((ulong)rec + rec->size);
- }
-}
-
-/*
- * 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()).
- * This is called very early on the boot process, after a minimal
- * MMU environment has been set up but before MMU_init is called.
- */
-void __init
-machine_init(unsigned long r3, unsigned long r4, unsigned long r5,
- unsigned long r6, unsigned long r7)
-{
-#ifdef CONFIG_CMDLINE
- strlcpy(cmd_line, CONFIG_CMDLINE, sizeof(cmd_line));
-#endif /* CONFIG_CMDLINE */
-
-#ifdef CONFIG_6xx
- ppc_md.power_save = ppc6xx_idle;
-#endif
-
- platform_init(r3, r4, r5, r6, r7);
-
- if (ppc_md.progress)
- ppc_md.progress("id mach(): done", 0x200);
-}
-#ifdef CONFIG_BOOKE_WDT
-/* Checks wdt=x and wdt_period=xx command-line option */
-int __init early_parse_wdt(char *p)
-{
- if (p && strncmp(p, "0", 1) != 0)
- booke_wdt_enabled = 1;
-
- return 0;
-}
-early_param("wdt", early_parse_wdt);
-
-int __init early_parse_wdt_period (char *p)
-{
- if (p)
- booke_wdt_period = simple_strtoul(p, NULL, 0);
-
- return 0;
-}
-early_param("wdt_period", early_parse_wdt_period);
-#endif /* CONFIG_BOOKE_WDT */
-
-/* Checks "l2cr=xxxx" command-line option */
-int __init ppc_setup_l2cr(char *str)
-{
- if (cpu_has_feature(CPU_FTR_L2CR)) {
- unsigned long val = simple_strtoul(str, NULL, 0);
- printk(KERN_INFO "l2cr set to %lx\n", val);
- _set_L2CR(0); /* force invalidate by disable cache */
- _set_L2CR(val); /* and enable it */
- }
- return 1;
-}
-__setup("l2cr=", ppc_setup_l2cr);
-
-#ifdef CONFIG_GENERIC_NVRAM
-
-/* Generic nvram hooks used by drivers/char/gen_nvram.c */
-unsigned char nvram_read_byte(int addr)
-{
- if (ppc_md.nvram_read_val)
- return ppc_md.nvram_read_val(addr);
- return 0xff;
-}
-EXPORT_SYMBOL(nvram_read_byte);
-
-void nvram_write_byte(unsigned char val, int addr)
-{
- if (ppc_md.nvram_write_val)
- ppc_md.nvram_write_val(addr, val);
-}
-EXPORT_SYMBOL(nvram_write_byte);
-
-void nvram_sync(void)
-{
- if (ppc_md.nvram_sync)
- ppc_md.nvram_sync();
-}
-EXPORT_SYMBOL(nvram_sync);
-
-#endif /* CONFIG_NVRAM */
-
-static struct cpu cpu_devices[NR_CPUS];
-
-int __init ppc_init(void)
-{
- int i;
-
- /* clear the progress line */
- if ( ppc_md.progress ) ppc_md.progress(" ", 0xffff);
-
- /* register CPU devices */
- for_each_possible_cpu(i)
- register_cpu(&cpu_devices[i], i);
-
- /* call platform init */
- if (ppc_md.init != NULL) {
- ppc_md.init();
- }
- return 0;
-}
-
-arch_initcall(ppc_init);
-
-/* Warning, IO base is not yet inited */
-void __init setup_arch(char **cmdline_p)
-{
- extern char *klimit;
- extern void do_init_bootmem(void);
-
- /* so udelay does something sensible, assume <= 1000 bogomips */
- loops_per_jiffy = 500000000 / HZ;
-
- if (ppc_md.init_early)
- ppc_md.init_early();
-
-#ifdef CONFIG_XMON
- xmon_init(1);
- if (strstr(cmd_line, "xmon"))
- xmon(NULL);
-#endif /* CONFIG_XMON */
- if ( ppc_md.progress ) ppc_md.progress("setup_arch: enter", 0x3eab);
-
-#if defined(CONFIG_KGDB)
- if (ppc_md.kgdb_map_scc)
- ppc_md.kgdb_map_scc();
- set_debug_traps();
- if (strstr(cmd_line, "gdb")) {
- if (ppc_md.progress)
- ppc_md.progress("setup_arch: kgdb breakpoint", 0x4000);
- printk("kgdb breakpoint activated\n");
- breakpoint();
- }
-#endif
-
- /*
- * Set cache line size based on type of cpu as a default.
- * Systems with OF can look in the properties on the cpu node(s)
- * for a possibly more accurate value.
- */
- if (! cpu_has_feature(CPU_FTR_UNIFIED_ID_CACHE)) {
- dcache_bsize = cur_cpu_spec->dcache_bsize;
- icache_bsize = cur_cpu_spec->icache_bsize;
- ucache_bsize = 0;
- } else
- ucache_bsize = dcache_bsize = icache_bsize
- = cur_cpu_spec->dcache_bsize;
-
- /* reboot on panic */
- panic_timeout = 180;
-
- init_mm.start_code = PAGE_OFFSET;
- init_mm.end_code = (unsigned long) _etext;
- init_mm.end_data = (unsigned long) _edata;
- init_mm.brk = (unsigned long) klimit;
-
- /* Save unparsed command line copy for /proc/cmdline */
- strlcpy(boot_command_line, cmd_line, COMMAND_LINE_SIZE);
- *cmdline_p = cmd_line;
-
- parse_early_param();
-
- /* set up the bootmem stuff with available memory */
- do_init_bootmem();
- if ( ppc_md.progress ) ppc_md.progress("setup_arch: bootmem", 0x3eab);
-
-#ifdef CONFIG_PPC_OCP
- /* Initialize OCP device list */
- ocp_early_init();
- if ( ppc_md.progress ) ppc_md.progress("ocp: exit", 0x3eab);
-#endif
-
-#ifdef CONFIG_DUMMY_CONSOLE
- conswitchp = &dummy_con;
-#endif
-
- ppc_md.setup_arch();
- if ( ppc_md.progress ) ppc_md.progress("arch: exit", 0x3eab);
-
- paging_init();
-}
diff --git a/arch/ppc/kernel/smp-tbsync.c b/arch/ppc/kernel/smp-tbsync.c
deleted file mode 100644
index d0cf3f86931d..000000000000
--- a/arch/ppc/kernel/smp-tbsync.c
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * Smp timebase synchronization for ppc.
- *
- * Copyright (C) 2003 Samuel Rydh (samuel@ibrium.se)
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/smp.h>
-#include <linux/unistd.h>
-#include <linux/init.h>
-#include <asm/atomic.h>
-#include <asm/smp.h>
-#include <asm/time.h>
-
-#define NUM_ITER 300
-
-enum {
- kExit=0, kSetAndTest, kTest
-};
-
-static struct {
- volatile int tbu;
- volatile int tbl;
- volatile int mark;
- volatile int cmd;
- volatile int handshake;
- int filler[3];
-
- volatile int ack;
- int filler2[7];
-
- volatile int race_result;
-} *tbsync;
-
-static volatile int running;
-
-static void __devinit
-enter_contest( int mark, int add )
-{
- while( (int)(get_tbl() - mark) < 0 )
- tbsync->race_result = add;
-}
-
-void __devinit
-smp_generic_take_timebase( void )
-{
- int cmd, tbl, tbu;
- unsigned long flags;
-
- local_irq_save(flags);
- while( !running )
- ;
- rmb();
-
- for( ;; ) {
- tbsync->ack = 1;
- while( !tbsync->handshake )
- ;
- rmb();
-
- cmd = tbsync->cmd;
- tbl = tbsync->tbl;
- tbu = tbsync->tbu;
- tbsync->ack = 0;
- if( cmd == kExit )
- break;
-
- if( cmd == kSetAndTest ) {
- while( tbsync->handshake )
- ;
- asm volatile ("mttbl %0" :: "r" (tbl) );
- asm volatile ("mttbu %0" :: "r" (tbu) );
- } else {
- while( tbsync->handshake )
- ;
- }
- enter_contest( tbsync->mark, -1 );
- }
- local_irq_restore(flags);
-}
-
-static int __devinit
-start_contest( int cmd, int offset, int num )
-{
- int i, tbu, tbl, mark, score=0;
-
- tbsync->cmd = cmd;
-
- local_irq_disable();
- for( i=-3; i<num; ) {
- tbl = get_tbl() + 400;
- tbsync->tbu = tbu = get_tbu();
- tbsync->tbl = tbl + offset;
- tbsync->mark = mark = tbl + 400;
-
- wmb();
-
- tbsync->handshake = 1;
- while( tbsync->ack )
- ;
-
- while( (int)(get_tbl() - tbl) <= 0 )
- ;
- tbsync->handshake = 0;
- enter_contest( mark, 1 );
-
- while( !tbsync->ack )
- ;
-
- if( tbsync->tbu != get_tbu() || ((tbsync->tbl ^ get_tbl()) & 0x80000000) )
- continue;
- if( i++ > 0 )
- score += tbsync->race_result;
- }
- local_irq_enable();
- return score;
-}
-
-void __devinit
-smp_generic_give_timebase( void )
-{
- int i, score, score2, old, min=0, max=5000, offset=1000;
-
- printk("Synchronizing timebase\n");
-
- /* if this fails then this kernel won't work anyway... */
- tbsync = kzalloc( sizeof(*tbsync), GFP_KERNEL );
- mb();
- running = 1;
-
- while( !tbsync->ack )
- ;
-
- /* binary search */
- for( old=-1 ; old != offset ; offset=(min+max)/2 ) {
- score = start_contest( kSetAndTest, offset, NUM_ITER );
-
- printk("score %d, offset %d\n", score, offset );
-
- if( score > 0 )
- max = offset;
- else
- min = offset;
- old = offset;
- }
- score = start_contest( kSetAndTest, min, NUM_ITER );
- score2 = start_contest( kSetAndTest, max, NUM_ITER );
-
- printk( "Min %d (score %d), Max %d (score %d)\n", min, score, max, score2 );
- score = abs( score );
- score2 = abs( score2 );
- offset = (score < score2) ? min : max;
-
- /* guard against inaccurate mttb */
- for( i=0; i<10; i++ ) {
- start_contest( kSetAndTest, offset, NUM_ITER/10 );
-
- if( (score2=start_contest(kTest, offset, NUM_ITER)) < 0 )
- score2 = -score2;
- if( score2 <= score || score2 < 20 )
- break;
- }
- printk("Final offset: %d (%d/%d)\n", offset, score2, NUM_ITER );
-
- /* exiting */
- tbsync->cmd = kExit;
- wmb();
- tbsync->handshake = 1;
- while( tbsync->ack )
- ;
- tbsync->handshake = 0;
- kfree( tbsync );
- tbsync = NULL;
- running = 0;
-
- /* all done */
- smp_tb_synchronized = 1;
-}
diff --git a/arch/ppc/kernel/smp.c b/arch/ppc/kernel/smp.c
deleted file mode 100644
index 055998575cb4..000000000000
--- a/arch/ppc/kernel/smp.c
+++ /dev/null
@@ -1,414 +0,0 @@
-/*
- * Smp support for ppc.
- *
- * Written by Cort Dougan (cort@cs.nmt.edu) borrowing a great
- * deal of code from the sparc and intel versions.
- *
- * Copyright (C) 1999 Cort Dougan <cort@cs.nmt.edu>
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/smp.h>
-#include <linux/interrupt.h>
-#include <linux/kernel_stat.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/spinlock.h>
-#include <linux/cache.h>
-
-#include <asm/ptrace.h>
-#include <asm/atomic.h>
-#include <asm/irq.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#include <asm/io.h>
-#include <asm/prom.h>
-#include <asm/smp.h>
-#include <asm/residual.h>
-#include <asm/time.h>
-#include <asm/thread_info.h>
-#include <asm/tlbflush.h>
-#include <asm/xmon.h>
-#include <asm/machdep.h>
-
-volatile int smp_commenced;
-int smp_tb_synchronized;
-struct cpuinfo_PPC cpu_data[NR_CPUS];
-atomic_t ipi_recv;
-atomic_t ipi_sent;
-cpumask_t cpu_online_map;
-cpumask_t cpu_possible_map;
-int smp_hw_index[NR_CPUS];
-struct thread_info *secondary_ti;
-static struct task_struct *idle_tasks[NR_CPUS];
-
-EXPORT_SYMBOL(cpu_online_map);
-EXPORT_SYMBOL(cpu_possible_map);
-
-/* SMP operations for this machine */
-struct smp_ops_t *smp_ops;
-
-/* all cpu mappings are 1-1 -- Cort */
-volatile unsigned long cpu_callin_map[NR_CPUS];
-
-int start_secondary(void *);
-void smp_call_function_interrupt(void);
-static int __smp_call_function(void (*func) (void *info), void *info,
- int wait, int target);
-
-/* Low level assembly function used to backup CPU 0 state */
-extern void __save_cpu_setup(void);
-
-/* Since OpenPIC has only 4 IPIs, we use slightly different message numbers.
- *
- * Make sure this matches openpic_request_IPIs in open_pic.c, or what shows up
- * in /proc/interrupts will be wrong!!! --Troy */
-#define PPC_MSG_CALL_FUNCTION 0
-#define PPC_MSG_RESCHEDULE 1
-#define PPC_MSG_INVALIDATE_TLB 2
-#define PPC_MSG_XMON_BREAK 3
-
-static inline void
-smp_message_pass(int target, int msg)
-{
- if (smp_ops) {
- atomic_inc(&ipi_sent);
- smp_ops->message_pass(target, msg);
- }
-}
-
-/*
- * Common functions
- */
-void smp_message_recv(int msg)
-{
- atomic_inc(&ipi_recv);
-
- switch( msg ) {
- case PPC_MSG_CALL_FUNCTION:
- smp_call_function_interrupt();
- break;
- case PPC_MSG_RESCHEDULE:
- set_need_resched();
- break;
- case PPC_MSG_INVALIDATE_TLB:
- _tlbia();
- break;
-#ifdef CONFIG_XMON
- case PPC_MSG_XMON_BREAK:
- xmon(get_irq_regs());
- break;
-#endif /* CONFIG_XMON */
- default:
- printk("SMP %d: smp_message_recv(): unknown msg %d\n",
- smp_processor_id(), msg);
- break;
- }
-}
-
-/*
- * 750's don't broadcast tlb invalidates so
- * we have to emulate that behavior.
- * -- Cort
- */
-void smp_send_tlb_invalidate(int cpu)
-{
- if ( PVR_VER(mfspr(SPRN_PVR)) == 8 )
- smp_message_pass(MSG_ALL_BUT_SELF, PPC_MSG_INVALIDATE_TLB);
-}
-
-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, PPC_MSG_RESCHEDULE);
-}
-
-#ifdef CONFIG_XMON
-void smp_send_xmon_break(int cpu)
-{
- smp_message_pass(cpu, PPC_MSG_XMON_BREAK);
-}
-#endif /* CONFIG_XMON */
-
-static void stop_this_cpu(void *dummy)
-{
- local_irq_disable();
- while (1)
- ;
-}
-
-void smp_send_stop(void)
-{
- smp_call_function(stop_this_cpu, NULL, 1, 0);
-}
-
-/*
- * Structure and data for smp_call_function(). This is designed to minimise
- * static memory requirements. It also looks cleaner.
- * Stolen from the i386 version.
- */
-static DEFINE_SPINLOCK(call_lock);
-
-static struct call_data_struct {
- void (*func) (void *info);
- void *info;
- atomic_t started;
- atomic_t finished;
- int wait;
-} *call_data;
-
-/*
- * this function sends a 'generic call function' IPI to all other CPUs
- * in the system.
- */
-
-int smp_call_function(void (*func) (void *info), void *info, int nonatomic,
- int wait)
-/*
- * [SUMMARY] Run a function on all other CPUs.
- * <func> The function to run. This must be fast and non-blocking.
- * <info> An arbitrary pointer to pass to the function.
- * <nonatomic> currently unused.
- * <wait> If true, wait (atomically) until function has completed on other CPUs.
- * [RETURNS] 0 on success, else a negative status code. Does not return until
- * remote CPUs are nearly ready to execute <<func>> or are or have executed.
- *
- * You must not call this function with disabled interrupts or from a
- * hardware interrupt handler or from a bottom half handler.
- */
-{
- /* FIXME: get cpu lock with hotplug cpus, or change this to
- bitmask. --RR */
- if (num_online_cpus() <= 1)
- return 0;
- /* Can deadlock when called with interrupts disabled */
- WARN_ON(irqs_disabled());
- return __smp_call_function(func, info, wait, MSG_ALL_BUT_SELF);
-}
-
-static int __smp_call_function(void (*func) (void *info), void *info,
- int wait, int target)
-{
- struct call_data_struct data;
- int ret = -1;
- int timeout;
- int ncpus = 1;
-
- if (target == MSG_ALL_BUT_SELF)
- ncpus = num_online_cpus() - 1;
- else if (target == MSG_ALL)
- ncpus = num_online_cpus();
-
- data.func = func;
- data.info = info;
- atomic_set(&data.started, 0);
- data.wait = wait;
- if (wait)
- atomic_set(&data.finished, 0);
-
- spin_lock(&call_lock);
- call_data = &data;
- /* Send a message to all other CPUs and wait for them to respond */
- smp_message_pass(target, PPC_MSG_CALL_FUNCTION);
-
- /* Wait for response */
- timeout = 1000000;
- while (atomic_read(&data.started) != ncpus) {
- if (--timeout == 0) {
- printk("smp_call_function on cpu %d: other cpus not responding (%d)\n",
- smp_processor_id(), atomic_read(&data.started));
- goto out;
- }
- barrier();
- udelay(1);
- }
-
- if (wait) {
- timeout = 1000000;
- while (atomic_read(&data.finished) != ncpus) {
- if (--timeout == 0) {
- printk("smp_call_function on cpu %d: other cpus not finishing (%d/%d)\n",
- smp_processor_id(), atomic_read(&data.finished), atomic_read(&data.started));
- goto out;
- }
- barrier();
- udelay(1);
- }
- }
- ret = 0;
-
- out:
- spin_unlock(&call_lock);
- return ret;
-}
-
-void smp_call_function_interrupt(void)
-{
- void (*func) (void *info) = call_data->func;
- void *info = call_data->info;
- int wait = call_data->wait;
-
- /*
- * Notify initiating CPU that I've grabbed the data and am
- * about to execute the function
- */
- atomic_inc(&call_data->started);
- /*
- * At this point the info structure may be out of scope unless wait==1
- */
- (*func)(info);
- if (wait)
- atomic_inc(&call_data->finished);
-}
-
-static void __devinit smp_store_cpu_info(int id)
-{
- struct cpuinfo_PPC *c = &cpu_data[id];
-
- /* assume bogomips are same for everything */
- c->loops_per_jiffy = loops_per_jiffy;
- c->pvr = mfspr(SPRN_PVR);
-}
-
-void __init smp_prepare_cpus(unsigned int max_cpus)
-{
- int num_cpus, i, cpu;
- struct task_struct *p;
-
- /* Fixup boot cpu */
- smp_store_cpu_info(smp_processor_id());
- cpu_callin_map[smp_processor_id()] = 1;
-
- if (smp_ops == NULL) {
- printk("SMP not supported on this machine.\n");
- return;
- }
-
- /* Probe platform for CPUs: always linear. */
- num_cpus = smp_ops->probe();
-
- if (num_cpus < 2)
- smp_tb_synchronized = 1;
-
- for (i = 0; i < num_cpus; ++i)
- cpu_set(i, cpu_possible_map);
-
- /* Backup CPU 0 state */
- __save_cpu_setup();
-
- for_each_possible_cpu(cpu) {
- if (cpu == smp_processor_id())
- continue;
- /* create a process for the processor */
- p = fork_idle(cpu);
- if (IS_ERR(p))
- panic("failed fork for CPU %u: %li", cpu, PTR_ERR(p));
- task_thread_info(p)->cpu = cpu;
- idle_tasks[cpu] = p;
- }
-}
-
-void __devinit smp_prepare_boot_cpu(void)
-{
- cpu_set(smp_processor_id(), cpu_online_map);
- cpu_set(smp_processor_id(), cpu_possible_map);
-}
-
-int __init setup_profiling_timer(unsigned int multiplier)
-{
- return 0;
-}
-
-/* Processor coming up starts here */
-int __devinit start_secondary(void *unused)
-{
- int cpu;
-
- atomic_inc(&init_mm.mm_count);
- current->active_mm = &init_mm;
-
- cpu = smp_processor_id();
- smp_store_cpu_info(cpu);
- set_dec(tb_ticks_per_jiffy);
- preempt_disable();
- cpu_callin_map[cpu] = 1;
-
- printk("CPU %d done callin...\n", cpu);
- smp_ops->setup_cpu(cpu);
- printk("CPU %d done setup...\n", cpu);
- smp_ops->take_timebase();
- printk("CPU %d done timebase take...\n", cpu);
-
- spin_lock(&call_lock);
- cpu_set(cpu, cpu_online_map);
- spin_unlock(&call_lock);
-
- local_irq_enable();
-
- cpu_idle();
- return 0;
-}
-
-int __cpu_up(unsigned int cpu)
-{
- char buf[32];
- int c;
-
- secondary_ti = task_thread_info(idle_tasks[cpu]);
- mb();
-
- /*
- * There was a cache flush loop here to flush the cache
- * to memory for the first 8MB of RAM. The cache flush
- * has been pushed into the kick_cpu function for those
- * platforms that need it.
- */
-
- /* wake up cpu */
- smp_ops->kick_cpu(cpu);
-
- /*
- * wait to see if the cpu made a callin (is actually up).
- * use this value that I found through experimentation.
- * -- Cort
- */
- for (c = 1000; c && !cpu_callin_map[cpu]; c--)
- udelay(100);
-
- if (!cpu_callin_map[cpu]) {
- sprintf(buf, "didn't find cpu %u", cpu);
- if (ppc_md.progress) ppc_md.progress(buf, 0x360+cpu);
- printk("Processor %u is stuck.\n", cpu);
- return -ENOENT;
- }
-
- sprintf(buf, "found cpu %u", cpu);
- if (ppc_md.progress) ppc_md.progress(buf, 0x350+cpu);
- printk("Processor %d found.\n", cpu);
-
- smp_ops->give_timebase();
-
- /* Wait until cpu puts itself in the online map */
- while (!cpu_online(cpu))
- cpu_relax();
-
- return 0;
-}
-
-void smp_cpus_done(unsigned int max_cpus)
-{
- smp_ops->setup_cpu(0);
-}
diff --git a/arch/ppc/kernel/softemu8xx.c b/arch/ppc/kernel/softemu8xx.c
deleted file mode 100644
index 9bbb6bf7b645..000000000000
--- a/arch/ppc/kernel/softemu8xx.c
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Software emulation of some PPC instructions for the 8xx core.
- *
- * Copyright (C) 1998 Dan Malek (dmalek@jlc.net)
- *
- * Software floating emuation for the MPC8xx processor. I did this mostly
- * because it was easier than trying to get the libraries compiled for
- * software floating point. The goal is still to get the libraries done,
- * but I lost patience and needed some hacks to at least get init and
- * shells running. The first problem is the setjmp/longjmp that save
- * and restore the floating point registers.
- *
- * For this emulation, our working registers are found on the register
- * save area.
- */
-
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/stddef.h>
-#include <linux/unistd.h>
-#include <linux/ptrace.h>
-#include <linux/slab.h>
-#include <linux/user.h>
-#include <linux/a.out.h>
-#include <linux/interrupt.h>
-
-#include <asm/pgtable.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <asm/io.h>
-
-extern void
-print_8xx_pte(struct mm_struct *mm, unsigned long addr);
-extern int
-get_8xx_pte(struct mm_struct *mm, unsigned long addr);
-
-/* Eventually we may need a look-up table, but this works for now.
-*/
-#define LFS 48
-#define LFD 50
-#define LFDU 51
-#define STFD 54
-#define STFDU 55
-#define FMR 63
-
-/*
- * We return 0 on success, 1 on unimplemented instruction, and EFAULT
- * if a load/store faulted.
- */
-int
-Soft_emulate_8xx(struct pt_regs *regs)
-{
- uint inst, instword;
- uint flreg, idxreg, disp;
- uint retval;
- signed short sdisp;
- uint *ea, *ip;
-
- retval = 0;
-
- instword = *((uint *)regs->nip);
- inst = instword >> 26;
-
- flreg = (instword >> 21) & 0x1f;
- idxreg = (instword >> 16) & 0x1f;
- disp = instword & 0xffff;
-
- ea = (uint *)(regs->gpr[idxreg] + disp);
- ip = (uint *)&current->thread.fpr[flreg];
-
- switch ( inst )
- {
- case LFD:
- /* this is a 16 bit quantity that is sign extended
- * so use a signed short here -- Cort
- */
- sdisp = (instword & 0xffff);
- ea = (uint *)(regs->gpr[idxreg] + sdisp);
- if (copy_from_user(ip, ea, sizeof(double)))
- retval = -EFAULT;
- break;
-
- case LFDU:
- if (copy_from_user(ip, ea, sizeof(double)))
- retval = -EFAULT;
- else
- regs->gpr[idxreg] = (uint)ea;
- break;
- case LFS:
- sdisp = (instword & 0xffff);
- ea = (uint *)(regs->gpr[idxreg] + sdisp);
- if (copy_from_user(ip, ea, sizeof(float)))
- retval = -EFAULT;
- break;
- case STFD:
- /* this is a 16 bit quantity that is sign extended
- * so use a signed short here -- Cort
- */
- sdisp = (instword & 0xffff);
- ea = (uint *)(regs->gpr[idxreg] + sdisp);
- if (copy_to_user(ea, ip, sizeof(double)))
- retval = -EFAULT;
- break;
-
- case STFDU:
- if (copy_to_user(ea, ip, sizeof(double)))
- retval = -EFAULT;
- else
- regs->gpr[idxreg] = (uint)ea;
- break;
- case FMR:
- /* assume this is a fp move -- Cort */
- memcpy( ip, &current->thread.fpr[(instword>>11)&0x1f],
- sizeof(double) );
- break;
- default:
- retval = 1;
- printk("Bad emulation %s/%d\n"
- " NIP: %08lx instruction: %08x opcode: %x "
- "A: %x B: %x C: %x code: %x rc: %x\n",
- current->comm,current->pid,
- regs->nip,
- instword,inst,
- (instword>>16)&0x1f,
- (instword>>11)&0x1f,
- (instword>>6)&0x1f,
- (instword>>1)&0x3ff,
- instword&1);
- {
- int pa;
- print_8xx_pte(current->mm,regs->nip);
- pa = get_8xx_pte(current->mm,regs->nip) & PAGE_MASK;
- pa |= (regs->nip & ~PAGE_MASK);
- pa = (unsigned long)__va(pa);
- printk("Kernel VA for NIP %x ", pa);
- print_8xx_pte(current->mm,pa);
- }
-
- }
-
- if (retval == 0)
- regs->nip += 4;
- return(retval);
-}
-
diff --git a/arch/ppc/kernel/time.c b/arch/ppc/kernel/time.c
deleted file mode 100644
index 18ee851e33e3..000000000000
--- a/arch/ppc/kernel/time.c
+++ /dev/null
@@ -1,445 +0,0 @@
-/*
- * Common time routines among all ppc machines.
- *
- * Written by Cort Dougan (cort@cs.nmt.edu) to merge
- * Paul Mackerras' version and mine for PReP and Pmac.
- * MPC8xx/MBX changes by Dan Malek (dmalek@jlc.net).
- *
- * First round of bugfixes by Gabriel Paubert (paubert@iram.es)
- * to make clock more stable (2.4.0-test5). The only thing
- * that this code assumes is that the timebases have been synchronized
- * by firmware on SMP and are never stopped (never do sleep
- * on SMP then, nap and doze are OK).
- *
- * TODO (not necessarily in this file):
- * - improve precision and reproducibility of timebase frequency
- * measurement at boot time.
- * - get rid of xtime_lock for gettimeofday (generic kernel problem
- * to be implemented on all architectures for SMP scalability and
- * eventually implementing gettimeofday without entering the kernel).
- * - put all time/clock related variables in a single structure
- * to minimize number of cache lines touched by gettimeofday()
- * - for astronomical applications: add a new function to get
- * non ambiguous timestamps even around leap seconds. This needs
- * a new timestamp format and a good name.
- *
- *
- * The following comment is partially obsolete (at least the long wait
- * is no more a valid reason):
- * Since the MPC8xx has a programmable interrupt timer, I decided to
- * use that rather than the decrementer. Two reasons: 1.) the clock
- * frequency is low, causing 2.) a long wait in the timer interrupt
- * while ((d = get_dec()) == dval)
- * loop. The MPC8xx can be driven from a variety of input clocks,
- * so a number of assumptions have been made here because the kernel
- * parameter HZ is a constant. We assume (correctly, today :-) that
- * the MPC8xx on the MBX board is driven from a 32.768 kHz crystal.
- * This is then divided by 4, providing a 8192 Hz clock into the PIT.
- * Since it is not possible to get a nice 100 Hz clock out of this, without
- * creating a software PLL, I have set HZ to 128. -- Dan
- *
- * 1997-09-10 Updated NTP code according to technical memorandum Jan '96
- * "A Kernel Model for Precision Timekeeping" by Dave Mills
- */
-
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/param.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/timex.h>
-#include <linux/kernel_stat.h>
-#include <linux/mc146818rtc.h>
-#include <linux/time.h>
-#include <linux/init.h>
-#include <linux/profile.h>
-
-#include <asm/io.h>
-#include <asm/nvram.h>
-#include <asm/cache.h>
-#include <asm/8xx_immap.h>
-#include <asm/machdep.h>
-#include <asm/irq_regs.h>
-
-#include <asm/time.h>
-
-unsigned long disarm_decr[NR_CPUS];
-
-extern struct timezone sys_tz;
-
-/* keep track of when we need to update the rtc */
-time_t last_rtc_update;
-
-/* The decrementer counts down by 128 every 128ns on a 601. */
-#define DECREMENTER_COUNT_601 (1000000000 / HZ)
-
-unsigned tb_ticks_per_jiffy;
-unsigned tb_to_us;
-unsigned tb_last_stamp;
-unsigned long tb_to_ns_scale;
-
-/* used for timezone offset */
-static long timezone_offset;
-
-DEFINE_SPINLOCK(rtc_lock);
-
-EXPORT_SYMBOL(rtc_lock);
-
-/* Timer interrupt helper function */
-static inline int tb_delta(unsigned *jiffy_stamp) {
- int delta;
- if (__USE_RTC()) {
- delta = get_rtcl();
- if (delta < *jiffy_stamp) *jiffy_stamp -= 1000000000;
- delta -= *jiffy_stamp;
- } else {
- delta = get_tbl() - *jiffy_stamp;
- }
- return delta;
-}
-
-#ifdef CONFIG_SMP
-unsigned long profile_pc(struct pt_regs *regs)
-{
- unsigned long pc = instruction_pointer(regs);
-
- if (in_lock_functions(pc))
- return regs->link;
-
- return pc;
-}
-EXPORT_SYMBOL(profile_pc);
-#endif
-
-void wakeup_decrementer(void)
-{
- set_dec(tb_ticks_per_jiffy);
- /* No currently-supported powerbook has a 601,
- * so use get_tbl, not native
- */
- last_jiffy_stamp(0) = tb_last_stamp = get_tbl();
-}
-
-/*
- * timer_interrupt - gets called when the decrementer overflows,
- * with interrupts disabled.
- * We set it up to overflow again in 1/HZ seconds.
- */
-void timer_interrupt(struct pt_regs * regs)
-{
- struct pt_regs *old_regs;
- int next_dec;
- unsigned long cpu = smp_processor_id();
- unsigned jiffy_stamp = last_jiffy_stamp(cpu);
- extern void do_IRQ(struct pt_regs *);
-
- if (atomic_read(&ppc_n_lost_interrupts) != 0)
- do_IRQ(regs);
-
- old_regs = set_irq_regs(regs);
- irq_enter();
-
- while ((next_dec = tb_ticks_per_jiffy - tb_delta(&jiffy_stamp)) <= 0) {
- jiffy_stamp += tb_ticks_per_jiffy;
-
- profile_tick(CPU_PROFILING);
- update_process_times(user_mode(regs));
-
- if (smp_processor_id())
- continue;
-
- /* We are in an interrupt, no need to save/restore flags */
- write_seqlock(&xtime_lock);
- tb_last_stamp = jiffy_stamp;
- do_timer(1);
-
- /*
- * update the rtc when needed, this should be performed on the
- * right fraction of a second. Half or full second ?
- * Full second works on mk48t59 clocks, others need testing.
- * Note that this update is basically only used through
- * the adjtimex system calls. Setting the HW clock in
- * any other way is a /dev/rtc and userland business.
- * This is still wrong by -0.5/+1.5 jiffies because of the
- * timer interrupt resolution and possible delay, but here we
- * hit a quantization limit which can only be solved by higher
- * resolution timers and decoupling time management from timer
- * interrupts. This is also wrong on the clocks
- * which require being written at the half second boundary.
- * We should have an rtc call that only sets the minutes and
- * seconds like on Intel to avoid problems with non UTC clocks.
- */
- if ( ppc_md.set_rtc_time && ntp_synced() &&
- xtime.tv_sec - last_rtc_update >= 659 &&
- abs((xtime.tv_nsec / 1000) - (1000000-1000000/HZ)) < 500000/HZ) {
- if (ppc_md.set_rtc_time(xtime.tv_sec+1 + timezone_offset) == 0)
- last_rtc_update = xtime.tv_sec+1;
- else
- /* Try again one minute later */
- last_rtc_update += 60;
- }
- write_sequnlock(&xtime_lock);
- }
- if ( !disarm_decr[smp_processor_id()] )
- set_dec(next_dec);
- last_jiffy_stamp(cpu) = jiffy_stamp;
-
- if (ppc_md.heartbeat && !ppc_md.heartbeat_count--)
- ppc_md.heartbeat();
-
- irq_exit();
- set_irq_regs(old_regs);
-}
-
-/*
- * This version of gettimeofday has microsecond resolution.
- */
-void do_gettimeofday(struct timeval *tv)
-{
- unsigned long flags;
- unsigned long seq;
- unsigned delta, usec, sec;
-
- do {
- seq = read_seqbegin_irqsave(&xtime_lock, flags);
- sec = xtime.tv_sec;
- usec = (xtime.tv_nsec / 1000);
- delta = tb_ticks_since(tb_last_stamp);
-#ifdef CONFIG_SMP
- /* As long as timebases are not in sync, gettimeofday can only
- * have jiffy resolution on SMP.
- */
- if (!smp_tb_synchronized)
- delta = 0;
-#endif /* CONFIG_SMP */
- } while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
-
- usec += mulhwu(tb_to_us, delta);
- while (usec >= 1000000) {
- sec++;
- usec -= 1000000;
- }
- tv->tv_sec = sec;
- tv->tv_usec = usec;
-}
-
-EXPORT_SYMBOL(do_gettimeofday);
-
-int do_settimeofday(struct timespec *tv)
-{
- time_t wtm_sec, new_sec = tv->tv_sec;
- long wtm_nsec, new_nsec = tv->tv_nsec;
- unsigned long flags;
- int tb_delta;
-
- if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
- return -EINVAL;
-
- write_seqlock_irqsave(&xtime_lock, flags);
- /* Updating the RTC is not the job of this code. If the time is
- * stepped under NTP, the RTC will be update after STA_UNSYNC
- * is cleared. Tool like clock/hwclock either copy the RTC
- * to the system time, in which case there is no point in writing
- * to the RTC again, or write to the RTC but then they don't call
- * settimeofday to perform this operation. Note also that
- * we don't touch the decrementer since:
- * a) it would lose timer interrupt synchronization on SMP
- * (if it is working one day)
- * b) it could make one jiffy spuriously shorter or longer
- * which would introduce another source of uncertainty potentially
- * harmful to relatively short timers.
- */
-
- /* This works perfectly on SMP only if the tb are in sync but
- * guarantees an error < 1 jiffy even if they are off by eons,
- * still reasonable when gettimeofday resolution is 1 jiffy.
- */
- tb_delta = tb_ticks_since(last_jiffy_stamp(smp_processor_id()));
-
- new_nsec -= 1000 * mulhwu(tb_to_us, tb_delta);
-
- wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - new_sec);
- wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - new_nsec);
-
- set_normalized_timespec(&xtime, new_sec, new_nsec);
- set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
-
- /* In case of a large backwards jump in time with NTP, we want the
- * clock to be updated as soon as the PLL is again in lock.
- */
- last_rtc_update = new_sec - 658;
-
- ntp_clear();
- write_sequnlock_irqrestore(&xtime_lock, flags);
- clock_was_set();
- return 0;
-}
-
-EXPORT_SYMBOL(do_settimeofday);
-
-/* This function is only called on the boot processor */
-void __init time_init(void)
-{
- time_t sec, old_sec;
- unsigned old_stamp, stamp, elapsed;
-
- if (ppc_md.time_init != NULL)
- timezone_offset = ppc_md.time_init();
-
- if (__USE_RTC()) {
- /* 601 processor: dec counts down by 128 every 128ns */
- tb_ticks_per_jiffy = DECREMENTER_COUNT_601;
- /* mulhwu_scale_factor(1000000000, 1000000) is 0x418937 */
- tb_to_us = 0x418937;
- } else {
- ppc_md.calibrate_decr();
- tb_to_ns_scale = mulhwu(tb_to_us, 1000 << 10);
- }
-
- /* Now that the decrementer is calibrated, it can be used in case the
- * clock is stuck, but the fact that we have to handle the 601
- * makes things more complex. Repeatedly read the RTC until the
- * next second boundary to try to achieve some precision. If there
- * is no RTC, we still need to set tb_last_stamp and
- * last_jiffy_stamp(cpu 0) to the current stamp.
- */
- stamp = get_native_tbl();
- if (ppc_md.get_rtc_time) {
- sec = ppc_md.get_rtc_time();
- elapsed = 0;
- do {
- old_stamp = stamp;
- old_sec = sec;
- stamp = get_native_tbl();
- if (__USE_RTC() && stamp < old_stamp)
- old_stamp -= 1000000000;
- elapsed += stamp - old_stamp;
- sec = ppc_md.get_rtc_time();
- } while ( sec == old_sec && elapsed < 2*HZ*tb_ticks_per_jiffy);
- if (sec==old_sec)
- printk("Warning: real time clock seems stuck!\n");
- xtime.tv_sec = sec;
- xtime.tv_nsec = 0;
- /* No update now, we just read the time from the RTC ! */
- last_rtc_update = xtime.tv_sec;
- }
- last_jiffy_stamp(0) = tb_last_stamp = stamp;
-
- /* Not exact, but the timer interrupt takes care of this */
- set_dec(tb_ticks_per_jiffy);
-
- /* If platform provided a timezone (pmac), we correct the time */
- if (timezone_offset) {
- sys_tz.tz_minuteswest = -timezone_offset / 60;
- sys_tz.tz_dsttime = 0;
- xtime.tv_sec -= timezone_offset;
- }
- set_normalized_timespec(&wall_to_monotonic,
- -xtime.tv_sec, -xtime.tv_nsec);
-}
-
-#define FEBRUARY 2
-#define STARTOFTIME 1970
-#define SECDAY 86400L
-#define SECYR (SECDAY * 365)
-
-/*
- * Note: this is wrong for 2100, but our signed 32-bit time_t will
- * have overflowed long before that, so who cares. -- paulus
- */
-#define leapyear(year) ((year) % 4 == 0)
-#define days_in_year(a) (leapyear(a) ? 366 : 365)
-#define days_in_month(a) (month_days[(a) - 1])
-
-static int month_days[12] = {
- 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
-};
-
-void to_tm(int tim, struct rtc_time * tm)
-{
- register int i;
- register long hms, day, gday;
-
- gday = day = tim / SECDAY;
- hms = tim % SECDAY;
-
- /* Hours, minutes, seconds are easy */
- tm->tm_hour = hms / 3600;
- tm->tm_min = (hms % 3600) / 60;
- tm->tm_sec = (hms % 3600) % 60;
-
- /* Number of years in days */
- for (i = STARTOFTIME; day >= days_in_year(i); i++)
- day -= days_in_year(i);
- tm->tm_year = i;
-
- /* Number of months in days left */
- if (leapyear(tm->tm_year))
- days_in_month(FEBRUARY) = 29;
- for (i = 1; day >= days_in_month(i); i++)
- day -= days_in_month(i);
- days_in_month(FEBRUARY) = 28;
- tm->tm_mon = i;
-
- /* Days are what is left over (+1) from all that. */
- tm->tm_mday = day + 1;
-
- /*
- * Determine the day of week. Jan. 1, 1970 was a Thursday.
- */
- tm->tm_wday = (gday + 4) % 7;
-}
-
-/* Auxiliary function to compute scaling factors */
-/* Actually the choice of a timebase running at 1/4 the of the bus
- * frequency giving resolution of a few tens of nanoseconds is quite nice.
- * It makes this computation very precise (27-28 bits typically) which
- * is optimistic considering the stability of most processor clock
- * oscillators and the precision with which the timebase frequency
- * is measured but does not harm.
- */
-unsigned mulhwu_scale_factor(unsigned inscale, unsigned outscale) {
- unsigned mlt=0, tmp, err;
- /* No concern for performance, it's done once: use a stupid
- * but safe and compact method to find the multiplier.
- */
- for (tmp = 1U<<31; tmp != 0; tmp >>= 1) {
- if (mulhwu(inscale, mlt|tmp) < outscale) mlt|=tmp;
- }
- /* We might still be off by 1 for the best approximation.
- * A side effect of this is that if outscale is too large
- * the returned value will be zero.
- * Many corner cases have been checked and seem to work,
- * some might have been forgotten in the test however.
- */
- err = inscale*(mlt+1);
- if (err <= inscale/2) mlt++;
- return mlt;
-}
-
-unsigned long long sched_clock(void)
-{
- unsigned long lo, hi, hi2;
- unsigned long long tb;
-
- if (!__USE_RTC()) {
- do {
- hi = get_tbu();
- lo = get_tbl();
- hi2 = get_tbu();
- } while (hi2 != hi);
- tb = ((unsigned long long) hi << 32) | lo;
- tb = (tb * tb_to_ns_scale) >> 10;
- } else {
- do {
- hi = get_rtcu();
- lo = get_rtcl();
- hi2 = get_rtcu();
- } while (hi2 != hi);
- tb = ((unsigned long long) hi) * 1000000000 + lo;
- }
- return tb;
-}
diff --git a/arch/ppc/kernel/traps.c b/arch/ppc/kernel/traps.c
deleted file mode 100644
index a467a429c2fe..000000000000
--- a/arch/ppc/kernel/traps.c
+++ /dev/null
@@ -1,826 +0,0 @@
-/*
- * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
- *
- * 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.
- *
- * Modified by Cort Dougan (cort@cs.nmt.edu)
- * and Paul Mackerras (paulus@cs.anu.edu.au)
- */
-
-/*
- * This file handles the architecture-dependent parts of hardware exceptions
- */
-
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/stddef.h>
-#include <linux/unistd.h>
-#include <linux/ptrace.h>
-#include <linux/slab.h>
-#include <linux/user.h>
-#include <linux/a.out.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/prctl.h>
-#include <linux/bug.h>
-
-#include <asm/pgtable.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/reg.h>
-#include <asm/xmon.h>
-#include <asm/pmc.h>
-
-#ifdef CONFIG_XMON
-extern int xmon_bpt(struct pt_regs *regs);
-extern int xmon_sstep(struct pt_regs *regs);
-extern int xmon_iabr_match(struct pt_regs *regs);
-extern int xmon_dabr_match(struct pt_regs *regs);
-
-int (*debugger)(struct pt_regs *regs) = xmon;
-int (*debugger_bpt)(struct pt_regs *regs) = xmon_bpt;
-int (*debugger_sstep)(struct pt_regs *regs) = xmon_sstep;
-int (*debugger_iabr_match)(struct pt_regs *regs) = xmon_iabr_match;
-int (*debugger_dabr_match)(struct pt_regs *regs) = xmon_dabr_match;
-void (*debugger_fault_handler)(struct pt_regs *regs);
-#else
-#ifdef CONFIG_KGDB
-int (*debugger)(struct pt_regs *regs);
-int (*debugger_bpt)(struct pt_regs *regs);
-int (*debugger_sstep)(struct pt_regs *regs);
-int (*debugger_iabr_match)(struct pt_regs *regs);
-int (*debugger_dabr_match)(struct pt_regs *regs);
-void (*debugger_fault_handler)(struct pt_regs *regs);
-#else
-#define debugger(regs) do { } while (0)
-#define debugger_bpt(regs) 0
-#define debugger_sstep(regs) 0
-#define debugger_iabr_match(regs) 0
-#define debugger_dabr_match(regs) 0
-#define debugger_fault_handler ((void (*)(struct pt_regs *))0)
-#endif
-#endif
-
-/*
- * Trap & Exception support
- */
-
-DEFINE_SPINLOCK(die_lock);
-
-int die(const char * str, struct pt_regs * fp, long err)
-{
- static int die_counter;
- int nl = 0;
- console_verbose();
- spin_lock_irq(&die_lock);
- printk("Oops: %s, sig: %ld [#%d]\n", str, err, ++die_counter);
-#ifdef CONFIG_PREEMPT
- printk("PREEMPT ");
- nl = 1;
-#endif
-#ifdef CONFIG_SMP
- printk("SMP NR_CPUS=%d ", NR_CPUS);
- nl = 1;
-#endif
- if (nl)
- printk("\n");
- show_regs(fp);
- add_taint(TAINT_DIE);
- spin_unlock_irq(&die_lock);
- /* do_exit() should take care of panic'ing from an interrupt
- * context so we don't handle it here
- */
- do_exit(err);
-}
-
-void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr)
-{
- siginfo_t info;
-
- if (!user_mode(regs)) {
- debugger(regs);
- die("Exception in kernel mode", regs, signr);
- }
- info.si_signo = signr;
- info.si_errno = 0;
- info.si_code = code;
- info.si_addr = (void __user *) addr;
- force_sig_info(signr, &info, current);
-
- /*
- * Init gets no signals that it doesn't have a handler for.
- * That's all very well, but if it has caused a synchronous
- * exception and we ignore the resulting signal, it will just
- * generate the same exception over and over again and we get
- * nowhere. Better to kill it and let the kernel panic.
- */
- if (is_global_init(current)) {
- __sighandler_t handler;
-
- spin_lock_irq(&current->sighand->siglock);
- handler = current->sighand->action[signr-1].sa.sa_handler;
- spin_unlock_irq(&current->sighand->siglock);
- if (handler == SIG_DFL) {
- /* init has generated a synchronous exception
- and it doesn't have a handler for the signal */
- printk(KERN_CRIT "init has generated signal %d "
- "but has no handler for it\n", signr);
- do_exit(signr);
- }
- }
-}
-
-/*
- * I/O accesses can cause machine checks on powermacs.
- * Check if the NIP corresponds to the address of a sync
- * instruction for which there is an entry in the exception
- * table.
- * Note that the 601 only takes a machine check on TEA
- * (transfer error ack) signal assertion, and does not
- * set any of the top 16 bits of SRR1.
- * -- paulus.
- */
-static inline int check_io_access(struct pt_regs *regs)
-{
-#if defined CONFIG_8xx
- unsigned long msr = regs->msr;
- const struct exception_table_entry *entry;
- unsigned int *nip = (unsigned int *)regs->nip;
-
- if (((msr & 0xffff0000) == 0 || (msr & (0x80000 | 0x40000)))
- && (entry = search_exception_tables(regs->nip)) != NULL) {
- /*
- * Check that it's a sync instruction, or somewhere
- * in the twi; isync; nop sequence that inb/inw/inl uses.
- * As the address is in the exception table
- * we should be able to read the instr there.
- * For the debug message, we look at the preceding
- * load or store.
- */
- if (*nip == 0x60000000) /* nop */
- nip -= 2;
- else if (*nip == 0x4c00012c) /* isync */
- --nip;
- /* eieio from I/O string functions */
- else if ((*nip) == 0x7c0006ac || *(nip+1) == 0x7c0006ac)
- nip += 2;
- if (*nip == 0x7c0004ac || (*nip >> 26) == 3 ||
- (*(nip+1) >> 26) == 3) {
- /* sync or twi */
- unsigned int rb;
-
- --nip;
- rb = (*nip >> 11) & 0x1f;
- printk(KERN_DEBUG "%s bad port %lx at %p\n",
- (*nip & 0x100)? "OUT to": "IN from",
- regs->gpr[rb] - _IO_BASE, nip);
- regs->msr |= MSR_RI;
- regs->nip = entry->fixup;
- return 1;
- }
- }
-#endif /* CONFIG_8xx */
- return 0;
-}
-
-#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
-/* On 4xx, the reason for the machine check or program exception
- is in the ESR. */
-#define get_reason(regs) ((regs)->dsisr)
-#define get_mc_reason(regs) ((regs)->dsisr)
-#define REASON_FP ESR_FP
-#define REASON_ILLEGAL (ESR_PIL | ESR_PUO)
-#define REASON_PRIVILEGED ESR_PPR
-#define REASON_TRAP ESR_PTR
-
-/* single-step stuff */
-#define single_stepping(regs) (current->thread.dbcr0 & DBCR0_IC)
-#define clear_single_step(regs) (current->thread.dbcr0 &= ~DBCR0_IC)
-
-#else
-/* On non-4xx, the reason for the machine check or program
- exception is in the MSR. */
-#define get_reason(regs) ((regs)->msr)
-#define get_mc_reason(regs) ((regs)->msr)
-#define REASON_FP 0x100000
-#define REASON_ILLEGAL 0x80000
-#define REASON_PRIVILEGED 0x40000
-#define REASON_TRAP 0x20000
-
-#define single_stepping(regs) ((regs)->msr & MSR_SE)
-#define clear_single_step(regs) ((regs)->msr &= ~MSR_SE)
-#endif
-
-/*
- * This is "fall-back" implementation for configurations
- * which don't provide platform-specific machine check info
- */
-void __attribute__ ((weak))
-platform_machine_check(struct pt_regs *regs)
-{
-}
-
-#if defined(CONFIG_4xx)
-int machine_check_4xx(struct pt_regs *regs)
-{
- unsigned long reason = get_mc_reason(regs);
-
- if (reason & ESR_IMCP) {
- printk("Instruction");
- mtspr(SPRN_ESR, reason & ~ESR_IMCP);
- } else
- printk("Data");
- printk(" machine check in kernel mode.\n");
-
- return 0;
-}
-
-int machine_check_440A(struct pt_regs *regs)
-{
- unsigned long reason = get_mc_reason(regs);
-
- printk("Machine check in kernel mode.\n");
- if (reason & ESR_IMCP){
- printk("Instruction Synchronous Machine Check exception\n");
- mtspr(SPRN_ESR, reason & ~ESR_IMCP);
- }
- else {
- u32 mcsr = mfspr(SPRN_MCSR);
- if (mcsr & MCSR_IB)
- printk("Instruction Read PLB Error\n");
- if (mcsr & MCSR_DRB)
- printk("Data Read PLB Error\n");
- if (mcsr & MCSR_DWB)
- printk("Data Write PLB Error\n");
- if (mcsr & MCSR_TLBP)
- printk("TLB Parity Error\n");
- if (mcsr & MCSR_ICP){
- flush_instruction_cache();
- printk("I-Cache Parity Error\n");
- }
- if (mcsr & MCSR_DCSP)
- printk("D-Cache Search Parity Error\n");
- if (mcsr & MCSR_DCFP)
- printk("D-Cache Flush Parity Error\n");
- if (mcsr & MCSR_IMPE)
- printk("Machine Check exception is imprecise\n");
-
- /* Clear MCSR */
- mtspr(SPRN_MCSR, mcsr);
- }
- return 0;
-}
-#else
-int machine_check_generic(struct pt_regs *regs)
-{
- unsigned long reason = get_mc_reason(regs);
-
- printk("Machine check in kernel mode.\n");
- printk("Caused by (from SRR1=%lx): ", reason);
- switch (reason & 0x601F0000) {
- case 0x80000:
- printk("Machine check signal\n");
- break;
- case 0: /* for 601 */
- case 0x40000:
- case 0x140000: /* 7450 MSS error and TEA */
- printk("Transfer error ack signal\n");
- break;
- case 0x20000:
- printk("Data parity error signal\n");
- break;
- case 0x10000:
- printk("Address parity error signal\n");
- break;
- case 0x20000000:
- printk("L1 Data Cache error\n");
- break;
- case 0x40000000:
- printk("L1 Instruction Cache error\n");
- break;
- case 0x00100000:
- printk("L2 data cache parity error\n");
- break;
- default:
- printk("Unknown values in msr\n");
- }
- return 0;
-}
-#endif /* everything else */
-
-void machine_check_exception(struct pt_regs *regs)
-{
- int recover = 0;
-
- if (cur_cpu_spec->machine_check)
- recover = cur_cpu_spec->machine_check(regs);
- if (recover > 0)
- return;
-
- if (user_mode(regs)) {
- regs->msr |= MSR_RI;
- _exception(SIGBUS, regs, BUS_ADRERR, regs->nip);
- return;
- }
-
-#if defined(CONFIG_8xx) && defined(CONFIG_PCI)
- /* the qspan pci read routines can cause machine checks -- Cort */
- bad_page_fault(regs, regs->dar, SIGBUS);
- return;
-#endif
-
- if (debugger_fault_handler) {
- debugger_fault_handler(regs);
- regs->msr |= MSR_RI;
- return;
- }
-
- if (check_io_access(regs))
- return;
-
- /*
- * Optional platform-provided routine to print out
- * additional info, e.g. bus error registers.
- */
- platform_machine_check(regs);
-
- debugger(regs);
- die("machine check", regs, SIGBUS);
-}
-
-void SMIException(struct pt_regs *regs)
-{
- debugger(regs);
-#if !(defined(CONFIG_XMON) || defined(CONFIG_KGDB))
- show_regs(regs);
- panic("System Management Interrupt");
-#endif
-}
-
-void unknown_exception(struct pt_regs *regs)
-{
- printk("Bad trap at PC: %lx, MSR: %lx, vector=%lx %s\n",
- regs->nip, regs->msr, regs->trap, print_tainted());
- _exception(SIGTRAP, regs, 0, 0);
-}
-
-void instruction_breakpoint_exception(struct pt_regs *regs)
-{
- if (debugger_iabr_match(regs))
- return;
- _exception(SIGTRAP, regs, TRAP_BRKPT, 0);
-}
-
-void RunModeException(struct pt_regs *regs)
-{
- _exception(SIGTRAP, regs, 0, 0);
-}
-
-/* Illegal instruction emulation support. Originally written to
- * provide the PVR to user applications using the mfspr rd, PVR.
- * Return non-zero if we can't emulate, or -EFAULT if the associated
- * memory access caused an access fault. Return zero on success.
- *
- * There are a couple of ways to do this, either "decode" the instruction
- * or directly match lots of bits. In this case, matching lots of
- * bits is faster and easier.
- *
- */
-#define INST_MFSPR_PVR 0x7c1f42a6
-#define INST_MFSPR_PVR_MASK 0xfc1fffff
-
-#define INST_DCBA 0x7c0005ec
-#define INST_DCBA_MASK 0x7c0007fe
-
-#define INST_MCRXR 0x7c000400
-#define INST_MCRXR_MASK 0x7c0007fe
-
-#define INST_STRING 0x7c00042a
-#define INST_STRING_MASK 0x7c0007fe
-#define INST_STRING_GEN_MASK 0x7c00067e
-#define INST_LSWI 0x7c0004aa
-#define INST_LSWX 0x7c00042a
-#define INST_STSWI 0x7c0005aa
-#define INST_STSWX 0x7c00052a
-
-static int emulate_string_inst(struct pt_regs *regs, u32 instword)
-{
- u8 rT = (instword >> 21) & 0x1f;
- u8 rA = (instword >> 16) & 0x1f;
- u8 NB_RB = (instword >> 11) & 0x1f;
- u32 num_bytes;
- unsigned long EA;
- int pos = 0;
-
- /* Early out if we are an invalid form of lswx */
- if ((instword & INST_STRING_MASK) == INST_LSWX)
- if ((rT == rA) || (rT == NB_RB))
- return -EINVAL;
-
- EA = (rA == 0) ? 0 : regs->gpr[rA];
-
- switch (instword & INST_STRING_MASK) {
- case INST_LSWX:
- case INST_STSWX:
- EA += NB_RB;
- num_bytes = regs->xer & 0x7f;
- break;
- case INST_LSWI:
- case INST_STSWI:
- num_bytes = (NB_RB == 0) ? 32 : NB_RB;
- break;
- default:
- return -EINVAL;
- }
-
- while (num_bytes != 0)
- {
- u8 val;
- u32 shift = 8 * (3 - (pos & 0x3));
-
- switch ((instword & INST_STRING_MASK)) {
- case INST_LSWX:
- case INST_LSWI:
- if (get_user(val, (u8 __user *)EA))
- return -EFAULT;
- /* first time updating this reg,
- * zero it out */
- if (pos == 0)
- regs->gpr[rT] = 0;
- regs->gpr[rT] |= val << shift;
- break;
- case INST_STSWI:
- case INST_STSWX:
- val = regs->gpr[rT] >> shift;
- if (put_user(val, (u8 __user *)EA))
- return -EFAULT;
- break;
- }
- /* move EA to next address */
- EA += 1;
- num_bytes--;
-
- /* manage our position within the register */
- if (++pos == 4) {
- pos = 0;
- if (++rT == 32)
- rT = 0;
- }
- }
-
- return 0;
-}
-
-static int emulate_instruction(struct pt_regs *regs)
-{
- u32 instword;
- u32 rd;
-
- if (!user_mode(regs))
- return -EINVAL;
- CHECK_FULL_REGS(regs);
-
- if (get_user(instword, (u32 __user *)(regs->nip)))
- return -EFAULT;
-
- /* Emulate the mfspr rD, PVR.
- */
- if ((instword & INST_MFSPR_PVR_MASK) == INST_MFSPR_PVR) {
- rd = (instword >> 21) & 0x1f;
- regs->gpr[rd] = mfspr(SPRN_PVR);
- return 0;
- }
-
- /* Emulating the dcba insn is just a no-op. */
- if ((instword & INST_DCBA_MASK) == INST_DCBA)
- return 0;
-
- /* Emulate the mcrxr insn. */
- if ((instword & INST_MCRXR_MASK) == INST_MCRXR) {
- int shift = (instword >> 21) & 0x1c;
- unsigned long msk = 0xf0000000UL >> shift;
-
- regs->ccr = (regs->ccr & ~msk) | ((regs->xer >> shift) & msk);
- regs->xer &= ~0xf0000000UL;
- return 0;
- }
-
- /* Emulate load/store string insn. */
- if ((instword & INST_STRING_GEN_MASK) == INST_STRING)
- return emulate_string_inst(regs, instword);
-
- return -EINVAL;
-}
-
-/*
- * After we have successfully emulated an instruction, we have to
- * check if the instruction was being single-stepped, and if so,
- * pretend we got a single-step exception. This was pointed out
- * by Kumar Gala. -- paulus
- */
-static void emulate_single_step(struct pt_regs *regs)
-{
- if (single_stepping(regs)) {
- clear_single_step(regs);
- _exception(SIGTRAP, regs, TRAP_TRACE, 0);
- }
-}
-
-int is_valid_bugaddr(unsigned long addr)
-{
- return addr >= PAGE_OFFSET;
-}
-
-void program_check_exception(struct pt_regs *regs)
-{
- unsigned int reason = get_reason(regs);
- extern int do_mathemu(struct pt_regs *regs);
-
-#ifdef CONFIG_MATH_EMULATION
- /* (reason & REASON_ILLEGAL) would be the obvious thing here,
- * but there seems to be a hardware bug on the 405GP (RevD)
- * that means ESR is sometimes set incorrectly - either to
- * ESR_DST (!?) or 0. In the process of chasing this with the
- * hardware people - not sure if it can happen on any illegal
- * instruction or only on FP instructions, whether there is a
- * pattern to occurrences etc. -dgibson 31/Mar/2003 */
- if (!(reason & REASON_TRAP) && do_mathemu(regs) == 0) {
- emulate_single_step(regs);
- return;
- }
-#endif /* CONFIG_MATH_EMULATION */
-
- if (reason & REASON_FP) {
- /* IEEE FP exception */
- int code = 0;
- u32 fpscr;
-
- /* We must make sure the FP state is consistent with
- * our MSR_FP in regs
- */
- preempt_disable();
- if (regs->msr & MSR_FP)
- giveup_fpu(current);
- preempt_enable();
-
- fpscr = current->thread.fpscr.val;
- fpscr &= fpscr << 22; /* mask summary bits with enables */
- if (fpscr & FPSCR_VX)
- code = FPE_FLTINV;
- else if (fpscr & FPSCR_OX)
- code = FPE_FLTOVF;
- else if (fpscr & FPSCR_UX)
- code = FPE_FLTUND;
- else if (fpscr & FPSCR_ZX)
- code = FPE_FLTDIV;
- else if (fpscr & FPSCR_XX)
- code = FPE_FLTRES;
- _exception(SIGFPE, regs, code, regs->nip);
- return;
- }
-
- if (reason & REASON_TRAP) {
- /* trap exception */
- if (debugger_bpt(regs))
- return;
-
- if (!(regs->msr & MSR_PR) && /* not user-mode */
- report_bug(regs->nip, regs) == BUG_TRAP_TYPE_WARN) {
- regs->nip += 4;
- return;
- }
- _exception(SIGTRAP, regs, TRAP_BRKPT, 0);
- return;
- }
-
- /* Try to emulate it if we should. */
- if (reason & (REASON_ILLEGAL | REASON_PRIVILEGED)) {
- switch (emulate_instruction(regs)) {
- case 0:
- regs->nip += 4;
- emulate_single_step(regs);
- return;
- case -EFAULT:
- _exception(SIGSEGV, regs, SEGV_MAPERR, regs->nip);
- return;
- }
- }
-
- if (reason & REASON_PRIVILEGED)
- _exception(SIGILL, regs, ILL_PRVOPC, regs->nip);
- else
- _exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
-}
-
-void single_step_exception(struct pt_regs *regs)
-{
- regs->msr &= ~(MSR_SE | MSR_BE); /* Turn off 'trace' bits */
- if (debugger_sstep(regs))
- return;
- _exception(SIGTRAP, regs, TRAP_TRACE, 0);
-}
-
-void alignment_exception(struct pt_regs *regs)
-{
- int sig, code, fixed = 0;
-
- fixed = fix_alignment(regs);
- if (fixed == 1) {
- regs->nip += 4; /* skip over emulated instruction */
- emulate_single_step(regs);
- return;
- }
- if (fixed == -EFAULT) {
- sig = SIGSEGV;
- code = SEGV_ACCERR;
- } else {
- sig = SIGBUS;
- code = BUS_ADRALN;
- }
- if (user_mode(regs))
- _exception(sig, regs, code, regs->dar);
- else
- bad_page_fault(regs, regs->dar, sig);
-}
-
-void StackOverflow(struct pt_regs *regs)
-{
- printk(KERN_CRIT "Kernel stack overflow in process %p, r1=%lx\n",
- current, regs->gpr[1]);
- debugger(regs);
- show_regs(regs);
- panic("kernel stack overflow");
-}
-
-void nonrecoverable_exception(struct pt_regs *regs)
-{
- printk(KERN_ERR "Non-recoverable exception at PC=%lx MSR=%lx\n",
- regs->nip, regs->msr);
- debugger(regs);
- die("nonrecoverable exception", regs, SIGKILL);
-}
-
-void trace_syscall(struct pt_regs *regs)
-{
- printk("Task: %p(%d), PC: %08lX/%08lX, Syscall: %3ld, Result: %s%ld %s\n",
- current, current->pid, regs->nip, regs->link, regs->gpr[0],
- regs->ccr&0x10000000?"Error=":"", regs->gpr[3], print_tainted());
-}
-
-#ifdef CONFIG_8xx
-void SoftwareEmulation(struct pt_regs *regs)
-{
- extern int do_mathemu(struct pt_regs *);
- extern int Soft_emulate_8xx(struct pt_regs *);
- int errcode;
-
- CHECK_FULL_REGS(regs);
-
- if (!user_mode(regs)) {
- debugger(regs);
- die("Kernel Mode Software FPU Emulation", regs, SIGFPE);
- }
-
-#ifdef CONFIG_MATH_EMULATION
- errcode = do_mathemu(regs);
-#else
- errcode = Soft_emulate_8xx(regs);
-#endif
- if (errcode) {
- if (errcode > 0)
- _exception(SIGFPE, regs, 0, 0);
- else if (errcode == -EFAULT)
- _exception(SIGSEGV, regs, 0, 0);
- else
- _exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
- } else
- emulate_single_step(regs);
-}
-#endif /* CONFIG_8xx */
-
-#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
-
-void DebugException(struct pt_regs *regs, unsigned long debug_status)
-{
- if (debug_status & DBSR_IC) { /* instruction completion */
- regs->msr &= ~MSR_DE;
- if (user_mode(regs)) {
- current->thread.dbcr0 &= ~DBCR0_IC;
- } else {
- /* Disable instruction completion */
- mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) & ~DBCR0_IC);
- /* Clear the instruction completion event */
- mtspr(SPRN_DBSR, DBSR_IC);
- if (debugger_sstep(regs))
- return;
- }
- _exception(SIGTRAP, regs, TRAP_TRACE, 0);
- }
-}
-#endif /* CONFIG_4xx || CONFIG_BOOKE */
-
-#if !defined(CONFIG_TAU_INT)
-void TAUException(struct pt_regs *regs)
-{
- printk("TAU trap at PC: %lx, MSR: %lx, vector=%lx %s\n",
- regs->nip, regs->msr, regs->trap, print_tainted());
-}
-#endif /* CONFIG_INT_TAU */
-
-/*
- * FP unavailable trap from kernel - print a message, but let
- * the task use FP in the kernel until it returns to user mode.
- */
-void kernel_fp_unavailable_exception(struct pt_regs *regs)
-{
- regs->msr |= MSR_FP;
- printk(KERN_ERR "floating point used in kernel (task=%p, pc=%lx)\n",
- current, regs->nip);
-}
-
-void altivec_unavailable_exception(struct pt_regs *regs)
-{
- static int kernel_altivec_count;
-
-#ifndef CONFIG_ALTIVEC
- if (user_mode(regs)) {
- /* A user program has executed an altivec instruction,
- but this kernel doesn't support altivec. */
- _exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
- return;
- }
-#endif
- /* The kernel has executed an altivec instruction without
- first enabling altivec. Whinge but let it do it. */
- if (++kernel_altivec_count < 10)
- printk(KERN_ERR "AltiVec used in kernel (task=%p, pc=%lx)\n",
- current, regs->nip);
- regs->msr |= MSR_VEC;
-}
-
-#ifdef CONFIG_ALTIVEC
-void altivec_assist_exception(struct pt_regs *regs)
-{
- int err;
-
- preempt_disable();
- if (regs->msr & MSR_VEC)
- giveup_altivec(current);
- preempt_enable();
- if (!user_mode(regs)) {
- printk(KERN_ERR "altivec assist exception in kernel mode"
- " at %lx\n", regs->nip);
- debugger(regs);
- die("altivec assist exception", regs, SIGFPE);
- return;
- }
-
- err = emulate_altivec(regs);
- if (err == 0) {
- regs->nip += 4; /* skip emulated instruction */
- emulate_single_step(regs);
- return;
- }
-
- if (err == -EFAULT) {
- /* got an error reading the instruction */
- _exception(SIGSEGV, regs, SEGV_ACCERR, regs->nip);
- } else {
- /* didn't recognize the instruction */
- /* XXX quick hack for now: set the non-Java bit in the VSCR */
- printk(KERN_ERR "unrecognized altivec instruction "
- "in %s at %lx\n", current->comm, regs->nip);
- current->thread.vscr.u[3] |= 0x10000;
- }
-}
-#endif /* CONFIG_ALTIVEC */
-
-#ifdef CONFIG_BOOKE_WDT
-/*
- * Default handler for a Watchdog exception,
- * spins until a reboot occurs
- */
-void __attribute__ ((weak)) WatchdogHandler(struct pt_regs *regs)
-{
- /* Generic WatchdogHandler, implement your own */
- mtspr(SPRN_TCR, mfspr(SPRN_TCR)&(~TCR_WIE));
- return;
-}
-
-void WatchdogException(struct pt_regs *regs)
-{
- printk (KERN_EMERG "PowerPC Book-E Watchdog Exception\n");
- WatchdogHandler(regs);
-}
-#endif
-
-void __init trap_init(void)
-{
-}
diff --git a/arch/ppc/kernel/vmlinux.lds.S b/arch/ppc/kernel/vmlinux.lds.S
deleted file mode 100644
index 8a24bc47eb6c..000000000000
--- a/arch/ppc/kernel/vmlinux.lds.S
+++ /dev/null
@@ -1,164 +0,0 @@
-#include <asm-generic/vmlinux.lds.h>
-
-OUTPUT_ARCH(powerpc:common)
-jiffies = jiffies_64 + 4;
-SECTIONS
-{
- /* Read-only sections, merged into text segment: */
- . = + SIZEOF_HEADERS;
- .interp : { *(.interp) }
- .hash : { *(.hash) }
- .gnu.hash : { *(.gnu.hash) }
- .dynsym : { *(.dynsym) }
- .dynstr : { *(.dynstr) }
- .rel.text : { *(.rel.text) }
- .rela.text : { *(.rela.text) }
- .rel.data : { *(.rel.data) }
- .rela.data : { *(.rela.data) }
- .rel.rodata : { *(.rel.rodata) }
- .rela.rodata : { *(.rela.rodata) }
- .rel.got : { *(.rel.got) }
- .rela.got : { *(.rela.got) }
- .rel.ctors : { *(.rel.ctors) }
- .rela.ctors : { *(.rela.ctors) }
- .rel.dtors : { *(.rel.dtors) }
- .rela.dtors : { *(.rela.dtors) }
- .rel.bss : { *(.rel.bss) }
- .rela.bss : { *(.rela.bss) }
- .rel.plt : { *(.rel.plt) }
- .rela.plt : { *(.rela.plt) }
-/* .init : { *(.init) } =0*/
- .plt : { *(.plt) }
- .text :
- {
- _text = .;
- TEXT_TEXT
- SCHED_TEXT
- LOCK_TEXT
- *(.fixup)
- *(.got1)
- __got2_start = .;
- *(.got2)
- __got2_end = .;
- }
- _etext = .;
- PROVIDE (etext = .);
-
- RODATA
- .fini : { *(.fini) } =0
- .ctors : { *(.ctors) }
- .dtors : { *(.dtors) }
-
- .fixup : { *(.fixup) }
-
- __ex_table : {
- __start___ex_table = .;
- *(__ex_table)
- __stop___ex_table = .;
- }
-
- __bug_table : {
- __start___bug_table = .;
- *(__bug_table)
- __stop___bug_table = .;
- }
-
- /* Read-write section, merged into data segment: */
- . = ALIGN(4096);
- .data :
- {
- DATA_DATA
- *(.data1)
- *(.sdata)
- *(.sdata2)
- *(.got.plt) *(.got)
- *(.dynamic)
- CONSTRUCTORS
- }
-
- . = ALIGN(4096);
- __nosave_begin = .;
- .data_nosave : { *(.data.nosave) }
- . = ALIGN(4096);
- __nosave_end = .;
-
- . = ALIGN(32);
- .data.cacheline_aligned : { *(.data.cacheline_aligned) }
-
- _edata = .;
- PROVIDE (edata = .);
-
- . = ALIGN(8192);
- .data.init_task : { *(.data.init_task) }
-
- NOTES
-
- . = ALIGN(4096);
- __init_begin = .;
- .init.text : {
- _sinittext = .;
- INIT_TEXT
- _einittext = .;
- }
- /* .exit.text is discarded at runtime, not link time,
- to deal with references from __bug_table */
- .exit.text : { EXIT_TEXT }
- .init.data : {
- INIT_DATA
- __vtop_table_begin = .;
- *(.vtop_fixup);
- __vtop_table_end = .;
- __ptov_table_begin = .;
- *(.ptov_fixup);
- __ptov_table_end = .;
- }
- . = ALIGN(16);
- __setup_start = .;
- .init.setup : { *(.init.setup) }
- __setup_end = .;
- __initcall_start = .;
- .initcall.init : {
- INITCALLS
- }
- __initcall_end = .;
-
- __con_initcall_start = .;
- .con_initcall.init : { *(.con_initcall.init) }
- __con_initcall_end = .;
-
- SECURITY_INIT
-
- __start___ftr_fixup = .;
- __ftr_fixup : { *(__ftr_fixup) }
- __stop___ftr_fixup = .;
-
- PERCPU(4096)
-
-#ifdef CONFIG_BLK_DEV_INITRD
- . = ALIGN(4096);
- __initramfs_start = .;
- .init.ramfs : { *(.init.ramfs) }
- __initramfs_end = .;
-#endif
-
- . = ALIGN(4096);
- __init_end = .;
- __bss_start = .;
- .bss :
- {
- *(.sbss) *(.scommon)
- *(.dynbss)
- *(.bss)
- *(COMMON)
- }
- __bss_stop = .;
-
- _end = . ;
- PROVIDE (end = .);
-
- /* Sections to be discarded. */
- /DISCARD/ : {
- *(.exitcall.exit)
- EXIT_DATA
- }
-}