From b14c0316866d169f12263df22b3dc2514611b394 Mon Sep 17 00:00:00 2001 From: Jan Kratochvil Date: Thu, 23 Jul 2026 04:28:52 +0200 Subject: [PATCH 01/41] 8385359: [CRaC] aarch64: c7g.medium <-> c8g.medium FAIL: vector length --- .../cpu/aarch64/vm_version_aarch64.cpp | 30 +++++++ .../cpu/aarch64/vm_version_aarch64.hpp | 5 +- src/hotspot/cpu/x86/vm_version_x86.hpp | 4 + src/hotspot/cpu/zero/vm_version_zero.hpp | 4 + .../vm_version_linux_aarch64.cpp | 30 ++++++- src/hotspot/share/runtime/crac_engine.cpp | 85 +++++++++++++++++++ src/hotspot/share/runtime/crac_engine.hpp | 3 + .../jdk/crac/CPUFeatures/CPUFeaturesAWS.sh | 9 +- 8 files changed, 164 insertions(+), 6 deletions(-) diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp index f07315a8637..791c629188c 100644 --- a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp @@ -63,6 +63,7 @@ GLIBC_UNSUPPORTED(A53MAC ); \ GLIBC_UNSUPPORTED(ECV ); \ GLIBC_UNSUPPORTED(WFXT ); \ + GLIBC_UNSUPPORTED(SVE256 ); \ GLIBC_UNSUPPORTED(NOTPACA ); \ /**/ #include "runtime/abstract_vm_version.inline.hpp" @@ -930,3 +931,32 @@ void VM_Version::CPUFeatures_apply_arch(VM_Features &parsed, VM_Features &missin missing.clear_feature(CPU_PACA); missing.clear_feature(CPU_NOTPACA); } + +bool VM_Version::restore_pre(VM_Features image_features, const char *image_location) { + bool boolvalue = image_features.supports_feature(CPU_SVE256); + if (boolvalue == _cpu_features.supports_feature(CPU_SVE256)) { + return true; + } + if (boolvalue && !_cpu_features.supports_feature(CPU_SVE256)) { + ResourceMark rm; + stringStream ss; + VM_Features sve256; + sve256.set_feature(CPU_SVE256); + VM_Features use = image_features & _cpu_features; + log_error(crac)("Image %s has -XX:CPUFeatures=%s with CPU_SVE256=%s, this CPU has CPUFeatures=%s not supporting CPU_SVE256, use -XX:CPUFeatures=%s during snapshot", + image_location, image_features.print_numbers(), sve256.print_numbers(), _cpu_features.print_numbers(), use.print_numbers()); + return false; + } + errno = 0; + int got = set_and_get_current_sve_vector_length(16); + if (got != 16) { + ResourceMark rm; + stringStream ss; + VM_Features sve256; + sve256.set_feature(CPU_SVE256); + log_error(crac)("Image %s has -XX:CPUFeatures=%s with CPU_SVE256=%s unset, this CPU has CPUFeatures=%s but PR_SVE_SET_VL reports %d: %m", + image_location, image_features.print_numbers(), sve256.print_numbers(), _cpu_features.print_numbers(), got); + return false; + } + return true; +} diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp index c44c9124523..12c501855ee 100644 --- a/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp @@ -59,6 +59,7 @@ class VM_Feature_Flag { decl(ECV, ecv, 21) \ decl(WFXT, wfxt, 22) \ /* These features are added for CRaC. */ \ + decl(SVE256, sve256, 62) \ decl(NOTPACA, notpaca, 63) \ /**/ @@ -68,7 +69,7 @@ class VM_Feature_Flag { #undef DECLARE_CPU_FEATURE_FLAG MAX_CPU_FEATURES, LAST_CPU_FEATURE = CPU_WFXT, - FIRST_GLIBC_FEATURE = CPU_NOTPACA + FIRST_GLIBC_FEATURE = CPU_SVE256 }; }; @@ -142,6 +143,8 @@ class VM_Version : public Abstract_VM_Version, public VM_Feature_Flag { static void insert_features_names(VM_Version::VM_Features features, outputStream& os); // The returned string needs a ResourceMark. static const char *restore_failed_check(const VM_Features *image_features, const VM_Features *current_features); + static bool restore_pre(VM_Features image_features, const char *image_location); + static constexpr bool restore_pre_needed = true; static void print_platform_virtualization_info(outputStream*); diff --git a/src/hotspot/cpu/x86/vm_version_x86.hpp b/src/hotspot/cpu/x86/vm_version_x86.hpp index 64e3011c764..cf571bbfe18 100644 --- a/src/hotspot/cpu/x86/vm_version_x86.hpp +++ b/src/hotspot/cpu/x86/vm_version_x86.hpp @@ -732,6 +732,10 @@ class VM_Version : public Abstract_VM_Version, protected VM_Feature_Flag { static const char *restore_failed_check(const VM_Features *image_features, const VM_Features *current_features) { return nullptr; } + static bool restore_pre(VM_Features image_features, const char *image_location) { + return false; + } + static constexpr bool restore_pre_needed = false; static bool os_supports_avx_vectors(); static bool os_supports_apx_egprs(); diff --git a/src/hotspot/cpu/zero/vm_version_zero.hpp b/src/hotspot/cpu/zero/vm_version_zero.hpp index 5ec01e360a1..131eeda9599 100644 --- a/src/hotspot/cpu/zero/vm_version_zero.hpp +++ b/src/hotspot/cpu/zero/vm_version_zero.hpp @@ -38,6 +38,10 @@ class VM_Version : public Abstract_VM_Version { static const char *restore_failed_check(const VM_Features *image_features, const VM_Features *current_features) { return nullptr; } + static bool restore_pre(VM_Features image_features, const char *image_location) { + return false; + } + static constexpr bool restore_pre_needed = false; constexpr static bool supports_stack_watermark_barrier() { return true; } diff --git a/src/hotspot/os_cpu/linux_aarch64/vm_version_linux_aarch64.cpp b/src/hotspot/os_cpu/linux_aarch64/vm_version_linux_aarch64.cpp index 3f935146084..7def6474a0d 100644 --- a/src/hotspot/os_cpu/linux_aarch64/vm_version_linux_aarch64.cpp +++ b/src/hotspot/os_cpu/linux_aarch64/vm_version_linux_aarch64.cpp @@ -24,6 +24,7 @@ */ #include "memory/resourceArea.hpp" +#include "runtime/globals_extension.hpp" #include "runtime/java.hpp" #include "runtime/os.hpp" #include "runtime/os.inline.hpp" @@ -120,9 +121,12 @@ int VM_Version::get_current_sve_vector_length() { return prctl(PR_SVE_GET_VL); } +// Limit what set_and_get_current_sve_vector_length is willing to set. +static int maximum_sve_vector_length = INT_MAX; + int VM_Version::set_and_get_current_sve_vector_length(int length) { assert(VM_Version::supports_sve(), "should not call this"); - int new_length = prctl(PR_SVE_SET_VL, length); + int new_length = prctl(PR_SVE_SET_VL, MIN2(length, maximum_sve_vector_length)); return new_length; } @@ -163,6 +167,10 @@ void VM_Version::get_os_cpu_info() { update_feature(auxv2, CPU_WFXT, HWCAP2_WFXT ); update_feature(~auxv, CPU_NOTPACA, HWCAP_PACA ); + if (supports_sve() && get_current_sve_vector_length() == 32) { + set_feature(CPU_SVE256); + } + uint64_t ctr_el0; uint64_t dczid_el0; __asm__ ( @@ -226,6 +234,26 @@ void VM_Version::check_os_cpu_info() { // GLIBC_TUNABLES=glibc.cpu.hwcaps is unsupported on aarch64 vm_exit_during_initialization(err_msg("LSE (%s) cannot be disabled via -XX:CPUFeatures on aarch64.", lse.print_numbers())); } + if (FLAG_IS_DEFAULT(CPUFeatures)) { + assert(_cpu_features.supports_feature(CPU_SVE256) == _features.supports_feature(CPU_SVE256), "CPU_SVE256 is not changed"); + } else if (!_cpu_features.supports_feature(CPU_SVE256) && _features.supports_feature(CPU_SVE256)) { + stringStream ss; + VM_Features sve256; + sve256.set_feature(VM_Feature_Flag::CPU_SVE256); + ss.print("Specified -XX:CPUFeatures=%s have CPU_SVE256=%s set but this CPU does not support it", _features.print_numbers(), sve256.print_numbers()); + vm_exit_during_initialization(ss.base()); + } else if (_cpu_features.supports_feature(CPU_SVE256) && !_features.supports_feature(CPU_SVE256)) { + maximum_sve_vector_length = 16; + int got = set_and_get_current_sve_vector_length(maximum_sve_vector_length); + if (got != maximum_sve_vector_length) { + stringStream ss; + VM_Features sve256; + sve256.set_feature(VM_Feature_Flag::CPU_SVE256); + ss.print("Specified -XX:CPUFeatures=%s have unset CPU_SVE256=%s, this CPU has CPUFeatures=%s but it cannot be disabled as PR_SVE_SET_VL reports %d: %m", + _features.print_numbers(), sve256.print_numbers(), _cpu_features.print_numbers(), got); + vm_exit_during_initialization(ss.base()); + } + } } static bool read_fully(const char *fname, char *buf, size_t buflen) { diff --git a/src/hotspot/share/runtime/crac_engine.cpp b/src/hotspot/share/runtime/crac_engine.cpp index 4207e91eea9..28022cf7e42 100644 --- a/src/hotspot/share/runtime/crac_engine.cpp +++ b/src/hotspot/share/runtime/crac_engine.cpp @@ -378,11 +378,96 @@ int CracEngine::checkpoint() const { return _api->checkpoint(_conf); } +static inline unsigned char from_hex(char c, bool* err) { + if (c >= '0' && c <= '9') { + return c - '0'; + } else if (c >= 'a' && c <= 'f') { + return c - 'a' + 10; + } else { + *err = true; + return 0; + } +} + +static constexpr char cpufeatures_prefix[] = "bitmap:cpu.features"; + +// FIXME: Replace "tags" parsing by a new constraint reader method call. +bool CracEngine::restore_pre_core(FILE *f) const { + static constexpr const size_t _MAX_VALUE_SIZE = 256; + char line[sizeof(cpufeatures_prefix) + 1 + _MAX_VALUE_SIZE + 2]; + while (fgets(line, (int) sizeof(line), f)) { + char* eq = strchr((char *) line, '='); + char* nl = strchr((char *) (eq + 1), '\n'); + if (eq == nullptr || nl == nullptr) { + log_error(crac)("Invalid format of tags file of image %s: %s", _image_location, line); + return false; + } + *eq = 0; + *nl = 0; + if (eq < nl && !strncmp(line, cpufeatures_prefix, strlen(cpufeatures_prefix)) && eq - line == strlen(cpufeatures_prefix)) { + size_t length = (size_t)(nl - eq - 1)/2; + if (2 * length != (size_t)(nl - eq - 1)) { + log_error(crac)("Invalid format of tags file (bad bitmap) of image %s: %s", _image_location, line); + return false; + } + union { + VM_Version::VM_Features features; + uint8_t bytes[sizeof(VM_Version::VM_Features)] = { 0 }; + } u; + bool err = false; + for (size_t i = 0; i < length; ++i) { + u.bytes[i] = (from_hex(eq[1 + 2 * i], &err) << 4) + from_hex(eq[2 + 2 * i], &err); + } + if (err) { + log_error(crac)("Invalid format of tags file (bad character in bitmap): %s", line); + return false; + } + return VM_Version::restore_pre(u.features, _image_location); + } + } + log_error(crac)("%s not found in image %s", cpufeatures_prefix, _image_location); + return false; +} + +static FILE* open_tags(const char* image_location, const char* mode) { + char fname[PATH_MAX]; + if (os::snprintf(fname, sizeof(fname), "%s/tags", image_location) >= (int) sizeof(fname) - 1) { + log_error(crac)("filename too long: %s/tags", image_location); + return nullptr; + } + FILE* f = fopen(fname, mode); + if (f == nullptr) { + log_error(crac)("cannot open %s in mode %s: %s", fname, mode, os::strerror(errno)); + return nullptr; + } + return f; +} + +bool CracEngine::restore_pre() const { + if (!VM_Version::restore_pre_needed) { + return true; + } + FILE* f = open_tags(_image_location, "r"); + if (f == nullptr) { + log_error(crac)("Cannot open tags for image %s", _image_location); + return false; + } + bool retval = restore_pre_core(f); + if (fclose(f)) { + log_error(crac)("cannot close %s/tags: %s", _image_location, os::strerror(errno)); + return false; + } + return retval; +} + int CracEngine::restore() const { precond(is_initialized()); if (!check_engine(_name, _image_location)) { return -1; } + if (!restore_pre()) { + return -1; + } return _api->restore(_conf); } diff --git a/src/hotspot/share/runtime/crac_engine.hpp b/src/hotspot/share/runtime/crac_engine.hpp index 5866cd8255c..c4fa07be0d9 100644 --- a/src/hotspot/share/runtime/crac_engine.hpp +++ b/src/hotspot/share/runtime/crac_engine.hpp @@ -92,6 +92,9 @@ class CracEngine : public CHeapObj { crlib_image_score_t *_image_score_api = nullptr; crlib_conf_option_t *_options = nullptr; + + bool restore_pre() const; + bool restore_pre_core(FILE *f) const; }; #endif // SHARE_RUNTIME_CRAC_ENGINE_HPP diff --git a/test/jdk/jdk/crac/CPUFeatures/CPUFeaturesAWS.sh b/test/jdk/jdk/crac/CPUFeatures/CPUFeaturesAWS.sh index 720ff3950b6..4d6aeebf74d 100755 --- a/test/jdk/jdk/crac/CPUFeatures/CPUFeaturesAWS.sh +++ b/test/jdk/jdk/crac/CPUFeatures/CPUFeaturesAWS.sh @@ -345,11 +345,12 @@ checkpoint_restore "$LINENO" a1.medium t4g.micro checkpoint_restore "$LINENO" t4g.micro a1.medium "1:Restore failed due to incompatible or missing CPU features, try using -XX:CPUFeatures=0x80000000000000ff on checkpoint." checkpoint_restore "$LINENO" t4g.micro a1.medium "-1:LSE (0x100) cannot be disabled via -XX:CPUFeatures on aarch64." "-XX:CPUFeatures=0x80000000000000ff" "" -# JDK-8385359: checkpoint_restore "$LINENO" c7g.medium c7g.medium -# JDK-8385359: checkpoint_restore "$LINENO" c8g.medium c8g.medium -# JDK-8385359: checkpoint_restore "$LINENO" c7g.medium c8g.medium +checkpoint_restore "$LINENO" c7g.medium c7g.medium +checkpoint_restore "$LINENO" c8g.medium c8g.medium +checkpoint_restore "$LINENO" c7g.medium c8g.medium "1:Image cr has -XX:CPUFeatures=0x4000000000017fff with CPU_SVE256=0x4000000000000000, this CPU has CPUFeatures=0x77fff not supporting CPU_SVE256, use -XX:CPUFeatures=0x17fff during snapshot" +checkpoint_restore "$LINENO" c7g.medium c8g.medium "" "-XX:CPUFeatures=0x17fff" "" checkpoint_restore "$LINENO" c8g.medium c7g.medium "1:Restore failed due to incompatible or missing CPU features, try using -XX:CPUFeatures=0x17fff on checkpoint." -# JDK-8385359: checkpoint_restore "$LINENO" c8g.medium c7g.medium "" "-XX:CPUFeatures=0x17fff" "" +checkpoint_restore "$LINENO" c8g.medium c7g.medium "" "-XX:CPUFeatures=0x17fff" "" checkpoint_restore "$LINENO" t4g.micro c8g.medium "1:Restore failed due to incompatible aarch64 CPU feature PACA (0x10000); these CPUs each require a separate image." checkpoint_restore "$LINENO" c8g.medium t4g.micro "1:Restore failed due to incompatible aarch64 CPU feature PACA (0x10000); these CPUs each require a separate image." From 8c528947c5db69cafbaf3bd4671e38bdef0e1b72 Mon Sep 17 00:00:00 2001 From: Jan Kratochvil Date: Thu, 23 Jul 2026 10:44:33 +0200 Subject: [PATCH 02/41] rename: boolvalue -> image_supports_sve256 --- src/hotspot/cpu/aarch64/vm_version_aarch64.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp index 791c629188c..1b425e60d81 100644 --- a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp @@ -933,11 +933,11 @@ void VM_Version::CPUFeatures_apply_arch(VM_Features &parsed, VM_Features &missin } bool VM_Version::restore_pre(VM_Features image_features, const char *image_location) { - bool boolvalue = image_features.supports_feature(CPU_SVE256); - if (boolvalue == _cpu_features.supports_feature(CPU_SVE256)) { + bool image_supports_sve256 = image_features.supports_feature(CPU_SVE256); + if (image_supports_sve256 == _cpu_features.supports_feature(CPU_SVE256)) { return true; } - if (boolvalue && !_cpu_features.supports_feature(CPU_SVE256)) { + if (image_supports_sve256 && !_cpu_features.supports_feature(CPU_SVE256)) { ResourceMark rm; stringStream ss; VM_Features sve256; From d985dadcf069022cc72d680f3bc0a76f99af6bb3 Mon Sep 17 00:00:00 2001 From: Jan Kratochvil Date: Thu, 23 Jul 2026 10:52:35 +0200 Subject: [PATCH 03/41] Fix Gitlab CI --- src/hotspot/share/runtime/crac_engine.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hotspot/share/runtime/crac_engine.cpp b/src/hotspot/share/runtime/crac_engine.cpp index 28022cf7e42..223c6f191f6 100644 --- a/src/hotspot/share/runtime/crac_engine.cpp +++ b/src/hotspot/share/runtime/crac_engine.cpp @@ -412,8 +412,8 @@ bool CracEngine::restore_pre_core(FILE *f) const { } union { VM_Version::VM_Features features; - uint8_t bytes[sizeof(VM_Version::VM_Features)] = { 0 }; - } u; + uint8_t bytes[sizeof(VM_Version::VM_Features)]; + } u = {}; // explicitly construct the first member bool err = false; for (size_t i = 0; i < length; ++i) { u.bytes[i] = (from_hex(eq[1 + 2 * i], &err) << 4) + from_hex(eq[2 + 2 * i], &err); From e08bde774b0ef1619d36b3c8e8668d2942a0d33b Mon Sep 17 00:00:00 2001 From: Jan Kratochvil Date: Thu, 23 Jul 2026 11:00:10 +0200 Subject: [PATCH 04/41] Fix whitespace --- src/hotspot/share/runtime/crac_engine.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hotspot/share/runtime/crac_engine.cpp b/src/hotspot/share/runtime/crac_engine.cpp index 223c6f191f6..4b9554aa2a6 100644 --- a/src/hotspot/share/runtime/crac_engine.cpp +++ b/src/hotspot/share/runtime/crac_engine.cpp @@ -411,8 +411,8 @@ bool CracEngine::restore_pre_core(FILE *f) const { return false; } union { - VM_Version::VM_Features features; - uint8_t bytes[sizeof(VM_Version::VM_Features)]; + VM_Version::VM_Features features; + uint8_t bytes[sizeof(VM_Version::VM_Features)]; } u = {}; // explicitly construct the first member bool err = false; for (size_t i = 0; i < length; ++i) { From fa57bb5029921b0fef0c2df26e38a619069cdf37 Mon Sep 17 00:00:00 2001 From: Jan Kratochvil Date: Thu, 23 Jul 2026 11:19:35 +0200 Subject: [PATCH 05/41] Fix one forgotten maximum_sve_vector_length set --- src/hotspot/cpu/aarch64/vm_version_aarch64.cpp | 3 +-- src/hotspot/cpu/aarch64/vm_version_aarch64.hpp | 2 ++ src/hotspot/os_cpu/bsd_aarch64/vm_version_bsd_aarch64.cpp | 4 ++++ .../os_cpu/linux_aarch64/vm_version_linux_aarch64.cpp | 5 ++++- .../os_cpu/windows_aarch64/vm_version_windows_aarch64.cpp | 5 +++++ 5 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp index 1b425e60d81..0e82d22feff 100644 --- a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp @@ -939,7 +939,6 @@ bool VM_Version::restore_pre(VM_Features image_features, const char *image_locat } if (image_supports_sve256 && !_cpu_features.supports_feature(CPU_SVE256)) { ResourceMark rm; - stringStream ss; VM_Features sve256; sve256.set_feature(CPU_SVE256); VM_Features use = image_features & _cpu_features; @@ -947,11 +946,11 @@ bool VM_Version::restore_pre(VM_Features image_features, const char *image_locat image_location, image_features.print_numbers(), sve256.print_numbers(), _cpu_features.print_numbers(), use.print_numbers()); return false; } + set_maximum_sve_vector_length(16); errno = 0; int got = set_and_get_current_sve_vector_length(16); if (got != 16) { ResourceMark rm; - stringStream ss; VM_Features sve256; sve256.set_feature(CPU_SVE256); log_error(crac)("Image %s has -XX:CPUFeatures=%s with CPU_SVE256=%s unset, this CPU has CPUFeatures=%s but PR_SVE_SET_VL reports %d: %m", diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp index 12c501855ee..dd637b9d112 100644 --- a/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp @@ -114,6 +114,8 @@ class VM_Version : public Abstract_VM_Version, public VM_Feature_Flag { // Return the length that will be used, or -ve if an error occurred. static int set_and_get_current_sve_vector_length(int len); static int get_current_sve_vector_length(); + // Limit what set_and_get_current_sve_vector_length is willing to set. + void set_maximum_sve_vector_length(int length); public: // Initialization diff --git a/src/hotspot/os_cpu/bsd_aarch64/vm_version_bsd_aarch64.cpp b/src/hotspot/os_cpu/bsd_aarch64/vm_version_bsd_aarch64.cpp index 9a2aa75a7b8..6d965e8a5bb 100644 --- a/src/hotspot/os_cpu/bsd_aarch64/vm_version_bsd_aarch64.cpp +++ b/src/hotspot/os_cpu/bsd_aarch64/vm_version_bsd_aarch64.cpp @@ -35,6 +35,10 @@ int VM_Version::get_current_sve_vector_length() { return -1; } +void VM_Version::set_maximum_sve_vector_length(int length) { + ShouldNotCallThis(); +} + int VM_Version::set_and_get_current_sve_vector_length(int length) { ShouldNotCallThis(); return -1; diff --git a/src/hotspot/os_cpu/linux_aarch64/vm_version_linux_aarch64.cpp b/src/hotspot/os_cpu/linux_aarch64/vm_version_linux_aarch64.cpp index 7def6474a0d..d3ce96de97a 100644 --- a/src/hotspot/os_cpu/linux_aarch64/vm_version_linux_aarch64.cpp +++ b/src/hotspot/os_cpu/linux_aarch64/vm_version_linux_aarch64.cpp @@ -121,9 +121,12 @@ int VM_Version::get_current_sve_vector_length() { return prctl(PR_SVE_GET_VL); } -// Limit what set_and_get_current_sve_vector_length is willing to set. static int maximum_sve_vector_length = INT_MAX; +void VM_Version::set_maximum_sve_vector_length(int length) { + maximum_sve_vector_length = length; +} + int VM_Version::set_and_get_current_sve_vector_length(int length) { assert(VM_Version::supports_sve(), "should not call this"); int new_length = prctl(PR_SVE_SET_VL, MIN2(length, maximum_sve_vector_length)); diff --git a/src/hotspot/os_cpu/windows_aarch64/vm_version_windows_aarch64.cpp b/src/hotspot/os_cpu/windows_aarch64/vm_version_windows_aarch64.cpp index 963ba06b2fd..b13419fc609 100644 --- a/src/hotspot/os_cpu/windows_aarch64/vm_version_windows_aarch64.cpp +++ b/src/hotspot/os_cpu/windows_aarch64/vm_version_windows_aarch64.cpp @@ -61,6 +61,11 @@ int VM_Version::get_current_sve_vector_length() { return VM_Version::supports_sve() ? get_sve_vector_length() : 0; } +void VM_Version::set_maximum_sve_vector_length(int length) { + // CPU_SVE256 cannot be set on Windows. + ShouldNotCallThis(); +} + int VM_Version::set_and_get_current_sve_vector_length(int length) { assert(VM_Version::supports_sve(), "should not call this"); From a46f297d6f0977d0f53ef2c22a00bfd6c82c7480 Mon Sep 17 00:00:00 2001 From: Jan Kratochvil Date: Thu, 23 Jul 2026 14:40:33 +0200 Subject: [PATCH 06/41] Fix aarch64 build --- src/hotspot/cpu/aarch64/vm_version_aarch64.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp index dd637b9d112..dccadd1bff5 100644 --- a/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp @@ -115,7 +115,7 @@ class VM_Version : public Abstract_VM_Version, public VM_Feature_Flag { static int set_and_get_current_sve_vector_length(int len); static int get_current_sve_vector_length(); // Limit what set_and_get_current_sve_vector_length is willing to set. - void set_maximum_sve_vector_length(int length); + static void set_maximum_sve_vector_length(int length); public: // Initialization From b46ded6358a18a81022ea47a8264bb283aa11368 Mon Sep 17 00:00:00 2001 From: Jan Kratochvil Date: Thu, 23 Jul 2026 15:17:33 +0200 Subject: [PATCH 07/41] Remove dead code --- .../os_cpu/linux_aarch64/vm_version_linux_aarch64.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/hotspot/os_cpu/linux_aarch64/vm_version_linux_aarch64.cpp b/src/hotspot/os_cpu/linux_aarch64/vm_version_linux_aarch64.cpp index d3ce96de97a..6e410c1a647 100644 --- a/src/hotspot/os_cpu/linux_aarch64/vm_version_linux_aarch64.cpp +++ b/src/hotspot/os_cpu/linux_aarch64/vm_version_linux_aarch64.cpp @@ -239,12 +239,6 @@ void VM_Version::check_os_cpu_info() { } if (FLAG_IS_DEFAULT(CPUFeatures)) { assert(_cpu_features.supports_feature(CPU_SVE256) == _features.supports_feature(CPU_SVE256), "CPU_SVE256 is not changed"); - } else if (!_cpu_features.supports_feature(CPU_SVE256) && _features.supports_feature(CPU_SVE256)) { - stringStream ss; - VM_Features sve256; - sve256.set_feature(VM_Feature_Flag::CPU_SVE256); - ss.print("Specified -XX:CPUFeatures=%s have CPU_SVE256=%s set but this CPU does not support it", _features.print_numbers(), sve256.print_numbers()); - vm_exit_during_initialization(ss.base()); } else if (_cpu_features.supports_feature(CPU_SVE256) && !_features.supports_feature(CPU_SVE256)) { maximum_sve_vector_length = 16; int got = set_and_get_current_sve_vector_length(maximum_sve_vector_length); From d5f84faae8a31e0bc60eb2e6519dc86b4b8fa426 Mon Sep 17 00:00:00 2001 From: Jan Kratochvil Date: Thu, 23 Jul 2026 15:33:46 +0200 Subject: [PATCH 08/41] Fix CheckCPUFeaturesTest.java --- src/hotspot/share/runtime/crac_engine.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/hotspot/share/runtime/crac_engine.cpp b/src/hotspot/share/runtime/crac_engine.cpp index 4b9554aa2a6..ea65e20d313 100644 --- a/src/hotspot/share/runtime/crac_engine.cpp +++ b/src/hotspot/share/runtime/crac_engine.cpp @@ -447,6 +447,9 @@ bool CracEngine::restore_pre() const { if (!VM_Version::restore_pre_needed) { return true; } + if (VM_Version::check_cpu_features_skip() || !strcmp(CheckCPUFeatures, "skip")) { + return true; + } FILE* f = open_tags(_image_location, "r"); if (f == nullptr) { log_error(crac)("Cannot open tags for image %s", _image_location); From 15449dd4a3d2ae3b07a7d8c5b918b14c3f433185 Mon Sep 17 00:00:00 2001 From: Jan Kratochvil Date: Thu, 23 Jul 2026 15:35:45 +0200 Subject: [PATCH 09/41] Fix linux-cross-compile --- src/hotspot/cpu/arm/vm_version_arm.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/hotspot/cpu/arm/vm_version_arm.hpp b/src/hotspot/cpu/arm/vm_version_arm.hpp index cd16e8c5d45..e60e343a399 100644 --- a/src/hotspot/cpu/arm/vm_version_arm.hpp +++ b/src/hotspot/cpu/arm/vm_version_arm.hpp @@ -45,6 +45,10 @@ class VM_Version: public Abstract_VM_Version { static const char *restore_failed_check(const VM_Features *image_features, const VM_Features *current_features) { return nullptr; } + static bool restore_pre(VM_Features image_features, const char *image_location) { + return false; + } + static constexpr bool restore_pre_needed = false; protected: From 0f62afafee9c0aa0a4cfa7d07ff5fce97b18ade5 Mon Sep 17 00:00:00 2001 From: Jan Kratochvil Date: Thu, 23 Jul 2026 20:48:26 +0200 Subject: [PATCH 10/41] Fix SIGSEGV --- src/hotspot/share/runtime/crac_engine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/share/runtime/crac_engine.cpp b/src/hotspot/share/runtime/crac_engine.cpp index ea65e20d313..a2a084e20f1 100644 --- a/src/hotspot/share/runtime/crac_engine.cpp +++ b/src/hotspot/share/runtime/crac_engine.cpp @@ -447,7 +447,7 @@ bool CracEngine::restore_pre() const { if (!VM_Version::restore_pre_needed) { return true; } - if (VM_Version::check_cpu_features_skip() || !strcmp(CheckCPUFeatures, "skip")) { + if (VM_Version::check_cpu_features_skip() || (CheckCPUFeatures != nullptr && !strcmp(CheckCPUFeatures, "skip"))) { return true; } FILE* f = open_tags(_image_location, "r"); From b86c5ff37d4d9e59ba82054ae5f53b057ac8f64b Mon Sep 17 00:00:00 2001 From: Jan Kratochvil Date: Thu, 23 Jul 2026 20:48:41 +0200 Subject: [PATCH 11/41] Follow -XX::CheckCPUFeatures=skip --- src/hotspot/cpu/aarch64/vm_version_aarch64.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp index 0e82d22feff..d98d55c3c67 100644 --- a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp @@ -938,6 +938,9 @@ bool VM_Version::restore_pre(VM_Features image_features, const char *image_locat return true; } if (image_supports_sve256 && !_cpu_features.supports_feature(CPU_SVE256)) { + if (VM_Version::check_cpu_features_skip() || (CheckCPUFeatures != nullptr && !strcmp(CheckCPUFeatures, "skip"))) { + return true; + } ResourceMark rm; VM_Features sve256; sve256.set_feature(CPU_SVE256); From 768aae45f59f4a44f72ebc6a9a21daac2c9b9a4e Mon Sep 17 00:00:00 2001 From: Jan Kratochvil Date: Fri, 24 Jul 2026 14:35:17 +0200 Subject: [PATCH 12/41] restore_pre -> pre_restore --- src/hotspot/cpu/aarch64/vm_version_aarch64.cpp | 2 +- src/hotspot/cpu/aarch64/vm_version_aarch64.hpp | 4 ++-- src/hotspot/cpu/arm/vm_version_arm.hpp | 4 ++-- src/hotspot/cpu/x86/vm_version_x86.hpp | 4 ++-- src/hotspot/cpu/zero/vm_version_zero.hpp | 4 ++-- src/hotspot/share/runtime/crac_engine.cpp | 12 ++++++------ src/hotspot/share/runtime/crac_engine.hpp | 4 ++-- 7 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp index d98d55c3c67..84b589bfee8 100644 --- a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp @@ -932,7 +932,7 @@ void VM_Version::CPUFeatures_apply_arch(VM_Features &parsed, VM_Features &missin missing.clear_feature(CPU_NOTPACA); } -bool VM_Version::restore_pre(VM_Features image_features, const char *image_location) { +bool VM_Version::pre_restore(VM_Features image_features, const char *image_location) { bool image_supports_sve256 = image_features.supports_feature(CPU_SVE256); if (image_supports_sve256 == _cpu_features.supports_feature(CPU_SVE256)) { return true; diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp index dccadd1bff5..7af723e3964 100644 --- a/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp @@ -145,8 +145,8 @@ class VM_Version : public Abstract_VM_Version, public VM_Feature_Flag { static void insert_features_names(VM_Version::VM_Features features, outputStream& os); // The returned string needs a ResourceMark. static const char *restore_failed_check(const VM_Features *image_features, const VM_Features *current_features); - static bool restore_pre(VM_Features image_features, const char *image_location); - static constexpr bool restore_pre_needed = true; + static bool pre_restore(VM_Features image_features, const char *image_location); + static constexpr bool pre_restore_needed = true; 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 e60e343a399..5bd5301e376 100644 --- a/src/hotspot/cpu/arm/vm_version_arm.hpp +++ b/src/hotspot/cpu/arm/vm_version_arm.hpp @@ -45,10 +45,10 @@ class VM_Version: public Abstract_VM_Version { static const char *restore_failed_check(const VM_Features *image_features, const VM_Features *current_features) { return nullptr; } - static bool restore_pre(VM_Features image_features, const char *image_location) { + static bool pre_restore(VM_Features image_features, const char *image_location) { return false; } - static constexpr bool restore_pre_needed = false; + static constexpr bool pre_restore_needed = false; protected: diff --git a/src/hotspot/cpu/x86/vm_version_x86.hpp b/src/hotspot/cpu/x86/vm_version_x86.hpp index cf571bbfe18..4983820cc6a 100644 --- a/src/hotspot/cpu/x86/vm_version_x86.hpp +++ b/src/hotspot/cpu/x86/vm_version_x86.hpp @@ -732,10 +732,10 @@ class VM_Version : public Abstract_VM_Version, protected VM_Feature_Flag { static const char *restore_failed_check(const VM_Features *image_features, const VM_Features *current_features) { return nullptr; } - static bool restore_pre(VM_Features image_features, const char *image_location) { + static bool pre_restore(VM_Features image_features, const char *image_location) { return false; } - static constexpr bool restore_pre_needed = false; + static constexpr bool pre_restore_needed = false; static bool os_supports_avx_vectors(); static bool os_supports_apx_egprs(); diff --git a/src/hotspot/cpu/zero/vm_version_zero.hpp b/src/hotspot/cpu/zero/vm_version_zero.hpp index 131eeda9599..d8a01a2d435 100644 --- a/src/hotspot/cpu/zero/vm_version_zero.hpp +++ b/src/hotspot/cpu/zero/vm_version_zero.hpp @@ -38,10 +38,10 @@ class VM_Version : public Abstract_VM_Version { static const char *restore_failed_check(const VM_Features *image_features, const VM_Features *current_features) { return nullptr; } - static bool restore_pre(VM_Features image_features, const char *image_location) { + static bool pre_restore(VM_Features image_features, const char *image_location) { return false; } - static constexpr bool restore_pre_needed = false; + static constexpr bool pre_restore_needed = false; constexpr static bool supports_stack_watermark_barrier() { return true; } diff --git a/src/hotspot/share/runtime/crac_engine.cpp b/src/hotspot/share/runtime/crac_engine.cpp index a2a084e20f1..c9e43a3734c 100644 --- a/src/hotspot/share/runtime/crac_engine.cpp +++ b/src/hotspot/share/runtime/crac_engine.cpp @@ -392,7 +392,7 @@ static inline unsigned char from_hex(char c, bool* err) { static constexpr char cpufeatures_prefix[] = "bitmap:cpu.features"; // FIXME: Replace "tags" parsing by a new constraint reader method call. -bool CracEngine::restore_pre_core(FILE *f) const { +bool CracEngine::pre_restore_core(FILE *f) const { static constexpr const size_t _MAX_VALUE_SIZE = 256; char line[sizeof(cpufeatures_prefix) + 1 + _MAX_VALUE_SIZE + 2]; while (fgets(line, (int) sizeof(line), f)) { @@ -422,7 +422,7 @@ bool CracEngine::restore_pre_core(FILE *f) const { log_error(crac)("Invalid format of tags file (bad character in bitmap): %s", line); return false; } - return VM_Version::restore_pre(u.features, _image_location); + return VM_Version::pre_restore(u.features, _image_location); } } log_error(crac)("%s not found in image %s", cpufeatures_prefix, _image_location); @@ -443,8 +443,8 @@ static FILE* open_tags(const char* image_location, const char* mode) { return f; } -bool CracEngine::restore_pre() const { - if (!VM_Version::restore_pre_needed) { +bool CracEngine::pre_restore() const { + if (!VM_Version::pre_restore_needed) { return true; } if (VM_Version::check_cpu_features_skip() || (CheckCPUFeatures != nullptr && !strcmp(CheckCPUFeatures, "skip"))) { @@ -455,7 +455,7 @@ bool CracEngine::restore_pre() const { log_error(crac)("Cannot open tags for image %s", _image_location); return false; } - bool retval = restore_pre_core(f); + bool retval = pre_restore_core(f); if (fclose(f)) { log_error(crac)("cannot close %s/tags: %s", _image_location, os::strerror(errno)); return false; @@ -468,7 +468,7 @@ int CracEngine::restore() const { if (!check_engine(_name, _image_location)) { return -1; } - if (!restore_pre()) { + if (!pre_restore()) { return -1; } return _api->restore(_conf); diff --git a/src/hotspot/share/runtime/crac_engine.hpp b/src/hotspot/share/runtime/crac_engine.hpp index c4fa07be0d9..d3e9d7660c1 100644 --- a/src/hotspot/share/runtime/crac_engine.hpp +++ b/src/hotspot/share/runtime/crac_engine.hpp @@ -93,8 +93,8 @@ class CracEngine : public CHeapObj { crlib_conf_option_t *_options = nullptr; - bool restore_pre() const; - bool restore_pre_core(FILE *f) const; + bool pre_restore() const; + bool pre_restore_core(FILE *f) const; }; #endif // SHARE_RUNTIME_CRAC_ENGINE_HPP From 588ee21ee013b622737cc3b70275f58b955d54fc Mon Sep 17 00:00:00 2001 From: Jan Kratochvil Date: Fri, 24 Jul 2026 15:49:06 +0200 Subject: [PATCH 13/41] Provide should_skip_cpu_features_check() --- src/hotspot/cpu/aarch64/vm_version_aarch64.cpp | 2 +- src/hotspot/cpu/aarch64/vm_version_aarch64.hpp | 8 +++++--- src/hotspot/cpu/arm/vm_version_arm.hpp | 4 +++- src/hotspot/cpu/ppc/vm_version_ppc.hpp | 4 +++- src/hotspot/cpu/riscv/vm_version_riscv.hpp | 4 +++- src/hotspot/cpu/s390/vm_version_s390.hpp | 3 ++- src/hotspot/cpu/x86/vm_version_x86.hpp | 8 +++++--- src/hotspot/cpu/zero/vm_version_zero.hpp | 4 +++- src/hotspot/share/runtime/abstract_vm_version.cpp | 4 ++++ src/hotspot/share/runtime/abstract_vm_version.hpp | 2 ++ src/hotspot/share/runtime/crac.cpp | 6 +++--- src/hotspot/share/runtime/crac_engine.cpp | 2 +- 12 files changed, 35 insertions(+), 16 deletions(-) diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp index 84b589bfee8..00dd04999bd 100644 --- a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp @@ -938,7 +938,7 @@ bool VM_Version::pre_restore(VM_Features image_features, const char *image_locat return true; } if (image_supports_sve256 && !_cpu_features.supports_feature(CPU_SVE256)) { - if (VM_Version::check_cpu_features_skip() || (CheckCPUFeatures != nullptr && !strcmp(CheckCPUFeatures, "skip"))) { + if (Abstract_VM_Version::should_skip_cpu_features_check()) { return true; } ResourceMark rm; diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp index 7af723e3964..e6b0593bac2 100644 --- a/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp @@ -117,14 +117,16 @@ class VM_Version : public Abstract_VM_Version, public VM_Feature_Flag { // Limit what set_and_get_current_sve_vector_length is willing to set. static void set_maximum_sve_vector_length(int length); + friend bool Abstract_VM_Version::should_skip_cpu_features_check(); + static bool check_cpu_features_skip() { + return _ignore_glibc_not_using; + } + public: // Initialization typedef ::VM_Features VM_Features; static void initialize(); static bool cpu_features_binary(VM_Features *data); - static bool check_cpu_features_skip() { - return _ignore_glibc_not_using; - } static void check_virtualizations(); static VM_Features CPUFeatures_mandatory(); diff --git a/src/hotspot/cpu/arm/vm_version_arm.hpp b/src/hotspot/cpu/arm/vm_version_arm.hpp index 5bd5301e376..688cb3b9ea1 100644 --- a/src/hotspot/cpu/arm/vm_version_arm.hpp +++ b/src/hotspot/cpu/arm/vm_version_arm.hpp @@ -32,6 +32,9 @@ class VM_Version: public Abstract_VM_Version { static bool _has_simd; static bool _has_mp_ext; + friend bool Abstract_VM_Version::should_skip_cpu_features_check(); + static bool check_cpu_features_skip() { return true; } + protected: // Are we done with vm version initialization static bool _is_initialized; @@ -41,7 +44,6 @@ 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 check_cpu_features_skip() { return true; } static const char *restore_failed_check(const VM_Features *image_features, const VM_Features *current_features) { return nullptr; } diff --git a/src/hotspot/cpu/ppc/vm_version_ppc.hpp b/src/hotspot/cpu/ppc/vm_version_ppc.hpp index 628a2493220..f6669e6858f 100644 --- a/src/hotspot/cpu/ppc/vm_version_ppc.hpp +++ b/src/hotspot/cpu/ppc/vm_version_ppc.hpp @@ -30,6 +30,9 @@ #include "runtime/globals_extension.hpp" class VM_Version: public Abstract_VM_Version { + friend bool Abstract_VM_Version::should_skip_cpu_features_check(); + static bool check_cpu_features_skip() { return true; } + protected: enum Feature_Flag { mfdscr, @@ -57,7 +60,6 @@ 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 check_cpu_features_skip() { return true; } // Override Abstract_VM_Version implementation static void print_platform_virtualization_info(outputStream*); diff --git a/src/hotspot/cpu/riscv/vm_version_riscv.hpp b/src/hotspot/cpu/riscv/vm_version_riscv.hpp index f5444bc1d6d..c0aaa709f47 100644 --- a/src/hotspot/cpu/riscv/vm_version_riscv.hpp +++ b/src/hotspot/cpu/riscv/vm_version_riscv.hpp @@ -496,13 +496,15 @@ class VM_Version : public Abstract_VM_Version { static void c2_initialize(); #endif // COMPILER2 + friend bool Abstract_VM_Version::should_skip_cpu_features_check(); + static bool check_cpu_features_skip() { return true; } + public: // Initialization static void initialize(); static void initialize_cpu_information(); struct VM_Features: public Zero_Features {}; static bool cpu_features_binary(VM_Features *data) { return false; } - static bool check_cpu_features_skip() { return true; } constexpr static bool supports_stack_watermark_barrier() { return true; } diff --git a/src/hotspot/cpu/s390/vm_version_s390.hpp b/src/hotspot/cpu/s390/vm_version_s390.hpp index 38c116f0ac8..6ed39265ea5 100644 --- a/src/hotspot/cpu/s390/vm_version_s390.hpp +++ b/src/hotspot/cpu/s390/vm_version_s390.hpp @@ -31,6 +31,8 @@ #include "runtime/globals_extension.hpp" class VM_Version: public Abstract_VM_Version { + friend bool Abstract_VM_Version::should_skip_cpu_features_check(); + static bool check_cpu_features_skip() { return true; } protected: // z/Architecture is the name of the 64-bit extension of the 31-bit s390 @@ -418,7 +420,6 @@ 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 check_cpu_features_skip() { return true; } // Override Abstract_VM_Version implementation static void print_platform_virtualization_info(outputStream*); diff --git a/src/hotspot/cpu/x86/vm_version_x86.hpp b/src/hotspot/cpu/x86/vm_version_x86.hpp index 4983820cc6a..9ecf05b8604 100644 --- a/src/hotspot/cpu/x86/vm_version_x86.hpp +++ b/src/hotspot/cpu/x86/vm_version_x86.hpp @@ -741,6 +741,11 @@ class VM_Version : public Abstract_VM_Version, protected VM_Feature_Flag { static bool os_supports_apx_egprs(); static void get_processor_features(); + friend bool Abstract_VM_Version::should_skip_cpu_features_check(); + static bool check_cpu_features_skip() { + return _ignore_glibc_not_using; + } + public: // Offsets for cpuid asm stub static ByteSize std_cpuid0_offset() { return byte_offset_of(CpuidInfo, std_max_function); } @@ -817,9 +822,6 @@ class VM_Version : public Abstract_VM_Version, protected VM_Feature_Flag { // Initialization static void initialize(); static bool cpu_features_binary(VM_Features *data); - static bool check_cpu_features_skip() { - return _ignore_glibc_not_using; - } // Override Abstract_VM_Version implementation static void print_platform_virtualization_info(outputStream*); diff --git a/src/hotspot/cpu/zero/vm_version_zero.hpp b/src/hotspot/cpu/zero/vm_version_zero.hpp index d8a01a2d435..f808940605e 100644 --- a/src/hotspot/cpu/zero/vm_version_zero.hpp +++ b/src/hotspot/cpu/zero/vm_version_zero.hpp @@ -30,11 +30,13 @@ #include "runtime/globals_extension.hpp" class VM_Version : public Abstract_VM_Version { + friend bool Abstract_VM_Version::should_skip_cpu_features_check(); + static bool check_cpu_features_skip() { return true; } + public: static void initialize(); struct VM_Features: public Zero_Features {}; static bool cpu_features_binary(VM_Features *data) { return false; } - static bool check_cpu_features_skip() { return true; } static const char *restore_failed_check(const VM_Features *image_features, const VM_Features *current_features) { return nullptr; } diff --git a/src/hotspot/share/runtime/abstract_vm_version.cpp b/src/hotspot/share/runtime/abstract_vm_version.cpp index 33fdb4caa3a..bcc8acc8aa7 100644 --- a/src/hotspot/share/runtime/abstract_vm_version.cpp +++ b/src/hotspot/share/runtime/abstract_vm_version.cpp @@ -401,3 +401,7 @@ void Abstract_VM_Version::check_cpufeatures_vmoptions() { tty->print_cr("Do not use -XX:ShowCPUFeatures: this architecture does not support any arch-specific strings."); } } + +bool Abstract_VM_Version::should_skip_cpu_features_check() { + return VM_Version::check_cpu_features_skip() || (CheckCPUFeatures != nullptr && !strcmp(CheckCPUFeatures, "skip")); +} diff --git a/src/hotspot/share/runtime/abstract_vm_version.hpp b/src/hotspot/share/runtime/abstract_vm_version.hpp index 35f623d2363..8e420edea11 100644 --- a/src/hotspot/share/runtime/abstract_vm_version.hpp +++ b/src/hotspot/share/runtime/abstract_vm_version.hpp @@ -268,6 +268,8 @@ class Abstract_VM_Version: AllStatic { // features_buffer is an opaque object that stores arch specific representation of cpu features static bool verify_aot_code_cache_features(void* features_buffer) { return false; }; + + static bool should_skip_cpu_features_check(); }; #endif // SHARE_RUNTIME_ABSTRACT_VM_VERSION_HPP diff --git a/src/hotspot/share/runtime/crac.cpp b/src/hotspot/share/runtime/crac.cpp index b935092d2a1..e3e2428b9e3 100644 --- a/src/hotspot/share/runtime/crac.cpp +++ b/src/hotspot/share/runtime/crac.cpp @@ -328,7 +328,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::check_cpu_features_skip()) { + if (_generation == 1 && !Abstract_VM_Version::should_skip_cpu_features_check()) { VM_Version::VM_Features current_features; if (VM_Version::cpu_features_binary(¤t_features)) { switch (_engine->prepare_image_constraints_api()) { @@ -873,12 +873,12 @@ void crac::restore(crac_restore_data& restore_data) { // Since the check itself is delegated to the C/R Engine we will simply // skip the check here. - bool ignore = VM_Version::check_cpu_features_skip(); + bool ignore = Abstract_VM_Version::should_skip_cpu_features_check(); bool exact = false; if (CheckCPUFeatures == nullptr || !strcmp(CheckCPUFeatures, "compatible")) { // default, compatible } else if (!strcmp(CheckCPUFeatures, "skip")) { - ignore = true; + assert(ignore, "Abstract_VM_Version::should_skip_cpu_features_check() has checked it"); } else if (!strcmp(CheckCPUFeatures, "exact")) { exact = true; } else { diff --git a/src/hotspot/share/runtime/crac_engine.cpp b/src/hotspot/share/runtime/crac_engine.cpp index c9e43a3734c..7fcd6a6b71e 100644 --- a/src/hotspot/share/runtime/crac_engine.cpp +++ b/src/hotspot/share/runtime/crac_engine.cpp @@ -447,7 +447,7 @@ bool CracEngine::pre_restore() const { if (!VM_Version::pre_restore_needed) { return true; } - if (VM_Version::check_cpu_features_skip() || (CheckCPUFeatures != nullptr && !strcmp(CheckCPUFeatures, "skip"))) { + if (Abstract_VM_Version::should_skip_cpu_features_check()) { return true; } FILE* f = open_tags(_image_location, "r"); From 52d526cf6c2fd8c2c702a9afaaa2f76adb24f102 Mon Sep 17 00:00:00 2001 From: Jan Kratochvil Date: Fri, 24 Jul 2026 15:52:21 +0200 Subject: [PATCH 14/41] +get_label, +get_bitmap --- .../include/crlib/crlib_image_constraints.h | 7 ++ src/hotspot/share/runtime/crac_engine.cpp | 84 +++---------------- .../share/native/libcrcommon/crcommon.cpp | 10 +++ .../native/libcrcommon/image_constraints.hpp | 44 ++++++---- 4 files changed, 57 insertions(+), 88 deletions(-) diff --git a/src/hotspot/share/include/crlib/crlib_image_constraints.h b/src/hotspot/share/include/crlib/crlib_image_constraints.h index 9f0caa935d6..9c13d774d24 100644 --- a/src/hotspot/share/include/crlib/crlib_image_constraints.h +++ b/src/hotspot/share/include/crlib/crlib_image_constraints.h @@ -69,6 +69,13 @@ typedef const struct crlib_image_constraints { // Returns the size of the data, in bytes — it can be more, equal to or less than // 'value_size'. Returned value of 0 represents an error. size_t (*get_failed_bitmap)(crlib_conf_t *, const char *name, unsigned char *value_return, size_t value_size); + + // It will copy value from the image to the provided buffer. + // Copies up to 'value_size' bytes of the data into 'value_return' of appropriate size. + // Returns the size of the data, in bytes — it can be more, equal to or less than + // 'value_size'. Returned value of 0 represents an error. + size_t (*get_label)(crlib_conf_t *, const char *name, char *value_return, size_t value_size); + size_t (*get_bitmap)(crlib_conf_t *, const char *name, unsigned char *value_return, size_t value_size); } crlib_image_constraints_t; #ifdef __cplusplus diff --git a/src/hotspot/share/runtime/crac_engine.cpp b/src/hotspot/share/runtime/crac_engine.cpp index 7fcd6a6b71e..f2228fcaac3 100644 --- a/src/hotspot/share/runtime/crac_engine.cpp +++ b/src/hotspot/share/runtime/crac_engine.cpp @@ -378,70 +378,8 @@ int CracEngine::checkpoint() const { return _api->checkpoint(_conf); } -static inline unsigned char from_hex(char c, bool* err) { - if (c >= '0' && c <= '9') { - return c - '0'; - } else if (c >= 'a' && c <= 'f') { - return c - 'a' + 10; - } else { - *err = true; - return 0; - } -} - -static constexpr char cpufeatures_prefix[] = "bitmap:cpu.features"; - -// FIXME: Replace "tags" parsing by a new constraint reader method call. -bool CracEngine::pre_restore_core(FILE *f) const { - static constexpr const size_t _MAX_VALUE_SIZE = 256; - char line[sizeof(cpufeatures_prefix) + 1 + _MAX_VALUE_SIZE + 2]; - while (fgets(line, (int) sizeof(line), f)) { - char* eq = strchr((char *) line, '='); - char* nl = strchr((char *) (eq + 1), '\n'); - if (eq == nullptr || nl == nullptr) { - log_error(crac)("Invalid format of tags file of image %s: %s", _image_location, line); - return false; - } - *eq = 0; - *nl = 0; - if (eq < nl && !strncmp(line, cpufeatures_prefix, strlen(cpufeatures_prefix)) && eq - line == strlen(cpufeatures_prefix)) { - size_t length = (size_t)(nl - eq - 1)/2; - if (2 * length != (size_t)(nl - eq - 1)) { - log_error(crac)("Invalid format of tags file (bad bitmap) of image %s: %s", _image_location, line); - return false; - } - union { - VM_Version::VM_Features features; - uint8_t bytes[sizeof(VM_Version::VM_Features)]; - } u = {}; // explicitly construct the first member - bool err = false; - for (size_t i = 0; i < length; ++i) { - u.bytes[i] = (from_hex(eq[1 + 2 * i], &err) << 4) + from_hex(eq[2 + 2 * i], &err); - } - if (err) { - log_error(crac)("Invalid format of tags file (bad character in bitmap): %s", line); - return false; - } - return VM_Version::pre_restore(u.features, _image_location); - } - } - log_error(crac)("%s not found in image %s", cpufeatures_prefix, _image_location); - return false; -} - -static FILE* open_tags(const char* image_location, const char* mode) { - char fname[PATH_MAX]; - if (os::snprintf(fname, sizeof(fname), "%s/tags", image_location) >= (int) sizeof(fname) - 1) { - log_error(crac)("filename too long: %s/tags", image_location); - return nullptr; - } - FILE* f = fopen(fname, mode); - if (f == nullptr) { - log_error(crac)("cannot open %s in mode %s: %s", fname, mode, os::strerror(errno)); - return nullptr; - } - return f; -} +static constexpr char cpuarch_name[] = "cpu.arch"; +static constexpr char cpufeatures_name[] = "cpu.features"; bool CracEngine::pre_restore() const { if (!VM_Version::pre_restore_needed) { @@ -450,17 +388,18 @@ bool CracEngine::pre_restore() const { if (Abstract_VM_Version::should_skip_cpu_features_check()) { return true; } - FILE* f = open_tags(_image_location, "r"); - if (f == nullptr) { - log_error(crac)("Cannot open tags for image %s", _image_location); + crlib_image_constraints_t *ics = CRLIB_EXTENSION_IMAGE_CONSTRAINTS(_api); + if (ics == nullptr) { + log_error(crac)("Cannot initialize constraints extension for image %s", _image_location); return false; } - bool retval = pre_restore_core(f); - if (fclose(f)) { - log_error(crac)("cannot close %s/tags: %s", _image_location, os::strerror(errno)); + VM_Features features; + size_t features_len = ics->get_bitmap(_conf, cpufeatures_name, reinterpret_cast(&features), sizeof(features)); + if (features_len != sizeof(features)) { + log_error(crac)("Cannot get CPUFeatures for image %s", _image_location); return false; } - return retval; + return VM_Version::pre_restore(features, _image_location); } int CracEngine::restore() const { @@ -595,9 +534,6 @@ const crlib_conf_option_t *CracEngine::configuration_options() { return _options; } -static constexpr char cpuarch_name[] = "cpu.arch"; -static constexpr char cpufeatures_name[] = "cpu.features"; - CracEngine::ApiStatus CracEngine::prepare_image_constraints_api() { prepare_extension_api(_image_constraints_api, CRLIB_EXTENSION_IMAGE_CONSTRAINTS_NAME) require_method(set_label) diff --git a/src/java.base/share/native/libcrcommon/crcommon.cpp b/src/java.base/share/native/libcrcommon/crcommon.cpp index 82f0a16666e..c880a5fb7b7 100644 --- a/src/java.base/share/native/libcrcommon/crcommon.cpp +++ b/src/java.base/share/native/libcrcommon/crcommon.cpp @@ -63,6 +63,14 @@ static size_t get_failed_bitmap(crlib_conf_t* conf, const char* name, unsigned c return COMMON(conf)->image_constraints.get_failed_bitmap(name, value_return, value_size); } +static size_t get_bitmap(crlib_conf_t* conf, const char* name, unsigned char* value_return, size_t value_size) { + return COMMON(conf)->image_constraints.get_bitmap(name, value_return, value_size); +} + +static size_t get_label(crlib_conf_t* conf, const char* name, char* value_return, size_t value_size) { + return COMMON(conf)->image_constraints.get_label(name, value_return, value_size); +} + static bool set_score(crlib_conf_t* conf, const char* name, double value) { return COMMON(conf)->image_score.set_score(name, value); } @@ -98,6 +106,8 @@ extern JNIEXPORT crlib_image_constraints_t image_constraints_extension = { require_bitmap, is_failed, get_failed_bitmap, + get_label, + get_bitmap, }; JNIEXPORT bool image_constraints_persist(const crcommon_t* conf, const char* image_location) { diff --git a/src/java.base/share/native/libcrcommon/image_constraints.hpp b/src/java.base/share/native/libcrcommon/image_constraints.hpp index 445408fd278..7236987c355 100644 --- a/src/java.base/share/native/libcrcommon/image_constraints.hpp +++ b/src/java.base/share/native/libcrcommon/image_constraints.hpp @@ -116,6 +116,24 @@ class ImageConstraints { bool check_tag(const char* type, const char* name, size_t value_size); + template + size_t get_any_tmpl(const char* name, ValueT *value_return, size_t value_size, bool only_failed, TagType type) const { + size_t result = 0; + _constraints.foreach([&](Constraint &c) { + if (c.type == type && !strcmp(c.name, name) && (!only_failed || c.failed)) { + if (c.image_data == nullptr) { + result = 0; + } else { + result = c.data_size; + if (value_return) { + memcpy(value_return, c.image_data, value_size <= c.data_size ? value_size : c.data_size); + } + } + } + }); + return result; + } + public: bool set_label(const char* name, const char* value); bool set_bitmap(const char* name, const unsigned char* value, size_t length_bytes); @@ -141,20 +159,18 @@ class ImageConstraints { } size_t get_failed_bitmap(const char* name, unsigned char *value_return, size_t value_size) const { - size_t result = 0; - _constraints.foreach([&](Constraint &c) { - if (!strcmp(c.name, name) && c.failed) { - if (c.image_data == nullptr) { - result = 0; - } else { - result = c.data_size; - if (value_return) { - memcpy(value_return, c.image_data, value_size <= c.data_size ? value_size : c.data_size); - } - } - } - }); - return result; + bool only_failed = true; + return get_any_tmpl(name, value_return, value_size, only_failed, TagType::BITMAP); + } + + size_t get_label(const char* name, char *value_return, size_t value_size) const { + bool only_failed = false; + return get_any_tmpl(name, value_return, value_size, only_failed, TagType::LABEL); + } + + size_t get_bitmap(const char* name, unsigned char *value_return, size_t value_size) const { + bool only_failed = false; + return get_any_tmpl(name, value_return, value_size, only_failed, TagType::BITMAP); } bool persist(const char* image_location) const; From cb710189db4cc2ce5a6c9130992db7db52b6cbfc Mon Sep 17 00:00:00 2001 From: Jan Kratochvil Date: Fri, 24 Jul 2026 17:31:31 +0200 Subject: [PATCH 15/41] Fix get_label,get_bitmap --- .../include/crlib/crlib_image_constraints.h | 5 +- .../native/libcrcommon/image_constraints.cpp | 69 +++++++++++++++---- .../native/libcrcommon/image_constraints.hpp | 50 ++++++-------- 3 files changed, 80 insertions(+), 44 deletions(-) diff --git a/src/hotspot/share/include/crlib/crlib_image_constraints.h b/src/hotspot/share/include/crlib/crlib_image_constraints.h index 9c13d774d24..b6a89e4be96 100644 --- a/src/hotspot/share/include/crlib/crlib_image_constraints.h +++ b/src/hotspot/share/include/crlib/crlib_image_constraints.h @@ -70,10 +70,7 @@ typedef const struct crlib_image_constraints { // 'value_size'. Returned value of 0 represents an error. size_t (*get_failed_bitmap)(crlib_conf_t *, const char *name, unsigned char *value_return, size_t value_size); - // It will copy value from the image to the provided buffer. - // Copies up to 'value_size' bytes of the data into 'value_return' of appropriate size. - // Returns the size of the data, in bytes — it can be more, equal to or less than - // 'value_size'. Returned value of 0 represents an error. + // Like get_failed_bitmap but there is no requirement for a previous failure. size_t (*get_label)(crlib_conf_t *, const char *name, char *value_return, size_t value_size); size_t (*get_bitmap)(crlib_conf_t *, const char *name, unsigned char *value_return, size_t value_size); } crlib_image_constraints_t; diff --git a/src/java.base/share/native/libcrcommon/image_constraints.cpp b/src/java.base/share/native/libcrcommon/image_constraints.cpp index f042fce7dc6..d384d65e67a 100644 --- a/src/java.base/share/native/libcrcommon/image_constraints.cpp +++ b/src/java.base/share/native/libcrcommon/image_constraints.cpp @@ -196,17 +196,9 @@ static void print_bitmap(const char* name, const unsigned char* data, size_t siz fputc('\n', stderr); } -bool ImageConstraints::validate(const char* image_location) const { - if (_constraints.size() == 0) { - // If there are no constraints don't even try to open the file (it's fine if it is missing) - return true; - } - FILE* f = open_tags(image_location, "r"); - if (f == nullptr) { - return false; - } +template +bool ImageConstraints::load_tags(FILE *f, CallbackT callback) const { char line[sizeof(BITMAP_PREFIX) + _MAX_NAME_SIZE + 1 + _MAX_VALUE_SIZE + 2]; - LinkedList tags; while (fgets(line, (int) sizeof(line), f)) { char* eq = strchr((char *) line, '='); char* nl = strchr((char *) (eq + 1), '\n'); @@ -220,7 +212,7 @@ bool ImageConstraints::validate(const char* image_location) const { if (!strncmp(line, LABEL_PREFIX, strlen(LABEL_PREFIX))) { char* name = strdup(line + strlen(LABEL_PREFIX)); char* value = strdup(eq + 1); - if (name == nullptr || value == nullptr || !tags.add({ TagType::LABEL, name, value, (size_t) (nl - eq) })) { + if (name == nullptr || value == nullptr || !callback({ TagType::LABEL, name, value, (size_t) (nl - eq) })) { LOG("Cannot allocate memory for validation"); free(name); free(value); @@ -246,7 +238,7 @@ bool ImageConstraints::validate(const char* image_location) const { return false; } char* name = strdup(line + strlen(BITMAP_PREFIX)); - if (name == nullptr || !tags.add({ TagType::BITMAP, name, data, length })) { + if (name == nullptr || !callback({ TagType::BITMAP, name, data, length })) { LOG("Cannot allocate memory for validation"); free(name); free(data); @@ -257,6 +249,35 @@ bool ImageConstraints::validate(const char* image_location) const { return false; } } + return true; +} + +template +bool ImageConstraints::load_tags(const char* image_location, CallbackT callback) const { + FILE* f = open_tags(image_location, "r"); + if (f == nullptr) { + LOG("error opening %s: %m", image_location); + return false; + } + load_tags(f, callback); + if (fclose(f) != 0) { + LOG("error closing %s: %m", image_location); + return false; + } + return true; +} + +bool ImageConstraints::validate(const char* image_location) const { + if (_constraints.size() == 0) { + // If there are no constraints don't even try to open the file (it's fine if it is missing) + return true; + } + LinkedList tags; + if (!load_tags(image_location, [&](Tag &&tag) { + return tags.add(std::move(tag)); + })) { + return false; + } const char** keys = new(std::nothrow) const char*[tags.size()]; if (keys == nullptr) { LOG("Insufficient memory"); @@ -302,3 +323,27 @@ bool ImageConstraints::validate(const char* image_location) const { }); return result; } + +size_t ImageConstraints::get_any(const char* image_location, const char* name, void *value_return, size_t value_size, ImageConstraints::TagType tagtype) const { + size_t retval = 0; + if (!load_tags(image_location, [&](ImageConstraints::Tag &&tag) { + if (tag.type == tagtype && strcmp(tag.name, name) == 0) { + retval = tag.data_size; + if (value_return) { + memcpy(value_return, tag.data, value_size <= tag.data_size ? value_size : tag.data_size); + } + } + return true; + })) { + return 0; + } + return retval; +} + +size_t ImageConstraints::get_label(const char* image_location, const char* name, char* value_return, size_t value_size) const { + return get_any(image_location, name, value_return, value_size, TagType::LABEL); +} + +size_t ImageConstraints::get_bitmap(const char* image_location, const char* name, unsigned char* value_return, size_t value_size) const { + return get_any(image_location, name, value_return, value_size, TagType::BITMAP); +} diff --git a/src/java.base/share/native/libcrcommon/image_constraints.hpp b/src/java.base/share/native/libcrcommon/image_constraints.hpp index 7236987c355..ca066289aff 100644 --- a/src/java.base/share/native/libcrcommon/image_constraints.hpp +++ b/src/java.base/share/native/libcrcommon/image_constraints.hpp @@ -116,23 +116,12 @@ class ImageConstraints { bool check_tag(const char* type, const char* name, size_t value_size); - template - size_t get_any_tmpl(const char* name, ValueT *value_return, size_t value_size, bool only_failed, TagType type) const { - size_t result = 0; - _constraints.foreach([&](Constraint &c) { - if (c.type == type && !strcmp(c.name, name) && (!only_failed || c.failed)) { - if (c.image_data == nullptr) { - result = 0; - } else { - result = c.data_size; - if (value_return) { - memcpy(value_return, c.image_data, value_size <= c.data_size ? value_size : c.data_size); - } - } - } - }); - return result; - } + template + bool load_tags(FILE *f, CallbackT callback) const; + template + bool load_tags(const char* image_location, CallbackT callback) const; + + size_t get_any(const char* image_location, const char* name, void *value_return, size_t value_size, ImageConstraints::TagType tagtype) const; public: bool set_label(const char* name, const char* value); @@ -159,19 +148,24 @@ class ImageConstraints { } size_t get_failed_bitmap(const char* name, unsigned char *value_return, size_t value_size) const { - bool only_failed = true; - return get_any_tmpl(name, value_return, value_size, only_failed, TagType::BITMAP); - } - - size_t get_label(const char* name, char *value_return, size_t value_size) const { - bool only_failed = false; - return get_any_tmpl(name, value_return, value_size, only_failed, TagType::LABEL); + size_t result = 0; + _constraints.foreach([&](Constraint &c) { + if (!strcmp(c.name, name) && c.failed) { + if (c.image_data == nullptr) { + result = 0; + } else { + result = c.data_size; + if (value_return) { + memcpy(value_return, c.image_data, value_size <= c.data_size ? value_size : c.data_size); + } + } + } + }); + return result; } - size_t get_bitmap(const char* name, unsigned char *value_return, size_t value_size) const { - bool only_failed = false; - return get_any_tmpl(name, value_return, value_size, only_failed, TagType::BITMAP); - } + size_t get_label(const char* image_location, const char* name, char* value_return, size_t value_size) const; + size_t get_bitmap(const char* image_location, const char* name, unsigned char* value_return, size_t value_size) const; bool persist(const char* image_location) const; bool validate(const char* image_location) const; From 8db9bc7edb99567682c8581d64ae0b77cfbbaf71 Mon Sep 17 00:00:00 2001 From: Jan Kratochvil Date: Fri, 24 Jul 2026 17:55:29 +0200 Subject: [PATCH 16/41] Compilation fix --- .../share/include/crlib/crlib_image_constraints.h | 4 ---- src/java.base/share/native/libcrcommon/crcommon.cpp | 10 ---------- 2 files changed, 14 deletions(-) diff --git a/src/hotspot/share/include/crlib/crlib_image_constraints.h b/src/hotspot/share/include/crlib/crlib_image_constraints.h index b6a89e4be96..9f0caa935d6 100644 --- a/src/hotspot/share/include/crlib/crlib_image_constraints.h +++ b/src/hotspot/share/include/crlib/crlib_image_constraints.h @@ -69,10 +69,6 @@ typedef const struct crlib_image_constraints { // Returns the size of the data, in bytes — it can be more, equal to or less than // 'value_size'. Returned value of 0 represents an error. size_t (*get_failed_bitmap)(crlib_conf_t *, const char *name, unsigned char *value_return, size_t value_size); - - // Like get_failed_bitmap but there is no requirement for a previous failure. - size_t (*get_label)(crlib_conf_t *, const char *name, char *value_return, size_t value_size); - size_t (*get_bitmap)(crlib_conf_t *, const char *name, unsigned char *value_return, size_t value_size); } crlib_image_constraints_t; #ifdef __cplusplus diff --git a/src/java.base/share/native/libcrcommon/crcommon.cpp b/src/java.base/share/native/libcrcommon/crcommon.cpp index c880a5fb7b7..82f0a16666e 100644 --- a/src/java.base/share/native/libcrcommon/crcommon.cpp +++ b/src/java.base/share/native/libcrcommon/crcommon.cpp @@ -63,14 +63,6 @@ static size_t get_failed_bitmap(crlib_conf_t* conf, const char* name, unsigned c return COMMON(conf)->image_constraints.get_failed_bitmap(name, value_return, value_size); } -static size_t get_bitmap(crlib_conf_t* conf, const char* name, unsigned char* value_return, size_t value_size) { - return COMMON(conf)->image_constraints.get_bitmap(name, value_return, value_size); -} - -static size_t get_label(crlib_conf_t* conf, const char* name, char* value_return, size_t value_size) { - return COMMON(conf)->image_constraints.get_label(name, value_return, value_size); -} - static bool set_score(crlib_conf_t* conf, const char* name, double value) { return COMMON(conf)->image_score.set_score(name, value); } @@ -106,8 +98,6 @@ extern JNIEXPORT crlib_image_constraints_t image_constraints_extension = { require_bitmap, is_failed, get_failed_bitmap, - get_label, - get_bitmap, }; JNIEXPORT bool image_constraints_persist(const crcommon_t* conf, const char* image_location) { From cbb074682c0c44ab0c5be8cfb3ef297bb2be6d56 Mon Sep 17 00:00:00 2001 From: Jan Kratochvil Date: Fri, 24 Jul 2026 18:15:17 +0200 Subject: [PATCH 17/41] Compilation fix #2 --- .../share/include/crlib/crlib_image_constraints.h | 4 ++++ src/hotspot/share/runtime/crac_engine.cpp | 2 +- src/java.base/share/native/libcrcommon/crcommon.cpp | 10 ++++++++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/hotspot/share/include/crlib/crlib_image_constraints.h b/src/hotspot/share/include/crlib/crlib_image_constraints.h index 9f0caa935d6..ecfbcd7df83 100644 --- a/src/hotspot/share/include/crlib/crlib_image_constraints.h +++ b/src/hotspot/share/include/crlib/crlib_image_constraints.h @@ -69,6 +69,10 @@ typedef const struct crlib_image_constraints { // Returns the size of the data, in bytes — it can be more, equal to or less than // 'value_size'. Returned value of 0 represents an error. size_t (*get_failed_bitmap)(crlib_conf_t *, const char *name, unsigned char *value_return, size_t value_size); + + // Like get_failed_bitmap but there is no requirement for a previous failure. + size_t (*get_label)(crlib_conf_t *, const char *image_location, const char *name, char *value_return, size_t value_size); + size_t (*get_bitmap)(crlib_conf_t *, const char *image_location, const char *name, unsigned char *value_return, size_t value_size); } crlib_image_constraints_t; #ifdef __cplusplus diff --git a/src/hotspot/share/runtime/crac_engine.cpp b/src/hotspot/share/runtime/crac_engine.cpp index f2228fcaac3..fe58de01bb1 100644 --- a/src/hotspot/share/runtime/crac_engine.cpp +++ b/src/hotspot/share/runtime/crac_engine.cpp @@ -394,7 +394,7 @@ bool CracEngine::pre_restore() const { return false; } VM_Features features; - size_t features_len = ics->get_bitmap(_conf, cpufeatures_name, reinterpret_cast(&features), sizeof(features)); + size_t features_len = ics->get_bitmap(_conf, _image_location, cpufeatures_name, reinterpret_cast(&features), sizeof(features)); if (features_len != sizeof(features)) { log_error(crac)("Cannot get CPUFeatures for image %s", _image_location); return false; diff --git a/src/java.base/share/native/libcrcommon/crcommon.cpp b/src/java.base/share/native/libcrcommon/crcommon.cpp index 82f0a16666e..5c526098b88 100644 --- a/src/java.base/share/native/libcrcommon/crcommon.cpp +++ b/src/java.base/share/native/libcrcommon/crcommon.cpp @@ -63,6 +63,14 @@ static size_t get_failed_bitmap(crlib_conf_t* conf, const char* name, unsigned c return COMMON(conf)->image_constraints.get_failed_bitmap(name, value_return, value_size); } +static size_t get_label(crlib_conf_t* conf, const char* image_location, const char* name, char* value_return, size_t value_size) { + return COMMON(conf)->image_constraints.get_label(image_location, name, value_return, value_size); +} + +static size_t get_bitmap(crlib_conf_t* conf, const char* image_location, const char* name, unsigned char* value_return, size_t value_size) { + return COMMON(conf)->image_constraints.get_bitmap(image_location, name, value_return, value_size); +} + static bool set_score(crlib_conf_t* conf, const char* name, double value) { return COMMON(conf)->image_score.set_score(name, value); } @@ -98,6 +106,8 @@ extern JNIEXPORT crlib_image_constraints_t image_constraints_extension = { require_bitmap, is_failed, get_failed_bitmap, + get_label, + get_bitmap, }; JNIEXPORT bool image_constraints_persist(const crcommon_t* conf, const char* image_location) { From be48727bf99c4c84c56f97030089b6883db50619 Mon Sep 17 00:00:00 2001 From: Jan Kratochvil Date: Fri, 24 Jul 2026 19:07:40 +0200 Subject: [PATCH 18/41] Fix a race in CPUFeaturesAWS.sh --- test/jdk/jdk/crac/CPUFeatures/CPUFeaturesAWS.sh | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/jdk/jdk/crac/CPUFeatures/CPUFeaturesAWS.sh b/test/jdk/jdk/crac/CPUFeatures/CPUFeaturesAWS.sh index 4d6aeebf74d..138070f5d8f 100755 --- a/test/jdk/jdk/crac/CPUFeatures/CPUFeaturesAWS.sh +++ b/test/jdk/jdk/crac/CPUFeatures/CPUFeaturesAWS.sh @@ -57,6 +57,13 @@ internal_checkpoint() { } internal_restore() { javasetup + tid=$(echo cr/core-*.img|tr -cd ' 0-9'|sed 's/^.* //') # highest + if [ -n "$tid" ];then + ls -l /proc/$tid/exe || : + bash -c 'echo $$' + (set +x;while [ $(bash -c 'echo $$') -le $tid ];do :;done) + bash -c 'echo $$' + fi bin/java -XX:CRaCRestoreFrom=cr $* & p=$! (sleep 2;kill $p) & From 09f983f870d927b6d812a0fb801ace6b2ecc1537 Mon Sep 17 00:00:00 2001 From: Jan Kratochvil Date: Fri, 24 Jul 2026 19:49:07 +0200 Subject: [PATCH 19/41] An unrelated fix for get_failed_bitmap --- src/java.base/share/native/libcrcommon/image_constraints.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/java.base/share/native/libcrcommon/image_constraints.hpp b/src/java.base/share/native/libcrcommon/image_constraints.hpp index ca066289aff..9d9c6bd21c0 100644 --- a/src/java.base/share/native/libcrcommon/image_constraints.hpp +++ b/src/java.base/share/native/libcrcommon/image_constraints.hpp @@ -150,7 +150,7 @@ class ImageConstraints { size_t get_failed_bitmap(const char* name, unsigned char *value_return, size_t value_size) const { size_t result = 0; _constraints.foreach([&](Constraint &c) { - if (!strcmp(c.name, name) && c.failed) { + if (c.type == TagType::BITMAP && !strcmp(c.name, name) && c.failed) { if (c.image_data == nullptr) { result = 0; } else { From 5e060d9fa97e2f845c1a3edb1248f6a78509b4bc Mon Sep 17 00:00:00 2001 From: Jan Kratochvil Date: Fri, 24 Jul 2026 22:05:54 +0200 Subject: [PATCH 20/41] %m fix --- src/java.base/share/native/libcrcommon/image_constraints.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/java.base/share/native/libcrcommon/image_constraints.cpp b/src/java.base/share/native/libcrcommon/image_constraints.cpp index d384d65e67a..190cbc612cc 100644 --- a/src/java.base/share/native/libcrcommon/image_constraints.cpp +++ b/src/java.base/share/native/libcrcommon/image_constraints.cpp @@ -256,12 +256,12 @@ template bool ImageConstraints::load_tags(const char* image_location, CallbackT callback) const { FILE* f = open_tags(image_location, "r"); if (f == nullptr) { - LOG("error opening %s: %m", image_location); + LOG("error opening %s: %s", image_location, strerror(errno)); return false; } load_tags(f, callback); if (fclose(f) != 0) { - LOG("error closing %s: %m", image_location); + LOG("error closing %s: %s", image_location, strerror(errno)); return false; } return true; From 5ea5d93a40d287466b73299e8e40355610ebb611 Mon Sep 17 00:00:00 2001 From: Jan Kratochvil Date: Fri, 24 Jul 2026 22:11:02 +0200 Subject: [PATCH 21/41] Fix secondary arches compilation --- src/hotspot/share/runtime/crac_engine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/share/runtime/crac_engine.cpp b/src/hotspot/share/runtime/crac_engine.cpp index fe58de01bb1..549c0bd474e 100644 --- a/src/hotspot/share/runtime/crac_engine.cpp +++ b/src/hotspot/share/runtime/crac_engine.cpp @@ -393,7 +393,7 @@ bool CracEngine::pre_restore() const { log_error(crac)("Cannot initialize constraints extension for image %s", _image_location); return false; } - VM_Features features; + VM_Version::VM_Features features; size_t features_len = ics->get_bitmap(_conf, _image_location, cpufeatures_name, reinterpret_cast(&features), sizeof(features)); if (features_len != sizeof(features)) { log_error(crac)("Cannot get CPUFeatures for image %s", _image_location); From 9e5927de021e6ee6b9a53fc6eeda8b0ae3673f2a Mon Sep 17 00:00:00 2001 From: Jan Kratochvil Date: Fri, 24 Jul 2026 22:19:25 +0200 Subject: [PATCH 22/41] Fix ups --- src/hotspot/cpu/aarch64/vm_version_aarch64.cpp | 4 ++-- src/hotspot/share/runtime/crac_engine.hpp | 1 - src/java.base/share/native/libcrcommon/image_constraints.cpp | 4 ++-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp index 00dd04999bd..7d5790d4153 100644 --- a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp @@ -956,8 +956,8 @@ bool VM_Version::pre_restore(VM_Features image_features, const char *image_locat ResourceMark rm; VM_Features sve256; sve256.set_feature(CPU_SVE256); - log_error(crac)("Image %s has -XX:CPUFeatures=%s with CPU_SVE256=%s unset, this CPU has CPUFeatures=%s but PR_SVE_SET_VL reports %d: %m", - image_location, image_features.print_numbers(), sve256.print_numbers(), _cpu_features.print_numbers(), got); + log_error(crac)("Image %s has -XX:CPUFeatures=%s with CPU_SVE256=%s unset, this CPU has CPUFeatures=%s but PR_SVE_SET_VL reports %d: %s", + image_location, image_features.print_numbers(), sve256.print_numbers(), _cpu_features.print_numbers(), got, os::strerror(errno)) return false; } return true; diff --git a/src/hotspot/share/runtime/crac_engine.hpp b/src/hotspot/share/runtime/crac_engine.hpp index d3e9d7660c1..c039e203aab 100644 --- a/src/hotspot/share/runtime/crac_engine.hpp +++ b/src/hotspot/share/runtime/crac_engine.hpp @@ -94,7 +94,6 @@ class CracEngine : public CHeapObj { crlib_conf_option_t *_options = nullptr; bool pre_restore() const; - bool pre_restore_core(FILE *f) const; }; #endif // SHARE_RUNTIME_CRAC_ENGINE_HPP diff --git a/src/java.base/share/native/libcrcommon/image_constraints.cpp b/src/java.base/share/native/libcrcommon/image_constraints.cpp index 190cbc612cc..49d1f6ad342 100644 --- a/src/java.base/share/native/libcrcommon/image_constraints.cpp +++ b/src/java.base/share/native/libcrcommon/image_constraints.cpp @@ -259,12 +259,12 @@ bool ImageConstraints::load_tags(const char* image_location, CallbackT callback) LOG("error opening %s: %s", image_location, strerror(errno)); return false; } - load_tags(f, callback); + bool retval = load_tags(f, callback); if (fclose(f) != 0) { LOG("error closing %s: %s", image_location, strerror(errno)); return false; } - return true; + return retval; } bool ImageConstraints::validate(const char* image_location) const { From 205080e8a37fdd03968dbf12566bddbafc6b554e Mon Sep 17 00:00:00 2001 From: Jan Kratochvil Date: Sat, 25 Jul 2026 08:56:14 +0200 Subject: [PATCH 23/41] Fix compilation --- src/hotspot/cpu/aarch64/vm_version_aarch64.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp index 7d5790d4153..06ab4802237 100644 --- a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp @@ -957,7 +957,7 @@ bool VM_Version::pre_restore(VM_Features image_features, const char *image_locat VM_Features sve256; sve256.set_feature(CPU_SVE256); log_error(crac)("Image %s has -XX:CPUFeatures=%s with CPU_SVE256=%s unset, this CPU has CPUFeatures=%s but PR_SVE_SET_VL reports %d: %s", - image_location, image_features.print_numbers(), sve256.print_numbers(), _cpu_features.print_numbers(), got, os::strerror(errno)) + image_location, image_features.print_numbers(), sve256.print_numbers(), _cpu_features.print_numbers(), got, os::strerror(errno)); return false; } return true; From c3d3644c0dccc8c220d3ed66bd8cde21da598eca Mon Sep 17 00:00:00 2001 From: Jan Kratochvil Date: Sun, 26 Jul 2026 17:50:09 +0200 Subject: [PATCH 24/41] get_* -> register_*_hook --- .../include/crlib/crlib_image_constraints.h | 8 +- src/hotspot/share/runtime/crac_engine.cpp | 25 +++-- src/hotspot/share/runtime/crac_engine.hpp | 2 + .../share/native/libcrcommon/crcommon.cpp | 16 ++-- .../native/libcrcommon/image_constraints.cpp | 94 +++++++++---------- .../native/libcrcommon/image_constraints.hpp | 28 +++++- 6 files changed, 101 insertions(+), 72 deletions(-) diff --git a/src/hotspot/share/include/crlib/crlib_image_constraints.h b/src/hotspot/share/include/crlib/crlib_image_constraints.h index ecfbcd7df83..1a72cf0d847 100644 --- a/src/hotspot/share/include/crlib/crlib_image_constraints.h +++ b/src/hotspot/share/include/crlib/crlib_image_constraints.h @@ -70,9 +70,11 @@ typedef const struct crlib_image_constraints { // 'value_size'. Returned value of 0 represents an error. size_t (*get_failed_bitmap)(crlib_conf_t *, const char *name, unsigned char *value_return, size_t value_size); - // Like get_failed_bitmap but there is no requirement for a previous failure. - size_t (*get_label)(crlib_conf_t *, const char *image_location, const char *name, char *value_return, size_t value_size); - size_t (*get_bitmap)(crlib_conf_t *, const char *image_location, const char *name, unsigned char *value_return, size_t value_size); + // Register callbacks before restore. Callbacks are called only during restore. + // If the callback returns false the restore is aborted. + // user_data is an arbitrary pointer value which is passed along. + bool (*register_label_hook)(crlib_conf_t *, const char *name, bool (*hook)(const char *value, void *user_data), void *user_data); + bool (*register_bitmap_hook)(crlib_conf_t *, const char *name, bool (*hook)(const unsigned char *value, size_t value_size, void *user_data), void *user_data); } crlib_image_constraints_t; #ifdef __cplusplus diff --git a/src/hotspot/share/runtime/crac_engine.cpp b/src/hotspot/share/runtime/crac_engine.cpp index 549c0bd474e..daeaab1a5dc 100644 --- a/src/hotspot/share/runtime/crac_engine.cpp +++ b/src/hotspot/share/runtime/crac_engine.cpp @@ -381,6 +381,22 @@ int CracEngine::checkpoint() const { static constexpr char cpuarch_name[] = "cpu.arch"; static constexpr char cpufeatures_name[] = "cpu.features"; +bool CracEngine::pre_restore_bitmap_hook(const unsigned char *value, size_t value_size) const { + VM_Version::VM_Features features; + if (value_size != sizeof(features)) { + log_error(crac)("Invalid CPUFeatures length for image %s - got %zu, want %zu", _image_location, value_size, sizeof(features)); + return false; + } + memcpy(&features, value, value_size); + return VM_Version::pre_restore(features, _image_location); +} + +bool CracEngine::pre_restore_bitmap_hook_trampoline(const unsigned char *value, size_t value_size, void *user_data) { + const CracEngine *self = static_cast(user_data); + + return self->pre_restore_bitmap_hook(value, value_size); +} + bool CracEngine::pre_restore() const { if (!VM_Version::pre_restore_needed) { return true; @@ -393,13 +409,8 @@ bool CracEngine::pre_restore() const { log_error(crac)("Cannot initialize constraints extension for image %s", _image_location); return false; } - VM_Version::VM_Features features; - size_t features_len = ics->get_bitmap(_conf, _image_location, cpufeatures_name, reinterpret_cast(&features), sizeof(features)); - if (features_len != sizeof(features)) { - log_error(crac)("Cannot get CPUFeatures for image %s", _image_location); - return false; - } - return VM_Version::pre_restore(features, _image_location); + void *user_data = const_cast(this); + return ics->register_bitmap_hook(_conf, cpufeatures_name, pre_restore_bitmap_hook_trampoline, user_data); } int CracEngine::restore() const { diff --git a/src/hotspot/share/runtime/crac_engine.hpp b/src/hotspot/share/runtime/crac_engine.hpp index c039e203aab..b792a208079 100644 --- a/src/hotspot/share/runtime/crac_engine.hpp +++ b/src/hotspot/share/runtime/crac_engine.hpp @@ -93,6 +93,8 @@ class CracEngine : public CHeapObj { crlib_conf_option_t *_options = nullptr; + bool pre_restore_bitmap_hook(const unsigned char *value, size_t value_size) const; + static bool pre_restore_bitmap_hook_trampoline(const unsigned char *value, size_t value_size, void *user_data); bool pre_restore() const; }; diff --git a/src/java.base/share/native/libcrcommon/crcommon.cpp b/src/java.base/share/native/libcrcommon/crcommon.cpp index 5c526098b88..baa3b2f4926 100644 --- a/src/java.base/share/native/libcrcommon/crcommon.cpp +++ b/src/java.base/share/native/libcrcommon/crcommon.cpp @@ -63,13 +63,13 @@ static size_t get_failed_bitmap(crlib_conf_t* conf, const char* name, unsigned c return COMMON(conf)->image_constraints.get_failed_bitmap(name, value_return, value_size); } -static size_t get_label(crlib_conf_t* conf, const char* image_location, const char* name, char* value_return, size_t value_size) { - return COMMON(conf)->image_constraints.get_label(image_location, name, value_return, value_size); -} +static bool register_label_hook(crlib_conf_t* conf, const char *name, ImageConstraints::LabelHook hook, void *user_data) { + return COMMON(conf)->image_constraints.register_label_hook(name, hook, user_data); +}; -static size_t get_bitmap(crlib_conf_t* conf, const char* image_location, const char* name, unsigned char* value_return, size_t value_size) { - return COMMON(conf)->image_constraints.get_bitmap(image_location, name, value_return, value_size); -} +static bool register_bitmap_hook(crlib_conf_t* conf, const char *name, ImageConstraints::BitmapHook hook, void *user_data) { + return COMMON(conf)->image_constraints.register_bitmap_hook(name, hook, user_data); +}; static bool set_score(crlib_conf_t* conf, const char* name, double value) { return COMMON(conf)->image_score.set_score(name, value); @@ -106,8 +106,8 @@ extern JNIEXPORT crlib_image_constraints_t image_constraints_extension = { require_bitmap, is_failed, get_failed_bitmap, - get_label, - get_bitmap, + register_label_hook, + register_bitmap_hook, }; JNIEXPORT bool image_constraints_persist(const crcommon_t* conf, const char* image_location) { diff --git a/src/java.base/share/native/libcrcommon/image_constraints.cpp b/src/java.base/share/native/libcrcommon/image_constraints.cpp index 49d1f6ad342..a546d5b089d 100644 --- a/src/java.base/share/native/libcrcommon/image_constraints.cpp +++ b/src/java.base/share/native/libcrcommon/image_constraints.cpp @@ -196,9 +196,17 @@ static void print_bitmap(const char* name, const unsigned char* data, size_t siz fputc('\n', stderr); } -template -bool ImageConstraints::load_tags(FILE *f, CallbackT callback) const { +bool ImageConstraints::validate(const char* image_location) const { + if (_constraints.size() == 0) { + // If there are no constraints don't even try to open the file (it's fine if it is missing) + return true; + } + FILE* f = open_tags(image_location, "r"); + if (f == nullptr) { + return false; + } char line[sizeof(BITMAP_PREFIX) + _MAX_NAME_SIZE + 1 + _MAX_VALUE_SIZE + 2]; + LinkedList tags; while (fgets(line, (int) sizeof(line), f)) { char* eq = strchr((char *) line, '='); char* nl = strchr((char *) (eq + 1), '\n'); @@ -212,7 +220,7 @@ bool ImageConstraints::load_tags(FILE *f, CallbackT callback) const { if (!strncmp(line, LABEL_PREFIX, strlen(LABEL_PREFIX))) { char* name = strdup(line + strlen(LABEL_PREFIX)); char* value = strdup(eq + 1); - if (name == nullptr || value == nullptr || !callback({ TagType::LABEL, name, value, (size_t) (nl - eq) })) { + if (name == nullptr || value == nullptr || !tags.add({ TagType::LABEL, name, value, (size_t) (nl - eq) })) { LOG("Cannot allocate memory for validation"); free(name); free(value); @@ -238,7 +246,7 @@ bool ImageConstraints::load_tags(FILE *f, CallbackT callback) const { return false; } char* name = strdup(line + strlen(BITMAP_PREFIX)); - if (name == nullptr || !callback({ TagType::BITMAP, name, data, length })) { + if (name == nullptr || !tags.add({ TagType::BITMAP, name, data, length })) { LOG("Cannot allocate memory for validation"); free(name); free(data); @@ -249,33 +257,27 @@ bool ImageConstraints::load_tags(FILE *f, CallbackT callback) const { return false; } } - return true; -} - -template -bool ImageConstraints::load_tags(const char* image_location, CallbackT callback) const { - FILE* f = open_tags(image_location, "r"); - if (f == nullptr) { - LOG("error opening %s: %s", image_location, strerror(errno)); - return false; - } - bool retval = load_tags(f, callback); - if (fclose(f) != 0) { - LOG("error closing %s: %s", image_location, strerror(errno)); - return false; - } - return retval; -} - -bool ImageConstraints::validate(const char* image_location) const { - if (_constraints.size() == 0) { - // If there are no constraints don't even try to open the file (it's fine if it is missing) - return true; - } - LinkedList tags; - if (!load_tags(image_location, [&](Tag &&tag) { - return tags.add(std::move(tag)); - })) { + bool hooks_result = true; + _hooks.foreach([&](const Hook& hook) { + tags.foreach([&](const Tag& t) { + if (!hooks_result || strcmp(hook.name, t.name) != 0) { + return; + } + if (t.type != hook.type) { + LOG("Image hook type mismatch for '%s'", hook.name); + return; + } + switch (hook.type) { + case TagType::LABEL: + hooks_result = hook.hook.label_hook(static_cast(t.data), hook.user_data); + break; + case TagType::BITMAP: + hooks_result = hook.hook.bitmap_hook(static_cast(t.data), t.data_size, hook.user_data); + break; + } + }); + }); + if (!hooks_result) { return false; } const char** keys = new(std::nothrow) const char*[tags.size()]; @@ -324,26 +326,18 @@ bool ImageConstraints::validate(const char* image_location) const { return result; } -size_t ImageConstraints::get_any(const char* image_location, const char* name, void *value_return, size_t value_size, ImageConstraints::TagType tagtype) const { - size_t retval = 0; - if (!load_tags(image_location, [&](ImageConstraints::Tag &&tag) { - if (tag.type == tagtype && strcmp(tag.name, name) == 0) { - retval = tag.data_size; - if (value_return) { - memcpy(value_return, tag.data, value_size <= tag.data_size ? value_size : tag.data_size); - } - } - return true; - })) { - return 0; +bool ImageConstraints::register_label_hook(const char *name, LabelHook hook, void *user_data) { + if (!_hooks.add(Hook(name, hook, user_data))) { + LOG("out of memory"); + return false; } - return retval; -} - -size_t ImageConstraints::get_label(const char* image_location, const char* name, char* value_return, size_t value_size) const { - return get_any(image_location, name, value_return, value_size, TagType::LABEL); + return true; } -size_t ImageConstraints::get_bitmap(const char* image_location, const char* name, unsigned char* value_return, size_t value_size) const { - return get_any(image_location, name, value_return, value_size, TagType::BITMAP); +bool ImageConstraints::register_bitmap_hook(const char *name, BitmapHook hook, void *user_data) { + if (!_hooks.add(Hook(name, hook, user_data))) { + LOG("out of memory"); + return false; + } + return true; } diff --git a/src/java.base/share/native/libcrcommon/image_constraints.hpp b/src/java.base/share/native/libcrcommon/image_constraints.hpp index 9d9c6bd21c0..7d2d651bb9f 100644 --- a/src/java.base/share/native/libcrcommon/image_constraints.hpp +++ b/src/java.base/share/native/libcrcommon/image_constraints.hpp @@ -33,6 +33,10 @@ #include "linkedlist.hpp" class ImageConstraints { +public: + using LabelHook = bool (*)(const char *value, void *user_data); + using BitmapHook = bool (*)(const unsigned char *value, size_t value_size, void *user_data); + private: enum class TagType: std::uint8_t { LABEL, @@ -108,8 +112,26 @@ class ImageConstraints { bool compare_bitmaps(const unsigned char* bitmap, size_t length) const; }; + struct Hook { + TagType type; + const char* name; + union U { + LabelHook label_hook; + BitmapHook bitmap_hook; + U(LabelHook h) : label_hook(h) {} + U(BitmapHook h) : bitmap_hook(h) {} + } hook; + void *user_data; + + Hook(const char* n, LabelHook h, void *ud): + type(TagType::LABEL), name(n), hook(h), user_data(ud) {} + Hook(const char* n, BitmapHook h, void *ud): + type(TagType::BITMAP), name(n), hook(h), user_data(ud) {} + }; + LinkedList _tags; LinkedList _constraints; + LinkedList _hooks; static constexpr const size_t _MAX_NAME_SIZE = 256; static constexpr const size_t _MAX_VALUE_SIZE = 256; @@ -121,8 +143,6 @@ class ImageConstraints { template bool load_tags(const char* image_location, CallbackT callback) const; - size_t get_any(const char* image_location, const char* name, void *value_return, size_t value_size, ImageConstraints::TagType tagtype) const; - public: bool set_label(const char* name, const char* value); bool set_bitmap(const char* name, const unsigned char* value, size_t length_bytes); @@ -164,8 +184,8 @@ class ImageConstraints { return result; } - size_t get_label(const char* image_location, const char* name, char* value_return, size_t value_size) const; - size_t get_bitmap(const char* image_location, const char* name, unsigned char* value_return, size_t value_size) const; + bool register_label_hook(const char *name, LabelHook hook, void *user_data); + bool register_bitmap_hook(const char *name, BitmapHook hook, void *user_data); bool persist(const char* image_location) const; bool validate(const char* image_location) const; From 7c8c8276caf854bd80c398c7e124d55583b6c7c1 Mon Sep 17 00:00:00 2001 From: Jan Kratochvil Date: Sun, 26 Jul 2026 18:15:44 +0200 Subject: [PATCH 25/41] fixups --- .../share/include/crlib/crlib_image_constraints.h | 1 + .../share/native/libcrcommon/image_constraints.cpp | 12 +++++++++--- .../share/native/libcrcommon/image_constraints.hpp | 6 +----- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/hotspot/share/include/crlib/crlib_image_constraints.h b/src/hotspot/share/include/crlib/crlib_image_constraints.h index 1a72cf0d847..952611b9e14 100644 --- a/src/hotspot/share/include/crlib/crlib_image_constraints.h +++ b/src/hotspot/share/include/crlib/crlib_image_constraints.h @@ -72,6 +72,7 @@ typedef const struct crlib_image_constraints { // Register callbacks before restore. Callbacks are called only during restore. // If the callback returns false the restore is aborted. + // name is not copied, its content must remain valid. // user_data is an arbitrary pointer value which is passed along. bool (*register_label_hook)(crlib_conf_t *, const char *name, bool (*hook)(const char *value, void *user_data), void *user_data); bool (*register_bitmap_hook)(crlib_conf_t *, const char *name, bool (*hook)(const unsigned char *value, size_t value_size, void *user_data), void *user_data); diff --git a/src/java.base/share/native/libcrcommon/image_constraints.cpp b/src/java.base/share/native/libcrcommon/image_constraints.cpp index a546d5b089d..32b9ed81f7a 100644 --- a/src/java.base/share/native/libcrcommon/image_constraints.cpp +++ b/src/java.base/share/native/libcrcommon/image_constraints.cpp @@ -197,7 +197,7 @@ static void print_bitmap(const char* name, const unsigned char* data, size_t siz } bool ImageConstraints::validate(const char* image_location) const { - if (_constraints.size() == 0) { + if (_constraints.is_empty() && _hooks.is_empty()) { // If there are no constraints don't even try to open the file (it's fine if it is missing) return true; } @@ -259,6 +259,7 @@ bool ImageConstraints::validate(const char* image_location) const { } bool hooks_result = true; _hooks.foreach([&](const Hook& hook) { + bool found = false; tags.foreach([&](const Tag& t) { if (!hooks_result || strcmp(hook.name, t.name) != 0) { return; @@ -267,15 +268,20 @@ bool ImageConstraints::validate(const char* image_location) const { LOG("Image hook type mismatch for '%s'", hook.name); return; } + found = true; switch (hook.type) { case TagType::LABEL: hooks_result = hook.hook.label_hook(static_cast(t.data), hook.user_data); - break; + break; case TagType::BITMAP: hooks_result = hook.hook.bitmap_hook(static_cast(t.data), t.data_size, hook.user_data); - break; + break; } }); + if (!found) { + LOG("Hook did not find its tag '%s'", hook.name); + hooks_result = false; + } }); if (!hooks_result) { return false; diff --git a/src/java.base/share/native/libcrcommon/image_constraints.hpp b/src/java.base/share/native/libcrcommon/image_constraints.hpp index 7d2d651bb9f..9088b1ef1c1 100644 --- a/src/java.base/share/native/libcrcommon/image_constraints.hpp +++ b/src/java.base/share/native/libcrcommon/image_constraints.hpp @@ -138,11 +138,6 @@ class ImageConstraints { bool check_tag(const char* type, const char* name, size_t value_size); - template - bool load_tags(FILE *f, CallbackT callback) const; - template - bool load_tags(const char* image_location, CallbackT callback) const; - public: bool set_label(const char* name, const char* value); bool set_bitmap(const char* name, const unsigned char* value, size_t length_bytes); @@ -184,6 +179,7 @@ class ImageConstraints { return result; } + // name is not copied, its content must remain valid. bool register_label_hook(const char *name, LabelHook hook, void *user_data); bool register_bitmap_hook(const char *name, BitmapHook hook, void *user_data); From 000138ba0458e31de3434b3f4f8c252996a73a5a Mon Sep 17 00:00:00 2001 From: Jan Kratochvil Date: Sun, 26 Jul 2026 18:17:36 +0200 Subject: [PATCH 26/41] Compilation fix --- src/java.base/share/native/libcrcommon/image_constraints.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/java.base/share/native/libcrcommon/image_constraints.cpp b/src/java.base/share/native/libcrcommon/image_constraints.cpp index 32b9ed81f7a..eae8d46ca76 100644 --- a/src/java.base/share/native/libcrcommon/image_constraints.cpp +++ b/src/java.base/share/native/libcrcommon/image_constraints.cpp @@ -197,7 +197,7 @@ static void print_bitmap(const char* name, const unsigned char* data, size_t siz } bool ImageConstraints::validate(const char* image_location) const { - if (_constraints.is_empty() && _hooks.is_empty()) { + if (_constraints.size() == 0 && _hooks.size() == 0) { // If there are no constraints don't even try to open the file (it's fine if it is missing) return true; } From 7eb8b8842283be610966d2feaf08ac940d9e27b0 Mon Sep 17 00:00:00 2001 From: Jan Kratochvil Date: Sun, 26 Jul 2026 22:44:10 +0200 Subject: [PATCH 27/41] Fix the 1st x86_64 testcase regresion --- src/hotspot/share/runtime/crac.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/hotspot/share/runtime/crac.cpp b/src/hotspot/share/runtime/crac.cpp index e3e2428b9e3..c7b23094bb3 100644 --- a/src/hotspot/share/runtime/crac.cpp +++ b/src/hotspot/share/runtime/crac.cpp @@ -328,7 +328,9 @@ 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 && !Abstract_VM_Version::should_skip_cpu_features_check()) { + // should_skip_cpu_features_check() is not valid here as -XX:CheckCPUFeatures=skip + // does not apply for storing of CPUFeatures. + if (_generation == 1 && !VM_Version::check_cpu_features_skip()) { VM_Version::VM_Features current_features; if (VM_Version::cpu_features_binary(¤t_features)) { switch (_engine->prepare_image_constraints_api()) { From fc737cc3520320fa24af5f166c8cb7b9b327645e Mon Sep 17 00:00:00 2001 From: Jan Kratochvil Date: Mon, 27 Jul 2026 08:40:40 +0200 Subject: [PATCH 28/41] Fix aarch64 compilation --- src/hotspot/cpu/aarch64/vm_version_aarch64.hpp | 8 +++----- src/hotspot/cpu/arm/vm_version_arm.hpp | 4 +--- src/hotspot/cpu/ppc/vm_version_ppc.hpp | 4 +--- src/hotspot/cpu/riscv/vm_version_riscv.hpp | 4 +--- src/hotspot/cpu/s390/vm_version_s390.hpp | 4 +--- src/hotspot/cpu/x86/vm_version_x86.hpp | 8 +++----- src/hotspot/cpu/zero/vm_version_zero.hpp | 4 +--- 7 files changed, 11 insertions(+), 25 deletions(-) diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp index e6b0593bac2..7af723e3964 100644 --- a/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp @@ -117,16 +117,14 @@ class VM_Version : public Abstract_VM_Version, public VM_Feature_Flag { // Limit what set_and_get_current_sve_vector_length is willing to set. static void set_maximum_sve_vector_length(int length); - friend bool Abstract_VM_Version::should_skip_cpu_features_check(); - static bool check_cpu_features_skip() { - return _ignore_glibc_not_using; - } - public: // Initialization typedef ::VM_Features VM_Features; static void initialize(); static bool cpu_features_binary(VM_Features *data); + static bool check_cpu_features_skip() { + return _ignore_glibc_not_using; + } static void check_virtualizations(); static VM_Features CPUFeatures_mandatory(); diff --git a/src/hotspot/cpu/arm/vm_version_arm.hpp b/src/hotspot/cpu/arm/vm_version_arm.hpp index 688cb3b9ea1..5bd5301e376 100644 --- a/src/hotspot/cpu/arm/vm_version_arm.hpp +++ b/src/hotspot/cpu/arm/vm_version_arm.hpp @@ -32,9 +32,6 @@ class VM_Version: public Abstract_VM_Version { static bool _has_simd; static bool _has_mp_ext; - friend bool Abstract_VM_Version::should_skip_cpu_features_check(); - static bool check_cpu_features_skip() { return true; } - protected: // Are we done with vm version initialization static bool _is_initialized; @@ -44,6 +41,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 check_cpu_features_skip() { return true; } static const char *restore_failed_check(const VM_Features *image_features, const VM_Features *current_features) { return nullptr; } diff --git a/src/hotspot/cpu/ppc/vm_version_ppc.hpp b/src/hotspot/cpu/ppc/vm_version_ppc.hpp index f6669e6858f..628a2493220 100644 --- a/src/hotspot/cpu/ppc/vm_version_ppc.hpp +++ b/src/hotspot/cpu/ppc/vm_version_ppc.hpp @@ -30,9 +30,6 @@ #include "runtime/globals_extension.hpp" class VM_Version: public Abstract_VM_Version { - friend bool Abstract_VM_Version::should_skip_cpu_features_check(); - static bool check_cpu_features_skip() { return true; } - protected: enum Feature_Flag { mfdscr, @@ -60,6 +57,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 check_cpu_features_skip() { return true; } // Override Abstract_VM_Version implementation static void print_platform_virtualization_info(outputStream*); diff --git a/src/hotspot/cpu/riscv/vm_version_riscv.hpp b/src/hotspot/cpu/riscv/vm_version_riscv.hpp index c0aaa709f47..f5444bc1d6d 100644 --- a/src/hotspot/cpu/riscv/vm_version_riscv.hpp +++ b/src/hotspot/cpu/riscv/vm_version_riscv.hpp @@ -496,15 +496,13 @@ class VM_Version : public Abstract_VM_Version { static void c2_initialize(); #endif // COMPILER2 - friend bool Abstract_VM_Version::should_skip_cpu_features_check(); - static bool check_cpu_features_skip() { return true; } - public: // Initialization static void initialize(); static void initialize_cpu_information(); struct VM_Features: public Zero_Features {}; static bool cpu_features_binary(VM_Features *data) { return false; } + static bool check_cpu_features_skip() { return true; } constexpr static bool supports_stack_watermark_barrier() { return true; } diff --git a/src/hotspot/cpu/s390/vm_version_s390.hpp b/src/hotspot/cpu/s390/vm_version_s390.hpp index 6ed39265ea5..6e523fff13a 100644 --- a/src/hotspot/cpu/s390/vm_version_s390.hpp +++ b/src/hotspot/cpu/s390/vm_version_s390.hpp @@ -31,9 +31,6 @@ #include "runtime/globals_extension.hpp" class VM_Version: public Abstract_VM_Version { - friend bool Abstract_VM_Version::should_skip_cpu_features_check(); - static bool check_cpu_features_skip() { return true; } - protected: // z/Architecture is the name of the 64-bit extension of the 31-bit s390 // architecture. @@ -420,6 +417,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 check_cpu_features_skip() { return true; } // Override Abstract_VM_Version implementation static void print_platform_virtualization_info(outputStream*); diff --git a/src/hotspot/cpu/x86/vm_version_x86.hpp b/src/hotspot/cpu/x86/vm_version_x86.hpp index 9ecf05b8604..4983820cc6a 100644 --- a/src/hotspot/cpu/x86/vm_version_x86.hpp +++ b/src/hotspot/cpu/x86/vm_version_x86.hpp @@ -741,11 +741,6 @@ class VM_Version : public Abstract_VM_Version, protected VM_Feature_Flag { static bool os_supports_apx_egprs(); static void get_processor_features(); - friend bool Abstract_VM_Version::should_skip_cpu_features_check(); - static bool check_cpu_features_skip() { - return _ignore_glibc_not_using; - } - public: // Offsets for cpuid asm stub static ByteSize std_cpuid0_offset() { return byte_offset_of(CpuidInfo, std_max_function); } @@ -822,6 +817,9 @@ class VM_Version : public Abstract_VM_Version, protected VM_Feature_Flag { // Initialization static void initialize(); static bool cpu_features_binary(VM_Features *data); + static bool check_cpu_features_skip() { + return _ignore_glibc_not_using; + } // Override Abstract_VM_Version implementation static void print_platform_virtualization_info(outputStream*); diff --git a/src/hotspot/cpu/zero/vm_version_zero.hpp b/src/hotspot/cpu/zero/vm_version_zero.hpp index f808940605e..d8a01a2d435 100644 --- a/src/hotspot/cpu/zero/vm_version_zero.hpp +++ b/src/hotspot/cpu/zero/vm_version_zero.hpp @@ -30,13 +30,11 @@ #include "runtime/globals_extension.hpp" class VM_Version : public Abstract_VM_Version { - friend bool Abstract_VM_Version::should_skip_cpu_features_check(); - static bool check_cpu_features_skip() { return true; } - public: static void initialize(); struct VM_Features: public Zero_Features {}; static bool cpu_features_binary(VM_Features *data) { return false; } + static bool check_cpu_features_skip() { return true; } static const char *restore_failed_check(const VM_Features *image_features, const VM_Features *current_features) { return nullptr; } From 4c4a201f6aab1c0213630ca4821337983e3d3ce5 Mon Sep 17 00:00:00 2001 From: Jan Kratochvil Date: Tue, 28 Jul 2026 23:30:44 +0200 Subject: [PATCH 29/41] check_cpu_features_skip()->get_cpu_features_ignore() _ignore_glibc_not_using->_cpu_features_ignore --- src/hotspot/cpu/aarch64/vm_version_aarch64.hpp | 6 +++--- src/hotspot/cpu/arm/vm_version_arm.hpp | 2 +- src/hotspot/cpu/ppc/vm_version_ppc.hpp | 2 +- src/hotspot/cpu/riscv/vm_version_riscv.hpp | 2 +- src/hotspot/cpu/s390/vm_version_s390.hpp | 2 +- src/hotspot/cpu/x86/vm_version_x86.hpp | 6 +++--- src/hotspot/cpu/zero/vm_version_zero.hpp | 2 +- src/hotspot/share/runtime/abstract_vm_version.cpp | 2 +- src/hotspot/share/runtime/abstract_vm_version.inline.hpp | 8 ++++---- src/hotspot/share/runtime/crac.cpp | 2 +- 10 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp index 7af723e3964..d5ba0b5c5b5 100644 --- a/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp @@ -122,8 +122,8 @@ class VM_Version : public Abstract_VM_Version, public VM_Feature_Flag { typedef ::VM_Features VM_Features; static void initialize(); static bool cpu_features_binary(VM_Features *data); - static bool check_cpu_features_skip() { - return _ignore_glibc_not_using; + static bool get_cpu_features_ignore() { + return _cpu_features_ignore; } static void check_virtualizations(); @@ -140,7 +140,7 @@ class VM_Version : public Abstract_VM_Version, public VM_Feature_Flag { static constexpr char glibc_prefix[] = ":glibc.cpu.hwcaps="; static constexpr size_t glibc_prefix_len = sizeof(glibc_prefix) - 1; #endif //LINUX - static bool _ignore_glibc_not_using; + static bool _cpu_features_ignore; static void print_using_features_cr(); static void insert_features_names(VM_Version::VM_Features features, outputStream& os); // The returned string needs a ResourceMark. diff --git a/src/hotspot/cpu/arm/vm_version_arm.hpp b/src/hotspot/cpu/arm/vm_version_arm.hpp index 5bd5301e376..6742f99cb99 100644 --- a/src/hotspot/cpu/arm/vm_version_arm.hpp +++ b/src/hotspot/cpu/arm/vm_version_arm.hpp @@ -41,7 +41,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 check_cpu_features_skip() { return true; } + static bool get_cpu_features_ignore() { return true; } static const char *restore_failed_check(const VM_Features *image_features, const VM_Features *current_features) { return nullptr; } diff --git a/src/hotspot/cpu/ppc/vm_version_ppc.hpp b/src/hotspot/cpu/ppc/vm_version_ppc.hpp index 628a2493220..e3d6a4553e7 100644 --- a/src/hotspot/cpu/ppc/vm_version_ppc.hpp +++ b/src/hotspot/cpu/ppc/vm_version_ppc.hpp @@ -57,7 +57,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 check_cpu_features_skip() { return true; } + static bool get_cpu_features_ignore() { return true; } // Override Abstract_VM_Version implementation static void print_platform_virtualization_info(outputStream*); diff --git a/src/hotspot/cpu/riscv/vm_version_riscv.hpp b/src/hotspot/cpu/riscv/vm_version_riscv.hpp index f5444bc1d6d..c9810cc9a61 100644 --- a/src/hotspot/cpu/riscv/vm_version_riscv.hpp +++ b/src/hotspot/cpu/riscv/vm_version_riscv.hpp @@ -502,7 +502,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 check_cpu_features_skip() { return true; } + static bool get_cpu_features_ignore() { return true; } constexpr static bool supports_stack_watermark_barrier() { return true; } diff --git a/src/hotspot/cpu/s390/vm_version_s390.hpp b/src/hotspot/cpu/s390/vm_version_s390.hpp index 6e523fff13a..0d9a8fd4c2d 100644 --- a/src/hotspot/cpu/s390/vm_version_s390.hpp +++ b/src/hotspot/cpu/s390/vm_version_s390.hpp @@ -417,7 +417,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 check_cpu_features_skip() { return true; } + static bool get_cpu_features_ignore() { return true; } // Override Abstract_VM_Version implementation static void print_platform_virtualization_info(outputStream*); diff --git a/src/hotspot/cpu/x86/vm_version_x86.hpp b/src/hotspot/cpu/x86/vm_version_x86.hpp index 4983820cc6a..31ace427bab 100644 --- a/src/hotspot/cpu/x86/vm_version_x86.hpp +++ b/src/hotspot/cpu/x86/vm_version_x86.hpp @@ -726,7 +726,7 @@ class VM_Version : public Abstract_VM_Version, protected VM_Feature_Flag { static constexpr char glibc_prefix[] = ":glibc.cpu.hwcaps="; static constexpr size_t glibc_prefix_len = sizeof(glibc_prefix) - 1; #endif //LINUX - static bool _ignore_glibc_not_using; + static bool _cpu_features_ignore; static void print_using_features_cr(); static void insert_features_names(VM_Version::VM_Features features, outputStream& os); static const char *restore_failed_check(const VM_Features *image_features, const VM_Features *current_features) { @@ -817,8 +817,8 @@ class VM_Version : public Abstract_VM_Version, protected VM_Feature_Flag { // Initialization static void initialize(); static bool cpu_features_binary(VM_Features *data); - static bool check_cpu_features_skip() { - return _ignore_glibc_not_using; + static bool get_cpu_features_ignore() { + return _cpu_features_ignore; } // Override Abstract_VM_Version implementation diff --git a/src/hotspot/cpu/zero/vm_version_zero.hpp b/src/hotspot/cpu/zero/vm_version_zero.hpp index d8a01a2d435..0ada32f38d2 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 check_cpu_features_skip() { return true; } + static bool get_cpu_features_ignore() { return true; } static const char *restore_failed_check(const VM_Features *image_features, const VM_Features *current_features) { return nullptr; } diff --git a/src/hotspot/share/runtime/abstract_vm_version.cpp b/src/hotspot/share/runtime/abstract_vm_version.cpp index bcc8acc8aa7..ffec602b8cc 100644 --- a/src/hotspot/share/runtime/abstract_vm_version.cpp +++ b/src/hotspot/share/runtime/abstract_vm_version.cpp @@ -403,5 +403,5 @@ void Abstract_VM_Version::check_cpufeatures_vmoptions() { } bool Abstract_VM_Version::should_skip_cpu_features_check() { - return VM_Version::check_cpu_features_skip() || (CheckCPUFeatures != nullptr && !strcmp(CheckCPUFeatures, "skip")); + return VM_Version::get_cpu_features_ignore() || (CheckCPUFeatures != nullptr && !strcmp(CheckCPUFeatures, "skip")); } diff --git a/src/hotspot/share/runtime/abstract_vm_version.inline.hpp b/src/hotspot/share/runtime/abstract_vm_version.inline.hpp index 8f710ef642d..98edee904e7 100644 --- a/src/hotspot/share/runtime/abstract_vm_version.inline.hpp +++ b/src/hotspot/share/runtime/abstract_vm_version.inline.hpp @@ -35,7 +35,7 @@ VM_Features VM_Version::CPUFeatures_parse(const char *str) { if (str == nullptr || strcmp(str, "native") == 0) { return _features; } else if (strcmp(str, "ignore") == 0) { - _ignore_glibc_not_using = true; + _cpu_features_ignore = true; return _features; } else if (strcmp(str, "generic") == 0) { return CPUFeatures_generic(); @@ -80,7 +80,7 @@ VM_Features VM_Version::CPUFeatures_parse_numeric(const char *str) { #endif // LINUX } -bool VM_Version::_ignore_glibc_not_using = LINUX_ONLY(false) NOT_LINUX(true); +bool VM_Version::_cpu_features_ignore = LINUX_ONLY(false) NOT_LINUX(true); #ifdef LINUX bool VM_Version::glibc_env_set(char *disable_str) { #define TUNABLES_NAME "GLIBC_TUNABLES" @@ -196,7 +196,7 @@ void VM_Version::glibc_reexec() { // Returns whether we should have got set a GLIBC_TUNABLES environment variables but did not get any. bool VM_Version::glibc_not_using() { - if (_ignore_glibc_not_using) + if (_cpu_features_ignore) return true; VM_Features features_expected; @@ -290,7 +290,7 @@ bool VM_Version::glibc_not_using() { #endif // LINUX void VM_Version::print_using_features_cr() { - if (_ignore_glibc_not_using) { + if (_cpu_features_ignore) { tty->print_raw_cr("CPU features are being kept intact as requested by -XX:CPUFeatures=ignore"); } else { tty->print_raw("CPU features being used are: -XX:CPUFeatures="); diff --git a/src/hotspot/share/runtime/crac.cpp b/src/hotspot/share/runtime/crac.cpp index c7b23094bb3..845dd668d06 100644 --- a/src/hotspot/share/runtime/crac.cpp +++ b/src/hotspot/share/runtime/crac.cpp @@ -330,7 +330,7 @@ int crac::checkpoint_restore(int *shmid) { // cannot change after initial boot (and we don't support switching the engine). // should_skip_cpu_features_check() is not valid here as -XX:CheckCPUFeatures=skip // does not apply for storing of CPUFeatures. - if (_generation == 1 && !VM_Version::check_cpu_features_skip()) { + if (_generation == 1 && !VM_Version::get_cpu_features_ignore()) { VM_Version::VM_Features current_features; if (VM_Version::cpu_features_binary(¤t_features)) { switch (_engine->prepare_image_constraints_api()) { From 0340e7607f90a67546f68bd9b9b4f72c5f836ab4 Mon Sep 17 00:00:00 2001 From: Jan Kratochvil Date: Tue, 28 Jul 2026 23:33:31 +0200 Subject: [PATCH 30/41] Message fix Invalid -> Incompatible Co-authored-by: Timofei Pushkin --- src/hotspot/share/runtime/crac_engine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/share/runtime/crac_engine.cpp b/src/hotspot/share/runtime/crac_engine.cpp index daeaab1a5dc..bd48d949552 100644 --- a/src/hotspot/share/runtime/crac_engine.cpp +++ b/src/hotspot/share/runtime/crac_engine.cpp @@ -384,7 +384,7 @@ static constexpr char cpufeatures_name[] = "cpu.features"; bool CracEngine::pre_restore_bitmap_hook(const unsigned char *value, size_t value_size) const { VM_Version::VM_Features features; if (value_size != sizeof(features)) { - log_error(crac)("Invalid CPUFeatures length for image %s - got %zu, want %zu", _image_location, value_size, sizeof(features)); + log_error(crac)("Incompatible CPUFeatures length in image %s - got %zu, want %zu", _image_location, value_size, sizeof(features)); return false; } memcpy(&features, value, value_size); From 32cf9c8acc9c7ea41d7e79d00056862cdf0e0c6d Mon Sep 17 00:00:00 2001 From: Jan Kratochvil Date: Wed, 29 Jul 2026 00:19:16 +0200 Subject: [PATCH 31/41] Use prepare_image_constraints_api() --- src/hotspot/share/runtime/crac_engine.cpp | 25 +++++++++++++++-------- src/hotspot/share/runtime/crac_engine.hpp | 4 ++-- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/src/hotspot/share/runtime/crac_engine.cpp b/src/hotspot/share/runtime/crac_engine.cpp index bd48d949552..fa4c816ba19 100644 --- a/src/hotspot/share/runtime/crac_engine.cpp +++ b/src/hotspot/share/runtime/crac_engine.cpp @@ -397,23 +397,28 @@ bool CracEngine::pre_restore_bitmap_hook_trampoline(const unsigned char *value, return self->pre_restore_bitmap_hook(value, value_size); } -bool CracEngine::pre_restore() const { +bool CracEngine::pre_restore() { if (!VM_Version::pre_restore_needed) { return true; } if (Abstract_VM_Version::should_skip_cpu_features_check()) { return true; } - crlib_image_constraints_t *ics = CRLIB_EXTENSION_IMAGE_CONSTRAINTS(_api); - if (ics == nullptr) { - log_error(crac)("Cannot initialize constraints extension for image %s", _image_location); - return false; - } - void *user_data = const_cast(this); - return ics->register_bitmap_hook(_conf, cpufeatures_name, pre_restore_bitmap_hook_trampoline, user_data); + switch (prepare_image_constraints_api()) { + case CracEngine::ApiStatus::OK: + break; + case CracEngine::ApiStatus::ERR: + return true; + case CracEngine::ApiStatus::UNSUPPORTED: + log_warning(crac)("Cannot verify CPUFeatures for arch-specific part of restore " + "with the selected CRaC engine"); + return true; + } + void *user_data = this; + return _image_constraints_api->register_bitmap_hook(_conf, cpufeatures_name, pre_restore_bitmap_hook_trampoline, user_data); } -int CracEngine::restore() const { +int CracEngine::restore() { precond(is_initialized()); if (!check_engine(_name, _image_location)) { return -1; @@ -552,6 +557,8 @@ CracEngine::ApiStatus CracEngine::prepare_image_constraints_api() { require_method(require_label) require_method(require_bitmap) require_method(is_failed) + require_method(get_failed_bitmap) + require_method(register_bitmap_hook) complete_extension_api(_image_constraints_api) } diff --git a/src/hotspot/share/runtime/crac_engine.hpp b/src/hotspot/share/runtime/crac_engine.hpp index b792a208079..ce9e1501513 100644 --- a/src/hotspot/share/runtime/crac_engine.hpp +++ b/src/hotspot/share/runtime/crac_engine.hpp @@ -53,7 +53,7 @@ class CracEngine : public CHeapObj { // Operations supported by all engines int checkpoint() const; - int restore() const; + int restore(); bool configure_image_location(const char *image_location); GrowableArrayCHeap *vm_controlled_options() const; @@ -95,7 +95,7 @@ class CracEngine : public CHeapObj { bool pre_restore_bitmap_hook(const unsigned char *value, size_t value_size) const; static bool pre_restore_bitmap_hook_trampoline(const unsigned char *value, size_t value_size, void *user_data); - bool pre_restore() const; + bool pre_restore(); }; #endif // SHARE_RUNTIME_CRAC_ENGINE_HPP From 416e16894ac7d36f6d7ab43aeb2b2c00db7cda96 Mon Sep 17 00:00:00 2001 From: Jan Kratochvil Date: Wed, 29 Jul 2026 00:28:06 +0200 Subject: [PATCH 32/41] rename: CracEngine::pre_restore -> CracEngine::register_constraints_hooks VM_Version::pre_restore -> VM_Version::process_image_cpu_features similar for VM_Version::pre_restore_needed --- src/hotspot/cpu/aarch64/vm_version_aarch64.cpp | 2 +- src/hotspot/cpu/aarch64/vm_version_aarch64.hpp | 4 ++-- src/hotspot/cpu/arm/vm_version_arm.hpp | 4 ++-- src/hotspot/cpu/x86/vm_version_x86.hpp | 4 ++-- src/hotspot/cpu/zero/vm_version_zero.hpp | 4 ++-- src/hotspot/share/runtime/crac_engine.cpp | 8 ++++---- src/hotspot/share/runtime/crac_engine.hpp | 2 +- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp index 06ab4802237..6ed6370a328 100644 --- a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp @@ -932,7 +932,7 @@ void VM_Version::CPUFeatures_apply_arch(VM_Features &parsed, VM_Features &missin missing.clear_feature(CPU_NOTPACA); } -bool VM_Version::pre_restore(VM_Features image_features, const char *image_location) { +bool VM_Version::process_image_cpu_features(VM_Features image_features, const char *image_location) { bool image_supports_sve256 = image_features.supports_feature(CPU_SVE256); if (image_supports_sve256 == _cpu_features.supports_feature(CPU_SVE256)) { return true; diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp index d5ba0b5c5b5..796feafe9f8 100644 --- a/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp @@ -145,8 +145,8 @@ class VM_Version : public Abstract_VM_Version, public VM_Feature_Flag { static void insert_features_names(VM_Version::VM_Features features, outputStream& os); // The returned string needs a ResourceMark. static const char *restore_failed_check(const VM_Features *image_features, const VM_Features *current_features); - static bool pre_restore(VM_Features image_features, const char *image_location); - static constexpr bool pre_restore_needed = true; + static bool process_image_cpu_features(VM_Features image_features, const char *image_location); + static constexpr bool process_image_cpu_features_needed = true; 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 6742f99cb99..da1ab584218 100644 --- a/src/hotspot/cpu/arm/vm_version_arm.hpp +++ b/src/hotspot/cpu/arm/vm_version_arm.hpp @@ -45,10 +45,10 @@ class VM_Version: public Abstract_VM_Version { static const char *restore_failed_check(const VM_Features *image_features, const VM_Features *current_features) { return nullptr; } - static bool pre_restore(VM_Features image_features, const char *image_location) { + static bool process_image_cpu_features(VM_Features image_features, const char *image_location) { return false; } - static constexpr bool pre_restore_needed = false; + static constexpr bool process_image_cpu_features_needed = false; protected: diff --git a/src/hotspot/cpu/x86/vm_version_x86.hpp b/src/hotspot/cpu/x86/vm_version_x86.hpp index 31ace427bab..3896c7691eb 100644 --- a/src/hotspot/cpu/x86/vm_version_x86.hpp +++ b/src/hotspot/cpu/x86/vm_version_x86.hpp @@ -732,10 +732,10 @@ class VM_Version : public Abstract_VM_Version, protected VM_Feature_Flag { static const char *restore_failed_check(const VM_Features *image_features, const VM_Features *current_features) { return nullptr; } - static bool pre_restore(VM_Features image_features, const char *image_location) { + static bool process_image_cpu_features(VM_Features image_features, const char *image_location) { return false; } - static constexpr bool pre_restore_needed = false; + static constexpr bool process_image_cpu_features_needed = false; static bool os_supports_avx_vectors(); static bool os_supports_apx_egprs(); diff --git a/src/hotspot/cpu/zero/vm_version_zero.hpp b/src/hotspot/cpu/zero/vm_version_zero.hpp index 0ada32f38d2..9eef31e0532 100644 --- a/src/hotspot/cpu/zero/vm_version_zero.hpp +++ b/src/hotspot/cpu/zero/vm_version_zero.hpp @@ -38,10 +38,10 @@ class VM_Version : public Abstract_VM_Version { static const char *restore_failed_check(const VM_Features *image_features, const VM_Features *current_features) { return nullptr; } - static bool pre_restore(VM_Features image_features, const char *image_location) { + static bool process_image_cpu_features(VM_Features image_features, const char *image_location) { return false; } - static constexpr bool pre_restore_needed = false; + static constexpr bool process_image_cpu_features_needed = false; constexpr static bool supports_stack_watermark_barrier() { return true; } diff --git a/src/hotspot/share/runtime/crac_engine.cpp b/src/hotspot/share/runtime/crac_engine.cpp index fa4c816ba19..be97358325a 100644 --- a/src/hotspot/share/runtime/crac_engine.cpp +++ b/src/hotspot/share/runtime/crac_engine.cpp @@ -388,7 +388,7 @@ bool CracEngine::pre_restore_bitmap_hook(const unsigned char *value, size_t valu return false; } memcpy(&features, value, value_size); - return VM_Version::pre_restore(features, _image_location); + return VM_Version::process_image_cpu_features(features, _image_location); } bool CracEngine::pre_restore_bitmap_hook_trampoline(const unsigned char *value, size_t value_size, void *user_data) { @@ -397,8 +397,8 @@ bool CracEngine::pre_restore_bitmap_hook_trampoline(const unsigned char *value, return self->pre_restore_bitmap_hook(value, value_size); } -bool CracEngine::pre_restore() { - if (!VM_Version::pre_restore_needed) { +bool CracEngine::register_constraints_hooks() { + if (!VM_Version::process_image_cpu_features_needed) { return true; } if (Abstract_VM_Version::should_skip_cpu_features_check()) { @@ -423,7 +423,7 @@ int CracEngine::restore() { if (!check_engine(_name, _image_location)) { return -1; } - if (!pre_restore()) { + if (!register_constraints_hooks()) { return -1; } return _api->restore(_conf); diff --git a/src/hotspot/share/runtime/crac_engine.hpp b/src/hotspot/share/runtime/crac_engine.hpp index ce9e1501513..78f10be1321 100644 --- a/src/hotspot/share/runtime/crac_engine.hpp +++ b/src/hotspot/share/runtime/crac_engine.hpp @@ -95,7 +95,7 @@ class CracEngine : public CHeapObj { bool pre_restore_bitmap_hook(const unsigned char *value, size_t value_size) const; static bool pre_restore_bitmap_hook_trampoline(const unsigned char *value, size_t value_size, void *user_data); - bool pre_restore(); + bool register_constraints_hooks(); }; #endif // SHARE_RUNTIME_CRAC_ENGINE_HPP From c1253a6bc18770c985754ebe545e1cf3e0001703 Mon Sep 17 00:00:00 2001 From: Jan Kratochvil Date: Wed, 29 Jul 2026 19:51:08 +0200 Subject: [PATCH 33/41] Remove pre_restore_bitmap_hook_trampoline Rename pre_restore_bitmap_hook -> bitmap_constraint_hook --- src/hotspot/cpu/aarch64/vm_version_aarch64.cpp | 10 +++++----- src/hotspot/cpu/aarch64/vm_version_aarch64.hpp | 2 +- src/hotspot/cpu/arm/vm_version_arm.hpp | 2 +- src/hotspot/cpu/x86/vm_version_x86.hpp | 2 +- src/hotspot/cpu/zero/vm_version_zero.hpp | 2 +- src/hotspot/share/runtime/crac_engine.cpp | 15 ++++----------- src/hotspot/share/runtime/crac_engine.hpp | 3 +-- 7 files changed, 14 insertions(+), 22 deletions(-) diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp index 6ed6370a328..1c11d366d17 100644 --- a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp @@ -932,7 +932,7 @@ void VM_Version::CPUFeatures_apply_arch(VM_Features &parsed, VM_Features &missin missing.clear_feature(CPU_NOTPACA); } -bool VM_Version::process_image_cpu_features(VM_Features image_features, const char *image_location) { +bool VM_Version::process_image_cpu_features(VM_Features image_features) { bool image_supports_sve256 = image_features.supports_feature(CPU_SVE256); if (image_supports_sve256 == _cpu_features.supports_feature(CPU_SVE256)) { return true; @@ -945,8 +945,8 @@ bool VM_Version::process_image_cpu_features(VM_Features image_features, const ch VM_Features sve256; sve256.set_feature(CPU_SVE256); VM_Features use = image_features & _cpu_features; - log_error(crac)("Image %s has -XX:CPUFeatures=%s with CPU_SVE256=%s, this CPU has CPUFeatures=%s not supporting CPU_SVE256, use -XX:CPUFeatures=%s during snapshot", - image_location, image_features.print_numbers(), sve256.print_numbers(), _cpu_features.print_numbers(), use.print_numbers()); + log_error(crac)("The image has -XX:CPUFeatures=%s with CPU_SVE256=%s, this CPU has CPUFeatures=%s not supporting CPU_SVE256, use -XX:CPUFeatures=%s during snapshot", + image_features.print_numbers(), sve256.print_numbers(), _cpu_features.print_numbers(), use.print_numbers()); return false; } set_maximum_sve_vector_length(16); @@ -956,8 +956,8 @@ bool VM_Version::process_image_cpu_features(VM_Features image_features, const ch ResourceMark rm; VM_Features sve256; sve256.set_feature(CPU_SVE256); - log_error(crac)("Image %s has -XX:CPUFeatures=%s with CPU_SVE256=%s unset, this CPU has CPUFeatures=%s but PR_SVE_SET_VL reports %d: %s", - image_location, image_features.print_numbers(), sve256.print_numbers(), _cpu_features.print_numbers(), got, os::strerror(errno)); + log_error(crac)("The image %s has -XX:CPUFeatures=%s with CPU_SVE256=%s unset, this CPU has CPUFeatures=%s but PR_SVE_SET_VL reports %d: %s", + image_features.print_numbers(), sve256.print_numbers(), _cpu_features.print_numbers(), got, os::strerror(errno)); return false; } return true; diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp index 796feafe9f8..6369c1a0553 100644 --- a/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp @@ -145,7 +145,7 @@ class VM_Version : public Abstract_VM_Version, public VM_Feature_Flag { static void insert_features_names(VM_Version::VM_Features features, outputStream& os); // The returned string needs a ResourceMark. static const char *restore_failed_check(const VM_Features *image_features, const VM_Features *current_features); - static bool process_image_cpu_features(VM_Features image_features, const char *image_location); + static bool process_image_cpu_features(VM_Features image_features); static constexpr bool process_image_cpu_features_needed = true; 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 da1ab584218..e5f3f6fac3c 100644 --- a/src/hotspot/cpu/arm/vm_version_arm.hpp +++ b/src/hotspot/cpu/arm/vm_version_arm.hpp @@ -45,7 +45,7 @@ class VM_Version: public Abstract_VM_Version { static const char *restore_failed_check(const VM_Features *image_features, const VM_Features *current_features) { return nullptr; } - static bool process_image_cpu_features(VM_Features image_features, const char *image_location) { + static bool process_image_cpu_features(VM_Features image_features) { return false; } static constexpr bool process_image_cpu_features_needed = false; diff --git a/src/hotspot/cpu/x86/vm_version_x86.hpp b/src/hotspot/cpu/x86/vm_version_x86.hpp index 3896c7691eb..3b4ab5340e4 100644 --- a/src/hotspot/cpu/x86/vm_version_x86.hpp +++ b/src/hotspot/cpu/x86/vm_version_x86.hpp @@ -732,7 +732,7 @@ class VM_Version : public Abstract_VM_Version, protected VM_Feature_Flag { static const char *restore_failed_check(const VM_Features *image_features, const VM_Features *current_features) { return nullptr; } - static bool process_image_cpu_features(VM_Features image_features, const char *image_location) { + static bool process_image_cpu_features(VM_Features image_features) { return false; } static constexpr bool process_image_cpu_features_needed = false; diff --git a/src/hotspot/cpu/zero/vm_version_zero.hpp b/src/hotspot/cpu/zero/vm_version_zero.hpp index 9eef31e0532..f2b6a088266 100644 --- a/src/hotspot/cpu/zero/vm_version_zero.hpp +++ b/src/hotspot/cpu/zero/vm_version_zero.hpp @@ -38,7 +38,7 @@ class VM_Version : public Abstract_VM_Version { static const char *restore_failed_check(const VM_Features *image_features, const VM_Features *current_features) { return nullptr; } - static bool process_image_cpu_features(VM_Features image_features, const char *image_location) { + static bool process_image_cpu_features(VM_Features image_features) { return false; } static constexpr bool process_image_cpu_features_needed = false; diff --git a/src/hotspot/share/runtime/crac_engine.cpp b/src/hotspot/share/runtime/crac_engine.cpp index be97358325a..7b5d0c45589 100644 --- a/src/hotspot/share/runtime/crac_engine.cpp +++ b/src/hotspot/share/runtime/crac_engine.cpp @@ -381,20 +381,14 @@ int CracEngine::checkpoint() const { static constexpr char cpuarch_name[] = "cpu.arch"; static constexpr char cpufeatures_name[] = "cpu.features"; -bool CracEngine::pre_restore_bitmap_hook(const unsigned char *value, size_t value_size) const { +bool CracEngine::bitmap_constraint_hook(const unsigned char *value, size_t value_size, void *user_data/*unused*/) { VM_Version::VM_Features features; if (value_size != sizeof(features)) { - log_error(crac)("Incompatible CPUFeatures length in image %s - got %zu, want %zu", _image_location, value_size, sizeof(features)); + log_error(crac)("Incompatible CPUFeatures length in the image - got %zu, want %zu", value_size, sizeof(features)); return false; } memcpy(&features, value, value_size); - return VM_Version::process_image_cpu_features(features, _image_location); -} - -bool CracEngine::pre_restore_bitmap_hook_trampoline(const unsigned char *value, size_t value_size, void *user_data) { - const CracEngine *self = static_cast(user_data); - - return self->pre_restore_bitmap_hook(value, value_size); + return VM_Version::process_image_cpu_features(features); } bool CracEngine::register_constraints_hooks() { @@ -414,8 +408,7 @@ bool CracEngine::register_constraints_hooks() { "with the selected CRaC engine"); return true; } - void *user_data = this; - return _image_constraints_api->register_bitmap_hook(_conf, cpufeatures_name, pre_restore_bitmap_hook_trampoline, user_data); + return _image_constraints_api->register_bitmap_hook(_conf, cpufeatures_name, bitmap_constraint_hook, nullptr /* user_data */); } int CracEngine::restore() { diff --git a/src/hotspot/share/runtime/crac_engine.hpp b/src/hotspot/share/runtime/crac_engine.hpp index 78f10be1321..7ad8904028c 100644 --- a/src/hotspot/share/runtime/crac_engine.hpp +++ b/src/hotspot/share/runtime/crac_engine.hpp @@ -93,8 +93,7 @@ class CracEngine : public CHeapObj { crlib_conf_option_t *_options = nullptr; - bool pre_restore_bitmap_hook(const unsigned char *value, size_t value_size) const; - static bool pre_restore_bitmap_hook_trampoline(const unsigned char *value, size_t value_size, void *user_data); + static bool bitmap_constraint_hook(const unsigned char *value, size_t value_size, void *user_data); bool register_constraints_hooks(); }; From 297ce421b784ae94e67ff22d997f6d03ee4121ec Mon Sep 17 00:00:00 2001 From: Jan Kratochvil Date: Wed, 29 Jul 2026 19:51:57 +0200 Subject: [PATCH 34/41] Rename get_cpu_features_ignore() -> cpu_features_ignore() --- src/hotspot/cpu/aarch64/vm_version_aarch64.hpp | 2 +- src/hotspot/cpu/arm/vm_version_arm.hpp | 2 +- src/hotspot/cpu/ppc/vm_version_ppc.hpp | 2 +- src/hotspot/cpu/riscv/vm_version_riscv.hpp | 2 +- src/hotspot/cpu/s390/vm_version_s390.hpp | 2 +- src/hotspot/cpu/x86/vm_version_x86.hpp | 2 +- src/hotspot/cpu/zero/vm_version_zero.hpp | 2 +- src/hotspot/share/runtime/abstract_vm_version.cpp | 2 +- src/hotspot/share/runtime/crac.cpp | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp index 6369c1a0553..e3125fe39f5 100644 --- a/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp @@ -122,7 +122,7 @@ class VM_Version : public Abstract_VM_Version, public VM_Feature_Flag { typedef ::VM_Features VM_Features; static void initialize(); static bool cpu_features_binary(VM_Features *data); - static bool get_cpu_features_ignore() { + static bool cpu_features_ignore() { return _cpu_features_ignore; } static void check_virtualizations(); diff --git a/src/hotspot/cpu/arm/vm_version_arm.hpp b/src/hotspot/cpu/arm/vm_version_arm.hpp index e5f3f6fac3c..e793ee7f4fc 100644 --- a/src/hotspot/cpu/arm/vm_version_arm.hpp +++ b/src/hotspot/cpu/arm/vm_version_arm.hpp @@ -41,7 +41,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 get_cpu_features_ignore() { return true; } + static bool cpu_features_ignore() { return true; } static const char *restore_failed_check(const VM_Features *image_features, const VM_Features *current_features) { return nullptr; } diff --git a/src/hotspot/cpu/ppc/vm_version_ppc.hpp b/src/hotspot/cpu/ppc/vm_version_ppc.hpp index e3d6a4553e7..0f33741c6d3 100644 --- a/src/hotspot/cpu/ppc/vm_version_ppc.hpp +++ b/src/hotspot/cpu/ppc/vm_version_ppc.hpp @@ -57,7 +57,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 get_cpu_features_ignore() { return true; } + static bool cpu_features_ignore() { return true; } // Override Abstract_VM_Version implementation static void print_platform_virtualization_info(outputStream*); diff --git a/src/hotspot/cpu/riscv/vm_version_riscv.hpp b/src/hotspot/cpu/riscv/vm_version_riscv.hpp index c9810cc9a61..07d409f79f7 100644 --- a/src/hotspot/cpu/riscv/vm_version_riscv.hpp +++ b/src/hotspot/cpu/riscv/vm_version_riscv.hpp @@ -502,7 +502,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 get_cpu_features_ignore() { return true; } + static bool cpu_features_ignore() { return true; } constexpr static bool supports_stack_watermark_barrier() { return true; } diff --git a/src/hotspot/cpu/s390/vm_version_s390.hpp b/src/hotspot/cpu/s390/vm_version_s390.hpp index 0d9a8fd4c2d..b9c9a67a76f 100644 --- a/src/hotspot/cpu/s390/vm_version_s390.hpp +++ b/src/hotspot/cpu/s390/vm_version_s390.hpp @@ -417,7 +417,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 get_cpu_features_ignore() { return true; } + static bool cpu_features_ignore() { return true; } // Override Abstract_VM_Version implementation static void print_platform_virtualization_info(outputStream*); diff --git a/src/hotspot/cpu/x86/vm_version_x86.hpp b/src/hotspot/cpu/x86/vm_version_x86.hpp index 3b4ab5340e4..89db0d97877 100644 --- a/src/hotspot/cpu/x86/vm_version_x86.hpp +++ b/src/hotspot/cpu/x86/vm_version_x86.hpp @@ -817,7 +817,7 @@ class VM_Version : public Abstract_VM_Version, protected VM_Feature_Flag { // Initialization static void initialize(); static bool cpu_features_binary(VM_Features *data); - static bool get_cpu_features_ignore() { + static bool cpu_features_ignore() { return _cpu_features_ignore; } diff --git a/src/hotspot/cpu/zero/vm_version_zero.hpp b/src/hotspot/cpu/zero/vm_version_zero.hpp index f2b6a088266..9ef24511c72 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 get_cpu_features_ignore() { return true; } + static bool cpu_features_ignore() { return true; } static const char *restore_failed_check(const VM_Features *image_features, const VM_Features *current_features) { return nullptr; } diff --git a/src/hotspot/share/runtime/abstract_vm_version.cpp b/src/hotspot/share/runtime/abstract_vm_version.cpp index ffec602b8cc..1cf1a16cde3 100644 --- a/src/hotspot/share/runtime/abstract_vm_version.cpp +++ b/src/hotspot/share/runtime/abstract_vm_version.cpp @@ -403,5 +403,5 @@ void Abstract_VM_Version::check_cpufeatures_vmoptions() { } bool Abstract_VM_Version::should_skip_cpu_features_check() { - return VM_Version::get_cpu_features_ignore() || (CheckCPUFeatures != nullptr && !strcmp(CheckCPUFeatures, "skip")); + return VM_Version::cpu_features_ignore() || (CheckCPUFeatures != nullptr && !strcmp(CheckCPUFeatures, "skip")); } diff --git a/src/hotspot/share/runtime/crac.cpp b/src/hotspot/share/runtime/crac.cpp index 845dd668d06..15a7aa20aa1 100644 --- a/src/hotspot/share/runtime/crac.cpp +++ b/src/hotspot/share/runtime/crac.cpp @@ -330,7 +330,7 @@ int crac::checkpoint_restore(int *shmid) { // cannot change after initial boot (and we don't support switching the engine). // should_skip_cpu_features_check() is not valid here as -XX:CheckCPUFeatures=skip // does not apply for storing of CPUFeatures. - if (_generation == 1 && !VM_Version::get_cpu_features_ignore()) { + if (_generation == 1 && !VM_Version::cpu_features_ignore()) { VM_Version::VM_Features current_features; if (VM_Version::cpu_features_binary(¤t_features)) { switch (_engine->prepare_image_constraints_api()) { From d41700778241fa5d5eafc2032360380108476ef3 Mon Sep 17 00:00:00 2001 From: Jan Kratochvil Date: Wed, 29 Jul 2026 19:58:33 +0200 Subject: [PATCH 35/41] Inline should_skip_cpu_features_check() --- src/hotspot/share/runtime/crac.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hotspot/share/runtime/crac.cpp b/src/hotspot/share/runtime/crac.cpp index 15a7aa20aa1..bc8221131dd 100644 --- a/src/hotspot/share/runtime/crac.cpp +++ b/src/hotspot/share/runtime/crac.cpp @@ -875,12 +875,12 @@ void crac::restore(crac_restore_data& restore_data) { // Since the check itself is delegated to the C/R Engine we will simply // skip the check here. - bool ignore = Abstract_VM_Version::should_skip_cpu_features_check(); + bool ignore = VM_Version::cpu_features_ignore(); bool exact = false; if (CheckCPUFeatures == nullptr || !strcmp(CheckCPUFeatures, "compatible")) { // default, compatible } else if (!strcmp(CheckCPUFeatures, "skip")) { - assert(ignore, "Abstract_VM_Version::should_skip_cpu_features_check() has checked it"); + ignore = true; } else if (!strcmp(CheckCPUFeatures, "exact")) { exact = true; } else { From 8b6f0af604dffa7cce194f5d41a5d1c8111297dc Mon Sep 17 00:00:00 2001 From: Jan Kratochvil Date: Wed, 29 Jul 2026 21:00:00 +0200 Subject: [PATCH 36/41] Fix aarch64 compilation --- src/hotspot/cpu/aarch64/vm_version_aarch64.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp index 1c11d366d17..2404e83c4c6 100644 --- a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp @@ -956,7 +956,7 @@ bool VM_Version::process_image_cpu_features(VM_Features image_features) { ResourceMark rm; VM_Features sve256; sve256.set_feature(CPU_SVE256); - log_error(crac)("The image %s has -XX:CPUFeatures=%s with CPU_SVE256=%s unset, this CPU has CPUFeatures=%s but PR_SVE_SET_VL reports %d: %s", + log_error(crac)("The image has -XX:CPUFeatures=%s with CPU_SVE256=%s unset, this CPU has CPUFeatures=%s but PR_SVE_SET_VL reports %d: %s", image_features.print_numbers(), sve256.print_numbers(), _cpu_features.print_numbers(), got, os::strerror(errno)); return false; } From 6473fb26865063e23a4f2a9edeb9bbc36ed99a84 Mon Sep 17 00:00:00 2001 From: Jan Kratochvil Date: Wed, 29 Jul 2026 22:15:56 +0200 Subject: [PATCH 37/41] cpu_features_ignore() -> !can_use_cpu_features() should_skip_cpu_features_check() -> !should_check_cpu_features() --- src/hotspot/cpu/aarch64/vm_version_aarch64.cpp | 2 +- src/hotspot/cpu/aarch64/vm_version_aarch64.hpp | 6 +++--- src/hotspot/cpu/arm/vm_version_arm.hpp | 2 +- src/hotspot/cpu/ppc/vm_version_ppc.hpp | 2 +- src/hotspot/cpu/riscv/vm_version_riscv.hpp | 2 +- src/hotspot/cpu/s390/vm_version_s390.hpp | 2 +- src/hotspot/cpu/x86/vm_version_x86.hpp | 6 +++--- src/hotspot/cpu/zero/vm_version_zero.hpp | 2 +- src/hotspot/share/runtime/abstract_vm_version.cpp | 4 ++-- src/hotspot/share/runtime/abstract_vm_version.hpp | 2 +- src/hotspot/share/runtime/crac.cpp | 6 +++--- src/hotspot/share/runtime/crac_engine.cpp | 2 +- 12 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp index 2404e83c4c6..7459a766b24 100644 --- a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp @@ -938,7 +938,7 @@ bool VM_Version::process_image_cpu_features(VM_Features image_features) { return true; } if (image_supports_sve256 && !_cpu_features.supports_feature(CPU_SVE256)) { - if (Abstract_VM_Version::should_skip_cpu_features_check()) { + if (!Abstract_VM_Version::should_check_cpu_features()) { return true; } ResourceMark rm; diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp index e3125fe39f5..b38c3c5bdb3 100644 --- a/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp @@ -122,8 +122,9 @@ class VM_Version : public Abstract_VM_Version, public VM_Feature_Flag { typedef ::VM_Features VM_Features; static void initialize(); static bool cpu_features_binary(VM_Features *data); - static bool cpu_features_ignore() { - return _cpu_features_ignore; + static bool _cpu_features_ignore; + static bool can_use_cpu_features() { + return !_cpu_features_ignore; } static void check_virtualizations(); @@ -140,7 +141,6 @@ class VM_Version : public Abstract_VM_Version, public VM_Feature_Flag { static constexpr char glibc_prefix[] = ":glibc.cpu.hwcaps="; static constexpr size_t glibc_prefix_len = sizeof(glibc_prefix) - 1; #endif //LINUX - static bool _cpu_features_ignore; static void print_using_features_cr(); static void insert_features_names(VM_Version::VM_Features features, outputStream& os); // The returned string needs a ResourceMark. diff --git a/src/hotspot/cpu/arm/vm_version_arm.hpp b/src/hotspot/cpu/arm/vm_version_arm.hpp index e793ee7f4fc..c15b446d442 100644 --- a/src/hotspot/cpu/arm/vm_version_arm.hpp +++ b/src/hotspot/cpu/arm/vm_version_arm.hpp @@ -41,7 +41,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 cpu_features_ignore() { return true; } + static bool can_use_cpu_features() { return false; } static const char *restore_failed_check(const VM_Features *image_features, const VM_Features *current_features) { return nullptr; } diff --git a/src/hotspot/cpu/ppc/vm_version_ppc.hpp b/src/hotspot/cpu/ppc/vm_version_ppc.hpp index 0f33741c6d3..5d3f015fc3d 100644 --- a/src/hotspot/cpu/ppc/vm_version_ppc.hpp +++ b/src/hotspot/cpu/ppc/vm_version_ppc.hpp @@ -57,7 +57,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 cpu_features_ignore() { return true; } + static bool can_use_cpu_features() { return false; } // Override Abstract_VM_Version implementation static void print_platform_virtualization_info(outputStream*); diff --git a/src/hotspot/cpu/riscv/vm_version_riscv.hpp b/src/hotspot/cpu/riscv/vm_version_riscv.hpp index 07d409f79f7..11d1c0e0ba9 100644 --- a/src/hotspot/cpu/riscv/vm_version_riscv.hpp +++ b/src/hotspot/cpu/riscv/vm_version_riscv.hpp @@ -502,7 +502,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 cpu_features_ignore() { return true; } + static bool can_use_cpu_features() { return false; } constexpr static bool supports_stack_watermark_barrier() { return true; } diff --git a/src/hotspot/cpu/s390/vm_version_s390.hpp b/src/hotspot/cpu/s390/vm_version_s390.hpp index b9c9a67a76f..c0a073f3f85 100644 --- a/src/hotspot/cpu/s390/vm_version_s390.hpp +++ b/src/hotspot/cpu/s390/vm_version_s390.hpp @@ -417,7 +417,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 cpu_features_ignore() { return true; } + static bool can_use_cpu_features() { return false; } // Override Abstract_VM_Version implementation static void print_platform_virtualization_info(outputStream*); diff --git a/src/hotspot/cpu/x86/vm_version_x86.hpp b/src/hotspot/cpu/x86/vm_version_x86.hpp index 89db0d97877..1884ed029f4 100644 --- a/src/hotspot/cpu/x86/vm_version_x86.hpp +++ b/src/hotspot/cpu/x86/vm_version_x86.hpp @@ -726,7 +726,6 @@ class VM_Version : public Abstract_VM_Version, protected VM_Feature_Flag { static constexpr char glibc_prefix[] = ":glibc.cpu.hwcaps="; static constexpr size_t glibc_prefix_len = sizeof(glibc_prefix) - 1; #endif //LINUX - static bool _cpu_features_ignore; static void print_using_features_cr(); static void insert_features_names(VM_Version::VM_Features features, outputStream& os); static const char *restore_failed_check(const VM_Features *image_features, const VM_Features *current_features) { @@ -817,8 +816,9 @@ class VM_Version : public Abstract_VM_Version, protected VM_Feature_Flag { // Initialization static void initialize(); static bool cpu_features_binary(VM_Features *data); - static bool cpu_features_ignore() { - return _cpu_features_ignore; + static bool _cpu_features_ignore; + static bool can_use_cpu_features() { + return !_cpu_features_ignore; } // Override Abstract_VM_Version implementation diff --git a/src/hotspot/cpu/zero/vm_version_zero.hpp b/src/hotspot/cpu/zero/vm_version_zero.hpp index 9ef24511c72..93b3fb1d834 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 cpu_features_ignore() { return true; } + static bool can_use_cpu_features() { return false; } static const char *restore_failed_check(const VM_Features *image_features, const VM_Features *current_features) { return nullptr; } diff --git a/src/hotspot/share/runtime/abstract_vm_version.cpp b/src/hotspot/share/runtime/abstract_vm_version.cpp index 1cf1a16cde3..3e39a8622e6 100644 --- a/src/hotspot/share/runtime/abstract_vm_version.cpp +++ b/src/hotspot/share/runtime/abstract_vm_version.cpp @@ -402,6 +402,6 @@ void Abstract_VM_Version::check_cpufeatures_vmoptions() { } } -bool Abstract_VM_Version::should_skip_cpu_features_check() { - return VM_Version::cpu_features_ignore() || (CheckCPUFeatures != nullptr && !strcmp(CheckCPUFeatures, "skip")); +bool Abstract_VM_Version::should_check_cpu_features() { + return VM_Version::can_use_cpu_features() && (CheckCPUFeatures == nullptr || strcmp(CheckCPUFeatures, "skip") != 0); } diff --git a/src/hotspot/share/runtime/abstract_vm_version.hpp b/src/hotspot/share/runtime/abstract_vm_version.hpp index 8e420edea11..7c5af8d0f4d 100644 --- a/src/hotspot/share/runtime/abstract_vm_version.hpp +++ b/src/hotspot/share/runtime/abstract_vm_version.hpp @@ -269,7 +269,7 @@ class Abstract_VM_Version: AllStatic { // features_buffer is an opaque object that stores arch specific representation of cpu features static bool verify_aot_code_cache_features(void* features_buffer) { return false; }; - static bool should_skip_cpu_features_check(); + static bool should_check_cpu_features(); }; #endif // SHARE_RUNTIME_ABSTRACT_VM_VERSION_HPP diff --git a/src/hotspot/share/runtime/crac.cpp b/src/hotspot/share/runtime/crac.cpp index bc8221131dd..7f46a5c7402 100644 --- a/src/hotspot/share/runtime/crac.cpp +++ b/src/hotspot/share/runtime/crac.cpp @@ -328,9 +328,9 @@ 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). - // should_skip_cpu_features_check() is not valid here as -XX:CheckCPUFeatures=skip + // should_check_cpu_features() is not valid here as -XX:CheckCPUFeatures=skip // does not apply for storing of CPUFeatures. - if (_generation == 1 && !VM_Version::cpu_features_ignore()) { + if (_generation == 1 && VM_Version::can_use_cpu_features()) { VM_Version::VM_Features current_features; if (VM_Version::cpu_features_binary(¤t_features)) { switch (_engine->prepare_image_constraints_api()) { @@ -875,7 +875,7 @@ void crac::restore(crac_restore_data& restore_data) { // Since the check itself is delegated to the C/R Engine we will simply // skip the check here. - bool ignore = VM_Version::cpu_features_ignore(); + bool ignore = !VM_Version::can_use_cpu_features(); bool exact = false; if (CheckCPUFeatures == nullptr || !strcmp(CheckCPUFeatures, "compatible")) { // default, compatible diff --git a/src/hotspot/share/runtime/crac_engine.cpp b/src/hotspot/share/runtime/crac_engine.cpp index 7b5d0c45589..4f3dca1293f 100644 --- a/src/hotspot/share/runtime/crac_engine.cpp +++ b/src/hotspot/share/runtime/crac_engine.cpp @@ -395,7 +395,7 @@ bool CracEngine::register_constraints_hooks() { if (!VM_Version::process_image_cpu_features_needed) { return true; } - if (Abstract_VM_Version::should_skip_cpu_features_check()) { + if (!Abstract_VM_Version::should_check_cpu_features()) { return true; } switch (prepare_image_constraints_api()) { From 667defa2859a6f7916db4f127e929c9e75d3cdb1 Mon Sep 17 00:00:00 2001 From: Jan Kratochvil Date: Wed, 29 Jul 2026 22:25:08 +0200 Subject: [PATCH 38/41] Fix vec128/256 for image selection --- .../cpu/aarch64/vm_version_aarch64.cpp | 22 ++++++++++++------- .../cpu/aarch64/vm_version_aarch64.hpp | 2 +- .../bsd_aarch64/vm_version_bsd_aarch64.cpp | 3 ++- .../vm_version_linux_aarch64.cpp | 4 +++- .../vm_version_windows_aarch64.cpp | 3 ++- 5 files changed, 22 insertions(+), 12 deletions(-) diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp index 7459a766b24..91e0514e214 100644 --- a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp @@ -933,11 +933,11 @@ void VM_Version::CPUFeatures_apply_arch(VM_Features &parsed, VM_Features &missin } bool VM_Version::process_image_cpu_features(VM_Features image_features) { + int want; bool image_supports_sve256 = image_features.supports_feature(CPU_SVE256); if (image_supports_sve256 == _cpu_features.supports_feature(CPU_SVE256)) { - return true; - } - if (image_supports_sve256 && !_cpu_features.supports_feature(CPU_SVE256)) { + want = 32; + } else if (image_supports_sve256 && !_cpu_features.supports_feature(CPU_SVE256)) { if (!Abstract_VM_Version::should_check_cpu_features()) { return true; } @@ -948,16 +948,22 @@ bool VM_Version::process_image_cpu_features(VM_Features image_features) { log_error(crac)("The image has -XX:CPUFeatures=%s with CPU_SVE256=%s, this CPU has CPUFeatures=%s not supporting CPU_SVE256, use -XX:CPUFeatures=%s during snapshot", image_features.print_numbers(), sve256.print_numbers(), _cpu_features.print_numbers(), use.print_numbers()); return false; + } else { + want = 16; + } + if (set_maximum_sve_vector_length(want) == want) { + return true; } - set_maximum_sve_vector_length(16); errno = 0; - int got = set_and_get_current_sve_vector_length(16); - if (got != 16) { + int got = set_and_get_current_sve_vector_length(want); + if (got != want) { ResourceMark rm; VM_Features sve256; sve256.set_feature(CPU_SVE256); - log_error(crac)("The image has -XX:CPUFeatures=%s with CPU_SVE256=%s unset, this CPU has CPUFeatures=%s but PR_SVE_SET_VL reports %d: %s", - image_features.print_numbers(), sve256.print_numbers(), _cpu_features.print_numbers(), got, os::strerror(errno)); + log_error(crac)("The image has -XX:CPUFeatures=%s with CPU_SVE256=%s %s, this CPU has CPUFeatures=%s but PR_SVE_SET_VL reports %d: %s", + image_features.print_numbers(), sve256.print_numbers(), + want == 32 ? "set" : "unset", + _cpu_features.print_numbers(), got, os::strerror(errno)); return false; } return true; diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp index b38c3c5bdb3..04631cf0436 100644 --- a/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp @@ -115,7 +115,7 @@ class VM_Version : public Abstract_VM_Version, public VM_Feature_Flag { static int set_and_get_current_sve_vector_length(int len); static int get_current_sve_vector_length(); // Limit what set_and_get_current_sve_vector_length is willing to set. - static void set_maximum_sve_vector_length(int length); + static int set_maximum_sve_vector_length(int length); public: // Initialization diff --git a/src/hotspot/os_cpu/bsd_aarch64/vm_version_bsd_aarch64.cpp b/src/hotspot/os_cpu/bsd_aarch64/vm_version_bsd_aarch64.cpp index 6d965e8a5bb..253998ad46d 100644 --- a/src/hotspot/os_cpu/bsd_aarch64/vm_version_bsd_aarch64.cpp +++ b/src/hotspot/os_cpu/bsd_aarch64/vm_version_bsd_aarch64.cpp @@ -35,8 +35,9 @@ int VM_Version::get_current_sve_vector_length() { return -1; } -void VM_Version::set_maximum_sve_vector_length(int length) { +int VM_Version::set_maximum_sve_vector_length(int length) { ShouldNotCallThis(); + return length; } int VM_Version::set_and_get_current_sve_vector_length(int length) { diff --git a/src/hotspot/os_cpu/linux_aarch64/vm_version_linux_aarch64.cpp b/src/hotspot/os_cpu/linux_aarch64/vm_version_linux_aarch64.cpp index 6e410c1a647..9667c351af0 100644 --- a/src/hotspot/os_cpu/linux_aarch64/vm_version_linux_aarch64.cpp +++ b/src/hotspot/os_cpu/linux_aarch64/vm_version_linux_aarch64.cpp @@ -123,8 +123,10 @@ int VM_Version::get_current_sve_vector_length() { static int maximum_sve_vector_length = INT_MAX; -void VM_Version::set_maximum_sve_vector_length(int length) { +int VM_Version::set_maximum_sve_vector_length(int length) { + int retval = maximum_sve_vector_length; maximum_sve_vector_length = length; + return retval; } int VM_Version::set_and_get_current_sve_vector_length(int length) { diff --git a/src/hotspot/os_cpu/windows_aarch64/vm_version_windows_aarch64.cpp b/src/hotspot/os_cpu/windows_aarch64/vm_version_windows_aarch64.cpp index b13419fc609..e08a2a10e2d 100644 --- a/src/hotspot/os_cpu/windows_aarch64/vm_version_windows_aarch64.cpp +++ b/src/hotspot/os_cpu/windows_aarch64/vm_version_windows_aarch64.cpp @@ -61,9 +61,10 @@ int VM_Version::get_current_sve_vector_length() { return VM_Version::supports_sve() ? get_sve_vector_length() : 0; } -void VM_Version::set_maximum_sve_vector_length(int length) { +int VM_Version::set_maximum_sve_vector_length(int length) { // CPU_SVE256 cannot be set on Windows. ShouldNotCallThis(); + return length; } int VM_Version::set_and_get_current_sve_vector_length(int length) { From a78f4a3c7eab3e4b1db5ab81e25b031e9c3df1ec Mon Sep 17 00:00:00 2001 From: Jan Kratochvil Date: Thu, 30 Jul 2026 00:59:31 +0200 Subject: [PATCH 39/41] Fix aarch64 multiple images selection --- src/hotspot/cpu/aarch64/vm_version_aarch64.cpp | 13 +++++++------ .../linux_aarch64/vm_version_linux_aarch64.cpp | 2 +- test/jdk/jdk/crac/CPUFeatures/CPUFeaturesAWS.sh | 2 +- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp index 91e0514e214..df90e735bfa 100644 --- a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp @@ -933,11 +933,8 @@ void VM_Version::CPUFeatures_apply_arch(VM_Features &parsed, VM_Features &missin } bool VM_Version::process_image_cpu_features(VM_Features image_features) { - int want; bool image_supports_sve256 = image_features.supports_feature(CPU_SVE256); - if (image_supports_sve256 == _cpu_features.supports_feature(CPU_SVE256)) { - want = 32; - } else if (image_supports_sve256 && !_cpu_features.supports_feature(CPU_SVE256)) { + if (image_supports_sve256 && !_cpu_features.supports_feature(CPU_SVE256)) { if (!Abstract_VM_Version::should_check_cpu_features()) { return true; } @@ -948,12 +945,16 @@ bool VM_Version::process_image_cpu_features(VM_Features image_features) { log_error(crac)("The image has -XX:CPUFeatures=%s with CPU_SVE256=%s, this CPU has CPUFeatures=%s not supporting CPU_SVE256, use -XX:CPUFeatures=%s during snapshot", image_features.print_numbers(), sve256.print_numbers(), _cpu_features.print_numbers(), use.print_numbers()); return false; - } else { - want = 16; } + int want = image_supports_sve256 ? 32 : 16; if (set_maximum_sve_vector_length(want) == want) { return true; } + if (!_cpu_features.supports_feature(CPU_SVE)) { + guarantee(want == 16, "CPU_SVE256 cannot be present without CPU_SVE"); + return true; + } + // Always call PR_SVE_SET_VL, we do not know who did execute this JVM. errno = 0; int got = set_and_get_current_sve_vector_length(want); if (got != want) { diff --git a/src/hotspot/os_cpu/linux_aarch64/vm_version_linux_aarch64.cpp b/src/hotspot/os_cpu/linux_aarch64/vm_version_linux_aarch64.cpp index 9667c351af0..f1b577fe098 100644 --- a/src/hotspot/os_cpu/linux_aarch64/vm_version_linux_aarch64.cpp +++ b/src/hotspot/os_cpu/linux_aarch64/vm_version_linux_aarch64.cpp @@ -130,7 +130,7 @@ int VM_Version::set_maximum_sve_vector_length(int length) { } int VM_Version::set_and_get_current_sve_vector_length(int length) { - assert(VM_Version::supports_sve(), "should not call this"); + assert(_cpu_features.supports_feature(CPU_SVE), "should not call this"); int new_length = prctl(PR_SVE_SET_VL, MIN2(length, maximum_sve_vector_length)); return new_length; } diff --git a/test/jdk/jdk/crac/CPUFeatures/CPUFeaturesAWS.sh b/test/jdk/jdk/crac/CPUFeatures/CPUFeaturesAWS.sh index 138070f5d8f..330ad22efbd 100755 --- a/test/jdk/jdk/crac/CPUFeatures/CPUFeaturesAWS.sh +++ b/test/jdk/jdk/crac/CPUFeatures/CPUFeaturesAWS.sh @@ -354,7 +354,7 @@ checkpoint_restore "$LINENO" t4g.micro a1.medium "-1:LSE (0x100) cannot be disab checkpoint_restore "$LINENO" c7g.medium c7g.medium checkpoint_restore "$LINENO" c8g.medium c8g.medium -checkpoint_restore "$LINENO" c7g.medium c8g.medium "1:Image cr has -XX:CPUFeatures=0x4000000000017fff with CPU_SVE256=0x4000000000000000, this CPU has CPUFeatures=0x77fff not supporting CPU_SVE256, use -XX:CPUFeatures=0x17fff during snapshot" +checkpoint_restore "$LINENO" c7g.medium c8g.medium "1:The image has -XX:CPUFeatures=0x4000000000017fff with CPU_SVE256=0x4000000000000000, this CPU has CPUFeatures=0x77fff not supporting CPU_SVE256, use -XX:CPUFeatures=0x17fff during snapshot" checkpoint_restore "$LINENO" c7g.medium c8g.medium "" "-XX:CPUFeatures=0x17fff" "" checkpoint_restore "$LINENO" c8g.medium c7g.medium "1:Restore failed due to incompatible or missing CPU features, try using -XX:CPUFeatures=0x17fff on checkpoint." checkpoint_restore "$LINENO" c8g.medium c7g.medium "" "-XX:CPUFeatures=0x17fff" "" From 28104d118b3b7e372efe58ca8b4adbe88de2743d Mon Sep 17 00:00:00 2001 From: Jan Kratochvil Date: Thu, 30 Jul 2026 02:25:32 +0200 Subject: [PATCH 40/41] +restore_cpuinfo() --- .../cpu/aarch64/vm_version_aarch64.cpp | 49 +++++++++----- .../cpu/aarch64/vm_version_aarch64.hpp | 2 +- src/hotspot/cpu/arm/vm_version_arm.hpp | 2 +- src/hotspot/cpu/x86/vm_version_x86.hpp | 2 +- src/hotspot/cpu/zero/vm_version_zero.hpp | 2 +- src/hotspot/share/runtime/crac.cpp | 19 +++++- src/hotspot/share/runtime/crac_engine.cpp | 66 ++++++++----------- src/hotspot/share/runtime/crac_engine.hpp | 6 +- 8 files changed, 84 insertions(+), 64 deletions(-) diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp index df90e735bfa..ff4f7440a6b 100644 --- a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp @@ -932,21 +932,28 @@ void VM_Version::CPUFeatures_apply_arch(VM_Features &parsed, VM_Features &missin missing.clear_feature(CPU_NOTPACA); } -bool VM_Version::process_image_cpu_features(VM_Features image_features) { - bool image_supports_sve256 = image_features.supports_feature(CPU_SVE256); - if (image_supports_sve256 && !_cpu_features.supports_feature(CPU_SVE256)) { - if (!Abstract_VM_Version::should_check_cpu_features()) { - return true; +bool VM_Version::process_image_cpu_features(const VM_Features *image_featuresp) { + int want; + if (image_featuresp == nullptr) { + // Cleanup after a failed restore. + want = supports_feature(CPU_SVE256) ? 32 : 16; + } else { + const VM_Features &image_features = *image_featuresp; + bool image_supports_sve256 = image_features.supports_feature(CPU_SVE256); + if (image_supports_sve256 && !_cpu_features.supports_feature(CPU_SVE256)) { + if (!Abstract_VM_Version::should_check_cpu_features()) { + return true; + } + ResourceMark rm; + VM_Features sve256; + sve256.set_feature(CPU_SVE256); + VM_Features use = image_features & _cpu_features; + log_error(crac)("The image has -XX:CPUFeatures=%s with CPU_SVE256=%s, this CPU has CPUFeatures=%s not supporting CPU_SVE256, use -XX:CPUFeatures=%s during snapshot", + image_features.print_numbers(), sve256.print_numbers(), _cpu_features.print_numbers(), use.print_numbers()); + return false; } - ResourceMark rm; - VM_Features sve256; - sve256.set_feature(CPU_SVE256); - VM_Features use = image_features & _cpu_features; - log_error(crac)("The image has -XX:CPUFeatures=%s with CPU_SVE256=%s, this CPU has CPUFeatures=%s not supporting CPU_SVE256, use -XX:CPUFeatures=%s during snapshot", - image_features.print_numbers(), sve256.print_numbers(), _cpu_features.print_numbers(), use.print_numbers()); - return false; + want = image_supports_sve256 ? 32 : 16; } - int want = image_supports_sve256 ? 32 : 16; if (set_maximum_sve_vector_length(want) == want) { return true; } @@ -961,10 +968,18 @@ bool VM_Version::process_image_cpu_features(VM_Features image_features) { ResourceMark rm; VM_Features sve256; sve256.set_feature(CPU_SVE256); - log_error(crac)("The image has -XX:CPUFeatures=%s with CPU_SVE256=%s %s, this CPU has CPUFeatures=%s but PR_SVE_SET_VL reports %d: %s", - image_features.print_numbers(), sve256.print_numbers(), - want == 32 ? "set" : "unset", - _cpu_features.print_numbers(), got, os::strerror(errno)); + if (image_featuresp != nullptr) { + const VM_Features &image_features = *image_featuresp; + log_error(crac)("The image has -XX:CPUFeatures=%s with CPU_SVE256=%s %s, this CPU has CPUFeatures=%s but PR_SVE_SET_VL reports %d: %s", + image_features.print_numbers(), sve256.print_numbers(), + want == 32 ? "set" : "unset", + _cpu_features.print_numbers(), got, os::strerror(errno)); + } else { + log_error(crac)("Cannot restore this JVM's CPUFeatures=%s with CPU_SVE256=%s %s, this CPU has CPUFeatures=%s but PR_SVE_SET_VL reports %d: %s", + _features.print_numbers(), sve256.print_numbers(), + want == 32 ? "set" : "unset", + _cpu_features.print_numbers(), got, os::strerror(errno)); + } return false; } return true; diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp index 04631cf0436..d31005924ae 100644 --- a/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp @@ -145,7 +145,7 @@ class VM_Version : public Abstract_VM_Version, public VM_Feature_Flag { static void insert_features_names(VM_Version::VM_Features features, outputStream& os); // The returned string needs a ResourceMark. static const char *restore_failed_check(const VM_Features *image_features, const VM_Features *current_features); - static bool process_image_cpu_features(VM_Features image_features); + static bool process_image_cpu_features(const VM_Features *image_featuresp); static constexpr bool process_image_cpu_features_needed = true; 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 c15b446d442..d2c0f5f65e2 100644 --- a/src/hotspot/cpu/arm/vm_version_arm.hpp +++ b/src/hotspot/cpu/arm/vm_version_arm.hpp @@ -45,7 +45,7 @@ class VM_Version: public Abstract_VM_Version { static const char *restore_failed_check(const VM_Features *image_features, const VM_Features *current_features) { return nullptr; } - static bool process_image_cpu_features(VM_Features image_features) { + static bool process_image_cpu_features(const VM_Features *image_featuresp) { return false; } static constexpr bool process_image_cpu_features_needed = false; diff --git a/src/hotspot/cpu/x86/vm_version_x86.hpp b/src/hotspot/cpu/x86/vm_version_x86.hpp index 1884ed029f4..c44be61c9fc 100644 --- a/src/hotspot/cpu/x86/vm_version_x86.hpp +++ b/src/hotspot/cpu/x86/vm_version_x86.hpp @@ -731,7 +731,7 @@ class VM_Version : public Abstract_VM_Version, protected VM_Feature_Flag { static const char *restore_failed_check(const VM_Features *image_features, const VM_Features *current_features) { return nullptr; } - static bool process_image_cpu_features(VM_Features image_features) { + static bool process_image_cpu_features(const VM_Features *image_featuresp) { return false; } static constexpr bool process_image_cpu_features_needed = false; diff --git a/src/hotspot/cpu/zero/vm_version_zero.hpp b/src/hotspot/cpu/zero/vm_version_zero.hpp index 93b3fb1d834..8718786c79b 100644 --- a/src/hotspot/cpu/zero/vm_version_zero.hpp +++ b/src/hotspot/cpu/zero/vm_version_zero.hpp @@ -38,7 +38,7 @@ class VM_Version : public Abstract_VM_Version { static const char *restore_failed_check(const VM_Features *image_features, const VM_Features *current_features) { return nullptr; } - static bool process_image_cpu_features(VM_Features image_features) { + static bool process_image_cpu_features(const VM_Features *image_featuresp) { return false; } static constexpr bool process_image_cpu_features_needed = false; diff --git a/src/hotspot/share/runtime/crac.cpp b/src/hotspot/share/runtime/crac.cpp index 7f46a5c7402..9e924882bac 100644 --- a/src/hotspot/share/runtime/crac.cpp +++ b/src/hotspot/share/runtime/crac.cpp @@ -854,6 +854,14 @@ void crac::prepare_restore(crac_restore_data& restore_data) { restore_data.restore_nanos = os::javaTimeNanos(); } +template +class RestoreCpuInfo { + F _f; +public: + explicit RestoreCpuInfo(F f) : _f(f) {} + ~RestoreCpuInfo() { _f(); } +}; + void crac::restore(crac_restore_data& restore_data) { precond(CRaCRestoreFrom != nullptr); @@ -892,7 +900,9 @@ void crac::restore(crac_restore_data& restore_data) { case CracEngine::ApiStatus::OK: { VM_Version::VM_Features current_features; if (VM_Version::cpu_features_binary(¤t_features)) { - engine.require_cpuinfo(¤t_features, exact); + if (!engine.require_cpuinfo(¤t_features, exact)) { + return; + } } } break; case CracEngine::ApiStatus::ERR: @@ -903,6 +913,9 @@ void crac::restore(crac_restore_data& restore_data) { break; } } + RestoreCpuInfo restore_cpu_info_obj([&]{ + engine.restore_cpuinfo(); + }); switch (engine.prepare_restore_data_api()) { case CracEngine::ApiStatus::OK: { @@ -941,7 +954,9 @@ void crac::restore(crac_restore_data& restore_data) { } const int ret = engine.restore(); - if (ret != 0) { + if (ret == 0) { + ShouldNotReachHere(); + } else { log_error(crac)("CRaC engine failed to restore from %s: error %d", CRaCRestoreFrom, ret); VM_Version::VM_Features current_features; VM_Version::cpu_features_binary(¤t_features); // ignore return value diff --git a/src/hotspot/share/runtime/crac_engine.cpp b/src/hotspot/share/runtime/crac_engine.cpp index 4f3dca1293f..9460a02e865 100644 --- a/src/hotspot/share/runtime/crac_engine.cpp +++ b/src/hotspot/share/runtime/crac_engine.cpp @@ -378,47 +378,11 @@ int CracEngine::checkpoint() const { return _api->checkpoint(_conf); } -static constexpr char cpuarch_name[] = "cpu.arch"; -static constexpr char cpufeatures_name[] = "cpu.features"; - -bool CracEngine::bitmap_constraint_hook(const unsigned char *value, size_t value_size, void *user_data/*unused*/) { - VM_Version::VM_Features features; - if (value_size != sizeof(features)) { - log_error(crac)("Incompatible CPUFeatures length in the image - got %zu, want %zu", value_size, sizeof(features)); - return false; - } - memcpy(&features, value, value_size); - return VM_Version::process_image_cpu_features(features); -} - -bool CracEngine::register_constraints_hooks() { - if (!VM_Version::process_image_cpu_features_needed) { - return true; - } - if (!Abstract_VM_Version::should_check_cpu_features()) { - return true; - } - switch (prepare_image_constraints_api()) { - case CracEngine::ApiStatus::OK: - break; - case CracEngine::ApiStatus::ERR: - return true; - case CracEngine::ApiStatus::UNSUPPORTED: - log_warning(crac)("Cannot verify CPUFeatures for arch-specific part of restore " - "with the selected CRaC engine"); - return true; - } - return _image_constraints_api->register_bitmap_hook(_conf, cpufeatures_name, bitmap_constraint_hook, nullptr /* user_data */); -} - -int CracEngine::restore() { +int CracEngine::restore() const { precond(is_initialized()); if (!check_engine(_name, _image_location)) { return -1; } - if (!register_constraints_hooks()) { - return -1; - } return _api->restore(_conf); } @@ -543,6 +507,19 @@ const crlib_conf_option_t *CracEngine::configuration_options() { return _options; } +bool CracEngine::bitmap_constraint_hook(const unsigned char *value, size_t value_size, void *user_data/*unused*/) { + VM_Version::VM_Features features; + if (value_size != sizeof(features)) { + log_error(crac)("Incompatible CPUFeatures length in the image - got %zu, want %zu", value_size, sizeof(features)); + return false; + } + memcpy(&features, value, value_size); + return VM_Version::process_image_cpu_features(&features); +} + +static constexpr char cpuarch_name[] = "cpu.arch"; +static constexpr char cpufeatures_name[] = "cpu.features"; + CracEngine::ApiStatus CracEngine::prepare_image_constraints_api() { prepare_extension_api(_image_constraints_api, CRLIB_EXTENSION_IMAGE_CONSTRAINTS_NAME) require_method(set_label) @@ -569,11 +546,24 @@ bool CracEngine::store_cpuinfo(const VM_Version::VM_Features *current_features) return true; } -void CracEngine::require_cpuinfo(const VM_Version::VM_Features *current_features, bool exact) const { +// Return success. +bool CracEngine::require_cpuinfo(const VM_Version::VM_Features *current_features, bool exact) const { log_debug(crac)("cpufeatures_load user data %s from %s...", cpufeatures_name, CRaCRestoreFrom); _image_constraints_api->require_label(_conf, cpuarch_name, ARCHPROPNAME); _image_constraints_api->require_bitmap(_conf, cpufeatures_name, reinterpret_cast(current_features), sizeof(*current_features), exact ? EQUALS : SUBSET); + if (VM_Version::process_image_cpu_features_needed + && !_image_constraints_api->register_bitmap_hook(_conf, cpufeatures_name, bitmap_constraint_hook, nullptr /* user_data */)) { + return false; + } + return true; +} + +void CracEngine::restore_cpuinfo() const { + log_debug(crac)("restore_cpuinfo..."); + if (VM_Version::process_image_cpu_features_needed) { + VM_Version::process_image_cpu_features(nullptr); + } } void CracEngine::check_cpuinfo(const VM_Version::VM_Features *current_features, bool exact) const { diff --git a/src/hotspot/share/runtime/crac_engine.hpp b/src/hotspot/share/runtime/crac_engine.hpp index 7ad8904028c..18e6fa6ef93 100644 --- a/src/hotspot/share/runtime/crac_engine.hpp +++ b/src/hotspot/share/runtime/crac_engine.hpp @@ -53,7 +53,7 @@ class CracEngine : public CHeapObj { // Operations supported by all engines int checkpoint() const; - int restore(); + int restore() const; bool configure_image_location(const char *image_location); GrowableArrayCHeap *vm_controlled_options() const; @@ -73,7 +73,8 @@ class CracEngine : public CHeapObj { ApiStatus prepare_image_constraints_api(); bool set_label(const char* label, const char* value); bool store_cpuinfo(const VM_Version::VM_Features *current_features) const; - void require_cpuinfo(const VM_Version::VM_Features *current_features, bool exact) const; + bool require_cpuinfo(const VM_Version::VM_Features *current_features, bool exact) const; + void restore_cpuinfo() const; void check_cpuinfo(const VM_Version::VM_Features *current_features, bool exact) const; ApiStatus prepare_image_score_api(); @@ -94,7 +95,6 @@ class CracEngine : public CHeapObj { crlib_conf_option_t *_options = nullptr; static bool bitmap_constraint_hook(const unsigned char *value, size_t value_size, void *user_data); - bool register_constraints_hooks(); }; #endif // SHARE_RUNTIME_CRAC_ENGINE_HPP From 77a7638c4fc88d88c19bc04660ff2394703f72c9 Mon Sep 17 00:00:00 2001 From: Jan Kratochvil Date: Fri, 31 Jul 2026 17:47:25 +0200 Subject: [PATCH 41/41] Cosmetic message unification --- src/hotspot/cpu/aarch64/vm_version_aarch64.cpp | 2 +- test/jdk/jdk/crac/CPUFeatures/CPUFeaturesAWS.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp index ff4f7440a6b..3e0b3600f4f 100644 --- a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp @@ -948,7 +948,7 @@ bool VM_Version::process_image_cpu_features(const VM_Features *image_featuresp) VM_Features sve256; sve256.set_feature(CPU_SVE256); VM_Features use = image_features & _cpu_features; - log_error(crac)("The image has -XX:CPUFeatures=%s with CPU_SVE256=%s, this CPU has CPUFeatures=%s not supporting CPU_SVE256, use -XX:CPUFeatures=%s during snapshot", + log_error(crac)("The image has -XX:CPUFeatures=%s with CPU_SVE256=%s, this CPU has CPUFeatures=%s not supporting CPU_SVE256, try using -XX:CPUFeatures=%s on checkpoint.", image_features.print_numbers(), sve256.print_numbers(), _cpu_features.print_numbers(), use.print_numbers()); return false; } diff --git a/test/jdk/jdk/crac/CPUFeatures/CPUFeaturesAWS.sh b/test/jdk/jdk/crac/CPUFeatures/CPUFeaturesAWS.sh index 330ad22efbd..8a1f18e9f72 100755 --- a/test/jdk/jdk/crac/CPUFeatures/CPUFeaturesAWS.sh +++ b/test/jdk/jdk/crac/CPUFeatures/CPUFeaturesAWS.sh @@ -354,7 +354,7 @@ checkpoint_restore "$LINENO" t4g.micro a1.medium "-1:LSE (0x100) cannot be disab checkpoint_restore "$LINENO" c7g.medium c7g.medium checkpoint_restore "$LINENO" c8g.medium c8g.medium -checkpoint_restore "$LINENO" c7g.medium c8g.medium "1:The image has -XX:CPUFeatures=0x4000000000017fff with CPU_SVE256=0x4000000000000000, this CPU has CPUFeatures=0x77fff not supporting CPU_SVE256, use -XX:CPUFeatures=0x17fff during snapshot" +checkpoint_restore "$LINENO" c7g.medium c8g.medium "1:The image has -XX:CPUFeatures=0x4000000000017fff with CPU_SVE256=0x4000000000000000, this CPU has CPUFeatures=0x77fff not supporting CPU_SVE256, try using -XX:CPUFeatures=0x17fff on checkpoint." checkpoint_restore "$LINENO" c7g.medium c8g.medium "" "-XX:CPUFeatures=0x17fff" "" checkpoint_restore "$LINENO" c8g.medium c7g.medium "1:Restore failed due to incompatible or missing CPU features, try using -XX:CPUFeatures=0x17fff on checkpoint." checkpoint_restore "$LINENO" c8g.medium c7g.medium "" "-XX:CPUFeatures=0x17fff" ""