From 1e92e5ec5e24f203532a0e54d36fc5a432d8d0e0 Mon Sep 17 00:00:00 2001 From: Radim Vansa Date: Mon, 15 Dec 2025 18:05:40 +0100 Subject: [PATCH 1/6] 8373781: [CRaC] Permit -XX:CPUFeatures on other platforms --- .../cpu/aarch64/vm_version_aarch64.cpp | 2 ++ .../cpu/aarch64/vm_version_aarch64.hpp | 2 +- src/hotspot/cpu/arm/vm_version_arm.hpp | 2 +- src/hotspot/cpu/arm/vm_version_arm_32.cpp | 2 ++ src/hotspot/cpu/ppc/vm_version_ppc.cpp | 2 ++ src/hotspot/cpu/ppc/vm_version_ppc.hpp | 2 +- src/hotspot/cpu/riscv/vm_version_riscv.cpp | 2 ++ src/hotspot/cpu/riscv/vm_version_riscv.hpp | 2 +- src/hotspot/cpu/s390/vm_version_s390.cpp | 2 ++ src/hotspot/cpu/s390/vm_version_s390.hpp | 2 +- src/hotspot/cpu/x86/globals_x86.hpp | 14 ----------- src/hotspot/cpu/x86/vm_version_x86.hpp | 4 ++-- src/hotspot/cpu/zero/vm_version_zero.cpp | 2 ++ src/hotspot/cpu/zero/vm_version_zero.hpp | 2 +- .../share/runtime/abstract_vm_version.cpp | 12 ++++++++++ .../share/runtime/abstract_vm_version.hpp | 3 +++ src/hotspot/share/runtime/crac.cpp | 4 ++-- src/hotspot/share/runtime/globals.hpp | 16 +++++++++++++ src/java.base/share/man/java.md | 23 +++++++++++++++---- 19 files changed, 71 insertions(+), 29 deletions(-) diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp index 941cb254532..ed17632bdc9 100644 --- a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp @@ -636,6 +636,8 @@ void VM_Version::initialize() { _features &= ~CPU_SVE; } + check_cpufeatures_vmoptions(); + // Construct the "features" string char buf[512]; int buf_used_len = os::snprintf_checked(buf, sizeof(buf), "0x%02x:0x%x:0x%03x:%d", _cpu, _variant, _model, _revision); diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp index de12413f214..df6fe9268f2 100644 --- a/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp @@ -66,7 +66,7 @@ class VM_Version : public Abstract_VM_Version { static void initialize(); struct VM_Features: public Zero_Features {}; static bool cpu_features_binary(VM_Features *data) { return false; } - static bool ignore_cpu_features(bool is_checkpoint) { return true; } + static bool ignore_cpu_features() { return true; } static void check_virtualizations(); static void print_platform_virtualization_info(outputStream*); diff --git a/src/hotspot/cpu/arm/vm_version_arm.hpp b/src/hotspot/cpu/arm/vm_version_arm.hpp index 1f9c73d9ce2..2f49cf4ac01 100644 --- a/src/hotspot/cpu/arm/vm_version_arm.hpp +++ b/src/hotspot/cpu/arm/vm_version_arm.hpp @@ -43,7 +43,7 @@ class VM_Version: public Abstract_VM_Version { static bool is_initialized() { return _is_initialized; } struct VM_Features: public Zero_Features {}; static bool cpu_features_binary(VM_Features *data) { return false; } - static bool ignore_cpu_features(bool is_checkpoint) { return true; } + static bool ignore_cpu_features() { return true; } protected: diff --git a/src/hotspot/cpu/arm/vm_version_arm_32.cpp b/src/hotspot/cpu/arm/vm_version_arm_32.cpp index d0941936035..8f88f9b3f89 100644 --- a/src/hotspot/cpu/arm/vm_version_arm_32.cpp +++ b/src/hotspot/cpu/arm/vm_version_arm_32.cpp @@ -350,6 +350,8 @@ void VM_Version::initialize() { FLAG_SET_DEFAULT(UseUnalignedAccesses, false); } + check_cpufeatures_vmoptions(); + _is_initialized = true; } diff --git a/src/hotspot/cpu/ppc/vm_version_ppc.cpp b/src/hotspot/cpu/ppc/vm_version_ppc.cpp index ad5e915a838..0bb7dbc971c 100644 --- a/src/hotspot/cpu/ppc/vm_version_ppc.cpp +++ b/src/hotspot/cpu/ppc/vm_version_ppc.cpp @@ -331,6 +331,8 @@ void VM_Version::initialize() { } check_virtualizations(); + + check_cpufeatures_vmoptions(); } void VM_Version::check_virtualizations() { diff --git a/src/hotspot/cpu/ppc/vm_version_ppc.hpp b/src/hotspot/cpu/ppc/vm_version_ppc.hpp index a0995b6981d..821e276cb6c 100644 --- a/src/hotspot/cpu/ppc/vm_version_ppc.hpp +++ b/src/hotspot/cpu/ppc/vm_version_ppc.hpp @@ -55,7 +55,7 @@ class VM_Version: public Abstract_VM_Version { static void check_virtualizations(); struct VM_Features: public Zero_Features {}; static bool cpu_features_binary(VM_Features *data) { return false; } - static bool ignore_cpu_features(bool is_checkpoint) { return true; } + static bool ignore_cpu_features() { return true; } // Override Abstract_VM_Version implementation static void print_platform_virtualization_info(outputStream*); diff --git a/src/hotspot/cpu/riscv/vm_version_riscv.cpp b/src/hotspot/cpu/riscv/vm_version_riscv.cpp index eca1bb83ab6..697df014706 100644 --- a/src/hotspot/cpu/riscv/vm_version_riscv.cpp +++ b/src/hotspot/cpu/riscv/vm_version_riscv.cpp @@ -62,6 +62,8 @@ void VM_Version::initialize() { #ifdef COMPILER2 c2_initialize(); #endif // COMPILER2 + + check_cpufeatures_vmoptions(); } void VM_Version::common_initialize() { diff --git a/src/hotspot/cpu/riscv/vm_version_riscv.hpp b/src/hotspot/cpu/riscv/vm_version_riscv.hpp index b14a8484d58..d2264cce092 100644 --- a/src/hotspot/cpu/riscv/vm_version_riscv.hpp +++ b/src/hotspot/cpu/riscv/vm_version_riscv.hpp @@ -309,7 +309,7 @@ class VM_Version : public Abstract_VM_Version { static void initialize_cpu_information(); struct VM_Features: public Zero_Features {}; static bool cpu_features_binary(VM_Features *data) { return false; } - static bool ignore_cpu_features(bool is_checkpoint) { return true; } + static bool ignore_cpu_features() { return true; } constexpr static bool supports_stack_watermark_barrier() { return true; } diff --git a/src/hotspot/cpu/s390/vm_version_s390.cpp b/src/hotspot/cpu/s390/vm_version_s390.cpp index 8261fbd083a..92e70b84926 100644 --- a/src/hotspot/cpu/s390/vm_version_s390.cpp +++ b/src/hotspot/cpu/s390/vm_version_s390.cpp @@ -328,6 +328,8 @@ void VM_Version::initialize() { if (FLAG_IS_DEFAULT(UseUnalignedAccesses)) { FLAG_SET_DEFAULT(UseUnalignedAccesses, true); } + + check_cpufeatures_vmoptions(); } diff --git a/src/hotspot/cpu/s390/vm_version_s390.hpp b/src/hotspot/cpu/s390/vm_version_s390.hpp index 02fb73dec6a..054e9a5ff33 100644 --- a/src/hotspot/cpu/s390/vm_version_s390.hpp +++ b/src/hotspot/cpu/s390/vm_version_s390.hpp @@ -416,7 +416,7 @@ class VM_Version: public Abstract_VM_Version { static bool is_determine_features_test_running() { return _is_determine_features_test_running; } struct VM_Features: public Zero_Features {}; static bool cpu_features_binary(VM_Features *data) { return false; } - static bool ignore_cpu_features(bool is_checkpoint) { return true; } + static bool ignore_cpu_features() { return true; } // Override Abstract_VM_Version implementation static void print_platform_virtualization_info(outputStream*); diff --git a/src/hotspot/cpu/x86/globals_x86.hpp b/src/hotspot/cpu/x86/globals_x86.hpp index 27de7eeb659..a1d4a71874f 100644 --- a/src/hotspot/cpu/x86/globals_x86.hpp +++ b/src/hotspot/cpu/x86/globals_x86.hpp @@ -182,20 +182,6 @@ define_pd_global(intx, InitArrayShortSize, 8*BytesPerLong); "Turn off JVM mitigations related to Intel micro code " \ "mitigations for the Intel JCC erratum") \ \ - product(ccstr, CPUFeatures, nullptr, "CPU feature set, " \ - "use -XX:CPUFeatures=0xnumber with -XX:CRaCCheckpointTo when you "\ - "get an error during -XX:CRaCRestoreFrom on a different machine; "\ - "-XX:CPUFeatures=native is the default; " \ - "-XX:CPUFeatures=ignore will disable the CPU features check; " \ - "-XX:CPUFeatures=generic is compatible but not as slow as 0") \ - \ - product(bool, ShowCPUFeatures, false, "Show features of this CPU " \ - "to be possibly used for the -XX:CPUFeatures=0xnumber option") \ - \ - product(bool, IgnoreCPUFeatures, false, RESTORE_SETTABLE | EXPERIMENTAL, \ - "Do not refuse to run after -XX:CRaCRestoreFrom finds out some " \ - "CPU features are missing") \ - \ product(int, X86ICacheSync, -1, DIAGNOSTIC, \ "Select the X86 ICache sync mechanism: -1 = auto-select; " \ "0 = none (dangerous); 1 = CLFLUSH loop; 2 = CLFLUSHOPT loop; "\ diff --git a/src/hotspot/cpu/x86/vm_version_x86.hpp b/src/hotspot/cpu/x86/vm_version_x86.hpp index be0c64ebe42..22afb5b085a 100644 --- a/src/hotspot/cpu/x86/vm_version_x86.hpp +++ b/src/hotspot/cpu/x86/vm_version_x86.hpp @@ -937,11 +937,11 @@ class VM_Version : public Abstract_VM_Version { // Initialization static void initialize(); static bool cpu_features_binary(VM_Features *data); - static bool ignore_cpu_features(bool is_checkpoint) { + static bool ignore_cpu_features() { // This gets triggered by -XX:CPUFeatures=ignore, not writing the features & arch // on checkpoint into the image at all, and skipping the check on restore. // IgnoreCPUFeatures is ignored on checkpoint - return _ignore_glibc_not_using || (!is_checkpoint && IgnoreCPUFeatures); + return _ignore_glibc_not_using; } static void restore_check(const char* str, const char* msg_prefix); diff --git a/src/hotspot/cpu/zero/vm_version_zero.cpp b/src/hotspot/cpu/zero/vm_version_zero.cpp index 3ce9227c193..1d6e62fd412 100644 --- a/src/hotspot/cpu/zero/vm_version_zero.cpp +++ b/src/hotspot/cpu/zero/vm_version_zero.cpp @@ -139,6 +139,8 @@ void VM_Version::initialize() { // the support unconditionally. _supports_cx8 = true; #endif + + check_cpufeatures_vmoptions(); } void VM_Version::initialize_cpu_information(void) { diff --git a/src/hotspot/cpu/zero/vm_version_zero.hpp b/src/hotspot/cpu/zero/vm_version_zero.hpp index 52e5248f179..fb4143a5df5 100644 --- a/src/hotspot/cpu/zero/vm_version_zero.hpp +++ b/src/hotspot/cpu/zero/vm_version_zero.hpp @@ -34,7 +34,7 @@ class VM_Version : public Abstract_VM_Version { static void initialize(); struct VM_Features: public Zero_Features {}; static bool cpu_features_binary(VM_Features *data) { return false; } - static bool ignore_cpu_features(bool is_checkpoint) { return true; } + static bool ignore_cpu_features() { return true; } constexpr static bool supports_stack_watermark_barrier() { return true; } diff --git a/src/hotspot/share/runtime/abstract_vm_version.cpp b/src/hotspot/share/runtime/abstract_vm_version.cpp index 5b9d36115f8..33d535da5ee 100644 --- a/src/hotspot/share/runtime/abstract_vm_version.cpp +++ b/src/hotspot/share/runtime/abstract_vm_version.cpp @@ -26,6 +26,7 @@ #include "compiler/compilerDefinitions.hpp" #include "jvm_io.h" #include "runtime/arguments.hpp" +#include "runtime/globals_extension.hpp" #include "runtime/vm_version.hpp" #include "utilities/globalDefinitions.hpp" @@ -402,3 +403,14 @@ const char* Abstract_VM_Version::cpu_description(void) { strncpy(tmp, _cpu_desc, CPU_DETAILED_DESC_BUF_SIZE); return tmp; } + +void Abstract_VM_Version::check_cpufeatures_vmoptions() { + if (!FLAG_IS_DEFAULT(CPUFeatures)) { + if (!strcmp(CPUFeatures, "native") || !strcmp(CPUFeatures, "generic") || !strcmp(CPUFeatures, "ignore")) { + vm_exit_during_initialization("This architecture does not support arch-specific -XX:CPUFeatures option"); + } + } + if (!FLAG_IS_DEFAULT(ShowCPUFeatures)) { + tty->print_cr("This architecture does not support any arch-specific strings."); + } +} diff --git a/src/hotspot/share/runtime/abstract_vm_version.hpp b/src/hotspot/share/runtime/abstract_vm_version.hpp index 3487eb6bb51..d1b242f89db 100644 --- a/src/hotspot/share/runtime/abstract_vm_version.hpp +++ b/src/hotspot/share/runtime/abstract_vm_version.hpp @@ -227,6 +227,9 @@ class Abstract_VM_Version: AllStatic { static char _cpu_name[CPU_TYPE_DESC_BUF_SIZE]; static char _cpu_desc[CPU_DETAILED_DESC_BUF_SIZE]; + // Default check for non-x86_64 architectures on VM options sanity + static void check_cpufeatures_vmoptions(); + public: static int number_of_threads(void); static int number_of_cores(void); diff --git a/src/hotspot/share/runtime/crac.cpp b/src/hotspot/share/runtime/crac.cpp index 0553fda52c4..40f3cacd502 100644 --- a/src/hotspot/share/runtime/crac.cpp +++ b/src/hotspot/share/runtime/crac.cpp @@ -317,7 +317,7 @@ int crac::checkpoint_restore(int *shmid) { // Setup CPU arch & features only during the first checkpoint; the feature set // cannot change after initial boot (and we don't support switching the engine). - if (_generation == 1 && !VM_Version::ignore_cpu_features(true)) { + if (_generation == 1 && !VM_Version::ignore_cpu_features()) { VM_Version::VM_Features data; if (VM_Version::cpu_features_binary(&data)) { switch (_engine->prepare_image_constraints_api()) { @@ -795,7 +795,7 @@ void crac::restore(crac_restore_data& restore_data) { // was printed out but continued even despite features not being satisfied. // Since the check itself is delegated to the C/R Engine we will simply // skip the check here. - if (!VM_Version::ignore_cpu_features(false)) { + if (!VM_Version::ignore_cpu_features() && !IgnoreCPUFeatures) { switch (engine.prepare_image_constraints_api()) { case CracEngine::ApiStatus::OK: { VM_Version::VM_Features data; diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp index f9f9ac48c79..22e0a1b1e6b 100644 --- a/src/hotspot/share/runtime/globals.hpp +++ b/src/hotspot/share/runtime/globals.hpp @@ -2029,6 +2029,22 @@ const int ObjectAlignmentInBytes = 8; product(size_t, CRaCMaxHeapSizeBeforeCheckpoint, 0, "Maximum size " \ "of heap before checkpoint. By default equals to -Xmx.") \ \ + product(ccstr, CPUFeatures, nullptr, "CPU feature set, " \ + "Limit set of CPU features to make the CRaC image compatible " \ + "for running on a machine with different CPU:" \ + "native: use all available features (default), " \ + "generic: compatible with most CPUs, " \ + "ignore: do not store CPU features at all, " \ + ": use -XX:+ShowCPUFeatures to find a suitable " \ + "architecture-specific string, e.g. 0xnumber,0xnumber on x86_64.")\ + \ + product(bool, ShowCPUFeatures, false, "Show features of this CPU " \ + "to be possibly used for the -XX:CPUFeatures=0xnumber option") \ + \ + product(bool, IgnoreCPUFeatures, false, RESTORE_SETTABLE | EXPERIMENTAL, \ + "Do not refuse to run after -XX:CRaCRestoreFrom finds out some " \ + "CPU features are missing") \ + \ product(int, LockingMode, LM_LIGHTWEIGHT, \ "(Deprecated) Select locking mode: " \ "0: (Deprecated) monitors only (LM_MONITOR), " \ diff --git a/src/java.base/share/man/java.md b/src/java.base/share/man/java.md index d7e178f5344..09212afad51 100644 --- a/src/java.base/share/man/java.md +++ b/src/java.base/share/man/java.md @@ -1881,11 +1881,24 @@ performed by the Java HotSpot VM. compilation while values greater than 1.0 delay compilation. Setting `CompileThresholdScaling` to 0 is equivalent to disabling compilation. -`-XX:CPUFeatures=`*0xnumber,0xnumber* -: CPU feature set, use `-XX:CPUFeatures=`*0xnumber,0xnumber* with - `-XX:CRaCCheckpointTo` when you get an error during `-XX:CRaCRestoreFrom` - on a different machine. `-XX:CPUFeatures=native` is the default. - `-XX:CPUFeatures=generic` is compatible with any CPU. +`-XX:CPUFeatures=`*features* +: Limit set of CPU features to make the CRaC image compatible for running + on a machine with different CPU: + + `native` + : Use all available CPU features (default). + + `generic` + : This option is compatible with most CPUs and faster than disabling + all optional features. + + `ignore` + : Do not store CPU features at all. + + *arch-specific* + : Architecture specific string, e.g. *0xnumber,0xnumber* on x86_64. + Use `-XX:+ShowCPUFeatures` to find a suitable architecture-specific + string. `-XX:+DoEscapeAnalysis` : Enables the use of escape analysis. This option is enabled by default. To From bea9f6deea6fe1d57fcec22fd596cb224265b309 Mon Sep 17 00:00:00 2001 From: Radim Vansa Date: Tue, 23 Dec 2025 16:39:35 +0100 Subject: [PATCH 2/6] Fix wording --- src/hotspot/share/runtime/abstract_vm_version.cpp | 4 ++-- src/java.base/share/man/java.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/hotspot/share/runtime/abstract_vm_version.cpp b/src/hotspot/share/runtime/abstract_vm_version.cpp index 33d535da5ee..2194a1aafef 100644 --- a/src/hotspot/share/runtime/abstract_vm_version.cpp +++ b/src/hotspot/share/runtime/abstract_vm_version.cpp @@ -407,10 +407,10 @@ const char* Abstract_VM_Version::cpu_description(void) { void Abstract_VM_Version::check_cpufeatures_vmoptions() { if (!FLAG_IS_DEFAULT(CPUFeatures)) { if (!strcmp(CPUFeatures, "native") || !strcmp(CPUFeatures, "generic") || !strcmp(CPUFeatures, "ignore")) { - vm_exit_during_initialization("This architecture does not support arch-specific -XX:CPUFeatures option"); + vm_exit_during_initialization("This architecture does not support any arch-specific -XX:CPUFeatures options"); } } if (!FLAG_IS_DEFAULT(ShowCPUFeatures)) { - tty->print_cr("This architecture does not support any arch-specific strings."); + tty->print_cr("Do not use -XX:ShowCPUFeatures: this architecture does not support any arch-specific strings."); } } diff --git a/src/java.base/share/man/java.md b/src/java.base/share/man/java.md index 09212afad51..59688b4e4a6 100644 --- a/src/java.base/share/man/java.md +++ b/src/java.base/share/man/java.md @@ -1882,8 +1882,8 @@ performed by the Java HotSpot VM. `CompileThresholdScaling` to 0 is equivalent to disabling compilation. `-XX:CPUFeatures=`*features* -: Limit set of CPU features to make the CRaC image compatible for running - on a machine with different CPU: +: Limit the set of CPU features to make the CRaC image compatible for running + on a machine with a different CPU: `native` : Use all available CPU features (default). From 2a0aecd134c9dce443b138c3d9e523436746ed1e Mon Sep 17 00:00:00 2001 From: Radim Vansa Date: Tue, 23 Dec 2025 16:41:54 +0100 Subject: [PATCH 3/6] Replace shell-based test with Java test & add other checks --- .../jdk/crac/CPUFeatures/SimpleCPUFeatures.sh | 49 -------- .../CPUFeatures/SimpleCPUFeaturesTest.java | 119 ++++++++++++++++++ 2 files changed, 119 insertions(+), 49 deletions(-) delete mode 100755 test/jdk/jdk/crac/CPUFeatures/SimpleCPUFeatures.sh create mode 100644 test/jdk/jdk/crac/CPUFeatures/SimpleCPUFeaturesTest.java diff --git a/test/jdk/jdk/crac/CPUFeatures/SimpleCPUFeatures.sh b/test/jdk/jdk/crac/CPUFeatures/SimpleCPUFeatures.sh deleted file mode 100755 index daffa173eb5..00000000000 --- a/test/jdk/jdk/crac/CPUFeatures/SimpleCPUFeatures.sh +++ /dev/null @@ -1,49 +0,0 @@ -#! /bin/bash -# Copyright (c) 2023, 2025, Azul Systems, Inc. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. - -# @test -# @requires os.family == "linux" -# @requires os.arch=="amd64" | os.arch=="x86_64" -# @run shell SimpleCPUFeatures.sh -# @summary On old glibc (without INCLUDE_CPU_FEATURE_ACTIVE) one could get an internal error. -# Error occurred during initialization of VM -# internal error: GLIBC_TUNABLES=:glibc.cpu.hwcaps=,-AVX,-FMA,-AVX2,-BMI1,-BMI2,-ERMS,-LZCNT,-SSSE3,-POPCNT,-SSE4_1,-SSE4_2,-AVX512F,-AVX512CD,-AVX512BW,-AVX512DQ,-AVX512VL,-IBT,-MOVBE,-SHSTK,-XSAVE,-OSXSAVE,-HTT failed and HOTSPOT_GLIBC_TUNABLES_REEXEC is set - -set -ex -export JAVA_HOME=$TESTJAVA - -unset GLIBC_TUNABLES -$JAVA_HOME/bin/java -XX:CPUFeatures=generic -XX:+ShowCPUFeatures -version 2>&1 | tee /proc/self/fd/2 | grep -q 'openjdk version' - -# The test from summary: -export GLIBC_TUNABLES=glibc.pthread.rseq=0 -$JAVA_HOME/bin/java -XX:CPUFeatures=generic -XX:+ShowCPUFeatures -version 2>&1 | tee /proc/self/fd/2 | grep -q 'openjdk version' - -for GLIBC_TUNABLES in \ - glibc.cpu.hwcaps=-AVX \ - glibc.pthread.rseq=0:glibc.cpu.hwcaps=-AVX \ - glibc.cpu.hwcaps=-AVX:glibc.pthread.rseq=0 \ - ; do - $JAVA_HOME/bin/java -XX:CPUFeatures=generic -XX:+ShowCPUFeatures -version 2>&1 | tee /proc/self/fd/2 | grep -q 'openjdk version' -done - -exit 0 diff --git a/test/jdk/jdk/crac/CPUFeatures/SimpleCPUFeaturesTest.java b/test/jdk/jdk/crac/CPUFeatures/SimpleCPUFeaturesTest.java new file mode 100644 index 00000000000..264adc4e347 --- /dev/null +++ b/test/jdk/jdk/crac/CPUFeatures/SimpleCPUFeaturesTest.java @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2023,2025, Azul Systems, Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Azul Systems, 385 Moffett Park Drive, Suite 115, Sunnyvale + * CA 94089 USA or visit www.azul.com if you need additional information or + * have any questions. + */ + +import jdk.test.lib.crac.*; +import jdk.test.lib.process.OutputAnalyzer; + +/* + * @test id=NAMED + * @library /test/lib + * @build SimpleCPUFeaturesTest + * @run driver jdk.test.lib.crac.CracTest native + * @run driver jdk.test.lib.crac.CracTest generic + * @run driver jdk.test.lib.crac.CracTest ignore + */ +/* + * @test id=TUNABLES + * @requires os.family == "linux" + * @requires os.arch=="amd64" | os.arch=="x86_64" + * @library /test/lib + * @build SimpleCPUFeaturesTest + * @summary On old glibc (without INCLUDE_CPU_FEATURE_ACTIVE) one could get an internal error. + * @comment Error occurred during initialization of VM + * @comment internal error: GLIBC_TUNABLES=:glibc.cpu.hwcaps=,-AVX,-FMA,-AVX2,-BMI1,-BMI2,-ERMS,-LZCNT,-SSSE3,-POPCNT,-SSE4_1,-SSE4_2,-AVX512F,-AVX512CD,-AVX512BW,-AVX512DQ,-AVX512VL,-IBT,-MOVBE,-SHSTK,-XSAVE,-OSXSAVE,-HTT failed and HOTSPOT_GLIBC_TUNABLES_REEXEC is set + * @run driver jdk.test.lib.crac.CracTest generic glibc.pthread.rseq=0 + * @run driver jdk.test.lib.crac.CracTest generic glibc.cpu.hwcaps=-AVX + * @run driver jdk.test.lib.crac.CracTest generic glibc.pthread.rseq=0:glibc.cpu.hwcaps=-AVX + * @run driver jdk.test.lib.crac.CracTest generic glibc.cpu.hwcaps=-AVX:glibc.pthread.rseq=0 + */ +/* + * @test id=X86 + * @requires os.arch=="amd64" | os.arch=="x86_64" + * @library /test/lib + * @build SimpleCPUFeaturesTest + * @comment FLUSH and SSE2 must be present + * @run driver jdk.test.lib.crac.CracTest 0x20000000080,0x0 + * @run driver jdk.test.lib.crac.CracTest foobar -- INVALID_FORMAT + * @run driver jdk.test.lib.crac.CracTest 0xfffff,0x0 -- MISSING_FEATURES + * @run driver jdk.test.lib.crac.CracTest 0x20000000080,0xfff -- MISSING_FEATURES + */ +/* + * @test id=AARCH64 + * @requires os.arch=="aarch64" + * @library /test/lib + * @build SimpleCPUFeaturesTest + * @run driver jdk.test.lib.crac.CracTest 0x0,0x0 -- UNSUPPORTED_ARCH + * @run driver jdk.test.lib.crac.CracTest foobar -- UNSUPPORTED_ARCH + */ + +public class SimpleCPUFeaturesTest implements CracTest { + private static final String SUCCESS = "SUCCESS"; + + // jtreg does not respect quoted strings + private enum ErrorMsg { + INVALID_FORMAT("must be of the form: 0xNUM,0xNUM"), + MISSING_FEATURES("missing features of this CPU are"), + UNSUPPORTED_ARCH("This architecture does not support any arch-specific") + ; + final String msg; + + ErrorMsg(String msg) { + this.msg = msg; + } + } + + @CracTestArg(0) + String cpuFeatures; + + @CracTestArg(value = 1, optional = true) + String glibcTunables; + + @CracTestArg(value = 2, optional = true) + ErrorMsg error; + + @Override + public void test() throws Exception { + CracBuilder builder = new CracBuilder() + .captureOutput(true) + .vmOption("-XX:CPUFeatures=" + cpuFeatures) + .vmOption("-XX:+ShowCPUFeatures"); + if (glibcTunables != null && !"--".equals(glibcTunables)) { + builder.env("GLIBC_TUNABLES", glibcTunables); + } + CracProcess process = builder.startPlain(); + process.waitFor(); + OutputAnalyzer oa = process.outputAnalyzer(); + if (error == null) { + oa.shouldHaveExitValue(0) + .stdoutShouldContain(SUCCESS); + } else { + oa.shouldNotHaveExitValue(0) + .stdoutShouldContain(error.msg); + } + } + + @Override + public void exec() { + System.out.println(SUCCESS); + } +} From a58eee1ee813df78b0d5ef7cb50393a71dd371a6 Mon Sep 17 00:00:00 2001 From: Radim Vansa Date: Tue, 23 Dec 2025 17:51:18 +0100 Subject: [PATCH 4/6] Fix CPUFeatures check --- src/hotspot/share/runtime/abstract_vm_version.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/share/runtime/abstract_vm_version.cpp b/src/hotspot/share/runtime/abstract_vm_version.cpp index 2194a1aafef..26bf5001481 100644 --- a/src/hotspot/share/runtime/abstract_vm_version.cpp +++ b/src/hotspot/share/runtime/abstract_vm_version.cpp @@ -406,7 +406,7 @@ const char* Abstract_VM_Version::cpu_description(void) { void Abstract_VM_Version::check_cpufeatures_vmoptions() { if (!FLAG_IS_DEFAULT(CPUFeatures)) { - if (!strcmp(CPUFeatures, "native") || !strcmp(CPUFeatures, "generic") || !strcmp(CPUFeatures, "ignore")) { + if (strcmp(CPUFeatures, "native") && strcmp(CPUFeatures, "generic") && strcmp(CPUFeatures, "ignore")) { vm_exit_during_initialization("This architecture does not support any arch-specific -XX:CPUFeatures options"); } } From e48496391f5a03ddcc572251b7d7af43cf53eaef Mon Sep 17 00:00:00 2001 From: Radim Vansa Date: Tue, 23 Dec 2025 18:01:32 +0100 Subject: [PATCH 5/6] Refine non-Linux behaviour --- .../crac/CPUFeatures/SimpleCPUFeaturesTest.java | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/test/jdk/jdk/crac/CPUFeatures/SimpleCPUFeaturesTest.java b/test/jdk/jdk/crac/CPUFeatures/SimpleCPUFeaturesTest.java index 264adc4e347..1b9655e39af 100644 --- a/test/jdk/jdk/crac/CPUFeatures/SimpleCPUFeaturesTest.java +++ b/test/jdk/jdk/crac/CPUFeatures/SimpleCPUFeaturesTest.java @@ -47,7 +47,8 @@ * @run driver jdk.test.lib.crac.CracTest generic glibc.cpu.hwcaps=-AVX:glibc.pthread.rseq=0 */ /* - * @test id=X86 + * @test id=X86-LINUX + * @requires os.family == "linux" * @requires os.arch=="amd64" | os.arch=="x86_64" * @library /test/lib * @build SimpleCPUFeaturesTest @@ -58,14 +59,22 @@ * @run driver jdk.test.lib.crac.CracTest 0x20000000080,0xfff -- MISSING_FEATURES */ /* - * @test id=AARCH64 + * @test id=AARCH64-LINUX + * @requires os.family == "linux" * @requires os.arch=="aarch64" * @library /test/lib * @build SimpleCPUFeaturesTest * @run driver jdk.test.lib.crac.CracTest 0x0,0x0 -- UNSUPPORTED_ARCH * @run driver jdk.test.lib.crac.CracTest foobar -- UNSUPPORTED_ARCH */ - +/* + * @test id=NON-LINUX + * @comment non-Linux behaves as if CPUFeatures=ignored was set + * @requires os.family != "linux" + * @library /test/lib + * @build SimpleCPUFeaturesTest + * @run driver jdk.test.lib.crac.CracTest foobar + */ public class SimpleCPUFeaturesTest implements CracTest { private static final String SUCCESS = "SUCCESS"; From 0bab0747c3f75f26c9ce0a9b21dcff70f29f5ba5 Mon Sep 17 00:00:00 2001 From: Radim Vansa Date: Mon, 5 Jan 2026 16:25:12 +0100 Subject: [PATCH 6/6] Fail on x86 non-Linux with not recognized CPUFeatures pattern --- src/hotspot/cpu/x86/vm_version_x86.cpp | 13 ++++++--- .../CPUFeatures/SimpleCPUFeaturesTest.java | 27 ++++++++++--------- 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/src/hotspot/cpu/x86/vm_version_x86.cpp b/src/hotspot/cpu/x86/vm_version_x86.cpp index 4409ce1cdb2..264a6e0cc05 100644 --- a/src/hotspot/cpu/x86/vm_version_x86.cpp +++ b/src/hotspot/cpu/x86/vm_version_x86.cpp @@ -891,8 +891,7 @@ class VM_Version_StubGenerator: public StubCodeGenerator { VM_Version::VM_Features VM_Version::CPUFeatures_parse(const char *str) { #ifndef LINUX _ignore_glibc_not_using = true; - return _features; -#else +#endif // !LINUX if (str == nullptr || strcmp(str, "native") == 0) { return _features; } @@ -901,6 +900,9 @@ VM_Version::VM_Features VM_Version::CPUFeatures_parse(const char *str) { return _features; } if (strcmp(str, "generic") == 0) { +#ifndef LINUX + return _features; +#else // 32-bit x86 cannot rely on anything. VM_Version::VM_Features retval; #ifdef AMD64 @@ -917,7 +919,12 @@ VM_Version::VM_Features VM_Version::CPUFeatures_parse(const char *str) { // CPU_LAHFSAHF is disabled in 'gcc -Q --help=target' and "Early Intel Pentium 4 CPUs with Intel 64 support ... lacked the LAHF and SAHF instructions" #endif return retval; +#endif // !LINUX } +#ifndef LINUX + vm_exit_during_initialization("This OS does not support any arch-specific -XX:CPUFeatures options"); + return {}; +#else // LINUX int count = VM_Version::VM_Features::features_bitmap_element_count(); VM_Version::VM_Features retval; const char *str_orig = str; @@ -946,7 +953,7 @@ VM_Version::VM_Features VM_Version::CPUFeatures_parse(const char *str) { } vm_exit_during_initialization(err_msg("VM option 'CPUFeatures=%s' must be of the form: %s", str_orig, buf + 1)); return {}; -#endif // LINUX +#endif } bool VM_Version::_ignore_glibc_not_using = false; diff --git a/test/jdk/jdk/crac/CPUFeatures/SimpleCPUFeaturesTest.java b/test/jdk/jdk/crac/CPUFeatures/SimpleCPUFeaturesTest.java index 1b9655e39af..0f5dd069479 100644 --- a/test/jdk/jdk/crac/CPUFeatures/SimpleCPUFeaturesTest.java +++ b/test/jdk/jdk/crac/CPUFeatures/SimpleCPUFeaturesTest.java @@ -54,26 +54,26 @@ * @build SimpleCPUFeaturesTest * @comment FLUSH and SSE2 must be present * @run driver jdk.test.lib.crac.CracTest 0x20000000080,0x0 - * @run driver jdk.test.lib.crac.CracTest foobar -- INVALID_FORMAT - * @run driver jdk.test.lib.crac.CracTest 0xfffff,0x0 -- MISSING_FEATURES + * @run driver jdk.test.lib.crac.CracTest foobar -- INVALID_FORMAT + * @run driver jdk.test.lib.crac.CracTest 0xfffff,0x0 -- MISSING_FEATURES * @run driver jdk.test.lib.crac.CracTest 0x20000000080,0xfff -- MISSING_FEATURES */ /* - * @test id=AARCH64-LINUX - * @requires os.family == "linux" - * @requires os.arch=="aarch64" + * @test id=x86-NON-LINUX + * @requires os.arch=="amd64" | os.arch=="x86_64" + * @requires os.family != "linux" * @library /test/lib * @build SimpleCPUFeaturesTest - * @run driver jdk.test.lib.crac.CracTest 0x0,0x0 -- UNSUPPORTED_ARCH - * @run driver jdk.test.lib.crac.CracTest foobar -- UNSUPPORTED_ARCH + * @run driver jdk.test.lib.crac.CracTest foobar -- OS_DOES_NOT_SUPPORT + * @run driver jdk.test.lib.crac.CracTest 0x20000000080,0x0 -- OS_DOES_NOT_SUPPORT */ /* - * @test id=NON-LINUX - * @comment non-Linux behaves as if CPUFeatures=ignored was set - * @requires os.family != "linux" - * @library /test/lib + * @test id=AARCH64 + * @requires os.arch=="aarch64" + * @library /test/lib * @build SimpleCPUFeaturesTest - * @run driver jdk.test.lib.crac.CracTest foobar + * @run driver jdk.test.lib.crac.CracTest 0x0,0x0 -- ARCH_DOES_NOT_SUPPORT + * @run driver jdk.test.lib.crac.CracTest foobar -- ARCH_DOES_NOT_SUPPORT */ public class SimpleCPUFeaturesTest implements CracTest { private static final String SUCCESS = "SUCCESS"; @@ -82,7 +82,8 @@ public class SimpleCPUFeaturesTest implements CracTest { private enum ErrorMsg { INVALID_FORMAT("must be of the form: 0xNUM,0xNUM"), MISSING_FEATURES("missing features of this CPU are"), - UNSUPPORTED_ARCH("This architecture does not support any arch-specific") + ARCH_DOES_NOT_SUPPORT("This architecture does not support any arch-specific"), + OS_DOES_NOT_SUPPORT("This OS does not support"), ; final String msg;