From ab3c8bea07449c2305e9b9ad10421e316ce1d453 Mon Sep 17 00:00:00 2001 From: David Karoly Date: Tue, 5 Apr 2022 18:58:19 +0200 Subject: [PATCH] gensyscalls: alignment fixup for ARM ARM ABI has different alignment requirements based on parameter size: * parameters not larger than 4 bytes are aligned on 4 bytes * parameters larger than 4 bytes are aligned on 8 bytes see: Procedure Call Standard for the Arm Architecture sections 5.1, Fundamental Data Types and 6.5, Parameter Passing Therefore the following changes are introduced in gensyscalls tool: * new optional define SYSCALL_LONG_PARAMETER_ALIGNMENT_TYPE is introduced * it's defined only on ARM * on other architectures it takes on the value of SYSCALL_PARAMETER_ALIGNMENT_TYPE as a default * constants kLongParameterAlignmentType and kLongParameterAlignmentSize are introduced * Syscall::AddParameter uses this value for aligning parameters larger than 4 bytes Change-Id: I7e766e0ea9d07001643e813722b462b1f044921a Reviewed-on: https://review.haiku-os.org/c/haiku/+/5112 Reviewed-by: Adrien Destugues Tested-by: Commit checker robot --- src/tools/gensyscalls/arch/arm/arch_gensyscalls.h | 5 +++-- src/tools/gensyscalls/gensyscallinfos.cpp | 15 +++++++++++++++ src/tools/gensyscalls/gensyscalls.cpp | 9 +++++++++ src/tools/gensyscalls/gensyscalls.h | 2 ++ 4 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/tools/gensyscalls/arch/arm/arch_gensyscalls.h b/src/tools/gensyscalls/arch/arm/arch_gensyscalls.h index d67d074574..42fb1c823f 100644 --- a/src/tools/gensyscalls/arch/arm/arch_gensyscalls.h +++ b/src/tools/gensyscalls/arch/arm/arch_gensyscalls.h @@ -1,2 +1,3 @@ -#define SYSCALL_RETURN_TYPE_ALIGNMENT_TYPE int -#define SYSCALL_PARAMETER_ALIGNMENT_TYPE int +#define SYSCALL_RETURN_TYPE_ALIGNMENT_TYPE int +#define SYSCALL_PARAMETER_ALIGNMENT_TYPE int +#define SYSCALL_LONG_PARAMETER_ALIGNMENT_TYPE long long diff --git a/src/tools/gensyscalls/gensyscallinfos.cpp b/src/tools/gensyscalls/gensyscallinfos.cpp index 4da80561b0..6483653443 100644 --- a/src/tools/gensyscalls/gensyscallinfos.cpp +++ b/src/tools/gensyscalls/gensyscallinfos.cpp @@ -18,6 +18,10 @@ #include "arch_gensyscalls.h" // for the alignment type macros (only for the type names) +#ifndef SYSCALL_LONG_PARAMETER_ALIGNMENT_TYPE +#define SYSCALL_LONG_PARAMETER_ALIGNMENT_TYPE SYSCALL_PARAMETER_ALIGNMENT_TYPE +#endif + // macro trickery to create a string literal #define MAKE_STRING(x) #x @@ -357,10 +361,15 @@ private: file << "const char* const kParameterAlignmentType = \"" EVAL_MACRO(MAKE_STRING, SYSCALL_PARAMETER_ALIGNMENT_TYPE) << "\";" << endl; + file << "const char* const kLongParameterAlignmentType = \"" + EVAL_MACRO(MAKE_STRING, SYSCALL_LONG_PARAMETER_ALIGNMENT_TYPE) + << "\";" << endl; file << "const int kReturnTypeAlignmentSize = " "SYSCALL_RETURN_TYPE_ALIGNMENT_SIZE;" << endl; file << "const int kParameterAlignmentSize = " "SYSCALL_PARAMETER_ALIGNMENT_SIZE;" << endl; + file << "const int kLongParameterAlignmentSize = " + "SYSCALL_LONG_PARAMETER_ALIGNMENT_SIZE;" << endl; file << endl; file << "SyscallVector* create_syscall_vector() {" << endl; @@ -418,12 +427,18 @@ private: file << endl; file << "#include \"arch_gensyscalls.h\"" << endl; file << endl; + file << "#ifndef SYSCALL_LONG_PARAMETER_ALIGNMENT_TYPE" << endl; + file << "#define SYSCALL_LONG_PARAMETER_ALIGNMENT_TYPE SYSCALL_PARAMETER_ALIGNMENT_TYPE" + << endl; + file << "#endif" << endl; file << "void dummy() {" << endl; file << "DEFINE_COMPUTED_ASM_MACRO(SYSCALL_RETURN_TYPE_ALIGNMENT_SIZE, " "sizeof(SYSCALL_RETURN_TYPE_ALIGNMENT_TYPE));" << endl; file << "DEFINE_COMPUTED_ASM_MACRO(SYSCALL_PARAMETER_ALIGNMENT_SIZE, " "sizeof(SYSCALL_PARAMETER_ALIGNMENT_TYPE));" << endl; + file << "DEFINE_COMPUTED_ASM_MACRO(SYSCALL_LONG_PARAMETER_ALIGNMENT_SIZE, " + "sizeof(SYSCALL_LONG_PARAMETER_ALIGNMENT_TYPE));" << endl; file << endl; // syscalls diff --git a/src/tools/gensyscalls/gensyscalls.cpp b/src/tools/gensyscalls/gensyscalls.cpp index 340c0a5a1e..e53f2890a5 100644 --- a/src/tools/gensyscalls/gensyscalls.cpp +++ b/src/tools/gensyscalls/gensyscalls.cpp @@ -166,6 +166,15 @@ Syscall::AddParameter(int size, const char* typeName, const char* parameterName) if (Parameter* previous = LastParameter()) offset = previous->Offset() + previous->UsedSize(); + // take care of extra alignment for long parameters + // this is needed to sort out parameter offsets on ARM + if (size >= kLongParameterAlignmentSize) { + if ((offset % kLongParameterAlignmentSize) != 0) { + offset += kLongParameterAlignmentSize + - offset % kLongParameterAlignmentSize; + } + } + int usedSize = (size + kParameterAlignmentSize - 1) / kParameterAlignmentSize * kParameterAlignmentSize; const char* alignmentType diff --git a/src/tools/gensyscalls/gensyscalls.h b/src/tools/gensyscalls/gensyscalls.h index fe8a19542d..9d40db503b 100644 --- a/src/tools/gensyscalls/gensyscalls.h +++ b/src/tools/gensyscalls/gensyscalls.h @@ -8,8 +8,10 @@ extern const char* const kReturnTypeAlignmentType; extern const char* const kParameterAlignmentType; +extern const char* const kLongParameterAlignmentType; extern const int kReturnTypeAlignmentSize; extern const int kParameterAlignmentSize; +extern const int kLongParameterAlignmentSize; // Type