1use crate::segmentation::SegmentSelector;
3use core::arch::asm;
4use core::fmt;
5use core::mem::size_of;
6
7#[repr(C, packed)]
10pub struct DescriptorTablePointer<Entry> {
11 pub limit: u16,
13 pub base: *const Entry,
15}
16
17impl<T> Default for DescriptorTablePointer<T> {
18 fn default() -> DescriptorTablePointer<T> {
19 DescriptorTablePointer {
20 limit: 0,
21 base: core::ptr::null(),
22 }
23 }
24}
25
26impl<T> DescriptorTablePointer<T> {
27 pub fn new(tbl: &T) -> Self {
28 let len = size_of::<T>() - 1;
32 assert!(len < 0x10000);
33 DescriptorTablePointer {
34 base: tbl as *const T,
35 limit: len as u16,
36 }
37 }
38
39 pub fn new_from_slice(slice: &[T]) -> Self {
40 let len = slice.len() * size_of::<T>() - 1;
44 assert!(len < 0x10000);
45 DescriptorTablePointer {
46 base: slice.as_ptr(),
47 limit: len as u16,
48 }
49 }
50}
51
52impl<T> fmt::Debug for DescriptorTablePointer<T> {
53 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
54 write!(f, "DescriptorTablePointer ({} {:?})", { self.limit }, {
55 self.base
56 })
57 }
58}
59
60pub unsafe fn lgdt<T>(gdt: &DescriptorTablePointer<T>) {
65 asm!("lgdt ({0})", in(reg) gdt, options(att_syntax));
66}
67
68pub unsafe fn sgdt<T>(idt: &mut DescriptorTablePointer<T>) {
73 asm!("sgdt ({0})", in(reg) idt as *mut DescriptorTablePointer<T>, options(att_syntax));
74}
75
76pub unsafe fn load_ldtr(selector: SegmentSelector) {
87 asm!("lldt {0:x}", in(reg) selector.bits(), options(att_syntax));
88}
89
90pub unsafe fn ldtr() -> SegmentSelector {
98 let selector: u16;
99 asm!("sldt {0:x}", out(reg) selector, options(att_syntax));
100 SegmentSelector::from_raw(selector)
101}
102
103pub unsafe fn lidt<T>(idt: &DescriptorTablePointer<T>) {
108 asm!("lidt ({0})", in(reg) idt, options(att_syntax));
109}
110
111pub unsafe fn sidt<T>(idt: &mut DescriptorTablePointer<T>) {
116 asm!("sidt ({0})", in(reg) idt as *mut DescriptorTablePointer<T>, options(att_syntax));
117}
118
119#[cfg(all(test, feature = "utest"))]
120mod test {
121 use super::*;
122
123 #[test]
124 fn check_sgdt() {
125 let mut gdtr: super::DescriptorTablePointer<u64> = Default::default();
126 gdtr.limit = 0xdead;
127 gdtr.base = 0xbadc0de as *mut u64;
128 unsafe {
129 sgdt(&mut gdtr);
130 }
131 let base = gdtr.base;
132 let limit = gdtr.limit;
133 assert_ne!(base, core::ptr::null_mut());
134 assert_ne!(limit, 0xdead);
135 assert_ne!(base as u64, 0xbadc0de);
136 }
137
138 #[test]
139 fn check_sidt() {
140 let mut gdtr: super::DescriptorTablePointer<u64> = Default::default();
141 gdtr.limit = 0xdead;
142 gdtr.base = 0xbadc0de as *mut u64;
143 unsafe {
144 sidt(&mut gdtr);
145 }
146 let base = gdtr.base;
147 let limit = gdtr.limit;
148 assert_ne!(base, core::ptr::null_mut());
149 assert_ne!(limit, 0xdead);
150 assert_ne!(base as u64, 0xbadc0de);
151 }
152}