Skip to content

Commit a0328f7

Browse files
committed
First draft
1 parent 4b1eaaf commit a0328f7

File tree

1 file changed

+154
-0
lines changed

1 file changed

+154
-0
lines changed
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
---
2+
simd: '0174'
3+
title: SBPF arithmetics improvements
4+
authors:
5+
- Alexander Meißner
6+
category: Standard
7+
type: Core
8+
status: Draft
9+
created: 2024-09-06
10+
feature: TBD
11+
extends: SIMD-0161
12+
---
13+
14+
## Summary
15+
16+
This proposal introduces wide multiplication, signed division and explicit sign
17+
extension to SBPF.
18+
19+
## Motivation
20+
21+
All major hardware ISAs support 64 x 64 = 128 bit multiplication; BPF does not.
22+
This hurts performance of big integer arithmetics. Similarly, signed division
23+
and signed remainder / mudolo instructions must be emulated in software as
24+
well.
25+
26+
Another issue related to arithemtics is that some 32 bit instructions perform
27+
sign extension of their results (output, **not** input, there is a difference)
28+
implicitly. This is first of all useless because source languages do not read
29+
the 32 MSBs of a 32 bit result stored in a 64 bit register. And second, it
30+
requires interpreters and compilers to perform extra work to add sign extension
31+
at the end of these instructions. Instead we should go the same route as the
32+
underlying hardware ISAs and require sign extension to be made explicit in a
33+
dedicated instruction.
34+
35+
Furthermore, the instruction `sub dst, imm` is redundant as it can also be
36+
encoded as `add dst, -imm`. If we were to swap the operands meaning of minuend
37+
and subtrahend, then the instruction would become usefull and would even render
38+
`neg dst` redundant. Negation would then be encoded as `reg = 0 - reg`. This
39+
would also make it clear how sign extension rules work for negation.
40+
41+
## Alternatives Considered
42+
43+
None.
44+
45+
## New Terminology
46+
47+
None.
48+
49+
## Detailed Design
50+
51+
The following must go into effect if and only if a program indicates the
52+
SBPF-version (TBD) or higher in its program header (see SIMD-0161).
53+
54+
### Changes to the Machinecode Verifier
55+
56+
A program containing one of the following instructions must throw
57+
`VerifierError::UnknownOpCode` during verification:
58+
59+
- the `MUL` instruction (opcodes `0x24`, `0x2C`, `0x27` and `0x2F`)
60+
- the `DIV` instruction (opcodes `0x34`, `0x3C`, `0x37` and `0x3F`)
61+
- the `MOD` instruction (opcodes `0x94`, `0x9C`, `0x97` and `0x9F`)
62+
- the `NEG` instruction (opcodes `0x84` and `0x87`)
63+
64+
A program containing one of the following instructions must **not** throw
65+
`VerifierError::UnknownOpCode` during verification anymore (opcodes are for
66+
immediate and register variant each, in that order):
67+
68+
- the `UHMUL64` instruction (opcode `0x36` and `0x3E`)
69+
- the `UDIV32` instruction (opcode `0x46` and `0x4E`)
70+
- the `UDIV64` instruction (opcode `0x56` and `0x5E`)
71+
- the `UREM32` instruction (opcode `0x66` and `0x6E`)
72+
- the `UREM64` instruction (opcode `0x76` and `0x7E`)
73+
- the `LMUL32` instruction (opcode `0x86` and `0x8E`)
74+
- the `LMUL64` instruction (opcode `0x96` and `0x9E`)
75+
- the `SHMUL64` instruction (opcode `0xB6` and `0xBE`)
76+
- the `SDIV32` instruction (opcode `0xC6` and `0xCE`)
77+
- the `SDIV64` instruction (opcode `0xD6` and `0xDE`)
78+
- the `SREM32` instruction (opcode `0xE6` and `0xEE`)
79+
- the `SREM64` instruction (opcode `0xF6` and `0xFE`)
80+
81+
The verification rule, that an immediate divisor must not be zero or else
82+
`VerifierError::DivisionByZero` is thrown, is moved to the new division like
83+
instructions: `UDIV32_IMM`, `UDIV64_IMM`, `UREM32_IMM`, `UREM64_IMM`,
84+
`SDIV32_IMM`, `SDIV64_IMM`, `SREM32_IMM`, `SREM64_IMM`.
85+
86+
### Changes to Execution
87+
88+
#### PQR Instruction Class
89+
90+
A new instruction class product, quotient and remainder (PQR) is introduced:
91+
92+
- the `UHMUL64` instruction (opcode `0x36` and `0x3E`) produces the 64 MSBs of
93+
the product of an unsigned 64 x 64 bit multiplication (`dst * imm` and
94+
`dst * src`).
95+
- the `UDIV32` instruction (opcode `0x46` and `0x4E`) produces the quotient of
96+
an unsigned 32 bit division (`dst / imm` and `dst / src`).
97+
- the `UDIV64` instruction (opcode `0x56` and `0x5E`) produces the quotient of
98+
an unsigned 64 bit division (`dst / imm` and `dst / src`).
99+
- the `UREM32` instruction (opcode `0x66` and `0x6E`) produces the remainder of
100+
an unsigned 64 bit division (`dst % imm` and `dst % src`).
101+
- the `UREM64` instruction (opcode `0x76` and `0x7E`) produces the remainder of
102+
an unsigned 64 bit division (`dst % imm` and `dst % src`).
103+
- the `LMUL32` instruction (opcode `0x86` and `0x8E`) produces the 32 LSBs of
104+
the product of any 32 x 32 bit multiplication (`dst * imm` and `dst * src`).
105+
- the `LMUL64` instruction (opcode `0x96` and `0x9E`) produces the 64 LSBs of
106+
the product of any 64 x 64 bit multiplication (`dst * imm` and `dst * src`).
107+
- the `SHMUL64` instruction (opcode `0xB6` and `0xBE`) produces the 64 MSBs of
108+
the product of a signed 64 x 64 bit multiplication (`dst * imm` and
109+
`dst * src`).
110+
- the `SDIV32` instruction (opcode `0xC6` and `0xCE`) produces the quotient of
111+
a signed 32 bit division (`dst / imm` and `dst / src`).
112+
- the `SDIV64` instruction (opcode `0xD6` and `0xDE`) produces the quotient of
113+
a signed 64 bit division (`dst / imm` and `dst / src`).
114+
- the `SREM32` instruction (opcode `0xE6` and `0xEE`) produces the remainder of
115+
a signed 32 bit division (`dst / imm` and `dst / src`).
116+
- the `SREM64` instruction (opcode `0xF6` and `0xFE`) produces the remainder of
117+
a signed 64 bit division (`dst / imm` and `dst / src`).
118+
119+
Runtime exceptions are:
120+
121+
- If the divisor (`imm` or `src`) of any division is zero,
122+
`EbpfError::DivideByZero` must be thrown.
123+
- If the dividend (`dst`) of a signed division has the minimal value for its
124+
bitwidth and the divisor (`imm` or `src`) is `-1`, then
125+
`EbpfError::DivideOverflow` must be thrown.
126+
127+
#### Explicit Sign Extension
128+
129+
The following instructions must stop performing implicit sign extension of
130+
their results, instead filling the 32 MSBs of `dst` with zeros:
131+
132+
- the `ADD32` instruction (opcode `0x04` and `0x0C`)
133+
- the `SUB32` instruction (opcode `0x14` and `0x1C`)
134+
- all of the new 32 bit PQR instructions: `UDIV32`, `UREM32`, `SDIV32`,
135+
`SREM32` and `LMUL32`
136+
137+
Instead the `MOV32_REG` instruction (opcode `0xBC`) which until now did zero
138+
out the 32 MSBs, must now perform sign extension in the 32 MSBs. Meaning this
139+
instruction becomes the explicit sign extension operation.
140+
141+
#### Register Immediate Subtraction
142+
143+
The operands roles of `SUB32_IMM` (opcode `0x14`) and `SUB64_IMM` (opcode
144+
`0x17`) must be swapped: Until now the resulting difference was `src - imm` and
145+
it must be changed to `imm - src`.
146+
147+
## Impact
148+
149+
The toolchain will emit machinecode according to the selected SBPF version.
150+
Big integer arithmetics and signed divisions will become cheaper CU wise.
151+
152+
## Security Considerations
153+
154+
None.

0 commit comments

Comments
 (0)