Signed-off-by: Nathan Lynch <ntl@xxxxxxxxx> --- clone_ppc.c | 43 ++++++++++++++++++++++++++++++++ clone_ppc_.S | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 120 insertions(+), 0 deletions(-) diff --git a/clone_ppc.c b/clone_ppc.c index 49797fd..c9eee8b 100644 --- a/clone_ppc.c +++ b/clone_ppc.c @@ -56,3 +56,46 @@ int clone_with_pids(int (*fn)(void *), void *child_stack, int flags, } #endif + +#include "eclone.h" + +extern int __eclone(int (*fn)(void *arg), + void *child_sp, + int flags, + void *fn_arg, + struct clone_args *args, + size_t args_size, + pid_t *pids); + +int eclone(int (*fn)(void *), void *fn_arg, int clone_flags_low, + struct clone_args *clone_args, pid_t *pids) +{ + struct clone_args my_args; + unsigned long child_sp; + int newpid; + + if (clone_args->child_stack) + child_sp = clone_args->child_stack + + clone_args->child_stack_size - 1; + else + child_sp = 0; + + my_args = *clone_args; + my_args.child_stack = child_sp; + my_args.child_stack_size = 0; + + newpid = __eclone(fn, + (void *)child_sp, + clone_flags_low, + fn_arg, + &my_args, + sizeof(my_args), + pids); + + if (newpid < 0) { + errno = -newpid; + newpid = -1; + } + + return newpid; +} diff --git a/clone_ppc_.S b/clone_ppc_.S index cb3e053..fa89c31 100644 --- a/clone_ppc_.S +++ b/clone_ppc_.S @@ -88,3 +88,80 @@ parent: neg r3,r3 blr +#ifndef __NR_eclone +#define __NR_eclone 323 +#endif + +/* int [r3] eclone(int (*fn)(void *arg) [r3], + * void *child_sp [r4], + * int flags [r5], + * void *fn_arg [r6], + * struct clone_args *args [r7], + * size_t args_size [r8], + * pid_t *pids [r9]); + * Creates a child task with the pids specified by pids. + * Returns to parent only, child execution and exit is handled here. + * On error, returns negated errno. On success, returns the pid of the child + * created. + */ + +.globl __eclone +__eclone: + + /* No argument validation. */ + + /* Set up parent's stack frame. */ + stwu r1,-32(r1) + + /* Save non-volatiles (r28-r31) which we plan to use. */ + stmw r28,16(r1) + + /* Set up child's stack frame. */ + clrrwi r4,r4,4 + li r0,0 + stw r0,-16(r4) + + /* Save fn, stack pointer, flags, and fn_arg across system call. */ + mr r28,r3 + mr r29,r4 + mr r30,r5 + mr r31,r6 + + /* Set up arguments for system call. */ + mr r3,r5 /* flags */ + mr r4,r7 /* clone_args */ + mr r5,r8 /* clone_args' size */ + mr r6,r9 /* pids */ + + /* Do the system call */ + li r0,__NR_eclone + sc + + /* Parent or child? */ + cmpwi cr1,r3,0 + crandc 4*cr1+eq,4*cr1+eq,4*cr0+so + bne cr1,eclone_parent + + /* Child. Call fn. */ + mtctr r28 + mr r3,r31 + bctrl + + /* Assume result of fn in r3 and exit. */ + li r0,__NR_exit + sc + +eclone_parent: + /* Restore non-volatiles. */ + lmw r28,16(r1) + + addi r1,r1,32 + + /* Return to caller on success. */ + bnslr + + /* Handle error. Negate the return value to signal an error + * to the caller, which must set errno. + */ + neg r3,r3 + blr -- 1.6.2.5 _______________________________________________ Containers mailing list Containers@xxxxxxxxxxxxxxxxxxxxxxxxxx https://lists.linux-foundation.org/mailman/listinfo/containers