Lưu ý
Mục đích của file này là để độc giả tiếng Việt có thể đọc và hiểu tài liệu nhân kernel dễ dàng hơn, không phải để tạo ra một nhánh tài liệu riêng. Nếu bạn có bất kỳ nhận xét hoặc cập nhật nào cho file này, vui lòng thử cập nhật file tiếng Anh gốc trước. Nếu bạn thấy có sự khác biệt giữa bản dịch và bản gốc, hoặc có vấn đề về bản dịch, vui lòng gửi góp ý hoặc patch cho người dịch của file này, hoặc nhờ người bảo trì và người review tài liệu tiếng Việt giúp đỡ.
- Bản gốc:
- Người dịch:
Google Translate (machine translation)
- Phiên bản gốc:
8541d8f725c6
Cảnh báo
Tài liệu này được dịch tự động bằng máy và chưa được review bởi người dịch. Nội dung có thể không chính xác hoặc khó hiểu ở một số chỗ. Khi có sự khác biệt với bản gốc, bản gốc luôn là chuẩn. Bản dịch chất lượng cao (được review) được đặt trong thư mục vi_VN/.
1 Kiến trúc tập lệnh BPF (ISA)¶
eBPF, cũng thường được gọi là BPF, là một công nghệ có nguồn gốc từ nhân Linux có thể chạy các chương trình không đáng tin cậy trong bối cảnh đặc quyền chẳng hạn như hạt nhân của hệ điều hành. Tài liệu này chỉ định lệnh BPF kiến trúc tập hợp (ISA).
Như một ghi chú lịch sử, BPF ban đầu là viết tắt của Bộ lọc gói Berkeley, nhưng giờ đây nó có thể làm được nhiều việc hơn là lọc gói, từ viết tắt không còn ý nghĩa nữa. BPF hiện được coi là một thuật ngữ độc lập không đại diện cho bất cứ điều gì. BPF ban đầu đôi khi được gọi dưới dạng cBPF (BPF cổ điển) để phân biệt với phiên bản hiện được triển khai rộng rãi eBPF (BPF mở rộng).
1.1 Quy ước tài liệu¶
Các từ khóa “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “NOT RECOMMENDED”, “MAY” và “OPTIONAL” trong tài liệu này được hiểu như được mô tả trong BCP 14 ZZ0000ZZ ZZ0001ZZ khi nào và chỉ khi nào chúng xuất hiện ở tất cả các chữ hoa, như được hiển thị ở đây.
Để ngắn gọn và nhất quán, tài liệu này đề cập đến các họ các loại sử dụng cú pháp tốc ký và đề cập đến một số cách giải thích, chức năng ghi nhớ khi mô tả ngữ nghĩa của hướng dẫn. Phạm vi giá trị hợp lệ cho các loại đó và ngữ nghĩa của chúng các chức năng được định nghĩa trong các tiểu mục sau.
1.1.1 Các loại¶
Tài liệu này đề cập đến các loại số nguyên có ký hiệu ZZ0000ZZ để chỉ định ký hiệu của loại (ZZ0001ZZ) và độ rộng bit (ZZ0002ZZ), tương ứng.
S |
Meaning |
|---|---|
u |
unsigned |
s |
signed |
N |
Bit width |
|---|---|
8 |
8 bits |
16 |
16 bits |
32 |
32 bits |
64 |
64 bits |
128 |
128 bits |
Ví dụ: ZZ0000ZZ là loại có giá trị hợp lệ là tất cả 32 bit không dấu số và ZZ0001ZZ là loại có giá trị hợp lệ là tất cả các ký hiệu 16 bit những con số.
1.1.2 Chức năng¶
Các hàm hoán đổi byte sau đây không xác định được hướng. Đó là, chức năng tương tự được sử dụng để chuyển đổi theo một trong hai hướng đã thảo luận bên dưới.
be16: Lấy một số 16-bit không dấu và chuyển đổi nó giữa thứ tự byte máy chủ và big-endian (ZZ0000ZZ) thứ tự byte.
be32: Lấy một số 32-bit không dấu và chuyển đổi nó giữa thứ tự byte máy chủ và thứ tự byte cuối lớn.
be64: Lấy một số 64-bit không dấu và chuyển đổi nó giữa thứ tự byte máy chủ và thứ tự byte cuối lớn.
bswap16: Lấy số 16-bit không dấu ở dạng endian lớn hoặc endian nhỏ định dạng và trả về số tương đương có cùng độ rộng bit nhưng độ bền trái ngược nhau.
bswap32: Lấy số 32-bit không dấu ở dạng endian lớn hoặc endian nhỏ định dạng và trả về số tương đương có cùng độ rộng bit nhưng độ bền trái ngược nhau.
bswap64: Lấy số 64-bit không dấu ở dạng endian lớn hoặc endian nhỏ định dạng và trả về số tương đương có cùng độ rộng bit nhưng độ bền trái ngược nhau.
le16: Lấy một số 16-bit không dấu và chuyển đổi nó giữa thứ tự byte máy chủ và thứ tự byte endian nhỏ.
le32: Lấy một số 32-bit không dấu và chuyển đổi nó giữa thứ tự byte máy chủ và thứ tự byte endian nhỏ.
le64: Lấy một số 64-bit không dấu và chuyển đổi nó giữa thứ tự byte máy chủ và thứ tự byte endian nhỏ.
1.1.3 định nghĩa¶
- Sign Extend¶
To sign extend an
X-bit number, A, to aY-bit number, B , means toCopy all
Xbits from A to the lowerXbits of B.Set the value of the remaining
Y-Xbits of B to the value of the most-significant bit of A.
Example
Sign extend an 8-bit number A to a 16-bit number B on a big-endian platform:
A: 10000110
B: 11111111 10000110
1.1.4 Nhóm tuân thủ¶
Việc triển khai không cần hỗ trợ tất cả các hướng dẫn được chỉ định trong tài liệu này tài liệu (ví dụ: hướng dẫn không được dùng nữa). Thay vào đó, một số sự phù hợp các nhóm được chỉ định. Việc triển khai MUST hỗ trợ tuân thủ base32 nhóm và MAY hỗ trợ các nhóm tuân thủ bổ sung, trong đó hỗ trợ một nhóm tuân thủ có nghĩa là MUST hỗ trợ tất cả các hướng dẫn trong sự tuân thủ đó nhóm.
Việc sử dụng các nhóm tuân thủ được đặt tên cho phép khả năng tương tác giữa thời gian chạy thực thi các hướng dẫn và các công cụ như trình biên dịch tạo ra hướng dẫn cho thời gian chạy. Vì vậy, việc phát hiện năng lực về mặt các nhóm tuân thủ có thể được người dùng thực hiện thủ công hoặc tự động bằng các công cụ.
Mỗi nhóm tuân thủ có một nhãn ASCII ngắn (ví dụ: “base32”) tương ứng với một tập hợp các hướng dẫn bắt buộc. Nghĩa là, mỗi hướng dẫn có một hoặc nhiều nhóm tuân thủ mà nó là thành viên.
Tài liệu này xác định các nhóm tuân thủ sau:
base32: bao gồm tất cả các hướng dẫn được xác định trong này đặc điểm kỹ thuật trừ khi có ghi chú khác.
base64: bao gồm base32, cộng với các hướng dẫn được ghi chú rõ ràng như nằm trong nhóm tuân thủ base64.
Atomic32: bao gồm hướng dẫn vận hành nguyên tử 32-bit (xem ZZ0000ZZ).
Atomic64: bao gồm Atomic32, cộng với hướng dẫn vận hành Atomic 64-bit.
divmul32: bao gồm các lệnh chia, nhân và modulo 32-bit.
divmul64: bao gồm divmul32, cộng với phép chia, phép nhân 64-bit, và hướng dẫn modulo.
gói: hướng dẫn truy cập gói không được dùng nữa.
1.2 Mã hóa lệnh¶
BPF có hai mã hóa lệnh:
mã hóa lệnh cơ bản, sử dụng 64 bit để mã hóa lệnh
mã hóa lệnh rộng, gắn thêm 64 bit thứ hai sau lệnh cơ bản với tổng số 128 bit.
1.2.1 Mã hóa lệnh cơ bản¶
Một lệnh cơ bản được mã hóa như sau:
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
ZZ0000ZZ đăng ký ZZ0001ZZ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ZZ0002ZZ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- ZZ0000ZZ
thao tác cần thực hiện, được mã hóa như sau:
Lớp |specific || +-+-+-+-+-+-+-+-+
- ZZ0000ZZ
Định dạng của các bit này thay đổi tùy theo lớp lệnh
- ZZ0001ZZ
Lớp hướng dẫn (xem ZZ0000ZZ)
- ZZ0000ZZ
Số thanh ghi nguồn và đích, được mã hóa như sau trên một máy chủ endian nhỏ:
|src_reg|dst_reg| +-+-+-+-+-+-+-+-+
và như sau trên máy chủ lớn:
+-+-+-+-+-+-+-+-+
|dst_reg|src_reg| +-+-+-+-+-+-+-+-+
- ZZ0001ZZ
số thanh ghi nguồn (0-10), trừ khi có quy định khác (ZZ0000ZZ tái sử dụng trường này cho các mục đích khác)
- ZZ0000ZZ
số thanh ghi đích (0-10), trừ khi có quy định khác (các hướng dẫn trong tương lai có thể sử dụng lại trường này cho các mục đích khác)
- ZZ0000ZZ
Độ lệch số nguyên có dấu được sử dụng với số học con trỏ, ngoại trừ khi được chỉ định khác (một số lệnh số học sử dụng lại trường này cho các mục đích khác)
- ZZ0000ZZ
giá trị tức thời của số nguyên đã ký
Lưu ý rằng nội dung của các trường nhiều byte (‘offset’ và ‘imm’) là được lưu trữ bằng cách sử dụng thứ tự byte lớn trên các máy chủ lớn và Thứ tự byte little-endian trên các máy chủ endian nhỏ.
Ví dụ:
- opcode bù đắp imm lắp ráp
src_reg dst_reg
- 07 0 1 00 00 44 33 22 11 r1 += 0x11223344 // nhỏ
dst_reg src_reg
07 1 0 00 00 11 22 33 44 r1 += 0x11223344 // lớn
Lưu ý rằng hầu hết các hướng dẫn không sử dụng tất cả các trường. Các trường không sử dụng SHALL sẽ bị xóa về 0.
1.2.2 Mã hóa lệnh rộng¶
Một số lệnh được xác định để sử dụng mã hóa lệnh rộng, sử dụng hai giá trị tức thời 32 bit. 64 bit sau định dạng lệnh cơ bản chứa một lệnh giả với ‘opcode’, ‘dst_reg’, ‘src_reg’ và ‘offset’ đều được đặt thành 0.
Điều này được mô tả trong hình sau:
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
ZZ0000ZZ đăng ký ZZ0001ZZ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ZZ0002ZZ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ZZ0003ZZ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ZZ0004ZZ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- ZZ0000ZZ
thao tác cần thực hiện, được mã hóa như đã giải thích ở trên
- ZZ0000ZZ
Số thanh ghi nguồn và đích (trừ khi có quy định khác) được chỉ định), được mã hóa như đã giải thích ở trên
- ZZ0000ZZ
offset số nguyên có dấu được sử dụng với số học con trỏ, trừ khi quy định khác
- ZZ0000ZZ
giá trị tức thời của số nguyên đã ký
- ZZ0000ZZ
không sử dụng, đặt về 0
- ZZ0000ZZ
giá trị ngay lập tức của số nguyên có dấu thứ hai
1.2.3 Lớp hướng dẫn¶
Ba bit có trọng số thấp nhất của trường ‘opcode’ lưu trữ lớp lệnh:
class |
value |
description |
reference |
|---|---|---|---|
LD |
0x0 |
non-standard load operations |
|
LDX |
0x1 |
load into register operations |
|
ST |
0x2 |
store from immediate operations |
|
STX |
0x3 |
store from register operations |
|
ALU |
0x4 |
32-bit arithmetic operations |
|
JMP |
0x5 |
64-bit jump operations |
|
JMP32 |
0x6 |
32-bit jump operations |
|
ALU64 |
0x7 |
64-bit arithmetic operations |
1.3 Hướng dẫn tính toán và nhảy¶
Đối với các lệnh số học và nhảy (ZZ0000ZZ, ZZ0001ZZ, ZZ0002ZZ và ZZ0003ZZ), trường ‘opcode’ 8 bit được chia thành ba phần:
+-+-+-+-+-+-+-+-+
code |s|class|
- ZZ0000ZZ
mã hoạt động, có ý nghĩa thay đổi tùy theo lớp lệnh
- ZZ0000ZZ
vị trí toán hạng nguồn, trừ khi có quy định khác, là một trong:
Source operand location¶ source
value
description
K
0
use 32-bit ‘imm’ value as source operand
X
1
use ‘src_reg’ register value as source operand
- ZZ0001ZZ
lớp hướng dẫn (xem ZZ0000ZZ)
1.3.1 Hướng dẫn số học¶
ZZ0000ZZ sử dụng toán hạng rộng 32 bit trong khi ZZ0001ZZ sử dụng toán hạng rộng 64 bit cho mặt khác hoạt động giống hệt nhau. Lệnh ZZ0002ZZ thuộc về nhóm tuân thủ base64 trừ khi có ghi chú khác. Trường ‘code’ mã hóa hoạt động như bên dưới, trong đó ‘src’ đề cập đến toán hạng nguồn và ‘dst’ đề cập đến giá trị của đích đăng ký.
name |
code |
offset |
description |
|---|---|---|---|
ADD |
0x0 |
0 |
dst += src |
SUB |
0x1 |
0 |
dst -= src |
MUL |
0x2 |
0 |
dst *= src |
DIV |
0x3 |
0 |
dst = (src != 0) ? (dst / src) : 0 |
SDIV |
0x3 |
1 |
dst = (src == 0) ? 0 : ((src == -1 && dst == LLONG_MIN) ? LLONG_MIN : (dst s/ src)) |
OR |
0x4 |
0 |
dst |= src |
AND |
0x5 |
0 |
dst &= src |
LSH |
0x6 |
0 |
dst <<= (src & mask) |
RSH |
0x7 |
0 |
dst >>= (src & mask) |
NEG |
0x8 |
0 |
dst = -dst |
MOD |
0x9 |
0 |
dst = (src != 0) ? (dst % src) : dst |
SMOD |
0x9 |
1 |
dst = (src == 0) ? dst : ((src == -1 && dst == LLONG_MIN) ? 0: (dst s% src)) |
XOR |
0xa |
0 |
dst ^= src |
MOV |
0xb |
0 |
dst = src |
MOVSX |
0xb |
8/16/32 |
dst = (s8,s16,s32)src |
ARSH |
0xc |
0 |
sign extending dst >>= (src & mask) |
END |
0xd |
0 |
byte swap operations (see `Byte swap instructions`_ below) |
Cho phép tràn và tràn trong các phép tính số học, nghĩa là giá trị 64 bit hoặc 32 bit sẽ bao bọc. Nếu việc thực hiện chương trình BPF sẽ dẫn đến chia cho 0, thay vào đó, thanh ghi đích được đặt thành 0. Mặt khác, đối với ZZ0000ZZ, nếu việc thực thi sẽ dẫn đến ZZ0001ZZ chia cho -1, thay vào đó, thanh ghi đích được đặt thành ZZ0002ZZ. cho ZZ0003ZZ, nếu việc thực thi sẽ dẫn đến ZZ0004ZZ chia cho -1, thì thay vào đó, thanh ghi đích được đặt thành ZZ0005ZZ.
Nếu việc thực thi dẫn đến modulo bằng 0, đối với ZZ0000ZZ, giá trị của thanh ghi đích không thay đổi trong khi đối với ZZ0001ZZ thì giá trị trên 32 bit của thanh ghi đích bằng 0. Mặt khác, đối với ZZ0002ZZ, nếu việc thực thi sẽ tiếp tục ở ZZ0003ZZ modulo -1, thì đích thay vào đó, thanh ghi được đặt thành 0. Đối với ZZ0004ZZ, nếu việc thực thi sẽ dẫn đến ZZ0005ZZ modulo -1, thay vào đó, thanh ghi đích được đặt thành 0.
ZZ0000ZZ, trong đó ‘mã’ = ZZ0001ZZ, ‘nguồn’ = ZZ0002ZZ và ‘class’ = ZZ0003ZZ, có nghĩa là:
dst = (u32) ((u32) dst + (u32) src)
trong đó ‘(u32)’ chỉ ra rằng 32 bit trên bằng 0.
ZZ0000ZZ có nghĩa là:
dst = dst + src
ZZ0000ZZ có nghĩa là:
dst = (u32) dst ^ (u32) imm
ZZ0000ZZ có nghĩa là:
dst = dst ^ im
Lưu ý rằng hầu hết các lệnh số học đều có ‘offset’ được đặt thành 0. Chỉ có ba lệnh (ZZ0000ZZ, ZZ0001ZZ, ZZ0002ZZ) có ‘độ lệch’ khác 0.
Các phép chia, nhân và modulo cho ZZ0000ZZ là một phần của nhóm tuân thủ “divmul32” và phép chia, phép nhân và các hoạt động modulo cho ZZ0001ZZ là một phần của tuân thủ “divmul64” nhóm. Các phép toán chia và modulo hỗ trợ cả hai loại có dấu và không dấu.
Đối với các hoạt động không dấu (ZZ0001ZZ và ZZ0002ZZ), đối với ZZ0003ZZ, ‘imm’ được hiểu là giá trị không dấu 32 bit. Đối với ZZ0004ZZ, ‘imm’ đầu tiên là ZZ0000ZZ từ 32 đến 64 bit, sau đó được hiểu là giá trị không dấu 64 bit.
Đối với các hoạt động đã ký (ZZ0001ZZ và ZZ0002ZZ), đối với ZZ0003ZZ, ‘imm’ được hiểu là giá trị có chữ ký 32 bit. Đối với ZZ0004ZZ, ‘tôi’ đầu tiên là ZZ0000ZZ từ 32 đến 64 bit, sau đó được hiểu là giá trị có chữ ký 64 bit.
Lưu ý rằng có nhiều định nghĩa khác nhau về phép toán modulo đã ký khi số bị chia hoặc số chia là số âm, khi việc thực hiện thường khác nhau tùy theo ngôn ngữ như Python, Ruby, v.v. khác với C, Go, Java, v.v. Thông số kỹ thuật này yêu cầu modulo MUST đã ký sử dụng phép chia cắt ngắn (trong đó -13 % 3 == -1) như được triển khai trong C, Go, v.v.:
a % n = a - n * trunc(a / n)
Lệnh ZZ0002ZZ thực hiện thao tác di chuyển với phần mở rộng dấu. ZZ0003ZZ ZZ0000ZZ Toán hạng 8 bit và 16 bit thành Toán hạng 32 bit và đưa về 0 cho 32 bit trên còn lại. ZZ0004ZZ ZZ0001ZZ 8 bit, 16 bit và 32 bit toán hạng thành toán hạng 64-bit. Không giống như các hướng dẫn số học khác, ZZ0005ZZ chỉ được xác định cho toán hạng nguồn đăng ký (ZZ0006ZZ).
ZZ0000ZZ có nghĩa là:
dst = (s64)tôimm
ZZ0000ZZ có nghĩa là:
dst = (u32)src
ZZ0000ZZ với ‘offset’ 8 có nghĩa là:
dst = (u32)(s32)(s8)src
Lệnh ZZ0000ZZ chỉ được xác định khi bit nguồn rõ ràng (ZZ0001ZZ).
Các thao tác thay đổi sử dụng mặt nạ 0x3F (63) cho các thao tác 64 bit và 0x1F (31) cho các hoạt động 32-bit.
1.3.2 Hướng dẫn hoán đổi byte¶
Lệnh hoán đổi byte sử dụng các lớp lệnh ZZ0000ZZ và ZZ0001ZZ và trường ‘mã’ 4 bit của ZZ0002ZZ.
Lệnh hoán đổi byte hoạt động trên thanh ghi đích chỉ và không sử dụng thanh ghi nguồn riêng biệt hoặc giá trị tức thời.
Đối với ZZ0000ZZ, trường toán hạng nguồn 1 bit trong opcode được sử dụng để chọn thứ tự byte mà thao tác chuyển đổi từ hoặc sang. cho ZZ0001ZZ, trường toán hạng nguồn 1 bit trong opcode được bảo lưu và MUST được đặt thành 0.
class |
source |
value |
description |
|---|---|---|---|
ALU |
LE |
0 |
convert between host byte order and little endian |
ALU |
BE |
1 |
convert between host byte order and big endian |
ALU64 |
Reserved |
0 |
do byte swap unconditionally |
Trường ‘imm’ mã hóa độ rộng của hoạt động hoán đổi. Các chiều rộng sau được hỗ trợ: 16, 32 và 64. Các phép toán có chiều rộng 64 thuộc về base64 nhóm tuân thủ và các hoạt động hoán đổi khác thuộc về base32 nhóm tuân thủ.
Ví dụ:
ZZ0000ZZ với ‘imm’ = 16/32/64 có nghĩa là:
- dst = le16(dst)
dst = le32(dst) dst = le64(dst)
ZZ0000ZZ với ‘imm’ = 16/32/64 có nghĩa là:
- dst = be16(dst)
dst = be32(dst) dst = be64(dst)
ZZ0000ZZ với ‘imm’ = 16/32/64 có nghĩa là:
- dst = bswap16(dst)
dst = bswap32(dst) dst = bswap64(dst)
1.3.3 Hướng dẫn nhảy¶
ZZ0000ZZ sử dụng toán hạng rộng 32 bit và biểu thị base32 nhóm tuân thủ, trong khi ZZ0001ZZ sử dụng toán hạng rộng 64-bit cho nếu không thì các hoạt động giống hệt nhau và cho biết sự tuân thủ base64 nhóm trừ khi có quy định khác. Trường ‘code’ mã hóa hoạt động như sau:
code |
value |
src_reg |
description |
notes |
|---|---|---|---|---|
JA |
0x0 |
0x0 |
PC += offset |
{JA, K, JMP} only |
JA |
0x0 |
0x0 |
PC += imm |
{JA, K, JMP32} only |
JEQ |
0x1 |
any |
PC += offset if dst == src |
|
JGT |
0x2 |
any |
PC += offset if dst > src |
unsigned |
JGE |
0x3 |
any |
PC += offset if dst >= src |
unsigned |
JSET |
0x4 |
any |
PC += offset if dst & src |
|
JNE |
0x5 |
any |
PC += offset if dst != src |
|
JSGT |
0x6 |
any |
PC += offset if dst > src |
signed |
JSGE |
0x7 |
any |
PC += offset if dst >= src |
signed |
CALL |
0x8 |
0x0 |
call helper function by static ID |
{CALL, K, JMP} only, see `Helper functions`_ |
CALL |
0x8 |
0x1 |
call PC += imm |
{CALL, K, JMP} only, see `Program-local functions`_ |
CALL |
0x8 |
0x2 |
call helper function by BTF ID |
{CALL, K, JMP} only, see `Helper functions`_ |
EXIT |
0x9 |
0x0 |
return |
{CALL, K, JMP} only |
JLT |
0xa |
any |
PC += offset if dst < src |
unsigned |
JLE |
0xb |
any |
PC += offset if dst <= src |
unsigned |
JSLT |
0xc |
any |
PC += offset if dst < src |
signed |
JSLE |
0xd |
any |
PC += offset if dst <= src |
signed |
trong đó ‘PC’ biểu thị bộ đếm chương trình và độ lệch tăng dần theo được tính theo đơn vị của lệnh 64-bit tương ứng với lệnh sau lệnh nhảy. Do đó ‘PC += 1’ bỏ qua việc thực hiện lệnh tiếp theo hướng dẫn nếu đó là hướng dẫn cơ bản hoặc dẫn đến hành vi không xác định nếu lệnh tiếp theo là lệnh rộng 128 bit.
Ví dụ:
ZZ0000ZZ có nghĩa là:
if (s32)dst s>= (s32)src goto +offset
trong đó ‘s>=’ biểu thị so sánh có dấu ‘>=’.
ZZ0000ZZ có nghĩa là:
if dst <= (u64)(s64)imm goto +offset
ZZ0000ZZ có nghĩa là:
gotol +imm
trong đó ‘imm’ có nghĩa là phần bù nhánh xuất phát từ trường ‘imm’.
Lưu ý rằng có hai loại lệnh ZZ0000ZZ. các Lớp ZZ0001ZZ cho phép độ lệch bước nhảy 16 bit được chỉ định bởi ‘độ lệch’ trường, trong khi lớp ZZ0002ZZ cho phép bù bước nhảy 32 bit được chỉ định bởi trường ‘imm’. Có thể có bước nhảy có điều kiện > 16-bit được chuyển đổi thành bước nhảy có điều kiện < 16 bit cộng với bước nhảy vô điều kiện 32 bit nhảy.
Tất cả các lệnh ZZ0000ZZ và ZZ0001ZZ đều thuộc về nhóm tuân thủ base32.
1.3.3.1 Chức năng trợ giúp¶
Các hàm trợ giúp là một khái niệm trong đó các chương trình BPF có thể gọi vào một tập hợp các lệnh gọi hàm được nền tảng cơ bản hiển thị.
Trước đây, mỗi chức năng trợ giúp được xác định bằng một ID tĩnh được mã hóa trong trường ‘imm’. Tài liệu bổ sung về các chức năng trợ giúp nằm ngoài phạm vi của tài liệu này và việc tiêu chuẩn hóa được dành cho công việc trong tương lai, nhưng việc sử dụng được triển khai rộng rãi và có thể cung cấp thêm thông tin được tìm thấy trong tài liệu dành riêng cho nền tảng (ví dụ: tài liệu về nhân Linux).
Các nền tảng hỗ trợ Định dạng loại BPF (BTF) hỗ trợ nhận dạng chức năng trợ giúp bằng ID BTF được mã hóa trong trường ‘imm’, trong đó ID BTF xác định tên và loại trợ giúp. Tài liệu bổ sung về BTF nằm ngoài phạm vi của tài liệu này và việc tiêu chuẩn hóa được dành cho công việc trong tương lai, nhưng việc sử dụng được triển khai rộng rãi và có thể cung cấp thêm thông tin được tìm thấy trong tài liệu dành riêng cho nền tảng (ví dụ: tài liệu về nhân Linux).
1.3.3.2 Các hàm cục bộ của chương trình¶
Các hàm cục bộ của chương trình là các hàm được hiển thị bởi cùng một chương trình BPF như người gọi và được tham chiếu bằng offset từ lệnh sau lệnh gọi hướng dẫn, tương tự như ZZ0000ZZ. Phần bù được mã hóa trong trường ‘imm’ của lệnh gọi. ZZ0001ZZ trong hàm chương trình cục bộ sẽ quay lại với người gọi.
1.4 Hướng dẫn tải và lưu trữ¶
Để biết hướng dẫn tải và lưu trữ (ZZ0000ZZ, ZZ0001ZZ, ZZ0002ZZ và ZZ0003ZZ), Trường ‘opcode’ 8 bit được chia như sau:
+-+-+-+-+-+-+-+-+
- ZZ0000ZZ
Công cụ sửa đổi chế độ là một trong:
Mode modifier¶ mode modifier
value
description
reference
IMM
0
64-bit immediate instructions
ABS
1
legacy BPF packet access (absolute)
IND
2
legacy BPF packet access (indirect)
MEM
3
regular load and store operations
MEMSX
4
sign-extension load operations
ATOMIC
6
atomic operations
- ZZ0000ZZ
Công cụ sửa đổi kích thước là một trong:
Size modifier¶ size
value
description
W
0
word (4 bytes)
H
1
half word (2 bytes)
B
2
byte
DW
3
double word (8 bytes)
Hướng dẫn sử dụng ZZ0000ZZ thuộc nhóm tuân thủ base64.
- ZZ0001ZZ
Lớp hướng dẫn (xem ZZ0000ZZ)
1.4.1 Hoạt động tải và lưu trữ thường xuyên¶
Bộ sửa đổi chế độ ZZ0000ZZ được sử dụng để mã hóa tải và lưu trữ thông thường lệnh truyền dữ liệu giữa thanh ghi và bộ nhớ.
ZZ0000ZZ có nghĩa là:
ZZ0000ZZ) (dst + offset) = src
ZZ0000ZZ có nghĩa là:
ZZ0000ZZ) (dst + offset) = imm
ZZ0000ZZ có nghĩa là:
dst = ZZ0000ZZ) (src + offset)
Trong đó ‘<size>’ là một trong: ZZ0000ZZ, ZZ0001ZZ, ZZ0002ZZ hoặc ZZ0003ZZ và ‘kích thước không dấu’ là một trong: u8, u16, u32 hoặc u64.
1.4.2 Hoạt động tải tiện ích mở rộng đăng nhập¶
Bộ sửa đổi chế độ ZZ0001ZZ được sử dụng để mã hóa tải ZZ0000ZZ lệnh truyền dữ liệu giữa thanh ghi và bộ nhớ.
ZZ0000ZZ có nghĩa là:
dst = ZZ0000ZZ) (src + offset)
Trong đó ‘<size>’ là một trong: ZZ0000ZZ, ZZ0001ZZ hoặc ZZ0002ZZ và ‘kích thước đã ký’ là một trong: s8, s16 hoặc s32.
1.4.3 Hoạt động nguyên tử¶
Các thao tác nguyên tử là các thao tác thực hiện trên bộ nhớ và không thể bị gián đoạn hoặc bị hỏng bởi quyền truy cập khác vào cùng vùng bộ nhớ bởi các chương trình BPF khác hoặc các phương tiện nằm ngoài thông số kỹ thuật này.
Tất cả các hoạt động nguyên tử được BPF hỗ trợ đều được mã hóa dưới dạng các hoạt động lưu trữ sử dụng công cụ sửa đổi chế độ ZZ0000ZZ như sau:
ZZ0000ZZ cho các hoạt động 32-bit, một phần của nhóm tuân thủ “atomic32”.
ZZ0001ZZ cho hoạt động 64-bit, một phần của nhóm tuân thủ “atomic64”.
Không hỗ trợ các hoạt động nguyên tử rộng 8 bit và 16 bit.
Trường ‘imm’ được sử dụng để mã hóa hoạt động nguyên tử thực tế. Hoạt động nguyên tử đơn giản sử dụng một tập hợp con các giá trị được xác định để mã hóa các phép toán số học trong trường ‘imm’ để mã hóa phép toán nguyên tử:
imm |
value |
description |
|---|---|---|
ADD |
0x00 |
atomic add |
OR |
0x40 |
atomic or |
AND |
0x50 |
atomic and |
XOR |
0xa0 |
atomic xor |
ZZ0000ZZ với ‘imm’ = ADD có nghĩa là:
ZZ0000ZZ)(dst + offset) += src
ZZ0000ZZ với ‘imm’ = ADD có nghĩa là:
ZZ0000ZZ)(dst + offset) += src
Ngoài các phép toán nguyên tử đơn giản, còn có một phép sửa đổi và hai hoạt động nguyên tử phức tạp:
imm |
value |
description |
|---|---|---|
FETCH |
0x01 |
modifier: return old value |
XCHG |
0xe0 | FETCH |
atomic exchange |
CMPXCHG |
0xf0 | FETCH |
atomic compare and exchange |
Công cụ sửa đổi ZZ0000ZZ là tùy chọn cho các hoạt động nguyên tử đơn giản và luôn được thiết lập cho các hoạt động nguyên tử phức tạp. Nếu cờ ZZ0001ZZ được thiết lập thì thao tác cũng sẽ ghi đè lên ZZ0002ZZ với giá trị đã có trong bộ nhớ trước khi nó được sửa đổi.
Hoạt động ZZ0000ZZ trao đổi nguyên tử ZZ0001ZZ với giá trị được giải quyết bởi ZZ0002ZZ.
Hoạt động ZZ0000ZZ so sánh nguyên tử giá trị được xử lý bởi ZZ0001ZZ với ZZ0002ZZ. Nếu chúng khớp nhau, giá trị được xử lý bởi ZZ0003ZZ được thay thế bằng ZZ0004ZZ. Trong cả hai trường hợp, giá trị ở ZZ0005ZZ trước khi hoạt động được mở rộng bằng 0 và tải trở lại ZZ0006ZZ.
1.4.4 Hướng dẫn tức thời 64-bit¶
Các lệnh với công cụ sửa đổi ‘chế độ’ ZZ0000ZZ sử dụng lệnh rộng mã hóa được xác định trong ZZ0001ZZ và sử dụng trường ‘src_reg’ của hướng dẫn cơ bản để giữ một kiểu con opcode.
Bảng sau định nghĩa một tập lệnh ZZ0000ZZ với các kiểu con opcode trong trường ‘src_reg’, sử dụng các thuật ngữ mới như “map” được xác định thêm dưới đây:
src_reg |
pseudocode |
imm type |
dst type |
|---|---|---|---|
0x0 |
dst = (next_imm << 32) | imm |
integer |
integer |
0x1 |
dst = map_by_fd(imm) |
map fd |
map |
0x2 |
dst = map_val(map_by_fd(imm)) + next_imm |
map fd |
data address |
0x3 |
dst = var_addr(imm) |
variable id |
data address |
0x4 |
dst = code_addr(imm) |
integer |
code address |
0x5 |
dst = map_by_idx(imm) |
map index |
map |
0x6 |
dst = map_val(map_by_idx(imm)) + next_imm |
map index |
data address |
Ở đâu
map_by_fd(imm) có nghĩa là chuyển đổi bộ mô tả tệp 32 bit thành địa chỉ của bản đồ (xem ZZ0000ZZ)
map_by_idx(imm) có nghĩa là chuyển đổi chỉ mục 32 bit thành địa chỉ của bản đồ
map_val(map) lấy địa chỉ của giá trị đầu tiên trong bản đồ nhất định
var_addr(imm) lấy địa chỉ của biến nền tảng (xem ZZ0001ZZ) với id đã cho
code_addr(imm) lấy địa chỉ của lệnh tại một độ lệch tương đối được chỉ định về số lượng lệnh (64-bit)
‘loại imm’ có thể được sử dụng bởi bộ phân tách để hiển thị
‘loại dst’ có thể được sử dụng cho mục đích xác minh và biên dịch JIT
1.4.4.1 Bản đồ¶
Bản đồ là vùng bộ nhớ dùng chung mà các chương trình BPF có thể truy cập trên một số nền tảng. Một bản đồ có thể có nhiều ngữ nghĩa khác nhau như được định nghĩa trong một tài liệu riêng biệt và có thể hoặc có thể không có một vùng bộ nhớ liền kề, nhưng ‘map_val(map)’ thì hiện chỉ được xác định cho các bản đồ có một vùng bộ nhớ liền kề.
Mỗi bản đồ có thể có một bộ mô tả tệp (fd) nếu được nền tảng hỗ trợ, trong đó ‘map_by_fd(imm)’ có nghĩa là lấy bản đồ với bộ mô tả tệp được chỉ định. Mỗi Chương trình BPF cũng có thể được xác định để sử dụng một bộ bản đồ liên kết với chương trình tại thời điểm tải và ‘map_by_idx(imm)’ có nghĩa là lấy bản đồ với thông số đã cho chỉ mục trong tập hợp được liên kết với chương trình BPF chứa lệnh.
1.4.4.2 Biến nền tảng¶
Biến nền tảng là các vùng bộ nhớ, được xác định bởi id số nguyên, được hiển thị bởi thời gian chạy và có thể truy cập được bởi các chương trình BPF trên một số nền tảng. các Hoạt động ‘var_addr(imm)’ có nghĩa là lấy địa chỉ của vùng bộ nhớ được xác định bởi id đã cho.
1.4.5 Hướng dẫn truy cập gói BPF kế thừa¶
BPF trước đây đã giới thiệu các hướng dẫn đặc biệt để truy cập vào dữ liệu gói được chuyển từ BPF cổ điển. Các hướng dẫn này sử dụng một hướng dẫn lớp ZZ0000ZZ, bộ sửa đổi kích thước của ZZ0001ZZ, ZZ0002ZZ hoặc ZZ0003ZZ và công cụ sửa đổi chế độ của ZZ0004ZZ hoặc ZZ0005ZZ. Các trường ‘dst_reg’ và ‘offset’ là được đặt thành 0 và ‘src_reg’ được đặt thành 0 cho ZZ0006ZZ. Tuy nhiên, những điều này hướng dẫn không được dùng nữa và SHOULD không còn được sử dụng nữa. Tất cả các gói kế thừa hướng dẫn truy cập thuộc nhóm tuân thủ “gói”.