Commit 294d62dd authored by Andrey Vagin's avatar Andrey Vagin Committed by Pavel Emelyanov

parasite: allocate stack for each thread

It will be used for executed parasite as a daemon.
What we have previously -- the stack has been preallocated in parasite
blob itself and bootstrap procedure calculated the value needed for %rsp.

With this patch applied we provide every thread own stack as:

- find out how many threads are present
- calculate the summary size of all stacks
- when we ask dumpee to provide us memory area needed to run
  parasite code, we pass summary size needed for everything
- when parasite code is asked to run we calculate %rsp needed
  taking into account the thread number (ie offsets) and then
  setup proper %rsp via ptrace call, instead of calculating it
  in bootstrap parasite code
Signed-off-by: 's avatarAndrey Vagin <avagin@openvz.org>
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent b21dd2bc
...@@ -36,9 +36,11 @@ static inline void __check_code_syscall(void) ...@@ -36,9 +36,11 @@ static inline void __check_code_syscall(void)
} }
void parasite_setup_regs(unsigned long new_ip, user_regs_struct_t *regs) void parasite_setup_regs(unsigned long new_ip, void *stack, user_regs_struct_t *regs)
{ {
regs->ARM_pc = new_ip; regs->ARM_pc = new_ip;
if (stack)
regs->ARM_sp = stack;
/* Avoid end of syscall processing */ /* Avoid end of syscall processing */
regs->ARM_ORIG_r0 = -1; regs->ARM_ORIG_r0 = -1;
...@@ -74,7 +76,7 @@ int syscall_seized(struct parasite_ctl *ctl, int nr, unsigned long *ret, ...@@ -74,7 +76,7 @@ int syscall_seized(struct parasite_ctl *ctl, int nr, unsigned long *ret,
regs.ARM_r4 = arg5; regs.ARM_r4 = arg5;
regs.ARM_r5 = arg6; regs.ARM_r5 = arg6;
parasite_setup_regs(ctl->syscall_ip, &regs); parasite_setup_regs(ctl->syscall_ip, 0, &regs);
err = __parasite_execute(ctl, ctl->pid.real, &regs); err = __parasite_execute(ctl, ctl->pid.real, &regs);
if (err) if (err)
return err; return err;
......
...@@ -9,7 +9,7 @@ extern const char code_syscall[]; ...@@ -9,7 +9,7 @@ extern const char code_syscall[];
extern const int code_syscall_size; extern const int code_syscall_size;
void parasite_setup_regs(unsigned long new_ip, user_regs_struct_t *regs); void parasite_setup_regs(unsigned long new_ip, void *stack, user_regs_struct_t *regs);
void *mmap_seized(struct parasite_ctl *ctl, void *mmap_seized(struct parasite_ctl *ctl,
void *addr, size_t length, int prot, void *addr, size_t length, int prot,
......
...@@ -5,11 +5,6 @@ ...@@ -5,11 +5,6 @@
ENTRY(__export_parasite_head_start) ENTRY(__export_parasite_head_start)
sub %r2, %pc, #8 @ get the address of this instruction sub %r2, %pc, #8 @ get the address of this instruction
adr %sp, parasite_stack_ptr
ldr %sp, [%sp]
add %sp, %sp, %r2 @ fixup __export_parasite_stack
bic %sp, %sp, #7 @ align the stack
adr %r0, __export_parasite_cmd adr %r0, __export_parasite_cmd
ldr %r0, [%r0] ldr %r0, [%r0]
...@@ -23,14 +18,6 @@ ENTRY(__export_parasite_head_start) ...@@ -23,14 +18,6 @@ ENTRY(__export_parasite_head_start)
parasite_args_ptr: parasite_args_ptr:
.long __export_parasite_args .long __export_parasite_args
parasite_stack_ptr:
.long __export_parasite_stack
__export_parasite_cmd: __export_parasite_cmd:
.long 0 .long 0
.space PARASITE_STACK_SIZE,0
.align 3
__export_parasite_stack:
.long 0
END(__export_parasite_head_start) END(__export_parasite_head_start)
...@@ -36,9 +36,11 @@ static inline void __check_code_syscall(void) ...@@ -36,9 +36,11 @@ static inline void __check_code_syscall(void)
BUILD_BUG_ON(!is_log2(sizeof(code_syscall))); BUILD_BUG_ON(!is_log2(sizeof(code_syscall)));
} }
void parasite_setup_regs(unsigned long new_ip, user_regs_struct_t *regs) void parasite_setup_regs(unsigned long new_ip, void *stack, user_regs_struct_t *regs)
{ {
regs->ip = new_ip; regs->ip = new_ip;
if (stack)
regs->sp = (unsigned long) stack;
/* Avoid end of syscall processing */ /* Avoid end of syscall processing */
regs->orig_ax = -1; regs->orig_ax = -1;
...@@ -98,7 +100,7 @@ int syscall_seized(struct parasite_ctl *ctl, int nr, unsigned long *ret, ...@@ -98,7 +100,7 @@ int syscall_seized(struct parasite_ctl *ctl, int nr, unsigned long *ret,
regs.r8 = arg5; regs.r8 = arg5;
regs.r9 = arg6; regs.r9 = arg6;
parasite_setup_regs(ctl->syscall_ip, &regs); parasite_setup_regs(ctl->syscall_ip, 0, &regs);
err = __parasite_execute(ctl, ctl->pid.real, &regs); err = __parasite_execute(ctl, ctl->pid.real, &regs);
if (err) if (err)
return err; return err;
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
extern const char code_syscall[]; extern const char code_syscall[];
extern const int code_syscall_size; extern const int code_syscall_size;
void parasite_setup_regs(unsigned long new_ip, user_regs_struct_t *regs); void parasite_setup_regs(unsigned long new_ip, void *stack, user_regs_struct_t *regs);
void *mmap_seized(struct parasite_ctl *ctl, void *mmap_seized(struct parasite_ctl *ctl,
void *addr, size_t length, int prot, void *addr, size_t length, int prot,
......
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
.section .head.text, "ax" .section .head.text, "ax"
ENTRY(__export_parasite_head_start) ENTRY(__export_parasite_head_start)
leaq __export_parasite_stack(%rip), %rsp
subq $16, %rsp subq $16, %rsp
andq $~15, %rsp andq $~15, %rsp
pushq $0 pushq $0
...@@ -15,7 +14,4 @@ ENTRY(__export_parasite_head_start) ...@@ -15,7 +14,4 @@ ENTRY(__export_parasite_head_start)
.align 8 .align 8
__export_parasite_cmd: __export_parasite_cmd:
.long 0 .long 0
.space PARASITE_STACK_SIZE,0
__export_parasite_stack:
.long 0
END(__export_parasite_head_start) END(__export_parasite_head_start)
...@@ -9,6 +9,8 @@ struct parasite_thread_ctl ...@@ -9,6 +9,8 @@ struct parasite_thread_ctl
{ {
pid_t tid; pid_t tid;
user_regs_struct_t regs_orig; /* original registers */ user_regs_struct_t regs_orig; /* original registers */
void *rstack;
}; };
/* parasite control block */ /* parasite control block */
......
...@@ -206,7 +206,7 @@ static int parasite_execute_by_id(unsigned int cmd, struct parasite_ctl *ctl, in ...@@ -206,7 +206,7 @@ static int parasite_execute_by_id(unsigned int cmd, struct parasite_ctl *ctl, in
*ctl->addr_cmd = cmd; *ctl->addr_cmd = cmd;
parasite_setup_regs(ctl->parasite_ip, &regs); parasite_setup_regs(ctl->parasite_ip, thread->rstack, &regs);
ret = __parasite_execute(ctl, pid, &regs); ret = __parasite_execute(ctl, pid, &regs);
if (ret == 0) if (ret == 0)
...@@ -883,8 +883,9 @@ static unsigned long parasite_args_size(struct vm_area_list *vmas, struct parasi ...@@ -883,8 +883,9 @@ static unsigned long parasite_args_size(struct vm_area_list *vmas, struct parasi
struct parasite_ctl *parasite_infect_seized(pid_t pid, struct pstree_item *item, struct parasite_ctl *parasite_infect_seized(pid_t pid, struct pstree_item *item,
struct vm_area_list *vma_area_list, struct parasite_drain_fd *dfds) struct vm_area_list *vma_area_list, struct parasite_drain_fd *dfds)
{ {
int ret; int ret, i;
struct parasite_ctl *ctl; struct parasite_ctl *ctl;
unsigned long p;
BUG_ON(item->threads[0].real != pid); BUG_ON(item->threads[0].real != pid);
...@@ -900,7 +901,8 @@ struct parasite_ctl *parasite_infect_seized(pid_t pid, struct pstree_item *item, ...@@ -900,7 +901,8 @@ struct parasite_ctl *parasite_infect_seized(pid_t pid, struct pstree_item *item,
*/ */
ctl->args_size = parasite_args_size(vma_area_list, dfds); ctl->args_size = parasite_args_size(vma_area_list, dfds);
ret = parasite_map_exchange(ctl, parasite_size + ctl->args_size); ret = parasite_map_exchange(ctl, parasite_size + ctl->args_size +
item->nr_threads * PARASITE_STACK_SIZE);
if (ret) if (ret)
goto err_restore; goto err_restore;
...@@ -912,6 +914,14 @@ struct parasite_ctl *parasite_infect_seized(pid_t pid, struct pstree_item *item, ...@@ -912,6 +914,14 @@ struct parasite_ctl *parasite_infect_seized(pid_t pid, struct pstree_item *item,
ctl->addr_cmd = parasite_sym(ctl->local_map, __export_parasite_cmd); ctl->addr_cmd = parasite_sym(ctl->local_map, __export_parasite_cmd);
ctl->addr_args = parasite_sym(ctl->local_map, __export_parasite_args); ctl->addr_args = parasite_sym(ctl->local_map, __export_parasite_args);
p = parasite_size + ctl->args_size;
for (i = 0; i < item->nr_threads; i++) {
struct parasite_thread_ctl *thread = &ctl->threads[i];
thread->rstack = ctl->remote_map + p;
p += PARASITE_STACK_SIZE;
}
ret = parasite_init(ctl, pid, item->nr_threads); ret = parasite_init(ctl, pid, item->nr_threads);
if (ret) { if (ret) {
pr_err("%d: Can't create a transport socket\n", pid); pr_err("%d: Can't create a transport socket\n", pid);
......
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