mirror of
https://github.com/checkpoint-restore/criu
synced 2025-09-04 08:15:37 +00:00
kernel: Explicit registers assignment
Since types might be changed one day Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
This commit is contained in:
@@ -27,7 +27,7 @@ Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
|
|||||||
arch/x86/include/asm/elf.h | 3
|
arch/x86/include/asm/elf.h | 3
|
||||||
arch/x86/include/asm/elf_ckpt.h | 80 ++++++++
|
arch/x86/include/asm/elf_ckpt.h | 80 ++++++++
|
||||||
arch/x86/kernel/Makefile | 2
|
arch/x86/kernel/Makefile | 2
|
||||||
arch/x86/kernel/elf_ckpt.c | 109 +++++++++++
|
arch/x86/kernel/elf_ckpt.c | 145 +++++++++++++++
|
||||||
arch/x86/vdso/vma.c | 22 ++
|
arch/x86/vdso/vma.c | 22 ++
|
||||||
fs/Kconfig.binfmt | 11 +
|
fs/Kconfig.binfmt | 11 +
|
||||||
fs/Makefile | 1
|
fs/Makefile | 1
|
||||||
@@ -36,7 +36,7 @@ Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
|
|||||||
fs/exec.c | 27 +-
|
fs/exec.c | 27 +-
|
||||||
include/linux/binfmts.h | 1
|
include/linux/binfmts.h | 1
|
||||||
include/linux/elf_ckpt.h | 90 +++++++++
|
include/linux/elf_ckpt.h | 90 +++++++++
|
||||||
12 files changed, 732 insertions(+), 12 deletions(-)
|
12 files changed, 768 insertions(+), 12 deletions(-)
|
||||||
|
|
||||||
Index: linux-2.6.git/arch/x86/include/asm/elf.h
|
Index: linux-2.6.git/arch/x86/include/asm/elf.h
|
||||||
===================================================================
|
===================================================================
|
||||||
@@ -154,7 +154,7 @@ Index: linux-2.6.git/arch/x86/kernel/elf_ckpt.c
|
|||||||
===================================================================
|
===================================================================
|
||||||
--- /dev/null
|
--- /dev/null
|
||||||
+++ linux-2.6.git/arch/x86/kernel/elf_ckpt.c
|
+++ linux-2.6.git/arch/x86/kernel/elf_ckpt.c
|
||||||
@@ -0,0 +1,109 @@
|
@@ -0,0 +1,145 @@
|
||||||
+#include <linux/module.h>
|
+#include <linux/module.h>
|
||||||
+#include <linux/kernel.h>
|
+#include <linux/kernel.h>
|
||||||
+#include <linux/fs.h>
|
+#include <linux/fs.h>
|
||||||
@@ -194,30 +194,66 @@ Index: linux-2.6.git/arch/x86/kernel/elf_ckpt.c
|
|||||||
+
|
+
|
||||||
+#ifdef CONFIG_X86_64
|
+#ifdef CONFIG_X86_64
|
||||||
+
|
+
|
||||||
|
+#define cp_reg(s, d, r) s.r = d.r
|
||||||
|
+
|
||||||
+int load_elf_ckpt_arch(struct task_struct *tsk, struct pt_regs *regs,
|
+int load_elf_ckpt_arch(struct task_struct *tsk, struct pt_regs *regs,
|
||||||
+ struct core_entry *core_entry)
|
+ struct core_entry *core_entry)
|
||||||
+{
|
+{
|
||||||
+ struct ckpt_arch_entry *arch = (struct ckpt_arch_entry *)core_entry->arch;
|
+ struct ckpt_arch_entry *arch = (struct ckpt_arch_entry *)core_entry->arch;
|
||||||
+ struct thread_struct *thread = ¤t->thread;
|
+ struct thread_struct *thread = ¤t->thread;
|
||||||
+ struct pt_regs *pt_regs_me = task_pt_regs(current);
|
+
|
||||||
|
+ struct user_regs_struct gpregs;
|
||||||
|
+ struct user_i387_struct fpregs;
|
||||||
|
+
|
||||||
+ mm_segment_t old_fs;
|
+ mm_segment_t old_fs;
|
||||||
+ int i, ret;
|
+ int i, ret;
|
||||||
+
|
+
|
||||||
+ BUILD_BUG_ON(CKPT_GDT_ENTRY_TLS_ENTRIES != GDT_ENTRY_TLS_ENTRIES);
|
+ BUILD_BUG_ON(CKPT_GDT_ENTRY_TLS_ENTRIES != GDT_ENTRY_TLS_ENTRIES);
|
||||||
+ BUILD_BUG_ON(sizeof(struct ckpt_arch_entry) > CKPT_ARCH_SIZE);
|
+ BUILD_BUG_ON(sizeof(struct ckpt_arch_entry) > CKPT_ARCH_SIZE);
|
||||||
+
|
+
|
||||||
|
+ memset(&gpregs, 0, sizeof(gpregs));
|
||||||
|
+ memset(&fpregs, 0, sizeof(fpregs));
|
||||||
|
+
|
||||||
+ /*
|
+ /*
|
||||||
+ * Registers setup.
|
+ * Registers setup.
|
||||||
+ */
|
+ */
|
||||||
+
|
+
|
||||||
|
+ cp_reg(arch->gpregs, gpregs, r15);
|
||||||
|
+ cp_reg(arch->gpregs, gpregs, r14);
|
||||||
|
+ cp_reg(arch->gpregs, gpregs, r13);
|
||||||
|
+ cp_reg(arch->gpregs, gpregs, r12);
|
||||||
|
+ cp_reg(arch->gpregs, gpregs, bp);
|
||||||
|
+ cp_reg(arch->gpregs, gpregs, bx);
|
||||||
|
+ cp_reg(arch->gpregs, gpregs, r11);
|
||||||
|
+ cp_reg(arch->gpregs, gpregs, r10);
|
||||||
|
+ cp_reg(arch->gpregs, gpregs, r9);
|
||||||
|
+ cp_reg(arch->gpregs, gpregs, r8);
|
||||||
|
+ cp_reg(arch->gpregs, gpregs, ax);
|
||||||
|
+ cp_reg(arch->gpregs, gpregs, cx);
|
||||||
|
+ cp_reg(arch->gpregs, gpregs, dx);
|
||||||
|
+ cp_reg(arch->gpregs, gpregs, si);
|
||||||
|
+ cp_reg(arch->gpregs, gpregs, di);
|
||||||
|
+ cp_reg(arch->gpregs, gpregs, orig_ax);
|
||||||
|
+ cp_reg(arch->gpregs, gpregs, ip);
|
||||||
|
+ cp_reg(arch->gpregs, gpregs, cs);
|
||||||
|
+ cp_reg(arch->gpregs, gpregs, flags);
|
||||||
|
+ cp_reg(arch->gpregs, gpregs, sp);
|
||||||
|
+ cp_reg(arch->gpregs, gpregs, ss);
|
||||||
|
+ cp_reg(arch->gpregs, gpregs, fs_base);
|
||||||
|
+ cp_reg(arch->gpregs, gpregs, gs_base);
|
||||||
|
+ cp_reg(arch->gpregs, gpregs, ds);
|
||||||
|
+ cp_reg(arch->gpregs, gpregs, es);
|
||||||
|
+ cp_reg(arch->gpregs, gpregs, fs);
|
||||||
|
+ cp_reg(arch->gpregs, gpregs, gs);
|
||||||
|
+
|
||||||
+ old_fs = get_fs();
|
+ old_fs = get_fs();
|
||||||
+ set_fs(KERNEL_DS);
|
+ set_fs(KERNEL_DS);
|
||||||
+ ret = arch_ptrace(current, PTRACE_SETREGS, 0, (unsigned long)&arch->gpregs);
|
+ ret = arch_ptrace(current, PTRACE_SETREGS, 0, (unsigned long)&gpregs);
|
||||||
+ set_fs(old_fs);
|
+ set_fs(old_fs);
|
||||||
+ if (ret)
|
+ if (ret)
|
||||||
+ goto out;
|
+ goto out;
|
||||||
+
|
+
|
||||||
+ *regs = *pt_regs_me;
|
+ *regs = *task_pt_regs(current);
|
||||||
+
|
+
|
||||||
+ thread->usersp = arch->gpregs.sp;
|
+ thread->usersp = arch->gpregs.sp;
|
||||||
+ thread->ds = arch->gpregs.ds;
|
+ thread->ds = arch->gpregs.ds;
|
||||||
@@ -233,23 +269,27 @@ Index: linux-2.6.git/arch/x86/kernel/elf_ckpt.c
|
|||||||
+ thread->tls_array[i].b = arch->tls_array[i].b;
|
+ thread->tls_array[i].b = arch->tls_array[i].b;
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ if (arch->gpregs.fs_base) {
|
|
||||||
+ ret = do_arch_prctl(current, ARCH_SET_FS, arch->gpregs.fs_base);
|
|
||||||
+ if (ret)
|
|
||||||
+ goto out_put;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (arch->gpregs.gs_base) {
|
|
||||||
+ ret = do_arch_prctl(current, ARCH_SET_GS, arch->gpregs.gs_base);
|
|
||||||
+ if (ret)
|
|
||||||
+ goto out_put;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ /* Restoring FPU */
|
+ /* Restoring FPU */
|
||||||
+ if (core_entry->task_flags & PF_USED_MATH) {
|
+ if (core_entry->task_flags & PF_USED_MATH) {
|
||||||
|
+
|
||||||
|
+ cp_reg(arch->fpregs, fpregs, cwd);
|
||||||
|
+ cp_reg(arch->fpregs, fpregs, swd);
|
||||||
|
+ cp_reg(arch->fpregs, fpregs, twd);
|
||||||
|
+ cp_reg(arch->fpregs, fpregs, fop);
|
||||||
|
+ cp_reg(arch->fpregs, fpregs, rip);
|
||||||
|
+ cp_reg(arch->fpregs, fpregs, rdp);
|
||||||
|
+ cp_reg(arch->fpregs, fpregs, mxcsr);
|
||||||
|
+ cp_reg(arch->fpregs, fpregs, mxcsr_mask);
|
||||||
|
+
|
||||||
|
+ for (i = 0; i < ARRAY_SIZE(arch->fpregs.st_space); i++)
|
||||||
|
+ cp_reg(arch->fpregs, fpregs, st_space[i]);
|
||||||
|
+
|
||||||
|
+ for (i = 0; i < ARRAY_SIZE(arch->fpregs.xmm_space); i++)
|
||||||
|
+ cp_reg(arch->fpregs, fpregs, xmm_space[i]);
|
||||||
|
+
|
||||||
+ old_fs = get_fs();
|
+ old_fs = get_fs();
|
||||||
+ set_fs(KERNEL_DS);
|
+ set_fs(KERNEL_DS);
|
||||||
+ ret = arch_ptrace(current, PTRACE_SETFPREGS, 0, (unsigned long)&arch->fpregs);
|
+ ret = arch_ptrace(current, PTRACE_SETFPREGS, 0, (unsigned long)&fpregs);
|
||||||
+ set_fs(old_fs);
|
+ set_fs(old_fs);
|
||||||
+ if (ret)
|
+ if (ret)
|
||||||
+ goto out;
|
+ goto out;
|
||||||
@@ -257,10 +297,6 @@ Index: linux-2.6.git/arch/x86/kernel/elf_ckpt.c
|
|||||||
+
|
+
|
||||||
+out:
|
+out:
|
||||||
+ return ret;
|
+ return ret;
|
||||||
+
|
|
||||||
+out_put:
|
|
||||||
+ put_cpu();
|
|
||||||
+ goto out;
|
|
||||||
+}
|
+}
|
||||||
+
|
+
|
||||||
+#endif /* CONFIG_X86_64 */
|
+#endif /* CONFIG_X86_64 */
|
||||||
|
Reference in New Issue
Block a user