Skip to content

Commit ffa3599

Browse files
authored
Merge pull request #42 from microsoft/swesonga/win-aarch64-fixes-jdk21u
Backport Windows AArch64 fixes to jdk21u
2 parents 8c322f5 + 0128619 commit ffa3599

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
@@ -2729,6 +2729,10 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) {
27292729
// Verify that OS save/restore AVX registers.
27302730
return Handle_Exception(exceptionInfo, VM_Version::cpuinfo_cont_addr());
27312731
}
2732+
#elif defined(_M_ARM64)
2733+
if (handle_safefetch(exception_code, pc, (void*)exceptionInfo->ContextRecord)) {
2734+
return EXCEPTION_CONTINUE_EXECUTION;
2735+
}
27322736
#endif
27332737

27342738
if (t != nullptr && t->is_Java_thread()) {
@@ -2761,10 +2765,8 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) {
27612765
// Fatal red zone violation.
27622766
overflow_state->disable_stack_red_zone();
27632767
tty->print_raw_cr("An unrecoverable stack overflow has occurred.");
2764-
#if !defined(USE_VECTORED_EXCEPTION_HANDLING)
27652768
report_error(t, exception_code, pc, exception_record,
27662769
exceptionInfo->ContextRecord);
2767-
#endif
27682770
return EXCEPTION_CONTINUE_SEARCH;
27692771
}
27702772
} else if (exception_code == EXCEPTION_ACCESS_VIOLATION) {
@@ -2820,10 +2822,8 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) {
28202822
#endif
28212823

28222824
// Stack overflow or null pointer exception in native code.
2823-
#if !defined(USE_VECTORED_EXCEPTION_HANDLING)
28242825
report_error(t, exception_code, pc, exception_record,
28252826
exceptionInfo->ContextRecord);
2826-
#endif
28272827
return EXCEPTION_CONTINUE_SEARCH;
28282828
} // /EXCEPTION_ACCESS_VIOLATION
28292829
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -2897,41 +2897,21 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) {
28972897
}
28982898
}
28992899

2900-
#if !defined(USE_VECTORED_EXCEPTION_HANDLING)
2901-
if (exception_code != EXCEPTION_BREAKPOINT) {
2902-
report_error(t, exception_code, pc, exception_record,
2903-
exceptionInfo->ContextRecord);
2904-
}
2905-
#endif
2906-
return EXCEPTION_CONTINUE_SEARCH;
2907-
}
2900+
bool should_report_error = (exception_code != EXCEPTION_BREAKPOINT);
29082901

2909-
#if defined(USE_VECTORED_EXCEPTION_HANDLING)
2910-
LONG WINAPI topLevelVectoredExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) {
2911-
PEXCEPTION_RECORD exceptionRecord = exceptionInfo->ExceptionRecord;
29122902
#if defined(_M_ARM64)
2913-
address pc = (address) exceptionInfo->ContextRecord->Pc;
2914-
#elif defined(_M_AMD64)
2915-
address pc = (address) exceptionInfo->ContextRecord->Rip;
2916-
#else
2917-
address pc = (address) exceptionInfo->ContextRecord->Eip;
2903+
should_report_error = should_report_error &&
2904+
FAILED(exception_code) &&
2905+
(exception_code != EXCEPTION_UNCAUGHT_CXX_EXCEPTION);
29182906
#endif
29192907

2920-
// Fast path for code part of the code cache
2921-
if (CodeCache::low_bound() <= pc && pc < CodeCache::high_bound()) {
2922-
return topLevelExceptionFilter(exceptionInfo);
2923-
}
2924-
2925-
// If the exception occurred in the codeCache, pass control
2926-
// to our normal exception handler.
2927-
CodeBlob* cb = CodeCache::find_blob(pc);
2928-
if (cb != nullptr) {
2929-
return topLevelExceptionFilter(exceptionInfo);
2908+
if (should_report_error) {
2909+
report_error(t, exception_code, pc, exception_record,
2910+
exceptionInfo->ContextRecord);
29302911
}
29312912

29322913
return EXCEPTION_CONTINUE_SEARCH;
29332914
}
2934-
#endif
29352915

29362916
#if defined(USE_VECTORED_EXCEPTION_HANDLING)
29372917
LONG WINAPI topLevelUnhandledExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) {
@@ -4657,7 +4637,7 @@ jint os::init_2(void) {
46574637
// Setup Windows Exceptions
46584638

46594639
#if defined(USE_VECTORED_EXCEPTION_HANDLING)
4660-
topLevelVectoredExceptionHandler = AddVectoredExceptionHandler(1, topLevelVectoredExceptionFilter);
4640+
topLevelVectoredExceptionHandler = AddVectoredExceptionHandler(1, topLevelExceptionFilter);
46614641
previousUnhandledExceptionFilter = SetUnhandledExceptionFilter(topLevelUnhandledExceptionFilter);
46624642
#endif
46634643

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

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)