criu/include/syscall.h
Cyrill Gorcunov 1e7bbd35de restore: Add threads restoration
Now threads restortion (and TLS as well) works.
Threads test reports the following

    2775 (main): Counter value:    3 tls_data =    1
    2775 (main): ( 0) fsgs_base 7f9597aa46f0
    2775 (main): ( 0) fsgs_base        0
    2775 (thr3): Counter value:    4 tls_data =    4
    2775 (thr3): ( 0) fsgs_base 42c57940
    2775 (thr3): ( 0) fsgs_base        0
    2775 (thr2): Counter value:    3 tls_data =    2
    2775 (thr2): ( 0) fsgs_base 42456940
    2775 (thr2): ( 0) fsgs_base        0
    2775 (thr1): Counter value:    4 tls_data =    3
    2775 (thr1): ( 0) fsgs_base 40c62940
    2775 (thr1): ( 0) fsgs_base        0
    2775 (main): Counter value:    4 tls_data =    1
    2775 (main): ( 0) fsgs_base 7f9597aa46f0
    2775 (main): ( 0) fsgs_base        0
    2775 (thr1): Counter value:    5 tls_data =    3
    2775 (thr1): ( 0) fsgs_base 40c62940
    2775 (thr1): ( 0) fsgs_base        0

as expected.

This commits merges all preliminary commits into
the final one (sigreturn branch was always experimental
and forced update).

Still some problems remain:

1) While creating threads with clone() the
   flags are to be revisited. We use some predefined
   set here but it's not really correct.

2) No setup of pids in PCB thread zone.

3) No restore of FPU.

But at least on some basic tasks restore works well.

Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
2011-11-12 19:26:40 +04:00

269 lines
6.4 KiB
C

#ifndef CR_SYSCALL_H_
#define CR_SYSCALL_H_
#include <sys/types.h>
#include "types.h"
#include "compiler.h"
#include "syscall-codes.h"
#ifdef CONFIG_X86_64
static always_inline long syscall0(int nr)
{
long ret;
asm volatile(
"movl %1, %%eax \t\n"
"syscall \t\n"
"movq %%rax, %0 \t\n"
: "=r"(ret)
: "g" ((int)nr)
: "rax", "memory");
return ret;
}
static always_inline long syscall1(int nr, unsigned long arg0)
{
long ret;
asm volatile(
"movl %1, %%eax \t\n"
"movq %2, %%rdi \t\n"
"syscall \t\n"
"movq %%rax, %0 \t\n"
: "=r"(ret)
: "g" ((int)nr), "g" (arg0)
: "rax", "rdi", "memory");
return ret;
}
static always_inline long syscall2(int nr, unsigned long arg0, unsigned long arg1)
{
long ret;
asm volatile(
"movl %1, %%eax \t\n"
"movq %2, %%rdi \t\n"
"movq %3, %%rsi \t\n"
"syscall \t\n"
"movq %%rax, %0 \t\n"
: "=r"(ret)
: "g" ((int)nr), "g" (arg0), "g" (arg1)
: "rax", "rdi", "rsi", "memory");
return ret;
}
static always_inline long syscall3(int nr, unsigned long arg0, unsigned long arg1,
unsigned long arg2)
{
long ret;
asm volatile(
"movl %1, %%eax \t\n"
"movq %2, %%rdi \t\n"
"movq %3, %%rsi \t\n"
"movq %4, %%rdx \t\n"
"syscall \t\n"
"movq %%rax, %0 \t\n"
: "=r"(ret)
: "g" ((int)nr), "g" (arg0), "g" (arg1), "g" (arg2)
: "rax", "rdi", "rsi", "rdx", "memory");
return ret;
}
static always_inline long syscall4(int nr, unsigned long arg0, unsigned long arg1,
unsigned long arg2, unsigned long arg3)
{
long ret;
asm volatile(
"movl %1, %%eax \t\n"
"movq %2, %%rdi \t\n"
"movq %3, %%rsi \t\n"
"movq %4, %%rdx \t\n"
"movq %5, %%r10 \t\n"
"syscall \t\n"
"movq %%rax, %0 \t\n"
: "=r"(ret)
: "g" ((int)nr), "g" (arg0), "g" (arg1), "g" (arg2),
"g" (arg3)
: "rax", "rdi", "rsi", "rdx", "r10", "memory");
return ret;
}
static long always_inline syscall5(int nr, unsigned long arg0, unsigned long arg1,
unsigned long arg2, unsigned long arg3,
unsigned long arg4)
{
long ret;
asm volatile(
"movl %1, %%eax \t\n"
"movq %2, %%rdi \t\n"
"movq %3, %%rsi \t\n"
"movq %4, %%rdx \t\n"
"movq %5, %%r10 \t\n"
"movq %6, %%r8 \t\n"
"syscall \t\n"
"movq %%rax, %0 \t\n"
: "=r"(ret)
: "g" ((int)nr), "g" (arg0), "g" (arg1), "g" (arg2),
"g" (arg3), "g" (arg4)
: "rax", "rdi", "rsi", "rdx", "r10", "r8", "memory");
return ret;
}
static long always_inline syscall6(int nr, unsigned long arg0, unsigned long arg1,
unsigned long arg2, unsigned long arg3,
unsigned long arg4, unsigned long arg5)
{
long ret;
asm volatile(
"movl %1, %%eax \t\n"
"movq %2, %%rdi \t\n"
"movq %3, %%rsi \t\n"
"movq %4, %%rdx \t\n"
"movq %5, %%r10 \t\n"
"movq %6, %%r8 \t\n"
"movq %7, %%r9 \t\n"
"syscall \t\n"
"movq %%rax, %0 \t\n"
: "=r"(ret)
: "g" ((int)nr), "g" (arg0), "g" (arg1), "g" (arg2),
"g" (arg3), "g" (arg4), "g" (arg5)
: "rax", "rdi", "rsi", "rdx", "r10", "r8", "r9", "memory");
return ret;
}
static always_inline unsigned long sys_pause(void)
{
return syscall0(__NR_pause);
}
static always_inline unsigned long sys_mmap(void *addr, unsigned long len, unsigned long prot,
unsigned long flags, unsigned long fd, unsigned long offset)
{
return syscall6(__NR_mmap, (unsigned long)addr,
len, prot, flags, fd, offset);
}
static always_inline unsigned long sys_munmap(void *addr,unsigned long len)
{
return syscall2(__NR_munmap, (unsigned long)addr, len);
}
static always_inline long sys_open(const char *filename, unsigned long flags, unsigned long mode)
{
return syscall3(__NR_open, (unsigned long)filename, flags, mode);
}
static always_inline long sys_close(int fd)
{
return syscall1(__NR_close, fd);
}
static always_inline long sys_write(unsigned long fd, const void *buf, unsigned long count)
{
return syscall3(__NR_write, fd, (unsigned long)buf, count);
}
static always_inline long sys_mincore(unsigned long addr, unsigned long size, void *vec)
{
return syscall3(__NR_mincore, addr, size, (unsigned long)vec);
}
static always_inline long sys_lseek(unsigned long fd, unsigned long offset, unsigned long origin)
{
return syscall3(__NR_lseek, fd, offset, origin);
}
static always_inline long sys_mprotect(unsigned long start, unsigned long len, unsigned long prot)
{
return syscall3(__NR_mprotect, start, len, prot);
}
static always_inline long sys_nanosleep(struct timespec *req, struct timespec *rem)
{
return syscall2(__NR_nanosleep, (unsigned long)req, (unsigned long)rem);
}
static always_inline long sys_read(unsigned long fd, void *buf, unsigned long count)
{
return syscall3(__NR_read, fd, (unsigned long)buf, count);
}
static always_inline long sys_exit(unsigned long error_code)
{
return syscall1(__NR_exit, error_code);
}
static always_inline unsigned long sys_getpid(void)
{
return syscall0(__NR_getpid);
}
static always_inline long sys_unlink(char *pathname)
{
return syscall1(__NR_unlink, (unsigned long)pathname);
}
/*
* Note this call expects a signal frame on stack
* (regs->sp) so be very carefull here!
*/
static always_inline long sys_rt_sigreturn(void)
{
return syscall0(__NR_rt_sigreturn);
}
static always_inline long sys_set_thread_area(user_desc_t *info)
{
return syscall1(__NR_set_thread_area, (long)info);
}
static always_inline long sys_get_thread_area(user_desc_t *info)
{
return syscall1(__NR_get_thread_area, (long)info);
}
static always_inline long sys_arch_prctl(int code, void *addr)
{
return syscall2(__NR_arch_prctl, code, (unsigned long)addr);
}
static always_inline long sys_prctl(int code, unsigned long arg2, unsigned long arg3,
unsigned long arg4, unsigned long arg5)
{
return syscall5(__NR_prctl, code, arg2, arg3, arg4, arg5);
}
static always_inline long sys_clone(unsigned long flags, void *child_stack,
void *parent_tid, void *child_tid)
{
return syscall4(__NR_clone, flags, (unsigned long)child_stack,
(unsigned long)parent_tid, (unsigned long)child_tid);
}
static always_inline long sys_futex(u32 *uaddr, int op, u32 val,
struct timespec *utime,
u32 *uaddr2, u32 val3)
{
return syscall6(__NR_futex, (unsigned long)uaddr,
(unsigned long)op, (unsigned long)val,
(unsigned long)utime,
(unsigned long)uaddr2,
(unsigned long)val3);
}
static void always_inline local_sleep(long seconds)
{
struct timespec req, rem;
req = (struct timespec){
.tv_sec = seconds,
.tv_nsec = 0,
};
sys_nanosleep(&req, &rem);
}
#else /* CONFIG_X86_64 */
# error x86-32 bit mode not yet implemented
#endif /* CONFIG_X86_64 */
#endif /* CR_SYSCALL_H_ */