diff --git a/tests/testDriver_stfle_alignment_precheck.c b/tests/testDriver_stfle_alignment_precheck.c new file mode 100644 index 0000000..7ce3422 --- /dev/null +++ b/tests/testDriver_stfle_alignment_precheck.c @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: Apache-2.0 +/* + * Copyright IBM Corp. 2024 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "testsupport.h" + +#include + +/* + * Regression coverage for an alignment edge case in the Linux STFLE path. + * + * When ZDNN_ENABLE_PRECHECK is enabled, invoke_stfle() verifies the facility + * list buffer is 8-byte aligned. Historically, zdnn_is_nnpa_installed() used a + * local unsigned-char array which is not *guaranteed* to be 8-byte aligned. + * + * This test asserts that enabling precheck does not trigger a + * ZDNN_MISALIGNED_PARMBLOCK failure in the STFLE path. + * + * Note: This is a Linux-only behavior; z/OS uses a system copy of STFLE. + */ + +void setUp(void) { +#ifdef __MVS__ + TEST_IGNORE_MESSAGE("Linux STFLE alignment regression test; skipping on z/OS"); +#endif +} + +void tearDown(void) {} + +void test_precheck_does_not_trigger_misaligned_parmblock(void) { + precheck_enabled = true; + + char buf_stderr[BUFSIZ] = {0}; + + stderr_to_pipe(); + (void)zdnn_is_nnpa_installed(); + restore_stderr(buf_stderr, BUFSIZ); + + TEST_ASSERT_NULL_MESSAGE( + strstr(buf_stderr, "ZDNN_MISALIGNED_PARMBLOCK"), + "Unexpected misaligned parmblock failure in STFLE path"); + + precheck_enabled = false; +} + +int main(void) { + UNITY_BEGIN(); + + RUN_TEST(test_precheck_does_not_trigger_misaligned_parmblock); + + return UNITY_END(); +} diff --git a/zdnn/initializer.cpp b/zdnn/initializer.cpp index 8b85a84..2d03132 100644 --- a/zdnn/initializer.cpp +++ b/zdnn/initializer.cpp @@ -18,7 +18,6 @@ extern "C" { #include "zdnn.h" } -#include /// Invoke initializer routine(s) at DLL-load time. /// diff --git a/zdnn/zdnn_init.c b/zdnn/zdnn_init.c index 1737854..f4d52e9 100644 --- a/zdnn/zdnn_init.c +++ b/zdnn/zdnn_init.c @@ -163,16 +163,19 @@ static inline int check_bitfield(const uint8_t *bitfield, int bitno) { bool zdnn_is_nnpa_installed() { #ifndef __MVS__ int nnpa_supported; - unsigned char facilities[STFLE_LENGTH] = {0}; + // invoke_stfle() requires the facility list to be 8-byte aligned when + // ZDNN_ENABLE_PRECHECK is enabled. Using a uint64_t array guarantees the + // required alignment regardless of compiler/stack placement decisions. + uint64_t facilities64[STFLE_LENGTH / 8] = {0}; int cc; - cc = invoke_stfle(facilities); + cc = invoke_stfle((unsigned char *)facilities64); if (cc) { LOG_ERROR("STFLE failed with %d", cc); return false; } - nnpa_supported = check_bitfield(facilities, STFLE_NNPA); + nnpa_supported = check_bitfield((uint8_t *)facilities64, STFLE_NNPA); LOG_INFO("Hardware NNPA support available - %s", nnpa_supported ? "TRUE" : "FALSE");