提交 3ae0af12 编写于 作者: L Linus Torvalds
...@@ -599,6 +599,10 @@ config HAVE_ARCH_EARLY_PFN_TO_NID ...@@ -599,6 +599,10 @@ config HAVE_ARCH_EARLY_PFN_TO_NID
def_bool y def_bool y
depends on NEED_MULTIPLE_NODES depends on NEED_MULTIPLE_NODES
config ARCH_MEMORY_PROBE
def_bool y
depends on MEMORY_HOTPLUG
# Some NUMA nodes have memory ranges that span # Some NUMA nodes have memory ranges that span
# other nodes. Even though a pfn is valid and # other nodes. Even though a pfn is valid and
# between a node's start and end pfns, it may not # between a node's start and end pfns, it may not
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
ifeq ($(CONFIG_PPC64),y) ifeq ($(CONFIG_PPC64),y)
EXTRA_CFLAGS += -mno-minimal-toc EXTRA_CFLAGS += -mno-minimal-toc
CFLAGS_ioctl32.o += -Ifs/
endif endif
ifeq ($(CONFIG_PPC32),y) ifeq ($(CONFIG_PPC32),y)
CFLAGS_prom_init.o += -fPIC CFLAGS_prom_init.o += -fPIC
...@@ -11,15 +12,21 @@ CFLAGS_btext.o += -fPIC ...@@ -11,15 +12,21 @@ CFLAGS_btext.o += -fPIC
endif endif
obj-y := semaphore.o cputable.o ptrace.o syscalls.o \ obj-y := semaphore.o cputable.o ptrace.o syscalls.o \
signal_32.o pmc.o irq.o signal_32.o pmc.o
obj-$(CONFIG_PPC64) += setup_64.o binfmt_elf32.o sys_ppc32.o \ obj-$(CONFIG_PPC64) += setup_64.o binfmt_elf32.o sys_ppc32.o \
signal_64.o ptrace32.o systbl.o signal_64.o ptrace32.o systbl.o \
paca.o ioctl32.o cpu_setup_power4.o \
firmware.o sysfs.o
obj-$(CONFIG_ALTIVEC) += vecemu.o vector.o obj-$(CONFIG_ALTIVEC) += vecemu.o vector.o
obj-$(CONFIG_POWER4) += idle_power4.o obj-$(CONFIG_POWER4) += idle_power4.o
obj-$(CONFIG_PPC_OF) += of_device.o obj-$(CONFIG_PPC_OF) += of_device.o
obj-$(CONFIG_PPC_RTAS) += rtas.o procfs-$(CONFIG_PPC64) := proc_ppc64.o
obj-$(CONFIG_PROC_FS) += $(procfs-y)
rtaspci-$(CONFIG_PPC64) := rtas_pci.o
obj-$(CONFIG_PPC_RTAS) += rtas.o $(rtaspci-y)
obj-$(CONFIG_RTAS_FLASH) += rtas_flash.o obj-$(CONFIG_RTAS_FLASH) += rtas_flash.o
obj-$(CONFIG_RTAS_PROC) += rtas-proc.o obj-$(CONFIG_RTAS_PROC) += rtas-proc.o
obj-$(CONFIG_LPARCFG) += lparcfg.o
obj-$(CONFIG_IBMVIO) += vio.o obj-$(CONFIG_IBMVIO) += vio.o
obj-$(CONFIG_GENERIC_TBSYNC) += smp-tbsync.o obj-$(CONFIG_GENERIC_TBSYNC) += smp-tbsync.o
......
...@@ -106,7 +106,6 @@ int main(void) ...@@ -106,7 +106,6 @@ int main(void)
DEFINE(ICACHEL1LINESIZE, offsetof(struct ppc64_caches, iline_size)); DEFINE(ICACHEL1LINESIZE, offsetof(struct ppc64_caches, iline_size));
DEFINE(ICACHEL1LOGLINESIZE, offsetof(struct ppc64_caches, log_iline_size)); DEFINE(ICACHEL1LOGLINESIZE, offsetof(struct ppc64_caches, log_iline_size));
DEFINE(ICACHEL1LINESPERPAGE, offsetof(struct ppc64_caches, ilines_per_page)); DEFINE(ICACHEL1LINESPERPAGE, offsetof(struct ppc64_caches, ilines_per_page));
DEFINE(PLATFORM, offsetof(struct systemcfg, platform));
DEFINE(PLATFORM_LPAR, PLATFORM_LPAR); DEFINE(PLATFORM_LPAR, PLATFORM_LPAR);
/* paca */ /* paca */
......
...@@ -52,6 +52,9 @@ extern void __setup_cpu_ppc970(unsigned long offset, struct cpu_spec* spec); ...@@ -52,6 +52,9 @@ extern void __setup_cpu_ppc970(unsigned long offset, struct cpu_spec* spec);
#define COMMON_USER (PPC_FEATURE_32 | PPC_FEATURE_HAS_FPU | \ #define COMMON_USER (PPC_FEATURE_32 | PPC_FEATURE_HAS_FPU | \
PPC_FEATURE_HAS_MMU) PPC_FEATURE_HAS_MMU)
#define COMMON_USER_PPC64 (COMMON_USER | PPC_FEATURE_64) #define COMMON_USER_PPC64 (COMMON_USER | PPC_FEATURE_64)
#define COMMON_USER_POWER4 (COMMON_USER_PPC64 | PPC_FEATURE_POWER4)
#define COMMON_USER_POWER5 (COMMON_USER_PPC64 | PPC_FEATURE_POWER5)
#define COMMON_USER_POWER5_PLUS (COMMON_USER_PPC64 | PPC_FEATURE_POWER5_PLUS)
/* We only set the spe features if the kernel was compiled with /* We only set the spe features if the kernel was compiled with
...@@ -160,7 +163,7 @@ struct cpu_spec cpu_specs[] = { ...@@ -160,7 +163,7 @@ struct cpu_spec cpu_specs[] = {
.pvr_value = 0x00350000, .pvr_value = 0x00350000,
.cpu_name = "POWER4 (gp)", .cpu_name = "POWER4 (gp)",
.cpu_features = CPU_FTRS_POWER4, .cpu_features = CPU_FTRS_POWER4,
.cpu_user_features = COMMON_USER_PPC64, .cpu_user_features = COMMON_USER_POWER4,
.icache_bsize = 128, .icache_bsize = 128,
.dcache_bsize = 128, .dcache_bsize = 128,
.num_pmcs = 8, .num_pmcs = 8,
...@@ -175,7 +178,7 @@ struct cpu_spec cpu_specs[] = { ...@@ -175,7 +178,7 @@ struct cpu_spec cpu_specs[] = {
.pvr_value = 0x00380000, .pvr_value = 0x00380000,
.cpu_name = "POWER4+ (gq)", .cpu_name = "POWER4+ (gq)",
.cpu_features = CPU_FTRS_POWER4, .cpu_features = CPU_FTRS_POWER4,
.cpu_user_features = COMMON_USER_PPC64, .cpu_user_features = COMMON_USER_POWER4,
.icache_bsize = 128, .icache_bsize = 128,
.dcache_bsize = 128, .dcache_bsize = 128,
.num_pmcs = 8, .num_pmcs = 8,
...@@ -190,7 +193,7 @@ struct cpu_spec cpu_specs[] = { ...@@ -190,7 +193,7 @@ struct cpu_spec cpu_specs[] = {
.pvr_value = 0x00390000, .pvr_value = 0x00390000,
.cpu_name = "PPC970", .cpu_name = "PPC970",
.cpu_features = CPU_FTRS_PPC970, .cpu_features = CPU_FTRS_PPC970,
.cpu_user_features = COMMON_USER_PPC64 | .cpu_user_features = COMMON_USER_POWER4 |
PPC_FEATURE_HAS_ALTIVEC_COMP, PPC_FEATURE_HAS_ALTIVEC_COMP,
.icache_bsize = 128, .icache_bsize = 128,
.dcache_bsize = 128, .dcache_bsize = 128,
...@@ -212,7 +215,7 @@ struct cpu_spec cpu_specs[] = { ...@@ -212,7 +215,7 @@ struct cpu_spec cpu_specs[] = {
#else #else
.cpu_features = CPU_FTRS_PPC970, .cpu_features = CPU_FTRS_PPC970,
#endif #endif
.cpu_user_features = COMMON_USER_PPC64 | .cpu_user_features = COMMON_USER_POWER4 |
PPC_FEATURE_HAS_ALTIVEC_COMP, PPC_FEATURE_HAS_ALTIVEC_COMP,
.icache_bsize = 128, .icache_bsize = 128,
.dcache_bsize = 128, .dcache_bsize = 128,
...@@ -230,7 +233,7 @@ struct cpu_spec cpu_specs[] = { ...@@ -230,7 +233,7 @@ struct cpu_spec cpu_specs[] = {
.pvr_value = 0x00440000, .pvr_value = 0x00440000,
.cpu_name = "PPC970MP", .cpu_name = "PPC970MP",
.cpu_features = CPU_FTRS_PPC970, .cpu_features = CPU_FTRS_PPC970,
.cpu_user_features = COMMON_USER_PPC64 | .cpu_user_features = COMMON_USER_POWER4 |
PPC_FEATURE_HAS_ALTIVEC_COMP, PPC_FEATURE_HAS_ALTIVEC_COMP,
.icache_bsize = 128, .icache_bsize = 128,
.dcache_bsize = 128, .dcache_bsize = 128,
...@@ -245,7 +248,7 @@ struct cpu_spec cpu_specs[] = { ...@@ -245,7 +248,7 @@ struct cpu_spec cpu_specs[] = {
.pvr_value = 0x003a0000, .pvr_value = 0x003a0000,
.cpu_name = "POWER5 (gr)", .cpu_name = "POWER5 (gr)",
.cpu_features = CPU_FTRS_POWER5, .cpu_features = CPU_FTRS_POWER5,
.cpu_user_features = COMMON_USER_PPC64, .cpu_user_features = COMMON_USER_POWER5,
.icache_bsize = 128, .icache_bsize = 128,
.dcache_bsize = 128, .dcache_bsize = 128,
.num_pmcs = 6, .num_pmcs = 6,
...@@ -260,7 +263,7 @@ struct cpu_spec cpu_specs[] = { ...@@ -260,7 +263,7 @@ struct cpu_spec cpu_specs[] = {
.pvr_value = 0x003b0000, .pvr_value = 0x003b0000,
.cpu_name = "POWER5 (gs)", .cpu_name = "POWER5 (gs)",
.cpu_features = CPU_FTRS_POWER5, .cpu_features = CPU_FTRS_POWER5,
.cpu_user_features = COMMON_USER_PPC64, .cpu_user_features = COMMON_USER_POWER5_PLUS,
.icache_bsize = 128, .icache_bsize = 128,
.dcache_bsize = 128, .dcache_bsize = 128,
.num_pmcs = 6, .num_pmcs = 6,
...@@ -276,7 +279,7 @@ struct cpu_spec cpu_specs[] = { ...@@ -276,7 +279,7 @@ struct cpu_spec cpu_specs[] = {
.cpu_name = "Cell Broadband Engine", .cpu_name = "Cell Broadband Engine",
.cpu_features = CPU_FTRS_CELL, .cpu_features = CPU_FTRS_CELL,
.cpu_user_features = COMMON_USER_PPC64 | .cpu_user_features = COMMON_USER_PPC64 |
PPC_FEATURE_HAS_ALTIVEC_COMP, PPC_FEATURE_CELL | PPC_FEATURE_HAS_ALTIVEC_COMP,
.icache_bsize = 128, .icache_bsize = 128,
.dcache_bsize = 128, .dcache_bsize = 128,
.cpu_setup = __setup_cpu_be, .cpu_setup = __setup_cpu_be,
......
/* /*
* arch/ppc64/kernel/firmware.c
*
* Extracted from cputable.c * Extracted from cputable.c
* *
* Copyright (C) 2001 Ben. Herrenschmidt (benh@kernel.crashing.org) * Copyright (C) 2001 Ben. Herrenschmidt (benh@kernel.crashing.org)
......
...@@ -41,20 +41,20 @@ _GLOBAL(load_up_fpu) ...@@ -41,20 +41,20 @@ _GLOBAL(load_up_fpu)
#ifndef CONFIG_SMP #ifndef CONFIG_SMP
LOADBASE(r3, last_task_used_math) LOADBASE(r3, last_task_used_math)
toreal(r3) toreal(r3)
LDL r4,OFF(last_task_used_math)(r3) PPC_LL r4,OFF(last_task_used_math)(r3)
CMPI 0,r4,0 PPC_LCMPI 0,r4,0
beq 1f beq 1f
toreal(r4) toreal(r4)
addi r4,r4,THREAD /* want last_task_used_math->thread */ addi r4,r4,THREAD /* want last_task_used_math->thread */
SAVE_32FPRS(0, r4) SAVE_32FPRS(0, r4)
mffs fr0 mffs fr0
stfd fr0,THREAD_FPSCR(r4) stfd fr0,THREAD_FPSCR(r4)
LDL r5,PT_REGS(r4) PPC_LL r5,PT_REGS(r4)
toreal(r5) toreal(r5)
LDL r4,_MSR-STACK_FRAME_OVERHEAD(r5) PPC_LL r4,_MSR-STACK_FRAME_OVERHEAD(r5)
li r10,MSR_FP|MSR_FE0|MSR_FE1 li r10,MSR_FP|MSR_FE0|MSR_FE1
andc r4,r4,r10 /* disable FP for previous task */ andc r4,r4,r10 /* disable FP for previous task */
STL r4,_MSR-STACK_FRAME_OVERHEAD(r5) PPC_STL r4,_MSR-STACK_FRAME_OVERHEAD(r5)
1: 1:
#endif /* CONFIG_SMP */ #endif /* CONFIG_SMP */
/* enable use of FP after return */ /* enable use of FP after return */
...@@ -77,7 +77,7 @@ _GLOBAL(load_up_fpu) ...@@ -77,7 +77,7 @@ _GLOBAL(load_up_fpu)
#ifndef CONFIG_SMP #ifndef CONFIG_SMP
subi r4,r5,THREAD subi r4,r5,THREAD
fromreal(r4) fromreal(r4)
STL r4,OFF(last_task_used_math)(r3) PPC_STL r4,OFF(last_task_used_math)(r3)
#endif /* CONFIG_SMP */ #endif /* CONFIG_SMP */
/* restore registers and return */ /* restore registers and return */
/* we haven't used ctr or xer or lr */ /* we haven't used ctr or xer or lr */
...@@ -97,24 +97,24 @@ _GLOBAL(giveup_fpu) ...@@ -97,24 +97,24 @@ _GLOBAL(giveup_fpu)
MTMSRD(r5) /* enable use of fpu now */ MTMSRD(r5) /* enable use of fpu now */
SYNC_601 SYNC_601
isync isync
CMPI 0,r3,0 PPC_LCMPI 0,r3,0
beqlr- /* if no previous owner, done */ beqlr- /* if no previous owner, done */
addi r3,r3,THREAD /* want THREAD of task */ addi r3,r3,THREAD /* want THREAD of task */
LDL r5,PT_REGS(r3) PPC_LL r5,PT_REGS(r3)
CMPI 0,r5,0 PPC_LCMPI 0,r5,0
SAVE_32FPRS(0, r3) SAVE_32FPRS(0, r3)
mffs fr0 mffs fr0
stfd fr0,THREAD_FPSCR(r3) stfd fr0,THREAD_FPSCR(r3)
beq 1f beq 1f
LDL r4,_MSR-STACK_FRAME_OVERHEAD(r5) PPC_LL r4,_MSR-STACK_FRAME_OVERHEAD(r5)
li r3,MSR_FP|MSR_FE0|MSR_FE1 li r3,MSR_FP|MSR_FE0|MSR_FE1
andc r4,r4,r3 /* disable FP for previous task */ andc r4,r4,r3 /* disable FP for previous task */
STL r4,_MSR-STACK_FRAME_OVERHEAD(r5) PPC_STL r4,_MSR-STACK_FRAME_OVERHEAD(r5)
1: 1:
#ifndef CONFIG_SMP #ifndef CONFIG_SMP
li r5,0 li r5,0
LOADBASE(r4,last_task_used_math) LOADBASE(r4,last_task_used_math)
STL r5,OFF(last_task_used_math)(r4) PPC_STL r5,OFF(last_task_used_math)(r4)
#endif /* CONFIG_SMP */ #endif /* CONFIG_SMP */
blr blr
......
...@@ -28,7 +28,6 @@ ...@@ -28,7 +28,6 @@
#include <asm/reg.h> #include <asm/reg.h>
#include <asm/page.h> #include <asm/page.h>
#include <asm/mmu.h> #include <asm/mmu.h>
#include <asm/systemcfg.h>
#include <asm/ppc_asm.h> #include <asm/ppc_asm.h>
#include <asm/asm-offsets.h> #include <asm/asm-offsets.h>
#include <asm/bug.h> #include <asm/bug.h>
...@@ -1697,25 +1696,14 @@ _GLOBAL(pmac_secondary_start) ...@@ -1697,25 +1696,14 @@ _GLOBAL(pmac_secondary_start)
* SPRG3 = paca virtual address * SPRG3 = paca virtual address
*/ */
_GLOBAL(__secondary_start) _GLOBAL(__secondary_start)
/* Set thread priority to MEDIUM */
HMT_MEDIUM
HMT_MEDIUM /* Set thread priority to MEDIUM */ /* Load TOC */
ld r2,PACATOC(r13) ld r2,PACATOC(r13)
li r6,0
stb r6,PACAPROCENABLED(r13) /* Do early setup for that CPU (stab, slb, hash table pointer) */
bl .early_setup_secondary
#ifndef CONFIG_PPC_ISERIES
/* Initialize the page table pointer register. */
LOADADDR(r6,_SDR1)
ld r6,0(r6) /* get the value of _SDR1 */
mtspr SPRN_SDR1,r6 /* set the htab location */
#endif
/* Initialize the first segment table (or SLB) entry */
ld r3,PACASTABVIRT(r13) /* get addr of segment table */
BEGIN_FTR_SECTION
bl .stab_initialize
END_FTR_SECTION_IFCLR(CPU_FTR_SLB)
bl .slb_initialize
/* Initialize the kernel stack. Just a repeat for iSeries. */ /* Initialize the kernel stack. Just a repeat for iSeries. */
LOADADDR(r3,current_set) LOADADDR(r3,current_set)
...@@ -1724,37 +1712,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SLB) ...@@ -1724,37 +1712,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SLB)
addi r1,r1,THREAD_SIZE-STACK_FRAME_OVERHEAD addi r1,r1,THREAD_SIZE-STACK_FRAME_OVERHEAD
std r1,PACAKSAVE(r13) std r1,PACAKSAVE(r13)
ld r3,PACASTABREAL(r13) /* get raddr of segment table */ /* Clear backchain so we get nice backtraces */
ori r4,r3,1 /* turn on valid bit */
#ifdef CONFIG_PPC_ISERIES
li r0,-1 /* hypervisor call */
li r3,1
sldi r3,r3,63 /* 0x8000000000000000 */
ori r3,r3,4 /* 0x8000000000000004 */
sc /* HvCall_setASR */
#else
/* set the ASR */
ld r3,systemcfg@got(r2) /* r3 = ptr to systemcfg */
ld r3,0(r3)
lwz r3,PLATFORM(r3) /* r3 = platform flags */
andi. r3,r3,PLATFORM_LPAR /* Test if bit 0 is set (LPAR bit) */
beq 98f /* branch if result is 0 */
mfspr r3,SPRN_PVR
srwi r3,r3,16
cmpwi r3,0x37 /* SStar */
beq 97f
cmpwi r3,0x36 /* IStar */
beq 97f
cmpwi r3,0x34 /* Pulsar */
bne 98f
97: li r3,H_SET_ASR /* hcall = H_SET_ASR */
HVSC /* Invoking hcall */
b 99f
98: /* !(rpa hypervisor) || !(star) */
mtasr r4 /* set the stab location */
99:
#endif
li r7,0 li r7,0
mtlr r7 mtlr r7
...@@ -1777,6 +1735,7 @@ _GLOBAL(start_secondary_prolog) ...@@ -1777,6 +1735,7 @@ _GLOBAL(start_secondary_prolog)
li r3,0 li r3,0
std r3,0(r1) /* Zero the stack frame pointer */ std r3,0(r1) /* Zero the stack frame pointer */
bl .start_secondary bl .start_secondary
b .
#endif #endif
/* /*
...@@ -1896,40 +1855,6 @@ _STATIC(start_here_multiplatform) ...@@ -1896,40 +1855,6 @@ _STATIC(start_here_multiplatform)
mr r3,r31 mr r3,r31
bl .early_setup bl .early_setup
/* set the ASR */
ld r3,PACASTABREAL(r13)
ori r4,r3,1 /* turn on valid bit */
ld r3,systemcfg@got(r2) /* r3 = ptr to systemcfg */
ld r3,0(r3)
lwz r3,PLATFORM(r3) /* r3 = platform flags */
andi. r3,r3,PLATFORM_LPAR /* Test if bit 0 is set (LPAR bit) */
beq 98f /* branch if result is 0 */
mfspr r3,SPRN_PVR
srwi r3,r3,16
cmpwi r3,0x37 /* SStar */
beq 97f
cmpwi r3,0x36 /* IStar */
beq 97f
cmpwi r3,0x34 /* Pulsar */
bne 98f
97: li r3,H_SET_ASR /* hcall = H_SET_ASR */
HVSC /* Invoking hcall */
b 99f
98: /* !(rpa hypervisor) || !(star) */
mtasr r4 /* set the stab location */
99:
/* Set SDR1 (hash table pointer) */
ld r3,systemcfg@got(r2) /* r3 = ptr to systemcfg */
ld r3,0(r3)
lwz r3,PLATFORM(r3) /* r3 = platform flags */
/* Test if bit 0 is set (LPAR bit) */
andi. r3,r3,PLATFORM_LPAR
bne 98f /* branch if result is !0 */
LOADADDR(r6,_SDR1) /* Only if NOT LPAR */
add r6,r6,r26
ld r6,0(r6) /* get the value of _SDR1 */
mtspr SPRN_SDR1,r6 /* set the htab location */
98:
LOADADDR(r3,.start_here_common) LOADADDR(r3,.start_here_common)
SET_REG_TO_CONST(r4, MSR_KERNEL) SET_REG_TO_CONST(r4, MSR_KERNEL)
mtspr SPRN_SRR0,r3 mtspr SPRN_SRR0,r3
......
...@@ -5,8 +5,8 @@ ...@@ -5,8 +5,8 @@
* Copyright (C) 1992 Linus Torvalds * Copyright (C) 1992 Linus Torvalds
* Adapted from arch/i386 by Gary Thomas * Adapted from arch/i386 by Gary Thomas
* Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
* Updated and modified by Cort Dougan (cort@cs.nmt.edu) * Updated and modified by Cort Dougan <cort@fsmlabs.com>
* Copyright (C) 1996 Cort Dougan * Copyright (C) 1996-2001 Cort Dougan
* Adapted for Power Macintosh by Paul Mackerras * Adapted for Power Macintosh by Paul Mackerras
* Copyright (C) 1996 Paul Mackerras (paulus@cs.anu.edu.au) * Copyright (C) 1996 Paul Mackerras (paulus@cs.anu.edu.au)
* Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
...@@ -21,6 +21,14 @@ ...@@ -21,6 +21,14 @@
* instead of just grabbing them. Thus setups with different IRQ numbers * instead of just grabbing them. Thus setups with different IRQ numbers
* shouldn't result in any weird surprises, and installing new handlers * shouldn't result in any weird surprises, and installing new handlers
* should be easier. * should be easier.
*
* The MPC8xx has an interrupt mask in the SIU. If a bit is set, the
* interrupt is _enabled_. As expected, IRQ0 is bit 0 in the 32-bit
* mask register (of which only 16 are defined), hence the weird shifting
* and complement of the cached_irq_mask. I want to be able to stuff
* this right into the SIU SMASK register.
* Many of the prep/chrp functions are conditional compiled on CONFIG_8xx
* to reduce code space and undefined function references.
*/ */
#include <linux/errno.h> #include <linux/errno.h>
...@@ -29,6 +37,7 @@ ...@@ -29,6 +37,7 @@
#include <linux/kernel_stat.h> #include <linux/kernel_stat.h>
#include <linux/signal.h> #include <linux/signal.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/ptrace.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/timex.h> #include <linux/timex.h>
...@@ -40,9 +49,13 @@ ...@@ -40,9 +49,13 @@
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include <linux/random.h> #include <linux/random.h>
#include <linux/kallsyms.h> #include <linux/seq_file.h>
#include <linux/cpumask.h>
#include <linux/profile.h> #include <linux/profile.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#ifdef CONFIG_PPC64
#include <linux/kallsyms.h>
#endif
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/system.h> #include <asm/system.h>
...@@ -52,35 +65,54 @@ ...@@ -52,35 +65,54 @@
#include <asm/cache.h> #include <asm/cache.h>
#include <asm/prom.h> #include <asm/prom.h>
#include <asm/ptrace.h> #include <asm/ptrace.h>
#include <asm/iseries/it_lp_queue.h>
#include <asm/machdep.h> #include <asm/machdep.h>
#ifdef CONFIG_PPC64
#include <asm/iseries/it_lp_queue.h>
#include <asm/paca.h> #include <asm/paca.h>
#endif
#ifdef CONFIG_SMP static int ppc_spurious_interrupts;
extern void iSeries_smp_message_recv( struct pt_regs * );
#if defined(CONFIG_PPC_ISERIES) && defined(CONFIG_SMP)
extern void iSeries_smp_message_recv(struct pt_regs *);
#endif
#ifdef CONFIG_PPC32
#define NR_MASK_WORDS ((NR_IRQS + 31) / 32)
unsigned long ppc_cached_irq_mask[NR_MASK_WORDS];
atomic_t ppc_n_lost_interrupts;
#ifdef CONFIG_TAU_INT
extern int tau_initialized;
extern int tau_interrupts(int);
#endif #endif
extern irq_desc_t irq_desc[NR_IRQS]; #if defined(CONFIG_SMP) && !defined(CONFIG_PPC_MERGE)
extern atomic_t ipi_recv;
extern atomic_t ipi_sent;
#endif
#endif /* CONFIG_PPC32 */
#ifdef CONFIG_PPC64
EXPORT_SYMBOL(irq_desc); EXPORT_SYMBOL(irq_desc);
int distribute_irqs = 1; int distribute_irqs = 1;
int __irq_offset_value; int __irq_offset_value;
int ppc_spurious_interrupts;
u64 ppc64_interrupt_controller; u64 ppc64_interrupt_controller;
#endif /* CONFIG_PPC64 */
int show_interrupts(struct seq_file *p, void *v) int show_interrupts(struct seq_file *p, void *v)
{ {
int i = *(loff_t *) v, j; int i = *(loff_t *)v, j;
struct irqaction * action; struct irqaction *action;
irq_desc_t *desc; irq_desc_t *desc;
unsigned long flags; unsigned long flags;
if (i == 0) { if (i == 0) {
seq_printf(p, " "); seq_puts(p, " ");
for (j=0; j<NR_CPUS; j++) { for_each_online_cpu(j)
if (cpu_online(j)) seq_printf(p, "CPU%d ", j);
seq_printf(p, "CPU%d ",j);
}
seq_putc(p, '\n'); seq_putc(p, '\n');
} }
...@@ -92,26 +124,41 @@ int show_interrupts(struct seq_file *p, void *v) ...@@ -92,26 +124,41 @@ int show_interrupts(struct seq_file *p, void *v)
goto skip; goto skip;
seq_printf(p, "%3d: ", i); seq_printf(p, "%3d: ", i);
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
for (j = 0; j < NR_CPUS; j++) { for_each_online_cpu(j)
if (cpu_online(j))
seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]); seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
}
#else #else
seq_printf(p, "%10u ", kstat_irqs(i)); seq_printf(p, "%10u ", kstat_irqs(i));
#endif /* CONFIG_SMP */ #endif /* CONFIG_SMP */
if (desc->handler) if (desc->handler)
seq_printf(p, " %s ", desc->handler->typename ); seq_printf(p, " %s ", desc->handler->typename);
else else
seq_printf(p, " None "); seq_puts(p, " None ");
seq_printf(p, "%s", (desc->status & IRQ_LEVEL) ? "Level " : "Edge "); seq_printf(p, "%s", (desc->status & IRQ_LEVEL) ? "Level " : "Edge ");
seq_printf(p, " %s",action->name); seq_printf(p, " %s", action->name);
for (action=action->next; action; action = action->next) for (action = action->next; action; action = action->next)
seq_printf(p, ", %s", action->name); seq_printf(p, ", %s", action->name);
seq_putc(p, '\n'); seq_putc(p, '\n');
skip: skip:
spin_unlock_irqrestore(&desc->lock, flags); spin_unlock_irqrestore(&desc->lock, flags);
} else if (i == NR_IRQS) } else if (i == NR_IRQS) {
#ifdef CONFIG_PPC32
#ifdef CONFIG_TAU_INT
if (tau_initialized){
seq_puts(p, "TAU: ");
for (j = 0; j < NR_CPUS; j++)
if (cpu_online(j))
seq_printf(p, "%10u ", tau_interrupts(j));
seq_puts(p, " PowerPC Thermal Assist (cpu temp)\n");
}
#endif
#if defined(CONFIG_SMP) && !defined(CONFIG_PPC_MERGE)
/* should this be per processor send/receive? */
seq_printf(p, "IPI (recv/sent): %10u/%u\n",
atomic_read(&ipi_recv), atomic_read(&ipi_sent));
#endif
#endif /* CONFIG_PPC32 */
seq_printf(p, "BAD: %10u\n", ppc_spurious_interrupts); seq_printf(p, "BAD: %10u\n", ppc_spurious_interrupts);
}
return 0; return 0;
} }
...@@ -144,126 +191,6 @@ void fixup_irqs(cpumask_t map) ...@@ -144,126 +191,6 @@ void fixup_irqs(cpumask_t map)
} }
#endif #endif
extern int noirqdebug;
/*
* Eventually, this should take an array of interrupts and an array size
* so it can dispatch multiple interrupts.
*/
void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq)
{
int status;
struct irqaction *action;
int cpu = smp_processor_id();
irq_desc_t *desc = get_irq_desc(irq);
irqreturn_t action_ret;
#ifdef CONFIG_IRQSTACKS
struct thread_info *curtp, *irqtp;
#endif
kstat_cpu(cpu).irqs[irq]++;
if (desc->status & IRQ_PER_CPU) {
/* no locking required for CPU-local interrupts: */
ack_irq(irq);
action_ret = handle_IRQ_event(irq, regs, desc->action);
desc->handler->end(irq);
return;
}
spin_lock(&desc->lock);
ack_irq(irq);
/*
REPLAY is when Linux resends an IRQ that was dropped earlier
WAITING is used by probe to mark irqs that are being tested
*/
status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING);
status |= IRQ_PENDING; /* we _want_ to handle it */
/*
* If the IRQ is disabled for whatever reason, we cannot
* use the action we have.
*/
action = NULL;
if (likely(!(status & (IRQ_DISABLED | IRQ_INPROGRESS)))) {
action = desc->action;
if (!action || !action->handler) {
ppc_spurious_interrupts++;
printk(KERN_DEBUG "Unhandled interrupt %x, disabled\n", irq);
/* We can't call disable_irq here, it would deadlock */
if (!desc->depth)
desc->depth = 1;
desc->status |= IRQ_DISABLED;
/* This is not a real spurrious interrupt, we
* have to eoi it, so we jump to out
*/
mask_irq(irq);
goto out;
}
status &= ~IRQ_PENDING; /* we commit to handling */
status |= IRQ_INPROGRESS; /* we are handling it */
}
desc->status = status;
/*
* If there is no IRQ handler or it was disabled, exit early.
Since we set PENDING, if another processor is handling
a different instance of this same irq, the other processor
will take care of it.
*/
if (unlikely(!action))
goto out;
/*
* Edge triggered interrupts need to remember
* pending events.
* This applies to any hw interrupts that allow a second
* instance of the same irq to arrive while we are in do_IRQ
* or in the handler. But the code here only handles the _second_
* instance of the irq, not the third or fourth. So it is mostly
* useful for irq hardware that does not mask cleanly in an
* SMP environment.
*/
for (;;) {
spin_unlock(&desc->lock);
#ifdef CONFIG_IRQSTACKS
/* Switch to the irq stack to handle this */
curtp = current_thread_info();
irqtp = hardirq_ctx[smp_processor_id()];
if (curtp != irqtp) {
irqtp->task = curtp->task;
irqtp->flags = 0;
action_ret = call_handle_IRQ_event(irq, regs, action, irqtp);
irqtp->task = NULL;
if (irqtp->flags)
set_bits(irqtp->flags, &curtp->flags);
} else
#endif
action_ret = handle_IRQ_event(irq, regs, action);
spin_lock(&desc->lock);
if (!noirqdebug)
note_interrupt(irq, desc, action_ret, regs);
if (likely(!(desc->status & IRQ_PENDING)))
break;
desc->status &= ~IRQ_PENDING;
}
out:
desc->status &= ~IRQ_INPROGRESS;
/*
* The ->end() handler has to deal with interrupts which got
* disabled while the handler was running.
*/
if (desc->handler) {
if (desc->handler->end)
desc->handler->end(irq);
else if (desc->handler->enable)
desc->handler->enable(irq);
}
spin_unlock(&desc->lock);
}
#ifdef CONFIG_PPC_ISERIES #ifdef CONFIG_PPC_ISERIES
void do_IRQ(struct pt_regs *regs) void do_IRQ(struct pt_regs *regs)
{ {
...@@ -310,6 +237,9 @@ void do_IRQ(struct pt_regs *regs) ...@@ -310,6 +237,9 @@ void do_IRQ(struct pt_regs *regs)
void do_IRQ(struct pt_regs *regs) void do_IRQ(struct pt_regs *regs)
{ {
int irq; int irq;
#ifdef CONFIG_IRQSTACKS
struct thread_info *curtp, *irqtp;
#endif
irq_enter(); irq_enter();
...@@ -328,20 +258,44 @@ void do_IRQ(struct pt_regs *regs) ...@@ -328,20 +258,44 @@ void do_IRQ(struct pt_regs *regs)
} }
#endif #endif
/*
* Every platform is required to implement ppc_md.get_irq.
* This function will either return an irq number or -1 to
* indicate there are no more pending.
* The value -2 is for buggy hardware and means that this IRQ
* has already been handled. -- Tom
*/
irq = ppc_md.get_irq(regs); irq = ppc_md.get_irq(regs);
if (irq >= 0) if (irq >= 0) {
ppc_irq_dispatch_handler(regs, irq); #ifdef CONFIG_IRQSTACKS
else /* Switch to the irq stack to handle this */
curtp = current_thread_info();
irqtp = hardirq_ctx[smp_processor_id()];
if (curtp != irqtp) {
irqtp->task = curtp->task;
irqtp->flags = 0;
call___do_IRQ(irq, regs, irqtp);
irqtp->task = NULL;
if (irqtp->flags)
set_bits(irqtp->flags, &curtp->flags);
} else
#endif
__do_IRQ(irq, regs);
} else
#ifdef CONFIG_PPC32
if (irq != -2)
#endif
/* That's not SMP safe ... but who cares ? */ /* That's not SMP safe ... but who cares ? */
ppc_spurious_interrupts++; ppc_spurious_interrupts++;
irq_exit(); irq_exit();
} }
#endif /* CONFIG_PPC_ISERIES */ #endif /* CONFIG_PPC_ISERIES */
void __init init_IRQ(void) void __init init_IRQ(void)
{ {
#ifdef CONFIG_PPC64
static int once = 0; static int once = 0;
if (once) if (once)
...@@ -349,10 +303,14 @@ void __init init_IRQ(void) ...@@ -349,10 +303,14 @@ void __init init_IRQ(void)
once++; once++;
#endif
ppc_md.init_IRQ(); ppc_md.init_IRQ();
#ifdef CONFIG_PPC64
irq_ctx_init(); irq_ctx_init();
#endif
} }
#ifdef CONFIG_PPC64
#ifndef CONFIG_PPC_ISERIES #ifndef CONFIG_PPC_ISERIES
/* /*
* Virtual IRQ mapping code, used on systems with XICS interrupt controllers. * Virtual IRQ mapping code, used on systems with XICS interrupt controllers.
...@@ -517,3 +475,4 @@ static int __init setup_noirqdistrib(char *str) ...@@ -517,3 +475,4 @@ static int __init setup_noirqdistrib(char *str)
} }
__setup("noirqdistrib", setup_noirqdistrib); __setup("noirqdistrib", setup_noirqdistrib);
#endif /* CONFIG_PPC64 */
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include <asm/time.h> #include <asm/time.h>
#include <asm/iseries/it_exp_vpd_panel.h> #include <asm/iseries/it_exp_vpd_panel.h>
#include <asm/prom.h> #include <asm/prom.h>
#include <asm/systemcfg.h>
#define MODULE_VERS "1.6" #define MODULE_VERS "1.6"
#define MODULE_NAME "lparcfg" #define MODULE_NAME "lparcfg"
...@@ -371,7 +372,7 @@ static int lparcfg_data(struct seq_file *m, void *v) ...@@ -371,7 +372,7 @@ static int lparcfg_data(struct seq_file *m, void *v)
lrdrp = (int *)get_property(rtas_node, "ibm,lrdr-capacity", NULL); lrdrp = (int *)get_property(rtas_node, "ibm,lrdr-capacity", NULL);
if (lrdrp == NULL) { if (lrdrp == NULL) {
partition_potential_processors = systemcfg->processorCount; partition_potential_processors = _systemcfg->processorCount;
} else { } else {
partition_potential_processors = *(lrdrp + 4); partition_potential_processors = *(lrdrp + 4);
} }
......
...@@ -519,7 +519,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE) ...@@ -519,7 +519,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
* *
* flush_icache_range(unsigned long start, unsigned long stop) * flush_icache_range(unsigned long start, unsigned long stop)
*/ */
_GLOBAL(flush_icache_range) _GLOBAL(__flush_icache_range)
BEGIN_FTR_SECTION BEGIN_FTR_SECTION
blr /* for 601, do nothing */ blr /* for 601, do nothing */
END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE) END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
...@@ -607,27 +607,6 @@ _GLOBAL(invalidate_dcache_range) ...@@ -607,27 +607,6 @@ _GLOBAL(invalidate_dcache_range)
sync /* wait for dcbi's to get to ram */ sync /* wait for dcbi's to get to ram */
blr 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. * Flush a particular page from the data cache to RAM.
* Note: this is necessary because the instruction cache does *not* * Note: this is necessary because the instruction cache does *not*
......
...@@ -89,12 +89,12 @@ _GLOBAL(call_do_softirq) ...@@ -89,12 +89,12 @@ _GLOBAL(call_do_softirq)
mtlr r0 mtlr r0
blr blr
_GLOBAL(call_handle_IRQ_event) _GLOBAL(call___do_IRQ)
mflr r0 mflr r0
std r0,16(r1) std r0,16(r1)
stdu r1,THREAD_SIZE-112(r6) stdu r1,THREAD_SIZE-112(r5)
mr r1,r6 mr r1,r5
bl .handle_IRQ_event bl .__do_IRQ
ld r1,0(r1) ld r1,0(r1)
ld r0,16(r1) ld r0,16(r1)
mtlr r0 mtlr r0
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/ptrace.h> #include <asm/ptrace.h>
#include <asm/page.h> #include <asm/page.h>
#include <asm/systemcfg.h>
#include <asm/lppaca.h> #include <asm/lppaca.h>
#include <asm/iseries/it_lp_queue.h> #include <asm/iseries/it_lp_queue.h>
#include <asm/paca.h> #include <asm/paca.h>
...@@ -24,8 +24,7 @@ static union { ...@@ -24,8 +24,7 @@ static union {
struct systemcfg data; struct systemcfg data;
u8 page[PAGE_SIZE]; u8 page[PAGE_SIZE];
} systemcfg_store __attribute__((__section__(".data.page.aligned"))); } systemcfg_store __attribute__((__section__(".data.page.aligned")));
struct systemcfg *systemcfg = &systemcfg_store.data; struct systemcfg *_systemcfg = &systemcfg_store.data;
EXPORT_SYMBOL(systemcfg);
/* This symbol is provided by the linker - let it fill in the paca /* This symbol is provided by the linker - let it fill in the paca
......
...@@ -44,6 +44,7 @@ ...@@ -44,6 +44,7 @@
#include <asm/cputable.h> #include <asm/cputable.h>
#include <asm/btext.h> #include <asm/btext.h>
#include <asm/div64.h> #include <asm/div64.h>
#include <asm/signal.h>
#ifdef CONFIG_8xx #ifdef CONFIG_8xx
#include <asm/commproc.h> #include <asm/commproc.h>
...@@ -56,7 +57,6 @@ extern void machine_check_exception(struct pt_regs *regs); ...@@ -56,7 +57,6 @@ extern void machine_check_exception(struct pt_regs *regs);
extern void alignment_exception(struct pt_regs *regs); extern void alignment_exception(struct pt_regs *regs);
extern void program_check_exception(struct pt_regs *regs); extern void program_check_exception(struct pt_regs *regs);
extern void single_step_exception(struct pt_regs *regs); extern void single_step_exception(struct pt_regs *regs);
extern int do_signal(sigset_t *, struct pt_regs *);
extern int pmac_newworld; extern int pmac_newworld;
extern int sys_sigreturn(struct pt_regs *regs); extern int sys_sigreturn(struct pt_regs *regs);
...@@ -188,9 +188,6 @@ EXPORT_SYMBOL(adb_try_handler_change); ...@@ -188,9 +188,6 @@ EXPORT_SYMBOL(adb_try_handler_change);
EXPORT_SYMBOL(cuda_request); EXPORT_SYMBOL(cuda_request);
EXPORT_SYMBOL(cuda_poll); EXPORT_SYMBOL(cuda_poll);
#endif /* CONFIG_ADB_CUDA */ #endif /* CONFIG_ADB_CUDA */
#if defined(CONFIG_PPC_MULTIPLATFORM) && defined(CONFIG_PPC32)
EXPORT_SYMBOL(_machine);
#endif
#ifdef CONFIG_PPC_PMAC #ifdef CONFIG_PPC_PMAC
EXPORT_SYMBOL(sys_ctrler); EXPORT_SYMBOL(sys_ctrler);
#endif #endif
......
/* /*
* arch/ppc64/kernel/proc_ppc64.c
*
* Copyright (C) 2001 Mike Corrigan & Dave Engebretsen IBM Corporation * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen IBM Corporation
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -53,7 +51,7 @@ static int __init proc_ppc64_create(void) ...@@ -53,7 +51,7 @@ static int __init proc_ppc64_create(void)
if (!root) if (!root)
return 1; return 1;
if (!(systemcfg->platform & (PLATFORM_PSERIES | PLATFORM_CELL))) if (!(platform_is_pseries() || _machine == PLATFORM_CELL))
return 0; return 0;
if (!proc_mkdir("rtas", root)) if (!proc_mkdir("rtas", root))
...@@ -74,7 +72,7 @@ static int __init proc_ppc64_init(void) ...@@ -74,7 +72,7 @@ static int __init proc_ppc64_init(void)
if (!pde) if (!pde)
return 1; return 1;
pde->nlink = 1; pde->nlink = 1;
pde->data = systemcfg; pde->data = _systemcfg;
pde->size = PAGE_SIZE; pde->size = PAGE_SIZE;
pde->proc_fops = &page_map_fops; pde->proc_fops = &page_map_fops;
......
...@@ -48,9 +48,6 @@ ...@@ -48,9 +48,6 @@
#include <asm/machdep.h> #include <asm/machdep.h>
#include <asm/pSeries_reconfig.h> #include <asm/pSeries_reconfig.h>
#include <asm/pci-bridge.h> #include <asm/pci-bridge.h>
#ifdef CONFIG_PPC64
#include <asm/systemcfg.h>
#endif
#ifdef DEBUG #ifdef DEBUG
#define DBG(fmt...) printk(KERN_ERR fmt) #define DBG(fmt...) printk(KERN_ERR fmt)
...@@ -74,10 +71,6 @@ struct isa_reg_property { ...@@ -74,10 +71,6 @@ struct isa_reg_property {
typedef int interpret_func(struct device_node *, unsigned long *, typedef int interpret_func(struct device_node *, unsigned long *,
int, int, int); int, int, int);
extern struct rtas_t rtas;
extern struct lmb lmb;
extern unsigned long klimit;
static int __initdata dt_root_addr_cells; static int __initdata dt_root_addr_cells;
static int __initdata dt_root_size_cells; static int __initdata dt_root_size_cells;
...@@ -391,7 +384,7 @@ static int __devinit finish_node_interrupts(struct device_node *np, ...@@ -391,7 +384,7 @@ static int __devinit finish_node_interrupts(struct device_node *np,
#ifdef CONFIG_PPC64 #ifdef CONFIG_PPC64
/* We offset irq numbers for the u3 MPIC by 128 in PowerMac */ /* We offset irq numbers for the u3 MPIC by 128 in PowerMac */
if (systemcfg->platform == PLATFORM_POWERMAC && ic && ic->parent) { if (_machine == PLATFORM_POWERMAC && ic && ic->parent) {
char *name = get_property(ic->parent, "name", NULL); char *name = get_property(ic->parent, "name", NULL);
if (name && !strcmp(name, "u3")) if (name && !strcmp(name, "u3"))
np->intrs[intrcount].line += 128; np->intrs[intrcount].line += 128;
...@@ -1087,9 +1080,9 @@ void __init unflatten_device_tree(void) ...@@ -1087,9 +1080,9 @@ void __init unflatten_device_tree(void)
static int __init early_init_dt_scan_cpus(unsigned long node, static int __init early_init_dt_scan_cpus(unsigned long node,
const char *uname, int depth, void *data) const char *uname, int depth, void *data)
{ {
char *type = of_get_flat_dt_prop(node, "device_type", NULL);
u32 *prop; u32 *prop;
unsigned long size = 0; unsigned long size;
char *type = of_get_flat_dt_prop(node, "device_type", &size);
/* We are scanning "cpu" nodes only */ /* We are scanning "cpu" nodes only */
if (type == NULL || strcmp(type, "cpu") != 0) if (type == NULL || strcmp(type, "cpu") != 0)
...@@ -1115,7 +1108,7 @@ static int __init early_init_dt_scan_cpus(unsigned long node, ...@@ -1115,7 +1108,7 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
#ifdef CONFIG_ALTIVEC #ifdef CONFIG_ALTIVEC
/* Check if we have a VMX and eventually update CPU features */ /* Check if we have a VMX and eventually update CPU features */
prop = (u32 *)of_get_flat_dt_prop(node, "ibm,vmx", &size); prop = (u32 *)of_get_flat_dt_prop(node, "ibm,vmx", NULL);
if (prop && (*prop) > 0) { if (prop && (*prop) > 0) {
cur_cpu_spec->cpu_features |= CPU_FTR_ALTIVEC; cur_cpu_spec->cpu_features |= CPU_FTR_ALTIVEC;
cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_ALTIVEC; cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_ALTIVEC;
...@@ -1161,13 +1154,9 @@ static int __init early_init_dt_scan_chosen(unsigned long node, ...@@ -1161,13 +1154,9 @@ static int __init early_init_dt_scan_chosen(unsigned long node,
prop = (u32 *)of_get_flat_dt_prop(node, "linux,platform", NULL); prop = (u32 *)of_get_flat_dt_prop(node, "linux,platform", NULL);
if (prop == NULL) if (prop == NULL)
return 0; return 0;
#ifdef CONFIG_PPC64
systemcfg->platform = *prop;
#else
#ifdef CONFIG_PPC_MULTIPLATFORM #ifdef CONFIG_PPC_MULTIPLATFORM
_machine = *prop; _machine = *prop;
#endif #endif
#endif
#ifdef CONFIG_PPC64 #ifdef CONFIG_PPC64
/* check if iommu is forced on or off */ /* check if iommu is forced on or off */
...@@ -1264,7 +1253,14 @@ static int __init early_init_dt_scan_memory(unsigned long node, ...@@ -1264,7 +1253,14 @@ static int __init early_init_dt_scan_memory(unsigned long node,
unsigned long l; unsigned long l;
/* We are scanning "memory" nodes only */ /* We are scanning "memory" nodes only */
if (type == NULL || strcmp(type, "memory") != 0) if (type == NULL) {
/*
* The longtrail doesn't have a device_type on the
* /memory node, so look for the node called /memory@0.
*/
if (depth != 1 || strcmp(uname, "memory@0") != 0)
return 0;
} else if (strcmp(type, "memory") != 0)
return 0; return 0;
reg = (cell_t *)of_get_flat_dt_prop(node, "reg", &l); reg = (cell_t *)of_get_flat_dt_prop(node, "reg", &l);
...@@ -1339,9 +1335,6 @@ void __init early_init_devtree(void *params) ...@@ -1339,9 +1335,6 @@ void __init early_init_devtree(void *params)
of_scan_flat_dt(early_init_dt_scan_memory, NULL); of_scan_flat_dt(early_init_dt_scan_memory, NULL);
lmb_enforce_memory_limit(memory_limit); lmb_enforce_memory_limit(memory_limit);
lmb_analyze(); lmb_analyze();
#ifdef CONFIG_PPC64
systemcfg->physicalMemorySize = lmb_phys_mem_size();
#endif
lmb_reserve(0, __pa(klimit)); lmb_reserve(0, __pa(klimit));
DBG("Phys. mem: %lx\n", lmb_phys_mem_size()); DBG("Phys. mem: %lx\n", lmb_phys_mem_size());
...@@ -1908,7 +1901,7 @@ static int of_finish_dynamic_node(struct device_node *node, ...@@ -1908,7 +1901,7 @@ static int of_finish_dynamic_node(struct device_node *node,
/* We don't support that function on PowerMac, at least /* We don't support that function on PowerMac, at least
* not yet * not yet
*/ */
if (systemcfg->platform == PLATFORM_POWERMAC) if (_machine == PLATFORM_POWERMAC)
return -ENODEV; return -ENODEV;
/* fix up new node's linux_phandle field */ /* fix up new node's linux_phandle field */
...@@ -1992,9 +1985,11 @@ int prom_add_property(struct device_node* np, struct property* prop) ...@@ -1992,9 +1985,11 @@ int prom_add_property(struct device_node* np, struct property* prop)
*next = prop; *next = prop;
write_unlock(&devtree_lock); write_unlock(&devtree_lock);
#ifdef CONFIG_PROC_DEVICETREE
/* try to add to proc as well if it was initialized */ /* try to add to proc as well if it was initialized */
if (np->pde) if (np->pde)
proc_device_tree_add_prop(np->pde, prop); proc_device_tree_add_prop(np->pde, prop);
#endif /* CONFIG_PROC_DEVICETREE */
return 0; return 0;
} }
......
...@@ -94,11 +94,17 @@ extern const struct linux_logo logo_linux_clut224; ...@@ -94,11 +94,17 @@ extern const struct linux_logo logo_linux_clut224;
#ifdef CONFIG_PPC64 #ifdef CONFIG_PPC64
#define RELOC(x) (*PTRRELOC(&(x))) #define RELOC(x) (*PTRRELOC(&(x)))
#define ADDR(x) (u32) add_reloc_offset((unsigned long)(x)) #define ADDR(x) (u32) add_reloc_offset((unsigned long)(x))
#define OF_WORKAROUNDS 0
#else #else
#define RELOC(x) (x) #define RELOC(x) (x)
#define ADDR(x) (u32) (x) #define ADDR(x) (u32) (x)
#define OF_WORKAROUNDS of_workarounds
int of_workarounds;
#endif #endif
#define OF_WA_CLAIM 1 /* do phys/virt claim separately, then map */
#define OF_WA_LONGTRAIL 2 /* work around longtrail bugs */
#define PROM_BUG() do { \ #define PROM_BUG() do { \
prom_printf("kernel BUG at %s line 0x%x!\n", \ prom_printf("kernel BUG at %s line 0x%x!\n", \
RELOC(__FILE__), __LINE__); \ RELOC(__FILE__), __LINE__); \
...@@ -111,11 +117,6 @@ extern const struct linux_logo logo_linux_clut224; ...@@ -111,11 +117,6 @@ extern const struct linux_logo logo_linux_clut224;
#define prom_debug(x...) #define prom_debug(x...)
#endif #endif
#ifdef CONFIG_PPC32
#define PLATFORM_POWERMAC _MACH_Pmac
#define PLATFORM_CHRP _MACH_chrp
#endif
typedef u32 prom_arg_t; typedef u32 prom_arg_t;
...@@ -128,10 +129,11 @@ struct prom_args { ...@@ -128,10 +129,11 @@ struct prom_args {
struct prom_t { struct prom_t {
ihandle root; ihandle root;
ihandle chosen; phandle chosen;
int cpu; int cpu;
ihandle stdout; ihandle stdout;
ihandle mmumap; ihandle mmumap;
ihandle memory;
}; };
struct mem_map_entry { struct mem_map_entry {
...@@ -360,16 +362,36 @@ static void __init prom_printf(const char *format, ...) ...@@ -360,16 +362,36 @@ static void __init prom_printf(const char *format, ...)
static unsigned int __init prom_claim(unsigned long virt, unsigned long size, static unsigned int __init prom_claim(unsigned long virt, unsigned long size,
unsigned long align) unsigned long align)
{ {
int ret;
struct prom_t *_prom = &RELOC(prom); struct prom_t *_prom = &RELOC(prom);
ret = call_prom("claim", 3, 1, (prom_arg_t)virt, (prom_arg_t)size, if (align == 0 && (OF_WORKAROUNDS & OF_WA_CLAIM)) {
(prom_arg_t)align); /*
if (ret != -1 && _prom->mmumap != 0) * Old OF requires we claim physical and virtual separately
/* old pmacs need us to map as well */ * and then map explicitly (assuming virtual mode)
*/
int ret;
prom_arg_t result;
ret = call_prom_ret("call-method", 5, 2, &result,
ADDR("claim"), _prom->memory,
align, size, virt);
if (ret != 0 || result == -1)
return -1;
ret = call_prom_ret("call-method", 5, 2, &result,
ADDR("claim"), _prom->mmumap,
align, size, virt);
if (ret != 0) {
call_prom("call-method", 4, 1, ADDR("release"),
_prom->memory, size, virt);
return -1;
}
/* the 0x12 is M (coherence) + PP == read/write */
call_prom("call-method", 6, 1, call_prom("call-method", 6, 1,
ADDR("map"), _prom->mmumap, 0, size, virt, virt); ADDR("map"), _prom->mmumap, 0x12, size, virt, virt);
return ret; return virt;
}
return call_prom("claim", 3, 1, (prom_arg_t)virt, (prom_arg_t)size,
(prom_arg_t)align);
} }
static void __init __attribute__((noreturn)) prom_panic(const char *reason) static void __init __attribute__((noreturn)) prom_panic(const char *reason)
...@@ -415,11 +437,52 @@ static int inline prom_getproplen(phandle node, const char *pname) ...@@ -415,11 +437,52 @@ static int inline prom_getproplen(phandle node, const char *pname)
return call_prom("getproplen", 2, 1, node, ADDR(pname)); return call_prom("getproplen", 2, 1, node, ADDR(pname));
} }
static int inline prom_setprop(phandle node, const char *pname, static void add_string(char **str, const char *q)
void *value, size_t valuelen) {
char *p = *str;
while (*q)
*p++ = *q++;
*p++ = ' ';
*str = p;
}
static char *tohex(unsigned int x)
{ {
static char digits[] = "0123456789abcdef";
static char result[9];
int i;
result[8] = 0;
i = 8;
do {
--i;
result[i] = digits[x & 0xf];
x >>= 4;
} while (x != 0 && i > 0);
return &result[i];
}
static int __init prom_setprop(phandle node, const char *nodename,
const char *pname, void *value, size_t valuelen)
{
char cmd[256], *p;
if (!(OF_WORKAROUNDS & OF_WA_LONGTRAIL))
return call_prom("setprop", 4, 1, node, ADDR(pname), return call_prom("setprop", 4, 1, node, ADDR(pname),
(u32)(unsigned long) value, (u32) valuelen); (u32)(unsigned long) value, (u32) valuelen);
/* gah... setprop doesn't work on longtrail, have to use interpret */
p = cmd;
add_string(&p, "dev");
add_string(&p, nodename);
add_string(&p, tohex((u32)(unsigned long) value));
add_string(&p, tohex(valuelen));
add_string(&p, tohex(ADDR(pname)));
add_string(&p, tohex(strlen(RELOC(pname))));
add_string(&p, "property");
*p = 0;
return call_prom("interpret", 1, 1, (u32)(unsigned long) cmd);
} }
/* We can't use the standard versions because of RELOC headaches. */ /* We can't use the standard versions because of RELOC headaches. */
...@@ -980,7 +1043,7 @@ static void __init prom_instantiate_rtas(void) ...@@ -980,7 +1043,7 @@ static void __init prom_instantiate_rtas(void)
rtas_inst = call_prom("open", 1, 1, ADDR("/rtas")); rtas_inst = call_prom("open", 1, 1, ADDR("/rtas"));
if (!IHANDLE_VALID(rtas_inst)) { if (!IHANDLE_VALID(rtas_inst)) {
prom_printf("opening rtas package failed"); prom_printf("opening rtas package failed (%x)\n", rtas_inst);
return; return;
} }
...@@ -988,7 +1051,7 @@ static void __init prom_instantiate_rtas(void) ...@@ -988,7 +1051,7 @@ static void __init prom_instantiate_rtas(void)
if (call_prom_ret("call-method", 3, 2, &entry, if (call_prom_ret("call-method", 3, 2, &entry,
ADDR("instantiate-rtas"), ADDR("instantiate-rtas"),
rtas_inst, base) == PROM_ERROR rtas_inst, base) != 0
|| entry == 0) { || entry == 0) {
prom_printf(" failed\n"); prom_printf(" failed\n");
return; return;
...@@ -997,8 +1060,10 @@ static void __init prom_instantiate_rtas(void) ...@@ -997,8 +1060,10 @@ static void __init prom_instantiate_rtas(void)
reserve_mem(base, size); reserve_mem(base, size);
prom_setprop(rtas_node, "linux,rtas-base", &base, sizeof(base)); prom_setprop(rtas_node, "/rtas", "linux,rtas-base",
prom_setprop(rtas_node, "linux,rtas-entry", &entry, sizeof(entry)); &base, sizeof(base));
prom_setprop(rtas_node, "/rtas", "linux,rtas-entry",
&entry, sizeof(entry));
prom_debug("rtas base = 0x%x\n", base); prom_debug("rtas base = 0x%x\n", base);
prom_debug("rtas entry = 0x%x\n", entry); prom_debug("rtas entry = 0x%x\n", entry);
...@@ -1089,10 +1154,6 @@ static void __init prom_initialize_tce_table(void) ...@@ -1089,10 +1154,6 @@ static void __init prom_initialize_tce_table(void)
if (base < local_alloc_bottom) if (base < local_alloc_bottom)
local_alloc_bottom = base; local_alloc_bottom = base;
/* Save away the TCE table attributes for later use. */
prom_setprop(node, "linux,tce-base", &base, sizeof(base));
prom_setprop(node, "linux,tce-size", &minsize, sizeof(minsize));
/* It seems OF doesn't null-terminate the path :-( */ /* It seems OF doesn't null-terminate the path :-( */
memset(path, 0, sizeof(path)); memset(path, 0, sizeof(path));
/* Call OF to setup the TCE hardware */ /* Call OF to setup the TCE hardware */
...@@ -1101,6 +1162,10 @@ static void __init prom_initialize_tce_table(void) ...@@ -1101,6 +1162,10 @@ static void __init prom_initialize_tce_table(void)
prom_printf("package-to-path failed\n"); prom_printf("package-to-path failed\n");
} }
/* Save away the TCE table attributes for later use. */
prom_setprop(node, path, "linux,tce-base", &base, sizeof(base));
prom_setprop(node, path, "linux,tce-size", &minsize, sizeof(minsize));
prom_debug("TCE table: %s\n", path); prom_debug("TCE table: %s\n", path);
prom_debug("\tnode = 0x%x\n", node); prom_debug("\tnode = 0x%x\n", node);
prom_debug("\tbase = 0x%x\n", base); prom_debug("\tbase = 0x%x\n", base);
...@@ -1342,6 +1407,7 @@ static void __init prom_init_client_services(unsigned long pp) ...@@ -1342,6 +1407,7 @@ static void __init prom_init_client_services(unsigned long pp)
/* /*
* For really old powermacs, we need to map things we claim. * For really old powermacs, we need to map things we claim.
* For that, we need the ihandle of the mmu. * For that, we need the ihandle of the mmu.
* Also, on the longtrail, we need to work around other bugs.
*/ */
static void __init prom_find_mmu(void) static void __init prom_find_mmu(void)
{ {
...@@ -1355,12 +1421,19 @@ static void __init prom_find_mmu(void) ...@@ -1355,12 +1421,19 @@ static void __init prom_find_mmu(void)
if (prom_getprop(oprom, "model", version, sizeof(version)) <= 0) if (prom_getprop(oprom, "model", version, sizeof(version)) <= 0)
return; return;
version[sizeof(version) - 1] = 0; version[sizeof(version) - 1] = 0;
prom_printf("OF version is '%s'\n", version);
/* XXX might need to add other versions here */ /* XXX might need to add other versions here */
if (strcmp(version, "Open Firmware, 1.0.5") != 0) if (strcmp(version, "Open Firmware, 1.0.5") == 0)
of_workarounds = OF_WA_CLAIM;
else if (strncmp(version, "FirmWorks,3.", 12) == 0) {
of_workarounds = OF_WA_CLAIM | OF_WA_LONGTRAIL;
call_prom("interpret", 1, 1, "dev /memory 0 to allow-reclaim");
} else
return; return;
_prom->memory = call_prom("open", 1, 1, ADDR("/memory"));
prom_getprop(_prom->chosen, "mmu", &_prom->mmumap, prom_getprop(_prom->chosen, "mmu", &_prom->mmumap,
sizeof(_prom->mmumap)); sizeof(_prom->mmumap));
if (!IHANDLE_VALID(_prom->memory) || !IHANDLE_VALID(_prom->mmumap))
of_workarounds &= ~OF_WA_CLAIM; /* hmmm */
} }
#else #else
#define prom_find_mmu() #define prom_find_mmu()
...@@ -1382,16 +1455,17 @@ static void __init prom_init_stdout(void) ...@@ -1382,16 +1455,17 @@ static void __init prom_init_stdout(void)
memset(path, 0, 256); memset(path, 0, 256);
call_prom("instance-to-path", 3, 1, _prom->stdout, path, 255); call_prom("instance-to-path", 3, 1, _prom->stdout, path, 255);
val = call_prom("instance-to-package", 1, 1, _prom->stdout); val = call_prom("instance-to-package", 1, 1, _prom->stdout);
prom_setprop(_prom->chosen, "linux,stdout-package", &val, sizeof(val)); prom_setprop(_prom->chosen, "/chosen", "linux,stdout-package",
&val, sizeof(val));
prom_printf("OF stdout device is: %s\n", RELOC(of_stdout_device)); prom_printf("OF stdout device is: %s\n", RELOC(of_stdout_device));
prom_setprop(_prom->chosen, "linux,stdout-path", prom_setprop(_prom->chosen, "/chosen", "linux,stdout-path",
RELOC(of_stdout_device), strlen(RELOC(of_stdout_device))+1); path, strlen(path) + 1);
/* If it's a display, note it */ /* If it's a display, note it */
memset(type, 0, sizeof(type)); memset(type, 0, sizeof(type));
prom_getprop(val, "device_type", type, sizeof(type)); prom_getprop(val, "device_type", type, sizeof(type));
if (strcmp(type, RELOC("display")) == 0) if (strcmp(type, RELOC("display")) == 0)
prom_setprop(val, "linux,boot-display", NULL, 0); prom_setprop(val, path, "linux,boot-display", NULL, 0);
} }
static void __init prom_close_stdin(void) static void __init prom_close_stdin(void)
...@@ -1514,7 +1588,7 @@ static void __init prom_check_displays(void) ...@@ -1514,7 +1588,7 @@ static void __init prom_check_displays(void)
/* Success */ /* Success */
prom_printf("done\n"); prom_printf("done\n");
prom_setprop(node, "linux,opened", NULL, 0); prom_setprop(node, path, "linux,opened", NULL, 0);
/* Setup a usable color table when the appropriate /* Setup a usable color table when the appropriate
* method is available. Should update this to set-colors */ * method is available. Should update this to set-colors */
...@@ -1884,9 +1958,11 @@ static void __init fixup_device_tree(void) ...@@ -1884,9 +1958,11 @@ static void __init fixup_device_tree(void)
/* interrupt on this revision of u3 is number 0 and level */ /* interrupt on this revision of u3 is number 0 and level */
interrupts[0] = 0; interrupts[0] = 0;
interrupts[1] = 1; interrupts[1] = 1;
prom_setprop(i2c, "interrupts", &interrupts, sizeof(interrupts)); prom_setprop(i2c, "/u3@0,f8000000/i2c@f8001000", "interrupts",
&interrupts, sizeof(interrupts));
parent = (u32)mpic; parent = (u32)mpic;
prom_setprop(i2c, "interrupt-parent", &parent, sizeof(parent)); prom_setprop(i2c, "/u3@0,f8000000/i2c@f8001000", "interrupt-parent",
&parent, sizeof(parent));
#endif #endif
} }
...@@ -1922,11 +1998,11 @@ static void __init prom_check_initrd(unsigned long r3, unsigned long r4) ...@@ -1922,11 +1998,11 @@ static void __init prom_check_initrd(unsigned long r3, unsigned long r4)
RELOC(prom_initrd_end) = RELOC(prom_initrd_start) + r4; RELOC(prom_initrd_end) = RELOC(prom_initrd_start) + r4;
val = RELOC(prom_initrd_start); val = RELOC(prom_initrd_start);
prom_setprop(_prom->chosen, "linux,initrd-start", &val, prom_setprop(_prom->chosen, "/chosen", "linux,initrd-start",
sizeof(val)); &val, sizeof(val));
val = RELOC(prom_initrd_end); val = RELOC(prom_initrd_end);
prom_setprop(_prom->chosen, "linux,initrd-end", &val, prom_setprop(_prom->chosen, "/chosen", "linux,initrd-end",
sizeof(val)); &val, sizeof(val));
reserve_mem(RELOC(prom_initrd_start), reserve_mem(RELOC(prom_initrd_start),
RELOC(prom_initrd_end) - RELOC(prom_initrd_start)); RELOC(prom_initrd_end) - RELOC(prom_initrd_start));
...@@ -1969,14 +2045,15 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, ...@@ -1969,14 +2045,15 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
prom_init_client_services(pp); prom_init_client_services(pp);
/* /*
* Init prom stdout device * See if this OF is old enough that we need to do explicit maps
* and other workarounds
*/ */
prom_init_stdout(); prom_find_mmu();
/* /*
* See if this OF is old enough that we need to do explicit maps * Init prom stdout device
*/ */
prom_find_mmu(); prom_init_stdout();
/* /*
* Check for an initrd * Check for an initrd
...@@ -1989,14 +2066,15 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, ...@@ -1989,14 +2066,15 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
*/ */
RELOC(of_platform) = prom_find_machine_type(); RELOC(of_platform) = prom_find_machine_type();
getprop_rval = RELOC(of_platform); getprop_rval = RELOC(of_platform);
prom_setprop(_prom->chosen, "linux,platform", prom_setprop(_prom->chosen, "/chosen", "linux,platform",
&getprop_rval, sizeof(getprop_rval)); &getprop_rval, sizeof(getprop_rval));
#ifdef CONFIG_PPC_PSERIES #ifdef CONFIG_PPC_PSERIES
/* /*
* On pSeries, inform the firmware about our capabilities * On pSeries, inform the firmware about our capabilities
*/ */
if (RELOC(of_platform) & PLATFORM_PSERIES) if (RELOC(of_platform) == PLATFORM_PSERIES ||
RELOC(of_platform) == PLATFORM_PSERIES_LPAR)
prom_send_capabilities(); prom_send_capabilities();
#endif #endif
...@@ -2050,21 +2128,23 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, ...@@ -2050,21 +2128,23 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
* Fill in some infos for use by the kernel later on * Fill in some infos for use by the kernel later on
*/ */
if (RELOC(prom_memory_limit)) if (RELOC(prom_memory_limit))
prom_setprop(_prom->chosen, "linux,memory-limit", prom_setprop(_prom->chosen, "/chosen", "linux,memory-limit",
&RELOC(prom_memory_limit), &RELOC(prom_memory_limit),
sizeof(prom_memory_limit)); sizeof(prom_memory_limit));
#ifdef CONFIG_PPC64 #ifdef CONFIG_PPC64
if (RELOC(ppc64_iommu_off)) if (RELOC(ppc64_iommu_off))
prom_setprop(_prom->chosen, "linux,iommu-off", NULL, 0); prom_setprop(_prom->chosen, "/chosen", "linux,iommu-off",
NULL, 0);
if (RELOC(iommu_force_on)) if (RELOC(iommu_force_on))
prom_setprop(_prom->chosen, "linux,iommu-force-on", NULL, 0); prom_setprop(_prom->chosen, "/chosen", "linux,iommu-force-on",
NULL, 0);
if (RELOC(prom_tce_alloc_start)) { if (RELOC(prom_tce_alloc_start)) {
prom_setprop(_prom->chosen, "linux,tce-alloc-start", prom_setprop(_prom->chosen, "/chosen", "linux,tce-alloc-start",
&RELOC(prom_tce_alloc_start), &RELOC(prom_tce_alloc_start),
sizeof(prom_tce_alloc_start)); sizeof(prom_tce_alloc_start));
prom_setprop(_prom->chosen, "linux,tce-alloc-end", prom_setprop(_prom->chosen, "/chosen", "linux,tce-alloc-end",
&RELOC(prom_tce_alloc_end), &RELOC(prom_tce_alloc_end),
sizeof(prom_tce_alloc_end)); sizeof(prom_tce_alloc_end));
} }
...@@ -2081,7 +2161,12 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, ...@@ -2081,7 +2161,12 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
prom_printf("copying OF device tree ...\n"); prom_printf("copying OF device tree ...\n");
flatten_device_tree(); flatten_device_tree();
/* in case stdin is USB and still active on IBM machines... */ /*
* in case stdin is USB and still active on IBM machines...
* Unfortunately quiesce crashes on some powermacs if we have
* closed stdin already (in particular the powerbook 101).
*/
if (RELOC(of_platform) != PLATFORM_POWERMAC)
prom_close_stdin(); prom_close_stdin();
/* /*
......
...@@ -259,7 +259,7 @@ static int __init proc_rtas_init(void) ...@@ -259,7 +259,7 @@ static int __init proc_rtas_init(void)
{ {
struct proc_dir_entry *entry; struct proc_dir_entry *entry;
if (!(systemcfg->platform & PLATFORM_PSERIES)) if (_machine != PLATFORM_PSERIES && _machine != PLATFORM_PSERIES_LPAR)
return 1; return 1;
rtas_node = of_find_node_by_name(NULL, "rtas"); rtas_node = of_find_node_by_name(NULL, "rtas");
......
...@@ -29,9 +29,6 @@ ...@@ -29,9 +29,6 @@
#include <asm/delay.h> #include <asm/delay.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/lmb.h> #include <asm/lmb.h>
#ifdef CONFIG_PPC64
#include <asm/systemcfg.h>
#endif
struct rtas_t rtas = { struct rtas_t rtas = {
.lock = SPIN_LOCK_UNLOCKED .lock = SPIN_LOCK_UNLOCKED
...@@ -671,7 +668,7 @@ void __init rtas_initialize(void) ...@@ -671,7 +668,7 @@ void __init rtas_initialize(void)
* the stop-self token if any * the stop-self token if any
*/ */
#ifdef CONFIG_PPC64 #ifdef CONFIG_PPC64
if (systemcfg->platform == PLATFORM_PSERIES_LPAR) if (_machine == PLATFORM_PSERIES_LPAR)
rtas_region = min(lmb.rmo_size, RTAS_INSTANTIATE_MAX); rtas_region = min(lmb.rmo_size, RTAS_INSTANTIATE_MAX);
#endif #endif
rtas_rmo_buf = lmb_alloc_base(RTAS_RMOBUF_MAX, PAGE_SIZE, rtas_region); rtas_rmo_buf = lmb_alloc_base(RTAS_RMOBUF_MAX, PAGE_SIZE, rtas_region);
......
...@@ -47,7 +47,7 @@ static int write_pci_config; ...@@ -47,7 +47,7 @@ static int write_pci_config;
static int ibm_read_pci_config; static int ibm_read_pci_config;
static int ibm_write_pci_config; static int ibm_write_pci_config;
static int config_access_valid(struct pci_dn *dn, int where) static inline int config_access_valid(struct pci_dn *dn, int where)
{ {
if (where < 256) if (where < 256)
return 1; return 1;
...@@ -72,16 +72,14 @@ static int of_device_available(struct device_node * dn) ...@@ -72,16 +72,14 @@ static int of_device_available(struct device_node * dn)
return 0; return 0;
} }
static int rtas_read_config(struct device_node *dn, int where, int size, u32 *val) static int rtas_read_config(struct pci_dn *pdn, int where, int size, u32 *val)
{ {
int returnval = -1; int returnval = -1;
unsigned long buid, addr; unsigned long buid, addr;
int ret; int ret;
struct pci_dn *pdn;
if (!dn || !dn->data) if (!pdn)
return PCIBIOS_DEVICE_NOT_FOUND; return PCIBIOS_DEVICE_NOT_FOUND;
pdn = dn->data;
if (!config_access_valid(pdn, where)) if (!config_access_valid(pdn, where))
return PCIBIOS_BAD_REGISTER_NUMBER; return PCIBIOS_BAD_REGISTER_NUMBER;
...@@ -90,7 +88,7 @@ static int rtas_read_config(struct device_node *dn, int where, int size, u32 *va ...@@ -90,7 +88,7 @@ static int rtas_read_config(struct device_node *dn, int where, int size, u32 *va
buid = pdn->phb->buid; buid = pdn->phb->buid;
if (buid) { if (buid) {
ret = rtas_call(ibm_read_pci_config, 4, 2, &returnval, ret = rtas_call(ibm_read_pci_config, 4, 2, &returnval,
addr, buid >> 32, buid & 0xffffffff, size); addr, BUID_HI(buid), BUID_LO(buid), size);
} else { } else {
ret = rtas_call(read_pci_config, 2, 2, &returnval, addr, size); ret = rtas_call(read_pci_config, 2, 2, &returnval, addr, size);
} }
...@@ -100,7 +98,7 @@ static int rtas_read_config(struct device_node *dn, int where, int size, u32 *va ...@@ -100,7 +98,7 @@ static int rtas_read_config(struct device_node *dn, int where, int size, u32 *va
return PCIBIOS_DEVICE_NOT_FOUND; return PCIBIOS_DEVICE_NOT_FOUND;
if (returnval == EEH_IO_ERROR_VALUE(size) && if (returnval == EEH_IO_ERROR_VALUE(size) &&
eeh_dn_check_failure (dn, NULL)) eeh_dn_check_failure (pdn->node, NULL))
return PCIBIOS_DEVICE_NOT_FOUND; return PCIBIOS_DEVICE_NOT_FOUND;
return PCIBIOS_SUCCESSFUL; return PCIBIOS_SUCCESSFUL;
...@@ -118,23 +116,23 @@ static int rtas_pci_read_config(struct pci_bus *bus, ...@@ -118,23 +116,23 @@ static int rtas_pci_read_config(struct pci_bus *bus,
busdn = bus->sysdata; /* must be a phb */ busdn = bus->sysdata; /* must be a phb */
/* Search only direct children of the bus */ /* Search only direct children of the bus */
for (dn = busdn->child; dn; dn = dn->sibling) for (dn = busdn->child; dn; dn = dn->sibling) {
if (dn->data && PCI_DN(dn)->devfn == devfn struct pci_dn *pdn = PCI_DN(dn);
if (pdn && pdn->devfn == devfn
&& of_device_available(dn)) && of_device_available(dn))
return rtas_read_config(dn, where, size, val); return rtas_read_config(pdn, where, size, val);
}
return PCIBIOS_DEVICE_NOT_FOUND; return PCIBIOS_DEVICE_NOT_FOUND;
} }
int rtas_write_config(struct device_node *dn, int where, int size, u32 val) int rtas_write_config(struct pci_dn *pdn, int where, int size, u32 val)
{ {
unsigned long buid, addr; unsigned long buid, addr;
int ret; int ret;
struct pci_dn *pdn;
if (!dn || !dn->data) if (!pdn)
return PCIBIOS_DEVICE_NOT_FOUND; return PCIBIOS_DEVICE_NOT_FOUND;
pdn = dn->data;
if (!config_access_valid(pdn, where)) if (!config_access_valid(pdn, where))
return PCIBIOS_BAD_REGISTER_NUMBER; return PCIBIOS_BAD_REGISTER_NUMBER;
...@@ -142,7 +140,8 @@ int rtas_write_config(struct device_node *dn, int where, int size, u32 val) ...@@ -142,7 +140,8 @@ int rtas_write_config(struct device_node *dn, int where, int size, u32 val)
(pdn->devfn << 8) | (where & 0xff); (pdn->devfn << 8) | (where & 0xff);
buid = pdn->phb->buid; buid = pdn->phb->buid;
if (buid) { if (buid) {
ret = rtas_call(ibm_write_pci_config, 5, 1, NULL, addr, buid >> 32, buid & 0xffffffff, size, (ulong) val); ret = rtas_call(ibm_write_pci_config, 5, 1, NULL, addr,
BUID_HI(buid), BUID_LO(buid), size, (ulong) val);
} else { } else {
ret = rtas_call(write_pci_config, 3, 1, NULL, addr, size, (ulong)val); ret = rtas_call(write_pci_config, 3, 1, NULL, addr, size, (ulong)val);
} }
...@@ -165,10 +164,12 @@ static int rtas_pci_write_config(struct pci_bus *bus, ...@@ -165,10 +164,12 @@ static int rtas_pci_write_config(struct pci_bus *bus,
busdn = bus->sysdata; /* must be a phb */ busdn = bus->sysdata; /* must be a phb */
/* Search only direct children of the bus */ /* Search only direct children of the bus */
for (dn = busdn->child; dn; dn = dn->sibling) for (dn = busdn->child; dn; dn = dn->sibling) {
if (dn->data && PCI_DN(dn)->devfn == devfn struct pci_dn *pdn = PCI_DN(dn);
if (pdn && pdn->devfn == devfn
&& of_device_available(dn)) && of_device_available(dn))
return rtas_write_config(dn, where, size, val); return rtas_write_config(pdn, where, size, val);
}
return PCIBIOS_DEVICE_NOT_FOUND; return PCIBIOS_DEVICE_NOT_FOUND;
} }
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#include <asm/io.h> #include <asm/io.h>
#include <asm/prom.h> #include <asm/prom.h>
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/systemcfg.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <asm/smp.h> #include <asm/smp.h>
#include <asm/elf.h> #include <asm/elf.h>
...@@ -51,6 +52,9 @@ ...@@ -51,6 +52,9 @@
#include <asm/page.h> #include <asm/page.h>
#include <asm/mmu.h> #include <asm/mmu.h>
#include <asm/lmb.h> #include <asm/lmb.h>
#include <asm/xmon.h>
#include "setup.h"
#undef DEBUG #undef DEBUG
...@@ -60,6 +64,13 @@ ...@@ -60,6 +64,13 @@
#define DBG(fmt...) #define DBG(fmt...)
#endif #endif
#ifdef CONFIG_PPC_MULTIPLATFORM
int _machine = 0;
EXPORT_SYMBOL(_machine);
#endif
unsigned long klimit = (unsigned long) _end;
/* /*
* This still seems to be needed... -- paulus * This still seems to be needed... -- paulus
*/ */
...@@ -510,7 +521,7 @@ void __init smp_setup_cpu_maps(void) ...@@ -510,7 +521,7 @@ void __init smp_setup_cpu_maps(void)
* On pSeries LPAR, we need to know how many cpus * On pSeries LPAR, we need to know how many cpus
* could possibly be added to this partition. * could possibly be added to this partition.
*/ */
if (systemcfg->platform == PLATFORM_PSERIES_LPAR && if (_machine == PLATFORM_PSERIES_LPAR &&
(dn = of_find_node_by_path("/rtas"))) { (dn = of_find_node_by_path("/rtas"))) {
int num_addr_cell, num_size_cell, maxcpus; int num_addr_cell, num_size_cell, maxcpus;
unsigned int *ireg; unsigned int *ireg;
...@@ -555,7 +566,27 @@ void __init smp_setup_cpu_maps(void) ...@@ -555,7 +566,27 @@ void __init smp_setup_cpu_maps(void)
cpu_set(cpu ^ 0x1, cpu_sibling_map[cpu]); cpu_set(cpu ^ 0x1, cpu_sibling_map[cpu]);
} }
systemcfg->processorCount = num_present_cpus(); _systemcfg->processorCount = num_present_cpus();
#endif /* CONFIG_PPC64 */ #endif /* CONFIG_PPC64 */
} }
#endif /* CONFIG_SMP */ #endif /* CONFIG_SMP */
#ifdef CONFIG_XMON
static int __init early_xmon(char *p)
{
/* ensure xmon is enabled */
if (p) {
if (strncmp(p, "on", 2) == 0)
xmon_init(1);
if (strncmp(p, "off", 3) == 0)
xmon_init(0);
if (strncmp(p, "early", 5) != 0)
return 0;
}
xmon_init(1);
debugger(NULL);
return 0;
}
early_param("xmon", early_xmon);
#endif
#ifndef _POWERPC_KERNEL_SETUP_H
#define _POWERPC_KERNEL_SETUP_H
void check_for_initrd(void);
#endif /* _POWERPC_KERNEL_SETUP_H */
...@@ -40,6 +40,8 @@ ...@@ -40,6 +40,8 @@
#include <asm/xmon.h> #include <asm/xmon.h>
#include <asm/time.h> #include <asm/time.h>
#include "setup.h"
#define DBG(fmt...) #define DBG(fmt...)
#if defined CONFIG_KGDB #if defined CONFIG_KGDB
...@@ -70,8 +72,6 @@ unsigned int DMA_MODE_WRITE; ...@@ -70,8 +72,6 @@ unsigned int DMA_MODE_WRITE;
int have_of = 1; int have_of = 1;
#ifdef CONFIG_PPC_MULTIPLATFORM #ifdef CONFIG_PPC_MULTIPLATFORM
int _machine = 0;
extern void prep_init(void); extern void prep_init(void);
extern void pmac_init(void); extern void pmac_init(void);
extern void chrp_init(void); extern void chrp_init(void);
...@@ -279,7 +279,6 @@ arch_initcall(ppc_init); ...@@ -279,7 +279,6 @@ arch_initcall(ppc_init);
/* Warning, IO base is not yet inited */ /* Warning, IO base is not yet inited */
void __init setup_arch(char **cmdline_p) void __init setup_arch(char **cmdline_p)
{ {
extern char *klimit;
extern void do_init_bootmem(void); extern void do_init_bootmem(void);
/* so udelay does something sensible, assume <= 1000 bogomips */ /* so udelay does something sensible, assume <= 1000 bogomips */
...@@ -303,14 +302,9 @@ void __init setup_arch(char **cmdline_p) ...@@ -303,14 +302,9 @@ void __init setup_arch(char **cmdline_p)
pmac_feature_init(); /* New cool way */ pmac_feature_init(); /* New cool way */
#endif #endif
#ifdef CONFIG_XMON #ifdef CONFIG_XMON_DEFAULT
xmon_map_scc();
if (strstr(cmd_line, "xmon")) {
xmon_init(1); xmon_init(1);
debugger(NULL); #endif
}
#endif /* CONFIG_XMON */
if ( ppc_md.progress ) ppc_md.progress("setup_arch: enter", 0x3eab);
#if defined(CONFIG_KGDB) #if defined(CONFIG_KGDB)
if (ppc_md.kgdb_map_scc) if (ppc_md.kgdb_map_scc)
...@@ -343,7 +337,7 @@ void __init setup_arch(char **cmdline_p) ...@@ -343,7 +337,7 @@ void __init setup_arch(char **cmdline_p)
init_mm.start_code = PAGE_OFFSET; init_mm.start_code = PAGE_OFFSET;
init_mm.end_code = (unsigned long) _etext; init_mm.end_code = (unsigned long) _etext;
init_mm.end_data = (unsigned long) _edata; init_mm.end_data = (unsigned long) _edata;
init_mm.brk = (unsigned long) klimit; init_mm.brk = klimit;
/* Save unparsed command line copy for /proc/cmdline */ /* Save unparsed command line copy for /proc/cmdline */
strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE); strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE);
......
...@@ -61,6 +61,8 @@ ...@@ -61,6 +61,8 @@
#include <asm/xmon.h> #include <asm/xmon.h>
#include <asm/udbg.h> #include <asm/udbg.h>
#include "setup.h"
#ifdef DEBUG #ifdef DEBUG
#define DBG(fmt...) udbg_printf(fmt) #define DBG(fmt...) udbg_printf(fmt)
#else #else
...@@ -94,15 +96,6 @@ extern void udbg_init_maple_realmode(void); ...@@ -94,15 +96,6 @@ extern void udbg_init_maple_realmode(void);
do { udbg_putc = call_rtas_display_status_delay; } while(0) do { udbg_putc = call_rtas_display_status_delay; } while(0)
#endif #endif
/* extern void *stab; */
extern unsigned long klimit;
extern void mm_init_ppc64(void);
extern void stab_initialize(unsigned long stab);
extern void htab_initialize(void);
extern void early_init_devtree(void *flat_dt);
extern void unflatten_device_tree(void);
int have_of = 1; int have_of = 1;
int boot_cpuid = 0; int boot_cpuid = 0;
int boot_cpuid_phys = 0; int boot_cpuid_phys = 0;
...@@ -254,11 +247,10 @@ void __init early_setup(unsigned long dt_ptr) ...@@ -254,11 +247,10 @@ void __init early_setup(unsigned long dt_ptr)
* Iterate all ppc_md structures until we find the proper * Iterate all ppc_md structures until we find the proper
* one for the current machine type * one for the current machine type
*/ */
DBG("Probing machine type for platform %x...\n", DBG("Probing machine type for platform %x...\n", _machine);
systemcfg->platform);
for (mach = machines; *mach; mach++) { for (mach = machines; *mach; mach++) {
if ((*mach)->probe(systemcfg->platform)) if ((*mach)->probe(_machine))
break; break;
} }
/* What can we do if we didn't find ? */ /* What can we do if we didn't find ? */
...@@ -290,6 +282,28 @@ void __init early_setup(unsigned long dt_ptr) ...@@ -290,6 +282,28 @@ void __init early_setup(unsigned long dt_ptr)
DBG(" <- early_setup()\n"); DBG(" <- early_setup()\n");
} }
#ifdef CONFIG_SMP
void early_setup_secondary(void)
{
struct paca_struct *lpaca = get_paca();
/* Mark enabled in PACA */
lpaca->proc_enabled = 0;
/* Initialize hash table for that CPU */
htab_initialize_secondary();
/* Initialize STAB/SLB. We use a virtual address as it works
* in real mode on pSeries and we want a virutal address on
* iSeries anyway
*/
if (cpu_has_feature(CPU_FTR_SLB))
slb_initialize();
else
stab_initialize(lpaca->stab_addr);
}
#endif /* CONFIG_SMP */
#if defined(CONFIG_SMP) || defined(CONFIG_KEXEC) #if defined(CONFIG_SMP) || defined(CONFIG_KEXEC)
void smp_release_cpus(void) void smp_release_cpus(void)
...@@ -315,7 +329,8 @@ void smp_release_cpus(void) ...@@ -315,7 +329,8 @@ void smp_release_cpus(void)
#endif /* CONFIG_SMP || CONFIG_KEXEC */ #endif /* CONFIG_SMP || CONFIG_KEXEC */
/* /*
* Initialize some remaining members of the ppc64_caches and systemcfg structures * Initialize some remaining members of the ppc64_caches and systemcfg
* structures
* (at least until we get rid of them completely). This is mostly some * (at least until we get rid of them completely). This is mostly some
* cache informations about the CPU that will be used by cache flush * cache informations about the CPU that will be used by cache flush
* routines and/or provided to userland * routines and/or provided to userland
...@@ -340,7 +355,7 @@ static void __init initialize_cache_info(void) ...@@ -340,7 +355,7 @@ static void __init initialize_cache_info(void)
const char *dc, *ic; const char *dc, *ic;
/* Then read cache informations */ /* Then read cache informations */
if (systemcfg->platform == PLATFORM_POWERMAC) { if (_machine == PLATFORM_POWERMAC) {
dc = "d-cache-block-size"; dc = "d-cache-block-size";
ic = "i-cache-block-size"; ic = "i-cache-block-size";
} else { } else {
...@@ -360,8 +375,8 @@ static void __init initialize_cache_info(void) ...@@ -360,8 +375,8 @@ static void __init initialize_cache_info(void)
DBG("Argh, can't find dcache properties ! " DBG("Argh, can't find dcache properties ! "
"sizep: %p, lsizep: %p\n", sizep, lsizep); "sizep: %p, lsizep: %p\n", sizep, lsizep);
systemcfg->dcache_size = ppc64_caches.dsize = size; _systemcfg->dcache_size = ppc64_caches.dsize = size;
systemcfg->dcache_line_size = _systemcfg->dcache_line_size =
ppc64_caches.dline_size = lsize; ppc64_caches.dline_size = lsize;
ppc64_caches.log_dline_size = __ilog2(lsize); ppc64_caches.log_dline_size = __ilog2(lsize);
ppc64_caches.dlines_per_page = PAGE_SIZE / lsize; ppc64_caches.dlines_per_page = PAGE_SIZE / lsize;
...@@ -378,8 +393,8 @@ static void __init initialize_cache_info(void) ...@@ -378,8 +393,8 @@ static void __init initialize_cache_info(void)
DBG("Argh, can't find icache properties ! " DBG("Argh, can't find icache properties ! "
"sizep: %p, lsizep: %p\n", sizep, lsizep); "sizep: %p, lsizep: %p\n", sizep, lsizep);
systemcfg->icache_size = ppc64_caches.isize = size; _systemcfg->icache_size = ppc64_caches.isize = size;
systemcfg->icache_line_size = _systemcfg->icache_line_size =
ppc64_caches.iline_size = lsize; ppc64_caches.iline_size = lsize;
ppc64_caches.log_iline_size = __ilog2(lsize); ppc64_caches.log_iline_size = __ilog2(lsize);
ppc64_caches.ilines_per_page = PAGE_SIZE / lsize; ppc64_caches.ilines_per_page = PAGE_SIZE / lsize;
...@@ -387,10 +402,12 @@ static void __init initialize_cache_info(void) ...@@ -387,10 +402,12 @@ static void __init initialize_cache_info(void)
} }
/* Add an eye catcher and the systemcfg layout version number */ /* Add an eye catcher and the systemcfg layout version number */
strcpy(systemcfg->eye_catcher, "SYSTEMCFG:PPC64"); strcpy(_systemcfg->eye_catcher, "SYSTEMCFG:PPC64");
systemcfg->version.major = SYSTEMCFG_MAJOR; _systemcfg->version.major = SYSTEMCFG_MAJOR;
systemcfg->version.minor = SYSTEMCFG_MINOR; _systemcfg->version.minor = SYSTEMCFG_MINOR;
systemcfg->processor = mfspr(SPRN_PVR); _systemcfg->processor = mfspr(SPRN_PVR);
_systemcfg->platform = _machine;
_systemcfg->physicalMemorySize = lmb_phys_mem_size();
DBG(" <- initialize_cache_info()\n"); DBG(" <- initialize_cache_info()\n");
} }
...@@ -479,10 +496,10 @@ void __init setup_system(void) ...@@ -479,10 +496,10 @@ void __init setup_system(void)
printk("-----------------------------------------------------\n"); printk("-----------------------------------------------------\n");
printk("ppc64_pft_size = 0x%lx\n", ppc64_pft_size); printk("ppc64_pft_size = 0x%lx\n", ppc64_pft_size);
printk("ppc64_interrupt_controller = 0x%ld\n", ppc64_interrupt_controller); printk("ppc64_interrupt_controller = 0x%ld\n", ppc64_interrupt_controller);
printk("systemcfg = 0x%p\n", systemcfg); printk("systemcfg = 0x%p\n", _systemcfg);
printk("systemcfg->platform = 0x%x\n", systemcfg->platform); printk("systemcfg->platform = 0x%x\n", _systemcfg->platform);
printk("systemcfg->processorCount = 0x%lx\n", systemcfg->processorCount); printk("systemcfg->processorCount = 0x%lx\n", _systemcfg->processorCount);
printk("systemcfg->physicalMemorySize = 0x%lx\n", systemcfg->physicalMemorySize); printk("systemcfg->physicalMemorySize = 0x%lx\n", _systemcfg->physicalMemorySize);
printk("ppc64_caches.dcache_line_size = 0x%x\n", printk("ppc64_caches.dcache_line_size = 0x%x\n",
ppc64_caches.dline_size); ppc64_caches.dline_size);
printk("ppc64_caches.icache_line_size = 0x%x\n", printk("ppc64_caches.icache_line_size = 0x%x\n",
...@@ -564,12 +581,12 @@ void __init setup_syscall_map(void) ...@@ -564,12 +581,12 @@ void __init setup_syscall_map(void)
for (i = 0; i < __NR_syscalls; i++) { for (i = 0; i < __NR_syscalls; i++) {
if (sys_call_table[i*2] != sys_ni_syscall) { if (sys_call_table[i*2] != sys_ni_syscall) {
count64++; count64++;
systemcfg->syscall_map_64[i >> 5] |= _systemcfg->syscall_map_64[i >> 5] |=
0x80000000UL >> (i & 0x1f); 0x80000000UL >> (i & 0x1f);
} }
if (sys_call_table[i*2+1] != sys_ni_syscall) { if (sys_call_table[i*2+1] != sys_ni_syscall) {
count32++; count32++;
systemcfg->syscall_map_32[i >> 5] |= _systemcfg->syscall_map_32[i >> 5] |=
0x80000000UL >> (i & 0x1f); 0x80000000UL >> (i & 0x1f);
} }
} }
...@@ -858,26 +875,6 @@ int check_legacy_ioport(unsigned long base_port) ...@@ -858,26 +875,6 @@ int check_legacy_ioport(unsigned long base_port)
} }
EXPORT_SYMBOL(check_legacy_ioport); EXPORT_SYMBOL(check_legacy_ioport);
#ifdef CONFIG_XMON
static int __init early_xmon(char *p)
{
/* ensure xmon is enabled */
if (p) {
if (strncmp(p, "on", 2) == 0)
xmon_init(1);
if (strncmp(p, "off", 3) == 0)
xmon_init(0);
if (strncmp(p, "early", 5) != 0)
return 0;
}
xmon_init(1);
debugger(NULL);
return 0;
}
early_param("xmon", early_xmon);
#endif
void cpu_die(void) void cpu_die(void)
{ {
if (ppc_md.cpu_die) if (ppc_md.cpu_die)
......
...@@ -42,6 +42,7 @@ ...@@ -42,6 +42,7 @@
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
#include <asm/sigcontext.h>
#ifdef CONFIG_PPC64 #ifdef CONFIG_PPC64
#include "ppc32.h" #include "ppc32.h"
#include <asm/unistd.h> #include <asm/unistd.h>
......
...@@ -44,6 +44,7 @@ ...@@ -44,6 +44,7 @@
#include <asm/cputable.h> #include <asm/cputable.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/mpic.h> #include <asm/mpic.h>
#include <asm/systemcfg.h>
#ifdef CONFIG_PPC64 #ifdef CONFIG_PPC64
#include <asm/paca.h> #include <asm/paca.h>
#endif #endif
...@@ -368,9 +369,11 @@ int generic_cpu_disable(void) ...@@ -368,9 +369,11 @@ int generic_cpu_disable(void)
if (cpu == boot_cpuid) if (cpu == boot_cpuid)
return -EBUSY; return -EBUSY;
systemcfg->processorCount--;
cpu_clear(cpu, cpu_online_map); cpu_clear(cpu, cpu_online_map);
#ifdef CONFIG_PPC64
_systemcfg->processorCount--;
fixup_irqs(cpu_online_map); fixup_irqs(cpu_online_map);
#endif
return 0; return 0;
} }
...@@ -388,9 +391,11 @@ int generic_cpu_enable(unsigned int cpu) ...@@ -388,9 +391,11 @@ int generic_cpu_enable(unsigned int cpu)
while (!cpu_online(cpu)) while (!cpu_online(cpu))
cpu_relax(); cpu_relax();
#ifdef CONFIG_PPC64
fixup_irqs(cpu_online_map); fixup_irqs(cpu_online_map);
/* counter the irq disable in fixup_irqs */ /* counter the irq disable in fixup_irqs */
local_irq_enable(); local_irq_enable();
#endif
return 0; return 0;
} }
...@@ -419,7 +424,9 @@ void generic_mach_cpu_die(void) ...@@ -419,7 +424,9 @@ void generic_mach_cpu_die(void)
while (__get_cpu_var(cpu_state) != CPU_UP_PREPARE) while (__get_cpu_var(cpu_state) != CPU_UP_PREPARE)
cpu_relax(); cpu_relax();
#ifdef CONFIG_PPC64
flush_tlb_pending(); flush_tlb_pending();
#endif
cpu_set(cpu, cpu_online_map); cpu_set(cpu, cpu_online_map);
local_irq_enable(); local_irq_enable();
} }
......
...@@ -52,7 +52,6 @@ ...@@ -52,7 +52,6 @@
#include <asm/semaphore.h> #include <asm/semaphore.h>
#include <asm/time.h> #include <asm/time.h>
#include <asm/mmu_context.h> #include <asm/mmu_context.h>
#include <asm/systemcfg.h>
#include <asm/ppc-pci.h> #include <asm/ppc-pci.h>
/* readdir & getdents */ /* readdir & getdents */
......
...@@ -271,13 +271,13 @@ static inline void update_gtod(u64 new_tb_stamp, u64 new_stamp_xsec, ...@@ -271,13 +271,13 @@ static inline void update_gtod(u64 new_tb_stamp, u64 new_stamp_xsec,
* tb_to_xs and stamp_xsec values are consistent. If not, then it * tb_to_xs and stamp_xsec values are consistent. If not, then it
* loops back and reads them again until this criteria is met. * loops back and reads them again until this criteria is met.
*/ */
++(systemcfg->tb_update_count); ++(_systemcfg->tb_update_count);
smp_wmb(); smp_wmb();
systemcfg->tb_orig_stamp = new_tb_stamp; _systemcfg->tb_orig_stamp = new_tb_stamp;
systemcfg->stamp_xsec = new_stamp_xsec; _systemcfg->stamp_xsec = new_stamp_xsec;
systemcfg->tb_to_xs = new_tb_to_xs; _systemcfg->tb_to_xs = new_tb_to_xs;
smp_wmb(); smp_wmb();
++(systemcfg->tb_update_count); ++(_systemcfg->tb_update_count);
#endif #endif
} }
...@@ -357,8 +357,9 @@ static void iSeries_tb_recal(void) ...@@ -357,8 +357,9 @@ static void iSeries_tb_recal(void)
do_gtod.tb_ticks_per_sec = tb_ticks_per_sec; do_gtod.tb_ticks_per_sec = tb_ticks_per_sec;
tb_to_xs = divres.result_low; tb_to_xs = divres.result_low;
do_gtod.varp->tb_to_xs = tb_to_xs; do_gtod.varp->tb_to_xs = tb_to_xs;
systemcfg->tb_ticks_per_sec = tb_ticks_per_sec; _systemcfg->tb_ticks_per_sec =
systemcfg->tb_to_xs = tb_to_xs; tb_ticks_per_sec;
_systemcfg->tb_to_xs = tb_to_xs;
} }
else { else {
printk( "Titan recalibrate: FAILED (difference > 4 percent)\n" printk( "Titan recalibrate: FAILED (difference > 4 percent)\n"
...@@ -483,6 +484,8 @@ void __init smp_space_timers(unsigned int max_cpus) ...@@ -483,6 +484,8 @@ void __init smp_space_timers(unsigned int max_cpus)
unsigned long offset = tb_ticks_per_jiffy / max_cpus; unsigned long offset = tb_ticks_per_jiffy / max_cpus;
unsigned long previous_tb = per_cpu(last_jiffy, boot_cpuid); unsigned long previous_tb = per_cpu(last_jiffy, boot_cpuid);
/* make sure tb > per_cpu(last_jiffy, cpu) for all cpus always */
previous_tb -= tb_ticks_per_jiffy;
for_each_cpu(i) { for_each_cpu(i) {
if (i != boot_cpuid) { if (i != boot_cpuid) {
previous_tb += offset; previous_tb += offset;
...@@ -559,8 +562,8 @@ int do_settimeofday(struct timespec *tv) ...@@ -559,8 +562,8 @@ int do_settimeofday(struct timespec *tv)
update_gtod(tb_last_jiffy, new_xsec, do_gtod.varp->tb_to_xs); update_gtod(tb_last_jiffy, new_xsec, do_gtod.varp->tb_to_xs);
#ifdef CONFIG_PPC64 #ifdef CONFIG_PPC64
systemcfg->tz_minuteswest = sys_tz.tz_minuteswest; _systemcfg->tz_minuteswest = sys_tz.tz_minuteswest;
systemcfg->tz_dsttime = sys_tz.tz_dsttime; _systemcfg->tz_dsttime = sys_tz.tz_dsttime;
#endif #endif
write_sequnlock_irqrestore(&xtime_lock, flags); write_sequnlock_irqrestore(&xtime_lock, flags);
...@@ -711,11 +714,11 @@ void __init time_init(void) ...@@ -711,11 +714,11 @@ void __init time_init(void)
do_gtod.varp->tb_to_xs = tb_to_xs; do_gtod.varp->tb_to_xs = tb_to_xs;
do_gtod.tb_to_us = tb_to_us; do_gtod.tb_to_us = tb_to_us;
#ifdef CONFIG_PPC64 #ifdef CONFIG_PPC64
systemcfg->tb_orig_stamp = tb_last_jiffy; _systemcfg->tb_orig_stamp = tb_last_jiffy;
systemcfg->tb_update_count = 0; _systemcfg->tb_update_count = 0;
systemcfg->tb_ticks_per_sec = tb_ticks_per_sec; _systemcfg->tb_ticks_per_sec = tb_ticks_per_sec;
systemcfg->stamp_xsec = xtime.tv_sec * XSEC_PER_SEC; _systemcfg->stamp_xsec = xtime.tv_sec * XSEC_PER_SEC;
systemcfg->tb_to_xs = tb_to_xs; _systemcfg->tb_to_xs = tb_to_xs;
#endif #endif
time_freq = 0; time_freq = 0;
......
...@@ -129,7 +129,7 @@ int die(const char *str, struct pt_regs *regs, long err) ...@@ -129,7 +129,7 @@ int die(const char *str, struct pt_regs *regs, long err)
nl = 1; nl = 1;
#endif #endif
#ifdef CONFIG_PPC64 #ifdef CONFIG_PPC64
switch (systemcfg->platform) { switch (_machine) {
case PLATFORM_PSERIES: case PLATFORM_PSERIES:
printk("PSERIES "); printk("PSERIES ");
nl = 1; nl = 1;
......
...@@ -41,7 +41,7 @@ unsigned long find_next_bit(const unsigned long *addr, unsigned long size, ...@@ -41,7 +41,7 @@ unsigned long find_next_bit(const unsigned long *addr, unsigned long size,
tmp = *p; tmp = *p;
found_first: found_first:
tmp &= (~0UL >> (64 - size)); tmp &= (~0UL >> (BITS_PER_LONG - size));
if (tmp == 0UL) /* Are any bits set? */ if (tmp == 0UL) /* Are any bits set? */
return result + size; /* Nope. */ return result + size; /* Nope. */
found_middle: found_middle:
......
...@@ -84,10 +84,11 @@ ...@@ -84,10 +84,11 @@
extern unsigned long dart_tablebase; extern unsigned long dart_tablebase;
#endif /* CONFIG_U3_DART */ #endif /* CONFIG_U3_DART */
static unsigned long _SDR1;
struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT];
hpte_t *htab_address; hpte_t *htab_address;
unsigned long htab_hash_mask; unsigned long htab_hash_mask;
unsigned long _SDR1;
struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT];
int mmu_linear_psize = MMU_PAGE_4K; int mmu_linear_psize = MMU_PAGE_4K;
int mmu_virtual_psize = MMU_PAGE_4K; int mmu_virtual_psize = MMU_PAGE_4K;
#ifdef CONFIG_HUGETLB_PAGE #ifdef CONFIG_HUGETLB_PAGE
...@@ -165,7 +166,7 @@ int htab_bolt_mapping(unsigned long vstart, unsigned long vend, ...@@ -165,7 +166,7 @@ int htab_bolt_mapping(unsigned long vstart, unsigned long vend,
* normal insert callback here. * normal insert callback here.
*/ */
#ifdef CONFIG_PPC_ISERIES #ifdef CONFIG_PPC_ISERIES
if (systemcfg->platform == PLATFORM_ISERIES_LPAR) if (_machine == PLATFORM_ISERIES_LPAR)
ret = iSeries_hpte_insert(hpteg, va, ret = iSeries_hpte_insert(hpteg, va,
virt_to_abs(paddr), virt_to_abs(paddr),
tmp_mode, tmp_mode,
...@@ -174,7 +175,7 @@ int htab_bolt_mapping(unsigned long vstart, unsigned long vend, ...@@ -174,7 +175,7 @@ int htab_bolt_mapping(unsigned long vstart, unsigned long vend,
else else
#endif #endif
#ifdef CONFIG_PPC_PSERIES #ifdef CONFIG_PPC_PSERIES
if (systemcfg->platform & PLATFORM_LPAR) if (_machine & PLATFORM_LPAR)
ret = pSeries_lpar_hpte_insert(hpteg, va, ret = pSeries_lpar_hpte_insert(hpteg, va,
virt_to_abs(paddr), virt_to_abs(paddr),
tmp_mode, tmp_mode,
...@@ -293,7 +294,7 @@ static void __init htab_init_page_sizes(void) ...@@ -293,7 +294,7 @@ static void __init htab_init_page_sizes(void)
* Not in the device-tree, let's fallback on known size * Not in the device-tree, let's fallback on known size
* list for 16M capable GP & GR * list for 16M capable GP & GR
*/ */
if ((systemcfg->platform != PLATFORM_ISERIES_LPAR) && if ((_machine != PLATFORM_ISERIES_LPAR) &&
cpu_has_feature(CPU_FTR_16M_PAGE)) cpu_has_feature(CPU_FTR_16M_PAGE))
memcpy(mmu_psize_defs, mmu_psize_defaults_gp, memcpy(mmu_psize_defs, mmu_psize_defaults_gp,
sizeof(mmu_psize_defaults_gp)); sizeof(mmu_psize_defaults_gp));
...@@ -364,7 +365,7 @@ static int __init htab_dt_scan_pftsize(unsigned long node, ...@@ -364,7 +365,7 @@ static int __init htab_dt_scan_pftsize(unsigned long node,
static unsigned long __init htab_get_table_size(void) static unsigned long __init htab_get_table_size(void)
{ {
unsigned long rnd_mem_size, pteg_count; unsigned long mem_size, rnd_mem_size, pteg_count;
/* If hash size isn't already provided by the platform, we try to /* If hash size isn't already provided by the platform, we try to
* retreive it from the device-tree. If it's not there neither, we * retreive it from the device-tree. If it's not there neither, we
...@@ -376,8 +377,9 @@ static unsigned long __init htab_get_table_size(void) ...@@ -376,8 +377,9 @@ static unsigned long __init htab_get_table_size(void)
return 1UL << ppc64_pft_size; return 1UL << ppc64_pft_size;
/* round mem_size up to next power of 2 */ /* round mem_size up to next power of 2 */
rnd_mem_size = 1UL << __ilog2(systemcfg->physicalMemorySize); mem_size = lmb_phys_mem_size();
if (rnd_mem_size < systemcfg->physicalMemorySize) rnd_mem_size = 1UL << __ilog2(mem_size);
if (rnd_mem_size < mem_size)
rnd_mem_size <<= 1; rnd_mem_size <<= 1;
/* # pages / 2 */ /* # pages / 2 */
...@@ -386,6 +388,15 @@ static unsigned long __init htab_get_table_size(void) ...@@ -386,6 +388,15 @@ static unsigned long __init htab_get_table_size(void)
return pteg_count << 7; return pteg_count << 7;
} }
#ifdef CONFIG_MEMORY_HOTPLUG
void create_section_mapping(unsigned long start, unsigned long end)
{
BUG_ON(htab_bolt_mapping(start, end, start,
_PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_COHERENT | PP_RWXX,
mmu_linear_psize));
}
#endif /* CONFIG_MEMORY_HOTPLUG */
void __init htab_initialize(void) void __init htab_initialize(void)
{ {
unsigned long table, htab_size_bytes; unsigned long table, htab_size_bytes;
...@@ -410,7 +421,7 @@ void __init htab_initialize(void) ...@@ -410,7 +421,7 @@ void __init htab_initialize(void)
htab_hash_mask = pteg_count - 1; htab_hash_mask = pteg_count - 1;
if (systemcfg->platform & PLATFORM_LPAR) { if (platform_is_lpar()) {
/* Using a hypervisor which owns the htab */ /* Using a hypervisor which owns the htab */
htab_address = NULL; htab_address = NULL;
_SDR1 = 0; _SDR1 = 0;
...@@ -431,6 +442,9 @@ void __init htab_initialize(void) ...@@ -431,6 +442,9 @@ void __init htab_initialize(void)
/* Initialize the HPT with no entries */ /* Initialize the HPT with no entries */
memset((void *)table, 0, htab_size_bytes); memset((void *)table, 0, htab_size_bytes);
/* Set SDR1 */
mtspr(SPRN_SDR1, _SDR1);
} }
mode_rw = _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_COHERENT | PP_RWXX; mode_rw = _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_COHERENT | PP_RWXX;
...@@ -500,6 +514,12 @@ void __init htab_initialize(void) ...@@ -500,6 +514,12 @@ void __init htab_initialize(void)
#undef KB #undef KB
#undef MB #undef MB
void __init htab_initialize_secondary(void)
{
if (!platform_is_lpar())
mtspr(SPRN_SDR1, _SDR1);
}
/* /*
* Called by asm hashtable.S for doing lazy icache flush * Called by asm hashtable.S for doing lazy icache flush
*/ */
......
...@@ -84,9 +84,6 @@ void MMU_init(void); ...@@ -84,9 +84,6 @@ void MMU_init(void);
/* XXX should be in current.h -- paulus */ /* XXX should be in current.h -- paulus */
extern struct task_struct *current_set[NR_CPUS]; extern struct task_struct *current_set[NR_CPUS];
char *klimit = _end;
struct device_node *memory_node;
extern int init_bootmem_done; extern int init_bootmem_done;
/* /*
......
...@@ -20,6 +20,8 @@ ...@@ -20,6 +20,8 @@
* *
*/ */
#undef DEBUG
#include <linux/config.h> #include <linux/config.h>
#include <linux/signal.h> #include <linux/signal.h>
#include <linux/sched.h> #include <linux/sched.h>
...@@ -64,6 +66,12 @@ ...@@ -64,6 +66,12 @@
#include <asm/vdso.h> #include <asm/vdso.h>
#include <asm/imalloc.h> #include <asm/imalloc.h>
#ifdef DEBUG
#define DBG(fmt...) printk(fmt)
#else
#define DBG(fmt...)
#endif
#if PGTABLE_RANGE > USER_VSID_RANGE #if PGTABLE_RANGE > USER_VSID_RANGE
#warning Limited user VSID range means pagetable space is wasted #warning Limited user VSID range means pagetable space is wasted
#endif #endif
...@@ -72,8 +80,6 @@ ...@@ -72,8 +80,6 @@
#warning TASK_SIZE is smaller than it needs to be. #warning TASK_SIZE is smaller than it needs to be.
#endif #endif
unsigned long klimit = (unsigned long)_end;
/* max amount of RAM to use */ /* max amount of RAM to use */
unsigned long __max_memory; unsigned long __max_memory;
...@@ -188,14 +194,14 @@ static void zero_ctor(void *addr, kmem_cache_t *cache, unsigned long flags) ...@@ -188,14 +194,14 @@ static void zero_ctor(void *addr, kmem_cache_t *cache, unsigned long flags)
} }
#ifdef CONFIG_PPC_64K_PAGES #ifdef CONFIG_PPC_64K_PAGES
static const int pgtable_cache_size[2] = { static const unsigned int pgtable_cache_size[3] = {
PTE_TABLE_SIZE, PGD_TABLE_SIZE PTE_TABLE_SIZE, PMD_TABLE_SIZE, PGD_TABLE_SIZE
}; };
static const char *pgtable_cache_name[ARRAY_SIZE(pgtable_cache_size)] = { static const char *pgtable_cache_name[ARRAY_SIZE(pgtable_cache_size)] = {
"pte_pmd_cache", "pgd_cache", "pte_pmd_cache", "pmd_cache", "pgd_cache",
}; };
#else #else
static const int pgtable_cache_size[2] = { static const unsigned int pgtable_cache_size[2] = {
PTE_TABLE_SIZE, PMD_TABLE_SIZE PTE_TABLE_SIZE, PMD_TABLE_SIZE
}; };
static const char *pgtable_cache_name[ARRAY_SIZE(pgtable_cache_size)] = { static const char *pgtable_cache_name[ARRAY_SIZE(pgtable_cache_size)] = {
...@@ -213,6 +219,8 @@ void pgtable_cache_init(void) ...@@ -213,6 +219,8 @@ void pgtable_cache_init(void)
int size = pgtable_cache_size[i]; int size = pgtable_cache_size[i];
const char *name = pgtable_cache_name[i]; const char *name = pgtable_cache_name[i];
DBG("Allocating page table cache %s (#%d) "
"for size: %08x...\n", name, i, size);
pgtable_cache[i] = kmem_cache_create(name, pgtable_cache[i] = kmem_cache_create(name,
size, size, size, size,
SLAB_HWCACHE_ALIGN | SLAB_HWCACHE_ALIGN |
......
...@@ -110,6 +110,7 @@ EXPORT_SYMBOL(phys_mem_access_prot); ...@@ -110,6 +110,7 @@ EXPORT_SYMBOL(phys_mem_access_prot);
void online_page(struct page *page) void online_page(struct page *page)
{ {
ClearPageReserved(page); ClearPageReserved(page);
set_page_count(page, 0);
free_cold_page(page); free_cold_page(page);
totalram_pages++; totalram_pages++;
num_physpages++; num_physpages++;
...@@ -127,6 +128,9 @@ int __devinit add_memory(u64 start, u64 size) ...@@ -127,6 +128,9 @@ int __devinit add_memory(u64 start, u64 size)
unsigned long start_pfn = start >> PAGE_SHIFT; unsigned long start_pfn = start >> PAGE_SHIFT;
unsigned long nr_pages = size >> PAGE_SHIFT; unsigned long nr_pages = size >> PAGE_SHIFT;
start += KERNELBASE;
create_section_mapping(start, start + size);
/* this should work for most non-highmem platforms */ /* this should work for most non-highmem platforms */
zone = pgdata->node_zones; zone = pgdata->node_zones;
......
...@@ -122,8 +122,11 @@ static int map_io_page(unsigned long ea, unsigned long pa, int flags) ...@@ -122,8 +122,11 @@ static int map_io_page(unsigned long ea, unsigned long pa, int flags)
* *
*/ */
if (htab_bolt_mapping(ea, ea + PAGE_SIZE, pa, flags, if (htab_bolt_mapping(ea, ea + PAGE_SIZE, pa, flags,
mmu_virtual_psize)) mmu_virtual_psize)) {
panic("Can't map bolted IO mapping"); printk(KERN_ERR "Failed to do bolted mapping IO "
"memory at %016lx !\n", pa);
return -ENOMEM;
}
} }
return 0; return 0;
} }
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include <asm/cputable.h> #include <asm/cputable.h>
#include <asm/lmb.h> #include <asm/lmb.h>
#include <asm/abs_addr.h> #include <asm/abs_addr.h>
#include <asm/firmware.h>
struct stab_entry { struct stab_entry {
unsigned long esid_data; unsigned long esid_data;
...@@ -256,7 +257,7 @@ void stabs_alloc(void) ...@@ -256,7 +257,7 @@ void stabs_alloc(void)
paca[cpu].stab_addr = newstab; paca[cpu].stab_addr = newstab;
paca[cpu].stab_real = virt_to_abs(newstab); paca[cpu].stab_real = virt_to_abs(newstab);
printk(KERN_DEBUG "Segment table for CPU %d at 0x%lx " printk(KERN_INFO "Segment table for CPU %d at 0x%lx "
"virtual, 0x%lx absolute\n", "virtual, 0x%lx absolute\n",
cpu, paca[cpu].stab_addr, paca[cpu].stab_real); cpu, paca[cpu].stab_addr, paca[cpu].stab_real);
} }
...@@ -270,10 +271,28 @@ void stabs_alloc(void) ...@@ -270,10 +271,28 @@ void stabs_alloc(void)
void stab_initialize(unsigned long stab) void stab_initialize(unsigned long stab)
{ {
unsigned long vsid = get_kernel_vsid(KERNELBASE); unsigned long vsid = get_kernel_vsid(KERNELBASE);
unsigned long stabreal;
asm volatile("isync; slbia; isync":::"memory"); asm volatile("isync; slbia; isync":::"memory");
make_ste(stab, GET_ESID(KERNELBASE), vsid); make_ste(stab, GET_ESID(KERNELBASE), vsid);
/* Order update */ /* Order update */
asm volatile("sync":::"memory"); asm volatile("sync":::"memory");
/* Set ASR */
stabreal = get_paca()->stab_real | 0x1ul;
#ifdef CONFIG_PPC_ISERIES
if (firmware_has_feature(FW_FEATURE_ISERIES)) {
HvCall1(HvCallBaseSetASR, stabreal);
return;
}
#endif /* CONFIG_PPC_ISERIES */
#ifdef CONFIG_PPC_PSERIES
if (platform_is_lpar()) {
plpar_hcall_norets(H_SET_ASR, stabreal);
return;
}
#endif
mtspr(SPRN_ASR, stabreal);
} }
...@@ -233,8 +233,7 @@ static unsigned long get_pc(struct pt_regs *regs) ...@@ -233,8 +233,7 @@ static unsigned long get_pc(struct pt_regs *regs)
mmcra = mfspr(SPRN_MMCRA); mmcra = mfspr(SPRN_MMCRA);
/* Were we in the hypervisor? */ /* Were we in the hypervisor? */
if ((systemcfg->platform == PLATFORM_PSERIES_LPAR) && if (platform_is_lpar() && (mmcra & MMCRA_SIHV))
(mmcra & MMCRA_SIHV))
/* function descriptor madness */ /* function descriptor madness */
return *((unsigned long *)hypervisor_bucket); return *((unsigned long *)hypervisor_bucket);
......
...@@ -361,7 +361,9 @@ static void __init chrp_find_openpic(void) ...@@ -361,7 +361,9 @@ static void __init chrp_find_openpic(void)
printk(KERN_INFO "OpenPIC at %lx\n", opaddr); printk(KERN_INFO "OpenPIC at %lx\n", opaddr);
irq_count = NR_IRQS - NUM_ISA_INTERRUPTS - 4; /* leave room for IPIs */ irq_count = NR_IRQS - NUM_ISA_INTERRUPTS - 4; /* leave room for IPIs */
prom_get_irq_senses(init_senses, NUM_8259_INTERRUPTS, NR_IRQS - 4); prom_get_irq_senses(init_senses, NUM_ISA_INTERRUPTS, NR_IRQS - 4);
/* i8259 cascade is always positive level */
init_senses[0] = IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE;
iranges = (unsigned int *) get_property(np, "interrupt-ranges", &len); iranges = (unsigned int *) get_property(np, "interrupt-ranges", &len);
if (iranges == NULL) if (iranges == NULL)
......
...@@ -103,6 +103,9 @@ static void intReceived(struct XmPciLpEvent *eventParm, ...@@ -103,6 +103,9 @@ static void intReceived(struct XmPciLpEvent *eventParm,
struct pt_regs *regsParm) struct pt_regs *regsParm)
{ {
int irq; int irq;
#ifdef CONFIG_IRQSTACKS
struct thread_info *curtp, *irqtp;
#endif
++Pci_Interrupt_Count; ++Pci_Interrupt_Count;
...@@ -110,7 +113,20 @@ static void intReceived(struct XmPciLpEvent *eventParm, ...@@ -110,7 +113,20 @@ static void intReceived(struct XmPciLpEvent *eventParm,
case XmPciLpEvent_SlotInterrupt: case XmPciLpEvent_SlotInterrupt:
irq = eventParm->hvLpEvent.xCorrelationToken; irq = eventParm->hvLpEvent.xCorrelationToken;
/* Dispatch the interrupt handlers for this irq */ /* Dispatch the interrupt handlers for this irq */
ppc_irq_dispatch_handler(regsParm, irq); #ifdef CONFIG_IRQSTACKS
/* Switch to the irq stack to handle this */
curtp = current_thread_info();
irqtp = hardirq_ctx[smp_processor_id()];
if (curtp != irqtp) {
irqtp->task = curtp->task;
irqtp->flags = 0;
call___do_IRQ(irq, regsParm, irqtp);
irqtp->task = NULL;
if (irqtp->flags)
set_bits(irqtp->flags, &curtp->flags);
} else
#endif
__do_IRQ(irq, regsParm);
HvCallPci_eoi(eventParm->eventData.slotInterrupt.busNumber, HvCallPci_eoi(eventParm->eventData.slotInterrupt.busNumber,
eventParm->eventData.slotInterrupt.subBusNumber, eventParm->eventData.slotInterrupt.subBusNumber,
eventParm->eventData.slotInterrupt.deviceId); eventParm->eventData.slotInterrupt.deviceId);
...@@ -310,10 +326,8 @@ static void iSeries_disable_IRQ(unsigned int irq) ...@@ -310,10 +326,8 @@ static void iSeries_disable_IRQ(unsigned int irq)
} }
/* /*
* Need to define this so ppc_irq_dispatch_handler will NOT call * This does nothing because there is not enough information
* enable_IRQ at the end of interrupt handling. However, this does * provided to do the EOI HvCall. This is done by XmPciLpEvent.c
* nothing because there is not enough information provided to do
* the EOI HvCall. This is done by XmPciLpEvent.c
*/ */
static void iSeries_end_IRQ(unsigned int irq) static void iSeries_end_IRQ(unsigned int irq)
{ {
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/asm-offsets.h> #include <asm/asm-offsets.h>
#include <asm/ppc_asm.h>
.text .text
......
...@@ -39,7 +39,8 @@ ...@@ -39,7 +39,8 @@
#include <asm/sections.h> #include <asm/sections.h>
#include <asm/iommu.h> #include <asm/iommu.h>
#include <asm/firmware.h> #include <asm/firmware.h>
#include <asm/systemcfg.h>
#include <asm/system.h>
#include <asm/time.h> #include <asm/time.h>
#include <asm/paca.h> #include <asm/paca.h>
#include <asm/cache.h> #include <asm/cache.h>
...@@ -71,7 +72,7 @@ extern void hvlog(char *fmt, ...); ...@@ -71,7 +72,7 @@ extern void hvlog(char *fmt, ...);
#endif #endif
/* Function Prototypes */ /* Function Prototypes */
static void build_iSeries_Memory_Map(void); static unsigned long build_iSeries_Memory_Map(void);
static void iseries_shared_idle(void); static void iseries_shared_idle(void);
static void iseries_dedicated_idle(void); static void iseries_dedicated_idle(void);
#ifdef CONFIG_PCI #ifdef CONFIG_PCI
...@@ -84,7 +85,6 @@ static void iSeries_pci_final_fixup(void) { } ...@@ -84,7 +85,6 @@ static void iSeries_pci_final_fixup(void) { }
int piranha_simulator; int piranha_simulator;
extern int rd_size; /* Defined in drivers/block/rd.c */ extern int rd_size; /* Defined in drivers/block/rd.c */
extern unsigned long klimit;
extern unsigned long embedded_sysmap_start; extern unsigned long embedded_sysmap_start;
extern unsigned long embedded_sysmap_end; extern unsigned long embedded_sysmap_end;
...@@ -403,9 +403,11 @@ void mschunks_alloc(unsigned long num_chunks) ...@@ -403,9 +403,11 @@ void mschunks_alloc(unsigned long num_chunks)
* a table used to translate Linux's physical addresses to these * a table used to translate Linux's physical addresses to these
* absolute addresses. Absolute addresses are needed when * absolute addresses. Absolute addresses are needed when
* communicating with the hypervisor (e.g. to build HPT entries) * communicating with the hypervisor (e.g. to build HPT entries)
*
* Returns the physical memory size
*/ */
static void __init build_iSeries_Memory_Map(void) static unsigned long __init build_iSeries_Memory_Map(void)
{ {
u32 loadAreaFirstChunk, loadAreaLastChunk, loadAreaSize; u32 loadAreaFirstChunk, loadAreaLastChunk, loadAreaSize;
u32 nextPhysChunk; u32 nextPhysChunk;
...@@ -538,7 +540,7 @@ static void __init build_iSeries_Memory_Map(void) ...@@ -538,7 +540,7 @@ static void __init build_iSeries_Memory_Map(void)
* which should be equal to * which should be equal to
* nextPhysChunk * nextPhysChunk
*/ */
systemcfg->physicalMemorySize = chunk_to_addr(nextPhysChunk); return chunk_to_addr(nextPhysChunk);
} }
/* /*
...@@ -564,8 +566,8 @@ static void __init iSeries_setup_arch(void) ...@@ -564,8 +566,8 @@ static void __init iSeries_setup_arch(void)
printk("Max physical processors = %d\n", printk("Max physical processors = %d\n",
itVpdAreas.xSlicMaxPhysicalProcs); itVpdAreas.xSlicMaxPhysicalProcs);
systemcfg->processor = xIoHriProcessorVpd[procIx].xPVR; _systemcfg->processor = xIoHriProcessorVpd[procIx].xPVR;
printk("Processor version = %x\n", systemcfg->processor); printk("Processor version = %x\n", _systemcfg->processor);
} }
static void iSeries_show_cpuinfo(struct seq_file *m) static void iSeries_show_cpuinfo(struct seq_file *m)
...@@ -702,7 +704,6 @@ static void iseries_shared_idle(void) ...@@ -702,7 +704,6 @@ static void iseries_shared_idle(void)
static void iseries_dedicated_idle(void) static void iseries_dedicated_idle(void)
{ {
long oldval;
set_thread_flag(TIF_POLLING_NRFLAG); set_thread_flag(TIF_POLLING_NRFLAG);
while (1) { while (1) {
...@@ -929,7 +930,7 @@ void dt_cpus(struct iseries_flat_dt *dt) ...@@ -929,7 +930,7 @@ void dt_cpus(struct iseries_flat_dt *dt)
dt_end_node(dt); dt_end_node(dt);
} }
void build_flat_dt(struct iseries_flat_dt *dt) void build_flat_dt(struct iseries_flat_dt *dt, unsigned long phys_mem_size)
{ {
u64 tmp[2]; u64 tmp[2];
...@@ -945,7 +946,7 @@ void build_flat_dt(struct iseries_flat_dt *dt) ...@@ -945,7 +946,7 @@ void build_flat_dt(struct iseries_flat_dt *dt)
dt_prop_str(dt, "name", "memory"); dt_prop_str(dt, "name", "memory");
dt_prop_str(dt, "device_type", "memory"); dt_prop_str(dt, "device_type", "memory");
tmp[0] = 0; tmp[0] = 0;
tmp[1] = systemcfg->physicalMemorySize; tmp[1] = phys_mem_size;
dt_prop_u64_list(dt, "reg", tmp, 2); dt_prop_u64_list(dt, "reg", tmp, 2);
dt_end_node(dt); dt_end_node(dt);
...@@ -965,13 +966,15 @@ void build_flat_dt(struct iseries_flat_dt *dt) ...@@ -965,13 +966,15 @@ void build_flat_dt(struct iseries_flat_dt *dt)
void * __init iSeries_early_setup(void) void * __init iSeries_early_setup(void)
{ {
unsigned long phys_mem_size;
iSeries_fixup_klimit(); iSeries_fixup_klimit();
/* /*
* Initialize the table which translate Linux physical addresses to * Initialize the table which translate Linux physical addresses to
* AS/400 absolute addresses * AS/400 absolute addresses
*/ */
build_iSeries_Memory_Map(); phys_mem_size = build_iSeries_Memory_Map();
iSeries_get_cmdline(); iSeries_get_cmdline();
...@@ -981,7 +984,7 @@ void * __init iSeries_early_setup(void) ...@@ -981,7 +984,7 @@ void * __init iSeries_early_setup(void)
/* Parse early parameters, in particular mem=x */ /* Parse early parameters, in particular mem=x */
parse_early_param(); parse_early_param();
build_flat_dt(&iseries_dt); build_flat_dt(&iseries_dt, phys_mem_size);
return (void *) __pa(&iseries_dt); return (void *) __pa(&iseries_dt);
} }
......
...@@ -380,9 +380,6 @@ void __init maple_pcibios_fixup(void) ...@@ -380,9 +380,6 @@ void __init maple_pcibios_fixup(void)
for_each_pci_dev(dev) for_each_pci_dev(dev)
pci_read_irq_line(dev); pci_read_irq_line(dev);
/* Do the mapping of the IO space */
phbs_remap_io();
DBG(" <- maple_pcibios_fixup\n"); DBG(" <- maple_pcibios_fixup\n");
} }
......
...@@ -918,9 +918,6 @@ void __init pmac_pci_init(void) ...@@ -918,9 +918,6 @@ void __init pmac_pci_init(void)
PCI_DN(np)->busno = 0xf0; PCI_DN(np)->busno = 0xf0;
} }
/* map in PCI I/O space */
phbs_remap_io();
/* pmac_check_ht_link(); */ /* pmac_check_ht_link(); */
/* Tell pci.c to not use the common resource allocation mechanism */ /* Tell pci.c to not use the common resource allocation mechanism */
......
...@@ -74,6 +74,9 @@ static DEFINE_SPINLOCK(pmac_pic_lock); ...@@ -74,6 +74,9 @@ static DEFINE_SPINLOCK(pmac_pic_lock);
#define GATWICK_IRQ_POOL_SIZE 10 #define GATWICK_IRQ_POOL_SIZE 10
static struct interrupt_info gatwick_int_pool[GATWICK_IRQ_POOL_SIZE]; static struct interrupt_info gatwick_int_pool[GATWICK_IRQ_POOL_SIZE];
#define NR_MASK_WORDS ((NR_IRQS + 31) / 32)
static unsigned long ppc_lost_interrupts[NR_MASK_WORDS];
/* /*
* Mark an irq as "lost". This is only used on the pmac * Mark an irq as "lost". This is only used on the pmac
* since it can lose interrupts (see pmac_set_irq_mask). * since it can lose interrupts (see pmac_set_irq_mask).
......
...@@ -305,9 +305,19 @@ static int __init smp_psurge_probe(void) ...@@ -305,9 +305,19 @@ static int __init smp_psurge_probe(void)
psurge_start = ioremap(PSURGE_START, 4); psurge_start = ioremap(PSURGE_START, 4);
psurge_pri_intr = ioremap(PSURGE_PRI_INTR, 4); psurge_pri_intr = ioremap(PSURGE_PRI_INTR, 4);
/* this is not actually strictly necessary -- paulus. */ /*
for (i = 1; i < ncpus; ++i) * This is necessary because OF doesn't know about the
smp_hw_index[i] = i; * secondary cpu(s), and thus there aren't nodes in the
* device tree for them, and smp_setup_cpu_maps hasn't
* set their bits in cpu_possible_map and cpu_present_map.
*/
if (ncpus > NR_CPUS)
ncpus = NR_CPUS;
for (i = 1; i < ncpus ; ++i) {
cpu_set(i, cpu_present_map);
cpu_set(i, cpu_possible_map);
set_hard_smp_processor_id(i, i);
}
if (ppc_md.progress) ppc_md.progress("smp_psurge_probe - done", 0x352); if (ppc_md.progress) ppc_md.progress("smp_psurge_probe - done", 0x352);
...@@ -348,6 +358,7 @@ static void __init psurge_dual_sync_tb(int cpu_nr) ...@@ -348,6 +358,7 @@ static void __init psurge_dual_sync_tb(int cpu_nr)
int t; int t;
set_dec(tb_ticks_per_jiffy); set_dec(tb_ticks_per_jiffy);
/* XXX fixme */
set_tb(0, 0); set_tb(0, 0);
last_jiffy_stamp(cpu_nr) = 0; last_jiffy_stamp(cpu_nr) = 0;
...@@ -363,8 +374,6 @@ static void __init psurge_dual_sync_tb(int cpu_nr) ...@@ -363,8 +374,6 @@ static void __init psurge_dual_sync_tb(int cpu_nr)
/* now interrupt the secondary, starting both TBs */ /* now interrupt the secondary, starting both TBs */
psurge_set_ipi(1); psurge_set_ipi(1);
smp_tb_synchronized = 1;
} }
static struct irqaction psurge_irqaction = { static struct irqaction psurge_irqaction = {
...@@ -625,9 +634,8 @@ void smp_core99_give_timebase(void) ...@@ -625,9 +634,8 @@ void smp_core99_give_timebase(void)
for (t = 100000; t > 0 && sec_tb_reset; --t) for (t = 100000; t > 0 && sec_tb_reset; --t)
udelay(10); udelay(10);
if (sec_tb_reset) if (sec_tb_reset)
/* XXX BUG_ON here? */
printk(KERN_WARNING "Timeout waiting sync(2) on second CPU\n"); printk(KERN_WARNING "Timeout waiting sync(2) on second CPU\n");
else
smp_tb_synchronized = 1;
/* Now, restart the timebase by leaving the GPIO to an open collector */ /* Now, restart the timebase by leaving the GPIO to an open collector */
pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, core99_tb_gpio, 0); pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, core99_tb_gpio, 0);
...@@ -810,19 +818,9 @@ static void __devinit smp_core99_setup_cpu(int cpu_nr) ...@@ -810,19 +818,9 @@ static void __devinit smp_core99_setup_cpu(int cpu_nr)
} }
/* Core99 Macs (dual G4s and G5s) */
struct smp_ops_t core99_smp_ops = {
.message_pass = smp_mpic_message_pass,
.probe = smp_core99_probe,
.kick_cpu = smp_core99_kick_cpu,
.setup_cpu = smp_core99_setup_cpu,
.give_timebase = smp_core99_give_timebase,
.take_timebase = smp_core99_take_timebase,
};
#if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PPC32) #if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PPC32)
int __cpu_disable(void) int smp_core99_cpu_disable(void)
{ {
cpu_clear(smp_processor_id(), cpu_online_map); cpu_clear(smp_processor_id(), cpu_online_map);
...@@ -846,7 +844,7 @@ void cpu_die(void) ...@@ -846,7 +844,7 @@ void cpu_die(void)
low_cpu_die(); low_cpu_die();
} }
void __cpu_die(unsigned int cpu) void smp_core99_cpu_die(unsigned int cpu)
{ {
int timeout; int timeout;
...@@ -858,8 +856,21 @@ void __cpu_die(unsigned int cpu) ...@@ -858,8 +856,21 @@ void __cpu_die(unsigned int cpu)
} }
msleep(1); msleep(1);
} }
cpu_callin_map[cpu] = 0;
cpu_dead[cpu] = 0; cpu_dead[cpu] = 0;
} }
#endif #endif
/* Core99 Macs (dual G4s and G5s) */
struct smp_ops_t core99_smp_ops = {
.message_pass = smp_mpic_message_pass,
.probe = smp_core99_probe,
.kick_cpu = smp_core99_kick_cpu,
.setup_cpu = smp_core99_setup_cpu,
.give_timebase = smp_core99_give_timebase,
.take_timebase = smp_core99_take_timebase,
#if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PPC32)
.cpu_disable = smp_core99_cpu_disable,
.cpu_die = smp_core99_cpu_die,
#endif
};
...@@ -3,3 +3,5 @@ obj-y := pci.o lpar.o hvCall.o nvram.o reconfig.o \ ...@@ -3,3 +3,5 @@ obj-y := pci.o lpar.o hvCall.o nvram.o reconfig.o \
obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_IBMVIO) += vio.o obj-$(CONFIG_IBMVIO) += vio.o
obj-$(CONFIG_XICS) += xics.o obj-$(CONFIG_XICS) += xics.o
obj-$(CONFIG_SCANLOG) += scanlog.o
obj-$(CONFIG_EEH) += eeh.o eeh_event.o
/*
* eeh_event.c
*
* 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Copyright (c) 2005 Linas Vepstas <linas@linas.org>
*/
#include <linux/list.h>
#include <linux/pci.h>
#include <asm/eeh_event.h>
/** Overview:
* EEH error states may be detected within exception handlers;
* however, the recovery processing needs to occur asynchronously
* in a normal kernel context and not an interrupt context.
* This pair of routines creates an event and queues it onto a
* work-queue, where a worker thread can drive recovery.
*/
/* EEH event workqueue setup. */
static spinlock_t eeh_eventlist_lock = SPIN_LOCK_UNLOCKED;
LIST_HEAD(eeh_eventlist);
static void eeh_thread_launcher(void *);
DECLARE_WORK(eeh_event_wq, eeh_thread_launcher, NULL);
/**
* eeh_panic - call panic() for an eeh event that cannot be handled.
* The philosophy of this routine is that it is better to panic and
* halt the OS than it is to risk possible data corruption by
* oblivious device drivers that don't know better.
*
* @dev pci device that had an eeh event
* @reset_state current reset state of the device slot
*/
static void eeh_panic(struct pci_dev *dev, int reset_state)
{
/*
* Since the panic_on_oops sysctl is used to halt the system
* in light of potential corruption, we can use it here.
*/
if (panic_on_oops) {
panic("EEH: MMIO failure (%d) on device:%s\n", reset_state,
pci_name(dev));
}
else {
printk(KERN_INFO "EEH: Ignored MMIO failure (%d) on device:%s\n",
reset_state, pci_name(dev));
}
}
/**
* eeh_event_handler - dispatch EEH events. The detection of a frozen
* slot can occur inside an interrupt, where it can be hard to do
* anything about it. The goal of this routine is to pull these
* detection events out of the context of the interrupt handler, and
* re-dispatch them for processing at a later time in a normal context.
*
* @dummy - unused
*/
static int eeh_event_handler(void * dummy)
{
unsigned long flags;
struct eeh_event *event;
daemonize ("eehd");
while (1) {
set_current_state(TASK_INTERRUPTIBLE);
spin_lock_irqsave(&eeh_eventlist_lock, flags);
event = NULL;
if (!list_empty(&eeh_eventlist)) {
event = list_entry(eeh_eventlist.next, struct eeh_event, list);
list_del(&event->list);
}
spin_unlock_irqrestore(&eeh_eventlist_lock, flags);
if (event == NULL)
break;
printk(KERN_INFO "EEH: Detected PCI bus error on device %s\n",
pci_name(event->dev));
eeh_panic (event->dev, event->state);
kfree(event);
}
return 0;
}
/**
* eeh_thread_launcher
*
* @dummy - unused
*/
static void eeh_thread_launcher(void *dummy)
{
if (kernel_thread(eeh_event_handler, NULL, CLONE_KERNEL) < 0)
printk(KERN_ERR "Failed to start EEH daemon\n");
}
/**
* eeh_send_failure_event - generate a PCI error event
* @dev pci device
*
* This routine can be called within an interrupt context;
* the actual event will be delivered in a normal context
* (from a workqueue).
*/
int eeh_send_failure_event (struct device_node *dn,
struct pci_dev *dev,
int state,
int time_unavail)
{
unsigned long flags;
struct eeh_event *event;
event = kmalloc(sizeof(*event), GFP_ATOMIC);
if (event == NULL) {
printk (KERN_ERR "EEH: out of memory, event not handled\n");
return 1;
}
if (dev)
pci_dev_get(dev);
event->dn = dn;
event->dev = dev;
event->state = state;
event->time_unavail = time_unavail;
/* We may or may not be called in an interrupt context */
spin_lock_irqsave(&eeh_eventlist_lock, flags);
list_add(&event->list, &eeh_eventlist);
spin_unlock_irqrestore(&eeh_eventlist_lock, flags);
schedule_work(&eeh_event_wq);
return 0;
}
/********************** END OF FILE ******************************/
...@@ -42,7 +42,6 @@ ...@@ -42,7 +42,6 @@
#include <asm/machdep.h> #include <asm/machdep.h>
#include <asm/abs_addr.h> #include <asm/abs_addr.h>
#include <asm/pSeries_reconfig.h> #include <asm/pSeries_reconfig.h>
#include <asm/systemcfg.h>
#include <asm/firmware.h> #include <asm/firmware.h>
#include <asm/tce.h> #include <asm/tce.h>
#include <asm/ppc-pci.h> #include <asm/ppc-pci.h>
...@@ -582,7 +581,7 @@ void iommu_init_early_pSeries(void) ...@@ -582,7 +581,7 @@ void iommu_init_early_pSeries(void)
return; return;
} }
if (systemcfg->platform & PLATFORM_LPAR) { if (platform_is_lpar()) {
if (firmware_has_feature(FW_FEATURE_MULTITCE)) { if (firmware_has_feature(FW_FEATURE_MULTITCE)) {
ppc_md.tce_build = tce_buildmulti_pSeriesLP; ppc_md.tce_build = tce_buildmulti_pSeriesLP;
ppc_md.tce_free = tce_freemulti_pSeriesLP; ppc_md.tce_free = tce_freemulti_pSeriesLP;
......
...@@ -107,7 +107,6 @@ static void __init pSeries_request_regions(void) ...@@ -107,7 +107,6 @@ static void __init pSeries_request_regions(void)
void __init pSeries_final_fixup(void) void __init pSeries_final_fixup(void)
{ {
phbs_remap_io();
pSeries_request_regions(); pSeries_request_regions();
pci_addr_cache_build(); pci_addr_cache_build();
...@@ -123,7 +122,7 @@ static void fixup_winbond_82c105(struct pci_dev* dev) ...@@ -123,7 +122,7 @@ static void fixup_winbond_82c105(struct pci_dev* dev)
int i; int i;
unsigned int reg; unsigned int reg;
if (!(systemcfg->platform & PLATFORM_PSERIES)) if (!platform_is_pseries())
return; return;
printk("Using INTC for W82c105 IDE controller.\n"); printk("Using INTC for W82c105 IDE controller.\n");
......
...@@ -408,7 +408,7 @@ static int proc_ppc64_create_ofdt(void) ...@@ -408,7 +408,7 @@ static int proc_ppc64_create_ofdt(void)
{ {
struct proc_dir_entry *ent; struct proc_dir_entry *ent;
if (!(systemcfg->platform & PLATFORM_PSERIES)) if (!platform_is_pseries())
return 0; return 0;
ent = create_proc_entry("ppc64/ofdt", S_IWUSR, NULL); ent = create_proc_entry("ppc64/ofdt", S_IWUSR, NULL);
......
...@@ -482,9 +482,11 @@ static int __init rtas_init(void) ...@@ -482,9 +482,11 @@ static int __init rtas_init(void)
{ {
struct proc_dir_entry *entry; struct proc_dir_entry *entry;
/* No RTAS, only warn if we are on a pSeries box */ if (!platform_is_pseries())
return 0;
/* No RTAS */
if (rtas_token("event-scan") == RTAS_UNKNOWN_SERVICE) { if (rtas_token("event-scan") == RTAS_UNKNOWN_SERVICE) {
if (systemcfg->platform & PLATFORM_PSERIES)
printk(KERN_INFO "rtasd: no event-scan on system\n"); printk(KERN_INFO "rtasd: no event-scan on system\n");
return 1; return 1;
} }
......
...@@ -249,7 +249,7 @@ static void __init pSeries_setup_arch(void) ...@@ -249,7 +249,7 @@ static void __init pSeries_setup_arch(void)
ppc_md.idle_loop = default_idle; ppc_md.idle_loop = default_idle;
} }
if (systemcfg->platform & PLATFORM_LPAR) if (platform_is_lpar())
ppc_md.enable_pmcs = pseries_lpar_enable_pmcs; ppc_md.enable_pmcs = pseries_lpar_enable_pmcs;
else else
ppc_md.enable_pmcs = power4_enable_pmcs; ppc_md.enable_pmcs = power4_enable_pmcs;
...@@ -378,7 +378,7 @@ static void __init pSeries_init_early(void) ...@@ -378,7 +378,7 @@ static void __init pSeries_init_early(void)
fw_feature_init(); fw_feature_init();
if (systemcfg->platform & PLATFORM_LPAR) if (platform_is_lpar())
hpte_init_lpar(); hpte_init_lpar();
else { else {
hpte_init_native(); hpte_init_native();
...@@ -388,7 +388,7 @@ static void __init pSeries_init_early(void) ...@@ -388,7 +388,7 @@ static void __init pSeries_init_early(void)
generic_find_legacy_serial_ports(&physport, &default_speed); generic_find_legacy_serial_ports(&physport, &default_speed);
if (systemcfg->platform & PLATFORM_LPAR) if (platform_is_lpar())
find_udbg_vterm(); find_udbg_vterm();
else if (physport) { else if (physport) {
/* Map the uart for udbg. */ /* Map the uart for udbg. */
...@@ -592,7 +592,7 @@ static void pseries_shared_idle(void) ...@@ -592,7 +592,7 @@ static void pseries_shared_idle(void)
static int pSeries_pci_probe_mode(struct pci_bus *bus) static int pSeries_pci_probe_mode(struct pci_bus *bus)
{ {
if (systemcfg->platform & PLATFORM_LPAR) if (platform_is_lpar())
return PCI_PROBE_DEVTREE; return PCI_PROBE_DEVTREE;
return PCI_PROBE_NORMAL; return PCI_PROBE_NORMAL;
} }
......
...@@ -46,6 +46,7 @@ ...@@ -46,6 +46,7 @@
#include <asm/rtas.h> #include <asm/rtas.h>
#include <asm/pSeries_reconfig.h> #include <asm/pSeries_reconfig.h>
#include <asm/mpic.h> #include <asm/mpic.h>
#include <asm/systemcfg.h>
#include "plpar_wrappers.h" #include "plpar_wrappers.h"
...@@ -96,7 +97,7 @@ int pSeries_cpu_disable(void) ...@@ -96,7 +97,7 @@ int pSeries_cpu_disable(void)
int cpu = smp_processor_id(); int cpu = smp_processor_id();
cpu_clear(cpu, cpu_online_map); cpu_clear(cpu, cpu_online_map);
systemcfg->processorCount--; _systemcfg->processorCount--;
/*fix boot_cpuid here*/ /*fix boot_cpuid here*/
if (cpu == boot_cpuid) if (cpu == boot_cpuid)
...@@ -441,7 +442,7 @@ void __init smp_init_pSeries(void) ...@@ -441,7 +442,7 @@ void __init smp_init_pSeries(void)
smp_ops->cpu_die = pSeries_cpu_die; smp_ops->cpu_die = pSeries_cpu_die;
/* Processors can be added/removed only on LPAR */ /* Processors can be added/removed only on LPAR */
if (systemcfg->platform == PLATFORM_PSERIES_LPAR) if (platform_is_lpar())
pSeries_reconfig_notifier_register(&pSeries_smp_nb); pSeries_reconfig_notifier_register(&pSeries_smp_nb);
#endif #endif
......
...@@ -545,7 +545,9 @@ void xics_init_IRQ(void) ...@@ -545,7 +545,9 @@ void xics_init_IRQ(void)
of_node_put(np); of_node_put(np);
} }
if (systemcfg->platform == PLATFORM_PSERIES) { if (platform_is_lpar())
ops = &pSeriesLP_ops;
else {
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
for_each_cpu(i) { for_each_cpu(i) {
int hard_id; int hard_id;
...@@ -561,12 +563,11 @@ void xics_init_IRQ(void) ...@@ -561,12 +563,11 @@ void xics_init_IRQ(void)
#else #else
xics_per_cpu[0] = ioremap(intr_base, intr_size); xics_per_cpu[0] = ioremap(intr_base, intr_size);
#endif /* CONFIG_SMP */ #endif /* CONFIG_SMP */
} else if (systemcfg->platform == PLATFORM_PSERIES_LPAR) {
ops = &pSeriesLP_ops;
} }
xics_8259_pic.enable = i8259_pic.enable; xics_8259_pic.enable = i8259_pic.enable;
xics_8259_pic.disable = i8259_pic.disable; xics_8259_pic.disable = i8259_pic.disable;
xics_8259_pic.end = i8259_pic.end;
for (i = 0; i < 16; ++i) for (i = 0; i < 16; ++i)
get_irq_desc(i)->handler = &xics_8259_pic; get_irq_desc(i)->handler = &xics_8259_pic;
for (; i < NR_IRQS; ++i) for (; i < NR_IRQS; ++i)
......
...@@ -226,7 +226,7 @@ static void iommu_table_u3_setup(void) ...@@ -226,7 +226,7 @@ static void iommu_table_u3_setup(void)
iommu_table_u3.it_busno = 0; iommu_table_u3.it_busno = 0;
iommu_table_u3.it_offset = 0; iommu_table_u3.it_offset = 0;
/* it_size is in number of entries */ /* it_size is in number of entries */
iommu_table_u3.it_size = dart_tablesize / sizeof(u32); iommu_table_u3.it_size = (dart_tablesize / sizeof(u32)) >> DART_PAGE_FACTOR;
/* Initialize the common IOMMU code */ /* Initialize the common IOMMU code */
iommu_table_u3.it_base = (unsigned long)dart_vbase; iommu_table_u3.it_base = (unsigned long)dart_vbase;
......
...@@ -8,4 +8,4 @@ obj-$(CONFIG_8xx) += start_8xx.o ...@@ -8,4 +8,4 @@ obj-$(CONFIG_8xx) += start_8xx.o
obj-$(CONFIG_6xx) += start_32.o obj-$(CONFIG_6xx) += start_32.o
obj-$(CONFIG_4xx) += start_32.o obj-$(CONFIG_4xx) += start_32.o
obj-$(CONFIG_PPC64) += start_64.o obj-$(CONFIG_PPC64) += start_64.o
obj-y += xmon.o ppc-dis.o ppc-opc.o subr_prf.o setjmp.o obj-y += xmon.o ppc-dis.o ppc-opc.o setjmp.o nonstdio.o
/*
* Copyright (C) 1996-2005 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/string.h>
#include <asm/time.h>
#include "nonstdio.h"
int xmon_putchar(int c)
{
char ch = c;
if (c == '\n')
xmon_putchar('\r');
return xmon_write(&ch, 1) == 1? c: -1;
}
static char line[256];
static char *lineptr;
static int lineleft;
int xmon_expect(const char *str, unsigned long timeout)
{
int c;
unsigned long t0;
/* assume 25MHz default timebase if tb_ticks_per_sec not set yet */
timeout *= tb_ticks_per_sec? tb_ticks_per_sec: 25000000;
t0 = get_tbl();
do {
lineptr = line;
for (;;) {
c = xmon_read_poll();
if (c == -1) {
if (get_tbl() - t0 > timeout)
return 0;
continue;
}
if (c == '\n')
break;
if (c != '\r' && lineptr < &line[sizeof(line) - 1])
*lineptr++ = c;
}
*lineptr = 0;
} while (strstr(line, str) == NULL);
return 1;
}
int xmon_getchar(void)
{
int c;
if (lineleft == 0) {
lineptr = line;
for (;;) {
c = xmon_readchar();
if (c == -1 || c == 4)
break;
if (c == '\r' || c == '\n') {
*lineptr++ = '\n';
xmon_putchar('\n');
break;
}
switch (c) {
case 0177:
case '\b':
if (lineptr > line) {
xmon_putchar('\b');
xmon_putchar(' ');
xmon_putchar('\b');
--lineptr;
}
break;
case 'U' & 0x1F:
while (lineptr > line) {
xmon_putchar('\b');
xmon_putchar(' ');
xmon_putchar('\b');
--lineptr;
}
break;
default:
if (lineptr >= &line[sizeof(line) - 1])
xmon_putchar('\a');
else {
xmon_putchar(c);
*lineptr++ = c;
}
}
}
lineleft = lineptr - line;
lineptr = line;
}
if (lineleft == 0)
return -1;
--lineleft;
return *lineptr++;
}
char *xmon_gets(char *str, int nb)
{
char *p;
int c;
for (p = str; p < str + nb - 1; ) {
c = xmon_getchar();
if (c == -1) {
if (p == str)
return NULL;
break;
}
*p++ = c;
if (c == '\n')
break;
}
*p = 0;
return str;
}
void xmon_printf(const char *format, ...)
{
va_list args;
int n;
static char xmon_outbuf[1024];
va_start(args, format);
n = vsnprintf(xmon_outbuf, sizeof(xmon_outbuf), format, args);
va_end(args);
xmon_write(xmon_outbuf, n);
}
typedef int FILE;
extern FILE *xmon_stdin, *xmon_stdout;
#define EOF (-1) #define EOF (-1)
#define stdin xmon_stdin
#define stdout xmon_stdout
#define printf xmon_printf #define printf xmon_printf
#define fprintf xmon_fprintf
#define fputs xmon_fputs
#define fgets xmon_fgets
#define putchar xmon_putchar #define putchar xmon_putchar
#define getchar xmon_getchar
#define putc xmon_putc
#define getc xmon_getc
#define fopen(n, m) NULL
#define fflush(f) do {} while (0)
#define fclose(f) do {} while (0)
extern char *fgets(char *, int, void *);
extern void xmon_printf(const char *, ...);
extern void xmon_fprintf(void *, const char *, ...);
extern void xmon_sprintf(char *, const char *, ...);
#define perror(s) printf("%s: no files!\n", (s)) extern int xmon_putchar(int c);
extern int xmon_getchar(void);
extern char *xmon_gets(char *, int);
extern void xmon_printf(const char *, ...);
extern void xmon_map_scc(void);
extern int xmon_expect(const char *str, unsigned long timeout);
extern int xmon_write(void *ptr, int nb);
extern int xmon_readchar(void);
extern int xmon_read_poll(void);
...@@ -14,61 +14,61 @@ ...@@ -14,61 +14,61 @@
_GLOBAL(xmon_setjmp) _GLOBAL(xmon_setjmp)
mflr r0 mflr r0
STL r0,0(r3) PPC_STL r0,0(r3)
STL r1,SZL(r3) PPC_STL r1,SZL(r3)
STL r2,2*SZL(r3) PPC_STL r2,2*SZL(r3)
mfcr r0 mfcr r0
STL r0,3*SZL(r3) PPC_STL r0,3*SZL(r3)
STL r13,4*SZL(r3) PPC_STL r13,4*SZL(r3)
STL r14,5*SZL(r3) PPC_STL r14,5*SZL(r3)
STL r15,6*SZL(r3) PPC_STL r15,6*SZL(r3)
STL r16,7*SZL(r3) PPC_STL r16,7*SZL(r3)
STL r17,8*SZL(r3) PPC_STL r17,8*SZL(r3)
STL r18,9*SZL(r3) PPC_STL r18,9*SZL(r3)
STL r19,10*SZL(r3) PPC_STL r19,10*SZL(r3)
STL r20,11*SZL(r3) PPC_STL r20,11*SZL(r3)
STL r21,12*SZL(r3) PPC_STL r21,12*SZL(r3)
STL r22,13*SZL(r3) PPC_STL r22,13*SZL(r3)
STL r23,14*SZL(r3) PPC_STL r23,14*SZL(r3)
STL r24,15*SZL(r3) PPC_STL r24,15*SZL(r3)
STL r25,16*SZL(r3) PPC_STL r25,16*SZL(r3)
STL r26,17*SZL(r3) PPC_STL r26,17*SZL(r3)
STL r27,18*SZL(r3) PPC_STL r27,18*SZL(r3)
STL r28,19*SZL(r3) PPC_STL r28,19*SZL(r3)
STL r29,20*SZL(r3) PPC_STL r29,20*SZL(r3)
STL r30,21*SZL(r3) PPC_STL r30,21*SZL(r3)
STL r31,22*SZL(r3) PPC_STL r31,22*SZL(r3)
li r3,0 li r3,0
blr blr
_GLOBAL(xmon_longjmp) _GLOBAL(xmon_longjmp)
CMPI r4,0 PPC_LCMPI r4,0
bne 1f bne 1f
li r4,1 li r4,1
1: LDL r13,4*SZL(r3) 1: PPC_LL r13,4*SZL(r3)
LDL r14,5*SZL(r3) PPC_LL r14,5*SZL(r3)
LDL r15,6*SZL(r3) PPC_LL r15,6*SZL(r3)
LDL r16,7*SZL(r3) PPC_LL r16,7*SZL(r3)
LDL r17,8*SZL(r3) PPC_LL r17,8*SZL(r3)
LDL r18,9*SZL(r3) PPC_LL r18,9*SZL(r3)
LDL r19,10*SZL(r3) PPC_LL r19,10*SZL(r3)
LDL r20,11*SZL(r3) PPC_LL r20,11*SZL(r3)
LDL r21,12*SZL(r3) PPC_LL r21,12*SZL(r3)
LDL r22,13*SZL(r3) PPC_LL r22,13*SZL(r3)
LDL r23,14*SZL(r3) PPC_LL r23,14*SZL(r3)
LDL r24,15*SZL(r3) PPC_LL r24,15*SZL(r3)
LDL r25,16*SZL(r3) PPC_LL r25,16*SZL(r3)
LDL r26,17*SZL(r3) PPC_LL r26,17*SZL(r3)
LDL r27,18*SZL(r3) PPC_LL r27,18*SZL(r3)
LDL r28,19*SZL(r3) PPC_LL r28,19*SZL(r3)
LDL r29,20*SZL(r3) PPC_LL r29,20*SZL(r3)
LDL r30,21*SZL(r3) PPC_LL r30,21*SZL(r3)
LDL r31,22*SZL(r3) PPC_LL r31,22*SZL(r3)
LDL r0,3*SZL(r3) PPC_LL r0,3*SZL(r3)
mtcrf 0x38,r0 mtcrf 0x38,r0
LDL r0,0(r3) PPC_LL r0,0(r3)
LDL r1,SZL(r3) PPC_LL r1,SZL(r3)
LDL r2,2*SZL(r3) PPC_LL r2,2*SZL(r3)
mtlr r0 mtlr r0
mr r3,r4 mr r3,r4
blr blr
...@@ -84,52 +84,52 @@ _GLOBAL(xmon_longjmp) ...@@ -84,52 +84,52 @@ _GLOBAL(xmon_longjmp)
* different ABIs, though). * different ABIs, though).
*/ */
_GLOBAL(xmon_save_regs) _GLOBAL(xmon_save_regs)
STL r0,0*SZL(r3) PPC_STL r0,0*SZL(r3)
STL r2,2*SZL(r3) PPC_STL r2,2*SZL(r3)
STL r3,3*SZL(r3) PPC_STL r3,3*SZL(r3)
STL r4,4*SZL(r3) PPC_STL r4,4*SZL(r3)
STL r5,5*SZL(r3) PPC_STL r5,5*SZL(r3)
STL r6,6*SZL(r3) PPC_STL r6,6*SZL(r3)
STL r7,7*SZL(r3) PPC_STL r7,7*SZL(r3)
STL r8,8*SZL(r3) PPC_STL r8,8*SZL(r3)
STL r9,9*SZL(r3) PPC_STL r9,9*SZL(r3)
STL r10,10*SZL(r3) PPC_STL r10,10*SZL(r3)
STL r11,11*SZL(r3) PPC_STL r11,11*SZL(r3)
STL r12,12*SZL(r3) PPC_STL r12,12*SZL(r3)
STL r13,13*SZL(r3) PPC_STL r13,13*SZL(r3)
STL r14,14*SZL(r3) PPC_STL r14,14*SZL(r3)
STL r15,15*SZL(r3) PPC_STL r15,15*SZL(r3)
STL r16,16*SZL(r3) PPC_STL r16,16*SZL(r3)
STL r17,17*SZL(r3) PPC_STL r17,17*SZL(r3)
STL r18,18*SZL(r3) PPC_STL r18,18*SZL(r3)
STL r19,19*SZL(r3) PPC_STL r19,19*SZL(r3)
STL r20,20*SZL(r3) PPC_STL r20,20*SZL(r3)
STL r21,21*SZL(r3) PPC_STL r21,21*SZL(r3)
STL r22,22*SZL(r3) PPC_STL r22,22*SZL(r3)
STL r23,23*SZL(r3) PPC_STL r23,23*SZL(r3)
STL r24,24*SZL(r3) PPC_STL r24,24*SZL(r3)
STL r25,25*SZL(r3) PPC_STL r25,25*SZL(r3)
STL r26,26*SZL(r3) PPC_STL r26,26*SZL(r3)
STL r27,27*SZL(r3) PPC_STL r27,27*SZL(r3)
STL r28,28*SZL(r3) PPC_STL r28,28*SZL(r3)
STL r29,29*SZL(r3) PPC_STL r29,29*SZL(r3)
STL r30,30*SZL(r3) PPC_STL r30,30*SZL(r3)
STL r31,31*SZL(r3) PPC_STL r31,31*SZL(r3)
/* go up one stack frame for SP */ /* go up one stack frame for SP */
LDL r4,0(r1) PPC_LL r4,0(r1)
STL r4,1*SZL(r3) PPC_STL r4,1*SZL(r3)
/* get caller's LR */ /* get caller's LR */
LDL r0,LRSAVE(r4) PPC_LL r0,LRSAVE(r4)
STL r0,_NIP-STACK_FRAME_OVERHEAD(r3) PPC_STL r0,_NIP-STACK_FRAME_OVERHEAD(r3)
STL r0,_LINK-STACK_FRAME_OVERHEAD(r3) PPC_STL r0,_LINK-STACK_FRAME_OVERHEAD(r3)
mfmsr r0 mfmsr r0
STL r0,_MSR-STACK_FRAME_OVERHEAD(r3) PPC_STL r0,_MSR-STACK_FRAME_OVERHEAD(r3)
mfctr r0 mfctr r0
STL r0,_CTR-STACK_FRAME_OVERHEAD(r3) PPC_STL r0,_CTR-STACK_FRAME_OVERHEAD(r3)
mfxer r0 mfxer r0
STL r0,_XER-STACK_FRAME_OVERHEAD(r3) PPC_STL r0,_XER-STACK_FRAME_OVERHEAD(r3)
mfcr r0 mfcr r0
STL r0,_CCR-STACK_FRAME_OVERHEAD(r3) PPC_STL r0,_CCR-STACK_FRAME_OVERHEAD(r3)
li r0,0 li r0,0
STL r0,_TRAP-STACK_FRAME_OVERHEAD(r3) PPC_STL r0,_TRAP-STACK_FRAME_OVERHEAD(r3)
blr blr
...@@ -11,7 +11,6 @@ ...@@ -11,7 +11,6 @@
#include <linux/cuda.h> #include <linux/cuda.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/sysrq.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include <asm/xmon.h> #include <asm/xmon.h>
#include <asm/prom.h> #include <asm/prom.h>
...@@ -22,10 +21,11 @@ ...@@ -22,10 +21,11 @@
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/delay.h> #include <asm/delay.h>
#include <asm/btext.h> #include <asm/btext.h>
#include <asm/time.h>
#include "nonstdio.h"
static volatile unsigned char __iomem *sccc, *sccd; static volatile unsigned char __iomem *sccc, *sccd;
unsigned int TXRDY, RXRDY, DLAB; unsigned int TXRDY, RXRDY, DLAB;
static int xmon_expect(const char *str, unsigned int timeout);
static int use_serial; static int use_serial;
static int use_screen; static int use_screen;
...@@ -33,16 +33,6 @@ static int via_modem; ...@@ -33,16 +33,6 @@ static int via_modem;
static int xmon_use_sccb; static int xmon_use_sccb;
static struct device_node *channel_node; static struct device_node *channel_node;
#define TB_SPEED 25000000
static inline unsigned int readtb(void)
{
unsigned int ret;
asm volatile("mftb %0" : "=r" (ret) :);
return ret;
}
void buf_access(void) void buf_access(void)
{ {
if (DLAB) if (DLAB)
...@@ -91,23 +81,7 @@ static unsigned long chrp_find_phys_io_base(void) ...@@ -91,23 +81,7 @@ static unsigned long chrp_find_phys_io_base(void)
} }
#endif /* CONFIG_PPC_CHRP */ #endif /* CONFIG_PPC_CHRP */
#ifdef CONFIG_MAGIC_SYSRQ void xmon_map_scc(void)
static void sysrq_handle_xmon(int key, struct pt_regs *regs,
struct tty_struct *tty)
{
xmon(regs);
}
static struct sysrq_key_op sysrq_xmon_op =
{
.handler = sysrq_handle_xmon,
.help_msg = "Xmon",
.action_msg = "Entering xmon",
};
#endif
void
xmon_map_scc(void)
{ {
#ifdef CONFIG_PPC_MULTIPLATFORM #ifdef CONFIG_PPC_MULTIPLATFORM
volatile unsigned char __iomem *base; volatile unsigned char __iomem *base;
...@@ -217,8 +191,6 @@ xmon_map_scc(void) ...@@ -217,8 +191,6 @@ xmon_map_scc(void)
RXRDY = 1; RXRDY = 1;
DLAB = 0x80; DLAB = 0x80;
#endif /* platform */ #endif /* platform */
register_sysrq_key('x', &sysrq_xmon_op);
} }
static int scc_initialized = 0; static int scc_initialized = 0;
...@@ -238,8 +210,7 @@ static inline void do_poll_adb(void) ...@@ -238,8 +210,7 @@ static inline void do_poll_adb(void)
#endif /* CONFIG_ADB_CUDA */ #endif /* CONFIG_ADB_CUDA */
} }
int int xmon_write(void *ptr, int nb)
xmon_write(void *handle, void *ptr, int nb)
{ {
char *p = ptr; char *p = ptr;
int i, c, ct; int i, c, ct;
...@@ -311,8 +282,7 @@ static unsigned char xmon_shift_keytab[128] = ...@@ -311,8 +282,7 @@ static unsigned char xmon_shift_keytab[128] =
"\0.\0*\0+\0\0\0\0\0/\r\0-\0" /* 0x40 - 0x4f */ "\0.\0*\0+\0\0\0\0\0/\r\0-\0" /* 0x40 - 0x4f */
"\0\0000123456789\0\0\0"; /* 0x50 - 0x5f */ "\0\0000123456789\0\0\0"; /* 0x50 - 0x5f */
static int static int xmon_get_adb_key(void)
xmon_get_adb_key(void)
{ {
int k, t, on; int k, t, on;
...@@ -350,32 +320,21 @@ xmon_get_adb_key(void) ...@@ -350,32 +320,21 @@ xmon_get_adb_key(void)
} }
#endif /* CONFIG_BOOTX_TEXT */ #endif /* CONFIG_BOOTX_TEXT */
int int xmon_readchar(void)
xmon_read(void *handle, void *ptr, int nb)
{ {
char *p = ptr;
int i;
#ifdef CONFIG_BOOTX_TEXT #ifdef CONFIG_BOOTX_TEXT
if (use_screen) { if (use_screen)
for (i = 0; i < nb; ++i) return xmon_get_adb_key();
*p++ = xmon_get_adb_key();
return i;
}
#endif #endif
if (!scc_initialized) if (!scc_initialized)
xmon_init_scc(); xmon_init_scc();
for (i = 0; i < nb; ++i) {
while ((*sccc & RXRDY) == 0) while ((*sccc & RXRDY) == 0)
do_poll_adb(); do_poll_adb();
buf_access(); buf_access();
*p++ = *sccd; return *sccd;
}
return i;
} }
int int xmon_read_poll(void)
xmon_read_poll(void)
{ {
if ((*sccc & RXRDY) == 0) { if ((*sccc & RXRDY) == 0) {
do_poll_adb(); do_poll_adb();
...@@ -395,8 +354,7 @@ static unsigned char scc_inittab[] = { ...@@ -395,8 +354,7 @@ static unsigned char scc_inittab[] = {
3, 0xc1, /* rx enable, 8 bits */ 3, 0xc1, /* rx enable, 8 bits */
}; };
void void xmon_init_scc(void)
xmon_init_scc(void)
{ {
if ( _machine == _MACH_chrp ) if ( _machine == _MACH_chrp )
{ {
...@@ -410,6 +368,7 @@ xmon_init_scc(void) ...@@ -410,6 +368,7 @@ xmon_init_scc(void)
else if ( _machine == _MACH_Pmac ) else if ( _machine == _MACH_Pmac )
{ {
int i, x; int i, x;
unsigned long timeout;
if (channel_node != 0) if (channel_node != 0)
pmac_call_feature( pmac_call_feature(
...@@ -424,8 +383,12 @@ xmon_init_scc(void) ...@@ -424,8 +383,12 @@ xmon_init_scc(void)
PMAC_FTR_MODEM_ENABLE, PMAC_FTR_MODEM_ENABLE,
channel_node, 0, 1); channel_node, 0, 1);
printk(KERN_INFO "Modem powered up by debugger !\n"); printk(KERN_INFO "Modem powered up by debugger !\n");
t0 = readtb(); t0 = get_tbl();
while (readtb() - t0 < 3*TB_SPEED) timeout = 3 * tb_ticks_per_sec;
if (timeout == 0)
/* assume 25MHz if tb_ticks_per_sec not set */
timeout = 75000000;
while (get_tbl() - t0 < timeout)
eieio(); eieio();
} }
/* use the B channel if requested */ /* use the B channel if requested */
...@@ -447,164 +410,19 @@ xmon_init_scc(void) ...@@ -447,164 +410,19 @@ xmon_init_scc(void)
scc_initialized = 1; scc_initialized = 1;
if (via_modem) { if (via_modem) {
for (;;) { for (;;) {
xmon_write(NULL, "ATE1V1\r", 7); xmon_write("ATE1V1\r", 7);
if (xmon_expect("OK", 5)) { if (xmon_expect("OK", 5)) {
xmon_write(NULL, "ATA\r", 4); xmon_write("ATA\r", 4);
if (xmon_expect("CONNECT", 40)) if (xmon_expect("CONNECT", 40))
break; break;
} }
xmon_write(NULL, "+++", 3); xmon_write("+++", 3);
xmon_expect("OK", 3); xmon_expect("OK", 3);
} }
} }
} }
void *xmon_stdin; void xmon_enter(void)
void *xmon_stdout;
void *xmon_stderr;
int xmon_putc(int c, void *f)
{
char ch = c;
if (c == '\n')
xmon_putc('\r', f);
return xmon_write(f, &ch, 1) == 1? c: -1;
}
int xmon_putchar(int c)
{
return xmon_putc(c, xmon_stdout);
}
int xmon_fputs(char *str, void *f)
{
int n = strlen(str);
return xmon_write(f, str, n) == n? 0: -1;
}
int
xmon_readchar(void)
{
char ch;
for (;;) {
switch (xmon_read(xmon_stdin, &ch, 1)) {
case 1:
return ch;
case -1:
xmon_printf("read(stdin) returned -1\r\n", 0, 0);
return -1;
}
}
}
static char line[256];
static char *lineptr;
static int lineleft;
int xmon_expect(const char *str, unsigned int timeout)
{
int c;
unsigned int t0;
timeout *= TB_SPEED;
t0 = readtb();
do {
lineptr = line;
for (;;) {
c = xmon_read_poll();
if (c == -1) {
if (readtb() - t0 > timeout)
return 0;
continue;
}
if (c == '\n')
break;
if (c != '\r' && lineptr < &line[sizeof(line) - 1])
*lineptr++ = c;
}
*lineptr = 0;
} while (strstr(line, str) == NULL);
return 1;
}
int
xmon_getchar(void)
{
int c;
if (lineleft == 0) {
lineptr = line;
for (;;) {
c = xmon_readchar();
if (c == -1 || c == 4)
break;
if (c == '\r' || c == '\n') {
*lineptr++ = '\n';
xmon_putchar('\n');
break;
}
switch (c) {
case 0177:
case '\b':
if (lineptr > line) {
xmon_putchar('\b');
xmon_putchar(' ');
xmon_putchar('\b');
--lineptr;
}
break;
case 'U' & 0x1F:
while (lineptr > line) {
xmon_putchar('\b');
xmon_putchar(' ');
xmon_putchar('\b');
--lineptr;
}
break;
default:
if (lineptr >= &line[sizeof(line) - 1])
xmon_putchar('\a');
else {
xmon_putchar(c);
*lineptr++ = c;
}
}
}
lineleft = lineptr - line;
lineptr = line;
}
if (lineleft == 0)
return -1;
--lineleft;
return *lineptr++;
}
char *
xmon_fgets(char *str, int nb, void *f)
{
char *p;
int c;
for (p = str; p < str + nb - 1; ) {
c = xmon_getchar();
if (c == -1) {
if (p == str)
return NULL;
break;
}
*p++ = c;
if (c == '\n')
break;
}
*p = 0;
return str;
}
void
xmon_enter(void)
{ {
#ifdef CONFIG_ADB_PMU #ifdef CONFIG_ADB_PMU
if (_machine == _MACH_Pmac) { if (_machine == _MACH_Pmac) {
...@@ -613,8 +431,7 @@ xmon_enter(void) ...@@ -613,8 +431,7 @@ xmon_enter(void)
#endif #endif
} }
void void xmon_leave(void)
xmon_leave(void)
{ {
#ifdef CONFIG_ADB_PMU #ifdef CONFIG_ADB_PMU
if (_machine == _MACH_Pmac) { if (_machine == _MACH_Pmac) {
......
...@@ -6,182 +6,29 @@ ...@@ -6,182 +6,29 @@
* as published by the Free Software Foundation; either version * as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version. * 2 of the License, or (at your option) any later version.
*/ */
#include <linux/config.h>
#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/sysrq.h>
#include <linux/init.h>
#include <asm/machdep.h> #include <asm/machdep.h>
#include <asm/io.h>
#include <asm/page.h>
#include <asm/prom.h>
#include <asm/processor.h>
#include <asm/udbg.h> #include <asm/udbg.h>
#include <asm/system.h>
#include "nonstdio.h" #include "nonstdio.h"
#ifdef CONFIG_MAGIC_SYSRQ void xmon_map_scc(void)
static void sysrq_handle_xmon(int key, struct pt_regs *pt_regs,
struct tty_struct *tty)
{ {
/* ensure xmon is enabled */
xmon_init(1);
debugger(pt_regs);
} }
static struct sysrq_key_op sysrq_xmon_op = int xmon_write(void *ptr, int nb)
{
.handler = sysrq_handle_xmon,
.help_msg = "Xmon",
.action_msg = "Entering xmon",
};
static int __init setup_xmon_sysrq(void)
{
register_sysrq_key('x', &sysrq_xmon_op);
return 0;
}
__initcall(setup_xmon_sysrq);
#endif /* CONFIG_MAGIC_SYSRQ */
int
xmon_write(void *handle, void *ptr, int nb)
{ {
return udbg_write(ptr, nb); return udbg_write(ptr, nb);
} }
int int xmon_readchar(void)
xmon_read(void *handle, void *ptr, int nb)
{ {
return udbg_read(ptr, nb); if (udbg_getc)
return udbg_getc();
return -1;
} }
int int xmon_read_poll(void)
xmon_read_poll(void)
{ {
if (udbg_getc_poll) if (udbg_getc_poll)
return udbg_getc_poll(); return udbg_getc_poll();
return -1; return -1;
} }
FILE *xmon_stdin;
FILE *xmon_stdout;
int
xmon_putc(int c, void *f)
{
char ch = c;
if (c == '\n')
xmon_putc('\r', f);
return xmon_write(f, &ch, 1) == 1? c: -1;
}
int
xmon_putchar(int c)
{
return xmon_putc(c, xmon_stdout);
}
int
xmon_fputs(char *str, void *f)
{
int n = strlen(str);
return xmon_write(f, str, n) == n? 0: -1;
}
int
xmon_readchar(void)
{
char ch;
for (;;) {
switch (xmon_read(xmon_stdin, &ch, 1)) {
case 1:
return ch;
case -1:
xmon_printf("read(stdin) returned -1\r\n", 0, 0);
return -1;
}
}
}
static char line[256];
static char *lineptr;
static int lineleft;
int
xmon_getchar(void)
{
int c;
if (lineleft == 0) {
lineptr = line;
for (;;) {
c = xmon_readchar();
if (c == -1 || c == 4)
break;
if (c == '\r' || c == '\n') {
*lineptr++ = '\n';
xmon_putchar('\n');
break;
}
switch (c) {
case 0177:
case '\b':
if (lineptr > line) {
xmon_putchar('\b');
xmon_putchar(' ');
xmon_putchar('\b');
--lineptr;
}
break;
case 'U' & 0x1F:
while (lineptr > line) {
xmon_putchar('\b');
xmon_putchar(' ');
xmon_putchar('\b');
--lineptr;
}
break;
default:
if (lineptr >= &line[sizeof(line) - 1])
xmon_putchar('\a');
else {
xmon_putchar(c);
*lineptr++ = c;
}
}
}
lineleft = lineptr - line;
lineptr = line;
}
if (lineleft == 0)
return -1;
--lineleft;
return *lineptr++;
}
char *
xmon_fgets(char *str, int nb, void *f)
{
char *p;
int c;
for (p = str; p < str + nb - 1; ) {
c = xmon_getchar();
if (c == -1) {
if (p == str)
return NULL;
break;
}
*p++ = c;
if (c == '\n')
break;
}
*p = 0;
return str;
}
...@@ -15,273 +15,30 @@ ...@@ -15,273 +15,30 @@
#include <asm/8xx_immap.h> #include <asm/8xx_immap.h>
#include <asm/mpc8xx.h> #include <asm/mpc8xx.h>
#include <asm/commproc.h> #include <asm/commproc.h>
#include "nonstdio.h"
extern void xmon_printf(const char *fmt, ...);
extern int xmon_8xx_write(char *str, int nb); extern int xmon_8xx_write(char *str, int nb);
extern int xmon_8xx_read_poll(void); extern int xmon_8xx_read_poll(void);
extern int xmon_8xx_read_char(void); extern int xmon_8xx_read_char(void);
void prom_drawhex(uint);
void prom_drawstring(const char *str);
static int use_screen = 1; /* default */ void xmon_map_scc(void)
#define TB_SPEED 25000000
static inline unsigned int readtb(void)
{
unsigned int ret;
asm volatile("mftb %0" : "=r" (ret) :);
return ret;
}
void buf_access(void)
{
}
void
xmon_map_scc(void)
{ {
cpmp = (cpm8xx_t *)&(((immap_t *)IMAP_ADDR)->im_cpm); cpmp = (cpm8xx_t *)&(((immap_t *)IMAP_ADDR)->im_cpm);
use_screen = 0;
prom_drawstring("xmon uses serial port\n");
} }
static int scc_initialized = 0;
void xmon_init_scc(void); void xmon_init_scc(void);
int int xmon_write(void *ptr, int nb)
xmon_write(void *handle, void *ptr, int nb)
{ {
char *p = ptr;
int i, c, ct;
if (!scc_initialized)
xmon_init_scc();
return(xmon_8xx_write(ptr, nb)); return(xmon_8xx_write(ptr, nb));
} }
int xmon_wants_key; int xmon_readchar(void)
int
xmon_read(void *handle, void *ptr, int nb)
{ {
char *p = ptr; return xmon_8xx_read_char();
int i;
if (!scc_initialized)
xmon_init_scc();
for (i = 0; i < nb; ++i) {
*p++ = xmon_8xx_read_char();
}
return i;
} }
int int xmon_read_poll(void)
xmon_read_poll(void)
{ {
return(xmon_8xx_read_poll()); return(xmon_8xx_read_poll());
} }
void
xmon_init_scc()
{
scc_initialized = 1;
}
#if 0
extern int (*prom_entry)(void *);
int
xmon_exit(void)
{
struct prom_args {
char *service;
} args;
for (;;) {
args.service = "exit";
(*prom_entry)(&args);
}
}
#endif
void *xmon_stdin;
void *xmon_stdout;
void *xmon_stderr;
void
xmon_init(void)
{
}
int
xmon_putc(int c, void *f)
{
char ch = c;
if (c == '\n')
xmon_putc('\r', f);
return xmon_write(f, &ch, 1) == 1? c: -1;
}
int
xmon_putchar(int c)
{
return xmon_putc(c, xmon_stdout);
}
int
xmon_fputs(char *str, void *f)
{
int n = strlen(str);
return xmon_write(f, str, n) == n? 0: -1;
}
int
xmon_readchar(void)
{
char ch;
for (;;) {
switch (xmon_read(xmon_stdin, &ch, 1)) {
case 1:
return ch;
case -1:
xmon_printf("read(stdin) returned -1\r\n", 0, 0);
return -1;
}
}
}
static char line[256];
static char *lineptr;
static int lineleft;
#if 0
int xmon_expect(const char *str, unsigned int timeout)
{
int c;
unsigned int t0;
timeout *= TB_SPEED;
t0 = readtb();
do {
lineptr = line;
for (;;) {
c = xmon_read_poll();
if (c == -1) {
if (readtb() - t0 > timeout)
return 0;
continue;
}
if (c == '\n')
break;
if (c != '\r' && lineptr < &line[sizeof(line) - 1])
*lineptr++ = c;
}
*lineptr = 0;
} while (strstr(line, str) == NULL);
return 1;
}
#endif
int
xmon_getchar(void)
{
int c;
if (lineleft == 0) {
lineptr = line;
for (;;) {
c = xmon_readchar();
if (c == -1 || c == 4)
break;
if (c == '\r' || c == '\n') {
*lineptr++ = '\n';
xmon_putchar('\n');
break;
}
switch (c) {
case 0177:
case '\b':
if (lineptr > line) {
xmon_putchar('\b');
xmon_putchar(' ');
xmon_putchar('\b');
--lineptr;
}
break;
case 'U' & 0x1F:
while (lineptr > line) {
xmon_putchar('\b');
xmon_putchar(' ');
xmon_putchar('\b');
--lineptr;
}
break;
default:
if (lineptr >= &line[sizeof(line) - 1])
xmon_putchar('\a');
else {
xmon_putchar(c);
*lineptr++ = c;
}
}
}
lineleft = lineptr - line;
lineptr = line;
}
if (lineleft == 0)
return -1;
--lineleft;
return *lineptr++;
}
char *
xmon_fgets(char *str, int nb, void *f)
{
char *p;
int c;
for (p = str; p < str + nb - 1; ) {
c = xmon_getchar();
if (c == -1) {
if (p == str)
return 0;
break;
}
*p++ = c;
if (c == '\n')
break;
}
*p = 0;
return str;
}
void
prom_drawhex(uint val)
{
unsigned char buf[10];
int i;
for (i = 7; i >= 0; i--)
{
buf[i] = "0123456789abcdef"[val & 0x0f];
val >>= 4;
}
buf[8] = '\0';
xmon_fputs(buf, xmon_stdout);
}
void
prom_drawstring(const char *str)
{
xmon_fputs(str, xmon_stdout);
}
/*
* Written by Cort Dougan to replace the version originally used
* by Paul Mackerras, which came from NetBSD and thus had copyright
* conflicts with Linux.
*
* This file makes liberal use of the standard linux utility
* routines to reduce the size of the binary. We assume we can
* trust some parts of Linux inside the debugger.
* -- Cort (cort@cs.nmt.edu)
*
* Copyright (C) 1999 Cort Dougan.
*
* 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/kernel.h>
#include <linux/string.h>
#include <linux/module.h>
#include <stdarg.h>
#include "nonstdio.h"
extern int xmon_write(void *, void *, int);
void xmon_vfprintf(void *f, const char *fmt, va_list ap)
{
static char xmon_buf[2048];
int n;
n = vsprintf(xmon_buf, fmt, ap);
xmon_write(f, xmon_buf, n);
}
void xmon_printf(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
xmon_vfprintf(stdout, fmt, ap);
va_end(ap);
}
EXPORT_SYMBOL(xmon_printf);
void xmon_fprintf(void *f, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
xmon_vfprintf(f, fmt, ap);
va_end(ap);
}
/* /*
* Routines providing a simple monitor for use on the PowerMac. * Routines providing a simple monitor for use on the PowerMac.
* *
* Copyright (C) 1996 Paul Mackerras. * Copyright (C) 1996-2005 Paul Mackerras.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <linux/kallsyms.h> #include <linux/kallsyms.h>
#include <linux/cpumask.h> #include <linux/cpumask.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/sysrq.h>
#include <asm/ptrace.h> #include <asm/ptrace.h>
#include <asm/string.h> #include <asm/string.h>
...@@ -144,15 +145,10 @@ static void xmon_print_symbol(unsigned long address, const char *mid, ...@@ -144,15 +145,10 @@ static void xmon_print_symbol(unsigned long address, const char *mid,
static const char *getvecname(unsigned long vec); static const char *getvecname(unsigned long vec);
extern int print_insn_powerpc(unsigned long, unsigned long, int); extern int print_insn_powerpc(unsigned long, unsigned long, int);
extern void printf(const char *fmt, ...);
extern void xmon_vfprintf(void *f, const char *fmt, va_list ap);
extern int xmon_putc(int c, void *f);
extern int putchar(int ch);
extern void xmon_enter(void); extern void xmon_enter(void);
extern void xmon_leave(void); extern void xmon_leave(void);
extern int xmon_read_poll(void);
extern long setjmp(long *); extern long setjmp(long *);
extern void longjmp(long *, long); extern void longjmp(long *, long);
extern void xmon_save_regs(struct pt_regs *); extern void xmon_save_regs(struct pt_regs *);
...@@ -748,7 +744,6 @@ cmds(struct pt_regs *excp) ...@@ -748,7 +744,6 @@ cmds(struct pt_regs *excp)
printf("%x:", smp_processor_id()); printf("%x:", smp_processor_id());
#endif /* CONFIG_SMP */ #endif /* CONFIG_SMP */
printf("mon> "); printf("mon> ");
fflush(stdout);
flush_input(); flush_input();
termch = 0; termch = 0;
cmd = skipbl(); cmd = skipbl();
...@@ -1797,7 +1792,7 @@ memex(void) ...@@ -1797,7 +1792,7 @@ memex(void)
for(;;){ for(;;){
if (!mnoread) if (!mnoread)
n = mread(adrs, val, size); n = mread(adrs, val, size);
printf("%.16x%c", adrs, brev? 'r': ' '); printf(REG"%c", adrs, brev? 'r': ' ');
if (!mnoread) { if (!mnoread) {
if (brev) if (brev)
byterev(val, size); byterev(val, size);
...@@ -1976,17 +1971,18 @@ prdump(unsigned long adrs, long ndump) ...@@ -1976,17 +1971,18 @@ prdump(unsigned long adrs, long ndump)
nr = mread(adrs, temp, r); nr = mread(adrs, temp, r);
adrs += nr; adrs += nr;
for (m = 0; m < r; ++m) { for (m = 0; m < r; ++m) {
if ((m & 7) == 0 && m > 0) if ((m & (sizeof(long) - 1)) == 0 && m > 0)
putchar(' '); putchar(' ');
if (m < nr) if (m < nr)
printf("%.2x", temp[m]); printf("%.2x", temp[m]);
else else
printf("%s", fault_chars[fault_type]); printf("%s", fault_chars[fault_type]);
} }
if (m <= 8) for (; m < 16; ++m) {
printf(" "); if ((m & (sizeof(long) - 1)) == 0)
for (; m < 16; ++m) putchar(' ');
printf(" "); printf(" ");
}
printf(" |"); printf(" |");
for (m = 0; m < r; ++m) { for (m = 0; m < r; ++m) {
if (m < nr) { if (m < nr) {
...@@ -2151,7 +2147,6 @@ memzcan(void) ...@@ -2151,7 +2147,6 @@ memzcan(void)
ok = mread(a, &v, 1); ok = mread(a, &v, 1);
if (ok && !ook) { if (ok && !ook) {
printf("%.8x .. ", a); printf("%.8x .. ", a);
fflush(stdout);
} else if (!ok && ook) } else if (!ok && ook)
printf("%.8x\n", a - mskip); printf("%.8x\n", a - mskip);
ook = ok; ook = ok;
...@@ -2372,7 +2367,7 @@ int ...@@ -2372,7 +2367,7 @@ int
inchar(void) inchar(void)
{ {
if (lineptr == NULL || *lineptr == 0) { if (lineptr == NULL || *lineptr == 0) {
if (fgets(line, sizeof(line), stdin) == NULL) { if (xmon_gets(line, sizeof(line)) == NULL) {
lineptr = NULL; lineptr = NULL;
return EOF; return EOF;
} }
...@@ -2526,4 +2521,29 @@ void xmon_init(int enable) ...@@ -2526,4 +2521,29 @@ void xmon_init(int enable)
__debugger_dabr_match = NULL; __debugger_dabr_match = NULL;
__debugger_fault_handler = NULL; __debugger_fault_handler = NULL;
} }
xmon_map_scc();
}
#ifdef CONFIG_MAGIC_SYSRQ
static void sysrq_handle_xmon(int key, struct pt_regs *pt_regs,
struct tty_struct *tty)
{
/* ensure xmon is enabled */
xmon_init(1);
debugger(pt_regs);
}
static struct sysrq_key_op sysrq_xmon_op =
{
.handler = sysrq_handle_xmon,
.help_msg = "Xmon",
.action_msg = "Entering xmon",
};
static int __init setup_xmon_sysrq(void)
{
register_sysrq_key('x', &sysrq_xmon_op);
return 0;
} }
__initcall(setup_xmon_sysrq);
#endif /* CONFIG_MAGIC_SYSRQ */
...@@ -19,6 +19,9 @@ extern prom_entry of_prom_entry; ...@@ -19,6 +19,9 @@ extern prom_entry of_prom_entry;
/* function declarations */ /* function declarations */
int call_prom(const char *service, int nargs, int nret, ...);
int call_prom_ret(const char *service, int nargs, int nret,
unsigned int *rets, ...);
void * claim(unsigned int virt, unsigned int size, unsigned int align); void * claim(unsigned int virt, unsigned int size, unsigned int align);
int map(unsigned int phys, unsigned int virt, unsigned int size); int map(unsigned int phys, unsigned int virt, unsigned int size);
void enter(void); void enter(void);
......
...@@ -3,4 +3,4 @@ ...@@ -3,4 +3,4 @@
# #
lib-y := claim.o enter.o exit.o finddevice.o getprop.o ofinit.o \ lib-y := claim.o enter.o exit.o finddevice.o getprop.o ofinit.o \
ofstdio.o read.o release.o write.o map.o ofstdio.o read.o release.o write.o map.o call_prom.o
/*
* Copyright (C) 1996-2005 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 "of1275.h"
#include <stdarg.h>
int call_prom(const char *service, int nargs, int nret, ...)
{
int i;
struct prom_args {
const char *service;
int nargs;
int nret;
unsigned int args[12];
} args;
va_list list;
args.service = service;
args.nargs = nargs;
args.nret = nret;
va_start(list, nret);
for (i = 0; i < nargs; i++)
args.args[i] = va_arg(list, unsigned int);
va_end(list);
for (i = 0; i < nret; i++)
args.args[nargs+i] = 0;
if (of_prom_entry(&args) < 0)
return -1;
return (nret > 0)? args.args[nargs]: 0;
}
int call_prom_ret(const char *service, int nargs, int nret,
unsigned int *rets, ...)
{
int i;
struct prom_args {
const char *service;
int nargs;
int nret;
unsigned int args[12];
} args;
va_list list;
args.service = service;
args.nargs = nargs;
args.nret = nret;
va_start(list, rets);
for (i = 0; i < nargs; i++)
args.args[i] = va_arg(list, unsigned int);
va_end(list);
for (i = 0; i < nret; i++)
args.args[nargs+i] = 0;
if (of_prom_entry(&args) < 0)
return -1;
if (rets != (void *) 0)
for (i = 1; i < nret; ++i)
rets[i-1] = args.args[nargs+i];
return (nret > 0)? args.args[nargs]: 0;
}
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册