第一章:Go test在申威平台卡死现象的全景观察
在基于申威(SW64)架构的国产服务器上运行 go test 时,大量用户反馈测试进程在执行中途无响应、CPU 占用率骤降至 0%,且无 panic、超时或日志输出,表现为典型的“静默卡死”。该现象并非偶发,已复现于申威 2100/2200 系统(内核 4.19.90 + SW64 Go 1.21.6 构建版),覆盖单元测试、基准测试及带 -race 标志的并发测试场景。
典型复现路径
- 在申威平台交叉编译或原生构建 Go 项目(确保
GOARCH=sw64,GOOS=linux); - 执行
go test -v ./...或针对单包如go test -v -run=TestConcurrentMap; - 进程在某测试用例启动后约 3–37 秒停滞,
strace -p <pid>显示最后系统调用常为futex(0x..., FUTEX_WAIT_PRIVATE, 0, NULL),且阻塞于 golang runtime 的park_m调度点。
关键差异线索
| 维度 | x86_64 平台 | 申威 SW64 平台 |
|---|---|---|
GOMAXPROCS 默认值 |
逻辑 CPU 数 | 恒为 1(即使 nproc=32) |
runtime.nanotime() 精度 |
纳秒级稳定 | 周期性跳变(±200ms),影响 timer 驱动 |
mmap 分配行为 |
支持 MAP_ANONYMOUS |
需显式 MAP_ANONYMOUS \| MAP_NORESERVE |
快速验证脚本
# 检查是否触发卡死前兆:timer 异常抖动
go run - <<'EOF'
package main
import (
"fmt"
"runtime"
"time"
)
func main() {
runtime.GOMAXPROCS(1) // 强制单线程暴露问题
for i := 0; i < 5; i++ {
t0 := time.Now()
time.Sleep(10 * time.Millisecond)
dt := time.Since(t0).Milliseconds()
fmt.Printf("sleep(10ms) actual: %.1f ms\n", dt)
}
}
EOF
若输出中出现 actual: 210.3 ms 等远超预期值,表明底层 timer 子系统已失准,极大概率导致 testing.T.Parallel() 或 time.AfterFunc 相关测试卡死。该现象与申威平台 clock_gettime(CLOCK_MONOTONIC) 实现缺陷强相关,非 Go 源码层可绕过。
第二章:申威sw64平台信号处理机制深度解析
2.1 sw64架构下信号传递路径与内核trap入口分析
sw64处理器采用类Alpha的64位RISC指令集,其信号(signal)交付依赖于精确的异常嵌套与trap处理机制。
trap入口向量布局
sw64内核在arch/sw64/kernel/entry.S中定义trap向量表,其中0x800偏移处为sys_call_trap,0x1000为interrupt_trap,而信号触发的EXC_INT_SSI(Software Signal Interrupt)映射至0x1800。
信号注入关键路径
- 用户态执行
syscall或访存异常后,硬件自动保存r0–r31、psl、pc至内核栈; do_ssi()被调用,解析current->pending中sigpending结构;- 调用
do_signal()完成sigframe构造与用户栈回跳。
# arch/sw64/kernel/entry.S: ssi_trap_handler
0x1800: ldq $r16, SIGMASK($r27) # 加载当前进程信号掩码
andnot $r16, $r16, $r15 # r15 = pending & ~blocked
beq $r16, no_signal # 无待决信号则跳过
jsr $r26, do_ssi # 进入C处理函数
上述汇编中:
$r27指向task_struct基址,SIGMASK为结构体内偏移;$r15暂存待决信号位图,beq实现零信号快速路径优化。
内核trap分发逻辑
| Trap类型 | 触发条件 | 入口函数 |
|---|---|---|
| EXC_INT_SSI | kill(), raise() |
ssi_trap_handler |
| EXC_INT_PAL | PAL调用(如halt) | palcall_trap |
| EXC_INT_MCHK | 机器校验异常 | mcheck_trap |
graph TD
A[用户态执行] -->|触发SSI中断| B[硬件trap至0x1800]
B --> C[保存上下文到pt_regs]
C --> D[调用do_ssi]
D --> E[检查sigpending & ~blocked]
E -->|有信号| F[setup_sigframe + ret_to_user]
E -->|无信号| G[直接返回用户态]
2.2 用户态信号注册与sigaction系统调用在sw64上的行为验证
在 sw64 架构下,sigaction() 系统调用需适配其特有的 ABI 与信号帧布局。用户态注册信号处理函数时,内核需正确保存/恢复浮点寄存器(如 f0–f31)及 sr0(软中断屏蔽位)。
sigaction 调用关键参数验证
struct sigaction sa = {
.sa_handler = handler,
.sa_flags = SA_RESTORER | SA_SIGINFO,
.sa_restorer = __kernel_rt_sigreturn // sw64 特定桩函数地址
};
sigaction(SIGUSR1, &sa, NULL);
sa_restorer必须指向 sw64 内核提供的__kernel_rt_sigreturn(位于arch/sw64/kernel/signal.c),否则用户栈无法安全返回;SA_SIGINFO启用三参数 handler,确保siginfo_t*和ucontext_t*正确传递至用户空间。
sw64 信号上下文寄存器保存差异
| 寄存器组 | 是否自动保存 | 说明 |
|---|---|---|
| 整数通用寄存器 | 是 | r0–r31,含 sp, ra |
| 浮点寄存器 | 是 | f0–f31,区别于 x86_64 |
| 控制寄存器 | 是 | sr0, psr, pc |
graph TD
A[用户调用 sigaction] --> B[内核校验 sa_restorer 地址]
B --> C{是否为有效 sw64 桩?}
C -->|否| D[返回 -EINVAL]
C -->|是| E[注册 handler 并设置信号掩码]
E --> F[触发 SIGUSR1 时构造 sw64 专用 ucontext_t]
2.3 sigprocmask与pending信号队列在sw64内核中的实际实现差异
数据同步机制
sw64内核中,sigprocmask() 不直接修改 task_struct->blocked,而是通过原子位操作配合内存屏障(smp_mb__before_atomic())确保 pending 队列可见性。
// arch/sw64/kernel/signal.c
int do_sigprocmask(int how, sigset_t *set, sigset_t *oldset) {
sigset_t new_blocked;
if (set) {
switch (how) {
case SIG_BLOCK: sigorsets(&new_blocked, ¤t->blocked, set); break;
case SIG_UNBLOCK: signandsets(&new_blocked, ¤t->blocked, set); break;
case SIG_SETMASK: new_blocked = *set; break;
}
// 关键:写入前强制刷新 pending 队列状态
smp_mb__before_atomic();
current->blocked = new_blocked;
}
}
该实现避免了x86中依赖signal_pending()轮询的开销;smp_mb__before_atomic()保证后续对shared_pending或private_pending的检查不会重排序。
pending队列双层结构
sw64采用分离式pending设计:
| 队列类型 | 存储位置 | 触发时机 |
|---|---|---|
shared_pending |
signal_struct |
进程组级信号(如SIGKILL) |
private_pending |
task_struct |
线程私有信号(如SIGUSR1) |
信号投递流程
graph TD
A[send_signal] --> B{是否线程私有?}
B -->|是| C[add_to_queue private_pending]
B -->|否| D[add_to_queue shared_pending]
C & D --> E[check_pending on next syscall/irq]
2.4 GDB动态追踪sw64上SIGCHLD/SIGPROF等测试关键信号的投递链路
在sw64平台调试信号行为时,GDB需结合内核态信号注入点与用户态sigreturn路径协同分析。关键在于定位信号从do_send_sig_info()到do_notify_parent()(SIGCHLD)或posix_timer_event()(SIGPROF)的完整投递路径。
核心追踪断点设置
# 在sw64-gdb中启用内核符号后设置:
(gdb) b do_send_sig_info
(gdb) b do_notify_parent
(gdb) b posix_timer_event
(gdb) set follow-fork-mode child
上述断点覆盖信号生成、子进程通知及定时器触发三类入口;
follow-fork-mode child确保子进程信号被GDB接管,避免被系统直接投递而丢失观测。
sw64信号投递关键路径对比
| 信号类型 | 触发源 | 内核处理函数 | 用户态可见时机 |
|---|---|---|---|
| SIGCHLD | 子进程终止 | do_notify_parent |
wait4() 返回时 |
| SIGPROF | POSIX timer到期 | posix_timer_event |
下一条用户指令前 |
graph TD
A[send_signal syscall] --> B[do_send_sig_info]
B --> C{signal == SIGCHLD?}
C -->|Yes| D[do_notify_parent → wake_up_process]
C -->|No| E[posix_timer_event → send_group_sig_info]
D & E --> F[task_struct->pending.signal bitmap]
F --> G[do_signal → handle_signal]
该流程图揭示:所有信号最终统一经do_signal()分发,但前置路径存在架构敏感分支——sw64的pt_regs寄存器布局差异直接影响handle_signal中sigframe构造逻辑。
2.5 对比x86_64与sw64信号向量表布局及异常帧构造差异实验
信号向量表物理布局差异
x86_64 使用 IDT(Interrupt Descriptor Table),基地址存于 IDTR 寄存器,每个描述符 16 字节;sw64 则采用固定地址 0x10000000 开始的 256 项向量表,每项仅 8 字节,直接存储 handler 地址。
| 特性 | x86_64 | sw64 |
|---|---|---|
| 表起始方式 | IDTR 寄存器动态加载 | 硬编码物理地址 |
| 向量项大小 | 16 字节(含权限/类型) | 8 字节(纯跳转地址) |
| 异常帧压栈顺序 | RSP 先压 RIP/RFLAGS | SP 先压 PC/PSW |
异常帧构造关键代码对比
# x86_64:通用中断入口(简化)
pushq %rax # 保存寄存器
pushq %rbp
movq %rsp, %rdi # 异常帧起始地址作为参数
call do_exception
逻辑分析:x86_64 在进入 handler 前由硬件自动压入 RIP/RFLAGS/CS,再由软件补全通用寄存器,形成完整异常帧;参数 %rdi 指向栈顶即帧首地址,用于上下文提取。
# sw64:同步异常入口(简化)
ldq $1, 0x10($30) # 加载 handler 地址($30 = SP)
jmp ($1)
逻辑分析:sw64 不自动压栈,handler 必须显式读取 PC/PSW(从特殊寄存器 $cr27/$cr28)并手动构建帧;$30 是栈指针,异常发生时已由硬件预置为帧基址。
异常处理流程差异
graph TD
A[异常触发] –> B{x86_64?}
A –> C{sw64?}
B –> D[硬件压栈 RIP/RFLAGS/CS → 跳转 IDT]
C –> E[硬件更新 PC/PSW → 跳转 0x10000000+vec*8]
D –> F[软件补全 GPR → 构建完整帧]
E –> G[软件读 CR27/28 → 手动构造帧]
第三章:Go runtime.sigtramp汇编实现缺陷定位
3.1 Go 1.21+ runtime.sigtramp在sw64目标平台的汇编生成逻辑逆向
Go 1.21 起,runtime.sigtramp 在 sw64 平台不再由手写汇编提供,而是通过 cmd/compile/internal/ssa 后端动态生成。
sigtramp 生成触发点
- 编译器检测到
GOOS=linux GOARCH=sw64且启用信号处理(buildmode=exe) runtime/signal_swr64.go中sigtramp符号被标记为//go:linkname sigtramp runtime.sigtramp
核心生成逻辑
TEXT ·sigtramp(SB), NOSPLIT|NOFRAME, $0-0
MOVQ R15, R14 // 保存旧栈帧指针
MOVQ $0x12345678, R1 // 加载 sigtramp stub 地址(运行时计算)
JMP (R1) // 间接跳转至动态注册的 handler
此汇编由
src/cmd/compile/internal/ssa/gen/sgen_sw64.go中genSigtramp函数生成;R1值在runtime.sighandler初始化时通过atomic.Storeuintptr(&sigtramp_addr, uintptr(unsafe.Pointer(&sighandler)))注入。
关键字段映射表
| 字段 | sw64 寄存器 | 用途 |
|---|---|---|
g 指针 |
R12 | 当前 goroutine 结构体地址 |
sig |
R13 | 信号编号(int32) |
info |
R14 | siginfo_t* |
graph TD
A[compile: ssaGen] --> B{GOARCH==sw64?}
B -->|Yes| C[genSigtramp: emit MOVQ/JMP]
C --> D[runtime.init → install sigtramp_addr]
D --> E[signal delivery → R1 jump]
3.2 sigtramp未正确保存/恢复浮点寄存器导致TestMain栈帧破坏实测
当信号处理函数通过 sigtramp 返回用户态时,若内核未保存/恢复 xmm0–xmm15(x86-64)或 q0–q31(aarch64)等浮点寄存器,TestMain 的浮点计算上下文将被意外覆盖。
栈帧破坏复现路径
- TestMain 中调用
math.Sin(0.5)后暂存结果至xmm0 - 触发
SIGUSR1,进入信号处理函数 sigtramp返回前仅压栈通用寄存器(rax,rbp,rip),忽略xmm*- 恢复后
xmm0为随机值,后续float64运算产生非法内存访问
# 典型有缺陷的 sigtramp 片段(x86-64)
pushq %rax # 保存通用寄存器
pushq %rbp
# ❌ 缺失:movdqa %xmm0, -0x10(%rsp) 等浮点寄存器保存指令
ret
该汇编片段跳过所有 XMM 寄存器的入栈操作,导致浮点状态丢失。%xmm0 在信号返回后不可信,直接用于后续 movsd 指令将污染 TestMain 的局部变量栈槽。
| 寄存器类型 | 是否被 sigtramp 保存 | 影响后果 |
|---|---|---|
%rax, %rbp |
✅ 是 | 控制流正常 |
%xmm0 |
❌ 否 | 浮点中间值被覆写 |
graph TD
A[TestMain: math.Sin] --> B[触发 SIGUSR1]
B --> C[sigtramp 执行]
C --> D{保存 xmm?}
D -->|否| E[返回后 xmm0 脏]
E --> F[TestMain 浮点运算 panic]
3.3 _g_指针切换与M级信号处理上下文在sw64上丢失的内存快照分析
根本诱因:寄存器窗口重叠与_g_别名冲突
sw64架构中,_g_指针被复用于全局数据区与M-mode信号栈基址。当异常嵌套发生时,mtval写入触发_g_重绑定,但未保存原值。
关键寄存器状态快照(异常入口前)
| 寄存器 | 值(十六进制) | 含义 |
|---|---|---|
r21 |
0x8000a000 |
原_g_指向内核全局区 |
sp |
0x9fffe000 |
M-mode栈顶 |
ra |
0x80001234 |
异常返回地址 |
上下文覆盖关键代码段
# sw64汇编片段:M-mode信号入口
mtrap_entry:
stq r21, 0(r22) # r22 = signal_stack_base → 覆盖_g_原始值
mov r21, r22 # _g_ now points to signal stack (NOT global area)
逻辑分析:
r21(即_g_)在未压栈保存前提下被直接赋值为信号栈基址r22。后续ldq r21, 0(r21)将从错误地址加载全局符号,导致current_task等关键结构体解引用失败。参数r22由硬件异常向量动态提供,不可预测。
数据同步机制
- 信号处理前必须执行
save_g_context指令序列 _g_切换需原子化:ldq r23, g_save_area; stq r21, g_save_area; mov r21, r22
graph TD
A[异常触发] --> B{是否首次M-mode进入?}
B -->|否| C[恢复_g_ from g_save_area]
B -->|是| D[保存_r21_到g_save_area]
D --> E[绑定新_g_]
第四章:Go测试框架与TestMain生命周期的平台耦合漏洞
4.1 TestMain函数调用链中runtime_Sigreturn阻塞点的汇编级断点复现
runtime_Sigreturn 是 Go 运行时处理信号返回的关键汇编入口,在 TestMain 启动后、主 goroutine 调度前常因信号上下文恢复而成为隐式阻塞点。
断点复现步骤
- 在
src/runtime/sys_linux_amd64.s中定位runtime·sigreturn符号(非SIGRETURN宏) - 使用
dlv加载测试二进制:dlv exec ./test -- -test.run=^TestMain$ - 设置汇编断点:
break *runtime.sigreturn(注意星号语法)
关键寄存器状态表
| 寄存器 | 典型值(阻塞时) | 语义说明 |
|---|---|---|
RSP |
0xc000000300 |
指向 sigctxt 结构体栈帧 |
RIP |
0x45a2b0 |
runtime.sigreturn 入口地址 |
RAX |
|
系统调用返回值,指示 sigreturn 成功 |
TEXT runtime·sigreturn(SB), NOSPLIT, $0-0
MOVQ SP, AX // 保存当前栈顶供 sigctxt 解析
MOVQ AX, g_m(g) // 关联 M 与信号上下文
CALL runtime·restoreG(SB) // 恢复 goroutine 状态 → 此处可能阻塞
该汇编块执行
restoreG前,若g.status == _Gwaiting且未就绪,将陷入调度器等待。SP所指sigctxt包含被中断的TestMain栈帧快照,是断点分析核心依据。
graph TD
A[TestMain启动] --> B[触发SIGURG或系统调用返回]
B --> C[runtime·sigreturn入口]
C --> D[解析sigctxt中的G/M状态]
D --> E{G是否可运行?}
E -->|否| F[阻塞于restoreG,等待唤醒]
E -->|是| G[恢复TestMain栈并继续]
4.2 testing.M.Run()与runtime.gogo协作时sw64 ABI调用约定违规验证
sw64架构要求函数调用严格遵循ABI规范:前6个整数参数通过r0–r5传递,浮点参数使用f0–f7,且调用方需在栈上预留256字节“寄存器保存区”。当testing.M.Run()经runtime.gogo跳转执行测试函数时,若未重置栈帧或未对齐sp,将触发ABI违规。
关键违规场景
gogo直接跳转不重建调用栈帧- 测试函数入口未校验sp % 16 == 0(sw64强制对齐)
- r0–r5在跳转前后未按ABI语义初始化
违规检测代码片段
// 汇编断言:检查gogo跳转后SP对齐性
check_sp_align:
andi $t0, $sp, 15 // t0 = sp & 0xF
bnez $t0, abi_violation
jr $ra
abi_violation:
li $a0, 0xdeadbeef // 触发panic信号
该汇编嵌入runtime.gogo尾部,用于捕获sp未16字节对齐的ABI违规。andi $t0, $sp, 15提取低4位,非零即违反sw64 ABI栈对齐约束。
| 寄存器 | ABI角色 | 违规后果 |
|---|---|---|
| r0–r5 | 整数参数/返回值 | 参数错乱、返回值污染 |
| sp | 栈顶指针 | 栈溢出或静默内存破坏 |
graph TD
A[testing.M.Run] --> B[runtime.gogo]
B --> C{SP % 16 == 0?}
C -->|否| D[触发abi_violation]
C -->|是| E[继续执行测试函数]
4.3 CGO_ENABLED=0模式下信号拦截失效与cgo初始化绕过路径对比实验
当 CGO_ENABLED=0 时,Go 运行时完全剥离 cgo,导致 os/signal 依赖的底层 sigaction 系统调用注册路径被跳过。
信号注册失效的核心原因
// signal_test.go(CGO_ENABLED=0 构建)
import "os/signal"
func main() {
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, syscall.SIGUSR1) // ❌ 无 effect:runtime.sigtramp 未初始化
}
逻辑分析:signal.Notify 在纯 Go 模式下不触发 runtime.enableSignal,因 cgo 初始化阶段缺失,sigtramp 函数指针仍为 nil,系统信号无法转发至 Go channel。
两种绕过路径对比
| 路径 | 是否触发 cgo 初始化 | 信号可捕获 | 适用场景 |
|---|---|---|---|
CGO_ENABLED=1 + os.Setenv("GODEBUG", "cgocheck=0") |
✅ | ✅ | 兼容性优先 |
CGO_ENABLED=0 + syscall.Signal 直接调用 |
❌ | ❌ | 静态二进制但需自研信号分发 |
关键流程差异
graph TD
A[程序启动] --> B{CGO_ENABLED=1?}
B -->|Yes| C[调用 libc sigaction → runtime.sigtramp]
B -->|No| D[跳过所有 signal setup]
C --> E[Go signal.Notify 可接收]
D --> F[仅支持 syscall.Kill + 自定义轮询]
4.4 自定义TestMain中显式调用runtime.LockOSThread后卡死的最小复现案例
当在自定义 TestMain 中调用 runtime.LockOSThread() 且未配对 runtime.UnlockOSThread(),会导致 Go 运行时调度器无法迁移 goroutine,进而阻塞测试主协程。
复现代码
func TestMain(m *testing.M) {
runtime.LockOSThread() // ⚠️ 锁定当前 OS 线程
os.Exit(m.Run()) // 测试结束后,主线程仍被锁定,runtime 无法安全退出
}
逻辑分析:
m.Run()执行完后,Go 运行时尝试清理并等待所有非守护 goroutine 结束;但因 OS 线程被锁定,且无对应UnlockOSThread(),导致内部fini阶段死锁。参数m *testing.M是测试生命周期控制器,其Run()返回后必须保证线程可调度。
关键约束对比
| 场景 | 是否调用 UnlockOSThread | 行为 |
|---|---|---|
| ✅ 正常退出 | 是 | 测试顺利结束 |
| ❌ 卡死 | 否 | 主线程永久绑定,os.Exit 前 runtime 阻塞 |
修复路径
- 总是在
defer runtime.UnlockOSThread()中配对; - 或仅在需绑定线程的短生命周期 goroutine 内使用。
第五章:国产CPU平台Go生态适配的演进路径
从源码构建到官方支持的关键跃迁
2021年,龙芯中科向Go官方提交了对LoongArch64架构的原生支持补丁(CL 312845),首次实现无需修改标准库即可编译运行net/http、crypto/tls等核心包。该补丁于Go 1.18正式合入,标志着国产CPU首次获得Go语言上游主线的原生支持。此后,统信UOS、麒麟V10等操作系统在默认仓库中启用GOOS=linux GOARCH=loong64交叉编译链,开发者可直接通过go build -o server server.go生成龙芯原生二进制。
麒麟软件与华为欧拉的双轨适配实践
在飞腾FT-2000+/64平台上,麒麟软件团队发现runtime/pprof中部分原子操作未对齐ARM64内存模型,导致火焰图采样丢失率达37%。他们通过补丁修复src/runtime/internal/atomic/atomic_arm64.s中的MOVD指令序列,并推动Go 1.21.0发布补丁版本。华为欧拉则针对鲲鹏920的NUMA拓扑,在GOMAXPROCS调度策略中引入numactl --cpunodebind=0绑定机制,使etcd集群在48核鲲鹏节点上的P99延迟下降42%。
典型兼容性问题与修复对照表
| 问题现象 | 根本原因 | 修复方式 | 影响范围 |
|---|---|---|---|
go test -race在申威SW64上崩溃 |
runtime/race未实现__tsan_read1等函数符号 |
补全src/runtime/race/cc.c中12个SW64汇编桩 |
所有启用了竞态检测的测试套件 |
net.LookupHost超时率>60% |
cgo调用getaddrinfo时未正确处理申威glibc 2.28的AI_ADDRCONFIG标志 |
修改src/net/cgo_unix.go中cgoLookupHost逻辑 |
DNS解析相关服务(如Prometheus exporter) |
Go Modules镜像与私有代理的本地化部署
中国电子云在郑州信创基地部署了Go Proxy集群,采用分层缓存策略:一级缓存为proxy.golang.org的只读镜像(每日同步),二级缓存为本地sum.golang.org验证服务(使用国密SM2签名替换RSA)。当某金融客户使用go mod download github.com/gogo/protobuf@v1.3.2时,请求命中二级缓存后响应时间从平均2.8s降至147ms,且规避了境外模块被篡改风险。
graph LR
A[开发者执行 go build] --> B{GOOS/GOARCH环境变量}
B -->|linux/loong64| C[调用LoongArch64汇编运行时]
B -->|linux/arm64| D[调用鲲鹏优化版gc]
C --> E[链接龙芯libc 2.32+]
D --> F[链接openEuler glibc 2.34]
E --> G[生成龙芯原生ELF]
F --> H[生成鲲鹏原生ELF]
性能调优工具链的国产化替代
针对pprof在兆芯ZX-C+平台浮点采样精度不足问题,上海交大开源项目zxprof实现了基于perf_event_open系统调用的硬件性能计数器直采方案,支持cycles、instructions、cache-misses三类事件,其生成的SVG火焰图与go tool pprof结果偏差小于3.2%。某省级政务云迁移至兆芯平台后,通过zxprof定位到encoding/json中reflect.Value.Call成为热点,改用jsoniter后API吞吐量提升2.7倍。
开源社区协作机制的制度化建设
由中科院软件所牵头成立的“Go for China”SIG小组,已建立RFC流程规范:所有国产平台补丁需经go/src/cmd/compile/internal/ssa静态分析验证、test/目录下新增至少3个平台特化测试用例、并通过龙芯/飞腾/鲲鹏三平台CI门禁(Jenkins流水线编号CICD-GO-CHN-2023)。截至2024年Q2,该小组累计提交217个PR,其中142个被上游合并,覆盖syscall、plugin、debug/gosym等11个子系统。
