1
- //! Manages GDT and TSS for VMX virtualization contexts.
1
+ //! Manages GDT, IDT, and TSS for VMX virtualization contexts.
2
2
//!
3
- //! Facilitates the creation and manipulation of the Global Descriptor Table (GDT) and
4
- //! Task State Segment (TSS) necessary for VMX operations. Supports both host and guest
5
- //! environments, ensuring compatibility and proper setup for virtualization.
3
+ //! Facilitates the creation and manipulation of the Global Descriptor Table (GDT),
4
+ //! Interrupt Descriptor Table (IDT), and Task State Segment (TSS) necessary for VMX operations.
5
+ //! Supports both host and guest environments, ensuring compatibility and proper setup for virtualization.
6
6
//! Credits to Satoshi Tanda: https://github.com/tandasat/Hello-VT-rp/blob/main/hypervisor/src/intel_vt/descriptors.rs
7
7
8
8
use {
9
- crate :: intel:: support:: sgdt,
9
+ crate :: intel:: support:: { sgdt, sidt } ,
10
10
alloc:: vec:: Vec ,
11
11
x86:: {
12
12
dtables:: DescriptorTablePointer ,
@@ -16,18 +16,22 @@ use {
16
16
} ,
17
17
} ;
18
18
19
- /// Manages GDT and TSS for VMX operations.
20
- ///
21
- /// Supports creating a new GDT that includes TSS, addressing compatibility issues in UEFI environments
22
- /// and ensuring proper VM and hypervisor states. This struct is essential for setting up the environment
23
- /// for both host and guest VMX operations.
19
+ /// Represents the descriptor tables (GDT and IDT) for the host and guest.
20
+ /// Contains the GDT, IDT, TSS, and their respective register pointers.
21
+ #[ repr( C , align( 4096 ) ) ]
24
22
pub struct Descriptors {
25
23
/// Vector holding the GDT entries.
26
24
pub gdt : Vec < u64 > ,
27
25
28
26
/// Descriptor table pointer to the GDT.
29
27
pub gdtr : DescriptorTablePointer < u64 > ,
30
28
29
+ /// Vector holding the IDT entries.
30
+ pub idt : Vec < u64 > ,
31
+
32
+ /// Descriptor table pointer to the IDT.
33
+ pub idtr : DescriptorTablePointer < u64 > ,
34
+
31
35
/// Code segment selector.
32
36
pub cs : SegmentSelector ,
33
37
@@ -46,16 +50,22 @@ impl Descriptors {
46
50
///
47
51
/// # Returns
48
52
/// A `Descriptors` instance with an updated GDT including TSS.
49
- pub fn new_from_current ( ) -> Self {
53
+ pub fn initialize_for_guest ( ) -> Self {
50
54
log:: debug!( "Creating a new GDT with TSS for guest" ) ;
51
55
52
56
// Get the current GDT.
53
57
let current_gdtr = sgdt ( ) ;
54
58
let current_gdt = unsafe { core:: slice:: from_raw_parts ( current_gdtr. base . cast :: < u64 > ( ) , usize:: from ( current_gdtr. limit + 1 ) / 8 ) } ;
55
59
60
+ // Get the current IDT.
61
+ let current_idtr = sidt ( ) ;
62
+ let current_idt = unsafe { core:: slice:: from_raw_parts ( current_idtr. base . cast :: < u64 > ( ) , usize:: from ( current_idtr. limit + 1 ) / 8 ) } ;
63
+
56
64
let mut descriptors = Descriptors {
57
65
gdt : current_gdt. to_vec ( ) ,
58
66
gdtr : DescriptorTablePointer :: < u64 > :: default ( ) ,
67
+ idt : current_idt. to_vec ( ) ,
68
+ idtr : DescriptorTablePointer :: < u64 > :: default ( ) ,
59
69
cs : SegmentSelector :: from_raw ( 0 ) ,
60
70
tr : SegmentSelector :: from_raw ( 0 ) ,
61
71
tss : TaskStateSegment :: default ( ) ,
@@ -83,12 +93,14 @@ impl Descriptors {
83
93
///
84
94
/// # Returns
85
95
/// A `Descriptors` instance with a newly created GDT for the host.
86
- pub fn new_for_host ( ) -> Self {
96
+ pub fn initialize_for_host ( ) -> Self {
87
97
log:: debug!( "Creating a new GDT with TSS for host" ) ;
88
98
89
99
let mut descriptors = Descriptors {
90
100
gdt : Vec :: new ( ) ,
91
101
gdtr : DescriptorTablePointer :: < u64 > :: default ( ) ,
102
+ idt : Vec :: new ( ) ,
103
+ idtr : DescriptorTablePointer :: < u64 > :: default ( ) ,
92
104
cs : SegmentSelector :: from_raw ( 0 ) ,
93
105
tr : SegmentSelector :: from_raw ( 0 ) ,
94
106
tss : TaskStateSegment :: default ( ) ,
@@ -103,7 +115,11 @@ impl Descriptors {
103
115
descriptors. cs = SegmentSelector :: new ( 1 , x86:: Ring :: Ring0 ) ;
104
116
descriptors. tr = SegmentSelector :: new ( 2 , x86:: Ring :: Ring0 ) ;
105
117
106
- log:: debug!( "New GDT with TSS created for host successfully!" ) ;
118
+ // Initialize the IDT with empty descriptors for the host
119
+ descriptors. idt = Self :: copy_current_idt ( ) ;
120
+ descriptors. idtr = DescriptorTablePointer :: new_from_slice ( & descriptors. idt ) ;
121
+
122
+ log:: debug!( "New GDT with TSS and IDT created for host successfully!" ) ;
107
123
108
124
descriptors
109
125
}
@@ -144,24 +160,29 @@ impl Descriptors {
144
160
. finish ( )
145
161
}
146
162
147
- /// Converts a descriptor table pointer to a slice of GDT entries.
148
- ///
149
- /// # Arguments
150
- ///
151
- /// - `pointer`: A reference to the `DescriptorTablePointer` for the GDT.
152
- ///
153
- /// # Returns
154
- ///
155
- /// A slice of the GDT entries represented as `u64` values.
156
- pub fn from_pointer ( pointer : & DescriptorTablePointer < u64 > ) -> & [ u64 ] {
157
- unsafe { core:: slice:: from_raw_parts ( pointer. base . cast :: < u64 > ( ) , ( pointer. limit + 1 ) as usize / size_of :: < u64 > ( ) ) }
163
+ /// Copies the current IDT for the guest.
164
+ fn copy_current_idt ( ) -> Vec < u64 > {
165
+ log:: trace!( "Copying current IDT" ) ;
166
+
167
+ // Get the current IDTR
168
+ let current_idtr = sidt ( ) ;
169
+
170
+ // Create a slice from the current IDT entries.
171
+ let current_idt = unsafe { core:: slice:: from_raw_parts ( current_idtr. base . cast :: < u64 > ( ) , usize:: from ( current_idtr. limit + 1 ) / 8 ) } ;
172
+
173
+ // Create a new IDT from the slice.
174
+ let new_idt = current_idt. to_vec ( ) ;
175
+
176
+ log:: trace!( "Copied current IDT" ) ;
177
+
178
+ new_idt
158
179
}
159
180
}
160
181
161
182
/// Represents the Task State Segment (TSS).
162
183
///
163
184
/// Encapsulates the TSS, which is critical for task-switching and storing state information
164
- /// in protected mode operations. Includes fields for the base address, limit, and access rights.:
185
+ /// in protected mode operations. Includes fields for the base address, limit, and access rights.
165
186
#[ derive( derivative:: Derivative ) ]
166
187
#[ derivative( Debug ) ]
167
188
pub struct TaskStateSegment {
@@ -203,7 +224,5 @@ impl Default for TaskStateSegment {
203
224
/// Low-level representation of the 64-bit Task State Segment (TSS).
204
225
///
205
226
/// Encapsulates the raw structure of the TSS as defined in the x86_64 architecture.
206
- /// This structure is used internally to manage the TSS's memory layout directly.
207
- /// See: Figure 8-11. 64-Bit TSS Format
208
227
#[ allow( dead_code) ]
209
228
struct TaskStateSegmentRaw ( [ u8 ; 104 ] ) ;
0 commit comments