1 // Copyright 2019 The Chromium OS Authors. All rights reserved. 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 super::command_ring_controller::{CommandRingController, CommandRingControllerError}; 6 use super::device_slot::{DeviceSlots, Error as DeviceSlotError}; 7 use super::interrupter::{Error as InterrupterError, Interrupter}; 8 use super::intr_resample_handler::IntrResampleHandler; 9 use super::ring_buffer_stop_cb::RingBufferStopCallback; 10 use super::usb_hub::UsbHub; 11 use super::xhci_backend_device_provider::XhciBackendDeviceProvider; 12 use super::xhci_regs::*; 13 use crate::usb::host_backend::{ 14 error::Error as HostBackendProviderError, 15 host_backend_device_provider::HostBackendDeviceProvider, 16 }; 17 use crate::utils::{Error as UtilsError, EventLoop, FailHandle}; 18 use crate::IrqLevelEvent; 19 use base::error; 20 use remain::sorted; 21 use std::sync::Arc; 22 use std::thread; 23 use sync::Mutex; 24 use thiserror::Error; 25 use vm_memory::{GuestAddress, GuestMemory}; 26 27 #[sorted] 28 #[derive(Error, Debug)] 29 pub enum Error { 30 #[error("failed to clone irq event: {0}")] 31 CloneIrqEvent(base::Error), 32 #[error("failed to clone resample event: {0}")] 33 CloneResampleEvent(base::Error), 34 #[error("failed to create command ring controller: {0}")] 35 CreateCommandRingController(CommandRingControllerError), 36 #[error("failed to enable interrupter: {0}")] 37 EnableInterrupter(InterrupterError), 38 #[error("failed to get device slot: {0}")] 39 GetDeviceSlot(u8), 40 #[error("failed to reset port")] 41 ResetPort, 42 #[error("failed to ring doorbell: {0}")] 43 RingDoorbell(DeviceSlotError), 44 #[error("failed to send interrupt: {0}")] 45 SendInterrupt(InterrupterError), 46 #[error("failed to set event handler busy: {0}")] 47 SetEventHandlerBusy(InterrupterError), 48 #[error("failed to set interrupter moderation: {0}")] 49 SetModeration(InterrupterError), 50 #[error("failed to setup event ring: {0}")] 51 SetupEventRing(InterrupterError), 52 #[error("failed to start event loop: {0}")] 53 StartEventLoop(UtilsError), 54 #[error("failed to start backend provider: {0}")] 55 StartProvider(HostBackendProviderError), 56 #[error("failed to start resample handler")] 57 StartResampleHandler, 58 } 59 60 type Result<T> = std::result::Result<T, Error>; 61 62 /// xHCI controller implementation. 63 pub struct Xhci { 64 fail_handle: Arc<dyn FailHandle>, 65 regs: XhciRegs, 66 interrupter: Arc<Mutex<Interrupter>>, 67 command_ring_controller: Arc<CommandRingController>, 68 device_slots: DeviceSlots, 69 event_loop: Arc<EventLoop>, 70 event_loop_join_handle: Option<thread::JoinHandle<()>>, 71 // resample handler and device provider only lives on EventLoop to handle corresponding events. 72 // By design, event loop only hold weak reference. We need to keep a strong reference here to 73 // keep it alive. 74 #[allow(dead_code)] 75 intr_resample_handler: Arc<IntrResampleHandler>, 76 #[allow(dead_code)] 77 device_provider: HostBackendDeviceProvider, 78 } 79 80 impl Xhci { 81 /// Create a new xHCI controller. new( fail_handle: Arc<dyn FailHandle>, mem: GuestMemory, device_provider: HostBackendDeviceProvider, interrupt_evt: IrqLevelEvent, regs: XhciRegs, ) -> Result<Arc<Self>>82 pub fn new( 83 fail_handle: Arc<dyn FailHandle>, 84 mem: GuestMemory, 85 device_provider: HostBackendDeviceProvider, 86 interrupt_evt: IrqLevelEvent, 87 regs: XhciRegs, 88 ) -> Result<Arc<Self>> { 89 let (event_loop, join_handle) = 90 EventLoop::start("xhci".to_string(), Some(fail_handle.clone())) 91 .map_err(Error::StartEventLoop)?; 92 let irq_evt = interrupt_evt 93 .get_trigger() 94 .try_clone() 95 .map_err(Error::CloneIrqEvent)?; 96 let interrupter = Arc::new(Mutex::new(Interrupter::new(mem.clone(), irq_evt, ®s))); 97 let event_loop = Arc::new(event_loop); 98 let irq_resample_evt = interrupt_evt 99 .get_resample() 100 .try_clone() 101 .map_err(Error::CloneResampleEvent)?; 102 let intr_resample_handler = 103 IntrResampleHandler::start(&event_loop, interrupter.clone(), irq_resample_evt) 104 .ok_or(Error::StartResampleHandler)?; 105 let hub = Arc::new(UsbHub::new(®s, interrupter.clone())); 106 107 let mut device_provider = device_provider; 108 device_provider 109 .start(fail_handle.clone(), event_loop.clone(), hub.clone()) 110 .map_err(Error::StartProvider)?; 111 112 let device_slots = DeviceSlots::new( 113 fail_handle.clone(), 114 regs.dcbaap.clone(), 115 hub, 116 interrupter.clone(), 117 event_loop.clone(), 118 mem.clone(), 119 ); 120 let command_ring_controller = CommandRingController::new( 121 mem, 122 event_loop.clone(), 123 device_slots.clone(), 124 interrupter.clone(), 125 ) 126 .map_err(Error::CreateCommandRingController)?; 127 let xhci = Arc::new(Xhci { 128 fail_handle, 129 regs, 130 intr_resample_handler, 131 interrupter, 132 command_ring_controller, 133 device_slots, 134 device_provider, 135 event_loop, 136 event_loop_join_handle: Some(join_handle), 137 }); 138 Self::init_reg_callbacks(&xhci); 139 Ok(xhci) 140 } 141 init_reg_callbacks(xhci: &Arc<Xhci>)142 fn init_reg_callbacks(xhci: &Arc<Xhci>) { 143 // All the callbacks will hold a weak reference to avoid memory leak. Thos weak upgrade 144 // should never fail. 145 let xhci_weak = Arc::downgrade(xhci); 146 xhci.regs.usbcmd.set_write_cb(move |val: u32| { 147 // All the weak reference upgrade should never fail. xhci hold reference to the 148 // registers, callback won't be invoked if xhci is gone. 149 let xhci = xhci_weak.upgrade().unwrap(); 150 let r = xhci.usbcmd_callback(val); 151 xhci.handle_register_callback_result(r, 0) 152 }); 153 154 let xhci_weak = Arc::downgrade(xhci); 155 xhci.regs.crcr.set_write_cb(move |val: u64| { 156 let xhci = xhci_weak.upgrade().unwrap(); 157 xhci.crcr_callback(val) 158 }); 159 160 for i in 0..xhci.regs.portsc.len() { 161 let xhci_weak = Arc::downgrade(xhci); 162 xhci.regs.portsc[i].set_write_cb(move |val: u32| { 163 let xhci = xhci_weak.upgrade().unwrap(); 164 let r = xhci.portsc_callback(i as u32, val); 165 xhci.handle_register_callback_result(r, 0) 166 }); 167 } 168 169 for i in 0..xhci.regs.doorbells.len() { 170 let xhci_weak = Arc::downgrade(xhci); 171 xhci.regs.doorbells[i].set_write_cb(move |val: u32| { 172 let xhci = xhci_weak.upgrade().unwrap(); 173 let r = xhci.doorbell_callback(i as u32, val); 174 xhci.handle_register_callback_result(r, ()); 175 val 176 }); 177 } 178 179 let xhci_weak = Arc::downgrade(xhci); 180 xhci.regs.iman.set_write_cb(move |val: u32| { 181 let xhci = xhci_weak.upgrade().unwrap(); 182 let r = xhci.iman_callback(val); 183 xhci.handle_register_callback_result(r, ()); 184 val 185 }); 186 187 let xhci_weak = Arc::downgrade(xhci); 188 xhci.regs.imod.set_write_cb(move |val: u32| { 189 let xhci = xhci_weak.upgrade().unwrap(); 190 let r = xhci.imod_callback(val); 191 xhci.handle_register_callback_result(r, ()); 192 val 193 }); 194 195 let xhci_weak = Arc::downgrade(xhci); 196 xhci.regs.erstsz.set_write_cb(move |val: u32| { 197 let xhci = xhci_weak.upgrade().unwrap(); 198 let r = xhci.erstsz_callback(val); 199 xhci.handle_register_callback_result(r, ()); 200 val 201 }); 202 203 let xhci_weak = Arc::downgrade(xhci); 204 xhci.regs.erstba.set_write_cb(move |val: u64| { 205 let xhci = xhci_weak.upgrade().unwrap(); 206 let r = xhci.erstba_callback(val); 207 xhci.handle_register_callback_result(r, ()); 208 val 209 }); 210 211 let xhci_weak = Arc::downgrade(xhci); 212 xhci.regs.erdp.set_write_cb(move |val: u64| { 213 let xhci = xhci_weak.upgrade().unwrap(); 214 let r = xhci.erdp_callback(val); 215 xhci.handle_register_callback_result(r, ()); 216 val 217 }); 218 } 219 handle_register_callback_result<T>(&self, r: Result<T>, t: T) -> T220 fn handle_register_callback_result<T>(&self, r: Result<T>, t: T) -> T { 221 match r { 222 Ok(v) => v, 223 Err(e) => { 224 error!("xhci controller failed: {}", e); 225 self.fail_handle.fail(); 226 t 227 } 228 } 229 } 230 231 // Callback for usbcmd register write. usbcmd_callback(&self, value: u32) -> Result<u32>232 fn usbcmd_callback(&self, value: u32) -> Result<u32> { 233 if (value & USB_CMD_RESET) > 0 { 234 usb_debug!("xhci_controller: reset controller"); 235 self.reset(); 236 return Ok(value & (!USB_CMD_RESET)); 237 } 238 239 if (value & USB_CMD_RUNSTOP) > 0 { 240 usb_debug!("xhci_controller: clear halt bits"); 241 self.regs.usbsts.clear_bits(USB_STS_HALTED); 242 } else { 243 usb_debug!("xhci_controller: halt device"); 244 self.halt(); 245 self.regs.crcr.clear_bits(CRCR_COMMAND_RING_RUNNING); 246 } 247 248 // Enable interrupter if needed. 249 let enabled = (value & USB_CMD_INTERRUPTER_ENABLE) > 0 250 && (self.regs.iman.get_value() & IMAN_INTERRUPT_ENABLE) > 0; 251 usb_debug!("xhci_controller: interrupter enable?: {}", enabled); 252 self.interrupter 253 .lock() 254 .set_enabled(enabled) 255 .map_err(Error::EnableInterrupter)?; 256 Ok(value) 257 } 258 259 // Callback for crcr register write. crcr_callback(&self, value: u64) -> u64260 fn crcr_callback(&self, value: u64) -> u64 { 261 usb_debug!("xhci_controller: write to crcr {:x}", value); 262 if (self.regs.crcr.get_value() & CRCR_COMMAND_RING_RUNNING) == 0 { 263 self.command_ring_controller 264 .set_dequeue_pointer(GuestAddress(value & CRCR_COMMAND_RING_POINTER)); 265 self.command_ring_controller 266 .set_consumer_cycle_state((value & CRCR_RING_CYCLE_STATE) > 0); 267 value 268 } else { 269 error!("Write to crcr while command ring is running"); 270 self.regs.crcr.get_value() 271 } 272 } 273 274 // Callback for portsc register write. portsc_callback(&self, index: u32, value: u32) -> Result<u32>275 fn portsc_callback(&self, index: u32, value: u32) -> Result<u32> { 276 let mut value = value; 277 usb_debug!( 278 "xhci_controller: write to portsc index {} value {:x}", 279 index, 280 value 281 ); 282 let port_id = (index + 1) as u8; 283 // xHCI spec 4.19.5. Note: we might want to change this logic if we support USB 3.0. 284 if (value & PORTSC_PORT_RESET) > 0 || (value & PORTSC_WARM_PORT_RESET) > 0 { 285 self.device_slots 286 .reset_port(port_id) 287 .map_err(|_| Error::ResetPort)?; 288 value &= !PORTSC_PORT_LINK_STATE_MASK; 289 value &= !PORTSC_PORT_RESET; 290 value |= PORTSC_PORT_ENABLED; 291 value |= PORTSC_PORT_RESET_CHANGE; 292 self.interrupter 293 .lock() 294 .send_port_status_change_trb(port_id) 295 .map_err(Error::SendInterrupt)?; 296 } 297 Ok(value) 298 } 299 300 // Callback for doorbell register write. doorbell_callback(&self, index: u32, value: u32) -> Result<()>301 fn doorbell_callback(&self, index: u32, value: u32) -> Result<()> { 302 usb_debug!( 303 "xhci_controller: write to doorbell index {} value {:x}", 304 index, 305 value 306 ); 307 let target = (value & DOORBELL_TARGET) as u8; 308 let stream_id: u16 = (value >> DOORBELL_STREAM_ID_OFFSET) as u16; 309 if (self.regs.usbcmd.get_value() & USB_CMD_RUNSTOP) > 0 { 310 // First doorbell is for command ring. 311 if index == 0 { 312 if target != 0 || stream_id != 0 { 313 return Ok(()); 314 } 315 usb_debug!("doorbell to command ring"); 316 self.regs.crcr.set_bits(CRCR_COMMAND_RING_RUNNING); 317 self.command_ring_controller.start(); 318 } else { 319 usb_debug!("doorbell to device slot"); 320 self.device_slots 321 .slot(index as u8) 322 .ok_or(Error::GetDeviceSlot(index as u8))? 323 .ring_doorbell(target, stream_id) 324 .map_err(Error::RingDoorbell)?; 325 } 326 } 327 Ok(()) 328 } 329 330 // Callback for iman register write. iman_callback(&self, value: u32) -> Result<()>331 fn iman_callback(&self, value: u32) -> Result<()> { 332 usb_debug!("xhci_controller: write to iman {:x}", value); 333 let enabled = ((value & IMAN_INTERRUPT_ENABLE) > 0) 334 && ((self.regs.usbcmd.get_value() & USB_CMD_INTERRUPTER_ENABLE) > 0); 335 self.interrupter 336 .lock() 337 .set_enabled(enabled) 338 .map_err(Error::EnableInterrupter) 339 } 340 341 // Callback for imod register write. imod_callback(&self, value: u32) -> Result<()>342 fn imod_callback(&self, value: u32) -> Result<()> { 343 usb_debug!("xhci_controller: write to imod {:x}", value); 344 self.interrupter 345 .lock() 346 .set_moderation( 347 (value & IMOD_INTERRUPT_MODERATION_INTERVAL) as u16, 348 (value >> IMOD_INTERRUPT_MODERATION_COUNTER_OFFSET) as u16, 349 ) 350 .map_err(Error::SetModeration) 351 } 352 353 // Callback for erstsz register write. erstsz_callback(&self, value: u32) -> Result<()>354 fn erstsz_callback(&self, value: u32) -> Result<()> { 355 usb_debug!("xhci_controller: write to erstz {:x}", value); 356 self.interrupter 357 .lock() 358 .set_event_ring_seg_table_size((value & ERSTSZ_SEGMENT_TABLE_SIZE) as u16) 359 .map_err(Error::SetupEventRing) 360 } 361 362 // Callback for erstba register write. erstba_callback(&self, value: u64) -> Result<()>363 fn erstba_callback(&self, value: u64) -> Result<()> { 364 usb_debug!("xhci_controller: write to erstba {:x}", value); 365 self.interrupter 366 .lock() 367 .set_event_ring_seg_table_base_addr(GuestAddress( 368 value & ERSTBA_SEGMENT_TABLE_BASE_ADDRESS, 369 )) 370 .map_err(Error::SetupEventRing) 371 } 372 373 // Callback for erdp register write. erdp_callback(&self, value: u64) -> Result<()>374 fn erdp_callback(&self, value: u64) -> Result<()> { 375 usb_debug!("xhci_controller: write to erdp {:x}", value); 376 let mut interrupter = self.interrupter.lock(); 377 interrupter 378 .set_event_ring_dequeue_pointer(GuestAddress(value & ERDP_EVENT_RING_DEQUEUE_POINTER)) 379 .map_err(Error::SetupEventRing)?; 380 interrupter 381 .set_event_handler_busy((value & ERDP_EVENT_HANDLER_BUSY) > 0) 382 .map_err(Error::SetEventHandlerBusy) 383 } 384 reset(&self)385 fn reset(&self) { 386 self.regs.usbsts.set_bits(USB_STS_CONTROLLER_NOT_READY); 387 let usbsts = self.regs.usbsts.clone(); 388 self.device_slots.stop_all_and_reset(move || { 389 usbsts.clear_bits(USB_STS_CONTROLLER_NOT_READY); 390 }); 391 } 392 halt(&self)393 fn halt(&self) { 394 let usbsts = self.regs.usbsts.clone(); 395 self.device_slots 396 .stop_all(RingBufferStopCallback::new(move || { 397 usbsts.set_bits(USB_STS_HALTED); 398 })); 399 } 400 } 401 402 impl Drop for Xhci { drop(&mut self)403 fn drop(&mut self) { 404 self.event_loop.stop(); 405 if let Some(join_handle) = self.event_loop_join_handle.take() { 406 let _ = join_handle.join(); 407 } 408 } 409 } 410