[PATCH v6] aarch64: Add split-stack support
Wilco Dijkstra
Wilco.Dijkstra@arm.com
Tue Feb 13 16:40:00 GMT 2018
Hi Adhemerval,
A few comments on the assembly code:
+# This function is called with non-standard calling convention: on entry
+# x10 is the requested stack pointer, x11 is previous stack pointer (if
+# functions has stacked arguments which needs to be restored), and x12 is
+# the caller link register on function entry (which will be restored by
+# morestack when returning to caller). The split-stack prologue is in
+# the form:
+#
+# function:
+# mrs x9, tpidr_el0
+# ldur x9, [x9, #-8]
+# mov x10, <required stack allocation>
+# movk x10, #0x0, lsl #16
+# sub x10, sp, x10
+# mov x11, sp # if function has stacked arguments
+# mov x12, x30
This should go...
+# cmp x9, x10
+# bcc .LX
+# main_fn_entry:
+# [function body]
+# LX:
...here:
mov x12, x30
+# bl __morestack
+# b main_fn_entry
Note using a bl here rather than a branch means you'll kill the return stack.
+# The N bit is also restored to indicate that the function is called
+# (so the prologue addition can set up the argument pointer correctly).
+
+ENTRY(__morestack)
+.LFB1:
+ .cfi_startproc
+
+#ifdef __PIC__
+ .cfi_personality 0x9b,DW.ref.__gcc_personality_v0
+ .cfi_lsda 0x1b,.LLSDA1
+#else
+ .cfi_personality 0x3,__gcc_personality_v0
+ .cfi_lsda 0x3,.LLSDA1
+#endif
+ # Calculate requested stack size.
+ sub x10, sp, x10
+
+ # Save parameters
+ stp x29, x12, [sp, -MORESTACK_FRAMESIZE]!
+ .cfi_def_cfa_offset MORESTACK_FRAMESIZE
+ .cfi_offset 29, -MORESTACK_FRAMESIZE
+ .cfi_offset 30, -MORESTACK_FRAMESIZE+8
+ add x29, sp, 0
+ .cfi_def_cfa_register 29
+ # Adjust the requested stack size for the frame pointer save.
+ stp x0, x1, [x29, 16]
+ stp x2, x3, [x29, 32]
+ add x10, x10, BACKOFF
+ stp x4, x5, [x29, 48]
+ stp x6, x7, [x29, 64]
+ stp x8, x30, [x29, 80]
+ str x10, [x29, 96]
Probably best to use NEWSTACK_SAVE here for clarity.
+ # void __morestack_block_signals (void)
+ bl __morestack_block_signals
+
+ # void *__generic_morestack (size_t *pframe_size,
+ # void *old_stack,
+ # size_t param_size)
+ # pframe_size: is the size of the required stack frame (the function
+ # amount of space remaining on the allocated stack).
+ # old_stack: points at the parameters the old stack
+ # param_size: size in bytes of parameters to copy to the new stack.
+ add x0, x29, NEWSTACK_SAVE
+ add x1, x29, MORESTACK_FRAMESIZE
+ mov x2, 0
+ bl __generic_morestack
+
+ # Start using new stack
+ mov sp, x0
+
+ # Set __private_ss stack guard for the new stack.
+ ldr x9, [x29, NEWSTACK_SAVE]
+ add x0, x0, BACKOFF
+ sub x0, x0, x9
+.LEHB0:
+ mrs x1, tpidr_el0
+ str x0, [x1, SPLITSTACK_PTR_TP]
Is the label for unwinding exactly at the right place?
+ # void __morestack_unblock_signals (void)
+ bl __morestack_unblock_signals
+
+ # Set up for a call to the target function.
+ ldp x0, x1, [x29, 16]
+ ldp x2, x3, [x29, 32]
+ ldp x4, x5, [x29, 48]
+ ldp x6, x7, [x29, 64]
+ ldp x8, x12, [x29, 80]
+ add x11, x29, MORESTACK_FRAMESIZE
+ ldr x30, [x29, 8]
+ # Indicate __morestack was called.
+ cmp x12, 0
No idea what this is for but the ldr/cmp are completely redundant.
+ blr x12
+
+ stp x0, x1, [x29, 16]
+ stp x2, x3, [x29, 32]
+ stp x4, x5, [x29, 48]
+ stp x6, x7, [x29, 64]
These 3 STPs are dead.
+ bl __morestack_block_signals
+
+ # void *__generic_releasestack (size_t *pavailable)
+ add x0, x29, NEWSTACK_SAVE
+ bl __generic_releasestack
+
+ # Reset __private_ss stack guard to value for old stack
+ ldr x9, [x29, NEWSTACK_SAVE]
+ add x0, x0, BACKOFF
+ sub x0, x0, x9
+
+ # Update TCB split stack field
+.LEHE0:
+ mrs x1, tpidr_el0
+ str x0, [x1, SPLITSTACK_PTR_TP]
+
+ bl __morestack_unblock_signals
+
+ # Use old stack again.
+ add sp, x29, MORESTACK_FRAMESIZE
+
+ ldp x0, x1, [x29, 16]
+ ldp x2, x3, [x29, 32]
+ ldp x4, x5, [x29, 48]
+ ldp x6, x7, [x29, 64]
These 3 LDPs are dead.
+ ldp x29, x30, [x29]
+
+ .cfi_remember_state
+ .cfi_restore 30
+ .cfi_restore 29
+ .cfi_def_cfa 31, 0
+
+ ret
More information about the Gcc-patches
mailing list