Similar to other select syscalls (fork, clone, execve), sys_restart
needs to access the pt_regs structure, so that it can modify it to
restore the original state from the time of the checkpoint.

(This is less of an issue for x86-32, however is required for those
architectures that otherwise save/restore partial state (e.g. not all
registers) during syscall entry/exit, like x86-64.

This patch prepares to support c/r on x86-64, specifically:

* Changes the syscall prototype and definition to accept the pt_regs
  struct as an argument (into %eax register).

* Move arch/x86/mm/checkpoint*.c to arch/x86/kernel/...

* Split 32bit-dependent part of arch/x86/kernel/checkpoint.c into a
  new arch/x86/kernel/checkpoint_32.c

Signed-off-by: Oren Laadan <[email protected]>
---
 arch/x86/include/asm/syscalls.h      |    5 +
 arch/x86/kernel/Makefile             |    8 +
 arch/x86/{mm => kernel}/checkpoint.c |  293 +++++++++-------------------------
 arch/x86/kernel/checkpoint_32.c      |  191 ++++++++++++++++++++++
 arch/x86/kernel/entry_32.S           |    3 +
 arch/x86/kernel/syscall_table_32.S   |    2 +-
 arch/x86/mm/Makefile                 |    2 -
 checkpoint/sys.c                     |    5 +-
 include/linux/checkpoint.h           |    2 +
 include/linux/syscalls.h             |    2 -
 10 files changed, 288 insertions(+), 225 deletions(-)
 rename arch/x86/{mm => kernel}/checkpoint.c (77%)
 create mode 100644 arch/x86/kernel/checkpoint_32.c

diff --git a/arch/x86/include/asm/syscalls.h b/arch/x86/include/asm/syscalls.h
index 2cadb8e..1079447 100644
--- a/arch/x86/include/asm/syscalls.h
+++ b/arch/x86/include/asm/syscalls.h
@@ -43,6 +43,11 @@ int sys_clone(struct pt_regs *);
 int sys_eclone(struct pt_regs *);
 int sys_execve(struct pt_regs *);
 
+/* kernel/checkpoint_32.c */
+#ifdef CONFIG_CHECKPOINT
+long sys_restart(struct pt_regs *);
+#endif
+
 /* kernel/signal.c */
 asmlinkage int sys_sigsuspend(int, int, old_sigset_t);
 asmlinkage int sys_sigaction(int, const struct old_sigaction __user *,
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index d8e5d0c..2821fd6 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -117,6 +117,14 @@ obj-$(CONFIG_X86_CHECK_BIOS_CORRUPTION) += check.o
 
 obj-$(CONFIG_SWIOTLB)                  += pci-swiotlb.o
 
+obj-$(CONFIG_CHECKPOINT)       += checkpoint.o
+
+###
+# 32 bit specific files
+ifeq ($(CONFIG_X86_32),y)
+       obj-$(CONFIG_CHECKPOINT)        += checkpoint_32.o
+endif
+
 ###
 # 64 bit specific files
 ifeq ($(CONFIG_X86_64),y)
diff --git a/arch/x86/mm/checkpoint.c b/arch/x86/kernel/checkpoint.c
similarity index 77%
rename from arch/x86/mm/checkpoint.c
rename to arch/x86/kernel/checkpoint.c
index 2752fdf..fbe9521 100644
--- a/arch/x86/mm/checkpoint.c
+++ b/arch/x86/kernel/checkpoint.c
@@ -18,59 +18,11 @@
 #include <linux/checkpoint.h>
 #include <linux/checkpoint_hdr.h>
 
-/*
- * helpers to encode/decode/validate registers/segments/eflags
- */
-
-static int check_eflags(__u32 eflags)
-{
-#define X86_EFLAGS_CKPT_MASK  \
-       (X86_EFLAGS_CF | X86_EFLAGS_PF | X86_EFLAGS_AF | X86_EFLAGS_ZF | \
-        X86_EFLAGS_SF | X86_EFLAGS_TF | X86_EFLAGS_DF | X86_EFLAGS_OF | \
-        X86_EFLAGS_NT | X86_EFLAGS_AC | X86_EFLAGS_ID | X86_EFLAGS_RF)
-
-       if ((eflags & ~X86_EFLAGS_CKPT_MASK) != (X86_EFLAGS_IF | 0x2))
-               return 0;
-       return 1;
-}
-
-static void restore_eflags(struct pt_regs *regs, __u32 eflags)
-{
-       /*
-        * A task may have had X86_EFLAGS_RF set at checkpoint, .e.g:
-        * 1) It ran in a KVM guest, and the guest was being debugged,
-        * 2) The kernel was debugged using kgbd,
-        * 3) From Intel's manual: "When calling an event handler,
-        *    Intel 64 and IA-32 processors establish the value of the
-        *    RF flag in the EFLAGS image pushed on the stack:
-        *  - For any fault-class exception except a debug exception
-        *    generated in response to an instruction breakpoint, the
-        *    value pushed for RF is 1.
-        *  - For any interrupt arriving after any iteration of a
-        *    repeated string instruction but the last iteration, the
-        *    value pushed for RF is 1.
-        *  - For any trap-class exception generated by any iteration
-        *    of a repeated string instruction but the last iteration,
-        *    the value pushed for RF is 1.
-        *  - For other cases, the value pushed for RF is the value
-        *    that was in EFLAG.RF at the time the event handler was
-        *    called.
-        *  [from: http://www.intel.com/Assets/PDF/manual/253668.pdf]
-        *
-        * The RF flag may be set in EFLAGS by the hardware, or by
-        * kvm/kgdb, or even by the user with ptrace or by setting a
-        * suitable context when returning from a signal handler.
-        *
-        * Therefore, on restart we (1) prserve X86_EFLAGS_RF from
-        * checkpoint time, and (2) preserve a X86_EFLAGS_RF of the
-        * restarting process if it already exists on saved EFLAGS.
-        * Disable preemption to protect EFLAG test-and-change.
-        */
-       preempt_disable();
-       eflags |= (regs->flags & X86_EFLAGS_RF);
-       regs->flags = eflags;
-       preempt_enable();
-}
+extern int check_segment(__u16 seg);
+extern __u16 encode_segment(unsigned short seg);
+extern unsigned short decode_segment(__u16 seg);
+extern void save_cpu_regs(struct ckpt_hdr_cpu *h, struct task_struct *t);
+extern int load_cpu_regs(struct ckpt_hdr_cpu *h, struct task_struct *t);
 
 static int check_tls(struct desc_struct *desc)
 {
@@ -81,70 +33,6 @@ static int check_tls(struct desc_struct *desc)
        return 1;
 }
 
-static int check_segment(__u16 seg)
-{
-       int ret = 0;
-
-       switch (seg) {
-       case CKPT_X86_SEG_NULL:
-       case CKPT_X86_SEG_USER32_CS:
-       case CKPT_X86_SEG_USER32_DS:
-               return 1;
-       }
-       if (seg & CKPT_X86_SEG_TLS) {
-               seg &= ~CKPT_X86_SEG_TLS;
-               if (seg <= GDT_ENTRY_TLS_MAX - GDT_ENTRY_TLS_MIN)
-                       ret = 1;
-       } else if (seg & CKPT_X86_SEG_LDT) {
-               seg &= ~CKPT_X86_SEG_LDT;
-               if (seg <= 0x1fff)
-                       ret = 1;
-       }
-       return ret;
-}
-
-static __u16 encode_segment(unsigned short seg)
-{
-       if (seg == 0)
-               return CKPT_X86_SEG_NULL;
-       BUG_ON((seg & 3) != 3);
-
-       if (seg == __USER_CS)
-               return CKPT_X86_SEG_USER32_CS;
-       if (seg == __USER_DS)
-               return CKPT_X86_SEG_USER32_DS;
-
-       if (seg & 4)
-               return CKPT_X86_SEG_LDT | (seg >> 3);
-
-       seg >>= 3;
-       if (GDT_ENTRY_TLS_MIN <= seg && seg <= GDT_ENTRY_TLS_MAX)
-               return CKPT_X86_SEG_TLS | (seg - GDT_ENTRY_TLS_MIN);
-
-       printk(KERN_ERR "c/r: (decode) bad segment %#hx\n", seg);
-       BUG();
-}
-
-static unsigned short decode_segment(__u16 seg)
-{
-       if (seg == CKPT_X86_SEG_NULL)
-               return 0;
-       if (seg == CKPT_X86_SEG_USER32_CS)
-               return __USER_CS;
-       if (seg == CKPT_X86_SEG_USER32_DS)
-               return __USER_DS;
-
-       if (seg & CKPT_X86_SEG_TLS) {
-               seg &= ~CKPT_X86_SEG_TLS;
-               return ((GDT_ENTRY_TLS_MIN + seg) << 3) | 3;
-       }
-       if (seg & CKPT_X86_SEG_LDT) {
-               seg &= ~CKPT_X86_SEG_LDT;
-               return (seg << 3) | 7;
-       }
-       BUG();
-}
-
 #define CKPT_X86_TIF_UNSUPPORTED   (_TIF_SECCOMP | _TIF_IO_BITMAP)
 
 /**************************************************************************
@@ -153,10 +41,12 @@ static unsigned short decode_segment(__u16 seg)
 
 static int may_checkpoint_thread(struct ckpt_ctx *ctx, struct task_struct *t)
 {
+#ifdef CONFIG_X86_32
        if (t->thread.vm86_info) {
                ckpt_err(ctx, -EBUSY, "%(T)Task in VM86 mode\n");
                return -EBUSY;
        }
+#endif
        if (task_thread_info(t)->flags & CKPT_X86_TIF_UNSUPPORTED) {
                ckpt_err(ctx, -EBUSY, "%(T)Bad thread info flags %#lx\n",
                         task_thread_info(t)->flags);
@@ -195,64 +85,10 @@ int checkpoint_thread(struct ckpt_ctx *ctx, struct 
task_struct *t)
        return ret;
 }
 
-#ifdef CONFIG_X86_32
-
-static void save_cpu_regs(struct ckpt_hdr_cpu *h, struct task_struct *t)
-{
-       struct thread_struct *thread = &t->thread;
-       struct pt_regs *regs = task_pt_regs(t);
-       unsigned long _gs;
-
-       h->bp = regs->bp;
-       h->bx = regs->bx;
-       h->ax = regs->ax;
-       h->cx = regs->cx;
-       h->dx = regs->dx;
-       h->si = regs->si;
-       h->di = regs->di;
-       h->orig_ax = regs->orig_ax;
-       h->ip = regs->ip;
-
-       h->flags = regs->flags;
-       h->sp = regs->sp;
-
-       h->cs = encode_segment(regs->cs);
-       h->ss = encode_segment(regs->ss);
-       h->ds = encode_segment(regs->ds);
-       h->es = encode_segment(regs->es);
-
-       /*
-        * for checkpoint in process context (from within a container)
-        * the GS segment register should be saved from the hardware;
-        * otherwise it is already saved on the thread structure
-        */
-       if (t == current)
-               _gs = get_user_gs(regs);
-       else
-               _gs = thread->gs;
-
-       h->fsindex = encode_segment(regs->fs);
-       h->gsindex = encode_segment(_gs);
-
-       /*
-        * for checkpoint in process context (from within a container),
-        * the actual syscall is taking place at this very moment; so
-        * we (optimistically) subtitute the future return value (0) of
-        * this syscall into the orig_eax, so that upon restart it will
-        * succeed (or it will endlessly retry checkpoint...)
-        */
-       if (t == current) {
-               BUG_ON(h->orig_ax < 0);
-               h->ax = 0;
-       }
-}
-
 static void save_cpu_debug(struct ckpt_hdr_cpu *h, struct task_struct *t)
 {
        struct thread_struct *thread = &t->thread;
 
-       /* debug regs */
-
        /*
         * for checkpoint in process context (from within a container),
         * get the actual registers; otherwise get the saved values.
@@ -315,8 +151,6 @@ static int checkpoint_cpu_fpu(struct ckpt_ctx *ctx, struct 
task_struct *t)
        return ret;
 }
 
-#endif /* CONFIG_X86_32 */
-
 /* dump the cpu state and registers of a given task */
 int checkpoint_cpu(struct ckpt_ctx *ctx, struct task_struct *t)
 {
@@ -438,6 +272,13 @@ int restore_thread(struct ckpt_ctx *ctx)
        load_TLS(thread, cpu);
        put_cpu();
 
+#if defined(CONFIG_X86_64) && defined(CONFIG_COMPAT)
+       if (h->thread_info_flags & _TIF_IA32)
+               set_thread_flag(TIF_IA32);
+       else
+               clear_thread_flag(TIF_IA32);
+#endif
+
        /* TODO: restore TIF flags as necessary (e.g. TIF_NOTSC) */
 
        ret = 0;
@@ -446,49 +287,6 @@ int restore_thread(struct ckpt_ctx *ctx)
        return ret;
 }
 
-#ifdef CONFIG_X86_32
-
-static int load_cpu_regs(struct ckpt_hdr_cpu *h, struct task_struct *t)
-{
-       struct thread_struct *thread = &t->thread;
-       struct pt_regs *regs = task_pt_regs(t);
-
-       if (!check_eflags(h->flags))
-               return -EINVAL;
-       if (h->cs == CKPT_X86_SEG_NULL)
-               return -EINVAL;
-       if (!check_segment(h->cs) || !check_segment(h->ds) ||
-           !check_segment(h->es) || !check_segment(h->ss) ||
-           !check_segment(h->fsindex) || !check_segment(h->gsindex))
-               return -EINVAL;
-
-       regs->bp = h->bp;
-       regs->bx = h->bx;
-       regs->ax = h->ax;
-       regs->cx = h->cx;
-       regs->dx = h->dx;
-       regs->si = h->si;
-       regs->di = h->di;
-       regs->orig_ax = h->orig_ax;
-       regs->ip = h->ip;
-
-       restore_eflags(regs, h->flags);
-       regs->sp = h->sp;
-
-       regs->ds = decode_segment(h->ds);
-       regs->es = decode_segment(h->es);
-       regs->cs = decode_segment(h->cs);
-       regs->ss = decode_segment(h->ss);
-
-       regs->fs = decode_segment(h->fsindex);
-       regs->gs = decode_segment(h->gsindex);
-
-       thread->gs = regs->gs;
-       lazy_load_gs(regs->gs);
-
-       return 0;
-}
-
 static int load_cpu_debug(struct ckpt_hdr_cpu *h, struct task_struct *t)
 {
        int ret;
@@ -548,7 +346,65 @@ static int restore_cpu_fpu(struct ckpt_ctx *ctx, struct 
task_struct *t)
        return ret;
 }
 
-#endif /* CONFIG_X86_32 */
+static int check_eflags(__u32 eflags)
+{
+#define X86_EFLAGS_CKPT_MASK  \
+       (X86_EFLAGS_CF | X86_EFLAGS_PF | X86_EFLAGS_AF | X86_EFLAGS_ZF | \
+        X86_EFLAGS_SF | X86_EFLAGS_TF | X86_EFLAGS_DF | X86_EFLAGS_OF | \
+        X86_EFLAGS_NT | X86_EFLAGS_AC | X86_EFLAGS_ID | X86_EFLAGS_RF)
+
+       if ((eflags & ~X86_EFLAGS_CKPT_MASK) != (X86_EFLAGS_IF | 0x2))
+               return 0;
+       return 1;
+}
+
+static void restore_eflags(struct pt_regs *regs, __u32 eflags)
+{
+       /*
+        * A task may have had X86_EFLAGS_RF set at checkpoint, .e.g:
+        * 1) It ran in a KVM guest, and the guest was being debugged,
+        * 2) The kernel was debugged using kgbd,
+        * 3) From Intel's manual: "When calling an event handler,
+        *    Intel 64 and IA-32 processors establish the value of the
+        *    RF flag in the EFLAGS image pushed on the stack:
+        *  - For any fault-class exception except a debug exception
+        *    generated in response to an instruction breakpoint, the
+        *    value pushed for RF is 1.
+        *  - For any interrupt arriving after any iteration of a
+        *    repeated string instruction but the last iteration, the
+        *    value pushed for RF is 1.
+        *  - For any trap-class exception generated by any iteration
+        *    of a repeated string instruction but the last iteration,
+        *    the value pushed for RF is 1.
+        *  - For other cases, the value pushed for RF is the value
+        *    that was in EFLAG.RF at the time the event handler was
+        *    called.
+        *  [from: http://www.intel.com/Assets/PDF/manual/253668.pdf]
+        *
+        * The RF flag may be set in EFLAGS by the hardware, or by
+        * kvm/kgdb, or even by the user with ptrace or by setting a
+        * suitable context when returning from a signal handler.
+        *
+        * Therefore, on restart we (1) prserve X86_EFLAGS_RF from
+        * checkpoint time, and (2) preserve a X86_EFLAGS_RF of the
+        * restarting process if it already exists on saved EFLAGS.
+        * Disable preemption to protect EFLAG test-and-change.
+        */
+       preempt_disable();
+       eflags |= (regs->flags & X86_EFLAGS_RF);
+       regs->flags = eflags;
+       preempt_enable();
+}
+
+static int load_cpu_eflags(struct ckpt_hdr_cpu *h, struct task_struct *t)
+{
+       struct pt_regs *regs = task_pt_regs(t);
+
+       if (!check_eflags(h->flags))
+               return -EINVAL;
+       restore_eflags(regs, h->flags);
+       return 0;
+}
 
 /* read the cpu state and registers for the current task */
 int restore_cpu(struct ckpt_ctx *ctx)
@@ -566,6 +422,9 @@ int restore_cpu(struct ckpt_ctx *ctx)
        ret = load_cpu_regs(h, t);
        if (ret < 0)
                goto out;
+       ret = load_cpu_eflags(h, t);
+       if (ret < 0)
+               goto out;
        ret = load_cpu_debug(h, t);
        if (ret < 0)
                goto out;
diff --git a/arch/x86/kernel/checkpoint_32.c b/arch/x86/kernel/checkpoint_32.c
new file mode 100644
index 0000000..d5ea6a0
--- /dev/null
+++ b/arch/x86/kernel/checkpoint_32.c
@@ -0,0 +1,191 @@
+/*
+ *  Checkpoint/restart - architecture specific support for x86_32
+ *
+ *  Copyright (C) 2008-2009 Oren Laadan
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License.  See the file COPYING in the main directory of the Linux
+ *  distribution for more details.
+ */
+
+/* default debug level for output */
+#define CKPT_DFLAG  CKPT_DSYS
+
+#include <asm/desc.h>
+#include <asm/i387.h>
+#include <asm/elf.h>
+
+#include <linux/checkpoint.h>
+#include <linux/checkpoint_hdr.h>
+
+/*
+ * sys_restart needs to access and modify the pt_regs structure to
+ * restore the original state from the time of the checkpoint.
+ */
+long sys_restart(struct pt_regs *regs)
+{
+       unsigned long flags;
+       int fd, logfd;
+       pid_t pid;
+
+       pid = regs->bx;
+       fd = regs->cx;
+       flags = regs->dx;
+       logfd = regs->di;
+
+       return do_sys_restart(pid, fd, flags, logfd);
+}
+
+/* helpers to encode/decode/validate segments */
+
+static int check_segment(__u16 seg)
+{
+       int ret = 0;
+
+       switch (seg) {
+       case CKPT_X86_SEG_NULL:
+       case CKPT_X86_SEG_USER32_CS:
+       case CKPT_X86_SEG_USER32_DS:
+               return 1;
+       }
+       if (seg & CKPT_X86_SEG_TLS) {
+               seg &= ~CKPT_X86_SEG_TLS;
+               if (seg <= GDT_ENTRY_TLS_MAX - GDT_ENTRY_TLS_MIN)
+                       ret = 1;
+       } else if (seg & CKPT_X86_SEG_LDT) {
+               seg &= ~CKPT_X86_SEG_LDT;
+               if (seg <= 0x1fff)
+                       ret = 1;
+       }
+       return ret;
+}
+
+static __u16 encode_segment(unsigned short seg)
+{
+       if (seg == 0)
+               return CKPT_X86_SEG_NULL;
+       BUG_ON((seg & 3) != 3);
+
+       if (seg == __USER_CS)
+               return CKPT_X86_SEG_USER32_CS;
+       if (seg == __USER_DS)
+               return CKPT_X86_SEG_USER32_DS;
+
+       if (seg & 4)
+               return CKPT_X86_SEG_LDT | (seg >> 3);
+
+       seg >>= 3;
+       if (GDT_ENTRY_TLS_MIN <= seg && seg <= GDT_ENTRY_TLS_MAX)
+               return CKPT_X86_SEG_TLS | (seg - GDT_ENTRY_TLS_MIN);
+
+       printk(KERN_ERR "c/r: (decode) bad segment %#hx\n", seg);
+       BUG();
+}
+
+static unsigned short decode_segment(__u16 seg)
+{
+       if (seg == CKPT_X86_SEG_NULL)
+               return 0;
+       if (seg == CKPT_X86_SEG_USER32_CS)
+               return __USER_CS;
+       if (seg == CKPT_X86_SEG_USER32_DS)
+               return __USER_DS;
+
+       if (seg & CKPT_X86_SEG_TLS) {
+               seg &= ~CKPT_X86_SEG_TLS;
+               return ((GDT_ENTRY_TLS_MIN + seg) << 3) | 3;
+       }
+       if (seg & CKPT_X86_SEG_LDT) {
+               seg &= ~CKPT_X86_SEG_LDT;
+               return (seg << 3) | 7;
+       }
+       BUG();
+}
+
+void save_cpu_regs(struct ckpt_hdr_cpu *h, struct task_struct *t)
+{
+       struct thread_struct *thread = &t->thread;
+       struct pt_regs *regs = task_pt_regs(t);
+       unsigned long _gs;
+
+       h->bp = regs->bp;
+       h->bx = regs->bx;
+       h->ax = regs->ax;
+       h->cx = regs->cx;
+       h->dx = regs->dx;
+       h->si = regs->si;
+       h->di = regs->di;
+       h->orig_ax = regs->orig_ax;
+       h->ip = regs->ip;
+
+       h->flags = regs->flags;
+       h->sp = regs->sp;
+
+       h->cs = encode_segment(regs->cs);
+       h->ss = encode_segment(regs->ss);
+       h->ds = encode_segment(regs->ds);
+       h->es = encode_segment(regs->es);
+
+       /*
+        * for checkpoint in process context (from within a container)
+        * the GS segment register should be saved from the hardware;
+        * otherwise it is already saved on the thread structure
+        */
+       if (t == current)
+               _gs = get_user_gs(regs);
+       else
+               _gs = thread->gs;
+
+       h->fsindex = encode_segment(regs->fs);
+       h->gsindex = encode_segment(_gs);
+
+       /*
+        * for checkpoint in process context (from within a container),
+        * the actual syscall is taking place at this very moment; so
+        * we (optimistically) subtitute the future return value (0) of
+        * this syscall into the orig_eax, so that upon restart it will
+        * succeed (or it will endlessly retry checkpoint...)
+        */
+       if (t == current) {
+               BUG_ON(h->orig_ax < 0);
+               h->ax = 0;
+       }
+}
+
+int load_cpu_regs(struct ckpt_hdr_cpu *h, struct task_struct *t)
+{
+       struct thread_struct *thread = &t->thread;
+       struct pt_regs *regs = task_pt_regs(t);
+
+       if (h->cs == CKPT_X86_SEG_NULL)
+               return -EINVAL;
+       if (!check_segment(h->cs) || !check_segment(h->ds) ||
+           !check_segment(h->es) || !check_segment(h->ss) ||
+           !check_segment(h->fsindex) || !check_segment(h->gsindex))
+               return -EINVAL;
+
+       regs->bp = h->bp;
+       regs->bx = h->bx;
+       regs->ax = h->ax;
+       regs->cx = h->cx;
+       regs->dx = h->dx;
+       regs->si = h->si;
+       regs->di = h->di;
+       regs->orig_ax = h->orig_ax;
+       regs->ip = h->ip;
+
+       regs->sp = h->sp;
+
+       regs->ds = decode_segment(h->ds);
+       regs->es = decode_segment(h->es);
+       regs->cs = decode_segment(h->cs);
+       regs->ss = decode_segment(h->ss);
+
+       regs->fs = decode_segment(h->fsindex);
+       regs->gs = decode_segment(h->gsindex);
+
+       thread->gs = regs->gs;
+       lazy_load_gs(regs->gs);
+
+       return 0;
+}
diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S
index 7e7f3c8..ecefd09 100644
--- a/arch/x86/kernel/entry_32.S
+++ b/arch/x86/kernel/entry_32.S
@@ -726,6 +726,9 @@ PTREGSCALL(sigreturn)
 PTREGSCALL(rt_sigreturn)
 PTREGSCALL(vm86)
 PTREGSCALL(vm86old)
+#ifdef CONFIG_CHECKPOINT
+PTREGSCALL(restart)
+#endif
 
 .macro FIXUP_ESPFIX_STACK
 /*
diff --git a/arch/x86/kernel/syscall_table_32.S 
b/arch/x86/kernel/syscall_table_32.S
index a1bc7f7..1ca053e 100644
--- a/arch/x86/kernel/syscall_table_32.S
+++ b/arch/x86/kernel/syscall_table_32.S
@@ -338,4 +338,4 @@ ENTRY(sys_call_table)
        .long sys_perf_event_open
        .long ptregs_eclone
        .long sys_checkpoint
-       .long sys_restart
+       .long ptregs_restart
diff --git a/arch/x86/mm/Makefile b/arch/x86/mm/Makefile
index 735c0b2..06630d2 100644
--- a/arch/x86/mm/Makefile
+++ b/arch/x86/mm/Makefile
@@ -26,5 +26,3 @@ obj-$(CONFIG_K8_NUMA)         += k8topology_64.o
 obj-$(CONFIG_ACPI_NUMA)                += srat_$(BITS).o
 
 obj-$(CONFIG_MEMTEST)          += memtest.o
-
-obj-$(CONFIG_CHECKPOINT)       += checkpoint.o
diff --git a/checkpoint/sys.c b/checkpoint/sys.c
index afcfa1e..89056d6 100644
--- a/checkpoint/sys.c
+++ b/checkpoint/sys.c
@@ -648,7 +648,7 @@ SYSCALL_DEFINE4(checkpoint, pid_t, pid, int, fd,
 }
 
 /**
- * sys_restart - restart a container
+ * do_sys_restart - restart a container
  * @pid: pid of task root (in coordinator's namespace), or 0
  * @fd: file from which read the checkpoint image
  * @flags: restart operation flags
@@ -657,8 +657,7 @@ SYSCALL_DEFINE4(checkpoint, pid_t, pid, int, fd,
  * Returns negative value on error, or otherwise returns in the realm
  * of the original checkpoint
  */
-SYSCALL_DEFINE4(restart, pid_t, pid, int, fd,
-               unsigned long, flags, int, logfd)
+long do_sys_restart(pid_t pid, int fd, unsigned long flags, int logfd)
 {
        struct ckpt_ctx *ctx = NULL;
        long ret;
diff --git a/include/linux/checkpoint.h b/include/linux/checkpoint.h
index c6c8d56..d81c59c 100644
--- a/include/linux/checkpoint.h
+++ b/include/linux/checkpoint.h
@@ -60,6 +60,8 @@
 #define CKPT_LSM_INFO_LEN 200
 #define CKPT_LSM_STRING_MAX 1024
 
+extern long do_sys_restart(pid_t pid, int fd, unsigned long flags, int logfd);
+
 extern int walk_task_subtree(struct task_struct *task,
                             int (*func)(struct task_struct *, void *),
                             void *data);
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 9ed192f..264a02e 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -874,8 +874,6 @@ asmlinkage long sys_ppoll(struct pollfd __user *, unsigned 
int,
                          size_t);
 asmlinkage long sys_checkpoint(pid_t pid, int fd, unsigned long flags,
                               int logfd);
-asmlinkage long sys_restart(pid_t pid, int fd, unsigned long flags,
-                           int logfd);
 
 int kernel_execve(const char *filename, char *const argv[], char *const 
envp[]);
 
-- 
1.6.3.3

_______________________________________________
Containers mailing list
[email protected]
https://lists.linux-foundation.org/mailman/listinfo/containers

_______________________________________________
Devel mailing list
[email protected]
https://openvz.org/mailman/listinfo/devel

Reply via email to