-
Notifications
You must be signed in to change notification settings - Fork 653
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
Move allow_readwrite and allow_readonly from SyscallDriver into common Grant framework #2906
Conversation
In order for
@phil-levis Would modifying TRD 104 or adding a new TRD be the correct process to do this? |
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 like the design overall, most of these comments are nits. I will try to take a pass on porting some more capsules sometime this week
One high-level comment:
There is a lot of code de-duplication in this PR which is largely separate from adding the actual allow implementations. For enter_grant_kernel_managed()
it makes sense from a code size perspective. De-duplicating the code in access_grant()
and access_grant_with_allocator()
is nice, though I do wonder what the implications are / if there was a reason those were initially duplicated code instead of what you have done. Most boards will never use the allocator so that is something to think about.
Regarding your potential cleanups:
- getting rid of Default for the ProcessBuffer types would be nice, and I don't immediately see any reason we shouldn't. Being able to drop the ref types in that case would be a win.
- I did try adding an
access_grant_inner()
when I first made a de-monomorphization pass on the grant code, and found doing so actually increased code size because there was not enough that could be taken out into the inner function to offset the extra overhead of a function call in the outer one. That may be worth revisiting though, given how much this file has changed. Either way I think that may be best left for a followup PR.
Boy scout motto: always try to leave the place cleaner than when you found it :) Also it pains me to copy and paste code when it is reasonable to de-dup it. There is much less potential for future mistakes. I also couldn't find any good reason to not de-dep in this way. I am actually now thinking about have make the allocator version an internal one that takes in its closure by Thanks for being willing to help out to convert some of these files! I figured we could just take an alphabetic chunk of the files. When someone wants to take a batch of files, please comment here first so we don't duplicate effort. I am going to take a batch of files later today since it seems like there aren't any major red flags with this PR. I will post the chunk I take then. |
Yay, this is still a draft! I added a commit that updates this draft TRD. I was going to add some text, but I thought the cleanest way to modify it was to actually just remove the paragraph that Johnathan mentioned completely; this matches the way the subscribe section is worded by not calling to attention that the application can rely on this behavior. |
My main concern here was that having Monomorphizing only on return type would be an interesting optimization for size -- many closures probably use the same few return types (e.g.
Alphabetic sounds good to me, I won't be touching anything today so I can take whatever chunk comes after yours. |
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 went through grant.rs and kernel.rs pretty closely and they look good to me.
The only thing I'm not 100% about is GrantEnterLifetimeGuard
. process.leave_grant(grant_num);
is only one line and provides a clear window between when the grant is entered and left. Adding another type and instructing the caller to hold on to the type seems like extra complexity for not a lot of benefit.
Thank you for taking a thorough look at it! I appreciate it!
It seems more dangerous (from incorrect behavior POV) to have the unmatched enter and leave grants occur because someone accidentally used the Should we make the guard hold the pointer, so you have to access the guard to get the pointer? I will upload a commit for that. |
That doesn't work as well as I thought for the two places we use it. I would want to wrap a |
I converted two files. These conversions take more time than I would have hoped. I do like the paradigm of creating something like the following at the top of the file. Thoughts? /// Ids for read-only allow buffers
mod ro_allow {
pub const WRITE: usize = 0;
/// The number of allow buffers the kernel stores for this grant
pub const COUNT: usize = 1;
}
/// Ids for read-write allow buffers
mod rw_allow {
pub const READ: usize = 0;
pub const CFG: usize = 1;
pub const RX_CFG: usize = 2;
/// The number of allow buffers the kernel stores for this grant
pub const COUNT: usize = 3;
} |
Thanks for doing the networking capsules, those are probably 2 of the harder ones to take on. I am a fan of that paradigm |
That was a marathon! I finished converting everything over and removed the I pulled out conversions to their own commit if there were any non-trivial changes-- specifically ipc, touch, screen, and bluetooth. Looks like we can't immediately remove the Assuming everything looks okay (I am assuming there will be feedback to incorporate first), this is ready to land! |
Looks like I already have a rebase conflict, should we leave it for now and do one rebase and force push at the end of the review or should I rebase and force push now (or try to merge mainline changes into this branch)? |
I suppose whatever works best for you. This touches a large number of files, sometimes it's easier to keep on track with smaller, more frequent conflicts. |
Surprisingly, this only saves 530 bytes of code size on Imix. While that is still a win, I must admit I was expecting a little more |
This is surprising, I was seeing about ~200 bytes savings for every |
I would like this PR even if there were no savings -- the reduction in duplicated code + correctness guarantees are really valuable. I am just surprised by the result |
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 tried out the IPC libtock-c apps (rot13_service/rot13_client) with this branch, and they do not work. That should be fixed before this is merged. I tried to debug it briefly but did not discover the cause -- I should have some time tomorrow to look further
We might just want to try out the alternate approach for IPC that leaves the handles unchanged. This does mean that every readwrite_allow call into the kernel will check for the IPC driver number for the special case logic, but I think that might be an okay cost to pay. Thoughts? |
I figured out what is wrong with the IPC implementation: the Is it okay to change the libtock-c implementation right now or should I put in the special case handling code for IPC in kernel? |
I made the speculative change for IPC in a libtock-c PR. This seems like the way to go. This will also let us drop the |
My instinct is that your fix is preferable -- I think we should avoid special case handling for IPC if at all possible, especially since there are a number of issues with IPC that we would still like to eventually resolve, and given that plenty of boards choose not to include IPC, and we would like to keep that decision zero cost. IPC is not a stable driver, so I think we can update it without a major version bump, but I think a minor version bump might be prudent. That said, we are probably due for a minor version bump reasonably soon anyway. Removing the extra upcall from the IPC driver is a nice added bonus. |
Changing IPC is fine. We don't guarantee any stability so we don't have to worry about version numbers. |
All tests should be passing now with the libtock-c PR change! Everything is rebased on ToT and merge conflicts are resolved. |
To update screen, it required non-trivial changes: - Allowing a buffer no longer check for the correct length - This check has been moved to the fill and write operation - Setting a new buffer while writing, will not start at the beginning of the buffer. This is okay because the documentation calls this out as undefined behavior Change-Id: Ia5ca9fd2dca559c990c83a565fe2fef8b7904951
To update touch, it required a non-trivial change: - Allowing a buffer no longer checks for multi touch support Change-Id: Ia5ca9fd2dca559c990c83a565fe2fef8b7904951
These files did not require any special changes Change-Id: Icd0b521e93e183ef5adafe1121f97720ae3d98c9
To move IPC over to kernel-based allow, the following significant change was made: - The target id returned by discover and used to notified is now the direct index number in the process array instead of an identifier - This means that the target process could restart and the sending process would not have to re-register the allow buffer again. This actually seems like behavior we might want since the sending process only has the granularity to discover by process name which only has the granularity of index within the process array. From the caller (application) POV, nothing should have changed. They still need to discover a target_id, then register an allow buffer and notify with that target_id. They same flow will work before and after this change. Change-Id: Ia0a7a54d464fe199be11552de71b36956e79fa5a
Now that kernel has taken over the read-only and read-write allow operations, remove the function from the SyscallDriver interface Change-Id: Id563e34c2d29baadc5879646a08ff776f85bf3bb
After reworking IPC implementation to use kernel-based allow framework, we only need NUM_PROCS upcalls instead of NUM_PROCS + 1 upcalls. We can remove the NUM_UPCALLS_IPCS concept everywhere. Change-Id: I4a280a935505d57ddf6c68b666f3e25fba7e89b1
The allows function set the active app, but we can no longer do that. Instead we should set the active app variable in the command right before we make the uart call that will trigger the callback which uses the active_app variable. Change-Id: Ia01a4c2ab669b46fcec986343b69bf5f1f269eb4
Now that the kernel handles allowing buffers, we can be more certain about which return code are return for which scenarios. Add this information to the documentation. Change-Id: I6c704f53279fd66e4a9c7e0f1529fc284f61c5cf
Change-Id: I624c87e4a49851299f96939d15c35d3bb5b515fe
Update comments to match new allow mechanics, and try to keep consistency.
The `Process::enqueue_task` function does not provide any information on whether or not a scheduled callback is a null-callback. Furthermore, we are scheduling an IPC task, which will ultimately get routed back to us. This will always succeed as long as there is sufficient space in the Process task queue and there are no other kernel-internal errors. Hence this removes a misleading comments about being able to handle null-callbacks differently here. Signed-off-by: Leon Schuermann <leon@is.currently.online>
Done. And thank you for figuring out the issue with libtock-c! |
271: ipc: allow registering client callback with svc_id = 0 r=hudson-ayers a=lschuermann ### Pull Request Overview With the changes of 321a5a0 ("ipc: register service callback with service name") and tock/tock#2906, it is possible for a service to be assigned the svc_id = 0. Thus we must allow clients to register callbacks with this svc_id. ### Testing Strategy This pull request was tested by running the failing LiteX simulation CI workflow locally. This resolves one of the issues of the failing CI. ### TODO or Help Wanted This pull request does not fix all of the issues of tock/tock#2906. Somehow these changes appear to affect either the load order or scheduling behavior of the rot13_{service,client} apps. Because IPC service discovery seems fundamentally racy, with currently no reliable way to tell whether notifying a service worked, it requires further changes to work reliably. Co-authored-by: Leon Schuermann <leon@is.currently.online>
No worries! And wohoo, the CI is happy again! |
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.
bors r+
finally!
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 looked over most of this PR, especially the kernel code and it looks pretty good to me. Great work @jettr!
welp... it appears i was a little to slow. :) |
270: ipc: register service callback with service name r=hudson-ayers a=jettr Use package name of service to register the service callback. This makes it more clear API and makes the kernel side easier. It will allow us to drop any special case code in kernel for IPC and it will most likely allow us to drop the `NUM_UPCALLS` const generic as well (and we can just use `NUM_PROCS` for both upcall and allows) See [RFC: Move allow_readwrite and allow_readonly from SyscallDriver into common Grant framework][0] for motivation [0]:tock/tock#2906 Co-authored-by: Jett Rink <jettrink@google.com>
With the changes of 321a5a0 ("ipc: register service callback with service name") and tock/tock#2906, it is possible for a service to be assigned the svc_id = 0. Thus we must allow clients to register callbacks with this svc_id. Fixes: 321a5a0 ("ipc: register service callback with service name") Signed-off-by: Leon Schuermann <leon@is.currently.online>
271: ipc: allow registering client callback with svc_id = 0 r=hudson-ayers a=lschuermann ### Pull Request Overview With the changes of 321a5a0 ("ipc: register service callback with service name") and tock/tock#2906, it is possible for a service to be assigned the svc_id = 0. Thus we must allow clients to register callbacks with this svc_id. ### Testing Strategy This pull request was tested by running the failing LiteX simulation CI workflow locally. This resolves one of the issues of the failing CI. ### TODO or Help Wanted This pull request does not fix all of the issues of tock/tock#2906. Somehow these changes appear to affect either the load order or scheduling behavior of the rot13_{service,client} apps. Because IPC service discovery seems fundamentally racy, with currently no reliable way to tell whether notifying a service worked, it requires further changes to work reliably. Co-authored-by: Leon Schuermann <leon@is.currently.online>
Pull Request Overview
Similar to how we removed subscribe from the
SyscallDriver
trait in favor of the kernel always managing the data, do the same for read-only and read-write process buffers.This has multiple advantages
SyscallDriver
implementationallow_readonly
orallow_readwrite
costs about 170 bytes of flashNote each commit builds and compiles (but isn't necessarily functional)
Testing Strategy
So far, I have tried this code out locally with a modification in kernel that handles both the
SyscallDriver
and new Grant-based process buffer allows. I didn't upload that, but I was able to convert a few capsules over to the new approach and they worked correctly.Once we migrate all of the capsules, we would need to test again of course
TODO or Help Wanted
allow_readonly
andallow_readwrite
function on theSyscallDriver
traitPotential cleanup: we may no longer need theDefault
implementation onReadOnlyProcessBuffer
andReadWriteProcessBuffer
since they no longer needed in a capsule specific grant region, which requiredDefault
.Potential cleanup: if we can removeDefault
and impl for process buffers, then we should be able to directly put a lifetime constraint on the process buffer structs themselves. This will allow us to drop theRef
s versions and permit theunsafe
callers ofnew
to more easily uphold the invariant of the pointer lifetimePotential cleanup: add aaccess_grant_inner
function to de-monomorphize if needed for size reduction.Documentation Updated
/docs
Formatting
make prepush
.