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 std::sync::Arc; 8 use vm_device::interrupt::{ 9 InterruptIndex, InterruptSourceConfig, InterruptSourceGroup, MsiIrqSourceConfig, 10 }; 11 12 // MSI control masks 13 const MSI_CTL_ENABLE: u16 = 0x1; 14 const MSI_CTL_MULTI_MSG_ENABLE: u16 = 0x70; 15 const MSI_CTL_64_BITS: u16 = 0x80; 16 const MSI_CTL_PER_VECTOR: u16 = 0x100; 17 18 // MSI message offsets 19 const MSI_MSG_CTL_OFFSET: u64 = 0x2; 20 const MSI_MSG_ADDR_LO_OFFSET: u64 = 0x4; 21 22 // MSI message masks 23 const MSI_MSG_ADDR_LO_MASK: u32 = 0xffff_fffc; 24 25 pub fn msi_num_enabled_vectors(msg_ctl: u16) -> usize { 26 let field = (msg_ctl >> 4) & 0x7; 27 28 if field > 5 { 29 return 0; 30 } 31 32 1 << field 33 } 34 35 #[derive(Clone, Copy, Default)] 36 pub struct MsiCap { 37 // Message Control Register 38 // 0: MSI enable. 39 // 3-1; Multiple message capable. 40 // 6-4: Multiple message enable. 41 // 7: 64 bits address capable. 42 // 8: Per-vector masking capable. 43 // 15-9: Reserved. 44 pub msg_ctl: u16, 45 // Message Address (LSB) 46 // 1-0: Reserved. 47 // 31-2: Message address. 48 pub msg_addr_lo: u32, 49 // Message Upper Address (MSB) 50 // 31-0: Message address. 51 pub msg_addr_hi: u32, 52 // Message Data 53 // 15-0: Message data. 54 pub msg_data: u16, 55 // Mask Bits 56 // 31-0: Mask bits. 57 pub mask_bits: u32, 58 // Pending Bits 59 // 31-0: Pending bits. 60 pub pending_bits: u32, 61 } 62 63 impl MsiCap { 64 fn addr_64_bits(&self) -> bool { 65 self.msg_ctl & MSI_CTL_64_BITS == MSI_CTL_64_BITS 66 } 67 68 fn per_vector_mask(&self) -> bool { 69 self.msg_ctl & MSI_CTL_PER_VECTOR == MSI_CTL_PER_VECTOR 70 } 71 72 fn enabled(&self) -> bool { 73 self.msg_ctl & MSI_CTL_ENABLE == MSI_CTL_ENABLE 74 } 75 76 fn num_enabled_vectors(&self) -> usize { 77 msi_num_enabled_vectors(self.msg_ctl) 78 } 79 80 fn vector_masked(&self, vector: usize) -> bool { 81 if !self.per_vector_mask() { 82 return false; 83 } 84 85 (self.mask_bits >> vector) & 0x1 == 0x1 86 } 87 88 fn size(&self) -> u64 { 89 let mut size: u64 = 0xa; 90 91 if self.addr_64_bits() { 92 size += 0x4; 93 } 94 if self.per_vector_mask() { 95 size += 0xa; 96 } 97 98 size 99 } 100 101 fn update(&mut self, offset: u64, data: &[u8]) { 102 // Calculate message data offset depending on the address being 32 or 103 // 64 bits. 104 // Calculate upper address offset if the address is 64 bits. 105 // Calculate mask bits offset based on the address being 32 or 64 bits 106 // and based on the per vector masking being enabled or not. 107 let (msg_data_offset, addr_hi_offset, mask_bits_offset): (u64, Option<u64>, Option<u64>) = 108 if self.addr_64_bits() { 109 let mask_bits = if self.per_vector_mask() { 110 Some(0x10) 111 } else { 112 None 113 }; 114 (0xc, Some(0x8), mask_bits) 115 } else { 116 let mask_bits = if self.per_vector_mask() { 117 Some(0xc) 118 } else { 119 None 120 }; 121 (0x8, None, mask_bits) 122 }; 123 124 // Update cache without overriding the read-only bits. 125 match data.len() { 126 2 => { 127 let value = LittleEndian::read_u16(data); 128 match offset { 129 MSI_MSG_CTL_OFFSET => { 130 self.msg_ctl = (self.msg_ctl & !(MSI_CTL_ENABLE | MSI_CTL_MULTI_MSG_ENABLE)) 131 | (value & (MSI_CTL_ENABLE | MSI_CTL_MULTI_MSG_ENABLE)) 132 } 133 x if x == msg_data_offset => self.msg_data = value, 134 _ => error!("invalid offset"), 135 } 136 } 137 4 => { 138 let value = LittleEndian::read_u32(data); 139 match offset { 140 0x0 => { 141 self.msg_ctl = (self.msg_ctl & !(MSI_CTL_ENABLE | MSI_CTL_MULTI_MSG_ENABLE)) 142 | ((value >> 16) as u16 & (MSI_CTL_ENABLE | MSI_CTL_MULTI_MSG_ENABLE)) 143 } 144 MSI_MSG_ADDR_LO_OFFSET => self.msg_addr_lo = value & MSI_MSG_ADDR_LO_MASK, 145 x if x == msg_data_offset => self.msg_data = value as u16, 146 x if addr_hi_offset.is_some() && x == addr_hi_offset.unwrap() => { 147 self.msg_addr_hi = value 148 } 149 x if mask_bits_offset.is_some() && x == mask_bits_offset.unwrap() => { 150 self.mask_bits = value 151 } 152 _ => error!("invalid offset"), 153 } 154 } 155 _ => error!("invalid data length"), 156 } 157 } 158 } 159 160 pub struct MsiConfig { 161 cap: MsiCap, 162 interrupt_source_group: Arc<Box<dyn InterruptSourceGroup>>, 163 } 164 165 impl MsiConfig { 166 pub fn new(msg_ctl: u16, interrupt_source_group: Arc<Box<dyn InterruptSourceGroup>>) -> Self { 167 let cap = MsiCap { 168 msg_ctl, 169 ..Default::default() 170 }; 171 172 MsiConfig { 173 cap, 174 interrupt_source_group, 175 } 176 } 177 178 pub fn enabled(&self) -> bool { 179 self.cap.enabled() 180 } 181 182 pub fn size(&self) -> u64 { 183 self.cap.size() 184 } 185 186 pub fn num_enabled_vectors(&self) -> usize { 187 self.cap.num_enabled_vectors() 188 } 189 190 pub fn update(&mut self, offset: u64, data: &[u8]) { 191 let old_enabled = self.cap.enabled(); 192 193 self.cap.update(offset, data); 194 195 if self.cap.enabled() { 196 for idx in 0..self.num_enabled_vectors() { 197 let config = MsiIrqSourceConfig { 198 high_addr: self.cap.msg_addr_hi, 199 low_addr: self.cap.msg_addr_lo, 200 data: self.cap.msg_data as u32, 201 devid: 0, 202 }; 203 204 if let Err(e) = self 205 .interrupt_source_group 206 .update(idx as InterruptIndex, InterruptSourceConfig::MsiIrq(config)) 207 { 208 error!("Failed updating vector: {:?}", e); 209 } 210 211 if self.cap.vector_masked(idx) { 212 if let Err(e) = self.interrupt_source_group.mask(idx as InterruptIndex) { 213 error!("Failed masking vector: {:?}", e); 214 } 215 } else if let Err(e) = self.interrupt_source_group.unmask(idx as InterruptIndex) { 216 error!("Failed unmasking vector: {:?}", e); 217 } 218 } 219 220 if !old_enabled { 221 if let Err(e) = self.interrupt_source_group.enable() { 222 error!("Failed enabling irq_fd: {:?}", e); 223 } 224 } 225 } else if old_enabled { 226 if let Err(e) = self.interrupt_source_group.disable() { 227 error!("Failed disabling irq_fd: {:?}", e); 228 } 229 } 230 } 231 } 232