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
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 \
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_SMP) += smp.o
......
......@@ -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 */
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;
/* start process with ar4 pointing to the correct address space */
p->thread.ar4 = get_fs().ar4;
......@@ -262,20 +267,13 @@ asmlinkage int sys_execve(struct pt_regs regs)
error = PTR_ERR(filename);
if (IS_ERR(filename))
goto out;
error = do_execve(filename, (char **) regs.gprs[3], (char **) regs.gprs[4], &regs);
if (error == 0)
{
error = do_execve(filename, (char **) regs.gprs[3],
(char **) regs.gprs[4], &regs);
if (error == 0) {
current->ptrace &= ~PT_DTRACE;
current->thread.fp_regs.fpc=0;
if(MACHINE_HAS_IEEE)
{
__asm__ __volatile__
("sr 0,0\n\t"
"sfpc 0,0\n\t"
:
:
:"0");
}
current->thread.fp_regs.fpc = 0;
if (MACHINE_HAS_IEEE)
asm volatile("sfpc %0,%0" : : "d" (0));
}
putname(filename);
out:
......@@ -288,7 +286,12 @@ asmlinkage int sys_execve(struct pt_regs regs)
*/
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;
}
......
/*
* 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
struct ucontext uc;
} 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.
*/
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;
......@@ -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)
{
int err;
s390_fp_regs fpregs;
err = __copy_to_user(&sregs->regs,regs,sizeof(_s390_regs_common));
if(!err)
{
save_fp_regs(&fpregs);
err=__copy_to_user(&sregs->fpregs,&fpregs,sizeof(fpregs));
}
return(err);
err = __copy_to_user(&sregs->regs, regs, sizeof(_s390_regs_common));
if (err != 0)
return err;
/*
* We have to store the fp registers to current->thread.fp_regs
* to merge them with the emulated registers.
*/
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 */
static int restore_sigregs(struct pt_regs *regs,_sigregs *sregs)
{
int err;
s390_fp_regs fpregs;
psw_t saved_psw=regs->psw;
err=__copy_from_user(regs,&sregs->regs,sizeof(_s390_regs_common));
if(!err)
{
regs->trap = -1; /* disable syscall checks */
regs->psw.mask=(saved_psw.mask&~PSW_MASK_DEBUGCHANGE)|
(regs->psw.mask&PSW_MASK_DEBUGCHANGE);
regs->psw.addr=(saved_psw.addr&~PSW_ADDR_DEBUGCHANGE)|
(regs->psw.addr&PSW_ADDR_DEBUGCHANGE);
err=__copy_from_user(&fpregs,&sregs->fpregs,sizeof(fpregs));
if(!err)
restore_fp_regs(&fpregs);
}
return(err);
err = __copy_from_user(regs, &sregs->regs, sizeof(_s390_regs_common));
regs->psw.mask = _USER_PSW_MASK | (regs->psw.mask & PSW_MASK_DEBUGCHANGE);
regs->psw.addr |= _ADDR_31;
if (err)
return err;
err = __copy_from_user(&current->thread.fp_regs, &sregs->fpregs,
sizeof(s390_fp_regs));
current->thread.fp_regs.fpc &= FPC_VALID_MASK;
if (err)
return err;
restore_fp_regs(&current->thread.fp_regs);
regs->trap = -1; /* disable syscall checks */
return 0;
}
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 \
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 \
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_SMP) += smp.o
......
......@@ -257,15 +257,12 @@ asmlinkage int sys_execve(struct pt_regs regs)
error = PTR_ERR(filename);
if (IS_ERR(filename))
goto out;
error = do_execve(filename, (char **) regs.gprs[3], (char **) regs.gprs[4], &regs);
if (error == 0)
{
error = do_execve(filename, (char **) regs.gprs[3],
(char **) regs.gprs[4], &regs);
if (error == 0) {
current->ptrace &= ~PT_DTRACE;
current->thread.fp_regs.fpc=0;
__asm__ __volatile__
("sr 0,0\n\t"
"sfpc 0,0\n\t"
: : :"0");
current->thread.fp_regs.fpc = 0;
asm volatile("sfpc %0,%0" : : "d" (0));
}
putname(filename);
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)
/* 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;
s390_fp_regs fpregs;
err = __copy_to_user(&sregs->regs,regs,sizeof(_s390_regs_common));
if(!err)
{
save_fp_regs(&fpregs);
err=__copy_to_user(&sregs->fpregs,&fpregs,sizeof(fpregs));
}
return(err);
err = __copy_to_user(&sregs->regs, regs, sizeof(_s390_regs_common));
if (err != 0)
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 */
static int restore_sigregs(struct pt_regs *regs,_sigregs *sregs)
static int restore_sigregs(struct pt_regs *regs, _sigregs *sregs)
{
int err;
s390_fp_regs fpregs;
psw_t saved_psw=regs->psw;
err=__copy_from_user(regs,&sregs->regs,sizeof(_s390_regs_common));
if(!err)
{
regs->trap = -1; /* disable syscall checks */
regs->psw.mask=(saved_psw.mask&~PSW_MASK_DEBUGCHANGE)|
(regs->psw.mask&PSW_MASK_DEBUGCHANGE);
regs->psw.addr=(saved_psw.addr&~PSW_ADDR_DEBUGCHANGE)|
(regs->psw.addr&PSW_ADDR_DEBUGCHANGE);
err=__copy_from_user(&fpregs,&sregs->fpregs,sizeof(fpregs));
if(!err)
restore_fp_regs(&fpregs);
}
return(err);
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)
return err;
err = __copy_from_user(&current->thread.fp_regs, &sregs->fpregs,
sizeof(s390_fp_regs));
current->thread.fp_regs.fpc &= FPC_VALID_MASK;
if (err)
return err;
restore_fp_regs(&current->thread.fp_regs);
regs->trap = -1; /* disable syscall checks */
return 0;
}
asmlinkage long sys_sigreturn(struct pt_regs *regs)
......
......@@ -32,7 +32,11 @@
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
#define _ADDR_31 0x80000000
#define _USER_PSW_MASK_EMU32 0x070DC000
#define _USER_PSW_MASK32 0x0705C00080000000
#define PSW_MASK_DEBUGCHANGE32 0x00003000UL
#define PSW_ADDR_DEBUGCHANGE32 0x7FFFFFFFUL
typedef struct
{
......@@ -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)
{
int err = 0;
s390_fp_regs fpregs;
int i;
for(i=0; i<NUM_GPRS; i++)
err |= __put_user(regs->gprs[i], &sregs->regs.gprs[i]);
for(i=0; i<NUM_ACRS; i++)
err |= __put_user(regs->acrs[i], &sregs->regs.acrs[i]);
err |= __copy_to_user(&sregs->regs.psw.mask, &regs->psw.mask, 4);
err |= __copy_to_user(&sregs->regs.psw.addr, ((char*)&regs->psw.addr)+4, 4);
if(!err)
{
save_fp_regs(&fpregs);
__put_user(fpregs.fpc, &sregs->fpregs.fpc);
for(i=0; i<NUM_FPRS; i++)
err |= __put_user(fpregs.fprs[i].d, &sregs->fpregs.fprs[i].d);
}
return(err);
_s390_regs_common32 regs32;
int err, i;
regs32.psw.mask = _USER_PSW_MASK_EMU32 |
(__u32)((regs->psw.mask & PSW_MASK_DEBUGCHANGE) >> 32);
regs32.psw.addr = _ADDR_31 | (__u32) regs->psw.addr;
for (i = 0; i < NUM_GPRS; i++)
regs32.gprs[i] = (__u32) regs->gprs[i];
memcpy(regs32.acrs, regs->acrs, sizeof(regs32.acrs));
err = __copy_to_user(&sregs->regs, &regs32, sizeof(regs32));
if (err)
return err;
save_fp_regs(&current->thread.fp_regs);
/* s390_fp_regs and _s390_fp_regs32 are the same ! */
return __copy_to_user(&sregs->fpregs, &current->thread.fp_regs,
sizeof(_s390_fp_regs32));
}
static int restore_sigregs32(struct pt_regs *regs,_sigregs32 *sregs)
{
int err = 0;
s390_fp_regs fpregs;
psw_t saved_psw=regs->psw;
int i;
for(i=0; i<NUM_GPRS; i++)
err |= __get_user(regs->gprs[i], &sregs->regs.gprs[i]);
for(i=0; i<NUM_ACRS; i++)
err |= __get_user(regs->acrs[i], &sregs->regs.acrs[i]);
err |= __copy_from_user(&regs->psw.mask, &sregs->regs.psw.mask, 4);
err |= __copy_from_user(((char*)&regs->psw.addr)+4, &sregs->regs.psw.addr, 4);
if(!err)
{
regs->trap = -1; /* disable syscall checks */
regs->psw.mask=(saved_psw.mask&~PSW_MASK_DEBUGCHANGE)|
(regs->psw.mask&PSW_MASK_DEBUGCHANGE);
regs->psw.addr=(saved_psw.addr&~PSW_ADDR_DEBUGCHANGE)|
(regs->psw.addr&PSW_ADDR_DEBUGCHANGE);
__get_user(fpregs.fpc, &sregs->fpregs.fpc);
for(i=0; i<NUM_FPRS; i++)
err |= __get_user(fpregs.fprs[i].d, &sregs->fpregs.fprs[i].d);
if(!err)
restore_fp_regs(&fpregs);
}
return(err);
_s390_regs_common32 regs32;
int err, i;
err = __copy_from_user(&regs32, &sregs->regs, sizeof(regs32));
if (err)
return err;
regs->psw.mask = _USER_PSW_MASK32 |
(__u64)(regs32.psw.mask & PSW_MASK_DEBUGCHANGE32) << 32;
regs->psw.addr = (__u64)(regs32.psw.addr & PSW_ADDR_DEBUGCHANGE32);
for (i = 0; i < NUM_GPRS; i++)
regs->gprs[i] = (__u64) regs32.gprs[i];
memcpy(regs->acrs, regs32.acrs, sizeof(regs32.acrs));
err = __copy_from_user(&current->thread.fp_regs, &sregs->fpregs,
sizeof(_s390_fp_regs32));
current->thread.fp_regs.fpc &= FPC_VALID_MASK;
if (err)
return err;
restore_fp_regs(&current->thread.fp_regs);
regs->trap = -1; /* disable syscall checks */
return 0;
}
asmlinkage long sys32_sigreturn(struct pt_regs *regs)
......
......@@ -12,22 +12,79 @@
#define __ASM_SYSTEM_H
#include <linux/config.h>
#include <linux/kernel.h>
#include <asm/types.h>
#include <asm/ptrace.h>
#include <asm/setup.h>
#ifdef __KERNEL__
#include <asm/lowcore.h>
#endif
#include <linux/kernel.h>
struct task_struct;
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 { \
if (prev == next) \
break; \
save_fp_regs1(&prev->thread.fp_regs); \
restore_fp_regs1(&next->thread.fp_regs); \
save_fp_regs(&prev->thread.fp_regs); \
restore_fp_regs(&next->thread.fp_regs); \
resume(prev,next); \
} while (0)
struct task_struct;
#define nop() __asm__ __volatile__ ("nop")
#define xchg(ptr,x) \
......@@ -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_clear_bit(cr, bit) __ctl_clear_bit(cr, bit)
#endif
#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);
#endif /* CONFIG_SMP */
extern void (*_machine_restart)(char *command);
extern void (*_machine_halt)(void);
extern void (*_machine_power_off)(void);
#endif
#endif /* __KERNEL__ */
#endif
......@@ -12,11 +12,62 @@
#define __ASM_SYSTEM_H
#include <linux/config.h>
#include <linux/kernel.h>
#include <asm/types.h>
#include <asm/ptrace.h>
#include <asm/setup.h>
#ifdef __KERNEL__
#include <asm/lowcore.h>
#endif
#include <linux/kernel.h>
struct task_struct;
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 { \
if (prev == next) \
......@@ -26,8 +77,6 @@
resume(prev,next); \
} while (0)
struct task_struct;
#define nop() __asm__ __volatile__ ("nop")
#define xchg(ptr,x) \
......@@ -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_clear_bit(cr, bit) __ctl_clear_bit(cr, bit)
#endif
#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);
#endif /* CONFIG_SMP */
extern void (*_machine_restart)(char *command);
extern void (*_machine_halt)(void);
extern void (*_machine_power_off)(void);
#endif
#endif /* __KERNEL __ */
#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