opal/patcher: fix xlc support
The xlc compiler seems to behave in a different way that gcc when it comes the inline asm. There were two problems with the code with xlc: - The TOC read in mca_patcher_base_patch_hook used the syntax register unsigned long toc asm("r2") to read $r2 (the TOC pointer). With gcc this seems to behave as expected but with xlc the result in toc is not the same as $r2. I updated the code to use asm volatile ("std 2, %0" : "=m" (toc)) to load the TOC pointer. - The OPAL_PATCHER_BEGIN macro is meant to be the first thing in a hook. On PPC64 it loads the correct TOC pointer (thanks to mca_patcher_base_patch_hook) and saves the old one. The OPAL_PATCHER_END macro restores the TOC pointer. Because we *need* the TOC to be correct before it is accessed in the hook the OPAL_PATCHER_BEGIN macro MUST come first. We did this and all was well with gcc. With xlc on the other hand there was a TOC access before the assembly inserted by OPAL_PATCHER_BEGIN. To fix this quickly I broke each hook into a pair of function with the OPAL_PATCHER_* macros on the top level functions. This works around the issue but is not a clean way to fix this. In the future we should 1) either update overwrite to not need this, or 2) figure out why xlc is not inserting the asm before the first TOC read. This fixes open-mpi/ompi#1854 Signed-off-by: Nathan Hjelm <hjelmn@lanl.gov>
Этот коммит содержится в:
родитель
c082068953
Коммит
a9bc692d99
@ -98,6 +98,12 @@ opal_memory_patcher_component_t mca_memory_patcher_component = {
|
||||
#define memory_patcher_syscall syscall
|
||||
#endif
|
||||
|
||||
/* All the hooks in this file have two levels. The first level has the OPAL_PATCHER_* macros
|
||||
* around the call to the second level. This was done because with xlc the compiler was
|
||||
* generating an access to r2 before the OPAL_PATCHER_* assembly. This was loading invalid
|
||||
* data. If this can be resolved the two levels can be joined.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The following block of code is #if 0'ed out because we do not need
|
||||
* to intercept mmap() any more (mmap() only deals with memory
|
||||
@ -148,9 +154,8 @@ static void *intercept_mmap(void *start, size_t length, int prot, int flags, int
|
||||
|
||||
static int (*original_munmap) (void *, size_t);
|
||||
|
||||
static int intercept_munmap(void *start, size_t length)
|
||||
static int _intercept_munmap(void *start, size_t length)
|
||||
{
|
||||
OPAL_PATCHER_BEGIN;
|
||||
int result = 0;
|
||||
|
||||
/* could be in a malloc implementation */
|
||||
@ -162,6 +167,13 @@ static int intercept_munmap(void *start, size_t length)
|
||||
result = original_munmap (start, length);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static int intercept_munmap(void *start, size_t length)
|
||||
{
|
||||
OPAL_PATCHER_BEGIN;
|
||||
int result = _intercept_munmap (start, length);
|
||||
OPAL_PATCHER_END;
|
||||
return result;
|
||||
}
|
||||
@ -178,12 +190,11 @@ static void *(*original_mremap) (void *, size_t, void *, size_t, int);
|
||||
#endif
|
||||
|
||||
#if defined(__linux__)
|
||||
static void *intercept_mremap (void *start, size_t oldlen, size_t newlen, int flags, void *new_address)
|
||||
static void *_intercept_mremap (void *start, size_t oldlen, size_t newlen, int flags, void *new_address)
|
||||
#else
|
||||
static void *intercept_mremap (void *start, size_t oldlen, void *new_address, size_t newlen, int flags)
|
||||
static void *_intercept_mremap (void *start, size_t oldlen, void *new_address, size_t newlen, int flags)
|
||||
#endif
|
||||
{
|
||||
OPAL_PATCHER_BEGIN;
|
||||
void *result = MAP_FAILED;
|
||||
|
||||
if (MAP_FAILED != start && oldlen > 0) {
|
||||
@ -210,9 +221,26 @@ static void *intercept_mremap (void *start, size_t oldlen, void *new_address, si
|
||||
}
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#if defined(__linux__)
|
||||
static void *intercept_mremap (void *start, size_t oldlen, size_t newlen, int flags, void *new_address)
|
||||
{
|
||||
OPAL_PATCHER_BEGIN;
|
||||
void *result = _intercept_mremap (start, oldlen, newlen, flags, new_address);
|
||||
OPAL_PATCHER_END;
|
||||
return result;
|
||||
}
|
||||
#else
|
||||
static void *intercept_mremap (void *start, size_t oldlen, void *new_address, size_t newlen, int flags)
|
||||
{
|
||||
OPAL_PATCHER_BEGIN;
|
||||
void *result = _intercept_mremap (start, oldlen, new_address, newlen, flags);
|
||||
OPAL_PATCHER_END;
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@ -220,9 +248,8 @@ static void *intercept_mremap (void *start, size_t oldlen, void *new_address, si
|
||||
|
||||
static int (*original_madvise) (void *, size_t, int);
|
||||
|
||||
static int intercept_madvise (void *start, size_t length, int advice)
|
||||
static int _intercept_madvise (void *start, size_t length, int advice)
|
||||
{
|
||||
OPAL_PATCHER_BEGIN;
|
||||
int result = 0;
|
||||
|
||||
if (advice == MADV_DONTNEED ||
|
||||
@ -240,6 +267,12 @@ static int intercept_madvise (void *start, size_t length, int advice)
|
||||
result = original_madvise (start, length, advice);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
static int intercept_madvise (void *start, size_t length, int advice)
|
||||
{
|
||||
OPAL_PATCHER_BEGIN;
|
||||
int result = _intercept_madvise (start, length, advice);
|
||||
OPAL_PATCHER_END;
|
||||
return result;
|
||||
}
|
||||
@ -254,9 +287,8 @@ extern void *__curbrk; /* in libc */
|
||||
|
||||
static int (*original_brk) (void *);
|
||||
|
||||
static int intercept_brk (void *addr)
|
||||
static int _intercept_brk (void *addr)
|
||||
{
|
||||
OPAL_PATCHER_BEGIN;
|
||||
int result = 0;
|
||||
void *old_addr, *new_addr;
|
||||
|
||||
@ -293,6 +325,13 @@ static int intercept_brk (void *addr)
|
||||
} else if (new_addr < old_addr) {
|
||||
opal_mem_hooks_release_hook (new_addr, (intptr_t) old_addr - (intptr_t) new_addr, true);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static int intercept_brk (void *addr)
|
||||
{
|
||||
OPAL_PATCHER_BEGIN;
|
||||
int result = _intercept_brk (addr);
|
||||
OPAL_PATCHER_END;
|
||||
return result;
|
||||
}
|
||||
@ -364,9 +403,8 @@ static size_t memory_patcher_get_shm_seg_size (const void *shmaddr)
|
||||
|
||||
static int (*original_shmdt) (const void *);
|
||||
|
||||
static int intercept_shmdt (const void *shmaddr)
|
||||
static int _intercept_shmdt (const void *shmaddr)
|
||||
{
|
||||
OPAL_PATCHER_BEGIN;
|
||||
int result;
|
||||
|
||||
/* opal_mem_hooks_release_hook should probably be updated to take a const void *.
|
||||
@ -379,6 +417,13 @@ static int intercept_shmdt (const void *shmaddr)
|
||||
result = memory_patcher_syscall (SYS_shmdt, shmaddr);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static int intercept_shmdt (const void *shmaddr)
|
||||
{
|
||||
OPAL_PATCHER_BEGIN;
|
||||
int result = _intercept_shmdt (shmaddr);
|
||||
OPAL_PATCHER_END;
|
||||
return result;
|
||||
}
|
||||
|
@ -175,7 +175,10 @@ int mca_patcher_base_patch_hook (mca_patcher_base_module_t *module, uintptr_t ho
|
||||
}
|
||||
|
||||
// generate code to restore TOC
|
||||
register unsigned long toc asm("r2");
|
||||
unsigned long toc;
|
||||
|
||||
asm volatile ("std 2, %0" : "=m" (toc));
|
||||
|
||||
hook_patch->patch_data_size = PatchLoadImm((uintptr_t)hook_patch->patch_data, 2, toc);
|
||||
|
||||
/* put the hook patch on the patch list so it will be undone on finalize */
|
||||
|
Загрузка…
Ссылка в новой задаче
Block a user