vmm_core/cpuid/
mod.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! VM CPUID support.
5
6use hvdef::VIRTUALIZATION_STACK_CPUID_INTERFACE;
7use hvdef::VIRTUALIZATION_STACK_CPUID_PROPERTIES;
8use hvdef::VIRTUALIZATION_STACK_CPUID_VENDOR;
9use hvdef::VS1_PARTITION_PROPERTIES_EAX_CONFIDENTIAL_VMBUS_AVAILABLE;
10use hvdef::VS1_PARTITION_PROPERTIES_EAX_EXTENDED_IOAPIC_RTE;
11use hvdef::VS1_PARTITION_PROPERTIES_EAX_IS_PORTABLE;
12use virt::CpuidLeaf;
13use x86defs::cpuid::CpuidFunction;
14
15/// Returns CPUID leaves for Hyper-V-style VMs.
16///
17/// `extended_ioapic_rte` indicates that MSIs and the IOAPIC can reference a
18/// 15-bit APIC ID instead of the architectural 8-bit value. To match Hyper-V
19/// behavior, this should be enabled for non-PCAT VMs.
20pub fn hyperv_cpuid_leaves(
21    extended_ioapic_rte: bool,
22    confidential_vmbus: bool,
23) -> impl Iterator<Item = CpuidLeaf> {
24    [
25        // Enable the virtualization bit.
26        //
27        // Not all hypervisors (e.g. KVM) enable this automatically.
28        CpuidLeaf::new(CpuidFunction::VersionAndFeatures.0, [0, 0, 1 << 31, 0]).masked([
29            0,
30            0,
31            1 << 31,
32            0,
33        ]),
34        CpuidLeaf::new(
35            VIRTUALIZATION_STACK_CPUID_VENDOR,
36            [
37                VIRTUALIZATION_STACK_CPUID_PROPERTIES,
38                u32::from_le_bytes(*b"Micr"),
39                u32::from_le_bytes(*b"osof"),
40                u32::from_le_bytes(*b"t VS"),
41            ],
42        ),
43        CpuidLeaf::new(
44            VIRTUALIZATION_STACK_CPUID_INTERFACE,
45            [u32::from_le_bytes(*b"VS#1"), 0, 0, 0],
46        ),
47        CpuidLeaf::new(
48            VIRTUALIZATION_STACK_CPUID_PROPERTIES,
49            [
50                VS1_PARTITION_PROPERTIES_EAX_IS_PORTABLE
51                    | if extended_ioapic_rte {
52                        VS1_PARTITION_PROPERTIES_EAX_EXTENDED_IOAPIC_RTE
53                    } else {
54                        0
55                    }
56                    | if confidential_vmbus {
57                        VS1_PARTITION_PROPERTIES_EAX_CONFIDENTIAL_VMBUS_AVAILABLE
58                    } else {
59                        0
60                    },
61                0,
62                0,
63                0,
64            ],
65        ),
66    ]
67    .into_iter()
68}