Commit a2c584bb authored by Peter Bergner's avatar Peter Bergner

Merge bk://ppc.bkbits.net/for-linus-ppc64

into brule.rchland.ibm.com:/u3/ppc64/linux-2.5-bergner
parents c03cd467 b9c4e8df
...@@ -61,7 +61,7 @@ struct HvReleaseData hvReleaseData = { ...@@ -61,7 +61,7 @@ struct HvReleaseData hvReleaseData = {
0xc8a5d9c4, /* desc = "HvRD" ebcdic */ 0xc8a5d9c4, /* desc = "HvRD" ebcdic */
sizeof(struct HvReleaseData), sizeof(struct HvReleaseData),
offsetof(struct naca_struct, xItVpdAreas), offsetof(struct naca_struct, xItVpdAreas),
(struct naca_struct *)(KERNELBASE+0x4000), /* 64-bit Naca address */ (struct naca_struct *)(NACA_VIRT_ADDR), /* 64-bit Naca address */
0x6000, /* offset of LparMap within loadarea (see head.S) */ 0x6000, /* offset of LparMap within loadarea (see head.S) */
0, 0,
1, /* tags inactive */ 1, /* tags inactive */
......
...@@ -15,7 +15,7 @@ obj-$(CONFIG_PPC_ISERIES) += iSeries_pci.o iSeries_pci_reset.o \ ...@@ -15,7 +15,7 @@ obj-$(CONFIG_PPC_ISERIES) += iSeries_pci.o iSeries_pci_reset.o \
iSeries_IoMmTable.o iSeries_irq.o \ iSeries_IoMmTable.o iSeries_irq.o \
iSeries_VpdInfo.o XmPciLpEvent.o \ iSeries_VpdInfo.o XmPciLpEvent.o \
HvCall.o HvLpConfig.o LparData.o mf_proc.o \ HvCall.o HvLpConfig.o LparData.o mf_proc.o \
proc_pmc.o iSeries_setup.o ItLpQueue.o hvCall.o \ iSeries_setup.o ItLpQueue.o hvCall.o \
mf.o HvLpEvent.o iSeries_proc.o mf.o HvLpEvent.o iSeries_proc.o
obj-$(CONFIG_PPC_PSERIES) += pSeries_pci.o pSeries_lpar.o pSeries_hvCall.o \ obj-$(CONFIG_PPC_PSERIES) += pSeries_pci.o pSeries_lpar.o pSeries_hvCall.o \
...@@ -25,6 +25,7 @@ obj-$(CONFIG_PPC_PSERIES) += pSeries_pci.o pSeries_lpar.o pSeries_hvCall.o \ ...@@ -25,6 +25,7 @@ obj-$(CONFIG_PPC_PSERIES) += pSeries_pci.o pSeries_lpar.o pSeries_hvCall.o \
obj-y += open_pic.o xics.o pSeries_htab.o rtas.o \ obj-y += open_pic.o xics.o pSeries_htab.o rtas.o \
chrp_setup.o i8259.o ras.o prom.o chrp_setup.o i8259.o ras.o prom.o
obj-$(CONFIG_PROC_FS) += proc_ppc64.o
obj-$(CONFIG_RTAS_FLASH) += rtas_flash.o obj-$(CONFIG_RTAS_FLASH) += rtas_flash.o
obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_MODULES) += module.o ppc_ksyms.o obj-$(CONFIG_MODULES) += module.o ppc_ksyms.o
......
...@@ -309,6 +309,7 @@ fix_alignment(struct pt_regs *regs) ...@@ -309,6 +309,7 @@ fix_alignment(struct pt_regs *regs)
/* Doing stfs, have to convert to single */ /* Doing stfs, have to convert to single */
enable_kernel_fp(); enable_kernel_fp();
cvt_df(&current->thread.fpr[reg], (float *)&data.v[4], &current->thread.fpscr); cvt_df(&current->thread.fpr[reg], (float *)&data.v[4], &current->thread.fpscr);
disable_kernel_fp();
} }
else else
data.dd = current->thread.fpr[reg]; data.dd = current->thread.fpr[reg];
...@@ -342,6 +343,7 @@ fix_alignment(struct pt_regs *regs) ...@@ -342,6 +343,7 @@ fix_alignment(struct pt_regs *regs)
/* Doing lfs, have to convert to double */ /* Doing lfs, have to convert to double */
enable_kernel_fp(); enable_kernel_fp();
cvt_fd((float *)&data.v[4], &current->thread.fpr[reg], &current->thread.fpscr); cvt_fd((float *)&data.v[4], &current->thread.fpr[reg], &current->thread.fpscr);
disable_kernel_fp();
} }
else else
current->thread.fpr[reg] = data.dd; current->thread.fpr[reg] = data.dd;
......
...@@ -59,14 +59,14 @@ int main(void) ...@@ -59,14 +59,14 @@ int main(void)
/* naca */ /* naca */
DEFINE(PACA, offsetof(struct naca_struct, paca)); DEFINE(PACA, offsetof(struct naca_struct, paca));
DEFINE(DCACHEL1LINESIZE, offsetof(struct naca_struct, dCacheL1LineSize)); DEFINE(DCACHEL1LINESIZE, offsetof(struct systemcfg, dCacheL1LineSize));
DEFINE(DCACHEL1LOGLINESIZE, offsetof(struct naca_struct, dCacheL1LogLineSize)); DEFINE(DCACHEL1LOGLINESIZE, offsetof(struct naca_struct, dCacheL1LogLineSize));
DEFINE(DCACHEL1LINESPERPAGE, offsetof(struct naca_struct, dCacheL1LinesPerPage)); DEFINE(DCACHEL1LINESPERPAGE, offsetof(struct naca_struct, dCacheL1LinesPerPage));
DEFINE(ICACHEL1LINESIZE, offsetof(struct naca_struct, iCacheL1LineSize)); DEFINE(ICACHEL1LINESIZE, offsetof(struct systemcfg, iCacheL1LineSize));
DEFINE(ICACHEL1LOGLINESIZE, offsetof(struct naca_struct, iCacheL1LogLineSize)); DEFINE(ICACHEL1LOGLINESIZE, offsetof(struct naca_struct, iCacheL1LogLineSize));
DEFINE(ICACHEL1LINESPERPAGE, offsetof(struct naca_struct, iCacheL1LinesPerPage)); DEFINE(ICACHEL1LINESPERPAGE, offsetof(struct naca_struct, iCacheL1LinesPerPage));
DEFINE(SLBSIZE, offsetof(struct naca_struct, slb_size)); DEFINE(SLBSIZE, offsetof(struct naca_struct, slb_size));
DEFINE(PLATFORM, offsetof(struct naca_struct, platform)); DEFINE(PLATFORM, offsetof(struct systemcfg, platform));
/* paca */ /* paca */
DEFINE(PACA_SIZE, sizeof(struct paca_struct)); DEFINE(PACA_SIZE, sizeof(struct paca_struct));
......
...@@ -228,6 +228,7 @@ chrp_init(unsigned long r3, unsigned long r4, unsigned long r5, ...@@ -228,6 +228,7 @@ chrp_init(unsigned long r3, unsigned long r4, unsigned long r5,
#endif /* CONFIG_BLK_DEV_INITRD */ #endif /* CONFIG_BLK_DEV_INITRD */
#endif #endif
ppc_md.ppc_machine = systemcfg->platform;
ppc_md.setup_arch = chrp_setup_arch; ppc_md.setup_arch = chrp_setup_arch;
ppc_md.setup_residual = NULL; ppc_md.setup_residual = NULL;
ppc_md.get_cpuinfo = chrp_get_cpuinfo; ppc_md.get_cpuinfo = chrp_get_cpuinfo;
......
...@@ -225,10 +225,6 @@ _GLOBAL(ppc32_rt_sigreturn) ...@@ -225,10 +225,6 @@ _GLOBAL(ppc32_rt_sigreturn)
bl .sys32_rt_sigreturn bl .sys32_rt_sigreturn
b 80f b 80f
_GLOBAL(ppc64_sigreturn)
bl .sys_sigreturn
b 80f
_GLOBAL(ppc64_rt_sigreturn) _GLOBAL(ppc64_rt_sigreturn)
bl .sys_rt_sigreturn bl .sys_rt_sigreturn
......
...@@ -29,6 +29,8 @@ ...@@ -29,6 +29,8 @@
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/page.h> #include <asm/page.h>
#include <asm/mmu.h> #include <asm/mmu.h>
#include <asm/naca.h>
#include <asm/systemcfg.h>
#include <asm/ppc_asm.h> #include <asm/ppc_asm.h>
#include <asm/offsets.h> #include <asm/offsets.h>
#include <asm/bug.h> #include <asm/bug.h>
...@@ -49,8 +51,9 @@ ...@@ -49,8 +51,9 @@
* 0x0100 - 0x2fff : pSeries Interrupt prologs * 0x0100 - 0x2fff : pSeries Interrupt prologs
* 0x3000 - 0x3fff : Interrupt support * 0x3000 - 0x3fff : Interrupt support
* 0x4000 - 0x4fff : NACA * 0x4000 - 0x4fff : NACA
* 0x5000 - 0x5fff : Initial segment table * 0x5000 - 0x5fff : SystemCfg
* 0x6000 : iSeries and common interrupt prologs * 0x6000 : iSeries and common interrupt prologs
* 0x9000 - 0x9fff : Initial segment table
*/ */
/* /*
...@@ -123,6 +126,10 @@ __secondary_hold_acknowledge: ...@@ -123,6 +126,10 @@ __secondary_hold_acknowledge:
* All of it must fit below the first exception vector at 0x100. * All of it must fit below the first exception vector at 0x100.
*/ */
_GLOBAL(__secondary_hold) _GLOBAL(__secondary_hold)
mfmsr r24
ori r24,r24,MSR_RI
mtmsrd r24 /* RI on */
/* Grab our linux cpu number */ /* Grab our linux cpu number */
mr r24,r3 mr r24,r3
...@@ -362,11 +369,11 @@ __start_interrupts: ...@@ -362,11 +369,11 @@ __start_interrupts:
STD_EXCEPTION_PSERIES( 0x1300, InstructionBreakpoint ) STD_EXCEPTION_PSERIES( 0x1300, InstructionBreakpoint )
/* Space for the naca. Architected to be located at real address /* Space for the naca. Architected to be located at real address
* 0x4000. Various tools rely on this location being fixed. * NACA_PHYS_ADDR. Various tools rely on this location being fixed.
* The first dword of the naca is required by iSeries LPAR to * The first dword of the naca is required by iSeries LPAR to
* point to itVpdAreas. On pSeries native, this value is not used. * point to itVpdAreas. On pSeries native, this value is not used.
*/ */
. = 0x4000 . = NACA_PHYS_ADDR
.globl __end_interrupts .globl __end_interrupts
.globl __start_naca .globl __start_naca
__end_interrupts: __end_interrupts:
...@@ -380,21 +387,14 @@ __start_naca: ...@@ -380,21 +387,14 @@ __start_naca:
.llong 0x0 .llong 0x0
.llong paca .llong paca
/* . = SYSTEMCFG_PHYS_ADDR
* Space for the initial segment table
* For LPAR, the hypervisor must fill in at least one entry
* before we get control (with relocate on)
*/
. = 0x5000
.globl __end_naca .globl __end_naca
.globl __start_stab .globl __start_systemcfg
__end_naca: __end_naca:
__start_stab: __start_systemcfg:
. = (SYSTEMCFG_PHYS_ADDR + PAGE_SIZE)
.globl __end_systemcfg
. = 0x6000 __end_systemcfg:
.globl __end_stab
__end_stab:
#ifdef CONFIG_PPC_ISERIES #ifdef CONFIG_PPC_ISERIES
/* /*
...@@ -408,7 +408,7 @@ __end_stab: ...@@ -408,7 +408,7 @@ __end_stab:
.llong 1 /* # ESIDs to be mapped by hypervisor */ .llong 1 /* # ESIDs to be mapped by hypervisor */
.llong 1 /* # memory ranges to be mapped by hypervisor */ .llong 1 /* # memory ranges to be mapped by hypervisor */
.llong 5 /* Page # of segment table within load area */ .llong STAB0_PAGE /* Page # of segment table within load area */
.llong 0 /* Reserved */ .llong 0 /* Reserved */
.llong 0 /* Reserved */ .llong 0 /* Reserved */
.llong 0 /* Reserved */ .llong 0 /* Reserved */
...@@ -529,6 +529,20 @@ SystemReset_FWNMI: ...@@ -529,6 +529,20 @@ SystemReset_FWNMI:
MachineCheck_FWNMI: MachineCheck_FWNMI:
EXCEPTION_PROLOG_PSERIES(0x200, MachineCheck_common) EXCEPTION_PROLOG_PSERIES(0x200, MachineCheck_common)
/*
* Space for the initial segment table
* For LPAR, the hypervisor must fill in at least one entry
* before we get control (with relocate on)
*/
. = STAB0_PHYS_ADDR
.globl __start_stab
__start_stab:
. = (STAB0_PHYS_ADDR + PAGE_SIZE)
.globl __end_stab
__end_stab:
/*** Common interrupt handlers ***/ /*** Common interrupt handlers ***/
STD_EXCEPTION_COMMON( 0x100, SystemReset, .SystemResetException ) STD_EXCEPTION_COMMON( 0x100, SystemReset, .SystemResetException )
...@@ -782,11 +796,16 @@ ProgramCheck_common: ...@@ -782,11 +796,16 @@ ProgramCheck_common:
FPUnavailable_common: FPUnavailable_common:
EXCEPTION_PROLOG_COMMON EXCEPTION_PROLOG_COMMON
bne .load_up_fpu /* if from user, just load it up */ bne .load_up_fpu /* if from user, just load it up */
li r20,0 addi r3,r1,STACK_FRAME_OVERHEAD
#ifdef DO_SOFT_DISABLE
ld r20,SOFTE(r1)
#else
rldicl r20,r23,49,63 /* copy EE bit from saved MSR */
#endif
li r6,0x800 li r6,0x800
bl .save_remaining_regs /* if from kernel, take a trap */ bl .save_remaining_regs
bl .KernelFP bl .KernelFPUnavailableException
b .ret_from_except BUG_OPCODE
.globl SystemCall_common .globl SystemCall_common
SystemCall_common: SystemCall_common:
...@@ -1252,9 +1271,12 @@ _GLOBAL(__start_initialization_iSeries) ...@@ -1252,9 +1271,12 @@ _GLOBAL(__start_initialization_iSeries)
addi r2,r2,0x4000 addi r2,r2,0x4000
addi r2,r2,0x4000 addi r2,r2,0x4000
LOADADDR(r9,systemcfg)
SET_REG_TO_CONST(r4, SYSTEMCFG_VIRT_ADDR)
std r4,0(r9) /* set the systemcfg pointer */
LOADADDR(r9,naca) LOADADDR(r9,naca)
SET_REG_TO_CONST(r4, KERNELBASE) SET_REG_TO_CONST(r4, NACA_VIRT_ADDR)
addi r4,r4,0x4000
std r4,0(r9) /* set the naca pointer */ std r4,0(r9) /* set the naca pointer */
/* Get the pointer to the segment table */ /* Get the pointer to the segment table */
...@@ -1285,13 +1307,18 @@ _GLOBAL(__start_initialization_pSeries) ...@@ -1285,13 +1307,18 @@ _GLOBAL(__start_initialization_pSeries)
/* Relocate the TOC from a virt addr to a real addr */ /* Relocate the TOC from a virt addr to a real addr */
sub r2,r2,r3 sub r2,r2,r3
/* setup the systemcfg pointer which is needed by prom_init */
LOADADDR(r9,systemcfg)
sub r9,r9,r3 /* addr of the variable systemcfg */
SET_REG_TO_CONST(r4, SYSTEMCFG_VIRT_ADDR)
sub r4,r4,r3
std r4,0(r9) /* set the value of systemcfg */
/* setup the naca pointer which is needed by prom_init */ /* setup the naca pointer which is needed by prom_init */
LOADADDR(r9,naca) LOADADDR(r9,naca)
sub r9,r9,r3 /* addr of the variable naca */ sub r9,r9,r3 /* addr of the variable naca */
SET_REG_TO_CONST(r4, NACA_VIRT_ADDR)
SET_REG_TO_CONST(r4, KERNELBASE)
sub r4,r4,r3 sub r4,r4,r3
addi r4,r4,0x4000
std r4,0(r9) /* set the value of naca */ std r4,0(r9) /* set the value of naca */
/* DRENG / PPPBBB Fix the following comment!!! -Peter */ /* DRENG / PPPBBB Fix the following comment!!! -Peter */
...@@ -1410,11 +1437,13 @@ _STATIC(copy_and_flush) ...@@ -1410,11 +1437,13 @@ _STATIC(copy_and_flush)
copy_to_here: copy_to_here:
/* /*
* load_up_fpu(unused, unused, tsk)
* Disable FP for the task which had the FPU previously, * Disable FP for the task which had the FPU previously,
* and save its floating-point registers in its thread_struct. * and save its floating-point registers in its thread_struct.
* Enables the FPU for use in the kernel on return. * Enables the FPU for use in the kernel on return.
* On SMP we know the fpu is free, since we give it up every * On SMP we know the fpu is free, since we give it up every
* switch. -- Cort * switch (ie, no lazy save of the FP registers).
* On entry: r13 == 'current' && last_task_used_math != 'current'
*/ */
_STATIC(load_up_fpu) _STATIC(load_up_fpu)
mfmsr r5 /* grab the current MSR */ mfmsr r5 /* grab the current MSR */
...@@ -1432,27 +1461,30 @@ _STATIC(load_up_fpu) ...@@ -1432,27 +1461,30 @@ _STATIC(load_up_fpu)
ld r4,last_task_used_math@l(r3) ld r4,last_task_used_math@l(r3)
cmpi 0,r4,0 cmpi 0,r4,0
beq 1f beq 1f
addi r4,r4,THREAD /* want THREAD of last_task_used_math */ /* Save FP state to last_task_used_math's THREAD struct */
addi r4,r4,THREAD
SAVE_32FPRS(0, r4) SAVE_32FPRS(0, r4)
mffs fr0 mffs fr0
stfd fr0,THREAD_FPSCR(r4) stfd fr0,THREAD_FPSCR(r4)
/* Disable FP for last_task_used_math */
ld r5,PT_REGS(r4) ld r5,PT_REGS(r4)
ld r4,_MSR-STACK_FRAME_OVERHEAD(r5) ld r4,_MSR-STACK_FRAME_OVERHEAD(r5)
li r20,MSR_FP|MSR_FE0|MSR_FE1 li r20,MSR_FP|MSR_FE0|MSR_FE1
andc r4,r4,r20 /* disable FP for previous task */ andc r4,r4,r20
std r4,_MSR-STACK_FRAME_OVERHEAD(r5) std 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 */
ld r4,PACACURRENT(r13) ld r4,PACACURRENT(r13)
addi r5,r4,THREAD /* Get THREAD */ addi r5,r4,THREAD /* Get THREAD */
lwz r4,THREAD_FPEXC_MODE(r5) ld r4,THREAD_FPEXC_MODE(r5)
ori r23,r23,MSR_FP ori r23,r23,MSR_FP
or r23,r23,r4 or r23,r23,r4
lfd fr0,THREAD_FPSCR(r5) lfd fr0,THREAD_FPSCR(r5)
mtfsf 0xff,fr0 mtfsf 0xff,fr0
REST_32FPRS(0, r5) REST_32FPRS(0, r5)
#ifndef CONFIG_SMP #ifndef CONFIG_SMP
/* Update last_task_used_math to 'current' */
subi r4,r5,THREAD /* Back to 'current' */ subi r4,r5,THREAD /* Back to 'current' */
std r4,last_task_used_math@l(r3) std r4,last_task_used_math@l(r3)
#endif /* CONFIG_SMP */ #endif /* CONFIG_SMP */
...@@ -1460,19 +1492,16 @@ _STATIC(load_up_fpu) ...@@ -1460,19 +1492,16 @@ _STATIC(load_up_fpu)
b fast_exception_return b fast_exception_return
/* /*
* FP unavailable trap from kernel - print a message, but let * disable_kernel_fp()
* the task use FP in the kernel until it returns to user mode. * Disable the FPU.
*/ */
_GLOBAL(KernelFP) _GLOBAL(disable_kernel_fp)
ld r3,_MSR(r1) mfmsr r3
ori r3,r3,MSR_FP rldicl r0,r3,(63-MSR_FP_LG),1
std r3,_MSR(r1) /* enable use of FP after return */ rldicl r3,r0,(MSR_FP_LG+1),0
LOADADDR(r3,86f) mtmsrd r3 /* disable use of fpu now */
ld r4,PACACURRENT(r13) /* current */ isync
ld r5,_NIP(r1) blr
b .ret_from_except
86: .string "floating point used in kernel (task=%p, pc=%x)\n"
.align 4
/* /*
* giveup_fpu(tsk) * giveup_fpu(tsk)
...@@ -1562,8 +1591,8 @@ _GLOBAL(__secondary_start) ...@@ -1562,8 +1591,8 @@ _GLOBAL(__secondary_start)
sc /* HvCall_setASR */ sc /* HvCall_setASR */
#else #else
/* set the ASR */ /* set the ASR */
addi r3,0,0x4000 /* r3 = ptr to naca */ li r3,SYSTEMCFG_PHYS_ADDR /* r3 = ptr to systemcfg */
lhz r3,PLATFORM(r3) /* r3 = platform flags */ lwz r3,PLATFORM(r3) /* r3 = platform flags */
cmpldi r3,PLATFORM_PSERIES_LPAR cmpldi r3,PLATFORM_PSERIES_LPAR
bne 98f bne 98f
mfspr r3,PVR mfspr r3,PVR
...@@ -1642,10 +1671,20 @@ _STATIC(start_here_pSeries) ...@@ -1642,10 +1671,20 @@ _STATIC(start_here_pSeries)
bl .reloc_offset bl .reloc_offset
mr r26,r3 mr r26,r3
mfmsr r6
ori r6,r6,MSR_RI
mtmsrd r6 /* RI on */
/* setup the systemcfg pointer which is needed by *tab_initialize */
LOADADDR(r6,systemcfg)
sub r6,r6,r26 /* addr of the variable systemcfg */
li r27,SYSTEMCFG_PHYS_ADDR
std r27,0(r6) /* set the value of systemcfg */
/* setup the naca pointer which is needed by *tab_initialize */ /* setup the naca pointer which is needed by *tab_initialize */
LOADADDR(r6,naca) LOADADDR(r6,naca)
sub r6,r6,r26 /* addr of the variable naca */ sub r6,r6,r26 /* addr of the variable naca */
li r27,0x4000 li r27,NACA_PHYS_ADDR
std r27,0(r6) /* set the value of naca */ std r27,0(r6) /* set the value of naca */
#ifdef CONFIG_HMT #ifdef CONFIG_HMT
...@@ -1709,15 +1748,12 @@ _STATIC(start_here_pSeries) ...@@ -1709,15 +1748,12 @@ _STATIC(start_here_pSeries)
sub r13,r13,r26 /* convert to physical addr */ sub r13,r13,r26 /* convert to physical addr */
mtspr SPRG3,r13 /* PPPBBB: Temp... -Peter */ mtspr SPRG3,r13 /* PPPBBB: Temp... -Peter */
li r3,0x5000 ld r3,PACASTABREAL(r13)
std r3,PACASTABREAL(r13)
LOADADDR(r24, __start_stab)
std r24,PACASTABVIRT(r13)
ori r4,r3,1 /* turn on valid bit */ ori r4,r3,1 /* turn on valid bit */
/* set the ASR */ /* set the ASR */
addi r3,0,0x4000 /* r3 = ptr to naca */ li r3,SYSTEMCFG_PHYS_ADDR /* r3 = ptr to systemcfg */
lhz r3,PLATFORM(r3) /* r3 = platform flags */ lwz r3,PLATFORM(r3) /* r3 = platform flags */
cmpldi r3,PLATFORM_PSERIES_LPAR cmpldi r3,PLATFORM_PSERIES_LPAR
bne 98f bne 98f
mfspr r3,PVR mfspr r3,PVR
...@@ -1741,8 +1777,8 @@ _STATIC(start_here_pSeries) ...@@ -1741,8 +1777,8 @@ _STATIC(start_here_pSeries)
bl .stab_initialize bl .stab_initialize
bl .htab_initialize bl .htab_initialize
addi r3,0,0x4000 /* r3 = ptr to naca */ li r3,SYSTEMCFG_PHYS_ADDR /* r3 = ptr to systemcfg */
lhz r3,PLATFORM(r3) /* r3 = platform flags */ lwz r3,PLATFORM(r3) /* r3 = platform flags */
cmpldi r3,PLATFORM_PSERIES cmpldi r3,PLATFORM_PSERIES
bne 98f bne 98f
LOADADDR(r6,_SDR1) /* Only if NOT LPAR */ LOADADDR(r6,_SDR1) /* Only if NOT LPAR */
...@@ -1791,11 +1827,14 @@ _STATIC(start_here_common) ...@@ -1791,11 +1827,14 @@ _STATIC(start_here_common)
addi r2,r2,0x4000 addi r2,r2,0x4000
addi r2,r2,0x4000 addi r2,r2,0x4000
/* setup the naca pointer */ /* setup the systemcfg pointer */
LOADADDR(r9,naca) LOADADDR(r9,systemcfg)
SET_REG_TO_CONST(r8, SYSTEMCFG_VIRT_ADDR)
std r8,0(r9)
SET_REG_TO_CONST(r8, KERNELBASE) /* setup the naca pointer */
addi r8,r8,0x4000 LOADADDR(r9,naca)
SET_REG_TO_CONST(r8, NACA_VIRT_ADDR)
std r8,0(r9) /* set the value of the naca ptr */ std r8,0(r9) /* set the value of the naca ptr */
LOADADDR(r26, boot_cpuid) LOADADDR(r26, boot_cpuid)
...@@ -1946,7 +1985,7 @@ ioremap_dir: ...@@ -1946,7 +1985,7 @@ ioremap_dir:
hardware_int_paca0: hardware_int_paca0:
.space 8*4096 .space 8*4096
/* 1 page segment table per cpu (max 48) */ /* 1 page segment table per cpu (max 48, cpu0 allocated at STAB0_PHYS_ADDR) */
.globl stab_array .globl stab_array
stab_array: stab_array:
.space 4096 * 48 .space 4096 * 48
......
...@@ -101,7 +101,7 @@ create_pte_mapping(unsigned long start, unsigned long end, ...@@ -101,7 +101,7 @@ create_pte_mapping(unsigned long start, unsigned long end,
hpteg = ((hash & htab_data.htab_hash_mask)*HPTES_PER_GROUP); hpteg = ((hash & htab_data.htab_hash_mask)*HPTES_PER_GROUP);
if (naca->platform == PLATFORM_PSERIES_LPAR) if (systemcfg->platform == PLATFORM_PSERIES_LPAR)
ret = pSeries_lpar_hpte_insert(hpteg, va, ret = pSeries_lpar_hpte_insert(hpteg, va,
(unsigned long)__v2a(addr) >> PAGE_SHIFT, (unsigned long)__v2a(addr) >> PAGE_SHIFT,
0, mode, 1, large); 0, mode, 1, large);
...@@ -140,7 +140,7 @@ htab_initialize(void) ...@@ -140,7 +140,7 @@ htab_initialize(void)
htab_data.htab_num_ptegs = pteg_count; htab_data.htab_num_ptegs = pteg_count;
htab_data.htab_hash_mask = pteg_count - 1; htab_data.htab_hash_mask = pteg_count - 1;
if (naca->platform == PLATFORM_PSERIES) { if (systemcfg->platform == PLATFORM_PSERIES) {
/* Find storage for the HPT. Must be contiguous in /* Find storage for the HPT. Must be contiguous in
* the absolute address space. * the absolute address space.
*/ */
...@@ -165,15 +165,15 @@ htab_initialize(void) ...@@ -165,15 +165,15 @@ htab_initialize(void)
mode_rw = _PAGE_ACCESSED | _PAGE_COHERENT | PP_RWXX; mode_rw = _PAGE_ACCESSED | _PAGE_COHERENT | PP_RWXX;
/* XXX we currently map kernel text rw, should fix this */ /* XXX we currently map kernel text rw, should fix this */
if (cpu_has_largepage() && naca->physicalMemorySize > 256*MB) { if (cpu_has_largepage() && systemcfg->physicalMemorySize > 256*MB) {
create_pte_mapping((unsigned long)KERNELBASE, create_pte_mapping((unsigned long)KERNELBASE,
KERNELBASE + 256*MB, mode_rw, 0); KERNELBASE + 256*MB, mode_rw, 0);
create_pte_mapping((unsigned long)KERNELBASE + 256*MB, create_pte_mapping((unsigned long)KERNELBASE + 256*MB,
KERNELBASE + (naca->physicalMemorySize), KERNELBASE + (systemcfg->physicalMemorySize),
mode_rw, 1); mode_rw, 1);
} else { } else {
create_pte_mapping((unsigned long)KERNELBASE, create_pte_mapping((unsigned long)KERNELBASE,
KERNELBASE+(naca->physicalMemorySize), KERNELBASE+(systemcfg->physicalMemorySize),
mode_rw, 0); mode_rw, 0);
} }
} }
......
...@@ -561,13 +561,13 @@ static void __init build_iSeries_Memory_Map(void) ...@@ -561,13 +561,13 @@ static void __init build_iSeries_Memory_Map(void)
* which should be equal to * which should be equal to
* nextPhysChunk * nextPhysChunk
*/ */
naca->physicalMemorySize = chunk_to_addr(nextPhysChunk); systemcfg->physicalMemorySize = chunk_to_addr(nextPhysChunk);
/* Bolt kernel mappings for all of memory */ /* Bolt kernel mappings for all of memory */
iSeries_bolt_kernel( 0, naca->physicalMemorySize ); iSeries_bolt_kernel( 0, systemcfg->physicalMemorySize );
lmb_init(); lmb_init();
lmb_add( 0, naca->physicalMemorySize ); lmb_add( 0, systemcfg->physicalMemorySize );
lmb_analyze(); /* ?? */ lmb_analyze(); /* ?? */
lmb_reserve( 0, __pa(klimit)); lmb_reserve( 0, __pa(klimit));
...@@ -584,29 +584,28 @@ static void __init build_iSeries_Memory_Map(void) ...@@ -584,29 +584,28 @@ static void __init build_iSeries_Memory_Map(void)
static void __init setup_iSeries_cache_sizes(void) static void __init setup_iSeries_cache_sizes(void)
{ {
unsigned i,n; unsigned int i, n;
unsigned procIx = get_paca()->xLpPaca.xDynHvPhysicalProcIndex; unsigned int procIx = get_paca()->xLpPaca.xDynHvPhysicalProcIndex;
systemcfg->iCacheL1Size = xIoHriProcessorVpd[procIx].xInstCacheSize * 1024;
systemcfg->iCacheL1LineSize = xIoHriProcessorVpd[procIx].xInstCacheOperandSize;
systemcfg->dCacheL1Size = xIoHriProcessorVpd[procIx].xDataL1CacheSizeKB * 1024;
systemcfg->dCacheL1LineSize = xIoHriProcessorVpd[procIx].xDataCacheOperandSize;
naca->iCacheL1LinesPerPage = PAGE_SIZE / systemcfg->iCacheL1LineSize;
naca->dCacheL1LinesPerPage = PAGE_SIZE / systemcfg->dCacheL1LineSize;
naca->iCacheL1LineSize = xIoHriProcessorVpd[procIx].xInstCacheOperandSize; i = systemcfg->iCacheL1LineSize;
naca->dCacheL1LineSize = xIoHriProcessorVpd[procIx].xDataCacheOperandSize;
naca->iCacheL1LinesPerPage = PAGE_SIZE / naca->iCacheL1LineSize;
naca->dCacheL1LinesPerPage = PAGE_SIZE / naca->dCacheL1LineSize;
i = naca->iCacheL1LineSize;
n = 0; n = 0;
while ((i=(i/2))) ++n; while ((i=(i/2))) ++n;
naca->iCacheL1LogLineSize = n; naca->iCacheL1LogLineSize = n;
i = naca->dCacheL1LineSize;
i = systemcfg->dCacheL1LineSize;
n = 0; n = 0;
while ((i=(i/2))) ++n; while ((i=(i/2))) ++n;
naca->dCacheL1LogLineSize = n; naca->dCacheL1LogLineSize = n;
printk( "D-cache line size = %d (log = %d)\n", printk( "D-cache line size = %d\n", (unsigned int)systemcfg->dCacheL1LineSize);
(unsigned)naca->dCacheL1LineSize, printk( "I-cache line size = %d\n", (unsigned int)systemcfg->iCacheL1LineSize);
(unsigned)naca->dCacheL1LogLineSize );
printk( "I-cache line size = %d (log = %d)\n",
(unsigned)naca->iCacheL1LineSize,
(unsigned)naca->iCacheL1LogLineSize );
} }
/* /*
...@@ -648,6 +647,11 @@ iSeries_setup_arch(void) ...@@ -648,6 +647,11 @@ iSeries_setup_arch(void)
void * eventStack; void * eventStack;
unsigned procIx = get_paca()->xLpPaca.xDynHvPhysicalProcIndex; unsigned procIx = get_paca()->xLpPaca.xDynHvPhysicalProcIndex;
/* Add an eye catcher and the systemcfg layout version number */
strcpy(systemcfg->eye_catcher, "SYSTEMCFG:PPC64");
systemcfg->version.major = SYSTEMCFG_MAJOR;
systemcfg->version.minor = SYSTEMCFG_MINOR;
/* Setup the Lp Event Queue */ /* Setup the Lp Event Queue */
/* Allocate a page for the Event Stack /* Allocate a page for the Event Stack
...@@ -696,8 +700,8 @@ iSeries_setup_arch(void) ...@@ -696,8 +700,8 @@ iSeries_setup_arch(void)
printk("Time base frequency = %lu.%02lu\n", printk("Time base frequency = %lu.%02lu\n",
tbFreqMhz, tbFreqMhz,
tbFreqMhzHundreths ); tbFreqMhzHundreths );
printk("Processor version = %x\n", systemcfg->processor = xIoHriProcessorVpd[procIx].xPVR;
xIoHriProcessorVpd[procIx].xPVR ); printk("Processor version = %x\n", systemcfg->processor);
} }
...@@ -726,9 +730,9 @@ void iSeries_setup_residual(struct seq_file *m) ...@@ -726,9 +730,9 @@ void iSeries_setup_residual(struct seq_file *m)
seq_printf(m,"time base\t: %lu.%02luMHz\n", seq_printf(m,"time base\t: %lu.%02luMHz\n",
tbFreqMhz, tbFreqMhzHundreths ); tbFreqMhz, tbFreqMhzHundreths );
seq_printf(m,"i-cache\t\t: %d\n", seq_printf(m,"i-cache\t\t: %d\n",
naca->iCacheL1LineSize); systemcfg->iCacheL1LineSize);
seq_printf(m,"d-cache\t\t: %d\n", seq_printf(m,"d-cache\t\t: %d\n",
naca->dCacheL1LineSize); systemcfg->dCacheL1LineSize);
} }
......
...@@ -170,12 +170,14 @@ _GLOBAL(flush_icache_range) ...@@ -170,12 +170,14 @@ _GLOBAL(flush_icache_range)
*/ */
LOADADDR(r10,naca) /* Get Naca address */ LOADADDR(r10,naca) /* Get Naca address */
ld r10,0(r10) ld r10,0(r10)
lhz r7,DCACHEL1LINESIZE(r10) /* Get cache line size */ LOADADDR(r11,systemcfg) /* Get systemcfg address */
ld r11,0(r11)
lwz r7,DCACHEL1LINESIZE(r11)/* Get cache line size */
addi r5,r7,-1 addi r5,r7,-1
andc r6,r3,r5 /* round low to line bdy */ andc r6,r3,r5 /* round low to line bdy */
subf r8,r6,r4 /* compute length */ subf r8,r6,r4 /* compute length */
add r8,r8,r5 /* ensure we get enough */ add r8,r8,r5 /* ensure we get enough */
lhz r9,DCACHEL1LOGLINESIZE(r10) /* Get log-2 of cache line size */ lwz r9,DCACHEL1LOGLINESIZE(r10) /* Get log-2 of cache line size */
srw. r8,r8,r9 /* compute line count */ srw. r8,r8,r9 /* compute line count */
beqlr /* nothing to do? */ beqlr /* nothing to do? */
mtctr r8 mtctr r8
...@@ -186,12 +188,12 @@ _GLOBAL(flush_icache_range) ...@@ -186,12 +188,12 @@ _GLOBAL(flush_icache_range)
/* Now invalidate the instruction cache */ /* Now invalidate the instruction cache */
lhz r7,ICACHEL1LINESIZE(r10) /* Get Icache line size */ lwz r7,ICACHEL1LINESIZE(r11) /* Get Icache line size */
addi r5,r7,-1 addi r5,r7,-1
andc r6,r3,r5 /* round low to line bdy */ andc r6,r3,r5 /* round low to line bdy */
subf r8,r6,r4 /* compute length */ subf r8,r6,r4 /* compute length */
add r8,r8,r5 add r8,r8,r5
lhz r9,ICACHEL1LOGLINESIZE(r10) /* Get log-2 of Icache line size */ lwz r9,ICACHEL1LOGLINESIZE(r10) /* Get log-2 of Icache line size */
srw. r8,r8,r9 /* compute line count */ srw. r8,r8,r9 /* compute line count */
beqlr /* nothing to do? */ beqlr /* nothing to do? */
mtctr r8 mtctr r8
...@@ -217,12 +219,14 @@ _GLOBAL(flush_dcache_range) ...@@ -217,12 +219,14 @@ _GLOBAL(flush_dcache_range)
*/ */
LOADADDR(r10,naca) /* Get Naca address */ LOADADDR(r10,naca) /* Get Naca address */
ld r10,0(r10) ld r10,0(r10)
lhz r7,DCACHEL1LINESIZE(r10) /* Get dcache line size */ LOADADDR(r11,systemcfg) /* Get systemcfg address */
ld r11,0(r11)
lwz r7,DCACHEL1LINESIZE(r11) /* Get dcache line size */
addi r5,r7,-1 addi r5,r7,-1
andc r6,r3,r5 /* round low to line bdy */ andc r6,r3,r5 /* round low to line bdy */
subf r8,r6,r4 /* compute length */ subf r8,r6,r4 /* compute length */
add r8,r8,r5 /* ensure we get enough */ add r8,r8,r5 /* ensure we get enough */
lhz r9,DCACHEL1LOGLINESIZE(r10) /* Get log-2 of dcache line size */ lwz r9,DCACHEL1LOGLINESIZE(r10) /* Get log-2 of dcache line size */
srw. r8,r8,r9 /* compute line count */ srw. r8,r8,r9 /* compute line count */
beqlr /* nothing to do? */ beqlr /* nothing to do? */
mtctr r8 mtctr r8
...@@ -249,9 +253,11 @@ _GLOBAL(__flush_dcache_icache) ...@@ -249,9 +253,11 @@ _GLOBAL(__flush_dcache_icache)
/* Flush the dcache */ /* Flush the dcache */
LOADADDR(r7,naca) LOADADDR(r7,naca)
ld r7,0(r7) ld r7,0(r7)
LOADADDR(r8,systemcfg) /* Get systemcfg address */
ld r8,0(r8)
clrrdi r3,r3,12 /* Page align */ clrrdi r3,r3,12 /* Page align */
lhz r4,DCACHEL1LINESPERPAGE(r7) /* Get # dcache lines per page */ lwz r4,DCACHEL1LINESPERPAGE(r7) /* Get # dcache lines per page */
lhz r5,DCACHEL1LINESIZE(r7) /* Get dcache line size */ lwz r5,DCACHEL1LINESIZE(r8) /* Get dcache line size */
mr r6,r3 mr r6,r3
mtctr r4 mtctr r4
0: dcbst 0,r6 0: dcbst 0,r6
...@@ -261,8 +267,8 @@ _GLOBAL(__flush_dcache_icache) ...@@ -261,8 +267,8 @@ _GLOBAL(__flush_dcache_icache)
/* Now invalidate the icache */ /* Now invalidate the icache */
lhz r4,ICACHEL1LINESPERPAGE(r7) /* Get # icache lines per page */ lwz r4,ICACHEL1LINESPERPAGE(r7) /* Get # icache lines per page */
lhz r5,ICACHEL1LINESIZE(r7) /* Get icache line size */ lwz r5,ICACHEL1LINESIZE(r8) /* Get icache line size */
mtctr r4 mtctr r4
1: icbi 0,r3 1: icbi 0,r3
add r3,r3,r5 add r3,r3,r5
...@@ -574,7 +580,7 @@ _GLOBAL(sys_call_table32) ...@@ -574,7 +580,7 @@ _GLOBAL(sys_call_table32)
.llong .sys32_ssetmask .llong .sys32_ssetmask
.llong .sys_setreuid /* 70 */ .llong .sys_setreuid /* 70 */
.llong .sys_setregid .llong .sys_setregid
.llong .sys_sigsuspend .llong .sys32_sigsuspend
.llong .compat_sys_sigpending .llong .compat_sys_sigpending
.llong .sys32_sethostname .llong .sys32_sethostname
.llong .sys32_setrlimit /* 75 */ .llong .sys32_setrlimit /* 75 */
...@@ -812,13 +818,13 @@ _GLOBAL(sys_call_table) ...@@ -812,13 +818,13 @@ _GLOBAL(sys_call_table)
.llong .sys_getppid .llong .sys_getppid
.llong .sys_getpgrp /* 65 */ .llong .sys_getpgrp /* 65 */
.llong .sys_setsid .llong .sys_setsid
.llong .sys_sigaction .llong .sys_ni_syscall
.llong .sys_sgetmask .llong .sys_sgetmask
.llong .sys_ssetmask .llong .sys_ssetmask
.llong .sys_setreuid /* 70 */ .llong .sys_setreuid /* 70 */
.llong .sys_setregid .llong .sys_setregid
.llong .sys_sigsuspend .llong .sys_ni_syscall
.llong .sys_sigpending .llong .sys_ni_syscall
.llong .sys_sethostname .llong .sys_sethostname
.llong .sys_setrlimit /* 75 */ .llong .sys_setrlimit /* 75 */
.llong .sys_ni_syscall /* old getrlimit syscall */ .llong .sys_ni_syscall /* old getrlimit syscall */
...@@ -864,14 +870,14 @@ _GLOBAL(sys_call_table) ...@@ -864,14 +870,14 @@ _GLOBAL(sys_call_table)
.llong .sys_sysinfo .llong .sys_sysinfo
.llong .sys_ipc .llong .sys_ipc
.llong .sys_fsync .llong .sys_fsync
.llong .ppc64_sigreturn .llong .sys_ni_syscall
.llong .sys_clone /* 120 */ .llong .sys_clone /* 120 */
.llong .sys_setdomainname .llong .sys_setdomainname
.llong .ppc64_newuname .llong .ppc64_newuname
.llong .sys_ni_syscall /* old modify_ldt syscall */ .llong .sys_ni_syscall /* old modify_ldt syscall */
.llong .sys_adjtimex .llong .sys_adjtimex
.llong .sys_mprotect /* 125 */ .llong .sys_mprotect /* 125 */
.llong .sys_sigprocmask .llong .sys_ni_syscall
.llong .sys_ni_syscall /* old create_module syscall */ .llong .sys_ni_syscall /* old create_module syscall */
.llong .sys_init_module .llong .sys_init_module
.llong .sys_delete_module .llong .sys_delete_module
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include <asm/paca.h> #include <asm/paca.h>
struct naca_struct *naca; struct naca_struct *naca;
struct systemcfg *systemcfg;
/* The Paca is an array with one entry per processor. Each contains an /* The Paca is an array with one entry per processor. Each contains an
* ItLpPaca, which contains the information shared between the * ItLpPaca, which contains the information shared between the
...@@ -65,9 +66,9 @@ struct naca_struct *naca; ...@@ -65,9 +66,9 @@ struct naca_struct *naca;
struct paca_struct paca[MAX_PACAS] __page_aligned = { struct paca_struct paca[MAX_PACAS] __page_aligned = {
#ifdef CONFIG_PPC_ISERIES #ifdef CONFIG_PPC_ISERIES
PACAINITDATA( 0, 1, &xItLpQueue, 0, 0xc000000000005000), PACAINITDATA( 0, 1, &xItLpQueue, 0, STAB0_VIRT_ADDR),
#else #else
PACAINITDATA( 0, 1, 0, 0x5000, 0xc000000000005000), PACAINITDATA( 0, 1, 0, STAB0_PHYS_ADDR, STAB0_VIRT_ADDR),
#endif #endif
PACAINITDATA( 1, 0, 0, 0, 0), PACAINITDATA( 1, 0, 0, 0, 0),
PACAINITDATA( 2, 0, 0, 0, 0), PACAINITDATA( 2, 0, 0, 0, 0),
......
...@@ -134,7 +134,7 @@ static inline struct TceTable *get_tce_table(struct pci_dev *dev) ...@@ -134,7 +134,7 @@ static inline struct TceTable *get_tce_table(struct pci_dev *dev)
dev = ppc64_isabridge_dev; dev = ppc64_isabridge_dev;
if (!dev) if (!dev)
return NULL; return NULL;
if (naca->platform == PLATFORM_ISERIES_LPAR) { if (systemcfg->platform == PLATFORM_ISERIES_LPAR) {
return ISERIES_DEVNODE(dev)->DevTceTable; return ISERIES_DEVNODE(dev)->DevTceTable;
} else { } else {
return PCI_GET_DN(dev)->tce_table; return PCI_GET_DN(dev)->tce_table;
...@@ -732,7 +732,7 @@ void create_tce_tables(void) { ...@@ -732,7 +732,7 @@ void create_tce_tables(void) {
struct pci_dev *dev; struct pci_dev *dev;
struct device_node *dn, *mydn; struct device_node *dn, *mydn;
if (naca->platform == PLATFORM_PSERIES_LPAR) { if (systemcfg->platform == PLATFORM_PSERIES_LPAR) {
create_tce_tables_for_busesLP(&pci_root_buses); create_tce_tables_for_busesLP(&pci_root_buses);
} }
else { else {
...@@ -773,7 +773,7 @@ void create_pci_bus_tce_table( unsigned long token ) { ...@@ -773,7 +773,7 @@ void create_pci_bus_tce_table( unsigned long token ) {
/* - Tce Table Share between buses, */ /* - Tce Table Share between buses, */
/* - Tce Table per logical slot. */ /* - Tce Table per logical slot. */
/*****************************************************************/ /*****************************************************************/
if(naca->platform == PLATFORM_ISERIES_LPAR) { if(systemcfg->platform == PLATFORM_ISERIES_LPAR) {
struct iSeries_Device_Node* DevNode = (struct iSeries_Device_Node*)token; struct iSeries_Device_Node* DevNode = (struct iSeries_Device_Node*)token;
getTceTableParmsiSeries(DevNode,newTceTable); getTceTableParmsiSeries(DevNode,newTceTable);
...@@ -797,7 +797,7 @@ void create_pci_bus_tce_table( unsigned long token ) { ...@@ -797,7 +797,7 @@ void create_pci_bus_tce_table( unsigned long token ) {
dn = (struct device_node *)token; dn = (struct device_node *)token;
phb = dn->phb; phb = dn->phb;
if (naca->platform == PLATFORM_PSERIES) if (systemcfg->platform == PLATFORM_PSERIES)
getTceTableParmsPSeries(phb, dn, newTceTable); getTceTableParmsPSeries(phb, dn, newTceTable);
else else
getTceTableParmsPSeriesLP(phb, dn, newTceTable); getTceTableParmsPSeriesLP(phb, dn, newTceTable);
......
/*
* arch/ppc64/kernel/proc_ppc64.c
*
* Copyright (C) 2001 Mike Corrigan & Dave Engebretsen IBM Corporation
*
* 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
*/
/*
* Change Activity:
* 2001 : mikec : Created
* 2001/06/05 : engebret : Software event count support.
* 2003/02/13 : bergner : Move PMC code to pmc.c
* End Change Activity
*/
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/proc_fs.h>
#include <asm/proc_fs.h>
#include <asm/naca.h>
#include <asm/paca.h>
#include <asm/systemcfg.h>
#include <asm/rtas.h>
#include <asm/uaccess.h>
struct proc_ppc64_t proc_ppc64;
void proc_ppc64_create_paca(int num);
static loff_t page_map_seek( struct file *file, loff_t off, int whence);
static ssize_t page_map_read( struct file *file, char *buf, size_t nbytes, loff_t *ppos);
static int page_map_mmap( struct file *file, struct vm_area_struct *vma );
static struct file_operations page_map_fops = {
llseek: page_map_seek,
read: page_map_read,
mmap: page_map_mmap
};
static int __init proc_ppc64_init(void)
{
printk(KERN_INFO "proc_ppc64: Creating /proc/ppc64/\n");
proc_ppc64.root = proc_mkdir("ppc64", 0);
if (!proc_ppc64.root)
return 0;
proc_ppc64.naca = create_proc_entry("naca", S_IRUSR, proc_ppc64.root);
if ( proc_ppc64.naca ) {
proc_ppc64.naca->nlink = 1;
proc_ppc64.naca->data = naca;
proc_ppc64.naca->size = 4096;
proc_ppc64.naca->proc_fops = &page_map_fops;
}
proc_ppc64.systemcfg = create_proc_entry("systemcfg", S_IFREG|S_IRUGO, proc_ppc64.root);
if ( proc_ppc64.systemcfg ) {
proc_ppc64.systemcfg->nlink = 1;
proc_ppc64.systemcfg->data = systemcfg;
proc_ppc64.systemcfg->size = 4096;
proc_ppc64.systemcfg->proc_fops = &page_map_fops;
}
/* /proc/ppc64/paca/XX -- raw paca contents. Only readable to root */
proc_ppc64.paca = proc_mkdir("paca", proc_ppc64.root);
if (proc_ppc64.paca) {
unsigned long i;
for (i = 0; i < NR_CPUS; i++) {
if (!cpu_online(i))
continue;
proc_ppc64_create_paca(i);
}
}
/* Placeholder for rtas interfaces. */
proc_ppc64.rtas = proc_mkdir("rtas", proc_ppc64.root);
return 0;
}
/*
* NOTE: since paca data is always in flux the values will never be a consistant set.
* In theory it could be made consistent if we made the corresponding cpu
* copy the page for us (via an IPI). Probably not worth it.
*
*/
void proc_ppc64_create_paca(int num)
{
struct proc_dir_entry *ent;
struct paca_struct *lpaca = paca + num;
char buf[16];
sprintf(buf, "%02x", num);
ent = create_proc_entry(buf, S_IRUSR, proc_ppc64.paca);
if ( ent ) {
ent->nlink = 1;
ent->data = lpaca;
ent->size = 4096;
ent->proc_fops = &page_map_fops;
}
}
static loff_t page_map_seek( struct file *file, loff_t off, int whence)
{
loff_t new;
struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
switch(whence) {
case 0:
new = off;
break;
case 1:
new = file->f_pos + off;
break;
case 2:
new = dp->size + off;
break;
default:
return -EINVAL;
}
if ( new < 0 || new > dp->size )
return -EINVAL;
return (file->f_pos = new);
}
static ssize_t page_map_read( struct file *file, char *buf, size_t nbytes, loff_t *ppos)
{
unsigned pos = *ppos;
struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
if ( pos >= dp->size )
return 0;
if ( nbytes >= dp->size )
nbytes = dp->size;
if ( pos + nbytes > dp->size )
nbytes = dp->size - pos;
copy_to_user( buf, (char *)dp->data + pos, nbytes );
*ppos = pos + nbytes;
return nbytes;
}
static int page_map_mmap( struct file *file, struct vm_area_struct *vma )
{
struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
vma->vm_flags |= VM_SHM | VM_LOCKED;
if ((vma->vm_end - vma->vm_start) > dp->size)
return -EINVAL;
remap_page_range( vma, vma->vm_start, __pa(dp->data), dp->size, vma->vm_page_prot );
return 0;
}
fs_initcall(proc_ppc64_init);
...@@ -118,7 +118,6 @@ static interpret_func interpret_root_props; ...@@ -118,7 +118,6 @@ static interpret_func interpret_root_props;
#define FB_MAX 8 #define FB_MAX 8
#endif #endif
static int ppc64_is_smp;
struct prom_t prom = { struct prom_t prom = {
0, /* entry */ 0, /* entry */
...@@ -301,7 +300,9 @@ prom_initialize_naca(unsigned long mem) ...@@ -301,7 +300,9 @@ prom_initialize_naca(unsigned long mem)
unsigned long offset = reloc_offset(); unsigned long offset = reloc_offset();
struct prom_t *_prom = PTRRELOC(&prom); struct prom_t *_prom = PTRRELOC(&prom);
struct naca_struct *_naca = RELOC(naca); struct naca_struct *_naca = RELOC(naca);
struct systemcfg *_systemcfg = RELOC(systemcfg);
/* NOTE: _naca->debug_switch is already initialized. */
#ifdef DEBUG_PROM #ifdef DEBUG_PROM
prom_print(RELOC("prom_initialize_naca: start...\n")); prom_print(RELOC("prom_initialize_naca: start...\n"));
#endif #endif
...@@ -320,25 +321,35 @@ prom_initialize_naca(unsigned long mem) ...@@ -320,25 +321,35 @@ prom_initialize_naca(unsigned long mem)
* d-cache and i-cache sizes... -Peter * d-cache and i-cache sizes... -Peter
*/ */
if ( num_cpus == 1 ) { if ( num_cpus == 1 ) {
u32 size; u32 size, lsize;
call_prom(RELOC("getprop"), 4, 1, node, call_prom(RELOC("getprop"), 4, 1, node,
RELOC("d-cache-line-size"), RELOC("d-cache-size"),
&size, sizeof(size)); &size, sizeof(size));
_naca->dCacheL1LineSize = size; call_prom(RELOC("getprop"), 4, 1, node,
_naca->dCacheL1LogLineSize = __ilog2(size); RELOC("d-cache-line-size"),
_naca->dCacheL1LinesPerPage = PAGE_SIZE / size; &lsize, sizeof(lsize));
_systemcfg->dCacheL1Size = size;
_systemcfg->dCacheL1LineSize = lsize;
_naca->dCacheL1LogLineSize = __ilog2(lsize);
_naca->dCacheL1LinesPerPage = PAGE_SIZE/lsize;
call_prom(RELOC("getprop"), 4, 1, node, call_prom(RELOC("getprop"), 4, 1, node,
RELOC("i-cache-line-size"), RELOC("i-cache-size"),
&size, sizeof(size)); &size, sizeof(size));
_naca->iCacheL1LineSize = size; call_prom(RELOC("getprop"), 4, 1, node,
_naca->iCacheL1LogLineSize = __ilog2(size); RELOC("i-cache-line-size"),
_naca->iCacheL1LinesPerPage = PAGE_SIZE / size; &lsize, sizeof(lsize));
_systemcfg->iCacheL1Size = size;
_systemcfg->iCacheL1LineSize = lsize;
_naca->iCacheL1LogLineSize = __ilog2(lsize);
_naca->iCacheL1LinesPerPage = PAGE_SIZE/lsize;
if (_naca->platform == PLATFORM_PSERIES_LPAR) { if (_systemcfg->platform == PLATFORM_PSERIES_LPAR) {
u32 pft_size[2]; u32 pft_size[2];
call_prom(RELOC("getprop"), 4, 1, node, call_prom(RELOC("getprop"), 4, 1, node,
RELOC("ibm,pft-size"), RELOC("ibm,pft-size"),
...@@ -408,20 +419,17 @@ prom_initialize_naca(unsigned long mem) ...@@ -408,20 +419,17 @@ prom_initialize_naca(unsigned long mem)
} }
/* We gotta have at least 1 cpu... */ /* We gotta have at least 1 cpu... */
if (num_cpus < 1) if ( (_systemcfg->processorCount = num_cpus) < 1 )
PROM_BUG(); PROM_BUG();
if (num_cpus > 1) _systemcfg->physicalMemorySize = lmb_phys_mem_size();
RELOC(ppc64_is_smp) = 1;
_naca->physicalMemorySize = lmb_phys_mem_size(); if (_systemcfg->platform == PLATFORM_PSERIES) {
if (_naca->platform == PLATFORM_PSERIES) {
unsigned long rnd_mem_size, pteg_count; unsigned long rnd_mem_size, pteg_count;
/* round mem_size up to next power of 2 */ /* round mem_size up to next power of 2 */
rnd_mem_size = 1UL << __ilog2(_naca->physicalMemorySize); rnd_mem_size = 1UL << __ilog2(_systemcfg->physicalMemorySize);
if (rnd_mem_size < _naca->physicalMemorySize) if (rnd_mem_size < _systemcfg->physicalMemorySize)
rnd_mem_size <<= 1; rnd_mem_size <<= 1;
/* # pages / 2 */ /* # pages / 2 */
...@@ -442,49 +450,43 @@ prom_initialize_naca(unsigned long mem) ...@@ -442,49 +450,43 @@ prom_initialize_naca(unsigned long mem)
*/ */
_naca->slb_size = 64; _naca->slb_size = 64;
#ifdef DEBUG_PROM /* Add an eye catcher and the systemcfg layout version number */
prom_print(RELOC("naca->physicalMemorySize = 0x")); strcpy(_systemcfg->eye_catcher, RELOC("SYSTEMCFG:PPC64"));
prom_print_hex(_naca->physicalMemorySize); _systemcfg->version.major = SYSTEMCFG_MAJOR;
prom_print_nl(); _systemcfg->version.minor = SYSTEMCFG_MINOR;
_systemcfg->processor = _get_PVR();
prom_print(RELOC("naca->pftSize = 0x"));
prom_print_hex(_naca->pftSize);
prom_print_nl();
prom_print(RELOC("naca->dCacheL1LineSize = 0x"));
prom_print_hex(_naca->dCacheL1LineSize);
prom_print_nl();
prom_print(RELOC("naca->dCacheL1LogLineSize = 0x")); #ifdef DEBUG_PROM
prom_print_hex(_naca->dCacheL1LogLineSize); prom_print(RELOC("systemcfg->processorCount = 0x"));
prom_print_hex(_systemcfg->processorCount);
prom_print_nl(); prom_print_nl();
prom_print(RELOC("naca->dCacheL1LinesPerPage = 0x")); prom_print(RELOC("systemcfg->physicalMemorySize = 0x"));
prom_print_hex(_naca->dCacheL1LinesPerPage); prom_print_hex(_systemcfg->physicalMemorySize);
prom_print_nl(); prom_print_nl();
prom_print(RELOC("naca->iCacheL1LineSize = 0x")); prom_print(RELOC("naca->pftSize = 0x"));
prom_print_hex(_naca->iCacheL1LineSize); prom_print_hex(_naca->pftSize);
prom_print_nl(); prom_print_nl();
prom_print(RELOC("naca->iCacheL1LogLineSize = 0x")); prom_print(RELOC("systemcfg->dCacheL1LineSize = 0x"));
prom_print_hex(_naca->iCacheL1LogLineSize); prom_print_hex(_systemcfg->dCacheL1LineSize);
prom_print_nl(); prom_print_nl();
prom_print(RELOC("naca->iCacheL1LinesPerPage = 0x")); prom_print(RELOC("systemcfg->iCacheL1LineSize = 0x"));
prom_print_hex(_naca->iCacheL1LinesPerPage); prom_print_hex(_systemcfg->iCacheL1LineSize);
prom_print_nl(); prom_print_nl();
prom_print(RELOC("naca->serialPortAddr = 0x")); prom_print(RELOC("naca->serialPortAddr = 0x"));
prom_print_hex(_naca->serialPortAddr); prom_print_hex(_naca->serialPortAddr);
prom_print_nl(); prom_print_nl();
prom_print(RELOC("naca->interrupt_controller = 0x")); prom_print(RELOC("naca->interrupt_controller = 0x"));
prom_print_hex(_naca->interrupt_controller); prom_print_hex(_naca->interrupt_controller);
prom_print_nl(); prom_print_nl();
prom_print(RELOC("naca->platform = 0x")); prom_print(RELOC("systemcfg->platform = 0x"));
prom_print_hex(_naca->platform); prom_print_hex(_systemcfg->platform);
prom_print_nl(); prom_print_nl();
prom_print(RELOC("prom_initialize_naca: end...\n")); prom_print(RELOC("prom_initialize_naca: end...\n"));
...@@ -549,7 +551,7 @@ prom_instantiate_rtas(void) ...@@ -549,7 +551,7 @@ prom_instantiate_rtas(void)
unsigned long offset = reloc_offset(); unsigned long offset = reloc_offset();
struct prom_t *_prom = PTRRELOC(&prom); struct prom_t *_prom = PTRRELOC(&prom);
struct rtas_t *_rtas = PTRRELOC(&rtas); struct rtas_t *_rtas = PTRRELOC(&rtas);
struct naca_struct *_naca = RELOC(naca); struct systemcfg *_systemcfg = RELOC(systemcfg);
ihandle prom_rtas; ihandle prom_rtas;
u32 getprop_rval; u32 getprop_rval;
...@@ -565,7 +567,7 @@ prom_instantiate_rtas(void) ...@@ -565,7 +567,7 @@ prom_instantiate_rtas(void)
RELOC("ibm,hypertas-functions"), RELOC("ibm,hypertas-functions"),
hypertas_funcs, hypertas_funcs,
sizeof(hypertas_funcs))) > 0) { sizeof(hypertas_funcs))) > 0) {
_naca->platform = PLATFORM_PSERIES_LPAR; _systemcfg->platform = PLATFORM_PSERIES_LPAR;
} }
call_prom(RELOC("getprop"), call_prom(RELOC("getprop"),
...@@ -582,7 +584,7 @@ prom_instantiate_rtas(void) ...@@ -582,7 +584,7 @@ prom_instantiate_rtas(void)
* of physical memory (or within the RMO region) because RTAS * of physical memory (or within the RMO region) because RTAS
* runs in 32-bit mode and relocate off. * runs in 32-bit mode and relocate off.
*/ */
if ( _naca->platform == PLATFORM_PSERIES_LPAR ) { if ( _systemcfg->platform == PLATFORM_PSERIES_LPAR ) {
struct lmb *_lmb = PTRRELOC(&lmb); struct lmb *_lmb = PTRRELOC(&lmb);
rtas_region = min(_lmb->rmo_size, RTAS_INSTANTIATE_MAX); rtas_region = min(_lmb->rmo_size, RTAS_INSTANTIATE_MAX);
} }
...@@ -773,7 +775,7 @@ prom_initialize_tce_table(void) ...@@ -773,7 +775,7 @@ prom_initialize_tce_table(void)
align = (minalign < minsize) ? minsize : minalign; align = (minalign < minsize) ? minsize : minalign;
/* Carve out storage for the TCE table. */ /* Carve out storage for the TCE table. */
base = lmb_alloc(8UL << 20, 8UL << 20); base = lmb_alloc(minsize, align);
if ( !base ) { if ( !base ) {
prom_print(RELOC("ERROR, cannot find space for TCE table.\n")); prom_print(RELOC("ERROR, cannot find space for TCE table.\n"));
...@@ -875,7 +877,7 @@ static void ...@@ -875,7 +877,7 @@ static void
prom_hold_cpus(unsigned long mem) prom_hold_cpus(unsigned long mem)
{ {
unsigned long i; unsigned long i;
unsigned int reg; unsigned int cpuid;
phandle node; phandle node;
unsigned long offset = reloc_offset(); unsigned long offset = reloc_offset();
char type[64], *path; char type[64], *path;
...@@ -885,9 +887,13 @@ prom_hold_cpus(unsigned long mem) ...@@ -885,9 +887,13 @@ prom_hold_cpus(unsigned long mem)
unsigned long *spinloop = __v2a(&__secondary_hold_spinloop); unsigned long *spinloop = __v2a(&__secondary_hold_spinloop);
unsigned long *acknowledge = __v2a(&__secondary_hold_acknowledge); unsigned long *acknowledge = __v2a(&__secondary_hold_acknowledge);
unsigned long secondary_hold = (unsigned long)__v2a(*PTRRELOC((unsigned long *)__secondary_hold)); unsigned long secondary_hold = (unsigned long)__v2a(*PTRRELOC((unsigned long *)__secondary_hold));
struct systemcfg *_systemcfg = RELOC(systemcfg);
struct paca_struct *_xPaca = PTRRELOC(&paca[0]); struct paca_struct *_xPaca = PTRRELOC(&paca[0]);
struct prom_t *_prom = PTRRELOC(&prom); struct prom_t *_prom = PTRRELOC(&prom);
/* Initially, we must have one active CPU. */
_systemcfg->processorCount = 1;
#ifdef DEBUG_PROM #ifdef DEBUG_PROM
prom_print(RELOC("prom_hold_cpus: start...\n")); prom_print(RELOC("prom_hold_cpus: start...\n"));
prom_print(RELOC(" 1) spinloop = 0x")); prom_print(RELOC(" 1) spinloop = 0x"));
...@@ -933,12 +939,12 @@ prom_hold_cpus(unsigned long mem) ...@@ -933,12 +939,12 @@ prom_hold_cpus(unsigned long mem)
if (strcmp(type, RELOC("okay")) != 0) if (strcmp(type, RELOC("okay")) != 0)
continue; continue;
reg = -1; cpuid = -1;
call_prom(RELOC("getprop"), 4, 1, node, RELOC("reg"), call_prom(RELOC("getprop"), 4, 1, node, RELOC("reg"),
&reg, sizeof(reg)); &cpuid, sizeof(cpuid));
/* Only need to start secondary procs, not ourself. */ /* Only need to start secondary procs, not ourself. */
if ( reg == _prom->cpu ) if ( cpuid == _prom->cpu )
continue; continue;
path = (char *) mem; path = (char *) mem;
...@@ -950,7 +956,7 @@ prom_hold_cpus(unsigned long mem) ...@@ -950,7 +956,7 @@ prom_hold_cpus(unsigned long mem)
#ifdef DEBUG_PROM #ifdef DEBUG_PROM
prom_print_nl(); prom_print_nl();
prom_print(RELOC("cpu hw idx = 0x")); prom_print(RELOC("cpu hw idx = 0x"));
prom_print_hex(reg); prom_print_hex(cpuid);
prom_print_nl(); prom_print_nl();
#endif #endif
prom_print(RELOC("starting cpu ")); prom_print(RELOC("starting cpu "));
...@@ -978,9 +984,8 @@ prom_hold_cpus(unsigned long mem) ...@@ -978,9 +984,8 @@ prom_hold_cpus(unsigned long mem)
prom_print(RELOC(" 3) secondary_hold = 0x")); prom_print(RELOC(" 3) secondary_hold = 0x"));
prom_print_hex(secondary_hold); prom_print_hex(secondary_hold);
prom_print_nl(); prom_print_nl();
prom_print_nl();
#endif #endif
call_prom(RELOC("start-cpu"), 3, 0, node, secondary_hold, reg); call_prom(RELOC("start-cpu"), 3, 0, node, secondary_hold, cpuid);
prom_print(RELOC("...")); prom_print(RELOC("..."));
for ( i = 0 ; (i < 100000000) && for ( i = 0 ; (i < 100000000) &&
(*acknowledge == ((unsigned long)-1)); i++ ) ; (*acknowledge == ((unsigned long)-1)); i++ ) ;
...@@ -992,10 +997,11 @@ prom_hold_cpus(unsigned long mem) ...@@ -992,10 +997,11 @@ prom_hold_cpus(unsigned long mem)
prom_print_nl(); prom_print_nl();
} }
#endif #endif
if (*acknowledge == reg) { if (*acknowledge == cpuid) {
prom_print(RELOC("ok\n")); prom_print(RELOC("ok\n"));
/* Set the number of active processors. */ /* Set the number of active processors. */
_xPaca[reg].active = 1; _systemcfg->processorCount++;
_xPaca[cpuid].active = 1;
} else { } else {
prom_print(RELOC("failed: ")); prom_print(RELOC("failed: "));
prom_print_hex(*acknowledge); prom_print_hex(*acknowledge);
...@@ -1024,8 +1030,8 @@ prom_hold_cpus(unsigned long mem) ...@@ -1024,8 +1030,8 @@ prom_hold_cpus(unsigned long mem)
} }
} }
_xPaca[i+1].active = 1; _xPaca[i+1].active = 1;
RELOC(hmt_thread_data)[i].threadid = i+1;
} }
_systemcfg->processorCount *= 2;
} else { } else {
prom_print(RELOC("Processor is not HMT capable\n")); prom_print(RELOC("Processor is not HMT capable\n"));
} }
...@@ -1046,20 +1052,21 @@ unsigned long __init ...@@ -1046,20 +1052,21 @@ unsigned long __init
prom_init(unsigned long r3, unsigned long r4, unsigned long pp, prom_init(unsigned long r3, unsigned long r4, unsigned long pp,
unsigned long r6, unsigned long r7) unsigned long r6, unsigned long r7)
{ {
int chrp = 0;
unsigned long mem; unsigned long mem;
ihandle prom_root, prom_cpu; ihandle prom_mmu, prom_op, prom_root, prom_cpu;
phandle cpu_pkg; phandle cpu_pkg;
unsigned long offset = reloc_offset(); unsigned long offset = reloc_offset();
long l; long l, sz;
char *p, *d; char *p, *d;
unsigned long phys; unsigned long phys;
u32 getprop_rval; u32 getprop_rval;
struct naca_struct *_naca = RELOC(naca); struct systemcfg *_systemcfg = RELOC(systemcfg);
struct paca_struct *_xPaca = PTRRELOC(&paca[0]); struct paca_struct *_xPaca = PTRRELOC(&paca[0]);
struct prom_t *_prom = PTRRELOC(&prom); struct prom_t *_prom = PTRRELOC(&prom);
/* Default machine type. */ /* Default machine type. */
_naca->platform = PLATFORM_PSERIES; _systemcfg->platform = PLATFORM_PSERIES;
#if 0 #if 0
/* Reset klimit to take into account the embedded system map */ /* Reset klimit to take into account the embedded system map */
...@@ -1106,6 +1113,31 @@ prom_init(unsigned long r3, unsigned long r4, unsigned long pp, ...@@ -1106,6 +1113,31 @@ prom_init(unsigned long r3, unsigned long r4, unsigned long pp,
} }
_prom->encode_phys_size = (getprop_rval==1) ? 32 : 64; _prom->encode_phys_size = (getprop_rval==1) ? 32 : 64;
/* Find the OF version */
prom_op = (ihandle)call_prom(RELOC("finddevice"), 1, 1, RELOC("/openprom"));
if (prom_op != (ihandle)-1) {
char model[64];
sz = (long)call_prom(RELOC("getprop"), 4, 1, prom_op,
RELOC("model"), model, 64);
if (sz > 0) {
char *c;
/* hack to skip the ibm chrp firmware # */
if ( strncmp(model,RELOC("IBM"),3) ) {
for (c = model; *c; c++)
if (*c >= '0' && *c <= '9') {
_prom->version = *c - '0';
break;
}
}
else
chrp = 1;
}
}
if (_prom->version >= 3)
prom_print(RELOC("OF Version 3 detected.\n"));
/* Determine which cpu is actually running right _now_ */ /* Determine which cpu is actually running right _now_ */
if ((long)call_prom(RELOC("getprop"), 4, 1, _prom->chosen, if ((long)call_prom(RELOC("getprop"), 4, 1, _prom->chosen,
RELOC("cpu"), &getprop_rval, RELOC("cpu"), &getprop_rval,
...@@ -1149,6 +1181,8 @@ prom_init(unsigned long r3, unsigned long r4, unsigned long pp, ...@@ -1149,6 +1181,8 @@ prom_init(unsigned long r3, unsigned long r4, unsigned long pp,
mem = prom_bi_rec_reserve(mem); mem = prom_bi_rec_reserve(mem);
mem = check_display(mem);
prom_instantiate_rtas(); prom_instantiate_rtas();
/* Initialize some system info into the Naca early... */ /* Initialize some system info into the Naca early... */
...@@ -1158,11 +1192,9 @@ prom_init(unsigned long r3, unsigned long r4, unsigned long pp, ...@@ -1158,11 +1192,9 @@ prom_init(unsigned long r3, unsigned long r4, unsigned long pp,
* following, regardless of whether we have an SMP * following, regardless of whether we have an SMP
* kernel or not. * kernel or not.
*/ */
if (RELOC(ppc64_is_smp)) if (_systemcfg->processorCount > 1)
prom_hold_cpus(mem); prom_hold_cpus(mem);
mem = check_display(mem);
#ifdef DEBUG_PROM #ifdef DEBUG_PROM
prom_print(RELOC("copying OF device tree...\n")); prom_print(RELOC("copying OF device tree...\n"));
#endif #endif
...@@ -1172,12 +1204,38 @@ prom_init(unsigned long r3, unsigned long r4, unsigned long pp, ...@@ -1172,12 +1204,38 @@ prom_init(unsigned long r3, unsigned long r4, unsigned long pp,
lmb_reserve(0, __pa(RELOC(klimit))); lmb_reserve(0, __pa(RELOC(klimit)));
if (_naca->platform == PLATFORM_PSERIES) if (_systemcfg->platform == PLATFORM_PSERIES)
prom_initialize_tce_table(); prom_initialize_tce_table();
prom_print(RELOC("Calling quiesce ...\n")); if ((long) call_prom(RELOC("getprop"), 4, 1,
call_prom(RELOC("quiesce"), 0, 0); _prom->chosen,
phys = KERNELBASE - offset; RELOC("mmu"),
&getprop_rval,
sizeof(getprop_rval)) <= 0) {
prom_print(RELOC(" no MMU found\n"));
prom_exit();
}
/* We assume the phys. address size is 3 cells */
RELOC(prom_mmu) = (ihandle)(unsigned long)getprop_rval;
if ((long)call_prom(RELOC("call-method"), 4, 4,
RELOC("translate"),
prom_mmu,
(void *)(KERNELBASE - offset),
(void *)1) != 0) {
prom_print(RELOC(" (translate failed) "));
} else {
prom_print(RELOC(" (translate ok) "));
phys = (unsigned long)_prom->args.rets[3];
}
/* If OpenFirmware version >= 3, then use quiesce call */
if (_prom->version >= 3) {
prom_print(RELOC("Calling quiesce ...\n"));
call_prom(RELOC("quiesce"), 0, 0);
phys = KERNELBASE - offset;
}
prom_print(RELOC("returning from prom_init\n")); prom_print(RELOC("returning from prom_init\n"));
return phys; return phys;
......
...@@ -201,7 +201,7 @@ void proc_rtas_init(void) ...@@ -201,7 +201,7 @@ void proc_rtas_init(void)
struct proc_dir_entry *entry; struct proc_dir_entry *entry;
rtas_node = find_devices("rtas"); rtas_node = find_devices("rtas");
if ((rtas_node == NULL) || (naca->platform == PLATFORM_ISERIES_LPAR)) { if ((rtas_node == NULL) || (systemcfg->platform == PLATFORM_ISERIES_LPAR)) {
return; return;
} }
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <asm/prom.h> #include <asm/prom.h>
#include <asm/proc_fs.h>
#include <asm/rtas.h> #include <asm/rtas.h>
#include <asm/semaphore.h> #include <asm/semaphore.h>
#include <asm/machdep.h> #include <asm/machdep.h>
...@@ -27,7 +28,6 @@ ...@@ -27,7 +28,6 @@
#include <asm/abs_addr.h> #include <asm/abs_addr.h>
#include <asm/udbg.h> #include <asm/udbg.h>
struct proc_dir_entry *rtas_proc_dir; /* /proc/ppc64/rtas dir */
struct flash_block_list_header rtas_firmware_flash_list = {0, 0}; struct flash_block_list_header rtas_firmware_flash_list = {0, 0};
/* /*
...@@ -283,7 +283,7 @@ rtas_halt(void) ...@@ -283,7 +283,7 @@ rtas_halt(void)
rtas_power_off(); rtas_power_off();
} }
EXPORT_SYMBOL(rtas_proc_dir); EXPORT_SYMBOL(proc_ppc64);
EXPORT_SYMBOL(rtas_firmware_flash_list); EXPORT_SYMBOL(rtas_firmware_flash_list);
EXPORT_SYMBOL(rtas_token); EXPORT_SYMBOL(rtas_token);
EXPORT_SYMBOL(rtas_call); EXPORT_SYMBOL(rtas_call);
......
...@@ -210,7 +210,7 @@ int __init rtas_flash_init(void) ...@@ -210,7 +210,7 @@ int __init rtas_flash_init(void)
{ {
struct proc_dir_entry *ent = NULL; struct proc_dir_entry *ent = NULL;
if (!rtas_proc_dir) { if (!proc_ppc64.rtas) {
printk(KERN_WARNING "rtas proc dir does not already exist"); printk(KERN_WARNING "rtas proc dir does not already exist");
return -ENOENT; return -ENOENT;
} }
...@@ -218,7 +218,7 @@ int __init rtas_flash_init(void) ...@@ -218,7 +218,7 @@ int __init rtas_flash_init(void)
if (rtas_token("ibm,update-flash-64-and-reboot") != RTAS_UNKNOWN_SERVICE) if (rtas_token("ibm,update-flash-64-and-reboot") != RTAS_UNKNOWN_SERVICE)
flash_possible = 1; flash_possible = 1;
if ((ent = create_proc_entry(FIRMWARE_FLASH_NAME, S_IRUSR | S_IWUSR, rtas_proc_dir)) != NULL) { if ((ent = create_proc_entry(FIRMWARE_FLASH_NAME, S_IRUSR | S_IWUSR, proc_ppc64.rtas)) != NULL) {
ent->nlink = 1; ent->nlink = 1;
ent->proc_fops = &rtas_flash_operations; ent->proc_fops = &rtas_flash_operations;
ent->owner = THIS_MODULE; ent->owner = THIS_MODULE;
...@@ -228,9 +228,9 @@ int __init rtas_flash_init(void) ...@@ -228,9 +228,9 @@ int __init rtas_flash_init(void)
void __exit rtas_flash_cleanup(void) void __exit rtas_flash_cleanup(void)
{ {
if (!rtas_proc_dir) if (!proc_ppc64.rtas)
return; return;
remove_proc_entry(FIRMWARE_FLASH_NAME, rtas_proc_dir); remove_proc_entry(FIRMWARE_FLASH_NAME, proc_ppc64.rtas);
} }
module_init(rtas_flash_init); module_init(rtas_flash_init);
......
...@@ -156,10 +156,10 @@ void setup_system(unsigned long r3, unsigned long r4, unsigned long r5, ...@@ -156,10 +156,10 @@ void setup_system(unsigned long r3, unsigned long r4, unsigned long r5,
#ifdef CONFIG_PPC_ISERIES #ifdef CONFIG_PPC_ISERIES
/* pSeries systems are identified in prom.c via OF. */ /* pSeries systems are identified in prom.c via OF. */
if ( itLpNaca.xLparInstalled == 1 ) if ( itLpNaca.xLparInstalled == 1 )
naca->platform = PLATFORM_ISERIES_LPAR; systemcfg->platform = PLATFORM_ISERIES_LPAR;
#endif #endif
switch (naca->platform) { switch (systemcfg->platform) {
#ifdef CONFIG_PPC_ISERIES #ifdef CONFIG_PPC_ISERIES
case PLATFORM_ISERIES_LPAR: case PLATFORM_ISERIES_LPAR:
iSeries_init_early(); iSeries_init_early();
...@@ -185,7 +185,7 @@ void setup_system(unsigned long r3, unsigned long r4, unsigned long r5, ...@@ -185,7 +185,7 @@ void setup_system(unsigned long r3, unsigned long r4, unsigned long r5,
#endif #endif
} }
if (naca->platform & PLATFORM_PSERIES) { if (systemcfg->platform & PLATFORM_PSERIES) {
early_console_initialized = 1; early_console_initialized = 1;
register_console(&udbg_console); register_console(&udbg_console);
} }
...@@ -193,32 +193,27 @@ void setup_system(unsigned long r3, unsigned long r4, unsigned long r5, ...@@ -193,32 +193,27 @@ void setup_system(unsigned long r3, unsigned long r4, unsigned long r5,
printk("Starting Linux PPC64 %s\n", UTS_RELEASE); printk("Starting Linux PPC64 %s\n", UTS_RELEASE);
printk("-----------------------------------------------------\n"); printk("-----------------------------------------------------\n");
printk("naca = 0x%p\n", naca); printk("naca = 0x%p\n", naca);
#if 0 printk("naca->pftSize = 0x%lx\n", naca->pftSize);
printk("naca->processorCount = 0x%x\n", naca->processorCount); printk("naca->debug_switch = 0x%lx\n", naca->debug_switch);
#endif printk("naca->interrupt_controller = 0x%d\n", naca->interrupt_controller);
printk("naca->physicalMemorySize = 0x%lx\n", naca->physicalMemorySize); printk("systemcf = 0x%p\n", systemcfg);
printk("naca->dCacheL1LineSize = 0x%x\n", naca->dCacheL1LineSize); printk("systemcfg->processorCount = 0x%x\n", systemcfg->processorCount);
printk("naca->dCacheL1LogLineSize = 0x%x\n", naca->dCacheL1LogLineSize); printk("systemcfg->physicalMemorySize = 0x%lx\n", systemcfg->physicalMemorySize);
printk("naca->dCacheL1LinesPerPage = 0x%x\n", naca->dCacheL1LinesPerPage); printk("systemcfg->dCacheL1LineSize = 0x%x\n", systemcfg->dCacheL1LineSize);
printk("naca->iCacheL1LineSize = 0x%x\n", naca->iCacheL1LineSize); printk("systemcfg->iCacheL1LineSize = 0x%x\n", systemcfg->iCacheL1LineSize);
printk("naca->iCacheL1LogLineSize = 0x%x\n", naca->iCacheL1LogLineSize); printk("htab_data.htab = 0x%p\n", htab_data.htab);
printk("naca->iCacheL1LinesPerPage = 0x%x\n", naca->iCacheL1LinesPerPage); printk("htab_data.num_ptegs = 0x%lx\n", htab_data.htab_num_ptegs);
printk("naca->pftSize = 0x%lx\n", naca->pftSize);
printk("naca->debug_switch = 0x%lx\n", naca->debug_switch);
printk("naca->interrupt_controller = 0x%d\n", naca->interrupt_controller);
printk("htab_data.htab = 0x%p\n", htab_data.htab);
printk("htab_data.num_ptegs = 0x%lx\n", htab_data.htab_num_ptegs);
printk("-----------------------------------------------------\n"); printk("-----------------------------------------------------\n");
if (naca->platform & PLATFORM_PSERIES) { if (systemcfg->platform & PLATFORM_PSERIES) {
finish_device_tree(); finish_device_tree();
chrp_init(r3, r4, r5, r6, r7); chrp_init(r3, r4, r5, r6, r7);
} }
mm_init_ppc64(); mm_init_ppc64();
switch (naca->platform) { switch (systemcfg->platform) {
#ifdef CONFIG_PPC_ISERIES #ifdef CONFIG_PPC_ISERIES
case PLATFORM_ISERIES_LPAR: case PLATFORM_ISERIES_LPAR:
iSeries_init(); iSeries_init();
...@@ -312,7 +307,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) ...@@ -312,7 +307,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
* Assume here that all clock rates are the same in a * Assume here that all clock rates are the same in a
* smp system. -- Cort * smp system. -- Cort
*/ */
if (naca->platform != PLATFORM_ISERIES_LPAR) { if (systemcfg->platform != PLATFORM_ISERIES_LPAR) {
struct device_node *cpu_node; struct device_node *cpu_node;
int *fp; int *fp;
...@@ -516,8 +511,8 @@ void __init setup_arch(char **cmdline_p) ...@@ -516,8 +511,8 @@ void __init setup_arch(char **cmdline_p)
* Systems with OF can look in the properties on the cpu node(s) * Systems with OF can look in the properties on the cpu node(s)
* for a possibly more accurate value. * for a possibly more accurate value.
*/ */
dcache_bsize = naca->dCacheL1LineSize; dcache_bsize = systemcfg->dCacheL1LineSize;
icache_bsize = naca->iCacheL1LineSize; icache_bsize = systemcfg->iCacheL1LineSize;
/* reboot on panic */ /* reboot on panic */
panic_timeout = 180; panic_timeout = 180;
......
...@@ -43,57 +43,29 @@ ...@@ -43,57 +43,29 @@
#endif #endif
#define GP_REGS_SIZE MIN(sizeof(elf_gregset_t), sizeof(struct pt_regs)) #define GP_REGS_SIZE MIN(sizeof(elf_gregset_t), sizeof(struct pt_regs))
#define FP_REGS_SIZE sizeof(elf_fpregset_t)
/* #define TRAMP_TRACEBACK 3
* These are the flags in the MSR that the user is allowed to change #define TRAMP_SIZE 6
* by modifying the saved value of the MSR on the stack. SE and BE
* should not be in this list since gdb may want to change these. I.e,
* you should be able to step out of a signal handler to see what
* instruction executes next after the signal handler completes.
* Alternately, if you stepped into a signal handler, you should be
* able to continue 'til the next breakpoint from within the signal
* handler, even if the handler returns.
*/
#if 0
#define MSR_USERCHANGE (MSR_FE0 | MSR_FE1)
#else
/*
* glibc tries to set FE0/FE1 via a signal handler. Since it only ever
* sets both bits and this is the default setting we now disable this
* behaviour. This is done to insure the new prctl which alters FE0/FE1 does
* not get overriden by glibc. Setting and clearing FE0/FE1 via signal
* handler has always been bogus since load_up_fpu used to set FE0/FE1
* unconditionally.
*/
#define MSR_USERCHANGE 0
#endif
/* /*
* When we have signals to deliver, we set up on the * When we have signals to deliver, we set up on the user stack,
* user stack, going down from the original stack pointer: * going down from the original stack pointer:
* a sigregs struct * 1) a rt_sigframe struct which contains the ucontext
* one or more sigcontext structs with * 2) a gap of __SIGNAL_FRAMESIZE bytes which acts as a dummy caller
* a gap of __SIGNAL_FRAMESIZE bytes * frame for the signal handler.
*
* Each of these things must be a multiple of 16 bytes in size.
*
*/ */
struct sigregs {
elf_gregset_t gp_regs;
double fp_regs[ELF_NFPREG];
unsigned int tramp[2];
/* 64 bit API allows for 288 bytes below sp before
decrementing it. */
int abigap[72];
};
struct rt_sigframe struct rt_sigframe {
{ /* sys_rt_sigreturn requires the ucontext be the first field */
unsigned long _unused[2]; struct ucontext uc;
unsigned long _unused[2];
unsigned int tramp[TRAMP_SIZE];
struct siginfo *pinfo; struct siginfo *pinfo;
void *puc; void *puc;
struct siginfo info; struct siginfo info;
struct ucontext uc; /* 64 bit ABI allows for 288 bytes below sp before decrementing it. */
char abigap[288];
}; };
...@@ -102,37 +74,6 @@ extern int do_signal(sigset_t *oldset, struct pt_regs *regs); ...@@ -102,37 +74,6 @@ extern int do_signal(sigset_t *oldset, struct pt_regs *regs);
/* /*
* Atomically swap in the new signal mask, and wait for a signal. * Atomically swap in the new signal mask, and wait for a signal.
*/ */
long sys_sigsuspend(old_sigset_t mask, int p2, int p3, int p4, int p6, int p7,
struct pt_regs *regs)
{
sigset_t saveset;
mask &= _BLOCKABLE;
spin_lock_irq(&current->sighand->siglock);
saveset = current->blocked;
siginitset(&current->blocked, mask);
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
regs->result = -EINTR;
regs->gpr[3] = EINTR;
regs->ccr |= 0x10000000;
while (1) {
current->state = TASK_INTERRUPTIBLE;
schedule();
if (do_signal(&saveset, regs))
/*
* If a signal handler needs to be called,
* do_signal() has set R3 to the signal number (the
* first argument of the signal handler), so don't
* overwrite that with EINTR !
* In the other cases, do_signal() doesn't touch
* R3, so it's still set to -EINTR (see above).
*/
return regs->gpr[3];
}
}
long sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize, int p3, int p4, int p6, long sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize, int p3, int p4, int p6,
int p7, struct pt_regs *regs) int p7, struct pt_regs *regs)
{ {
...@@ -170,339 +111,232 @@ long sys_sigaltstack(const stack_t *uss, stack_t *uoss, unsigned long r5, ...@@ -170,339 +111,232 @@ long sys_sigaltstack(const stack_t *uss, stack_t *uoss, unsigned long r5,
return do_sigaltstack(uss, uoss, regs->gpr[1]); return do_sigaltstack(uss, uoss, regs->gpr[1]);
} }
long sys_sigaction(int sig, const struct old_sigaction *act,
struct old_sigaction *oact) /*
* Set up the sigcontext for the signal frame.
*/
static int
setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs,
int signr, sigset_t *set, unsigned long handler)
{ {
struct k_sigaction new_ka, old_ka; int err = 0;
int ret;
if (act) {
old_sigset_t mask;
if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
__get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
__get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
return -EFAULT;
__get_user(new_ka.sa.sa_flags, &act->sa_flags);
__get_user(mask, &act->sa_mask);
siginitset(&new_ka.sa.sa_mask, mask);
}
ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); if (regs->msr & MSR_FP)
if (!ret && oact) { giveup_fpu(current);
if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
__put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
__put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
return -EFAULT;
__put_user(old_ka.sa.sa_flags, &oact->sa_flags);
__put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
}
return ret; current->thread.saved_msr = regs->msr & ~(MSR_FP | MSR_FE0 | MSR_FE1);
regs->msr = current->thread.saved_msr | current->thread.fpexc_mode;
current->thread.saved_softe = regs->softe;
err |= __put_user(&sc->gp_regs, &sc->regs);
err |= __copy_to_user(&sc->gp_regs, regs, GP_REGS_SIZE);
err |= __copy_to_user(&sc->fp_regs, &current->thread.fpr, FP_REGS_SIZE);
err |= __put_user(signr, &sc->signal);
err |= __put_user(handler, &sc->handler);
if (set != NULL)
err |= __put_user(set->sig[0], &sc->oldmask);
regs->msr &= ~(MSR_FP | MSR_FE0 | MSR_FE1);
current->thread.fpscr = 0;
return err;
} }
/* /*
* When we have rt signals to deliver, we set up on the * Restore the sigcontext from the signal frame.
* user stack, going down from the original stack pointer:
* a sigregs struct
* one rt_sigframe struct (siginfo + ucontext)
* a gap of __SIGNAL_FRAMESIZE bytes
*
* Each of these things must be a multiple of 16 bytes in size.
*
*/ */
int sys_rt_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5, static int
unsigned long r6, unsigned long r7, unsigned long r8, restore_sigcontext(struct pt_regs *regs, sigset_t *set, struct sigcontext *sc)
struct pt_regs *regs)
{ {
struct rt_sigframe *rt_sf; unsigned int err = 0;
struct sigcontext sigctx;
struct sigregs *sr;
elf_gregset_t saved_regs; /* an array of ELF_NGREG unsigned longs */
sigset_t set;
stack_t st;
rt_sf = (struct rt_sigframe *)(regs->gpr[1] + __SIGNAL_FRAMESIZE);
if (copy_from_user(&sigctx, &rt_sf->uc.uc_mcontext, sizeof(sigctx))
|| copy_from_user(&set, &rt_sf->uc.uc_sigmask, sizeof(set))
|| copy_from_user(&st, &rt_sf->uc.uc_stack, sizeof(st)))
goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE);
spin_lock_irq(&current->sighand->siglock);
current->blocked = set;
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
if (regs->msr & MSR_FP) if (regs->msr & MSR_FP)
giveup_fpu(current); giveup_fpu(current);
/* restore registers - err |= __copy_from_user(regs, &sc->gp_regs, GP_REGS_SIZE);
* sigctx is initialized to point to the err |= __copy_from_user(&current->thread.fpr, &sc->fp_regs, FP_REGS_SIZE);
* preamble frame (where registers are stored) current->thread.fpexc_mode = regs->msr & (MSR_FE0 | MSR_FE1);
* see handle_signal() if (set != NULL)
*/ err |= __get_user(set->sig[0], &sc->oldmask);
sr = (struct sigregs *)sigctx.regs;
if (copy_from_user(saved_regs, &sr->gp_regs, sizeof(sr->gp_regs)))
goto badframe;
saved_regs[PT_MSR] = (regs->msr & ~MSR_USERCHANGE)
| (saved_regs[PT_MSR] & MSR_USERCHANGE);
saved_regs[PT_SOFTE] = regs->softe;
memcpy(regs, saved_regs, GP_REGS_SIZE);
if (copy_from_user(current->thread.fpr, &sr->fp_regs,
sizeof(sr->fp_regs)))
goto badframe;
/* This function sets back the stack flags into
the current task structure. */
sys_sigaltstack(&st, NULL, 0, 0, 0, 0, regs);
return regs->result; /* Don't allow the signal handler to change these modulo FE{0,1} */
regs->msr = current->thread.saved_msr & ~(MSR_FP | MSR_FE0 | MSR_FE1);
regs->softe = current->thread.saved_softe;
badframe: return err;
do_exit(SIGSEGV);
} }
static void setup_rt_frame(struct pt_regs *regs, struct sigregs *frame, /*
signed long newsp) * Allocate space for the signal frame
*/
static inline void *
get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
{ {
struct rt_sigframe *rt_sf = (struct rt_sigframe *)newsp; unsigned long newsp;
/* Handler is *really* a pointer to the function descriptor for
* the signal routine. The first entry in the function
* descriptor is the entry address of signal and the second
* entry is the TOC value we need to use.
*/
struct funct_descr_entry {
unsigned long entry;
unsigned long toc;
};
struct funct_descr_entry * funct_desc_ptr;
unsigned long temp_ptr;
/* Set up preamble frame */
if (verify_area(VERIFY_WRITE, frame, sizeof(*frame)))
goto badframe;
if (regs->msr & MSR_FP)
giveup_fpu(current);
if (__copy_to_user(&frame->gp_regs, regs, GP_REGS_SIZE)
|| __copy_to_user(&frame->fp_regs, current->thread.fpr,
ELF_NFPREG * sizeof(double))
/* li r0, __NR_rt_sigreturn */
|| __put_user(0x38000000UL + __NR_rt_sigreturn, &frame->tramp[0])
/* sc */
|| __put_user(0x44000002UL, &frame->tramp[1]))
goto badframe;
flush_icache_range((unsigned long)&frame->tramp[0],
(unsigned long)&frame->tramp[2]);
current->thread.fpscr = 0; /* turn off all fp exceptions */
/* Retrieve rt_sigframe from stack and /* Default to using normal stack */
set up registers for signal handler newsp = regs->gpr[1];
*/
newsp -= __SIGNAL_FRAMESIZE;
if (get_user(temp_ptr, &rt_sf->uc.uc_mcontext.handler)) { if (ka->sa.sa_flags & SA_ONSTACK) {
goto badframe; if (! on_sig_stack(regs->gpr[1]))
newsp = (current->sas_ss_sp + current->sas_ss_size);
} }
funct_desc_ptr = (struct funct_descr_entry *)temp_ptr; return (void *)((newsp - frame_size) & -8ul);
}
if (put_user(regs->gpr[1], (unsigned long *)newsp)
|| get_user(regs->nip, &funct_desc_ptr->entry)
|| get_user(regs->gpr[2], &funct_desc_ptr->toc)
|| get_user(regs->gpr[3], &rt_sf->uc.uc_mcontext.signal)
|| get_user(regs->gpr[4], (unsigned long *)&rt_sf->pinfo)
|| get_user(regs->gpr[5], (unsigned long *)&rt_sf->puc))
goto badframe;
regs->gpr[1] = newsp; static int
regs->gpr[6] = (unsigned long)rt_sf; setup_trampoline(unsigned int syscall, unsigned int *tramp)
regs->link = (unsigned long)frame->tramp; {
int i, err = 0;
return; /* addi r1, r1, __SIGNAL_FRAMESIZE # Pop the dummy stackframe */
err |= __put_user(0x38210000UL | (__SIGNAL_FRAMESIZE & 0xffff), &tramp[0]);
/* li r0, __NR_[rt_]sigreturn| */
err |= __put_user(0x38000000UL | (syscall & 0xffff), &tramp[1]);
/* sc */
err |= __put_user(0x44000002UL, &tramp[2]);
badframe: /* Minimal traceback info */
#if DEBUG_SIG for (i=TRAMP_TRACEBACK; i < TRAMP_SIZE ;i++)
printk("badframe in setup_rt_frame, regs=%p frame=%p newsp=%lx\n", err |= __put_user(0, &tramp[i]);
regs, frame, newsp);
#endif if (!err)
do_exit(SIGSEGV); flush_icache_range((unsigned long) &tramp[0],
(unsigned long) &tramp[TRAMP_SIZE]);
return err;
} }
/* /*
* Do a signal return; undo the signal stack. * Do a signal return; undo the signal stack.
*/ */
long sys_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7, unsigned long r8, int sys_rt_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5,
struct pt_regs *regs) unsigned long r6, unsigned long r7, unsigned long r8,
struct pt_regs *regs)
{ {
struct sigcontext *sc, sigctx; struct ucontext *uc = (struct ucontext *)regs->gpr[1];
struct sigregs *sr;
elf_gregset_t saved_regs; /* an array of ELF_NGREG unsigned longs */
sigset_t set; sigset_t set;
stack_t st;
sc = (struct sigcontext *)(regs->gpr[1] + __SIGNAL_FRAMESIZE); if (verify_area(VERIFY_READ, uc, sizeof(*uc)))
if (copy_from_user(&sigctx, sc, sizeof(sigctx)))
goto badframe; goto badframe;
set.sig[0] = sigctx.oldmask; if (__copy_from_user(&set, &uc->uc_sigmask, sizeof(set)))
#if _NSIG_WORDS > 1 goto badframe;
set.sig[1] = sigctx._unused[3];
#endif
sigdelsetmask(&set, ~_BLOCKABLE); sigdelsetmask(&set, ~_BLOCKABLE);
spin_lock_irq(&current->sighand->siglock); spin_lock_irq(&current->sighand->siglock);
current->blocked = set; current->blocked = set;
recalc_sigpending(); recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock); spin_unlock_irq(&current->sighand->siglock);
if (regs->msr & MSR_FP)
giveup_fpu(current);
/* restore registers */ if (restore_sigcontext(regs, NULL, &uc->uc_mcontext))
sr = (struct sigregs *)sigctx.regs;
if (copy_from_user(saved_regs, &sr->gp_regs, sizeof(sr->gp_regs)))
goto badframe; goto badframe;
saved_regs[PT_MSR] = (regs->msr & ~MSR_USERCHANGE)
| (saved_regs[PT_MSR] & MSR_USERCHANGE);
saved_regs[PT_SOFTE] = regs->softe;
memcpy(regs, saved_regs, GP_REGS_SIZE);
if (copy_from_user(current->thread.fpr, &sr->fp_regs, if (__copy_from_user(&st, &uc->uc_stack, sizeof(st)))
sizeof(sr->fp_regs)))
goto badframe; goto badframe;
/* This function sets back the stack flags into
the current task structure. */
sys_sigaltstack(&st, NULL, 0, 0, 0, 0, regs);
return regs->result; return regs->result;
badframe: badframe:
#if DEBUG_SIG
printk("badframe in sys_rt_sigreturn, regs=%p uc=%p &uc->uc_mcontext=%p\n",
regs, uc, &uc->uc_mcontext);
#endif
do_exit(SIGSEGV); do_exit(SIGSEGV);
} }
/* static void
* Set up a signal frame. setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info,
*/ sigset_t *set, struct pt_regs *regs)
static void setup_frame(struct pt_regs *regs, struct sigregs *frame,
unsigned long newsp)
{ {
/* Handler is *really* a pointer to the function descriptor for /* Handler is *really* a pointer to the function descriptor for
* the signal routine. The first entry in the function * the signal routine. The first entry in the function
* descriptor is the entry address of signal and the second * descriptor is the entry address of signal and the second
* entry is the TOC value we need to use. * entry is the TOC value we need to use.
*/ */
struct funct_descr_entry { func_descr_t *funct_desc_ptr;
unsigned long entry; struct rt_sigframe *frame;
unsigned long toc; unsigned long newsp = 0;
}; int err = 0;
struct funct_descr_entry * funct_desc_ptr; frame = get_sigframe(ka, regs, sizeof(*frame));
unsigned long temp_ptr;
struct sigcontext *sc = (struct sigcontext *)newsp;
if (verify_area(VERIFY_WRITE, frame, sizeof(*frame))) if (verify_area(VERIFY_WRITE, frame, sizeof(*frame)))
goto badframe; goto badframe;
if (regs->msr & MSR_FP)
giveup_fpu(current); err |= __put_user(&frame->info, &frame->pinfo);
if (__copy_to_user(&frame->gp_regs, regs, GP_REGS_SIZE) err |= __put_user(&frame->uc, &frame->puc);
|| __copy_to_user(&frame->fp_regs, current->thread.fpr, err |= copy_siginfo_to_user(&frame->info, info);
ELF_NFPREG * sizeof(double)) if (err)
/* li r0, __NR_sigreturn */
|| __put_user(0x38000000UL + __NR_sigreturn, &frame->tramp[0])
/* sc */
|| __put_user(0x44000002UL, &frame->tramp[1]))
goto badframe; goto badframe;
flush_icache_range((unsigned long)&frame->tramp[0],
(unsigned long)&frame->tramp[2]);
current->thread.fpscr = 0; /* turn off all fp exceptions */
newsp -= __SIGNAL_FRAMESIZE; /* Create the ucontext. */
if (get_user(temp_ptr, &sc->handler)) err |= __put_user(0, &frame->uc.uc_flags);
err |= __put_user(0, &frame->uc.uc_link);
err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
err |= __put_user(sas_ss_flags(regs->gpr[1]),
&frame->uc.uc_stack.ss_flags);
err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, signr, NULL,
(unsigned long)ka->sa.sa_handler);
err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
if (err)
goto badframe; goto badframe;
funct_desc_ptr = (struct funct_descr_entry *)temp_ptr;
if (put_user(regs->gpr[1], (unsigned long *)newsp) /* Set up to return from userspace. */
|| get_user(regs->nip, &funct_desc_ptr ->entry) err |= setup_trampoline(__NR_rt_sigreturn, &frame->tramp[0]);
|| get_user(regs->gpr[2],&funct_desc_ptr->toc) if (err)
|| get_user(regs->gpr[3], &sc->signal))
goto badframe; goto badframe;
funct_desc_ptr = (func_descr_t *) ka->sa.sa_handler;
/* Allocate a dummy caller frame for the signal handler. */
newsp = (unsigned long)frame - __SIGNAL_FRAMESIZE;
err |= put_user(0, (unsigned long *)newsp);
/* Set up "regs" so we "return" to the signal handler. */
err |= get_user(regs->nip, &funct_desc_ptr->entry);
regs->link = (unsigned long) &frame->tramp[0];
regs->gpr[1] = newsp; regs->gpr[1] = newsp;
regs->gpr[4] = (unsigned long)sc; err |= get_user(regs->gpr[2], &funct_desc_ptr->toc);
regs->link = (unsigned long)frame->tramp; regs->gpr[3] = signr;
if (ka->sa.sa_flags & SA_SIGINFO) {
err |= get_user(regs->gpr[4], (unsigned long *)&frame->pinfo);
err |= get_user(regs->gpr[5], (unsigned long *)&frame->puc);
regs->gpr[6] = (unsigned long) frame;
} else {
regs->gpr[4] = (unsigned long)&frame->uc.uc_mcontext;
}
if (err)
goto badframe;
return; return;
badframe: badframe:
#if DEBUG_SIG #if DEBUG_SIG
printk("badframe in setup_frame, regs=%p frame=%p newsp=%lx\n", printk("badframe in setup_rt_frame, regs=%p frame=%p newsp=%lx\n",
regs, frame, newsp); regs, frame, newsp);
#endif #endif
do_exit(SIGSEGV); do_exit(SIGSEGV);
} }
/* /*
* OK, we're invoking a handler * OK, we're invoking a handler
*/ */
static void handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset, static void
struct pt_regs * regs, unsigned long *newspp, unsigned long frame) handle_signal(unsigned long sig, struct k_sigaction *ka,
siginfo_t *info, sigset_t *oldset, struct pt_regs *regs)
{ {
struct sigcontext *sc;
struct rt_sigframe *rt_sf;
struct k_sigaction *ka = &current->sighand->action[sig-1];
if (regs->trap == 0x0C00 /* System Call! */
&& ((int)regs->result == -ERESTARTNOHAND ||
(int)regs->result == -ERESTART_RESTARTBLOCK ||
((int)regs->result == -ERESTARTSYS &&
!(ka->sa.sa_flags & SA_RESTART)))) {
if ((int)regs->result == -ERESTART_RESTARTBLOCK)
current_thread_info()->restart_block.fn
= do_no_restart_syscall;
regs->result = -EINTR;
}
/* Set up Signal Frame */ /* Set up Signal Frame */
if (ka->sa.sa_flags & SA_SIGINFO) { setup_rt_frame(sig, ka, info, oldset, regs);
/* Put a Real Time Context onto stack */
*newspp -= sizeof(*rt_sf);
rt_sf = (struct rt_sigframe *)*newspp;
if (verify_area(VERIFY_WRITE, rt_sf, sizeof(*rt_sf)))
goto badframe;
if (__put_user((unsigned long)ka->sa.sa_handler,
&rt_sf->uc.uc_mcontext.handler)
|| __put_user(&rt_sf->info, &rt_sf->pinfo)
|| __put_user(&rt_sf->uc, &rt_sf->puc)
/* Put the siginfo */
|| copy_siginfo_to_user(&rt_sf->info, info)
/* Create the ucontext */
|| __put_user(0, &rt_sf->uc.uc_flags)
|| __put_user(0, &rt_sf->uc.uc_link)
|| __put_user(current->sas_ss_sp, &rt_sf->uc.uc_stack.ss_sp)
|| __put_user(sas_ss_flags(regs->gpr[1]),
&rt_sf->uc.uc_stack.ss_flags)
|| __put_user(current->sas_ss_size,
&rt_sf->uc.uc_stack.ss_size)
|| __copy_to_user(&rt_sf->uc.uc_sigmask,
oldset, sizeof(*oldset))
/* mcontext.regs points to preamble register frame */
|| __put_user((struct pt_regs *)frame, &rt_sf->uc.uc_mcontext.regs)
|| __put_user(sig, &rt_sf->uc.uc_mcontext.signal))
goto badframe;
} else {
/* Put a sigcontext on the stack */
*newspp -= sizeof(*sc);
sc = (struct sigcontext *)*newspp;
if (verify_area(VERIFY_WRITE, sc, sizeof(*sc)))
goto badframe;
if (__put_user((unsigned long)ka->sa.sa_handler, &sc->handler)
|| __put_user(oldset->sig[0], &sc->oldmask)
#if _NSIG_WORDS > 1
|| __put_user(oldset->sig[1], &sc->_unused[3])
#endif
|| __put_user((struct pt_regs *)frame, &sc->regs)
|| __put_user(sig, &sc->signal))
goto badframe;
}
if (ka->sa.sa_flags & SA_ONESHOT) if (ka->sa.sa_flags & SA_ONESHOT)
ka->sa.sa_handler = SIG_DFL; ka->sa.sa_handler = SIG_DFL;
...@@ -515,14 +349,40 @@ static void handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset, ...@@ -515,14 +349,40 @@ static void handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset,
spin_unlock_irq(&current->sighand->siglock); spin_unlock_irq(&current->sighand->siglock);
} }
return; return;
}
badframe: static inline void
#if DEBUG_SIG syscall_restart(struct pt_regs *regs, struct k_sigaction *ka)
printk("badframe in handle_signal, regs=%p frame=%lx newsp=%lx\n", {
regs, frame, *newspp); switch ((int)regs->result) {
printk("sc=%p sig=%d ka=%p info=%p oldset=%p\n", sc, sig, ka, info, oldset); case -ERESTART_RESTARTBLOCK:
#endif current_thread_info()->restart_block.fn = do_no_restart_syscall;
do_exit(SIGSEGV); /* fallthrough */
case -ERESTARTNOHAND:
/* ERESTARTNOHAND means that the syscall should only be
* restarted if there was no handler for the signal, and since
* we only get here if there is a handler, we dont restart.
*/
regs->result = -EINTR;
break;
case -ERESTARTSYS:
/* ERESTARTSYS means to restart the syscall if there is no
* handler or the handler was registered with SA_RESTART
*/
if (!(ka->sa.sa_flags & SA_RESTART)) {
regs->result = -EINTR;
break;
}
/* fallthrough */
case -ERESTARTNOINTR:
/* ERESTARTNOINTR means that the syscall should be
* called again after the signal handler returns.
*/
regs->gpr[3] = regs->orig_gpr3;
regs->nip -= 4;
regs->result = 0;
break;
}
} }
/* /*
...@@ -535,8 +395,6 @@ extern int do_signal32(sigset_t *oldset, struct pt_regs *regs); ...@@ -535,8 +395,6 @@ extern int do_signal32(sigset_t *oldset, struct pt_regs *regs);
int do_signal(sigset_t *oldset, struct pt_regs *regs) int do_signal(sigset_t *oldset, struct pt_regs *regs)
{ {
siginfo_t info; siginfo_t info;
struct k_sigaction *ka;
unsigned long frame, newsp;
int signr; int signr;
/* /*
...@@ -549,20 +407,15 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs) ...@@ -549,20 +407,15 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
if (!oldset) if (!oldset)
oldset = &current->blocked; oldset = &current->blocked;
newsp = frame = 0;
signr = get_signal_to_deliver(&info, regs, NULL); signr = get_signal_to_deliver(&info, regs, NULL);
if (signr > 0) { if (signr > 0) {
ka = &current->sighand->action[signr-1]; struct k_sigaction *ka = &current->sighand->action[signr-1];
if ((ka->sa.sa_flags & SA_ONSTACK)
&& (!on_sig_stack(regs->gpr[1])))
newsp = (current->sas_ss_sp + current->sas_ss_size);
else
newsp = regs->gpr[1];
newsp = frame = newsp - sizeof(struct sigregs);
/* Whee! Actually deliver the signal. */ /* Whee! Actually deliver the signal. */
handle_signal(signr, &info, oldset, regs, &newsp, frame); if (regs->trap == 0x0C00)
syscall_restart(regs, ka);
handle_signal(signr, ka, &info, oldset, regs);
return 1;
} }
if (regs->trap == 0x0C00) { /* System Call! */ if (regs->trap == 0x0C00) { /* System Call! */
...@@ -579,13 +432,8 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs) ...@@ -579,13 +432,8 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
} }
} }
if (newsp == frame) return 0;
return 0; /* no signals delivered */
/* Invoke correct stack setup routine */
if (ka->sa.sa_flags & SA_SIGINFO)
setup_rt_frame(regs, (struct sigregs *)frame, newsp);
else
setup_frame(regs, (struct sigregs *)frame, newsp);
return 1;
} }
...@@ -114,6 +114,40 @@ struct rt_sigframe_32 { ...@@ -114,6 +114,40 @@ struct rt_sigframe_32 {
* setup_frame32 * setup_frame32
*/ */
/*
* Atomically swap in the new signal mask, and wait for a signal.
*/
long sys32_sigsuspend(old_sigset_t mask, int p2, int p3, int p4, int p6, int p7,
struct pt_regs *regs)
{
sigset_t saveset;
mask &= _BLOCKABLE;
spin_lock_irq(&current->sighand->siglock);
saveset = current->blocked;
siginitset(&current->blocked, mask);
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
regs->result = -EINTR;
regs->gpr[3] = EINTR;
regs->ccr |= 0x10000000;
while (1) {
current->state = TASK_INTERRUPTIBLE;
schedule();
if (do_signal32(&saveset, regs))
/*
* If a signal handler needs to be called,
* do_signal32() has set R3 to the signal number (the
* first argument of the signal handler), so don't
* overwrite that with EINTR !
* In the other cases, do_signal32() doesn't touch
* R3, so it's still set to -EINTR (see above).
*/
return regs->gpr[3];
}
}
long sys32_sigaction(int sig, struct old_sigaction32 *act, long sys32_sigaction(int sig, struct old_sigaction32 *act,
struct old_sigaction32 *oact) struct old_sigaction32 *oact)
{ {
...@@ -792,13 +826,13 @@ int sys32_rt_sigsuspend(compat_sigset_t* unewset, size_t sigsetsize, int p3, ...@@ -792,13 +826,13 @@ int sys32_rt_sigsuspend(compat_sigset_t* unewset, size_t sigsetsize, int p3,
while (1) { while (1) {
current->state = TASK_INTERRUPTIBLE; current->state = TASK_INTERRUPTIBLE;
schedule(); schedule();
if (do_signal(&saveset, regs)) if (do_signal32(&saveset, regs))
/* /*
* If a signal handler needs to be called, * If a signal handler needs to be called,
* do_signal() has set R3 to the signal number (the * do_signal32() has set R3 to the signal number (the
* first argument of the signal handler), so don't * first argument of the signal handler), so don't
* overwrite that with EINTR ! * overwrite that with EINTR !
* In the other cases, do_signal() doesn't touch * In the other cases, do_signal32() doesn't touch
* R3, so it's still set to -EINTR (see above). * R3, so it's still set to -EINTR (see above).
*/ */
return regs->gpr[3]; return regs->gpr[3];
......
...@@ -179,7 +179,7 @@ void __init smp_init_iSeries(void) ...@@ -179,7 +179,7 @@ void __init smp_init_iSeries(void)
smp_ops->kick_cpu = smp_iSeries_kick_cpu; smp_ops->kick_cpu = smp_iSeries_kick_cpu;
smp_ops->setup_cpu = smp_iSeries_setup_cpu; smp_ops->setup_cpu = smp_iSeries_setup_cpu;
#warning fix for iseries #warning fix for iseries
naca->processorCount = smp_iSeries_numProcs(); systemcfg->processorCount = smp_iSeries_numProcs();
} }
#endif #endif
...@@ -343,7 +343,7 @@ void __init smp_init_pSeries(void) ...@@ -343,7 +343,7 @@ void __init smp_init_pSeries(void)
smp_ops->probe = smp_xics_probe; smp_ops->probe = smp_xics_probe;
} }
if (naca->platform == PLATFORM_PSERIES) { if (systemcfg->platform == PLATFORM_PSERIES) {
smp_ops->give_timebase = pSeries_give_timebase; smp_ops->give_timebase = pSeries_give_timebase;
smp_ops->take_timebase = pSeries_take_timebase; smp_ops->take_timebase = pSeries_take_timebase;
} }
......
...@@ -345,6 +345,14 @@ ProgramCheckException(struct pt_regs *regs) ...@@ -345,6 +345,14 @@ ProgramCheckException(struct pt_regs *regs)
} }
} }
void
KernelFPUnavailableException(struct pt_regs *regs)
{
printk("Illegal floating point used in kernel (task=0x%016lx, pc=0x%016lx, trap=0x%08x)\n",
current, regs->nip, regs->trap);
panic("Unrecoverable FP Unavailable Exception in Kernel");
}
void void
SingleStepException(struct pt_regs *regs) SingleStepException(struct pt_regs *regs)
{ {
......
...@@ -176,7 +176,7 @@ udbg_puthex(unsigned long val) ...@@ -176,7 +176,7 @@ udbg_puthex(unsigned long val)
void void
udbg_printSP(const char *s) udbg_printSP(const char *s)
{ {
if (naca->platform == PLATFORM_PSERIES) { if (systemcfg->platform == PLATFORM_PSERIES) {
unsigned long sp; unsigned long sp;
asm("mr %0,1" : "=r" (sp) :); asm("mr %0,1" : "=r" (sp) :);
if (s) if (s)
......
...@@ -457,7 +457,7 @@ void xics_init_IRQ(void) ...@@ -457,7 +457,7 @@ void xics_init_IRQ(void)
xics_irq_8259_cascade = virt_irq_create_mapping(xics_irq_8259_cascade_real); xics_irq_8259_cascade = virt_irq_create_mapping(xics_irq_8259_cascade_real);
} }
if (naca->platform == PLATFORM_PSERIES) { if (systemcfg->platform == PLATFORM_PSERIES) {
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
for (i = 0; i < NR_CPUS; ++i) { for (i = 0; i < NR_CPUS; ++i) {
if (!cpu_possible(i)) if (!cpu_possible(i))
...@@ -474,7 +474,7 @@ void xics_init_IRQ(void) ...@@ -474,7 +474,7 @@ void xics_init_IRQ(void)
/* actually iSeries does not use any of xics...but it has link dependencies /* actually iSeries does not use any of xics...but it has link dependencies
* for now, except this new one... * for now, except this new one...
*/ */
} else if (naca->platform == PLATFORM_PSERIES_LPAR) { } else if (systemcfg->platform == PLATFORM_PSERIES_LPAR) {
ops = &pSeriesLP_ops; ops = &pSeriesLP_ops;
#endif #endif
} }
......
...@@ -453,7 +453,7 @@ insert_bpts() ...@@ -453,7 +453,7 @@ insert_bpts()
int i; int i;
struct bpt *bp; struct bpt *bp;
if (naca->platform != PLATFORM_PSERIES) if (systemcfg->platform != PLATFORM_PSERIES)
return; return;
bp = bpts; bp = bpts;
for (i = 0; i < NBPTS; ++i, ++bp) { for (i = 0; i < NBPTS; ++i, ++bp) {
...@@ -482,7 +482,7 @@ remove_bpts() ...@@ -482,7 +482,7 @@ remove_bpts()
struct bpt *bp; struct bpt *bp;
unsigned instr; unsigned instr;
if (naca->platform != PLATFORM_PSERIES) if (systemcfg->platform != PLATFORM_PSERIES)
return; return;
if (cpu_has_dabr()) if (cpu_has_dabr())
......
...@@ -90,6 +90,8 @@ struct machdep_calls { ...@@ -90,6 +90,8 @@ struct machdep_calls {
unsigned char (*udbg_getc)(void); unsigned char (*udbg_getc)(void);
int (*udbg_getc_poll)(void); int (*udbg_getc_poll)(void);
/* this is for modules, since _machine can be a define -- Cort */
int ppc_machine;
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
/* functions for dealing with other cpus */ /* functions for dealing with other cpus */
struct smp_ops_t smp_ops; struct smp_ops_t smp_ops;
......
...@@ -221,6 +221,13 @@ static inline void _tlbiel(unsigned long va) ...@@ -221,6 +221,13 @@ static inline void _tlbiel(unsigned long va)
#endif /* __ASSEMBLY__ */ #endif /* __ASSEMBLY__ */
/*
* Location of cpu0's segment table
*/
#define STAB0_PAGE 0x9
#define STAB0_PHYS_ADDR (STAB0_PAGE<<PAGE_SHIFT)
#define STAB0_VIRT_ADDR (KERNELBASE+STAB0_PHYS_ADDR)
/* Block size masks */ /* Block size masks */
#define BL_128K 0x000 #define BL_128K 0x000
#define BL_256K 0x001 #define BL_256K 0x001
......
...@@ -11,29 +11,41 @@ ...@@ -11,29 +11,41 @@
*/ */
#include <asm/types.h> #include <asm/types.h>
#include <asm/systemcfg.h>
#ifndef __ASSEMBLY__
struct naca_struct { struct naca_struct {
void *xItVpdAreas; /*==================================================================
void *xRamDisk; * Cache line 1: 0x0000 - 0x007F
u64 xRamDiskSize; /* In pages */ * Kernel only data - undefined for user space
struct paca_struct *paca; /* Ptr to an array of pacas */ *==================================================================
u64 debug_switch; /* Bits to control debug printing */ */
u16 dCacheL1LineSize; /* Line size of L1 DCache in bytes */ void *xItVpdAreas; /* VPD Data 0x00 */
u16 dCacheL1LogLineSize; /* Log-2 of DCache line size */ void *xRamDisk; /* iSeries ramdisk 0x08 */
u16 dCacheL1LinesPerPage; /* DCache lines per page */ u64 xRamDiskSize; /* In pages 0x10 */
u16 iCacheL1LineSize; /* Line size of L1 ICache in bytes */ struct paca_struct *paca; /* Ptr to an array of pacas 0x18 */
u16 iCacheL1LogLineSize; /* Log-2 of ICache line size */ u64 debug_switch; /* Debug print control 0x20 */
u16 iCacheL1LinesPerPage; /* ICache lines per page */ u64 banner; /* Ptr to banner string 0x28 */
u16 slb_size; /* SLB size in entries */ u64 log; /* Ptr to log buffer 0x30 */
u64 physicalMemorySize; /* Size of real memory in bytes */ u64 serialPortAddr; /* Phy addr of serial port 0x38 */
u64 pftSize; /* Log base 2 of page table size */ u64 interrupt_controller; /* Type of int controller 0x40 */
u64 serialPortAddr; /* Phyical address of serial port */ u64 slb_size; /* SLB size in entries 0x48 */
u8 interrupt_controller; /* Type of interrupt controller */ u64 pftSize; /* Log 2 of page table size 0x50 */
u8 resv0; /* Type of interrupt controller */ void *systemcfg; /* Pointer to systemcfg data 0x58 */
u16 platform; /* Platform flags */ u32 dCacheL1LogLineSize; /* L1 d-cache line size Log2 0x60 */
u8 resv1[12]; /* Padding */ u32 dCacheL1LinesPerPage; /* L1 d-cache lines / page 0x64 */
u32 iCacheL1LogLineSize; /* L1 i-cache line size Log2 0x68 */
u32 iCacheL1LinesPerPage; /* L1 i-cache lines / page 0x6c */
u64 resv0[2]; /* Reserved 0x70 - 0x7F */
}; };
extern struct naca_struct *naca; extern struct naca_struct *naca;
#endif /* __ASSEMBLY__ */
#define NACA_PAGE 0x4
#define NACA_PHYS_ADDR (NACA_PAGE<<PAGE_SHIFT)
#define NACA_VIRT_ADDR (KERNELBASE+NACA_PHYS_ADDR)
#endif /* _NACA_H */ #endif /* _NACA_H */
...@@ -14,7 +14,11 @@ ...@@ -14,7 +14,11 @@
/* PAGE_SHIFT determines the page size */ /* PAGE_SHIFT determines the page size */
#define PAGE_SHIFT 12 #define PAGE_SHIFT 12
#define PAGE_SIZE (1UL << PAGE_SHIFT) #ifndef __ASSEMBLY__
# define PAGE_SIZE (1UL << PAGE_SHIFT)
#else
# define PAGE_SIZE (1 << PAGE_SHIFT)
#endif
#define PAGE_MASK (~(PAGE_SIZE-1)) #define PAGE_MASK (~(PAGE_SIZE-1))
#define PAGE_OFFSET_MASK (PAGE_SIZE-1) #define PAGE_OFFSET_MASK (PAGE_SIZE-1)
...@@ -22,6 +26,19 @@ ...@@ -22,6 +26,19 @@
#define SID_MASK 0xfffffffff #define SID_MASK 0xfffffffff
#define GET_ESID(x) (((x) >> SID_SHIFT) & SID_MASK) #define GET_ESID(x) (((x) >> SID_SHIFT) & SID_MASK)
/* align addr on a size boundary - adjust address up/down if needed */
#define _ALIGN_UP(addr,size) (((addr)+((size)-1))&(~((size)-1)))
#define _ALIGN_DOWN(addr,size) ((addr)&(~((size)-1)))
/* align addr on a size boundary - adjust address up if needed */
#define _ALIGN(addr,size) _ALIGN_UP(addr,size)
/* to align the pointer to the (next) double word boundary */
#define DOUBLEWORD_ALIGN(addr) _ALIGN(addr,sizeof(unsigned long))
/* to align the pointer to the (next) page boundary */
#define PAGE_ALIGN(addr) _ALIGN(addr, PAGE_SIZE)
#ifdef __KERNEL__ #ifdef __KERNEL__
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
#include <asm/naca.h> #include <asm/naca.h>
...@@ -37,7 +54,7 @@ static __inline__ void clear_page(void *addr) ...@@ -37,7 +54,7 @@ static __inline__ void clear_page(void *addr)
{ {
unsigned long lines, line_size; unsigned long lines, line_size;
line_size = naca->dCacheL1LineSize; line_size = systemcfg->dCacheL1LineSize;
lines = naca->dCacheL1LinesPerPage; lines = naca->dCacheL1LinesPerPage;
__asm__ __volatile__( __asm__ __volatile__(
...@@ -114,19 +131,6 @@ static inline int get_order(unsigned long size) ...@@ -114,19 +131,6 @@ static inline int get_order(unsigned long size)
#endif /* __ASSEMBLY__ */ #endif /* __ASSEMBLY__ */
/* align addr on a size boundary - adjust address up/down if needed */
#define _ALIGN_UP(addr,size) (((addr)+((size)-1))&(~((size)-1)))
#define _ALIGN_DOWN(addr,size) ((addr)&(~((size)-1)))
/* align addr on a size boundary - adjust address up if needed */
#define _ALIGN(addr,size) _ALIGN_UP(addr,size)
/* to align the pointer to the (next) double word boundary */
#define DOUBLEWORD_ALIGN(addr) _ALIGN(addr,sizeof(unsigned long))
/* to align the pointer to the (next) page boundary */
#define PAGE_ALIGN(addr) _ALIGN(addr, PAGE_SIZE)
#ifdef MODULE #ifdef MODULE
#define __page_aligned __attribute__((__aligned__(PAGE_SIZE))) #define __page_aligned __attribute__((__aligned__(PAGE_SIZE)))
#else #else
......
...@@ -25,9 +25,14 @@ ...@@ -25,9 +25,14 @@
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
void pmc_proc_init(struct proc_dir_entry *iSeries_proc); struct proc_ppc64_t {
void proc_ppc64_init(void); struct proc_dir_entry *root;
struct proc_dir_entry *naca;
struct proc_dir_entry *paca;
struct proc_dir_entry *systemcfg;
struct proc_dir_entry *rtas;
};
#include <asm/iSeries/iSeries_proc.h> extern struct proc_ppc64_t proc_ppc64;
#endif #endif /* _PPC64_PROC_FS_H */
...@@ -469,8 +469,6 @@ ...@@ -469,8 +469,6 @@
#define IOCR_SPC 0x00000001 #define IOCR_SPC 0x00000001
/* Processor Version Register */
/* Processor Version Register (PVR) field extraction */ /* Processor Version Register (PVR) field extraction */
#define PVR_VER(pvr) (((pvr) >> 16) & 0xFFFF) /* Version field */ #define PVR_VER(pvr) (((pvr) >> 16) & 0xFFFF) /* Version field */
...@@ -656,8 +654,10 @@ struct thread_struct { ...@@ -656,8 +654,10 @@ struct thread_struct {
struct pt_regs *regs; /* Pointer to saved register state */ struct pt_regs *regs; /* Pointer to saved register state */
mm_segment_t fs; /* for get_fs() validation */ mm_segment_t fs; /* for get_fs() validation */
double fpr[32]; /* Complete floating point set */ double fpr[32]; /* Complete floating point set */
unsigned long fpscr; /* Floating point status */ unsigned long fpscr; /* Floating point status (plus pad) */
unsigned int fpexc_mode; /* Floating-point exception mode */ unsigned long fpexc_mode; /* Floating-point exception mode */
unsigned long saved_msr; /* Save MSR across signal handlers */
unsigned long saved_softe; /* Ditto for Soft Enable/Disable */
}; };
#define INIT_SP (sizeof(init_stack) + (unsigned long) &init_stack) #define INIT_SP (sizeof(init_stack) + (unsigned long) &init_stack)
...@@ -704,7 +704,7 @@ static inline unsigned int __unpack_fe01(unsigned long msr_bits) ...@@ -704,7 +704,7 @@ static inline unsigned int __unpack_fe01(unsigned long msr_bits)
return ((msr_bits & MSR_FE0) >> 10) | ((msr_bits & MSR_FE1) >> 8); return ((msr_bits & MSR_FE0) >> 10) | ((msr_bits & MSR_FE1) >> 8);
} }
static inline unsigned int __pack_fe01(unsigned int fpmode) static inline unsigned long __pack_fe01(unsigned int fpmode)
{ {
return ((fpmode << 10) & MSR_FE0) | ((fpmode << 8) & MSR_FE1); return ((fpmode << 10) & MSR_FE0) | ((fpmode << 8) & MSR_FE1);
} }
......
...@@ -64,9 +64,8 @@ struct pt_regs32 { ...@@ -64,9 +64,8 @@ struct pt_regs32 {
#define STACK_FRAME_OVERHEAD 112 /* size of minimum stack frame */ #define STACK_FRAME_OVERHEAD 112 /* size of minimum stack frame */
/* Size of stack frame allocated when calling signal handler. */ /* Size of dummy stack frame allocated when calling signal handler. */
/* FIXME: What should this be on 64-bit kernel (64 for 32-bit) */ #define __SIGNAL_FRAMESIZE 128
#define __SIGNAL_FRAMESIZE 64
#define __SIGNAL_FRAMESIZE32 64 #define __SIGNAL_FRAMESIZE32 64
#define instruction_pointer(regs) ((regs)->nip) #define instruction_pointer(regs) ((regs)->nip)
......
...@@ -166,8 +166,6 @@ extern void rtas_restart(char *cmd); ...@@ -166,8 +166,6 @@ extern void rtas_restart(char *cmd);
extern void rtas_power_off(void); extern void rtas_power_off(void);
extern void rtas_halt(void); extern void rtas_halt(void);
extern struct proc_dir_entry *rtas_proc_dir;
/* Some RTAS ops require a data buffer and that buffer must be < 4G. /* Some RTAS ops require a data buffer and that buffer must be < 4G.
* Rather than having a memory allocator, just use this buffer * Rather than having a memory allocator, just use this buffer
* (get the lock first), make the RTAS call. Copy the data instead * (get the lock first), make the RTAS call. Copy the data instead
......
...@@ -9,6 +9,8 @@ ...@@ -9,6 +9,8 @@
*/ */
#include <asm/ptrace.h> #include <asm/ptrace.h>
#include <asm/elf.h>
struct sigcontext { struct sigcontext {
unsigned long _unused[4]; unsigned long _unused[4];
...@@ -16,7 +18,9 @@ struct sigcontext { ...@@ -16,7 +18,9 @@ struct sigcontext {
int _pad0; int _pad0;
unsigned long handler; unsigned long handler;
unsigned long oldmask; unsigned long oldmask;
struct pt_regs *regs; struct pt_regs *regs;
elf_gregset_t gp_regs;
elf_fpregset_t fp_regs;
}; };
#endif /* _ASM_PPC64_SIGCONTEXT_H */ #endif /* _ASM_PPC64_SIGCONTEXT_H */
#ifndef _SYSTEMCFG_H
#define _SYSTEMCFG_H
/*
* Copyright (C) 2002 Peter Bergner <bergner@vnet.ibm.com>, IBM
*
* 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.
*/
/* Change Activity:
* 2002/09/30 : bergner : Created
* End Change Activity
*/
#ifndef __KERNEL__
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <linux/types.h>
#endif
/*
* If the major version changes we are incompatible.
* Minor version changes are a hint.
*/
#define SYSTEMCFG_MAJOR 1
#define SYSTEMCFG_MINOR 0
#ifndef __ASSEMBLY__
struct systemcfg {
__u8 eye_catcher[16]; /* Eyecatcher: SYSTEMCFG:PPC64 0x00 */
struct { /* Systemcfg version numbers */
__u32 major; /* Major number 0x10 */
__u32 minor; /* Minor number 0x14 */
} version;
__u32 platform; /* Platform flags 0x18 */
__u32 processor; /* Processor type 0x1C */
__u64 processorCount; /* # of physical processors 0x20 */
__u64 physicalMemorySize; /* Size of real memory(B) 0x28 */
__u64 tb_orig_stamp; /* Timebase at boot 0x30 */
__u64 tb_ticks_per_sec; /* Timebase tics / sec 0x38 */
__u64 tb_to_xs; /* Inverse of TB to 2^20 0x40 */
__u64 stamp_xsec; /* 0x48 */
__u64 tb_update_count; /* Timebase atomicity ctr 0x50 */
__u32 tz_minuteswest; /* Minutes west of Greenwich 0x58 */
__u32 tz_dsttime; /* Type of dst correction 0x5C */
__u32 dCacheL1Size; /* L1 d-cache size 0x60 */
__u32 dCacheL1LineSize; /* L1 d-cache line size 0x64 */
__u32 iCacheL1Size; /* L1 i-cache size 0x68 */
__u32 iCacheL1LineSize; /* L1 i-cache line size 0x6C */
__u8 reserved0[3984]; /* Reserve rest of page 0x70 */
};
#ifdef __KERNEL__
extern struct systemcfg *systemcfg;
#else
/* Processor Version Register (PVR) field extraction */
#define PVR_VER(pvr) (((pvr) >> 16) & 0xFFFF) /* Version field */
#define PVR_REV(pvr) (((pvr) >> 0) & 0xFFFF) /* Revison field */
/* Processor Version Numbers */
#define PV_NORTHSTAR 0x0033
#define PV_PULSAR 0x0034
#define PV_POWER4 0x0035
#define PV_ICESTAR 0x0036
#define PV_SSTAR 0x0037
#define PV_POWER4p 0x0038
#define PV_630 0x0040
#define PV_630p 0x0041
/* Platforms supported by PPC64 */
#define PLATFORM_PSERIES 0x0100
#define PLATFORM_PSERIES_LPAR 0x0101
#define PLATFORM_ISERIES_LPAR 0x0201
static inline volatile struct systemcfg *systemcfg_init(void)
{
int fd = open("/proc/ppc64/systemcfg", O_RDONLY);
volatile struct systemcfg *ret;
if (fd == -1)
return 0;
ret = mmap(0, sizeof(struct systemcfg), PROT_READ, MAP_SHARED, fd, 0);
close(fd);
if (!ret)
return 0;
if (ret->version.major != SYSTEMCFG_MAJOR || ret->version.minor < SYSTEMCFG_MINOR) {
munmap((void *)ret, sizeof(struct systemcfg));
return 0;
}
return ret;
}
#endif /* __KERNEL__ */
#endif /* __ASSEMBLY__ */
#define SYSTEMCFG_PAGE 0x5
#define SYSTEMCFG_PHYS_ADDR (SYSTEMCFG_PAGE<<PAGE_SHIFT)
#define SYSTEMCFG_VIRT_ADDR (KERNELBASE+SYSTEMCFG_PHYS_ADDR)
#endif /* _SYSTEMCFG_H */
...@@ -66,6 +66,11 @@ typedef __vector128 vector128; ...@@ -66,6 +66,11 @@ typedef __vector128 vector128;
typedef u32 dma_addr_t; typedef u32 dma_addr_t;
typedef u64 dma64_addr_t; typedef u64 dma64_addr_t;
typedef struct {
unsigned long entry;
unsigned long toc;
unsigned long env;
} func_descr_t;
#endif /* __ASSEMBLY__ */ #endif /* __ASSEMBLY__ */
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
......
#ifndef _ASMPPC64_UCONTEXT_H #ifndef _ASMPPC64_UCONTEXT_H
#define _ASMPPC64_UCONTEXT_H #define _ASMPPC64_UCONTEXT_H
/* Copied from i386. #include <asm/sigcontext.h>
*
/*
* 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
* as published by the Free Software Foundation; either version * as published by the Free Software Foundation; either version
...@@ -13,8 +14,9 @@ struct ucontext { ...@@ -13,8 +14,9 @@ struct ucontext {
unsigned long uc_flags; unsigned long uc_flags;
struct ucontext *uc_link; struct ucontext *uc_link;
stack_t uc_stack; stack_t uc_stack;
struct sigcontext uc_mcontext; sigset_t uc_sigmask;
sigset_t uc_sigmask; /* mask last for extensibility */ sigset_t __unsued[15]; /* Allow for uc_sigmask growth */
struct sigcontext uc_mcontext; /* last for extensibility */
}; };
#endif /* _ASMPPC64_UCONTEXT_H */ #endif /* _ASMPPC64_UCONTEXT_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment