x86defs/
msi.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! x86 definitions of non-translated MSI address and data.
5
6use crate::apic::APIC_BASE_ADDRESS;
7use bitfield_struct::bitfield;
8
9/// The layout of the MSI address element.
10#[bitfield(u32)]
11pub struct MsiAddress {
12    #[bits(2)]
13    _reserved: u32,
14    pub destination_mode_logical: bool,
15    pub redirection_hint: bool,
16    pub extended_destination: u8,
17    pub destination: u8,
18    #[bits(12)]
19    pub address: u16,
20}
21
22/// The expected value for MsiAddress::address.
23pub const MSI_ADDRESS: u16 = (APIC_BASE_ADDRESS >> 20) as u16;
24
25impl MsiAddress {
26    /// Returns a 15-bit destination encoded in the MSI address. This is not
27    /// architectural--normally only an 8-bit destination is supported unless
28    /// interrupt redirection is enabled--but this is supported by some
29    /// virtualization platforms (including Hyper-V and KVM).
30    ///
31    /// The high 7 bits are encoded as the high 7 bits of the extended
32    /// destination field. The low bit of that field is ignored and presumed to
33    /// be zero in this configuration.
34    pub fn virt_destination(&self) -> u16 {
35        self.destination() as u16 | ((self.extended_destination() as u16 & !1) << 7)
36    }
37
38    /// Returns a value with a 15-bit destination encoded as guests expect when
39    /// running with Hyper-V or KVM virtualization extensions.
40    ///
41    /// This updates the destination and extended destination fields.
42    pub fn with_virt_destination(self, destination: u16) -> Self {
43        self.with_destination(destination as u8)
44            .with_extended_destination((destination >> 7) as u8 & !1)
45    }
46
47    /// Updates the value with a 15-bit destination encoded as guests expect
48    /// when running with Hyper-V or KVM virtualization extensions.
49    ///
50    /// This updates the destination and extended destination fields.
51    pub fn set_virt_destination(&mut self, destination: u16) {
52        *self = self.with_virt_destination(destination);
53    }
54}
55
56/// The layout of the MSI data element.
57///
58/// Note that the significant bits correspond to low bits of
59/// [`Icr`](super::apic::Icr).
60#[bitfield(u32)]
61pub struct MsiData {
62    pub vector: u8,
63    #[bits(3)]
64    pub delivery_mode: u8,
65    pub destination_mode_logical: bool,
66    #[bits(2)]
67    _reserved: u8,
68    pub assert: bool,
69    pub trigger_mode_level: bool,
70    _reserved: u16,
71}