1use std::mem;
6use std::sync::atomic::AtomicBool;
7use std::sync::atomic::Ordering;
8use std::sync::Arc;
9
10use base::error;
11use base::AsRawDescriptor;
12use base::RawDescriptor;
13use base::SharedMemory;
14use resources::Alloc;
15use resources::AllocOptions;
16use resources::SystemAllocator;
17use vm_memory::GuestMemory;
18
19use crate::pci::BarRange;
20use crate::pci::PciAddress;
21use crate::pci::PciBarConfiguration;
22use crate::pci::PciBarPrefetchable;
23use crate::pci::PciBarRegionType;
24use crate::pci::PciClassCode;
25use crate::pci::PciConfiguration;
26use crate::pci::PciDevice;
27use crate::pci::PciDeviceError;
28use crate::pci::PciHeaderType;
29use crate::pci::PciInterruptPin;
30use crate::pci::PciProgrammingInterface;
31use crate::pci::PciSerialBusSubClass;
32use crate::register_space::Register;
33use crate::register_space::RegisterSpace;
34use crate::usb::xhci::xhci_backend_device_provider::XhciBackendDeviceProvider;
35use crate::usb::xhci::xhci_regs::init_xhci_mmio_space_and_regs;
36use crate::usb::xhci::xhci_regs::XhciRegs;
37use crate::usb::xhci::Xhci;
38use crate::utils::FailHandle;
39use crate::IrqLevelEvent;
40use crate::Suspendable;
41
42const XHCI_BAR0_SIZE: u64 = 0x10000;
43
44#[derive(Clone, Copy)]
45enum UsbControllerProgrammingInterface {
46 Usb3HostController = 0x30,
47}
48
49impl PciProgrammingInterface for UsbControllerProgrammingInterface {
50 fn get_register_value(&self) -> u8 {
51 *self as u8
52 }
53}
54
55pub struct XhciFailHandle {
57 usbcmd: Register<u32>,
58 usbsts: Register<u32>,
59 xhci_failed: AtomicBool,
60}
61
62impl XhciFailHandle {
63 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
72impl FailHandle for XhciFailHandle {
73 fn fail(&self) {
75 const USBCMD_STOPPED: u32 = 0;
77 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 fn failed(&self) -> bool {
88 self.xhci_failed.load(Ordering::SeqCst)
89 }
90}
91
92enum XhciControllerState {
96 Unknown,
97 Created {
98 device_provider: Box<dyn XhciBackendDeviceProvider>,
99 },
100 IrqAssigned {
101 device_provider: Box<dyn XhciBackendDeviceProvider>,
102 irq_evt: IrqLevelEvent,
103 },
104 Initialized {
105 mmio: RegisterSpace,
106 #[allow(dead_code)]
108 xhci: Option<Arc<Xhci>>,
109 fail_handle: Arc<dyn FailHandle>,
110 },
111}
112
113pub struct XhciController {
115 config_regs: PciConfiguration,
116 pci_address: Option<PciAddress>,
117 mem: GuestMemory,
118 state: XhciControllerState,
119 initial_usb_devices: Vec<std::fs::File>,
120}
121
122impl XhciController {
123 pub fn new(mem: GuestMemory, usb_provider: Box<dyn XhciBackendDeviceProvider>) -> Self {
125 let config_regs = PciConfiguration::new(
126 0x01b73, 0x1400, PciClassCode::SerialBusController,
129 &PciSerialBusSubClass::Usb,
130 Some(&UsbControllerProgrammingInterface::Usb3HostController),
131 PciHeaderType::Device,
132 0,
133 0,
134 0,
135 );
136 XhciController {
137 config_regs,
138 pci_address: None,
139 mem,
140 state: XhciControllerState::Created {
141 device_provider: usb_provider,
142 },
143 initial_usb_devices: Vec::new(),
144 }
145 }
146
147 pub fn set_initial_usb_devices(&mut self, devices: Vec<std::fs::File>) {
149 self.initial_usb_devices = devices;
150 }
151
152 pub fn init_when_forked(&mut self) {
154 match mem::replace(&mut self.state, XhciControllerState::Unknown) {
155 XhciControllerState::IrqAssigned {
156 device_provider,
157 irq_evt,
158 } => {
159 let (mmio, regs) = init_xhci_mmio_space_and_regs();
160 let fail_handle: Arc<dyn FailHandle> = Arc::new(XhciFailHandle::new(®s));
161 let initial_devices = mem::take(&mut self.initial_usb_devices);
162 let xhci = match Xhci::new_with_devices(
163 fail_handle.clone(),
164 self.mem.clone(),
165 device_provider,
166 irq_evt,
167 regs,
168 initial_devices,
169 ) {
170 Ok(xhci) => Some(xhci),
171 Err(_) => {
172 error!("fail to init xhci");
173 fail_handle.fail();
174 return;
175 }
176 };
177
178 self.state = XhciControllerState::Initialized {
179 mmio,
180 xhci,
181 fail_handle,
182 }
183 }
184 _ => {
185 error!("xhci controller is in a wrong state");
186 }
187 }
188 }
189}
190
191impl PciDevice for XhciController {
192 fn debug_label(&self) -> String {
193 "xhci controller".to_owned()
194 }
195
196 fn allocate_address(
197 &mut self,
198 resources: &mut SystemAllocator,
199 ) -> Result<PciAddress, PciDeviceError> {
200 if self.pci_address.is_none() {
201 self.pci_address = resources.allocate_pci(0, self.debug_label());
202 }
203 self.pci_address.ok_or(PciDeviceError::PciAllocationFailed)
204 }
205
206 fn keep_rds(&self) -> Vec<RawDescriptor> {
207 match &self.state {
208 XhciControllerState::Created { device_provider } => device_provider.keep_rds(),
209 XhciControllerState::IrqAssigned {
210 device_provider,
211 irq_evt,
212 } => {
213 let mut keep_rds = device_provider.keep_rds();
214 keep_rds.push(irq_evt.get_trigger().as_raw_descriptor());
215 keep_rds.push(irq_evt.get_resample().as_raw_descriptor());
216 keep_rds
217 }
218 _ => {
219 error!("xhci controller is in a wrong state");
220 vec![]
221 }
222 }
223 }
224
225 fn assign_irq(&mut self, irq_evt: IrqLevelEvent, pin: PciInterruptPin, irq_num: u32) {
226 match mem::replace(&mut self.state, XhciControllerState::Unknown) {
227 XhciControllerState::Created { device_provider } => {
228 self.config_regs.set_irq(irq_num as u8, pin);
229 self.state = XhciControllerState::IrqAssigned {
230 device_provider,
231 irq_evt,
232 }
233 }
234 _ => {
235 error!("xhci controller is in a wrong state");
236 }
237 }
238 }
239
240 fn allocate_io_bars(
241 &mut self,
242 resources: &mut SystemAllocator,
243 ) -> std::result::Result<Vec<BarRange>, PciDeviceError> {
244 let address = self
245 .pci_address
246 .expect("assign_address must be called prior to allocate_io_bars");
247 let bar0_addr = resources
249 .allocate_mmio(
250 XHCI_BAR0_SIZE,
251 Alloc::PciBar {
252 bus: address.bus,
253 dev: address.dev,
254 func: address.func,
255 bar: 0,
256 },
257 "xhci_bar0".to_string(),
258 AllocOptions::new()
259 .max_address(u32::MAX.into())
260 .align(XHCI_BAR0_SIZE),
261 )
262 .map_err(|e| PciDeviceError::IoAllocationFailed(XHCI_BAR0_SIZE, e))?;
263 let bar0_config = PciBarConfiguration::new(
264 0,
265 XHCI_BAR0_SIZE,
266 PciBarRegionType::Memory32BitRegion,
267 PciBarPrefetchable::NotPrefetchable,
268 )
269 .set_address(bar0_addr);
270 self.config_regs
271 .add_pci_bar(bar0_config)
272 .map_err(|e| PciDeviceError::IoRegistrationFailed(bar0_addr, e))?;
273 Ok(vec![BarRange {
274 addr: bar0_addr,
275 size: XHCI_BAR0_SIZE,
276 prefetchable: false,
277 }])
278 }
279
280 fn get_bar_configuration(&self, bar_num: usize) -> Option<PciBarConfiguration> {
281 self.config_regs.get_bar_configuration(bar_num)
282 }
283
284 fn read_config_register(&self, reg_idx: usize) -> u32 {
285 self.config_regs.read_reg(reg_idx)
286 }
287
288 fn write_config_register(&mut self, reg_idx: usize, offset: u64, data: &[u8]) {
289 self.config_regs.write_reg(reg_idx, offset, data);
290 }
291
292 fn setup_pci_config_mapping(
293 &mut self,
294 shmem: &SharedMemory,
295 base: usize,
296 len: usize,
297 ) -> Result<bool, PciDeviceError> {
298 self.config_regs
299 .setup_mapping(shmem, base, len)
300 .map(|_| true)
301 .map_err(PciDeviceError::MmioSetup)
302 }
303
304 fn read_bar(&mut self, bar_index: usize, offset: u64, data: &mut [u8]) {
305 if bar_index != 0 {
306 return;
307 }
308
309 match &self.state {
310 XhciControllerState::Initialized { mmio, .. } => {
311 mmio.read(offset, data);
313 }
314 _ => {
315 error!("xhci controller is in a wrong state");
316 }
317 }
318 }
319
320 fn write_bar(&mut self, bar_index: usize, offset: u64, data: &[u8]) {
321 if bar_index != 0 {
322 return;
323 }
324
325 match &self.state {
326 XhciControllerState::Initialized {
327 mmio, fail_handle, ..
328 } => {
329 if !fail_handle.failed() {
330 mmio.write(offset, data);
331 }
332 }
333 _ => {
334 error!("xhci controller is in a wrong state");
335 }
336 }
337 }
338
339 fn on_device_sandboxed(&mut self) {
340 self.init_when_forked();
341 }
342}
343
344impl Suspendable for XhciController {}