[CRIU] [PATCH 06/22] parasite: introduced the multiarch support into the parasite.
Alexander Kartashov
alekskartashov at parallels.com
Thu Dec 27 01:50:57 EST 2012
* Introduced the TLS area retrieval in the routine parasite_dump_thread_seized
since ARM requires saving/restoring it.
* Introduced the macro ARCH_SI_TRAP to abstract from behavior of breakpoints:
they generate different values of the field siginfo.si_code on different architectures.
* Introduced the macro REG_RES to reference the syscall return value register in
the struct user_regs_struct_t.
Signed-off-by: Alexander Kartashov <alekskartashov at parallels.com>
---
arch/x86/include/asm/parasite-syscall.h | 2 ++
arch/x86/include/asm/parasite.h | 8 ++++++++
arch/x86/include/asm/types.h | 3 +++
include/parasite-syscall.h | 3 ++-
include/parasite.h | 7 +++++++
parasite-syscall.c | 24 ++++++++++++++++++++----
pie/parasite.c | 12 +++++++++---
7 files changed, 51 insertions(+), 8 deletions(-)
create mode 100644 arch/x86/include/asm/parasite.h
diff --git a/arch/x86/include/asm/parasite-syscall.h b/arch/x86/include/asm/parasite-syscall.h
index f3bd363..69b0bdf 100644
--- a/arch/x86/include/asm/parasite-syscall.h
+++ b/arch/x86/include/asm/parasite-syscall.h
@@ -1,6 +1,8 @@
#ifndef __CR_ASM_PARASITE_SYSCALL_H__
#define __CR_ASM_PARASITE_SYSCALL_H__
+#define ARCH_SI_TRAP SI_KERNEL
+
/*
* Injected syscall instruction
*/
diff --git a/arch/x86/include/asm/parasite.h b/arch/x86/include/asm/parasite.h
new file mode 100644
index 0000000..0c6bcb4
--- /dev/null
+++ b/arch/x86/include/asm/parasite.h
@@ -0,0 +1,8 @@
+#ifndef __ASM_PARASITE_H__
+#define __ASM_PARASITE_H__
+
+static uint32_t arch_get_tls() {
+ return 0;
+}
+
+#endif
diff --git a/arch/x86/include/asm/types.h b/arch/x86/include/asm/types.h
index 98c90d1..2b9f3ec 100644
--- a/arch/x86/include/asm/types.h
+++ b/arch/x86/include/asm/types.h
@@ -249,6 +249,9 @@ typedef struct {
typedef struct { } UserFPState;
+#define REG_RES(regs) ((regs).ax)
+#define REG_IP(regs) ((regs).ip)
+
#define TASK_SIZE ((1UL << 47) - 1)
typedef uint64_t auxv_t;
diff --git a/include/parasite-syscall.h b/include/parasite-syscall.h
index 6b0d659..bea74d3 100644
--- a/include/parasite-syscall.h
+++ b/include/parasite-syscall.h
@@ -38,7 +38,7 @@ extern int parasite_dump_pages_seized(struct parasite_ctl *ctl,
struct parasite_dump_thread;
extern int parasite_dump_thread_seized(struct parasite_ctl *ctl, pid_t pid,
unsigned int **tid_add, pid_t *tid,
- void *blocked);
+ void *blocked, u32* tls);
struct parasite_drain_fd;
struct fd_opts;
@@ -49,6 +49,7 @@ extern int parasite_get_proc_fd_seized(struct parasite_ctl *ctl);
struct pstree_item;
extern int parasite_cure_seized(struct parasite_ctl *ctl, struct pstree_item *item);
+extern uint32_t parasite_get_tls_seized(struct parasite_ctl* ctl);
extern struct parasite_ctl *parasite_infect_seized(pid_t pid,
struct pstree_item *item,
struct list_head *vma_area_list);
diff --git a/include/parasite.h b/include/parasite.h
index f743e06..b5e874a 100644
--- a/include/parasite.h
+++ b/include/parasite.h
@@ -37,6 +37,8 @@ enum {
PARASITE_CMD_GET_PROC_FD,
PARASITE_CMD_DUMP_TTY,
+ PARASITE_CMD_GET_TLS,
+
PARASITE_CMD_MAX,
};
@@ -97,6 +99,7 @@ struct parasite_dump_thread {
unsigned int *tid_addr;
pid_t tid;
k_rtsigset_t blocked;
+ u32 tls;
};
#define PARASITE_MAX_FDS (PAGE_SIZE / sizeof(int))
@@ -106,6 +109,10 @@ struct parasite_drain_fd {
int fds[PARASITE_MAX_FDS];
};
+struct parasite_get_tls_args {
+ uint32_t tls;
+};
+
static inline int drain_fds_size(struct parasite_drain_fd *dfds)
{
return sizeof(dfds->nr_fds) + dfds->nr_fds * sizeof(dfds->fds[0]);
diff --git a/parasite-syscall.c b/parasite-syscall.c
index 85b7db6..ae91756 100644
--- a/parasite-syscall.c
+++ b/parasite-syscall.c
@@ -1,4 +1,5 @@
#include <unistd.h>
+#include <inttypes.h>
#include <sys/stat.h>
#include <sys/wait.h>
@@ -98,7 +99,7 @@ again:
goto err;
}
- if (WSTOPSIG(status) != SIGTRAP || siginfo.si_code != SI_KERNEL) {
+ if (WSTOPSIG(status) != SIGTRAP || siginfo.si_code != ARCH_SI_TRAP) {
retry_signal:
pr_debug("** delivering signal %d si_code=%d\n",
siginfo.si_signo, siginfo.si_code);
@@ -211,7 +212,7 @@ static int parasite_execute_by_pid(unsigned int cmd, struct parasite_ctl *ctl, p
ret = __parasite_execute(ctl, pid, ®s);
if (ret == 0)
- ret = (int)regs.ax;
+ ret = (int)REG_RES(regs);
if (ret)
pr_err("Parasite exited with %d\n", ret);
@@ -365,7 +366,8 @@ err:
int parasite_dump_thread_seized(struct parasite_ctl *ctl, pid_t pid,
unsigned int **tid_addr, pid_t *tid,
- void *blocked)
+ void *blocked,
+ u32* tls)
{
struct parasite_dump_thread *args;
int ret;
@@ -377,6 +379,7 @@ int parasite_dump_thread_seized(struct parasite_ctl *ctl, pid_t pid,
memcpy(blocked, &args->blocked, sizeof(args->blocked));
*tid_addr = args->tid_addr;
*tid = args->tid;
+ *tls = args->tls;
return ret;
}
@@ -549,6 +552,10 @@ int parasite_dump_pages_seized(struct parasite_ctl *ctl, struct list_head *vma_a
continue;
}
+ if (vma_area->vma.end > TASK_SIZE) {
+ continue;
+ }
+
ret = parasite_execute(PARASITE_CMD_DUMPPAGES, ctl);
if (ret) {
pr_err("Dumping pages failed with %d\n", ret);
@@ -676,6 +683,15 @@ int parasite_fini_threads_seized(struct parasite_ctl *ctl, struct pstree_item *i
return ret;
}
+uint32_t parasite_get_tls_seized(struct parasite_ctl *ctl) {
+ struct parasite_get_tls_args *tls_args;
+
+ tls_args = (struct parasite_get_tls_args*)parasite_args_s(ctl, sizeof(*tls_args));
+ parasite_execute(PARASITE_CMD_GET_TLS, ctl);
+
+ return tls_args->tls;
+}
+
int parasite_cure_seized(struct parasite_ctl *ctl, struct pstree_item *item)
{
int ret = 0;
@@ -738,7 +754,7 @@ struct parasite_ctl *parasite_prep_ctl(pid_t pid, struct list_head *vma_area_lis
goto err;
}
- vma_area = get_vma_by_ip(vma_area_list, ctl->regs_orig.ip);
+ vma_area = get_vma_by_ip(vma_area_list, REG_IP(ctl->regs_orig));
if (!vma_area) {
pr_err("No suitable VMA found to run parasite "
"bootstrap code (pid: %d)\n", pid);
diff --git a/pie/parasite.c b/pie/parasite.c
index d9e2a1d..3338e03 100644
--- a/pie/parasite.c
+++ b/pie/parasite.c
@@ -12,9 +12,7 @@
#include <string.h>
-#ifndef CONFIG_X86_64
-#error non-x86-64 mode not yet implemented
-#endif
+#include "asm/parasite.h"
static void *brk_start, *brk_end, *brk_tail;
@@ -372,6 +370,7 @@ static int dump_thread(struct parasite_dump_thread *args)
args->blocked = s->sig_blocked;
args->tid = tid;
+ args->tls = arch_get_tls();
return 0;
}
@@ -584,6 +583,10 @@ static int parasite_cfg_log(struct parasite_log_args *args)
return ret;
}
+static void parasite_get_tls(struct parasite_get_tls_args* args) {
+ args->tls = arch_get_tls();
+}
+
static int fini(void)
{
int ret;
@@ -635,6 +638,9 @@ int __used parasite_service(unsigned int cmd, void *args)
return parasite_get_proc_fd();
case PARASITE_CMD_DUMP_TTY:
return parasite_dump_tty(args);
+ case PARASITE_CMD_GET_TLS:
+ parasite_get_tls((struct parasite_get_tls_args*)args);
+ return 0;
}
pr_err("Unknown command to parasite\n");
--
1.7.10.4
More information about the CRIU
mailing list