1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
|
/*
* linux/arch/i386/kernel/i387.c
*
* Copyright (C) 1994 Linus Torvalds
*
* Pentium III FXSR, SSE support
* General FPU state handling cleanups
* Gareth Hughes <gareth@valinux.com>, May 2000
*/
#include <xen/config.h>
#include <xen/sched.h>
#include <asm/current.h>
#include <asm/processor.h>
#include <asm/i387.h>
void init_fpu(void)
{
__asm__ __volatile__ ( "fninit" );
if ( cpu_has_xmm )
load_mxcsr(0x1f80);
set_bit(_VCPUF_fpu_initialised, ¤t->vcpu_flags);
}
void save_init_fpu(struct vcpu *tsk)
{
/*
* The guest OS may have set the 'virtual STTS' flag.
* This causes us to set the real flag, so we'll need
* to temporarily clear it while saving f-p state.
*/
if ( test_bit(_VCPUF_guest_stts, &tsk->vcpu_flags) )
clts();
if ( cpu_has_fxsr )
__asm__ __volatile__ (
"fxsave %0 ; fnclex"
: "=m" (tsk->arch.guest_context.fpu_ctxt) );
else
__asm__ __volatile__ (
"fnsave %0 ; fwait"
: "=m" (tsk->arch.guest_context.fpu_ctxt) );
clear_bit(_VCPUF_fpu_dirtied, &tsk->vcpu_flags);
stts();
}
void restore_fpu(struct vcpu *tsk)
{
/*
* FXRSTOR can fault if passed a corrupted data block. We handle this
* possibility, which may occur if the block was passed to us by control
* tools, by silently clearing the block.
*/
if ( cpu_has_fxsr )
__asm__ __volatile__ (
"1: fxrstor %0 \n"
".section .fixup,\"ax\" \n"
"2: push %%"__OP"ax \n"
" push %%"__OP"cx \n"
" push %%"__OP"di \n"
" lea %0,%%"__OP"di \n"
" mov %1,%%ecx \n"
" xor %%eax,%%eax \n"
" rep ; stosl \n"
" pop %%"__OP"di \n"
" pop %%"__OP"cx \n"
" pop %%"__OP"ax \n"
" jmp 1b \n"
".previous \n"
".section __ex_table,\"a\"\n"
" "__FIXUP_ALIGN" \n"
" "__FIXUP_WORD" 1b,2b \n"
".previous \n"
:
: "m" (tsk->arch.guest_context.fpu_ctxt),
"i" (sizeof(tsk->arch.guest_context.fpu_ctxt)/4) );
else
__asm__ __volatile__ (
"frstor %0"
: : "m" (tsk->arch.guest_context.fpu_ctxt) );
}
/*
* Local variables:
* mode: C
* c-set-style: "BSD"
* c-basic-offset: 4
* tab-width: 4
* indent-tabs-mode: nil
* End:
*/
|