You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
winlinvip
changed the title
How to porting ST to other OS and CPU arch? 如何移植ST到其他系统或CPU体系?
How to porting ST to other OS/CPU? 如何移植ST到其他系统或CPU?
Sep 30, 2021
移植ST比想象的要简单很多,最关键的就是实现
setjmp/longjmp
,也就是保存寄存器和恢复寄存器。目前已经实现的OS和CPU如下:
OS
编译ST需要明确指定OS,比如:
make linux-debug
make darwin-debug
make cygwin64-debug
不同的OS的依赖的文件可能不同,如果需要支持其他OS则需要修改Makefile。
CPU
不同CPU的寄存器布局不同,比如Linux下支持多种CPU,一般可以通过宏定义检测到,所以一般都使用如下命令编译:
如果发现报错
Unknown CPU architecture
,那么可以明确指定你的CPU体系:make linux-debug EXTRA_CFLAGS="-D__x86_64__"
make linux-debug EXTRA_CFLAGS="-D__arm__"
make linux-debug EXTRA_CFLAGS="-D__aarch64__"
make linux-debug EXTRA_CFLAGS="-D__mips__"
make linux-debug EXTRA_CFLAGS="-D__mips64"
make linux-debug EXTRA_CFLAGS="-D__loongarch64"
make linux-debug EXTRA_CFLAGS="-D__riscv"
使用命令检测你的CPU,比如检测
armv8/aarch64/arm64
:如果你的CPU不属于已经适配的CPU,就需要适配,也并不难。下面介绍一些适配的工具。
Tools
适配新CPU的工具如下:
jmpbuf
的定义可能会有所不同,我们自己定义了这个数据结构,参考 Define and use a new jmpbuf, because the structure is different. #29 ,有个小工具可以打印这个结构体的定义,是通过gcc -E
预处理指令可以看到头文件中关于jmpbuf
的定义,参考jmpbuf.c。了解这些工具后,可以很方便的适配新的CPU,参考下面的步骤。
Porting
以MIPS为例,我们找下MIPS Calling Conventions,可以看到Callee主要保存以下寄存器:
$gp
global pointer$fp
frame pointer$sp
stack pointer$s0–$s7
saved temporaries我们修改porting.c,增加MIPS下的
print_jmpbuf
,并在OpenWRT上执行,可以看到setjmp
还是明文并没有混淆:可以调试下setjmp,在gdb执行
disassemble
,就可以看到它保存的寄存器:同样的,可以看下longmp,可以发现恢复寄存器后,就是直接跳转到ra的地址:
ASM
接下来就是关键的用汇编实现寄存器保存,根据OS的不同,分成了不同的汇编文件:
md_linux.S
,所有Linux平台的汇编,根据CPU架构(宏)实现不同平台的函数。md_darwin.S
,针对OSX/Mac的汇编,目前实现了x86_64
架构,M1(aarch64)的支持情况请看最开始的表格。md_cygwin64.S
,针对Cygwin64/Windows的汇编,目前实现了x86_64
架构,还没有支持32位Windows。显然
OpenWRT/MIPS
是Linux平台,所以我们先实现两个空函数:然后我们编译ST,用verify.c验证这两个函数是否正常工作。
最后,就是用汇编实现函数,需要找下平台相关的资料。也可以直接通过调试setjmp和longjmp的实现,来学习如何将寄存器保存到jmpbuf,以及如何从jmpbuf恢复):
Build
实现汇编后,有些地方需要修改,比如MIPS的jmpbuf定义不太一样。
一般的jmpbuf定义如下,字段名是
__jmpbuf
:而在MIPS中定义的字段不同,它的字段名是
__jb
:因此,需要我们在
md.h
中定义如何使用jmpbuf,SP是在__jb[0]
的位置:其中,宏定义
MD_GET_SP
,就是如何将jmpbuf的SP,更新为协程的栈地址。这是在MD_INIT_CONTEXT
,也就是创建协程时调用的。HelloWorld
编译成功后,我们使用一个小工具验证,会初始化ST后,不断打印日志,参考helloworld.c。
大功告成。
The text was updated successfully, but these errors were encountered: