diff --git a/arch/arm/arm64/ctx.S b/arch/arm/arm64/ctx.S index 68ce8993676214bacb10e4a04ea335a2c76bef72..5fefa6e97e0aa053fefa8d58b7b9eccadfc0b0de 100644 --- a/arch/arm/arm64/ctx.S +++ b/arch/arm/arm64/ctx.S @@ -78,7 +78,7 @@ ENTRY(_ctx_arm_clearregs) ldr x30, [sp], #16 ret -ENTRY(_ctx_arm_call0) +ENTRY(_ctx_arm_callip) #if !__OMIT_FRAMEPOINTER__ mov x29, xzr /* reset frame pointer */ #endif /* !__OMIT_FRAMEPOINTER__ */ @@ -86,13 +86,27 @@ ENTRY(_ctx_arm_call0) ldr x30, [sp], #16 ret +ENTRY(_ctx_arm_call0) +#if !__OMIT_FRAMEPOINTER__ + mov x29, xzr /* reset frame pointer */ +#endif /* !__OMIT_FRAMEPOINTER__ */ + ldr x0, [sp], #16 + /* pop cleanup func into x30 as return address */ + ldr x30, [sp], #16 + br x0 + ret + ENTRY(_ctx_arm_call1) #if !__OMIT_FRAMEPOINTER__ mov x29, xzr /* reset frame pointer */ #endif /* !__OMIT_FRAMEPOINTER__ */ ldr x0, [sp], #16 - /* jump to entrance function left on stack */ + /* Load entry function address as x1 */ + ldr x1, [sp], #16 + /* pop cleanup func into x30 as return address */ ldr x30, [sp], #16 + /* jump to entry func */ + br x1 ret ENTRY(_ctx_arm_call2) @@ -101,8 +115,12 @@ ENTRY(_ctx_arm_call2) #endif /* !__OMIT_FRAMEPOINTER__ */ ldr x1, [sp], #16 ldr x0, [sp], #16 - /* jump to entrance function left on stack */ + /* Load entry function address as x2 */ + ldr x2, [sp], #16 + /* pop cleanup func into x30 as return address */ ldr x30, [sp], #16 + /* jump to entry func */ + br x2 ret /* diff --git a/arch/arm/ctx.c b/arch/arm/ctx.c index 9dc48fa98f865d4c228c721e29395ac40bd2d0c2..5c863785e1f8a2e12df91614b5d7a056c2c8fad7 100644 --- a/arch/arm/ctx.c +++ b/arch/arm/ctx.c @@ -41,12 +41,7 @@ #define UK_ASSERT(..) do {} while (0) #define uk_pr_debug(..) do {} while (0) #endif /* !CONFIG_LIBUKDEBUG */ - -/* Assembler functions */ -void _ctx_arm_clearregs(void); -void _ctx_arm_call0(void); -void _ctx_arm_call1(void); -void _ctx_arm_call2(void); +#include "ctx.h" void ukarch_ctx_init(struct ukarch_ctx *ctx, __uptr sp, int keep_regs, @@ -59,16 +54,16 @@ void ukarch_ctx_init(struct ukarch_ctx *ctx, UK_ASSERT(ip); /* IP == NULL would cause a crash */ UK_ASSERT(!keep_regs && sp); /* stack is needed for clearing regs */ - _sp = ukarch_rstack_push(sp, (long) ip); + _sp = ukarch_rstack_push(sp, (long)ip); if (keep_regs) { - ukarch_ctx_init_bare(ctx, _sp, (long) _ctx_arm_call0); + ukarch_ctx_init_bare(ctx, _sp, (long)_ctx_arm_callip); } else { - _sp = ukarch_rstack_push(_sp, (long) _ctx_arm_call0); + _sp = ukarch_rstack_push(_sp, (long)_ctx_arm_callip); ukarch_ctx_init_bare(ctx, _sp, (long) _ctx_arm_clearregs); } - uk_pr_debug("ukarch_ctx %p: start:%p sp:%p\n", - ctx, (void *) ip, (void *) sp); + uk_pr_debug("ukarch_ctx %p: start:%p sp:%p\n", ctx, (void *)ip, + (void *)_sp); } void ukarch_ctx_init_entry0(struct ukarch_ctx *ctx, @@ -82,7 +77,8 @@ void ukarch_ctx_init_entry0(struct ukarch_ctx *ctx, UK_ASSERT(entry); /* entry == NULL will cause a crash */ UK_ASSERT(!(sp & UKARCH_SP_ALIGN_MASK)); /* sp properly aligned? */ - _sp = ukarch_rstack_push(sp, (long) entry); + _sp = ukarch_rstack_push(sp, (long)uk_sched_thread_exit); + _sp = ukarch_rstack_push(_sp, (long)entry); if (keep_regs) { ukarch_ctx_init_bare(ctx, _sp, (long) _ctx_arm_call0); } else { @@ -90,8 +86,8 @@ void ukarch_ctx_init_entry0(struct ukarch_ctx *ctx, ukarch_ctx_init_bare(ctx, _sp, (long) _ctx_arm_clearregs); } - uk_pr_debug("ukarch_ctx %p: entry:%p(), sp:%p\n", - ctx, entry, (void *) sp); + uk_pr_debug("ukarch_ctx %p: entry:%p(), sp:%p\n", ctx, entry, + (void *)_sp); } void ukarch_ctx_init_entry1(struct ukarch_ctx *ctx, @@ -105,7 +101,8 @@ void ukarch_ctx_init_entry1(struct ukarch_ctx *ctx, UK_ASSERT(entry); /* NULL as func will cause a crash */ UK_ASSERT(!(sp & UKARCH_SP_ALIGN_MASK)); /* sp properly aligned? */ - _sp = ukarch_rstack_push(sp, (long) entry); + _sp = ukarch_rstack_push(sp, (long)uk_sched_thread_exit); + _sp = ukarch_rstack_push(_sp, (long)entry); _sp = ukarch_rstack_push(_sp, arg); if (keep_regs) { ukarch_ctx_init_bare(ctx, _sp, (long) _ctx_arm_call1); @@ -114,8 +111,8 @@ void ukarch_ctx_init_entry1(struct ukarch_ctx *ctx, ukarch_ctx_init_bare(ctx, _sp, (long) _ctx_arm_clearregs); } - uk_pr_debug("ukarch_ctx %p: entry:%p(%lx), sp:%p\n", - ctx, entry, arg, (void *) sp); + uk_pr_debug("ukarch_ctx %p: entry:%p(%lx), sp:%p\n", ctx, entry, arg, + (void *)_sp); } void ukarch_ctx_init_entry2(struct ukarch_ctx *ctx, @@ -129,7 +126,8 @@ void ukarch_ctx_init_entry2(struct ukarch_ctx *ctx, UK_ASSERT(entry); /* NULL as func will cause a crash */ UK_ASSERT(!(sp & UKARCH_SP_ALIGN_MASK)); /* sp properly aligned? */ - _sp = ukarch_rstack_push(sp, (long) entry); + _sp = ukarch_rstack_push(sp, (long)uk_sched_thread_exit); + _sp = ukarch_rstack_push(_sp, (long)entry); _sp = ukarch_rstack_push(_sp, arg0); _sp = ukarch_rstack_push(_sp, arg1); if (keep_regs) { @@ -139,6 +137,6 @@ void ukarch_ctx_init_entry2(struct ukarch_ctx *ctx, ukarch_ctx_init_bare(ctx, _sp, (long) _ctx_arm_clearregs); } - uk_pr_debug("ukarch_ctx %p: entry:%p(%lx, %lx), sp:%p\n", - ctx, entry, arg0, arg1, (void *) sp); + uk_pr_debug("ukarch_ctx %p: entry:%p(%lx, %lx), sp:%p\n", ctx, entry, + arg0, arg1, (void *)_sp); } diff --git a/arch/arm/ctx.h b/arch/arm/ctx.h new file mode 100644 index 0000000000000000000000000000000000000000..8b45208b6cefad7eadd803a786ef2cbf3c86d366 --- /dev/null +++ b/arch/arm/ctx.h @@ -0,0 +1,28 @@ +/* Copyright 2023 Hangzhou Yingyi Technology Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if !__ASSEMBLY__ + +/* thread cleanup func */ +extern void uk_sched_thread_exit(void); + +/* Assembler functions */ +void _ctx_arm_clearregs(void); +void _ctx_arm_callip(void); +void _ctx_arm_call0(void); +void _ctx_arm_call1(void); +void _ctx_arm_call2(void); + +#endif /* !__ASSEMBLY__ */ diff --git a/arch/x86/ctx.c b/arch/x86/ctx.c index d850b2337b31466aba12fb687644137dc192795c..e3aff8289ccb40d25a88daa30ed65be70d52fd0d 100644 --- a/arch/x86/ctx.c +++ b/arch/x86/ctx.c @@ -40,12 +40,7 @@ #define UK_ASSERT(..) do {} while (0) #define uk_pr_debug(..) do {} while (0) #endif /* !CONFIG_LIBUKDEBUG */ - -/* Assembler functions */ -void _ctx_x86_clearregs(void); -void _ctx_x86_call0(void); -void _ctx_x86_call1(void); -void _ctx_x86_call2(void); +#include "ctx.h" void ukarch_ctx_init(struct ukarch_ctx *ctx, __uptr sp, int keep_regs, @@ -58,16 +53,17 @@ void ukarch_ctx_init(struct ukarch_ctx *ctx, UK_ASSERT(ip); /* NULL as IP will cause a crash */ UK_ASSERT(!keep_regs && sp); /* a stack is needed when clearing */ - _sp = ukarch_rstack_push(sp, (long) ip); + _sp = ukarch_rstack_push(sp, (long)ip); + if (keep_regs) { - ukarch_ctx_init_bare(ctx, _sp, (long) _ctx_x86_call0); + ukarch_ctx_init_bare(ctx, _sp, (long)_ctx_x86_callip); } else { - _sp = ukarch_rstack_push(_sp, (long) _ctx_x86_call0); + _sp = ukarch_rstack_push(_sp, (long)_ctx_x86_callip); ukarch_ctx_init_bare(ctx, _sp, (long) _ctx_x86_clearregs); } - uk_pr_debug("ukarch_ctx %p: start:%p sp:%p\n", - ctx, (void *) ip, (void *) sp); + uk_pr_debug("ukarch_ctx %p: start:%p sp:%p\n", ctx, (void *)ip, + (void *)_sp); } void ukarch_ctx_init_entry0(struct ukarch_ctx *ctx, @@ -97,7 +93,8 @@ void ukarch_ctx_init_entry0(struct ukarch_ctx *ctx, * through. */ sp = ukarch_rstack_push(sp, (__u64) 0x0); - _sp = ukarch_rstack_push(sp, (long) entry); + _sp = ukarch_rstack_push(sp, (long)uk_sched_thread_exit); + _sp = ukarch_rstack_push(_sp, (long)entry); if (keep_regs) { ukarch_ctx_init_bare(ctx, _sp, (long) _ctx_x86_call0); } else { @@ -105,8 +102,8 @@ void ukarch_ctx_init_entry0(struct ukarch_ctx *ctx, ukarch_ctx_init_bare(ctx, _sp, (long) _ctx_x86_clearregs); } - uk_pr_debug("ukarch_ctx %p: entry:%p(), sp:%p\n", - ctx, entry, (void *) sp); + uk_pr_debug("ukarch_ctx %p: entry:%p(), sp:%p\n", ctx, entry, + (void *)_sp); } void ukarch_ctx_init_entry1(struct ukarch_ctx *ctx, @@ -121,7 +118,8 @@ void ukarch_ctx_init_entry1(struct ukarch_ctx *ctx, UK_ASSERT(!(sp & UKARCH_SP_ALIGN_MASK)); /* sp properly aligned? */ sp = ukarch_rstack_push(sp, (__u64) 0x0); /* SystemV call convention */ - _sp = ukarch_rstack_push(sp, (long) entry); + _sp = ukarch_rstack_push(sp, (long)uk_sched_thread_exit); + _sp = ukarch_rstack_push(_sp, (long)entry); _sp = ukarch_rstack_push(_sp, arg); if (keep_regs) { ukarch_ctx_init_bare(ctx, _sp, (long) _ctx_x86_call1); @@ -130,8 +128,8 @@ void ukarch_ctx_init_entry1(struct ukarch_ctx *ctx, ukarch_ctx_init_bare(ctx, _sp, (long) _ctx_x86_clearregs); } - uk_pr_debug("ukarch_ctx %p: entry:%p(%lx), sp:%p\n", - ctx, entry, arg, (void *) sp); + uk_pr_debug("ukarch_ctx %p: entry:%p(%lx), sp:%p\n", ctx, entry, arg, + (void *)_sp); } void ukarch_ctx_init_entry2(struct ukarch_ctx *ctx, @@ -146,7 +144,8 @@ void ukarch_ctx_init_entry2(struct ukarch_ctx *ctx, UK_ASSERT(!(sp & UKARCH_SP_ALIGN_MASK)); /* sp properly aligned? */ sp = ukarch_rstack_push(sp, (__u64) 0x0); /* SystemV call convention */ - _sp = ukarch_rstack_push(sp, (long) entry); + _sp = ukarch_rstack_push(sp, (long)uk_sched_thread_exit); + _sp = ukarch_rstack_push(_sp, (long)entry); _sp = ukarch_rstack_push(_sp, arg0); _sp = ukarch_rstack_push(_sp, arg1); if (keep_regs) { @@ -156,6 +155,6 @@ void ukarch_ctx_init_entry2(struct ukarch_ctx *ctx, ukarch_ctx_init_bare(ctx, _sp, (long) _ctx_x86_clearregs); } - uk_pr_debug("ukarch_ctx %p: entry:%p(%lx, %lx), sp:%p\n", - ctx, entry, arg0, arg1, (void *) sp); + uk_pr_debug("ukarch_ctx %p: entry:%p(%lx, %lx), sp:%p\n", ctx, entry, + arg0, arg1, (void *)_sp); } diff --git a/arch/x86/ctx.h b/arch/x86/ctx.h new file mode 100644 index 0000000000000000000000000000000000000000..a147c6c423ca43516ccb89b64690720ba997f3e0 --- /dev/null +++ b/arch/x86/ctx.h @@ -0,0 +1,28 @@ +/* Copyright 2023 Hangzhou Yingyi Technology Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if !__ASSEMBLY__ + +/* thread cleanup func */ +extern void uk_sched_thread_exit(void); + +/* Assembler functions */ +void _ctx_x86_clearregs(void); +void _ctx_x86_callip(void); +void _ctx_x86_call0(void); +void _ctx_x86_call1(void); +void _ctx_x86_call2(void); + +#endif /* !__ASSEMBLY__ */ diff --git a/arch/x86/x86_64/ctx.S b/arch/x86/x86_64/ctx.S index 87e2d9713ba425ce9466d37446051d0b2f2737c1..a7083060b2cf5fbb3d7fd709b61dac9aa6de4836 100644 --- a/arch/x86/x86_64/ctx.S +++ b/arch/x86/x86_64/ctx.S @@ -54,18 +54,29 @@ ENTRY(_ctx_x86_clearregs) ret /* jump to entrance function left on stack */ -ENTRY(_ctx_x86_call0) +ENTRY(_ctx_x86_callip) #if !__OMIT_FRAMEPOINTER__ xorq %rbp, %rbp /* reset frame pointer */ #endif /* !__OMIT_FRAMEPOINTER__ */ ret /* jump to entrance function left on stack */ +ENTRY(_ctx_x86_call0) +#if !__OMIT_FRAMEPOINTER__ + xorq %rbp, %rbp /* reset frame pointer */ +#endif /* !__OMIT_FRAMEPOINTER__ */ + popq %rax /* Get the 'entry' function address */ + call *%rax /* Call 'entry' */ + ret /* jump to thread cleanup function left on stack */ + ENTRY(_ctx_x86_call1) #if !__OMIT_FRAMEPOINTER__ xorq %rbp, %rbp /* reset frame pointer */ #endif /* !__OMIT_FRAMEPOINTER__ */ - popq %rdi /* load first argument from stack */ - ret /* jump to entrance function left on stack */ + /* Retrieve and call the 'entry' function, argument already in place */ + popq %rdi /* Get the argument for 'entry' */ + popq %rax /* Get the 'entry' function address */ + call *%rax /* Call 'entry', it uses the argument from %rdi */ + ret /* jump to thread cleanup function left on stack */ ENTRY(_ctx_x86_call2) #if !__OMIT_FRAMEPOINTER__ @@ -73,7 +84,9 @@ ENTRY(_ctx_x86_call2) #endif /* !__OMIT_FRAMEPOINTER__ */ popq %rsi /* load second argument from stack */ popq %rdi /* load first argument from stack */ - ret /* jump to entrance function left on stack */ + popq %rax /* Get the 'entry' function address */ + call *%rax /* Call 'entry', it uses the argument from %rdi %rsi */ + ret /* jump to thread cleanup function left on stack */ /* * Do a local context switch diff --git a/lib/syscall_shim/arch/arm64/syscall_ctx.S b/lib/syscall_shim/arch/arm64/syscall_ctx.S index 10b7be8f9724a1a7db50299d308b7b9da7b47507..496e3996f0e841e697a1776a73b80d826eead34c 100644 --- a/lib/syscall_shim/arch/arm64/syscall_ctx.S +++ b/lib/syscall_shim/arch/arm64/syscall_ctx.S @@ -14,7 +14,7 @@ ENTRY(uk_syscall_ctx_popall) mov x0, sp add x0, x0, #(__REGS_SIZEOF + UKARCH_SYSREGS_SIZE) - bl ukarch_ectx_store + bl ukarch_ectx_load mov x0, sp add x0, x0, #(__REGS_SIZEOF)