1 // Copyright 2019 The ChromiumOS Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 use std::mem; 6 use std::sync::atomic::AtomicBool; 7 use std::sync::atomic::Ordering; 8 use std::sync::Arc; 9 10 use base::error; 11 use base::AsRawDescriptor; 12 use base::RawDescriptor; 13 use resources::Alloc; 14 use resources::AllocOptions; 15 use resources::SystemAllocator; 16 use vm_memory::GuestMemory; 17 18 use crate::pci::BarRange; 19 use crate::pci::PciAddress; 20 use crate::pci::PciBarConfiguration; 21 use crate::pci::PciBarPrefetchable; 22 use crate::pci::PciBarRegionType; 23 use crate::pci::PciClassCode; 24 use crate::pci::PciConfiguration; 25 use crate::pci::PciDevice; 26 use crate::pci::PciDeviceError; 27 use crate::pci::PciHeaderType; 28 use crate::pci::PciInterruptPin; 29 use crate::pci::PciProgrammingInterface; 30 use crate::pci::PciSerialBusSubClass; 31 use crate::register_space::Register; 32 use crate::register_space::RegisterSpace; 33 use crate::usb::host_backend::host_backend_device_provider::HostBackendDeviceProvider; 34 use crate::usb::xhci::xhci::Xhci; 35 use crate::usb::xhci::xhci_backend_device_provider::XhciBackendDeviceProvider; 36 use crate::usb::xhci::xhci_regs::init_xhci_mmio_space_and_regs; 37 use crate::usb::xhci::xhci_regs::XhciRegs; 38 use crate::utils::FailHandle; 39 use crate::IrqLevelEvent; 40 use crate::Suspendable; 41 42 const XHCI_BAR0_SIZE: u64 = 0x10000; 43 44 #[derive(Clone, Copy)] 45 enum UsbControllerProgrammingInterface { 46 Usb3HostController = 0x30, 47 } 48 49 impl PciProgrammingInterface for UsbControllerProgrammingInterface { get_register_value(&self) -> u850 fn get_register_value(&self) -> u8 { 51 *self as u8 52 } 53 } 54 55 /// Use this handle to fail xhci controller. 56 pub struct XhciFailHandle { 57 usbcmd: Register<u32>, 58 usbsts: Register<u32>, 59 xhci_failed: AtomicBool, 60 } 61 62 impl XhciFailHandle { new(regs: &XhciRegs) -> XhciFailHandle63 pub fn new(regs: &XhciRegs) -> XhciFailHandle { 64 XhciFailHandle { 65 usbcmd: regs.usbcmd.clone(), 66 usbsts: regs.usbsts.clone(), 67 xhci_failed: AtomicBool::new(false), 68 } 69 } 70 } 71 72 impl FailHandle for XhciFailHandle { 73 /// Fail this controller. Will set related registers and flip failed bool. fail(&self)74 fn fail(&self) { 75 // set run/stop to stop. 76 const USBCMD_STOPPED: u32 = 0; 77 // Set host system error bit. 78 const USBSTS_HSE: u32 = 1 << 2; 79 self.usbcmd.set_value(USBCMD_STOPPED); 80 self.usbsts.set_value(USBSTS_HSE); 81 82 self.xhci_failed.store(true, Ordering::SeqCst); 83 error!("xhci controller stopped working"); 84 } 85 86 /// Returns true if xhci is already failed. failed(&self) -> bool87 fn failed(&self) -> bool { 88 self.xhci_failed.load(Ordering::SeqCst) 89 } 90 } 91 92 // Xhci controller should be created with backend device provider. Then irq should be assigned 93 // before initialized. We are not making `failed` as a state here to optimize performance. Cause we 94 // need to set failed in other threads. 95 enum XhciControllerState { 96 Unknown, 97 Created { 98 device_provider: HostBackendDeviceProvider, 99 }, 100 IrqAssigned { 101 device_provider: HostBackendDeviceProvider, 102 irq_evt: IrqLevelEvent, 103 }, 104 Initialized { 105 mmio: RegisterSpace, 106 // Xhci init could fail. 107 #[allow(dead_code)] 108 xhci: Option<Arc<Xhci>>, 109 fail_handle: Arc<dyn FailHandle>, 110 }, 111 } 112 113 /// xHCI PCI interface implementation. 114 pub struct XhciController { 115 config_regs: PciConfiguration, 116 pci_address: Option<PciAddress>, 117 mem: GuestMemory, 118 state: XhciControllerState, 119 } 120 121 impl XhciController { 122 /// Create new xhci controller. new(mem: GuestMemory, usb_provider: HostBackendDeviceProvider) -> Self123 pub fn new(mem: GuestMemory, usb_provider: HostBackendDeviceProvider) -> Self { 124 let config_regs = PciConfiguration::new( 125 0x01b73, // fresco logic, (google = 0x1ae0) 126 0x1000, // fresco logic pdk. This chip has broken msi. See kernel xhci-pci.c 127 PciClassCode::SerialBusController, 128 &PciSerialBusSubClass::Usb, 129 Some(&UsbControllerProgrammingInterface::Usb3HostController), 130 PciHeaderType::Device, 131 0, 132 0, 133 0, 134 ); 135 XhciController { 136 config_regs, 137 pci_address: None, 138 mem, 139 state: XhciControllerState::Created { 140 device_provider: usb_provider, 141 }, 142 } 143 } 144 145 /// Init xhci controller when it's forked. init_when_forked(&mut self)146 pub fn init_when_forked(&mut self) { 147 match mem::replace(&mut self.state, XhciControllerState::Unknown) { 148 XhciControllerState::IrqAssigned { 149 device_provider, 150 irq_evt, 151 } => { 152 let (mmio, regs) = init_xhci_mmio_space_and_regs(); 153 let fail_handle: Arc<dyn FailHandle> = Arc::new(XhciFailHandle::new(®s)); 154 let xhci = match Xhci::new( 155 fail_handle.clone(), 156 self.mem.clone(), 157 device_provider, 158 irq_evt, 159 regs, 160 ) { 161 Ok(xhci) => Some(xhci), 162 Err(_) => { 163 error!("fail to init xhci"); 164 fail_handle.fail(); 165 return; 166 } 167 }; 168 169 self.state = XhciControllerState::Initialized { 170 mmio, 171 xhci, 172 fail_handle, 173 } 174 } 175 _ => { 176 error!("xhci controller is in a wrong state"); 177 } 178 } 179 } 180 } 181 182 impl PciDevice for XhciController { debug_label(&self) -> String183 fn debug_label(&self) -> String { 184 "xhci controller".to_owned() 185 } 186 allocate_address( &mut self, resources: &mut SystemAllocator, ) -> Result<PciAddress, PciDeviceError>187 fn allocate_address( 188 &mut self, 189 resources: &mut SystemAllocator, 190 ) -> Result<PciAddress, PciDeviceError> { 191 if self.pci_address.is_none() { 192 self.pci_address = match resources.allocate_pci(0, self.debug_label()) { 193 Some(Alloc::PciBar { 194 bus, 195 dev, 196 func, 197 bar: _, 198 }) => Some(PciAddress { bus, dev, func }), 199 _ => None, 200 } 201 } 202 self.pci_address.ok_or(PciDeviceError::PciAllocationFailed) 203 } 204 keep_rds(&self) -> Vec<RawDescriptor>205 fn keep_rds(&self) -> Vec<RawDescriptor> { 206 match &self.state { 207 XhciControllerState::Created { device_provider } => device_provider.keep_rds(), 208 XhciControllerState::IrqAssigned { 209 device_provider, 210 irq_evt, 211 } => { 212 let mut keep_rds = device_provider.keep_rds(); 213 keep_rds.push(irq_evt.get_trigger().as_raw_descriptor()); 214 keep_rds.push(irq_evt.get_resample().as_raw_descriptor()); 215 keep_rds 216 } 217 _ => { 218 error!("xhci controller is in a wrong state"); 219 vec![] 220 } 221 } 222 } 223 assign_irq(&mut self, irq_evt: IrqLevelEvent, pin: PciInterruptPin, irq_num: u32)224 fn assign_irq(&mut self, irq_evt: IrqLevelEvent, pin: PciInterruptPin, irq_num: u32) { 225 match mem::replace(&mut self.state, XhciControllerState::Unknown) { 226 XhciControllerState::Created { device_provider } => { 227 self.config_regs.set_irq(irq_num as u8, pin); 228 self.state = XhciControllerState::IrqAssigned { 229 device_provider, 230 irq_evt, 231 } 232 } 233 _ => { 234 error!("xhci controller is in a wrong state"); 235 } 236 } 237 } 238 allocate_io_bars( &mut self, resources: &mut SystemAllocator, ) -> std::result::Result<Vec<BarRange>, PciDeviceError>239 fn allocate_io_bars( 240 &mut self, 241 resources: &mut SystemAllocator, 242 ) -> std::result::Result<Vec<BarRange>, PciDeviceError> { 243 let address = self 244 .pci_address 245 .expect("assign_address must be called prior to allocate_io_bars"); 246 // xHCI spec 5.2.1. 247 let bar0_addr = resources 248 .allocate_mmio( 249 XHCI_BAR0_SIZE, 250 Alloc::PciBar { 251 bus: address.bus, 252 dev: address.dev, 253 func: address.func, 254 bar: 0, 255 }, 256 "xhci_bar0".to_string(), 257 AllocOptions::new() 258 .max_address(u32::MAX.into()) 259 .align(XHCI_BAR0_SIZE), 260 ) 261 .map_err(|e| PciDeviceError::IoAllocationFailed(XHCI_BAR0_SIZE, e))?; 262 let bar0_config = PciBarConfiguration::new( 263 0, 264 XHCI_BAR0_SIZE, 265 PciBarRegionType::Memory32BitRegion, 266 PciBarPrefetchable::NotPrefetchable, 267 ) 268 .set_address(bar0_addr); 269 self.config_regs 270 .add_pci_bar(bar0_config) 271 .map_err(|e| PciDeviceError::IoRegistrationFailed(bar0_addr, e))?; 272 Ok(vec![BarRange { 273 addr: bar0_addr, 274 size: XHCI_BAR0_SIZE, 275 prefetchable: false, 276 }]) 277 } 278 get_bar_configuration(&self, bar_num: usize) -> Option<PciBarConfiguration>279 fn get_bar_configuration(&self, bar_num: usize) -> Option<PciBarConfiguration> { 280 self.config_regs.get_bar_configuration(bar_num) 281 } 282 read_config_register(&self, reg_idx: usize) -> u32283 fn read_config_register(&self, reg_idx: usize) -> u32 { 284 self.config_regs.read_reg(reg_idx) 285 } 286 write_config_register(&mut self, reg_idx: usize, offset: u64, data: &[u8])287 fn write_config_register(&mut self, reg_idx: usize, offset: u64, data: &[u8]) { 288 self.config_regs.write_reg(reg_idx, offset, data) 289 } 290 read_bar(&mut self, addr: u64, data: &mut [u8])291 fn read_bar(&mut self, addr: u64, data: &mut [u8]) { 292 let bar0 = self.config_regs.get_bar_addr(0); 293 if addr < bar0 || addr > bar0 + XHCI_BAR0_SIZE { 294 return; 295 } 296 match &self.state { 297 XhciControllerState::Initialized { mmio, .. } => { 298 // Read bar would still work even if it's already failed. 299 mmio.read(addr - bar0, data); 300 } 301 _ => { 302 error!("xhci controller is in a wrong state"); 303 } 304 } 305 } 306 write_bar(&mut self, addr: u64, data: &[u8])307 fn write_bar(&mut self, addr: u64, data: &[u8]) { 308 let bar0 = self.config_regs.get_bar_addr(0); 309 if addr < bar0 || addr > bar0 + XHCI_BAR0_SIZE { 310 return; 311 } 312 match &self.state { 313 XhciControllerState::Initialized { 314 mmio, fail_handle, .. 315 } => { 316 if !fail_handle.failed() { 317 mmio.write(addr - bar0, data); 318 } 319 } 320 _ => { 321 error!("xhci controller is in a wrong state"); 322 } 323 } 324 } 325 on_device_sandboxed(&mut self)326 fn on_device_sandboxed(&mut self) { 327 self.init_when_forked(); 328 } 329 } 330 331 impl Suspendable for XhciController {} 332