1 // Copyright 2019 The ChromiumOS Authors 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 std::time::Duration; 6 use std::time::Instant; 7 8 use base::Clock; 9 use base::Error as SysError; 10 use base::Event; 11 use remain::sorted; 12 use thiserror::Error; 13 use vm_memory::GuestAddress; 14 use vm_memory::GuestMemory; 15 16 use super::event_ring::Error as EventRingError; 17 use super::event_ring::EventRing; 18 use super::xhci_abi::CommandCompletionEventTrb; 19 use super::xhci_abi::Error as TrbError; 20 use super::xhci_abi::PortStatusChangeEventTrb; 21 use super::xhci_abi::TransferEventTrb; 22 use super::xhci_abi::Trb; 23 use super::xhci_abi::TrbCast; 24 use super::xhci_abi::TrbCompletionCode; 25 use super::xhci_abi::TrbType; 26 use super::xhci_regs::XhciRegs; 27 use super::xhci_regs::ERDP_EVENT_HANDLER_BUSY; 28 use super::xhci_regs::IMAN_INTERRUPT_PENDING; 29 use super::xhci_regs::USB_STS_EVENT_INTERRUPT; 30 use crate::register_space::Register; 31 32 #[sorted] 33 #[derive(Error, Debug)] 34 pub enum Error { 35 #[error("cannot add event: {0}")] 36 AddEvent(EventRingError), 37 #[error("cannot cast trb: {0}")] 38 CastTrb(TrbError), 39 #[error("cannot send interrupt: {0}")] 40 SendInterrupt(SysError), 41 #[error("cannot set seg table base addr: {0}")] 42 SetSegTableBaseAddr(EventRingError), 43 #[error("cannot set seg table size: {0}")] 44 SetSegTableSize(EventRingError), 45 } 46 47 type Result<T> = std::result::Result<T, Error>; 48 49 /// See spec 4.17 for interrupters. Controller can send an event back to guest kernel driver 50 /// through interrupter. 51 pub struct Interrupter { 52 interrupt_evt: Event, 53 usbsts: Register<u32>, 54 iman: Register<u32>, 55 erdp: Register<u64>, 56 event_handler_busy: bool, 57 enabled: bool, 58 moderation_interval: u16, 59 moderation_counter: u16, 60 event_ring: EventRing, 61 last_interrupt_time: Instant, 62 clock: Clock, 63 } 64 65 impl Interrupter { 66 /// Create a new interrupter. new(mem: GuestMemory, irq_evt: Event, regs: &XhciRegs) -> Self67 pub fn new(mem: GuestMemory, irq_evt: Event, regs: &XhciRegs) -> Self { 68 let clock = Clock::new(); 69 Interrupter { 70 interrupt_evt: irq_evt, 71 usbsts: regs.usbsts.clone(), 72 iman: regs.iman.clone(), 73 erdp: regs.erdp.clone(), 74 event_handler_busy: false, 75 enabled: false, 76 moderation_interval: 4000, // default to 1ms as per xhci 5.5.2.2 77 moderation_counter: 0, // xhci specs leave this as undefined 78 event_ring: EventRing::new(mem), 79 last_interrupt_time: clock.now(), 80 clock, 81 } 82 } 83 84 /// Returns true if event ring is empty. event_ring_is_empty(&self) -> bool85 pub fn event_ring_is_empty(&self) -> bool { 86 self.event_ring.is_empty() 87 } 88 89 /// Add event to event ring. add_event(&mut self, trb: Trb) -> Result<()>90 fn add_event(&mut self, trb: Trb) -> Result<()> { 91 self.event_ring.add_event(trb).map_err(Error::AddEvent)?; 92 self.interrupt_if_needed() 93 } 94 95 /// Send port status change trb for port. send_port_status_change_trb(&mut self, port_id: u8) -> Result<()>96 pub fn send_port_status_change_trb(&mut self, port_id: u8) -> Result<()> { 97 let mut trb = Trb::new(); 98 let psctrb = trb 99 .cast_mut::<PortStatusChangeEventTrb>() 100 .map_err(Error::CastTrb)?; 101 psctrb.set_port_id(port_id); 102 psctrb.set_completion_code(TrbCompletionCode::Success); 103 psctrb.set_trb_type(TrbType::PortStatusChangeEvent); 104 self.add_event(trb) 105 } 106 107 /// Send command completion trb. send_command_completion_trb( &mut self, completion_code: TrbCompletionCode, slot_id: u8, trb_addr: GuestAddress, ) -> Result<()>108 pub fn send_command_completion_trb( 109 &mut self, 110 completion_code: TrbCompletionCode, 111 slot_id: u8, 112 trb_addr: GuestAddress, 113 ) -> Result<()> { 114 let mut trb = Trb::new(); 115 let ctrb = trb 116 .cast_mut::<CommandCompletionEventTrb>() 117 .map_err(Error::CastTrb)?; 118 ctrb.set_trb_pointer(trb_addr.0); 119 ctrb.set_command_completion_parameter(0); 120 ctrb.set_completion_code(completion_code); 121 ctrb.set_trb_type(TrbType::CommandCompletionEvent); 122 ctrb.set_vf_id(0); 123 ctrb.set_slot_id(slot_id); 124 self.add_event(trb) 125 } 126 127 /// Send transfer event trb. send_transfer_event_trb( &mut self, completion_code: TrbCompletionCode, trb_pointer: u64, transfer_length: u32, event_data: bool, slot_id: u8, endpoint_id: u8, ) -> Result<()>128 pub fn send_transfer_event_trb( 129 &mut self, 130 completion_code: TrbCompletionCode, 131 trb_pointer: u64, 132 transfer_length: u32, 133 event_data: bool, 134 slot_id: u8, 135 endpoint_id: u8, 136 ) -> Result<()> { 137 let mut trb = Trb::new(); 138 let event_trb = trb.cast_mut::<TransferEventTrb>().map_err(Error::CastTrb)?; 139 event_trb.set_trb_pointer(trb_pointer); 140 event_trb.set_trb_transfer_length(transfer_length); 141 event_trb.set_completion_code(completion_code); 142 event_trb.set_event_data(event_data.into()); 143 event_trb.set_trb_type(TrbType::TransferEvent); 144 event_trb.set_endpoint_id(endpoint_id); 145 event_trb.set_slot_id(slot_id); 146 self.add_event(trb) 147 } 148 149 /// Enable/Disable this interrupter. set_enabled(&mut self, enabled: bool) -> Result<()>150 pub fn set_enabled(&mut self, enabled: bool) -> Result<()> { 151 xhci_trace!("interrupter set_enabled({})", enabled); 152 self.enabled = enabled; 153 self.interrupt_if_needed() 154 } 155 156 /// Set interrupt moderation. set_moderation(&mut self, interval: u16, counter: u16) -> Result<()>157 pub fn set_moderation(&mut self, interval: u16, counter: u16) -> Result<()> { 158 xhci_trace!("interrupter set_moderation({}, {})", interval, counter); 159 self.moderation_interval = interval; 160 self.moderation_counter = counter; 161 self.interrupt_if_needed() 162 } 163 164 /// Set event ring seg table size. set_event_ring_seg_table_size(&mut self, size: u16) -> Result<()>165 pub fn set_event_ring_seg_table_size(&mut self, size: u16) -> Result<()> { 166 xhci_trace!("interrupter set_event_ring_seg_table_size({})", size); 167 self.event_ring 168 .set_seg_table_size(size) 169 .map_err(Error::SetSegTableSize) 170 } 171 172 /// Set event ring segment table base address. set_event_ring_seg_table_base_addr(&mut self, addr: GuestAddress) -> Result<()>173 pub fn set_event_ring_seg_table_base_addr(&mut self, addr: GuestAddress) -> Result<()> { 174 xhci_trace!("interrupter set_table_base_addr({:#x})", addr.0); 175 self.event_ring 176 .set_seg_table_base_addr(addr) 177 .map_err(Error::SetSegTableBaseAddr) 178 } 179 180 /// Set event ring dequeue pointer. set_event_ring_dequeue_pointer(&mut self, addr: GuestAddress, busy: bool) -> Result<()>181 pub fn set_event_ring_dequeue_pointer(&mut self, addr: GuestAddress, busy: bool) -> Result<()> { 182 xhci_trace!( 183 "interrupter set_dequeue_pointer(addr = {:#x}, busy = {})", 184 addr.0, 185 busy 186 ); 187 self.event_ring.set_dequeue_pointer(addr); 188 self.event_handler_busy = busy; 189 self.interrupt_if_needed() 190 } 191 192 /// Send and interrupt. interrupt(&mut self) -> Result<()>193 pub fn interrupt(&mut self) -> Result<()> { 194 self.event_handler_busy = true; 195 self.usbsts.set_bits(USB_STS_EVENT_INTERRUPT); 196 self.iman.set_bits(IMAN_INTERRUPT_PENDING); 197 self.erdp.set_bits(ERDP_EVENT_HANDLER_BUSY); 198 self.moderation_counter = self.moderation_interval; 199 self.last_interrupt_time = self.clock.now(); 200 self.interrupt_evt.signal().map_err(Error::SendInterrupt) 201 } 202 interrupt_interval(&self) -> Duration203 fn interrupt_interval(&self) -> Duration { 204 // Formula from xhci spec 4.17.2 in nanoseconds, but we use the imodc value instead of the 205 // imodi value because our implementation automatically adjusts the range of the duration 206 // based on the remaining time left in the moderation counter, which may be software 207 // defined. 208 Duration::new(0, 250 * u32::from(self.moderation_counter)) 209 } 210 interrupt_if_needed(&mut self) -> Result<()>211 fn interrupt_if_needed(&mut self) -> Result<()> { 212 let can_interrupt = self.last_interrupt_time.elapsed() >= self.interrupt_interval(); 213 if self.enabled && can_interrupt && !self.event_ring.is_empty() && !self.event_handler_busy 214 { 215 self.interrupt()?; 216 } 217 Ok(()) 218 } 219 } 220