@c Copyright (C) 2019-2023 Free Software Foundation, Inc.
@c This is part of the GAS manual.
@c For copying conditions, see the file as.texinfo.
@ifset GENERIC
@page
@node BPF-Dependent
@chapter BPF Dependent Features
@end ifset
@ifclear GENERIC
@node Machine Dependencies
@chapter BPF Dependent Features
@end ifclear
@cindex BPF support
@menu
* BPF Options:: Options
* BPF Syntax:: Syntax
* BPF Directives:: Machine Directives
* BPF Opcodes:: Opcodes
* BPF Pseudo-C Syntax:: Alternative Pseudo-C Assembly Syntax
@end menu
@node BPF Options
@section Options
@cindex BPF options (none)
@cindex options for BPF (none)
@c man begin OPTIONS
@table @gcctabopt
@cindex @option{-EB} command-line option, BPF
@item -EB
This option specifies that the assembler should emit big-endian eBPF.
@cindex @option{-EL} command-line option, BPF
@item -EL
This option specifies that the assembler should emit little-endian
eBPF.
@end table
Note that if no endianness option is specified in the command line,
the host endianness is used.
@c man end
@node BPF Syntax
@section Syntax
@menu
* BPF-Chars:: Special Characters
* BPF-Regs:: Register Names
* BPF-Pseudo-Maps:: Pseudo map fds
@end menu
@node BPF-Chars
@subsection Special Characters
@cindex line comment character, BPF
@cindex BPF line comment character
The presence of a @samp{;} on a line indicates the start of a comment
that extends to the end of the current line. If a @samp{#} appears as
the first character of a line, the whole line is treated as a comment.
@cindex statement separator, BPF
Statements and assembly directives are separated by newlines.
@node BPF-Regs
@subsection Register Names
@cindex BPF register names
@cindex register names, BPF
The eBPF processor provides ten general-purpose 64-bit registers,
which are read-write, and a read-only frame pointer register:
@table @samp
@item %r0 .. %r9
General-purpose registers.
@item %r10
Frame pointer register.
@end table
Some registers have additional names, to reflect their role in the
eBPF ABI:
@table @samp
@item %a
This is @samp{%r0}.
@item %ctx
This is @samp{%r6}.
@item %fp
This is @samp{%r10}.
@end table
@node BPF-Pseudo-Maps
@subsection Pseudo Maps
@cindex pseudo map fd, BPF
The @samp{LDDW} instruction can take a literal pseudo map file
descriptor as its second argument. This uses the syntax
@samp{%map_fd(N)} where @samp{N} is a signed number.
For example, to load the address of the pseudo map with file
descriptor @samp{2} in register @samp{r1} we would do:
@smallexample
lddw %r1, %map_fd(2)
@end smallexample
@node BPF Directives
@section Machine Directives
@cindex machine directives, BPF
The BPF version of @code{@value{AS}} supports the following additional
machine directives:
@table @code
@cindex @code{half} directive, BPF
@item .word
The @code{.half} directive produces a 16 bit value.
@cindex @code{word} directive, BPF
@item .word
The @code{.word} directive produces a 32 bit value.
@cindex @code{dword} directive, BPF
@item .dword
The @code{.dword} directive produces a 64 bit value.
@end table
@node BPF Opcodes
@section Opcodes
@cindex BPF opcodes
@cindex opcodes for BPF
In the instruction descriptions below the following field descriptors
are used:
@table @code
@item %d
Destination general-purpose register whose role is to be destination
of an operation.
@item %s
Source general-purpose register whose role is to be the source of an
operation.
@item disp16
16-bit signed PC-relative offset, measured in number of 64-bit words,
minus one.
@item disp32
32-bit signed PC-relative offset, measured in number of 64-bit words,
minus one.
@item offset16
Signed 16-bit immediate.
@item imm32
Signed 32-bit immediate.
@item imm64
Signed 64-bit immediate.
@end table
@subsubsection Arithmetic instructions
The destination register in these instructions act like an
accumulator.
@table @code
@item add %d, (%s|imm32)
64-bit arithmetic addition.
@item sub %d, (%s|imm32)
64-bit arithmetic subtraction.
@item mul %d, (%s|imm32)
64-bit arithmetic multiplication.
@item div %d, (%s|imm32)
64-bit arithmetic integer division.
@item mod %d, (%s|imm32)
64-bit integer remainder.
@item and %d, (%s|imm32)
64-bit bit-wise ``and'' operation.
@item or %d, (%s|imm32)
64-bit bit-wise ``or'' operation.
@item xor %d, (%s|imm32)
64-bit bit-wise exclusive-or operation.
@item lsh %d, (%s|imm32)
64-bit left shift, by @code{%s} or @code{imm32} bits.
@item rsh %d, (%s|imm32)
64-bit right logical shift, by @code{%s} or @code{imm32} bits.
@item arsh %d, (%s|imm32)
64-bit right arithmetic shift, by @code{%s} or @code{imm32} bits.
@item neg %d
64-bit arithmetic negation.
@item mov %d, (%s|imm32)
Move the 64-bit value of @code{%s} in @code{%d}, or load @code{imm32}
in @code{%d}.
@end table
@subsubsection 32-bit arithmetic instructions
The destination register in these instructions act as an accumulator.
@table @code
@item add32 %d, (%s|imm32)
32-bit arithmetic addition.
@item sub32 %d, (%s|imm32)
32-bit arithmetic subtraction.
@item mul32 %d, (%s|imm32)
32-bit arithmetic multiplication.
@item div32 %d, (%s|imm32)
32-bit arithmetic integer division.
@item mod32 %d, (%s|imm32)
32-bit integer remainder.
@item and32 %d, (%s|imm32)
32-bit bit-wise ``and'' operation.
@item or32 %d, (%s|imm32)
32-bit bit-wise ``or'' operation.
@item xor32 %d, (%s|imm32)
32-bit bit-wise exclusive-or operation.
@item lsh32 %d, (%s|imm32)
32-bit left shift, by @code{%s} or @code{imm32} bits.
@item rsh32 %d, (%s|imm32)
32-bit right logical shift, by @code{%s} or @code{imm32} bits.
@item arsh32 %d, (%s|imm32)
32-bit right arithmetic shift, by @code{%s} or @code{imm32} bits.
@item neg32 %d
32-bit arithmetic negation.
@item mov32 %d, (%s|imm32)
Move the 32-bit value of @code{%s} in @code{%d}, or load @code{imm32}
in @code{%d}.
@end table
@subsubsection Endianness conversion instructions
@table @code
@item endle %d, (16|32|64)
Convert the 16-bit, 32-bit or 64-bit value in @code{%d} to
little-endian.
@item endbe %d, (16|32|64)
Convert the 16-bit, 32-bit or 64-bit value in @code{%d} to big-endian.
@end table
@subsubsection 64-bit load and pseudo maps
@table @code
@item lddw %d, imm64
Load the given signed 64-bit immediate, or pseudo map descriptor, to
the destination register @code{%d}.
@item lddw %d, %map_fd(N)
Load the address of the given pseudo map fd @emph{N} to the
destination register @code{%d}.
@end table
@subsubsection Load instructions for socket filters
The following instructions are intended to be used in socket filters,
and are therefore not general-purpose: they make assumptions on the
contents of several registers. See the file
@file{Documentation/networking/filter.txt} in the Linux kernel source
tree for more information.
Absolute loads:
@table @code
@item ldabsdw imm32
Absolute 64-bit load.
@item ldabsw imm32
Absolute 32-bit load.
@item ldabsh imm32
Absolute 16-bit load.
@item ldabsb imm32
Absolute 8-bit load.
@end table
Indirect loads:
@table @code
@item ldinddw %s, imm32
Indirect 64-bit load.
@item ldindw %s, imm32
Indirect 32-bit load.
@item ldindh %s, imm32
Indirect 16-bit load.
@item ldindb %s, imm32
Indirect 8-bit load.
@end table
@subsubsection Generic load/store instructions
General-purpose load and store instructions are provided for several
word sizes.
Load to register instructions:
@table @code
@item ldxdw %d, [%s+offset16]
Generic 64-bit load.
@item ldxw %d, [%s+offset16]
Generic 32-bit load.
@item ldxh %d, [%s+offset16]
Generic 16-bit load.
@item ldxb %d, [%s+offset16]
Generic 8-bit load.
@end table
Store from register instructions:
@table @code
@item stxdw [%d+offset16], %s
Generic 64-bit store.
@item stxw [%d+offset16], %s
Generic 32-bit store.
@item stxh [%d+offset16], %s
Generic 16-bit store.
@item stxb [%d+offset16], %s
Generic 8-bit store.
@end table
Store from immediates instructions:
@table @code
@item stddw [%d+offset16], imm32
Store immediate as 64-bit.
@item stdw [%d+offset16], imm32
Store immediate as 32-bit.
@item stdh [%d+offset16], imm32
Store immediate as 16-bit.
@item stdb [%d+offset16], imm32
Store immediate as 8-bit.
@end table
@subsubsection Jump instructions
eBPF provides the following compare-and-jump instructions, which
compare the values of the two given registers, or the values of a
register and an immediate, and perform a branch in case the comparison
holds true.
@table @code
@item ja %d,(%s|imm32),disp16
Jump-always.
@item jeq %d,(%s|imm32),disp16
Jump if equal, unsigned.
@item jgt %d,(%s|imm32),disp16
Jump if greater, unsigned.
@item jge %d,(%s|imm32),disp16
Jump if greater or equal.
@item jlt %d,(%s|imm32),disp16
Jump if lesser.
@item jle %d,(%s|imm32),disp16
Jump if lesser or equal.
@item jset %d,(%s|imm32),disp16
Jump if signed equal.
@item jne %d,(%s|imm32),disp16
Jump if not equal.
@item jsgt %d,(%s|imm32),disp16
Jump if signed greater.
@item jsge %d,(%s|imm32),disp16
Jump if signed greater or equal.
@item jslt %d,(%s|imm32),disp16
Jump if signed lesser.
@item jsle %d,(%s|imm32),disp16
Jump if signed lesser or equal.
@end table
A call instruction is provided in order to perform calls to other eBPF
functions, or to external kernel helpers:
@table @code
@item call (disp32|imm32)
Jump and link to the offset @emph{disp32}, or to the kernel helper
function identified by @emph{imm32}.
@end table
Finally:
@table @code
@item exit
Terminate the eBPF program.
@end table
@subsubsection Atomic instructions
Atomic exchange-and-add instructions are provided in two flavors: one
for swapping 64-bit quantities and another for 32-bit quantities.
@table @code
@item xadddw [%d+offset16],%s
Exchange-and-add a 64-bit value at the specified location.
@item xaddw [%d+offset16],%s
Exchange-and-add a 32-bit value at the specified location.
@end table
@node BPF Pseudo-C Syntax
@section BPF Pseudo-C Syntax
This assembler supports another syntax to denote BPF instructions,
which is an alternative to the normal looking syntax documented above.
This alternatative syntax, which we call @dfn{pseudo-C syntax}, is
supported by the LLVM/clang integrated assembler.
This syntax is very unconventional, but we need to support it in order
to support inline assembly in existing BPF programs.
Note that the assembler is able to parse sources in which both
syntaxes coexist: some instructions can use the usual assembly like
syntax, whereas some other instructions in the same file can use the
pseudo-C syntax.
@subsubsection Pseudo-C Register Names
All BPF registers are 64-bit long. However, in the Pseudo-C syntax
registers can be referred using different names, which actually
reflect the kind of instruction they appear on:
@table @samp
@item r0..r9
General-purpose register in an instruction that operates on its value
as if it was a 64-bit value.
@item w0..w9
General-purpose register in an instruction that operates on its value
as if it was a 32-bit value.
@end table
@noindent
Note that in the Pseudo-C syntax register names are not preceded by
@code{%} characters.
@subsubsection Arithmetic instructions
In all the instructions below, the operations are 64-bit or 32-bit
depending on the names used to refer to the registers. For example
@code{r3 += r2} will perform 64-bit addition, whereas @code{w3 += w2}
will perform 32-bit addition. Mixing register prefixes is an error,
for example @code{r3 += w2}.
@table @code
@item dst_reg += (imm32|src_reg)
Arithmetic addition.
@item dst_reg -= (imm32|src_reg)
Arithmetic subtraction.
@item dst_reg *= (imm32|src_reg)
Arithmetic multiplication.
@item dst_reg /= (imm32|src_reg)
Arithmetic integer unsigned division.
@item dst_reg %= (imm32|src_reg)
Arithmetic integer unsigned remainder.
@item dst_reg &= (imm32|src_reg)
Bit-wise ``and'' operation.
@item dst_reg |= (imm32|src_reg)
Bit-wise ``or'' operation.
@item dst_reg ^= (imm32|src_reg)
Bit-wise exclusive-or operation.
@item dst_reg <<= (imm32|src_reg)
Left shift, by whatever specified number of bits.
@item dst_reg >>= (imm32|src_reg)
Right logical shift, by whatever specified number of bits.
@item dst_reg s>>= (imm32|src_reg)
Right arithmetic shift, by whatever specified number of bits.
@item dst_reg = (imm32|src_reg)
Move the value in @code{imm32} or @code{src_reg} in @code{dst_reg}.
@item dst_reg = -dst_reg
Arithmetic negation.
@end table
@subsubsection Endianness conversion instructions
@table @code
@item dst_reg = le16 src_reg
Convert the 16-bit value in @code{src_reg} to little-endian.
@item dst_reg = le32 src_reg
Convert the 32-bit value in @code{src_reg} to little-endian.
@item dst_reg = le64 src_reg
Convert the 64-bit value in @code{src_reg} to little-endian.
@item dst_reg = be16 src_reg
Convert the 16-bit value in @code{src_reg} to big-endian.
@item dst_reg = be32 src_reg
Convert the 32-bit value in @code{src_reg} to big-endian.
@item dst_reg = be64 src_reg
Convert the 64-bit value in @code{src_reg} to big-endian.
@end table
@subsubsection 64-bit load and pseudo maps
@table @code
@item dst_reg = imm64 ll
Load the given signed 64-bit immediate, or pseudo map descriptor, to
the destination register @code{dst_reg}.
@end table
@subsubsection Load instructions for socket filters
@table @code
@item r0 = *(u8 *)skb[imm32]
Absolute 8-bit load.
@item r0 = *(u16 *)skb[imm32]
Absolute 16-bit load.
@item r0 = *(u32 *)skb[imm32]
Absolute 32-bit load.
@item r0 = *(u64 *)skb[imm32]
Absolute 64-bit load.
@item r0 = *(u8 *)skb[src_reg + imm32]
Indirect 8-bit load.
@item r0 = *(u16 *)skb[src_reg + imm32]
Indirect 16-bit load.
@item r0 = *(u32 *)skb[src_reg + imm32]
Indirect 32-bit load.
@item r0 = *(u64 *)skb[src_reg + imm32]
Indirect 64-bit load.
@end table
@subsubsection Generic load/store instructions
@table @code
@item dst_reg = *(u8 *)(src_reg + offset16)
Generic 8-bit load.
@item dst_reg = *(u16 *)(src_reg + offset16)
Generic 16-bit load.
@item dst_reg = *(u32 *)(src_reg + offset16)
Generic 32-bit load.
@item dst_reg = *(u64 *)(src_reg + offset16)
Generic 64-bit load.
@c XXX stb
@c NO PSEUDOC-SYNTAX
@c XXX sth
@c NO PSEUDOC-SYNTAX
@c XXX stw
@c NO PSEUDOC-SYNTAX
@c XXX stdw
@c NO PSEUDOC-SYNTAX
@item *(u8 *)(dst_reg + offset16) = src_reg
Generic 8-bit store.
@item *(u16 *)(dst_reg + offset16) = src_reg
Generic 16-bit store.
@item *(u32 *)(dst_reg + offset16) = src_reg
Generic 32-bit store.
@item *(u64 *)(dst_reg + offset16) = src_reg
Generic 64-bit store.
@end table
@subsubsection Jump instructions
@table @code
@item goto disp16
Jump-always.
@item if dst_reg == (imm32|src_reg) goto disp16
Jump if equal.
@item if dst_reg & (imm32|src_reg) goto disp16
Jump if signed equal.
@item if dst_reg != (imm32|src_reg) goto disp16
Jump if not equal.
@item if dst_reg > (imm32|src_reg) goto disp16
Jump if bigger, unsigned.
@item if dst_reg < (imm32|src_reg) goto disp16
Jump if smaller, unsigned.
@item if dst_reg >= (imm32|src_reg) goto disp16
Jump if bigger or equal, unsigned.
@item if dst_reg <= (imm32|src_reg) goto disp16
Jump if smaller or equal, unsigned.
@item if dst_reg s> (imm32|src_reg) goto disp16
Jump if bigger, signed.
@item if dst_reg s< (imm32|src_reg) goto disp16
Jump if smaller, signed.
@item if dst_reg s>= (imm32|src_reg) goto disp16
Jump if bigger or equal, signed.
@item if dst_reg s<= (imm32|src_reg) goto disp16
Jump if smaller or equal, signed.
@item call imm32
Jump and link.
@item exit
Terminate the eBPF program.
@end table
@subsubsection Atomic instructions
@table @code
@item lock *(u64 *)(dst_reg + offset16) += src_reg
Exchange-and-add a 64-bit value at the specified location.
@item lock *(u32 *)(dst_reg + offset16) += src_reg
Exchange-and-add a 32-bit value at the specified location.
@end table