-
-
Notifications
You must be signed in to change notification settings - Fork 779
RISC-V: Add context switching #1323
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
Conversation
| lw x30, 31*4(sp) | ||
| lw x31, 32*4(sp) | ||
| addi sp, sp, 33*4 // Reset kernel stack pointer |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is a lot of assembly here. At this point, however, with the kernel registers restored, we should be able to switch back to rust. The reason it is all in assembly is that the assembly needs the reference to state, but once I pass the &mut state to asm!() Rust complains whenever I try to use it again. If someone knows how to remedy this we can probably remove some of this assembly.
| */ | ||
| KEEP(*(.riscv.start)); | ||
| . = ALIGN(64); | ||
| KEEP(*(.riscv.trap)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The trap handler must be aligned to a multiple of 64 bytes. With global_asm!() this could be inserted in the assembly for the start trap function. However, using functions with asm!() I think the only place to add this is here. Does anyone know a better way?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To remove the padding on boards without this, this works:
. = DEFINED(_start_trap) ? ALIGN(64) : ALIGN(1);
Though whether it's worth the worst-case 63 bytes, I'm not sure I care as much
Obviously setting the baud rate for UART depends on the clock speed. Make this a parameter because different boards use different settings. We probably want a more formal way to do this, but this is simple and works for now.
Co-authored-by: Samyukta Venkat <[email protected]>
|
OK anyone want to take a look at this? I think we should merge quickly so we can work on #1324 more easily, and get this in for 1.4 release testing. |
|
Maybe @DieracDelta can take a look? @bradjc can you maybe add a link in the PR to whatever RISC-V reference is appropriate for this? |
|
All that said, I agree we should merge this reasonably promptly, since we decided we're allowing RISC-V to move fast for now as long as it's changes that don't interfere with other platforms. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 to generally staying out of the way of self-contained RISC-V stuff for now, mostly looks good to me, a few comments but nothing I would hard-block on.
Final thought, maybe a README or something in the cores directory explaining what this beast is:
boards/arty-e21/core/sifive_coreip_E21_FPGA_Evaluation_v19_02_rc0.mcs
?
| */ | ||
| KEEP(*(.riscv.start)); | ||
| . = ALIGN(64); | ||
| KEEP(*(.riscv.trap)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To remove the padding on boards without this, this works:
. = DEFINED(_start_trap) ? ALIGN(64) : ALIGN(1);
Though whether it's worth the worst-case 63 bytes, I'm not sure I care as much
Co-Authored-By: Niklas Adolfsson <[email protected]>
|
Any other comments? |
| } | ||
| } | ||
| 1 => kernel::syscall::ContextSwitchReason::Interrupted, | ||
| 2 => kernel::syscall::ContextSwitchReason::Fault, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this seems redundant, would be caught by wildcard
| pub struct SysCall(); | ||
|
|
||
| impl SysCall { | ||
| pub const unsafe fn new() -> SysCall { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unnecessary unsafe, alternatively add some docs which explains why it is marked as unsafe
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree that this is only meaningful if SysCall cannot otherwise be easily instatiated by anyone (which I believe this unsafe is meant to protect)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is either a copy-and-paste artifact, or the unsafe was needed at some point during the development, and the compiler only tells you when it is necessary to add it.
arch/rv32i/src/syscall.rs
Outdated
| } | ||
|
|
||
| /// Implementation of the `UserspaceKernelBoundary` for the RISC-V architecture. | ||
| pub struct SysCall(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would prefer pub struct SysCall; over empty unit struct but it is ok.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, I think none of the above (including what’s in the code) is what we want. All of these options allow anyone to construct a SysCall since all of it’s fields (of which there are none) are public.
SysCall needs to be a singleton (I think?), and should only be insatiable through the unsafe fn new() function.
The declaration should, therefore, be:
pub struct SysCall( () ); // Can elide spacesWhich would result in an error if someone outside of this module tries to create one. Unlike:
pub struct SysCall(pub ());Which can be instantiated by anyone.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, if it needs to be a singleton then it makes sense.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I updated this correctly, let me know if not.
| } | ||
|
|
||
| impl ArtyExx { | ||
| pub unsafe fn new() -> ArtyExx { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unsafe block could be removed if you agree with my comment in SysCall impl
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is cool, LGTM overall but I haven't read the assembly stuff...
Added some inline comments mainly rust style stuff
arch/rv32i/src/syscall.rs
Outdated
| pub struct SysCall(()); | ||
|
|
||
| impl SysCall { | ||
| pub const fn new() -> SysCall { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it, or is it not safe to have multiple instances of SysCall? If it is, than this is fine, but the definition of SysCall doesn't need to have any extra parens or unit types, just a plain pub struct SysCall; is good enough.
If it does, then this has to be marked unsafe.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a discrepancy we have in the cortex-m variants as well (where this was likely copied from). Let's decide here and fix in the cortex-m in a different PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It certainly doesn't make a lot of sense to have multiple SysCall objects, but I'm not sure if it is strictly safe or not. Since everything is handled on the stack it might be safe.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We typically think of it as potentially unsafe when we have might end up with two instances that use the same set of hardware registers, so that they are not actually isolated instances...
I think in this particular case, I think switch_to_process is what should motivate us to ensure SysCall is a singleton and keep new unsafe: It's operating on a shared hardware variables, such as mscratch, mepc etc...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree.
|
bors r+ |
1323: RISC-V: Add context switching r=bradjc a=bradjc ### Pull Request Overview This pull request implements the `UserlandKernelBoundary` trait for RISC-V platforms. This PR is towards tracking issue #1135. This depends on #1318 so those commits have been included here. That PR should be merged first, and then I can update this one. While I pulled things together for the PR, @sv2bb did much of this. ### Testing Strategy This pull request was tested by running blink and c_hello on the the arty-e21 FPGA based board. ### TODO or Help Wanted See inline comments. ### Documentation Updated - [x] Updated the relevant files in `/docs`, or no updates are required. ### Formatting - [x] Ran `make formatall`. Co-authored-by: Brad Campbell <[email protected]>
Build succeeded |
Pull Request Overview
This pull request implements the
UserlandKernelBoundarytrait for RISC-V platforms.This PR is towards tracking issue #1135.
This depends on #1318 so those commits have been included here. That PR should be merged first, and then I can update this one.
While I pulled things together for the PR, @sv2bb did much of this.
Testing Strategy
This pull request was tested by running blink and c_hello on the the arty-e21 FPGA based board.
TODO or Help Wanted
See inline comments.
Documentation Updated
/docs, or no updates are required.Formatting
make formatall.