-
Notifications
You must be signed in to change notification settings - Fork 9
Add warm_boot_entry for suspend support #40
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -32,7 +32,7 @@ use core::arch::asm; | |
| #[cfg(not(feature = "initial-pagetable"))] | ||
| use core::arch::naked_asm; | ||
| use core::mem::ManuallyDrop; | ||
| pub use entry::secondary_entry; | ||
| pub use entry::{SuspendContext, secondary_entry, warm_boot_entry}; | ||
| #[cfg(feature = "exceptions")] | ||
| pub use exceptions::{ExceptionHandlers, RegisterState, RegisterStateRef}; | ||
| #[cfg(all(feature = "initial-pagetable", feature = "el1"))] | ||
|
|
@@ -333,3 +333,36 @@ fn dsb_st() { | |
| asm!("dsb st", options(nostack)); | ||
| } | ||
| } | ||
|
|
||
| #[cfg(feature = "psci")] | ||
| /// Issues a PSCI CPU_SUSPEND call to suspend the current CPU core. | ||
| /// | ||
| /// If the PSCI CPU_SUSPEND call doesn't return, then on resume `warm_boot_entry` will be called to | ||
| /// re-enable the MMU, set the given stack pointer, set the exception vector, and then call the | ||
| /// given `entry` function with `data` as its parameter. | ||
| /// | ||
| /// # Safety | ||
| /// | ||
| /// `stack_ptr` must be a valid stack pointer to use for the resuming core. Depending on how you | ||
| /// want to handle resuming this could either be the bottom of the stack (if you want to treat | ||
| /// resuming like `CPU_ON`) or the top (if `entry` will restore register state and return from the | ||
| /// point where the suspend happened). | ||
| pub unsafe fn suspend_core<C: smccc::Call, T: Sized>( | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We don't use |
||
| power_state: u32, | ||
| stack_ptr: *mut u64, | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nitpick: it feels like this should be |
||
| entry: extern "C" fn(u64) -> !, | ||
| data: u64, | ||
| ) -> Result<(), smccc::psci::Error> { | ||
| let suspend_context = SuspendContext { | ||
| stack_ptr, | ||
| entry, | ||
| data, | ||
| }; | ||
| // Passing a pointer to `suspend_context` is safe here, because it will remain valid until | ||
| // either `cpu_suspend` returns or the stack pointer is reset by `warm_boot_entry`. | ||
| smccc::psci::cpu_suspend::<C>( | ||
| power_state, | ||
| warm_boot_entry as u64, | ||
| (&raw const suspend_context) as u64, | ||
| ) | ||
| } | ||
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 stack pointer needs to be set before calling
set_exception_vector, as it is a Rust function. It may also clobberx0andx1, so you need to get the entry function pointer after this.