圈内人士都知道Spectre2的漏洞有若干解决方案,目前最优化的当然是retpoline方式,几乎没有性能损耗,另一种次之的是通过更新微码打开软件层对BTB硬件单元的控制,这种方式有10%-15%的性能损耗。
但是retpoline也并非万能,在Skylake架构以上的Intel x86处理器中还有RSB相关的漏洞导致这种方式只在Skylake之前的架构中可用。而AMD则更倾向于lfence这种barrier方式。
为了利用retpoline,XEN内核手动把所有间接近跳转转换为ret形式的跳转。从此内核中再无间接近跳转,这类指令目前算是废了。
下面是retpoline的替代代码,仅仅5行汇编。
.macro IND_THUNK_RETPOLINE reg:req
call 2f
1:
lfence
jmp 1b
2:
mov %\reg, (%rsp)
ret
.endm
为了对间接近跳转赶尽杀绝,GCC同样做了更新。以便和内核中的retpoline紧密结合到一块,全面使能retpoline的支持。
增加了一个新的编译选项,-mindirect-branch=choice
choice可取keep/chunk/chunk-inline/chunk-extern
每一个选项的意思从其名字已经很清楚,XEN中使用的是chunk-extern,因为XEN内核对每个间接的寄存器都提供了一个retpoline的实现,具体看下面代码。
/* Instantiate GEN_INDIRECT_THUNK for each register except %rsp. */
.irp reg, ax, cx, dx, bx, bp, si, di, 8, 9, 10, 11, 12, 13, 14, 15
GEN_INDIRECT_THUNK reg=r\reg
.endr
linux内核没有时间看,估计逻辑实现上也没有大的区别吧。