Commit 48822524 authored by Anton Blanchard's avatar Anton Blanchard

rework kernel stack usage

remove old ioctls
parent efe80e09
......@@ -42,10 +42,19 @@ show_syscalls_task:
.long -1
#endif
.section ".toc","aw"
.SYS_CALL_TABLE:
.tc .sys_call_table[TC],.sys_call_table
.SYS_CALL_TABLE32:
.tc .sys_call_table32[TC],.sys_call_table32
.section ".text"
.align 3
/*
* Handle a system call.
*/
.text
_GLOBAL(DoSyscall)
std r0,THREAD+LAST_SYSCALL(r13)
ld r11,_CCR(r1) /* Clear SO bit in CR */
......@@ -94,7 +103,7 @@ _GLOBAL(DoSyscall)
#ifdef CONFIG_BINFMT_ELF32
andi. r11,r10,_TIF_32BIT
beq- 15f
LOADADDR(r10,.sys_call_table32)
ld r10,.SYS_CALL_TABLE32@toc(2)
/*
* Now mung the first 4 parameters into shape, by making certain that
* the high bits (most significant 32 bits in 64 bit reg) are 0
......@@ -111,7 +120,7 @@ _GLOBAL(DoSyscall)
b 17f
15:
#endif
LOADADDR(r10,.sys_call_table)
ld r10,.SYS_CALL_TABLE@toc(2)
17: slwi r0,r0,3
ldx r10,r10,r0 /* Fetch system call handler [ptr] */
mtlr r10
......@@ -167,7 +176,7 @@ _GLOBAL(ret_from_syscall_1)
ld r10,TI_FLAGS(r10)
andi. r11,r10,_TIF_32BIT
beq- 55f
LOADADDR(r10,.sys_call_table32)
ld r10,.SYS_CALL_TABLE32@toc(2)
/*
* Now mung the first 4 parameters into shape, by making certain that
* the high bits (most significant 32 bits in 64 bit reg) are 0
......@@ -184,7 +193,7 @@ _GLOBAL(ret_from_syscall_1)
b 57f
55:
#endif
LOADADDR(r10,.sys_call_table)
ld r10,.SYS_CALL_TABLE@toc(2)
57:
slwi r0,r0,3
ldx r10,r10,r0 /* Fetch system call handler [ptr] */
......@@ -255,38 +264,33 @@ _GLOBAL(ppc64_rt_sigreturn)
* Note: there are two ways to get to the "going out" portion
* of this code; either by coming in via the entry (_switch)
* or via "fork" which must set up an environment equivalent
* to the "_switch" path. If you change this (or in particular, the
* SAVE_REGS macro), you'll have to change the fork code also.
* to the "_switch" path. If you change this you'll have to change
* the fork code also.
*
* The code which creates the new task context is in 'copy_thread'
* in arch/ppc/kernel/process.c
* in arch/ppc64/kernel/process.c
*/
_GLOBAL(_switch)
stdu r1,-INT_FRAME_SIZE(r1)
ld r6,0(r1)
std r6,GPR1(r1)
mflr r0
std r0,16(r1)
stdu r1,-SWITCH_FRAME_SIZE(r1)
/* r3-r13 are caller saved -- Cort */
SAVE_GPR(2, r1)
SAVE_8GPRS(14, r1)
SAVE_10GPRS(22, r1)
mflr r20 /* Return to switch caller */
mfmsr r22
andi. r21, r22, MSR_FP
beq+ 1f
li r6,MSR_FP /* Disable floating-point */
andc r22,r22,r6
mtmsrd r22
isync
std r20,_NIP(r1)
std r22,_MSR(r1)
std r20,_LINK(r1)
mfcr r20
std r20,_CCR(r1)
li r6,0x0ff0
std r6,TRAP(r1)
1: std r20,_NIP(r1)
mfcr r23
std r23,_CCR(r1)
std r1,KSP(r3) /* Set old stack pointer */
mfspr r5,SPRG3 /* Get Paca */
/* XXX remove - Anton */
addi r3,r3,-THREAD /* old 'current' for return value */
addi r13,r4,-THREAD /* Convert THREAD to 'current' */
std r13,PACACURRENT(r5) /* Set new 'current' */
......@@ -298,6 +302,7 @@ _GLOBAL(_switch)
insrdi r9,r7,1,63 /* Insert run light into CTRL */
mtspr CTRLT,r9
#endif
ld r1,KSP(r4) /* Load new stack pointer */
ld r6,_CCR(r1)
mtcrf 0xFF,r6
......@@ -306,8 +311,8 @@ _GLOBAL(_switch)
REST_10GPRS(22, r1)
ld r7,_NIP(r1) /* Return to _switch caller in new task */
ld r1,GPR1(r1)
mtlr r7
addi r1,r1,SWITCH_FRAME_SIZE
blr
_GLOBAL(ret_from_fork)
......@@ -377,6 +382,7 @@ restore:
mtlr r0
ld r3,_XER(r1)
mtspr XER,r3
REST_8GPRS(5, r1)
REST_10GPRS(14, r1)
REST_8GPRS(24, r1)
......
......@@ -3737,8 +3737,6 @@ COMPATIBLE_IOCTL(BLKROSET),
COMPATIBLE_IOCTL(BLKROGET),
COMPATIBLE_IOCTL(BLKRRPART),
COMPATIBLE_IOCTL(BLKFLSBUF),
COMPATIBLE_IOCTL(BLKRASET),
COMPATIBLE_IOCTL(BLKFRASET),
COMPATIBLE_IOCTL(BLKSECTSET),
COMPATIBLE_IOCTL(BLKSSZGET),
COMPATIBLE_IOCTL(BLKBSZGET),
......@@ -4311,10 +4309,8 @@ HANDLE_IOCTL(SIOCDELRT, routing_ioctl),
HANDLE_IOCTL(SIOCRTMSG, ret_einval),
HANDLE_IOCTL(SIOCGSTAMP, do_siocgstamp),
HANDLE_IOCTL(HDIO_GETGEO, hdio_getgeo),
HANDLE_IOCTL(BLKRAGET, w_long),
HANDLE_IOCTL(BLKGETSIZE, w_long),
HANDLE_IOCTL(0x1260, broken_blkgetsize),
HANDLE_IOCTL(BLKFRAGET, w_long),
HANDLE_IOCTL(BLKSECTGET, w_long),
HANDLE_IOCTL(BLKPG, blkpg_ioctl_trans),
HANDLE_IOCTL(HDIO_GET_KEEPSETTINGS, hdio_ioctl_trans),
......
......@@ -496,25 +496,15 @@ _GLOBAL(cvt_df)
* kernel_thread(fn, arg, flags)
*/
_GLOBAL(kernel_thread)
/* XXX fix this when we optimise syscall entry to not save volatiles */
mr r6,r3 /* function */
ori r3,r5,CLONE_VM /* flags */
li r0,__NR_clone
sc
cmpi 0,r3,0 /* parent or child? */
bnelr /* return if parent */
li r0,0 /* clear out p->thread.regs */
std r0,THREAD+PT_REGS(r13) /* since we don't have user ctx */
clrrdi r5,r1,THREAD_SHIFT
ld r0,TI_FLAGS(r5)
li r7,_TIF_32BIT
andc r0,r0,r7
#ifdef CONFIG_PPC_ISERIES
ori r0,r0,_TIF_RUN_LIGHT /* Run light on */
#endif
std r0,TI_FLAGS(r5)
li r0,0
stdu r0,-STACK_FRAME_OVERHEAD(r1)
ld r2,8(r6)
ld r6,0(r6)
mtlr r6 /* fn addr in lr */
......
......@@ -115,12 +115,14 @@ main(void)
/* Interrupt register frame */
DEFINE(STACK_FRAME_OVERHEAD, STACK_FRAME_OVERHEAD);
DEFINE(SWITCH_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs));
/* 288 = # of volatile regs, int & fp, for leaf routines */
/* which do not stack a frame. See the PPC64 ABI. */
DEFINE(INT_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs) + 288);
/* Create extra stack space for SRR0 and SRR1 when calling prom/rtas. */
DEFINE(PROM_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs) + 16 + 288);
DEFINE(RTAS_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs) + 16 + 288);
DEFINE(PROM_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs) + 16);
DEFINE(RTAS_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs) + 16);
DEFINE(GPR0, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[0]));
DEFINE(GPR1, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[1]));
DEFINE(GPR2, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[2]));
......
/*
* linux/arch/ppc/kernel/process.c
* linux/arch/ppc64/kernel/process.c
*
* Derived from "arch/i386/kernel/process.c"
* Copyright (C) 1995 Linus Torvalds
......@@ -45,19 +45,18 @@
#include <asm/iSeries/HvCallHpt.h>
#include <asm/Naca.h>
#include "ppc_defs.h"
int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpregs);
extern unsigned long _get_SP(void);
struct task_struct *last_task_used_math = NULL;
struct mm_struct ioremap_mm = { pgd : ioremap_dir
,page_table_lock : SPIN_LOCK_UNLOCKED };
char *sysmap = NULL;
char *sysmap = NULL;
unsigned long sysmap_size = 0;
extern char __toc_start;
void
enable_kernel_fp(void)
{
......@@ -84,10 +83,7 @@ void
_switch_to(struct task_struct *prev, struct task_struct *new)
{
struct thread_struct *new_thread, *old_thread;
unsigned long s;
__save_flags(s);
__cli();
unsigned long flags;
#ifdef CONFIG_SMP
/* avoid complexity of lazy save/restore of fpu
......@@ -99,14 +95,16 @@ _switch_to(struct task_struct *prev, struct task_struct *new)
* every switch, just a save.
* -- Cort
*/
if ( prev->thread.regs && (prev->thread.regs->msr & MSR_FP) )
if (prev->thread.regs && (prev->thread.regs->msr & MSR_FP))
giveup_fpu(prev);
#endif /* CONFIG_SMP */
new_thread = &new->thread;
old_thread = &current->thread;
__save_and_cli(flags);
_switch(old_thread, new_thread);
__restore_flags(s);
__restore_flags(flags);
}
void show_regs(struct pt_regs * regs)
......@@ -172,45 +170,50 @@ release_thread(struct task_struct *t)
int
copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
unsigned long unused,
struct task_struct * p, struct pt_regs * regs)
struct task_struct *p, struct pt_regs *regs)
{
unsigned long msr;
struct pt_regs *childregs, *kregs;
extern void ret_from_fork(void);
/* XXX get rid of the -2 Anton */
unsigned long sp = (unsigned long)p->thread_info + THREAD_SIZE;
/* Copy registers */
childregs = ((struct pt_regs *)
((unsigned long)p->thread_info + THREAD_SIZE
- STACK_FRAME_OVERHEAD)) - 2;
sp -= sizeof(struct pt_regs);
childregs = (struct pt_regs *) sp;
*childregs = *regs;
if ((childregs->msr & MSR_PR) == 0) {
/* for kernel thread, set `current' and stackptr in new task */
childregs->gpr[1] = sp + sizeof(struct pt_regs);
childregs->gpr[13] = (unsigned long) p;
p->thread.regs = NULL; /* no user register state */
clear_ti_thread_flag(p->thread_info, TIF_32BIT);
#ifdef CONFIG_PPC_ISERIES
set_ti_thread_flag(p->thread_info, TIF_RUN_LIGHT);
#endif
} else
p->thread.regs = childregs;
childregs->gpr[3] = 0; /* Result from fork() */
p->thread.regs = childregs;
p->thread.ksp = (unsigned long) childregs - STACK_FRAME_OVERHEAD;
p->thread.ksp -= sizeof(struct pt_regs ) + STACK_FRAME_OVERHEAD;
kregs = (struct pt_regs *)(p->thread.ksp + STACK_FRAME_OVERHEAD);
/* The PPC64 compiler makes use of a TOC to contain function
sp -= STACK_FRAME_OVERHEAD;
/*
* The way this works is that at some point in the future
* some task will call _switch to switch to the new task.
* That will pop off the stack frame created below and start
* the new task running at ret_from_fork. The new task will
* do some house keeping and then return from the fork or clone
* system call, using the stack frame created above.
*/
sp -= sizeof(struct pt_regs);
kregs = (struct pt_regs *) sp;
sp -= STACK_FRAME_OVERHEAD;
p->thread.ksp = sp;
/*
* The PPC64 ABI makes use of a TOC to contain function
* pointers. The function (ret_from_except) is actually a pointer
* to the TOC entry. The first entry is a pointer to the actual
* function.
*/
kregs->nip = *((unsigned long *)ret_from_fork);
asm volatile("mfmsr %0" : "=r" (msr):);
kregs->msr = msr;
kregs->gpr[1] = (unsigned long)childregs - STACK_FRAME_OVERHEAD;
kregs->gpr[2] = (((unsigned long)&__toc_start) + 0x8000);
if (usp >= (unsigned long) regs) {
/* Stack is in kernel space - must adjust */
childregs->gpr[1] = (unsigned long)(childregs + 1);
*((unsigned long *) childregs->gpr[1]) = 0;
childregs->gpr[13] = (unsigned long) p;
} else {
/* Provided stack is in user space */
childregs->gpr[1] = usp;
}
p->thread.last_syscall = -1;
/*
* copy fpu info - assume lazy fpu switch now always
......@@ -223,6 +226,8 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
memcpy(&p->thread.fpr, &current->thread.fpr, sizeof(p->thread.fpr));
p->thread.fpscr = current->thread.fpscr;
p->thread.last_syscall = -1;
return 0;
}
......@@ -239,7 +244,6 @@ void start_thread(struct pt_regs *regs, unsigned long nip, unsigned long sp)
unsigned long *entry = (unsigned long *)nip;
unsigned long *toc = entry + 1;
set_fs(USER_DS);
memset(regs->gpr, 0, sizeof(regs->gpr));
memset(&regs->ctr, 0, 4 * sizeof(regs->ctr));
......@@ -252,53 +256,27 @@ void start_thread(struct pt_regs *regs, unsigned long nip, unsigned long sp)
current->thread.fpscr = 0;
}
asmlinkage int sys_clone(int p1, int p2, int p3, int p4, int p5, int p6,
struct pt_regs *regs)
int sys_clone(int p1, int p2, int p3, int p4, int p5, int p6,
struct pt_regs *regs)
{
unsigned long clone_flags = p1;
int res;
res = do_fork(clone_flags, regs->gpr[1], regs, 0);
#ifdef CONFIG_SMP
/* When we clone the idle task we keep the same pid but
* the return value of 0 for both causes problems.
* -- Cort
*/
if ((current->pid == 0) && (current == &init_task))
res = 1;
#endif /* CONFIG_SMP */
return res;
return do_fork(p1, regs->gpr[1], regs, 0);
}
asmlinkage int sys_fork(int p1, int p2, int p3, int p4, int p5, int p6,
struct pt_regs *regs)
int sys_fork(int p1, int p2, int p3, int p4, int p5, int p6,
struct pt_regs *regs)
{
int res;
res = do_fork(SIGCHLD, regs->gpr[1], regs, 0);
#ifdef CONFIG_SMP
/* When we clone the idle task we keep the same pid but
* the return value of 0 for both causes problems.
* -- Cort
*/
if ((current->pid == 0) && (current == &init_task))
res = 1;
#endif /* CONFIG_SMP */
return res;
return do_fork(SIGCHLD, regs->gpr[1], regs, 0);
}
asmlinkage int sys_vfork(int p1, int p2, int p3, int p4, int p5, int p6,
int sys_vfork(int p1, int p2, int p3, int p4, int p5, int p6,
struct pt_regs *regs)
{
return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->gpr[1], regs, 0);
}
asmlinkage int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
unsigned long a3, unsigned long a4, unsigned long a5,
struct pt_regs *regs)
int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
unsigned long a3, unsigned long a4, unsigned long a5,
struct pt_regs *regs)
{
int error;
char * filename;
......
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