Commit c1ee055c authored by Nathan Scott's avatar Nathan Scott

Merge sgi.com:/source2/linux-2.6 into sgi.com:/source2/xfs-linux-2.6

parents 6860067c 3900b963
...@@ -279,8 +279,8 @@ setup_memory(void *kernel_end) ...@@ -279,8 +279,8 @@ setup_memory(void *kernel_end)
initrd_end, initrd_end,
phys_to_virt(PFN_PHYS(max_low_pfn))); phys_to_virt(PFN_PHYS(max_low_pfn)));
} else { } else {
nid = NODE_DATA(kvaddr_to_nid(initrd_start)); nid = kvaddr_to_nid(initrd_start);
reserve_bootmem_node(nid, reserve_bootmem_node(NODE_DATA(nid),
virt_to_phys((void *)initrd_start), virt_to_phys((void *)initrd_start),
INITRD_SIZE); INITRD_SIZE);
} }
......
...@@ -198,7 +198,6 @@ config SCHED_SMT ...@@ -198,7 +198,6 @@ config SCHED_SMT
config PREEMPT config PREEMPT
bool "Preemptible Kernel" bool "Preemptible Kernel"
depends on BROKEN
help help
This option reduces the latency of the kernel when reacting to This option reduces the latency of the kernel when reacting to
real-time or interactive events by allowing a low priority process to real-time or interactive events by allowing a low priority process to
......
...@@ -22,8 +22,6 @@ ...@@ -22,8 +22,6 @@
#include <asm/cache.h> #include <asm/cache.h>
#include <asm/cputable.h> #include <asm/cputable.h>
void disable_kernel_fp(void); /* asm function from head.S */
struct aligninfo { struct aligninfo {
unsigned char len; unsigned char len;
unsigned char flags; unsigned char flags;
...@@ -280,8 +278,11 @@ fix_alignment(struct pt_regs *regs) ...@@ -280,8 +278,11 @@ fix_alignment(struct pt_regs *regs)
} }
/* Force the fprs into the save area so we can reference them */ /* Force the fprs into the save area so we can reference them */
if ((flags & F) && (regs->msr & MSR_FP)) if (flags & F) {
giveup_fpu(current); if (!user_mode(regs))
return 0;
flush_fp_to_thread(current);
}
/* If we are loading, get the data from user space */ /* If we are loading, get the data from user space */
if (flags & LD) { if (flags & LD) {
...@@ -310,9 +311,11 @@ fix_alignment(struct pt_regs *regs) ...@@ -310,9 +311,11 @@ fix_alignment(struct pt_regs *regs)
if (flags & F) { if (flags & F) {
if (nb == 4) { if (nb == 4) {
/* Doing stfs, have to convert to single */ /* Doing stfs, have to convert to single */
preempt_disable();
enable_kernel_fp(); enable_kernel_fp();
cvt_df(&current->thread.fpr[reg], (float *)&data.v[4], &current->thread.fpscr); cvt_df(&current->thread.fpr[reg], (float *)&data.v[4], &current->thread.fpscr);
disable_kernel_fp(); disable_kernel_fp();
preempt_enable();
} }
else else
data.dd = current->thread.fpr[reg]; data.dd = current->thread.fpr[reg];
...@@ -344,9 +347,11 @@ fix_alignment(struct pt_regs *regs) ...@@ -344,9 +347,11 @@ fix_alignment(struct pt_regs *regs)
if (flags & F) { if (flags & F) {
if (nb == 4) { if (nb == 4) {
/* Doing lfs, have to convert to double */ /* Doing lfs, have to convert to double */
preempt_disable();
enable_kernel_fp(); enable_kernel_fp();
cvt_fd((float *)&data.v[4], &current->thread.fpr[reg], &current->thread.fpscr); cvt_fd((float *)&data.v[4], &current->thread.fpr[reg], &current->thread.fpscr);
disable_kernel_fp(); disable_kernel_fp();
preempt_enable();
} }
else else
current->thread.fpr[reg] = data.dd; current->thread.fpr[reg] = data.dd;
......
...@@ -48,6 +48,8 @@ int main(void) ...@@ -48,6 +48,8 @@ int main(void)
DEFINE(THREAD_SHIFT, THREAD_SHIFT); DEFINE(THREAD_SHIFT, THREAD_SHIFT);
DEFINE(THREAD_SIZE, THREAD_SIZE); DEFINE(THREAD_SIZE, THREAD_SIZE);
DEFINE(TI_FLAGS, offsetof(struct thread_info, flags)); DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count));
DEFINE(TI_SC_NOERR, offsetof(struct thread_info, syscall_noerror));
/* task_struct->thread */ /* task_struct->thread */
DEFINE(THREAD, offsetof(struct task_struct, thread)); DEFINE(THREAD, offsetof(struct task_struct, thread));
...@@ -99,7 +101,10 @@ int main(void) ...@@ -99,7 +101,10 @@ int main(void)
DEFINE(PACALPPACA, offsetof(struct paca_struct, xLpPaca)); DEFINE(PACALPPACA, offsetof(struct paca_struct, xLpPaca));
DEFINE(LPPACA, offsetof(struct paca_struct, xLpPaca)); DEFINE(LPPACA, offsetof(struct paca_struct, xLpPaca));
DEFINE(PACAREGSAV, offsetof(struct paca_struct, xRegSav)); DEFINE(PACAREGSAV, offsetof(struct paca_struct, xRegSav));
DEFINE(PACAEXC, offsetof(struct paca_struct, exception_stack)); DEFINE(PACA_EXGEN, offsetof(struct paca_struct, exgen));
DEFINE(PACA_EXMC, offsetof(struct paca_struct, exmc));
DEFINE(PACA_EXSLB, offsetof(struct paca_struct, exslb));
DEFINE(PACA_EXDSI, offsetof(struct paca_struct, exdsi));
DEFINE(PACAGUARD, offsetof(struct paca_struct, guard)); DEFINE(PACAGUARD, offsetof(struct paca_struct, guard));
DEFINE(LPPACASRR0, offsetof(struct ItLpPaca, xSavedSrr0)); DEFINE(LPPACASRR0, offsetof(struct ItLpPaca, xSavedSrr0));
DEFINE(LPPACASRR1, offsetof(struct ItLpPaca, xSavedSrr1)); DEFINE(LPPACASRR1, offsetof(struct ItLpPaca, xSavedSrr1));
...@@ -136,6 +141,10 @@ int main(void) ...@@ -136,6 +141,10 @@ int main(void)
DEFINE(GPR7, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[7])); DEFINE(GPR7, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[7]));
DEFINE(GPR8, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[8])); DEFINE(GPR8, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[8]));
DEFINE(GPR9, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[9])); DEFINE(GPR9, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[9]));
DEFINE(GPR10, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[10]));
DEFINE(GPR11, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[11]));
DEFINE(GPR12, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[12]));
DEFINE(GPR13, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[13]));
DEFINE(GPR20, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[20])); DEFINE(GPR20, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[20]));
DEFINE(GPR21, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[21])); DEFINE(GPR21, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[21]));
DEFINE(GPR22, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[22])); DEFINE(GPR22, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[22]));
...@@ -154,7 +163,7 @@ int main(void) ...@@ -154,7 +163,7 @@ int main(void)
DEFINE(_DSISR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, dsisr)); DEFINE(_DSISR, 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));
DEFINE(SOFTE, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, softe)); DEFINE(SOFTE, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, softe));
/* These _only_ to be used with {PROM,RTAS}_FRAME_SIZE!!! */ /* These _only_ to be used with {PROM,RTAS}_FRAME_SIZE!!! */
......
This diff is collapsed.
This diff is collapsed.
...@@ -85,16 +85,17 @@ _GLOBAL(local_irq_restore) ...@@ -85,16 +85,17 @@ _GLOBAL(local_irq_restore)
cmpw 0,r3,r5 cmpw 0,r3,r5
beqlr beqlr
/* are we enabling interrupts? */ /* are we enabling interrupts? */
cmpi 0,r3,0 cmpdi 0,r3,0
stb r3,PACAPROCENABLED(r13) stb r3,PACAPROCENABLED(r13)
beqlr beqlr
/* Check pending interrupts */ /* Check pending interrupts */
/* A decrementer, IPI or PMC interrupt may have occurred /* A decrementer, IPI or PMC interrupt may have occurred
* while we were in the hypervisor (which enables) */ * while we were in the hypervisor (which enables) */
CHECKANYINT(r4,r5) ld r4,PACALPPACA+LPPACAANYINT(r13)
cmpdi r4,0
beqlr beqlr
/* /*
* Handle pending interrupts in interrupt context * Handle pending interrupts in interrupt context
*/ */
li r0,0x5555 li r0,0x5555
...@@ -608,7 +609,7 @@ _GLOBAL(kernel_thread) ...@@ -608,7 +609,7 @@ _GLOBAL(kernel_thread)
_GLOBAL(sys_call_table32) _GLOBAL(sys_call_table32)
.llong .sys_restart_syscall /* 0 */ .llong .sys_restart_syscall /* 0 */
.llong .sys_exit .llong .sys_exit
.llong .sys_fork .llong .ppc_fork
.llong .sys_read .llong .sys_read
.llong .sys_write .llong .sys_write
.llong .sys32_open /* 5 */ .llong .sys32_open /* 5 */
...@@ -678,7 +679,7 @@ _GLOBAL(sys_call_table32) ...@@ -678,7 +679,7 @@ _GLOBAL(sys_call_table32)
.llong .sys32_ssetmask .llong .sys32_ssetmask
.llong .sys_setreuid /* 70 */ .llong .sys_setreuid /* 70 */
.llong .sys_setregid .llong .sys_setregid
.llong .sys32_sigsuspend .llong .ppc32_sigsuspend
.llong .compat_sys_sigpending .llong .compat_sys_sigpending
.llong .sys32_sethostname .llong .sys32_sethostname
.llong .compat_sys_setrlimit /* 75 */ .llong .compat_sys_setrlimit /* 75 */
...@@ -726,7 +727,7 @@ _GLOBAL(sys_call_table32) ...@@ -726,7 +727,7 @@ _GLOBAL(sys_call_table32)
.llong .sys32_ipc .llong .sys32_ipc
.llong .sys_fsync .llong .sys_fsync
.llong .ppc32_sigreturn .llong .ppc32_sigreturn
.llong .sys_clone /* 120 */ .llong .ppc_clone /* 120 */
.llong .sys32_setdomainname .llong .sys32_setdomainname
.llong .ppc64_newuname .llong .ppc64_newuname
.llong .sys_ni_syscall /* old modify_ldt syscall */ .llong .sys_ni_syscall /* old modify_ldt syscall */
...@@ -784,7 +785,7 @@ _GLOBAL(sys_call_table32) ...@@ -784,7 +785,7 @@ _GLOBAL(sys_call_table32)
.llong .sys32_rt_sigpending /* 175 */ .llong .sys32_rt_sigpending /* 175 */
.llong .sys32_rt_sigtimedwait .llong .sys32_rt_sigtimedwait
.llong .sys32_rt_sigqueueinfo .llong .sys32_rt_sigqueueinfo
.llong .sys32_rt_sigsuspend .llong .ppc32_rt_sigsuspend
.llong .sys32_pread64 .llong .sys32_pread64
.llong .sys32_pwrite64 /* 180 */ .llong .sys32_pwrite64 /* 180 */
.llong .sys_chown .llong .sys_chown
...@@ -795,7 +796,7 @@ _GLOBAL(sys_call_table32) ...@@ -795,7 +796,7 @@ _GLOBAL(sys_call_table32)
.llong .sys32_sendfile .llong .sys32_sendfile
.llong .sys_ni_syscall /* reserved for streams1 */ .llong .sys_ni_syscall /* reserved for streams1 */
.llong .sys_ni_syscall /* reserved for streams2 */ .llong .sys_ni_syscall /* reserved for streams2 */
.llong .sys_vfork .llong .ppc_vfork
.llong .compat_sys_getrlimit /* 190 */ .llong .compat_sys_getrlimit /* 190 */
.llong .sys32_readahead .llong .sys32_readahead
.llong .sys32_mmap2 .llong .sys32_mmap2
...@@ -880,7 +881,7 @@ _GLOBAL(sys_call_table32) ...@@ -880,7 +881,7 @@ _GLOBAL(sys_call_table32)
_GLOBAL(sys_call_table) _GLOBAL(sys_call_table)
.llong .sys_restart_syscall /* 0 */ .llong .sys_restart_syscall /* 0 */
.llong .sys_exit .llong .sys_exit
.llong .sys_fork .llong .ppc_fork
.llong .sys_read .llong .sys_read
.llong .sys_write .llong .sys_write
.llong .sys_open /* 5 */ .llong .sys_open /* 5 */
...@@ -998,7 +999,7 @@ _GLOBAL(sys_call_table) ...@@ -998,7 +999,7 @@ _GLOBAL(sys_call_table)
.llong .sys_ipc .llong .sys_ipc
.llong .sys_fsync .llong .sys_fsync
.llong .sys_ni_syscall .llong .sys_ni_syscall
.llong .sys_clone /* 120 */ .llong .ppc_clone /* 120 */
.llong .sys_setdomainname .llong .sys_setdomainname
.llong .ppc64_newuname .llong .ppc64_newuname
.llong .sys_ni_syscall /* old modify_ldt syscall */ .llong .sys_ni_syscall /* old modify_ldt syscall */
...@@ -1056,7 +1057,7 @@ _GLOBAL(sys_call_table) ...@@ -1056,7 +1057,7 @@ _GLOBAL(sys_call_table)
.llong .sys_rt_sigpending /* 175 */ .llong .sys_rt_sigpending /* 175 */
.llong .sys_rt_sigtimedwait .llong .sys_rt_sigtimedwait
.llong .sys_rt_sigqueueinfo .llong .sys_rt_sigqueueinfo
.llong .sys_rt_sigsuspend .llong .ppc64_rt_sigsuspend
.llong .sys_pread64 .llong .sys_pread64
.llong .sys_pwrite64 /* 180 */ .llong .sys_pwrite64 /* 180 */
.llong .sys_chown .llong .sys_chown
...@@ -1067,7 +1068,7 @@ _GLOBAL(sys_call_table) ...@@ -1067,7 +1068,7 @@ _GLOBAL(sys_call_table)
.llong .sys_sendfile64 .llong .sys_sendfile64
.llong .sys_ni_syscall /* reserved for streams1 */ .llong .sys_ni_syscall /* reserved for streams1 */
.llong .sys_ni_syscall /* reserved for streams2 */ .llong .sys_ni_syscall /* reserved for streams2 */
.llong .sys_vfork .llong .ppc_vfork
.llong .sys_getrlimit /* 190 */ .llong .sys_getrlimit /* 190 */
.llong .sys_readahead .llong .sys_readahead
.llong .sys_ni_syscall /* 32bit only mmap2 */ .llong .sys_ni_syscall /* 32bit only mmap2 */
......
...@@ -62,8 +62,6 @@ struct systemcfg *systemcfg; ...@@ -62,8 +62,6 @@ struct systemcfg *systemcfg;
.xDesc = 0xd397d9e2, /* "LpRS" */ \ .xDesc = 0xd397d9e2, /* "LpRS" */ \
.xSize = sizeof(struct ItLpRegSave) \ .xSize = sizeof(struct ItLpRegSave) \
}, \ }, \
.exception_sp = \
(&paca[number].exception_stack[0]) - EXC_FRAME_SIZE, \
} }
struct paca_struct paca[] __page_aligned = { struct paca_struct paca[] __page_aligned = {
......
...@@ -65,8 +65,43 @@ struct mm_struct ioremap_mm = { ...@@ -65,8 +65,43 @@ struct mm_struct ioremap_mm = {
.page_table_lock = SPIN_LOCK_UNLOCKED, .page_table_lock = SPIN_LOCK_UNLOCKED,
}; };
/*
* Make sure the floating-point register state in the
* the thread_struct is up to date for task tsk.
*/
void flush_fp_to_thread(struct task_struct *tsk)
{
if (tsk->thread.regs) {
/*
* We need to disable preemption here because if we didn't,
* another process could get scheduled after the regs->msr
* test but before we have finished saving the FP registers
* to the thread_struct. That process could take over the
* FPU, and then when we get scheduled again we would store
* bogus values for the remaining FP registers.
*/
preempt_disable();
if (tsk->thread.regs->msr & MSR_FP) {
#ifdef CONFIG_SMP
/*
* This should only ever be called for current or
* for a stopped child process. Since we save away
* the FP register state on context switch on SMP,
* there is something wrong if a stopped child appears
* to still have its FP state in the CPU registers.
*/
BUG_ON(tsk != current);
#endif
giveup_fpu(current);
}
preempt_enable();
}
}
void enable_kernel_fp(void) void enable_kernel_fp(void)
{ {
WARN_ON(preemptible());
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
if (current->thread.regs && (current->thread.regs->msr & MSR_FP)) if (current->thread.regs && (current->thread.regs->msr & MSR_FP))
giveup_fpu(current); giveup_fpu(current);
...@@ -80,12 +115,9 @@ EXPORT_SYMBOL(enable_kernel_fp); ...@@ -80,12 +115,9 @@ EXPORT_SYMBOL(enable_kernel_fp);
int dump_task_fpu(struct task_struct *tsk, elf_fpregset_t *fpregs) int dump_task_fpu(struct task_struct *tsk, elf_fpregset_t *fpregs)
{ {
struct pt_regs *regs = tsk->thread.regs; if (!tsk->thread.regs)
if (!regs)
return 0; return 0;
if (tsk == current && (regs->msr & MSR_FP)) flush_fp_to_thread(current);
giveup_fpu(current);
memcpy(fpregs, &tsk->thread.fpr[0], sizeof(*fpregs)); memcpy(fpregs, &tsk->thread.fpr[0], sizeof(*fpregs));
...@@ -96,6 +128,8 @@ int dump_task_fpu(struct task_struct *tsk, elf_fpregset_t *fpregs) ...@@ -96,6 +128,8 @@ int dump_task_fpu(struct task_struct *tsk, elf_fpregset_t *fpregs)
void enable_kernel_altivec(void) void enable_kernel_altivec(void)
{ {
WARN_ON(preemptible());
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
if (current->thread.regs && (current->thread.regs->msr & MSR_VEC)) if (current->thread.regs && (current->thread.regs->msr & MSR_VEC))
giveup_altivec(current); giveup_altivec(current);
...@@ -107,10 +141,29 @@ void enable_kernel_altivec(void) ...@@ -107,10 +141,29 @@ void enable_kernel_altivec(void)
} }
EXPORT_SYMBOL(enable_kernel_altivec); EXPORT_SYMBOL(enable_kernel_altivec);
/*
* Make sure the VMX/Altivec register state in the
* the thread_struct is up to date for task tsk.
*/
void flush_altivec_to_thread(struct task_struct *tsk)
{
#ifdef CONFIG_ALTIVEC
if (tsk->thread.regs) {
preempt_disable();
if (tsk->thread.regs->msr & MSR_VEC) {
#ifdef CONFIG_SMP
BUG_ON(tsk != current);
#endif
giveup_altivec(current);
}
preempt_enable();
}
#endif
}
int dump_task_altivec(struct pt_regs *regs, elf_vrregset_t *vrregs) int dump_task_altivec(struct pt_regs *regs, elf_vrregset_t *vrregs)
{ {
if (regs->msr & MSR_VEC) flush_altivec_to_thread(current);
giveup_altivec(current);
memcpy(vrregs, &current->thread.vr[0], sizeof(*vrregs)); memcpy(vrregs, &current->thread.vr[0], sizeof(*vrregs));
return 1; return 1;
} }
...@@ -166,6 +219,7 @@ struct task_struct *__switch_to(struct task_struct *prev, ...@@ -166,6 +219,7 @@ struct task_struct *__switch_to(struct task_struct *prev,
void show_regs(struct pt_regs * regs) void show_regs(struct pt_regs * regs)
{ {
int i; int i;
unsigned long trap;
printk("NIP: %016lX XER: %016lX LR: %016lX\n", printk("NIP: %016lX XER: %016lX LR: %016lX\n",
regs->nip, regs->xer, regs->link); regs->nip, regs->xer, regs->link);
...@@ -176,7 +230,8 @@ void show_regs(struct pt_regs * regs) ...@@ -176,7 +230,8 @@ void show_regs(struct pt_regs * regs)
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 == 0x380 || regs->trap == 0x600) trap = TRAP(regs);
if (trap == 0x300 || trap == 0x380 || trap == 0x600)
printk("DAR: %016lx, DSISR: %016lx\n", regs->dar, regs->dsisr); printk("DAR: %016lx, DSISR: %016lx\n", regs->dar, regs->dsisr);
printk("TASK: %p[%d] '%s' THREAD: %p", printk("TASK: %p[%d] '%s' THREAD: %p",
current, current->pid, current->comm, current->thread_info); current, current->pid, current->comm, current->thread_info);
...@@ -191,6 +246,8 @@ void show_regs(struct pt_regs * regs) ...@@ -191,6 +246,8 @@ void show_regs(struct pt_regs * regs)
} }
printk("%016lX ", regs->gpr[i]); printk("%016lX ", regs->gpr[i]);
if (i == 13 && !FULL_REGS(regs))
break;
} }
printk("\n"); printk("\n");
/* /*
...@@ -245,16 +302,8 @@ release_thread(struct task_struct *t) ...@@ -245,16 +302,8 @@ release_thread(struct task_struct *t)
*/ */
void prepare_to_copy(struct task_struct *tsk) void prepare_to_copy(struct task_struct *tsk)
{ {
struct pt_regs *regs = tsk->thread.regs; flush_fp_to_thread(current);
flush_altivec_to_thread(current);
if (regs == NULL)
return;
if (regs->msr & MSR_FP)
giveup_fpu(current);
#ifdef CONFIG_ALTIVEC
if (regs->msr & MSR_VEC)
giveup_altivec(current);
#endif /* CONFIG_ALTIVEC */
} }
/* /*
...@@ -439,12 +488,8 @@ int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2, ...@@ -439,12 +488,8 @@ int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
error = PTR_ERR(filename); error = PTR_ERR(filename);
if (IS_ERR(filename)) if (IS_ERR(filename))
goto out; goto out;
if (regs->msr & MSR_FP) flush_fp_to_thread(current);
giveup_fpu(current); flush_altivec_to_thread(current);
#ifdef CONFIG_ALTIVEC
if (regs->msr & MSR_VEC)
giveup_altivec(current);
#endif /* CONFIG_ALTIVEC */
error = do_execve(filename, (char __user * __user *) a1, error = do_execve(filename, (char __user * __user *) a1,
(char __user * __user *) a2, regs); (char __user * __user *) a2, regs);
......
...@@ -119,8 +119,7 @@ int sys_ptrace(long request, long pid, long addr, long data) ...@@ -119,8 +119,7 @@ int sys_ptrace(long request, long pid, long addr, long data)
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->msr & MSR_FP) flush_fp_to_thread(child);
giveup_fpu(child);
tmp = ((unsigned long *)child->thread.fpr)[index - PT_FPR0]; tmp = ((unsigned long *)child->thread.fpr)[index - PT_FPR0];
} }
ret = put_user(tmp,(unsigned long __user *) data); ret = put_user(tmp,(unsigned long __user *) data);
...@@ -152,8 +151,7 @@ int sys_ptrace(long request, long pid, long addr, long data) ...@@ -152,8 +151,7 @@ int sys_ptrace(long request, long pid, long addr, long data)
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->msr & MSR_FP) flush_fp_to_thread(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;
} }
...@@ -245,8 +243,7 @@ int sys_ptrace(long request, long pid, long addr, long data) ...@@ -245,8 +243,7 @@ int sys_ptrace(long request, long pid, long addr, long data)
unsigned long *reg = &((unsigned long *)child->thread.fpr)[0]; unsigned long *reg = &((unsigned long *)child->thread.fpr)[0];
unsigned long __user *tmp = (unsigned long __user *)addr; unsigned long __user *tmp = (unsigned long __user *)addr;
if (child->thread.regs->msr & MSR_FP) flush_fp_to_thread(child);
giveup_fpu(child);
for (i = 0; i < 32; i++) { for (i = 0; i < 32; i++) {
ret = put_user(*reg, tmp); ret = put_user(*reg, tmp);
...@@ -263,8 +260,7 @@ int sys_ptrace(long request, long pid, long addr, long data) ...@@ -263,8 +260,7 @@ int sys_ptrace(long request, long pid, long addr, long data)
unsigned long *reg = &((unsigned long *)child->thread.fpr)[0]; unsigned long *reg = &((unsigned long *)child->thread.fpr)[0];
unsigned long __user *tmp = (unsigned long __user *)addr; unsigned long __user *tmp = (unsigned long __user *)addr;
if (child->thread.regs->msr & MSR_FP) flush_fp_to_thread(child);
giveup_fpu(child);
for (i = 0; i < 32; i++) { for (i = 0; i < 32; i++) {
ret = get_user(*reg, tmp); ret = get_user(*reg, tmp);
......
...@@ -136,8 +136,7 @@ int sys32_ptrace(long request, long pid, unsigned long addr, unsigned long data) ...@@ -136,8 +136,7 @@ int sys32_ptrace(long request, long pid, unsigned long addr, unsigned long data)
if (index < PT_FPR0) { if (index < PT_FPR0) {
tmp = get_reg(child, index); tmp = get_reg(child, index);
} else { } else {
if (child->thread.regs->msr & MSR_FP) flush_fp_to_thread(child);
giveup_fpu(child);
/* /*
* the user space code considers the floating point * the user space code considers the floating point
* to be an array of unsigned int (32 bits) - the * to be an array of unsigned int (32 bits) - the
...@@ -179,8 +178,7 @@ int sys32_ptrace(long request, long pid, unsigned long addr, unsigned long data) ...@@ -179,8 +178,7 @@ int sys32_ptrace(long request, long pid, unsigned long addr, unsigned long data)
break; break;
if (numReg >= PT_FPR0) { if (numReg >= PT_FPR0) {
if (child->thread.regs->msr & MSR_FP) flush_fp_to_thread(child);
giveup_fpu(child);
tmp = ((unsigned long int *)child->thread.fpr)[numReg - PT_FPR0]; tmp = ((unsigned long int *)child->thread.fpr)[numReg - PT_FPR0];
} else { /* register within PT_REGS struct */ } else { /* register within PT_REGS struct */
tmp = get_reg(child, numReg); tmp = get_reg(child, numReg);
...@@ -244,8 +242,7 @@ int sys32_ptrace(long request, long pid, unsigned long addr, unsigned long data) ...@@ -244,8 +242,7 @@ int sys32_ptrace(long request, long pid, unsigned long addr, unsigned long data)
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->msr & MSR_FP) flush_fp_to_thread(child);
giveup_fpu(child);
/* /*
* the user space code considers the floating point * the user space code considers the floating point
* to be an array of unsigned int (32 bits) - the * to be an array of unsigned int (32 bits) - the
...@@ -283,8 +280,7 @@ int sys32_ptrace(long request, long pid, unsigned long addr, unsigned long data) ...@@ -283,8 +280,7 @@ int sys32_ptrace(long request, long pid, unsigned long addr, unsigned long data)
|| ((numReg > PT_CCR) && (numReg < PT_FPR0))) || ((numReg > PT_CCR) && (numReg < PT_FPR0)))
break; break;
if (numReg >= PT_FPR0) { if (numReg >= PT_FPR0) {
if (child->thread.regs->msr & MSR_FP) flush_fp_to_thread(child);
giveup_fpu(child);
} }
if (numReg == PT_MSR) if (numReg == PT_MSR)
data = (data & MSR_DEBUGCHANGE) data = (data & MSR_DEBUGCHANGE)
...@@ -379,8 +375,7 @@ int sys32_ptrace(long request, long pid, unsigned long addr, unsigned long data) ...@@ -379,8 +375,7 @@ int sys32_ptrace(long request, long pid, unsigned long addr, unsigned long data)
unsigned long *reg = &((unsigned long *)child->thread.fpr)[0]; unsigned long *reg = &((unsigned long *)child->thread.fpr)[0];
unsigned int __user *tmp = (unsigned int __user *)addr; unsigned int __user *tmp = (unsigned int __user *)addr;
if (child->thread.regs->msr & MSR_FP) flush_fp_to_thread(child);
giveup_fpu(child);
for (i = 0; i < 32; i++) { for (i = 0; i < 32; i++) {
ret = put_user(*reg, tmp); ret = put_user(*reg, tmp);
...@@ -397,8 +392,7 @@ int sys32_ptrace(long request, long pid, unsigned long addr, unsigned long data) ...@@ -397,8 +392,7 @@ int sys32_ptrace(long request, long pid, unsigned long addr, unsigned long data)
unsigned long *reg = &((unsigned long *)child->thread.fpr)[0]; unsigned long *reg = &((unsigned long *)child->thread.fpr)[0];
unsigned int __user *tmp = (unsigned int __user *)addr; unsigned int __user *tmp = (unsigned int __user *)addr;
if (child->thread.regs->msr & MSR_FP) flush_fp_to_thread(child);
giveup_fpu(child);
for (i = 0; i < 32; i++) { for (i = 0; i < 32; i++) {
ret = get_user(*reg, tmp); ret = get_user(*reg, tmp);
......
...@@ -68,10 +68,11 @@ char rtas_data_buf[RTAS_DATA_BUF_SIZE]__page_aligned; ...@@ -68,10 +68,11 @@ char rtas_data_buf[RTAS_DATA_BUF_SIZE]__page_aligned;
void void
call_rtas_display_status(char c) call_rtas_display_status(char c)
{ {
struct rtas_args *args = &(get_paca()->xRtas); struct rtas_args *args;
unsigned long s; unsigned long s;
spin_lock_irqsave(&rtas.lock, s); spin_lock_irqsave(&rtas.lock, s);
args = &(get_paca()->xRtas);
args->token = 10; args->token = 10;
args->nargs = 1; args->nargs = 1;
...@@ -145,7 +146,7 @@ rtas_call(int token, int nargs, int nret, ...@@ -145,7 +146,7 @@ rtas_call(int token, int nargs, int nret,
va_list list; va_list list;
int i, logit = 0; int i, logit = 0;
unsigned long s; unsigned long s;
struct rtas_args *rtas_args = &(get_paca()->xRtas); struct rtas_args *rtas_args;
long ret; long ret;
PPCDBG(PPCDBG_RTAS, "Entering rtas_call\n"); PPCDBG(PPCDBG_RTAS, "Entering rtas_call\n");
...@@ -158,6 +159,7 @@ rtas_call(int token, int nargs, int nret, ...@@ -158,6 +159,7 @@ rtas_call(int token, int nargs, int nret,
/* Gotta do something different here, use global lock for now... */ /* Gotta do something different here, use global lock for now... */
spin_lock_irqsave(&rtas.lock, s); spin_lock_irqsave(&rtas.lock, s);
rtas_args = &(get_paca()->xRtas);
rtas_args->token = token; rtas_args->token = token;
rtas_args->nargs = nargs; rtas_args->nargs = nargs;
......
...@@ -131,8 +131,7 @@ static long setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, ...@@ -131,8 +131,7 @@ static long setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
#endif #endif
long err = 0; long err = 0;
if (regs->msr & MSR_FP) flush_fp_to_thread(current);
giveup_fpu(current);
/* Make sure signal doesn't get spurrious FP exceptions */ /* Make sure signal doesn't get spurrious FP exceptions */
current->thread.fpscr = 0; current->thread.fpscr = 0;
...@@ -141,9 +140,8 @@ static long setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, ...@@ -141,9 +140,8 @@ static long setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
err |= __put_user(v_regs, &sc->v_regs); err |= __put_user(v_regs, &sc->v_regs);
/* save altivec registers */ /* save altivec registers */
if (current->thread.used_vr) { if (current->thread.used_vr) {
if (regs->msr & MSR_VEC) flush_altivec_to_thread(current);
giveup_altivec(current);
/* Copy 33 vec registers (vr0..31 and vscr) to the stack */ /* Copy 33 vec registers (vr0..31 and vscr) to the stack */
err |= __copy_to_user(v_regs, current->thread.vr, 33 * sizeof(vector128)); err |= __copy_to_user(v_regs, current->thread.vr, 33 * sizeof(vector128));
/* set MSR_VEC in the MSR value in the frame to indicate that sc->v_reg) /* set MSR_VEC in the MSR value in the frame to indicate that sc->v_reg)
...@@ -530,13 +528,13 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs) ...@@ -530,13 +528,13 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
struct k_sigaction *ka = &current->sighand->action[signr-1]; struct k_sigaction *ka = &current->sighand->action[signr-1];
/* Whee! Actually deliver the signal. */ /* Whee! Actually deliver the signal. */
if (regs->trap == 0x0C00) if (TRAP(regs) == 0x0C00)
syscall_restart(regs, ka); syscall_restart(regs, ka);
handle_signal(signr, ka, &info, oldset, regs); handle_signal(signr, ka, &info, oldset, regs);
return 1; return 1;
} }
if (regs->trap == 0x0C00) { /* System Call! */ if (TRAP(regs) == 0x0C00) { /* System Call! */
if ((int)regs->result == -ERESTARTNOHAND || if ((int)regs->result == -ERESTARTNOHAND ||
(int)regs->result == -ERESTARTSYS || (int)regs->result == -ERESTARTSYS ||
(int)regs->result == -ERESTARTNOINTR) { (int)regs->result == -ERESTARTNOINTR) {
......
...@@ -130,11 +130,10 @@ static int save_user_regs(struct pt_regs *regs, struct mcontext32 __user *frame, ...@@ -130,11 +130,10 @@ static int save_user_regs(struct pt_regs *regs, struct mcontext32 __user *frame,
{ {
elf_greg_t64 *gregs = (elf_greg_t64 *)regs; elf_greg_t64 *gregs = (elf_greg_t64 *)regs;
int i, err = 0; int i, err = 0;
/* Make sure floating point registers are stored in regs */ /* Make sure floating point registers are stored in regs */
if (regs->msr & MSR_FP) flush_fp_to_thread(current);
giveup_fpu(current);
/* save general and floating-point registers */ /* save general and floating-point registers */
for (i = 0; i <= PT_RESULT; i ++) for (i = 0; i <= PT_RESULT; i ++)
err |= __put_user((unsigned int)gregs[i], &frame->mc_gregs[i]); err |= __put_user((unsigned int)gregs[i], &frame->mc_gregs[i]);
...@@ -148,8 +147,7 @@ static int save_user_regs(struct pt_regs *regs, struct mcontext32 __user *frame, ...@@ -148,8 +147,7 @@ static int save_user_regs(struct pt_regs *regs, struct mcontext32 __user *frame,
#ifdef CONFIG_ALTIVEC #ifdef CONFIG_ALTIVEC
/* save altivec registers */ /* save altivec registers */
if (current->thread.used_vr) { if (current->thread.used_vr) {
if (regs->msr & MSR_VEC) flush_altivec_to_thread(current);
giveup_altivec(current);
if (__copy_to_user(&frame->mc_vregs, current->thread.vr, if (__copy_to_user(&frame->mc_vregs, current->thread.vr,
ELF_NVRREG32 * sizeof(vector128))) ELF_NVRREG32 * sizeof(vector128)))
return 1; return 1;
...@@ -934,7 +932,7 @@ int do_signal32(sigset_t *oldset, struct pt_regs *regs) ...@@ -934,7 +932,7 @@ int do_signal32(sigset_t *oldset, struct pt_regs *regs)
ka = (signr == 0)? NULL: &current->sighand->action[signr-1]; ka = (signr == 0)? NULL: &current->sighand->action[signr-1];
if (regs->trap == 0x0C00 /* System Call! */ if (TRAP(regs) == 0x0C00 /* System Call! */
&& regs->ccr & 0x10000000 /* error signalled */ && regs->ccr & 0x10000000 /* error signalled */
&& ((ret = regs->gpr[3]) == ERESTARTSYS && ((ret = regs->gpr[3]) == ERESTARTSYS
|| ret == ERESTARTNOHAND || ret == ERESTARTNOINTR || ret == ERESTARTNOHAND || ret == ERESTARTNOINTR
......
...@@ -617,12 +617,8 @@ long sys32_execve(unsigned long a0, unsigned long a1, unsigned long a2, ...@@ -617,12 +617,8 @@ long sys32_execve(unsigned long a0, unsigned long a1, unsigned long a2,
error = PTR_ERR(filename); error = PTR_ERR(filename);
if (IS_ERR(filename)) if (IS_ERR(filename))
goto out; goto out;
if (regs->msr & MSR_FP) flush_fp_to_thread(current);
giveup_fpu(current); flush_altivec_to_thread(current);
#ifdef CONFIG_ALTIVEC
if (regs->msr & MSR_VEC)
giveup_altivec(current);
#endif /* CONFIG_ALTIVEC */
error = compat_do_execve(filename, compat_ptr(a1), compat_ptr(a2), regs); error = compat_do_execve(filename, compat_ptr(a1), compat_ptr(a2), regs);
......
...@@ -237,5 +237,19 @@ asmlinkage time_t sys64_time(time_t __user * tloc) ...@@ -237,5 +237,19 @@ asmlinkage time_t sys64_time(time_t __user * tloc)
return secs; return secs;
} }
void do_show_syscall(unsigned long r3, unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7, unsigned long r8,
struct pt_regs *regs)
{
printk("syscall %ld(%lx, %lx, %lx, %lx, %lx, %lx) regs=%p current=%p"
" cpu=%d\n", regs->gpr[0], r3, r4, r5, r6, r7, r8, regs,
current, smp_processor_id());
}
void do_show_syscall_exit(unsigned long r3)
{
printk(" -> %lx, current=%p cpu=%d\n", r3, current, smp_processor_id());
}
/* Only exists on P-series. */ /* Only exists on P-series. */
cond_syscall(ppc_rtas); cond_syscall(ppc_rtas);
...@@ -308,8 +308,7 @@ static void parse_fpe(struct pt_regs *regs) ...@@ -308,8 +308,7 @@ static void parse_fpe(struct pt_regs *regs)
siginfo_t info; siginfo_t info;
unsigned long fpscr; unsigned long fpscr;
if (regs->msr & MSR_FP) flush_fp_to_thread(current);
giveup_fpu(current);
fpscr = current->thread.fpscr; fpscr = current->thread.fpscr;
...@@ -442,8 +441,22 @@ void KernelFPUnavailableException(struct pt_regs *regs) ...@@ -442,8 +441,22 @@ void KernelFPUnavailableException(struct pt_regs *regs)
die("Unrecoverable FP Unavailable Exception", regs, SIGABRT); die("Unrecoverable FP Unavailable Exception", regs, SIGABRT);
} }
void KernelAltivecUnavailableException(struct pt_regs *regs) void AltivecUnavailableException(struct pt_regs *regs)
{ {
#ifndef CONFIG_ALTIVEC
if (user_mode(regs)) {
/* A user program has executed an altivec instruction,
but this kernel doesn't support altivec. */
siginfo_t info;
memset(&info, 0, sizeof(info));
info.si_signo = SIGILL;
info.si_code = ILL_ILLOPC;
info.si_addr = (void *) regs->nip;
_exception(SIGILL, &info, regs);
return;
}
#endif
printk(KERN_EMERG "Unrecoverable VMX/Altivec Unavailable Exception " printk(KERN_EMERG "Unrecoverable VMX/Altivec Unavailable Exception "
"%lx at %lx\n", regs->trap, regs->nip); "%lx at %lx\n", regs->trap, regs->nip);
die("Unrecoverable VMX/Altivec Unavailable Exception", regs, SIGABRT); die("Unrecoverable VMX/Altivec Unavailable Exception", regs, SIGABRT);
...@@ -531,8 +544,7 @@ AlignmentException(struct pt_regs *regs) ...@@ -531,8 +544,7 @@ AlignmentException(struct pt_regs *regs)
void void
AltivecAssistException(struct pt_regs *regs) AltivecAssistException(struct pt_regs *regs)
{ {
if (regs->msr & MSR_VEC) flush_altivec_to_thread(current);
giveup_altivec(current);
/* XXX quick hack for now: set the non-Java bit in the VSCR */ /* XXX quick hack for now: set the non-Java bit in the VSCR */
current->thread.vscr.u[3] |= 0x10000; current->thread.vscr.u[3] |= 0x10000;
} }
......
...@@ -80,36 +80,45 @@ static int store_updates_sp(struct pt_regs *regs) ...@@ -80,36 +80,45 @@ static int store_updates_sp(struct pt_regs *regs)
* - DSISR for a non-SLB data access fault, * - DSISR for a non-SLB data access fault,
* - SRR1 & 0x08000000 for a non-SLB instruction access fault * - SRR1 & 0x08000000 for a non-SLB instruction access fault
* - 0 any SLB fault. * - 0 any SLB fault.
* The return value is 0 if the fault was handled, or the signal
* number if this is a kernel fault that can't be handled here.
*/ */
void do_page_fault(struct pt_regs *regs, unsigned long address, int do_page_fault(struct pt_regs *regs, unsigned long address,
unsigned long error_code) unsigned long error_code)
{ {
struct vm_area_struct * vma; struct vm_area_struct * vma;
struct mm_struct *mm = current->mm; struct mm_struct *mm = current->mm;
siginfo_t info; siginfo_t info;
unsigned long code = SEGV_MAPERR; unsigned long code = SEGV_MAPERR;
unsigned long is_write = error_code & 0x02000000; unsigned long is_write = error_code & 0x02000000;
unsigned long trap = TRAP(regs);
if (regs->trap == 0x300 || regs->trap == 0x380) { if (trap == 0x300 || trap == 0x380) {
if (debugger_fault_handler(regs)) if (debugger_fault_handler(regs))
return; return 0;
} }
/* On a kernel SLB miss we can only check for a valid exception entry */ /* On a kernel SLB miss we can only check for a valid exception entry */
if (!user_mode(regs) && (regs->trap == 0x380)) { if (!user_mode(regs) && (trap == 0x380 || address >= TASK_SIZE))
bad_page_fault(regs, address, SIGSEGV); return SIGSEGV;
return;
}
if (error_code & 0x00400000) { if (error_code & 0x00400000) {
if (debugger_dabr_match(regs)) if (debugger_dabr_match(regs))
return; return 0;
} }
if (in_atomic() || mm == NULL) { if (in_atomic() || mm == NULL) {
bad_page_fault(regs, address, SIGSEGV); if (!user_mode(regs))
return; return SIGSEGV;
/* in_atomic() in user mode is really bad,
as is current->mm == NULL. */
printk(KERN_EMERG "Page fault in user mode with"
"in_atomic() = %d mm = %p\n", in_atomic(), mm);
printk(KERN_EMERG "NIP = %lx MSR = %lx\n",
regs->nip, regs->msr);
die("Weird page fault", regs, SIGSEGV);
} }
down_read(&mm->mmap_sem); down_read(&mm->mmap_sem);
vma = find_vma(mm, address); vma = find_vma(mm, address);
if (!vma) if (!vma)
...@@ -195,7 +204,7 @@ void do_page_fault(struct pt_regs *regs, unsigned long address, ...@@ -195,7 +204,7 @@ void do_page_fault(struct pt_regs *regs, unsigned long address,
} }
up_read(&mm->mmap_sem); up_read(&mm->mmap_sem);
return; return 0;
bad_area: bad_area:
up_read(&mm->mmap_sem); up_read(&mm->mmap_sem);
...@@ -207,11 +216,10 @@ void do_page_fault(struct pt_regs *regs, unsigned long address, ...@@ -207,11 +216,10 @@ void do_page_fault(struct pt_regs *regs, unsigned long address,
info.si_code = code; info.si_code = code;
info.si_addr = (void *) address; info.si_addr = (void *) address;
force_sig_info(SIGSEGV, &info, current); force_sig_info(SIGSEGV, &info, current);
return; return 0;
} }
bad_page_fault(regs, address, SIGSEGV); return SIGSEGV;
return;
/* /*
* We ran out of memory, or some other thing happened to us that made * We ran out of memory, or some other thing happened to us that made
...@@ -227,18 +235,19 @@ void do_page_fault(struct pt_regs *regs, unsigned long address, ...@@ -227,18 +235,19 @@ void do_page_fault(struct pt_regs *regs, unsigned long address,
printk("VM: killing process %s\n", current->comm); printk("VM: killing process %s\n", current->comm);
if (user_mode(regs)) if (user_mode(regs))
do_exit(SIGKILL); do_exit(SIGKILL);
bad_page_fault(regs, address, SIGKILL); return SIGKILL;
return;
do_sigbus: do_sigbus:
up_read(&mm->mmap_sem); up_read(&mm->mmap_sem);
info.si_signo = SIGBUS; if (user_mode(regs)) {
info.si_errno = 0; info.si_signo = SIGBUS;
info.si_code = BUS_ADRERR; info.si_errno = 0;
info.si_addr = (void *)address; info.si_code = BUS_ADRERR;
force_sig_info (SIGBUS, &info, current); info.si_addr = (void *)address;
if (!user_mode(regs)) force_sig_info(SIGBUS, &info, current);
bad_page_fault(regs, address, SIGBUS); return 0;
}
return SIGBUS;
} }
/* /*
......
...@@ -251,6 +251,7 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap) ...@@ -251,6 +251,7 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap)
struct mm_struct *mm; struct mm_struct *mm;
pte_t *ptep; pte_t *ptep;
int ret; int ret;
int cpu;
int user_region = 0; int user_region = 0;
int local = 0; int local = 0;
cpumask_t tmp; cpumask_t tmp;
...@@ -302,7 +303,8 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap) ...@@ -302,7 +303,8 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap)
if (pgdir == NULL) if (pgdir == NULL)
return 1; return 1;
tmp = cpumask_of_cpu(smp_processor_id()); cpu = get_cpu();
tmp = cpumask_of_cpu(cpu);
if (user_region && cpus_equal(mm->cpu_vm_mask, tmp)) if (user_region && cpus_equal(mm->cpu_vm_mask, tmp))
local = 1; local = 1;
...@@ -311,11 +313,13 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap) ...@@ -311,11 +313,13 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap)
ret = hash_huge_page(mm, access, ea, vsid, local); ret = hash_huge_page(mm, access, ea, vsid, local);
else { else {
ptep = find_linux_pte(pgdir, ea); ptep = find_linux_pte(pgdir, ea);
if (ptep == NULL) if (ptep == NULL) {
put_cpu();
return 1; return 1;
}
ret = __hash_page(ea, access, vsid, ptep, trap, local); ret = __hash_page(ea, access, vsid, ptep, trap, local);
} }
put_cpu();
return ret; return ret;
} }
......
...@@ -375,6 +375,7 @@ void unmap_hugepage_range(struct vm_area_struct *vma, ...@@ -375,6 +375,7 @@ void unmap_hugepage_range(struct vm_area_struct *vma,
unsigned long addr; unsigned long addr;
hugepte_t *ptep; hugepte_t *ptep;
struct page *page; struct page *page;
int cpu;
int local = 0; int local = 0;
cpumask_t tmp; cpumask_t tmp;
...@@ -383,7 +384,8 @@ void unmap_hugepage_range(struct vm_area_struct *vma, ...@@ -383,7 +384,8 @@ void unmap_hugepage_range(struct vm_area_struct *vma,
BUG_ON((end % HPAGE_SIZE) != 0); BUG_ON((end % HPAGE_SIZE) != 0);
/* XXX are there races with checking cpu_vm_mask? - Anton */ /* XXX are there races with checking cpu_vm_mask? - Anton */
tmp = cpumask_of_cpu(smp_processor_id()); cpu = get_cpu();
tmp = cpumask_of_cpu(cpu);
if (cpus_equal(vma->vm_mm->cpu_vm_mask, tmp)) if (cpus_equal(vma->vm_mm->cpu_vm_mask, tmp))
local = 1; local = 1;
...@@ -406,6 +408,7 @@ void unmap_hugepage_range(struct vm_area_struct *vma, ...@@ -406,6 +408,7 @@ void unmap_hugepage_range(struct vm_area_struct *vma,
put_page(page); put_page(page);
} }
put_cpu();
mm->rss -= (end - start) >> PAGE_SHIFT; mm->rss -= (end - start) >> PAGE_SHIFT;
} }
......
...@@ -764,6 +764,7 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long ea, ...@@ -764,6 +764,7 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long ea,
void *pgdir; void *pgdir;
pte_t *ptep; pte_t *ptep;
int local = 0; int local = 0;
int cpu;
cpumask_t tmp; cpumask_t tmp;
/* handle i-cache coherency */ /* handle i-cache coherency */
...@@ -794,12 +795,14 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long ea, ...@@ -794,12 +795,14 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long ea,
vsid = get_vsid(vma->vm_mm->context.id, ea); vsid = get_vsid(vma->vm_mm->context.id, ea);
tmp = cpumask_of_cpu(smp_processor_id()); cpu = get_cpu();
tmp = cpumask_of_cpu(cpu);
if (cpus_equal(vma->vm_mm->cpu_vm_mask, tmp)) if (cpus_equal(vma->vm_mm->cpu_vm_mask, tmp))
local = 1; local = 1;
__hash_page(ea, pte_val(pte) & (_PAGE_USER|_PAGE_RW), vsid, ptep, __hash_page(ea, pte_val(pte) & (_PAGE_USER|_PAGE_RW), vsid, ptep,
0x300, local); 0x300, local);
put_cpu();
} }
void * reserve_phb_iospace(unsigned long size) void * reserve_phb_iospace(unsigned long size)
......
...@@ -91,12 +91,15 @@ void hpte_update(pte_t *ptep, unsigned long pte, int wrprot) ...@@ -91,12 +91,15 @@ void hpte_update(pte_t *ptep, unsigned long pte, int wrprot)
void __flush_tlb_pending(struct ppc64_tlb_batch *batch) void __flush_tlb_pending(struct ppc64_tlb_batch *batch)
{ {
int i; int i;
cpumask_t tmp = cpumask_of_cpu(smp_processor_id()); int cpu;
cpumask_t tmp;
int local = 0; int local = 0;
BUG_ON(in_interrupt()); BUG_ON(in_interrupt());
cpu = get_cpu();
i = batch->index; i = batch->index;
tmp = cpumask_of_cpu(cpu);
if (cpus_equal(batch->mm->cpu_vm_mask, tmp)) if (cpus_equal(batch->mm->cpu_vm_mask, tmp))
local = 1; local = 1;
...@@ -106,6 +109,7 @@ void __flush_tlb_pending(struct ppc64_tlb_batch *batch) ...@@ -106,6 +109,7 @@ void __flush_tlb_pending(struct ppc64_tlb_batch *batch)
else else
flush_hash_range(batch->context, i, local); flush_hash_range(batch->context, i, local);
batch->index = 0; batch->index = 0;
put_cpu();
} }
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
......
...@@ -44,9 +44,6 @@ static int xmon_owner; ...@@ -44,9 +44,6 @@ static int xmon_owner;
static int xmon_gate; static int xmon_gate;
#endif /* CONFIG_SMP */ #endif /* CONFIG_SMP */
#define TRAP(regs) ((regs)->trap)
#define FULL_REGS(regs) 1
static unsigned long in_xmon = 0; static unsigned long in_xmon = 0;
static unsigned long adrs; static unsigned long adrs;
......
...@@ -82,9 +82,11 @@ typedef struct { ...@@ -82,9 +82,11 @@ typedef struct {
#ifdef CONFIG_PREEMPT #ifdef CONFIG_PREEMPT
# define in_atomic() ((preempt_count() & ~PREEMPT_ACTIVE) != kernel_locked()) # define in_atomic() ((preempt_count() & ~PREEMPT_ACTIVE) != kernel_locked())
# define preemptible() (preempt_count() == 0 && !irqs_disabled())
# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1) # define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
#else #else
# define in_atomic() (preempt_count() != 0) # define in_atomic() (preempt_count() != 0)
# define preemptible() 0
# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET # define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
#endif #endif
#define irq_exit() \ #define irq_exit() \
......
...@@ -136,23 +136,21 @@ struct paca_struct { ...@@ -136,23 +136,21 @@ struct paca_struct {
u8 rsvd6[0x500 - 0x8]; u8 rsvd6[0x500 - 0x8];
/*===================================================================================== /*=====================================================================================
* CACHE_LINE_31 0x0F00 - 0x0F7F Exception stack * CACHE_LINE_31-32 0x0F00 - 0x0FFF Exception register save areas
*===================================================================================== *=====================================================================================
*/ */
u8 exception_stack[N_EXC_STACK*EXC_FRAME_SIZE]; u64 exgen[8]; /* used for most interrupts/exceptions */
u64 exmc[8]; /* used for machine checks */
u64 exslb[8]; /* used for SLB/segment table misses
* on the linear mapping */
u64 exdsi[8]; /* used for linear mapping hash table misses */
/*===================================================================================== /*=====================================================================================
* CACHE_LINE_32 0x0F80 - 0x0FFF Reserved * Page 2 used as a stack when we detect a bad kernel stack pointer,
* and early in SMP boots before relocation is enabled.
*===================================================================================== *=====================================================================================
*/ */
u8 rsvd7[0x80]; /* Give the stack some rope ... */ u8 guard[0x1000];
/*=====================================================================================
* Page 2 Reserved for guard page. Also used as a stack early in SMP boots before
* relocation is enabled.
*=====================================================================================
*/
u8 guard[0x1000]; /* ... and then hang 'em */
}; };
#endif /* _PPC64_PACA_H */ #endif /* _PPC64_PACA_H */
...@@ -28,6 +28,9 @@ ...@@ -28,6 +28,9 @@
#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_8GPRS(14, base); SAVE_10GPRS(22, base)
#define REST_NVGPRS(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)
...@@ -54,11 +57,6 @@ ...@@ -54,11 +57,6 @@
#define REST_16VRS(n,b,base) REST_8VRS(n,b,base); REST_8VRS(n+8,b,base) #define REST_16VRS(n,b,base) REST_8VRS(n,b,base); REST_8VRS(n+8,b,base)
#define REST_32VRS(n,b,base) REST_16VRS(n,b,base); REST_16VRS(n+16,b,base) #define REST_32VRS(n,b,base) REST_16VRS(n,b,base); REST_16VRS(n+16,b,base)
#define CHECKANYINT(ra,rb) \
mfspr rb,SPRG3; /* Get Paca address */\
ld ra,PACALPPACA+LPPACAANYINT(rb); /* Get pending interrupt flags */\
cmpldi 0,ra,0;
/* Macros to adjust thread priority for Iseries hardware multithreading */ /* Macros to adjust thread priority for Iseries hardware multithreading */
#define HMT_LOW or 1,1,1 #define HMT_LOW or 1,1,1
#define HMT_MEDIUM or 2,2,2 #define HMT_MEDIUM or 2,2,2
......
...@@ -543,8 +543,7 @@ struct thread_struct { ...@@ -543,8 +543,7 @@ struct thread_struct {
double fpr[32]; /* Complete floating point set */ double fpr[32]; /* Complete floating point set */
unsigned long fpscr; /* Floating point status (plus pad) */ unsigned long fpscr; /* Floating point status (plus pad) */
unsigned long fpexc_mode; /* Floating-point exception mode */ unsigned long fpexc_mode; /* Floating-point exception mode */
unsigned long saved_msr; /* Save MSR across signal handlers */ unsigned long pad[3]; /* was saved_msr, saved_softe */
unsigned long saved_softe; /* Ditto for Soft Enable/Disable */
#ifdef CONFIG_ALTIVEC #ifdef CONFIG_ALTIVEC
/* Complete AltiVec register set */ /* Complete AltiVec register set */
vector128 vr[32] __attribute((aligned(16))); vector128 vr[32] __attribute((aligned(16)));
......
...@@ -71,6 +71,18 @@ struct pt_regs32 { ...@@ -71,6 +71,18 @@ struct pt_regs32 {
#define instruction_pointer(regs) ((regs)->nip) #define instruction_pointer(regs) ((regs)->nip)
#define user_mode(regs) ((((regs)->msr) >> MSR_PR_LG) & 0x1) #define user_mode(regs) ((((regs)->msr) >> MSR_PR_LG) & 0x1)
#define force_successful_syscall_return() \
(current_thread_info()->syscall_noerror = 1)
/*
* 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.
*/
#define FULL_REGS(regs) (((regs)->trap & 1) == 0)
#define TRAP(regs) ((regs)->trap & ~0xF)
#define CHECK_FULL_REGS(regs) BUG_ON(regs->trap & 1)
/* /*
* Offsets used by 'ptrace' system call interface. * Offsets used by 'ptrace' system call interface.
*/ */
......
...@@ -111,6 +111,8 @@ extern void flush_instruction_cache(void); ...@@ -111,6 +111,8 @@ extern void flush_instruction_cache(void);
extern int _get_PVR(void); extern int _get_PVR(void);
extern void giveup_fpu(struct task_struct *); extern void giveup_fpu(struct task_struct *);
extern void disable_kernel_fp(void); extern void disable_kernel_fp(void);
extern void flush_fp_to_thread(struct task_struct *);
extern void flush_altivec_to_thread(struct task_struct *);
extern void enable_kernel_fp(void); extern void enable_kernel_fp(void);
extern void giveup_altivec(struct task_struct *); extern void giveup_altivec(struct task_struct *);
extern void disable_kernel_altivec(void); extern void disable_kernel_altivec(void);
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
#include <linux/config.h> #include <linux/config.h>
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/page.h>
#include <linux/stringify.h> #include <linux/stringify.h>
/* /*
...@@ -23,8 +24,10 @@ struct thread_info { ...@@ -23,8 +24,10 @@ struct thread_info {
struct exec_domain *exec_domain; /* execution domain */ struct exec_domain *exec_domain; /* execution domain */
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;
struct restart_block restart_block; struct restart_block restart_block;
/* set by force_successful_syscall_return */
unsigned char syscall_noerror;
}; };
/* /*
...@@ -73,7 +76,7 @@ struct thread_info { ...@@ -73,7 +76,7 @@ struct thread_info {
static inline struct thread_info *current_thread_info(void) static inline struct thread_info *current_thread_info(void)
{ {
struct thread_info *ti; struct thread_info *ti;
__asm__("clrrdi %0,1,14" : "=r"(ti)); __asm__("clrrdi %0,1,%1" : "=r"(ti) : "i" (THREAD_SHIFT));
return ti; return ti;
} }
......
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