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
next prev parent 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.