• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, &regs)));
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(&regs, 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