Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bpf2c and eBPF-for-Windows should support global variables in BPF programs (aka platform variables) as defined in 5.4 of BPF ISA #3958

Open
Alan-Jowett opened this issue Oct 28, 2024 · 4 comments
Assignees
Labels
blocked Blocked on another issue that must be done first enhancement New feature or request optimization Affects perf but not correctness or applicability P2 triaged Discussed in a triage meeting
Milestone

Comments

@Alan-Jowett
Copy link
Member

The BPF ISA defines additional 64bit immediate load instructions. eBPF-for-Windows should add support for type 3 at a minimum. This support can improve the performance of certain BPF programs by eliminating the need to perform map lookups.

5.4.  64-bit immediate instructions

   Instructions with the IMM 'mode' modifier use the wide instruction
   encoding defined in Instruction encoding (Section 3), and use the
   'src_reg' field of the basic instruction to hold an opcode subtype.

   The following table defines a set of {IMM, DW, LD} instructions with
   opcode subtypes in the 'src_reg' field, using new terms such as "map"
   defined further below:

    +=========+================================+==========+==========+
    | 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))  | map fd   | data     |
    |         | + next_imm                     |          | address  |
    +---------+--------------------------------+----------+----------+
    | 0x3     | dst = var_addr(imm)            | variable | data     |
    |         |                                | id       | address  |
    +---------+--------------------------------+----------+----------+
    | 0x4     | dst = code_addr(imm)           | integer  | code     |
    |         |                                |          | address  |
    +---------+--------------------------------+----------+----------+
    | 0x5     | dst = map_by_idx(imm)          | map      | map      |
    |         |                                | index    |          |
    +---------+--------------------------------+----------+----------+
    | 0x6     | dst = map_val(map_by_idx(imm)) | map      | data     |
    |         | + next_imm                     | index    | address  |
    +---------+--------------------------------+----------+----------+

                 Table 12: 64-bit immediate instructions
@Alan-Jowett
Copy link
Member Author

Alan-Jowett commented Oct 28, 2024

iovisor/ubpf#590

@Alan-Jowett Alan-Jowett added enhancement New feature or request optimization Affects perf but not correctness or applicability labels Oct 28, 2024
@Alan-Jowett
Copy link
Member Author

vbpf/ebpf-verifier#763

@saxena-anurag
Copy link
Contributor

Question: Are these global variables compile time constants?

@shankarseal shankarseal added blocked Blocked on another issue that must be done first triaged Discussed in a triage meeting labels Oct 28, 2024
@shankarseal shankarseal added this to the Backlog milestone Oct 28, 2024
@shankarseal shankarseal added the P2 label Oct 28, 2024
@lmb
Copy link
Collaborator

lmb commented Oct 28, 2024

On Linux, the use case for this feature is to be able to modify a "compile time constant" at load time of a BPF program. For example being able to change ETH_HLEN to accomodate VLAN tagging or similar. The verifier will then inline the constant into the BPF instruction stream before JITing. This makes this essentially free in terms of performance.

Roughly how it works from user space (I think this is type 0x2 in the list above):

  1. Compile a program which refers to a volatile const. The compiler turns the reference to the const into a load from the .rodata section at a specific offset
  2. Load the ELF and synthesis a single-element array map from the .rodata section
  3. User space then has the opportunity to change the contents of the array map via some API
  4. Before load, the map is loaded and frozen via BPF_MAP_FREEZE
  5. Verifier sees the load, realises that the map is frozen, and replaces the ldimm64 with a constant load

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
blocked Blocked on another issue that must be done first enhancement New feature or request optimization Affects perf but not correctness or applicability P2 triaged Discussed in a triage meeting
Projects
None yet
Development

No branches or pull requests

5 participants