diff --git a/README.md b/README.md index 91c2a44..0b180b5 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,8 @@ For Linux aarch64, which fail with `Unknown CPU architecture`: make linux-debug EXTRA_CFLAGS="-D__aarch64__" ``` +> Note: For more CPU architectures, please see [#22](https://github.com/ossrs/state-threads/issues/22) + Linux with valgrind: ```bash @@ -110,6 +112,7 @@ The branch [srs](https://github.com/ossrs/state-threads/tree/srs) will be patche - [x] LOONGARCH: Support loongarch for loongson CPU, [#24](https://github.com/ossrs/state-threads/issues/24). - [x] System: Support Multiple Threads for Linux and Darwin. [#19](https://github.com/ossrs/state-threads/issues/19), [srs#2188](https://github.com/ossrs/srs/issues/2188). - [x] RISCV: Support RISCV for RISCV CPU, [#24](https://github.com/ossrs/state-threads/pull/28). +- [x] MIPS: Support Linux/MIPS64 for loongson 3A4000/3B3000, [#21](https://github.com/ossrs/state-threads/pull/21). - [ ] IDE: Support CLion for debugging and learning. - [ ] System: Support sendmmsg for UDP, [#12](https://github.com/ossrs/state-threads/issues/12). diff --git a/md.h b/md.h index 9968f79..a5c7581 100644 --- a/md.h +++ b/md.h @@ -182,6 +182,10 @@ #error "ARM/Linux pre-glibc2 not supported yet" #endif /* defined(__GLIBC__) && __GLIBC__ >= 2 */ + #elif defined(__mips64) + /* https://github.com/ossrs/state-threads/issues/21 */ + #define MD_USE_BUILTIN_SETJMP + #define MD_GET_SP(_t) *((long *)&((_t)->context[0].__jmpbuf[0])) #elif defined(__mips__) /* https://github.com/ossrs/state-threads/issues/21 */ #define MD_USE_BUILTIN_SETJMP diff --git a/md_linux.S b/md_linux.S index f5e9684..ac194d0 100644 --- a/md_linux.S +++ b/md_linux.S @@ -433,9 +433,87 @@ +#elif defined(__mips64) + + /****************************************************************/ + /* For MIPS64, see https://s3-eu-west-1.amazonaws.com/downloads-mips/documents/MIPS_Architecture_MIPS64_InstructionSet_%20AFP_P_MD00087_06.05.pdf */ + + /* + * Internal __jmp_buf layout + */ + #define JB_SP 0 /* Stack pointer */ + #define JB_RA 11 /* Return address */ + #define JB_GP 1 /* Global pointer */ + #define JB_S0 3 /* S0-S7, Saved temporaries */ + #define JB_S1 4 /* S0-S7, Saved temporaries */ + #define JB_S2 5 /* S0-S7, Saved temporaries */ + #define JB_S3 6 /* S0-S7, Saved temporaries */ + #define JB_S4 7 /* S0-S7, Saved temporaries */ + #define JB_S5 8 /* S0-S7, Saved temporaries */ + #define JB_S6 9 /* S0-S7, Saved temporaries */ + #define JB_S7 10 /* S0-S7, Saved temporaries */ + #define JB_FP 2 /* FP/S8 Frame pointer */ + + .file "md_linux.S" + .text + + /* _st_md_cxt_save(__jmp_buf env) */ /* The env is $a0, https://en.wikipedia.org/wiki/MIPS_architecture#Calling_conventions */ + .globl _st_md_cxt_save + .type _st_md_cxt_save, %function + .align 2 + _st_md_cxt_save: + sd $sp, 0($a0) /* Save sp to env[0], *(long*)($a0+ 0) =sp */ + sd $ra, 8($a0) /* Save ra to env[1], *(long*)($a0+ 8)=ra, the return address, https://chortle.ccsu.edu/AssemblyTutorial/Chapter-26/ass26_4.html */ + sd $gp, 16($a0) /* Save gp to env[2], *(long*)($a0+16) =gp */ + sd $s0, 24($a0) /* Save s0 to env[3], *(long*)($a0+24)=s0 */ + sd $s1, 32($a0) /* Save s1 to env[4], *(long*)($a0+32)=s1 */ + sd $s2, 40($a0) /* Save s2 to env[5], *(long*)($a0+40)=s2 */ + sd $s3, 48($a0) /* Save s3 to env[6], *(long*)($a0+48)=s3 */ + sd $s4, 56($a0) /* Save s4 to env[7], *(long*)($a0+56)=s4 */ + sd $s5, 64($a0) /* Save s5 to env[8], *(long*)($a0+64)=s5 */ + sd $s6, 72($a0) /* Save s6 to env[9], *(long*)($a0+72)=s6 */ + sd $s7, 80($a0) /* Save s7 to env[10], *(long*)($a0+80)=s7 */ + sd $fp, 88($a0) /* Save fp to env[11], *(long*)($a0+88) =fp */ + li $v0, 0 /* Set return value to 0 */ + jr $ra /* Return */ + + .size _st_md_cxt_save, .-_st_md_cxt_save + + /****************************************************************/ + + /* _st_md_cxt_restore(__jmp_buf env, int val) */ + .globl _st_md_cxt_restore + .type _st_md_cxt_restore, %function + .align 2 + _st_md_cxt_restore: + ld $sp, 0($a0) /* Load sp from env[0], sp=*(long*)($a0+ 0) */ + ld $ra, 8($a0) /* Load sp from env[1], ra=*(long*)($a0+ 8), the saved return address */ + ld $gp, 16($a0) /* Load sp from env[2], gp=*(long*)($a0+16) */ + ld $s0, 24($a0) /* Load sp from env[3], s0=*(long*)($a0+24) */ + ld $s1, 32($a0) /* Load sp from env[4], s1=*(long*)($a0+32) */ + ld $s2, 40($a0) /* Load sp from env[5], s2=*(long*)($a0+40) */ + ld $s3, 48($a0) /* Load sp from env[6], s3=*(long*)($a0+48) */ + ld $s4, 56($a0) /* Load sp from env[7], s4=*(long*)($a0+56) */ + ld $s5, 64($a0) /* Load sp from env[8], s5=*(long*)($a0+64) */ + ld $s6, 72($a0) /* Load sp from env[9], s6=*(long*)($a0+72) */ + ld $s7, 80($a0) /* Load sp from env[10], s7=*(long*)($a0+80) */ + ld $fp, 88($a0) /* Load sp from env[2], fp=*(long*)($a0+88) */ + li $v0, 1 /* Set return value to 1 */ + jr $ra /* Return to the saved return address */ + + .size _st_md_cxt_restore, .-_st_md_cxt_restore + + /****************************************************************/ + + + + + + #elif defined(__mips__) /****************************************************************/ + /* For MIPS32, see https://s3-eu-west-1.amazonaws.com/downloads-mips/documents/MD00565-2B-MIPS32-QRC-01.01.pdf */ /* * Internal __jmp_buf layout diff --git a/tools/helloworld/helloworld.c b/tools/helloworld/helloworld.c index 2f3481a..0ce1de5 100644 --- a/tools/helloworld/helloworld.c +++ b/tools/helloworld/helloworld.c @@ -9,7 +9,8 @@ int main(int argc, char** argv) { st_init(); - for (int i = 0; i < 10000; i++) { + int i; + for (i = 0; i < 10000; i++) { printf("#%03d, Hello, state-threads world!\n", i); st_sleep(1); } diff --git a/tools/jmpbuf/.gitignore b/tools/jmpbuf/.gitignore new file mode 100644 index 0000000..2d81d8f --- /dev/null +++ b/tools/jmpbuf/.gitignore @@ -0,0 +1,3 @@ +jmpbuf +jmpbuf.E.c + diff --git a/tools/jmpbuf/Makefile b/tools/jmpbuf/Makefile new file mode 100644 index 0000000..1c063ea --- /dev/null +++ b/tools/jmpbuf/Makefile @@ -0,0 +1,15 @@ +.PHONY: default clean pre + +CFLAGS=-g -O0 + +default: ./jmpbuf pre + +./jmpbuf: jmpbuf.c + $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -Wall -o $@ $^ $(LDLIBS) + +pre: jmpbuf.c + $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -Wall -E -o jmpbuf.E.c $^ $(LDLIBS) + +clean: + rm -f jmpbuf jmpbuf.E.c + diff --git a/tools/jmpbuf/jmpbuf.c b/tools/jmpbuf/jmpbuf.c new file mode 100644 index 0000000..d26d89f --- /dev/null +++ b/tools/jmpbuf/jmpbuf.c @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: MIT */ +/* Copyright (c) 2022 Winlin */ + +#include +#include + +int main(int argc, char** argv) +{ + jmp_buf ctx = {0}; + int r0 = setjmp(ctx); + + int nn_jb = sizeof(ctx); + printf("r0=%d, sizeof(jmp_buf)=%d (unsigned long long [%d])\n", r0, nn_jb, nn_jb/8); + return 0; +} + diff --git a/tools/porting/porting.c b/tools/porting/porting.c index 4e19055..de51565 100644 --- a/tools/porting/porting.c +++ b/tools/porting/porting.c @@ -25,11 +25,14 @@ int main(int argc, char** argv) // https://s3-eu-west-1.amazonaws.com/downloads-mips/documents/MD00565-2B-MIPS32-QRC-01.01.pdf printf("__mips__: %d, __mips: %d, _MIPSEL: %d\n", __mips__, __mips, _MIPSEL); #endif +#ifdef __mips64 + printf("__mips64: %d\n", __mips64); +#endif #ifdef __x86_64__ printf("__x86_64__: %d\n", __x86_64__); #endif #ifdef __loongarch64 - printf("__loongarch64 :%d\n", __loongarch64); + printf("__loongarch__: %d __loongarch64: %d\n", __loongarch__, __loongarch64); #endif #ifdef __riscv printf("__riscv: %d\n", __riscv); @@ -84,9 +87,48 @@ int foo_return_one_arg1(int r0) #if defined(__riscv) || defined(__arm__) || defined(__aarch64__) void print_jmpbuf() { } -#endif +#elif __mips64 +void print_jmpbuf() +{ + // https://en.wikipedia.org/wiki/MIPS_architecture#Calling_conventions + register void* ra asm("ra"); + register void* gp asm("gp"); + register void* sp asm("sp"); + register void* fp asm("fp"); + // $s0–$s7 $16–$23 saved temporaries + register void* s0 asm("s0"); + register void* s1 asm("s1"); + register void* s2 asm("s2"); + register void* s3 asm("s3"); + register void* s4 asm("s4"); + register void* s5 asm("s5"); + register void* s6 asm("s6"); + register void* s7 asm("s7"); -#ifdef __mips__ + /* + typedef unsigned long long __jmp_buf[13]; + typedef struct __jmp_buf_tag { + __jmp_buf __jmpbuf; + int __mask_was_saved; + __sigset_t __saved_mask; + } jmp_buf[1]; + */ + jmp_buf ctx = {0}; + int r0 = setjmp(ctx); + if (!r0) { + longjmp(ctx, 1); + } + + printf("ra=%p, sp=%p, s0=%p, s1=%p, s2=%p, s3=%p, s4=%p, s5=%p, s6=%p, s7=%p, fp=%p, gp=%p\n", + ra, sp, s0, s1, s2, s3, s4, s5, s6, s7, fp, gp); + + int nn_jb = sizeof(ctx[0].__jmpbuf); + printf("sizeof(jmp_buf)=%d (unsigned long long [%d])\n", nn_jb, nn_jb/8); + + unsigned char* p = (unsigned char*)ctx[0].__jmpbuf; + print_buf(p, nn_jb); +} +#elif __mips__ void print_jmpbuf() { // https://en.wikipedia.org/wiki/MIPS_architecture#Calling_conventions @@ -207,7 +249,8 @@ void print_buf(unsigned char* p, int nn_jb) { printf(" "); - for (int i = 0; i < nn_jb; i++) { + int i; + for (i = 0; i < nn_jb; i++) { printf("0x%02x ", (unsigned char)p[i]); int newline = ((i + 1) % sizeof(void*));