Get the current CPU state Ordering requirements: KVM_GET_MP_STATE calls kvm_apic_accept_events(), which might modify vCPU/LAPIC state. As such, it must be done before most everything else, otherwise we cannot restore everything and expect it to work. KVM_GET_VCPU_EVENTS/KVM_SET_VCPU_EVENTS is unsafe if other vCPUs are still running. KVM_GET_LAPIC may change state of LAPIC before returning it.
(&self)
| 2860 | /// let state = vcpu.state().unwrap(); |
| 2861 | /// ``` |
| 2862 | fn state(&self) -> cpu::Result<CpuState> { |
| 2863 | let cpuid = self.get_cpuid2(kvm_bindings::KVM_MAX_CPUID_ENTRIES)?; |
| 2864 | let mp_state = self.get_mp_state()?.into(); |
| 2865 | let regs = self.get_regs()?; |
| 2866 | let sregs = self.get_sregs()?; |
| 2867 | let xsave = if self.xsave_size > 0 { |
| 2868 | self.get_xsave2()? |
| 2869 | } else { |
| 2870 | self.get_xsave()? |
| 2871 | }; |
| 2872 | let xcrs = self.get_xcrs()?; |
| 2873 | let lapic_state = self.get_lapic()?; |
| 2874 | let fpu = self.get_fpu()?; |
| 2875 | let nested_state = self.nested_state()?; |
| 2876 | |
| 2877 | // Try to get all MSRs based on the list previously retrieved from KVM. |
| 2878 | // If the number of MSRs obtained from GET_MSRS is different from the |
| 2879 | // expected amount, we fallback onto a slower method by getting MSRs |
| 2880 | // by chunks. This is the only way to make sure we try to get as many |
| 2881 | // MSRs as possible, even if some MSRs are not supported. |
| 2882 | let mut msr_entries = self.msrs.clone(); |
| 2883 | |
| 2884 | // Save extra MSRs if the Hyper-V synthetic interrupt controller is |
| 2885 | // emulated. |
| 2886 | let hyperv_synic = self.hyperv_synic.load(Ordering::Acquire); |
| 2887 | if hyperv_synic { |
| 2888 | let hyperv_synic_msrs = vec![ |
| 2889 | 0x40000020, 0x40000021, 0x40000080, 0x40000081, 0x40000082, 0x40000083, 0x40000084, |
| 2890 | 0x40000090, 0x40000091, 0x40000092, 0x40000093, 0x40000094, 0x40000095, 0x40000096, |
| 2891 | 0x40000097, 0x40000098, 0x40000099, 0x4000009a, 0x4000009b, 0x4000009c, 0x4000009d, |
| 2892 | 0x4000009e, 0x4000009f, 0x400000b0, 0x400000b1, 0x400000b2, 0x400000b3, 0x400000b4, |
| 2893 | 0x400000b5, 0x400000b6, 0x400000b7, |
| 2894 | ]; |
| 2895 | for index in hyperv_synic_msrs { |
| 2896 | let msr = kvm_msr_entry { |
| 2897 | index, |
| 2898 | ..Default::default() |
| 2899 | }; |
| 2900 | msr_entries.push(msr.into()); |
| 2901 | } |
| 2902 | } |
| 2903 | |
| 2904 | let expected_num_msrs = msr_entries.len(); |
| 2905 | let num_msrs = self.get_msrs(&mut msr_entries)?; |
| 2906 | let msrs = if num_msrs == expected_num_msrs { |
| 2907 | msr_entries |
| 2908 | } else { |
| 2909 | let mut faulty_msr_index = num_msrs; |
| 2910 | let mut msr_entries_tmp = msr_entries[..faulty_msr_index].to_vec(); |
| 2911 | |
| 2912 | loop { |
| 2913 | warn!( |
| 2914 | "Detected faulty MSR 0x{:x} while getting MSRs", |
| 2915 | msr_entries[faulty_msr_index].index |
| 2916 | ); |
| 2917 | |
| 2918 | // Skip the first bad MSR |
| 2919 | let start_pos = faulty_msr_index + 1; |
nothing calls this directly
no test coverage detected