Commit 3a810fc8 authored by Linus Torvalds's avatar Linus Torvalds

Import 2.4.0-test2pre9

parent cca405a2
...@@ -18,7 +18,7 @@ export-objs := mca.o mtrr.o msr.o cpuid.o microcode.o i386_ksyms.o ...@@ -18,7 +18,7 @@ export-objs := mca.o mtrr.o msr.o cpuid.o microcode.o i386_ksyms.o
obj-y := process.o semaphore.o signal.o entry.o traps.o irq.o vm86.o \ obj-y := process.o semaphore.o signal.o entry.o traps.o irq.o vm86.o \
ptrace.o i8259.o ioport.o ldt.o setup.o time.o sys_i386.o \ ptrace.o i8259.o ioport.o ldt.o setup.o time.o sys_i386.o \
pci-dma.o i386_ksyms.o pci-dma.o i386_ksyms.o i387.o
ifdef CONFIG_PCI ifdef CONFIG_PCI
......
...@@ -323,6 +323,11 @@ ENTRY(coprocessor_error) ...@@ -323,6 +323,11 @@ ENTRY(coprocessor_error)
pushl $ SYMBOL_NAME(do_coprocessor_error) pushl $ SYMBOL_NAME(do_coprocessor_error)
jmp error_code jmp error_code
ENTRY(simd_coprocessor_error)
pushl $0
pushl $ SYMBOL_NAME(do_simd_coprocessor_error)
jmp error_code
ENTRY(device_not_available) ENTRY(device_not_available)
pushl $-1 # mark this as an int pushl $-1 # mark this as an int
SAVE_ALL SAVE_ALL
...@@ -414,11 +419,6 @@ ENTRY(spurious_interrupt_bug) ...@@ -414,11 +419,6 @@ ENTRY(spurious_interrupt_bug)
pushl $ SYMBOL_NAME(do_spurious_interrupt_bug) pushl $ SYMBOL_NAME(do_spurious_interrupt_bug)
jmp error_code jmp error_code
ENTRY(xmm_fault)
pushl $0
pushl $ SYMBOL_NAME(do_xmm_fault)
jmp error_code
.data .data
ENTRY(sys_call_table) ENTRY(sys_call_table)
.long SYMBOL_NAME(sys_ni_syscall) /* 0 - old "setup()" system call*/ .long SYMBOL_NAME(sys_ni_syscall) /* 0 - old "setup()" system call*/
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <asm/semaphore.h> #include <asm/semaphore.h>
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/i387.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/checksum.h> #include <asm/checksum.h>
#include <asm/io.h> #include <asm/io.h>
...@@ -24,7 +25,6 @@ ...@@ -24,7 +25,6 @@
#include <asm/desc.h> #include <asm/desc.h>
extern void dump_thread(struct pt_regs *, struct user *); extern void dump_thread(struct pt_regs *, struct user *);
extern int dump_fpu(elf_fpregset_t *);
extern spinlock_t rtc_lock; extern spinlock_t rtc_lock;
#if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE) #if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE)
...@@ -51,6 +51,7 @@ EXPORT_SYMBOL(MCA_bus); ...@@ -51,6 +51,7 @@ EXPORT_SYMBOL(MCA_bus);
EXPORT_SYMBOL(__verify_write); EXPORT_SYMBOL(__verify_write);
EXPORT_SYMBOL(dump_thread); EXPORT_SYMBOL(dump_thread);
EXPORT_SYMBOL(dump_fpu); EXPORT_SYMBOL(dump_fpu);
EXPORT_SYMBOL(dump_extended_fpu);
EXPORT_SYMBOL(__ioremap); EXPORT_SYMBOL(__ioremap);
EXPORT_SYMBOL(iounmap); EXPORT_SYMBOL(iounmap);
EXPORT_SYMBOL(__io_virt_debug); EXPORT_SYMBOL(__io_virt_debug);
......
This diff is collapsed.
...@@ -2,8 +2,9 @@ ...@@ -2,8 +2,9 @@
* linux/arch/i386/kernel/process.c * linux/arch/i386/kernel/process.c
* *
* Copyright (C) 1995 Linus Torvalds * Copyright (C) 1995 Linus Torvalds
* Pentium III code by Ingo Molnar with changes and support for *
* OS exception support by Goutham Rao * Pentium III FXSR, SSE support
* Gareth Hughes <gareth@valinux.com>, May 2000
*/ */
/* /*
...@@ -38,6 +39,7 @@ ...@@ -38,6 +39,7 @@
#include <asm/io.h> #include <asm/io.h>
#include <asm/ldt.h> #include <asm/ldt.h>
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/i387.h>
#include <asm/desc.h> #include <asm/desc.h>
#include <asm/mmu_context.h> #include <asm/mmu_context.h>
#ifdef CONFIG_MATH_EMULATION #ifdef CONFIG_MATH_EMULATION
...@@ -471,94 +473,6 @@ void copy_segments(struct task_struct *p, struct mm_struct *new_mm) ...@@ -471,94 +473,6 @@ void copy_segments(struct task_struct *p, struct mm_struct *new_mm)
return; return;
} }
#ifdef CONFIG_X86_FXSR
int i387_hard_to_user ( struct _fpstate * user,
struct i387_hard_struct * hard)
{
int i, err = 0;
short *tmp, *tmp2;
long *ltmp1, *ltmp2;
err |= put_user(hard->cwd, &user->cw);
err |= put_user(hard->swd, &user->sw);
err |= put_user(fputag_KNIto387(hard->twd), &user->tag);
err |= put_user(hard->fip, &user->ipoff);
err |= put_user(hard->fcs, &user->cssel);
err |= put_user(hard->fdp, &user->dataoff);
err |= put_user(hard->fds, &user->datasel);
err |= put_user(hard->mxcsr, &user->mxcsr);
tmp = (short *)&user->_st;
tmp2 = (short *)&hard->st_space;
/*
* Transform the two layouts:
* (we do not mix 32-bit access with 16-bit access because
* thats suboptimal on PPros)
*/
for (i = 0; i < 8; i++)
{
err |= put_user(*tmp2, tmp); tmp++; tmp2++;
err |= put_user(*tmp2, tmp); tmp++; tmp2++;
err |= put_user(*tmp2, tmp); tmp++; tmp2++;
err |= put_user(*tmp2, tmp); tmp++; tmp2++;
err |= put_user(*tmp2, tmp); tmp++; tmp2 += 3;
}
ltmp1 = (unsigned long *)&(user->_xmm[0]);
ltmp2 = (unsigned long *)&(hard->xmm_space[0]);
for(i = 0; i < 88; i++)
{
err |= put_user(*ltmp2, ltmp1);
ltmp1++; ltmp2++;
}
return err;
}
int i387_user_to_hard (struct i387_hard_struct * hard,
struct _fpstate * user)
{
int i, err = 0;
short *tmp, *tmp2;
long *ltmp1, *ltmp2;
err |= get_user(hard->cwd, &user->cw);
err |= get_user(hard->swd, &user->sw);
err |= get_user(hard->twd, &user->tag);
hard->twd = fputag_387toKNI(hard->twd);
err |= get_user(hard->fip, &user->ipoff);
err |= get_user(hard->fcs, &user->cssel);
err |= get_user(hard->fdp, &user->dataoff);
err |= get_user(hard->fds, &user->datasel);
err |= get_user(hard->mxcsr, &user->mxcsr);
tmp2 = (short *)&hard->st_space;
tmp = (short *)&user->_st;
for (i = 0; i < 8; i++)
{
err |= get_user(*tmp2, tmp); tmp++; tmp2++;
err |= get_user(*tmp2, tmp); tmp++; tmp2++;
err |= get_user(*tmp2, tmp); tmp++; tmp2++;
err |= get_user(*tmp2, tmp); tmp++; tmp2++;
err |= get_user(*tmp2, tmp); tmp++; tmp2 += 3;
}
ltmp1 = (unsigned long *)(&user->_xmm[0]);
ltmp2 = (unsigned long *)(&hard->xmm_space[0]);
for(i = 0; i < (88); i++)
{
err |= get_user(*ltmp2, ltmp1);
ltmp2++; ltmp1++;
}
return err;
}
#endif
/* /*
* Save a segment. * Save a segment.
*/ */
...@@ -589,23 +503,6 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long esp, ...@@ -589,23 +503,6 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long esp,
return 0; return 0;
} }
/*
* fill in the FPU structure for a core dump.
*/
int dump_fpu (struct pt_regs * regs, struct user_i387_struct* fpu)
{
int fpvalid;
struct task_struct *tsk = current;
fpvalid = tsk->used_math;
if (fpvalid) {
unlazy_fpu(tsk);
memcpy(fpu,&tsk->thread.i387.hard,sizeof(*fpu));
}
return fpvalid;
}
/* /*
* fill in the user structure for a core dump.. * fill in the user structure for a core dump..
*/ */
......
/* ptrace.c */ /* ptrace.c */
/* By Ross Biro 1/23/92 */ /* By Ross Biro 1/23/92 */
/* FXSAVE/FXRSTOR support by Ingo Molnar and modifications by Goutham Rao */ /*
/* edited by Linus Torvalds */ * Pentium III FXSR, SSE support
* Gareth Hughes <gareth@valinux.com>, May 2000
*/
#include <linux/config.h> /* for CONFIG_MATH_EMULATION */ #include <linux/config.h> /* for CONFIG_MATH_EMULATION */
#include <linux/kernel.h> #include <linux/kernel.h>
...@@ -17,6 +19,7 @@ ...@@ -17,6 +19,7 @@
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/i387.h>
#include <asm/debugreg.h> #include <asm/debugreg.h>
/* /*
...@@ -392,48 +395,62 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) ...@@ -392,48 +395,62 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
} }
case PTRACE_GETFPREGS: { /* Get the child FPU state. */ case PTRACE_GETFPREGS: { /* Get the child FPU state. */
if (!access_ok(VERIFY_WRITE, (unsigned *)data, sizeof(struct user_i387_struct))) { if (!access_ok(VERIFY_WRITE, (unsigned *)data,
sizeof(struct user_i387_struct))) {
ret = -EIO; ret = -EIO;
break; break;
} }
ret = 0; ret = 0;
if ( !child->used_math ) { if ( !child->used_math ) {
/* Simulate an empty FPU. */ /* Simulate an empty FPU. */
i387_set_cwd(child->thread.i387.hard, 0x037f); set_fpu_cwd(child, 0x037f);
i387_set_swd(child->thread.i387.hard, 0x0000); set_fpu_swd(child, 0x0000);
i387_set_twd(child->thread.i387.hard, 0xffff); set_fpu_twd(child, 0xffff);
}
#ifdef CONFIG_MATH_EMULATION
if ( boot_cpu_data.hard_math ) {
#endif
i387_hard_to_user((struct _fpstate *)data, &child->thread.i387.hard);
#ifdef CONFIG_MATH_EMULATION
} else {
save_i387_soft(&child->thread.i387.soft, (struct _fpstate *)data);
} }
#endif get_fpregs((struct user_i387_struct *)data, child);
break; break;
} }
case PTRACE_SETFPREGS: { /* Set the child FPU state. */ case PTRACE_SETFPREGS: { /* Set the child FPU state. */
if (!access_ok(VERIFY_READ, (unsigned *)data, sizeof(struct user_i387_struct))) { if (!access_ok(VERIFY_READ, (unsigned *)data,
sizeof(struct user_i387_struct))) {
ret = -EIO; ret = -EIO;
break; break;
} }
child->used_math = 1; child->used_math = 1;
#ifdef CONFIG_MATH_EMULATION set_fpregs(child, (struct user_i387_struct *)data);
if ( boot_cpu_data.hard_math ) {
#endif
i387_user_to_hard(&child->thread.i387.hard,(struct _fpstate *)data);
#ifdef CONFIG_MATH_EMULATION
} else {
restore_i387_soft(&child->thread.i387.soft, (struct _fpstate *)data);
}
#endif
ret = 0; ret = 0;
break; break;
} }
case PTRACE_GETFPXREGS: { /* Get the child extended FPU state. */
if (!access_ok(VERIFY_WRITE, (unsigned *)data,
sizeof(struct user_fxsr_struct))) {
ret = -EIO;
break;
}
if ( !child->used_math ) {
/* Simulate an empty FPU. */
set_fpu_cwd(child, 0x037f);
set_fpu_swd(child, 0x0000);
set_fpu_twd(child, 0xffff);
set_fpu_mxcsr(child, 0x1f80);
}
ret = get_fpxregs((struct user_fxsr_struct *)data, child);
break;
}
case PTRACE_SETFPXREGS: { /* Set the child extended FPU state. */
if (!access_ok(VERIFY_READ, (unsigned *)data,
sizeof(struct user_fxsr_struct))) {
ret = -EIO;
break;
}
child->used_math = 1;
ret = set_fpxregs(child, (struct user_fxsr_struct *)data);
break;
}
default: default:
ret = -EIO; ret = -EIO;
break; break;
......
...@@ -39,8 +39,10 @@ ...@@ -39,8 +39,10 @@
* Detection for Celeron coppermine, identify_cpu() overhauled, * Detection for Celeron coppermine, identify_cpu() overhauled,
* and a few other clean ups. * and a few other clean ups.
* Dave Jones <dave@powertweak.com>, April 2000 * Dave Jones <dave@powertweak.com>, April 2000
* Pentium-III code by Ingo Molnar and modifications by Goutham Rao
* *
* Pentium III FXSR, SSE support
* General FPU state handling cleanups
* Gareth Hughes <gareth@valinux.com>, May 2000
*/ */
/* /*
...@@ -784,20 +786,6 @@ void __init setup_arch(char **cmdline_p) ...@@ -784,20 +786,6 @@ void __init setup_arch(char **cmdline_p)
conswitchp = &dummy_con; conswitchp = &dummy_con;
#endif #endif
#endif #endif
#ifdef CONFIG_X86_FXSR
if (boot_cpu_data.x86_capability & X86_FEATURE_FXSR)
{
printk("Enabling extended fast FPU save and restore ... ");
set_in_cr4(X86_CR4_OSFXSR);
printk("done.\n");
}
if (boot_cpu_data.x86_capability & X86_FEATURE_XMM)
{
printk("Enabling KNI unmasked exception support ... ");
set_in_cr4(X86_CR4_OSXMMEXCPT);
printk("done.\n");
}
#endif
} }
static int __init get_model_name(struct cpuinfo_x86 *c) static int __init get_model_name(struct cpuinfo_x86 *c)
......
...@@ -4,8 +4,7 @@ ...@@ -4,8 +4,7 @@
* Copyright (C) 1991, 1992 Linus Torvalds * Copyright (C) 1991, 1992 Linus Torvalds
* *
* 1997-11-28 Modified for POSIX.1b signals by Richard Henderson * 1997-11-28 Modified for POSIX.1b signals by Richard Henderson
* Pentium III support by Ingo Molnar, modifications and OS Exception support * 2000-06-20 Pentium III FXSR, SSE support by Gareth Hughes
* by Goutham Rao
*/ */
#include <linux/config.h> #include <linux/config.h>
...@@ -23,6 +22,7 @@ ...@@ -23,6 +22,7 @@
#include <linux/stddef.h> #include <linux/stddef.h>
#include <asm/ucontext.h> #include <asm/ucontext.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/i387.h>
#define DEBUG_SIG 0 #define DEBUG_SIG 0
...@@ -187,29 +187,6 @@ struct rt_sigframe ...@@ -187,29 +187,6 @@ struct rt_sigframe
char retcode[8]; char retcode[8];
}; };
static inline int restore_i387_hard(struct _fpstate *buf)
{
struct task_struct *tsk = current;
clear_fpu(tsk);
return i387_user_to_hard(&tsk->thread.i387.hard, buf);
}
static inline int restore_i387(struct _fpstate *buf)
{
int err;
#ifndef CONFIG_MATH_EMULATION
err = restore_i387_hard(buf);
#else
if (boot_cpu_data.hard_math)
err = restore_i387_hard(buf);
else
err = restore_i387_soft(&current->thread.i387.soft, buf);
#endif
current->used_math = 1;
return err;
}
static int static int
restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc, int *peax) restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc, int *peax)
{ {
...@@ -340,35 +317,6 @@ asmlinkage int sys_rt_sigreturn(unsigned long __unused) ...@@ -340,35 +317,6 @@ asmlinkage int sys_rt_sigreturn(unsigned long __unused)
* Set up a signal frame. * Set up a signal frame.
*/ */
static inline int save_i387_hard(struct _fpstate * buf)
{
struct task_struct *tsk = current;
unlazy_fpu(tsk);
tsk->thread.i387.hard.status = tsk->thread.i387.hard.swd;
if (i387_hard_to_user(buf, &tsk->thread.i387.hard))
return -1;
return 1;
}
static int save_i387(struct _fpstate *buf)
{
if (!current->used_math)
return 0;
/* This will cause a "finit" to be triggered by the next
attempted FPU operation by the 'current' process.
*/
current->used_math = 0;
#ifndef CONFIG_MATH_EMULATION
return save_i387_hard(buf);
#else
return boot_cpu_data.hard_math ? save_i387_hard(buf)
: save_i387_soft(&current->thread.i387.soft, buf);
#endif
}
static int static int
setup_sigcontext(struct sigcontext *sc, struct _fpstate *fpstate, setup_sigcontext(struct sigcontext *sc, struct _fpstate *fpstate,
struct pt_regs *regs, unsigned long mask) struct pt_regs *regs, unsigned long mask)
......
...@@ -2,7 +2,9 @@ ...@@ -2,7 +2,9 @@
* linux/arch/i386/traps.c * linux/arch/i386/traps.c
* *
* Copyright (C) 1991, 1992 Linus Torvalds * Copyright (C) 1991, 1992 Linus Torvalds
* FXSAVE/FXRSTOR support by Ingo Molnar, OS exception support by Goutham Rao *
* Pentium III FXSR, SSE support
* Gareth Hughes <gareth@valinux.com>, May 2000
*/ */
/* /*
...@@ -35,6 +37,7 @@ ...@@ -35,6 +37,7 @@
#include <asm/atomic.h> #include <asm/atomic.h>
#include <asm/debugreg.h> #include <asm/debugreg.h>
#include <asm/desc.h> #include <asm/desc.h>
#include <asm/i387.h>
#include <asm/smp.h> #include <asm/smp.h>
#include <asm/pgalloc.h> #include <asm/pgalloc.h>
...@@ -152,10 +155,10 @@ asmlinkage void stack_segment(void); ...@@ -152,10 +155,10 @@ asmlinkage void stack_segment(void);
asmlinkage void general_protection(void); asmlinkage void general_protection(void);
asmlinkage void page_fault(void); asmlinkage void page_fault(void);
asmlinkage void coprocessor_error(void); asmlinkage void coprocessor_error(void);
asmlinkage void simd_coprocessor_error(void);
asmlinkage void reserved(void); asmlinkage void reserved(void);
asmlinkage void alignment_check(void); asmlinkage void alignment_check(void);
asmlinkage void spurious_interrupt_bug(void); asmlinkage void spurious_interrupt_bug(void);
asmlinkage void xmm_fault(void);
int kstack_depth_to_print = 24; int kstack_depth_to_print = 24;
...@@ -318,7 +321,6 @@ DO_ERROR(11, SIGBUS, "segment not present", segment_not_present, current) ...@@ -318,7 +321,6 @@ DO_ERROR(11, SIGBUS, "segment not present", segment_not_present, current)
DO_ERROR(12, SIGBUS, "stack segment", stack_segment, current) DO_ERROR(12, SIGBUS, "stack segment", stack_segment, current)
DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, current, BUS_ADRALN, get_cr2()) DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, current, BUS_ADRALN, get_cr2())
DO_ERROR(18, SIGSEGV, "reserved", reserved, current) DO_ERROR(18, SIGSEGV, "reserved", reserved, current)
DO_VM86_ERROR(19, SIGFPE, "XMM fault", xmm_fault, current)
asmlinkage void do_general_protection(struct pt_regs * regs, long error_code) asmlinkage void do_general_protection(struct pt_regs * regs, long error_code)
{ {
...@@ -584,13 +586,13 @@ void math_error(void *eip) ...@@ -584,13 +586,13 @@ void math_error(void *eip)
{ {
struct task_struct * task; struct task_struct * task;
siginfo_t info; siginfo_t info;
unsigned short cwd, swd;
/* /*
* Save the info for the exception handler * Save the info for the exception handler and clear the error.
* (this will also clear the error)
*/ */
task = current; task = current;
save_fpu(task); save_init_fpu(task);
task->thread.trap_no = 16; task->thread.trap_no = 16;
task->thread.error_code = 0; task->thread.error_code = 0;
info.si_signo = SIGFPE; info.si_signo = SIGFPE;
...@@ -607,9 +609,9 @@ void math_error(void *eip) ...@@ -607,9 +609,9 @@ void math_error(void *eip)
* and it will suffer the consequences since we won't be able to * and it will suffer the consequences since we won't be able to
* fully reproduce the context of the exception * fully reproduce the context of the exception
*/ */
switch(((~task->thread.i387.hard.cwd) & cwd = get_fpu_cwd(task);
task->thread.i387.hard.swd & 0x3f) | swd = get_fpu_swd(task);
(task->thread.i387.hard.swd & 0x240)) { switch (((~cwd) & swd & 0x3f) | (swd & 0x240)) {
case 0x000: case 0x000:
default: default:
break; break;
...@@ -641,6 +643,79 @@ asmlinkage void do_coprocessor_error(struct pt_regs * regs, long error_code) ...@@ -641,6 +643,79 @@ asmlinkage void do_coprocessor_error(struct pt_regs * regs, long error_code)
math_error((void *)regs->eip); math_error((void *)regs->eip);
} }
void simd_math_error(void *eip)
{
struct task_struct * task;
siginfo_t info;
unsigned short mxcsr;
/*
* Save the info for the exception handler and clear the error.
*/
task = current;
save_init_fpu(task);
load_mxcsr(0x1f80);
task->thread.trap_no = 19;
task->thread.error_code = 0;
info.si_signo = SIGFPE;
info.si_errno = 0;
info.si_code = __SI_FAULT;
info.si_addr = eip;
/*
* The SIMD FPU exceptions are handled a little differently, as there
* is only a single status/control register. Thus, to determine which
* unmasked exception was caught we must mask the exception mask bits
* at 0x1f80, and then use these to mask the exception bits at 0x3f.
*/
mxcsr = get_fpu_mxcsr(task);
switch (~((mxcsr & 0x1f80) >> 7) & (mxcsr & 0x3f)) {
case 0x000:
default:
break;
case 0x001: /* Invalid Op */
info.si_code = FPE_FLTINV;
break;
case 0x002: /* Denormalize */
case 0x010: /* Underflow */
info.si_code = FPE_FLTUND;
break;
case 0x004: /* Zero Divide */
info.si_code = FPE_FLTDIV;
break;
case 0x008: /* Overflow */
info.si_code = FPE_FLTOVF;
break;
case 0x020: /* Precision */
info.si_code = FPE_FLTRES;
break;
}
force_sig_info(SIGFPE, &info, task);
}
asmlinkage void do_simd_coprocessor_error(struct pt_regs * regs,
long error_code)
{
if (cpu_has_xmm) {
/* Handle SIMD FPU exceptions on PIII+ processors. */
ignore_irq13 = 1;
simd_math_error((void *)regs->eip);
} else {
/*
* Handle strange cache flush from user space exception
* in all other cases. This is undocumented behaviour.
*/
if (regs->eflags & VM_MASK) {
handle_vm86_fault((struct kernel_vm86_regs *)regs,
error_code);
return;
}
die_if_kernel("cache flush denied", regs, error_code);
current->thread.trap_no = 19;
current->thread.error_code = error_code;
force_sig(SIGSEGV, current);
}
}
asmlinkage void do_spurious_interrupt_bug(struct pt_regs * regs, asmlinkage void do_spurious_interrupt_bug(struct pt_regs * regs,
long error_code) long error_code)
{ {
...@@ -661,17 +736,16 @@ asmlinkage void math_state_restore(struct pt_regs regs) ...@@ -661,17 +736,16 @@ asmlinkage void math_state_restore(struct pt_regs regs)
{ {
__asm__ __volatile__("clts"); /* Allow maths ops (or we recurse) */ __asm__ __volatile__("clts"); /* Allow maths ops (or we recurse) */
if(current->used_math) if (current->used_math) {
i387_restore_hard(current->thread.i387); restore_fpu(current);
else } else {
{
/* /*
* Our first FPU usage, clean the chip. * Our first FPU usage, clean the chip.
*/ */
__asm__("fninit"); __asm__("fninit");
current->used_math = 1; current->used_math = 1;
} }
current->flags|=PF_USEDFPU; /* So we fnsave on switch_to() */ current->flags |= PF_USEDFPU; /* So we fnsave on switch_to() */
} }
#ifndef CONFIG_MATH_EMULATION #ifndef CONFIG_MATH_EMULATION
...@@ -905,7 +979,7 @@ void __init trap_init(void) ...@@ -905,7 +979,7 @@ void __init trap_init(void)
set_trap_gate(15,&spurious_interrupt_bug); set_trap_gate(15,&spurious_interrupt_bug);
set_trap_gate(16,&coprocessor_error); set_trap_gate(16,&coprocessor_error);
set_trap_gate(17,&alignment_check); set_trap_gate(17,&alignment_check);
set_trap_gate(19,&xmm_fault); set_trap_gate(19,&simd_coprocessor_error);
set_system_gate(SYSCALL_VECTOR,&system_call); set_system_gate(SYSCALL_VECTOR,&system_call);
......
...@@ -8,6 +8,9 @@ ...@@ -8,6 +8,9 @@
* <rreilova@ececs.uc.edu> * <rreilova@ececs.uc.edu>
* - Channing Corn (tests & fixes), * - Channing Corn (tests & fixes),
* - Andrew D. Balsa (code cleanup). * - Andrew D. Balsa (code cleanup).
*
* Pentium III FXSR, SSE support
* Gareth Hughes <gareth@valinux.com>, May 2000
*/ */
/* /*
...@@ -19,6 +22,7 @@ ...@@ -19,6 +22,7 @@
#include <linux/config.h> #include <linux/config.h>
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/i387.h>
#include <asm/msr.h> #include <asm/msr.h>
static int __init no_halt(char *s) static int __init no_halt(char *s)
...@@ -62,6 +66,9 @@ static void __init copro_timeout(void) ...@@ -62,6 +66,9 @@ static void __init copro_timeout(void)
static double __initdata x = 4195835.0; static double __initdata x = 4195835.0;
static double __initdata y = 3145727.0; static double __initdata y = 3145727.0;
static float __initdata zero[4] = { 0.0, 0.0, 0.0, 0.0 };
static float __initdata one[4] = { 1.0, 1.0, 1.0, 1.0 };
static void __init check_fpu(void) static void __init check_fpu(void)
{ {
unsigned short control_word; unsigned short control_word;
...@@ -139,6 +146,37 @@ static void __init check_fpu(void) ...@@ -139,6 +146,37 @@ static void __init check_fpu(void)
printk("OK, FPU using exception 16 error reporting.\n"); printk("OK, FPU using exception 16 error reporting.\n");
else else
printk("Hmm, FPU using exception 16 error reporting with FDIV bug.\n"); printk("Hmm, FPU using exception 16 error reporting with FDIV bug.\n");
#if defined(CONFIG_X86_FXSR) || defined(CONFIG_X86_RUNTIME_FXSR)
/*
* Verify that the FXSAVE/FXRSTOR data will be 16-byte aligned.
*/
if (offsetof(struct task_struct, thread.i387.fxsave) & 15)
panic("Kernel compiled for PII/PIII+ with FXSR, data not 16-byte aligned!");
if (cpu_has_fxsr) {
printk(KERN_INFO "Enabling fast FPU save and restore... ");
set_in_cr4(X86_CR4_OSFXSR);
printk("done.\n");
}
#endif
#ifdef CONFIG_X86_XMM
if (cpu_has_xmm) {
printk(KERN_INFO "Enabling unmasked SIMD FPU exception support... ");
set_in_cr4(X86_CR4_OSXMMEXCPT);
printk("done.\n");
/* Check if exception 19 works okay. */
load_mxcsr(0x0000);
printk(KERN_INFO "Checking SIMD FPU exceptions... ");
__asm__("movups %0,%%xmm0\n\t"
"movups %1,%%xmm1\n\t"
"divps %%xmm0,%%xmm1\n\t"
: : "m" (*&zero), "m" (*&one));
printk("OK, SIMD FPU using exception 19 error reporting.\n");
load_mxcsr(0x1f80);
}
#endif
} }
static void __init check_hlt(void) static void __init check_hlt(void)
...@@ -424,6 +462,14 @@ static void __init check_config(void) ...@@ -424,6 +462,14 @@ static void __init check_config(void)
&& (boot_cpu_data.x86_mask < 6 || boot_cpu_data.x86_mask == 11)) && (boot_cpu_data.x86_mask < 6 || boot_cpu_data.x86_mask == 11))
panic("Kernel compiled for PPro+, assumes a local APIC without the read-before-write bug!"); panic("Kernel compiled for PPro+, assumes a local APIC without the read-before-write bug!");
#endif #endif
/*
* If we configured ourselves for FXSR, we'd better have it.
*/
#ifdef CONFIG_X86_FXSR
if (!cpu_has_fxsr)
panic("Kernel compiled for PII/PIII+, requires FXSR feature!");
#endif
} }
static void __init check_bugs(void) static void __init check_bugs(void)
......
...@@ -14,6 +14,7 @@ typedef unsigned long elf_greg_t; ...@@ -14,6 +14,7 @@ typedef unsigned long elf_greg_t;
typedef elf_greg_t elf_gregset_t[ELF_NGREG]; typedef elf_greg_t elf_gregset_t[ELF_NGREG];
typedef struct user_i387_struct elf_fpregset_t; typedef struct user_i387_struct elf_fpregset_t;
typedef struct user_fxsr_struct elf_fpxregset_t;
/* /*
* This is used to ensure we don't load something for the wrong architecture. * This is used to ensure we don't load something for the wrong architecture.
......
/*
* include/asm-i386/i387.h
*
* Copyright (C) 1994 Linus Torvalds
*
* Pentium III FXSR, SSE support
* General FPU state handling cleanups
* Gareth Hughes <gareth@valinux.com>, May 2000
*/
#ifndef __ASM_I386_I387_H
#define __ASM_I386_I387_H
#include <linux/config.h>
#include <linux/sched.h>
#include <asm/processor.h>
#include <asm/sigcontext.h>
#include <asm/user.h>
/*
* FPU lazy state save handling...
*/
extern void save_fpu( struct task_struct *tsk );
extern void save_init_fpu( struct task_struct *tsk );
extern void restore_fpu( struct task_struct *tsk );
#define unlazy_fpu( tsk ) do { \
if ( tsk->flags & PF_USEDFPU ) \
save_fpu( tsk ); \
} while (0)
#define clear_fpu( tsk ) do { \
if ( tsk->flags & PF_USEDFPU ) { \
tsk->flags &= ~PF_USEDFPU; \
stts(); \
} \
} while (0)
/*
* FPU state interaction...
*/
extern unsigned short get_fpu_cwd( struct task_struct *tsk );
extern unsigned short get_fpu_swd( struct task_struct *tsk );
extern unsigned short get_fpu_twd( struct task_struct *tsk );
extern unsigned short get_fpu_mxcsr( struct task_struct *tsk );
extern void set_fpu_cwd( struct task_struct *tsk, unsigned short cwd );
extern void set_fpu_swd( struct task_struct *tsk, unsigned short swd );
extern void set_fpu_twd( struct task_struct *tsk, unsigned short twd );
extern void set_fpu_mxcsr( struct task_struct *tsk, unsigned short mxcsr );
#define load_mxcsr( val ) do { \
if ( cpu_has_xmm ) { \
unsigned long __mxcsr = ((unsigned long)(val) & 0xffff); \
asm volatile( "ldmxcsr %0" : : "m" (__mxcsr) ); \
} \
} while (0)
/*
* Signal frame handlers...
*/
extern int save_i387( struct _fpstate *buf );
extern int restore_i387( struct _fpstate *buf );
/*
* ptrace request handers...
*/
extern int get_fpregs( struct user_i387_struct *buf,
struct task_struct *tsk );
extern int set_fpregs( struct task_struct *tsk,
struct user_i387_struct *buf );
extern int get_fpxregs( struct user_fxsr_struct *buf,
struct task_struct *tsk );
extern int set_fpxregs( struct task_struct *tsk,
struct user_fxsr_struct *buf );
/*
* FPU state for core dumps...
*/
extern int dump_fpu( struct pt_regs *regs,
struct user_i387_struct *fpu );
extern int dump_extended_fpu( struct pt_regs *regs,
struct user_fxsr_struct *fpu );
#endif /* __ASM_I386_I387_H */
...@@ -83,24 +83,22 @@ struct cpuinfo_x86 { ...@@ -83,24 +83,22 @@ struct cpuinfo_x86 {
#define X86_FEATURE_PGE 0x00002000 /* Page Global Enable */ #define X86_FEATURE_PGE 0x00002000 /* Page Global Enable */
#define X86_FEATURE_MCA 0x00004000 /* Machine Check Architecture */ #define X86_FEATURE_MCA 0x00004000 /* Machine Check Architecture */
#define X86_FEATURE_CMOV 0x00008000 /* CMOV instruction (FCMOVCC and FCOMI too if FPU present) */ #define X86_FEATURE_CMOV 0x00008000 /* CMOV instruction (FCMOVCC and FCOMI too if FPU present) */
#define X86_FEATURE_PAT 0x00010000 /* Page Attribute Table */ #define X86_FEATURE_PAT 0x00010000 /* Page Attribute Table */
#define X86_FEATURE_PSE36 0x00020000 /* 36-bit PSEs */ #define X86_FEATURE_PSE36 0x00020000 /* 36-bit PSEs */
#define X86_FEATURE_18 0x00040000 #define X86_FEATURE_18 0x00040000
#define X86_FEATURE_19 0x00080000 #define X86_FEATURE_19 0x00080000
#define X86_FEATURE_20 0x00100000 #define X86_FEATURE_20 0x00100000
#define X86_FEATURE_21 0x00200000 #define X86_FEATURE_21 0x00200000
#define X86_FEATURE_22 0x00400000 #define X86_FEATURE_22 0x00400000
#define X86_FEATURE_MMX 0x00800000 /* multimedia extensions */ #define X86_FEATURE_MMX 0x00800000 /* Multimedia Extensions */
#define X86_FEATURE_FXSR 0x01000000 /* FXSAVE and FXRSTOR instructions (fast save and restore of FPU context), and CR4.OSFXSR (OS uses these instructions) available */ #define X86_FEATURE_FXSR 0x01000000 /* FXSAVE and FXRSTOR instructions (fast save and restore of FPU context), and CR4.OSFXSR (OS uses these instructions) available */
#define X86_FEATURE_XMM 0x02000000 /* Intel MMX2 instruction set */ #define X86_FEATURE_XMM 0x02000000 /* Streaming SIMD Extensions */
#define X86_FEATURE_26 0x04000000 #define X86_FEATURE_26 0x04000000
#define X86_FEATURE_27 0x08000000 #define X86_FEATURE_27 0x08000000
#define X86_FEATURE_28 0x10000000 #define X86_FEATURE_28 0x10000000
#define X86_FEATURE_29 0x20000000 #define X86_FEATURE_29 0x20000000
#define X86_FEATURE_30 0x40000000 #define X86_FEATURE_30 0x40000000
#define X86_FEATURE_AMD3D 0x80000000 #define X86_FEATURE_AMD3D 0x80000000
#define X86_CR4_OSFXSR 0x0200 /* fast FPU save/restore */
#define X86_CR4_OSXMMEXCPT 0x0400 /* KNI (MMX2) unmasked exception 16 */
extern struct cpuinfo_x86 boot_cpu_data; extern struct cpuinfo_x86 boot_cpu_data;
extern struct tss_struct init_tss[NR_CPUS]; extern struct tss_struct init_tss[NR_CPUS];
...@@ -125,6 +123,10 @@ extern struct cpuinfo_x86 cpu_data[]; ...@@ -125,6 +123,10 @@ extern struct cpuinfo_x86 cpu_data[];
(boot_cpu_data.x86_capability & X86_FEATURE_DE) (boot_cpu_data.x86_capability & X86_FEATURE_DE)
#define cpu_has_vme \ #define cpu_has_vme \
(boot_cpu_data.x86_capability & X86_FEATURE_VME) (boot_cpu_data.x86_capability & X86_FEATURE_VME)
#define cpu_has_fxsr \
(boot_cpu_data.x86_capability & X86_FEATURE_FXSR)
#define cpu_has_xmm \
(boot_cpu_data.x86_capability & X86_FEATURE_XMM)
extern char ignore_irq13; extern char ignore_irq13;
...@@ -150,15 +152,17 @@ extern inline void cpuid(int op, int *eax, int *ebx, int *ecx, int *edx) ...@@ -150,15 +152,17 @@ extern inline void cpuid(int op, int *eax, int *ebx, int *ecx, int *edx)
/* /*
* Intel CPU features in CR4 * Intel CPU features in CR4
*/ */
#define X86_CR4_VME 0x0001 /* enable vm86 extensions */ #define X86_CR4_VME 0x0001 /* enable vm86 extensions */
#define X86_CR4_PVI 0x0002 /* virtual interrupts flag enable */ #define X86_CR4_PVI 0x0002 /* virtual interrupts flag enable */
#define X86_CR4_TSD 0x0004 /* disable time stamp at ipl 3 */ #define X86_CR4_TSD 0x0004 /* disable time stamp at ipl 3 */
#define X86_CR4_DE 0x0008 /* enable debugging extensions */ #define X86_CR4_DE 0x0008 /* enable debugging extensions */
#define X86_CR4_PSE 0x0010 /* enable page size extensions */ #define X86_CR4_PSE 0x0010 /* enable page size extensions */
#define X86_CR4_PAE 0x0020 /* enable physical address extensions */ #define X86_CR4_PAE 0x0020 /* enable physical address extensions */
#define X86_CR4_MCE 0x0040 /* Machine check enable */ #define X86_CR4_MCE 0x0040 /* Machine check enable */
#define X86_CR4_PGE 0x0080 /* enable global pages */ #define X86_CR4_PGE 0x0080 /* enable global pages */
#define X86_CR4_PCE 0x0100 /* enable performance counters at ipl 3 */ #define X86_CR4_PCE 0x0100 /* enable performance counters at ipl 3 */
#define X86_CR4_OSFXSR 0x0200 /* enable fast FPU save and restore */
#define X86_CR4_OSXMMEXCPT 0x0400 /* enable unmasked SSE exceptions */
/* /*
* Save the cr4 feature set we're using (ie * Save the cr4 feature set we're using (ie
...@@ -244,23 +248,7 @@ extern unsigned int mca_pentium_flag; ...@@ -244,23 +248,7 @@ extern unsigned int mca_pentium_flag;
#define IO_BITMAP_OFFSET offsetof(struct tss_struct,io_bitmap) #define IO_BITMAP_OFFSET offsetof(struct tss_struct,io_bitmap)
#define INVALID_IO_BITMAP_OFFSET 0x8000 #define INVALID_IO_BITMAP_OFFSET 0x8000
#ifndef CONFIG_X86_FXSR struct i387_fsave_struct {
#define i387_save_hard(x) \
__asm__("fnsave %0\n\tfwait": :"m" (x))
#define i387_restore_hard(x) \
__asm__("frstor %0": :"m" (x))
#define i387_hard_to_user(uaddr, x) \
__copy_to_user((uaddr), (x), sizeof(struct i387_hard_struct))
#define i387_user_to_hard(x, uaddr) \
__copy_from_user((x), (uaddr), sizeof(struct i387_hard_struct))
#define i387_set_cwd(x,v) do { (x).cwd = 0xffff0000 | (v); } while (0)
#define i387_set_swd(x,v) do { (x).swd = 0xffff0000 | (v); } while (0)
#define i387_set_twd(x,v) do { (x).twd = 0xffff0000 | (v); } while (0)
struct i387_hard_struct {
long cwd; long cwd;
long swd; long swd;
long twd; long twd;
...@@ -272,69 +260,22 @@ struct i387_hard_struct { ...@@ -272,69 +260,22 @@ struct i387_hard_struct {
long status; /* software status information */ long status; /* software status information */
}; };
#else struct i387_fxsave_struct {
/*
* has to be 128-bit aligned
*/
struct i387_hard_struct {
unsigned short cwd; unsigned short cwd;
unsigned short swd; unsigned short swd;
unsigned short twd; unsigned short twd;
unsigned short fopcode; unsigned short fop;
unsigned int fip; long fip;
unsigned short fcs; long fcs;
unsigned short __reserved_01; long foo;
unsigned int fdp; long fos;
unsigned short fds; long mxcsr;
unsigned short __reserved_02; long reserved;
unsigned int mxcsr; long st_space[32]; /* 8*16 bytes for each FP-reg = 128 bytes */
unsigned int __reserved_03; long xmm_space[32]; /* 8*16 bytes for each XMM-reg = 128 bytes */
unsigned int st_space[32]; /* 8*16 bytes for each FP/MMX-reg = 128 bytes */ long padding[56];
unsigned int xmm_space[22*4]; /* 22 cachelines for MMX2 registers */
unsigned long status;
} __attribute__ ((aligned (16))); } __attribute__ ((aligned (16)));
/*
* tag word conversion (thanks to Gabriel Paubert for noticing the
* subtle format difference and implementing these functions)
*
* there are several erratas wrt. the tag word in the i387, thus
* any software relying on it's value is questionable, but we
* definitely want to be as close as possible.
*/
static inline unsigned short fputag_KNIto387(unsigned char tb) {
unsigned short tw = tb;
tw = ((tw<<4) | tw) &0x0f0f; /* zzzz7654zzzz3210 */
tw = ((tw<<2) | tw) &0x3333; /* zz76zz54zz32zz10 */
tw = ((tw<<1) | tw) &0x5555; /* z7z6z5z4z3z2z1z0 */
return ~(tw*3);
}
static inline unsigned char fputag_387toKNI(unsigned short tw) {
tw = ~tw;
tw = (tw | (tw>>1)) & 0x5555; /* z7z6z5z4z3z2z1z0 */
tw = (tw | (tw>>1)) & 0x3333; /* zz76zz54zz32zz10 */
tw = (tw | (tw>>3)) & 0x0f0f; /* zzzz7654zzzz3210 */
return (tw|(tw>>4)) & 0x00ff; /* zzzzzzzz76543210 */
}
#define i387_set_cwd(x,v) do { (x).cwd = (short)(v); } while (0)
#define i387_set_swd(x,v) do { (x).swd = (short)(v); } while (0)
#define i387_set_twd(x,v) do { (x).twd = fputag_387toKNI(v); } while (0)
#define i387_save_hard(x) \
{ __asm__ __volatile__(".byte 0x0f, 0xae, 0x06": :"S" (&(x))); } while (0)
#define i387_restore_hard(x) \
do { __asm__ __volatile__(".byte 0x0f, 0xae, 0x4f, 0x00": :"D" (&(x))); } while(0)
extern int i387_hard_to_user ( struct _fpstate * user,
struct i387_hard_struct * hard);
extern int i387_user_to_hard (struct i387_hard_struct * hard,
struct _fpstate * user);
#endif
struct i387_soft_struct { struct i387_soft_struct {
long cwd; long cwd;
long swd; long swd;
...@@ -350,7 +291,8 @@ struct i387_soft_struct { ...@@ -350,7 +291,8 @@ struct i387_soft_struct {
}; };
union i387_union { union i387_union {
struct i387_hard_struct hard; struct i387_fsave_struct fsave;
struct i387_fxsave_struct fxsave;
struct i387_soft_struct soft; struct i387_soft_struct soft;
}; };
...@@ -466,27 +408,6 @@ extern void copy_segments(struct task_struct *p, struct mm_struct * mm); ...@@ -466,27 +408,6 @@ extern void copy_segments(struct task_struct *p, struct mm_struct * mm);
extern void release_segments(struct mm_struct * mm); extern void release_segments(struct mm_struct * mm);
extern void forget_segments(void); extern void forget_segments(void);
/*
* FPU lazy state save handling..
*/
#define save_fpu(tsk) do { \
i387_save_hard(tsk->thread.i387); \
tsk->flags &= ~PF_USEDFPU; \
stts(); \
} while (0)
#define unlazy_fpu(tsk) do { \
if (tsk->flags & PF_USEDFPU) \
save_fpu(tsk); \
} while (0)
#define clear_fpu(tsk) do { \
if (tsk->flags & PF_USEDFPU) { \
tsk->flags &= ~PF_USEDFPU; \
stts(); \
} \
} while (0)
/* /*
* Return saved PC of a blocked thread. * Return saved PC of a blocked thread.
*/ */
......
...@@ -46,6 +46,8 @@ struct pt_regs { ...@@ -46,6 +46,8 @@ struct pt_regs {
#define PTRACE_SETREGS 13 #define PTRACE_SETREGS 13
#define PTRACE_GETFPREGS 14 #define PTRACE_GETFPREGS 14
#define PTRACE_SETFPREGS 15 #define PTRACE_SETFPREGS 15
#define PTRACE_GETFPXREGS 18
#define PTRACE_SETFPXREGS 19
#ifdef __KERNEL__ #ifdef __KERNEL__
#define user_mode(regs) ((VM_MASK & (regs)->eflags) || (3 & (regs)->xcs)) #define user_mode(regs) ((VM_MASK & (regs)->eflags) || (3 & (regs)->xcs))
......
#ifndef _ASMi386_SIGCONTEXT_H #ifndef _ASMi386_SIGCONTEXT_H
#define _ASMi386_SIGCONTEXT_H #define _ASMi386_SIGCONTEXT_H
#include <linux/config.h>
/* /*
* As documented in the iBCS2 standard.. * As documented in the iBCS2 standard..
* *
* The first part of "struct _fpstate" is just the * The first part of "struct _fpstate" is just the normal i387
* normal i387 hardware setup, the extra "status" * hardware setup, the extra "status" word is used to save the
* word is used to save the coprocessor status word * coprocessor status word before entering the handler.
* before entering the handler. *
* Pentium III FXSR, SSE support
* Gareth Hughes <gareth@valinux.com>, May 2000
*
* The FPU state data structure has had to grow to accomodate the
* extended FPU state required by the Streaming SIMD Extensions.
* There is no documented standard to accomplish this at the moment.
*/ */
struct _fpreg { struct _fpreg {
unsigned short significand[4]; unsigned short significand[4];
unsigned short exponent; unsigned short exponent;
}; };
struct _fpxreg {
unsigned short significand[4];
unsigned short exponent;
unsigned short padding[3];
};
struct _xmmreg {
unsigned long element[4];
};
struct _fpstate { struct _fpstate {
unsigned long cw, /* Regular FPU environment */
sw, unsigned long cw;
tag, unsigned long sw;
ipoff, unsigned long tag;
cssel, unsigned long ipoff;
dataoff, unsigned long cssel;
datasel; unsigned long dataoff;
unsigned long datasel;
struct _fpreg _st[8]; struct _fpreg _st[8];
unsigned long status; unsigned short status;
#ifdef CONFIG_X86_FXSR unsigned short magic; /* 0xffff = regular FPU data only */
/* FXSR FPU environment */
unsigned long _fxsr_env[6]; /* FXSR FPU env is ignored */
unsigned long mxcsr; unsigned long mxcsr;
unsigned long _xmm[4*22]; unsigned long reserved;
#endif struct _fpxreg _fxsr_st[8]; /* FXSR FPU reg data is ignored */
struct _xmmreg _xmm[8];
unsigned long padding[56];
}; };
#define X86_FXSR_MAGIC 0x0000
struct sigcontext { struct sigcontext {
unsigned short gs, __gsh; unsigned short gs, __gsh;
unsigned short fs, __fsh; unsigned short fs, __fsh;
......
...@@ -30,6 +30,18 @@ ...@@ -30,6 +30,18 @@
The minimum core file size is 3 pages, or 12288 bytes. The minimum core file size is 3 pages, or 12288 bytes.
*/ */
/*
* Pentium III FXSR, SSE support
* Gareth Hughes <gareth@valinux.com>, May 2000
*
* Provide support for the GDB 5.0+ PTRACE_{GET|SET}FPXREGS requests for
* interacting with the FXSR-format floating point environment. Floating
* point data can be accessed in the regular format in the usual manner,
* and both the standard and SIMD floating point data can be accessed via
* the new ptrace requests. In either case, changes to the FPU environment
* will be reflected in the task's state as expected.
*/
struct user_i387_struct { struct user_i387_struct {
long cwd; long cwd;
long swd; long swd;
...@@ -41,6 +53,22 @@ struct user_i387_struct { ...@@ -41,6 +53,22 @@ struct user_i387_struct {
long st_space[20]; /* 8*10 bytes for each FP-reg = 80 bytes */ long st_space[20]; /* 8*10 bytes for each FP-reg = 80 bytes */
}; };
struct user_fxsr_struct {
unsigned short cwd;
unsigned short swd;
unsigned short twd;
unsigned short fop;
long fip;
long fcs;
long foo;
long fos;
long mxcsr;
long reserved;
long st_space[32]; /* 8*16 bytes for each FP-reg = 128 bytes */
long xmm_space[32]; /* 8*16 bytes for each XMM-reg = 128 bytes */
long padding[56];
};
/* /*
* This is the old layout of "struct pt_regs", and * This is the old layout of "struct pt_regs", and
* is still the layout used by user mode (the new * is still the layout used by user mode (the new
......
...@@ -565,6 +565,7 @@ typedef struct elf64_shdr { ...@@ -565,6 +565,7 @@ typedef struct elf64_shdr {
#define NT_PRFPREG 2 #define NT_PRFPREG 2
#define NT_PRPSINFO 3 #define NT_PRPSINFO 3
#define NT_TASKSTRUCT 4 #define NT_TASKSTRUCT 4
#define NT_PRFPXREG 20
/* Note header in a PT_NOTE section */ /* Note header in a PT_NOTE section */
typedef struct elf32_note { typedef struct elf32_note {
......
...@@ -20,6 +20,7 @@ struct elf_siginfo ...@@ -20,6 +20,7 @@ struct elf_siginfo
typedef elf_greg_t greg_t; typedef elf_greg_t greg_t;
typedef elf_gregset_t gregset_t; typedef elf_gregset_t gregset_t;
typedef elf_fpregset_t fpregset_t; typedef elf_fpregset_t fpregset_t;
typedef elf_fpxregset_t fpxregset_t;
#define NGREG ELF_NGREG #define NGREG ELF_NGREG
#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