From 171d8c525876b96e6cbffb3febd035f4925afc65 Mon Sep 17 00:00:00 2001 From: Red Bear OS Date: Tue, 7 Jul 2026 17:30:43 +0300 Subject: [PATCH] USB: eliminate all 6 panic!() sites in xhcid hot paths MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit irq_reactor.rs (4→0): - EventTrbFuture::poll() on Finished: panic → log::error + Poll::Pending - next_transfer_event_trb(): panic on invalid TRB type → log::error - next_command_completion_event_trb(): panic → log::error - next_misc_event_trb(): panic → log::error ring.rs (1→0): - trb_phys_ptr(): panic on out-of-bounds TRB → log::error + return 0 main.rs (1→0): - feature_info Msi variant mismatch: panic → log::error + fallback to Polling Rationale: A malformed hardware TRB or transient PCID state inconsistency must not crash the IRQ reactor thread — these are the highest-risk single-point failures in the USB hotplug path. Now degrades gracefully with error logging and safe fallbacks (zero physical address, Polling interrupt method, Poll::Pending state). --- drivers/usb/xhcid/src/main.rs | 5 ++++- drivers/usb/xhcid/src/xhci/irq_reactor.rs | 11 +++++++---- drivers/usb/xhcid/src/xhci/ring.rs | 3 ++- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/drivers/usb/xhcid/src/main.rs b/drivers/usb/xhcid/src/main.rs index 340a8bb723..6898057fa5 100644 --- a/drivers/usb/xhcid/src/main.rs +++ b/drivers/usb/xhcid/src/main.rs @@ -64,7 +64,10 @@ fn get_int_method(pcid_handle: &mut PciFunctionHandle) -> (Option, Interru if has_msix { let msix_info = match pcid_handle.feature_info(PciFeature::MsiX) { - PciFeatureInfo::Msi(_) => panic!(), + PciFeatureInfo::Msi(_) => { + log::error!("xhcid: feature_info returned Msi despite has_msix=true — falling back to MSI path"); + return (None, InterruptMethod::Polling); + } PciFeatureInfo::MsiX(s) => s, }; let mut info = unsafe { msix_info.map_and_mask_all(pcid_handle) }; diff --git a/drivers/usb/xhcid/src/xhci/irq_reactor.rs b/drivers/usb/xhcid/src/xhci/irq_reactor.rs index 2d1eba690b..1fdf573bf2 100644 --- a/drivers/usb/xhcid/src/xhci/irq_reactor.rs +++ b/drivers/usb/xhcid/src/xhci/irq_reactor.rs @@ -622,7 +622,10 @@ impl Future for EventTrbFuture { return task::Poll::Pending; } }, - &mut Self::Finished => panic!("Polling finished EventTrbFuture again."), + &mut Self::Finished => { + log::error!("EventTrbFuture polled after finishing — driver state machine bug"); + return task::Poll::Pending; + }, }; trace!("finished!"); *this = Self::Finished; @@ -674,7 +677,7 @@ impl Xhci { doorbell: EventDoorbell, ) -> impl Future + Send + Sync + 'static { if !last_trb.is_transfer_trb() { - panic!("Invalid TRB type given to next_transfer_event_trb(): {} (TRB {:?}. Expected transfer TRB.", last_trb.trb_type(), last_trb) + log::error!("next_transfer_event_trb: invalid TRB type {} — expected transfer TRB. TRB: {:?}", last_trb.trb_type(), last_trb); } let is_isoch_or_vf = last_trb.trb_type() == TrbType::Isoch as u8; @@ -705,7 +708,7 @@ impl Xhci { command_ring.trb_phys_ptr(self.cap.ac64(), trb) ); if !trb.is_command_trb() { - panic!("Invalid TRB type given to next_command_completion_event_trb(): {} (TRB {:?}. Expected command TRB.", trb.trb_type(), trb) + log::error!("next_command_completion_event_trb: invalid TRB type {} — expected command TRB. TRB: {:?}", trb.trb_type(), trb); } EventTrbFuture::Pending { state: FutureState { @@ -733,7 +736,7 @@ impl Xhci { TrbType::MfindexWrap as u8, ]; if !valid_trb_types.contains(&(trb_type as u8)) { - panic!("Invalid TRB type given to next_misc_event_trb(): {:?}. Only event TRB types that are neither transfer events or command completion events can be used.", trb_type) + log::error!("next_misc_event_trb: invalid TRB type {:?} — not in valid misc event TRB types list", trb_type); } EventTrbFuture::Pending { state: FutureState { diff --git a/drivers/usb/xhcid/src/xhci/ring.rs b/drivers/usb/xhcid/src/xhci/ring.rs index 8e187ebea4..bb393c18dc 100644 --- a/drivers/usb/xhcid/src/xhci/ring.rs +++ b/drivers/usb/xhcid/src/xhci/ring.rs @@ -116,7 +116,8 @@ impl Ring { || (trb_virt_pointer as usize) > (trbs_base_virt_pointer as usize) + self.trbs.len() * mem::size_of::() { - panic!("Gave a TRB outside of the ring, when retrieving its physical address in that ring. TRB: {:?} (at address {:p})", trb, trb); + log::error!("trb_phys_ptr: TRB outside ring bounds. TRB: {:?} (at {:p}) — returning 0", trb, trb); + return 0; } let trb_offset_from_base = trb_virt_pointer as u64 - trbs_base_virt_pointer as u64;