From 76ebb7352681fda6a6bc353ae14a78953f4b7f25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E9=98=B3?= <657837019@qq.com> Date: Thu, 5 Mar 2026 16:07:33 +0800 Subject: [PATCH] feat: add riscv64 architecture support for context switching Implement native context switching for RISC-V 64-bit (riscv64) following the LP64D calling convention. Changes: - coctx.h: add regs[16] for riscv64 (14 callee-saved regs + a0/a1 for argument passing) - coctx.cpp: add coctx_make() and coctx_init() for riscv64, initializing ra (entry point), sp (stack pointer), s0 (frame pointer), and a0/a1 (function arguments) - coctx_swap.S: add riscv64 assembly for coctx_swap(), saving/restoring ra, sp, s0-s11, a0, a1 per the RISC-V LP64D ABI This enables libco to compile and run on riscv64 platforms. Verified on OBS (openSUSE Tumbleweed) for both x86_64 and riscv64. --- coctx.cpp | 27 +++++++++++++++++++++++++++ coctx.h | 2 ++ coctx_swap.S | 38 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+) diff --git a/coctx.cpp b/coctx.cpp index d5eeed1..aeb926e 100644 --- a/coctx.cpp +++ b/coctx.cpp @@ -41,6 +41,13 @@ available. #define RCX 11 #define R8 12 #define R9 13 +// ----------- +// RISC-V 64-bit +#define RISCV_RA 0 +#define RISCV_SP 1 +#define RISCV_S0 2 +#define RISCV_A0 14 +#define RISCV_A1 15 //----- -------- // 32 bit @@ -129,4 +136,24 @@ int coctx_init(coctx_t* ctx) { return 0; } +#elif defined(__riscv) && __riscv_xlen == 64 +int coctx_make(coctx_t* ctx, coctx_pfn_t pfn, const void* s, const void* s1) { + char* sp = ctx->ss_sp + ctx->ss_size - sizeof(void*); + sp = (char*)((unsigned long)sp & -16LL); + + memset(ctx->regs, 0, sizeof(ctx->regs)); + + ctx->regs[RISCV_SP] = sp; + ctx->regs[RISCV_RA] = (char*)pfn; + ctx->regs[RISCV_S0] = sp; + ctx->regs[RISCV_A0] = (char*)s; + ctx->regs[RISCV_A1] = (char*)s1; + return 0; +} + +int coctx_init(coctx_t* ctx) { + memset(ctx, 0, sizeof(*ctx)); + return 0; +} + #endif diff --git a/coctx.h b/coctx.h index c1fdfa9..807bee2 100644 --- a/coctx.h +++ b/coctx.h @@ -29,6 +29,8 @@ struct coctx_t { #if defined(__i386__) void *regs[ 8 ]; +#elif defined(__riscv) && __riscv_xlen == 64 + void *regs[ 16 ]; #else void *regs[ 14 ]; #endif diff --git a/coctx_swap.S b/coctx_swap.S index 0e4ce1c..de6bc9e 100644 --- a/coctx_swap.S +++ b/coctx_swap.S @@ -80,4 +80,42 @@ coctx_swap: movq 64(%rsi), %rsi ret +#elif defined(__riscv) && __riscv_xlen == 64 + /* Save curr context registers to regs[] pointed by a0 */ + /* regs layout: [0]=ra [1]=sp [2]=s0 [3]=s1 ... [13]=s11 [14]=a0 [15]=a1 */ + sd ra, 0(a0) + sd sp, 8(a0) + sd s0, 16(a0) + sd s1, 24(a0) + sd s2, 32(a0) + sd s3, 40(a0) + sd s4, 48(a0) + sd s5, 56(a0) + sd s6, 64(a0) + sd s7, 72(a0) + sd s8, 80(a0) + sd s9, 88(a0) + sd s10, 96(a0) + sd s11, 104(a0) + sd a0, 112(a0) + sd a1, 120(a0) + + /* Restore pending context registers from regs[] pointed by a1 */ + ld ra, 0(a1) + ld sp, 8(a1) + ld s0, 16(a1) + ld s1, 24(a1) + ld s2, 32(a1) + ld s3, 40(a1) + ld s4, 48(a1) + ld s5, 56(a1) + ld s6, 64(a1) + ld s7, 72(a1) + ld s8, 80(a1) + ld s9, 88(a1) + ld s10, 96(a1) + ld s11, 104(a1) + ld a0, 112(a1) + ld a1, 120(a1) + ret #endif