From dc3d53417e7e806638592a40a7ceb9c8b92b450a Mon Sep 17 00:00:00 2001 From: Jeff Waugh Date: Thu, 27 Oct 2016 13:52:15 +1100 Subject: [PATCH 1/2] Retain in-register error descriptions when not using IPC buffer - Fixes "lost" error descriptions when using *WithMRs system call variants [1]. - Only stores real registers to IPC buffer if there's an error. - If there's an error in a struct-returning function, return early without setting any struct members. - Passes the sabre/qemu test suite... with and without --buffer! [1] https://sel4.systems/pipermail/devel/2016-October/001079.html --- libsel4/tools/syscall_stub_gen.py | 53 +++++++++++++++++-------------- 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/libsel4/tools/syscall_stub_gen.py b/libsel4/tools/syscall_stub_gen.py index ae044bd96..a178a9066 100644 --- a/libsel4/tools/syscall_stub_gen.py +++ b/libsel4/tools/syscall_stub_gen.py @@ -557,11 +557,10 @@ def generate_stub(arch, wordsize, interface_name, method_name, method_id, input_ # # Setup variables we will need. # - if returning_struct: - result.append("\t%s result;" % return_type) + result.append("\t%s result;" % return_type) result.append("\tseL4_MessageInfo_t tag = seL4_MessageInfo_new(%s, 0, %d, %d);" % (method_id, len(cap_expressions), len(input_expressions))) result.append("\tseL4_MessageInfo_t output_tag;") - for i in range(min(num_mrs, max(input_param_words, output_param_words))): + for i in range(num_mrs): result.append("\tseL4_Word mr%d;" % i) result.append("") @@ -584,24 +583,22 @@ def generate_stub(arch, wordsize, interface_name, method_name, method_id, input_ # seL4_SetMR(i, v); # ... # - if len(input_expressions) > 0: - result.append("\t/* Marshal input parameters. */") - for i in range(len(input_expressions)): - if i < num_mrs: + if max(num_mrs, len(input_expressions)) > 0: + result.append("\t/* Marshal and initialise parameters. */") + # Initialise in-register parameters + for i in range(num_mrs): + if i < len(input_expressions): result.append("\tmr%d = %s;" % (i, input_expressions[i])) else: - result.append("\tseL4_SetMR(%d, %s);" % (i, input_expressions[i])) + result.append("\tmr%d = 0;" % i) + # Initialise buffered parameters + for i in range(num_mrs, len(input_expressions)): + result.append("\tseL4_SetMR(%d, %s);" % (i, input_expressions[i])) result.append("") # # Generate the call. # - call_arguments = [] - for i in range(num_mrs): - if i < max(input_param_words, output_param_words): - call_arguments.append("&mr%d" % i) - else: - call_arguments.append("seL4_Null") if use_only_ipc_buffer: result.append("\t/* Perform the call. */") result.append("\toutput_tag = seL4_Call(%s, tag);" % service_cap) @@ -609,9 +606,25 @@ def generate_stub(arch, wordsize, interface_name, method_name, method_id, input_ result.append("\t/* Perform the call, passing in-register arguments directly. */") result.append("\toutput_tag = seL4_CallWithMRs(%s, tag," % (service_cap)) result.append("\t\t%s);" % ', '.join( - [call_arguments[i] for i in range(num_mrs)])) + ("&mr%d" % i) for i in range(num_mrs))) + + # + # Prepare the result. + # + label = "result.error" if returning_struct else "result" + result.append("\t%s = seL4_MessageInfo_get_label(output_tag);" % label) result.append("") + if not use_only_ipc_buffer: + result.append("\t/* Unmarshal registers into IPC buffer on error. */") + result.append("\tif (%s != seL4_NoError) {" % label) + for i in range(num_mrs): + result.append("\t\tseL4_SetMR(%d, mr%d);" % (i, i)) + if returning_struct: + result.append("\t\treturn result;") + result.append("\t}") + result.append("") + # # Generate unmarshalling code. # @@ -639,18 +652,10 @@ def generate_stub(arch, wordsize, interface_name, method_name, method_id, input_ for word in words: result.append("\tresult.%s = %s;" % (param.name, word % source_words)) - result.append("") - - # Return result - if returning_struct: - result.append("\tresult.error = seL4_MessageInfo_get_label(output_tag);") - result.append("\treturn result;") - else: - result.append("\treturn seL4_MessageInfo_get_label(output_tag);") - # # } # + result.append("\treturn result;") result.append("}") return "\n".join(result) + "\n" From be68b0c0bde5bfa439376fac4c8be255dacaa958 Mon Sep 17 00:00:00 2001 From: Adrian Danis Date: Fri, 28 Oct 2016 15:24:09 +1100 Subject: [PATCH 2/2] libsel4: Allow invocations to not use IPC buffer Reintroduces Kconfig option removed in 5271925ba54639b849261e652e73ab56ee243fb2 that allows invocations to use the WithMRs variants of syscalls instead of using the IPC buffer --- libsel4/Kconfig | 10 ++++++++++ libsel4/Makefile | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/libsel4/Kconfig b/libsel4/Kconfig index 383a07212..e5b0d6c81 100644 --- a/libsel4/Kconfig +++ b/libsel4/Kconfig @@ -26,6 +26,16 @@ config LIB_SEL4_INLINE_INVOCATIONS for verification, so setting to 'n' will forcively prevent the function from being inlined +config LIB_SEL4_STUBS_USE_IPC_BUFFER_ONLY + bool "use only IPC buffer for syscalls" + depends on LIB_SEL4 + default n + help + When generating syscall wrappers, only use the IPC buffer for + marshalling and unmarshalling arguments. Without this option set, + arguments will be passed in registers where possible for better + performance. + config HAVE_LIB_SEL4 bool endmenu diff --git a/libsel4/Makefile b/libsel4/Makefile index 3a0e2d86e..fd472308d 100644 --- a/libsel4/Makefile +++ b/libsel4/Makefile @@ -121,5 +121,5 @@ include/interfaces/sel4_client.h: \ @mkdir -p $(dir $@) @${CHANGED_PATH} $@ \ ${PYTHON} ${SOURCE_DIR}/tools/syscall_stub_gen.py \ - --buffer \ + $(if ${CONFIG_LIB_SEL4_STUBS_USE_IPC_BUFFER_ONLY},--buffer,) \ -a $(SEL4_ARCH) -c ${srctree}/.config -o $@ $^