debuggers.hg

view xen/arch/x86/i387.c @ 22796:4b7cb21caf0e

x86: Avoid calling xsave_alloc_save_area before xsave_init

Currently, xsave_alloc_save_area will be called in
init_idle_domain->scheduler_init->alloc_vcpu->vcpu_initialise calls
with xsave_cntxt_size=0, it is earlier than xsave_init called in
identity_cpu(). This may causing buffer overflow on xmem_pool.

Idle domain isn't using FPU,SSE,AVX or any such extended state and
doesn't need it saved. xsave_{alloc,free}_save_area() should
test-and-exit on is_idle_vcpu(), and our context switch code should
not be doing XSAVE when switching out an idle vcpu.

Signed-off-by: Wei Gang <gang.wei@intel.com>
Signed-off-by: Keir Fraser <keir@xen.org>
author Keir Fraser <keir@xen.org>
date Fri Jan 14 08:34:53 2011 +0000 (2011-01-14)
parents 2762b6d3149c
children 58304c1cc725
line source
1 /*
2 * linux/arch/i386/kernel/i387.c
3 *
4 * Copyright (C) 1994 Linus Torvalds
5 *
6 * Pentium III FXSR, SSE support
7 * General FPU state handling cleanups
8 * Gareth Hughes <gareth@valinux.com>, May 2000
9 */
11 #include <xen/config.h>
12 #include <xen/sched.h>
13 #include <asm/current.h>
14 #include <asm/processor.h>
15 #include <asm/hvm/support.h>
16 #include <asm/i387.h>
17 #include <asm/asm_defns.h>
19 void setup_fpu(struct vcpu *v)
20 {
21 ASSERT(!is_idle_vcpu(v));
23 /* Avoid recursion. */
24 clts();
26 if ( !v->fpu_dirtied )
27 {
28 v->fpu_dirtied = 1;
29 if ( cpu_has_xsave )
30 {
31 if ( !v->fpu_initialised )
32 v->fpu_initialised = 1;
34 /* XCR0 normally represents what guest OS set. In case of Xen
35 * itself, we set all supported feature mask before doing
36 * save/restore.
37 */
38 set_xcr0(v->arch.xcr0_accum);
39 xrstor(v);
40 set_xcr0(v->arch.xcr0);
41 }
42 else
43 {
44 if ( v->fpu_initialised )
45 restore_fpu(v);
46 else
47 init_fpu();
48 }
49 }
50 }
52 void init_fpu(void)
53 {
54 asm volatile ( "fninit" );
55 if ( cpu_has_xmm )
56 load_mxcsr(0x1f80);
57 current->fpu_initialised = 1;
58 }
60 void save_init_fpu(struct vcpu *v)
61 {
62 unsigned long cr0 = read_cr0();
63 char *fpu_ctxt = v->arch.guest_context.fpu_ctxt.x;
65 ASSERT(!is_idle_vcpu(v));
67 /* This can happen, if a paravirtualised guest OS has set its CR0.TS. */
68 if ( cr0 & X86_CR0_TS )
69 clts();
71 if ( cpu_has_xsave )
72 {
73 /* XCR0 normally represents what guest OS set. In case of Xen itself,
74 * we set all accumulated feature mask before doing save/restore.
75 */
76 set_xcr0(v->arch.xcr0_accum);
77 if ( cpu_has_xsaveopt )
78 xsaveopt(v);
79 else
80 xsave(v);
81 set_xcr0(v->arch.xcr0);
82 }
83 else if ( cpu_has_fxsr )
84 {
85 #ifdef __i386__
86 asm volatile (
87 "fxsave %0"
88 : "=m" (*fpu_ctxt) );
89 #else /* __x86_64__ */
90 /*
91 * The only way to force fxsaveq on a wide range of gas versions. On
92 * older versions the rex64 prefix works only if we force an
93 * addressing mode that doesn't require extended registers.
94 */
95 asm volatile (
96 REX64_PREFIX "fxsave (%1)"
97 : "=m" (*fpu_ctxt) : "cdaSDb" (fpu_ctxt) );
98 #endif
100 /* Clear exception flags if FSW.ES is set. */
101 if ( unlikely(fpu_ctxt[2] & 0x80) )
102 asm volatile ("fnclex");
104 /*
105 * AMD CPUs don't save/restore FDP/FIP/FOP unless an exception
106 * is pending. Clear the x87 state here by setting it to fixed
107 * values. The hypervisor data segment can be sometimes 0 and
108 * sometimes new user value. Both should be ok. Use the FPU saved
109 * data block as a safe address because it should be in L1.
110 */
111 if ( boot_cpu_data.x86_vendor == X86_VENDOR_AMD )
112 {
113 asm volatile (
114 "emms\n\t" /* clear stack tags */
115 "fildl %0" /* load to clear state */
116 : : "m" (*fpu_ctxt) );
117 }
118 }
119 else
120 {
121 /* FWAIT is required to make FNSAVE synchronous. */
122 asm volatile ( "fnsave %0 ; fwait" : "=m" (*fpu_ctxt) );
123 }
125 v->fpu_dirtied = 0;
126 write_cr0(cr0|X86_CR0_TS);
127 }
129 void restore_fpu(struct vcpu *v)
130 {
131 char *fpu_ctxt = v->arch.guest_context.fpu_ctxt.x;
133 /*
134 * FXRSTOR can fault if passed a corrupted data block. We handle this
135 * possibility, which may occur if the block was passed to us by control
136 * tools, by silently clearing the block.
137 */
138 if ( cpu_has_fxsr )
139 {
140 asm volatile (
141 #ifdef __i386__
142 "1: fxrstor %0 \n"
143 #else /* __x86_64__ */
144 /* See above for why the operands/constraints are this way. */
145 "1: " REX64_PREFIX "fxrstor (%2)\n"
146 #endif
147 ".section .fixup,\"ax\" \n"
148 "2: push %%"__OP"ax \n"
149 " push %%"__OP"cx \n"
150 " push %%"__OP"di \n"
151 " lea %0,%%"__OP"di \n"
152 " mov %1,%%ecx \n"
153 " xor %%eax,%%eax \n"
154 " rep ; stosl \n"
155 " pop %%"__OP"di \n"
156 " pop %%"__OP"cx \n"
157 " pop %%"__OP"ax \n"
158 " jmp 1b \n"
159 ".previous \n"
160 _ASM_EXTABLE(1b, 2b)
161 :
162 : "m" (*fpu_ctxt),
163 "i" (sizeof(v->arch.guest_context.fpu_ctxt)/4)
164 #ifdef __x86_64__
165 ,"cdaSDb" (fpu_ctxt)
166 #endif
167 );
168 }
169 else
170 {
171 asm volatile ( "frstor %0" : : "m" (v->arch.guest_context.fpu_ctxt) );
172 }
173 }
175 #define XSTATE_CPUID 0xd
176 #define XSAVE_AREA_MIN_SIZE (512 + 64) /* FP/SSE + XSAVE.HEADER */
178 /*
179 * Maximum size (in byte) of the XSAVE/XRSTOR save area required by all
180 * the supported and enabled features on the processor, including the
181 * XSAVE.HEADER. We only enable XCNTXT_MASK that we have known.
182 */
183 u32 xsave_cntxt_size;
185 /* A 64-bit bitmask of the XSAVE/XRSTOR features supported by processor. */
186 u64 xfeature_mask;
188 /* Cached xcr0 for fast read */
189 DEFINE_PER_CPU(uint64_t, xcr0);
191 bool_t __read_mostly cpu_has_xsaveopt;
193 void xsave_init(void)
194 {
195 u32 eax, ebx, ecx, edx;
196 int cpu = smp_processor_id();
197 u32 min_size;
199 if ( boot_cpu_data.cpuid_level < XSTATE_CPUID ) {
200 printk(XENLOG_ERR "XSTATE_CPUID missing\n");
201 return;
202 }
204 cpuid_count(XSTATE_CPUID, 0, &eax, &ebx, &ecx, &edx);
206 printk("%s: cpu%d: cntxt_max_size: 0x%x and states: %08x:%08x\n",
207 __func__, cpu, ecx, edx, eax);
209 if ( ((eax & XSTATE_FP_SSE) != XSTATE_FP_SSE) ||
210 ((eax & XSTATE_YMM) && !(eax & XSTATE_SSE)) )
211 {
212 BUG();
213 }
215 /* FP/SSE, XSAVE.HEADER, YMM */
216 min_size = XSAVE_AREA_MIN_SIZE;
217 if ( eax & XSTATE_YMM )
218 min_size += XSTATE_YMM_SIZE;
219 BUG_ON(ecx < min_size);
221 /*
222 * Set CR4_OSXSAVE and run "cpuid" to get xsave_cntxt_size.
223 */
224 set_in_cr4(X86_CR4_OSXSAVE);
225 set_xcr0((((u64)edx << 32) | eax) & XCNTXT_MASK);
226 cpuid_count(XSTATE_CPUID, 0, &eax, &ebx, &ecx, &edx);
228 if ( cpu == 0 )
229 {
230 /*
231 * xsave_cntxt_size is the max size required by enabled features.
232 * We know FP/SSE and YMM about eax, and nothing about edx at present.
233 */
234 xsave_cntxt_size = ebx;
235 xfeature_mask = eax + ((u64)edx << 32);
236 xfeature_mask &= XCNTXT_MASK;
237 printk("%s: using cntxt_size: 0x%x and states: 0x%"PRIx64"\n",
238 __func__, xsave_cntxt_size, xfeature_mask);
240 /* Check XSAVEOPT feature. */
241 cpuid_count(XSTATE_CPUID, 1, &eax, &ebx, &ecx, &edx);
242 cpu_has_xsaveopt = !!(eax & XSAVEOPT);
243 }
244 else
245 {
246 BUG_ON(xsave_cntxt_size != ebx);
247 BUG_ON(xfeature_mask != (xfeature_mask & XCNTXT_MASK));
248 }
249 }
251 int xsave_alloc_save_area(struct vcpu *v)
252 {
253 void *save_area;
255 if ( !cpu_has_xsave || is_idle_vcpu(v) )
256 return 0;
258 BUG_ON(xsave_cntxt_size < XSAVE_AREA_MIN_SIZE);
260 /* XSAVE/XRSTOR requires the save area be 64-byte-boundary aligned. */
261 save_area = _xmalloc(xsave_cntxt_size, 64);
262 if ( save_area == NULL )
263 return -ENOMEM;
265 memset(save_area, 0, xsave_cntxt_size);
266 ((u32 *)save_area)[6] = 0x1f80; /* MXCSR */
267 *(uint64_t *)(save_area + 512) = XSTATE_FP_SSE; /* XSETBV */
269 v->arch.xsave_area = save_area;
270 v->arch.xcr0 = XSTATE_FP_SSE;
271 v->arch.xcr0_accum = XSTATE_FP_SSE;
273 return 0;
274 }
276 void xsave_free_save_area(struct vcpu *v)
277 {
278 xfree(v->arch.xsave_area);
279 v->arch.xsave_area = NULL;
280 }
282 /*
283 * Local variables:
284 * mode: C
285 * c-set-style: "BSD"
286 * c-basic-offset: 4
287 * tab-width: 4
288 * indent-tabs-mode: nil
289 * End:
290 */