Commit c3553db6 authored by Cyrill Gorcunov's avatar Cyrill Gorcunov

kernel: Use ptrace helper to restore GPRs

This shrinks code a bit
Signed-off-by: 's avatarCyrill Gorcunov <gorcunov@gmail.com>
parent a997fcf6
...@@ -27,16 +27,16 @@ Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org> ...@@ -27,16 +27,16 @@ 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 | 120 ++++++++++++ arch/x86/kernel/elf_ckpt.c | 109 +++++++++++
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
fs/binfmt_elf.c | 17 + fs/binfmt_elf.c | 17 +
fs/binfmt_elf_ckpt.c | 379 ++++++++++++++++++++++++++++++++++++++++ fs/binfmt_elf_ckpt.c | 381 ++++++++++++++++++++++++++++++++++++++++
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, 741 insertions(+), 12 deletions(-) 12 files changed, 732 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 ...@@ -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,120 @@ @@ -0,0 +1,109 @@
+#include <linux/module.h> +#include <linux/module.h>
+#include <linux/kernel.h> +#include <linux/kernel.h>
+#include <linux/fs.h> +#include <linux/fs.h>
...@@ -197,8 +197,9 @@ Index: linux-2.6.git/arch/x86/kernel/elf_ckpt.c ...@@ -197,8 +197,9 @@ Index: linux-2.6.git/arch/x86/kernel/elf_ckpt.c
+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 thread_struct *thread = &current->thread;
+ 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 = &current->thread;
+ struct pt_regs *pt_regs_me = task_pt_regs(current);
+ mm_segment_t old_fs; + mm_segment_t old_fs;
+ int i, ret; + int i, ret;
+ +
...@@ -209,26 +210,14 @@ Index: linux-2.6.git/arch/x86/kernel/elf_ckpt.c ...@@ -209,26 +210,14 @@ Index: linux-2.6.git/arch/x86/kernel/elf_ckpt.c
+ * Registers setup. + * Registers setup.
+ */ + */
+ +
+ regs->ip = arch->gpregs.ip; + old_fs = get_fs();
+ regs->sp = arch->gpregs.sp; + set_fs(KERNEL_DS);
+ regs->cs = arch->gpregs.cs; + ret = arch_ptrace(current, PTRACE_SETREGS, 0, (unsigned long)&arch->gpregs);
+ regs->ss = arch->gpregs.ss; + set_fs(old_fs);
+ regs->flags = arch->gpregs.flags; + if (ret)
+ regs->r15 = arch->gpregs.r15; + goto out;
+ regs->r14 = arch->gpregs.r14; +
+ regs->r13 = arch->gpregs.r13; + *regs = *pt_regs_me;
+ regs->r12 = arch->gpregs.r12;
+ regs->bp = arch->gpregs.bp;
+ regs->bx = arch->gpregs.bx;
+ regs->r11 = arch->gpregs.r11;
+ regs->r10 = arch->gpregs.r10;
+ regs->r8 = arch->gpregs.r8;
+ regs->ax = arch->gpregs.ax;
+ regs->cx = arch->gpregs.cx;
+ regs->dx = arch->gpregs.dx;
+ regs->si = arch->gpregs.si;
+ regs->di = arch->gpregs.di;
+ regs->orig_ax = arch->gpregs.orig_ax;
+ +
+ thread->usersp = arch->gpregs.sp; + thread->usersp = arch->gpregs.sp;
+ thread->ds = arch->gpregs.ds; + thread->ds = arch->gpregs.ds;
...@@ -388,7 +377,7 @@ Index: linux-2.6.git/fs/binfmt_elf_ckpt.c ...@@ -388,7 +377,7 @@ Index: linux-2.6.git/fs/binfmt_elf_ckpt.c
=================================================================== ===================================================================
--- /dev/null --- /dev/null
+++ linux-2.6.git/fs/binfmt_elf_ckpt.c +++ linux-2.6.git/fs/binfmt_elf_ckpt.c
@@ -0,0 +1,379 @@ @@ -0,0 +1,381 @@
+#include <linux/module.h> +#include <linux/module.h>
+#include <linux/kernel.h> +#include <linux/kernel.h>
+#include <linux/fs.h> +#include <linux/fs.h>
...@@ -443,7 +432,10 @@ Index: linux-2.6.git/fs/binfmt_elf_ckpt.c ...@@ -443,7 +432,10 @@ Index: linux-2.6.git/fs/binfmt_elf_ckpt.c
+ unsigned long start_code, end_code, start_data, end_data; + unsigned long start_code, end_code, start_data, end_data;
+ unsigned long start_brk, brk, start_stack; + unsigned long start_brk, brk, start_stack;
+ unsigned long elf_bss, elf_brk; + unsigned long elf_bss, elf_brk;
+ unsigned long vdso; +
+#ifdef ARCH_HAS_SETUP_ADDITIONAL_PAGES
+ unsigned long vdso = -1UL;
+#endif
+ +
+ struct core_entry *core_entry = NULL; + struct core_entry *core_entry = NULL;
+ int i, ret = -ENOEXEC; + int i, ret = -ENOEXEC;
...@@ -470,8 +462,6 @@ Index: linux-2.6.git/fs/binfmt_elf_ckpt.c ...@@ -470,8 +462,6 @@ Index: linux-2.6.git/fs/binfmt_elf_ckpt.c
+ start_brk = -1UL; + start_brk = -1UL;
+ brk = -1UL; + brk = -1UL;
+ +
+ vdso = -1UL;
+
+ fa = flex_array_alloc(sizeof(vma_entry), elf_ex->e_phnum, GFP_KERNEL); + fa = flex_array_alloc(sizeof(vma_entry), elf_ex->e_phnum, GFP_KERNEL);
+ if (!fa || flex_array_prealloc(fa, 0, elf_ex->e_phnum, GFP_KERNEL)) { + if (!fa || flex_array_prealloc(fa, 0, elf_ex->e_phnum, GFP_KERNEL)) {
+ ret = -ENOMEM; + ret = -ENOMEM;
...@@ -580,8 +570,10 @@ Index: linux-2.6.git/fs/binfmt_elf_ckpt.c ...@@ -580,8 +570,10 @@ Index: linux-2.6.git/fs/binfmt_elf_ckpt.c
+ if (vma_entry_ptr->status & VMA_AREA_HEAP) + if (vma_entry_ptr->status & VMA_AREA_HEAP)
+ start_brk = vma_entry_ptr->start; + start_brk = vma_entry_ptr->start;
+ +
+#ifdef ARCH_HAS_SETUP_ADDITIONAL_PAGES
+ if (vma_entry_ptr->status & VMA_AREA_VDSO) + if (vma_entry_ptr->status & VMA_AREA_VDSO)
+ vdso = vma_entry_ptr->start; + vdso = vma_entry_ptr->start;
+#endif
+ +
+ /* Anything special should be ignored */ + /* Anything special should be ignored */
+ if (!(vma_entry_ptr->status & VMA_AREA_REGULAR)) + if (!(vma_entry_ptr->status & VMA_AREA_REGULAR))
...@@ -620,7 +612,6 @@ Index: linux-2.6.git/fs/binfmt_elf_ckpt.c ...@@ -620,7 +612,6 @@ Index: linux-2.6.git/fs/binfmt_elf_ckpt.c
+ } + }
+ +
+ /* + /*
+ * FIXME
+ * Some heuristics to guess previously loaded real + * Some heuristics to guess previously loaded real
+ * elf file structure. Probably this things should + * elf file structure. Probably this things should
+ * be exported via /proc somewhere instead. + * be exported via /proc somewhere instead.
...@@ -740,7 +731,7 @@ Index: linux-2.6.git/fs/binfmt_elf_ckpt.c ...@@ -740,7 +731,7 @@ Index: linux-2.6.git/fs/binfmt_elf_ckpt.c
+ * Architecture specific setup for registers + * Architecture specific setup for registers
+ * and friends, it's done lately since if + * and friends, it's done lately since if
+ * an error happened before there is no much + * an error happened before there is no much
+ * point to setup this kind of things at all. + * point to setup arch-specific things at all.
+ */ + */
+ ret = load_elf_ckpt_arch(current, regs, core_entry); + ret = load_elf_ckpt_arch(current, regs, core_entry);
+ if (ret) + if (ret)
...@@ -839,11 +830,11 @@ Index: linux-2.6.git/include/linux/elf_ckpt.h ...@@ -839,11 +830,11 @@ Index: linux-2.6.git/include/linux/elf_ckpt.h
+#ifndef _LINUX_ELF_CHECKPOINT_H +#ifndef _LINUX_ELF_CHECKPOINT_H
+#define _LINUX_ELF_CHECKPOINT_H +#define _LINUX_ELF_CHECKPOINT_H
+ +
+#ifdef __KERNEL__
+
+#include <linux/types.h> +#include <linux/types.h>
+#include <linux/elf-em.h> +#include <linux/elf-em.h>
+ +
+#ifdef __KERNEL__
+
+#include <asm/elf.h> +#include <asm/elf.h>
+#include <asm/elf_ckpt.h> +#include <asm/elf_ckpt.h>
+ +
...@@ -906,7 +897,7 @@ Index: linux-2.6.git/include/linux/elf_ckpt.h ...@@ -906,7 +897,7 @@ Index: linux-2.6.git/include/linux/elf_ckpt.h
+ +
+struct core_entry { +struct core_entry {
+ struct image_header header; + struct image_header header;
+ __u8 arch[CKPT_ARCH_SIZE]; /* should be enough for all */ + __u8 arch[CKPT_ARCH_SIZE]; /* should be enough for all archs */
+ __u32 task_personality; + __u32 task_personality;
+ __u8 task_comm[CKPT_TASK_COMM_LEN]; + __u8 task_comm[CKPT_TASK_COMM_LEN];
+ __u32 task_flags; + __u32 task_flags;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment