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