[Canary] Build and test for RISC-V64 libco backend - #12243
Draft
cosmo0920 wants to merge 3 commits into
Draft
Conversation
Signed-off-by: Hiroshi Hatake <hiroshi@chronosphere.io>
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
THIS IS CANARY PR. DO NOT MERGE.
Currently, we didn't have riscv64 backend on flb_libco library and bundled library as in monkey HTTP server.
This PR fills the gap of riscv64 coroutine implementation for RISC-V64 Linux environment.
Without this patch, runtime tests of filter_wasm were failed.
After applying this patch, we get on the actual RISC-V64 Linux environment:
Plus, the implemented coroutine function can be used as:
Background of RISC-V64 implementation
The backend works because it saves exactly the state that the RISC-V ELF ABI says must survive an ordinary C function call. From each coroutine’s perspective,
co_switch()behaves like a function that pauses and later returns normally.The register classification comes from the RISC-V ELF psABI calling convention.
How a context switch happens
The C wrapper passes two context pointers to the assembly routine:
By the normal RISC-V calling convention:
The assembly first saves the current coroutine:
It then loads the target coroutine:
The final
retjumps to theraloaded from the target context.For a suspended coroutine, that
rapoints immediately after its earlier call toco_switch_riscv64(). Execution therefore continues as thoughco_switch()had just returned.For a new coroutine, [co_create() (line 173)](C:/Users/cosmo/Documents/GitHub/fluent-bit/lib/flb_libco/riscv64.c:173) initializes:
Its first
retenters the trampoline on the newly allocated stack. The trampoline invokes the actual coroutine entry function and aborts if that function unexpectedly returns.Why caller-saved registers are omitted
The backend does not need to save
a0–a7ort0–t6. They are caller-saved registers. When the compiler generates a call toco_switch(), it already spills any live caller-saved values that will be needed afterward.Likewise:
gpis fixed by the ABI and must not be modified.tpidentifies the current OS thread. Fluent Bit coroutines remain on the same pthread, so it must remain unchanged.co_switch().This backend therefore assumes that a coroutine is never migrated to another pthread, matching Fluent Bit’s current coroutine model.
Floating-point ABI handling
The compiler exposes the selected ABI through predefined macros:
__riscv_float_abi_single__riscv_float_abi_doubleLP64D uses 64-bit operations:
LP64F uses 32-bit operations:
Soft-float LP64 does not preserve floating-point registers because that ABI does not classify them as callee-saved program state.
On a typical DC ROMA II LP64D environment, GCC should report:
Expected relevant definitions include:
These macros select riscv64.c and enable its double-precision register-save path.
Stack correctness
RISC-V requires the stack pointer to remain 16-byte aligned. Both the requested stack size and context header are rounded to multiples of 16. Linux RV64
malloc()supplies suitably aligned memory, so the calculated top of the allocation remains 16-byte aligned.The stack grows downward from that address, while the saved context resides at the bottom of the allocation:
How the focused test proves preservation
The test commit does more than verify that switching does not crash:
s0–s11,fs0–fs11, andfcsr.Correct return flow also implicitly verifies
raandsp: an incorrect value for either normally returns to the wrong instruction or accesses the wrong stack and crashes.RV64E and LP64Q are excluded because their register sets or floating-point widths require different layouts. They continue to the generic backend instead of silently using an incompatible context representation.
The backend works because it saves exactly the state that the RISC-V ELF ABI says must survive an ordinary C function call. From each coroutine’s perspective,
co_switch()behaves like a function that pauses and later returns normally.rasps0–s11fs0–fs11fcsrThe register classification comes from the [RISC-V ELF psABI calling convention](https://riscv-non-isa.github.io/riscv-elf-psabi-doc/).
How a context switch happens
The C wrapper passes two context pointers to the assembly routine:
By the normal RISC-V calling convention:
The assembly first saves the current coroutine:
It then loads the target coroutine:
The final
retjumps to theraloaded from the target context.For a suspended coroutine, that
rapoints immediately after its earlier call toco_switch_riscv64(). Execution therefore continues as thoughco_switch()had just returned.For a new coroutine, co_create() initializes:
Its first
retenters the trampoline on the newly allocated stack. The trampoline invokes the actual coroutine entry function and aborts if that function unexpectedly returns.Why caller-saved registers are omitted
The backend does not need to save
a0–a7ort0–t6. They are caller-saved registers. When the compiler generates a call toco_switch(), it already spills any live caller-saved values that will be needed afterward.Likewise:
gpis fixed by the ABI and must not be modified.tpidentifies the current OS thread. Fluent Bit coroutines remain on the same pthread, so it must remain unchanged.co_switch().This backend therefore assumes that a coroutine is never migrated to another pthread, matching Fluent Bit’s current coroutine model.
Floating-point ABI handling
The compiler exposes the selected ABI through predefined macros:
__riscv_float_abi_single__riscv_float_abi_doubleLP64D uses 64-bit operations:
LP64F uses 32-bit operations:
Soft-float LP64 does not preserve floating-point registers because that ABI does not classify them as callee-saved program state.
On a typical DC ROMA II LP64D environment, GCC should report:
Expected relevant definitions include:
These macros select riscv64.c and enable its double-precision register-save path.
Stack correctness
RISC-V requires the stack pointer to remain 16-byte aligned. Both the requested stack size and context header are rounded to multiples of 16. Linux RV64
malloc()supplies suitably aligned memory, so the calculated top of the allocation remains 16-byte aligned.The stack grows downward from that address, while the saved context resides at the bottom of the allocation:
How the focused test proves preservation
The test commit does more than verify that switching does not crash:
s0–s11,fs0–fs11, andfcsr.Correct return flow also implicitly verifies
raandsp: an incorrect value for either normally returns to the wrong instruction or accesses the wrong stack and crashes.RV64E and LP64Q are excluded because their register sets or floating-point widths require different layouts. They continue to the generic backend instead of silently using an incompatible context representation.
Enter
[N/A]in the box, if an item is not applicable to your change.Testing
Before we can approve your change; please submit the following in a comment:
If this is a change to packaging of containers or native binaries then please confirm it works for all targets.
ok-package-testlabel to test for all targets (requires maintainer to do).Documentation
Backporting
Fluent Bit is licensed under Apache 2.0, by submitting this pull request I understand that this code will be released under the terms of that license.