Skip to content

Commit 3806bce

Browse files
committed
[fixme] rebase, problem in xstate
1 parent ab5d872 commit 3806bce

3 files changed

Lines changed: 92 additions & 143 deletions

File tree

src/context.rs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ use x86_64::{addr::PhysAddr, structures::paging::PhysFrame};
99
use crate::msr::Msr;
1010
use crate::regs::GeneralRegisters;
1111
use crate::segmentation::{Segment, SegmentAccessRights};
12-
use crate::xstate::XState;
1312

1413
const SAVED_LINUX_REGS: usize = 8;
1514

@@ -52,8 +51,7 @@ pub struct LinuxContext {
5251
pub kernel_gsbase: u64,
5352
pub pat: u64,
5453
pub mtrr_def_type: u64,
55-
56-
pub xstate: XState,
54+
// TODO: xstate
5755
}
5856

5957
unsafe impl Send for LinuxContext {}
@@ -99,7 +97,6 @@ impl Default for LinuxContext {
9997
kernel_gsbase: 0,
10098
pat: 0,
10199
mtrr_def_type: 0,
102-
xstate: XState::default(),
103100
}
104101
}
105102
}
@@ -158,7 +155,6 @@ impl LinuxContext {
158155
kernel_gsbase: Msr::IA32_KERNEL_GSBASE.read(),
159156
pat: Msr::IA32_PAT.read(),
160157
mtrr_def_type: Msr::IA32_MTRR_DEF_TYPE.read(),
161-
xstate: XState::new(),
162158
}
163159
}
164160

@@ -239,7 +235,6 @@ impl LinuxContext {
239235
kernel_gsbase: 0,
240236
pat: 0,
241237
mtrr_def_type: 0,
242-
xstate: XState::default(),
243238
}
244239
}
245240

src/vmx/vcpu.rs

Lines changed: 6 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -42,16 +42,6 @@ const VMX_PREEMPTION_TIMER_SET_VALUE: u32 = 1_000_000;
4242
const QEMU_EXIT_PORT: u16 = 0x604;
4343
const QEMU_EXIT_MAGIC: u64 = 0x2000;
4444

45-
pub struct XState {
46-
host_xcr0: u64,
47-
guest_xcr0: u64,
48-
host_xss: u64,
49-
guest_xss: u64,
50-
51-
xsave_available: bool,
52-
xsaves_available: bool,
53-
}
54-
5545
#[derive(PartialEq, Eq, Debug)]
5646
pub enum VmCpuMode {
5747
Real,
@@ -60,97 +50,6 @@ pub enum VmCpuMode {
6050
Mode64, // IA-32E mode (CS.L = 1)
6151
}
6252

63-
impl XState {
64-
/// Create a new [`XState`] instance with current host state
65-
fn new() -> Self {
66-
// Check if XSAVE is available
67-
let xsave_available = Self::xsave_available();
68-
// Check if XSAVES and XRSTORS (as well as IA32_XSS) are available
69-
let xsaves_available = if xsave_available {
70-
Self::xsaves_available()
71-
} else {
72-
false
73-
};
74-
75-
// Read XCR0 iff XSAVE is available
76-
let xcr0 = if xsave_available {
77-
unsafe { xcr0_read().bits() }
78-
} else {
79-
0
80-
};
81-
// Read IA32_XSS iff XSAVES is available
82-
let xss = if xsaves_available {
83-
Msr::IA32_XSS.read()
84-
} else {
85-
0
86-
};
87-
88-
Self {
89-
host_xcr0: xcr0,
90-
guest_xcr0: xcr0,
91-
host_xss: xss,
92-
guest_xss: xss,
93-
xsave_available,
94-
xsaves_available,
95-
}
96-
}
97-
98-
/// Enable extended processor state management instructions, including XGETBV and XSAVE.
99-
pub fn enable_xsave() {
100-
if Self::xsave_available() {
101-
unsafe { Cr4::write(Cr4::read() | Cr4Flags::OSXSAVE) };
102-
}
103-
}
104-
105-
/// Check if XSAVE is available on the current CPU.
106-
pub fn xsave_available() -> bool {
107-
let cpuid = CpuId::new();
108-
cpuid
109-
.get_feature_info()
110-
.map(|f| f.has_xsave())
111-
.unwrap_or(false)
112-
}
113-
114-
/// Check if XSAVES and XRSTORS (as well as IA32_XSS) are available on the current CPU.
115-
pub fn xsaves_available() -> bool {
116-
let cpuid = CpuId::new();
117-
cpuid
118-
.get_extended_state_info()
119-
.map(|f| f.has_xsaves_xrstors())
120-
.unwrap_or(false)
121-
}
122-
123-
/// Save the current host XCR0 and IA32_XSS values and load the guest values.
124-
pub fn switch_to_guest(&mut self) {
125-
unsafe {
126-
if self.xsave_available {
127-
self.host_xcr0 = xcr0_read().bits();
128-
xcr0_write(Xcr0::from_bits_unchecked(self.guest_xcr0));
129-
130-
if self.xsaves_available {
131-
self.host_xss = Msr::IA32_XSS.read();
132-
Msr::IA32_XSS.write(self.guest_xss);
133-
}
134-
}
135-
}
136-
}
137-
138-
/// Save the current guest XCR0 and IA32_XSS values and load the host values.
139-
pub fn switch_to_host(&mut self) {
140-
unsafe {
141-
if self.xsave_available {
142-
self.guest_xcr0 = xcr0_read().bits();
143-
xcr0_write(Xcr0::from_bits_unchecked(self.host_xcr0));
144-
145-
if self.xsaves_available {
146-
self.guest_xss = Msr::IA32_XSS.read();
147-
Msr::IA32_XSS.write(self.host_xss);
148-
}
149-
}
150-
}
151-
}
152-
}
153-
15453
const MSR_IA32_EFER_LMA_BIT: u64 = 1 << 10;
15554
const CR0_PE: usize = 1 << 0;
15655

@@ -169,10 +68,7 @@ pub struct VmxVcpu<H: AxVCpuHal> {
16968

17069
pending_events: VecDeque<(u8, Option<u32>)>,
17170
// xstate: XState,
172-
/// XState used by the guest OS, loaded before running the guest.
173-
guest_xstate: XState,
174-
/// XState used by the hypervisor itself, stored before running the guest.
175-
cur_xstate: XState,
71+
xstate: XState,
17672
entry: Option<GuestPhysAddr>,
17773
ept_root: Option<HostPhysAddr>,
17874

@@ -191,8 +87,7 @@ impl<H: AxVCpuHal> VmxVcpu<H> {
19187
msr_bitmap: MsrBitmap::passthrough_all()?,
19288
eptp_list: EptpList::new()?,
19389
pending_events: VecDeque::with_capacity(8),
194-
guest_xstate: XState::new(),
195-
cur_xstate: XState::new(),
90+
xstate: XState::new(),
19691
entry: None,
19792
ept_root: None,
19893
id,
@@ -1315,7 +1210,7 @@ impl<H: AxVCpuHal> VmxVcpu<H> {
13151210
})
13161211
.ok_or(ax_err_type!(InvalidInput))
13171212
.and_then(|x| {
1318-
self.guest_xstate.xcr0 = x;
1213+
self.xstate.guest_xcr0 = x.bits();
13191214
self.advance_rip(VM_EXIT_INSTR_LEN_XSETBV)
13201215
})
13211216
} else {
@@ -1329,15 +1224,16 @@ impl<H: AxVCpuHal> VmxVcpu<H> {
13291224
///
13301225
/// This function is generally called before VM-entry.
13311226
fn load_guest_xstate(&mut self) {
1332-
self.xstate.switch_to_guest();
1227+
// FIXME: Linux will throw a UD exception if we save/restore xstate.
1228+
// self.xstate.switch_to_guest();
13331229
}
13341230

13351231
/// Save the current guest state to the vcpu,
13361232
/// restore the host state from the vcpu into registers.
13371233
///
13381234
/// This function is generally called after VM-exit.
13391235
fn load_host_xstate(&mut self) {
1340-
self.xstate.switch_to_host();
1236+
// self.xstate.switch_to_host();
13411237
}
13421238
}
13431239

src/xstate.rs

Lines changed: 85 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,109 @@
1+
use raw_cpuid::CpuId;
12
use x86::controlregs::{Xcr0, xcr0 as xcr0_read, xcr0_write};
23
use x86_64::registers::control::{Cr4, Cr4Flags};
34

45
use crate::msr::Msr;
56

6-
#[derive(Debug, Clone, Copy)]
7+
#[allow(unused)]
78
pub struct XState {
8-
pub xcr0: Xcr0,
9-
pub xss: u64,
10-
}
9+
host_xcr0: u64,
10+
pub(crate) guest_xcr0: u64,
11+
host_xss: u64,
12+
guest_xss: u64,
1113

12-
impl Default for XState {
13-
fn default() -> Self {
14-
Self {
15-
xcr0: Xcr0::empty(),
16-
xss: 0,
17-
}
18-
}
14+
xsave_available: bool,
15+
xsaves_available: bool,
1916
}
2017

2118
impl XState {
2219
/// Create a new [`XState`] instance with current host state
2320
pub fn new() -> Self {
21+
// Check if XSAVE is available
22+
let xsave_available = Self::xsave_available();
23+
// Check if XSAVES and XRSTORS (as well as IA32_XSS) are available
24+
let xsaves_available = if xsave_available {
25+
Self::xsaves_available()
26+
} else {
27+
false
28+
};
29+
30+
// Read XCR0 iff XSAVE is available
31+
let xcr0 = if xsave_available {
32+
unsafe { xcr0_read().bits() }
33+
} else {
34+
0
35+
};
36+
// Read IA32_XSS iff XSAVES is available
37+
let xss = if xsaves_available {
38+
Msr::IA32_XSS.read()
39+
} else {
40+
0
41+
};
42+
2443
Self {
25-
xcr0: unsafe { xcr0_read() },
26-
xss: Msr::IA32_XSS.read(),
44+
host_xcr0: xcr0,
45+
guest_xcr0: xcr0,
46+
host_xss: xss,
47+
guest_xss: xss,
48+
xsave_available,
49+
xsaves_available,
2750
}
2851
}
2952

30-
pub fn save(&mut self) {
31-
self.xcr0 = unsafe { xcr0_read() };
32-
self.xss = Msr::IA32_XSS.read();
33-
warn!("XState::save: xcr0: {:?}, xss: {:#x}", self.xcr0, self.xss);
53+
/// Enable extended processor state management instructions, including XGETBV and XSAVE.
54+
pub fn enable_xsave() {
55+
if Self::xsave_available() {
56+
unsafe { Cr4::write(Cr4::read() | Cr4Flags::OSXSAVE) };
57+
}
3458
}
3559

36-
pub fn restore(&self) {
37-
warn!(
38-
"XState::restore: xcr0: {:?}, xss: {:#x}",
39-
self.xcr0, self.xss
40-
);
60+
/// Check if XSAVE is available on the current CPU.
61+
pub fn xsave_available() -> bool {
62+
let cpuid = CpuId::new();
63+
cpuid
64+
.get_feature_info()
65+
.map(|f| f.has_xsave())
66+
.unwrap_or(false)
67+
}
68+
69+
/// Check if XSAVES and XRSTORS (as well as IA32_XSS) are available on the current CPU.
70+
pub fn xsaves_available() -> bool {
71+
let cpuid = CpuId::new();
72+
cpuid
73+
.get_extended_state_info()
74+
.map(|f| f.has_xsaves_xrstors())
75+
.unwrap_or(false)
76+
}
77+
78+
/// Save the current host XCR0 and IA32_XSS values and load the guest values.
79+
#[allow(unused)]
80+
pub fn switch_to_guest(&mut self) {
4181
unsafe {
42-
xcr0_write(self.xcr0);
43-
Msr::IA32_XSS.write(self.xss);
82+
if self.xsave_available {
83+
self.host_xcr0 = xcr0_read().bits();
84+
xcr0_write(Xcr0::from_bits_unchecked(self.guest_xcr0));
85+
86+
if self.xsaves_available {
87+
self.host_xss = Msr::IA32_XSS.read();
88+
Msr::IA32_XSS.write(self.guest_xss);
89+
}
90+
}
4491
}
4592
}
4693

47-
/// Enables extended processor state management instructions, including XGETBV and XSAVE.
48-
pub fn enable_xsave() {
49-
unsafe { Cr4::write(Cr4::read() | Cr4Flags::OSXSAVE) };
94+
/// Save the current guest XCR0 and IA32_XSS values and load the host values.
95+
#[allow(unused)]
96+
pub fn switch_to_host(&mut self) {
97+
unsafe {
98+
if self.xsave_available {
99+
self.guest_xcr0 = xcr0_read().bits();
100+
xcr0_write(Xcr0::from_bits_unchecked(self.host_xcr0));
101+
102+
if self.xsaves_available {
103+
self.guest_xss = Msr::IA32_XSS.read();
104+
Msr::IA32_XSS.write(self.host_xss);
105+
}
106+
}
107+
}
50108
}
51109
}

0 commit comments

Comments
 (0)