1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2022 The ChromiumOS Authors 2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be 3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file. 4*bb4ee6a4SAndroid Build Coastguard Worker 5*bb4ee6a4SAndroid Build Coastguard Worker #![cfg_attr(windows, allow(dead_code))] 6*bb4ee6a4SAndroid Build Coastguard Worker 7*bb4ee6a4SAndroid Build Coastguard Worker use base::error; 8*bb4ee6a4SAndroid Build Coastguard Worker use base::AsRawDescriptor; 9*bb4ee6a4SAndroid Build Coastguard Worker use base::Event; 10*bb4ee6a4SAndroid Build Coastguard Worker use base::RawDescriptor; 11*bb4ee6a4SAndroid Build Coastguard Worker use base::Tube; 12*bb4ee6a4SAndroid Build Coastguard Worker use bit_field::*; 13*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::VmIrqRequest; 14*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::VmIrqResponse; 15*bb4ee6a4SAndroid Build Coastguard Worker use zerocopy::AsBytes; 16*bb4ee6a4SAndroid Build Coastguard Worker use zerocopy::FromBytes; 17*bb4ee6a4SAndroid Build Coastguard Worker use zerocopy::FromZeroes; 18*bb4ee6a4SAndroid Build Coastguard Worker 19*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::pci_configuration::PciCapConfig; 20*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::pci_configuration::PciCapConfigWriteResult; 21*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::PciCapability; 22*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::PciCapabilityID; 23*bb4ee6a4SAndroid Build Coastguard Worker 24*bb4ee6a4SAndroid Build Coastguard Worker // MSI registers 25*bb4ee6a4SAndroid Build Coastguard Worker pub const PCI_MSI_NEXT_POINTER: u32 = 0x1; // Next cap pointer 26*bb4ee6a4SAndroid Build Coastguard Worker pub const PCI_MSI_FLAGS: u32 = 0x2; // Message Control 27*bb4ee6a4SAndroid Build Coastguard Worker const PCI_MSI_FLAGS_ENABLE: u16 = 0x0001; // MSI feature enabled 28*bb4ee6a4SAndroid Build Coastguard Worker pub const PCI_MSI_FLAGS_64BIT: u16 = 0x0080; // 64-bit addresses allowed 29*bb4ee6a4SAndroid Build Coastguard Worker pub const PCI_MSI_FLAGS_MASKBIT: u16 = 0x0100; // Per-vector masking capable 30*bb4ee6a4SAndroid Build Coastguard Worker const PCI_MSI_ADDRESS_LO: u32 = 0x4; // MSI address lower 32 bits 31*bb4ee6a4SAndroid Build Coastguard Worker const PCI_MSI_ADDRESS_HI: u32 = 0x8; // MSI address upper 32 bits (if 64 bit allowed) 32*bb4ee6a4SAndroid Build Coastguard Worker const PCI_MSI_DATA_32: u32 = 0x8; // 16 bits of data for 32-bit message address 33*bb4ee6a4SAndroid Build Coastguard Worker const PCI_MSI_DATA_64: u32 = 0xC; // 16 bits of date for 64-bit message address 34*bb4ee6a4SAndroid Build Coastguard Worker 35*bb4ee6a4SAndroid Build Coastguard Worker // MSI length 36*bb4ee6a4SAndroid Build Coastguard Worker const MSI_LENGTH_32BIT_WITHOUT_MASK: u32 = 0xA; 37*bb4ee6a4SAndroid Build Coastguard Worker const MSI_LENGTH_32BIT_WITH_MASK: u32 = 0x14; 38*bb4ee6a4SAndroid Build Coastguard Worker const MSI_LENGTH_64BIT_WITHOUT_MASK: u32 = 0xE; 39*bb4ee6a4SAndroid Build Coastguard Worker const MSI_LENGTH_64BIT_WITH_MASK: u32 = 0x18; 40*bb4ee6a4SAndroid Build Coastguard Worker 41*bb4ee6a4SAndroid Build Coastguard Worker pub enum MsiStatus { 42*bb4ee6a4SAndroid Build Coastguard Worker Enabled, 43*bb4ee6a4SAndroid Build Coastguard Worker Disabled, 44*bb4ee6a4SAndroid Build Coastguard Worker NothingToDo, 45*bb4ee6a4SAndroid Build Coastguard Worker } 46*bb4ee6a4SAndroid Build Coastguard Worker 47*bb4ee6a4SAndroid Build Coastguard Worker /// Wrapper over MSI Capability Structure 48*bb4ee6a4SAndroid Build Coastguard Worker pub struct MsiConfig { 49*bb4ee6a4SAndroid Build Coastguard Worker is_64bit: bool, 50*bb4ee6a4SAndroid Build Coastguard Worker mask_cap: bool, 51*bb4ee6a4SAndroid Build Coastguard Worker ctrl: u16, 52*bb4ee6a4SAndroid Build Coastguard Worker address: u64, 53*bb4ee6a4SAndroid Build Coastguard Worker data: u16, 54*bb4ee6a4SAndroid Build Coastguard Worker vm_socket_irq: Tube, 55*bb4ee6a4SAndroid Build Coastguard Worker irqfd: Option<Event>, 56*bb4ee6a4SAndroid Build Coastguard Worker gsi: Option<u32>, 57*bb4ee6a4SAndroid Build Coastguard Worker device_id: u32, 58*bb4ee6a4SAndroid Build Coastguard Worker device_name: String, 59*bb4ee6a4SAndroid Build Coastguard Worker } 60*bb4ee6a4SAndroid Build Coastguard Worker 61*bb4ee6a4SAndroid Build Coastguard Worker impl MsiConfig { new( is_64bit: bool, mask_cap: bool, vm_socket_irq: Tube, device_id: u32, device_name: String, ) -> Self62*bb4ee6a4SAndroid Build Coastguard Worker pub fn new( 63*bb4ee6a4SAndroid Build Coastguard Worker is_64bit: bool, 64*bb4ee6a4SAndroid Build Coastguard Worker mask_cap: bool, 65*bb4ee6a4SAndroid Build Coastguard Worker vm_socket_irq: Tube, 66*bb4ee6a4SAndroid Build Coastguard Worker device_id: u32, 67*bb4ee6a4SAndroid Build Coastguard Worker device_name: String, 68*bb4ee6a4SAndroid Build Coastguard Worker ) -> Self { 69*bb4ee6a4SAndroid Build Coastguard Worker let mut ctrl: u16 = 0; 70*bb4ee6a4SAndroid Build Coastguard Worker if is_64bit { 71*bb4ee6a4SAndroid Build Coastguard Worker ctrl |= PCI_MSI_FLAGS_64BIT; 72*bb4ee6a4SAndroid Build Coastguard Worker } 73*bb4ee6a4SAndroid Build Coastguard Worker if mask_cap { 74*bb4ee6a4SAndroid Build Coastguard Worker ctrl |= PCI_MSI_FLAGS_MASKBIT; 75*bb4ee6a4SAndroid Build Coastguard Worker } 76*bb4ee6a4SAndroid Build Coastguard Worker MsiConfig { 77*bb4ee6a4SAndroid Build Coastguard Worker is_64bit, 78*bb4ee6a4SAndroid Build Coastguard Worker mask_cap, 79*bb4ee6a4SAndroid Build Coastguard Worker ctrl, 80*bb4ee6a4SAndroid Build Coastguard Worker address: 0, 81*bb4ee6a4SAndroid Build Coastguard Worker data: 0, 82*bb4ee6a4SAndroid Build Coastguard Worker vm_socket_irq, 83*bb4ee6a4SAndroid Build Coastguard Worker irqfd: None, 84*bb4ee6a4SAndroid Build Coastguard Worker gsi: None, 85*bb4ee6a4SAndroid Build Coastguard Worker device_id, 86*bb4ee6a4SAndroid Build Coastguard Worker device_name, 87*bb4ee6a4SAndroid Build Coastguard Worker } 88*bb4ee6a4SAndroid Build Coastguard Worker } 89*bb4ee6a4SAndroid Build Coastguard Worker len(&self) -> u3290*bb4ee6a4SAndroid Build Coastguard Worker fn len(&self) -> u32 { 91*bb4ee6a4SAndroid Build Coastguard Worker match (self.is_64bit, self.mask_cap) { 92*bb4ee6a4SAndroid Build Coastguard Worker (true, true) => MSI_LENGTH_64BIT_WITH_MASK, 93*bb4ee6a4SAndroid Build Coastguard Worker (true, false) => MSI_LENGTH_64BIT_WITHOUT_MASK, 94*bb4ee6a4SAndroid Build Coastguard Worker (false, true) => MSI_LENGTH_32BIT_WITH_MASK, 95*bb4ee6a4SAndroid Build Coastguard Worker (false, false) => MSI_LENGTH_32BIT_WITHOUT_MASK, 96*bb4ee6a4SAndroid Build Coastguard Worker } 97*bb4ee6a4SAndroid Build Coastguard Worker } 98*bb4ee6a4SAndroid Build Coastguard Worker is_msi_reg(&self, offset: u32, index: u64, len: usize) -> bool99*bb4ee6a4SAndroid Build Coastguard Worker pub fn is_msi_reg(&self, offset: u32, index: u64, len: usize) -> bool { 100*bb4ee6a4SAndroid Build Coastguard Worker let msi_len = self.len(); 101*bb4ee6a4SAndroid Build Coastguard Worker index >= offset as u64 102*bb4ee6a4SAndroid Build Coastguard Worker && index + len as u64 <= (offset + msi_len) as u64 103*bb4ee6a4SAndroid Build Coastguard Worker && len as u32 <= msi_len 104*bb4ee6a4SAndroid Build Coastguard Worker } 105*bb4ee6a4SAndroid Build Coastguard Worker read_msi_capability(&self, offset: u32, data: u32) -> u32106*bb4ee6a4SAndroid Build Coastguard Worker pub fn read_msi_capability(&self, offset: u32, data: u32) -> u32 { 107*bb4ee6a4SAndroid Build Coastguard Worker if offset == 0 { 108*bb4ee6a4SAndroid Build Coastguard Worker (self.ctrl as u32) << 16 | (data & u16::MAX as u32) 109*bb4ee6a4SAndroid Build Coastguard Worker } else { 110*bb4ee6a4SAndroid Build Coastguard Worker data 111*bb4ee6a4SAndroid Build Coastguard Worker } 112*bb4ee6a4SAndroid Build Coastguard Worker } 113*bb4ee6a4SAndroid Build Coastguard Worker write_msi_capability(&mut self, offset: u32, data: &[u8]) -> MsiStatus114*bb4ee6a4SAndroid Build Coastguard Worker pub fn write_msi_capability(&mut self, offset: u32, data: &[u8]) -> MsiStatus { 115*bb4ee6a4SAndroid Build Coastguard Worker let len = data.len(); 116*bb4ee6a4SAndroid Build Coastguard Worker let mut ret = MsiStatus::NothingToDo; 117*bb4ee6a4SAndroid Build Coastguard Worker let old_address = self.address; 118*bb4ee6a4SAndroid Build Coastguard Worker let old_data = self.data; 119*bb4ee6a4SAndroid Build Coastguard Worker 120*bb4ee6a4SAndroid Build Coastguard Worker // write msi ctl 121*bb4ee6a4SAndroid Build Coastguard Worker if len == 2 && offset == PCI_MSI_FLAGS { 122*bb4ee6a4SAndroid Build Coastguard Worker let was_enabled = self.is_msi_enabled(); 123*bb4ee6a4SAndroid Build Coastguard Worker let value: [u8; 2] = [data[0], data[1]]; 124*bb4ee6a4SAndroid Build Coastguard Worker self.ctrl = u16::from_le_bytes(value); 125*bb4ee6a4SAndroid Build Coastguard Worker let is_enabled = self.is_msi_enabled(); 126*bb4ee6a4SAndroid Build Coastguard Worker if !was_enabled && is_enabled { 127*bb4ee6a4SAndroid Build Coastguard Worker self.enable(); 128*bb4ee6a4SAndroid Build Coastguard Worker ret = MsiStatus::Enabled; 129*bb4ee6a4SAndroid Build Coastguard Worker } else if was_enabled && !is_enabled { 130*bb4ee6a4SAndroid Build Coastguard Worker ret = MsiStatus::Disabled; 131*bb4ee6a4SAndroid Build Coastguard Worker } 132*bb4ee6a4SAndroid Build Coastguard Worker } else if len == 4 && offset == PCI_MSI_ADDRESS_LO && !self.is_64bit { 133*bb4ee6a4SAndroid Build Coastguard Worker //write 32 bit message address 134*bb4ee6a4SAndroid Build Coastguard Worker let value: [u8; 8] = [data[0], data[1], data[2], data[3], 0, 0, 0, 0]; 135*bb4ee6a4SAndroid Build Coastguard Worker self.address = u64::from_le_bytes(value); 136*bb4ee6a4SAndroid Build Coastguard Worker } else if len == 4 && offset == PCI_MSI_ADDRESS_LO && self.is_64bit { 137*bb4ee6a4SAndroid Build Coastguard Worker // write 64 bit message address low part 138*bb4ee6a4SAndroid Build Coastguard Worker let value: [u8; 8] = [data[0], data[1], data[2], data[3], 0, 0, 0, 0]; 139*bb4ee6a4SAndroid Build Coastguard Worker self.address &= !0xffffffff; 140*bb4ee6a4SAndroid Build Coastguard Worker self.address |= u64::from_le_bytes(value); 141*bb4ee6a4SAndroid Build Coastguard Worker } else if len == 4 && offset == PCI_MSI_ADDRESS_HI && self.is_64bit { 142*bb4ee6a4SAndroid Build Coastguard Worker //write 64 bit message address high part 143*bb4ee6a4SAndroid Build Coastguard Worker let value: [u8; 8] = [0, 0, 0, 0, data[0], data[1], data[2], data[3]]; 144*bb4ee6a4SAndroid Build Coastguard Worker self.address &= 0xffffffff; 145*bb4ee6a4SAndroid Build Coastguard Worker self.address |= u64::from_le_bytes(value); 146*bb4ee6a4SAndroid Build Coastguard Worker } else if len == 8 && offset == PCI_MSI_ADDRESS_LO && self.is_64bit { 147*bb4ee6a4SAndroid Build Coastguard Worker // write 64 bit message address 148*bb4ee6a4SAndroid Build Coastguard Worker let value: [u8; 8] = [ 149*bb4ee6a4SAndroid Build Coastguard Worker data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7], 150*bb4ee6a4SAndroid Build Coastguard Worker ]; 151*bb4ee6a4SAndroid Build Coastguard Worker self.address = u64::from_le_bytes(value); 152*bb4ee6a4SAndroid Build Coastguard Worker } else if len == 2 153*bb4ee6a4SAndroid Build Coastguard Worker && ((offset == PCI_MSI_DATA_32 && !self.is_64bit) 154*bb4ee6a4SAndroid Build Coastguard Worker || (offset == PCI_MSI_DATA_64 && self.is_64bit)) 155*bb4ee6a4SAndroid Build Coastguard Worker { 156*bb4ee6a4SAndroid Build Coastguard Worker // write message data 157*bb4ee6a4SAndroid Build Coastguard Worker let value: [u8; 2] = [data[0], data[1]]; 158*bb4ee6a4SAndroid Build Coastguard Worker self.data = u16::from_le_bytes(value); 159*bb4ee6a4SAndroid Build Coastguard Worker } 160*bb4ee6a4SAndroid Build Coastguard Worker 161*bb4ee6a4SAndroid Build Coastguard Worker if self.is_msi_enabled() && (old_address != self.address || old_data != self.data) { 162*bb4ee6a4SAndroid Build Coastguard Worker self.add_msi_route(); 163*bb4ee6a4SAndroid Build Coastguard Worker } 164*bb4ee6a4SAndroid Build Coastguard Worker 165*bb4ee6a4SAndroid Build Coastguard Worker ret 166*bb4ee6a4SAndroid Build Coastguard Worker } 167*bb4ee6a4SAndroid Build Coastguard Worker is_msi_enabled(&self) -> bool168*bb4ee6a4SAndroid Build Coastguard Worker pub fn is_msi_enabled(&self) -> bool { 169*bb4ee6a4SAndroid Build Coastguard Worker self.ctrl & PCI_MSI_FLAGS_ENABLE == PCI_MSI_FLAGS_ENABLE 170*bb4ee6a4SAndroid Build Coastguard Worker } 171*bb4ee6a4SAndroid Build Coastguard Worker add_msi_route(&self)172*bb4ee6a4SAndroid Build Coastguard Worker fn add_msi_route(&self) { 173*bb4ee6a4SAndroid Build Coastguard Worker let gsi = match self.gsi { 174*bb4ee6a4SAndroid Build Coastguard Worker Some(g) => g, 175*bb4ee6a4SAndroid Build Coastguard Worker None => { 176*bb4ee6a4SAndroid Build Coastguard Worker error!("Add msi route but gsi is none"); 177*bb4ee6a4SAndroid Build Coastguard Worker return; 178*bb4ee6a4SAndroid Build Coastguard Worker } 179*bb4ee6a4SAndroid Build Coastguard Worker }; 180*bb4ee6a4SAndroid Build Coastguard Worker if let Err(e) = self.vm_socket_irq.send(&VmIrqRequest::AddMsiRoute { 181*bb4ee6a4SAndroid Build Coastguard Worker gsi, 182*bb4ee6a4SAndroid Build Coastguard Worker msi_address: self.address, 183*bb4ee6a4SAndroid Build Coastguard Worker msi_data: self.data.into(), 184*bb4ee6a4SAndroid Build Coastguard Worker }) { 185*bb4ee6a4SAndroid Build Coastguard Worker error!("failed to send AddMsiRoute request at {:?}", e); 186*bb4ee6a4SAndroid Build Coastguard Worker return; 187*bb4ee6a4SAndroid Build Coastguard Worker } 188*bb4ee6a4SAndroid Build Coastguard Worker match self.vm_socket_irq.recv() { 189*bb4ee6a4SAndroid Build Coastguard Worker Ok(VmIrqResponse::Err(e)) => error!("failed to call AddMsiRoute request {:?}", e), 190*bb4ee6a4SAndroid Build Coastguard Worker Ok(_) => {} 191*bb4ee6a4SAndroid Build Coastguard Worker Err(e) => error!("failed to receive AddMsiRoute response {:?}", e), 192*bb4ee6a4SAndroid Build Coastguard Worker } 193*bb4ee6a4SAndroid Build Coastguard Worker } 194*bb4ee6a4SAndroid Build Coastguard Worker allocate_one_msi(&mut self)195*bb4ee6a4SAndroid Build Coastguard Worker fn allocate_one_msi(&mut self) { 196*bb4ee6a4SAndroid Build Coastguard Worker let irqfd = match self.irqfd.take() { 197*bb4ee6a4SAndroid Build Coastguard Worker Some(e) => e, 198*bb4ee6a4SAndroid Build Coastguard Worker None => match Event::new() { 199*bb4ee6a4SAndroid Build Coastguard Worker Ok(e) => e, 200*bb4ee6a4SAndroid Build Coastguard Worker Err(e) => { 201*bb4ee6a4SAndroid Build Coastguard Worker error!("failed to create event: {:?}", e); 202*bb4ee6a4SAndroid Build Coastguard Worker return; 203*bb4ee6a4SAndroid Build Coastguard Worker } 204*bb4ee6a4SAndroid Build Coastguard Worker }, 205*bb4ee6a4SAndroid Build Coastguard Worker }; 206*bb4ee6a4SAndroid Build Coastguard Worker 207*bb4ee6a4SAndroid Build Coastguard Worker let request = VmIrqRequest::AllocateOneMsi { 208*bb4ee6a4SAndroid Build Coastguard Worker irqfd, 209*bb4ee6a4SAndroid Build Coastguard Worker device_id: self.device_id, 210*bb4ee6a4SAndroid Build Coastguard Worker queue_id: 0, 211*bb4ee6a4SAndroid Build Coastguard Worker device_name: self.device_name.clone(), 212*bb4ee6a4SAndroid Build Coastguard Worker }; 213*bb4ee6a4SAndroid Build Coastguard Worker let request_result = self.vm_socket_irq.send(&request); 214*bb4ee6a4SAndroid Build Coastguard Worker 215*bb4ee6a4SAndroid Build Coastguard Worker // Stash the irqfd in self immediately because we used take above. 216*bb4ee6a4SAndroid Build Coastguard Worker self.irqfd = match request { 217*bb4ee6a4SAndroid Build Coastguard Worker VmIrqRequest::AllocateOneMsi { irqfd, .. } => Some(irqfd), 218*bb4ee6a4SAndroid Build Coastguard Worker _ => unreachable!(), 219*bb4ee6a4SAndroid Build Coastguard Worker }; 220*bb4ee6a4SAndroid Build Coastguard Worker 221*bb4ee6a4SAndroid Build Coastguard Worker if let Err(e) = request_result { 222*bb4ee6a4SAndroid Build Coastguard Worker error!("failed to send AllocateOneMsi request: {:?}", e); 223*bb4ee6a4SAndroid Build Coastguard Worker return; 224*bb4ee6a4SAndroid Build Coastguard Worker } 225*bb4ee6a4SAndroid Build Coastguard Worker 226*bb4ee6a4SAndroid Build Coastguard Worker match self.vm_socket_irq.recv() { 227*bb4ee6a4SAndroid Build Coastguard Worker Ok(VmIrqResponse::AllocateOneMsi { gsi }) => self.gsi = Some(gsi), 228*bb4ee6a4SAndroid Build Coastguard Worker _ => error!("failed to receive AllocateOneMsi Response"), 229*bb4ee6a4SAndroid Build Coastguard Worker } 230*bb4ee6a4SAndroid Build Coastguard Worker } 231*bb4ee6a4SAndroid Build Coastguard Worker enable(&mut self)232*bb4ee6a4SAndroid Build Coastguard Worker fn enable(&mut self) { 233*bb4ee6a4SAndroid Build Coastguard Worker if self.gsi.is_none() || self.irqfd.is_none() { 234*bb4ee6a4SAndroid Build Coastguard Worker self.allocate_one_msi(); 235*bb4ee6a4SAndroid Build Coastguard Worker } 236*bb4ee6a4SAndroid Build Coastguard Worker 237*bb4ee6a4SAndroid Build Coastguard Worker self.add_msi_route(); 238*bb4ee6a4SAndroid Build Coastguard Worker } 239*bb4ee6a4SAndroid Build Coastguard Worker get_irqfd(&self) -> Option<&Event>240*bb4ee6a4SAndroid Build Coastguard Worker pub fn get_irqfd(&self) -> Option<&Event> { 241*bb4ee6a4SAndroid Build Coastguard Worker self.irqfd.as_ref() 242*bb4ee6a4SAndroid Build Coastguard Worker } 243*bb4ee6a4SAndroid Build Coastguard Worker destroy(&mut self)244*bb4ee6a4SAndroid Build Coastguard Worker pub fn destroy(&mut self) { 245*bb4ee6a4SAndroid Build Coastguard Worker if let Some(gsi) = self.gsi { 246*bb4ee6a4SAndroid Build Coastguard Worker if let Some(irqfd) = self.irqfd.take() { 247*bb4ee6a4SAndroid Build Coastguard Worker let request = VmIrqRequest::ReleaseOneIrq { gsi, irqfd }; 248*bb4ee6a4SAndroid Build Coastguard Worker if self.vm_socket_irq.send(&request).is_ok() { 249*bb4ee6a4SAndroid Build Coastguard Worker let _ = self.vm_socket_irq.recv::<VmIrqResponse>(); 250*bb4ee6a4SAndroid Build Coastguard Worker } 251*bb4ee6a4SAndroid Build Coastguard Worker } 252*bb4ee6a4SAndroid Build Coastguard Worker } 253*bb4ee6a4SAndroid Build Coastguard Worker } 254*bb4ee6a4SAndroid Build Coastguard Worker 255*bb4ee6a4SAndroid Build Coastguard Worker /// Return the raw descriptor of the MSI device socket get_msi_socket(&self) -> RawDescriptor256*bb4ee6a4SAndroid Build Coastguard Worker pub fn get_msi_socket(&self) -> RawDescriptor { 257*bb4ee6a4SAndroid Build Coastguard Worker self.vm_socket_irq.as_raw_descriptor() 258*bb4ee6a4SAndroid Build Coastguard Worker } 259*bb4ee6a4SAndroid Build Coastguard Worker trigger(&self)260*bb4ee6a4SAndroid Build Coastguard Worker pub fn trigger(&self) { 261*bb4ee6a4SAndroid Build Coastguard Worker if let Some(irqfd) = self.irqfd.as_ref() { 262*bb4ee6a4SAndroid Build Coastguard Worker irqfd.signal().unwrap(); 263*bb4ee6a4SAndroid Build Coastguard Worker } 264*bb4ee6a4SAndroid Build Coastguard Worker } 265*bb4ee6a4SAndroid Build Coastguard Worker } 266*bb4ee6a4SAndroid Build Coastguard Worker 267*bb4ee6a4SAndroid Build Coastguard Worker #[bitfield] 268*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Copy, Clone, AsBytes, FromZeroes, FromBytes)] 269*bb4ee6a4SAndroid Build Coastguard Worker pub struct MsiCtrl { 270*bb4ee6a4SAndroid Build Coastguard Worker enable: B1, 271*bb4ee6a4SAndroid Build Coastguard Worker multi_msg_capable: B3, 272*bb4ee6a4SAndroid Build Coastguard Worker multi_msg_enable: B3, 273*bb4ee6a4SAndroid Build Coastguard Worker is_64bit: B1, 274*bb4ee6a4SAndroid Build Coastguard Worker per_vector_masking: B1, 275*bb4ee6a4SAndroid Build Coastguard Worker extended_msg_data_capable: B1, 276*bb4ee6a4SAndroid Build Coastguard Worker extended_msg_data_enable: B1, 277*bb4ee6a4SAndroid Build Coastguard Worker reserved: B5, 278*bb4ee6a4SAndroid Build Coastguard Worker } 279*bb4ee6a4SAndroid Build Coastguard Worker 280*bb4ee6a4SAndroid Build Coastguard Worker #[allow(dead_code)] 281*bb4ee6a4SAndroid Build Coastguard Worker #[repr(C, align(4))] 282*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Clone, Copy, Default, AsBytes, FromZeroes, FromBytes)] 283*bb4ee6a4SAndroid Build Coastguard Worker struct Msi32BitWithoutMask { 284*bb4ee6a4SAndroid Build Coastguard Worker msg_data: u16, 285*bb4ee6a4SAndroid Build Coastguard Worker msg_extended_data: u16, 286*bb4ee6a4SAndroid Build Coastguard Worker _padding: [u8; 12], 287*bb4ee6a4SAndroid Build Coastguard Worker } 288*bb4ee6a4SAndroid Build Coastguard Worker 289*bb4ee6a4SAndroid Build Coastguard Worker #[allow(dead_code)] 290*bb4ee6a4SAndroid Build Coastguard Worker #[repr(C, align(4))] 291*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Clone, Copy, Default, AsBytes, FromZeroes, FromBytes)] 292*bb4ee6a4SAndroid Build Coastguard Worker struct Msi32BitWithMask { 293*bb4ee6a4SAndroid Build Coastguard Worker msg_data: u16, 294*bb4ee6a4SAndroid Build Coastguard Worker msg_extended_data: u16, 295*bb4ee6a4SAndroid Build Coastguard Worker mask_bits: u32, 296*bb4ee6a4SAndroid Build Coastguard Worker pending_bits: u32, 297*bb4ee6a4SAndroid Build Coastguard Worker _padding: [u8; 4], 298*bb4ee6a4SAndroid Build Coastguard Worker } 299*bb4ee6a4SAndroid Build Coastguard Worker 300*bb4ee6a4SAndroid Build Coastguard Worker #[allow(dead_code)] 301*bb4ee6a4SAndroid Build Coastguard Worker #[repr(C, align(4))] 302*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Clone, Copy, Default, AsBytes, FromZeroes, FromBytes)] 303*bb4ee6a4SAndroid Build Coastguard Worker struct Msi64BitWithoutMask { 304*bb4ee6a4SAndroid Build Coastguard Worker msg_upper: u32, 305*bb4ee6a4SAndroid Build Coastguard Worker msg_data: u16, 306*bb4ee6a4SAndroid Build Coastguard Worker msg_extended_data: u16, 307*bb4ee6a4SAndroid Build Coastguard Worker _padding: [u8; 8], 308*bb4ee6a4SAndroid Build Coastguard Worker } 309*bb4ee6a4SAndroid Build Coastguard Worker 310*bb4ee6a4SAndroid Build Coastguard Worker #[allow(dead_code)] 311*bb4ee6a4SAndroid Build Coastguard Worker #[repr(C)] 312*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Clone, Copy, Default, AsBytes, FromZeroes, FromBytes)] 313*bb4ee6a4SAndroid Build Coastguard Worker struct Msi64BitWithMask { 314*bb4ee6a4SAndroid Build Coastguard Worker msg_upper: u32, 315*bb4ee6a4SAndroid Build Coastguard Worker msg_data: u16, 316*bb4ee6a4SAndroid Build Coastguard Worker msg_extended_data: u16, 317*bb4ee6a4SAndroid Build Coastguard Worker mask_bits: u32, 318*bb4ee6a4SAndroid Build Coastguard Worker pending_bits: u32, 319*bb4ee6a4SAndroid Build Coastguard Worker } 320*bb4ee6a4SAndroid Build Coastguard Worker 321*bb4ee6a4SAndroid Build Coastguard Worker #[allow(dead_code)] 322*bb4ee6a4SAndroid Build Coastguard Worker #[repr(C)] 323*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Clone, Copy, AsBytes, FromZeroes, FromBytes)] 324*bb4ee6a4SAndroid Build Coastguard Worker union MsiVary { 325*bb4ee6a4SAndroid Build Coastguard Worker msi_32bit_without_mask: Msi32BitWithoutMask, 326*bb4ee6a4SAndroid Build Coastguard Worker msi_32bit_with_mask: Msi32BitWithMask, 327*bb4ee6a4SAndroid Build Coastguard Worker msi_64bit_without_mask: Msi64BitWithoutMask, 328*bb4ee6a4SAndroid Build Coastguard Worker msi_64bit_with_mask: Msi64BitWithMask, 329*bb4ee6a4SAndroid Build Coastguard Worker } 330*bb4ee6a4SAndroid Build Coastguard Worker 331*bb4ee6a4SAndroid Build Coastguard Worker #[allow(dead_code)] 332*bb4ee6a4SAndroid Build Coastguard Worker #[repr(C)] 333*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Clone, Copy, AsBytes, FromZeroes, FromBytes)] 334*bb4ee6a4SAndroid Build Coastguard Worker /// MSI Capability Structure 335*bb4ee6a4SAndroid Build Coastguard Worker pub struct MsiCap { 336*bb4ee6a4SAndroid Build Coastguard Worker // To make add_capability() happy 337*bb4ee6a4SAndroid Build Coastguard Worker _cap_vndr: u8, 338*bb4ee6a4SAndroid Build Coastguard Worker _cap_next: u8, 339*bb4ee6a4SAndroid Build Coastguard Worker // Message Control Register 340*bb4ee6a4SAndroid Build Coastguard Worker msg_ctl: MsiCtrl, 341*bb4ee6a4SAndroid Build Coastguard Worker // Message Address 342*bb4ee6a4SAndroid Build Coastguard Worker msg_addr: u32, 343*bb4ee6a4SAndroid Build Coastguard Worker // Msi Vary structure 344*bb4ee6a4SAndroid Build Coastguard Worker msi_vary: MsiVary, 345*bb4ee6a4SAndroid Build Coastguard Worker } 346*bb4ee6a4SAndroid Build Coastguard Worker 347*bb4ee6a4SAndroid Build Coastguard Worker impl PciCapability for MsiCap { bytes(&self) -> &[u8]348*bb4ee6a4SAndroid Build Coastguard Worker fn bytes(&self) -> &[u8] { 349*bb4ee6a4SAndroid Build Coastguard Worker self.as_bytes() 350*bb4ee6a4SAndroid Build Coastguard Worker } 351*bb4ee6a4SAndroid Build Coastguard Worker id(&self) -> PciCapabilityID352*bb4ee6a4SAndroid Build Coastguard Worker fn id(&self) -> PciCapabilityID { 353*bb4ee6a4SAndroid Build Coastguard Worker PciCapabilityID::MessageSignalledInterrupts 354*bb4ee6a4SAndroid Build Coastguard Worker } 355*bb4ee6a4SAndroid Build Coastguard Worker writable_bits(&self) -> Vec<u32>356*bb4ee6a4SAndroid Build Coastguard Worker fn writable_bits(&self) -> Vec<u32> { 357*bb4ee6a4SAndroid Build Coastguard Worker // Check spec for detail 358*bb4ee6a4SAndroid Build Coastguard Worker match ( 359*bb4ee6a4SAndroid Build Coastguard Worker self.msg_ctl.get_is_64bit(), 360*bb4ee6a4SAndroid Build Coastguard Worker self.msg_ctl.get_per_vector_masking(), 361*bb4ee6a4SAndroid Build Coastguard Worker ) { 362*bb4ee6a4SAndroid Build Coastguard Worker (0, 0) => vec![0x0471_0000, 0xffff_fffc, 0xffff_ffff], 363*bb4ee6a4SAndroid Build Coastguard Worker (0, 1) => vec![0x0471_0000, 0xffff_fffc, 0xffff_ffff, 0xffff_ffff], 364*bb4ee6a4SAndroid Build Coastguard Worker (1, 0) => vec![ 365*bb4ee6a4SAndroid Build Coastguard Worker 0x0471_0000, 366*bb4ee6a4SAndroid Build Coastguard Worker 0xffff_fffc, 367*bb4ee6a4SAndroid Build Coastguard Worker 0xffff_ffff, 368*bb4ee6a4SAndroid Build Coastguard Worker 0xffff_ffff, 369*bb4ee6a4SAndroid Build Coastguard Worker 0x0000_0000, 370*bb4ee6a4SAndroid Build Coastguard Worker ], 371*bb4ee6a4SAndroid Build Coastguard Worker (1, 1) => vec![ 372*bb4ee6a4SAndroid Build Coastguard Worker 0x0471_0000, 373*bb4ee6a4SAndroid Build Coastguard Worker 0xffff_fffc, 374*bb4ee6a4SAndroid Build Coastguard Worker 0xffff_ffff, 375*bb4ee6a4SAndroid Build Coastguard Worker 0xffff_ffff, 376*bb4ee6a4SAndroid Build Coastguard Worker 0xffff_ffff, 377*bb4ee6a4SAndroid Build Coastguard Worker 0x0000_0000, 378*bb4ee6a4SAndroid Build Coastguard Worker ], 379*bb4ee6a4SAndroid Build Coastguard Worker (_, _) => Vec::new(), 380*bb4ee6a4SAndroid Build Coastguard Worker } 381*bb4ee6a4SAndroid Build Coastguard Worker } 382*bb4ee6a4SAndroid Build Coastguard Worker } 383*bb4ee6a4SAndroid Build Coastguard Worker 384*bb4ee6a4SAndroid Build Coastguard Worker impl MsiCap { new(is_64bit: bool, mask_cap: bool) -> Self385*bb4ee6a4SAndroid Build Coastguard Worker pub fn new(is_64bit: bool, mask_cap: bool) -> Self { 386*bb4ee6a4SAndroid Build Coastguard Worker let mut msg_ctl = MsiCtrl::new(); 387*bb4ee6a4SAndroid Build Coastguard Worker if is_64bit { 388*bb4ee6a4SAndroid Build Coastguard Worker msg_ctl.set_is_64bit(1); 389*bb4ee6a4SAndroid Build Coastguard Worker } 390*bb4ee6a4SAndroid Build Coastguard Worker if mask_cap { 391*bb4ee6a4SAndroid Build Coastguard Worker msg_ctl.set_per_vector_masking(1); 392*bb4ee6a4SAndroid Build Coastguard Worker } 393*bb4ee6a4SAndroid Build Coastguard Worker let msi_vary = match (is_64bit, mask_cap) { 394*bb4ee6a4SAndroid Build Coastguard Worker (false, false) => MsiVary { 395*bb4ee6a4SAndroid Build Coastguard Worker msi_32bit_without_mask: Msi32BitWithoutMask::default(), 396*bb4ee6a4SAndroid Build Coastguard Worker }, 397*bb4ee6a4SAndroid Build Coastguard Worker (false, true) => MsiVary { 398*bb4ee6a4SAndroid Build Coastguard Worker msi_32bit_with_mask: Msi32BitWithMask::default(), 399*bb4ee6a4SAndroid Build Coastguard Worker }, 400*bb4ee6a4SAndroid Build Coastguard Worker (true, false) => MsiVary { 401*bb4ee6a4SAndroid Build Coastguard Worker msi_64bit_without_mask: Msi64BitWithoutMask::default(), 402*bb4ee6a4SAndroid Build Coastguard Worker }, 403*bb4ee6a4SAndroid Build Coastguard Worker (true, true) => MsiVary { 404*bb4ee6a4SAndroid Build Coastguard Worker msi_64bit_with_mask: Msi64BitWithMask::default(), 405*bb4ee6a4SAndroid Build Coastguard Worker }, 406*bb4ee6a4SAndroid Build Coastguard Worker }; 407*bb4ee6a4SAndroid Build Coastguard Worker MsiCap { 408*bb4ee6a4SAndroid Build Coastguard Worker _cap_vndr: 0, 409*bb4ee6a4SAndroid Build Coastguard Worker _cap_next: 0, 410*bb4ee6a4SAndroid Build Coastguard Worker msg_ctl, 411*bb4ee6a4SAndroid Build Coastguard Worker msg_addr: 0, 412*bb4ee6a4SAndroid Build Coastguard Worker msi_vary, 413*bb4ee6a4SAndroid Build Coastguard Worker } 414*bb4ee6a4SAndroid Build Coastguard Worker } 415*bb4ee6a4SAndroid Build Coastguard Worker } 416*bb4ee6a4SAndroid Build Coastguard Worker 417*bb4ee6a4SAndroid Build Coastguard Worker const MSI_CONFIG_READ_MASK: [u32; MSI_LENGTH_64BIT_WITH_MASK as usize / 4] = 418*bb4ee6a4SAndroid Build Coastguard Worker [0xffff_0000, 0, 0, 0, 0, 0]; 419*bb4ee6a4SAndroid Build Coastguard Worker 420*bb4ee6a4SAndroid Build Coastguard Worker impl PciCapConfig for MsiConfig { read_mask(&self) -> &'static [u32]421*bb4ee6a4SAndroid Build Coastguard Worker fn read_mask(&self) -> &'static [u32] { 422*bb4ee6a4SAndroid Build Coastguard Worker let num_regs = (self.len() + 3) / 4; 423*bb4ee6a4SAndroid Build Coastguard Worker &MSI_CONFIG_READ_MASK[0..(num_regs as usize)] 424*bb4ee6a4SAndroid Build Coastguard Worker } 425*bb4ee6a4SAndroid Build Coastguard Worker read_reg(&self, reg_idx: usize) -> u32426*bb4ee6a4SAndroid Build Coastguard Worker fn read_reg(&self, reg_idx: usize) -> u32 { 427*bb4ee6a4SAndroid Build Coastguard Worker self.read_msi_capability(reg_idx as u32 * 4, 0) 428*bb4ee6a4SAndroid Build Coastguard Worker } 429*bb4ee6a4SAndroid Build Coastguard Worker write_reg( &mut self, reg_idx: usize, offset: u64, data: &[u8], ) -> Option<Box<dyn PciCapConfigWriteResult>>430*bb4ee6a4SAndroid Build Coastguard Worker fn write_reg( 431*bb4ee6a4SAndroid Build Coastguard Worker &mut self, 432*bb4ee6a4SAndroid Build Coastguard Worker reg_idx: usize, 433*bb4ee6a4SAndroid Build Coastguard Worker offset: u64, 434*bb4ee6a4SAndroid Build Coastguard Worker data: &[u8], 435*bb4ee6a4SAndroid Build Coastguard Worker ) -> Option<Box<dyn PciCapConfigWriteResult>> { 436*bb4ee6a4SAndroid Build Coastguard Worker let offset = reg_idx as u32 * 4 + offset as u32; 437*bb4ee6a4SAndroid Build Coastguard Worker self.write_msi_capability(offset, data); 438*bb4ee6a4SAndroid Build Coastguard Worker None 439*bb4ee6a4SAndroid Build Coastguard Worker } 440*bb4ee6a4SAndroid Build Coastguard Worker } 441