eBPF指令集v1.0使用规范介绍

目的:编译成功的ebpf程序,加载时偶尔会过不了内核bpf verifier,冒出一堆汇编语句。理解ebpf指令集,可以帮助我们调试这类问题。
1. ebpf指令集规范v1.0
本文档是ebpf指令集规范,版本 1.0
1.1 寄存器和使用规范
ebpf有10个通用寄存器和一个只读的栈帧寄存器,他们都是64-bit宽度。
ebpf的寄存器使用规范为:
r0: 保存函数返回值和ebpf程序退出值。
r1 - r5: 用于函数调用参数。
r6 - r9: callee函数负责进入时保存这几个寄存器到栈中,函数退出前再恢复寄存器原有值。(callee saved registers that function calls will preserve)
r10: 只读的栈帧寄存器,用于访问栈。
r0 - r5是临时寄存器,ebpf程序如果希望在函数调用后寄存器值不变,需要自己保存和恢复寄存器。(r0 - r5 are scratch registers and ebpf programs needs to spill/fill them if necessary across calls.)
译者注:
scratch register / temporary register:顾名思义,用于保存临时值或者中间值。
caller 和 callee: a函数中调用b函数,那么 a是caller,b是callee。
caller saved registers 和 callee saved registers
caller saved registers(aka volatile registers, or call-clobbered) callee saved registers(aka non-volatile registers, or call-preserved)
caller函数负责保存和恢复寄存器(也可以不保存和恢复) callee函数负责保存和恢复寄存器,这样寄存器的值在子函数调用后不会改变
更多资料
1.2 指令编码
ebpf有两种编码模式:
基础编码,64bit固定长度编码。
宽指令编码,在基础编码后增加了一个64bit的立即数(imm64)。这样指令为128bit。
基础编码格式,每一列约定为field:
32 bits (msb,最高bit位) 16 bits 4 bits 4 bits 8 bits (lsb,最低比特位)
imm32(立即数) off16(偏移) src_reg(源寄存器) dst_reg(目的寄存器) opcode(操作码)
注意:绝大多数指令不会使用所有的field,不使用的field被置0。
宽指令编码目前只有64-bit立即数指令使用。
1.2.1 指令类型(class)
基础编码中的field的opcode,一共8bit,其中最低位3bit用来保存指令类型:
class value description reference
bpf_ld 0x00 只能用于宽指令,从imm64中加载数据到寄存器 load 和 store指令
bpf_ldx 0x01 从内存中加载数据到dst_reg load 和 store指令
bpf_st 0x02 把imm32数据保存到内存中 load 和 store指令
bpf_stx 0x03 把src_reg寄存器数据保存到内存 load 和 store指令
bpf_alu 0x04 32bit算术运算 算术和跳转指令
bpf_jmp 0x05 64bit跳转操作 算术和跳转指令
bpf_jmp32 0x06 32bit跳转操作 算术和跳转指令
bpf_alu64 0x07 64bit算术运算 算术和跳转指令
1.3 算术和跳转指令
(bpf_alu, bpf_alu64, bpf_jmp和bpf_jmp32)称为算术和跳转指令。8bit的opcode被分为3个部分:
4 bits (msb,最高bit位) 1 bit 3 bits (lsb,最低bit位)
operation code source 指令类型(bpf_alu, bpf_alu64, bpf_jmp或bpf_jmp32)
第4个bit(source)含义:
source value description
bpf_k 0x00 使用32-bitimm32作为源操作数
bpf_x 0x08 使用源寄存器(src_reg)作为源操作数
4个bit的operation code用来存储具体指令操作码。
1.3.1 算术指令(bpf_alu, bpf_alu64)
bpf_alu操作数为32bit,bpf_alu64操作数为64bit。4个bit的operation code编码了如下操作:
operation code value description
bpf_add 0x00 dst += src
bpf_sub 0x10 dst -= src
bpf_mul 0x20 dst *= src
bpf_div 0x30 dst /= src
bpf_or 0x40 dst |= src
bpf_and 0x50 dst &= src
bpf_lsh 0x60 dst <>= src
bpf_neg 0x80 dst = ~src
bpf_mod 0x90 dst %= src
bpf_xor 0xa0 dst ^= src
bpf_mov 0xb0 dst = src
bpf_arsh 0xc0 算术右移操作。对于负数,右移会在左边最高位补上右移次数个1,对于正数则补0
bpf_end 0xd0 字节的swap操作
译者注:
上表中dst一定是指目的寄存器,不支持内存地址。
上表中src可能是源寄存器,也可能是imm32,根据source位(bpf_k或者bpf_x)来区分。
ebpf寄存器都是64bit,根据操作数类型,可以使用全部64bit,也可以只使用其中32bit。
一些例子:
bpf_add | bpf_x | bpf_alu :
dst_reg = (u32) dst_reg + (u32) src_reg;
bpf_xor | bpf_k | bpf_alu64 :
dst_reg = dst_reg + src_reg
bpf_xor | bpf_k | bpf_alu :
dst_reg = (u32) dst_reg ^ (u32) imm32
bpf_xor | bpf_k | bpf_alu64 :
dst_reg = dst_reg ^ imm32
1.3.1.1 字节swap指令
字节swap指令,属于bpf_alu分类,操作码为bpf_end。
字节swap指令操作数只有dst_reg,不操作src_reg和imm32。
opcode中的source位含义现在更改为:
source value description
bpf_to_le 0x00 主机字节序到小端字节序
bpf_to_be 0x08 主字节序序到大端字节序
基础编码格式中的imm32,此时编码了swap操作的位宽。支持:16,32和64bit。
例子:
bpf_alu | bpf_to_le | bpf_end,并且imm32 = 16:
dst_reg = htole16(dst_reg)
bpf_alu | bpf_to_le | bpf_end,并且imm32 = 64:
dst_reg = htole64(dst_reg)
1.3.2 跳转指令(bpf_jmp32, bpf_jmp)
操作数为寄存器,bpf_jmp32使用32bit,bpf_jmp使用64bit,其它行为都一样。operation code含义如下:
operation code value description notes
bpf_ja 0x00 pc += off 仅用在bpf_jmp中
bpf_jeq 0x10 pc += off if dst == src  
bpf_jgt 0x20 pc += off if dst > src unsigned
bpf_jge 0x30 pc += off if dst >= src unsigned
bpf_jset 0x40 pc += off if dst & src  
bpf_jne 0x50 pc += off if dst != src  
bpf_jsgt 0x60 pc += off if dst > src signed
bpf_jsge 0x70 pc += off if dst >= src signed
bpf_call 0x80 函数调用  
bpf_exit 0x90 函数或者程序返回 仅用在bpf_jmp分类中
bpf_jlt 0xa0 pc += off if dst < src unsigned
bpf_jle 0xb0 pc += off if dst <= src unsigned
bpf_jslt 0xc0 pc += off if dst < src signed
bpf_jsle 0xd0 pc += off if dst <= src signed
ebpf程序在调用bpf_exit前,需要把返回值保存在r0寄存器中。
译者注: 上表中的术语:
pc:程序计数器。
off: 基础编码格式中的off16。
src,dst: 都是指的寄存器的值。
1.4 load 和 store指令
bpf_ld, bpf_ldx, bpf_st和bpf_stx指令类型中,8bit的opcode含义为:
3 bits (msb) 2 bit 3 bits (lsb)
mode size 指令类型(bpf_ld, bpf_ldx, bpf_st或bpf_stx)
mode含义是:
mode value description reference
bpf_imm 0x00 64bit立即数指令 64bit立即数指令
bpf_abs 0x20 经典bpf数据包访问(直接) 经典bpf数据包访问指令
bpf_ind 0x40 经典bpf数据包访问(间接) 经典bpf数据包访问指令
bpf_mem 0x60 标准load和store操作 标准load和store指令
bpf_atomic 0xc0 原子操作 原子操作
size含义:
size value description
bpf_w 0x00 字长(4字节)
bpf_h 0x08 半字长(2字节)
bpf_b 0x010 字节(1字节)
bpf_dw 0x18 双字长(8字节)
1.4.1 标准load和store指令
bpf_mem代表了标准load和store指令,这些指令用于寄存器和内存之间传递数据。
bpf_mem | | bpf_stx:
*(size *) (dst_reg + off16) = src_reg
bpf_mem | | bpf_st:
*(size *) (dst_reg + off16) = imm32
bpf_mem | | bpf_ldx:
dst_reg = *(size *) (src_reg + off16)
size 可选值:bpf_b, bpf_h, bpf_w, or bpf_dw
1.4.2 原子操作
原子操作,指的的是对内存的操作,不会被其他ebpf程序中途扰乱。
ebpf所有的原子操作由bpf_atomic指定,例如:
bpf_atomic | bpf_w | bpf_stx :32-bit原子操作。
bpf_atomic | bpf_dw | bpf_stx :64-bit原子操作。
8-bit和16-bit原子操作不支持。
基本编码格式的imm32用来编码真正的原子操作, 以下是简单原子指令:
imm32 value description
bpf_add 0x00 原子加
bpf_or 0x40 原子或
bpf_and 0x50 原子与
bpf_xor 0xa0 原子异或
bpf_atomic | bpf_w | bpf_stx, imm32 = bpf_add,含义:
*(u32 *)(dst_reg + off16) += src_reg
bpf_atomic | bpf_dw | bpf_stx, imm32 = bpf_add, 含义:
*(u64 *)(dst_reg + off16) += src_reg
除了以上比较简单的原子操作,还有2个复杂原子指令:
imm32 value description
bpf_xchg 0xe0|bpf_fetch 原子交换,交换src_reg和(dst_reg + off16)指向内存的值
bpf_cmpxchg 0xf0|bpf_fetch 原子cas.if (*(uxx*)(dst_reg + off16) == r0) { *(uxx*)(dst_reg + off16) = (src_reg) }; 无论是否交换成功,r0都会保存(dst_reg + off16)指向内存的被修改前的原始值。如果是32bit操作数,那么用会0补齐高位后再保存到r0。
bpf_fetch:
imm32 value description
bpf_fetch 0x01 代表需要返回旧值
对于简单原子指令是可选的,如果设置了,src_reg将保存(dst_reg + off16)指向的内存中被修改前的原始值。
对于复杂原子指令是必选的。
1.4.3 64bit立即数指令
mode为bpf_imm的指令,用于ebpf宽指令,有额外的一个imm64值。
目前只有一条指令:
bpf_ld | bpf_dw | bpf_imm,含义为:
dst_reg = imm64
1.4.4 经典bpf数据包访问指令
ebpf之前为了兼容经典bpf,引入了一些访问数据包的指令。现在已经废弃不再使用。


IMX6 MfgTool烧录指导手册
LG计划在华设OLED面板厂 地点花落广州
移远通信斩获七个模组集采项目
机器人上岗 确保企业安全生产
魅族Pro7什么时候上市?魅族Pro7最新消息:高性能、高颜值将开启曲面屏新时代!
eBPF指令集v1.0使用规范介绍
STM32F103的简易串口驱动(查询方式)
T5/T8灯管、led灯管\t8led日光灯专用贴片陶瓷电容
本征的表面赝电容储钠行为简析
你知道洗衣机应该怎么用吗 这里面的窍门你知道吗
无线业资深人士王刚加入莱特波特 担任中国业务副总裁兼总经理
O-RAN到底是什么,它有什么特别之处
重磅!具备商用条件的 5G无人机全球首飞成功
小米手机销量迎来触底反弹的曙光
华为员工家属:华为人收入高背后是全家人的付出
北京首都机场引入令令开门无接触乘梯
索尼今日或发布四款新品手机
斯坦德不做选择题,实现封测物流自动化
湖南温室大棚智能管理系统,自动化集成系统,温室环境采集系统
晶闸管的工作原理、结构及作用