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}