summaryrefslogtreecommitdiff
path: root/src/systemc/tests/systemc/bugs/stack_alignment/stack_alignment.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/systemc/tests/systemc/bugs/stack_alignment/stack_alignment.cpp')
-rw-r--r--src/systemc/tests/systemc/bugs/stack_alignment/stack_alignment.cpp129
1 files changed, 129 insertions, 0 deletions
diff --git a/src/systemc/tests/systemc/bugs/stack_alignment/stack_alignment.cpp b/src/systemc/tests/systemc/bugs/stack_alignment/stack_alignment.cpp
new file mode 100644
index 000000000..e20395e2f
--- /dev/null
+++ b/src/systemc/tests/systemc/bugs/stack_alignment/stack_alignment.cpp
@@ -0,0 +1,129 @@
+/*****************************************************************************
+
+ Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
+ more contributor license agreements. See the NOTICE file distributed
+ with this work for additional information regarding copyright ownership.
+ Accellera licenses this file to you 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.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ stack_alignment.cpp -- This example shows the crash of an fxsave instruction
+ in the sc_thread stack environment, but not in the
+ original linux process stack, which is correctly
+ aligned on first function.
+
+ Please note that this test probably runs OK on a faulty implementation in
+ 64-bit in general (depending on your libc implementation), but will crash
+ for sure in 32-bit.
+
+ Original Author: Eric Paire, STMicroelectronics
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ MODIFICATION LOG - modifiers, enter your name, affiliation, date and
+ changes you are making here.
+
+ Name, Affiliation, Date:
+ Description of Modification:
+
+ *****************************************************************************/
+
+#include "systemc.h"
+
+/*
+ * This program exhibits a bug in the management by QT of the stack of each
+ * SystemC process. At least on i686 & x86_64, GCC makes the assumption that
+ * the stack is aligned on a 16-byte boundary on each C/C++ function entry.
+ * This convention allows GCC to respects constraints of automatic (stack)
+ * variable alignment, using the __attribute)__ ((align(X))) GCC extension.
+ *
+ * The X is known to be 16 for i686 & x86_64, as this is the largest alignment
+ * required by instructions operands, actually used by fxsave instruction.
+ *
+ * The attached code shows up the problem by crashing when fxsave is executed
+ * in a SystemC thread, and executing correctly the *same* code on the initial
+ * process stack, as initialized by the libc runtime.
+ *
+ * This misbehavior does not occur systematically for x86_64 (no crash,
+ * or crash difficult to reproduce with standard malloc()), but often does
+ * with i686. Notice that the instruction with the right alignment is shown
+ * when using the myfpxregs address which is aligned on 16-byte boundary.
+ */
+
+#if defined(__x86_64__)
+# define FXSAVE "fxsaveq"
+#else
+# define FXSAVE "fxsave"
+#endif
+
+#if defined(__GNUC__)
+# define ALIGNED_ARRAY( Type, Name, Size, Align ) \
+ Type Name[Size] __attribute__((aligned(Align)))
+#elif defined(_MSC_VER)
+# define ALIGNED_ARRAY( Type, Name, Size, Align ) \
+ __declspec(align(Align)) Type Name[Size]
+#endif
+
+#if defined(__GNUC__) && ( defined(__x86_64__) || defined(__i386__) )
+# define ASM( Assembly ) __asm__ __volatile__( Assembly )
+#else
+# define ASM( Assembly ) /* not implemented */
+#endif
+
+// Class
+SC_MODULE(C)
+{
+public:
+ SC_CTOR(C) {
+ SC_THREAD(run);
+ }
+ void run(void)
+ {
+ ALIGNED_ARRAY( char, fpxregs64, 512+15, 16 );
+
+ cout << "Inside C::run() " << endl;
+
+ // manually enforce alignment (volatile to avoid optmizations)
+ char * volatile myfpxregs = fpxregs64;
+ while ((uintptr_t)myfpxregs & 0xF)
+ myfpxregs++;
+
+ // the "real" requirement: enforced alignment works
+ sc_assert( !((uintptr_t)fpxregs64 & 0xF) );
+ sc_assert( !((uintptr_t)myfpxregs & 0xF) );
+ sc_assert( myfpxregs == fpxregs64 );
+
+ // test assembly on supported platforms
+ ASM( FXSAVE " (%0)" :: "r"(myfpxregs) );
+ cout << "Between C::run() " << endl;
+ ASM( FXSAVE " %0" : "=m"(fpxregs64) );
+
+ cout << "Out of C::run() " << endl;
+ }
+};
+
+int sc_main(int , char** ) {
+ C the_C("C");
+
+ ALIGNED_ARRAY( char, fpxregs64, 512, 16 );
+
+ cout << "Inside sc_main() " << endl;
+ ASM( FXSAVE " %0" : "=m"(fpxregs64) );
+ sc_start(1, SC_NS);
+ cout << "Out of sc_main() " << endl;
+ return 0;
+}