-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Support mixed SSE/AVX audit and check AVX only once.
This patch fixes mixed SSE/AVX audit and checks AVX only once in _dl_runtime_profile. When an AVX or SSE register value in pltenter is modified, we have to make sure that the SSE part value is the same in both lr_xmm and lr_vector fields so that pltexit will get the correct value from either lr_xmm or lr_vector fields. AVX-enabled pltenter should update both lr_xmm and lr_vector fields to support stacked AVX/SSE pltenter functions.
- Loading branch information
H.J. Lu
authored and
Ulrich Drepper
committed
Aug 8, 2009
1 parent
fc1870e
commit 4e1e2f4
Showing
11 changed files
with
1,062 additions
and
239 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
/* Test case for x86-64 preserved registers in dynamic linker. */ | ||
|
||
#include <stdlib.h> | ||
#include <string.h> | ||
#include <cpuid.h> | ||
#include <emmintrin.h> | ||
|
||
extern __m128i audit_test (__m128i, __m128i, __m128i, __m128i, | ||
__m128i, __m128i, __m128i, __m128i); | ||
|
||
int | ||
main (void) | ||
{ | ||
unsigned int eax, ebx, ecx, edx; | ||
|
||
/* Run AVX test only if AVX is supported. */ | ||
if (__get_cpuid (1, &eax, &ebx, &ecx, &edx) | ||
&& (ecx & bit_AVX)) | ||
{ | ||
__m128i xmm = _mm_setzero_si128 (); | ||
__m128i ret = audit_test (xmm, xmm, xmm, xmm, xmm, xmm, xmm, xmm); | ||
|
||
xmm = _mm_set1_epi32 (0x98abcdef); | ||
if (memcmp (&xmm, &ret, sizeof (ret))) | ||
abort (); | ||
} | ||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
#include "tst-audit6.c" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
/* Test case for x86-64 preserved registers in dynamic linker. */ | ||
|
||
#include <stdlib.h> | ||
#include <string.h> | ||
#include <emmintrin.h> | ||
|
||
__m128i | ||
audit_test (__m128i x0, __m128i x1, __m128i x2, __m128i x3, | ||
__m128i x4, __m128i x5, __m128i x6, __m128i x7) | ||
{ | ||
__m128i xmm; | ||
|
||
xmm = _mm_set1_epi32 (0x100); | ||
if (memcmp (&xmm, &x0, sizeof (xmm))) | ||
abort (); | ||
|
||
xmm = _mm_set1_epi32 (0x101); | ||
if (memcmp (&xmm, &x1, sizeof (xmm))) | ||
abort (); | ||
|
||
xmm = _mm_set1_epi32 (0x102); | ||
if (memcmp (&xmm, &x2, sizeof (xmm))) | ||
abort (); | ||
|
||
xmm = _mm_set1_epi32 (0x103); | ||
if (memcmp (&xmm, &x3, sizeof (xmm))) | ||
abort (); | ||
|
||
xmm = _mm_set1_epi32 (0x104); | ||
if (memcmp (&xmm, &x4, sizeof (xmm))) | ||
abort (); | ||
|
||
xmm = _mm_set1_epi32 (0x105); | ||
if (memcmp (&xmm, &x5, sizeof (xmm))) | ||
abort (); | ||
|
||
xmm = _mm_set1_epi32 (0x106); | ||
if (memcmp (&xmm, &x6, sizeof (xmm))) | ||
abort (); | ||
|
||
xmm = _mm_set1_epi32 (0x107); | ||
if (memcmp (&xmm, &x7, sizeof (xmm))) | ||
abort (); | ||
|
||
return _mm_setzero_si128 (); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,220 @@ | ||
/* Verify that changing AVX registers in audit library won't affect | ||
function parameter passing/return. */ | ||
|
||
#include <dlfcn.h> | ||
#include <stdint.h> | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include <string.h> | ||
#include <unistd.h> | ||
#include <bits/wordsize.h> | ||
#include <gnu/lib-names.h> | ||
|
||
unsigned int | ||
la_version (unsigned int v) | ||
{ | ||
setlinebuf (stdout); | ||
|
||
printf ("version: %u\n", v); | ||
|
||
char buf[20]; | ||
sprintf (buf, "%u", v); | ||
|
||
return v; | ||
} | ||
|
||
void | ||
la_activity (uintptr_t *cookie, unsigned int flag) | ||
{ | ||
if (flag == LA_ACT_CONSISTENT) | ||
printf ("activity: consistent\n"); | ||
else if (flag == LA_ACT_ADD) | ||
printf ("activity: add\n"); | ||
else if (flag == LA_ACT_DELETE) | ||
printf ("activity: delete\n"); | ||
else | ||
printf ("activity: unknown activity %u\n", flag); | ||
} | ||
|
||
char * | ||
la_objsearch (const char *name, uintptr_t *cookie, unsigned int flag) | ||
{ | ||
char buf[100]; | ||
const char *flagstr; | ||
if (flag == LA_SER_ORIG) | ||
flagstr = "LA_SET_ORIG"; | ||
else if (flag == LA_SER_LIBPATH) | ||
flagstr = "LA_SER_LIBPATH"; | ||
else if (flag == LA_SER_RUNPATH) | ||
flagstr = "LA_SER_RUNPATH"; | ||
else if (flag == LA_SER_CONFIG) | ||
flagstr = "LA_SER_CONFIG"; | ||
else if (flag == LA_SER_DEFAULT) | ||
flagstr = "LA_SER_DEFAULT"; | ||
else if (flag == LA_SER_SECURE) | ||
flagstr = "LA_SER_SECURE"; | ||
else | ||
{ | ||
sprintf (buf, "unknown flag %d", flag); | ||
flagstr = buf; | ||
} | ||
printf ("objsearch: %s, %s\n", name, flagstr); | ||
|
||
return (char *) name; | ||
} | ||
|
||
unsigned int | ||
la_objopen (struct link_map *l, Lmid_t lmid, uintptr_t *cookie) | ||
{ | ||
printf ("objopen: %ld, %s\n", lmid, l->l_name); | ||
|
||
return 3; | ||
} | ||
|
||
void | ||
la_preinit (uintptr_t *cookie) | ||
{ | ||
printf ("preinit\n"); | ||
} | ||
|
||
unsigned int | ||
la_objclose (uintptr_t *cookie) | ||
{ | ||
printf ("objclose\n"); | ||
return 0; | ||
} | ||
|
||
uintptr_t | ||
la_symbind64 (Elf64_Sym *sym, unsigned int ndx, uintptr_t *refcook, | ||
uintptr_t *defcook, unsigned int *flags, const char *symname) | ||
{ | ||
printf ("symbind64: symname=%s, st_value=%#lx, ndx=%u, flags=%u\n", | ||
symname, (long int) sym->st_value, ndx, *flags); | ||
|
||
return sym->st_value; | ||
} | ||
|
||
#define pltenter la_x86_64_gnu_pltenter | ||
#define pltexit la_x86_64_gnu_pltexit | ||
#define La_regs La_x86_64_regs | ||
#define La_retval La_x86_64_retval | ||
#define int_retval lrv_rax | ||
|
||
#include <tst-audit.h> | ||
|
||
#ifdef __AVX__ | ||
#include <immintrin.h> | ||
#include <cpuid.h> | ||
|
||
static int avx = -1; | ||
|
||
static int | ||
__attribute ((always_inline)) | ||
check_avx (void) | ||
{ | ||
if (avx == -1) | ||
{ | ||
unsigned int eax, ebx, ecx, edx; | ||
|
||
if (__get_cpuid (1, &eax, &ebx, &ecx, &edx) | ||
&& (ecx & bit_AVX)) | ||
avx = 1; | ||
else | ||
avx = 0; | ||
} | ||
return avx; | ||
} | ||
#else | ||
#include <emmintrin.h> | ||
#endif | ||
|
||
ElfW(Addr) | ||
pltenter (ElfW(Sym) *sym, unsigned int ndx, uintptr_t *refcook, | ||
uintptr_t *defcook, La_regs *regs, unsigned int *flags, | ||
const char *symname, long int *framesizep) | ||
{ | ||
printf ("pltenter: symname=%s, st_value=%#lx, ndx=%u, flags=%u\n", | ||
symname, (long int) sym->st_value, ndx, *flags); | ||
|
||
#ifdef __AVX__ | ||
if (check_avx () && strcmp (symname, "audit_test") == 0) | ||
{ | ||
int i; | ||
|
||
__m128i xmm = _mm_setzero_si128 (); | ||
for (i = 0; i < 8; i++) | ||
if (memcmp (®s->lr_xmm[i], &xmm, sizeof (xmm)) | ||
|| memcmp (®s->lr_vector[i], &xmm, sizeof (xmm))) | ||
abort (); | ||
|
||
for (i = 0; i < 8; i += 2) | ||
{ | ||
regs->lr_xmm[i] = (La_x86_64_xmm) _mm_set1_epi32 (i + 1); | ||
regs->lr_vector[i].xmm[0] = regs->lr_xmm[i]; | ||
regs->lr_vector[i + 1].ymm[0] | ||
= (La_x86_64_ymm) _mm256_set1_epi32 (i + 2); | ||
regs->lr_xmm[i + 1] = regs->lr_vector[i + 1].xmm[0]; | ||
} | ||
|
||
__m256i ymm = _mm256_set1_epi32 (-1); | ||
asm volatile ("vmovdqa %0, %%ymm0" : : "x" (ymm) : "xmm0" ); | ||
asm volatile ("vmovdqa %0, %%ymm1" : : "x" (ymm) : "xmm1" ); | ||
asm volatile ("vmovdqa %0, %%ymm2" : : "x" (ymm) : "xmm2" ); | ||
asm volatile ("vmovdqa %0, %%ymm3" : : "x" (ymm) : "xmm3" ); | ||
asm volatile ("vmovdqa %0, %%ymm4" : : "x" (ymm) : "xmm4" ); | ||
asm volatile ("vmovdqa %0, %%ymm5" : : "x" (ymm) : "xmm5" ); | ||
asm volatile ("vmovdqa %0, %%ymm6" : : "x" (ymm) : "xmm6" ); | ||
asm volatile ("vmovdqa %0, %%ymm7" : : "x" (ymm) : "xmm7" ); | ||
|
||
*framesizep = 1024; | ||
} | ||
#endif | ||
|
||
return sym->st_value; | ||
} | ||
|
||
unsigned int | ||
pltexit (ElfW(Sym) *sym, unsigned int ndx, uintptr_t *refcook, | ||
uintptr_t *defcook, const La_regs *inregs, La_retval *outregs, | ||
const char *symname) | ||
{ | ||
printf ("pltexit: symname=%s, st_value=%#lx, ndx=%u, retval=%tu\n", | ||
symname, (long int) sym->st_value, ndx, outregs->int_retval); | ||
|
||
#ifdef __AVX__ | ||
if (check_avx () && strcmp (symname, "audit_test") == 0) | ||
{ | ||
int i; | ||
|
||
__m128i xmm = _mm_setzero_si128 (); | ||
if (memcmp (&outregs->lrv_xmm0, &xmm, sizeof (xmm)) | ||
|| memcmp (&outregs->lrv_vector0, &xmm, sizeof (xmm))) | ||
abort (); | ||
|
||
__m256i ymm; | ||
|
||
for (i = 0; i < 8; i += 2) | ||
{ | ||
xmm = _mm_set1_epi32 (i + 0x100); | ||
if (memcmp (&inregs->lr_xmm[i], &xmm, sizeof (xmm)) | ||
|| memcmp (&inregs->lr_vector[i], &xmm, sizeof (xmm))) | ||
abort (); | ||
|
||
ymm = _mm256_set1_epi32 (i + 0x101); | ||
if (memcmp (&inregs->lr_xmm[i + 1], | ||
&inregs->lr_vector[i + 1].xmm[0], sizeof (xmm)) | ||
|| memcmp (&inregs->lr_vector[i + 1], &ymm, sizeof (ymm))) | ||
abort (); | ||
} | ||
|
||
outregs->lrv_vector0.ymm[0] | ||
= (La_x86_64_ymm) _mm256_set1_epi32 (0x12349876); | ||
|
||
ymm = _mm256_set1_epi32 (-1); | ||
asm volatile ("vmovdqa %0, %%ymm0" : : "x" (ymm) : "xmm0" ); | ||
asm volatile ("vmovdqa %0, %%ymm1" : : "x" (ymm) : "xmm1" ); | ||
} | ||
#endif | ||
|
||
return 0; | ||
} |
Oops, something went wrong.