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

Fix register restoration #50

Merged
merged 1 commit into from
Dec 9, 2024
Merged

Fix register restoration #50

merged 1 commit into from
Dec 9, 2024

Conversation

stevenewald
Copy link
Owner

@stevenewald stevenewald commented Dec 9, 2024

Previously, I tried to be clever. After returning from an async callback, it would restore registers from the stack in userspace. This made it fast (not that it really matters), but also left it vulnerable to an interrupt during register restoration, which would cause corruption of the stack.

This is a crude diagram of the stack with the new design

After yield(), assuming callback is ready
-- original stack ptr (before yield) --
-- regs pushed to stack on SVC entry from yield --
-- new regs that we created so we go to async callback on return --
-- new stack ptr (right before we return from kernel during exception) --

During callback
-- original stack ptr (before yield) --
-- regs pushed to stack on SVC entry from yield --
-- stack allocations during async callback --
-- new stack ptr --

After we return from callback, which triggers a REG_RESTORE SVC call, and brings us to kernel
-- original stack ptr (before yield) --
-- regs pushed to stack on SVC entry from yield --
-- regs pushed to stack on REG_RESTORE svc call --
-- new stack ptr --

After we return from kernel space, we will pop the regs on the stack. We can increment the stack ptr and skip over the regs pushed to stack on REG_RESTORE call (we don't care about the async callback regs at this point, we are returning from it), which will return us to the original location.

* I don't think this current isolation technique will work for bss, so I've enabled user read/write of all bss code
* If we made a real OS, we would have a different binary for each program, but because this is a mini os, we didn't bother.
*
* Because of this reason (and discovering it during finals week), I have disabled the MPU
Copy link
Collaborator

Choose a reason for hiding this comment

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

agree

asm volatile("ldr pc, [sp, #-84]");
void Scheduler::restore_current_task_regs(exception_stack_registers* regs)
{
__set_PSP(reinterpret_cast<unsigned>(&regs[1]) + 4);
Copy link
Owner Author

Choose a reason for hiding this comment

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

exception_stack_regs already contains reserved regs due to alignment. I don't know why this is +4. It works though. lol

@@ -11,7 +11,8 @@ class GPIOPinEvent {
GPIOPinEvent(
uint8_t pin, GPIOConfiguration resistance,
aidan::GPIOEventController::GPIOEventCallback callback
) : pin(pin)
) :
Copy link
Collaborator

Choose a reason for hiding this comment

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

i think ur nvim formatter is clashing with make format

@stevenewald stevenewald merged commit a7177f4 into main Dec 9, 2024
1 check passed
@stevenewald stevenewald deleted the fix-reg-restore branch December 9, 2024 17:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants