From: Sergiu Moga Date: Fri, 7 Feb 2025 12:23:23 +0000 (+0200) Subject: lib/syscall_shim: Introduce `uk_syscall_do_` variant X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=fc2384906dc1c8638a080997dfc4e645047367bf;p=unikraft%2Funikraft.git lib/syscall_shim: Introduce `uk_syscall_do_` variant Since either the `uk_syscall_r_`/`uk_syscall_r_e` or `uk_syscall_e`/`uk_syscall_e_e` end up calling the syscall enter and exit tables, we need a new, third, variant that guarantees calling nothing but the actual implementation logic of the syscall itself. Thus, introduce such a variant: the `uk_syscall_do_` variant. This will be the exact same as what the `uk_syscall_r_` variant was, previous to the introduction of the system call tables. Signed-off-by: Sergiu Moga Approved-by: Michalis Pappas Reviewed-by: Michalis Pappas GitHub-Closes: #1277 --- diff --git a/lib/syscall_shim/Makefile.uk b/lib/syscall_shim/Makefile.uk index a317b63c8..365aad528 100644 --- a/lib/syscall_shim/Makefile.uk +++ b/lib/syscall_shim/Makefile.uk @@ -55,6 +55,10 @@ LIBSYSCALL_SHIM_SRCS-y += $(LIBSYSCALL_SHIM_BASE)/syscall_r_static.awk>.h LIBSYSCALL_SHIM_SYSCALL_R_STATIC_SUBBUILD = $(LIBSYSCALL_SHIM_INCLUDES_SUBBUILD) LIBSYSCALL_SHIM_SYSCALL_R_STATIC_AWKINCLUDES-y += $(LIBSYSCALL_SHIM_BUILD)/provided_syscalls.in LIBSYSCALL_SHIM_SYSCALL_R_STATIC_AWKFLAGS-y += -F '-' +LIBSYSCALL_SHIM_SRCS-y += $(LIBSYSCALL_SHIM_BASE)/syscall_do_static.awk>.h +LIBSYSCALL_SHIM_SYSCALL_DO_STATIC_SUBBUILD = $(LIBSYSCALL_SHIM_INCLUDES_SUBBUILD) +LIBSYSCALL_SHIM_SYSCALL_DO_STATIC_AWKINCLUDES-y += $(LIBSYSCALL_SHIM_BUILD)/provided_syscalls.in +LIBSYSCALL_SHIM_SYSCALL_DO_STATIC_AWKFLAGS-y += -F '-' LIBSYSCALL_SHIM_SRCS-y += $(LIBSYSCALL_SHIM_BASE)/syscall_nrs.awk>.h LIBSYSCALL_SHIM_SYSCALL_NRS_SUBBUILD = $(LIBSYSCALL_SHIM_INCLUDES_SUBBUILD) @@ -81,6 +85,9 @@ LIBSYSCALL_SHIM_UK_SYSCALL6_AWKFLAGS-y += -F '-' LIBSYSCALL_SHIM_SRCS-y += $(LIBSYSCALL_SHIM_BASE)/uk_syscall6_r.awk>.c LIBSYSCALL_SHIM_UK_SYSCALL6_R_AWKINCLUDES-y += $(LIBSYSCALL_SHIM_BUILD)/provided_syscalls.in LIBSYSCALL_SHIM_UK_SYSCALL6_R_AWKFLAGS-y += -F '-' +LIBSYSCALL_SHIM_SRCS-y += $(LIBSYSCALL_SHIM_BASE)/uk_syscall6_do.awk>.c +LIBSYSCALL_SHIM_UK_SYSCALL6_DO_AWKINCLUDES-y += $(LIBSYSCALL_SHIM_BUILD)/provided_syscalls.in +LIBSYSCALL_SHIM_UK_SYSCALL6_DO_AWKFLAGS-y += -F '-' LIBSYSCALL_SHIM_SRCS-y += $(LIBSYSCALL_SHIM_BASE)/uk_syscall_name.awk>.c LIBSYSCALL_SHIM_UK_SYSCALL_NAME_AWKINCLUDES-y += $(LIBSYSCALL_SHIM_ARCH_TEMPLATE) diff --git a/lib/syscall_shim/include/uk/syscall.h b/lib/syscall_shim/include/uk/syscall.h index b39ece4eb..770a179ae 100644 --- a/lib/syscall_shim/include/uk/syscall.h +++ b/lib/syscall_shim/include/uk/syscall.h @@ -114,6 +114,7 @@ typedef long uk_syscall_arg_t; #define __UK_NAME2SCALLE_FN(name) UK_CONCAT(uk_syscall_e_, name) #define __UK_NAME2SCALLR_FN(name) UK_CONCAT(uk_syscall_r_, name) +#define __UK_NAME2SCALLDO_FN(name) UK_CONCAT(uk_syscall_do_, name) #define UK_ARG_MAP0(...) #define UK_ARG_MAP2(m, type, arg) m(type, arg) @@ -289,7 +290,7 @@ typedef long uk_syscall_arg_t; * UK_LLSYSCALL_DEFINE() * Low-level variant, does not provide a libc-style wrapper */ -#define __UK_LLSYSCALL_DEFINE(x, rtype, name, ename, rname, ...) \ +#define __UK_LLSYSCALL_DEFINE(x, rtype, name, ename, rname, doname, ...)\ long ename(UK_ARG_MAPx(x, UK_S_ARG_LONG, __VA_ARGS__)); \ long rname(UK_ARG_MAPx(x, UK_S_ARG_LONG, __VA_ARGS__)) \ { \ @@ -320,6 +321,23 @@ typedef long uk_syscall_arg_t; _uk_syscall_wrapper_do_exittab(NULL); \ \ return ret; \ + } \ + \ + long doname(UK_ARG_MAPx(x, UK_S_ARG_LONG, __VA_ARGS__)) \ + { \ + int _errno = errno; \ + long ret; \ + \ + __UK_SYSCALL_PRINTD(x, rtype, doname, __VA_ARGS__); \ + \ + errno = 0; \ + ret = (long) __##ename( \ + UK_ARG_MAPx(x, UK_S_ARG_CAST_ACTUAL, __VA_ARGS__)); \ + if (ret == -1) \ + ret = errno ? -errno : -EFAULT; \ + errno = _errno; \ + \ + return ret; \ } \ static inline rtype __##ename(UK_ARG_MAPx(x, \ UK_S_ARG_ACTUAL_MAYBE_UNUSED,\ @@ -331,6 +349,7 @@ typedef long uk_syscall_arg_t; name, \ __UK_NAME2SCALLE_FN(name), \ __UK_NAME2SCALLR_FN(name), \ + __UK_NAME2SCALLDO_FN(name), \ __VA_ARGS__) /* @@ -339,7 +358,7 @@ typedef long uk_syscall_arg_t; * in case UK_LIBC_SYSCALLS is enabled */ #if UK_LIBC_SYSCALLS -#define __UK_SYSCALL_DEFINE(x, rtype, name, ename, rname, ...) \ +#define __UK_SYSCALL_DEFINE(x, rtype, name, ename, rname, doname, ...) \ long ename(UK_ARG_MAPx(x, UK_S_ARG_LONG, __VA_ARGS__)); \ rtype name(UK_ARG_MAPx(x, UK_S_ARG_ACTUAL, __VA_ARGS__)) \ { \ @@ -349,7 +368,7 @@ typedef long uk_syscall_arg_t; UK_ARG_MAPx(x, UK_S_ARG_CAST_LONG, __VA_ARGS__)); \ return ret; \ } \ - __UK_LLSYSCALL_DEFINE(x, rtype, name, ename, rname, __VA_ARGS__) + __UK_LLSYSCALL_DEFINE(x, rtype, name, ename, rname, doname, __VA_ARGS__) #define _UK_SYSCALL_DEFINE(...) __UK_SYSCALL_DEFINE(__VA_ARGS__) #define UK_SYSCALL_DEFINE(rtype, name, ...) \ _UK_SYSCALL_DEFINE(UK_NARGS(__VA_ARGS__), \ @@ -357,6 +376,7 @@ typedef long uk_syscall_arg_t; name, \ __UK_NAME2SCALLE_FN(name), \ __UK_NAME2SCALLR_FN(name), \ + __UK_NAME2SCALLDO_FN(name), \ __VA_ARGS__) #else #define UK_SYSCALL_DEFINE(rtype, name, ...) \ @@ -365,6 +385,7 @@ typedef long uk_syscall_arg_t; name, \ __UK_NAME2SCALLE_FN(name), \ __UK_NAME2SCALLR_FN(name), \ + __UK_NAME2SCALLDO_FN(name), \ __VA_ARGS__) #endif /* UK_LIBC_SYSCALLS */ @@ -376,7 +397,7 @@ typedef long uk_syscall_arg_t; * UK_LLSYSCALL_R_DEFINE() * Low-level variant, does not provide a libc-style wrapper */ -#define __UK_LLSYSCALL_R_DEFINE(x, rtype, name, ename, rname, ...) \ +#define __UK_LLSYSCALL_R_DEFINE(x, rtype, name, ename, rname, doname, ...)\ long rname(UK_ARG_MAPx(x, UK_S_ARG_LONG, __VA_ARGS__)); \ long ename(UK_ARG_MAPx(x, UK_S_ARG_LONG, __VA_ARGS__)) \ { \ @@ -406,6 +427,17 @@ typedef long uk_syscall_arg_t; _uk_syscall_wrapper_do_exittab(NULL); \ \ return ret; \ + } \ + \ + long doname(UK_ARG_MAPx(x, UK_S_ARG_LONG, __VA_ARGS__)) \ + { \ + long ret; \ + \ + __UK_SYSCALL_PRINTD(x, rtype, doname, __VA_ARGS__); \ + \ + ret = (long) __##rname( \ + UK_ARG_MAPx(x, UK_S_ARG_CAST_ACTUAL, __VA_ARGS__)); \ + return ret; \ } \ static inline rtype __##rname(UK_ARG_MAPx(x, \ UK_S_ARG_ACTUAL_MAYBE_UNUSED,\ @@ -417,9 +449,10 @@ typedef long uk_syscall_arg_t; name, \ __UK_NAME2SCALLE_FN(name), \ __UK_NAME2SCALLR_FN(name), \ + __UK_NAME2SCALLDO_FN(name), \ __VA_ARGS__) -#define __UK_LLSYSCALL_R_E_DEFINE(x, rtype, name, ename, rname, ...) \ +#define __UK_LLSYSCALL_R_E_DEFINE(x, rtype, name, ename, rname, doname, ...)\ long rname(long _execenv); \ long __used ename(long _execenv) \ { \ @@ -453,6 +486,22 @@ typedef long uk_syscall_arg_t; _uk_syscall_wrapper_do_exittab(execenv); \ \ return ret; \ + } \ + \ + long __used doname(long _execenv) \ + { \ + struct ukarch_execenv *execenv; \ + long ret; \ + \ + execenv = (struct ukarch_execenv *)_execenv; \ + __UK_SYSCALL_EXECENV_PRINTD(execenv, x, rtype, doname, \ + __VA_ARGS__); \ + \ + ret = (long) __##rname(UK_EXECENV_CALLMAPx(x, \ + UK_S_ARG_ACTUAL, \ + __VA_ARGS__)); \ + \ + return ret; \ } \ static inline rtype __used __##rname(UK_EXECENV_DECLMAPx( \ UK_S_EXECENV_ARG_ACTUAL_MAYBE_UNUSED,\ @@ -468,11 +517,16 @@ typedef long uk_syscall_arg_t; __UK_NAME2SCALLR_FN(e_##name), \ UK_NARGS(__VA_ARGS__), \ __VA_ARGS__) \ + UK_SYSCALL_EXECENV_PROLOGUE_DEFINE(__UK_NAME2SCALLDO_FN(name), \ + __UK_NAME2SCALLDO_FN(e_##name), \ + UK_NARGS(__VA_ARGS__), \ + __VA_ARGS__) \ _UK_LLSYSCALL_R_E_DEFINE(UK_NARGS(__VA_ARGS__), \ rtype, \ name, \ __UK_NAME2SCALLE_FN(e_##name), \ __UK_NAME2SCALLR_FN(e_##name), \ + __UK_NAME2SCALLDO_FN(e_##name), \ __VA_ARGS__) /* @@ -481,7 +535,7 @@ typedef long uk_syscall_arg_t; * in case UK_LIBC_SYSCALLS is enabled */ #if UK_LIBC_SYSCALLS -#define __UK_SYSCALL_R_DEFINE(x, rtype, name, ename, rname, ...) \ +#define __UK_SYSCALL_R_DEFINE(x, rtype, name, ename, rname, doname, ...)\ long ename(UK_ARG_MAPx(x, UK_S_ARG_LONG, __VA_ARGS__)); \ rtype name(UK_ARG_MAPx(x, UK_S_ARG_ACTUAL, __VA_ARGS__)) \ { \ @@ -491,7 +545,8 @@ typedef long uk_syscall_arg_t; UK_ARG_MAPx(x, UK_S_ARG_CAST_LONG, __VA_ARGS__)); \ return ret; \ } \ - __UK_LLSYSCALL_R_DEFINE(x, rtype, name, ename, rname, __VA_ARGS__) + __UK_LLSYSCALL_R_DEFINE(x, rtype, name, ename, rname, doname, \ + __VA_ARGS__) #define _UK_SYSCALL_R_DEFINE(...) __UK_SYSCALL_R_DEFINE(__VA_ARGS__) #define UK_SYSCALL_R_DEFINE(rtype, name, ...) \ _UK_SYSCALL_R_DEFINE(UK_NARGS(__VA_ARGS__), \ @@ -499,6 +554,7 @@ typedef long uk_syscall_arg_t; name, \ __UK_NAME2SCALLE_FN(name), \ __UK_NAME2SCALLR_FN(name), \ + __UK_NAME2SCALLDO_FN(name), \ __VA_ARGS__) #else #define UK_SYSCALL_R_DEFINE(rtype, name, ...) \ @@ -507,6 +563,7 @@ typedef long uk_syscall_arg_t; name, \ __UK_NAME2SCALLE_FN(name), \ __UK_NAME2SCALLR_FN(name), \ + __UK_NAME2SCALLDO_FN(name), \ __VA_ARGS__) #endif /* UK_LIBC_SYSCALLS */ @@ -527,6 +584,8 @@ typedef long uk_syscall_arg_t; long __UK_NAME2SCALLE_FN(syscall_name)(__UK_SPROTO_ARGSx(args_nr)) #define UK_SYSCALL_R_PROTO(args_nr, syscall_name) \ long __UK_NAME2SCALLR_FN(syscall_name)(__UK_SPROTO_ARGSx(args_nr)) +#define UK_SYSCALL_DO_PROTO(args_nr, syscall_name) \ + long __UK_NAME2SCALLDO_FN(syscall_name)(__UK_SPROTO_ARGSx(args_nr)) #define uk_syscall_e_stub(syscall_name) ({ \ uk_pr_debug("System call \"" syscall_name \ @@ -584,6 +643,7 @@ long uk_syscall6(long nr, long arg1, long arg2, long arg3, long uk_syscall_r(long nr, ...); long uk_vsyscall_r(long nr, va_list arg); long uk_syscall6_r_e(struct ukarch_execenv *execenv); +long uk_syscall6_do_e(struct ukarch_execenv *execenv); long uk_syscall6_r(long nr, long arg1, long arg2, long arg3, long arg4, long arg5, long arg6); diff --git a/lib/syscall_shim/syscall_do_static.awk b/lib/syscall_shim/syscall_do_static.awk new file mode 100644 index 000000000..e14a406e5 --- /dev/null +++ b/lib/syscall_shim/syscall_do_static.awk @@ -0,0 +1,71 @@ +BEGIN { + max_args = 6 + print "/* Auto generated file. DO NOT EDIT */\n\n" +} + +/[a-zA-Z0-9]+-[0-9]+e?/ { + name = $1 + args_nr = $2 + 0 + + printf "\n/* SYS_%s: %d argument(s) */\n", name, args_nr; + for (i = 0; i <= max_args; i++) + { + if (substr($0, length($0)) == "e") { + printf "#define uk_syscall_do%d_e_%s(", i, name; + for (j = 1; j <= i; j++) + { + if (j > 1) + printf ", " + printf "arg%d", j; + } + printf ") \\\n"; + + printf "\tuk_syscall_do_e_%s(", name; + + # hand-over given arguments + for (j = 1; j <= i && j <= args_nr; j++) + { + if (j > 1) + printf ", " + printf "__uk_scc(arg%d)", j; + } + + # fill-up missing arguments + for (j = i + 1; j <= args_nr; j++) + { + if (j > 1) + printf ", " + printf "__uk_scc(0)"; + } + printf ")\n"; + } + + printf "#define uk_syscall_do%d_%s(", i, name; + for (j = 1; j <= i; j++) + { + if (j > 1) + printf ", " + printf "arg%d", j; + } + printf ") \\\n"; + + printf "\tuk_syscall_do_%s(", name; + + # hand-over given arguments + for (j = 1; j <= i && j <= args_nr; j++) + { + if (j > 1) + printf ", " + printf "__uk_scc(arg%d)", j; + } + + # fill-up missing arguments + for (j = i + 1; j <= args_nr; j++) + { + if (j > 1) + printf ", " + printf "__uk_scc(0)"; + } + printf ")\n"; + } +} diff --git a/lib/syscall_shim/syscall_gensyms.awk b/lib/syscall_shim/syscall_gensyms.awk index 194ad0b5c..6abc52add 100644 --- a/lib/syscall_shim/syscall_gensyms.awk +++ b/lib/syscall_shim/syscall_gensyms.awk @@ -5,5 +5,8 @@ if (substr($0, length($0)) == "e") { printf "uk_syscall_r_e_%s\n", name; printf "uk_syscall_e_e_%s\n", name; + printf "uk_syscall_do_e_%s\n", name; + } else { + printf "uk_syscall_do_%s\n", name; } } diff --git a/lib/syscall_shim/syscall_provided.awk b/lib/syscall_shim/syscall_provided.awk index 9bb0ea4e3..b2391c88e 100644 --- a/lib/syscall_shim/syscall_provided.awk +++ b/lib/syscall_shim/syscall_provided.awk @@ -24,13 +24,16 @@ BEGIN { printf "#define HAVE_uk_syscall_e_%s t\n", $1; printf "UK_SYSCALL_E_PROTO(1, e_%s);\n", $1; printf "UK_SYSCALL_R_PROTO(1, e_%s);\n", $1; + printf "UK_SYSCALL_DO_PROTO(1, e_%s);\n", $1; printf "#define HAVE_uk_syscall_%s t\n", $1; printf "UK_SYSCALL_E_PROTO(%s, %s);\n", $2 + 0, $1; printf "UK_SYSCALL_R_PROTO(%s, %s);\n", $2 + 0, $1; + printf "UK_SYSCALL_DO_PROTO(%s, %s);\n", $2 + 0, $1; } else { printf "#define HAVE_uk_syscall_%s t\n", $1; printf "UK_SYSCALL_E_PROTO(%s, %s);\n", $2, $1; printf "UK_SYSCALL_R_PROTO(%s, %s);\n", $2, $1; + printf "UK_SYSCALL_DO_PROTO(%s, %s);\n", $2, $1; } printf "#endif /* !SYS_%s */\n", $1; } diff --git a/lib/syscall_shim/syscall_stubs.awk b/lib/syscall_shim/syscall_stubs.awk index 8ae5cf35d..ab6393084 100644 --- a/lib/syscall_shim/syscall_stubs.awk +++ b/lib/syscall_shim/syscall_stubs.awk @@ -4,9 +4,11 @@ BEGIN { print "/* Auto generated file. Do not edit */" } printf "\n#ifndef HAVE_uk_syscall_%s", name; printf "\n#define uk_syscall_e_%s(...) uk_syscall_e_stub(\"%s\")", name, name; printf "\n#define uk_syscall_r_%s(...) uk_syscall_r_stub(\"%s\")", name, name; + printf "\n#define uk_syscall_do_%s(...) uk_syscall_r_stub(\"%s\")", name, name; printf "\n#ifndef HAVE_uk_syscall_e_%s", name; printf "\n#define uk_syscall_e_e_%s(...) uk_syscall_e_stub(\"%s\")", name, name; printf "\n#define uk_syscall_r_e_%s(...) uk_syscall_r_stub(\"%s\")", name, name; + printf "\n#define uk_syscall_do_e_%s(...) uk_syscall_r_stub(\"%s\")", name, name; printf "\n#endif /* !HAVE_uk_syscall_e_%s */\n", name; printf "\n#endif /* !HAVE_uk_syscall_%s */\n", name; } diff --git a/lib/syscall_shim/uk_syscall6_do.awk b/lib/syscall_shim/uk_syscall6_do.awk new file mode 100644 index 000000000..9cd58978d --- /dev/null +++ b/lib/syscall_shim/uk_syscall6_do.awk @@ -0,0 +1,47 @@ +BEGIN { + max_args = 6 + print "/* Auto generated file. DO NOT EDIT */\n\n" + + print "#include " + print "#include " + print "#include \n" + + print "UK_SYSCALL_EXECENV_PROLOGUE_DEFINE(uk_syscall6_do, uk_syscall6_do_e," + print "\t\t\t\t14, long, nr, long, arg1, long, arg2, long, arg3, long, arg4, long, arg5, long, arg6)"; + print "\nlong __used uk_syscall6_do_e(struct ukarch_execenv *execenv)" + print "{" + print "\tlong ret;" + print "\n\tswitch (execenv->regs.__syscall_rsyscall) {" +} + +/[a-zA-Z0-9]+-[0-9]+/{ + name = $1 + sys_name = "SYS_" name + uk_syscall_do = "uk_syscall_do_" name + uk_syscall_do_e = "uk_syscall_do_e_" name + args_nr = $2 + 0 + printf "\n#ifdef HAVE_uk_syscall_%s\n", name; + printf "\tcase %s:\n", sys_name; + printf "\n#ifdef HAVE_uk_syscall_e_%s\n", name; + printf "\t\tret = %s((long)execenv);\n", uk_syscall_do_e; + printf "#else /* !HAVE_uk_syscall_e_%s */\n", name; + printf "\t\tret = %s(\n\t\t\t\t\t", uk_syscall_do; + for (i = 0; i < args_nr - 1; i++) + printf("execenv->regs.__syscall_rarg%d, ", i) + if (args_nr > 0) + printf("execenv->regs.__syscall_rarg%d", args_nr - 1) + printf(");\n") + printf "\n#endif /* !HAVE_uk_syscall_e_%s */\n\n", name; + printf "\t\tbreak;\n" + printf "\n#endif /* HAVE_uk_syscall_%s */\n", name; +} + +END { + printf "\tdefault:\n" + printf "\t\tuk_pr_debug(\"syscall \\\"%%s\\\" is not available\\n\", uk_syscall_name(execenv->regs.__syscall_rsyscall));\n" + printf "\t\tret = -ENOSYS;\n" + printf "\t}\n" + printf "\treturn ret;\n" + printf "}\n" + printf "\n" +}