[Devel] [PATCH 3/4] x86_64: make some changes to fs/gs register handling
serue at us.ibm.com
serue at us.ibm.com
Mon Jan 25 17:48:14 PST 2010
From: Serge E. Hallyn <serue at us.ibm.com>
1. always save/restore fs/gs
not just if CONFIG_COMPAT and the task is 64-bit. Pretty
sure that block wasn't doing what it wanted to do anyway :)
2. use rdmsrl for fs/gs for self-checkpoint
<shrug> other code seems to do it. It doesn't seem to make
a difference one way or the other.
3. null out fs/gs if index is set
like __switch_to() does
4. fs and gs are not encoded segments, so don't run them through
check_segment().
Signed-off-by: Serge E. Hallyn <serue at us.ibm.com>
---
arch/x86/kernel/checkpoint_64.c | 32 ++++++++++++++++----------------
1 files changed, 16 insertions(+), 16 deletions(-)
diff --git a/arch/x86/kernel/checkpoint_64.c b/arch/x86/kernel/checkpoint_64.c
index ee01e17..46f2256 100644
--- a/arch/x86/kernel/checkpoint_64.c
+++ b/arch/x86/kernel/checkpoint_64.c
@@ -162,21 +162,26 @@ void save_cpu_regs(struct ckpt_hdr_cpu *h, struct task_struct *t)
savesegment(es, _es);
savesegment(fs, _fs);
savesegment(gs, _gs);
+ rdmsrl(MSR_FS_BASE, h->fs);
+ rdmsrl(MSR_KERNEL_GS_BASE, h->gs);
} else {
_ds = t->thread.ds;
_es = t->thread.es;
_fs = t->thread.fsindex;
_gs = t->thread.gsindex;
+ h->fs = t->thread.fs;
+ h->gs = t->thread.gs;
}
h->ds = encode_segment(_ds);
h->es = encode_segment(_es);
h->fsindex = encode_segment(_fs);
h->gsindex = encode_segment(_gs);
- if (!test_tsk_thread_flag(t, TIF_IA32)) {
- h->fs = t->thread.fs;
- h->gs = t->thread.gs;
- }
+ /* see comment in __switch_to() */
+ if (_fs)
+ h->fs = 0;
+ if (_gs)
+ h->gs = 0;
/*
* for checkpoint in process context (from within a container),
@@ -203,12 +208,6 @@ int load_cpu_regs(struct ckpt_hdr_cpu *h, struct task_struct *t)
!check_segment(h->fsindex) || !check_segment(h->gsindex))
return -EINVAL;
-#ifdef CONFIG_COMPAT
- if (test_tsk_thread_flag(t, TIF_IA32) &&
- (!check_segment(h->fs) || !check_segment(h->gs)))
- return -EINVAL;
-#endif
-
regs->r15 = h->r15;
regs->r14 = h->r14;
regs->r13 = h->r13;
@@ -240,18 +239,19 @@ int load_cpu_regs(struct ckpt_hdr_cpu *h, struct task_struct *t)
thread->fsindex = decode_segment(h->fsindex);
thread->gsindex = decode_segment(h->gsindex);
-#ifdef CONFIG_COMPAT
- if (!test_tsk_thread_flag(t, TIF_IA32)) {
- thread->fs = h->fs;
- thread->gs = h->gs;
- }
-#endif
+ thread->fs = h->fs;
+ thread->gs = h->gs;
/* XXX - unsure is this really needed ... */
loadsegment(fs, thread->fsindex);
if (thread->fs)
wrmsrl(MSR_FS_BASE, thread->fs);
load_gs_index(thread->gsindex);
+ /*
+ * when we switch to user-space, the MSR_KERNEL_GS_BASE
+ * will be moved back to MSR_GS_BASE.
+ * http://lists.openwall.net/linux-kernel/2008/11/18/340
+ */
if (thread->gs)
wrmsrl(MSR_KERNEL_GS_BASE, thread->gs);
--
1.6.0.6
_______________________________________________
Containers mailing list
Containers at lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/containers
More information about the Devel
mailing list