Commit 4e416e98 authored by Paul Mackerras's avatar Paul Mackerras

PPC32: This changeset adds preemptible kernel support for ppc32

and also streamlines the exception entry/exit code by not saving
all the GPRs on the common exceptions (system call, external
interrupt and decrementer).
parent bb3ffc11
...@@ -165,7 +165,9 @@ bool 'Symmetric multi-processing support' CONFIG_SMP ...@@ -165,7 +165,9 @@ bool 'Symmetric multi-processing support' CONFIG_SMP
if [ "$CONFIG_SMP" = "y" ]; then if [ "$CONFIG_SMP" = "y" ]; then
bool ' Distribute interrupts on all CPUs by default' CONFIG_IRQ_ALL_CPUS bool ' Distribute interrupts on all CPUs by default' CONFIG_IRQ_ALL_CPUS
fi fi
define_bool CONFIG_PREEMPT n if [ "$CONFIG_SMP" != "y" ]; then
bool 'Preemptible Kernel' CONFIG_PREEMPT
fi
if [ "$CONFIG_6xx" = "y" -a "$CONFIG_8260" = "n" ];then if [ "$CONFIG_6xx" = "y" -a "$CONFIG_8260" = "n" ];then
bool 'AltiVec Support' CONFIG_ALTIVEC bool 'AltiVec Support' CONFIG_ALTIVEC
......
...@@ -200,6 +200,8 @@ fix_alignment(struct pt_regs *regs) ...@@ -200,6 +200,8 @@ fix_alignment(struct pt_regs *regs)
unsigned char v[8]; unsigned char v[8];
} data; } data;
CHECK_FULL_REGS(regs);
#if defined(CONFIG_4xx) #if defined(CONFIG_4xx)
/* The 4xx-family processors have no DSISR register, /* The 4xx-family processors have no DSISR register,
* so we emulate it. * so we emulate it.
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -1017,20 +1017,28 @@ _GLOBAL(cvt_df) ...@@ -1017,20 +1017,28 @@ _GLOBAL(cvt_df)
* kernel_thread(fn, arg, flags) * kernel_thread(fn, arg, flags)
*/ */
_GLOBAL(kernel_thread) _GLOBAL(kernel_thread)
mr r6,r3 /* function */ stwu r1,-16(r1)
stw r30,8(r1)
stw r31,12(r1)
mr r30,r3 /* function */
mr r31,r4 /* argument */
ori r3,r5,CLONE_VM /* flags */ ori r3,r5,CLONE_VM /* flags */
li r0,__NR_clone li r0,__NR_clone
sc sc
cmpi 0,r3,0 /* parent or child? */ cmpi 0,r3,0 /* parent or child? */
bnelr /* return if parent */ bne 1f /* return if parent */
li r0,0 /* make top-level stack frame */ li r0,0 /* make top-level stack frame */
stwu r0,-16(r1) stwu r0,-16(r1)
mtlr r6 /* fn addr in lr */ mtlr r30 /* fn addr in lr */
mr r3,r4 /* load arg and call fn */ mr r3,r31 /* load arg and call fn */
blrl blrl
li r0,__NR_exit /* exit after child exits */ li r0,__NR_exit /* exit if function returns */
li r3,0 li r3,0
sc sc
1: lwz r30,8(r1)
lwz r31,12(r1)
addi r1,r1,16
blr
/* /*
* This routine is just here to keep GCC happy - sigh... * This routine is just here to keep GCC happy - sigh...
...@@ -1050,19 +1058,15 @@ _GLOBAL(name) \ ...@@ -1050,19 +1058,15 @@ _GLOBAL(name) \
#define __NR__exit __NR_exit #define __NR__exit __NR_exit
SYSCALL(sync)
SYSCALL(setsid) SYSCALL(setsid)
SYSCALL(open)
SYSCALL(read)
SYSCALL(write) SYSCALL(write)
SYSCALL(lseek)
SYSCALL(close)
SYSCALL(dup) SYSCALL(dup)
SYSCALL(execve) SYSCALL(execve)
SYSCALL(open)
SYSCALL(close)
SYSCALL(waitpid) SYSCALL(waitpid)
SYSCALL(fork)
SYSCALL(delete_module)
SYSCALL(_exit)
SYSCALL(lseek)
SYSCALL(read)
/* Why isn't this a) automatic, b) written in 'C'? */ /* Why isn't this a) automatic, b) written in 'C'? */
.data .data
...@@ -1070,7 +1074,7 @@ SYSCALL(read) ...@@ -1070,7 +1074,7 @@ SYSCALL(read)
_GLOBAL(sys_call_table) _GLOBAL(sys_call_table)
.long sys_ni_syscall /* 0 - old "setup()" system call */ .long sys_ni_syscall /* 0 - old "setup()" system call */
.long sys_exit .long sys_exit
.long sys_fork .long ppc_fork
.long sys_read .long sys_read
.long sys_write .long sys_write
.long sys_open /* 5 */ .long sys_open /* 5 */
...@@ -1140,7 +1144,7 @@ _GLOBAL(sys_call_table) ...@@ -1140,7 +1144,7 @@ _GLOBAL(sys_call_table)
.long sys_ssetmask .long sys_ssetmask
.long sys_setreuid /* 70 */ .long sys_setreuid /* 70 */
.long sys_setregid .long sys_setregid
.long sys_sigsuspend .long ppc_sigsuspend
.long sys_sigpending .long sys_sigpending
.long sys_sethostname .long sys_sethostname
.long sys_setrlimit /* 75 */ .long sys_setrlimit /* 75 */
...@@ -1188,7 +1192,7 @@ _GLOBAL(sys_call_table) ...@@ -1188,7 +1192,7 @@ _GLOBAL(sys_call_table)
.long sys_ipc .long sys_ipc
.long sys_fsync .long sys_fsync
.long sys_sigreturn .long sys_sigreturn
.long sys_clone /* 120 */ .long ppc_clone /* 120 */
.long sys_setdomainname .long sys_setdomainname
.long sys_newuname .long sys_newuname
.long sys_modify_ldt .long sys_modify_ldt
...@@ -1246,7 +1250,7 @@ _GLOBAL(sys_call_table) ...@@ -1246,7 +1250,7 @@ _GLOBAL(sys_call_table)
.long sys_rt_sigpending /* 175 */ .long sys_rt_sigpending /* 175 */
.long sys_rt_sigtimedwait .long sys_rt_sigtimedwait
.long sys_rt_sigqueueinfo .long sys_rt_sigqueueinfo
.long sys_rt_sigsuspend .long ppc_rt_sigsuspend
.long sys_pread .long sys_pread
.long sys_pwrite /* 180 */ .long sys_pwrite /* 180 */
.long sys_chown .long sys_chown
...@@ -1257,7 +1261,7 @@ _GLOBAL(sys_call_table) ...@@ -1257,7 +1261,7 @@ _GLOBAL(sys_call_table)
.long sys_sendfile .long sys_sendfile
.long sys_ni_syscall /* streams1 */ .long sys_ni_syscall /* streams1 */
.long sys_ni_syscall /* streams2 */ .long sys_ni_syscall /* streams2 */
.long sys_vfork .long ppc_vfork
.long sys_getrlimit /* 190 */ .long sys_getrlimit /* 190 */
.long sys_readahead .long sys_readahead
.long sys_mmap2 .long sys_mmap2
......
...@@ -107,10 +107,13 @@ main(void) ...@@ -107,10 +107,13 @@ main(void)
DEFINE(_DSISR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, dsisr)); DEFINE(_DSISR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, dsisr));
/* The PowerPC 400-class processors have neither the DAR nor the DSISR /* The PowerPC 400-class processors have neither the DAR nor the DSISR
* SPRs. Hence, we overload them to hold the similar DEAR and ESR SPRs * SPRs. Hence, we overload them to hold the similar DEAR and ESR SPRs
* for such processors. * for such processors. For critical interrupts we use them to
* hold SRR0 and SRR1.
*/ */
DEFINE(_DEAR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, dar)); DEFINE(_DEAR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, dar));
DEFINE(_ESR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, dsisr)); DEFINE(_ESR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, dsisr));
DEFINE(_SRR0, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, dar));
DEFINE(_SRR1, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, dsisr));
DEFINE(ORIG_GPR3, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, orig_gpr3)); DEFINE(ORIG_GPR3, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, orig_gpr3));
DEFINE(RESULT, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, result)); DEFINE(RESULT, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, result));
DEFINE(TRAP, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, trap)); DEFINE(TRAP, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, trap));
......
...@@ -75,7 +75,6 @@ int abs(int); ...@@ -75,7 +75,6 @@ int abs(int);
extern unsigned char __res[]; extern unsigned char __res[];
extern unsigned long ret_to_user_hook;
extern unsigned long mm_ptov (unsigned long paddr); extern unsigned long mm_ptov (unsigned long paddr);
extern void *consistent_alloc(int gfp, size_t size, dma_addr_t *dma_handle); extern void *consistent_alloc(int gfp, size_t size, dma_addr_t *dma_handle);
...@@ -313,9 +312,7 @@ EXPORT_SYMBOL(__save_flags_ptr_end); ...@@ -313,9 +312,7 @@ EXPORT_SYMBOL(__save_flags_ptr_end);
EXPORT_SYMBOL(__restore_flags); EXPORT_SYMBOL(__restore_flags);
EXPORT_SYMBOL(__restore_flags_end); EXPORT_SYMBOL(__restore_flags_end);
#endif #endif
EXPORT_SYMBOL(timer_interrupt_intercept);
EXPORT_SYMBOL(timer_interrupt); EXPORT_SYMBOL(timer_interrupt);
EXPORT_SYMBOL(do_IRQ_intercept);
EXPORT_SYMBOL(irq_desc); EXPORT_SYMBOL(irq_desc);
void ppc_irq_dispatch_handler(struct pt_regs *, int); void ppc_irq_dispatch_handler(struct pt_regs *, int);
EXPORT_SYMBOL(ppc_irq_dispatch_handler); EXPORT_SYMBOL(ppc_irq_dispatch_handler);
...@@ -356,7 +353,6 @@ EXPORT_SYMBOL(cpm_free_handler); ...@@ -356,7 +353,6 @@ EXPORT_SYMBOL(cpm_free_handler);
EXPORT_SYMBOL(request_8xxirq); EXPORT_SYMBOL(request_8xxirq);
#endif #endif
EXPORT_SYMBOL(ret_to_user_hook);
EXPORT_SYMBOL(next_mmu_context); EXPORT_SYMBOL(next_mmu_context);
EXPORT_SYMBOL(set_context); EXPORT_SYMBOL(set_context);
EXPORT_SYMBOL(handle_mm_fault); /* For MOL */ EXPORT_SYMBOL(handle_mm_fault); /* For MOL */
...@@ -366,8 +362,6 @@ EXPORT_SYMBOL(flush_hash_pages); /* For MOL */ ...@@ -366,8 +362,6 @@ EXPORT_SYMBOL(flush_hash_pages); /* For MOL */
extern long *intercept_table; extern long *intercept_table;
EXPORT_SYMBOL(intercept_table); EXPORT_SYMBOL(intercept_table);
#endif #endif
extern long *ret_from_intercept;
EXPORT_SYMBOL(ret_from_intercept);
EXPORT_SYMBOL(cur_cpu_spec); EXPORT_SYMBOL(cur_cpu_spec);
#if defined(CONFIG_ALL_PPC) #if defined(CONFIG_ALL_PPC)
extern unsigned long agp_special_page; extern unsigned long agp_special_page;
......
...@@ -251,16 +251,18 @@ void switch_to(struct task_struct *prev, struct task_struct *new) ...@@ -251,16 +251,18 @@ void switch_to(struct task_struct *prev, struct task_struct *new)
void show_regs(struct pt_regs * regs) void show_regs(struct pt_regs * regs)
{ {
int i; int i, trap;
printk("NIP: %08lX XER: %08lX LR: %08lX SP: %08lX REGS: %p TRAP: %04lx %s\n", printk("NIP: %08lX LR: %08lX SP: %08lX REGS: %p TRAP: %04lx %s\n",
regs->nip, regs->xer, regs->link, regs->gpr[1], regs,regs->trap, print_tainted()); regs->nip, regs->link, regs->gpr[1], regs, regs->trap,
print_tainted());
printk("MSR: %08lx EE: %01x PR: %01x FP: %01x ME: %01x IR/DR: %01x%01x\n", printk("MSR: %08lx EE: %01x PR: %01x FP: %01x ME: %01x IR/DR: %01x%01x\n",
regs->msr, regs->msr&MSR_EE ? 1 : 0, regs->msr&MSR_PR ? 1 : 0, regs->msr, regs->msr&MSR_EE ? 1 : 0, regs->msr&MSR_PR ? 1 : 0,
regs->msr & MSR_FP ? 1 : 0,regs->msr&MSR_ME ? 1 : 0, regs->msr & MSR_FP ? 1 : 0,regs->msr&MSR_ME ? 1 : 0,
regs->msr&MSR_IR ? 1 : 0, regs->msr&MSR_IR ? 1 : 0,
regs->msr&MSR_DR ? 1 : 0); regs->msr&MSR_DR ? 1 : 0);
if (regs->trap == 0x300 || regs->trap == 0x600) trap = TRAP(regs);
if (trap == 0x300 || trap == 0x600)
printk("DAR: %08lX, DSISR: %08lX\n", regs->dar, regs->dsisr); printk("DAR: %08lX, DSISR: %08lX\n", regs->dar, regs->dsisr);
printk("TASK = %p[%d] '%s' ", printk("TASK = %p[%d] '%s' ",
current, current->pid, current->comm); current, current->pid, current->comm);
...@@ -280,25 +282,18 @@ void show_regs(struct pt_regs * regs) ...@@ -280,25 +282,18 @@ void show_regs(struct pt_regs * regs)
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
printk(" CPU: %d", smp_processor_id()); printk(" CPU: %d", smp_processor_id());
#endif /* CONFIG_SMP */ #endif /* CONFIG_SMP */
printk("\n"); for (i = 0; i < 32; i++) {
for (i = 0; i < 32; i++)
{
long r; long r;
if ((i % 8) == 0) if ((i % 8) == 0)
{ printk("\n" KERN_INFO "GPR%02d: ", i);
printk("GPR%02d: ", i); if (__get_user(r, &regs->gpr[i]))
} break;
if ( __get_user(r, &(regs->gpr[i])) )
goto out;
printk("%08lX ", r); printk("%08lX ", r);
if ((i % 8) == 7) if (i == 12 && !FULL_REGS(regs))
{ break;
printk("\n");
}
} }
out: printk("\n");
print_backtrace((unsigned long *)regs->gpr[1]); print_backtrace((unsigned long *)regs->gpr[1]);
} }
...@@ -336,6 +331,7 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp, ...@@ -336,6 +331,7 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
unsigned long sp = (unsigned long)p->thread_info + THREAD_SIZE; unsigned long sp = (unsigned long)p->thread_info + THREAD_SIZE;
unsigned long childframe; unsigned long childframe;
CHECK_FULL_REGS(regs);
/* Copy registers */ /* Copy registers */
sp -= sizeof(struct pt_regs); sp -= sizeof(struct pt_regs);
childregs = (struct pt_regs *) sp; childregs = (struct pt_regs *) sp;
...@@ -441,18 +437,21 @@ int set_fpexc_mode(struct task_struct *tsk, unsigned int val) ...@@ -441,18 +437,21 @@ int set_fpexc_mode(struct task_struct *tsk, unsigned int val)
int sys_clone(int p1, int p2, int p3, int p4, int p5, int p6, int sys_clone(int p1, int p2, int p3, int p4, int p5, int p6,
struct pt_regs *regs) struct pt_regs *regs)
{ {
CHECK_FULL_REGS(regs);
return do_fork(p1, regs->gpr[1], regs, 0); return do_fork(p1, regs->gpr[1], regs, 0);
} }
int sys_fork(int p1, int p2, int p3, int p4, int p5, int p6, int sys_fork(int p1, int p2, int p3, int p4, int p5, int p6,
struct pt_regs *regs) struct pt_regs *regs)
{ {
CHECK_FULL_REGS(regs);
return do_fork(SIGCHLD, regs->gpr[1], regs, 0); return do_fork(SIGCHLD, regs->gpr[1], regs, 0);
} }
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) struct pt_regs *regs)
{ {
CHECK_FULL_REGS(regs);
return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->gpr[1], regs, 0); return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->gpr[1], regs, 0);
} }
......
...@@ -218,14 +218,15 @@ int sys_ptrace(long request, long pid, long addr, long data) ...@@ -218,14 +218,15 @@ int sys_ptrace(long request, long pid, long addr, long data)
ret = -EIO; ret = -EIO;
/* convert to index and check */ /* convert to index and check */
index = (unsigned long) addr >> 2; index = (unsigned long) addr >> 2;
if ((addr & 3) || index > PT_FPSCR) if ((addr & 3) || index > PT_FPSCR
|| child->thread.regs == NULL)
break; break;
CHECK_FULL_REGS(child->thread.regs);
if (index < PT_FPR0) { if (index < PT_FPR0) {
tmp = get_reg(child, (int) index); tmp = get_reg(child, (int) index);
} else { } else {
if (child->thread.regs != NULL if (child->thread.regs->msr & MSR_FP)
&& child->thread.regs->msr & MSR_FP)
giveup_fpu(child); giveup_fpu(child);
tmp = ((unsigned long *)child->thread.fpr)[index - PT_FPR0]; tmp = ((unsigned long *)child->thread.fpr)[index - PT_FPR0];
} }
...@@ -243,23 +244,23 @@ int sys_ptrace(long request, long pid, long addr, long data) ...@@ -243,23 +244,23 @@ int sys_ptrace(long request, long pid, long addr, long data)
break; break;
/* write the word at location addr in the USER area */ /* write the word at location addr in the USER area */
/* XXX this will need fixing for 64-bit */
case PTRACE_POKEUSR: { case PTRACE_POKEUSR: {
unsigned long index; unsigned long index;
ret = -EIO; ret = -EIO;
/* convert to index and check */ /* convert to index and check */
index = (unsigned long) addr >> 2; index = (unsigned long) addr >> 2;
if ((addr & 3) || index > PT_FPSCR) if ((addr & 3) || index > PT_FPSCR
|| child->thread.regs == NULL)
break; break;
CHECK_FULL_REGS(child->thread.regs);
if (index == PT_ORIG_R3) if (index == PT_ORIG_R3)
break; break;
if (index < PT_FPR0) { if (index < PT_FPR0) {
ret = put_reg(child, index, data); ret = put_reg(child, index, data);
} else { } else {
if (child->thread.regs != NULL if (child->thread.regs->msr & MSR_FP)
&& child->thread.regs->msr & MSR_FP)
giveup_fpu(child); giveup_fpu(child);
((unsigned long *)child->thread.fpr)[index - PT_FPR0] = data; ((unsigned long *)child->thread.fpr)[index - PT_FPR0] = data;
ret = 0; ret = 0;
......
...@@ -44,6 +44,8 @@ ...@@ -44,6 +44,8 @@
#define MIN(a,b) (((a) < (b)) ? (a) : (b)) #define MIN(a,b) (((a) < (b)) ? (a) : (b))
#endif #endif
extern void sigreturn_exit(struct pt_regs *);
#define GP_REGS_SIZE MIN(sizeof(elf_gregset_t), sizeof(struct pt_regs)) #define GP_REGS_SIZE MIN(sizeof(elf_gregset_t), sizeof(struct pt_regs))
/* /*
...@@ -111,20 +113,14 @@ sys_sigsuspend(old_sigset_t mask, int p2, int p3, int p4, int p6, int p7, ...@@ -111,20 +113,14 @@ sys_sigsuspend(old_sigset_t mask, int p2, int p3, int p4, int p6, int p7,
recalc_sigpending(); recalc_sigpending();
spin_unlock_irq(&current->sigmask_lock); spin_unlock_irq(&current->sigmask_lock);
regs->gpr[3] = -EINTR; regs->result = -EINTR;
regs->ccr |= 0x10000000;
regs->gpr[3] = EINTR;
while (1) { while (1) {
current->state = TASK_INTERRUPTIBLE; current->state = TASK_INTERRUPTIBLE;
schedule(); schedule();
if (do_signal(&saveset, regs)) if (do_signal(&saveset, regs))
/* sigreturn_exit(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];
} }
} }
...@@ -148,20 +144,22 @@ sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize, int p3, int p4, int p6, ...@@ -148,20 +144,22 @@ sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize, int p3, int p4, int p6,
recalc_sigpending(); recalc_sigpending();
spin_unlock_irq(&current->sigmask_lock); spin_unlock_irq(&current->sigmask_lock);
regs->gpr[3] = -EINTR; regs->result = -EINTR;
regs->ccr |= 0x10000000;
regs->gpr[3] = EINTR;
while (1) { while (1) {
current->state = TASK_INTERRUPTIBLE; current->state = TASK_INTERRUPTIBLE;
schedule(); schedule();
if (do_signal(&saveset, regs)) if (do_signal(&saveset, regs))
return regs->gpr[3]; sigreturn_exit(regs);
} }
} }
int int
sys_sigaltstack(const stack_t *uss, stack_t *uoss) sys_sigaltstack(const stack_t *uss, stack_t *uoss, int r5, int r6,
int r7, int r8, struct pt_regs *regs)
{ {
struct pt_regs *regs = (struct pt_regs *) &uss;
return do_sigaltstack(uss, uoss, regs->gpr[1]); return do_sigaltstack(uss, uoss, regs->gpr[1]);
} }
...@@ -236,16 +234,15 @@ struct rt_sigframe ...@@ -236,16 +234,15 @@ struct rt_sigframe
* Each of these things must be a multiple of 16 bytes in size. * Each of these things must be a multiple of 16 bytes in size.
* *
*/ */
int sys_rt_sigreturn(struct pt_regs *regs) int sys_rt_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8,
struct pt_regs *regs)
{ {
struct rt_sigframe *rt_sf; struct rt_sigframe *rt_sf;
struct sigcontext_struct sigctx; struct sigcontext_struct sigctx;
struct sigregs *sr; struct sigregs *sr;
int ret;
elf_gregset_t saved_regs; /* an array of ELF_NGREG unsigned longs */ elf_gregset_t saved_regs; /* an array of ELF_NGREG unsigned longs */
sigset_t set; sigset_t set;
stack_t st; stack_t st;
unsigned long prevsp;
rt_sf = (struct rt_sigframe *)(regs->gpr[1] + __SIGNAL_FRAMESIZE); rt_sf = (struct rt_sigframe *)(regs->gpr[1] + __SIGNAL_FRAMESIZE);
if (copy_from_user(&sigctx, &rt_sf->uc.uc_mcontext, sizeof(sigctx)) if (copy_from_user(&sigctx, &rt_sf->uc.uc_mcontext, sizeof(sigctx))
...@@ -260,50 +257,26 @@ int sys_rt_sigreturn(struct pt_regs *regs) ...@@ -260,50 +257,26 @@ int sys_rt_sigreturn(struct pt_regs *regs)
if (regs->msr & MSR_FP) if (regs->msr & MSR_FP)
giveup_fpu(current); giveup_fpu(current);
rt_sf++; /* Look at next rt_sigframe */ /* restore registers -
if (rt_sf == (struct rt_sigframe *)(sigctx.regs)) { * sigctx is initialized to point to the
/* Last stacked signal - restore registers - * preamble frame (where registers are stored)
* sigctx is initialized to point to the * see handle_signal()
* 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)))
sr = (struct sigregs *) sigctx.regs; goto badframe;
if (copy_from_user(saved_regs, &sr->gp_regs, saved_regs[PT_MSR] = (regs->msr & ~MSR_USERCHANGE)
sizeof(sr->gp_regs))) | (saved_regs[PT_MSR] & MSR_USERCHANGE);
goto badframe; memcpy(regs, saved_regs, GP_REGS_SIZE);
saved_regs[PT_MSR] = (regs->msr & ~MSR_USERCHANGE) if (copy_from_user(current->thread.fpr, &sr->fp_regs,
| (saved_regs[PT_MSR] & MSR_USERCHANGE); sizeof(sr->fp_regs)))
memcpy(regs, saved_regs, GP_REGS_SIZE); goto badframe;
if (copy_from_user(current->thread.fpr, &sr->fp_regs, /* This function sets back the stack flags into
sizeof(sr->fp_regs))) the current task structure. */
goto badframe; sys_sigaltstack(&st, NULL, 0, 0, 0, 0, regs);
/* This function sets back the stack flags into
the current task structure. */
sys_sigaltstack(&st, NULL);
ret = regs->result; sigreturn_exit(regs); /* doesn't return here */
} else { return 0;
/* More signals to go */
/* Set up registers for next signal handler */
regs->gpr[1] = (unsigned long)rt_sf - __SIGNAL_FRAMESIZE;
if (copy_from_user(&sigctx, &rt_sf->uc.uc_mcontext, sizeof(sigctx)))
goto badframe;
sr = (struct sigregs *) sigctx.regs;
regs->gpr[3] = ret = sigctx.signal;
/* Get the siginfo */
get_user(regs->gpr[4], (unsigned long *)&rt_sf->pinfo);
/* Get the ucontext */
get_user(regs->gpr[5], (unsigned long *)&rt_sf->puc);
regs->gpr[6] = (unsigned long) rt_sf;
regs->link = (unsigned long) &sr->tramp;
regs->nip = sigctx.handler;
if (get_user(prevsp, &sr->gp_regs[PT_R1])
|| put_user(prevsp, (unsigned long *) regs->gpr[1]))
goto badframe;
current->thread.fpscr = 0;
}
return ret;
badframe: badframe:
do_exit(SIGSEGV); do_exit(SIGSEGV);
...@@ -318,6 +291,7 @@ setup_rt_frame(struct pt_regs *regs, struct sigregs *frame, ...@@ -318,6 +291,7 @@ setup_rt_frame(struct pt_regs *regs, struct sigregs *frame,
/* Set up preamble frame */ /* Set up preamble frame */
if (verify_area(VERIFY_WRITE, frame, sizeof(*frame))) if (verify_area(VERIFY_WRITE, frame, sizeof(*frame)))
goto badframe; goto badframe;
CHECK_FULL_REGS(regs);
if (regs->msr & MSR_FP) if (regs->msr & MSR_FP)
giveup_fpu(current); giveup_fpu(current);
if (__copy_to_user(&frame->gp_regs, regs, GP_REGS_SIZE) if (__copy_to_user(&frame->gp_regs, regs, GP_REGS_SIZE)
...@@ -327,7 +301,7 @@ setup_rt_frame(struct pt_regs *regs, struct sigregs *frame, ...@@ -327,7 +301,7 @@ setup_rt_frame(struct pt_regs *regs, struct sigregs *frame,
It calls the sc exception at offset 0x9999 It calls the sc exception at offset 0x9999
for sys_rt_sigreturn(). for sys_rt_sigreturn().
*/ */
|| __put_user(0x38006666UL, &frame->tramp[0]) /* li r0,0x6666 */ || __put_user(0x38000000UL + __NR_rt_sigreturn, &frame->tramp[0])
|| __put_user(0x44000002UL, &frame->tramp[1])) /* sc */ || __put_user(0x44000002UL, &frame->tramp[1])) /* sc */
goto badframe; goto badframe;
flush_icache_range((unsigned long) &frame->tramp[0], flush_icache_range((unsigned long) &frame->tramp[0],
...@@ -362,14 +336,13 @@ setup_rt_frame(struct pt_regs *regs, struct sigregs *frame, ...@@ -362,14 +336,13 @@ setup_rt_frame(struct pt_regs *regs, struct sigregs *frame,
/* /*
* Do a signal return; undo the signal stack. * Do a signal return; undo the signal stack.
*/ */
int sys_sigreturn(struct pt_regs *regs) int sys_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8,
struct pt_regs *regs)
{ {
struct sigcontext_struct *sc, sigctx; struct sigcontext_struct *sc, sigctx;
struct sigregs *sr; struct sigregs *sr;
int ret;
elf_gregset_t saved_regs; /* an array of ELF_NGREG unsigned longs */ elf_gregset_t saved_regs; /* an array of ELF_NGREG unsigned longs */
sigset_t set; sigset_t set;
unsigned long prevsp;
sc = (struct sigcontext_struct *)(regs->gpr[1] + __SIGNAL_FRAMESIZE); sc = (struct sigcontext_struct *)(regs->gpr[1] + __SIGNAL_FRAMESIZE);
if (copy_from_user(&sigctx, sc, sizeof(sigctx))) if (copy_from_user(&sigctx, sc, sizeof(sigctx)))
...@@ -387,40 +360,20 @@ int sys_sigreturn(struct pt_regs *regs) ...@@ -387,40 +360,20 @@ int sys_sigreturn(struct pt_regs *regs)
if (regs->msr & MSR_FP ) if (regs->msr & MSR_FP )
giveup_fpu(current); giveup_fpu(current);
sc++; /* Look at next sigcontext */ /* restore registers */
if (sc == (struct sigcontext_struct *)(sigctx.regs)) { sr = (struct sigregs *) sigctx.regs;
/* Last stacked signal - restore registers */ if (copy_from_user(saved_regs, &sr->gp_regs, sizeof(sr->gp_regs)))
sr = (struct sigregs *) sigctx.regs; goto badframe;
if (copy_from_user(saved_regs, &sr->gp_regs, saved_regs[PT_MSR] = (regs->msr & ~MSR_USERCHANGE)
sizeof(sr->gp_regs))) | (saved_regs[PT_MSR] & MSR_USERCHANGE);
goto badframe; memcpy(regs, saved_regs, GP_REGS_SIZE);
saved_regs[PT_MSR] = (regs->msr & ~MSR_USERCHANGE)
| (saved_regs[PT_MSR] & MSR_USERCHANGE);
memcpy(regs, saved_regs, GP_REGS_SIZE);
if (copy_from_user(current->thread.fpr, &sr->fp_regs, if (copy_from_user(current->thread.fpr, &sr->fp_regs,
sizeof(sr->fp_regs))) sizeof(sr->fp_regs)))
goto badframe; goto badframe;
ret = regs->result; sigreturn_exit(regs); /* doesn't return here */
return 0;
} else {
/* More signals to go */
regs->gpr[1] = (unsigned long)sc - __SIGNAL_FRAMESIZE;
if (copy_from_user(&sigctx, sc, sizeof(sigctx)))
goto badframe;
sr = (struct sigregs *) sigctx.regs;
regs->gpr[3] = ret = sigctx.signal;
regs->gpr[4] = (unsigned long) sc;
regs->link = (unsigned long) &sr->tramp;
regs->nip = sigctx.handler;
if (get_user(prevsp, &sr->gp_regs[PT_R1])
|| put_user(prevsp, (unsigned long *) regs->gpr[1]))
goto badframe;
current->thread.fpscr = 0;
}
return ret;
badframe: badframe:
do_exit(SIGSEGV); do_exit(SIGSEGV);
...@@ -437,12 +390,13 @@ setup_frame(struct pt_regs *regs, struct sigregs *frame, ...@@ -437,12 +390,13 @@ setup_frame(struct pt_regs *regs, struct sigregs *frame,
if (verify_area(VERIFY_WRITE, frame, sizeof(*frame))) if (verify_area(VERIFY_WRITE, frame, sizeof(*frame)))
goto badframe; goto badframe;
CHECK_FULL_REGS(regs);
if (regs->msr & MSR_FP) if (regs->msr & MSR_FP)
giveup_fpu(current); giveup_fpu(current);
if (__copy_to_user(&frame->gp_regs, regs, GP_REGS_SIZE) if (__copy_to_user(&frame->gp_regs, regs, GP_REGS_SIZE)
|| __copy_to_user(&frame->fp_regs, current->thread.fpr, || __copy_to_user(&frame->fp_regs, current->thread.fpr,
ELF_NFPREG * sizeof(double)) ELF_NFPREG * sizeof(double))
|| __put_user(0x38007777UL, &frame->tramp[0]) /* li r0,0x7777 */ || __put_user(0x38000000UL + __NR_sigreturn, &frame->tramp[0])
|| __put_user(0x44000002UL, &frame->tramp[1])) /* sc */ || __put_user(0x44000002UL, &frame->tramp[1])) /* sc */
goto badframe; goto badframe;
flush_icache_range((unsigned long) &frame->tramp[0], flush_icache_range((unsigned long) &frame->tramp[0],
...@@ -479,11 +433,14 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, ...@@ -479,11 +433,14 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
struct sigcontext_struct *sc; struct sigcontext_struct *sc;
struct rt_sigframe *rt_sf; struct rt_sigframe *rt_sf;
if (regs->trap == 0x0C00 /* System Call! */ if (TRAP(regs) == 0x0C00 /* System Call! */
&& ((int)regs->result == -ERESTARTNOHAND || && ((int)regs->result == -ERESTARTNOHAND ||
((int)regs->result == -ERESTARTSYS && ((int)regs->result == -ERESTARTSYS &&
!(ka->sa.sa_flags & SA_RESTART)))) !(ka->sa.sa_flags & SA_RESTART)))) {
regs->result = -EINTR; regs->result = -EINTR;
regs->gpr[3] = EINTR;
regs->ccr |= 0x10000000;
}
/* Set up Signal Frame */ /* Set up Signal Frame */
if (ka->sa.sa_flags & SA_SIGINFO) { if (ka->sa.sa_flags & SA_SIGINFO) {
...@@ -511,7 +468,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, ...@@ -511,7 +468,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
|| __put_user(sig, &rt_sf->uc.uc_mcontext.signal)) || __put_user(sig, &rt_sf->uc.uc_mcontext.signal))
goto badframe; goto badframe;
} else { } else {
/* Put another sigcontext on the stack */ /* Put a sigcontext on the stack */
*newspp -= sizeof(*sc); *newspp -= sizeof(*sc);
sc = (struct sigcontext_struct *) *newspp; sc = (struct sigcontext_struct *) *newspp;
if (verify_area(VERIFY_WRITE, sc, sizeof(*sc))) if (verify_area(VERIFY_WRITE, sc, sizeof(*sc)))
...@@ -665,7 +622,7 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs) ...@@ -665,7 +622,7 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
break; break;
} }
if (regs->trap == 0x0C00 /* System Call! */ && if (TRAP(regs) == 0x0C00 /* System Call! */ &&
((int)regs->result == -ERESTARTNOHAND || ((int)regs->result == -ERESTARTNOHAND ||
(int)regs->result == -ERESTARTSYS || (int)regs->result == -ERESTARTSYS ||
(int)regs->result == -ERESTARTNOINTR)) { (int)regs->result == -ERESTARTNOINTR)) {
......
...@@ -172,6 +172,7 @@ MachineCheckException(struct pt_regs *regs) ...@@ -172,6 +172,7 @@ MachineCheckException(struct pt_regs *regs)
printk(KERN_DEBUG "%s bad port %lx at %p\n", printk(KERN_DEBUG "%s bad port %lx at %p\n",
(*nip & 0x100)? "OUT to": "IN from", (*nip & 0x100)? "OUT to": "IN from",
regs->gpr[rb] - _IO_BASE, nip); regs->gpr[rb] - _IO_BASE, nip);
regs->msr |= MSR_RI;
regs->nip = fixup; regs->nip = fixup;
return; return;
} }
...@@ -223,7 +224,7 @@ SMIException(struct pt_regs *regs) ...@@ -223,7 +224,7 @@ SMIException(struct pt_regs *regs)
void void
UnknownException(struct pt_regs *regs) UnknownException(struct pt_regs *regs)
{ {
printk("Bad trap at PC: %lx, SR: %lx, vector=%lx %s\n", printk("Bad trap at PC: %lx, MSR: %lx, vector=%lx %s\n",
regs->nip, regs->msr, regs->trap, print_tainted()); regs->nip, regs->msr, regs->trap, print_tainted());
_exception(SIGTRAP, regs); _exception(SIGTRAP, regs);
} }
...@@ -266,6 +267,7 @@ emulate_instruction(struct pt_regs *regs) ...@@ -266,6 +267,7 @@ emulate_instruction(struct pt_regs *regs)
if (!user_mode(regs)) if (!user_mode(regs))
return retval; return retval;
CHECK_FULL_REGS(regs);
if (get_user(instword, (uint *)(regs->nip))) if (get_user(instword, (uint *)(regs->nip)))
return -EFAULT; return -EFAULT;
...@@ -366,6 +368,14 @@ StackOverflow(struct pt_regs *regs) ...@@ -366,6 +368,14 @@ StackOverflow(struct pt_regs *regs)
panic("kernel stack overflow"); panic("kernel stack overflow");
} }
void nonrecoverable_exception(struct pt_regs *regs)
{
printk(KERN_ERR "Non-recoverable exception at PC=%lx MSR=%lx\n",
regs->nip, regs->msr);
debugger(regs);
die("nonrecoverable exception", regs, SIGKILL);
}
void void
trace_syscall(struct pt_regs *regs) trace_syscall(struct pt_regs *regs)
{ {
...@@ -382,6 +392,8 @@ SoftwareEmulation(struct pt_regs *regs) ...@@ -382,6 +392,8 @@ SoftwareEmulation(struct pt_regs *regs)
extern int Soft_emulate_8xx(struct pt_regs *); extern int Soft_emulate_8xx(struct pt_regs *);
int errcode; int errcode;
CHECK_FULL_REGS(regs);
if (!user_mode(regs)) { if (!user_mode(regs)) {
debugger(regs); debugger(regs);
die("Kernel Mode Software FPU Emulation", regs, SIGFPE); die("Kernel Mode Software FPU Emulation", regs, SIGFPE);
...@@ -423,7 +435,7 @@ void DebugException(struct pt_regs *regs) ...@@ -423,7 +435,7 @@ void DebugException(struct pt_regs *regs)
} else if (debug_status & DBSR_IC) { /* instruction completion */ } else if (debug_status & DBSR_IC) { /* instruction completion */
mtspr(SPRN_DBSR, DBSR_IC); mtspr(SPRN_DBSR, DBSR_IC);
regs->dbcr0 &= ~DBCR0_IC; mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) & ~DBCR0_IC);
if (!user_mode(regs) && debugger_sstep(regs)) if (!user_mode(regs) && debugger_sstep(regs))
return; return;
...@@ -436,7 +448,7 @@ void DebugException(struct pt_regs *regs) ...@@ -436,7 +448,7 @@ void DebugException(struct pt_regs *regs)
void void
TAUException(struct pt_regs *regs) TAUException(struct pt_regs *regs)
{ {
printk("TAU trap at PC: %lx, SR: %lx, vector=%lx %s\n", printk("TAU trap at PC: %lx, MSR: %lx, vector=%lx %s\n",
regs->nip, regs->msr, regs->trap, print_tainted()); regs->nip, regs->msr, regs->trap, print_tainted());
} }
#endif /* CONFIG_INT_TAU */ #endif /* CONFIG_INT_TAU */
......
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
#include <asm/mmu_context.h> #include <asm/mmu_context.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/tlbflush.h>
#if defined(CONFIG_XMON) || defined(CONFIG_KGDB) #if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
extern void (*debugger)(struct pt_regs *); extern void (*debugger)(struct pt_regs *);
...@@ -81,14 +82,14 @@ void do_page_fault(struct pt_regs *regs, unsigned long address, ...@@ -81,14 +82,14 @@ void do_page_fault(struct pt_regs *regs, unsigned long address,
* bits we are interested in. But there are some bits which * bits we are interested in. But there are some bits which
* indicate errors in DSISR but can validly be set in SRR1. * indicate errors in DSISR but can validly be set in SRR1.
*/ */
if (regs->trap == 0x400) if (TRAP(regs) == 0x400)
error_code &= 0x48200000; error_code &= 0x48200000;
else else
is_write = error_code & 0x02000000; is_write = error_code & 0x02000000;
#endif /* CONFIG_4xx */ #endif /* CONFIG_4xx */
#if defined(CONFIG_XMON) || defined(CONFIG_KGDB) #if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
if (debugger_fault_handler && regs->trap == 0x300) { if (debugger_fault_handler && TRAP(regs) == 0x300) {
debugger_fault_handler(regs); debugger_fault_handler(regs);
return; return;
} }
...@@ -140,7 +141,7 @@ void do_page_fault(struct pt_regs *regs, unsigned long address, ...@@ -140,7 +141,7 @@ void do_page_fault(struct pt_regs *regs, unsigned long address,
goto bad_area; goto bad_area;
#if defined(CONFIG_4xx) #if defined(CONFIG_4xx)
/* an exec - 4xx allows for per-page execute permission */ /* an exec - 4xx allows for per-page execute permission */
} else if (regs->trap == 0x400) { } else if (TRAP(regs) == 0x400) {
pte_t *ptep; pte_t *ptep;
#if 0 #if 0
...@@ -159,8 +160,8 @@ void do_page_fault(struct pt_regs *regs, unsigned long address, ...@@ -159,8 +160,8 @@ void do_page_fault(struct pt_regs *regs, unsigned long address,
struct page *page = pte_page(*ptep); struct page *page = pte_page(*ptep);
if (! test_bit(PG_arch_1, &page->flags)) { if (! test_bit(PG_arch_1, &page->flags)) {
__flush_dcache_icache((unsigned long)kmap(page)); unsigned long phys = page_to_pfn(page) << PAGE_SHIFT;
kunmap(page); __flush_dcache_icache_phys(phys);
set_bit(PG_arch_1, &page->flags); set_bit(PG_arch_1, &page->flags);
} }
pte_update(ptep, 0, _PAGE_HWEXEC); pte_update(ptep, 0, _PAGE_HWEXEC);
......
...@@ -43,13 +43,13 @@ ...@@ -43,13 +43,13 @@
* Load a PTE into the hash table, if possible. * Load a PTE into the hash table, if possible.
* The address is in r4, and r3 contains an access flag: * The address is in r4, and r3 contains an access flag:
* _PAGE_RW (0x400) if a write. * _PAGE_RW (0x400) if a write.
* r23 contains the SRR1 value, from which we use the MSR_PR bit. * r9 contains the SRR1 value, from which we use the MSR_PR bit.
* SPRG3 contains the physical address of the current task's thread. * SPRG3 contains the physical address of the current task's thread.
* *
* Returns to the caller if the access is illegal or there is no * Returns to the caller if the access is illegal or there is no
* mapping for the address. Otherwise it places an appropriate PTE * mapping for the address. Otherwise it places an appropriate PTE
* in the hash table and returns from the exception. * in the hash table and returns from the exception.
* Uses r0, r2 - r7, ctr, lr. * Uses r0, r3 - r8, ctr, lr.
*/ */
.text .text
.globl hash_page .globl hash_page
...@@ -62,34 +62,34 @@ hash_page: ...@@ -62,34 +62,34 @@ hash_page:
#endif #endif
tophys(r7,0) /* gets -KERNELBASE into r7 */ tophys(r7,0) /* gets -KERNELBASE into r7 */
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
addis r2,r7,mmu_hash_lock@h addis r8,r7,mmu_hash_lock@h
ori r2,r2,mmu_hash_lock@l ori r8,r8,mmu_hash_lock@l
lis r0,0x0fff lis r0,0x0fff
b 10f b 10f
11: lwz r6,0(r2) 11: lwz r6,0(r8)
cmpwi 0,r6,0 cmpwi 0,r6,0
bne 11b bne 11b
10: lwarx r6,0,r2 10: lwarx r6,0,r8
cmpwi 0,r6,0 cmpwi 0,r6,0
bne- 11b bne- 11b
stwcx. r0,0,r2 stwcx. r0,0,r8
bne- 10b bne- 10b
isync isync
#endif #endif
/* Get PTE (linux-style) and check access */ /* Get PTE (linux-style) and check access */
lis r0,KERNELBASE@h /* check if kernel address */ lis r0,KERNELBASE@h /* check if kernel address */
cmplw 0,r4,r0 cmplw 0,r4,r0
mfspr r2,SPRG3 /* current task's THREAD (phys) */ mfspr r8,SPRG3 /* current task's THREAD (phys) */
ori r3,r3,_PAGE_USER|_PAGE_PRESENT /* test low addresses as user */ ori r3,r3,_PAGE_USER|_PAGE_PRESENT /* test low addresses as user */
lwz r5,PGDIR(r2) /* virt page-table root */ lwz r5,PGDIR(r8) /* virt page-table root */
blt+ 112f /* assume user more likely */ blt+ 112f /* assume user more likely */
lis r5,swapper_pg_dir@ha /* if kernel address, use */ lis r5,swapper_pg_dir@ha /* if kernel address, use */
addi r5,r5,swapper_pg_dir@l /* kernel page table */ addi r5,r5,swapper_pg_dir@l /* kernel page table */
rlwimi r3,r23,32-12,29,29 /* MSR_PR -> _PAGE_USER */ rlwimi r3,r9,32-12,29,29 /* MSR_PR -> _PAGE_USER */
112: add r5,r5,r7 /* convert to phys addr */ 112: add r5,r5,r7 /* convert to phys addr */
rlwimi r5,r4,12,20,29 /* insert top 10 bits of address */ rlwimi r5,r4,12,20,29 /* insert top 10 bits of address */
lwz r2,0(r5) /* get pmd entry */ lwz r8,0(r5) /* get pmd entry */
rlwinm. r2,r2,0,0,19 /* extract address of pte page */ rlwinm. r8,r8,0,0,19 /* extract address of pte page */
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
beq- hash_page_out /* return if no mapping */ beq- hash_page_out /* return if no mapping */
#else #else
...@@ -99,7 +99,7 @@ hash_page: ...@@ -99,7 +99,7 @@ hash_page:
to the address following the rfi. */ to the address following the rfi. */
beqlr- beqlr-
#endif #endif
rlwimi r2,r4,22,20,29 /* insert next 10 bits of address */ rlwimi r8,r4,22,20,29 /* insert next 10 bits of address */
rlwinm r0,r3,32-3,24,24 /* _PAGE_RW access -> _PAGE_DIRTY */ rlwinm r0,r3,32-3,24,24 /* _PAGE_RW access -> _PAGE_DIRTY */
ori r0,r0,_PAGE_ACCESSED|_PAGE_HASHPTE ori r0,r0,_PAGE_ACCESSED|_PAGE_HASHPTE
...@@ -110,7 +110,7 @@ hash_page: ...@@ -110,7 +110,7 @@ hash_page:
* to update the PTE to set _PAGE_HASHPTE. -- paulus. * to update the PTE to set _PAGE_HASHPTE. -- paulus.
*/ */
retry: retry:
lwarx r6,0,r2 /* get linux-style pte */ lwarx r6,0,r8 /* get linux-style pte */
andc. r5,r3,r6 /* check access & ~permission */ andc. r5,r3,r6 /* check access & ~permission */
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
bne- hash_page_out /* return if access not permitted */ bne- hash_page_out /* return if access not permitted */
...@@ -118,13 +118,13 @@ retry: ...@@ -118,13 +118,13 @@ retry:
bnelr- bnelr-
#endif #endif
or r5,r0,r6 /* set accessed/dirty bits */ or r5,r0,r6 /* set accessed/dirty bits */
stwcx. r5,0,r2 /* attempt to update PTE */ stwcx. r5,0,r8 /* attempt to update PTE */
bne- retry /* retry if someone got there first */ bne- retry /* retry if someone got there first */
mfsrin r3,r4 /* get segment reg for segment */ mfsrin r3,r4 /* get segment reg for segment */
mr r2,r8 /* we have saved r2 but not r8 */ mfctr r0
stw r0,_CTR(r11)
bl create_hpte /* add the hash table entry */ bl create_hpte /* add the hash table entry */
mr r8,r2
/* /*
* htab_reloads counts the number of times we have to fault an * htab_reloads counts the number of times we have to fault an
...@@ -134,48 +134,34 @@ retry: ...@@ -134,48 +134,34 @@ retry:
* update_mmu_cache gets called to put the HPTE into the hash table * update_mmu_cache gets called to put the HPTE into the hash table
* and those are counted as preloads rather than reloads. * and those are counted as preloads rather than reloads.
*/ */
addis r2,r7,htab_reloads@ha addis r8,r7,htab_reloads@ha
lwz r3,htab_reloads@l(r2) lwz r3,htab_reloads@l(r8)
addi r3,r3,1 addi r3,r3,1
stw r3,htab_reloads@l(r2) stw r3,htab_reloads@l(r8)
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
eieio eieio
addis r2,r7,mmu_hash_lock@ha addis r8,r7,mmu_hash_lock@ha
li r0,0 li r0,0
stw r0,mmu_hash_lock@l(r2) stw r0,mmu_hash_lock@l(r8)
#endif #endif
/* Return from the exception */ /* Return from the exception */
lwz r3,_CCR(r21) lwz r4,_LINK(r11)
lwz r4,_LINK(r21) lwz r5,_CTR(r11)
lwz r5,_CTR(r21)
mtcrf 0xff,r3
mtlr r4 mtlr r4
mtctr r5 mtctr r5
lwz r0,GPR0(r21) lwz r0,GPR0(r11)
lwz r1,GPR1(r21) lwz r7,GPR7(r11)
lwz r2,GPR2(r21) lwz r8,GPR8(r11)
lwz r3,GPR3(r21) b fast_exception_return
lwz r4,GPR4(r21)
lwz r5,GPR5(r21)
lwz r6,GPR6(r21)
lwz r7,GPR7(r21)
/* we haven't used xer */
mtspr SRR1,r23
mtspr SRR0,r22
lwz r20,GPR20(r21)
lwz r22,GPR22(r21)
lwz r23,GPR23(r21)
lwz r21,GPR21(r21)
RFI
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
hash_page_out: hash_page_out:
eieio eieio
addis r2,r7,mmu_hash_lock@ha addis r8,r7,mmu_hash_lock@ha
li r0,0 li r0,0
stw r0,mmu_hash_lock@l(r2) stw r0,mmu_hash_lock@l(r8)
blr blr
#endif /* CONFIG_SMP */ #endif /* CONFIG_SMP */
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <asm/prom.h> #include <asm/prom.h>
#include <asm/bitops.h> #include <asm/bitops.h>
#include <asm/bootx.h> #include <asm/bootx.h>
#include <asm/machdep.h>
#ifdef CONFIG_PMAC_BACKLIGHT #ifdef CONFIG_PMAC_BACKLIGHT
#include <asm/backlight.h> #include <asm/backlight.h>
#endif #endif
...@@ -105,6 +106,7 @@ static void cpu_cmd(void); ...@@ -105,6 +106,7 @@ static void cpu_cmd(void);
#endif /* CONFIG_SMP */ #endif /* CONFIG_SMP */
static int pretty_print_addr(unsigned long addr); static int pretty_print_addr(unsigned long addr);
static void csum(void); static void csum(void);
static void bootcmds(void);
extern int print_insn_big_powerpc(FILE *, unsigned long, unsigned); extern int print_insn_big_powerpc(FILE *, unsigned long, unsigned);
extern void printf(const char *fmt, ...); extern void printf(const char *fmt, ...);
...@@ -482,10 +484,26 @@ cmds(struct pt_regs *excp) ...@@ -482,10 +484,26 @@ cmds(struct pt_regs *excp)
cpu_cmd(); cpu_cmd();
break; break;
#endif /* CONFIG_SMP */ #endif /* CONFIG_SMP */
case 'z':
bootcmds();
break;
} }
} }
} }
static void bootcmds(void)
{
int cmd;
cmd = inchar();
if (cmd == 'r')
ppc_md.restart(NULL);
else if (cmd == 'h')
ppc_md.halt();
else if (cmd == 'p')
ppc_md.power_off();
}
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
static void cpu_cmd(void) static void cpu_cmd(void)
{ {
...@@ -670,7 +688,7 @@ bpt_cmds(void) ...@@ -670,7 +688,7 @@ bpt_cmds(void)
printf("r"); printf("r");
if (dabr.address & 2) if (dabr.address & 2)
printf("w"); printf("w");
if (dabr.address & 4) if (!(dabr.address & 4))
printf("p"); printf("p");
printf("]\n"); printf("]\n");
} }
...@@ -707,8 +725,7 @@ backtrace(struct pt_regs *excp) ...@@ -707,8 +725,7 @@ backtrace(struct pt_regs *excp)
unsigned sp; unsigned sp;
unsigned stack[2]; unsigned stack[2];
struct pt_regs regs; struct pt_regs regs;
extern char ret_from_intercept, ret_from_syscall_1, ret_from_syscall_2; extern char ret_from_except, ret_from_except_full, ret_from_syscall;
extern char ret_from_except;
printf("backtrace:\n"); printf("backtrace:\n");
...@@ -723,10 +740,9 @@ backtrace(struct pt_regs *excp) ...@@ -723,10 +740,9 @@ backtrace(struct pt_regs *excp)
break; break;
pretty_print_addr(stack[1]); pretty_print_addr(stack[1]);
printf(" "); printf(" ");
if (stack[1] == (unsigned) &ret_from_intercept if (stack[1] == (unsigned) &ret_from_except
|| stack[1] == (unsigned) &ret_from_except || stack[1] == (unsigned) &ret_from_except_full
|| stack[1] == (unsigned) &ret_from_syscall_1 || stack[1] == (unsigned) &ret_from_syscall) {
|| stack[1] == (unsigned) &ret_from_syscall_2) {
if (mread(sp+16, &regs, sizeof(regs)) != sizeof(regs)) if (mread(sp+16, &regs, sizeof(regs)) != sizeof(regs))
break; break;
printf("\nexception:%x [%x] %x ", regs.trap, sp+16, printf("\nexception:%x [%x] %x ", regs.trap, sp+16,
...@@ -751,6 +767,8 @@ getsp() ...@@ -751,6 +767,8 @@ getsp()
void void
excprint(struct pt_regs *fp) excprint(struct pt_regs *fp)
{ {
int trap;
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
printf("cpu %d: ", smp_processor_id()); printf("cpu %d: ", smp_processor_id());
#endif /* CONFIG_SMP */ #endif /* CONFIG_SMP */
...@@ -759,7 +777,8 @@ excprint(struct pt_regs *fp) ...@@ -759,7 +777,8 @@ excprint(struct pt_regs *fp)
printf(", lr = "); printf(", lr = ");
pretty_print_addr(fp->link); pretty_print_addr(fp->link);
printf("\nmsr = %x, sp = %x [%x]\n", fp->msr, fp->gpr[1], fp); printf("\nmsr = %x, sp = %x [%x]\n", fp->msr, fp->gpr[1], fp);
if (fp->trap == 0x300 || fp->trap == 0x600) trap = TRAP(fp);
if (trap == 0x300 || trap == 0x600)
printf("dar = %x, dsisr = %x\n", fp->dar, fp->dsisr); printf("dar = %x, dsisr = %x\n", fp->dar, fp->dsisr);
if (current) if (current)
printf("current = %x, pid = %d, comm = %s\n", printf("current = %x, pid = %d, comm = %s\n",
...@@ -774,9 +793,14 @@ prregs(struct pt_regs *fp) ...@@ -774,9 +793,14 @@ prregs(struct pt_regs *fp)
if (scanhex(&base)) if (scanhex(&base))
fp = (struct pt_regs *) base; fp = (struct pt_regs *) base;
for (n = 0; n < 32; ++n) for (n = 0; n < 32; ++n) {
printf("R%.2d = %.8x%s", n, fp->gpr[n], printf("R%.2d = %.8x%s", n, fp->gpr[n],
(n & 3) == 3? "\n": " "); (n & 3) == 3? "\n": " ");
if (n == 12 && !FULL_REGS(fp)) {
printf("\n");
break;
}
}
printf("pc = %.8x msr = %.8x lr = %.8x cr = %.8x\n", printf("pc = %.8x msr = %.8x lr = %.8x cr = %.8x\n",
fp->nip, fp->msr, fp->link, fp->ccr); fp->nip, fp->msr, fp->link, fp->ccr);
printf("ctr = %.8x xer = %.8x trap = %4x\n", printf("ctr = %.8x xer = %.8x trap = %4x\n",
...@@ -1160,7 +1184,7 @@ static char *fault_chars[] = { "--", "**", "##" }; ...@@ -1160,7 +1184,7 @@ static char *fault_chars[] = { "--", "**", "##" };
static void static void
handle_fault(struct pt_regs *regs) handle_fault(struct pt_regs *regs)
{ {
fault_type = regs->trap == 0x200? 0: regs->trap == 0x300? 1: 2; fault_type = TRAP(regs) == 0x200? 0: TRAP(regs) == 0x300? 1: 2;
longjmp(bus_error_jmp, 1); longjmp(bus_error_jmp, 1);
} }
......
...@@ -8,7 +8,6 @@ ...@@ -8,7 +8,6 @@
#include <linux/config.h> #include <linux/config.h>
#include <asm/smp.h> #include <asm/smp.h>
/* entry.S is sensitive to the offsets of these fields */
/* The __last_jiffy_stamp field is needed to ensure that no decrementer /* The __last_jiffy_stamp field is needed to ensure that no decrementer
* interrupt is lost on SMP machines. Since on most CPUs it is in the same * interrupt is lost on SMP machines. Since on most CPUs it is in the same
* cache line as local_irq_count, it is cheap to access and is also used on UP * cache line as local_irq_count, it is cheap to access and is also used on UP
...@@ -40,8 +39,8 @@ typedef struct { ...@@ -40,8 +39,8 @@ typedef struct {
#define hardirq_trylock(cpu) (local_irq_count(cpu) == 0) #define hardirq_trylock(cpu) (local_irq_count(cpu) == 0)
#define hardirq_endlock(cpu) do { } while (0) #define hardirq_endlock(cpu) do { } while (0)
#define hardirq_enter(cpu) (local_irq_count(cpu)++) #define hardirq_enter(cpu) do { preempt_disable(); local_irq_count(cpu)++; } while (0)
#define hardirq_exit(cpu) (local_irq_count(cpu)--) #define hardirq_exit(cpu) do { local_irq_count(cpu)--; preempt_enable(); } while (0)
#define synchronize_irq() do { } while (0) #define synchronize_irq() do { } while (0)
#define release_irqlock(cpu) do { } while (0) #define release_irqlock(cpu) do { } while (0)
...@@ -75,7 +74,8 @@ static inline void release_irqlock(int cpu) ...@@ -75,7 +74,8 @@ static inline void release_irqlock(int cpu)
static inline void hardirq_enter(int cpu) static inline void hardirq_enter(int cpu)
{ {
unsigned int loops = 10000000; unsigned int loops = 10000000;
preempt_disable();
++local_irq_count(cpu); ++local_irq_count(cpu);
while (test_bit(0,&global_irq_lock)) { while (test_bit(0,&global_irq_lock)) {
if (cpu == global_irq_holder) { if (cpu == global_irq_holder) {
...@@ -97,6 +97,7 @@ static inline void hardirq_enter(int cpu) ...@@ -97,6 +97,7 @@ static inline void hardirq_enter(int cpu)
static inline void hardirq_exit(int cpu) static inline void hardirq_exit(int cpu)
{ {
--local_irq_count(cpu); --local_irq_count(cpu);
preempt_enable();
} }
static inline int hardirq_trylock(int cpu) static inline int hardirq_trylock(int cpu)
......
...@@ -31,6 +31,11 @@ ...@@ -31,6 +31,11 @@
#define REST_8GPRS(n, base) REST_4GPRS(n, base); REST_4GPRS(n+4, base) #define REST_8GPRS(n, base) REST_4GPRS(n, base); REST_4GPRS(n+4, base)
#define REST_10GPRS(n, base) REST_8GPRS(n, base); REST_2GPRS(n+8, base) #define REST_10GPRS(n, base) REST_8GPRS(n, base); REST_2GPRS(n+8, base)
#define SAVE_NVGPRS(base) SAVE_GPR(13, base); SAVE_8GPRS(14, base); \
SAVE_10GPRS(22, base)
#define REST_NVGPRS(base) REST_GPR(13, base); REST_8GPRS(14, base); \
REST_10GPRS(22, base)
#define SAVE_FPR(n, base) stfd n,THREAD_FPR0+8*(n)(base) #define SAVE_FPR(n, base) stfd n,THREAD_FPR0+8*(n)(base)
#define SAVE_2FPRS(n, base) SAVE_FPR(n, base); SAVE_FPR(n+1, base) #define SAVE_2FPRS(n, base) SAVE_FPR(n, base); SAVE_FPR(n+1, base)
#define SAVE_4FPRS(n, base) SAVE_2FPRS(n, base); SAVE_2FPRS(n+2, base) #define SAVE_4FPRS(n, base) SAVE_2FPRS(n, base); SAVE_2FPRS(n+2, base)
......
...@@ -49,12 +49,12 @@ ...@@ -49,12 +49,12 @@
#define MSR_LE (1<<0) /* Little Endian */ #define MSR_LE (1<<0) /* Little Endian */
#ifdef CONFIG_APUS_FAST_EXCEPT #ifdef CONFIG_APUS_FAST_EXCEPT
#define MSR_ MSR_ME|MSR_IP|MSR_RI #define MSR_ (MSR_ME|MSR_IP|MSR_RI)
#else #else
#define MSR_ MSR_ME|MSR_RI #define MSR_ (MSR_ME|MSR_RI)
#endif #endif
#define MSR_KERNEL MSR_|MSR_IR|MSR_DR #define MSR_KERNEL (MSR_|MSR_IR|MSR_DR)
#define MSR_USER MSR_KERNEL|MSR_PR|MSR_EE #define MSR_USER (MSR_KERNEL|MSR_PR|MSR_EE)
/* Floating Point Status and Control Register (FPSCR) Fields */ /* Floating Point Status and Control Register (FPSCR) Fields */
......
...@@ -33,14 +33,16 @@ struct pt_regs { ...@@ -33,14 +33,16 @@ struct pt_regs {
unsigned long mq; /* 601 only (not used at present) */ unsigned long mq; /* 601 only (not used at present) */
/* Used on APUS to hold IPL value. */ /* Used on APUS to hold IPL value. */
unsigned long trap; /* Reason for being here */ unsigned long trap; /* Reason for being here */
/* N.B. for critical exceptions on 4xx, the dar and dsisr
fields are overloaded to hold srr0 and srr1. */
unsigned long dar; /* Fault registers */ unsigned long dar; /* Fault registers */
unsigned long dsisr; unsigned long dsisr;
unsigned long result; /* Result of a system call */ unsigned long result; /* Result of a system call */
}; };
#endif
/* iSeries uses mq field for soft enable flag */ /* iSeries uses mq field for soft enable flag */
#define softEnable mq #define softEnable mq
#endif /* __ASSEMBLY__ */
#ifdef __KERNEL__ #ifdef __KERNEL__
#define STACK_FRAME_OVERHEAD 16 /* size of minimum stack frame */ #define STACK_FRAME_OVERHEAD 16 /* size of minimum stack frame */
...@@ -48,9 +50,28 @@ struct pt_regs { ...@@ -48,9 +50,28 @@ struct pt_regs {
/* Size of stack frame allocated when calling signal handler. */ /* Size of stack frame allocated when calling signal handler. */
#define __SIGNAL_FRAMESIZE 64 #define __SIGNAL_FRAMESIZE 64
#ifndef __ASSEMBLY__
#define instruction_pointer(regs) ((regs)->nip) #define instruction_pointer(regs) ((regs)->nip)
#define user_mode(regs) (((regs)->msr & MSR_PR) != 0) #define user_mode(regs) (((regs)->msr & MSR_PR) != 0)
/*
* We use the least-significant bit of the trap field to indicate
* whether we have saved the full set of registers, or only a
* partial set. A 1 there means the partial set.
* On 4xx we use the next bit to indicate whether the exception
* is a critical exception (1 means it is).
*/
#define FULL_REGS(regs) (((regs)->trap & 1) == 0)
#define IS_CRITICAL_EXC(regs) (((regs)->trap & 2) == 0)
#define TRAP(regs) ((regs)->trap & ~0xF)
#define CHECK_FULL_REGS(regs) \
do { \
if ((regs)->trap & 1) \
printk(KERN_CRIT "%s: partial register set\n", __FUNCTION__); \
} while (0)
#endif /* __ASSEMBLY__ */
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
/* /*
......
/* /*
* BK Id: SCCS/s.smplock.h 1.10 10/23/01 08:09:35 trini * BK Id: %F% %I% %G% %U% %#%
*/ */
/* /*
* <asm/smplock.h> * <asm/smplock.h>
...@@ -15,26 +15,28 @@ ...@@ -15,26 +15,28 @@
extern spinlock_t kernel_flag; extern spinlock_t kernel_flag;
#ifdef CONFIG_SMP
#define kernel_locked() spin_is_locked(&kernel_flag) #define kernel_locked() spin_is_locked(&kernel_flag)
#elif defined(CONFIG_PREEMPT)
#define kernel_locked() preempt_get_count()
#endif
/* /*
* Release global kernel lock and global interrupt lock * Release global kernel lock and global interrupt lock
*/ */
#define release_kernel_lock(task, cpu) \ #define release_kernel_lock(task, cpu) \
do { \ do { \
if (task->lock_depth >= 0) \ if (unlikely(task->lock_depth >= 0)) \
spin_unlock(&kernel_flag); \ spin_unlock(&kernel_flag); \
release_irqlock(cpu); \
__sti(); \
} while (0) } while (0)
/* /*
* Re-acquire the kernel lock * Re-acquire the kernel lock
*/ */
#define reacquire_kernel_lock(task) \ #define reacquire_kernel_lock(task) \
do { \ do { \
if (task->lock_depth >= 0) \ if (unlikely(task->lock_depth >= 0)) \
spin_lock(&kernel_flag); \ spin_lock(&kernel_flag); \
} while (0) } while (0)
...@@ -47,8 +49,14 @@ do { \ ...@@ -47,8 +49,14 @@ do { \
*/ */
static __inline__ void lock_kernel(void) static __inline__ void lock_kernel(void)
{ {
#ifdef CONFIG_PREEMPT
if (current->lock_depth == -1)
spin_lock(&kernel_flag);
++current->lock_depth;
#else
if (!++current->lock_depth) if (!++current->lock_depth)
spin_lock(&kernel_flag); spin_lock(&kernel_flag);
#endif /* CONFIG_PREEMPT */
} }
static __inline__ void unlock_kernel(void) static __inline__ void unlock_kernel(void)
......
/* /*
* BK Id: SCCS/s.softirq.h 1.13 07/12/01 20:02:34 paulus * BK Id: %F% %I% %G% %U% %#%
*/ */
#ifdef __KERNEL__ #ifdef __KERNEL__
#ifndef __ASM_SOFTIRQ_H #ifndef __ASM_SOFTIRQ_H
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#define local_bh_disable() \ #define local_bh_disable() \
do { \ do { \
preempt_disable(); \
local_bh_count(smp_processor_id())++; \ local_bh_count(smp_processor_id())++; \
barrier(); \ barrier(); \
} while (0) } while (0)
...@@ -18,14 +19,17 @@ do { \ ...@@ -18,14 +19,17 @@ do { \
do { \ do { \
barrier(); \ barrier(); \
local_bh_count(smp_processor_id())--; \ local_bh_count(smp_processor_id())--; \
preempt_enable(); \
} while (0) } while (0)
#define local_bh_enable() \ #define local_bh_enable() \
do { \ do { \
barrier(); \
if (!--local_bh_count(smp_processor_id()) \ if (!--local_bh_count(smp_processor_id()) \
&& softirq_pending(smp_processor_id())) { \ && softirq_pending(smp_processor_id())) { \
do_softirq(); \ do_softirq(); \
} \ } \
preempt_enable(); \
} while (0) } while (0)
#define in_softirq() (local_bh_count(smp_processor_id()) != 0) #define in_softirq() (local_bh_count(smp_processor_id()) != 0)
......
...@@ -23,6 +23,8 @@ struct thread_info { ...@@ -23,6 +23,8 @@ struct thread_info {
unsigned long flags; /* low level flags */ unsigned long flags; /* low level flags */
int cpu; /* cpu we're on */ int cpu; /* cpu we're on */
int preempt_count; /* not used at present */ int preempt_count; /* not used at present */
int softirq_count;
int hardirq_count;
}; };
/* /*
...@@ -67,6 +69,9 @@ static inline struct thread_info *current_thread_info(void) ...@@ -67,6 +69,9 @@ static inline struct thread_info *current_thread_info(void)
#define TI_EXECDOMAIN 4 #define TI_EXECDOMAIN 4
#define TI_FLAGS 8 #define TI_FLAGS 8
#define TI_CPU 12 #define TI_CPU 12
#define TI_PREEMPT 16
#define TI_SOFTIRQ 20
#define TI_HARDIRQ 24
#define PREEMPT_ACTIVE 0x4000000 #define PREEMPT_ACTIVE 0x4000000
......
...@@ -234,7 +234,6 @@ ...@@ -234,7 +234,6 @@
#define __NR(n) #n #define __NR(n) #n
#define __syscall_return(type) \ #define __syscall_return(type) \
return (__sc_err & 0x10000000 ? errno = __sc_ret, __sc_ret = -1 : 0), \ return (__sc_err & 0x10000000 ? errno = __sc_ret, __sc_ret = -1 : 0), \
(type) __sc_ret (type) __sc_ret
...@@ -403,8 +402,9 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) \ ...@@ -403,8 +402,9 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) \
__syscall_return (type); \ __syscall_return (type); \
} }
#ifdef __KERNEL__
#ifdef __KERNEL_SYSCALLS__ #define __NR__exit __NR_exit
/* /*
* Forking from kernel space will result in the child getting a new, * Forking from kernel space will result in the child getting a new,
...@@ -414,29 +414,24 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) \ ...@@ -414,29 +414,24 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) \
* the child. * the child.
*/ */
#ifdef __KERNEL_SYSCALLS__
/* /*
* System call prototypes. * System call prototypes.
*/ */
#define __NR__exit __NR_exit extern pid_t setsid(void);
static inline _syscall0(int,pause) extern int write(int fd, const char *buf, off_t count);
static inline _syscall0(int,sync) extern int read(int fd, char *buf, off_t count);
static inline _syscall0(pid_t,setsid) extern off_t lseek(int fd, off_t offset, int count);
static inline _syscall3(int,write,int,fd,const char *,buf,off_t,count) extern int dup(int fd);
static inline _syscall3(int,read,int,fd,char *,buf,off_t,count) extern int execve(const char *file, char **argv, char **envp);
static inline _syscall3(off_t,lseek,int,fd,off_t,offset,int,count) extern int open(const char *file, int flag, int mode);
static inline _syscall1(int,dup,int,fd) extern int close(int fd);
static inline _syscall3(int,execve,const char *,file,char **,argv,char **,envp) extern pid_t waitpid(pid_t pid, int *wait_stat, int options);
static inline _syscall3(int,open,const char *,file,int,flag,int,mode)
static inline _syscall1(int,close,int,fd)
static inline _syscall1(int,_exit,int,exitcode)
static inline _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options)
static inline _syscall1(int,delete_module,const char *,name)
static inline pid_t wait(int * wait_stat) static inline pid_t wait(int * wait_stat)
{ {
return waitpid(-1, wait_stat, 0); return waitpid(-1, wait_stat, 0);
} }
#endif /* __KERNEL_SYSCALLS__ */ #endif /* __KERNEL_SYSCALLS__ */
/* /*
...@@ -447,4 +442,6 @@ static inline pid_t wait(int * wait_stat) ...@@ -447,4 +442,6 @@ static inline pid_t wait(int * wait_stat)
*/ */
#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall"); #define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
#endif /* __KERNEL__ */
#endif /* _ASM_PPC_UNISTD_H_ */ #endif /* _ASM_PPC_UNISTD_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