xref: /aosp_15_r20/external/crosvm/devices/src/pci/pcie/pcie_port.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1 // Copyright 2022 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::str::FromStr;
6 use std::sync::Arc;
7 
8 use base::error;
9 use base::warn;
10 use base::Event;
11 use resources::Alloc;
12 use resources::SystemAllocator;
13 use sync::Mutex;
14 use zerocopy::FromBytes;
15 
16 use crate::pci::pci_configuration::PciCapConfig;
17 use crate::pci::pci_configuration::PciCapConfigWriteResult;
18 use crate::pci::pci_configuration::PciCapMapping;
19 use crate::pci::pci_configuration::PciCapability;
20 use crate::pci::pcie::pci_bridge::PciBridgeBusRange;
21 use crate::pci::pcie::pcie_device::PcieCap;
22 use crate::pci::pcie::pcie_device::PcieDevice;
23 use crate::pci::pcie::pcie_host::PcieHostPort;
24 use crate::pci::pcie::*;
25 use crate::pci::pm::PciDevicePower;
26 use crate::pci::pm::PciPmCap;
27 use crate::pci::pm::PmConfig;
28 use crate::pci::pm::PmStatusChange;
29 use crate::pci::MsiConfig;
30 use crate::pci::PciAddress;
31 use crate::pci::PciDeviceError;
32 
33 // reserve 8MB memory window
34 const PCIE_BR_MEM_SIZE: u64 = 0x80_0000;
35 // reserve 64MB prefetch window
36 const PCIE_BR_PREF_MEM_SIZE: u64 = 0x400_0000;
37 
trigger_interrupt(msi: &Option<Arc<Mutex<MsiConfig>>>)38 fn trigger_interrupt(msi: &Option<Arc<Mutex<MsiConfig>>>) {
39     if let Some(msi_config) = msi {
40         let msi_config = msi_config.lock();
41         if msi_config.is_msi_enabled() {
42             msi_config.trigger()
43         }
44     }
45 }
46 
47 struct PcieRootCap {
48     secondary_bus_num: u8,
49     subordinate_bus_num: u8,
50 
51     control: u16,
52     status: u32,
53     pme_pending_requester_id: Option<u16>,
54 
55     msi_config: Option<Arc<Mutex<MsiConfig>>>,
56 }
57 
58 impl PcieRootCap {
new(secondary_bus_num: u8, subordinate_bus_num: u8) -> Self59     fn new(secondary_bus_num: u8, subordinate_bus_num: u8) -> Self {
60         PcieRootCap {
61             secondary_bus_num,
62             subordinate_bus_num,
63             control: 0,
64             status: 0,
65             pme_pending_requester_id: None,
66             msi_config: None,
67         }
68     }
69 
clone_interrupt(&mut self, msi_config: Arc<Mutex<MsiConfig>>)70     fn clone_interrupt(&mut self, msi_config: Arc<Mutex<MsiConfig>>) {
71         self.msi_config = Some(msi_config);
72     }
73 
trigger_pme_interrupt(&self)74     fn trigger_pme_interrupt(&self) {
75         if (self.control & PCIE_ROOTCTL_PME_ENABLE) != 0
76             && (self.status & PCIE_ROOTSTA_PME_STATUS) != 0
77         {
78             trigger_interrupt(&self.msi_config)
79         }
80     }
81 }
82 
83 static PCIE_ROOTS_CAP: Mutex<Vec<Arc<Mutex<PcieRootCap>>>> = Mutex::new(Vec::new());
84 
push_pcie_root_cap(root_cap: Arc<Mutex<PcieRootCap>>)85 fn push_pcie_root_cap(root_cap: Arc<Mutex<PcieRootCap>>) {
86     PCIE_ROOTS_CAP.lock().push(root_cap);
87 }
88 
get_pcie_root_cap(bus_num: u8) -> Option<Arc<Mutex<PcieRootCap>>>89 fn get_pcie_root_cap(bus_num: u8) -> Option<Arc<Mutex<PcieRootCap>>> {
90     for root_cap in PCIE_ROOTS_CAP.lock().iter() {
91         let root_cap_lock = root_cap.lock();
92         if root_cap_lock.secondary_bus_num <= bus_num
93             && root_cap_lock.subordinate_bus_num >= bus_num
94         {
95             return Some(root_cap.clone());
96         }
97     }
98 
99     None
100 }
101 
102 pub struct PciePort {
103     device_id: u16,
104     debug_label: String,
105     preferred_address: Option<PciAddress>,
106     pci_address: Option<PciAddress>,
107     bus_range: PciBridgeBusRange,
108     pcie_host: Option<PcieHostPort>,
109     pcie_config: Arc<Mutex<PcieConfig>>,
110     pm_config: Arc<Mutex<PmConfig>>,
111 
112     msi_config: Option<Arc<Mutex<MsiConfig>>>,
113 
114     // For PcieRootPort, root_cap point to itself
115     // For PcieDownstreamPort or PciDownstreamPort, root_cap point to PcieRootPort its behind.
116     root_cap: Arc<Mutex<PcieRootCap>>,
117     port_type: PcieDevicePortType,
118 
119     prepare_hotplug: bool,
120 }
121 
122 impl PciePort {
123     /// Constructs a new PCIE port
new( device_id: u16, debug_label: String, primary_bus_num: u8, secondary_bus_num: u8, slot_implemented: bool, port_type: PcieDevicePortType, ) -> Self124     pub fn new(
125         device_id: u16,
126         debug_label: String,
127         primary_bus_num: u8,
128         secondary_bus_num: u8,
129         slot_implemented: bool,
130         port_type: PcieDevicePortType,
131     ) -> Self {
132         let bus_range = PciBridgeBusRange {
133             primary: primary_bus_num,
134             secondary: secondary_bus_num,
135             subordinate: secondary_bus_num,
136         };
137 
138         let root_cap = if port_type == PcieDevicePortType::RootPort {
139             let cap = Arc::new(Mutex::new(PcieRootCap::new(
140                 secondary_bus_num,
141                 secondary_bus_num,
142             )));
143             push_pcie_root_cap(cap.clone());
144             cap
145         } else {
146             get_pcie_root_cap(primary_bus_num).expect("Pcie root port should be created at first")
147         };
148 
149         PciePort {
150             device_id,
151             debug_label,
152             preferred_address: None,
153             pci_address: None,
154             bus_range,
155             pcie_host: None,
156             msi_config: None,
157             pcie_config: Arc::new(Mutex::new(PcieConfig::new(
158                 root_cap.clone(),
159                 slot_implemented,
160                 port_type,
161             ))),
162             pm_config: Arc::new(Mutex::new(PmConfig::new(false))),
163 
164             root_cap,
165             port_type,
166 
167             prepare_hotplug: false,
168         }
169     }
170 
new_from_host( pcie_host: PcieHostPort, slot_implemented: bool, port_type: PcieDevicePortType, ) -> std::result::Result<Self, PciDeviceError>171     pub fn new_from_host(
172         pcie_host: PcieHostPort,
173         slot_implemented: bool,
174         port_type: PcieDevicePortType,
175     ) -> std::result::Result<Self, PciDeviceError> {
176         let bus_range = pcie_host.get_bus_range();
177         let host_address = PciAddress::from_str(&pcie_host.host_name())
178             .map_err(|e| PciDeviceError::PciAddressParseFailure(pcie_host.host_name(), e))?;
179         let root_cap = if port_type == PcieDevicePortType::RootPort {
180             let cap = Arc::new(Mutex::new(PcieRootCap::new(
181                 bus_range.secondary,
182                 bus_range.subordinate,
183             )));
184             push_pcie_root_cap(cap.clone());
185             cap
186         } else {
187             get_pcie_root_cap(bus_range.primary).expect("Pcie root port should be created at first")
188         };
189 
190         Ok(PciePort {
191             device_id: pcie_host.read_device_id(),
192             debug_label: pcie_host.host_name(),
193             preferred_address: Some(host_address),
194             pci_address: None,
195             bus_range,
196             pcie_host: Some(pcie_host),
197             msi_config: None,
198             pcie_config: Arc::new(Mutex::new(PcieConfig::new(
199                 root_cap.clone(),
200                 slot_implemented,
201                 port_type,
202             ))),
203             pm_config: Arc::new(Mutex::new(PmConfig::new(false))),
204 
205             root_cap,
206             port_type,
207 
208             prepare_hotplug: false,
209         })
210     }
211 
get_device_id(&self) -> u16212     pub fn get_device_id(&self) -> u16 {
213         self.device_id
214     }
215 
get_address(&self) -> Option<PciAddress>216     pub fn get_address(&self) -> Option<PciAddress> {
217         self.pci_address
218     }
219 
debug_label(&self) -> String220     pub fn debug_label(&self) -> String {
221         self.debug_label.clone()
222     }
223 
preferred_address(&self) -> Option<PciAddress>224     pub fn preferred_address(&self) -> Option<PciAddress> {
225         self.preferred_address
226     }
227 
allocate_address( &mut self, resources: &mut SystemAllocator, ) -> std::result::Result<PciAddress, PciDeviceError>228     pub fn allocate_address(
229         &mut self,
230         resources: &mut SystemAllocator,
231     ) -> std::result::Result<PciAddress, PciDeviceError> {
232         if self.pci_address.is_none() {
233             if let Some(address) = self.preferred_address {
234                 if resources.reserve_pci(
235                     Alloc::PciBar {
236                         bus: address.bus,
237                         dev: address.dev,
238                         func: address.func,
239                         bar: 0,
240                     },
241                     self.debug_label(),
242                 ) {
243                     self.pci_address = Some(address);
244                 } else {
245                     self.pci_address = None;
246                 }
247             } else {
248                 match resources.allocate_pci(self.bus_range.primary, self.debug_label()) {
249                     Some(Alloc::PciBar {
250                         bus,
251                         dev,
252                         func,
253                         bar: _,
254                     }) => self.pci_address = Some(PciAddress { bus, dev, func }),
255                     _ => self.pci_address = None,
256                 }
257             }
258         }
259         self.pci_address.ok_or(PciDeviceError::PciAllocationFailed)
260     }
261 
read_config(&self, reg_idx: usize, data: &mut u32)262     pub fn read_config(&self, reg_idx: usize, data: &mut u32) {
263         if let Some(host) = &self.pcie_host {
264             host.read_config(reg_idx, data);
265         }
266     }
267 
write_config(&mut self, reg_idx: usize, offset: u64, data: &[u8])268     pub fn write_config(&mut self, reg_idx: usize, offset: u64, data: &[u8]) {
269         if let Some(host) = self.pcie_host.as_mut() {
270             host.write_config(reg_idx, offset, data);
271         }
272     }
273 
handle_cap_write_result(&mut self, res: Box<dyn PciCapConfigWriteResult>)274     pub fn handle_cap_write_result(&mut self, res: Box<dyn PciCapConfigWriteResult>) {
275         if let Some(status) = res.downcast_ref::<PmStatusChange>() {
276             if status.from == PciDevicePower::D3
277                 && status.to == PciDevicePower::D0
278                 && self.prepare_hotplug
279             {
280                 if let Some(host) = self.pcie_host.as_mut() {
281                     host.hotplug_probe();
282                     self.prepare_hotplug = false;
283                 }
284             }
285         }
286     }
287 
get_caps(&self) -> Vec<(Box<dyn PciCapability>, Option<Box<dyn PciCapConfig>>)>288     pub fn get_caps(&self) -> Vec<(Box<dyn PciCapability>, Option<Box<dyn PciCapConfig>>)> {
289         vec![
290             (
291                 Box::new(PcieCap::new(self.port_type, self.hotplug_implemented(), 0)),
292                 Some(Box::new(self.pcie_config.clone())),
293             ),
294             (
295                 Box::new(PciPmCap::new()),
296                 Some(Box::new(self.pm_config.clone())),
297             ),
298         ]
299     }
300 
get_bus_range(&self) -> Option<PciBridgeBusRange>301     pub fn get_bus_range(&self) -> Option<PciBridgeBusRange> {
302         Some(self.bus_range)
303     }
304 
get_bridge_window_size(&self) -> (u64, u64)305     pub fn get_bridge_window_size(&self) -> (u64, u64) {
306         if let Some(host) = &self.pcie_host {
307             host.get_bridge_window_size()
308         } else {
309             (PCIE_BR_MEM_SIZE, PCIE_BR_PREF_MEM_SIZE)
310         }
311     }
312 
get_slot_control(&self) -> u16313     pub fn get_slot_control(&self) -> u16 {
314         self.pcie_config.lock().get_slot_control()
315     }
316 
clone_interrupt(&mut self, msi_config: Arc<Mutex<MsiConfig>>)317     pub fn clone_interrupt(&mut self, msi_config: Arc<Mutex<MsiConfig>>) {
318         if self.port_type == PcieDevicePortType::RootPort {
319             self.root_cap.lock().clone_interrupt(msi_config.clone());
320         }
321         self.pcie_config.lock().msi_config = Some(msi_config.clone());
322         self.msi_config = Some(msi_config);
323     }
324 
hotplug_implemented(&self) -> bool325     pub fn hotplug_implemented(&self) -> bool {
326         self.pcie_config.lock().slot_control.is_some()
327     }
328 
inject_pme(&mut self, requester_id: u16)329     pub fn inject_pme(&mut self, requester_id: u16) {
330         let mut r = self.root_cap.lock();
331         if (r.status & PCIE_ROOTSTA_PME_STATUS) != 0 {
332             r.status |= PCIE_ROOTSTA_PME_PENDING;
333             r.pme_pending_requester_id = Some(requester_id);
334         } else {
335             r.status &= !PCIE_ROOTSTA_PME_REQ_ID_MASK;
336             r.status |= requester_id as u32;
337             r.pme_pending_requester_id = None;
338             r.status |= PCIE_ROOTSTA_PME_STATUS;
339             r.trigger_pme_interrupt();
340         }
341     }
342 
343     /// Has command completion pending.
is_hpc_pending(&self) -> bool344     pub fn is_hpc_pending(&self) -> bool {
345         self.pcie_config.lock().hpc_sender.is_some()
346     }
347 
348     /// Sets a sender for hot plug or unplug complete.
set_hpc_sender(&mut self, event: Event)349     pub fn set_hpc_sender(&mut self, event: Event) {
350         self.pcie_config
351             .lock()
352             .hpc_sender
353             .replace(HotPlugCompleteSender::new(event));
354     }
355 
trigger_hp_or_pme_interrupt(&mut self)356     pub fn trigger_hp_or_pme_interrupt(&mut self) {
357         if self.pm_config.lock().should_trigger_pme() {
358             self.pcie_config.lock().hp_interrupt_pending = true;
359             self.inject_pme(self.pci_address.unwrap().pme_requester_id());
360         } else {
361             self.pcie_config.lock().trigger_hp_interrupt();
362         }
363     }
364 
is_host(&self) -> bool365     pub fn is_host(&self) -> bool {
366         self.pcie_host.is_some()
367     }
368 
369     /// Checks if the slot is enabled by guest and ready for hotplug events.
is_hotplug_ready(&self) -> bool370     pub fn is_hotplug_ready(&self) -> bool {
371         self.pcie_config.lock().is_hotplug_ready()
372     }
373 
374     /// Gets a notification when the port is ready for hotplug.  If the port is already ready, then
375     /// the notification event is triggerred immediately.
get_ready_notification(&mut self) -> std::result::Result<Event, PciDeviceError>376     pub fn get_ready_notification(&mut self) -> std::result::Result<Event, PciDeviceError> {
377         self.pcie_config.lock().get_ready_notification()
378     }
379 
hot_unplug(&mut self)380     pub fn hot_unplug(&mut self) {
381         if let Some(host) = self.pcie_host.as_mut() {
382             host.hot_unplug()
383         }
384     }
385 
is_match(&self, host_addr: PciAddress) -> Option<u8>386     pub fn is_match(&self, host_addr: PciAddress) -> Option<u8> {
387         if host_addr.bus == self.bus_range.secondary || self.pcie_host.is_none() {
388             Some(self.bus_range.secondary)
389         } else {
390             None
391         }
392     }
393 
removed_downstream_valid(&self) -> bool394     pub fn removed_downstream_valid(&self) -> bool {
395         self.pcie_config.lock().removed_downstream_valid
396     }
397 
mask_slot_status(&mut self, mask: u16)398     pub fn mask_slot_status(&mut self, mask: u16) {
399         self.pcie_config.lock().mask_slot_status(mask);
400     }
401 
set_slot_status(&mut self, flag: u16)402     pub fn set_slot_status(&mut self, flag: u16) {
403         self.pcie_config.lock().set_slot_status(flag);
404     }
405 
should_trigger_pme(&mut self) -> bool406     pub fn should_trigger_pme(&mut self) -> bool {
407         self.pm_config.lock().should_trigger_pme()
408     }
409 
prepare_hotplug(&mut self)410     pub fn prepare_hotplug(&mut self) {
411         self.prepare_hotplug = true;
412     }
413 }
414 
415 struct HotPlugCompleteSender {
416     sender: Event,
417     armed: bool,
418 }
419 
420 impl HotPlugCompleteSender {
new(sender: Event) -> Self421     fn new(sender: Event) -> Self {
422         Self {
423             sender,
424             armed: false,
425         }
426     }
427 
arm(&mut self)428     fn arm(&mut self) {
429         self.armed = true;
430     }
431 
armed(&self) -> bool432     fn armed(&self) -> bool {
433         self.armed
434     }
435 
signal(&self) -> base::Result<()>436     fn signal(&self) -> base::Result<()> {
437         self.sender.signal()
438     }
439 }
440 
441 pub struct PcieConfig {
442     msi_config: Option<Arc<Mutex<MsiConfig>>>,
443 
444     slot_control: Option<u16>,
445     slot_status: u16,
446 
447     // For PcieRootPort, root_cap point to itself
448     // For PcieDownstreamPort or PciDownstreamPort, root_cap point to PcieRootPort its behind.
449     root_cap: Arc<Mutex<PcieRootCap>>,
450     port_type: PcieDevicePortType,
451 
452     hpc_sender: Option<HotPlugCompleteSender>,
453     hp_interrupt_pending: bool,
454     removed_downstream_valid: bool,
455 
456     enabled: bool,
457     hot_plug_ready_notifications: Vec<Event>,
458     cap_mapping: Option<PciCapMapping>,
459 }
460 
461 impl PcieConfig {
new( root_cap: Arc<Mutex<PcieRootCap>>, slot_implemented: bool, port_type: PcieDevicePortType, ) -> Self462     fn new(
463         root_cap: Arc<Mutex<PcieRootCap>>,
464         slot_implemented: bool,
465         port_type: PcieDevicePortType,
466     ) -> Self {
467         PcieConfig {
468             msi_config: None,
469 
470             slot_control: if slot_implemented {
471                 Some(PCIE_SLTCTL_PIC_OFF | PCIE_SLTCTL_AIC_OFF)
472             } else {
473                 None
474             },
475             slot_status: 0,
476 
477             root_cap,
478             port_type,
479 
480             hpc_sender: None,
481             hp_interrupt_pending: false,
482             removed_downstream_valid: false,
483 
484             enabled: false,
485             hot_plug_ready_notifications: Vec::new(),
486             cap_mapping: None,
487         }
488     }
489 
read_pcie_cap(&self, offset: usize, data: &mut u32)490     fn read_pcie_cap(&self, offset: usize, data: &mut u32) {
491         if offset == PCIE_SLTCTL_OFFSET {
492             *data = ((self.slot_status as u32) << 16) | (self.get_slot_control() as u32);
493         } else if offset == PCIE_ROOTCTL_OFFSET {
494             *data = match self.port_type {
495                 PcieDevicePortType::RootPort => self.root_cap.lock().control as u32,
496                 _ => 0,
497             };
498         } else if offset == PCIE_ROOTSTA_OFFSET {
499             *data = match self.port_type {
500                 PcieDevicePortType::RootPort => self.root_cap.lock().status,
501                 _ => 0,
502             };
503         }
504     }
505 
506     // Checks if the slot is enabled by guest and ready for hotplug events.
is_hotplug_ready(&self) -> bool507     fn is_hotplug_ready(&self) -> bool {
508         // The hotplug capability flags are set when the guest enables the device. Checks all flags
509         // required by the hotplug mechanism.
510         let slot_control = self.get_slot_control();
511         (slot_control & (PCIE_SLTCTL_PDCE | PCIE_SLTCTL_ABPE)) != 0
512             && (slot_control & PCIE_SLTCTL_CCIE) != 0
513             && (slot_control & PCIE_SLTCTL_HPIE) != 0
514     }
515 
516     /// Gets a notification when the port is ready for hotplug. If the port is already ready, then
517     /// the notification event is triggerred immediately.
get_ready_notification(&mut self) -> std::result::Result<Event, PciDeviceError>518     fn get_ready_notification(&mut self) -> std::result::Result<Event, PciDeviceError> {
519         let event = Event::new().map_err(|e| PciDeviceError::EventCreationFailed(e.errno()))?;
520         if self.is_hotplug_ready() {
521             event
522                 .signal()
523                 .map_err(|e| PciDeviceError::EventSignalFailed(e.errno()))?;
524         } else {
525             self.hot_plug_ready_notifications.push(
526                 event
527                     .try_clone()
528                     .map_err(|e| PciDeviceError::EventCloneFailed(e.errno()))?,
529             );
530         }
531         Ok(event)
532     }
533 
write_pcie_cap(&mut self, offset: usize, data: &[u8])534     fn write_pcie_cap(&mut self, offset: usize, data: &[u8]) {
535         self.removed_downstream_valid = false;
536         match offset {
537             PCIE_SLTCTL_OFFSET => {
538                 let value = match u16::read_from(data) {
539                     Some(v) => v,
540                     None => {
541                         warn!("write SLTCTL isn't word, len: {}", data.len());
542                         return;
543                     }
544                 };
545                 if !self.enabled
546                     && (value & (PCIE_SLTCTL_PDCE | PCIE_SLTCTL_ABPE)) != 0
547                     && (value & PCIE_SLTCTL_CCIE) != 0
548                     && (value & PCIE_SLTCTL_HPIE) != 0
549                 {
550                     // Device is getting enabled by the guest.
551                     for notf_event in self.hot_plug_ready_notifications.drain(..) {
552                         if let Err(e) = notf_event.signal() {
553                             error!("Failed to signal hot plug ready: {}", e);
554                         }
555                     }
556                     self.enabled = true;
557                 }
558 
559                 // if slot is populated, power indicator is off,
560                 // it will detach devices
561                 let old_control = self.get_slot_control();
562                 match self.slot_control.as_mut() {
563                     Some(v) => *v = value,
564                     None => return,
565                 }
566                 if (self.slot_status & PCIE_SLTSTA_PDS != 0)
567                     && (value & PCIE_SLTCTL_PIC == PCIE_SLTCTL_PIC_OFF)
568                     && (old_control & PCIE_SLTCTL_PIC != PCIE_SLTCTL_PIC_OFF)
569                 {
570                     self.removed_downstream_valid = true;
571                     self.slot_status &= !PCIE_SLTSTA_PDS;
572                     self.trigger_hp_interrupt();
573                 }
574 
575                 // Guest enable hotplug interrupt and has hotplug interrupt
576                 // pending, inject it right row.
577                 if (old_control & PCIE_SLTCTL_HPIE == 0)
578                     && (value & PCIE_SLTCTL_HPIE == PCIE_SLTCTL_HPIE)
579                     && self.hp_interrupt_pending
580                 {
581                     self.hp_interrupt_pending = false;
582                     self.trigger_hp_interrupt();
583                 }
584 
585                 if old_control != value {
586                     let old_pic_state = old_control & PCIE_SLTCTL_PIC;
587                     let pic_state = value & PCIE_SLTCTL_PIC;
588                     if old_pic_state == PCIE_SLTCTL_PIC_BLINK && old_pic_state != pic_state {
589                         // The power indicator (PIC) is controled by the guest to indicate the power
590                         // state of the slot.
591                         // For successful hotplug: OFF => BLINK => (board enabled) => ON
592                         // For failed hotplug: OFF => BLINK => (board enable failed) => OFF
593                         // For hot unplug: ON => BLINK => (board disabled) => OFF
594                         // hot (un)plug is completed at next slot status write after it changed to
595                         // ON or OFF state.
596 
597                         if let Some(sender) = self.hpc_sender.as_mut() {
598                             sender.arm();
599                         }
600                     }
601                     self.slot_status |= PCIE_SLTSTA_CC;
602                     self.trigger_cc_interrupt();
603                 }
604             }
605             PCIE_SLTSTA_OFFSET => {
606                 if self.slot_control.is_none() {
607                     return;
608                 }
609                 if let Some(hpc_sender) = self.hpc_sender.as_mut() {
610                     if hpc_sender.armed() {
611                         if let Err(e) = hpc_sender.signal() {
612                             error!("Failed to send hot un/plug complete signal: {}", e);
613                         }
614                         self.hpc_sender = None;
615                     }
616                 }
617                 let value = match u16::read_from(data) {
618                     Some(v) => v,
619                     None => {
620                         warn!("write SLTSTA isn't word, len: {}", data.len());
621                         return;
622                     }
623                 };
624                 if value & PCIE_SLTSTA_ABP != 0 {
625                     self.slot_status &= !PCIE_SLTSTA_ABP;
626                 }
627                 if value & PCIE_SLTSTA_PFD != 0 {
628                     self.slot_status &= !PCIE_SLTSTA_PFD;
629                 }
630                 if value & PCIE_SLTSTA_PDC != 0 {
631                     self.slot_status &= !PCIE_SLTSTA_PDC;
632                 }
633                 if value & PCIE_SLTSTA_CC != 0 {
634                     self.slot_status &= !PCIE_SLTSTA_CC;
635                 }
636                 if value & PCIE_SLTSTA_DLLSC != 0 {
637                     self.slot_status &= !PCIE_SLTSTA_DLLSC;
638                 }
639             }
640             PCIE_ROOTCTL_OFFSET => match u16::read_from(data) {
641                 Some(v) => {
642                     if self.port_type == PcieDevicePortType::RootPort {
643                         self.root_cap.lock().control = v;
644                     } else {
645                         warn!("write root control register while device isn't root port");
646                     }
647                 }
648                 None => warn!("write root control isn't word, len: {}", data.len()),
649             },
650             PCIE_ROOTSTA_OFFSET => match u32::read_from(data) {
651                 Some(v) => {
652                     if self.port_type == PcieDevicePortType::RootPort {
653                         if v & PCIE_ROOTSTA_PME_STATUS != 0 {
654                             let mut r = self.root_cap.lock();
655                             if let Some(requester_id) = r.pme_pending_requester_id {
656                                 r.status &= !PCIE_ROOTSTA_PME_PENDING;
657                                 r.status &= !PCIE_ROOTSTA_PME_REQ_ID_MASK;
658                                 r.status |= requester_id as u32;
659                                 r.status |= PCIE_ROOTSTA_PME_STATUS;
660                                 r.pme_pending_requester_id = None;
661                                 r.trigger_pme_interrupt();
662                             } else {
663                                 r.status &= !PCIE_ROOTSTA_PME_STATUS;
664                             }
665                         }
666                     } else {
667                         warn!("write root status register while device isn't root port");
668                     }
669                 }
670                 None => warn!("write root status isn't dword, len: {}", data.len()),
671             },
672             _ => (),
673         }
674     }
675 
get_slot_control(&self) -> u16676     fn get_slot_control(&self) -> u16 {
677         if let Some(slot_control) = self.slot_control {
678             return slot_control;
679         }
680         0
681     }
682 
trigger_cc_interrupt(&self)683     fn trigger_cc_interrupt(&self) {
684         if (self.get_slot_control() & PCIE_SLTCTL_CCIE) != 0
685             && (self.slot_status & PCIE_SLTSTA_CC) != 0
686         {
687             trigger_interrupt(&self.msi_config)
688         }
689     }
690 
trigger_hp_interrupt(&mut self)691     fn trigger_hp_interrupt(&mut self) {
692         let slot_control = self.get_slot_control();
693         if (slot_control & PCIE_SLTCTL_HPIE) != 0 {
694             self.set_slot_status(PCIE_SLTSTA_PDC);
695             if (self.slot_status & slot_control & (PCIE_SLTCTL_ABPE | PCIE_SLTCTL_PDCE)) != 0 {
696                 trigger_interrupt(&self.msi_config)
697             }
698         }
699     }
700 
mask_slot_status(&mut self, mask: u16)701     fn mask_slot_status(&mut self, mask: u16) {
702         self.slot_status &= mask;
703         if let Some(mapping) = self.cap_mapping.as_mut() {
704             mapping.set_reg(
705                 PCIE_SLTCTL_OFFSET / 4,
706                 (self.slot_status as u32) << 16,
707                 0xffff0000,
708             );
709         }
710     }
711 
set_slot_status(&mut self, flag: u16)712     fn set_slot_status(&mut self, flag: u16) {
713         self.slot_status |= flag;
714         if let Some(mapping) = self.cap_mapping.as_mut() {
715             mapping.set_reg(
716                 PCIE_SLTCTL_OFFSET / 4,
717                 (self.slot_status as u32) << 16,
718                 0xffff0000,
719             );
720         }
721     }
722 }
723 
724 const PCIE_CONFIG_READ_MASK: [u32; PCIE_CAP_LEN / 4] = {
725     let mut arr: [u32; PCIE_CAP_LEN / 4] = [0; PCIE_CAP_LEN / 4];
726     arr[PCIE_SLTCTL_OFFSET / 4] = 0xffffffff;
727     arr[PCIE_ROOTCTL_OFFSET / 4] = 0xffffffff;
728     arr[PCIE_ROOTSTA_OFFSET / 4] = 0xffffffff;
729     arr
730 };
731 
732 impl PciCapConfig for PcieConfig {
read_mask(&self) -> &'static [u32]733     fn read_mask(&self) -> &'static [u32] {
734         &PCIE_CONFIG_READ_MASK
735     }
736 
read_reg(&self, reg_idx: usize) -> u32737     fn read_reg(&self, reg_idx: usize) -> u32 {
738         let mut data = 0;
739         self.read_pcie_cap(reg_idx * 4, &mut data);
740         data
741     }
742 
write_reg( &mut self, reg_idx: usize, offset: u64, data: &[u8], ) -> Option<Box<dyn PciCapConfigWriteResult>>743     fn write_reg(
744         &mut self,
745         reg_idx: usize,
746         offset: u64,
747         data: &[u8],
748     ) -> Option<Box<dyn PciCapConfigWriteResult>> {
749         self.write_pcie_cap(reg_idx * 4 + offset as usize, data);
750         None
751     }
752 
set_cap_mapping(&mut self, mapping: PciCapMapping)753     fn set_cap_mapping(&mut self, mapping: PciCapMapping) {
754         self.cap_mapping = Some(mapping);
755     }
756 }
757 
758 /// Helper trait for implementing PcieDevice where most functions
759 /// are proxied directly to a PciePort instance.
760 pub trait PciePortVariant: Send {
get_pcie_port(&self) -> &PciePort761     fn get_pcie_port(&self) -> &PciePort;
get_pcie_port_mut(&mut self) -> &mut PciePort762     fn get_pcie_port_mut(&mut self) -> &mut PciePort;
763 
764     /// Called via PcieDevice.get_removed_devices
get_removed_devices_impl(&self) -> Vec<PciAddress>765     fn get_removed_devices_impl(&self) -> Vec<PciAddress>;
766 
767     /// Called via PcieDevice.hotplug_implemented
hotplug_implemented_impl(&self) -> bool768     fn hotplug_implemented_impl(&self) -> bool;
769 
770     /// Called via PcieDevice.hotplug
hotplugged_impl(&self) -> bool771     fn hotplugged_impl(&self) -> bool;
772 }
773 
774 impl<T: PciePortVariant> PcieDevice for T {
get_device_id(&self) -> u16775     fn get_device_id(&self) -> u16 {
776         self.get_pcie_port().get_device_id()
777     }
778 
debug_label(&self) -> String779     fn debug_label(&self) -> String {
780         self.get_pcie_port().debug_label()
781     }
782 
preferred_address(&self) -> Option<PciAddress>783     fn preferred_address(&self) -> Option<PciAddress> {
784         self.get_pcie_port().preferred_address()
785     }
786 
allocate_address( &mut self, resources: &mut SystemAllocator, ) -> std::result::Result<PciAddress, PciDeviceError>787     fn allocate_address(
788         &mut self,
789         resources: &mut SystemAllocator,
790     ) -> std::result::Result<PciAddress, PciDeviceError> {
791         self.get_pcie_port_mut().allocate_address(resources)
792     }
793 
clone_interrupt(&mut self, msi_config: Arc<Mutex<MsiConfig>>)794     fn clone_interrupt(&mut self, msi_config: Arc<Mutex<MsiConfig>>) {
795         self.get_pcie_port_mut().clone_interrupt(msi_config);
796     }
797 
read_config(&self, reg_idx: usize, data: &mut u32)798     fn read_config(&self, reg_idx: usize, data: &mut u32) {
799         self.get_pcie_port().read_config(reg_idx, data);
800     }
801 
write_config(&mut self, reg_idx: usize, offset: u64, data: &[u8])802     fn write_config(&mut self, reg_idx: usize, offset: u64, data: &[u8]) {
803         self.get_pcie_port_mut().write_config(reg_idx, offset, data);
804     }
805 
get_caps(&self) -> Vec<(Box<dyn PciCapability>, Option<Box<dyn PciCapConfig>>)>806     fn get_caps(&self) -> Vec<(Box<dyn PciCapability>, Option<Box<dyn PciCapConfig>>)> {
807         self.get_pcie_port().get_caps()
808     }
809 
handle_cap_write_result(&mut self, res: Box<dyn PciCapConfigWriteResult>)810     fn handle_cap_write_result(&mut self, res: Box<dyn PciCapConfigWriteResult>) {
811         self.get_pcie_port_mut().handle_cap_write_result(res)
812     }
813 
get_bus_range(&self) -> Option<PciBridgeBusRange>814     fn get_bus_range(&self) -> Option<PciBridgeBusRange> {
815         self.get_pcie_port().get_bus_range()
816     }
817 
get_removed_devices(&self) -> Vec<PciAddress>818     fn get_removed_devices(&self) -> Vec<PciAddress> {
819         self.get_removed_devices_impl()
820     }
821 
hotplug_implemented(&self) -> bool822     fn hotplug_implemented(&self) -> bool {
823         self.hotplug_implemented_impl()
824     }
825 
hotplugged(&self) -> bool826     fn hotplugged(&self) -> bool {
827         self.hotplugged_impl()
828     }
829 
get_bridge_window_size(&self) -> (u64, u64)830     fn get_bridge_window_size(&self) -> (u64, u64) {
831         self.get_pcie_port().get_bridge_window_size()
832     }
833 }
834