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

ppc64le: support OPENSSL_ppccap ENV variable #1569

Merged
merged 4 commits into from
May 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 27 additions & 8 deletions crypto/fipsmodule/cpucap/cpu_intel.c
Original file line number Diff line number Diff line change
Expand Up @@ -133,28 +133,47 @@ static void handle_cpu_env(uint32_t *out, const char *in) {
const int or = in[0] == '|';
const int skip_first_byte = invert || or;
const int hex = in[skip_first_byte] == '0' && in[skip_first_byte+1] == 'x';
uint32_t intelcap0 = out[0];
uint32_t intelcap1 = out[1];

int sscanf_result;
uint64_t v;
if (hex) {
sscanf_result = sscanf(in + invert + 2, "%" PRIx64, &v);
sscanf_result = sscanf(in + skip_first_byte + 2, "%" PRIx64, &v);
} else {
sscanf_result = sscanf(in + invert, "%" PRIu64, &v);
sscanf_result = sscanf(in + skip_first_byte, "%" PRIu64, &v);
}

if (!sscanf_result) {
return;
}

uint32_t reqcap0 = (uint32_t)(v & UINT32_MAX);
uint32_t reqcap1 = (uint32_t)(v >> 32);

// Detect if the user is trying to use the environment variable to set
// a capability that is _not_ available on the CPU.
// The case of invert cannot enable an unexisting capability;
// it can only disable an existing one.
if (!invert && (intelcap0 || intelcap1)) {
// Allow Intel indicator bit to be set for testing
if((~(1u << 30 | intelcap0) & reqcap0) || (~intelcap1 & reqcap1)) {
fprintf(stderr,
"Fatal Error: HW capability found: 0x%02X 0x%02X, but HW capability requested: 0x%02X 0x%02X.\n",
intelcap0, intelcap1, reqcap0, reqcap1);
abort();
}
}

if (invert) {
out[0] &= ~v;
out[1] &= ~(v >> 32);
out[0] &= ~reqcap0;
out[1] &= ~reqcap1;
} else if (or) {
out[0] |= v;
out[1] |= (v >> 32);
out[0] |= reqcap0;
out[1] |= reqcap1;
} else {
out[0] = v;
out[1] = v >> 32;
out[0] = reqcap0;
out[1] = reqcap1;
}
}

Expand Down
57 changes: 57 additions & 0 deletions crypto/fipsmodule/cpucap/cpu_ppc64le.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,68 @@
#define PPC_FEATURE2_HAS_VCRYPTO 0x02000000
#endif

static void handle_cpu_env(unsigned long *out, const char *in) {
justsmth marked this conversation as resolved.
Show resolved Hide resolved
OPENSSL_STATIC_ASSERT(sizeof(unsigned long) == 8, PPC64LE_UNSIGNED_LONG_NOT_8_BYTES);

const int invert = in[0] == '~';
const int or = in[0] == '|';
const int skip_first_byte = (invert || or) ? 1 : 0;
const int hex = in[skip_first_byte] == '0' && in[skip_first_byte+1] == 'x';
unsigned long ppccap = *out;

int sscanf_result;
uint64_t reqcap;
if (hex) {
sscanf_result = sscanf(in + skip_first_byte + 2, "%" PRIx64, &reqcap);
} else {
sscanf_result = sscanf(in + skip_first_byte, "%" PRIu64, &reqcap);
}

if (!sscanf_result) {
return;
}

// Detect if the user is trying to use the environment variable to set
// a capability that is _not_ available on the CPU.
// The case of invert cannot enable an unexisting capability;
// it can only disable an existing one.
if (!invert && ppccap && (~ppccap & reqcap)) {
fprintf(stderr,
"Fatal Error: HW capability found: 0x%02lX, but HW capability requested: 0x%02lX.\n",
ppccap, reqcap);
abort();
}

if (invert) {
*out &= ~reqcap;
} else if (or) {
*out |= reqcap;
} else {
*out = reqcap;
}
}

extern uint8_t OPENSSL_cpucap_initialized;

void OPENSSL_cpuid_setup(void) {
OPENSSL_ppc64le_hwcap2 = getauxval(AT_HWCAP2);
OPENSSL_cpucap_initialized = 1;

// OPENSSL_ppccap is a 64-bit hex string which may start with "0x".
// Prior to the value, a '~' or '|' may be given.
//
// If the '~' prefix is present:
// the value is inverted and ANDed with the probed CPUID result
// If the '|' prefix is present:
// the value is ORed with the probed CPUID result
// Otherwise:
// the value is taken as the result of the CPUID
const char *env;
env = getenv("OPENSSL_ppccap");
if (env != NULL) {
handle_cpu_env(&OPENSSL_ppc64le_hwcap2, env);
}

}

int CRYPTO_is_PPC64LE_vcrypto_capable(void) {
Expand Down
Loading