1f9b51a41SMuminul Islam // Copyright © 2019 Intel Corporation
2f9b51a41SMuminul Islam //
372ae1577SMuminul Islam // SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause
4f9b51a41SMuminul Islam //
5f9b51a41SMuminul Islam // Copyright © 2020, Microsoft Corporation
6f9b51a41SMuminul Islam //
7f9b51a41SMuminul Islam // Copyright 2018-2019 CrowdStrike, Inc.
8f9b51a41SMuminul Islam //
9f9b51a41SMuminul Islam //
10f9b51a41SMuminul Islam
113a0429c9SMaksym Pavlenko use serde::{Deserialize, Serialize};
12f9b51a41SMuminul Islam ///
13f9b51a41SMuminul Islam /// Export generically-named wrappers of kvm-bindings for Unix-based platforms
14f9b51a41SMuminul Islam ///
15f9b51a41SMuminul Islam pub use {
166a8c0fc8SWei Liu kvm_bindings::kvm_cpuid_entry2, kvm_bindings::kvm_dtable, kvm_bindings::kvm_fpu,
1705e5106bSWei Liu kvm_bindings::kvm_lapic_state, kvm_bindings::kvm_mp_state as MpState,
18f21fc1dcSWei Liu kvm_bindings::kvm_msr_entry, kvm_bindings::kvm_regs, kvm_bindings::kvm_segment,
1908135fa0SWei Liu kvm_bindings::kvm_sregs, kvm_bindings::kvm_vcpu_events as VcpuEvents,
203ce0fef7SBo Chen kvm_bindings::kvm_xcrs as ExtendedControlRegisters, kvm_bindings::kvm_xsave,
2149b4fba2SSebastien Boeuf kvm_bindings::CpuId, kvm_bindings::MsrList, kvm_bindings::Msrs as MsrEntries,
2208135fa0SWei Liu kvm_bindings::KVM_CPUID_FLAG_SIGNIFCANT_INDEX,
23f9b51a41SMuminul Islam };
2472e39a34SMuminul Islam
25*88a9f799SRob Bradford use crate::arch::x86::{
26*88a9f799SRob Bradford CpuIdEntry, DescriptorTable, FpuState, LapicState, MsrEntry, SegmentRegister, SpecialRegisters,
27*88a9f799SRob Bradford XsaveState, CPUID_FLAG_VALID_INDEX,
28*88a9f799SRob Bradford };
29*88a9f799SRob Bradford use crate::kvm::{Cap, Kvm, KvmError, KvmResult};
30*88a9f799SRob Bradford
3172e39a34SMuminul Islam ///
3272e39a34SMuminul Islam /// Check KVM extension for Linux
3372e39a34SMuminul Islam ///
check_required_kvm_extensions(kvm: &Kvm) -> KvmResult<()>3472e39a34SMuminul Islam pub fn check_required_kvm_extensions(kvm: &Kvm) -> KvmResult<()> {
35c07671edSWei Liu macro_rules! check_extension {
36c07671edSWei Liu ($cap:expr) => {
37c07671edSWei Liu if !kvm.check_extension($cap) {
38c07671edSWei Liu return Err(KvmError::CapabilityMissing($cap));
3972e39a34SMuminul Islam }
40c07671edSWei Liu };
4172e39a34SMuminul Islam }
42c07671edSWei Liu
43241d1d5cSWei Liu // DeviceCtrl, EnableCap, and SetGuestDebug are also required, but some kernels have
44241d1d5cSWei Liu // the features implemented without the capability flags.
45241d1d5cSWei Liu check_extension!(Cap::AdjustClock);
46241d1d5cSWei Liu check_extension!(Cap::ExtCpuid);
47c07671edSWei Liu check_extension!(Cap::GetTscKhz);
48c07671edSWei Liu check_extension!(Cap::ImmediateExit);
49241d1d5cSWei Liu check_extension!(Cap::Ioeventfd);
50241d1d5cSWei Liu check_extension!(Cap::Irqchip);
51241d1d5cSWei Liu check_extension!(Cap::Irqfd);
52241d1d5cSWei Liu check_extension!(Cap::IrqRouting);
53241d1d5cSWei Liu check_extension!(Cap::MpState);
54c07671edSWei Liu check_extension!(Cap::SetIdentityMapAddr);
55c07671edSWei Liu check_extension!(Cap::SetTssAddr);
56c07671edSWei Liu check_extension!(Cap::SplitIrqchip);
57c07671edSWei Liu check_extension!(Cap::TscDeadlineTimer);
58241d1d5cSWei Liu check_extension!(Cap::UserMemory);
59241d1d5cSWei Liu check_extension!(Cap::UserNmi);
60241d1d5cSWei Liu check_extension!(Cap::VcpuEvents);
61241d1d5cSWei Liu check_extension!(Cap::Xcrs);
62241d1d5cSWei Liu check_extension!(Cap::Xsave);
6372e39a34SMuminul Islam Ok(())
6472e39a34SMuminul Islam }
65241d1d5cSWei Liu
66c48d0c1aSMuminul Islam #[derive(Clone, Serialize, Deserialize)]
67c48d0c1aSMuminul Islam pub struct VcpuKvmState {
6845fbf840SWei Liu pub cpuid: Vec<CpuIdEntry>,
694d2cc377SWei Liu pub msrs: Vec<MsrEntry>,
70c48d0c1aSMuminul Islam pub vcpu_events: VcpuEvents,
718b7781e2SWei Liu pub regs: kvm_regs,
72f1ab86feSWei Liu pub sregs: kvm_sregs,
73c48d0c1aSMuminul Islam pub fpu: FpuState,
74c48d0c1aSMuminul Islam pub lapic_state: LapicState,
753ce0fef7SBo Chen pub xsave: XsaveState,
76c48d0c1aSMuminul Islam pub xcrs: ExtendedControlRegisters,
77c48d0c1aSMuminul Islam pub mp_state: MpState,
7844f200d6SRob Bradford pub tsc_khz: Option<u32>,
79c48d0c1aSMuminul Islam }
808b7781e2SWei Liu
8175797827SWei Liu impl From<SegmentRegister> for kvm_segment {
from(s: SegmentRegister) -> Self8275797827SWei Liu fn from(s: SegmentRegister) -> Self {
8375797827SWei Liu Self {
8475797827SWei Liu base: s.base,
8575797827SWei Liu limit: s.limit,
8675797827SWei Liu selector: s.selector,
8775797827SWei Liu type_: s.type_,
8875797827SWei Liu present: s.present,
8975797827SWei Liu dpl: s.dpl,
9075797827SWei Liu db: s.db,
9175797827SWei Liu s: s.s,
9275797827SWei Liu l: s.l,
9375797827SWei Liu g: s.g,
9475797827SWei Liu avl: s.avl,
9575797827SWei Liu unusable: s.unusable,
9675797827SWei Liu ..Default::default()
9775797827SWei Liu }
9875797827SWei Liu }
9975797827SWei Liu }
10075797827SWei Liu
10175797827SWei Liu impl From<kvm_segment> for SegmentRegister {
from(s: kvm_segment) -> Self10275797827SWei Liu fn from(s: kvm_segment) -> Self {
10375797827SWei Liu Self {
10475797827SWei Liu base: s.base,
10575797827SWei Liu limit: s.limit,
10675797827SWei Liu selector: s.selector,
10775797827SWei Liu type_: s.type_,
10875797827SWei Liu present: s.present,
10975797827SWei Liu dpl: s.dpl,
11075797827SWei Liu db: s.db,
11175797827SWei Liu s: s.s,
11275797827SWei Liu l: s.l,
11375797827SWei Liu g: s.g,
11475797827SWei Liu avl: s.avl,
11575797827SWei Liu unusable: s.unusable,
11675797827SWei Liu }
11775797827SWei Liu }
11875797827SWei Liu }
119d2b194c4SWei Liu
120d2b194c4SWei Liu impl From<DescriptorTable> for kvm_dtable {
from(dt: DescriptorTable) -> Self121d2b194c4SWei Liu fn from(dt: DescriptorTable) -> Self {
122d2b194c4SWei Liu Self {
123d2b194c4SWei Liu base: dt.base,
124d2b194c4SWei Liu limit: dt.limit,
125d2b194c4SWei Liu ..Default::default()
126d2b194c4SWei Liu }
127d2b194c4SWei Liu }
128d2b194c4SWei Liu }
129d2b194c4SWei Liu
130d2b194c4SWei Liu impl From<kvm_dtable> for DescriptorTable {
from(dt: kvm_dtable) -> Self131d2b194c4SWei Liu fn from(dt: kvm_dtable) -> Self {
132d2b194c4SWei Liu Self {
133d2b194c4SWei Liu base: dt.base,
134d2b194c4SWei Liu limit: dt.limit,
135d2b194c4SWei Liu }
136d2b194c4SWei Liu }
137d2b194c4SWei Liu }
138f1ab86feSWei Liu
139f1ab86feSWei Liu impl From<SpecialRegisters> for kvm_sregs {
from(s: SpecialRegisters) -> Self140f1ab86feSWei Liu fn from(s: SpecialRegisters) -> Self {
141f1ab86feSWei Liu Self {
142f1ab86feSWei Liu cs: s.cs.into(),
143f1ab86feSWei Liu ds: s.ds.into(),
144f1ab86feSWei Liu es: s.es.into(),
145f1ab86feSWei Liu fs: s.fs.into(),
146f1ab86feSWei Liu gs: s.gs.into(),
147f1ab86feSWei Liu ss: s.ss.into(),
148f1ab86feSWei Liu tr: s.tr.into(),
149f1ab86feSWei Liu ldt: s.ldt.into(),
150f1ab86feSWei Liu gdt: s.gdt.into(),
151f1ab86feSWei Liu idt: s.idt.into(),
152f1ab86feSWei Liu cr0: s.cr0,
153f1ab86feSWei Liu cr2: s.cr2,
154f1ab86feSWei Liu cr3: s.cr3,
155f1ab86feSWei Liu cr4: s.cr4,
156f1ab86feSWei Liu cr8: s.cr8,
157f1ab86feSWei Liu efer: s.efer,
158f1ab86feSWei Liu apic_base: s.apic_base,
159f1ab86feSWei Liu interrupt_bitmap: s.interrupt_bitmap,
160f1ab86feSWei Liu }
161f1ab86feSWei Liu }
162f1ab86feSWei Liu }
163f1ab86feSWei Liu
164f1ab86feSWei Liu impl From<kvm_sregs> for SpecialRegisters {
from(s: kvm_sregs) -> Self165f1ab86feSWei Liu fn from(s: kvm_sregs) -> Self {
166f1ab86feSWei Liu Self {
167f1ab86feSWei Liu cs: s.cs.into(),
168f1ab86feSWei Liu ds: s.ds.into(),
169f1ab86feSWei Liu es: s.es.into(),
170f1ab86feSWei Liu fs: s.fs.into(),
171f1ab86feSWei Liu gs: s.gs.into(),
172f1ab86feSWei Liu ss: s.ss.into(),
173f1ab86feSWei Liu tr: s.tr.into(),
174f1ab86feSWei Liu ldt: s.ldt.into(),
175f1ab86feSWei Liu gdt: s.gdt.into(),
176f1ab86feSWei Liu idt: s.idt.into(),
177f1ab86feSWei Liu cr0: s.cr0,
178f1ab86feSWei Liu cr2: s.cr2,
179f1ab86feSWei Liu cr3: s.cr3,
180f1ab86feSWei Liu cr4: s.cr4,
181f1ab86feSWei Liu cr8: s.cr8,
182f1ab86feSWei Liu efer: s.efer,
183f1ab86feSWei Liu apic_base: s.apic_base,
184f1ab86feSWei Liu interrupt_bitmap: s.interrupt_bitmap,
185f1ab86feSWei Liu }
186f1ab86feSWei Liu }
187f1ab86feSWei Liu }
18808135fa0SWei Liu
18908135fa0SWei Liu impl From<CpuIdEntry> for kvm_cpuid_entry2 {
from(e: CpuIdEntry) -> Self19008135fa0SWei Liu fn from(e: CpuIdEntry) -> Self {
19108135fa0SWei Liu let flags = if e.flags & CPUID_FLAG_VALID_INDEX != 0 {
19208135fa0SWei Liu KVM_CPUID_FLAG_SIGNIFCANT_INDEX
19308135fa0SWei Liu } else {
19408135fa0SWei Liu 0
19508135fa0SWei Liu };
19608135fa0SWei Liu Self {
19708135fa0SWei Liu function: e.function,
19808135fa0SWei Liu index: e.index,
19908135fa0SWei Liu flags,
20008135fa0SWei Liu eax: e.eax,
20108135fa0SWei Liu ebx: e.ebx,
20208135fa0SWei Liu ecx: e.ecx,
20308135fa0SWei Liu edx: e.edx,
20408135fa0SWei Liu ..Default::default()
20508135fa0SWei Liu }
20608135fa0SWei Liu }
20708135fa0SWei Liu }
20808135fa0SWei Liu
20908135fa0SWei Liu impl From<kvm_cpuid_entry2> for CpuIdEntry {
from(e: kvm_cpuid_entry2) -> Self21008135fa0SWei Liu fn from(e: kvm_cpuid_entry2) -> Self {
21108135fa0SWei Liu let flags = if e.flags & KVM_CPUID_FLAG_SIGNIFCANT_INDEX != 0 {
21208135fa0SWei Liu CPUID_FLAG_VALID_INDEX
21308135fa0SWei Liu } else {
21408135fa0SWei Liu 0
21508135fa0SWei Liu };
21608135fa0SWei Liu Self {
21708135fa0SWei Liu function: e.function,
21808135fa0SWei Liu index: e.index,
21908135fa0SWei Liu flags,
22008135fa0SWei Liu eax: e.eax,
22108135fa0SWei Liu ebx: e.ebx,
22208135fa0SWei Liu ecx: e.ecx,
22308135fa0SWei Liu edx: e.edx,
22408135fa0SWei Liu }
22508135fa0SWei Liu }
22608135fa0SWei Liu }
2276a8c0fc8SWei Liu
2286a8c0fc8SWei Liu impl From<kvm_fpu> for FpuState {
from(s: kvm_fpu) -> Self2296a8c0fc8SWei Liu fn from(s: kvm_fpu) -> Self {
2306a8c0fc8SWei Liu Self {
2316a8c0fc8SWei Liu fpr: s.fpr,
2326a8c0fc8SWei Liu fcw: s.fcw,
2336a8c0fc8SWei Liu fsw: s.fsw,
2346a8c0fc8SWei Liu ftwx: s.ftwx,
2356a8c0fc8SWei Liu last_opcode: s.last_opcode,
2366a8c0fc8SWei Liu last_ip: s.last_ip,
2376a8c0fc8SWei Liu last_dp: s.last_dp,
2386a8c0fc8SWei Liu xmm: s.xmm,
2396a8c0fc8SWei Liu mxcsr: s.mxcsr,
2406a8c0fc8SWei Liu }
2416a8c0fc8SWei Liu }
2426a8c0fc8SWei Liu }
2436a8c0fc8SWei Liu
2446a8c0fc8SWei Liu impl From<FpuState> for kvm_fpu {
from(s: FpuState) -> Self2456a8c0fc8SWei Liu fn from(s: FpuState) -> Self {
2466a8c0fc8SWei Liu Self {
2476a8c0fc8SWei Liu fpr: s.fpr,
2486a8c0fc8SWei Liu fcw: s.fcw,
2496a8c0fc8SWei Liu fsw: s.fsw,
2506a8c0fc8SWei Liu ftwx: s.ftwx,
2516a8c0fc8SWei Liu last_opcode: s.last_opcode,
2526a8c0fc8SWei Liu last_ip: s.last_ip,
2536a8c0fc8SWei Liu last_dp: s.last_dp,
2546a8c0fc8SWei Liu xmm: s.xmm,
2556a8c0fc8SWei Liu mxcsr: s.mxcsr,
2566a8c0fc8SWei Liu ..Default::default()
2576a8c0fc8SWei Liu }
2586a8c0fc8SWei Liu }
2596a8c0fc8SWei Liu }
26005e5106bSWei Liu
26105e5106bSWei Liu impl From<LapicState> for kvm_lapic_state {
from(s: LapicState) -> Self26205e5106bSWei Liu fn from(s: LapicState) -> Self {
263bec47ebcSWei Liu Self { regs: s.regs }
26405e5106bSWei Liu }
26505e5106bSWei Liu }
26605e5106bSWei Liu
26705e5106bSWei Liu impl From<kvm_lapic_state> for LapicState {
from(s: kvm_lapic_state) -> Self26805e5106bSWei Liu fn from(s: kvm_lapic_state) -> Self {
269bec47ebcSWei Liu Self { regs: s.regs }
27005e5106bSWei Liu }
27105e5106bSWei Liu }
272f21fc1dcSWei Liu
273f21fc1dcSWei Liu impl From<kvm_msr_entry> for MsrEntry {
from(e: kvm_msr_entry) -> Self274f21fc1dcSWei Liu fn from(e: kvm_msr_entry) -> Self {
275f21fc1dcSWei Liu Self {
276f21fc1dcSWei Liu index: e.index,
277f21fc1dcSWei Liu data: e.data,
278f21fc1dcSWei Liu }
279f21fc1dcSWei Liu }
280f21fc1dcSWei Liu }
281f21fc1dcSWei Liu
282f21fc1dcSWei Liu impl From<MsrEntry> for kvm_msr_entry {
from(e: MsrEntry) -> Self283f21fc1dcSWei Liu fn from(e: MsrEntry) -> Self {
284f21fc1dcSWei Liu Self {
285f21fc1dcSWei Liu index: e.index,
286f21fc1dcSWei Liu data: e.data,
287f21fc1dcSWei Liu ..Default::default()
288f21fc1dcSWei Liu }
289f21fc1dcSWei Liu }
290f21fc1dcSWei Liu }
2913ce0fef7SBo Chen
2923ce0fef7SBo Chen impl From<kvm_xsave> for XsaveState {
from(s: kvm_xsave) -> Self2933ce0fef7SBo Chen fn from(s: kvm_xsave) -> Self {
2943ce0fef7SBo Chen Self { region: s.region }
2953ce0fef7SBo Chen }
2963ce0fef7SBo Chen }
2973ce0fef7SBo Chen
2983ce0fef7SBo Chen impl From<XsaveState> for kvm_xsave {
from(s: XsaveState) -> Self2993ce0fef7SBo Chen fn from(s: XsaveState) -> Self {
3003ce0fef7SBo Chen Self {
3013ce0fef7SBo Chen region: s.region,
3023ce0fef7SBo Chen extra: Default::default(),
3033ce0fef7SBo Chen }
3043ce0fef7SBo Chen }
3053ce0fef7SBo Chen }
306