Prechádzať zdrojové kódy

SIMD-0174: SBPF arithmetics improvements (#174)

* First draft

* Assigns SBPF version.
Alexander Meißner 4 mesiacov pred
rodič
commit
35045d23d3
1 zmenil súbory, kde vykonal 154 pridanie a 0 odobranie
  1. 154 0
      proposals/0174-sbpf-arithmetics-improvements.md

+ 154 - 0
proposals/0174-sbpf-arithmetics-improvements.md

@@ -0,0 +1,154 @@
+---
+simd: '0174'
+title: SBPF arithmetics improvements
+authors:
+  - Alexander Meißner
+category: Standard
+type: Core
+status: Review
+created: 2024-09-06
+feature: F6UVKh1ujTEFK3en2SyAL3cdVnqko1FVEXWhmdLRu6WP
+extends: SIMD-0161
+---
+
+## Summary
+
+This proposal introduces wide multiplication, signed division and explicit sign
+extension to SBPF.
+
+## Motivation
+
+All major hardware ISAs support 64 x 64 = 128 bit multiplication; BPF does not.
+This hurts performance of big integer arithmetics. Similarly, signed division
+and signed remainder / modulo instructions must be emulated in software as
+well.
+
+Another issue related to arithmetics is that some 32 bit instructions perform
+sign extension of their results (output, **not** input, there is a difference)
+implicitly. This is first of all useless because source languages do not read
+the 32 MSBs of a 32 bit result stored in a 64 bit register. And second, it
+requires interpreters and compilers to perform extra work to add sign extension
+at the end of these instructions. Instead we should go the same route as the
+underlying hardware ISAs and require sign extension to be made explicit in a
+dedicated instruction.
+
+Furthermore, the instruction `sub dst, imm` is redundant as it can also be
+encoded as `add dst, -imm`. If we were to swap the operands meaning of minuend
+and subtrahend, then the instruction would become useful and would even render
+`neg dst` redundant. Negation would then be encoded as `reg = 0 - reg`. This
+would also make it clear how sign extension rules work for negation.
+
+## Alternatives Considered
+
+None.
+
+## New Terminology
+
+None.
+
+## Detailed Design
+
+The following must go into effect if and only if a program indicates the
+SBPF-version (v2) or higher in its program header (see SIMD-0161).
+
+### Changes to the Bytecode Verifier
+
+A program containing one of the following instructions must throw
+`VerifierError::UnknownOpCode` during verification:
+
+- the `MUL` instruction (opcodes `0x24`, `0x2C`, `0x27` and `0x2F`)
+- the `DIV` instruction (opcodes `0x34`, `0x3C`, `0x37` and `0x3F`)
+- the `MOD` instruction (opcodes `0x94`, `0x9C`, `0x97` and `0x9F`)
+- the `NEG` instruction (opcodes `0x84` and `0x87`)
+
+A program containing one of the following instructions must **not** throw
+`VerifierError::UnknownOpCode` during verification anymore (opcodes are for
+immediate and register variant each, in that order):
+
+- the `UHMUL64` instruction (opcode `0x36` and `0x3E`)
+- the `UDIV32` instruction (opcode `0x46` and `0x4E`)
+- the `UDIV64` instruction (opcode `0x56` and `0x5E`)
+- the `UREM32` instruction (opcode `0x66` and `0x6E`)
+- the `UREM64` instruction (opcode `0x76` and `0x7E`)
+- the `LMUL32` instruction (opcode `0x86` and `0x8E`)
+- the `LMUL64` instruction (opcode `0x96` and `0x9E`)
+- the `SHMUL64` instruction (opcode `0xB6` and `0xBE`)
+- the `SDIV32` instruction (opcode `0xC6` and `0xCE`)
+- the `SDIV64` instruction (opcode `0xD6` and `0xDE`)
+- the `SREM32` instruction (opcode `0xE6` and `0xEE`)
+- the `SREM64` instruction (opcode `0xF6` and `0xFE`)
+
+The verification rule, that an immediate divisor must not be zero or else
+`VerifierError::DivisionByZero` is thrown, is moved to the new division like
+instructions: `UDIV32_IMM`, `UDIV64_IMM`, `UREM32_IMM`, `UREM64_IMM`,
+`SDIV32_IMM`, `SDIV64_IMM`, `SREM32_IMM`, `SREM64_IMM`.
+
+### Changes to Execution
+
+#### PQR Instruction Class
+
+A new instruction class product, quotient and remainder (PQR) is introduced:
+
+- the `UHMUL64` instruction (opcode `0x36` and `0x3E`) produces the 64 MSBs of
+the product of an unsigned 64 x 64 bit multiplication (`dst * imm` and
+`dst * src`).
+- the `UDIV32` instruction (opcode `0x46` and `0x4E`) produces the quotient of
+an unsigned 32 bit division (`dst / imm` and `dst / src`).
+- the `UDIV64` instruction (opcode `0x56` and `0x5E`) produces the quotient of
+an unsigned 64 bit division (`dst / imm` and `dst / src`).
+- the `UREM32` instruction (opcode `0x66` and `0x6E`) produces the remainder of
+an unsigned 64 bit division (`dst % imm` and `dst % src`).
+- the `UREM64` instruction (opcode `0x76` and `0x7E`) produces the remainder of
+an unsigned 64 bit division (`dst % imm` and `dst % src`).
+- the `LMUL32` instruction (opcode `0x86` and `0x8E`) produces the 32 LSBs of
+the product of any 32 x 32 bit multiplication (`dst * imm` and `dst * src`).
+- the `LMUL64` instruction (opcode `0x96` and `0x9E`) produces the 64 LSBs of
+the product of any 64 x 64 bit multiplication (`dst * imm` and `dst * src`).
+- the `SHMUL64` instruction (opcode `0xB6` and `0xBE`) produces the 64 MSBs of
+the product of a signed 64 x 64 bit multiplication (`dst * imm` and
+`dst * src`).
+- the `SDIV32` instruction (opcode `0xC6` and `0xCE`) produces the quotient of
+a signed 32 bit division (`dst / imm` and `dst / src`).
+- the `SDIV64` instruction (opcode `0xD6` and `0xDE`) produces the quotient of
+a signed 64 bit division (`dst / imm` and `dst / src`).
+- the `SREM32` instruction (opcode `0xE6` and `0xEE`) produces the remainder of
+a signed 32 bit division (`dst / imm` and `dst / src`).
+- the `SREM64` instruction (opcode `0xF6` and `0xFE`) produces the remainder of
+a signed 64 bit division (`dst / imm` and `dst / src`).
+
+Runtime exceptions are:
+
+- If the divisor (`imm` or `src`) of any division is zero,
+`EbpfError::DivideByZero` must be thrown.
+- If the dividend (`dst`) of a signed division has the minimal value for its
+bit-width and the divisor (`imm` or `src`) is `-1`, then
+`EbpfError::DivideOverflow` must be thrown.
+
+#### Explicit Sign Extension
+
+The following instructions must stop performing implicit sign extension of
+their results, instead filling the 32 MSBs of `dst` with zeros:
+
+- the `ADD32` instruction (opcode `0x04` and `0x0C`)
+- the `SUB32` instruction (opcode `0x14` and `0x1C`)
+- all of the new 32 bit PQR instructions: `UDIV32`, `UREM32`, `SDIV32`,
+`SREM32` and `LMUL32`
+
+Instead the `MOV32_REG` instruction (opcode `0xBC`) which until now did zero
+out the 32 MSBs, must now perform sign extension in the 32 MSBs. Meaning this
+instruction becomes the explicit sign extension operation.
+
+#### Register Immediate Subtraction
+
+The operands roles of `SUB32_IMM` (opcode `0x14`) and `SUB64_IMM` (opcode
+`0x17`) must be swapped: Until now the resulting difference was `src - imm` and
+it must be changed to `imm - src`.
+
+## Impact
+
+The toolchain will emit machine-code according to the selected SBPF version.
+Big integer arithmetics and signed divisions will become cheaper CU wise.
+
+## Security Considerations
+
+None.