diff options
author | Eduardo Habkost <ehabkost@redhat.com> | 2008-07-08 18:07:10 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-07-16 05:04:55 -0400 |
commit | 8a95408e183b3e4aaf3b6a66fa34bff4db53011b (patch) | |
tree | af3d69d791d65fe324d4883fbe6a2e3d5f065fd0 | |
parent | 4a5c3e77f70b3ea8b361d7fa9eb2e4dad18f70ae (diff) |
xen64: Clear %fs on xen_load_tls()
We need to do this, otherwise we can get a GPF on hypercall return
after TLS descriptor is cleared but %fs is still pointing to it.
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
Cc: Stephen Tweedie <sct@redhat.com>
Cc: Eduardo Habkost <ehabkost@redhat.com>
Cc: Mark McLoughlin <markmc@redhat.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r-- | arch/x86/xen/enlighten.c | 31 |
1 files changed, 22 insertions, 9 deletions
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 0172ba774523..c13698faae54 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c | |||
@@ -364,14 +364,6 @@ static void load_TLS_descriptor(struct thread_struct *t, | |||
364 | 364 | ||
365 | static void xen_load_tls(struct thread_struct *t, unsigned int cpu) | 365 | static void xen_load_tls(struct thread_struct *t, unsigned int cpu) |
366 | { | 366 | { |
367 | xen_mc_batch(); | ||
368 | |||
369 | load_TLS_descriptor(t, cpu, 0); | ||
370 | load_TLS_descriptor(t, cpu, 1); | ||
371 | load_TLS_descriptor(t, cpu, 2); | ||
372 | |||
373 | xen_mc_issue(PARAVIRT_LAZY_CPU); | ||
374 | |||
375 | /* | 367 | /* |
376 | * XXX sleazy hack: If we're being called in a lazy-cpu zone, | 368 | * XXX sleazy hack: If we're being called in a lazy-cpu zone, |
377 | * it means we're in a context switch, and %gs has just been | 369 | * it means we're in a context switch, and %gs has just been |
@@ -380,9 +372,30 @@ static void xen_load_tls(struct thread_struct *t, unsigned int cpu) | |||
380 | * Either way, it has been saved, and the new value will get | 372 | * Either way, it has been saved, and the new value will get |
381 | * loaded properly. This will go away as soon as Xen has been | 373 | * loaded properly. This will go away as soon as Xen has been |
382 | * modified to not save/restore %gs for normal hypercalls. | 374 | * modified to not save/restore %gs for normal hypercalls. |
375 | * | ||
376 | * On x86_64, this hack is not used for %gs, because gs points | ||
377 | * to KERNEL_GS_BASE (and uses it for PDA references), so we | ||
378 | * must not zero %gs on x86_64 | ||
379 | * | ||
380 | * For x86_64, we need to zero %fs, otherwise we may get an | ||
381 | * exception between the new %fs descriptor being loaded and | ||
382 | * %fs being effectively cleared at __switch_to(). | ||
383 | */ | 383 | */ |
384 | if (paravirt_get_lazy_mode() == PARAVIRT_LAZY_CPU) | 384 | if (paravirt_get_lazy_mode() == PARAVIRT_LAZY_CPU) { |
385 | #ifdef CONFIG_X86_32 | ||
385 | loadsegment(gs, 0); | 386 | loadsegment(gs, 0); |
387 | #else | ||
388 | loadsegment(fs, 0); | ||
389 | #endif | ||
390 | } | ||
391 | |||
392 | xen_mc_batch(); | ||
393 | |||
394 | load_TLS_descriptor(t, cpu, 0); | ||
395 | load_TLS_descriptor(t, cpu, 1); | ||
396 | load_TLS_descriptor(t, cpu, 2); | ||
397 | |||
398 | xen_mc_issue(PARAVIRT_LAZY_CPU); | ||
386 | } | 399 | } |
387 | 400 | ||
388 | #ifdef CONFIG_X86_64 | 401 | #ifdef CONFIG_X86_64 |