Commit 91b9f2e4 authored by Martin Schwidefsky's avatar Martin Schwidefsky Committed by Linus Torvalds

[PATCH] s390 update (18/27): fpu registers.

Cleanup load/store of fpu register on s390.
parent fbd32c90
...@@ -8,7 +8,7 @@ EXTRA_AFLAGS := -traditional ...@@ -8,7 +8,7 @@ EXTRA_AFLAGS := -traditional
export-objs := debug.o ebcdic.o s390_ext.o smp.o s390_ksyms.o export-objs := debug.o ebcdic.o s390_ext.o smp.o s390_ksyms.o
obj-y := entry.o bitmap.o traps.o time.o process.o \ obj-y := entry.o bitmap.o traps.o time.o process.o \
setup.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \ setup.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \
semaphore.o s390fpu.o reipl.o s390_ext.o debug.o semaphore.o reipl.o s390_ext.o debug.o
obj-$(CONFIG_MODULES) += s390_ksyms.o obj-$(CONFIG_MODULES) += s390_ksyms.o
obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_SMP) += smp.o
......
...@@ -199,8 +199,13 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long new_stackp, ...@@ -199,8 +199,13 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long new_stackp,
/* fake return stack for resume(), don't go back to schedule */ /* fake return stack for resume(), don't go back to schedule */
frame->gprs[9] = (unsigned long) frame; frame->gprs[9] = (unsigned long) frame;
/* save fprs, if used in last task */ /*
save_fp_regs(&p->thread.fp_regs); * save fprs to current->thread.fp_regs to merge them with
* the emulated registers and then copy the result to the child.
*/
save_fp_regs(&current->thread.fp_regs);
memcpy(&p->thread.fp_regs, &current->thread.fp_regs,
sizeof(s390_fp_regs));
p->thread.user_seg = __pa((unsigned long) p->mm->pgd) | _SEGMENT_TABLE; p->thread.user_seg = __pa((unsigned long) p->mm->pgd) | _SEGMENT_TABLE;
/* start process with ar4 pointing to the correct address space */ /* start process with ar4 pointing to the correct address space */
p->thread.ar4 = get_fs().ar4; p->thread.ar4 = get_fs().ar4;
...@@ -262,20 +267,13 @@ asmlinkage int sys_execve(struct pt_regs regs) ...@@ -262,20 +267,13 @@ asmlinkage int sys_execve(struct pt_regs regs)
error = PTR_ERR(filename); error = PTR_ERR(filename);
if (IS_ERR(filename)) if (IS_ERR(filename))
goto out; goto out;
error = do_execve(filename, (char **) regs.gprs[3], (char **) regs.gprs[4], &regs); error = do_execve(filename, (char **) regs.gprs[3],
if (error == 0) (char **) regs.gprs[4], &regs);
{ if (error == 0) {
current->ptrace &= ~PT_DTRACE; current->ptrace &= ~PT_DTRACE;
current->thread.fp_regs.fpc=0; current->thread.fp_regs.fpc = 0;
if(MACHINE_HAS_IEEE) if (MACHINE_HAS_IEEE)
{ asm volatile("sfpc %0,%0" : : "d" (0));
__asm__ __volatile__
("sr 0,0\n\t"
"sfpc 0,0\n\t"
:
:
:"0");
}
} }
putname(filename); putname(filename);
out: out:
...@@ -288,7 +286,12 @@ asmlinkage int sys_execve(struct pt_regs regs) ...@@ -288,7 +286,12 @@ asmlinkage int sys_execve(struct pt_regs regs)
*/ */
int dump_fpu (struct pt_regs * regs, s390_fp_regs *fpregs) int dump_fpu (struct pt_regs * regs, s390_fp_regs *fpregs)
{ {
save_fp_regs(fpregs); /*
* save fprs to current->thread.fp_regs to merge them with
* the emulated registers and then copy the result to the dump.
*/
save_fp_regs(&current->thread.fp_regs);
memcpy(fpregs, &current->thread.fp_regs, sizeof(s390_fp_regs));
return 1; return 1;
} }
......
/*
* arch/s390/kernel/s390fpu.c
*
* S390 version
* Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
* Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
*
* s390fpu.h functions for saving & restoring the fpu state.
*
* I couldn't inline these as linux/sched.h included half the world
* & was required to at the task structure.
* & the functions were too complex to make macros from.
* ( & as usual I didn't feel like debugging inline code ).
*/
#include <linux/config.h>
#include <linux/sched.h>
int save_fp_regs1(s390_fp_regs *fpregs)
{
int has_ieee=MACHINE_HAS_IEEE;
/*
I don't think we can use STE here as this would load
fp registers 0 & 2 into memory locations 0 & 1 etc.
*/
asm volatile ("STD 0,8(%0)\n\t"
"STD 2,24(%0)\n\t"
"STD 4,40(%0)\n\t"
"STD 6,56(%0)"
:
: "a" (fpregs)
: "memory"
);
if(has_ieee)
{
asm volatile ("STFPC 0(%0)\n\t"
"STD 1,16(%0)\n\t"
"STD 3,32(%0)\n\t"
"STD 5,48(%0)\n\t"
"STD 7,64(%0)\n\t"
"STD 8,72(%0)\n\t"
"STD 9,80(%0)\n\t"
"STD 10,88(%0)\n\t"
"STD 11,96(%0)\n\t"
"STD 12,104(%0)\n\t"
"STD 13,112(%0)\n\t"
"STD 14,120(%0)\n\t"
"STD 15,128(%0)\n\t"
:
: "a" (fpregs)
: "memory"
);
}
return(has_ieee);
}
void save_fp_regs(s390_fp_regs *fpregs)
{
#if CONFIG_MATHEMU
s390_fp_regs *currentfprs;
if(!save_fp_regs1(fpregs))
{
currentfprs=&current->thread.fp_regs;
fpregs->fpc=currentfprs->fpc;
fpregs->fprs[1].d=currentfprs->fprs[1].d;
fpregs->fprs[3].d=currentfprs->fprs[3].d;
fpregs->fprs[5].d=currentfprs->fprs[5].d;
fpregs->fprs[7].d=currentfprs->fprs[7].d;
memcpy(&fpregs->fprs[8].d,&currentfprs->fprs[8].d,sizeof(freg_t)*8);
}
#else
save_fp_regs1(fpregs);
#endif
}
int restore_fp_regs1(s390_fp_regs *fpregs)
{
int has_ieee=MACHINE_HAS_IEEE;
/* If we don't mask with the FPC_VALID_MASK here
* we've got a very quick shutdown -h now command
* via a kernel specification exception.
*/
fpregs->fpc&=FPC_VALID_MASK;
asm volatile ("LD 0,8(%0)\n\t"
"LD 2,24(%0)\n\t"
"LD 4,40(%0)\n\t"
"LD 6,56(%0)"
:
: "a" (fpregs)
: "memory"
);
if(has_ieee)
{
asm volatile ("LFPC 0(%0)\n\t"
"LD 1,16(%0)\n\t"
"LD 3,32(%0)\n\t"
"LD 5,48(%0)\n\t"
"LD 7,64(%0)\n\t"
"LD 8,72(%0)\n\t"
"LD 9,80(%0)\n\t"
"LD 10,88(%0)\n\t"
"LD 11,96(%0)\n\t"
"LD 12,104(%0)\n\t"
"LD 13,112(%0)\n\t"
"LD 14,120(%0)\n\t"
"LD 15,128(%0)\n\t"
:
: "a" (fpregs)
: "memory"
);
}
return(has_ieee);
}
void restore_fp_regs(s390_fp_regs *fpregs)
{
#if CONFIG_MATHEMU
s390_fp_regs *currentfprs;
if(!restore_fp_regs1(fpregs))
{
currentfprs=&current->thread.fp_regs;
currentfprs->fpc=fpregs->fpc;
currentfprs->fprs[1].d=fpregs->fprs[1].d;
currentfprs->fprs[3].d=fpregs->fprs[3].d;
currentfprs->fprs[5].d=fpregs->fprs[5].d;
currentfprs->fprs[7].d=fpregs->fprs[7].d;
memcpy(&currentfprs->fprs[8].d,&fpregs->fprs[8].d,sizeof(freg_t)*8);
}
#else
restore_fp_regs1(fpregs);
#endif
}
...@@ -49,13 +49,14 @@ typedef struct ...@@ -49,13 +49,14 @@ typedef struct
struct ucontext uc; struct ucontext uc;
} rt_sigframe; } rt_sigframe;
asmlinkage int FASTCALL(do_signal(struct pt_regs *regs, sigset_t *oldset)); int do_signal(struct pt_regs *regs, sigset_t *oldset);
/* /*
* Atomically swap in the new signal mask, and wait for a signal. * Atomically swap in the new signal mask, and wait for a signal.
*/ */
asmlinkage int asmlinkage int
sys_sigsuspend(struct pt_regs * regs,int history0, int history1, old_sigset_t mask) sys_sigsuspend(struct pt_regs * regs, int history0, int history1,
old_sigset_t mask)
{ {
sigset_t saveset; sigset_t saveset;
...@@ -147,37 +148,39 @@ sys_sigaltstack(const stack_t *uss, stack_t *uoss, struct pt_regs *regs) ...@@ -147,37 +148,39 @@ sys_sigaltstack(const stack_t *uss, stack_t *uoss, struct pt_regs *regs)
static int save_sigregs(struct pt_regs *regs,_sigregs *sregs) static int save_sigregs(struct pt_regs *regs,_sigregs *sregs)
{ {
int err; int err;
s390_fp_regs fpregs;
err = __copy_to_user(&sregs->regs,regs,sizeof(_s390_regs_common)); err = __copy_to_user(&sregs->regs, regs, sizeof(_s390_regs_common));
if(!err) if (err != 0)
{ return err;
save_fp_regs(&fpregs); /*
err=__copy_to_user(&sregs->fpregs,&fpregs,sizeof(fpregs)); * We have to store the fp registers to current->thread.fp_regs
} * to merge them with the emulated registers.
return(err); */
save_fp_regs(&current->thread.fp_regs);
return __copy_to_user(&sregs->fpregs, &current->thread.fp_regs,
sizeof(s390_fp_regs));
} }
/* Returns positive number on error */ /* Returns positive number on error */
static int restore_sigregs(struct pt_regs *regs,_sigregs *sregs) static int restore_sigregs(struct pt_regs *regs,_sigregs *sregs)
{ {
int err; int err;
s390_fp_regs fpregs;
psw_t saved_psw=regs->psw; err = __copy_from_user(regs, &sregs->regs, sizeof(_s390_regs_common));
err=__copy_from_user(regs,&sregs->regs,sizeof(_s390_regs_common)); regs->psw.mask = _USER_PSW_MASK | (regs->psw.mask & PSW_MASK_DEBUGCHANGE);
if(!err) regs->psw.addr |= _ADDR_31;
{ if (err)
regs->trap = -1; /* disable syscall checks */ return err;
regs->psw.mask=(saved_psw.mask&~PSW_MASK_DEBUGCHANGE)|
(regs->psw.mask&PSW_MASK_DEBUGCHANGE); err = __copy_from_user(&current->thread.fp_regs, &sregs->fpregs,
regs->psw.addr=(saved_psw.addr&~PSW_ADDR_DEBUGCHANGE)| sizeof(s390_fp_regs));
(regs->psw.addr&PSW_ADDR_DEBUGCHANGE); current->thread.fp_regs.fpc &= FPC_VALID_MASK;
err=__copy_from_user(&fpregs,&sregs->fpregs,sizeof(fpregs)); if (err)
if(!err) return err;
restore_fp_regs(&fpregs);
} restore_fp_regs(&current->thread.fp_regs);
return(err); regs->trap = -1; /* disable syscall checks */
return 0;
} }
asmlinkage long sys_sigreturn(struct pt_regs *regs) asmlinkage long sys_sigreturn(struct pt_regs *regs)
......
...@@ -10,7 +10,7 @@ export-objs := debug.o ebcdic.o s390_ext.o smp.o s390_ksyms.o \ ...@@ -10,7 +10,7 @@ export-objs := debug.o ebcdic.o s390_ext.o smp.o s390_ksyms.o \
obj-y := entry.o bitmap.o traps.o time.o process.o \ obj-y := entry.o bitmap.o traps.o time.o process.o \
setup.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \ setup.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \
semaphore.o s390fpu.o reipl.o s390_ext.o debug.o semaphore.o reipl.o s390_ext.o debug.o
obj-$(CONFIG_MODULES) += s390_ksyms.o obj-$(CONFIG_MODULES) += s390_ksyms.o
obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_SMP) += smp.o
......
...@@ -257,15 +257,12 @@ asmlinkage int sys_execve(struct pt_regs regs) ...@@ -257,15 +257,12 @@ asmlinkage int sys_execve(struct pt_regs regs)
error = PTR_ERR(filename); error = PTR_ERR(filename);
if (IS_ERR(filename)) if (IS_ERR(filename))
goto out; goto out;
error = do_execve(filename, (char **) regs.gprs[3], (char **) regs.gprs[4], &regs); error = do_execve(filename, (char **) regs.gprs[3],
if (error == 0) (char **) regs.gprs[4], &regs);
{ if (error == 0) {
current->ptrace &= ~PT_DTRACE; current->ptrace &= ~PT_DTRACE;
current->thread.fp_regs.fpc=0; current->thread.fp_regs.fpc = 0;
__asm__ __volatile__ asm volatile("sfpc %0,%0" : : "d" (0));
("sr 0,0\n\t"
"sfpc 0,0\n\t"
: : :"0");
} }
putname(filename); putname(filename);
out: out:
......
/*
* arch/s390/kernel/s390fpu.c
*
* S390 version
* Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
* Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
*
* s390fpu.h functions for saving & restoring the fpu state.
*
* I couldn't inline these as linux/sched.h included half the world
* & was required to at the task structure.
* & the functions were too complex to make macros from.
* ( & as usual I didn't feel like debugging inline code ).
*/
#include <linux/sched.h>
void save_fp_regs(s390_fp_regs *fpregs)
{
/*
* I don't think we can use STE here as this would load
* fp registers 0 & 2 into memory locations 0 & 1 etc.
*/
asm volatile ("STFPC 0(%0)\n\t"
"STD 0,8(%0)\n\t"
"STD 1,16(%0)\n\t"
"STD 2,24(%0)\n\t"
"STD 3,32(%0)\n\t"
"STD 4,40(%0)\n\t"
"STD 5,48(%0)\n\t"
"STD 6,56(%0)\n\t"
"STD 7,64(%0)\n\t"
"STD 8,72(%0)\n\t"
"STD 9,80(%0)\n\t"
"STD 10,88(%0)\n\t"
"STD 11,96(%0)\n\t"
"STD 12,104(%0)\n\t"
"STD 13,112(%0)\n\t"
"STD 14,120(%0)\n\t"
"STD 15,128(%0)\n\t"
:
: "a" (fpregs)
: "memory"
);
}
void restore_fp_regs(s390_fp_regs *fpregs)
{
/* If we don't mask with the FPC_VALID_MASK here
* we've got a very quick shutdown -h now command
* via a kernel specification exception.
*/
fpregs->fpc&=FPC_VALID_MASK;
asm volatile ("LFPC 0(%0)\n\t"
"LD 0,8(%0)\n\t"
"LD 1,16(%0)\n\t"
"LD 2,24(%0)\n\t"
"LD 3,32(%0)\n\t"
"LD 4,40(%0)\n\t"
"LD 5,48(%0)\n\t"
"LD 6,56(%0)\n\t"
"LD 7,64(%0)\n\t"
"LD 8,72(%0)\n\t"
"LD 9,80(%0)\n\t"
"LD 10,88(%0)\n\t"
"LD 11,96(%0)\n\t"
"LD 12,104(%0)\n\t"
"LD 13,112(%0)\n\t"
"LD 14,120(%0)\n\t"
"LD 15,128(%0)\n\t"
:
: "a" (fpregs)
: "memory"
);
}
...@@ -144,40 +144,37 @@ sys_sigaltstack(const stack_t *uss, stack_t *uoss, struct pt_regs *regs) ...@@ -144,40 +144,37 @@ sys_sigaltstack(const stack_t *uss, stack_t *uoss, struct pt_regs *regs)
/* Returns non-zero on fault */ /* Returns non-zero on fault */
static int save_sigregs(struct pt_regs *regs,_sigregs *sregs) static int save_sigregs(struct pt_regs *regs, _sigregs *sregs)
{ {
int err; int err;
s390_fp_regs fpregs;
err = __copy_to_user(&sregs->regs,regs,sizeof(_s390_regs_common)); err = __copy_to_user(&sregs->regs, regs, sizeof(_s390_regs_common));
if(!err) if (err != 0)
{ return err;
save_fp_regs(&fpregs); save_fp_regs(&current->thread.fp_regs);
err=__copy_to_user(&sregs->fpregs,&fpregs,sizeof(fpregs)); return __copy_to_user(&sregs->fpregs, &current->thread.fp_regs,
} sizeof(s390_fp_regs));
return(err);
} }
/* Returns positive number on error */ /* Returns positive number on error */
static int restore_sigregs(struct pt_regs *regs,_sigregs *sregs) static int restore_sigregs(struct pt_regs *regs, _sigregs *sregs)
{ {
int err; int err;
s390_fp_regs fpregs;
psw_t saved_psw=regs->psw; err = __copy_from_user(regs, &sregs->regs, sizeof(_s390_regs_common));
err=__copy_from_user(regs,&sregs->regs,sizeof(_s390_regs_common)); regs->psw.mask = _USER_PSW_MASK | (regs->psw.mask & PSW_MASK_DEBUGCHANGE);
if(!err) if (err)
{ return err;
regs->trap = -1; /* disable syscall checks */
regs->psw.mask=(saved_psw.mask&~PSW_MASK_DEBUGCHANGE)| err = __copy_from_user(&current->thread.fp_regs, &sregs->fpregs,
(regs->psw.mask&PSW_MASK_DEBUGCHANGE); sizeof(s390_fp_regs));
regs->psw.addr=(saved_psw.addr&~PSW_ADDR_DEBUGCHANGE)| current->thread.fp_regs.fpc &= FPC_VALID_MASK;
(regs->psw.addr&PSW_ADDR_DEBUGCHANGE); if (err)
err=__copy_from_user(&fpregs,&sregs->fpregs,sizeof(fpregs)); return err;
if(!err)
restore_fp_regs(&fpregs); restore_fp_regs(&current->thread.fp_regs);
} regs->trap = -1; /* disable syscall checks */
return(err); return 0;
} }
asmlinkage long sys_sigreturn(struct pt_regs *regs) asmlinkage long sys_sigreturn(struct pt_regs *regs)
......
...@@ -32,7 +32,11 @@ ...@@ -32,7 +32,11 @@
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
#define _ADDR_31 0x80000000
#define _USER_PSW_MASK_EMU32 0x070DC000
#define _USER_PSW_MASK32 0x0705C00080000000 #define _USER_PSW_MASK32 0x0705C00080000000
#define PSW_MASK_DEBUGCHANGE32 0x00003000UL
#define PSW_ADDR_DEBUGCHANGE32 0x7FFFFFFFUL
typedef struct typedef struct
{ {
...@@ -290,55 +294,48 @@ sys32_sigaltstack(const stack_t32 *uss, stack_t32 *uoss, struct pt_regs *regs) ...@@ -290,55 +294,48 @@ sys32_sigaltstack(const stack_t32 *uss, stack_t32 *uoss, struct pt_regs *regs)
static int save_sigregs32(struct pt_regs *regs,_sigregs32 *sregs) static int save_sigregs32(struct pt_regs *regs,_sigregs32 *sregs)
{ {
int err = 0; _s390_regs_common32 regs32;
s390_fp_regs fpregs; int err, i;
int i;
regs32.psw.mask = _USER_PSW_MASK_EMU32 |
for(i=0; i<NUM_GPRS; i++) (__u32)((regs->psw.mask & PSW_MASK_DEBUGCHANGE) >> 32);
err |= __put_user(regs->gprs[i], &sregs->regs.gprs[i]); regs32.psw.addr = _ADDR_31 | (__u32) regs->psw.addr;
for(i=0; i<NUM_ACRS; i++) for (i = 0; i < NUM_GPRS; i++)
err |= __put_user(regs->acrs[i], &sregs->regs.acrs[i]); regs32.gprs[i] = (__u32) regs->gprs[i];
err |= __copy_to_user(&sregs->regs.psw.mask, &regs->psw.mask, 4); memcpy(regs32.acrs, regs->acrs, sizeof(regs32.acrs));
err |= __copy_to_user(&sregs->regs.psw.addr, ((char*)&regs->psw.addr)+4, 4); err = __copy_to_user(&sregs->regs, &regs32, sizeof(regs32));
if(!err) if (err)
{ return err;
save_fp_regs(&fpregs); save_fp_regs(&current->thread.fp_regs);
__put_user(fpregs.fpc, &sregs->fpregs.fpc); /* s390_fp_regs and _s390_fp_regs32 are the same ! */
for(i=0; i<NUM_FPRS; i++) return __copy_to_user(&sregs->fpregs, &current->thread.fp_regs,
err |= __put_user(fpregs.fprs[i].d, &sregs->fpregs.fprs[i].d); sizeof(_s390_fp_regs32));
}
return(err);
} }
static int restore_sigregs32(struct pt_regs *regs,_sigregs32 *sregs) static int restore_sigregs32(struct pt_regs *regs,_sigregs32 *sregs)
{ {
int err = 0; _s390_regs_common32 regs32;
s390_fp_regs fpregs; int err, i;
psw_t saved_psw=regs->psw;
int i; err = __copy_from_user(&regs32, &sregs->regs, sizeof(regs32));
if (err)
for(i=0; i<NUM_GPRS; i++) return err;
err |= __get_user(regs->gprs[i], &sregs->regs.gprs[i]); regs->psw.mask = _USER_PSW_MASK32 |
for(i=0; i<NUM_ACRS; i++) (__u64)(regs32.psw.mask & PSW_MASK_DEBUGCHANGE32) << 32;
err |= __get_user(regs->acrs[i], &sregs->regs.acrs[i]); regs->psw.addr = (__u64)(regs32.psw.addr & PSW_ADDR_DEBUGCHANGE32);
err |= __copy_from_user(&regs->psw.mask, &sregs->regs.psw.mask, 4); for (i = 0; i < NUM_GPRS; i++)
err |= __copy_from_user(((char*)&regs->psw.addr)+4, &sregs->regs.psw.addr, 4); regs->gprs[i] = (__u64) regs32.gprs[i];
memcpy(regs->acrs, regs32.acrs, sizeof(regs32.acrs));
if(!err)
{ err = __copy_from_user(&current->thread.fp_regs, &sregs->fpregs,
regs->trap = -1; /* disable syscall checks */ sizeof(_s390_fp_regs32));
regs->psw.mask=(saved_psw.mask&~PSW_MASK_DEBUGCHANGE)| current->thread.fp_regs.fpc &= FPC_VALID_MASK;
(regs->psw.mask&PSW_MASK_DEBUGCHANGE); if (err)
regs->psw.addr=(saved_psw.addr&~PSW_ADDR_DEBUGCHANGE)| return err;
(regs->psw.addr&PSW_ADDR_DEBUGCHANGE);
__get_user(fpregs.fpc, &sregs->fpregs.fpc); restore_fp_regs(&current->thread.fp_regs);
for(i=0; i<NUM_FPRS; i++) regs->trap = -1; /* disable syscall checks */
err |= __get_user(fpregs.fprs[i].d, &sregs->fpregs.fprs[i].d); return 0;
if(!err)
restore_fp_regs(&fpregs);
}
return(err);
} }
asmlinkage long sys32_sigreturn(struct pt_regs *regs) asmlinkage long sys32_sigreturn(struct pt_regs *regs)
......
...@@ -12,22 +12,79 @@ ...@@ -12,22 +12,79 @@
#define __ASM_SYSTEM_H #define __ASM_SYSTEM_H
#include <linux/config.h> #include <linux/config.h>
#include <linux/kernel.h>
#include <asm/types.h> #include <asm/types.h>
#include <asm/ptrace.h>
#include <asm/setup.h>
#ifdef __KERNEL__ #ifdef __KERNEL__
#include <asm/lowcore.h>
#endif struct task_struct;
#include <linux/kernel.h>
extern struct task_struct *resume(void *, void *);
static inline void save_fp_regs(s390_fp_regs *fpregs)
{
asm volatile (
" std 0,8(%0)\n"
" std 2,24(%0)\n"
" std 4,40(%0)\n"
" std 6,56(%0)"
: : "a" (fpregs) : "memory" );
if (!MACHINE_HAS_IEEE)
return;
asm volatile(
" stfpc 0(%0)\n"
" std 1,16(%0)\n"
" std 3,32(%0)\n"
" std 5,48(%0)\n"
" std 7,64(%0)\n"
" std 8,72(%0)\n"
" std 9,80(%0)\n"
" std 10,88(%0)\n"
" std 11,96(%0)\n"
" std 12,104(%0)\n"
" std 13,112(%0)\n"
" std 14,120(%0)\n"
" std 15,128(%0)\n"
: : "a" (fpregs) : "memory" );
}
static inline void restore_fp_regs(s390_fp_regs *fpregs)
{
asm volatile (
" ld 0,8(%0)\n"
" ld 2,24(%0)\n"
" ld 4,40(%0)\n"
" ld 6,56(%0)"
: : "a" (fpregs));
if (!MACHINE_HAS_IEEE)
return;
asm volatile(
" lfpc 0(%0)\n"
" ld 1,16(%0)\n"
" ld 3,32(%0)\n"
" ld 5,48(%0)\n"
" ld 7,64(%0)\n"
" ld 8,72(%0)\n"
" ld 9,80(%0)\n"
" ld 10,88(%0)\n"
" ld 11,96(%0)\n"
" ld 12,104(%0)\n"
" ld 13,112(%0)\n"
" ld 14,120(%0)\n"
" ld 15,128(%0)\n"
: : "a" (fpregs));
}
#define switch_to(prev,next,last) do { \ #define switch_to(prev,next,last) do { \
if (prev == next) \ if (prev == next) \
break; \ break; \
save_fp_regs1(&prev->thread.fp_regs); \ save_fp_regs(&prev->thread.fp_regs); \
restore_fp_regs1(&next->thread.fp_regs); \ restore_fp_regs(&next->thread.fp_regs); \
resume(prev,next); \ resume(prev,next); \
} while (0) } while (0)
struct task_struct;
#define nop() __asm__ __volatile__ ("nop") #define nop() __asm__ __volatile__ ("nop")
#define xchg(ptr,x) \ #define xchg(ptr,x) \
...@@ -281,23 +338,13 @@ extern void smp_ctl_clear_bit(int cr, int bit); ...@@ -281,23 +338,13 @@ extern void smp_ctl_clear_bit(int cr, int bit);
#define ctl_set_bit(cr, bit) __ctl_set_bit(cr, bit) #define ctl_set_bit(cr, bit) __ctl_set_bit(cr, bit)
#define ctl_clear_bit(cr, bit) __ctl_clear_bit(cr, bit) #define ctl_clear_bit(cr, bit) __ctl_clear_bit(cr, bit)
#endif #endif /* CONFIG_SMP */
#ifdef __KERNEL__
extern struct task_struct *resume(void *, void *);
extern int save_fp_regs1(s390_fp_regs *fpregs);
extern void save_fp_regs(s390_fp_regs *fpregs);
extern int restore_fp_regs1(s390_fp_regs *fpregs);
extern void restore_fp_regs(s390_fp_regs *fpregs);
extern void (*_machine_restart)(char *command); extern void (*_machine_restart)(char *command);
extern void (*_machine_halt)(void); extern void (*_machine_halt)(void);
extern void (*_machine_power_off)(void); extern void (*_machine_power_off)(void);
#endif #endif /* __KERNEL__ */
#endif #endif
...@@ -12,11 +12,62 @@ ...@@ -12,11 +12,62 @@
#define __ASM_SYSTEM_H #define __ASM_SYSTEM_H
#include <linux/config.h> #include <linux/config.h>
#include <linux/kernel.h>
#include <asm/types.h> #include <asm/types.h>
#include <asm/ptrace.h>
#include <asm/setup.h>
#ifdef __KERNEL__ #ifdef __KERNEL__
#include <asm/lowcore.h>
#endif struct task_struct;
#include <linux/kernel.h>
extern struct task_struct *resume(void *, void *);
static inline void save_fp_regs(s390_fp_regs *fpregs)
{
asm volatile (
" stfpc 0(%0)\n"
" std 0,8(%0)\n"
" std 1,16(%0)\n"
" std 2,24(%0)\n"
" std 3,32(%0)\n"
" std 4,40(%0)\n"
" std 5,48(%0)\n"
" std 6,56(%0)\n"
" std 7,64(%0)\n"
" std 8,72(%0)\n"
" std 9,80(%0)\n"
" std 10,88(%0)\n"
" std 11,96(%0)\n"
" std 12,104(%0)\n"
" std 13,112(%0)\n"
" std 14,120(%0)\n"
" std 15,128(%0)\n"
: : "a" (fpregs) : "memory" );
}
static inline void restore_fp_regs(s390_fp_regs *fpregs)
{
asm volatile (
" lfpc 0(%0)\n"
" ld 0,8(%0)\n"
" ld 1,16(%0)\n"
" ld 2,24(%0)\n"
" ld 3,32(%0)\n"
" ld 4,40(%0)\n"
" ld 5,48(%0)\n"
" ld 6,56(%0)\n"
" ld 7,64(%0)\n"
" ld 8,72(%0)\n"
" ld 9,80(%0)\n"
" ld 10,88(%0)\n"
" ld 11,96(%0)\n"
" ld 12,104(%0)\n"
" ld 13,112(%0)\n"
" ld 14,120(%0)\n"
" ld 15,128(%0)\n"
: : "a" (fpregs));
}
#define switch_to(prev,next,last) do { \ #define switch_to(prev,next,last) do { \
if (prev == next) \ if (prev == next) \
...@@ -26,8 +77,6 @@ ...@@ -26,8 +77,6 @@
resume(prev,next); \ resume(prev,next); \
} while (0) } while (0)
struct task_struct;
#define nop() __asm__ __volatile__ ("nop") #define nop() __asm__ __volatile__ ("nop")
#define xchg(ptr,x) \ #define xchg(ptr,x) \
...@@ -297,23 +346,13 @@ extern void smp_ctl_clear_bit(int cr, int bit); ...@@ -297,23 +346,13 @@ extern void smp_ctl_clear_bit(int cr, int bit);
#define ctl_set_bit(cr, bit) __ctl_set_bit(cr, bit) #define ctl_set_bit(cr, bit) __ctl_set_bit(cr, bit)
#define ctl_clear_bit(cr, bit) __ctl_clear_bit(cr, bit) #define ctl_clear_bit(cr, bit) __ctl_clear_bit(cr, bit)
#endif #endif /* CONFIG_SMP */
#ifdef __KERNEL__
extern struct task_struct *resume(void *, void *);
extern int save_fp_regs1(s390_fp_regs *fpregs);
extern void save_fp_regs(s390_fp_regs *fpregs);
extern int restore_fp_regs1(s390_fp_regs *fpregs);
extern void restore_fp_regs(s390_fp_regs *fpregs);
extern void (*_machine_restart)(char *command); extern void (*_machine_restart)(char *command);
extern void (*_machine_halt)(void); extern void (*_machine_halt)(void);
extern void (*_machine_power_off)(void); extern void (*_machine_power_off)(void);
#endif #endif /* __KERNEL __ */
#endif #endif
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