Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

s390x assembly pack: use getauxval to detect hw capabilities #9410

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
95 changes: 63 additions & 32 deletions crypto/s390xcap.c
Expand Up @@ -16,6 +16,13 @@
#include "internal/ctype.h"
#include "s390x_arch.h"

#if defined(__GLIBC__) && defined(__GLIBC_PREREQ)
# if __GLIBC_PREREQ(2, 16)
# include <sys/auxv.h>
# define OSSL_IMPLEMENT_GETAUXVAL
# endif
#endif

#define LEN 128
#define STR_(S) #S
#define STR(S) STR_(S)
Expand Down Expand Up @@ -47,25 +54,26 @@
memcpy(cap, &NAME, sizeof(*cap)); \
}

#ifndef OSSL_IMPLEMENT_GETAUXVAL
static sigjmp_buf ill_jmp;
static void ill_handler(int sig)
{
siglongjmp(ill_jmp, sig);
}

void OPENSSL_vx_probe(void);
#endif

static const char *env;
static int parse_env(struct OPENSSL_s390xcap_st *cap);

void OPENSSL_s390x_facilities(void);
void OPENSSL_s390x_functions(void);
void OPENSSL_vx_probe(void);

struct OPENSSL_s390xcap_st OPENSSL_s390xcap_P;

void OPENSSL_cpuid_setup(void)
{
sigset_t oset;
struct sigaction ill_act, oact_ill, oact_fpe;
struct OPENSSL_s390xcap_st cap;

if (OPENSSL_s390xcap_P.stfle[0])
Expand All @@ -74,47 +82,70 @@ void OPENSSL_cpuid_setup(void)
/* set a bit that will not be tested later */
OPENSSL_s390xcap_P.stfle[0] |= S390X_CAPBIT(0);

#ifdef OSSL_IMPLEMENT_GETAUXVAL
{
const unsigned long hwcap = getauxval(AT_HWCAP);

/* protection against missing store-facility-list-extended */
if (hwcap & HWCAP_S390_STFLE)
OPENSSL_s390x_facilities();

/* protection against disabled vector facility */
if (!(hwcap & HWCAP_S390_VX)) {
OPENSSL_s390xcap_P.stfle[2] &= ~(S390X_CAPBIT(S390X_VX)
| S390X_CAPBIT(S390X_VXD)
| S390X_CAPBIT(S390X_VXE));
}
}
#else
{
sigset_t oset;
struct sigaction ill_act, oact_ill, oact_fpe;

memset(&ill_act, 0, sizeof(ill_act));
ill_act.sa_handler = ill_handler;
sigfillset(&ill_act.sa_mask);
sigdelset(&ill_act.sa_mask, SIGILL);
sigdelset(&ill_act.sa_mask, SIGFPE);
sigdelset(&ill_act.sa_mask, SIGTRAP);

sigprocmask(SIG_SETMASK, &ill_act.sa_mask, &oset);
sigaction(SIGILL, &ill_act, &oact_ill);
sigaction(SIGFPE, &ill_act, &oact_fpe);

/* protection against missing store-facility-list-extended */
if (sigsetjmp(ill_jmp, 1) == 0)
OPENSSL_s390x_facilities();

/* protection against disabled vector facility */
if ((OPENSSL_s390xcap_P.stfle[2] & S390X_CAPBIT(S390X_VX))
&& (sigsetjmp(ill_jmp, 1) == 0)) {
OPENSSL_vx_probe();
} else {
OPENSSL_s390xcap_P.stfle[2] &= ~(S390X_CAPBIT(S390X_VX)
| S390X_CAPBIT(S390X_VXD)
| S390X_CAPBIT(S390X_VXE));
}

sigaction(SIGFPE, &oact_fpe, NULL);
sigaction(SIGILL, &oact_ill, NULL);
sigprocmask(SIG_SETMASK, &oset, NULL);
}
#endif

env = getenv("OPENSSL_s390xcap");
if (env != NULL) {
if (!parse_env(&cap))
env = NULL;
}

memset(&ill_act, 0, sizeof(ill_act));
ill_act.sa_handler = ill_handler;
sigfillset(&ill_act.sa_mask);
sigdelset(&ill_act.sa_mask, SIGILL);
sigdelset(&ill_act.sa_mask, SIGFPE);
sigdelset(&ill_act.sa_mask, SIGTRAP);
sigprocmask(SIG_SETMASK, &ill_act.sa_mask, &oset);
sigaction(SIGILL, &ill_act, &oact_ill);
sigaction(SIGFPE, &ill_act, &oact_fpe);

/* protection against missing store-facility-list-extended */
if (sigsetjmp(ill_jmp, 1) == 0)
OPENSSL_s390x_facilities();

if (env != NULL) {
OPENSSL_s390xcap_P.stfle[0] &= cap.stfle[0];
OPENSSL_s390xcap_P.stfle[1] &= cap.stfle[1];
OPENSSL_s390xcap_P.stfle[2] &= cap.stfle[2];
}

/* protection against disabled vector facility */
if ((OPENSSL_s390xcap_P.stfle[2] & S390X_CAPBIT(S390X_VX))
&& (sigsetjmp(ill_jmp, 1) == 0)) {
OPENSSL_vx_probe();
} else {
OPENSSL_s390xcap_P.stfle[2] &= ~(S390X_CAPBIT(S390X_VX)
| S390X_CAPBIT(S390X_VXD)
| S390X_CAPBIT(S390X_VXE));
}

sigaction(SIGFPE, &oact_fpe, NULL);
sigaction(SIGILL, &oact_ill, NULL);
sigprocmask(SIG_SETMASK, &oset, NULL);

OPENSSL_s390x_functions();
OPENSSL_s390x_functions(); /* check OPENSSL_s390xcap_P.stfle */

if (env != NULL) {
OPENSSL_s390xcap_P.kimd[0] &= cap.kimd[0];
Expand Down