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

add bpf2c support for non-inlined local function calls #3506

Merged
merged 24 commits into from
Oct 31, 2024

Conversation

dthaler
Copy link
Collaborator

@dthaler dthaler commented Apr 28, 2024

Description

Previous to this PR, bpf2c only supported inlined function calls, not bpf2bpf function calls.
PREVAIL support for non-inlined function calls is in vbpf/ebpf-verifier#608.
This PR adds support in bpf2c, as well as a bindmonitor_bpf2bpf.c test sample.

The "gsl" changes in include paths are due to vbpf/ebpf-verifier#707 now requiring GSL for the verifier.

Fixes #3388
Fixes #3885

Note: stack variables in the callee are not yet supported. Those will come in a future PR once vbpf/ebpf-verifier#720 is fixed. For now, this works when the callee only needs registers.

Testing

This PR adds a bindmonitor_bpf2bpf.c test sample
It also adds tests for issue #3885

Documentation

This PR includes a doc update to isa-support.rst

Installation

No impact

Copy link
Collaborator

@hawkinsw hawkinsw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One minor comment about ubpf support for calling local functions.

docs/isa-support.rst Outdated Show resolved Hide resolved
@dthaler dthaler force-pushed the calllocal branch 4 times, most recently from 56ad36d to e72b0a8 Compare April 30, 2024 22:14
@dthaler dthaler force-pushed the calllocal branch 3 times, most recently from 514bc26 to c3486b3 Compare May 7, 2024 14:08
@dthaler dthaler marked this pull request as ready for review May 7, 2024 15:03
@Alan-Jowett
Copy link
Member

I strongly suspect this change won't pass conformance tests once Alan-Jowett/bpf_conformance#245 merges.

The BPF ISA appears to assume that the JIT compiler adjusts R10 when calling the child function. The code needs to be modified to do one of two things:

  1. Each frame gets its own 512 of stack space.
  2. Caller and callee share stack space, but caller adjusts R10 to highest used address before calling child.

@dthaler
Copy link
Collaborator Author

dthaler commented May 11, 2024

I strongly suspect this change won't pass conformance tests once Alan-Jowett/bpf_conformance#245 merges.

If so, I think that PR should be fixed.

The BPF ISA appears to assume that the JIT compiler adjusts R10 when calling the child function.

The BPF ISA has no such assumption. See https://datatracker.ietf.org/doc/draft-ietf-bpf-isa/
The ISA itself does not define any specific meaning for R10 or any specific stack size.
That is the psABI not the ISA and in my opinion any conformance tests for ISA vs psABI should be separate.
That's because per https://datatracker.ietf.org/wg/bpf/about/ the ABI is intended to be a standard but the psABI is just informational so may vary by runtime.

The code needs to be modified to do one of two things:

  1. Each frame gets its own 512 of stack space.
  2. Caller and callee share stack space, but caller adjusts R10 to highest used address before calling child.

This might be needed to match the Linux psABI but not for conformance to the ABI. As such, I'd treat them as part of a separate pull request that may need additional verifier support.

Alan-Jowett
Alan-Jowett previously approved these changes May 29, 2024
mikeagun
mikeagun previously approved these changes Jun 20, 2024
@Alan-Jowett
Copy link
Member

@dthaler can you resolve the conflicts on this? We should be able to merge it after that.

@shankarseal
Copy link
Collaborator

@dthaler can you resolve the conflicts on this? We should be able to merge it after that.

@dthaler - can you please take a look?

Signed-off-by: Dave Thaler <dthaler1968@gmail.com>
Signed-off-by: Dave Thaler <dthaler1968@gmail.com>
Signed-off-by: Dave Thaler <dthaler1968@gmail.com>
Signed-off-by: Dave Thaler <dthaler1968@gmail.com>
Signed-off-by: Dave Thaler <dthaler1968@gmail.com>
Signed-off-by: Dave Thaler <dthaler1968@gmail.com>
Signed-off-by: Dave Thaler <dthaler1968@gmail.com>
Signed-off-by: Dave Thaler <dthaler1968@gmail.com>
Signed-off-by: Dave Thaler <dthaler1968@gmail.com>
Signed-off-by: Dave Thaler <dthaler1968@gmail.com>
Signed-off-by: Dave Thaler <dthaler1968@gmail.com>
Alan-Jowett
Alan-Jowett previously approved these changes Oct 10, 2024
Signed-off-by: Dave Thaler <dthaler1968@gmail.com>
ebpf_program_next(_In_opt_ const struct bpf_program* previous, _In_ const struct bpf_object* object) NO_EXCEPT_TRY
// This function is derived from libbpf's function of the same name.
static _Ret_maybenull_ struct bpf_program*
__bpf_program__iter(_In_opt_ const struct bpf_program* program, _In_ const struct bpf_object* object, bool forward)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: should this function be in one of the libbpf_* files?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's static, I didn't see any value in exporting it just for use in 1 other file since it's also internal in libbpf.

@@ -291,9 +291,14 @@ main(int argc, char** argv)

// Parse per-program data.
for (const ebpf_api_program_info_t* program = infos; program; program = program->next) {
// Skip if a subprogram. A subprogram is defined by libbpf as any
// program in the .text section when multiple programs exist.
if (!strcmp(program->section_name, ".text") && infos->next != nullptr) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: does subprogram here mean the bpf-to-bpf functions? (which are not the entry BPF programs)? are they always guaranteed to be in ".text" section?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Libbpf only treats them as such if they are in the ".text" section. So apparently.

"r3",
"r4",
"r5",
"r10",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: why do we need to pass stack pointer to the sub-program? The current sample program does not use this? Should we enhance the sample programs to test cases where the sub-program uses r10 also?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes it's part of the future PR I referred to in the PR description, for which vbpf/ebpf-verifier#721 is the prerequisite.

REQUIRE(bpf_object__prev_program(object, nullptr) == program);

// Load the program.
REQUIRE(bpf_object__load(object) == 0);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: should we validate that only one BPF program is loaded in kernel?

@dthaler dthaler added this pull request to the merge queue Oct 31, 2024
Merged via the queue into microsoft:main with commit e71e7f7 Oct 31, 2024
90 checks passed
@dthaler dthaler deleted the calllocal branch October 31, 2024 07:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
6 participants