Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 21 additions & 17 deletions src/coreclr/nativeaot/Runtime/arm64/GcProbe.S
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@
#define PROBE_FRAME_SIZE 0xD0 // 4 * 8 for fixed part of PInvokeTransitionFrame (fp, lr, m_pThread, m_Flags) +
// 10 * 8 for callee saved registers +
// 1 * 8 for caller SP +
// 2 * 8 for int returns +
// 1 * 8 for alignment padding +
// 3 * 8 for int returns (x0, x1, x2) +
// 4 * 16 for FP/HFA/HVA returns

// See PUSH_COOP_PINVOKE_FRAME, this macro is very similar, but also saves return registers
Expand Down Expand Up @@ -38,10 +37,9 @@

// Slot at [sp, #0x70] is reserved for caller sp

// Save the integer return registers
// Save the integer return registers, x2 might contain an objectref (async continuation)
stp x0, x1, [sp, #0x78]

// Slot at [sp, #0x88] is alignment padding
str x2, [sp, #0x88]

// Save the FP/HFA/HVA return registers
stp q0, q1, [sp, #0x90]
Expand All @@ -68,11 +66,12 @@
.macro POP_PROBE_FRAME

// Restore the integer return registers
ldp x0, x1, [sp, #0x78]
ldp x0, x1, [sp, #0x78]
ldr x2, [sp, #0x88]

// Restore the FP/HFA/HVA return registers
ldp q0, q1, [sp, #0x90]
ldp q2, q3, [sp, #0xB0]
ldp q0, q1, [sp, #0x90]
ldp q2, q3, [sp, #0xB0]

// Restore callee saved registers
EPILOG_RESTORE_REG_PAIR x19, x20, 0x20
Expand All @@ -92,27 +91,32 @@
// All registers correct for return to the original return address.
//
// Register state on exit:
// x2: thread pointer
// x4: thread pointer
// x0, x1, x2: preserved
//
.macro FixupHijackedCallstack

// x2 <- GetThread()
// Store thread pointer temporarily in x3, then move it to x4
// x4 <- GetThread()

#ifdef FEATURE_EMULATED_TLS
GETTHREAD_ETLS_2
GETTHREAD_ETLS_3
#else
INLINE_GETTHREAD x2
INLINE_GETTHREAD x3
#endif

mov x4, x3

//
// Fix the stack by restoring the original return address
//
ldr lr, [x2, #OFFSETOF__Thread__m_pvHijackedReturnAddress]
ldr lr, [x4, #OFFSETOF__Thread__m_pvHijackedReturnAddress]

//
// Clear hijack state
//
// Clear m_ppvHijackedReturnAddressLocation and m_pvHijackedReturnAddress
stp xzr, xzr, [x2, #OFFSETOF__Thread__m_ppvHijackedReturnAddressLocation]
stp xzr, xzr, [x4, #OFFSETOF__Thread__m_ppvHijackedReturnAddressLocation]
.endm

//
Expand All @@ -126,17 +130,17 @@ NESTED_ENTRY RhpGcProbeHijack, _TEXT, NoHandler
ret

LOCAL_LABEL(WaitForGC):
mov x12, DEFAULT_FRAME_SAVE_FLAGS + PTFF_SAVE_X0 + PTFF_SAVE_X1
mov x12, DEFAULT_FRAME_SAVE_FLAGS + PTFF_SAVE_X0 + PTFF_SAVE_X1 + PTFF_SAVE_X2
movk x12, PTFF_THREAD_HIJACK_HI, lsl #32
b C_FUNC(RhpWaitForGC)
NESTED_END RhpGcProbeHijack

.global C_FUNC(RhpThrowHwEx)

NESTED_ENTRY RhpWaitForGC, _TEXT, NoHandler
PUSH_PROBE_FRAME x2, x3, x12
PUSH_PROBE_FRAME x4, x3, x12

ldr x0, [x2, #OFFSETOF__Thread__m_pDeferredTransitionFrame]
ldr x0, [x4, #OFFSETOF__Thread__m_pDeferredTransitionFrame]
bl C_FUNC(RhpWaitForGC2)

POP_PROBE_FRAME
Expand Down
34 changes: 17 additions & 17 deletions src/coreclr/nativeaot/Runtime/arm64/GcProbe.asm
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@
field OFFSETOF__PInvokeTransitionFrame__m_PreservedRegs
field 10 * 8 ; x19..x28
m_CallersSP field 8 ; SP at routine entry
field 2 * 8 ; x0..x1
field 8 ; alignment padding
field 3 * 8 ; x0..x2
field 4 * 16; q0..q3
PROBE_FRAME_SIZE field 0

Expand Down Expand Up @@ -47,10 +46,9 @@ PROBE_FRAME_SIZE field 0

;; Slot at [sp, #0x70] is reserved for caller sp

;; Save the integer return registers
;; Save the integer return registers, x2 might contain an objectref (async continuation)
PROLOG_NOP stp x0, x1, [sp, #0x78]

;; Slot at [sp, #0x88] is alignment padding
PROLOG_NOP str x2, [sp, #0x88]

;; Save the FP/HFA/HVA return registers
PROLOG_NOP stp q0, q1, [sp, #0x90]
Expand Down Expand Up @@ -80,6 +78,7 @@ PROBE_FRAME_SIZE field 0

;; Restore the integer return registers
PROLOG_NOP ldp x0, x1, [sp, #0x78]
PROLOG_NOP ldr x2, [sp, #0x88]

; Restore the FP/HFA/HVA return registers
EPILOG_NOP ldp q0, q1, [sp, #0x90]
Expand All @@ -103,26 +102,26 @@ PROBE_FRAME_SIZE field 0
;; All registers correct for return to the original return address.
;;
;; Register state on exit:
;; x2: thread pointer
;; x4: thread pointer
;; x3: trashed
;;
MACRO
FixupHijackedCallstack

;; x2 <- GetThread(), TRASHES x3
INLINE_GETTHREAD x2, x3
;; x4 <- GetThread(), TRASHES x3
INLINE_GETTHREAD x4, x3

;;
;; Fix the stack by restoring the original return address
;;
ldr lr, [x2, #OFFSETOF__Thread__m_pvHijackedReturnAddress]
ldr lr, [x4, #OFFSETOF__Thread__m_pvHijackedReturnAddress]

;;
;; Clear hijack state
;;
ASSERT OFFSETOF__Thread__m_pvHijackedReturnAddress == (OFFSETOF__Thread__m_ppvHijackedReturnAddressLocation + 8)
;; Clear m_ppvHijackedReturnAddressLocation and m_pvHijackedReturnAddress
stp xzr, xzr, [x2, #OFFSETOF__Thread__m_ppvHijackedReturnAddressLocation]
stp xzr, xzr, [x4, #OFFSETOF__Thread__m_ppvHijackedReturnAddressLocation]
MEND

MACRO
Expand Down Expand Up @@ -154,17 +153,17 @@ PROBE_FRAME_SIZE field 0
ret

WaitForGC
mov x12, #(DEFAULT_FRAME_SAVE_FLAGS + PTFF_SAVE_X0 + PTFF_SAVE_X1)
mov x12, #(DEFAULT_FRAME_SAVE_FLAGS + PTFF_SAVE_X0 + PTFF_SAVE_X1 + PTFF_SAVE_X2)
movk x12, #PTFF_THREAD_HIJACK_HI, lsl #32
b RhpWaitForGC
NESTED_END RhpGcProbeHijackWrapper

EXTERN RhpThrowHwEx

NESTED_ENTRY RhpWaitForGC
PUSH_PROBE_FRAME x2, x3, x12
PUSH_PROBE_FRAME x4, x3, x12

ldr x0, [x2, #OFFSETOF__Thread__m_pDeferredTransitionFrame]
ldr x0, [x4, #OFFSETOF__Thread__m_pDeferredTransitionFrame]
bl RhpWaitForGC2

POP_PROBE_FRAME
Expand Down Expand Up @@ -194,7 +193,7 @@ WaitForGC
;;
LEAF_ENTRY RhpGcStressHijack
FixupHijackedCallstack
orr x12, x12, #(DEFAULT_FRAME_SAVE_FLAGS + PTFF_SAVE_X0 + PTFF_SAVE_X1)
mov x12, #(DEFAULT_FRAME_SAVE_FLAGS + PTFF_SAVE_X0 + PTFF_SAVE_X1 + PTFF_SAVE_X2)
b RhpGcStressProbe
LEAF_END RhpGcStressHijack
;;
Expand All @@ -205,15 +204,16 @@ WaitForGC
;; Register state on entry:
;; x0: hijacked function return value
;; x1: hijacked function return value
;; x2: thread pointer
;; x2: hijacked function async continuation value
;; x4: thread pointer
;; w12: register bitmask
;;
;; Register state on exit:
;; Scratch registers, except for x0, have been trashed
;; Scratch registers, except for x0, x1, x2, have been trashed
;; All other registers restored as they were when the hijack was first reached.
;;
NESTED_ENTRY RhpGcStressProbe
PUSH_PROBE_FRAME x2, x3, x12
PUSH_PROBE_FRAME x4, x3, x12

bl RhpStressGc

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,7 @@ C_FUNC(\Name):
#define PTFF_SAVE_SP 0x00000400
#define PTFF_SAVE_X0 0x00000800
#define PTFF_SAVE_X1 0x00001000
#define PTFF_SAVE_X2 0x00002000
#define PTFF_SAVE_ALL_PRESERVED 0x000003FF // NOTE: x19-x28
#define PTFF_THREAD_HIJACK_HI 0x00000001 // upper 32 bits of the PTFF_THREAD_HIJACK

Expand Down