git://git.onelab.eu
/
linux-2.6.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
VServer 1.9.2 (patch-2.6.8.1-vs1.9.2.diff)
[linux-2.6.git]
/
arch
/
ppc64
/
kernel
/
align.c
diff --git
a/arch/ppc64/kernel/align.c
b/arch/ppc64/kernel/align.c
index
dc45583
..
853b3ae
100644
(file)
--- a/
arch/ppc64/kernel/align.c
+++ b/
arch/ppc64/kernel/align.c
@@
-22,8
+22,6
@@
#include <asm/cache.h>
#include <asm/cputable.h>
#include <asm/cache.h>
#include <asm/cputable.h>
-void disable_kernel_fp(void); /* asm function from head.S */
-
struct aligninfo {
unsigned char len;
unsigned char flags;
struct aligninfo {
unsigned char len;
unsigned char flags;
@@
-215,8
+213,9
@@
fix_alignment(struct pt_regs *regs)
unsigned long i;
int ret;
unsigned dsisr;
unsigned long i;
int ret;
unsigned dsisr;
- unsigned char *addr, *p;
- unsigned long *lp;
+ unsigned char __user *addr;
+ unsigned char __user *p;
+ unsigned long __user *lp;
union {
long ll;
double dd;
union {
long ll;
double dd;
@@
-241,9
+240,9
@@
fix_alignment(struct pt_regs *regs)
if (cur_cpu_spec->cpu_features & CPU_FTR_NODSISRALIGN) {
unsigned int real_instr;
if (cur_cpu_spec->cpu_features & CPU_FTR_NODSISRALIGN) {
unsigned int real_instr;
- if (__get_user(real_instr, (unsigned int *)regs->nip))
+ if (__get_user(real_instr, (unsigned int
__user
*)regs->nip))
return 0;
return 0;
- dsisr = make_dsisr(
*((unsigned *)regs->nip)
);
+ dsisr = make_dsisr(
real_instr
);
}
/* extract the operation and registers from the dsisr */
}
/* extract the operation and registers from the dsisr */
@@
-257,7
+256,7
@@
fix_alignment(struct pt_regs *regs)
flags = aligninfo[instr].flags;
/* DAR has the operand effective address */
flags = aligninfo[instr].flags;
/* DAR has the operand effective address */
- addr = (unsigned char *)regs->dar;
+ addr = (unsigned char
__user
*)regs->dar;
/* A size of 0 indicates an instruction we don't support */
/* we also don't support the multiples (lmw, stmw, lmd, stmd) */
/* A size of 0 indicates an instruction we don't support */
/* we also don't support the multiples (lmw, stmw, lmd, stmd) */
@@
-270,7
+269,7
@@
fix_alignment(struct pt_regs *regs)
* storage
*/
if (instr == DCBZ)
* storage
*/
if (instr == DCBZ)
- addr = (unsigned char *) ((unsigned long)addr & -L1_CACHE_BYTES);
+ addr = (unsigned char
__user
*) ((unsigned long)addr & -L1_CACHE_BYTES);
/* Verify the address of the operand */
if (user_mode(regs)) {
/* Verify the address of the operand */
if (user_mode(regs)) {
@@
-279,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))
- giveup_fpu(current);
+ if (flags & F) {
+ if (!user_mode(regs))
+ return 0;
+ flush_fp_to_thread(current);
+ }
/* If we are loading, get the data from user space */
if (flags & LD) {
/* If we are loading, get the data from user space */
if (flags & LD) {
@@
-309,9
+311,11
@@
fix_alignment(struct pt_regs *regs)
if (flags & F) {
if (nb == 4) {
/* Doing stfs, have to convert to single */
if (flags & F) {
if (nb == 4) {
/* Doing stfs, have to convert to single */
+ preempt_disable();
enable_kernel_fp();
cvt_df(¤t->thread.fpr[reg], (float *)&data.v[4], ¤t->thread.fpscr);
disable_kernel_fp();
enable_kernel_fp();
cvt_df(¤t->thread.fpr[reg], (float *)&data.v[4], ¤t->thread.fpscr);
disable_kernel_fp();
+ preempt_enable();
}
else
data.dd = current->thread.fpr[reg];
}
else
data.dd = current->thread.fpr[reg];
@@
-343,9
+347,11
@@
fix_alignment(struct pt_regs *regs)
if (flags & F) {
if (nb == 4) {
/* Doing lfs, have to convert to double */
if (flags & F) {
if (nb == 4) {
/* Doing lfs, have to convert to double */
+ preempt_disable();
enable_kernel_fp();
cvt_fd((float *)&data.v[4], ¤t->thread.fpr[reg], ¤t->thread.fpscr);
disable_kernel_fp();
enable_kernel_fp();
cvt_fd((float *)&data.v[4], ¤t->thread.fpr[reg], ¤t->thread.fpscr);
disable_kernel_fp();
+ preempt_enable();
}
else
current->thread.fpr[reg] = data.dd;
}
else
current->thread.fpr[reg] = data.dd;
@@
-360,7
+366,7
@@
fix_alignment(struct pt_regs *regs)
p = addr;
switch (nb) {
case 128: /* Special case - must be dcbz */
p = addr;
switch (nb) {
case 128: /* Special case - must be dcbz */
- lp = (unsigned long *)p;
+ lp = (unsigned long
__user
*)p;
for (i = 0; i < L1_CACHE_BYTES / sizeof(long); ++i)
ret |= __put_user(0, lp++);
break;
for (i = 0; i < L1_CACHE_BYTES / sizeof(long); ++i)
ret |= __put_user(0, lp++);
break;