user.rs 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
  1. use core::pin::Pin;
  2. use super::{CPU, GDTEntry};
  3. #[derive(Debug, Clone)]
  4. pub enum UserTLS {
  5. /// TODO: This is not used yet.
  6. #[allow(dead_code)]
  7. TLS64(u64),
  8. TLS32 {
  9. base: u64,
  10. desc: GDTEntry,
  11. },
  12. }
  13. impl UserTLS {
  14. /// # Return
  15. /// Returns the TLS descriptor and the index of the TLS segment.
  16. pub fn new32(base: u32, limit: u32, is_limit_in_pages: bool) -> (Self, u32) {
  17. let flags = if is_limit_in_pages { 0xc } else { 0x4 };
  18. (
  19. Self::TLS32 {
  20. base: base as u64,
  21. desc: GDTEntry::new(base, limit, 0xf2, flags),
  22. },
  23. 7,
  24. )
  25. }
  26. pub fn load(&self, cpu_status: Pin<&mut CPU>) {
  27. match self {
  28. Self::TLS64(base) => {
  29. const IA32_KERNEL_GS_BASE: u32 = 0xc0000102;
  30. super::wrmsr(IA32_KERNEL_GS_BASE, *base);
  31. }
  32. Self::TLS32 { base, desc } => {
  33. unsafe {
  34. // SAFETY: We don't move the CPUStatus object.
  35. let cpu_mut = cpu_status.get_unchecked_mut();
  36. cpu_mut.set_tls32(*desc);
  37. }
  38. const IA32_KERNEL_GS_BASE: u32 = 0xc0000102;
  39. super::wrmsr(IA32_KERNEL_GS_BASE, *base);
  40. }
  41. }
  42. }
  43. }
  44. pub unsafe fn load_interrupt_stack(cpu_status: Pin<&mut CPU>, stack: u64) {
  45. // SAFETY: We don't move the CPUStatus object.
  46. cpu_status.get_unchecked_mut().set_rsp0(stack);
  47. }