All of lore.kernel.org
 help / color / mirror / Atom feed
From: Valerie Aurora <val@versity.com>
To: rpdfs-devel@lists.linux.dev
Cc: Valerie Aurora <val@versity.com>
Subject: [PATCH 1/3] Initial support for ARM64, incompatible with x86_64
Date: Tue, 24 Feb 2026 17:33:24 +0100	[thread overview]
Message-ID: <20260224163327.2441-2-val@versity.com> (raw)
In-Reply-To: <20260224163327.2441-1-val@versity.com>

A quick hack to support task switching on ARM64 without any attempt to
make it portable or compatible with x86_64. Will come back to it later
if there is interest.
---
 Makefile           |  9 +++--
 utask/utask.c      | 17 +++++++++-
 utask/utask_asm.S  | 84 ++++++++++++++++++++++++++++++----------------
 utask/utask_defs.h |  2 +-
 4 files changed, 79 insertions(+), 33 deletions(-)

diff --git a/Makefile b/Makefile
index 8253885..6511202 100644
--- a/Makefile
+++ b/Makefile
@@ -3,7 +3,9 @@
 # make every target depend on the makefile
 .EXTRA_PREREQS:= $(abspath $(lastword $(MAKEFILE_LIST)))
 
-CFLAGS := -I. -O2 -ggdb -Wall -Werror -D_FILE_OFFSET_BITS=64 -msse4.2 -fno-strict-aliasing -fno-omit-frame-pointer
+#CFLAGS := -I. -O2 -ggdb -Wall -Werror -D_FILE_OFFSET_BITS=64 -msse4.2 -fno-strict-aliasing -fno-omit-frame-pointer
+
+CFLAGS := -I. -I/usr/lib64/ -O2 -ggdb -Wall -Werror -D_FILE_OFFSET_BITS=64 -fno-strict-aliasing -fno-omit-frame-pointer
 
 # function entrance/exit profiling for uftrace
 CFLAGS += -pg
@@ -16,6 +18,9 @@ LDFLAGS := -Wl,--gc-sections -lxxhash -luring -luuid -lsystemd
 # provide dynamic symbol tables for backtrace()
 LDFLAGS += -rdynamic
 
+# aarch64 needs this to find libraries
+LDFLAGS += -L/usr/lib64/
+
 # build all c files in source directories
 DIR := cli devd shared shared/lk utask
 SRC := $(foreach d,$(DIR),$(wildcard $(d)/*.c))
@@ -73,7 +78,7 @@ $(OBJ_S): %.o: %.S utask/utask_defs.h utask/utask_gen_defs.h
 utask/utask.s: utask/utask.c
 	gcc -I. -S -o ./utask/utask.s  ./utask/utask.c
 
-# extract defines from complied asm so we can include it from asm source
+# extract defines from compiled asm so we can include it from asm source
 utask/utask_gen_defs.h: utask/utask.s
 	grep '#define.*\<UTASK_ASM' utask/utask.s > utask/utask_gen_defs.h
 
diff --git a/utask/utask.c b/utask/utask.c
index 7006f5c..3575b67 100644
--- a/utask/utask.c
+++ b/utask/utask.c
@@ -97,7 +97,7 @@ static struct utask *get_current_utask(void)
 	struct utask *tsk;
 	unsigned long sp;
 
-	asm("movq %%rsp, %0 		\n\t"
+	asm("mov %0, sp 		\n\t"
 	    : "=rm" (sp) : : );
 
 	tsk = (void *)(round_up(sp, UTASK_STACK_SIZE) - sizeof(struct utask));
@@ -405,6 +405,7 @@ int utask_create_name_nowake(char *name, utask_fn_t fn, void *data, struct utask
 	struct utask *tsk = NULL;
 	unsigned long after;
 	void *stack;
+	void *fp;
 	int ret;
 
 	ret = posix_memalign(&stack, UTASK_STACK_SIZE, UTASK_STACK_SIZE);
@@ -439,15 +440,29 @@ int utask_create_name_nowake(char *name, utask_fn_t fn, void *data, struct utask
 	if (!IS_ALIGNED(after, 16))
 		tsk->sp -= 16 - (after & 15);
 
+	/* for alignment (I think?) */
+	push_stack(tsk, NULL);
+
 	/* final null address to terminate backtracing unwinders */
 	push_stack(tsk, NULL);
+
 	/* first switch_to jumps to _entry */
 	push_stack(tsk, utask_entry);
 
+	/* aarch64 wants the return address and the frame pointer on the stack */
+	fp = tsk->sp;
+	push_stack(tsk, fp);
+
 	/* initial zeroed saved registers */
 	tsk->sp -= UTASK_SAVED_BYTES;
 	memset(tsk->sp, 0, UTASK_SAVED_BYTES);
 
+	/* aarch64 - write the frame pointer into the second to last register */
+	*(void **)(tsk->sp) = fp;
+
+	/* aarch64 - write the return address into the last register (link register) */
+	*(void **)(tsk->sp + sizeof(void *)) = utask_entry;
+
 	ret = 0;
 out:
 	if (ret < 0)
diff --git a/utask/utask_asm.S b/utask/utask_asm.S
index a693520..c69a090 100644
--- a/utask/utask_asm.S
+++ b/utask/utask_asm.S
@@ -14,46 +14,48 @@
 # and epilogue.  So we save and restore them as we switch to and from
 # stacks.
 #
-# ``Registers %rbp, %rbx and %r12 through %r15 “belong” to the calling
+# ``Registers %rbp, %rbx and %r12 through %r15 "belong" to the calling
 # function and the called function is required to preserve their
 # values.'' -- x86_64 ABI.
 #
 .macro push_callee_saved
-	push %rbx
-	push %r12
-	push %r13
-	push %r14
-	push %r15
-	push %rbp
+	stp	x19, x20, [sp, #-16]!
+	stp	x21, x22, [sp, #-16]!
+	stp	x23, x24, [sp, #-16]!
+	stp	x25, x26, [sp, #-16]!
+	stp	x27, x28, [sp, #-16]!
+	stp	x29, x30, [sp, #-16]!
 .endm
 
 .macro pop_callee_saved
-	pop %rbp
-	pop %r15
-	pop %r14
-	pop %r13
-	pop %r12
-	pop %rbx
+	ldp	x29, x30, [sp], #16
+	ldp	x27, x28, [sp], #16
+	ldp	x25, x26, [sp], #16
+	ldp	x23, x24, [sp], #16
+	ldp	x21, x22, [sp], #16
+	ldp	x19, x20, [sp], #16
 .endm
 
 #
-# set rbx to the address of the utask struct found at the base of the
+# set x9 to the address of the utask struct found at the base of the
 # stack.
 #
-.macro load_utask_rbx
-	movq %rsp, %rbx
-	andq $UTASK_STACK_BASE_MASK, %rbx
-	addq $(UTASK_STACK_SIZE - UTASK_ASM_SIZEOF_UTASK), %rbx
+.macro load_utask_x9
+	mov	x9, sp
+	mov	x10, #UTASK_STACK_BASE_MASK
+	and	x9, x9, x10
+	mov	x10, #(UTASK_STACK_SIZE - UTASK_ASM_SIZEOF_UTASK)
+	add	x9, x9, x10
 .endm
 
 #
-# int utask_switch_to(utask *utask /* rdi */);
+# int utask_switch_to(utask *utask /* x0 */);
 #
 # Resume execution of a utask that was previously stopped by switching
 # from the scheduler's stack to the task's.
 #
 # Save the calling scheduler's stack pointer, restore the utask's stack
-# pointer, and return into the address that the utask pushed as they
+# pointer, and return into the address that the utask saved as they
 # last called _switch_from.
 #
 # The ret here is returning to the caller of _switch_from, which is void,
@@ -63,8 +65,18 @@
 .type utask_switch_to, @function
 utask_switch_to:
 	push_callee_saved
-	movq %rsp, UTASK_ASM_OFFSETOF_SCHED_SP(%rdi)
-	movq UTASK_ASM_OFFSETOF_SP(%rdi), %rsp
+	// store scheduler/caller sp into utask struct at x0
+	mov x9, x0
+	add x9, x9, UTASK_ASM_OFFSETOF_SCHED_SP
+	mov x10, sp
+	str x10, [x9]
+
+	// load utask sp from utask struct into sp
+	mov x9, x0
+	add x9, x9, UTASK_ASM_OFFSETOF_SP
+	ldr x10, [x9]
+	mov sp, x10
+
 	pop_callee_saved
 	ret
 
@@ -83,11 +95,22 @@ utask_switch_to:
 .type utask_switch_from, @function
 utask_switch_from:
 	push_callee_saved
-	load_utask_rbx
-	movq %rsp, UTASK_ASM_OFFSETOF_SP(%rbx)
-	movq UTASK_ASM_OFFSETOF_SCHED_SP(%rbx), %rsp
+	load_utask_x9 // load the calling utask's utask struct into x9
+
+	// store the utask sp into utask struct
+	mov x10, x9
+	add x10, x10, UTASK_ASM_OFFSETOF_SP // add the utask sp offset
+	mov x11, sp
+	str x11, [x10] // store sp in utask sp
+
+	// load the scheduler sp into the sp of the utask struct in x9
+	mov x10, x9
+	add x10, x10, UTASK_ASM_OFFSETOF_SCHED_SP // add the sched sp offset
+	ldr x11, [x10]
+	mov sp, x11
+
 	pop_callee_saved
-	movq $UTASK_RET_SCHEDULED, %rax
+	mov x0, UTASK_RET_SCHEDULED
 	ret
 
 #
@@ -102,8 +125,11 @@ utask_switch_from:
 .globl utask_finish
 .type utask_finish, @function
 utask_finish:
-	load_utask_rbx
-	movq UTASK_ASM_OFFSETOF_SCHED_SP(%rbx), %rsp
+	// load scheduler sp out of utask struct into sp
+	load_utask_x9
+	add x9, x9, UTASK_ASM_OFFSETOF_SCHED_SP // add the sched sp offset
+	ldr x10, [x9]
+	mov sp, x10
 	pop_callee_saved
-	mov $UTASK_RET_FINISHED, %rax
+	mov x0, UTASK_RET_FINISHED // return UTASK_RET_FINISHED
 	ret
diff --git a/utask/utask_defs.h b/utask/utask_defs.h
index 5f186c3..f5cd62d 100644
--- a/utask/utask_defs.h
+++ b/utask/utask_defs.h
@@ -11,7 +11,7 @@
 #define UTASK_STACK_SIZE	(8 * 1024)
 #define UTASK_STACK_BASE_MASK	(~(UTASK_STACK_SIZE - 1))
 
-#define UTASK_SAVED_BYTES	(6 * 8)
+#define UTASK_SAVED_BYTES	(12 * 8)
 
 #define UTASK_RET_SCHEDULED	0
 #define UTASK_RET_FINISHED	1
-- 
2.49.0


  reply	other threads:[~2026-02-24 16:33 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-02-24 16:33 [PATCH 0/3] rpdfs-progs: ARM64 support and documentation Valerie Aurora
2026-02-24 16:33 ` Valerie Aurora [this message]
2026-02-25 23:36   ` [PATCH 1/3] Initial support for ARM64, incompatible with x86_64 Zach Brown
2026-02-24 16:33 ` [PATCH 2/3] Workaround for short read from io_uring on aarch64 Valerie Aurora
2026-02-25 23:37   ` Zach Brown
2026-02-24 16:33 ` [PATCH 3/3] Update documentation Valerie Aurora
2026-02-25 23:39   ` Zach Brown

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260224163327.2441-2-val@versity.com \
    --to=val@versity.com \
    --cc=rpdfs-devel@lists.linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.