-
Notifications
You must be signed in to change notification settings - Fork 18
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
8bd35ba
commit b5448e6
Showing
6 changed files
with
128 additions
and
3 deletions.
There are no files selected for viewing
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
use super::Context; | ||
|
||
pub unsafe fn activate(_: *mut Context) { | ||
todo!(); | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
use crate::proc::Thread; | ||
use alloc::sync::Arc; | ||
|
||
#[cfg_attr(target_arch = "aarch64", path = "aarch64.rs")] | ||
#[cfg_attr(target_arch = "x86_64", path = "x86_64.rs")] | ||
mod arch; | ||
|
||
/// Implementation of `pcpu` structure. | ||
/// | ||
/// Access to this structure must be done by **atomic reading or writing its field directly**. It is | ||
/// not safe to have a temporary a pointer or reference to this struct or its field because the CPU | ||
/// might get interupted, which mean it is possible for the next instruction to get executed on | ||
/// a different CPU if the interupt cause the CPU to switch the task. | ||
/// | ||
/// We don't support `pc_cpuid` field here because it value is 100% unpredictable due to the above | ||
/// reason. Once we have loaded `pc_cpuid` the next instruction might get executed on a different | ||
/// CPU, which render the loaded value incorrect. The only way to prevent this issue is to disable | ||
/// interupt before reading `pc_cpuid`, which can make the CPU missed some events from the other | ||
/// hardwares. | ||
pub struct Context { | ||
thread: *const Thread, // pc_curthread | ||
} | ||
|
||
impl Context { | ||
/// See `pcpu_init` on the PS4 for a reference. | ||
pub fn new(td: Arc<Thread>) -> Self { | ||
Self { | ||
thread: Arc::into_raw(td), | ||
} | ||
} | ||
|
||
/// # Safety | ||
/// The only place this method is safe to call is in the CPU entry point. Once this method | ||
/// return this instance must outlive the CPU lifetime and it must never be accessed via this | ||
/// variable again. The simple way to achieve this is keep the activated [`Context`] as a local | ||
/// variable then move all code after it to a dedicated no-return function. | ||
pub unsafe fn activate(&mut self) { | ||
self::arch::activate(self); | ||
} | ||
} | ||
|
||
impl Drop for Context { | ||
fn drop(&mut self) { | ||
unsafe { drop(Arc::from_raw(self.thread)) }; | ||
} | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
use super::Context; | ||
use core::arch::asm; | ||
|
||
/// Set kernel `GS` segment register to `cx`. | ||
/// | ||
/// This also set user-mode `FS` and `GS` to null. | ||
pub unsafe fn activate(cx: *mut Context) { | ||
// Set GS for kernel mode. | ||
let cx = cx as usize; | ||
|
||
asm!( | ||
"wrmsr", | ||
in("ecx") 0xc0000101u32, | ||
in("edx") cx >> 32, | ||
in("eax") cx, | ||
options(preserves_flags, nostack) | ||
); | ||
|
||
// Clear FS and GS for user mode. | ||
asm!( | ||
"wrmsr", | ||
in("ecx") 0xc0000100u32, | ||
in("edx") 0, | ||
in("eax") 0, | ||
options(preserves_flags, nostack) | ||
); | ||
|
||
asm!( | ||
"wrmsr", | ||
in("ecx") 0xc0000102u32, | ||
in("edx") 0, | ||
in("eax") 0, | ||
options(preserves_flags, nostack) | ||
); | ||
} |
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
pub use self::thread::*; | ||
|
||
mod thread; |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
/// Implementation of `thread` structure. | ||
pub struct Thread {} | ||
|
||
impl Thread { | ||
/// # Safety | ||
/// This function does not do anything except initialize the struct memory. It is the caller | ||
/// responsibility to configure the thread after this so it have a proper states and trigger | ||
/// necessary events. | ||
pub unsafe fn new_bare() -> Self { | ||
Self {} | ||
} | ||
} |