Skip to content

Commit 4df76f4

Browse files
author
Java Platform Infrastructure
committed
Merge branch 'ms-patches/win-aarch64-fixes' into ms/jdk-21.0.10_3
2 parents 01a78c7 + eddc5b9 commit 4df76f4

File tree

16 files changed

+358
-128
lines changed

16 files changed

+358
-128
lines changed

make/autoconf/flags-other.m4

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,11 @@ AC_DEFUN([FLAGS_SETUP_ASFLAGS],
106106
# Force preprocessor to run, just to make sure
107107
BASIC_ASFLAGS="-x assembler-with-cpp"
108108
elif test "x$TOOLCHAIN_TYPE" = xmicrosoft; then
109-
BASIC_ASFLAGS="-nologo -c"
109+
if test "x$OPENJDK_TARGET_CPU" = xaarch64; then
110+
BASIC_ASFLAGS="-nologo"
111+
else
112+
BASIC_ASFLAGS="-nologo -c"
113+
fi
110114
fi
111115
AC_SUBST(BASIC_ASFLAGS)
112116

make/autoconf/toolchain.m4

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -727,8 +727,11 @@ AC_DEFUN_ONCE([TOOLCHAIN_DETECT_TOOLCHAIN_CORE],
727727
if test "x$TOOLCHAIN_TYPE" != xmicrosoft; then
728728
AS="$CC -c"
729729
else
730-
if test "x$OPENJDK_TARGET_CPU_BITS" = "x64"; then
731-
# On 64 bit windows, the assembler is "ml64.exe"
730+
if test "x$OPENJDK_TARGET_CPU" = "xaarch64"; then
731+
# On Windows aarch64, the assembler is "armasm64.exe"
732+
UTIL_LOOKUP_TOOLCHAIN_PROGS(AS, armasm64)
733+
elif test "x$OPENJDK_TARGET_CPU_BITS" = "x64"; then
734+
# On Windows x64, the assembler is "ml64.exe"
732735
UTIL_LOOKUP_TOOLCHAIN_PROGS(AS, ml64)
733736
else
734737
# otherwise, the assembler is "ml.exe"

make/common/NativeCompilation.gmk

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,12 @@ define SetupCompileNativeFileBody
398398
endif
399399
$1_FLAGS := $$($1_FLAGS) -DASSEMBLY_SRC_FILE='"$$($1_REL_ASM_SRC)"' \
400400
-include $(TOPDIR)/make/data/autoheaders/assemblyprefix.h
401+
else ifeq ($(TOOLCHAIN_TYPE), microsoft)
402+
ifeq ($(OPENJDK_TARGET_CPU), aarch64)
403+
$1_NON_ASM_EXTENSION_FLAG :=
404+
else
405+
$1_NON_ASM_EXTENSION_FLAG := "-Ta"
406+
endif
401407
endif
402408
else ifneq ($$(filter %.cpp %.cc %.mm, $$($1_FILENAME)), )
403409
# Compile as a C++ or Objective-C++ file
@@ -479,7 +485,7 @@ define SetupCompileNativeFileBody
479485
# For assembler calls just create empty dependency lists
480486
$$(call ExecuteWithLog, $$@, $$(call MakeCommandRelative, \
481487
$$($1_COMPILER) $$($1_FLAGS) \
482-
$(CC_OUT_OPTION)$$($1_OBJ) -Ta $$($1_SRC_FILE))) \
488+
$(CC_OUT_OPTION)$$($1_OBJ) $$($1_NON_ASM_EXTENSION_FLAG) $$($1_SRC_FILE))) \
483489
| $(TR) -d '\r' | $(GREP) -v -e "Assembling:" || test "$$$$?" = "1" ; \
484490
$(ECHO) > $$($1_DEPS_FILE) ; \
485491
$(ECHO) > $$($1_DEPS_TARGETS_FILE)

ms-patches/win-aarch64-fixes.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
title: Windows AArch64 bug fixes
2+
- work_item: 2547147
3+
- jbs_bug:
4+
- author: kthatipally, macarte, swesonga
5+
- owner: kthatipally, macarte, swesonga
6+
- contributors: kthatipally, macarte, swesonga
7+
- details:
8+
- release_note:
9+
- Fixes serviceability bugs that result in thread contexts being unavailable in hsdb on Windows AArch64
10+
- Fixes core dump creation failure on Windows AArch64

src/hotspot/os/windows/os_windows.cpp

Lines changed: 119 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2752,6 +2752,10 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) {
27522752
// Verify that OS save/restore AVX registers.
27532753
return Handle_Exception(exceptionInfo, VM_Version::cpuinfo_cont_addr());
27542754
}
2755+
#elif defined(_M_ARM64)
2756+
if (handle_safefetch(exception_code, pc, (void*)exceptionInfo->ContextRecord)) {
2757+
return EXCEPTION_CONTINUE_EXECUTION;
2758+
}
27552759
#endif
27562760

27572761
if (t != nullptr && t->is_Java_thread()) {
@@ -2784,10 +2788,8 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) {
27842788
// Fatal red zone violation.
27852789
overflow_state->disable_stack_red_zone();
27862790
tty->print_raw_cr("An unrecoverable stack overflow has occurred.");
2787-
#if !defined(USE_VECTORED_EXCEPTION_HANDLING)
27882791
report_error(t, exception_code, pc, exception_record,
27892792
exceptionInfo->ContextRecord);
2790-
#endif
27912793
return EXCEPTION_CONTINUE_SEARCH;
27922794
}
27932795
} else if (exception_code == EXCEPTION_ACCESS_VIOLATION) {
@@ -2843,10 +2845,8 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) {
28432845
#endif
28442846

28452847
// Stack overflow or null pointer exception in native code.
2846-
#if !defined(USE_VECTORED_EXCEPTION_HANDLING)
28472848
report_error(t, exception_code, pc, exception_record,
28482849
exceptionInfo->ContextRecord);
2849-
#endif
28502850
return EXCEPTION_CONTINUE_SEARCH;
28512851
} // /EXCEPTION_ACCESS_VIOLATION
28522852
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -2920,41 +2920,21 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) {
29202920
}
29212921
}
29222922

2923-
#if !defined(USE_VECTORED_EXCEPTION_HANDLING)
2924-
if (exception_code != EXCEPTION_BREAKPOINT) {
2925-
report_error(t, exception_code, pc, exception_record,
2926-
exceptionInfo->ContextRecord);
2927-
}
2928-
#endif
2929-
return EXCEPTION_CONTINUE_SEARCH;
2930-
}
2923+
bool should_report_error = (exception_code != EXCEPTION_BREAKPOINT);
29312924

2932-
#if defined(USE_VECTORED_EXCEPTION_HANDLING)
2933-
LONG WINAPI topLevelVectoredExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) {
2934-
PEXCEPTION_RECORD exceptionRecord = exceptionInfo->ExceptionRecord;
29352925
#if defined(_M_ARM64)
2936-
address pc = (address) exceptionInfo->ContextRecord->Pc;
2937-
#elif defined(_M_AMD64)
2938-
address pc = (address) exceptionInfo->ContextRecord->Rip;
2939-
#else
2940-
address pc = (address) exceptionInfo->ContextRecord->Eip;
2926+
should_report_error = should_report_error &&
2927+
FAILED(exception_code) &&
2928+
(exception_code != EXCEPTION_UNCAUGHT_CXX_EXCEPTION);
29412929
#endif
29422930

2943-
// Fast path for code part of the code cache
2944-
if (CodeCache::low_bound() <= pc && pc < CodeCache::high_bound()) {
2945-
return topLevelExceptionFilter(exceptionInfo);
2946-
}
2947-
2948-
// If the exception occurred in the codeCache, pass control
2949-
// to our normal exception handler.
2950-
CodeBlob* cb = CodeCache::find_blob(pc);
2951-
if (cb != nullptr) {
2952-
return topLevelExceptionFilter(exceptionInfo);
2931+
if (should_report_error) {
2932+
report_error(t, exception_code, pc, exception_record,
2933+
exceptionInfo->ContextRecord);
29532934
}
29542935

29552936
return EXCEPTION_CONTINUE_SEARCH;
29562937
}
2957-
#endif
29582938

29592939
#if defined(USE_VECTORED_EXCEPTION_HANDLING)
29602940
LONG WINAPI topLevelUnhandledExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) {
@@ -4681,7 +4661,7 @@ jint os::init_2(void) {
46814661
// Setup Windows Exceptions
46824662

46834663
#if defined(USE_VECTORED_EXCEPTION_HANDLING)
4684-
topLevelVectoredExceptionHandler = AddVectoredExceptionHandler(1, topLevelVectoredExceptionFilter);
4664+
topLevelVectoredExceptionHandler = AddVectoredExceptionHandler(1, topLevelExceptionFilter);
46854665
previousUnhandledExceptionFilter = SetUnhandledExceptionFilter(topLevelUnhandledExceptionFilter);
46864666
#endif
46874667

@@ -6428,3 +6408,110 @@ void os::print_user_info(outputStream* st) {
64286408
void os::print_active_locale(outputStream* st) {
64296409
// not implemented yet
64306410
}
6411+
6412+
/*
6413+
TODO: Investigate whether Windows AArch64 uses stack frames the way Java expects.
6414+
If so, we can replace the os::win32::platform_print_native_stack() implementation
6415+
with one that uses the mechanism in vmError.cpp (and whether this comment is still
6416+
accurate about that being the correct way to print native stacks). Otherwise, we
6417+
need to keep this implementation and document that Windows AArch64 is similar
6418+
to Windows x64 where there is commentary about Windows x64 behavior.
6419+
*/
6420+
/*
6421+
* Windows/x64 does not use stack frames the way expected by Java:
6422+
* [1] in most cases, there is no frame pointer. All locals are addressed via RSP
6423+
* [2] in rare cases, when alloca() is used, a frame pointer is used, but this may
6424+
* not be RBP.
6425+
* See http://msdn.microsoft.com/en-us/library/ew5tede7.aspx
6426+
*
6427+
* So it's not possible to print the native stack using the
6428+
* while (...) {... fr = os::get_sender_for_C_frame(&fr); }
6429+
* loop in vmError.cpp. We need to roll our own loop.
6430+
*/
6431+
bool os::win32::platform_print_native_stack(outputStream* st, const void* context,
6432+
char *buf, int buf_size, address& lastpc)
6433+
{
6434+
CONTEXT ctx;
6435+
if (context != nullptr) {
6436+
memcpy(&ctx, context, sizeof(ctx));
6437+
} else {
6438+
RtlCaptureContext(&ctx);
6439+
}
6440+
6441+
st->print_cr("Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)");
6442+
6443+
DWORD machine_type;
6444+
STACKFRAME stk;
6445+
memset(&stk, 0, sizeof(stk));
6446+
stk.AddrStack.Mode = AddrModeFlat;
6447+
stk.AddrFrame.Mode = AddrModeFlat;
6448+
stk.AddrPC.Mode = AddrModeFlat;
6449+
6450+
#if defined(_M_AMD64)
6451+
stk.AddrStack.Offset = ctx.Rsp;
6452+
stk.AddrFrame.Offset = ctx.Rbp;
6453+
stk.AddrPC.Offset = ctx.Rip;
6454+
machine_type = IMAGE_FILE_MACHINE_AMD64;
6455+
#elif defined(_M_ARM64)
6456+
stk.AddrStack.Offset = ctx.Sp;
6457+
stk.AddrFrame.Offset = ctx.Fp;
6458+
stk.AddrPC.Offset = ctx.Pc;
6459+
machine_type = IMAGE_FILE_MACHINE_ARM64;
6460+
#else
6461+
#error unknown architecture
6462+
#endif
6463+
6464+
int count = 0;
6465+
address lastpc_internal = 0;
6466+
while (count++ < StackPrintLimit) {
6467+
intptr_t* sp = (intptr_t*)stk.AddrStack.Offset;
6468+
intptr_t* fp = (intptr_t*)stk.AddrFrame.Offset; // NOT necessarily the same as ctx.Rbp!
6469+
address pc = (address)stk.AddrPC.Offset;
6470+
6471+
if (pc != nullptr) {
6472+
if (count == 2 && lastpc_internal == pc) {
6473+
// Skip it -- StackWalk64() may return the same PC
6474+
// (but different SP) on the first try.
6475+
} else {
6476+
// Don't try to create a frame(sp, fp, pc) -- on WinX64, stk.AddrFrame
6477+
// may not contain what Java expects, and may cause the frame() constructor
6478+
// to crash. Let's just print out the symbolic address.
6479+
frame::print_C_frame(st, buf, buf_size, pc);
6480+
// print source file and line, if available
6481+
char buf[128];
6482+
int line_no;
6483+
if (SymbolEngine::get_source_info(pc, buf, sizeof(buf), &line_no)) {
6484+
st->print(" (%s:%d)", buf, line_no);
6485+
} else {
6486+
st->print(" (no source info available)");
6487+
}
6488+
st->cr();
6489+
}
6490+
lastpc_internal = pc;
6491+
}
6492+
6493+
PVOID p = WindowsDbgHelp::symFunctionTableAccess64(GetCurrentProcess(), stk.AddrPC.Offset);
6494+
if (!p) {
6495+
// StackWalk64() can't handle this PC. Calling StackWalk64 again may cause crash.
6496+
lastpc = lastpc_internal;
6497+
break;
6498+
}
6499+
6500+
BOOL result = WindowsDbgHelp::stackWalk64(
6501+
machine_type, // __in DWORD MachineType,
6502+
GetCurrentProcess(), // __in HANDLE hProcess,
6503+
GetCurrentThread(), // __in HANDLE hThread,
6504+
&stk, // __inout LP STACKFRAME64 StackFrame,
6505+
&ctx); // __inout PVOID ContextRecord,
6506+
6507+
if (!result) {
6508+
break;
6509+
}
6510+
}
6511+
if (count > StackPrintLimit) {
6512+
st->print_cr("...<more frames>...");
6513+
}
6514+
st->cr();
6515+
6516+
return true;
6517+
}

src/hotspot/os/windows/os_windows.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,8 @@ class os::win32 {
172172
// signal support
173173
static void* install_signal_handler(int sig, signal_handler_t handler);
174174
static void* user_handler();
175+
176+
static void context_set_pc(CONTEXT* uc, address pc);
175177
};
176178

177179
#endif // OS_WINDOWS_OS_WINDOWS_HPP
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/*
2+
* Copyright (c) 2022 SAP SE. All rights reserved.
3+
* Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved.
4+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5+
*
6+
* This code is free software; you can redistribute it and/or modify it
7+
* under the terms of the GNU General Public License version 2 only, as
8+
* published by the Free Software Foundation.
9+
*
10+
* This code is distributed in the hope that it will be useful, but WITHOUT
11+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13+
* version 2 for more details (a copy is included in the LICENSE file that
14+
* accompanied this code).
15+
*
16+
* You should have received a copy of the GNU General Public License version
17+
* 2 along with this work; if not, write to the Free Software Foundation,
18+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19+
*
20+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21+
* or visit www.oracle.com if you need additional information or have any
22+
* questions.
23+
*
24+
*/
25+
26+
27+
#include "precompiled.hpp"
28+
#include "os_windows.hpp"
29+
#include "runtime/os.hpp"
30+
#include "runtime/safefetch.hpp"
31+
#include "utilities/globalDefinitions.hpp"
32+
33+
#ifdef SAFEFETCH_METHOD_STATIC_ASSEMBLY
34+
35+
// SafeFetch handling, static assembly style:
36+
//
37+
// SafeFetch32 and SafeFetchN are implemented via static assembly
38+
// and live in os_cpu/xx_xx/safefetch_xx_xx.S
39+
40+
extern "C" char _SafeFetch32_continuation[];
41+
extern "C" char _SafeFetch32_fault[];
42+
43+
#ifdef _LP64
44+
extern "C" char _SafeFetchN_continuation[];
45+
extern "C" char _SafeFetchN_fault[];
46+
#endif // _LP64
47+
48+
bool handle_safefetch(int exception_code, address pc, void* context) {
49+
CONTEXT* ctx = (CONTEXT*)context;
50+
if (exception_code == EXCEPTION_ACCESS_VIOLATION && ctx != nullptr) {
51+
if (pc == (address)_SafeFetch32_fault) {
52+
os::win32::context_set_pc(ctx, (address)_SafeFetch32_continuation);
53+
return true;
54+
}
55+
#ifdef _LP64
56+
if (pc == (address)_SafeFetchN_fault) {
57+
os::win32::context_set_pc(ctx, (address)_SafeFetchN_continuation);
58+
return true;
59+
}
60+
#endif
61+
}
62+
return false;
63+
}
64+
65+
#endif // SAFEFETCH_METHOD_STATIC_ASSEMBLY

src/hotspot/os_cpu/windows_aarch64/os_windows_aarch64.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,10 @@ frame os::fetch_frame_from_context(const void* ucVoid) {
9999
return frame(sp, fp, epc);
100100
}
101101

102+
void os::win32::context_set_pc(CONTEXT* uc, address pc) {
103+
uc->Pc = (intptr_t)pc;
104+
}
105+
102106
bool os::win32::get_frame_at_stack_banging_point(JavaThread* thread,
103107
struct _EXCEPTION_POINTERS* exceptionInfo, address pc, frame* fr) {
104108
PEXCEPTION_RECORD exceptionRecord = exceptionInfo->ExceptionRecord;

src/hotspot/os_cpu/windows_aarch64/os_windows_aarch64.inline.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,10 @@ inline bool os::register_code_area(char *low, char *high) {
3232
return true;
3333
}
3434

35+
#define HAVE_PLATFORM_PRINT_NATIVE_STACK 1
36+
inline bool os::platform_print_native_stack(outputStream* st, const void* context,
37+
char *buf, int buf_size, address& lastpc) {
38+
return os::win32::platform_print_native_stack(st, context, buf, buf_size, lastpc);
39+
}
40+
3541
#endif // OS_CPU_WINDOWS_AARCH64_OS_WINDOWS_AARCH64_INLINE_HPP

0 commit comments

Comments
 (0)