Commit f42a2cae authored by Anton Blanchard's avatar Anton Blanchard

Merge samba.org:/home/anton/ppc64/tmp

into samba.org:/home/anton/ppc64/for-linus-ppc64
parents 634e7218 c8248804
......@@ -61,7 +61,7 @@ struct HvReleaseData hvReleaseData = {
0xc8a5d9c4, /* desc = "HvRD" ebcdic */
sizeof(struct HvReleaseData),
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) */
0,
1, /* tags inactive */
......
......@@ -15,7 +15,7 @@ obj-$(CONFIG_PPC_ISERIES) += iSeries_pci.o iSeries_pci_reset.o \
iSeries_IoMmTable.o iSeries_irq.o \
iSeries_VpdInfo.o XmPciLpEvent.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
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 \
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_SMP) += smp.o
obj-$(CONFIG_MODULES) += module.o ppc_ksyms.o
......
......@@ -309,6 +309,7 @@ fix_alignment(struct pt_regs *regs)
/* Doing stfs, have to convert to single */
enable_kernel_fp();
cvt_df(&current->thread.fpr[reg], (float *)&data.v[4], &current->thread.fpscr);
disable_kernel_fp();
}
else
data.dd = current->thread.fpr[reg];
......@@ -342,6 +343,7 @@ fix_alignment(struct pt_regs *regs)
/* Doing lfs, have to convert to double */
enable_kernel_fp();
cvt_fd((float *)&data.v[4], &current->thread.fpr[reg], &current->thread.fpscr);
disable_kernel_fp();
}
else
current->thread.fpr[reg] = data.dd;
......
......@@ -59,14 +59,14 @@ int main(void)
/* naca */
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(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(ICACHEL1LINESPERPAGE, offsetof(struct naca_struct, iCacheL1LinesPerPage));
DEFINE(SLBSIZE, offsetof(struct naca_struct, slb_size));
DEFINE(PLATFORM, offsetof(struct naca_struct, platform));
DEFINE(PLATFORM, offsetof(struct systemcfg, platform));
/* paca */
DEFINE(PACA_SIZE, sizeof(struct paca_struct));
......
......@@ -228,6 +228,7 @@ chrp_init(unsigned long r3, unsigned long r4, unsigned long r5,
#endif /* CONFIG_BLK_DEV_INITRD */
#endif
ppc_md.ppc_machine = systemcfg->platform;
ppc_md.setup_arch = chrp_setup_arch;
ppc_md.setup_residual = NULL;
ppc_md.get_cpuinfo = chrp_get_cpuinfo;
......
......@@ -225,10 +225,6 @@ _GLOBAL(ppc32_rt_sigreturn)
bl .sys32_rt_sigreturn
b 80f
_GLOBAL(ppc64_sigreturn)
bl .sys_sigreturn
b 80f
_GLOBAL(ppc64_rt_sigreturn)
bl .sys_rt_sigreturn
......
......@@ -29,6 +29,8 @@
#include <asm/processor.h>
#include <asm/page.h>
#include <asm/mmu.h>
#include <asm/naca.h>
#include <asm/systemcfg.h>
#include <asm/ppc_asm.h>
#include <asm/offsets.h>
#include <asm/bug.h>
......@@ -49,8 +51,9 @@
* 0x0100 - 0x2fff : pSeries Interrupt prologs
* 0x3000 - 0x3fff : Interrupt support
* 0x4000 - 0x4fff : NACA
* 0x5000 - 0x5fff : Initial segment table
* 0x5000 - 0x5fff : SystemCfg
* 0x6000 : iSeries and common interrupt prologs
* 0x9000 - 0x9fff : Initial segment table
*/
/*
......@@ -123,6 +126,10 @@ __secondary_hold_acknowledge:
* All of it must fit below the first exception vector at 0x100.
*/
_GLOBAL(__secondary_hold)
mfmsr r24
ori r24,r24,MSR_RI
mtmsrd r24 /* RI on */
/* Grab our linux cpu number */
mr r24,r3
......@@ -362,11 +369,11 @@ __start_interrupts:
STD_EXCEPTION_PSERIES( 0x1300, InstructionBreakpoint )
/* 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
* point to itVpdAreas. On pSeries native, this value is not used.
*/
. = 0x4000
. = NACA_PHYS_ADDR
.globl __end_interrupts
.globl __start_naca
__end_interrupts:
......@@ -380,21 +387,14 @@ __start_naca:
.llong 0x0
.llong paca
/*
* 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
. = SYSTEMCFG_PHYS_ADDR
.globl __end_naca
.globl __start_stab
.globl __start_systemcfg
__end_naca:
__start_stab:
. = 0x6000
.globl __end_stab
__end_stab:
__start_systemcfg:
. = (SYSTEMCFG_PHYS_ADDR + PAGE_SIZE)
.globl __end_systemcfg
__end_systemcfg:
#ifdef CONFIG_PPC_ISERIES
/*
......@@ -408,7 +408,7 @@ __end_stab:
.llong 1 /* # ESIDs 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 */
......@@ -529,6 +529,20 @@ SystemReset_FWNMI:
MachineCheck_FWNMI:
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 ***/
STD_EXCEPTION_COMMON( 0x100, SystemReset, .SystemResetException )
......@@ -782,11 +796,16 @@ ProgramCheck_common:
FPUnavailable_common:
EXCEPTION_PROLOG_COMMON
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
bl .save_remaining_regs /* if from kernel, take a trap */
bl .KernelFP
b .ret_from_except
bl .save_remaining_regs
bl .KernelFPUnavailableException
BUG_OPCODE
.globl SystemCall_common
SystemCall_common:
......@@ -1252,9 +1271,12 @@ _GLOBAL(__start_initialization_iSeries)
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)
SET_REG_TO_CONST(r4, KERNELBASE)
addi r4,r4,0x4000
SET_REG_TO_CONST(r4, NACA_VIRT_ADDR)
std r4,0(r9) /* set the naca pointer */
/* Get the pointer to the segment table */
......@@ -1285,13 +1307,18 @@ _GLOBAL(__start_initialization_pSeries)
/* Relocate the TOC from a virt addr to a real addr */
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 */
LOADADDR(r9,naca)
sub r9,r9,r3 /* addr of the variable naca */
SET_REG_TO_CONST(r4, KERNELBASE)
SET_REG_TO_CONST(r4, NACA_VIRT_ADDR)
sub r4,r4,r3
addi r4,r4,0x4000
std r4,0(r9) /* set the value of naca */
/* DRENG / PPPBBB Fix the following comment!!! -Peter */
......@@ -1410,11 +1437,13 @@ _STATIC(copy_and_flush)
copy_to_here:
/*
* load_up_fpu(unused, unused, tsk)
* Disable FP for the task which had the FPU previously,
* and save its floating-point registers in its thread_struct.
* Enables the FPU for use in the kernel on return.
* 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)
mfmsr r5 /* grab the current MSR */
......@@ -1432,27 +1461,30 @@ _STATIC(load_up_fpu)
ld r4,last_task_used_math@l(r3)
cmpi 0,r4,0
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)
mffs fr0
stfd fr0,THREAD_FPSCR(r4)
/* Disable FP for last_task_used_math */
ld r5,PT_REGS(r4)
ld r4,_MSR-STACK_FRAME_OVERHEAD(r5)
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)
1:
#endif /* CONFIG_SMP */
/* enable use of FP after return */
ld r4,PACACURRENT(r13)
addi r5,r4,THREAD /* Get THREAD */
lwz r4,THREAD_FPEXC_MODE(r5)
ld r4,THREAD_FPEXC_MODE(r5)
ori r23,r23,MSR_FP
or r23,r23,r4
lfd fr0,THREAD_FPSCR(r5)
mtfsf 0xff,fr0
REST_32FPRS(0, r5)
#ifndef CONFIG_SMP
/* Update last_task_used_math to 'current' */
subi r4,r5,THREAD /* Back to 'current' */
std r4,last_task_used_math@l(r3)
#endif /* CONFIG_SMP */
......@@ -1460,19 +1492,16 @@ _STATIC(load_up_fpu)
b fast_exception_return
/*
* FP unavailable trap from kernel - print a message, but let
* the task use FP in the kernel until it returns to user mode.
* disable_kernel_fp()
* Disable the FPU.
*/
_GLOBAL(KernelFP)
ld r3,_MSR(r1)
ori r3,r3,MSR_FP
std r3,_MSR(r1) /* enable use of FP after return */
LOADADDR(r3,86f)
ld r4,PACACURRENT(r13) /* current */
ld r5,_NIP(r1)
b .ret_from_except
86: .string "floating point used in kernel (task=%p, pc=%x)\n"
.align 4
_GLOBAL(disable_kernel_fp)
mfmsr r3
rldicl r0,r3,(63-MSR_FP_LG),1
rldicl r3,r0,(MSR_FP_LG+1),0
mtmsrd r3 /* disable use of fpu now */
isync
blr
/*
* giveup_fpu(tsk)
......@@ -1562,8 +1591,8 @@ _GLOBAL(__secondary_start)
sc /* HvCall_setASR */
#else
/* set the ASR */
addi r3,0,0x4000 /* r3 = ptr to naca */
lhz r3,PLATFORM(r3) /* r3 = platform flags */
li r3,SYSTEMCFG_PHYS_ADDR /* r3 = ptr to systemcfg */
lwz r3,PLATFORM(r3) /* r3 = platform flags */
cmpldi r3,PLATFORM_PSERIES_LPAR
bne 98f
mfspr r3,PVR
......@@ -1642,10 +1671,20 @@ _STATIC(start_here_pSeries)
bl .reloc_offset
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 */
LOADADDR(r6,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 */
#ifdef CONFIG_HMT
......@@ -1709,15 +1748,12 @@ _STATIC(start_here_pSeries)
sub r13,r13,r26 /* convert to physical addr */
mtspr SPRG3,r13 /* PPPBBB: Temp... -Peter */
li r3,0x5000
std r3,PACASTABREAL(r13)
LOADADDR(r24, __start_stab)
std r24,PACASTABVIRT(r13)
ld r3,PACASTABREAL(r13)
ori r4,r3,1 /* turn on valid bit */
/* set the ASR */
addi r3,0,0x4000 /* r3 = ptr to naca */
lhz r3,PLATFORM(r3) /* r3 = platform flags */
li r3,SYSTEMCFG_PHYS_ADDR /* r3 = ptr to systemcfg */
lwz r3,PLATFORM(r3) /* r3 = platform flags */
cmpldi r3,PLATFORM_PSERIES_LPAR
bne 98f
mfspr r3,PVR
......@@ -1741,8 +1777,8 @@ _STATIC(start_here_pSeries)
bl .stab_initialize
bl .htab_initialize
addi r3,0,0x4000 /* r3 = ptr to naca */
lhz r3,PLATFORM(r3) /* r3 = platform flags */
li r3,SYSTEMCFG_PHYS_ADDR /* r3 = ptr to systemcfg */
lwz r3,PLATFORM(r3) /* r3 = platform flags */
cmpldi r3,PLATFORM_PSERIES
bne 98f
LOADADDR(r6,_SDR1) /* Only if NOT LPAR */
......@@ -1791,11 +1827,14 @@ _STATIC(start_here_common)
addi r2,r2,0x4000
addi r2,r2,0x4000
/* setup the systemcfg pointer */
LOADADDR(r9,systemcfg)
SET_REG_TO_CONST(r8, SYSTEMCFG_VIRT_ADDR)
std r8,0(r9)
/* setup the naca pointer */
LOADADDR(r9,naca)
SET_REG_TO_CONST(r8, KERNELBASE)
addi r8,r8,0x4000
SET_REG_TO_CONST(r8, NACA_VIRT_ADDR)
std r8,0(r9) /* set the value of the naca ptr */
LOADADDR(r26, boot_cpuid)
......@@ -1946,7 +1985,7 @@ ioremap_dir:
hardware_int_paca0:
.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
stab_array:
.space 4096 * 48
......
......@@ -101,7 +101,7 @@ create_pte_mapping(unsigned long start, unsigned long end,
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,
(unsigned long)__v2a(addr) >> PAGE_SHIFT,
0, mode, 1, large);
......@@ -140,7 +140,7 @@ htab_initialize(void)
htab_data.htab_num_ptegs = pteg_count;
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
* the absolute address space.
*/
......@@ -165,15 +165,15 @@ htab_initialize(void)
mode_rw = _PAGE_ACCESSED | _PAGE_COHERENT | PP_RWXX;
/* 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,
KERNELBASE + 256*MB, mode_rw, 0);
create_pte_mapping((unsigned long)KERNELBASE + 256*MB,
KERNELBASE + (naca->physicalMemorySize),
KERNELBASE + (systemcfg->physicalMemorySize),
mode_rw, 1);
} else {
create_pte_mapping((unsigned long)KERNELBASE,
KERNELBASE+(naca->physicalMemorySize),
KERNELBASE+(systemcfg->physicalMemorySize),
mode_rw, 0);
}
}
......
......@@ -561,13 +561,13 @@ static void __init build_iSeries_Memory_Map(void)
* which should be equal to
* nextPhysChunk
*/
naca->physicalMemorySize = chunk_to_addr(nextPhysChunk);
systemcfg->physicalMemorySize = chunk_to_addr(nextPhysChunk);
/* Bolt kernel mappings for all of memory */
iSeries_bolt_kernel( 0, naca->physicalMemorySize );
iSeries_bolt_kernel( 0, systemcfg->physicalMemorySize );
lmb_init();
lmb_add( 0, naca->physicalMemorySize );
lmb_add( 0, systemcfg->physicalMemorySize );
lmb_analyze(); /* ?? */
lmb_reserve( 0, __pa(klimit));
......@@ -584,29 +584,28 @@ static void __init build_iSeries_Memory_Map(void)
static void __init setup_iSeries_cache_sizes(void)
{
unsigned i,n;
unsigned procIx = get_paca()->xLpPaca.xDynHvPhysicalProcIndex;
unsigned int i, n;
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;
naca->dCacheL1LineSize = xIoHriProcessorVpd[procIx].xDataCacheOperandSize;
naca->iCacheL1LinesPerPage = PAGE_SIZE / naca->iCacheL1LineSize;
naca->dCacheL1LinesPerPage = PAGE_SIZE / naca->dCacheL1LineSize;
i = naca->iCacheL1LineSize;
i = systemcfg->iCacheL1LineSize;
n = 0;
while ((i=(i/2))) ++n;
naca->iCacheL1LogLineSize = n;
i = naca->dCacheL1LineSize;
i = systemcfg->dCacheL1LineSize;
n = 0;
while ((i=(i/2))) ++n;
naca->dCacheL1LogLineSize = n;
printk( "D-cache line size = %d (log = %d)\n",
(unsigned)naca->dCacheL1LineSize,
(unsigned)naca->dCacheL1LogLineSize );
printk( "I-cache line size = %d (log = %d)\n",
(unsigned)naca->iCacheL1LineSize,
(unsigned)naca->iCacheL1LogLineSize );
printk( "D-cache line size = %d\n", (unsigned int)systemcfg->dCacheL1LineSize);
printk( "I-cache line size = %d\n", (unsigned int)systemcfg->iCacheL1LineSize);
}
/*
......@@ -648,6 +647,11 @@ iSeries_setup_arch(void)
void * eventStack;
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 */
/* Allocate a page for the Event Stack
......@@ -696,8 +700,8 @@ iSeries_setup_arch(void)
printk("Time base frequency = %lu.%02lu\n",
tbFreqMhz,
tbFreqMhzHundreths );
printk("Processor version = %x\n",
xIoHriProcessorVpd[procIx].xPVR );
systemcfg->processor = xIoHriProcessorVpd[procIx].xPVR;
printk("Processor version = %x\n", systemcfg->processor);
}
......@@ -726,9 +730,9 @@ void iSeries_setup_residual(struct seq_file *m)
seq_printf(m,"time base\t: %lu.%02luMHz\n",
tbFreqMhz, tbFreqMhzHundreths );
seq_printf(m,"i-cache\t\t: %d\n",
naca->iCacheL1LineSize);
systemcfg->iCacheL1LineSize);
seq_printf(m,"d-cache\t\t: %d\n",
naca->dCacheL1LineSize);
systemcfg->dCacheL1LineSize);
}
......
......@@ -170,12 +170,14 @@ _GLOBAL(flush_icache_range)
*/
LOADADDR(r10,naca) /* Get Naca address */
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
andc r6,r3,r5 /* round low to line bdy */
subf r8,r6,r4 /* compute length */
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 */
beqlr /* nothing to do? */
mtctr r8
......@@ -186,12 +188,12 @@ _GLOBAL(flush_icache_range)
/* 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
andc r6,r3,r5 /* round low to line bdy */
subf r8,r6,r4 /* compute length */
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 */
beqlr /* nothing to do? */
mtctr r8
......@@ -217,12 +219,14 @@ _GLOBAL(flush_dcache_range)
*/
LOADADDR(r10,naca) /* Get Naca address */
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
andc r6,r3,r5 /* round low to line bdy */
subf r8,r6,r4 /* compute length */
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 */
beqlr /* nothing to do? */
mtctr r8
......@@ -249,9 +253,11 @@ _GLOBAL(__flush_dcache_icache)
/* Flush the dcache */
LOADADDR(r7,naca)
ld r7,0(r7)
LOADADDR(r8,systemcfg) /* Get systemcfg address */
ld r8,0(r8)
clrrdi r3,r3,12 /* Page align */
lhz r4,DCACHEL1LINESPERPAGE(r7) /* Get # dcache lines per page */
lhz r5,DCACHEL1LINESIZE(r7) /* Get dcache line size */
lwz r4,DCACHEL1LINESPERPAGE(r7) /* Get # dcache lines per page */
lwz r5,DCACHEL1LINESIZE(r8) /* Get dcache line size */
mr r6,r3
mtctr r4
0: dcbst 0,r6
......@@ -261,8 +267,8 @@ _GLOBAL(__flush_dcache_icache)
/* Now invalidate the icache */
lhz r4,ICACHEL1LINESPERPAGE(r7) /* Get # icache lines per page */
lhz r5,ICACHEL1LINESIZE(r7) /* Get icache line size */
lwz r4,ICACHEL1LINESPERPAGE(r7) /* Get # icache lines per page */
lwz r5,ICACHEL1LINESIZE(r8) /* Get icache line size */
mtctr r4
1: icbi 0,r3
add r3,r3,r5
......@@ -574,7 +580,7 @@ _GLOBAL(sys_call_table32)
.llong .sys32_ssetmask
.llong .sys_setreuid /* 70 */
.llong .sys_setregid
.llong .sys_sigsuspend
.llong .sys32_sigsuspend
.llong .compat_sys_sigpending
.llong .sys32_sethostname
.llong .compat_sys_setrlimit /* 75 */
......@@ -812,13 +818,13 @@ _GLOBAL(sys_call_table)
.llong .sys_getppid
.llong .sys_getpgrp /* 65 */
.llong .sys_setsid
.llong .sys_sigaction
.llong .sys_ni_syscall
.llong .sys_sgetmask
.llong .sys_ssetmask
.llong .sys_setreuid /* 70 */
.llong .sys_setregid
.llong .sys_sigsuspend
.llong .sys_sigpending
.llong .sys_ni_syscall
.llong .sys_ni_syscall
.llong .sys_sethostname
.llong .sys_setrlimit /* 75 */
.llong .sys_ni_syscall /* old getrlimit syscall */
......@@ -864,14 +870,14 @@ _GLOBAL(sys_call_table)
.llong .sys_sysinfo
.llong .sys_ipc
.llong .sys_fsync
.llong .ppc64_sigreturn
.llong .sys_ni_syscall
.llong .sys_clone /* 120 */
.llong .sys_setdomainname
.llong .ppc64_newuname
.llong .sys_ni_syscall /* old modify_ldt syscall */
.llong .sys_adjtimex
.llong .sys_mprotect /* 125 */
.llong .sys_sigprocmask
.llong .sys_ni_syscall
.llong .sys_ni_syscall /* old create_module syscall */
.llong .sys_init_module
.llong .sys_delete_module
......
......@@ -20,6 +20,7 @@
#include <asm/paca.h>
struct naca_struct *naca;
struct systemcfg *systemcfg;
/* The Paca is an array with one entry per processor. Each contains an
* ItLpPaca, which contains the information shared between the
......@@ -65,9 +66,9 @@ struct naca_struct *naca;
struct paca_struct paca[MAX_PACAS] __page_aligned = {
#ifdef CONFIG_PPC_ISERIES
PACAINITDATA( 0, 1, &xItLpQueue, 0, 0xc000000000005000),
PACAINITDATA( 0, 1, &xItLpQueue, 0, STAB0_VIRT_ADDR),
#else
PACAINITDATA( 0, 1, 0, 0x5000, 0xc000000000005000),
PACAINITDATA( 0, 1, 0, STAB0_PHYS_ADDR, STAB0_VIRT_ADDR),
#endif
PACAINITDATA( 1, 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)
dev = ppc64_isabridge_dev;
if (!dev)
return NULL;
if (naca->platform == PLATFORM_ISERIES_LPAR) {
if (systemcfg->platform == PLATFORM_ISERIES_LPAR) {
return ISERIES_DEVNODE(dev)->DevTceTable;
} else {
return PCI_GET_DN(dev)->tce_table;
......@@ -732,7 +732,7 @@ void create_tce_tables(void) {
struct pci_dev *dev;
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);
}
else {
......@@ -773,7 +773,7 @@ void create_pci_bus_tce_table( unsigned long token ) {
/* - Tce Table Share between buses, */
/* - 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;
getTceTableParmsiSeries(DevNode,newTceTable);
......@@ -797,7 +797,7 @@ void create_pci_bus_tce_table( unsigned long token ) {
dn = (struct device_node *)token;
phb = dn->phb;
if (naca->platform == PLATFORM_PSERIES)
if (systemcfg->platform == PLATFORM_PSERIES)
getTceTableParmsPSeries(phb, dn, newTceTable);
else
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;
#define FB_MAX 8
#endif
static int ppc64_is_smp;
struct prom_t prom = {
0, /* entry */
......@@ -301,7 +300,9 @@ prom_initialize_naca(unsigned long mem)
unsigned long offset = reloc_offset();
struct prom_t *_prom = PTRRELOC(&prom);
struct naca_struct *_naca = RELOC(naca);
struct systemcfg *_systemcfg = RELOC(systemcfg);
/* NOTE: _naca->debug_switch is already initialized. */
#ifdef DEBUG_PROM
prom_print(RELOC("prom_initialize_naca: start...\n"));
#endif
......@@ -320,25 +321,35 @@ prom_initialize_naca(unsigned long mem)
* d-cache and i-cache sizes... -Peter
*/
if ( num_cpus == 1 ) {
u32 size;
u32 size, lsize;
call_prom(RELOC("getprop"), 4, 1, node,
RELOC("d-cache-line-size"),
RELOC("d-cache-size"),
&size, sizeof(size));
_naca->dCacheL1LineSize = size;
_naca->dCacheL1LogLineSize = __ilog2(size);
_naca->dCacheL1LinesPerPage = PAGE_SIZE / size;
call_prom(RELOC("getprop"), 4, 1, node,
RELOC("d-cache-line-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,
RELOC("i-cache-line-size"),
RELOC("i-cache-size"),
&size, sizeof(size));
_naca->iCacheL1LineSize = size;
_naca->iCacheL1LogLineSize = __ilog2(size);
_naca->iCacheL1LinesPerPage = PAGE_SIZE / size;
call_prom(RELOC("getprop"), 4, 1, node,
RELOC("i-cache-line-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];
call_prom(RELOC("getprop"), 4, 1, node,
RELOC("ibm,pft-size"),
......@@ -408,20 +419,17 @@ prom_initialize_naca(unsigned long mem)
}
/* We gotta have at least 1 cpu... */
if (num_cpus < 1)
if ( (_systemcfg->processorCount = num_cpus) < 1 )
PROM_BUG();
if (num_cpus > 1)
RELOC(ppc64_is_smp) = 1;
_systemcfg->physicalMemorySize = lmb_phys_mem_size();
_naca->physicalMemorySize = lmb_phys_mem_size();
if (_naca->platform == PLATFORM_PSERIES) {
if (_systemcfg->platform == PLATFORM_PSERIES) {
unsigned long rnd_mem_size, pteg_count;
/* round mem_size up to next power of 2 */
rnd_mem_size = 1UL << __ilog2(_naca->physicalMemorySize);
if (rnd_mem_size < _naca->physicalMemorySize)
rnd_mem_size = 1UL << __ilog2(_systemcfg->physicalMemorySize);
if (rnd_mem_size < _systemcfg->physicalMemorySize)
rnd_mem_size <<= 1;
/* # pages / 2 */
......@@ -442,37 +450,31 @@ prom_initialize_naca(unsigned long mem)
*/
_naca->slb_size = 64;
#ifdef DEBUG_PROM
prom_print(RELOC("naca->physicalMemorySize = 0x"));
prom_print_hex(_naca->physicalMemorySize);
prom_print_nl();
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();
/* Add an eye catcher and the systemcfg layout version number */
strcpy(_systemcfg->eye_catcher, RELOC("SYSTEMCFG:PPC64"));
_systemcfg->version.major = SYSTEMCFG_MAJOR;
_systemcfg->version.minor = SYSTEMCFG_MINOR;
_systemcfg->processor = _get_PVR();
prom_print(RELOC("naca->dCacheL1LogLineSize = 0x"));
prom_print_hex(_naca->dCacheL1LogLineSize);
#ifdef DEBUG_PROM
prom_print(RELOC("systemcfg->processorCount = 0x"));
prom_print_hex(_systemcfg->processorCount);
prom_print_nl();
prom_print(RELOC("naca->dCacheL1LinesPerPage = 0x"));
prom_print_hex(_naca->dCacheL1LinesPerPage);
prom_print(RELOC("systemcfg->physicalMemorySize = 0x"));
prom_print_hex(_systemcfg->physicalMemorySize);
prom_print_nl();
prom_print(RELOC("naca->iCacheL1LineSize = 0x"));
prom_print_hex(_naca->iCacheL1LineSize);
prom_print(RELOC("naca->pftSize = 0x"));
prom_print_hex(_naca->pftSize);
prom_print_nl();
prom_print(RELOC("naca->iCacheL1LogLineSize = 0x"));
prom_print_hex(_naca->iCacheL1LogLineSize);
prom_print(RELOC("systemcfg->dCacheL1LineSize = 0x"));
prom_print_hex(_systemcfg->dCacheL1LineSize);
prom_print_nl();
prom_print(RELOC("naca->iCacheL1LinesPerPage = 0x"));
prom_print_hex(_naca->iCacheL1LinesPerPage);
prom_print(RELOC("systemcfg->iCacheL1LineSize = 0x"));
prom_print_hex(_systemcfg->iCacheL1LineSize);
prom_print_nl();
prom_print(RELOC("naca->serialPortAddr = 0x"));
......@@ -483,8 +485,8 @@ prom_initialize_naca(unsigned long mem)
prom_print_hex(_naca->interrupt_controller);
prom_print_nl();
prom_print(RELOC("naca->platform = 0x"));
prom_print_hex(_naca->platform);
prom_print(RELOC("systemcfg->platform = 0x"));
prom_print_hex(_systemcfg->platform);
prom_print_nl();
prom_print(RELOC("prom_initialize_naca: end...\n"));
......@@ -549,7 +551,7 @@ prom_instantiate_rtas(void)
unsigned long offset = reloc_offset();
struct prom_t *_prom = PTRRELOC(&prom);
struct rtas_t *_rtas = PTRRELOC(&rtas);
struct naca_struct *_naca = RELOC(naca);
struct systemcfg *_systemcfg = RELOC(systemcfg);
ihandle prom_rtas;
u32 getprop_rval;
......@@ -565,7 +567,7 @@ prom_instantiate_rtas(void)
RELOC("ibm,hypertas-functions"),
hypertas_funcs,
sizeof(hypertas_funcs))) > 0) {
_naca->platform = PLATFORM_PSERIES_LPAR;
_systemcfg->platform = PLATFORM_PSERIES_LPAR;
}
call_prom(RELOC("getprop"),
......@@ -582,7 +584,7 @@ prom_instantiate_rtas(void)
* of physical memory (or within the RMO region) because RTAS
* 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);
rtas_region = min(_lmb->rmo_size, RTAS_INSTANTIATE_MAX);
}
......@@ -773,7 +775,7 @@ prom_initialize_tce_table(void)
align = (minalign < minsize) ? minsize : minalign;
/* Carve out storage for the TCE table. */
base = lmb_alloc(8UL << 20, 8UL << 20);
base = lmb_alloc(minsize, align);
if ( !base ) {
prom_print(RELOC("ERROR, cannot find space for TCE table.\n"));
......@@ -875,7 +877,7 @@ static void
prom_hold_cpus(unsigned long mem)
{
unsigned long i;
unsigned int reg;
unsigned int cpuid;
phandle node;
unsigned long offset = reloc_offset();
char type[64], *path;
......@@ -885,9 +887,13 @@ prom_hold_cpus(unsigned long mem)
unsigned long *spinloop = __v2a(&__secondary_hold_spinloop);
unsigned long *acknowledge = __v2a(&__secondary_hold_acknowledge);
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 prom_t *_prom = PTRRELOC(&prom);
/* Initially, we must have one active CPU. */
_systemcfg->processorCount = 1;
#ifdef DEBUG_PROM
prom_print(RELOC("prom_hold_cpus: start...\n"));
prom_print(RELOC(" 1) spinloop = 0x"));
......@@ -933,12 +939,12 @@ prom_hold_cpus(unsigned long mem)
if (strcmp(type, RELOC("okay")) != 0)
continue;
reg = -1;
cpuid = -1;
call_prom(RELOC("getprop"), 4, 1, node, RELOC("reg"),
&reg, sizeof(reg));
&cpuid, sizeof(cpuid));
/* Only need to start secondary procs, not ourself. */
if ( reg == _prom->cpu )
if ( cpuid == _prom->cpu )
continue;
path = (char *) mem;
......@@ -950,7 +956,7 @@ prom_hold_cpus(unsigned long mem)
#ifdef DEBUG_PROM
prom_print_nl();
prom_print(RELOC("cpu hw idx = 0x"));
prom_print_hex(reg);
prom_print_hex(cpuid);
prom_print_nl();
#endif
prom_print(RELOC("starting cpu "));
......@@ -978,9 +984,8 @@ prom_hold_cpus(unsigned long mem)
prom_print(RELOC(" 3) secondary_hold = 0x"));
prom_print_hex(secondary_hold);
prom_print_nl();
prom_print_nl();
#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("..."));
for ( i = 0 ; (i < 100000000) &&
(*acknowledge == ((unsigned long)-1)); i++ ) ;
......@@ -992,10 +997,11 @@ prom_hold_cpus(unsigned long mem)
prom_print_nl();
}
#endif
if (*acknowledge == reg) {
if (*acknowledge == cpuid) {
prom_print(RELOC("ok\n"));
/* Set the number of active processors. */
_xPaca[reg].active = 1;
_systemcfg->processorCount++;
_xPaca[cpuid].active = 1;
} else {
prom_print(RELOC("failed: "));
prom_print_hex(*acknowledge);
......@@ -1024,8 +1030,8 @@ prom_hold_cpus(unsigned long mem)
}
}
_xPaca[i+1].active = 1;
RELOC(hmt_thread_data)[i].threadid = i+1;
}
_systemcfg->processorCount *= 2;
} else {
prom_print(RELOC("Processor is not HMT capable\n"));
}
......@@ -1046,20 +1052,21 @@ unsigned long __init
prom_init(unsigned long r3, unsigned long r4, unsigned long pp,
unsigned long r6, unsigned long r7)
{
int chrp = 0;
unsigned long mem;
ihandle prom_root, prom_cpu;
ihandle prom_mmu, prom_op, prom_root, prom_cpu;
phandle cpu_pkg;
unsigned long offset = reloc_offset();
long l;
long l, sz;
char *p, *d;
unsigned long phys;
u32 getprop_rval;
struct naca_struct *_naca = RELOC(naca);
struct systemcfg *_systemcfg = RELOC(systemcfg);
struct paca_struct *_xPaca = PTRRELOC(&paca[0]);
struct prom_t *_prom = PTRRELOC(&prom);
/* Default machine type. */
_naca->platform = PLATFORM_PSERIES;
_systemcfg->platform = PLATFORM_PSERIES;
#if 0
/* 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,
}
_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_ */
if ((long)call_prom(RELOC("getprop"), 4, 1, _prom->chosen,
RELOC("cpu"), &getprop_rval,
......@@ -1149,6 +1181,8 @@ prom_init(unsigned long r3, unsigned long r4, unsigned long pp,
mem = prom_bi_rec_reserve(mem);
mem = check_display(mem);
prom_instantiate_rtas();
/* Initialize some system info into the Naca early... */
......@@ -1158,11 +1192,9 @@ prom_init(unsigned long r3, unsigned long r4, unsigned long pp,
* following, regardless of whether we have an SMP
* kernel or not.
*/
if (RELOC(ppc64_is_smp))
if (_systemcfg->processorCount > 1)
prom_hold_cpus(mem);
mem = check_display(mem);
#ifdef DEBUG_PROM
prom_print(RELOC("copying OF device tree...\n"));
#endif
......@@ -1172,12 +1204,38 @@ prom_init(unsigned long r3, unsigned long r4, unsigned long pp,
lmb_reserve(0, __pa(RELOC(klimit)));
if (_naca->platform == PLATFORM_PSERIES)
if (_systemcfg->platform == PLATFORM_PSERIES)
prom_initialize_tce_table();
if ((long) call_prom(RELOC("getprop"), 4, 1,
_prom->chosen,
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"));
return phys;
......
......@@ -201,7 +201,7 @@ void proc_rtas_init(void)
struct proc_dir_entry *entry;
rtas_node = find_devices("rtas");
if ((rtas_node == NULL) || (naca->platform == PLATFORM_ISERIES_LPAR)) {
if ((rtas_node == NULL) || (systemcfg->platform == PLATFORM_ISERIES_LPAR)) {
return;
}
......
......@@ -18,6 +18,7 @@
#include <linux/module.h>
#include <asm/prom.h>
#include <asm/proc_fs.h>
#include <asm/rtas.h>
#include <asm/semaphore.h>
#include <asm/machdep.h>
......@@ -27,7 +28,6 @@
#include <asm/abs_addr.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};
/*
......@@ -283,7 +283,7 @@ rtas_halt(void)
rtas_power_off();
}
EXPORT_SYMBOL(rtas_proc_dir);
EXPORT_SYMBOL(proc_ppc64);
EXPORT_SYMBOL(rtas_firmware_flash_list);
EXPORT_SYMBOL(rtas_token);
EXPORT_SYMBOL(rtas_call);
......
......@@ -210,7 +210,7 @@ int __init rtas_flash_init(void)
{
struct proc_dir_entry *ent = NULL;
if (!rtas_proc_dir) {
if (!proc_ppc64.rtas) {
printk(KERN_WARNING "rtas proc dir does not already exist");
return -ENOENT;
}
......@@ -218,7 +218,7 @@ int __init rtas_flash_init(void)
if (rtas_token("ibm,update-flash-64-and-reboot") != RTAS_UNKNOWN_SERVICE)
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->proc_fops = &rtas_flash_operations;
ent->owner = THIS_MODULE;
......@@ -228,9 +228,9 @@ int __init rtas_flash_init(void)
void __exit rtas_flash_cleanup(void)
{
if (!rtas_proc_dir)
if (!proc_ppc64.rtas)
return;
remove_proc_entry(FIRMWARE_FLASH_NAME, rtas_proc_dir);
remove_proc_entry(FIRMWARE_FLASH_NAME, proc_ppc64.rtas);
}
module_init(rtas_flash_init);
......
......@@ -156,10 +156,10 @@ void setup_system(unsigned long r3, unsigned long r4, unsigned long r5,
#ifdef CONFIG_PPC_ISERIES
/* pSeries systems are identified in prom.c via OF. */
if ( itLpNaca.xLparInstalled == 1 )
naca->platform = PLATFORM_ISERIES_LPAR;
systemcfg->platform = PLATFORM_ISERIES_LPAR;
#endif
switch (naca->platform) {
switch (systemcfg->platform) {
#ifdef CONFIG_PPC_ISERIES
case PLATFORM_ISERIES_LPAR:
iSeries_init_early();
......@@ -185,7 +185,7 @@ void setup_system(unsigned long r3, unsigned long r4, unsigned long r5,
#endif
}
if (naca->platform & PLATFORM_PSERIES) {
if (systemcfg->platform & PLATFORM_PSERIES) {
early_console_initialized = 1;
register_console(&udbg_console);
}
......@@ -194,31 +194,26 @@ void setup_system(unsigned long r3, unsigned long r4, unsigned long r5,
printk("-----------------------------------------------------\n");
printk("naca = 0x%p\n", naca);
#if 0
printk("naca->processorCount = 0x%x\n", naca->processorCount);
#endif
printk("naca->physicalMemorySize = 0x%lx\n", naca->physicalMemorySize);
printk("naca->dCacheL1LineSize = 0x%x\n", naca->dCacheL1LineSize);
printk("naca->dCacheL1LogLineSize = 0x%x\n", naca->dCacheL1LogLineSize);
printk("naca->dCacheL1LinesPerPage = 0x%x\n", naca->dCacheL1LinesPerPage);
printk("naca->iCacheL1LineSize = 0x%x\n", naca->iCacheL1LineSize);
printk("naca->iCacheL1LogLineSize = 0x%x\n", naca->iCacheL1LogLineSize);
printk("naca->iCacheL1LinesPerPage = 0x%x\n", naca->iCacheL1LinesPerPage);
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("systemcf = 0x%p\n", systemcfg);
printk("systemcfg->processorCount = 0x%x\n", systemcfg->processorCount);
printk("systemcfg->physicalMemorySize = 0x%lx\n", systemcfg->physicalMemorySize);
printk("systemcfg->dCacheL1LineSize = 0x%x\n", systemcfg->dCacheL1LineSize);
printk("systemcfg->iCacheL1LineSize = 0x%x\n", systemcfg->iCacheL1LineSize);
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");
if (naca->platform & PLATFORM_PSERIES) {
if (systemcfg->platform & PLATFORM_PSERIES) {
finish_device_tree();
chrp_init(r3, r4, r5, r6, r7);
}
mm_init_ppc64();
switch (naca->platform) {
switch (systemcfg->platform) {
#ifdef CONFIG_PPC_ISERIES
case PLATFORM_ISERIES_LPAR:
iSeries_init();
......@@ -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
* smp system. -- Cort
*/
if (naca->platform != PLATFORM_ISERIES_LPAR) {
if (systemcfg->platform != PLATFORM_ISERIES_LPAR) {
struct device_node *cpu_node;
int *fp;
......@@ -516,8 +511,8 @@ void __init setup_arch(char **cmdline_p)
* Systems with OF can look in the properties on the cpu node(s)
* for a possibly more accurate value.
*/
dcache_bsize = naca->dCacheL1LineSize;
icache_bsize = naca->iCacheL1LineSize;
dcache_bsize = systemcfg->dCacheL1LineSize;
icache_bsize = systemcfg->iCacheL1LineSize;
/* reboot on panic */
panic_timeout = 180;
......
......@@ -43,57 +43,29 @@
#endif
#define GP_REGS_SIZE MIN(sizeof(elf_gregset_t), sizeof(struct pt_regs))
#define FP_REGS_SIZE sizeof(elf_fpregset_t)
/*
* These are the flags in the MSR that the user is allowed to change
* 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
#define TRAMP_TRACEBACK 3
#define TRAMP_SIZE 6
/*
* When we have signals to deliver, we set up on the
* user stack, going down from the original stack pointer:
* a sigregs struct
* one or more sigcontext structs with
* a gap of __SIGNAL_FRAMESIZE bytes
*
* Each of these things must be a multiple of 16 bytes in size.
*
* When we have signals to deliver, we set up on the user stack,
* going down from the original stack pointer:
* 1) a rt_sigframe struct which contains the ucontext
* 2) a gap of __SIGNAL_FRAMESIZE bytes which acts as a dummy caller
* frame for the signal handler.
*/
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 */
struct ucontext uc;
unsigned long _unused[2];
unsigned int tramp[TRAMP_SIZE];
struct siginfo *pinfo;
void *puc;
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);
/*
* 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,
int p7, struct pt_regs *regs)
{
......@@ -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]);
}
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 ret;
int err = 0;
if (act) {
old_sigset_t mask;
if (regs->msr & MSR_FP)
giveup_fpu(current);
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);
}
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;
ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
if (!ret && oact) {
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);
}
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);
return ret;
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
* 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.
*
* Restore the sigcontext from the signal frame.
*/
int sys_rt_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7, unsigned long r8,
struct pt_regs *regs)
static int
restore_sigcontext(struct pt_regs *regs, sigset_t *set, struct sigcontext *sc)
{
struct rt_sigframe *rt_sf;
struct sigcontext sigctx;
struct sigregs *sr;
elf_gregset_t saved_regs; /* an array of ELF_NGREG unsigned longs */
sigset_t set;
stack_t st;
unsigned int err = 0;
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)
giveup_fpu(current);
/* restore registers -
* sigctx is initialized to point to the
* preamble frame (where registers are stored)
* see handle_signal()
*/
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);
err |= __copy_from_user(regs, &sc->gp_regs, GP_REGS_SIZE);
err |= __copy_from_user(&current->thread.fpr, &sc->fp_regs, FP_REGS_SIZE);
current->thread.fpexc_mode = regs->msr & (MSR_FE0 | MSR_FE1);
if (set != NULL)
err |= __get_user(set->sig[0], &sc->oldmask);
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:
do_exit(SIGSEGV);
return err;
}
static void setup_rt_frame(struct pt_regs *regs, struct sigregs *frame,
signed long newsp)
{
struct rt_sigframe *rt_sf = (struct rt_sigframe *)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.
/*
* Allocate space for the signal frame
*/
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 */
static inline void *
get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
{
unsigned long newsp;
/* Retrieve rt_sigframe from stack and
set up registers for signal handler
*/
newsp -= __SIGNAL_FRAMESIZE;
/* Default to using normal stack */
newsp = regs->gpr[1];
if (get_user(temp_ptr, &rt_sf->uc.uc_mcontext.handler)) {
goto badframe;
if (ka->sa.sa_flags & SA_ONSTACK) {
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;
static int
setup_trampoline(unsigned int syscall, unsigned int *tramp)
{
int i, err = 0;
regs->gpr[1] = newsp;
regs->gpr[6] = (unsigned long)rt_sf;
regs->link = (unsigned long)frame->tramp;
/* 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]);
return;
/* Minimal traceback info */
for (i=TRAMP_TRACEBACK; i < TRAMP_SIZE ;i++)
err |= __put_user(0, &tramp[i]);
badframe:
#if DEBUG_SIG
printk("badframe in setup_rt_frame, regs=%p frame=%p newsp=%lx\n",
regs, frame, newsp);
#endif
do_exit(SIGSEGV);
if (!err)
flush_icache_range((unsigned long) &tramp[0],
(unsigned long) &tramp[TRAMP_SIZE]);
return err;
}
/*
* Do a signal return; undo the signal stack.
*/
long sys_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5,
int sys_rt_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7, unsigned long r8,
struct pt_regs *regs)
{
struct sigcontext *sc, sigctx;
struct sigregs *sr;
elf_gregset_t saved_regs; /* an array of ELF_NGREG unsigned longs */
struct ucontext *uc = (struct ucontext *)regs->gpr[1];
sigset_t set;
stack_t st;
sc = (struct sigcontext *)(regs->gpr[1] + __SIGNAL_FRAMESIZE);
if (copy_from_user(&sigctx, sc, sizeof(sigctx)))
if (verify_area(VERIFY_READ, uc, sizeof(*uc)))
goto badframe;
set.sig[0] = sigctx.oldmask;
#if _NSIG_WORDS > 1
set.sig[1] = sigctx._unused[3];
#endif
if (__copy_from_user(&set, &uc->uc_sigmask, sizeof(set)))
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)
giveup_fpu(current);
/* restore registers */
sr = (struct sigregs *)sigctx.regs;
if (copy_from_user(saved_regs, &sr->gp_regs, sizeof(sr->gp_regs)))
if (restore_sigcontext(regs, NULL, &uc->uc_mcontext))
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)))
if (__copy_from_user(&st, &uc->uc_stack, sizeof(st)))
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;
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);
}
/*
* Set up a signal frame.
*/
static void setup_frame(struct pt_regs *regs, struct sigregs *frame,
unsigned long newsp)
static void
setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info,
sigset_t *set, struct pt_regs *regs)
{
/* 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;
};
func_descr_t *funct_desc_ptr;
struct rt_sigframe *frame;
unsigned long newsp = 0;
int err = 0;
struct funct_descr_entry * funct_desc_ptr;
unsigned long temp_ptr;
struct sigcontext *sc = (struct sigcontext *)newsp;
frame = get_sigframe(ka, regs, sizeof(*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_sigreturn */
|| __put_user(0x38000000UL + __NR_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 */
newsp -= __SIGNAL_FRAMESIZE;
if (get_user(temp_ptr, &sc->handler))
err |= __put_user(&frame->info, &frame->pinfo);
err |= __put_user(&frame->uc, &frame->puc);
err |= copy_siginfo_to_user(&frame->info, info);
if (err)
goto badframe;
funct_desc_ptr = (struct funct_descr_entry *)temp_ptr;
/* Create the ucontext. */
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;
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], &sc->signal))
/* Set up to return from userspace. */
err |= setup_trampoline(__NR_rt_sigreturn, &frame->tramp[0]);
if (err)
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[4] = (unsigned long)sc;
regs->link = (unsigned long)frame->tramp;
err |= get_user(regs->gpr[2], &funct_desc_ptr->toc);
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;
badframe:
#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);
#endif
do_exit(SIGSEGV);
}
/*
* OK, we're invoking a handler
*/
static void handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset,
struct pt_regs * regs, unsigned long *newspp, unsigned long frame)
static void
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 */
if (ka->sa.sa_flags & SA_SIGINFO) {
/* 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;
}
setup_rt_frame(sig, ka, info, oldset, regs);
if (ka->sa.sa_flags & SA_ONESHOT)
ka->sa.sa_handler = SIG_DFL;
......@@ -515,14 +349,40 @@ static void handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset,
spin_unlock_irq(&current->sighand->siglock);
}
return;
}
badframe:
#if DEBUG_SIG
printk("badframe in handle_signal, regs=%p frame=%lx newsp=%lx\n",
regs, frame, *newspp);
printk("sc=%p sig=%d ka=%p info=%p oldset=%p\n", sc, sig, ka, info, oldset);
#endif
do_exit(SIGSEGV);
static inline void
syscall_restart(struct pt_regs *regs, struct k_sigaction *ka)
{
switch ((int)regs->result) {
case -ERESTART_RESTARTBLOCK:
current_thread_info()->restart_block.fn = do_no_restart_syscall;
/* 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);
int do_signal(sigset_t *oldset, struct pt_regs *regs)
{
siginfo_t info;
struct k_sigaction *ka;
unsigned long frame, newsp;
int signr;
/*
......@@ -549,20 +407,15 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
if (!oldset)
oldset = &current->blocked;
newsp = frame = 0;
signr = get_signal_to_deliver(&info, regs, NULL);
if (signr > 0) {
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);
struct k_sigaction *ka = &current->sighand->action[signr-1];
/* 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! */
......@@ -579,13 +432,8 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
}
}
if (newsp == frame)
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;
return 0;
}
......@@ -114,6 +114,40 @@ struct rt_sigframe_32 {
* 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,
struct old_sigaction32 *oact)
{
......@@ -792,13 +826,13 @@ int sys32_rt_sigsuspend(compat_sigset_t* unewset, size_t sigsetsize, int p3,
while (1) {
current->state = TASK_INTERRUPTIBLE;
schedule();
if (do_signal(&saveset, regs))
if (do_signal32(&saveset, regs))
/*
* 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
* 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).
*/
return regs->gpr[3];
......
......@@ -178,7 +178,7 @@ void __init smp_init_iSeries(void)
smp_ops->kick_cpu = smp_iSeries_kick_cpu;
smp_ops->setup_cpu = smp_iSeries_setup_cpu;
#warning fix for iseries
naca->processorCount = smp_iSeries_numProcs();
systemcfg->processorCount = smp_iSeries_numProcs();
}
#endif
......@@ -342,7 +342,7 @@ void __init smp_init_pSeries(void)
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->take_timebase = pSeries_take_timebase;
}
......
......@@ -346,6 +346,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
SingleStepException(struct pt_regs *regs)
{
......
......@@ -176,7 +176,7 @@ udbg_puthex(unsigned long val)
void
udbg_printSP(const char *s)
{
if (naca->platform == PLATFORM_PSERIES) {
if (systemcfg->platform == PLATFORM_PSERIES) {
unsigned long sp;
asm("mr %0,1" : "=r" (sp) :);
if (s)
......
......@@ -460,7 +460,7 @@ void xics_init_IRQ(void)
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
for (i = 0; i < NR_CPUS; ++i) {
if (!cpu_possible(i))
......@@ -477,7 +477,7 @@ void xics_init_IRQ(void)
/* actually iSeries does not use any of xics...but it has link dependencies
* for now, except this new one...
*/
} else if (naca->platform == PLATFORM_PSERIES_LPAR) {
} else if (systemcfg->platform == PLATFORM_PSERIES_LPAR) {
ops = &pSeriesLP_ops;
#endif
}
......
......@@ -453,7 +453,7 @@ insert_bpts()
int i;
struct bpt *bp;
if (naca->platform != PLATFORM_PSERIES)
if (systemcfg->platform != PLATFORM_PSERIES)
return;
bp = bpts;
for (i = 0; i < NBPTS; ++i, ++bp) {
......@@ -482,7 +482,7 @@ remove_bpts()
struct bpt *bp;
unsigned instr;
if (naca->platform != PLATFORM_PSERIES)
if (systemcfg->platform != PLATFORM_PSERIES)
return;
if (cpu_has_dabr())
......
......@@ -90,6 +90,8 @@ struct machdep_calls {
unsigned char (*udbg_getc)(void);
int (*udbg_getc_poll)(void);
/* this is for modules, since _machine can be a define -- Cort */
int ppc_machine;
#ifdef CONFIG_SMP
/* functions for dealing with other cpus */
struct smp_ops_t smp_ops;
......
......@@ -221,6 +221,13 @@ static inline void _tlbiel(unsigned long va)
#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 */
#define BL_128K 0x000
#define BL_256K 0x001
......
......@@ -11,29 +11,41 @@
*/
#include <asm/types.h>
#include <asm/systemcfg.h>
#ifndef __ASSEMBLY__
struct naca_struct {
void *xItVpdAreas;
void *xRamDisk;
u64 xRamDiskSize; /* In pages */
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 */
u16 dCacheL1LogLineSize; /* Log-2 of DCache line size */
u16 dCacheL1LinesPerPage; /* DCache lines per page */
u16 iCacheL1LineSize; /* Line size of L1 ICache in bytes */
u16 iCacheL1LogLineSize; /* Log-2 of ICache line size */
u16 iCacheL1LinesPerPage; /* ICache lines per page */
u16 slb_size; /* SLB size in entries */
u64 physicalMemorySize; /* Size of real memory in bytes */
u64 pftSize; /* Log base 2 of page table size */
u64 serialPortAddr; /* Phyical address of serial port */
u8 interrupt_controller; /* Type of interrupt controller */
u8 resv0; /* Type of interrupt controller */
u16 platform; /* Platform flags */
u8 resv1[12]; /* Padding */
/*==================================================================
* Cache line 1: 0x0000 - 0x007F
* Kernel only data - undefined for user space
*==================================================================
*/
void *xItVpdAreas; /* VPD Data 0x00 */
void *xRamDisk; /* iSeries ramdisk 0x08 */
u64 xRamDiskSize; /* In pages 0x10 */
struct paca_struct *paca; /* Ptr to an array of pacas 0x18 */
u64 debug_switch; /* Debug print control 0x20 */
u64 banner; /* Ptr to banner string 0x28 */
u64 log; /* Ptr to log buffer 0x30 */
u64 serialPortAddr; /* Phy addr of serial port 0x38 */
u64 interrupt_controller; /* Type of int controller 0x40 */
u64 slb_size; /* SLB size in entries 0x48 */
u64 pftSize; /* Log 2 of page table size 0x50 */
void *systemcfg; /* Pointer to systemcfg data 0x58 */
u32 dCacheL1LogLineSize; /* L1 d-cache line size Log2 0x60 */
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;
#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 */
......@@ -14,7 +14,11 @@
/* PAGE_SHIFT determines the page size */
#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_OFFSET_MASK (PAGE_SIZE-1)
......@@ -22,6 +26,19 @@
#define SID_MASK 0xfffffffff
#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__
#ifndef __ASSEMBLY__
#include <asm/naca.h>
......@@ -37,7 +54,7 @@ static __inline__ void clear_page(void *addr)
{
unsigned long lines, line_size;
line_size = naca->dCacheL1LineSize;
line_size = systemcfg->dCacheL1LineSize;
lines = naca->dCacheL1LinesPerPage;
__asm__ __volatile__(
......@@ -114,19 +131,6 @@ static inline int get_order(unsigned long size)
#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
#define __page_aligned __attribute__((__aligned__(PAGE_SIZE)))
#else
......
......@@ -25,9 +25,14 @@
#include <linux/proc_fs.h>
void pmc_proc_init(struct proc_dir_entry *iSeries_proc);
void proc_ppc64_init(void);
struct proc_ppc64_t {
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 @@
#define IOCR_SPC 0x00000001
/* Processor Version Register */
/* Processor Version Register (PVR) field extraction */
#define PVR_VER(pvr) (((pvr) >> 16) & 0xFFFF) /* Version field */
......@@ -656,8 +654,10 @@ struct thread_struct {
struct pt_regs *regs; /* Pointer to saved register state */
mm_segment_t fs; /* for get_fs() validation */
double fpr[32]; /* Complete floating point set */
unsigned long fpscr; /* Floating point status */
unsigned int fpexc_mode; /* Floating-point exception mode */
unsigned long fpscr; /* Floating point status (plus pad) */
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)
......@@ -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);
}
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);
}
......
......@@ -64,9 +64,8 @@ struct pt_regs32 {
#define STACK_FRAME_OVERHEAD 112 /* size of minimum stack frame */
/* Size of stack frame allocated when calling signal handler. */
/* FIXME: What should this be on 64-bit kernel (64 for 32-bit) */
#define __SIGNAL_FRAMESIZE 64
/* Size of dummy stack frame allocated when calling signal handler. */
#define __SIGNAL_FRAMESIZE 128
#define __SIGNAL_FRAMESIZE32 64
#define instruction_pointer(regs) ((regs)->nip)
......
......@@ -166,8 +166,6 @@ extern void rtas_restart(char *cmd);
extern void rtas_power_off(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.
* Rather than having a memory allocator, just use this buffer
* (get the lock first), make the RTAS call. Copy the data instead
......
......@@ -9,6 +9,8 @@
*/
#include <asm/ptrace.h>
#include <asm/elf.h>
struct sigcontext {
unsigned long _unused[4];
......@@ -17,6 +19,8 @@ struct sigcontext {
unsigned long handler;
unsigned long oldmask;
struct pt_regs *regs;
elf_gregset_t gp_regs;
elf_fpregset_t fp_regs;
};
#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;
typedef u32 dma_addr_t;
typedef u64 dma64_addr_t;
typedef struct {
unsigned long entry;
unsigned long toc;
unsigned long env;
} func_descr_t;
#endif /* __ASSEMBLY__ */
#endif /* __KERNEL__ */
......
#ifndef _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
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
......@@ -13,8 +14,9 @@ struct ucontext {
unsigned long uc_flags;
struct ucontext *uc_link;
stack_t uc_stack;
struct sigcontext uc_mcontext;
sigset_t uc_sigmask; /* mask last for extensibility */
sigset_t uc_sigmask;
sigset_t __unsued[15]; /* Allow for uc_sigmask growth */
struct sigcontext uc_mcontext; /* last for extensibility */
};
#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