Skip to content

Commit 65ef20d

Browse files
zangruochenzangruochen
andauthored
Add support for LoongArch (#7343)
* vm_dump.c: Dump machine registers on loongarch64 Linux. * coroutines: Support for native loongarch64 coroutines. --------- Co-authored-by: zangruochen <zangruochen@loongson.cn>
1 parent 2798b13 commit 65ef20d

File tree

4 files changed

+146
-2
lines changed

4 files changed

+146
-2
lines changed

configure.ac

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2623,6 +2623,9 @@ AS_CASE([$coroutine_type], [yes|''], [
26232623
[riscv64-linux*], [
26242624
coroutine_type=riscv64
26252625
],
2626+
[loongarch64-linux*], [
2627+
coroutine_type=loongarch64
2628+
],
26262629
[x86_64-freebsd*], [
26272630
coroutine_type=amd64
26282631
],

coroutine/loongarch64/Context.S

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
#define TOKEN_PASTE(x,y) x##y
2+
#define PREFIXED_SYMBOL(prefix,name) TOKEN_PASTE(prefix,name)
3+
4+
.text
5+
.align 2
6+
7+
.global PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer)
8+
PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer):
9+
10+
# Make space on the stack for caller registers
11+
addi.d $sp, $sp, -0xa0
12+
13+
# Save caller registers
14+
st.d $s0, $sp, 0x00
15+
st.d $s1, $sp, 0x08
16+
st.d $s2, $sp, 0x10
17+
st.d $s3, $sp, 0x18
18+
st.d $s4, $sp, 0x20
19+
st.d $s5, $sp, 0x28
20+
st.d $s6, $sp, 0x30
21+
st.d $s7, $sp, 0x38
22+
st.d $s8, $sp, 0x40
23+
st.d $fp, $sp, 0x48
24+
fst.d $fs0, $sp, 0x50
25+
fst.d $fs1, $sp, 0x58
26+
fst.d $fs2, $sp, 0x60
27+
fst.d $fs3, $sp, 0x68
28+
fst.d $fs4, $sp, 0x70
29+
fst.d $fs5, $sp, 0x78
30+
fst.d $fs6, $sp, 0x80
31+
fst.d $fs7, $sp, 0x88
32+
33+
# Save return address
34+
st.d $ra, $sp, 0x90
35+
36+
# Save stack pointer to a0 (first argument)
37+
st.d $sp, $a0, 0x00
38+
39+
# Load stack pointer from a1 (second argument)
40+
ld.d $sp, $a1, 0x00
41+
42+
# Restore caller registers
43+
ld.d $s0, $sp, 0x00
44+
ld.d $s1, $sp, 0x08
45+
ld.d $s2, $sp, 0x10
46+
ld.d $s3, $sp, 0x18
47+
ld.d $s4, $sp, 0x20
48+
ld.d $s5, $sp, 0x28
49+
ld.d $s6, $sp, 0x30
50+
ld.d $s7, $sp, 0x38
51+
ld.d $s8, $sp, 0x40
52+
ld.d $fp, $sp, 0x48
53+
fld.d $fs0, $sp, 0x50
54+
fld.d $fs1, $sp, 0x58
55+
fld.d $fs2, $sp, 0x60
56+
fld.d $fs3, $sp, 0x68
57+
fld.d $fs4, $sp, 0x70
58+
fld.d $fs5, $sp, 0x78
59+
fld.d $fs6, $sp, 0x80
60+
fld.d $fs7, $sp, 0x88
61+
62+
# Load return address
63+
ld.d $ra, $sp, 0x90
64+
65+
# Pop stack frame
66+
addi.d $sp, $sp, 0xa0
67+
68+
# Jump to return address
69+
jr $ra
70+
71+
#if defined(__linux__) && defined(__ELF__)
72+
.section .note.GNU-stack,"",%progbits
73+
#endif

coroutine/loongarch64/Context.h

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#pragma once
2+
3+
#include <assert.h>
4+
#include <stddef.h>
5+
#include <stdint.h>
6+
#include <string.h>
7+
8+
#define COROUTINE __attribute__((noreturn)) void
9+
10+
enum {COROUTINE_REGISTERS = 0xa0 / 8};
11+
12+
struct coroutine_context
13+
{
14+
void **stack_pointer;
15+
void *argument;
16+
};
17+
18+
typedef COROUTINE(* coroutine_start)(struct coroutine_context *from, struct coroutine_context *self);
19+
20+
static inline void coroutine_initialize_main(struct coroutine_context * context) {
21+
context->stack_pointer = NULL;
22+
}
23+
24+
static inline void coroutine_initialize(
25+
struct coroutine_context *context,
26+
coroutine_start start,
27+
void *stack,
28+
size_t size
29+
) {
30+
assert(start && stack && size >= 1024);
31+
32+
// Stack grows down. Force 16-byte alignment.
33+
char * top = (char*)stack + size;
34+
context->stack_pointer = (void**)((uintptr_t)top & ~0xF);
35+
36+
context->stack_pointer -= COROUTINE_REGISTERS;
37+
memset(context->stack_pointer, 0, sizeof(void*) * COROUTINE_REGISTERS);
38+
39+
context->stack_pointer[0x90 / 8] = (void*)start;
40+
}
41+
42+
struct coroutine_context * coroutine_transfer(struct coroutine_context * current, struct coroutine_context * target);
43+
44+
static inline void coroutine_destroy(struct coroutine_context * context)
45+
{
46+
}

vm_dump.c

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -808,7 +808,7 @@ rb_print_backtrace(void)
808808
#endif
809809

810810
#if defined __linux__
811-
# if defined __x86_64__ || defined __i386__ || defined __aarch64__ || defined __arm__ || defined __riscv
811+
# if defined __x86_64__ || defined __i386__ || defined __aarch64__ || defined __arm__ || defined __riscv || defined __loongarch64
812812
# define HAVE_PRINT_MACHINE_REGISTERS 1
813813
# endif
814814
#elif defined __APPLE__
@@ -837,7 +837,7 @@ print_machine_register(size_t reg, const char *reg_name, int col_count, int max_
837837
# ifdef __linux__
838838
# if defined(__x86_64__) || defined(__i386__)
839839
# define dump_machine_register(reg) (col_count = print_machine_register(mctx->gregs[REG_##reg], #reg, col_count, 80))
840-
# elif defined(__aarch64__) || defined(__arm__) || defined(__riscv)
840+
# elif defined(__aarch64__) || defined(__arm__) || defined(__riscv) || defined(__loongarch64)
841841
# define dump_machine_register(reg, regstr) (col_count = print_machine_register(reg, regstr, col_count, 80))
842842
# endif
843843
# elif defined __APPLE__
@@ -958,6 +958,28 @@ rb_dump_machine_register(const ucontext_t *ctx)
958958
dump_machine_register(mctx->__gregs[REG_S2+7], "s9");
959959
dump_machine_register(mctx->__gregs[REG_S2+8], "s10");
960960
dump_machine_register(mctx->__gregs[REG_S2+9], "s11");
961+
# elif defined __loongarch64
962+
dump_machine_register(mctx->__gregs[LARCH_REG_SP], "sp");
963+
dump_machine_register(mctx->__gregs[LARCH_REG_S0], "s0");
964+
dump_machine_register(mctx->__gregs[LARCH_REG_S1], "s1");
965+
dump_machine_register(mctx->__gregs[LARCH_REG_A0], "a0");
966+
dump_machine_register(mctx->__gregs[LARCH_REG_A0+1], "a1");
967+
dump_machine_register(mctx->__gregs[LARCH_REG_A0+2], "a2");
968+
dump_machine_register(mctx->__gregs[LARCH_REG_A0+3], "a3");
969+
dump_machine_register(mctx->__gregs[LARCH_REG_A0+4], "a4");
970+
dump_machine_register(mctx->__gregs[LARCH_REG_A0+5], "a5");
971+
dump_machine_register(mctx->__gregs[LARCH_REG_A0+6], "a6");
972+
dump_machine_register(mctx->__gregs[LARCH_REG_A0+7], "a7");
973+
dump_machine_register(mctx->__gregs[LARCH_REG_A0+7], "a7");
974+
dump_machine_register(mctx->__gregs[LARCH_REG_S0], "s0");
975+
dump_machine_register(mctx->__gregs[LARCH_REG_S0+1], "s1");
976+
dump_machine_register(mctx->__gregs[LARCH_REG_S0+2], "s2");
977+
dump_machine_register(mctx->__gregs[LARCH_REG_S0+3], "s3");
978+
dump_machine_register(mctx->__gregs[LARCH_REG_S0+4], "s4");
979+
dump_machine_register(mctx->__gregs[LARCH_REG_S0+5], "s5");
980+
dump_machine_register(mctx->__gregs[LARCH_REG_S0+6], "s6");
981+
dump_machine_register(mctx->__gregs[LARCH_REG_S0+7], "s7");
982+
dump_machine_register(mctx->__gregs[LARCH_REG_S0+8], "s8");
961983
# endif
962984
}
963985
# elif defined __APPLE__

0 commit comments

Comments
 (0)