Skip to content

Commit

Permalink
Support mixed SSE/AVX audit and check AVX only once.
Browse files Browse the repository at this point in the history
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
Show file tree
Hide file tree
Showing 11 changed files with 1,062 additions and 239 deletions.
28 changes: 28 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,31 @@
2009-08-01 H.J. Lu <hongjiu.lu@intel.com>

* elf/Makefile (distribute): Add tst-audit6.c tst-auditmod6a.c
tst-auditmod6b.c tst-auditmod6c.c tst-audit7.c tst-auditmod7a.c
tst-auditmod7b.c.
(tests): Add tst-audit6 tst-audit7.
(modules-names): Add st-auditmod6a tst-auditmod6b tst-auditmod6c
tst-auditmod7a tst-auditmod7b.
($(objpfx)tst-audit6): New.
($(objpfx)tst-audit6.out): Likewise.
($(objpfx)tst-audit7): Likewise.
($(objpfx)tst-audit7.out): Likewise.
(tst-audit6-ENV): Likewise.
(tst-audit7-ENV): Likewise.
(CFLAGS-tst-auditmod6b.c): Likewise.
(CFLAGS-tst-auditmod6c.c): Likewise.
(CFLAGS-tst-auditmod7b.c): Likewise.
* elf/tst-audit6.c: New file.
* elf/tst-audit7.c: New file.
* elf/tst-auditmod6a.c: New file.
* elf/tst-auditmod6b.c: New file.
* elf/tst-auditmod6c.c: New file.
* elf/tst-auditmod7a.c: New file.
* elf/tst-auditmod7b.c: New file.
* sysdeps/x86_64/dl-trampoline.S (_dl_runtime_profile): Move
saving and restoring SSE/AVX registers to ...
* sysdeps/x86_64/dl-trampoline.h: This. New file.

2009-08-07 H.J. Lu <hongjiu.lu@intel.com>

* sysdeps/i386/i686/multiarch/strcspn.S (STRCSPN): Use PIC
Expand Down
21 changes: 19 additions & 2 deletions elf/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,9 @@ distribute := rtld-Rules \
tst-auditmod1.c tst-auditmod3a.c tst-auditmod3b.c \
tst-auditmod4a.c tst-auditmod4b.c \
tst-audit5.c tst-auditmod5a.c tst-auditmod5b.c \
tst-audit6.c tst-auditmod6a.c tst-auditmod6b.c \
tst-auditmod6c.c \
tst-audit7.c tst-auditmod7a.c tst-auditmod7b.c \
order2mod1.c order2mod2.c order2mod3.c order2mod4.c \
tst-stackguard1.c tst-stackguard1-static.c \
tst-array5.c tst-array5-static.c tst-array5dep.c \
Expand Down Expand Up @@ -200,7 +203,7 @@ tests += loadtest restest1 preloadtest loadfail multiload origtest resolvfail \
test-srcs = tst-pathopt
tests-execstack-yes = tst-execstack tst-execstack-needed tst-execstack-prog
ifeq (x86_64,$(config-machine))
tests += tst-audit3 tst-audit4 tst-audit5
tests += tst-audit3 tst-audit4 tst-audit5 tst-audit6 tst-audit7
endif
endif
ifeq (yesyes,$(have-fpie)$(build-shared))
Expand Down Expand Up @@ -255,7 +258,9 @@ endif
ifeq (x86_64,$(config-machine))
modules-names += tst-auditmod3a tst-auditmod3b \
tst-auditmod4a tst-auditmod4b \
tst-auditmod5a tst-auditmod5b
tst-auditmod5a tst-auditmod5b \
tst-auditmod6a tst-auditmod6b tst-auditmod6c \
tst-auditmod7a tst-auditmod7b
endif
modules-execstack-yes = tst-execstack-mod
extra-test-objs += $(addsuffix .os,$(strip $(modules-names)))
Expand Down Expand Up @@ -987,6 +992,15 @@ $(objpfx)tst-audit5: $(objpfx)tst-auditmod5a.so
$(objpfx)tst-audit5.out: $(objpfx)tst-auditmod5b.so
tst-audit5-ENV = LD_AUDIT=$(objpfx)tst-auditmod5b.so

$(objpfx)tst-audit6: $(objpfx)tst-auditmod6a.so
$(objpfx)tst-audit6.out: $(objpfx)tst-auditmod6b.so \
$(objpfx)tst-auditmod6c.so
tst-audit6-ENV = LD_AUDIT=$(objpfx)tst-auditmod6b.so:$(objpfx)tst-auditmod6c.so

$(objpfx)tst-audit7: $(objpfx)tst-auditmod7a.so
$(objpfx)tst-audit7.out: $(objpfx)tst-auditmod7b.so
tst-audit7-ENV = LD_AUDIT=$(objpfx)tst-auditmod7b.so

$(objpfx)tst-global1: $(libdl)
$(objpfx)tst-global1.out: $(objpfx)testobj6.so $(objpfx)testobj2.so

Expand Down Expand Up @@ -1134,4 +1148,7 @@ ifeq (yes,$(config-cflags-avx))
CFLAGS-tst-audit4.c += -mavx
CFLAGS-tst-auditmod4a.c += -mavx
CFLAGS-tst-auditmod4b.c += -mavx
CFLAGS-tst-auditmod6b.c += -mavx
CFLAGS-tst-auditmod6c.c += -mavx
CFLAGS-tst-auditmod7b.c += -mavx
endif
28 changes: 28 additions & 0 deletions elf/tst-audit6.c
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;
}
1 change: 1 addition & 0 deletions elf/tst-audit7.c
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#include "tst-audit6.c"
46 changes: 46 additions & 0 deletions elf/tst-auditmod6a.c
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 ();
}
220 changes: 220 additions & 0 deletions elf/tst-auditmod6b.c
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 (&regs->lr_xmm[i], &xmm, sizeof (xmm))
|| memcmp (&regs->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;
}
Loading

0 comments on commit 4e1e2f4

Please sign in to comment.