1 // Copyright © 2019 Intel Corporation 2 // 3 // SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause 4 // 5 6 use byteorder::{ByteOrder, LittleEndian}; 7 use serde::{Deserialize, Serialize}; 8 use std::io; 9 use std::sync::Arc; 10 use thiserror::Error; 11 use vm_device::interrupt::{ 12 InterruptIndex, InterruptSourceConfig, InterruptSourceGroup, MsiIrqSourceConfig, 13 }; 14 use vm_migration::{MigratableError, Pausable, Snapshot, Snapshottable}; 15 16 // MSI control masks 17 const MSI_CTL_ENABLE: u16 = 0x1; 18 const MSI_CTL_MULTI_MSG_ENABLE: u16 = 0x70; 19 const MSI_CTL_64_BITS: u16 = 0x80; 20 const MSI_CTL_PER_VECTOR: u16 = 0x100; 21 22 // MSI message offsets 23 const MSI_MSG_CTL_OFFSET: u64 = 0x2; 24 const MSI_MSG_ADDR_LO_OFFSET: u64 = 0x4; 25 26 // MSI message masks 27 const MSI_MSG_ADDR_LO_MASK: u32 = 0xffff_fffc; 28 29 pub fn msi_num_enabled_vectors(msg_ctl: u16) -> usize { 30 let field = (msg_ctl >> 4) & 0x7; 31 32 if field > 5 { 33 return 0; 34 } 35 36 1 << field 37 } 38 39 #[derive(Error, Debug)] 40 pub enum Error { 41 #[error("Failed enabling the interrupt route: {0}")] 42 EnableInterruptRoute(io::Error), 43 #[error("Failed updating the interrupt route: {0}")] 44 UpdateInterruptRoute(io::Error), 45 } 46 47 pub const MSI_CONFIG_ID: &str = "msi_config"; 48 49 #[derive(Clone, Copy, Default, Serialize, Deserialize)] 50 pub struct MsiCap { 51 // Message Control Register 52 // 0: MSI enable. 53 // 3-1; Multiple message capable. 54 // 6-4: Multiple message enable. 55 // 7: 64 bits address capable. 56 // 8: Per-vector masking capable. 57 // 15-9: Reserved. 58 pub msg_ctl: u16, 59 // Message Address (LSB) 60 // 1-0: Reserved. 61 // 31-2: Message address. 62 pub msg_addr_lo: u32, 63 // Message Upper Address (MSB) 64 // 31-0: Message address. 65 pub msg_addr_hi: u32, 66 // Message Data 67 // 15-0: Message data. 68 pub msg_data: u16, 69 // Mask Bits 70 // 31-0: Mask bits. 71 pub mask_bits: u32, 72 // Pending Bits 73 // 31-0: Pending bits. 74 pub pending_bits: u32, 75 } 76 77 impl MsiCap { 78 fn addr_64_bits(&self) -> bool { 79 self.msg_ctl & MSI_CTL_64_BITS == MSI_CTL_64_BITS 80 } 81 82 fn per_vector_mask(&self) -> bool { 83 self.msg_ctl & MSI_CTL_PER_VECTOR == MSI_CTL_PER_VECTOR 84 } 85 86 fn enabled(&self) -> bool { 87 self.msg_ctl & MSI_CTL_ENABLE == MSI_CTL_ENABLE 88 } 89 90 fn num_enabled_vectors(&self) -> usize { 91 msi_num_enabled_vectors(self.msg_ctl) 92 } 93 94 fn vector_masked(&self, vector: usize) -> bool { 95 if !self.per_vector_mask() { 96 return false; 97 } 98 99 (self.mask_bits >> vector) & 0x1 == 0x1 100 } 101 102 fn size(&self) -> u64 { 103 let mut size: u64 = 0xa; 104 105 if self.addr_64_bits() { 106 size += 0x4; 107 } 108 if self.per_vector_mask() { 109 size += 0xa; 110 } 111 112 size 113 } 114 115 fn update(&mut self, offset: u64, data: &[u8]) { 116 // Calculate message data offset depending on the address being 32 or 117 // 64 bits. 118 // Calculate upper address offset if the address is 64 bits. 119 // Calculate mask bits offset based on the address being 32 or 64 bits 120 // and based on the per vector masking being enabled or not. 121 let (msg_data_offset, addr_hi_offset, mask_bits_offset): (u64, Option<u64>, Option<u64>) = 122 if self.addr_64_bits() { 123 let mask_bits = if self.per_vector_mask() { 124 Some(0x10) 125 } else { 126 None 127 }; 128 (0xc, Some(0x8), mask_bits) 129 } else { 130 let mask_bits = if self.per_vector_mask() { 131 Some(0xc) 132 } else { 133 None 134 }; 135 (0x8, None, mask_bits) 136 }; 137 138 // Update cache without overriding the read-only bits. 139 match data.len() { 140 2 => { 141 let value = LittleEndian::read_u16(data); 142 match offset { 143 MSI_MSG_CTL_OFFSET => { 144 self.msg_ctl = (self.msg_ctl & !(MSI_CTL_ENABLE | MSI_CTL_MULTI_MSG_ENABLE)) 145 | (value & (MSI_CTL_ENABLE | MSI_CTL_MULTI_MSG_ENABLE)) 146 } 147 x if x == msg_data_offset => self.msg_data = value, 148 _ => error!("invalid offset"), 149 } 150 } 151 4 => { 152 let value = LittleEndian::read_u32(data); 153 match offset { 154 0x0 => { 155 self.msg_ctl = (self.msg_ctl & !(MSI_CTL_ENABLE | MSI_CTL_MULTI_MSG_ENABLE)) 156 | ((value >> 16) as u16 & (MSI_CTL_ENABLE | MSI_CTL_MULTI_MSG_ENABLE)) 157 } 158 MSI_MSG_ADDR_LO_OFFSET => self.msg_addr_lo = value & MSI_MSG_ADDR_LO_MASK, 159 x if x == msg_data_offset => self.msg_data = value as u16, 160 x if addr_hi_offset.is_some() && x == addr_hi_offset.unwrap() => { 161 self.msg_addr_hi = value 162 } 163 x if mask_bits_offset.is_some() && x == mask_bits_offset.unwrap() => { 164 self.mask_bits = value 165 } 166 _ => error!("invalid offset"), 167 } 168 } 169 _ => error!("invalid data length"), 170 } 171 } 172 } 173 174 #[derive(Serialize, Deserialize)] 175 pub struct MsiConfigState { 176 cap: MsiCap, 177 } 178 179 pub struct MsiConfig { 180 pub cap: MsiCap, 181 interrupt_source_group: Arc<dyn InterruptSourceGroup>, 182 } 183 184 impl MsiConfig { 185 pub fn new( 186 msg_ctl: u16, 187 interrupt_source_group: Arc<dyn InterruptSourceGroup>, 188 state: Option<MsiConfigState>, 189 ) -> Result<Self, Error> { 190 let cap = if let Some(state) = state { 191 if state.cap.enabled() { 192 for idx in 0..state.cap.num_enabled_vectors() { 193 let config = MsiIrqSourceConfig { 194 high_addr: state.cap.msg_addr_hi, 195 low_addr: state.cap.msg_addr_lo, 196 data: state.cap.msg_data as u32, 197 devid: 0, 198 }; 199 200 interrupt_source_group 201 .update( 202 idx as InterruptIndex, 203 InterruptSourceConfig::MsiIrq(config), 204 state.cap.vector_masked(idx), 205 false, 206 ) 207 .map_err(Error::UpdateInterruptRoute)?; 208 } 209 210 interrupt_source_group 211 .set_gsi() 212 .map_err(Error::EnableInterruptRoute)?; 213 214 interrupt_source_group 215 .enable() 216 .map_err(Error::EnableInterruptRoute)?; 217 } 218 219 state.cap 220 } else { 221 MsiCap { 222 msg_ctl, 223 ..Default::default() 224 } 225 }; 226 227 Ok(MsiConfig { 228 cap, 229 interrupt_source_group, 230 }) 231 } 232 233 fn state(&self) -> MsiConfigState { 234 MsiConfigState { cap: self.cap } 235 } 236 237 pub fn enabled(&self) -> bool { 238 self.cap.enabled() 239 } 240 241 pub fn size(&self) -> u64 { 242 self.cap.size() 243 } 244 245 pub fn num_enabled_vectors(&self) -> usize { 246 self.cap.num_enabled_vectors() 247 } 248 249 pub fn update(&mut self, offset: u64, data: &[u8]) { 250 let old_enabled = self.cap.enabled(); 251 252 self.cap.update(offset, data); 253 254 if self.cap.enabled() { 255 for idx in 0..self.num_enabled_vectors() { 256 let config = MsiIrqSourceConfig { 257 high_addr: self.cap.msg_addr_hi, 258 low_addr: self.cap.msg_addr_lo, 259 data: self.cap.msg_data as u32, 260 devid: 0, 261 }; 262 263 if let Err(e) = self.interrupt_source_group.update( 264 idx as InterruptIndex, 265 InterruptSourceConfig::MsiIrq(config), 266 self.cap.vector_masked(idx), 267 true, 268 ) { 269 error!("Failed updating vector: {:?}", e); 270 } 271 } 272 273 if !old_enabled { 274 if let Err(e) = self.interrupt_source_group.enable() { 275 error!("Failed enabling irq_fd: {:?}", e); 276 } 277 } 278 } else if old_enabled { 279 if let Err(e) = self.interrupt_source_group.disable() { 280 error!("Failed disabling irq_fd: {:?}", e); 281 } 282 } 283 } 284 } 285 286 impl Pausable for MsiConfig {} 287 288 impl Snapshottable for MsiConfig { 289 fn id(&self) -> String { 290 String::from(MSI_CONFIG_ID) 291 } 292 293 fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> { 294 Snapshot::new_from_state(&self.state()) 295 } 296 } 297