1/***************************************************************************** 2 3 Licensed to Accellera Systems Initiative Inc. (Accellera) under one or 4 more contributor license agreements. See the NOTICE file distributed 5 with this work for additional information regarding copyright ownership. 6 Accellera licenses this file to you under the Apache License, Version 2.0 7 (the "License"); you may not use this file except in compliance with the 8 License. You may obtain a copy of the License at 9 10 http://www.apache.org/licenses/LICENSE-2.0 11 12 Unless required by applicable law or agreed to in writing, software 13 distributed under the License is distributed on an "AS IS" BASIS, 14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 15 implied. See the License for the specific language governing 16 permissions and limitations under the License. 17 18 *****************************************************************************/ 19 20/***************************************************************************** 21 22 stack_alignment.cpp -- This example shows the crash of an fxsave instruction 23 in the sc_thread stack environment, but not in the 24 original linux process stack, which is correctly 25 aligned on first function. 26 27 Please note that this test probably runs OK on a faulty implementation in 28 64-bit in general (depending on your libc implementation), but will crash 29 for sure in 32-bit. 30 31 Original Author: Eric Paire, STMicroelectronics 32 33 *****************************************************************************/ 34 35/***************************************************************************** 36 37 MODIFICATION LOG - modifiers, enter your name, affiliation, date and 38 changes you are making here. 39 40 Name, Affiliation, Date: 41 Description of Modification: 42 43 *****************************************************************************/ 44 45#include "systemc.h" 46 47/* 48 * This program exhibits a bug in the management by QT of the stack of each 49 * SystemC process. At least on i686 & x86_64, GCC makes the assumption that 50 * the stack is aligned on a 16-byte boundary on each C/C++ function entry. 51 * This convention allows GCC to respects constraints of automatic (stack) 52 * variable alignment, using the __attribute)__ ((align(X))) GCC extension. 53 * 54 * The X is known to be 16 for i686 & x86_64, as this is the largest alignment 55 * required by instructions operands, actually used by fxsave instruction. 56 * 57 * The attached code shows up the problem by crashing when fxsave is executed 58 * in a SystemC thread, and executing correctly the *same* code on the initial 59 * process stack, as initialized by the libc runtime. 60 * 61 * This misbehavior does not occur systematically for x86_64 (no crash, 62 * or crash difficult to reproduce with standard malloc()), but often does 63 * with i686. Notice that the instruction with the right alignment is shown 64 * when using the myfpxregs address which is aligned on 16-byte boundary. 65 */ 66 67#if defined(__x86_64__) 68# define FXSAVE "fxsaveq" 69#else 70# define FXSAVE "fxsave" 71#endif 72 73#if defined(__GNUC__) 74# define ALIGNED_ARRAY( Type, Name, Size, Align ) \ 75 Type Name[Size] __attribute__((aligned(Align))) 76#elif defined(_MSC_VER) 77# define ALIGNED_ARRAY( Type, Name, Size, Align ) \ 78 __declspec(align(Align)) Type Name[Size] 79#endif 80 81#if defined(__GNUC__) && ( defined(__x86_64__) || defined(__i386__) ) 82# define ASM( Assembly ) __asm__ __volatile__( Assembly ) 83#else 84# define ASM( Assembly ) /* not implemented */ 85#endif 86 87// Class 88SC_MODULE(C) 89{ 90public: 91 SC_CTOR(C) { 92 SC_THREAD(run); 93 } 94 void run(void) 95 { 96 ALIGNED_ARRAY( char, fpxregs64, 512+15, 16 ); 97 98 cout << "Inside C::run() " << endl; 99 100 // manually enforce alignment (volatile to avoid optmizations) 101 char * volatile myfpxregs = fpxregs64; 102 while ((uintptr_t)myfpxregs & 0xF) 103 myfpxregs++; 104 105 // the "real" requirement: enforced alignment works 106 sc_assert( !((uintptr_t)fpxregs64 & 0xF) ); 107 sc_assert( !((uintptr_t)myfpxregs & 0xF) ); 108 sc_assert( myfpxregs == fpxregs64 ); 109 110 // test assembly on supported platforms 111 ASM( FXSAVE " (%0)" :: "r"(myfpxregs) ); 112 cout << "Between C::run() " << endl; 113 ASM( FXSAVE " %0" : "=m"(fpxregs64) ); 114 115 cout << "Out of C::run() " << endl; 116 } 117}; 118 119int sc_main(int , char** ) { 120 C the_C("C"); 121 122 ALIGNED_ARRAY( char, fpxregs64, 512, 16 ); 123 124 cout << "Inside sc_main() " << endl; 125 ASM( FXSAVE " %0" : "=m"(fpxregs64) ); 126 sc_start(1, SC_NS); 127 cout << "Out of sc_main() " << endl; 128 return 0; 129} 130