1use bitflags::*;
4
5use core::arch::asm;
6use core::fmt;
7
8use crate::Ring;
9
10bitflags! {
11    pub struct SegmentSelector: u16 {
17        const RPL_0 = 0b00;
19        const RPL_1 = 0b01;
20        const RPL_2 = 0b10;
21        const RPL_3 = 0b11;
22
23        const TI_GDT = 0 << 2;
25        const TI_LDT = 1 << 2;
27    }
28}
29
30impl SegmentSelector {
31    pub const fn new(index: u16, rpl: Ring) -> SegmentSelector {
37        SegmentSelector {
38            bits: index << 3 | (rpl as u16),
39        }
40    }
41
42    pub fn index(&self) -> u16 {
44        self.bits >> 3
45    }
46
47    pub const fn from_raw(bits: u16) -> SegmentSelector {
49        SegmentSelector { bits }
50    }
51}
52
53impl fmt::Display for SegmentSelector {
54    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
55        let r0 = match self.contains(SegmentSelector::RPL_0) {
56            false => "",
57            true => "Ring 0 segment selector.",
58        };
59        let r1 = match self.contains(SegmentSelector::RPL_1) {
60            false => "",
61            true => "Ring 1 segment selector.",
62        };
63        let r2 = match self.contains(SegmentSelector::RPL_2) {
64            false => "",
65            true => "Ring 2 segment selector.",
66        };
67        let r3 = match self.contains(SegmentSelector::RPL_3) {
68            false => "",
69            true => "Ring 3 segment selector.",
70        };
71        let tbl = match self.contains(SegmentSelector::TI_LDT) {
72            false => "GDT Table",
73            true => "LDT Table",
74        };
75
76        write!(
77            f,
78            "Index {} in {}, {}{}{}{}",
79            self.bits >> 3,
80            tbl,
81            r0,
82            r1,
83            r2,
84            r3
85        )
86    }
87}
88
89#[allow(clippy::upper_case_acronyms)]
92#[repr(u8)]
93#[derive(Copy, Clone, Debug, Eq, PartialEq)]
94pub enum SystemDescriptorTypes64 {
95    LDT = 0b0010,
98    TssAvailable = 0b1001,
105    TssBusy = 0b1011,
107    CallGate = 0b1100,
108    InterruptGate = 0b1110,
110    TrapGate = 0b1111,
111}
112
113#[allow(clippy::upper_case_acronyms)]
116#[repr(u8)]
117#[derive(Copy, Clone, Debug, Eq, PartialEq)]
118pub enum SystemDescriptorTypes32 {
119    TSSAvailable16 = 0b0001,
121    LDT = 0b0010,
122    TSSBusy16 = 0b0011,
123    CallGate16 = 0b0100,
124    TaskGate = 0b0101,
125    InterruptGate16 = 0b0110,
126    TrapGate16 = 0b0111,
127    TssAvailable32 = 0b1001,
129    TssBusy32 = 0b1011,
131    CallGate32 = 0b1100,
132    InterruptGate32 = 0b1110,
134    TrapGate32 = 0b1111,
135}
136
137#[repr(u8)]
140#[derive(Copy, Clone, Debug, Eq, PartialEq)]
141pub enum DataSegmentType {
142    ReadOnly = 0b0000,
144    ReadOnlyAccessed = 0b0001,
146    ReadWrite = 0b0010,
148    ReadWriteAccessed = 0b0011,
150    ReadExpand = 0b0100,
152    ReadExpandAccessed = 0b0101,
154    ReadWriteExpand = 0b0110,
156    ReadWriteExpandAccessed = 0b0111,
158}
159
160#[repr(u8)]
163#[derive(Copy, Clone, Debug, Eq, PartialEq)]
164pub enum CodeSegmentType {
165    Execute = 0b1000,
167    ExecuteAccessed = 0b1001,
169    ExecuteRead = 0b1010,
171    ExecuteReadAccessed = 0b1011,
173    ExecuteConforming = 0b1100,
175    ExecuteConformingAccessed = 0b1101,
177    ExecuteReadConforming = 0b1110,
179    ExecuteReadConformingAccessed = 0b1111,
181}
182
183#[derive(Debug, Eq, PartialEq)]
185pub(crate) enum DescriptorType {
186    System64(SystemDescriptorTypes64),
187    System32(SystemDescriptorTypes32),
188    Data(DataSegmentType),
189    Code(CodeSegmentType),
190}
191
192pub trait GateDescriptorBuilder<Size> {
195    fn tss_descriptor(base: u64, limit: u64, available: bool) -> Self;
196    fn call_gate_descriptor(selector: SegmentSelector, offset: Size) -> Self;
197    fn interrupt_descriptor(selector: SegmentSelector, offset: Size) -> Self;
198    fn trap_gate_descriptor(selector: SegmentSelector, offset: Size) -> Self;
199}
200
201pub trait TaskGateDescriptorBuilder {
204    fn task_gate_descriptor(selector: SegmentSelector) -> Self;
205}
206
207pub trait SegmentDescriptorBuilder<Size> {
209    fn code_descriptor(base: Size, limit: Size, cst: CodeSegmentType) -> Self;
210    fn data_descriptor(base: Size, limit: Size, dst: DataSegmentType) -> Self;
211}
212
213pub trait LdtDescriptorBuilder<Size> {
216    fn ldt_descriptor(base: Size, limit: Size) -> Self;
217}
218
219pub trait BuildDescriptor<Descriptor> {
220    fn finish(&self) -> Descriptor;
221}
222
223#[derive(Debug)]
225pub struct DescriptorBuilder {
226    pub(crate) base_limit: Option<(u64, u64)>,
229    pub(crate) selector_offset: Option<(SegmentSelector, u64)>,
231    pub(crate) typ: Option<DescriptorType>,
233    pub(crate) dpl: Option<Ring>,
235    pub(crate) present: bool,
237    pub(crate) avl: bool,
239    pub(crate) db: bool,
241    pub(crate) limit_granularity_4k: bool,
243    pub(crate) l: bool,
245    pub(crate) ist: u8,
247}
248
249impl DescriptorBuilder {
250    pub(crate) fn with_base_limit(base: u64, limit: u64) -> DescriptorBuilder {
252        DescriptorBuilder {
253            base_limit: Some((base, limit)),
254            selector_offset: None,
255            typ: None,
256            dpl: None,
257            present: false,
258            avl: false,
259            db: false,
260            limit_granularity_4k: false,
261            l: false,
262            ist: 0,
263        }
264    }
265
266    pub(crate) fn with_selector_offset(
268        selector: SegmentSelector,
269        offset: u64,
270    ) -> DescriptorBuilder {
271        DescriptorBuilder {
272            base_limit: None,
273            selector_offset: Some((selector, offset)),
274            typ: None,
275            dpl: None,
276            present: false,
277            avl: false,
278            db: false,
279            limit_granularity_4k: false,
280            l: false,
281            ist: 0,
282        }
283    }
284
285    pub(crate) fn set_type(mut self, typ: DescriptorType) -> DescriptorBuilder {
286        self.typ = Some(typ);
287        self
288    }
289
290    pub fn limit_granularity_4kb(mut self) -> DescriptorBuilder {
292        self.limit_granularity_4k = true;
293        self
294    }
295
296    pub fn present(mut self) -> DescriptorBuilder {
298        self.present = true;
299        self
300    }
301
302    pub fn dpl(mut self, dpl: Ring) -> DescriptorBuilder {
304        self.dpl = Some(dpl);
305        self
306    }
307
308    pub fn avl(mut self) -> DescriptorBuilder {
310        self.avl = true;
311        self
312    }
313
314    pub fn db(mut self) -> DescriptorBuilder {
316        self.db = true;
317        self
318    }
319
320    pub fn l(mut self) -> DescriptorBuilder {
324        self.l = true;
325        self
326    }
327
328    pub fn ist(mut self, index: u8) -> DescriptorBuilder {
330        debug_assert!(index <= 7);
331        self.ist = index;
332        self
333    }
334}
335
336impl GateDescriptorBuilder<u32> for DescriptorBuilder {
337    fn tss_descriptor(base: u64, limit: u64, available: bool) -> DescriptorBuilder {
338        let typ = match available {
339            true => DescriptorType::System32(SystemDescriptorTypes32::TssAvailable32),
340            false => DescriptorType::System32(SystemDescriptorTypes32::TssBusy32),
341        };
342
343        DescriptorBuilder::with_base_limit(base, limit).set_type(typ)
344    }
345
346    fn call_gate_descriptor(selector: SegmentSelector, offset: u32) -> DescriptorBuilder {
347        DescriptorBuilder::with_selector_offset(selector, offset.into()).set_type(
348            DescriptorType::System32(SystemDescriptorTypes32::CallGate32),
349        )
350    }
351
352    fn interrupt_descriptor(selector: SegmentSelector, offset: u32) -> DescriptorBuilder {
353        DescriptorBuilder::with_selector_offset(selector, offset.into()).set_type(
354            DescriptorType::System32(SystemDescriptorTypes32::InterruptGate32),
355        )
356    }
357
358    fn trap_gate_descriptor(selector: SegmentSelector, offset: u32) -> DescriptorBuilder {
359        DescriptorBuilder::with_selector_offset(selector, offset.into()).set_type(
360            DescriptorType::System32(SystemDescriptorTypes32::TrapGate32),
361        )
362    }
363}
364
365impl TaskGateDescriptorBuilder for DescriptorBuilder {
366    fn task_gate_descriptor(selector: SegmentSelector) -> DescriptorBuilder {
367        DescriptorBuilder::with_selector_offset(selector, 0)
368            .set_type(DescriptorType::System32(SystemDescriptorTypes32::TaskGate))
369    }
370}
371
372impl SegmentDescriptorBuilder<u32> for DescriptorBuilder {
373    fn code_descriptor(base: u32, limit: u32, cst: CodeSegmentType) -> DescriptorBuilder {
374        DescriptorBuilder::with_base_limit(base.into(), limit.into())
375            .set_type(DescriptorType::Code(cst))
376    }
377
378    fn data_descriptor(base: u32, limit: u32, dst: DataSegmentType) -> DescriptorBuilder {
379        DescriptorBuilder::with_base_limit(base.into(), limit.into())
380            .set_type(DescriptorType::Data(dst))
381    }
382}
383
384impl LdtDescriptorBuilder<u32> for DescriptorBuilder {
385    fn ldt_descriptor(base: u32, limit: u32) -> DescriptorBuilder {
386        DescriptorBuilder::with_base_limit(base.into(), limit.into())
387            .set_type(DescriptorType::System32(SystemDescriptorTypes32::LDT))
388    }
389}
390
391impl BuildDescriptor<Descriptor> for DescriptorBuilder {
392    fn finish(&self) -> Descriptor {
393        let mut desc: Descriptor = Default::default();
394        desc.apply_builder_settings(self);
395
396        let typ = match self.typ {
397            Some(DescriptorType::System64(_)) => {
398                panic!("You shall not use 64-bit types on 32-bit descriptor.")
399            }
400            Some(DescriptorType::System32(typ)) => typ as u8,
401            Some(DescriptorType::Data(typ)) => {
402                desc.set_s();
403                typ as u8
404            }
405            Some(DescriptorType::Code(typ)) => {
406                desc.set_s();
407                typ as u8
408            }
409            None => unreachable!("Type not set, this is a library bug in x86."),
410        };
411        desc.set_type(typ);
412
413        desc
414    }
415}
416
417#[derive(Copy, Clone, Debug, Default)]
421#[repr(packed)]
422pub struct Descriptor {
423    pub lower: u32,
424    pub upper: u32,
425}
426
427impl fmt::Display for Descriptor {
428    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
429        write!(f, "Descriptor(0x{:x})", self.as_u64())
430    }
431}
432
433impl Descriptor {
434    pub const NULL: Descriptor = Descriptor { lower: 0, upper: 0 };
435
436    pub fn as_u64(&self) -> u64 {
437        (self.upper as u64) << 32 | self.lower as u64
438    }
439
440    pub(crate) fn apply_builder_settings(&mut self, builder: &DescriptorBuilder) {
441        if let Some(ring) = builder.dpl {
442            self.set_dpl(ring)
443        }
444        if let Some((base, limit)) = builder.base_limit {
445            self.set_base_limit(base as u32, limit as u32)
446        }
447        if let Some((selector, offset)) = builder.selector_offset {
448            self.set_selector_offset(selector, offset as u32)
449        }
450
451        if builder.present {
452            self.set_p();
453        }
454        if builder.avl {
455            self.set_avl();
456        }
457        if builder.db {
458            self.set_db();
459        }
460        if builder.limit_granularity_4k {
461            self.set_g();
462        }
463        if builder.l {
464            self.set_l();
465        }
466    }
467
468    pub fn set_base_limit(&mut self, base: u32, limit: u32) {
471        self.lower = 0;
473        self.upper &= 0x00F0FF00;
474
475        self.lower |= base << 16;
477        self.upper |= (base >> 16) & 0xff;
478        self.upper |= (base >> 24) << 24;
479
480        self.lower |= limit & 0xffff;
482        let limit_last_four_bits = (limit >> 16) & 0x0f;
483        self.upper |= limit_last_four_bits << 16;
484    }
485
486    pub fn set_selector_offset(&mut self, selector: SegmentSelector, offset: u32) {
489        self.lower = 0;
491        self.upper &= 0x0000ffff;
492
493        self.lower |= (selector.bits() as u32) << 16;
495
496        self.lower |= offset & 0x0000ffff;
498        self.upper |= offset & 0xffff0000;
499    }
500
501    pub fn set_type(&mut self, typ: u8) {
506        self.upper &= !(0x0f << 8); self.upper |= (typ as u32 & 0x0f) << 8;
508    }
509
510    pub fn set_s(&mut self) {
512        self.upper |= bit!(12);
513    }
514
515    pub fn set_dpl(&mut self, ring: Ring) {
517        assert!(ring as u32 <= 0b11);
518        self.upper &= !(0b11 << 13);
519        self.upper |= (ring as u32) << 13;
520    }
521
522    pub fn set_p(&mut self) {
527        self.upper |= bit!(15);
528    }
529
530    pub fn set_avl(&mut self) {
532        self.upper |= bit!(20);
533    }
534
535    pub fn set_l(&mut self) {
541        self.upper |= bit!(21);
542    }
543
544    pub fn set_db(&mut self) {
548        self.upper |= bit!(22);
549    }
550
551    pub fn set_g(&mut self) {
556        self.upper |= bit!(23);
557    }
558}
559
560pub unsafe fn load_ss(sel: SegmentSelector) {
565    asm!("movw {0:x}, %ss", in(reg) sel.bits(), options(att_syntax));
566}
567
568pub unsafe fn load_ds(sel: SegmentSelector) {
573    asm!("movw {0:x}, %ds", in(reg) sel.bits(), options(att_syntax));
574}
575
576pub unsafe fn load_es(sel: SegmentSelector) {
581    asm!("movw {0:x}, %es", in(reg) sel.bits(), options(att_syntax));
582}
583
584pub unsafe fn load_fs(sel: SegmentSelector) {
589    asm!("movw {0:x}, %fs", in(reg) sel.bits(), options(att_syntax));
590}
591
592pub unsafe fn load_gs(sel: SegmentSelector) {
597    asm!("movw {0:x}, %gs", in(reg) sel.bits(), options(att_syntax));
598}
599
600pub use crate::current::segmentation::load_cs;
601
602pub fn cs() -> SegmentSelector {
604    let segment: u16;
605    unsafe { asm!("mov %cs, {0:x}", out(reg) segment, options(att_syntax)) };
606    SegmentSelector::from_raw(segment)
607}
608
609pub fn es() -> SegmentSelector {
611    let segment: u16;
612    unsafe { asm!("mov %es, {0:x}", out(reg) segment, options(att_syntax)) };
613    SegmentSelector::from_raw(segment)
614}
615
616pub fn ss() -> SegmentSelector {
618    let segment: u16;
619    unsafe { asm!("mov %ss, {0:x}", out(reg) segment, options(att_syntax)) };
620    SegmentSelector::from_raw(segment)
621}
622
623pub fn ds() -> SegmentSelector {
625    let segment: u16;
626    unsafe { asm!("mov %ds, {0:x}", out(reg) segment, options(att_syntax)) };
627    SegmentSelector::from_raw(segment)
628}
629
630pub fn fs() -> SegmentSelector {
632    let segment: u16;
633    unsafe { asm!("mov %fs, {0:x}", out(reg) segment, options(att_syntax)) };
634    SegmentSelector::from_raw(segment)
635}
636
637pub fn gs() -> SegmentSelector {
639    let segment: u16;
640    unsafe { asm!("mov %gs, {0:x}", out(reg) segment, options(att_syntax)) };
641    SegmentSelector::from_raw(segment)
642}
643
644#[cfg(all(test, feature = "utest"))]
645mod test {
646    use super::*;
647    use crate::Ring;
648
649    #[test]
650    fn test_x86_64_default_gdt() {
651        let null: Descriptor = Default::default();
652        let code_kernel: Descriptor =
653            DescriptorBuilder::code_descriptor(0, 0xFFFFF, CodeSegmentType::ExecuteRead)
654                .present()
655                .dpl(Ring::Ring0)
656                .limit_granularity_4kb()
657                .db()
658                .finish();
659        let stack_kernel: Descriptor =
660            DescriptorBuilder::data_descriptor(0, 0xFFFFF, DataSegmentType::ReadWrite)
661                .present()
662                .dpl(Ring::Ring0)
663                .limit_granularity_4kb()
664                .db()
665                .finish();
666        let code_user: Descriptor =
667            DescriptorBuilder::code_descriptor(0, 0xFFFFF, CodeSegmentType::ExecuteRead)
668                .present()
669                .limit_granularity_4kb()
670                .db()
671                .dpl(Ring::Ring3)
672                .finish();
673        let stack_user: Descriptor =
674            DescriptorBuilder::data_descriptor(0, 0xFFFFF, DataSegmentType::ReadWrite)
675                .present()
676                .limit_granularity_4kb()
677                .db()
678                .dpl(Ring::Ring3)
679                .finish();
680
681        assert_eq!(0x0000000000000000u64, null.as_u64());
682        assert_eq!(
683            0x00CF9A000000FFFFu64,
684            code_kernel.as_u64(),
685            "code_kernel: {:#b} first bit to differ is {}",
686            (code_kernel.as_u64() ^ 0x00CF9A000000FFFFu64),
687            (code_kernel.as_u64() ^ 0x00CF9A000000FFFFu64).trailing_zeros()
688        );
689        assert_eq!(
690            0x00CF92000000FFFFu64,
691            stack_kernel.as_u64(),
692            "stack_kernel: {:#b} first bit to differ is {}",
693            (stack_kernel.as_u64() ^ 0x00CF92000000FFFFu64),
694            (stack_kernel.as_u64() ^ 0x00CF92000000FFFFu64).trailing_zeros()
695        );
696        assert_eq!(
697            0x00CFFA000000FFFFu64,
698            code_user.as_u64(),
699            "code_user: {:#b} first bit to differ is {}",
700            (code_user.as_u64() ^ 0x00CFFA000000FFFFu64),
701            (code_user.as_u64() ^ 0x00CFFA000000FFFFu64).trailing_zeros()
702        );
703        assert_eq!(
704            0x00CFF2000000FFFFu64,
705            stack_user.as_u64(),
706            "stack_user: {:#b} first bit to differ is {}",
707            (stack_user.as_u64() ^ 0x00CFF2000000FFFFu64),
708            (stack_user.as_u64() ^ 0x00CFF2000000FFFFu64).trailing_zeros()
709        );
710    }
711}