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}
120
121impl XhciController {
122 pub fn new(mem: GuestMemory, usb_provider: Box<dyn XhciBackendDeviceProvider>) -> Self {
124 let config_regs = PciConfiguration::new(
125 0x01b73, 0x1400, 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 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
182impl PciDevice for XhciController {
183 fn debug_label(&self) -> String {
184 "xhci controller".to_owned()
185 }
186
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 = resources.allocate_pci(0, self.debug_label());
193 }
194 self.pci_address.ok_or(PciDeviceError::PciAllocationFailed)
195 }
196
197 fn keep_rds(&self) -> Vec<RawDescriptor> {
198 match &self.state {
199 XhciControllerState::Created { device_provider } => device_provider.keep_rds(),
200 XhciControllerState::IrqAssigned {
201 device_provider,
202 irq_evt,
203 } => {
204 let mut keep_rds = device_provider.keep_rds();
205 keep_rds.push(irq_evt.get_trigger().as_raw_descriptor());
206 keep_rds.push(irq_evt.get_resample().as_raw_descriptor());
207 keep_rds
208 }
209 _ => {
210 error!("xhci controller is in a wrong state");
211 vec![]
212 }
213 }
214 }
215
216 fn assign_irq(&mut self, irq_evt: IrqLevelEvent, pin: PciInterruptPin, irq_num: u32) {
217 match mem::replace(&mut self.state, XhciControllerState::Unknown) {
218 XhciControllerState::Created { device_provider } => {
219 self.config_regs.set_irq(irq_num as u8, pin);
220 self.state = XhciControllerState::IrqAssigned {
221 device_provider,
222 irq_evt,
223 }
224 }
225 _ => {
226 error!("xhci controller is in a wrong state");
227 }
228 }
229 }
230
231 fn allocate_io_bars(
232 &mut self,
233 resources: &mut SystemAllocator,
234 ) -> std::result::Result<Vec<BarRange>, PciDeviceError> {
235 let address = self
236 .pci_address
237 .expect("assign_address must be called prior to allocate_io_bars");
238 let bar0_addr = resources
240 .allocate_mmio(
241 XHCI_BAR0_SIZE,
242 Alloc::PciBar {
243 bus: address.bus,
244 dev: address.dev,
245 func: address.func,
246 bar: 0,
247 },
248 "xhci_bar0".to_string(),
249 AllocOptions::new()
250 .max_address(u32::MAX.into())
251 .align(XHCI_BAR0_SIZE),
252 )
253 .map_err(|e| PciDeviceError::IoAllocationFailed(XHCI_BAR0_SIZE, e))?;
254 let bar0_config = PciBarConfiguration::new(
255 0,
256 XHCI_BAR0_SIZE,
257 PciBarRegionType::Memory32BitRegion,
258 PciBarPrefetchable::NotPrefetchable,
259 )
260 .set_address(bar0_addr);
261 self.config_regs
262 .add_pci_bar(bar0_config)
263 .map_err(|e| PciDeviceError::IoRegistrationFailed(bar0_addr, e))?;
264 Ok(vec![BarRange {
265 addr: bar0_addr,
266 size: XHCI_BAR0_SIZE,
267 prefetchable: false,
268 }])
269 }
270
271 fn get_bar_configuration(&self, bar_num: usize) -> Option<PciBarConfiguration> {
272 self.config_regs.get_bar_configuration(bar_num)
273 }
274
275 fn read_config_register(&self, reg_idx: usize) -> u32 {
276 self.config_regs.read_reg(reg_idx)
277 }
278
279 fn write_config_register(&mut self, reg_idx: usize, offset: u64, data: &[u8]) {
280 self.config_regs.write_reg(reg_idx, offset, data);
281 }
282
283 fn setup_pci_config_mapping(
284 &mut self,
285 shmem: &SharedMemory,
286 base: usize,
287 len: usize,
288 ) -> Result<bool, PciDeviceError> {
289 self.config_regs
290 .setup_mapping(shmem, base, len)
291 .map(|_| true)
292 .map_err(PciDeviceError::MmioSetup)
293 }
294
295 fn read_bar(&mut self, bar_index: usize, offset: u64, data: &mut [u8]) {
296 if bar_index != 0 {
297 return;
298 }
299
300 match &self.state {
301 XhciControllerState::Initialized { mmio, .. } => {
302 mmio.read(offset, data);
304 }
305 _ => {
306 error!("xhci controller is in a wrong state");
307 }
308 }
309 }
310
311 fn write_bar(&mut self, bar_index: usize, offset: u64, data: &[u8]) {
312 if bar_index != 0 {
313 return;
314 }
315
316 match &self.state {
317 XhciControllerState::Initialized {
318 mmio, fail_handle, ..
319 } => {
320 if !fail_handle.failed() {
321 mmio.write(offset, data);
322 }
323 }
324 _ => {
325 error!("xhci controller is in a wrong state");
326 }
327 }
328 }
329
330 fn on_device_sandboxed(&mut self) {
331 self.init_when_forked();
332 }
333}
334
335impl Suspendable for XhciController {}