//#endif //!USING_DDK////////////////////////////////////////////////////////////////////////////////////// Name: readITC// Purpose: To read the IA64 Itanium's Interval Time Counter (ITC, AR-44). The// ITC is equivalent to the IA32 Time Stamp Counter (TSC). The IA32// TSC can be read using the IA32 RDTSC instruction (opcode 0F 31h) but// there is no equivalent IA64 instruction to read the ITC.// Returns: The value of the ITC// Parameters: None.///////////////////////////////////////////////////////////////////////////////////// DWORDLONG rdtsc() { // *** Removed *** // GetTickCount() is a temporary function used to get a number for getting Time // Metrics for IA64 until a better function is found that works. Unfortunately // the resoultion of this timer function isn't small enough. It's in milliseconds. // // Also need to change Performance::Get_Processor_Speed() in IOPerformanc.cpp to // use milliseconds instead of using the CPU's speed if using GetTickCount(). // // IMPORTANT: If GetTickCount() is added back in then search IOPerformance.cpp for // WIN64_COUNTER_WORKAROUND for other changes that need to be added back in. // //return (DWORDLONG)GetTickCount(); // *** End removed *** // // Should read the Itanium's Interval Time Counter (ITC - AR44). // This is equivalent to the IA32 Time Stamp Counter (TSC) that is read by // the IA32 RDTSC instruction (opcode 0F 31h) // // __getReg is a compiler intrinsic defined in 'wdm.h' of the DDK. // defined. CV_IA64_ApITC is defined in 'ia64reg.h' in the DDK. // return __getReg(CV_IA64_ApITC); }
/* RDTSC from Scott Duplichan */ static ulong64 TIMFUNC(void) { #if defined __GNUC__ #if defined(__i386__) || defined(__x86_64__) unsigned long long a; __asm__ __volatile__("rdtsc\nmovl %%eax,%0\nmovl %%edx,4+%0\n":: "m"(a):"%eax", "%edx"); return a; #else /* gcc-IA64 version */ unsigned long result; __asm__ __volatile__("mov %0=ar.itc":"=r"(result)::"memory"); while (__builtin_expect((int) result == -1, 0)) __asm__ __volatile__("mov %0=ar.itc":"=r"(result)::"memory"); return result; #endif // Microsoft and Intel Windows compilers #elif defined _M_IX86 __asm rdtsc #elif defined _M_AMD64 return __rdtsc(); #elif defined _M_IA64 #if defined __INTEL_COMPILER #include <ia64intrin.h> #endif return __getReg(3116); #else #error need rdtsc function for this build #endif }
static inline unsigned long current_gp (void) { # if defined(__GNUC__) && !defined(__INTEL_COMPILER) register unsigned long gp __asm__("gp"); return gp; # elif HAVE_IA64INTRIN_H return __getReg (_IA64_REG_GP); # else # error Implement me. # endif }
uintptr_t get_bsp (void) { #if UNW_TARGET_IA64 # ifdef __INTEL_COMPILER return __getReg (_IA64_REG_AR_BSP); # else return (uintptr_t) __builtin_ia64_bsp (); # endif #else return 0; #endif }
int __cdecl _resetstkoflw(void) { LPBYTE pStack, pStackBase, pMaxGuard, pMinGuard; #if defined (_M_IA64) LPBYTE pBspBase; DWORD BspRegionSize; #endif /* defined (_M_IA64) */ MEMORY_BASIC_INFORMATION mbi; SYSTEM_INFO si; DWORD PageSize; DWORD RegionSize; DWORD flNewProtect; DWORD flOldProtect; BOOL (*SetThreadStackGuaranteePointer)( ULONG * StackSizeInBytes ); unsigned int osplatform = 0; // Use _alloca() to get the current stack pointer #pragma warning(push) #pragma warning(disable:6255) // prefast(6255): This alloca is safe and we do not want a __try here pStack = (LPBYTE)_alloca(1); #pragma warning(pop) // Find the base of the stack. if (VirtualQuery(pStack, &mbi, sizeof mbi) == 0) { return 0; } pStackBase = (LPBYTE)mbi.AllocationBase; GetSystemInfo(&si); PageSize = si.dwPageSize; RegionSize = 0; // Enable the new guard page. _ERRCHECK(_get_osplatform(&osplatform)); if (osplatform == VER_PLATFORM_WIN32_NT) { // // Note: if the GuaranteedStackBytes TEB field is 0 // (on older OS versions or if SetThreadStackGuarantee is // not being used) we will use the default value of // RegionSize (2 pages for ia64, 1 page for other platforms). // ULONG StackSizeInBytes; HMODULE ModuleHandle; // // Don't call SetThreadStackGuarantee directly as older kernel32.dll // versions do not have this export. // ModuleHandle = GetModuleHandle("kernel32.dll"); if (ModuleHandle != NULL) { SetThreadStackGuaranteePointer = (PVOID) GetProcAddress(ModuleHandle, "SetThreadStackGuarantee"); if (SetThreadStackGuaranteePointer != NULL) { StackSizeInBytes = 0; // Indicate just querying if (SetThreadStackGuaranteePointer(&StackSizeInBytes) == TRUE && StackSizeInBytes > 0) { RegionSize = StackSizeInBytes; } } } } flNewProtect = (osplatform == VER_PLATFORM_WIN32_WINDOWS) ? PAGE_NOACCESS : PAGE_READWRITE | PAGE_GUARD; RegionSize = (RegionSize + PageSize - 1) & ~(PageSize - 1); // // If there is a stack guarantee (RegionSize nonzero), then increase // our guard page size by 1 so that even a subsequent fault that occurs // midway (instead of at the beginning) through the first guard page // will have the extra page to preserve the guarantee. // if (RegionSize != 0) { RegionSize += PageSize; } #if defined (_M_IA64) // // Reset the backstore stack pages. // // // Calculate the top of the BSP stack, by getting the size of the normal // stack and adding it to the StackBase. // pBspBase = (LPBYTE)(((ULONG_PTR)(((PNT_TIB)NtCurrentTeb())->StackBase) - (ULONG_PTR) mbi.AllocationBase) + (ULONG_PTR)(((PNT_TIB)NtCurrentTeb())->StackBase)); // // Get the current BSP and round up since the BSP grows up. // pMinGuard = (LPBYTE)((__getReg(__REG_IA64_RsBSP) + PageSize) & ~(ULONG_PTR)(PageSize - 1)); // // The highest BSP address is the top of the BSP stack less one page for // the guard. // pMaxGuard = pBspBase - PageSize; BspRegionSize = RegionSize; if (BspRegionSize < MIN_BSP_REQ_WINNT * PageSize) { BspRegionSize = MIN_BSP_REQ_WINNT * PageSize; } if (((ULONG_PTR)pMaxGuard < BspRegionSize) || (pMaxGuard - BspRegionSize) < pMinGuard) { // // The current BSP is already in the highest guard region. // return 0; } if (VirtualAlloc(pMinGuard, BspRegionSize, MEM_COMMIT, PAGE_READWRITE) == NULL || VirtualProtect(pMinGuard, BspRegionSize, flNewProtect, &flOldProtect) == 0) { return 0; } #endif /* defined (_M_IA64) */ if (RegionSize < MIN_STACK_REQ_WINNT * PageSize) { RegionSize = MIN_STACK_REQ_WINNT * PageSize; } // // Find the page(s) just below where the stack pointer currently points. // This is the highest potential guard page. // pMaxGuard = (LPBYTE)(((DWORD_PTR)pStack & ~(DWORD_PTR)(PageSize - 1)) - RegionSize); // // If the potential guard page is too close to the start of the stack // region, abandon the reset effort for lack of space. Win9x has a // larger reserved stack requirement. // pMinGuard = pStackBase + ( (osplatform == VER_PLATFORM_WIN32_WINDOWS) ? MIN_STACK_REQ_WIN9X : PageSize); if (pMaxGuard < pMinGuard) { return 0; } // Set the new guard page just below the current stack page. if (VirtualAlloc(pMaxGuard, RegionSize, MEM_COMMIT, PAGE_READWRITE) == NULL || VirtualProtect(pMaxGuard, RegionSize, flNewProtect, &flOldProtect) == 0) { return 0; } return 1; }
unsigned __int64 check__getReg() { unsigned volatile __int64 reg; reg = __getReg(18); reg = __getReg(31); return reg; }