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>
This commit is contained in:
parent
4a5c3e77f7
commit
8a95408e18
|
@ -364,14 +364,6 @@ static void load_TLS_descriptor(struct thread_struct *t,
|
||||||
|
|
||||||
static void xen_load_tls(struct thread_struct *t, unsigned int cpu)
|
static void xen_load_tls(struct thread_struct *t, unsigned int cpu)
|
||||||
{
|
{
|
||||||
xen_mc_batch();
|
|
||||||
|
|
||||||
load_TLS_descriptor(t, cpu, 0);
|
|
||||||
load_TLS_descriptor(t, cpu, 1);
|
|
||||||
load_TLS_descriptor(t, cpu, 2);
|
|
||||||
|
|
||||||
xen_mc_issue(PARAVIRT_LAZY_CPU);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* XXX sleazy hack: If we're being called in a lazy-cpu zone,
|
* XXX sleazy hack: If we're being called in a lazy-cpu zone,
|
||||||
* it means we're in a context switch, and %gs has just been
|
* 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)
|
||||||
* Either way, it has been saved, and the new value will get
|
* Either way, it has been saved, and the new value will get
|
||||||
* loaded properly. This will go away as soon as Xen has been
|
* loaded properly. This will go away as soon as Xen has been
|
||||||
* modified to not save/restore %gs for normal hypercalls.
|
* modified to not save/restore %gs for normal hypercalls.
|
||||||
|
*
|
||||||
|
* On x86_64, this hack is not used for %gs, because gs points
|
||||||
|
* to KERNEL_GS_BASE (and uses it for PDA references), so we
|
||||||
|
* must not zero %gs on x86_64
|
||||||
|
*
|
||||||
|
* For x86_64, we need to zero %fs, otherwise we may get an
|
||||||
|
* exception between the new %fs descriptor being loaded and
|
||||||
|
* %fs being effectively cleared at __switch_to().
|
||||||
*/
|
*/
|
||||||
if (paravirt_get_lazy_mode() == PARAVIRT_LAZY_CPU)
|
if (paravirt_get_lazy_mode() == PARAVIRT_LAZY_CPU) {
|
||||||
|
#ifdef CONFIG_X86_32
|
||||||
loadsegment(gs, 0);
|
loadsegment(gs, 0);
|
||||||
|
#else
|
||||||
|
loadsegment(fs, 0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
xen_mc_batch();
|
||||||
|
|
||||||
|
load_TLS_descriptor(t, cpu, 0);
|
||||||
|
load_TLS_descriptor(t, cpu, 1);
|
||||||
|
load_TLS_descriptor(t, cpu, 2);
|
||||||
|
|
||||||
|
xen_mc_issue(PARAVIRT_LAZY_CPU);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_X86_64
|
#ifdef CONFIG_X86_64
|
||||||
|
|
Loading…
Reference in a new issue