ostd/arch/x86/vm/
context.rs1use x86::msr::{IA32_FMASK, IA32_LSTAR, IA32_STAR, wrmsr};
4use x86_64::{VirtAddr, registers::control::Cr2};
5
6use super::{
7 GuestInterrupt, GuestTimerInstant, VcpuMsrs, VcpuRegs, VcpuSregs,
8 guest_mode::SyscallMsrsRestorer,
9 vmx::{VmxGuard, vmcs::Vmcs},
10 x86::write_cr2_raw,
11};
12use crate::{Error, arch::cpu::context::GsBase, irq::DisabledLocalIrqGuard, prelude::*};
13
14pub struct GuestContext {
21 arch: VcpuArchState,
22 vmcs: Vmcs,
23}
24
25impl GuestContext {
26 pub fn new(regs: VcpuRegs, sregs: VcpuSregs, msrs: VcpuMsrs) -> Result<Self> {
32 let vmx_guard = VmxGuard::acquire_vmx()?;
33 Ok(Self {
34 arch: VcpuArchState {
35 regs,
36 sregs,
37 msrs,
38 pending_interrupt: None,
39 timer_deadline: None,
40 },
41 vmcs: Vmcs::new(&vmx_guard)?,
42 })
43 }
44
45 pub fn regs(&self) -> &VcpuRegs {
47 &self.arch.regs
48 }
49
50 pub fn regs_mut(&mut self) -> &mut VcpuRegs {
53 &mut self.arch.regs
54 }
55
56 pub fn sregs(&self) -> &VcpuSregs {
58 &self.arch.sregs
59 }
60
61 pub fn sregs_mut(&mut self) -> &mut VcpuSregs {
63 &mut self.arch.sregs
64 }
65
66 pub fn msrs(&self) -> &VcpuMsrs {
68 &self.arch.msrs
69 }
70
71 pub fn msrs_mut(&mut self) -> &mut VcpuMsrs {
73 &mut self.arch.msrs
74 }
75
76 pub(super) fn arch_and_vmcs(&mut self) -> (&mut VcpuArchState, &Vmcs) {
78 (&mut self.arch, &self.vmcs)
79 }
80}
81
82impl Drop for GuestContext {
83 fn drop(&mut self) {
84 if let Err(err) =
85 VmxGuard::acquire_vmx().and_then(|vmx_guard| self.vmcs.deactivate(&vmx_guard))
86 {
87 error!("failed to clear VMCS during context destruction: {:?}", err);
89 }
90 }
91}
92
93pub struct VcpuArchState {
95 pub regs: VcpuRegs,
97 pub sregs: VcpuSregs,
99 pub msrs: VcpuMsrs,
101 pub pending_interrupt: Option<GuestInterrupt>,
103 pub timer_deadline: Option<GuestTimerInstant>,
105}
106
107impl VcpuArchState {
108 pub(super) unsafe fn load_run_state<'a>(
114 &self,
115 irq_guard: &'a DisabledLocalIrqGuard,
116 ) -> Result<SyscallMsrsRestorer<'a>> {
117 for value in [self.msrs.kernel_gs_base, self.msrs.lstar] {
120 if VirtAddr::try_new(value).is_err() {
121 return Err(Error::InvalidArgs);
122 }
123 }
124 if self.msrs.syscall_mask > u32::MAX as u64 {
125 return Err(Error::InvalidArgs);
126 }
127
128 let syscall_msrs_restorer = SyscallMsrsRestorer::new(irq_guard);
129 unsafe {
133 wrmsr(IA32_STAR, self.msrs.star);
134 wrmsr(IA32_LSTAR, self.msrs.lstar);
135 wrmsr(IA32_FMASK, self.msrs.syscall_mask);
136 }
137
138 write_cr2_raw(self.sregs.cr2);
139 GsBase::new(self.msrs.kernel_gs_base as usize).load(irq_guard);
140 Ok(syscall_msrs_restorer)
141 }
142
143 pub(super) fn save_run_state(&mut self, irq_guard: &DisabledLocalIrqGuard) {
145 self.sregs.cr2 = Cr2::read_raw();
146 self.msrs.kernel_gs_base = {
148 let mut kernel_gs_base = GsBase::default();
149 kernel_gs_base.save(irq_guard);
150 kernel_gs_base.addr() as u64
151 };
152 }
153}