[PATCH 28 of 36] Save %fs and %gs before load_TLS() and arch_leave_lazy_cpu_mode()

Jeremy Fitzhardinge
2008-06-25T04:45:56Z

We must do this because load_TLS() may need to clear %fs and %gs,
such (e.g. under Xen).

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
---
arch/x86/kernel/process_64.c | 17 +++++++++++------
1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -579,6 +579,7 @@
*next = &next_p->thread;
int cpu = smp_processor_id();
struct tss_struct *tss = &per_cpu(init_tss, cpu);
+ unsigned fsindex, gsindex;

/* we're going to use this soon, after a few expensive things */
if (next_p->fpu_counter>5)
@@ -601,6 +602,15 @@
if (unlikely(next->ds | prev->ds))
loadsegment(ds, next->ds);

+
+ /* We must save %fs and %gs before load_TLS() because
+ * %fs and %gs may be cleared by load_TLS().
+ *
+ * (e.g. xen_load_tls())
+ */
+ savesegment(fs, fsindex);
+ savesegment(gs, gsindex);
+
load_TLS(next, cpu);

/*
@@ -616,8 +626,6 @@
* Switch FS and GS.
*/
{
- unsigned fsindex;
- savesegment(fs, fsindex);
/* segment register != 0 always requires a reload.
also reload when it has changed.
when prev process used 64bit base always reload
@@ -635,10 +643,7 @@
if (next->fs)
wrmsrl(MSR_FS_BASE, next->fs);
prev->fsindex = fsindex;
- }
- {
- unsigned gsindex;
- savesegment(gs, gsindex);
+
if (unlikely(gsindex | next->gsindex | prev->gs)) {
load_gs_index(next->gsindex);
if (gsindex)