gdt.rs 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. use core::arch::asm;
  2. use crate::task::TSS;
  3. #[repr(transparent)]
  4. #[derive(Debug, Clone, Copy)]
  5. pub struct GDTEntry(u64);
  6. pub struct GDT([GDTEntry; GDT::LEN]);
  7. impl GDTEntry {
  8. const NULL: Self = Self(0);
  9. const KERNEL_CODE64: Self = Self::new(0, 0, 0x9a, 0x2);
  10. const KERNEL_DATA64: Self = Self::new(0, 0, 0x92, 0x0);
  11. const USER_CODE64: Self = Self::new(0, 0, 0xfa, 0x2);
  12. const USER_DATA64: Self = Self::new(0, 0, 0xf2, 0x0);
  13. const USER_CODE32: Self = Self::new(0, 0xfffff, 0xfa, 0xc);
  14. const USER_DATA32: Self = Self::new(0, 0xfffff, 0xf2, 0xc);
  15. pub const fn new(base: u32, limit: u32, access: u8, flags: u8) -> Self {
  16. let mut entry = 0u64;
  17. entry |= (limit & 0x0000_ffff) as u64;
  18. entry |= ((limit & 0x000f_0000) as u64) << 32;
  19. entry |= ((base & 0x00ff_ffff) as u64) << 16;
  20. entry |= ((base & 0xff00_0000) as u64) << 32;
  21. entry |= (access as u64) << 40;
  22. entry |= (flags as u64) << 52;
  23. GDTEntry(entry)
  24. }
  25. pub const fn new_ldt(base: u64, limit: u32) -> [Self; 2] {
  26. let first = Self::new(base as u32, limit, 0x82, 0x0);
  27. let second = Self(base >> 32);
  28. [first, second]
  29. }
  30. pub const fn new_tss(base: u64, limit: u32) -> [Self; 2] {
  31. let first = Self::new(base as u32, limit, 0x89, 0x0);
  32. let second = Self(base >> 32);
  33. [first, second]
  34. }
  35. }
  36. impl GDT {
  37. const LEN: usize = 10;
  38. const TLS32_INDEX: usize = 7;
  39. const TSS_INDEX: usize = 8;
  40. pub fn new() -> Self {
  41. Self([
  42. GDTEntry::NULL,
  43. GDTEntry::KERNEL_CODE64,
  44. GDTEntry::KERNEL_DATA64,
  45. GDTEntry::USER_CODE64,
  46. GDTEntry::USER_DATA64,
  47. GDTEntry::USER_CODE32,
  48. GDTEntry::USER_DATA32,
  49. GDTEntry::NULL, // User TLS 32bit
  50. GDTEntry::NULL, // TSS Descriptor Low
  51. GDTEntry::NULL, // TSS Descriptor High
  52. ])
  53. }
  54. pub fn set_tss(&mut self, base: u64) {
  55. let tss = GDTEntry::new_tss(base, size_of::<TSS>() as u32 - 1);
  56. self.0[Self::TSS_INDEX] = tss[0];
  57. self.0[Self::TSS_INDEX + 1] = tss[1];
  58. }
  59. pub fn set_tls32(&mut self, desc: GDTEntry) {
  60. self.0[7] = desc;
  61. }
  62. pub unsafe fn load(&self) {
  63. let len = Self::LEN * 8 - 1;
  64. let descriptor: [u64; 2] = [(len as u64) << 48, self.0.as_ptr() as u64];
  65. assert!(len < 0x10000, "GDT too large");
  66. let descriptor_address = &descriptor as *const _ as usize + 6;
  67. asm!(
  68. "lgdt ({})",
  69. "ltr %ax",
  70. in(reg) descriptor_address,
  71. in("ax") Self::TSS_INDEX as u16 * 8,
  72. options(att_syntax)
  73. );
  74. }
  75. }