capabilities.rs 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591
  1. use raw_cpuid::CpuId;
  2. use x86::{
  3. msr,
  4. vmx::vmcs::control::{
  5. EntryControls, ExitControls, PinbasedControls, PrimaryControls, SecondaryControls,
  6. },
  7. };
  8. use crate::{
  9. arch::vm::{
  10. mmu::kvm_mmu::PageLevel, CPU_BASED_ALWAYSON_WITHOUT_TRUE_MSR,
  11. PIN_BASED_ALWAYSON_WITHOUT_TRUE_MSR, VM_ENTRY_ALWAYSON_WITHOUT_TRUE_MSR,
  12. VM_EXIT_ALWAYSON_WITHOUT_TRUE_MSR,
  13. },
  14. virt::vm::kvm_host::vcpu::VirtCpu,
  15. };
  16. use super::{vmcs::feat::VmxFeat, Vmx};
  17. #[derive(Debug)]
  18. pub struct VmcsConfig {
  19. pub size: u32,
  20. pub basic_cap: u32,
  21. pub revision_id: u32,
  22. pub pin_based_exec_ctrl: PinbasedControls,
  23. pub cpu_based_exec_ctrl: PrimaryControls,
  24. pub cpu_based_2nd_exec_ctrl: SecondaryControls,
  25. pub cpu_based_3rd_exec_ctrl: u32,
  26. pub vmexit_ctrl: ExitControls,
  27. pub vmentry_ctrl: EntryControls,
  28. pub misc: u64,
  29. pub nested: NestedVmxMsrs,
  30. }
  31. impl Default for VmcsConfig {
  32. fn default() -> Self {
  33. Self {
  34. size: Default::default(),
  35. basic_cap: Default::default(),
  36. revision_id: Default::default(),
  37. pin_based_exec_ctrl: PinbasedControls::empty(),
  38. cpu_based_exec_ctrl: PrimaryControls::empty(),
  39. cpu_based_2nd_exec_ctrl: SecondaryControls::empty(),
  40. cpu_based_3rd_exec_ctrl: Default::default(),
  41. vmexit_ctrl: ExitControls::empty(),
  42. vmentry_ctrl: EntryControls::empty(),
  43. misc: Default::default(),
  44. nested: Default::default(),
  45. }
  46. }
  47. }
  48. #[derive(Debug, Default)]
  49. pub struct NestedVmxMsrs {
  50. /// 主处理器基于控制,分为低32位和高32位
  51. pub procbased_ctls_low: u32,
  52. /// 主处理器基于控制,分为低32位和高32位
  53. pub procbased_ctls_high: u32,
  54. /// 次要处理器控制,分为低32位和高32位
  55. pub secondary_ctls_low: u32,
  56. /// 次要处理器控制,分为低32位和高32位
  57. pub secondary_ctls_high: u32,
  58. /// VMX 的针脚基于控制,分为低32位和高32位
  59. pub pinbased_ctls_low: u32,
  60. /// VMX 的针脚基于控制,分为低32位和高32位
  61. pub pinbased_ctls_high: u32,
  62. /// VM退出控制,分为低32位和高32位
  63. pub exit_ctls_low: u32,
  64. /// VM退出控制,分为低32位和高32位
  65. pub exit_ctls_high: u32,
  66. /// VM进入控制,分为低32位和高32位
  67. pub entry_ctls_low: u32,
  68. /// VM进入控制,分为低32位和高32位
  69. pub entry_ctls_high: u32,
  70. /// VMX 的其他杂项控制,分为低32位和高32位
  71. pub misc_low: u32,
  72. /// VMX 的其他杂项控制,分为低32位和高32位
  73. pub misc_high: u32,
  74. /// 扩展页表(EPT)的能力信息
  75. pub ept_caps: u32,
  76. /// 虚拟处理器标识(VPID)的能力信息
  77. pub vpid_caps: u32,
  78. /// 基本能力
  79. pub basic: u64,
  80. /// VMX 控制的CR0寄存器的固定位
  81. pub cr0_fixed0: u64,
  82. /// VMX 控制的CR0寄存器的固定位
  83. pub cr0_fixed1: u64,
  84. /// VMX 控制的CR4寄存器的固定位
  85. pub cr4_fixed0: u64,
  86. /// VMX 控制的CR4寄存器的固定位
  87. pub cr4_fixed1: u64,
  88. /// VMX 控制的VMCS寄存器的编码
  89. pub vmcs_enum: u64,
  90. /// VM功能控制
  91. pub vmfunc_controls: u64,
  92. }
  93. impl NestedVmxMsrs {
  94. pub fn control_msr(low: u32, high: u32) -> u64 {
  95. (high as u64) << 32 | low as u64
  96. }
  97. pub fn get_vmx_msr(&self, msr_index: u32) -> Option<u64> {
  98. match msr_index {
  99. msr::IA32_VMX_BASIC => {
  100. return Some(self.basic);
  101. }
  102. msr::IA32_VMX_TRUE_PINBASED_CTLS | msr::IA32_VMX_PINBASED_CTLS => {
  103. let mut data =
  104. NestedVmxMsrs::control_msr(self.pinbased_ctls_low, self.pinbased_ctls_high);
  105. if msr_index == msr::IA32_VMX_PINBASED_CTLS {
  106. data |= PIN_BASED_ALWAYSON_WITHOUT_TRUE_MSR;
  107. }
  108. return Some(data);
  109. }
  110. msr::IA32_VMX_TRUE_PROCBASED_CTLS | msr::IA32_VMX_PROCBASED_CTLS => {
  111. let mut data =
  112. NestedVmxMsrs::control_msr(self.procbased_ctls_low, self.procbased_ctls_high);
  113. if msr_index == msr::IA32_VMX_PROCBASED_CTLS {
  114. data |= CPU_BASED_ALWAYSON_WITHOUT_TRUE_MSR;
  115. }
  116. return Some(data);
  117. }
  118. msr::IA32_VMX_TRUE_EXIT_CTLS | msr::IA32_VMX_EXIT_CTLS => {
  119. let mut data = NestedVmxMsrs::control_msr(self.exit_ctls_low, self.exit_ctls_high);
  120. if msr_index == msr::IA32_VMX_EXIT_CTLS {
  121. data |= VM_EXIT_ALWAYSON_WITHOUT_TRUE_MSR;
  122. }
  123. return Some(data);
  124. }
  125. msr::IA32_VMX_TRUE_ENTRY_CTLS | msr::IA32_VMX_ENTRY_CTLS => {
  126. let mut data =
  127. NestedVmxMsrs::control_msr(self.entry_ctls_low, self.entry_ctls_high);
  128. if msr_index == msr::IA32_VMX_ENTRY_CTLS {
  129. data |= VM_ENTRY_ALWAYSON_WITHOUT_TRUE_MSR;
  130. }
  131. return Some(data);
  132. }
  133. msr::IA32_VMX_MISC => {
  134. return Some(NestedVmxMsrs::control_msr(self.misc_low, self.misc_high));
  135. }
  136. msr::IA32_VMX_CR0_FIXED0 => {
  137. return Some(self.cr0_fixed0);
  138. }
  139. msr::IA32_VMX_CR0_FIXED1 => {
  140. return Some(self.cr0_fixed1);
  141. }
  142. msr::IA32_VMX_CR4_FIXED0 => {
  143. return Some(self.cr4_fixed0);
  144. }
  145. msr::IA32_VMX_CR4_FIXED1 => {
  146. return Some(self.cr4_fixed1);
  147. }
  148. msr::IA32_VMX_VMCS_ENUM => {
  149. return Some(self.vmcs_enum);
  150. }
  151. msr::IA32_VMX_PROCBASED_CTLS2 => {
  152. return Some(NestedVmxMsrs::control_msr(
  153. self.secondary_ctls_low,
  154. self.secondary_ctls_high,
  155. ));
  156. }
  157. msr::IA32_VMX_EPT_VPID_CAP => {
  158. return Some(self.ept_caps as u64 | ((self.vpid_caps as u64) << 32));
  159. }
  160. msr::IA32_VMX_VMFUNC => {
  161. return Some(self.vmfunc_controls);
  162. }
  163. _ => {
  164. return None;
  165. }
  166. }
  167. }
  168. }
  169. #[derive(Debug, Default)]
  170. pub struct VmxCapability {
  171. pub ept: EptFlag,
  172. pub vpid: VpidFlag,
  173. }
  174. #[derive(Debug, PartialEq)]
  175. pub enum ProcessorTraceMode {
  176. System,
  177. HostGuest,
  178. }
  179. bitflags! {
  180. #[derive(Default)]
  181. pub struct VpidFlag: u32 {
  182. /// 表示处理器支持 INVVPID 指令
  183. const INVVPID = 1 << 0; /* (32 - 32) */
  184. /// 表示 VPID 支持以单独地址方式进行范围
  185. const EXTENT_INDIVIDUAL_ADDR = 1 << 8; /* (40 - 32) */
  186. /// 表示 VPID 支持以单个上下文方式进行范围
  187. const EXTENT_SINGLE_CONTEXT = 1 << 9; /* (41 - 32) */
  188. /// 表示 VPID 支持以全局上下文方式进行范围
  189. const EXTENT_GLOBAL_CONTEXT = 1 << 10; /* (42 - 32) */
  190. /// 表示 VPID 支持以单个非全局方式进行范围
  191. const EXTENT_SINGLE_NON_GLOBAL = 1 << 11; /* (43 - 32) */
  192. }
  193. #[derive(Default)]
  194. pub struct EptFlag: u32 {
  195. /// EPT 条目是否允许执行
  196. const EPT_EXECUTE_ONLY = 1;
  197. /// 处理器是否支持 4 级页表
  198. const EPT_PAGE_WALK_4 = 1 << 6;
  199. /// 处理器是否支持 5 级页表
  200. const EPT_PAGE_WALK_5 = 1 << 7;
  201. /// EPT 表的内存类型是否为不可缓存(uncached)
  202. const EPTP_UC = 1 << 8;
  203. /// EPT 表的内存类型是否为写回(write-back)
  204. const EPTP_WB = 1 << 14;
  205. /// 处理器是否支持 2MB 大页
  206. const EPT_2MB_PAGE = 1 << 16;
  207. /// 处理器是否支持 1GB 大页
  208. const EPT_1GB_PAGE = 1 << 17;
  209. /// 处理器是否支持 INV-EPT 指令,用于刷新 EPT TLB
  210. const EPT_INVEPT = 1 << 20;
  211. /// EPT 表是否支持访问位(Access-Dirty)
  212. const EPT_AD = 1 << 21;
  213. /// 处理器是否支持上下文扩展
  214. const EPT_EXTENT_CONTEXT = 1 << 25;
  215. /// 处理器是否支持全局扩展
  216. const EPT_EXTENT_GLOBAL = 1 << 26;
  217. }
  218. }
  219. impl VmxCapability {
  220. pub fn set_val_from_msr_val(&mut self, val: u64) {
  221. self.ept = EptFlag::from_bits_truncate(val as u32);
  222. self.vpid = VpidFlag::from_bits_truncate((val >> 32) as u32);
  223. }
  224. }
  225. impl Vmx {
  226. /// 检查处理器是否支持VMX基本控制结构的输入输出功能
  227. #[inline]
  228. #[allow(dead_code)]
  229. pub fn has_basic_inout(&self) -> bool {
  230. return ((self.vmcs_config.basic_cap as u64) << 32) & VmxFeat::VMX_BASIC_INOUT != 0;
  231. }
  232. /// 检查处理器是否支持虚拟的非屏蔽中断(NMI)
  233. #[inline]
  234. pub fn has_virtual_nmis(&self) -> bool {
  235. return self
  236. .vmcs_config
  237. .pin_based_exec_ctrl
  238. .contains(PinbasedControls::VIRTUAL_NMIS)
  239. && self
  240. .vmcs_config
  241. .cpu_based_exec_ctrl
  242. .contains(PrimaryControls::NMI_WINDOW_EXITING);
  243. }
  244. /// 检查处理器是否支持VMX的抢占计时器功能
  245. #[inline]
  246. pub fn has_preemption_timer(&self) -> bool {
  247. return self
  248. .vmcs_config
  249. .pin_based_exec_ctrl
  250. .contains(PinbasedControls::VMX_PREEMPTION_TIMER);
  251. }
  252. /// 检查处理器是否支持VMX的posted interrupt功能
  253. #[inline]
  254. pub fn has_posted_intr(&self) -> bool {
  255. return self
  256. .vmcs_config
  257. .pin_based_exec_ctrl
  258. .contains(PinbasedControls::POSTED_INTERRUPTS);
  259. }
  260. /// 是否支持加载IA32_EFER寄存器
  261. #[inline]
  262. pub fn has_load_ia32_efer(&self) -> bool {
  263. return self
  264. .vmcs_config
  265. .vmentry_ctrl
  266. .contains(EntryControls::LOAD_IA32_EFER);
  267. }
  268. /// 是否支持加载IA32_PERF_GLOBAL_CTRL寄存器
  269. #[inline]
  270. pub fn has_load_perf_global_ctrl(&self) -> bool {
  271. return self
  272. .vmcs_config
  273. .vmentry_ctrl
  274. .contains(EntryControls::LOAD_IA32_PERF_GLOBAL_CTRL);
  275. }
  276. /// 是否支持加载边界检查配置寄存器(MPX)
  277. #[inline]
  278. pub fn has_mpx(&self) -> bool {
  279. return self
  280. .vmcs_config
  281. .vmentry_ctrl
  282. .contains(EntryControls::LOAD_IA32_BNDCFGS);
  283. }
  284. /// 是否支持虚拟处理器的任务优先级(TPR)影子
  285. #[inline]
  286. pub fn has_tpr_shadow(&self) -> bool {
  287. return self
  288. .vmcs_config
  289. .cpu_based_exec_ctrl
  290. .contains(PrimaryControls::USE_TPR_SHADOW);
  291. }
  292. /// 检查处理器是否支持 VMX中的 VPID(Virtual Processor ID)功能
  293. ///
  294. /// VPID 允许虚拟机监视器为每个虚拟处理器分配唯一的标识符,从而使得在不同的虚拟机之间进行快速的上下文切换和恢复成为可能。
  295. ///
  296. /// 通过使用 VPID,VMM 可以更快速地识别和恢复之前保存的虚拟处理器的状态,从而提高了虚拟化性能和效率。
  297. #[inline]
  298. pub fn has_vpid(&self) -> bool {
  299. return self
  300. .vmcs_config
  301. .cpu_based_2nd_exec_ctrl
  302. .contains(SecondaryControls::ENABLE_VPID);
  303. }
  304. /// 是否支持invvpid
  305. ///
  306. /// INVVPID 指令用于通知处理器无效化指定虚拟处理器标识符(VPID)相关的 TLB(Translation Lookaside Buffer)条目
  307. #[inline]
  308. pub fn has_invvpid(&self) -> bool {
  309. return self.vmx_cap.vpid.contains(VpidFlag::INVVPID);
  310. }
  311. /// VPID 是否支持以单独地址方式进行范围
  312. #[allow(dead_code)]
  313. #[inline]
  314. pub fn has_invvpid_individual_addr(&self) -> bool {
  315. return self.vmx_cap.vpid.contains(VpidFlag::EXTENT_INDIVIDUAL_ADDR);
  316. }
  317. /// VPID 是否支持以单个上下文方式进行范围
  318. #[inline]
  319. pub fn has_invvpid_single(&self) -> bool {
  320. return self.vmx_cap.vpid.contains(VpidFlag::EXTENT_SINGLE_CONTEXT);
  321. }
  322. /// VPID 是否支持以全局上下文方式进行范围
  323. #[inline]
  324. pub fn has_invvpid_global(&self) -> bool {
  325. return self.vmx_cap.vpid.contains(VpidFlag::EXTENT_GLOBAL_CONTEXT);
  326. }
  327. /// 是否启用EPT(Extended Page Tables)
  328. ///
  329. /// EPT:EPT 是一种硬件虚拟化技术,允许虚拟机管理程序(例如 Hypervisor) 控制客户操作系统中虚拟地址和物理地址之间的映射。
  330. ///
  331. /// 通过启用 EPT,处理器可以将虚拟地址直接映射到物理地址,从而提高虚拟机的性能和安全性。
  332. #[inline]
  333. pub fn has_ept(&self) -> bool {
  334. return self
  335. .vmcs_config
  336. .cpu_based_2nd_exec_ctrl
  337. .contains(SecondaryControls::ENABLE_EPT);
  338. }
  339. /// 是否支持4级页表
  340. #[inline]
  341. pub fn has_ept_4levels(&self) -> bool {
  342. return self.vmx_cap.ept.contains(EptFlag::EPT_PAGE_WALK_4);
  343. }
  344. /// 是否支持5级页表
  345. #[inline]
  346. pub fn has_ept_5levels(&self) -> bool {
  347. return self.vmx_cap.ept.contains(EptFlag::EPT_PAGE_WALK_5);
  348. }
  349. pub fn get_max_ept_level(&self) -> usize {
  350. if self.has_ept_5levels() {
  351. return 5;
  352. }
  353. return 4;
  354. }
  355. pub fn ept_cap_to_lpage_level(&self) -> PageLevel {
  356. if self.vmx_cap.ept.contains(EptFlag::EPT_1GB_PAGE) {
  357. return PageLevel::Level1G;
  358. }
  359. if self.vmx_cap.ept.contains(EptFlag::EPT_2MB_PAGE) {
  360. return PageLevel::Level2M;
  361. }
  362. return PageLevel::Level4K;
  363. }
  364. /// 判断mt(Memory type)是否为write back
  365. #[inline]
  366. pub fn has_ept_mt_wb(&self) -> bool {
  367. return self.vmx_cap.ept.contains(EptFlag::EPTP_WB);
  368. }
  369. #[inline]
  370. pub fn has_vmx_invept_context(&self) -> bool {
  371. self.vmx_cap.ept.contains(EptFlag::EPT_EXTENT_CONTEXT)
  372. }
  373. /// EPT是否支持全局拓展
  374. #[inline]
  375. pub fn has_invept_global(&self) -> bool {
  376. return self.vmx_cap.ept.contains(EptFlag::EPT_EXTENT_GLOBAL);
  377. }
  378. /// EPT是否支持访问位
  379. #[inline]
  380. pub fn has_ept_ad_bits(&self) -> bool {
  381. return self.vmx_cap.ept.contains(EptFlag::EPT_AD);
  382. }
  383. /// 是否支持 VMX 中的无限制客户(unrestricted guest)功能
  384. ///
  385. /// 无限制客户功能允许客户操作系统在未受到主机操作系统干预的情况下运行
  386. #[inline]
  387. pub fn has_unrestricted_guest(&self) -> bool {
  388. return self
  389. .vmcs_config
  390. .cpu_based_2nd_exec_ctrl
  391. .contains(SecondaryControls::UNRESTRICTED_GUEST);
  392. }
  393. /// 是否支持 VMX 中的 FlexPriority 功能
  394. ///
  395. /// FlexPriority 是一种功能,可以在 TPR shadow 和虚拟化 APIC 访问同时可用时启用。
  396. ///
  397. /// TPR shadow 允许虚拟机管理程序(VMM)跟踪虚拟机中处理器的 TPR 值,并在需要时拦截和修改。
  398. ///
  399. /// 虚拟化 APIC 访问允许 VMM 控制虚拟机中的 APIC 寄存器访问。
  400. #[inline]
  401. pub fn has_flexproirity(&self) -> bool {
  402. return self.has_tpr_shadow() && self.has_virtualize_apic_accesses();
  403. }
  404. /// 是否支持 VMX 中的虚拟化 APIC 访问功能。
  405. ///
  406. /// 当启用此功能时,虚拟机管理程序(VMM)可以控制虚拟机中的 APIC 寄存器访问。
  407. #[inline]
  408. pub fn has_virtualize_apic_accesses(&self) -> bool {
  409. return self
  410. .vmcs_config
  411. .cpu_based_2nd_exec_ctrl
  412. .contains(SecondaryControls::VIRTUALIZE_APIC);
  413. }
  414. /// 是否支持 VMX 中的 ENCLS 指令导致的 VM 退出功能
  415. #[inline]
  416. pub fn has_encls_vmexit(&self) -> bool {
  417. return self
  418. .vmcs_config
  419. .cpu_based_2nd_exec_ctrl
  420. .contains(SecondaryControls::ENCLS_EXITING);
  421. }
  422. /// 是否支持 VMX 中的 PLE (Pause Loop Exiting) 功能。
  423. #[inline]
  424. pub fn has_ple(&self) -> bool {
  425. return self
  426. .vmcs_config
  427. .cpu_based_2nd_exec_ctrl
  428. .contains(SecondaryControls::PAUSE_LOOP_EXITING);
  429. }
  430. /// 是否支持 VMX 中的 APICv 功能
  431. #[inline]
  432. pub fn has_apicv(&self) -> bool {
  433. return self.has_apic_register_virt()
  434. && self.has_posted_intr()
  435. && self.has_virtual_intr_delivery();
  436. }
  437. /// 是否支持虚拟化的 APIC 寄存器功能
  438. #[inline]
  439. pub fn has_apic_register_virt(&self) -> bool {
  440. return self
  441. .vmcs_config
  442. .cpu_based_2nd_exec_ctrl
  443. .contains(SecondaryControls::VIRTUALIZE_APIC_REGISTER);
  444. }
  445. /// 是否支持虚拟化的中断传递功能
  446. #[inline]
  447. pub fn has_virtual_intr_delivery(&self) -> bool {
  448. return self
  449. .vmcs_config
  450. .cpu_based_2nd_exec_ctrl
  451. .contains(SecondaryControls::VIRTUAL_INTERRUPT_DELIVERY);
  452. }
  453. /// 是否支持虚拟化的中断注入(Inter-Processor Interrupt Virtualization,IPIV)
  454. #[inline]
  455. pub fn has_ipiv(&self) -> bool {
  456. return false;
  457. }
  458. /// 是否支持虚拟化的 TSC 缩放功能
  459. #[inline]
  460. pub fn has_tsc_scaling(&self) -> bool {
  461. return self
  462. .vmcs_config
  463. .cpu_based_2nd_exec_ctrl
  464. .contains(SecondaryControls::USE_TSC_SCALING);
  465. }
  466. /// 是否支持虚拟化的页修改日志(Page Modification Logging)
  467. #[inline]
  468. pub fn has_pml(&self) -> bool {
  469. return self
  470. .vmcs_config
  471. .cpu_based_2nd_exec_ctrl
  472. .contains(SecondaryControls::ENABLE_PML);
  473. }
  474. /// 检查 CPU 是否支持使用 MSR 位图来控制 VMX
  475. #[inline]
  476. pub fn has_msr_bitmap(&self) -> bool {
  477. return self
  478. .vmcs_config
  479. .cpu_based_exec_ctrl
  480. .contains(PrimaryControls::USE_MSR_BITMAPS);
  481. }
  482. #[inline]
  483. pub fn has_sceondary_exec_ctrls(&self) -> bool {
  484. self.vmcs_config
  485. .cpu_based_exec_ctrl
  486. .contains(PrimaryControls::SECONDARY_CONTROLS)
  487. }
  488. #[inline]
  489. pub fn has_rdtscp(&self) -> bool {
  490. self.vmcs_config
  491. .cpu_based_2nd_exec_ctrl
  492. .contains(SecondaryControls::ENABLE_RDTSCP)
  493. }
  494. #[inline]
  495. pub fn has_vmfunc(&self) -> bool {
  496. self.vmcs_config
  497. .cpu_based_2nd_exec_ctrl
  498. .contains(SecondaryControls::ENABLE_VM_FUNCTIONS)
  499. }
  500. #[inline]
  501. pub fn has_xsaves(&self) -> bool {
  502. self.vmcs_config
  503. .cpu_based_2nd_exec_ctrl
  504. .contains(SecondaryControls::ENABLE_XSAVES_XRSTORS)
  505. }
  506. #[inline]
  507. pub fn vmx_umip_emulated(&self) -> bool {
  508. let feat = CpuId::new().get_extended_feature_info().unwrap().has_umip();
  509. return !feat
  510. && (self
  511. .vmcs_config
  512. .cpu_based_2nd_exec_ctrl
  513. .contains(SecondaryControls::DTABLE_EXITING));
  514. }
  515. #[inline]
  516. pub fn has_tertiary_exec_ctrls(&self) -> bool {
  517. false
  518. }
  519. #[inline]
  520. pub fn has_bus_lock_detection(&self) -> bool {
  521. false
  522. }
  523. #[inline]
  524. pub fn has_notify_vmexit(&self) -> bool {
  525. false
  526. }
  527. /// 是否需要拦截页面故障
  528. #[inline]
  529. pub fn vmx_need_pf_intercept(&self, _vcpu: &VirtCpu) -> bool {
  530. // if (!enable_ept)
  531. // return true;
  532. false
  533. }
  534. }