• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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::collections::BTreeMap;
6 #[cfg(feature = "direct")]
7 use std::fs;
8 #[cfg(feature = "direct")]
9 use std::io::Error as IoError;
10 #[cfg(feature = "direct")]
11 use std::path::PathBuf;
12 use std::str::FromStr;
13 use std::sync::Arc;
14 
15 use acpi_tables::aml;
16 use acpi_tables::aml::Aml;
17 use anyhow::Context;
18 use base::custom_serde::serialize_arc_mutex;
19 use base::error;
20 use base::warn;
21 use base::Error as SysError;
22 use base::Event;
23 use base::EventToken;
24 use base::SendTube;
25 use base::VmEventType;
26 use base::WaitContext;
27 use base::WorkerThread;
28 use serde::Deserialize;
29 use serde::Serialize;
30 use sync::Mutex;
31 use thiserror::Error;
32 use vm_control::GpeNotify;
33 use vm_control::PmResource;
34 use vm_control::PmeNotify;
35 
36 use crate::ac_adapter::AcAdapter;
37 use crate::pci::CrosvmDeviceId;
38 use crate::BusAccessInfo;
39 use crate::BusDevice;
40 use crate::BusResumeDevice;
41 use crate::DeviceId;
42 use crate::IrqLevelEvent;
43 use crate::Suspendable;
44 
45 #[derive(Error, Debug)]
46 pub enum ACPIPMError {
47     /// Creating WaitContext failed.
48     #[error("failed to create wait context: {0}")]
49     CreateWaitContext(SysError),
50     /// Error while waiting for events.
51     #[error("failed to wait for events: {0}")]
52     WaitError(SysError),
53     #[error("Did not find group_id corresponding to acpi_mc_group")]
54     AcpiMcGroupError,
55     #[error("Failed to create and bind NETLINK_GENERIC socket for acpi_mc_group: {0}")]
56     AcpiEventSockError(base::Error),
57     #[error("GPE {0} is out of bound")]
58     GpeOutOfBound(u32),
59 }
60 
61 #[derive(Debug, Copy, Clone, Serialize, Deserialize)]
62 pub enum ACPIPMFixedEvent {
63     GlobalLock,
64     PowerButton,
65     SleepButton,
66     RTC,
67 }
68 
69 #[derive(Serialize, Deserialize, Clone)]
70 pub(crate) struct Pm1Resource {
71     pub(crate) status: u16,
72     enable: u16,
73     control: u16,
74 }
75 
76 #[derive(Serialize, Deserialize, Clone)]
77 pub(crate) struct GpeResource {
78     pub(crate) status: [u8; ACPIPM_RESOURCE_GPE0_BLK_LEN as usize / 2],
79     enable: [u8; ACPIPM_RESOURCE_GPE0_BLK_LEN as usize / 2],
80     #[serde(skip_serializing, skip_deserializing)]
81     pub(crate) gpe_notify: BTreeMap<u32, Vec<Arc<Mutex<dyn GpeNotify>>>>,
82 }
83 
84 #[derive(Serialize, Deserialize, Clone)]
85 pub(crate) struct PciResource {
86     #[serde(skip_serializing, skip_deserializing)]
87     pub(crate) pme_notify: BTreeMap<u8, Vec<Arc<Mutex<dyn PmeNotify>>>>,
88 }
89 
90 #[cfg(feature = "direct")]
91 struct DirectGpe {
92     num: u32,
93     path: PathBuf,
94     ready: bool,
95     enabled: bool,
96 }
97 
98 #[cfg(feature = "direct")]
99 struct DirectFixedEvent {
100     evt: ACPIPMFixedEvent,
101     bitshift: u16,
102     path: PathBuf,
103     enabled: bool,
104 }
105 
106 /// ACPI PM resource for handling OS suspend/resume request
107 #[allow(dead_code)]
108 #[derive(Serialize)]
109 pub struct ACPIPMResource {
110     // This is SCI interrupt that will be raised in the VM.
111     #[serde(skip_serializing)]
112     sci_evt: IrqLevelEvent,
113     // This is the host SCI that is being handled by crosvm.
114     #[cfg(feature = "direct")]
115     #[serde(skip_serializing)]
116     sci_direct_evt: Option<IrqLevelEvent>,
117     #[cfg(feature = "direct")]
118     #[serde(skip_serializing)]
119     direct_gpe: Vec<DirectGpe>,
120     #[cfg(feature = "direct")]
121     #[serde(skip_serializing)]
122     direct_fixed_evts: Vec<DirectFixedEvent>,
123     #[serde(skip_serializing)]
124     worker_thread: Option<WorkerThread<()>>,
125     #[serde(skip_serializing)]
126     suspend_evt: Event,
127     #[serde(skip_serializing)]
128     exit_evt_wrtube: SendTube,
129     #[serde(serialize_with = "serialize_arc_mutex")]
130     pm1: Arc<Mutex<Pm1Resource>>,
131     #[serde(serialize_with = "serialize_arc_mutex")]
132     gpe0: Arc<Mutex<GpeResource>>,
133     #[serde(serialize_with = "serialize_arc_mutex")]
134     pci: Arc<Mutex<PciResource>>,
135     #[serde(skip_serializing)]
136     acdc: Option<Arc<Mutex<AcAdapter>>>,
137 }
138 
139 #[derive(Deserialize)]
140 struct ACPIPMResrourceSerializable {
141     pm1: Pm1Resource,
142     gpe0: GpeResource,
143 }
144 
145 impl ACPIPMResource {
146     /// Constructs ACPI Power Management Resouce.
147     ///
148     /// `direct_evt_info` - tuple of:
149     ///     1. host SCI trigger and resample events
150     ///     2. list of direct GPEs
151     ///     3. list of direct fixed events
152     #[allow(dead_code)]
new( sci_evt: IrqLevelEvent, #[cfg(feature = "direct")] direct_evt_info: Option<( IrqLevelEvent, &[u32], &[ACPIPMFixedEvent], )>, suspend_evt: Event, exit_evt_wrtube: SendTube, acdc: Option<Arc<Mutex<AcAdapter>>>, ) -> ACPIPMResource153     pub fn new(
154         sci_evt: IrqLevelEvent,
155         #[cfg(feature = "direct")] direct_evt_info: Option<(
156             IrqLevelEvent,
157             &[u32],
158             &[ACPIPMFixedEvent],
159         )>,
160         suspend_evt: Event,
161         exit_evt_wrtube: SendTube,
162         acdc: Option<Arc<Mutex<AcAdapter>>>,
163     ) -> ACPIPMResource {
164         let pm1 = Pm1Resource {
165             status: 0,
166             enable: 0,
167             control: 0,
168         };
169         let gpe0 = GpeResource {
170             status: Default::default(),
171             enable: Default::default(),
172             gpe_notify: BTreeMap::new(),
173         };
174         let pci = PciResource {
175             pme_notify: BTreeMap::new(),
176         };
177 
178         #[cfg(feature = "direct")]
179         let (sci_direct_evt, direct_gpe, direct_fixed_evts) = if let Some(info) = direct_evt_info {
180             let (evt, gpes, fixed_evts) = info;
181             let gpe_vec = gpes.iter().map(|gpe| DirectGpe::new(*gpe)).collect();
182             let fixed_evt_vec = fixed_evts
183                 .iter()
184                 .map(|evt| DirectFixedEvent::new(*evt))
185                 .collect();
186             (Some(evt), gpe_vec, fixed_evt_vec)
187         } else {
188             (None, Vec::new(), Vec::new())
189         };
190 
191         ACPIPMResource {
192             sci_evt,
193             #[cfg(feature = "direct")]
194             sci_direct_evt,
195             #[cfg(feature = "direct")]
196             direct_gpe,
197             #[cfg(feature = "direct")]
198             direct_fixed_evts,
199             worker_thread: None,
200             suspend_evt,
201             exit_evt_wrtube,
202             pm1: Arc::new(Mutex::new(pm1)),
203             gpe0: Arc::new(Mutex::new(gpe0)),
204             pci: Arc::new(Mutex::new(pci)),
205             acdc,
206         }
207     }
208 
start(&mut self)209     pub fn start(&mut self) {
210         let sci_evt = self.sci_evt.try_clone().expect("failed to clone event");
211         let pm1 = self.pm1.clone();
212         let gpe0 = self.gpe0.clone();
213         let acdc = self.acdc.clone();
214 
215         #[cfg(feature = "direct")]
216         let sci_direct_evt = self.sci_direct_evt.take();
217 
218         #[cfg(feature = "direct")]
219         // ACPI event listener is currently used only for notifying gpe_notify
220         // notifiers when a GPE is fired in the host. For direct forwarded GPEs,
221         // we notify gpe_notify in a different way, ensuring that the notifier
222         // completes synchronously before we inject the GPE into the guest.
223         // So tell ACPI event listener to ignore direct GPEs.
224         let acpi_event_ignored_gpe = self.direct_gpe.iter().map(|gpe| gpe.num).collect();
225 
226         #[cfg(not(feature = "direct"))]
227         let acpi_event_ignored_gpe = Vec::new();
228 
229         self.worker_thread = Some(WorkerThread::start("ACPI PM worker", move |kill_evt| {
230             if let Err(e) = run_worker(
231                 sci_evt,
232                 kill_evt,
233                 pm1,
234                 gpe0,
235                 acpi_event_ignored_gpe,
236                 #[cfg(feature = "direct")]
237                 sci_direct_evt,
238                 acdc,
239             ) {
240                 error!("{}", e);
241             }
242         }));
243     }
244 }
245 
246 impl Suspendable for ACPIPMResource {
snapshot(&self) -> anyhow::Result<serde_json::Value>247     fn snapshot(&self) -> anyhow::Result<serde_json::Value> {
248         serde_json::to_value(self)
249             .with_context(|| format!("error serializing {}", self.debug_label()))
250     }
251 
restore(&mut self, data: serde_json::Value) -> anyhow::Result<()>252     fn restore(&mut self, data: serde_json::Value) -> anyhow::Result<()> {
253         let acpi_snapshot: ACPIPMResrourceSerializable = serde_json::from_value(data)
254             .with_context(|| format!("error deserializing {}", self.debug_label()))?;
255         {
256             let mut pm1 = self.pm1.lock();
257             *pm1 = acpi_snapshot.pm1;
258         }
259         {
260             let mut gpe0 = self.gpe0.lock();
261             gpe0.status = acpi_snapshot.gpe0.status;
262             gpe0.enable = acpi_snapshot.gpe0.enable;
263         }
264         Ok(())
265     }
266 
sleep(&mut self) -> anyhow::Result<()>267     fn sleep(&mut self) -> anyhow::Result<()> {
268         if let Some(worker_thread) = self.worker_thread.take() {
269             worker_thread.stop();
270         }
271         Ok(())
272     }
273 
wake(&mut self) -> anyhow::Result<()>274     fn wake(&mut self) -> anyhow::Result<()> {
275         self.start();
276         Ok(())
277     }
278 }
279 
run_worker( sci_evt: IrqLevelEvent, kill_evt: Event, pm1: Arc<Mutex<Pm1Resource>>, gpe0: Arc<Mutex<GpeResource>>, acpi_event_ignored_gpe: Vec<u32>, #[cfg(feature = "direct")] sci_direct_evt: Option<IrqLevelEvent>, arced_ac_adapter: Option<Arc<Mutex<AcAdapter>>>, ) -> Result<(), ACPIPMError>280 fn run_worker(
281     sci_evt: IrqLevelEvent,
282     kill_evt: Event,
283     pm1: Arc<Mutex<Pm1Resource>>,
284     gpe0: Arc<Mutex<GpeResource>>,
285     acpi_event_ignored_gpe: Vec<u32>,
286     #[cfg(feature = "direct")] sci_direct_evt: Option<IrqLevelEvent>,
287     arced_ac_adapter: Option<Arc<Mutex<AcAdapter>>>,
288 ) -> Result<(), ACPIPMError> {
289     let acpi_event_sock = crate::sys::get_acpi_event_sock()?;
290     #[derive(EventToken)]
291     enum Token {
292         AcpiEvent,
293         InterruptResample,
294         #[cfg(feature = "direct")]
295         InterruptTriggerDirect,
296         Kill,
297     }
298 
299     let wait_ctx: WaitContext<Token> = WaitContext::build_with(&[
300         (sci_evt.get_resample(), Token::InterruptResample),
301         (&kill_evt, Token::Kill),
302     ])
303     .map_err(ACPIPMError::CreateWaitContext)?;
304     if let Some(acpi_event_sock) = &acpi_event_sock {
305         wait_ctx
306             .add(acpi_event_sock, Token::AcpiEvent)
307             .map_err(ACPIPMError::CreateWaitContext)?;
308     }
309 
310     #[cfg(feature = "direct")]
311     if let Some(ref evt) = sci_direct_evt {
312         wait_ctx
313             .add(evt.get_trigger(), Token::InterruptTriggerDirect)
314             .map_err(ACPIPMError::CreateWaitContext)?;
315     }
316 
317     #[cfg(feature = "direct")]
318     let mut pending_sci_direct: Option<&IrqLevelEvent> = None;
319 
320     loop {
321         let events = wait_ctx.wait().map_err(ACPIPMError::WaitError)?;
322         for event in events.iter().filter(|e| e.is_readable) {
323             match event.token {
324                 Token::AcpiEvent => {
325                     crate::sys::acpi_event_run(
326                         &sci_evt,
327                         &acpi_event_sock,
328                         &gpe0,
329                         &acpi_event_ignored_gpe,
330                         &arced_ac_adapter,
331                     );
332                 }
333                 Token::InterruptResample => {
334                     sci_evt.clear_resample();
335 
336                     #[cfg(feature = "direct")]
337                     if let Some(evt) = pending_sci_direct.take() {
338                         if let Err(e) = evt.trigger_resample() {
339                             error!("ACPIPM: failed to resample sci event: {}", e);
340                         }
341                     }
342 
343                     // Re-trigger SCI if PM1 or GPE status is still not cleared.
344                     pm1.lock().trigger_sci(&sci_evt);
345                     gpe0.lock().trigger_sci(&sci_evt);
346                 }
347                 #[cfg(feature = "direct")]
348                 Token::InterruptTriggerDirect => {
349                     if let Some(ref evt) = sci_direct_evt {
350                         evt.clear_trigger();
351 
352                         for (gpe, devs) in &gpe0.lock().gpe_notify {
353                             if DirectGpe::is_gpe_trigger(*gpe).unwrap_or(false) {
354                                 for dev in devs {
355                                     dev.lock().notify();
356                                 }
357                             }
358                         }
359 
360                         if let Err(e) = sci_evt.trigger() {
361                             error!("ACPIPM: failed to trigger sci event: {}", e);
362                         }
363                         pending_sci_direct = Some(evt);
364                     }
365                 }
366                 Token::Kill => return Ok(()),
367             }
368         }
369     }
370 }
371 
372 impl Pm1Resource {
trigger_sci(&self, sci_evt: &IrqLevelEvent)373     fn trigger_sci(&self, sci_evt: &IrqLevelEvent) {
374         if self.status & self.enable & ACPIPMFixedEvent::bitmask_all() != 0 {
375             if let Err(e) = sci_evt.trigger() {
376                 error!("ACPIPM: failed to trigger sci event for pm1: {}", e);
377             }
378         }
379     }
380 }
381 
382 impl GpeResource {
trigger_sci(&self, sci_evt: &IrqLevelEvent)383     pub fn trigger_sci(&self, sci_evt: &IrqLevelEvent) {
384         if (0..self.status.len()).any(|i| self.status[i] & self.enable[i] != 0) {
385             if let Err(e) = sci_evt.trigger() {
386                 error!("ACPIPM: failed to trigger sci event for gpe: {}", e);
387             }
388         }
389     }
390 
set_active(&mut self, gpe: u32) -> Result<(), ACPIPMError>391     pub fn set_active(&mut self, gpe: u32) -> Result<(), ACPIPMError> {
392         if let Some(status_byte) = self.status.get_mut(gpe as usize / 8) {
393             *status_byte |= 1 << (gpe % 8);
394         } else {
395             return Err(ACPIPMError::GpeOutOfBound(gpe));
396         }
397         Ok(())
398     }
399 }
400 
401 #[cfg(feature = "direct")]
402 impl DirectGpe {
new(gpe: u32) -> DirectGpe403     fn new(gpe: u32) -> DirectGpe {
404         DirectGpe {
405             num: gpe,
406             path: PathBuf::from("/sys/firmware/acpi/interrupts").join(format!("gpe{:02X}", gpe)),
407             ready: false,
408             enabled: false,
409         }
410     }
411 
is_status_set(&self) -> Result<bool, IoError>412     fn is_status_set(&self) -> Result<bool, IoError> {
413         match fs::read_to_string(&self.path) {
414             Err(e) => {
415                 error!("ACPIPM: failed to read gpe {} STS: {}", self.num, e);
416                 Err(e)
417             }
418             Ok(s) => Ok(s.split_whitespace().any(|s| s == "STS")),
419         }
420     }
421 
is_enabled(&self) -> Result<bool, IoError>422     fn is_enabled(&self) -> Result<bool, IoError> {
423         match fs::read_to_string(&self.path) {
424             Err(e) => {
425                 error!("ACPIPM: failed to read gpe {} EN: {}", self.num, e);
426                 Err(e)
427             }
428             Ok(s) => Ok(s.split_whitespace().any(|s| s == "EN")),
429         }
430     }
431 
clear(&self)432     fn clear(&self) {
433         if !self.is_status_set().unwrap_or(false) {
434             // Just to avoid harmless error messages due to clearing an already cleared GPE.
435             return;
436         }
437 
438         if let Err(e) = fs::write(&self.path, "clear\n") {
439             error!("ACPIPM: failed to clear gpe {}: {}", self.num, e);
440         }
441     }
442 
enable(&mut self)443     fn enable(&mut self) {
444         if self.enabled {
445             // Just to avoid harmless error messages due to enabling an already enabled GPE.
446             return;
447         }
448 
449         if !self.ready {
450             // The GPE is being enabled for the first time.
451             // Use "enable" to ensure the ACPICA's reference count for this GPE is > 0.
452             match fs::write(&self.path, "enable\n") {
453                 Err(e) => error!("ACPIPM: failed to enable gpe {}: {}", self.num, e),
454                 Ok(()) => {
455                     self.ready = true;
456                     self.enabled = true;
457                 }
458             }
459         } else {
460             // Use "unmask" instead of "enable", to bypass ACPICA's reference counting.
461             match fs::write(&self.path, "unmask\n") {
462                 Err(e) => error!("ACPIPM: failed to unmask gpe {}: {}", self.num, e),
463                 Ok(()) => {
464                     self.enabled = true;
465                 }
466             }
467         }
468     }
469 
disable(&mut self)470     fn disable(&mut self) {
471         if !self.enabled {
472             // Just to avoid harmless error messages due to disabling an already disabled GPE.
473             return;
474         }
475 
476         // Use "mask" instead of "disable", to bypass ACPICA's reference counting.
477         match fs::write(&self.path, "mask\n") {
478             Err(e) => error!("ACPIPM: failed to mask gpe {}: {}", self.num, e),
479             Ok(()) => {
480                 self.enabled = false;
481             }
482         }
483     }
484 
is_gpe_trigger(gpe: u32) -> Result<bool, IoError>485     fn is_gpe_trigger(gpe: u32) -> Result<bool, IoError> {
486         let path = PathBuf::from("/sys/firmware/acpi/interrupts").join(format!("gpe{:02X}", gpe));
487         let s = fs::read_to_string(&path)?;
488         let mut enable = false;
489         let mut status = false;
490         for itr in s.split_whitespace() {
491             match itr {
492                 "EN" => enable = true,
493                 "STS" => status = true,
494                 _ => (),
495             }
496         }
497 
498         Ok(enable && status)
499     }
500 }
501 
502 #[cfg(feature = "direct")]
503 impl DirectFixedEvent {
new(evt: ACPIPMFixedEvent) -> DirectFixedEvent504     fn new(evt: ACPIPMFixedEvent) -> DirectFixedEvent {
505         DirectFixedEvent {
506             evt,
507             bitshift: evt.bitshift(),
508             path: PathBuf::from("/sys/firmware/acpi/interrupts").join(match evt {
509                 ACPIPMFixedEvent::GlobalLock => "ff_gbl_lock",
510                 ACPIPMFixedEvent::PowerButton => "ff_pwr_btn",
511                 ACPIPMFixedEvent::SleepButton => "ff_slp_btn",
512                 ACPIPMFixedEvent::RTC => "ff_rt_clk",
513             }),
514             enabled: false,
515         }
516     }
517 
is_status_set(&self) -> Result<bool, IoError>518     fn is_status_set(&self) -> Result<bool, IoError> {
519         match fs::read_to_string(&self.path) {
520             Err(e) => {
521                 error!("ACPIPM: failed to read {:?} event STS: {}", self.evt, e);
522                 Err(e)
523             }
524             Ok(s) => Ok(s.split_whitespace().any(|s| s == "STS")),
525         }
526     }
527 
is_enabled(&self) -> Result<bool, IoError>528     fn is_enabled(&self) -> Result<bool, IoError> {
529         match fs::read_to_string(&self.path) {
530             Err(e) => {
531                 error!("ACPIPM: failed to read {:?} event EN: {}", self.evt, e);
532                 Err(e)
533             }
534             Ok(s) => Ok(s.split_whitespace().any(|s| s == "EN")),
535         }
536     }
537 
clear(&self)538     fn clear(&self) {
539         if !self.is_status_set().unwrap_or(false) {
540             // Just to avoid harmless error messages due to clearing an already cleared event.
541             return;
542         }
543 
544         if let Err(e) = fs::write(&self.path, "clear\n") {
545             error!("ACPIPM: failed to clear {:?} event: {}", self.evt, e);
546         }
547     }
548 
enable(&mut self)549     fn enable(&mut self) {
550         if self.enabled {
551             // Just to avoid harmless error messages due to enabling an already enabled event.
552             return;
553         }
554 
555         match fs::write(&self.path, "enable\n") {
556             Err(e) => error!("ACPIPM: failed to enable {:?} event: {}", self.evt, e),
557             Ok(()) => {
558                 self.enabled = true;
559             }
560         }
561     }
562 
disable(&mut self)563     fn disable(&mut self) {
564         if !self.enabled {
565             // Just to avoid harmless error messages due to disabling an already disabled event.
566             return;
567         }
568 
569         match fs::write(&self.path, "disable\n") {
570             Err(e) => error!("ACPIPM: failed to disable {:?} event: {}", self.evt, e),
571             Ok(()) => {
572                 self.enabled = false;
573             }
574         }
575     }
576 }
577 
578 /// the ACPI PM register length.
579 pub const ACPIPM_RESOURCE_EVENTBLK_LEN: u8 = 4;
580 pub const ACPIPM_RESOURCE_CONTROLBLK_LEN: u8 = 2;
581 pub const ACPIPM_RESOURCE_GPE0_BLK_LEN: u8 = 64;
582 pub const ACPIPM_RESOURCE_LEN: u8 = ACPIPM_RESOURCE_EVENTBLK_LEN + 4 + ACPIPM_RESOURCE_GPE0_BLK_LEN;
583 
584 // Should be in sync with gpe_allocator range
585 pub const ACPIPM_GPE_MAX: u16 = ACPIPM_RESOURCE_GPE0_BLK_LEN as u16 / 2 * 8 - 1;
586 
587 /// ACPI PM register value definitions
588 
589 /// 4.8.4.1.1 PM1 Status Registers, ACPI Spec Version 6.4
590 /// Register Location: <PM1a_EVT_BLK / PM1b_EVT_BLK> System I/O or Memory Space (defined in FADT)
591 /// Size: PM1_EVT_LEN / 2 (defined in FADT)
592 const PM1_STATUS: u16 = 0;
593 
594 /// 4.8.4.1.2 PM1Enable Registers, ACPI Spec Version 6.4
595 /// Register Location: <<PM1a_EVT_BLK / PM1b_EVT_BLK> + PM1_EVT_LEN / 2 System I/O or Memory Space
596 /// (defined in FADT)
597 /// Size: PM1_EVT_LEN / 2 (defined in FADT)
598 const PM1_ENABLE: u16 = PM1_STATUS + (ACPIPM_RESOURCE_EVENTBLK_LEN as u16 / 2);
599 
600 /// 4.8.4.2.1 PM1 Control Registers, ACPI Spec Version 6.4
601 /// Register Location: <PM1a_CNT_BLK / PM1b_CNT_BLK> System I/O or Memory Space (defined in FADT)
602 /// Size: PM1_CNT_LEN (defined in FADT)
603 const PM1_CONTROL: u16 = PM1_STATUS + ACPIPM_RESOURCE_EVENTBLK_LEN as u16;
604 
605 /// 4.8.5.1 General-Purpose Event Register Blocks, ACPI Spec Version 6.4
606 /// - Each register block contains two registers: an enable and a status register.
607 /// - Each register block is 32-bit aligned.
608 /// - Each register in the block is accessed as a byte.
609 
610 /// 4.8.5.1.1 General-Purpose Event 0 Register Block, ACPI Spec Version 6.4
611 /// This register block consists of two registers: The GPE0_STS and the GPE0_EN registers. Each
612 /// register’s length is defined to be half the length of the GPE0 register block, and is described
613 /// in the ACPI FADT’s GPE0_BLK and GPE0_BLK_LEN operators.
614 
615 /// 4.8.5.1.1.1 General-Purpose Event 0 Status Register, ACPI Spec Version 6.4
616 /// Register Location: <GPE0_STS> System I/O or System Memory Space (defined in FADT)
617 /// Size: GPE0_BLK_LEN/2 (defined in FADT)
618 const GPE0_STATUS: u16 = PM1_STATUS + ACPIPM_RESOURCE_EVENTBLK_LEN as u16 + 4; // ensure alignment
619 
620 /// 4.8.5.1.1.2 General-Purpose Event 0 Enable Register, ACPI Spec Version 6.4
621 /// Register Location: <GPE0_EN> System I/O or System Memory Space (defined in FADT)
622 /// Size: GPE0_BLK_LEN/2 (defined in FADT)
623 const GPE0_ENABLE: u16 = GPE0_STATUS + (ACPIPM_RESOURCE_GPE0_BLK_LEN as u16 / 2);
624 
625 /// 4.8.4.1.1, 4.8.4.1.2 Fixed event bits in both PM1 Status and PM1 Enable registers.
626 const BITSHIFT_PM1_GBL: u16 = 5;
627 const BITSHIFT_PM1_PWRBTN: u16 = 8;
628 const BITSHIFT_PM1_SLPBTN: u16 = 9;
629 const BITSHIFT_PM1_RTC: u16 = 10;
630 
631 const BITMASK_PM1CNT_SLEEP_ENABLE: u16 = 0x2000;
632 const BITMASK_PM1CNT_WAKE_STATUS: u16 = 0x8000;
633 
634 #[cfg(not(feature = "direct"))]
635 const BITMASK_PM1CNT_SLEEP_TYPE: u16 = 0x1C00;
636 #[cfg(not(feature = "direct"))]
637 const SLEEP_TYPE_S1: u16 = 1 << 10;
638 #[cfg(not(feature = "direct"))]
639 const SLEEP_TYPE_S5: u16 = 0 << 10;
640 
641 impl ACPIPMFixedEvent {
bitshift(self) -> u16642     fn bitshift(self) -> u16 {
643         match self {
644             ACPIPMFixedEvent::GlobalLock => BITSHIFT_PM1_GBL,
645             ACPIPMFixedEvent::PowerButton => BITSHIFT_PM1_PWRBTN,
646             ACPIPMFixedEvent::SleepButton => BITSHIFT_PM1_SLPBTN,
647             ACPIPMFixedEvent::RTC => BITSHIFT_PM1_RTC,
648         }
649     }
650 
bitmask(self) -> u16651     pub(crate) fn bitmask(self) -> u16 {
652         1 << self.bitshift()
653     }
654 
bitmask_all() -> u16655     fn bitmask_all() -> u16 {
656         (1 << BITSHIFT_PM1_GBL)
657             | (1 << BITSHIFT_PM1_PWRBTN)
658             | (1 << BITSHIFT_PM1_SLPBTN)
659             | (1 << BITSHIFT_PM1_RTC)
660     }
661 }
662 
663 impl FromStr for ACPIPMFixedEvent {
664     type Err = &'static str;
665 
from_str(s: &str) -> Result<Self, Self::Err>666     fn from_str(s: &str) -> Result<Self, Self::Err> {
667         match s {
668             "gbllock" => Ok(ACPIPMFixedEvent::GlobalLock),
669             "powerbtn" => Ok(ACPIPMFixedEvent::PowerButton),
670             "sleepbtn" => Ok(ACPIPMFixedEvent::SleepButton),
671             "rtc" => Ok(ACPIPMFixedEvent::RTC),
672             _ => Err("unknown event, must be: gbllock|powerbtn|sleepbtn|rtc"),
673         }
674     }
675 }
676 
677 impl PmResource for ACPIPMResource {
pwrbtn_evt(&mut self)678     fn pwrbtn_evt(&mut self) {
679         let mut pm1 = self.pm1.lock();
680 
681         pm1.status |= ACPIPMFixedEvent::PowerButton.bitmask();
682         pm1.trigger_sci(&self.sci_evt);
683     }
684 
slpbtn_evt(&mut self)685     fn slpbtn_evt(&mut self) {
686         let mut pm1 = self.pm1.lock();
687 
688         pm1.status |= ACPIPMFixedEvent::SleepButton.bitmask();
689         pm1.trigger_sci(&self.sci_evt);
690     }
691 
rtc_evt(&mut self)692     fn rtc_evt(&mut self) {
693         let mut pm1 = self.pm1.lock();
694 
695         pm1.status |= ACPIPMFixedEvent::RTC.bitmask();
696         pm1.trigger_sci(&self.sci_evt);
697     }
698 
gpe_evt(&mut self, gpe: u32)699     fn gpe_evt(&mut self, gpe: u32) {
700         let mut gpe0 = self.gpe0.lock();
701 
702         match gpe0.set_active(gpe) {
703             Ok(_) => gpe0.trigger_sci(&self.sci_evt),
704             Err(e) => error!("{}", e),
705         }
706     }
707 
pme_evt(&mut self, requester_id: u16)708     fn pme_evt(&mut self, requester_id: u16) {
709         let bus = ((requester_id >> 8) & 0xFF) as u8;
710         let mut pci = self.pci.lock();
711         if let Some(root_ports) = pci.pme_notify.get_mut(&bus) {
712             for root_port in root_ports {
713                 root_port.lock().notify(requester_id);
714             }
715         }
716     }
717 
register_gpe_notify_dev(&mut self, gpe: u32, notify_dev: Arc<Mutex<dyn GpeNotify>>)718     fn register_gpe_notify_dev(&mut self, gpe: u32, notify_dev: Arc<Mutex<dyn GpeNotify>>) {
719         let mut gpe0 = self.gpe0.lock();
720         match gpe0.gpe_notify.get_mut(&gpe) {
721             Some(v) => v.push(notify_dev),
722             None => {
723                 gpe0.gpe_notify.insert(gpe, vec![notify_dev]);
724             }
725         }
726     }
727 
register_pme_notify_dev(&mut self, bus: u8, notify_dev: Arc<Mutex<dyn PmeNotify>>)728     fn register_pme_notify_dev(&mut self, bus: u8, notify_dev: Arc<Mutex<dyn PmeNotify>>) {
729         let mut pci = self.pci.lock();
730         match pci.pme_notify.get_mut(&bus) {
731             Some(v) => v.push(notify_dev),
732             None => {
733                 pci.pme_notify.insert(bus, vec![notify_dev]);
734             }
735         }
736     }
737 }
738 
739 const PM1_STATUS_LAST: u16 = PM1_STATUS + (ACPIPM_RESOURCE_EVENTBLK_LEN as u16 / 2) - 1;
740 const PM1_ENABLE_LAST: u16 = PM1_ENABLE + (ACPIPM_RESOURCE_EVENTBLK_LEN as u16 / 2) - 1;
741 const PM1_CONTROL_LAST: u16 = PM1_CONTROL + ACPIPM_RESOURCE_CONTROLBLK_LEN as u16 - 1;
742 const GPE0_STATUS_LAST: u16 = GPE0_STATUS + (ACPIPM_RESOURCE_GPE0_BLK_LEN as u16 / 2) - 1;
743 const GPE0_ENABLE_LAST: u16 = GPE0_ENABLE + (ACPIPM_RESOURCE_GPE0_BLK_LEN as u16 / 2) - 1;
744 
745 impl BusDevice for ACPIPMResource {
device_id(&self) -> DeviceId746     fn device_id(&self) -> DeviceId {
747         CrosvmDeviceId::ACPIPMResource.into()
748     }
749 
debug_label(&self) -> String750     fn debug_label(&self) -> String {
751         "ACPIPMResource".to_owned()
752     }
753 
read(&mut self, info: BusAccessInfo, data: &mut [u8])754     fn read(&mut self, info: BusAccessInfo, data: &mut [u8]) {
755         match info.offset as u16 {
756             // Accesses to the PM1 registers are done through byte or word accesses
757             PM1_STATUS..=PM1_STATUS_LAST => {
758                 if data.len() > std::mem::size_of::<u16>()
759                     || info.offset + data.len() as u64 > (PM1_STATUS_LAST + 1).into()
760                 {
761                     warn!("ACPIPM: bad read size: {}", data.len());
762                     return;
763                 }
764                 let offset = (info.offset - PM1_STATUS as u64) as usize;
765 
766                 let v = self.pm1.lock().status.to_ne_bytes();
767                 for (i, j) in (offset..offset + data.len()).enumerate() {
768                     data[i] = v[j];
769 
770                     #[cfg(feature = "direct")]
771                     for evt in self
772                         .direct_fixed_evts
773                         .iter()
774                         .filter(|evt| evt.bitshift / 8 == j as u16)
775                     {
776                         data[i] &= !(1 << (evt.bitshift % 8));
777                         if evt.is_status_set().unwrap_or(false) {
778                             data[i] |= 1 << (evt.bitshift % 8);
779                         }
780                     }
781                 }
782             }
783             PM1_ENABLE..=PM1_ENABLE_LAST => {
784                 if data.len() > std::mem::size_of::<u16>()
785                     || info.offset + data.len() as u64 > (PM1_ENABLE_LAST + 1).into()
786                 {
787                     warn!("ACPIPM: bad read size: {}", data.len());
788                     return;
789                 }
790                 let offset = (info.offset - PM1_ENABLE as u64) as usize;
791 
792                 let v = self.pm1.lock().enable.to_ne_bytes();
793                 for (i, j) in (offset..offset + data.len()).enumerate() {
794                     data[i] = v[j];
795 
796                     #[cfg(feature = "direct")]
797                     for evt in self
798                         .direct_fixed_evts
799                         .iter()
800                         .filter(|evt| evt.bitshift / 8 == j as u16)
801                     {
802                         data[i] &= !(1 << (evt.bitshift % 8));
803                         if evt.is_enabled().unwrap_or(false) {
804                             data[i] |= 1 << (evt.bitshift % 8);
805                         }
806                     }
807                 }
808             }
809             PM1_CONTROL..=PM1_CONTROL_LAST => {
810                 if data.len() > std::mem::size_of::<u16>()
811                     || info.offset + data.len() as u64 > (PM1_CONTROL_LAST + 1).into()
812                 {
813                     warn!("ACPIPM: bad read size: {}", data.len());
814                     return;
815                 }
816                 let offset = (info.offset - PM1_CONTROL as u64) as usize;
817                 data.copy_from_slice(
818                     &self.pm1.lock().control.to_ne_bytes()[offset..offset + data.len()],
819                 );
820             }
821             // OSPM accesses GPE registers through byte accesses (regardless of their length)
822             GPE0_STATUS..=GPE0_STATUS_LAST => {
823                 if data.len() > std::mem::size_of::<u8>()
824                     || info.offset + data.len() as u64 > (GPE0_STATUS_LAST + 1).into()
825                 {
826                     warn!("ACPIPM: bad read size: {}", data.len());
827                     return;
828                 }
829                 let offset = (info.offset - GPE0_STATUS as u64) as usize;
830                 data[0] = self.gpe0.lock().status[offset];
831 
832                 #[cfg(feature = "direct")]
833                 for gpe in self
834                     .direct_gpe
835                     .iter()
836                     .filter(|gpe| gpe.num / 8 == offset as u32)
837                 {
838                     data[0] &= !(1 << (gpe.num % 8));
839                     if gpe.is_status_set().unwrap_or(false) {
840                         data[0] |= 1 << (gpe.num % 8);
841                     }
842                 }
843             }
844             GPE0_ENABLE..=GPE0_ENABLE_LAST => {
845                 if data.len() > std::mem::size_of::<u8>()
846                     || info.offset + data.len() as u64 > (GPE0_ENABLE_LAST + 1).into()
847                 {
848                     warn!("ACPIPM: bad read size: {}", data.len());
849                     return;
850                 }
851                 let offset = (info.offset - GPE0_ENABLE as u64) as usize;
852                 data[0] = self.gpe0.lock().enable[offset];
853 
854                 #[cfg(feature = "direct")]
855                 for gpe in self
856                     .direct_gpe
857                     .iter()
858                     .filter(|gpe| gpe.num / 8 == offset as u32)
859                 {
860                     data[0] &= !(1 << (gpe.num % 8));
861                     if gpe.is_enabled().unwrap_or(false) {
862                         data[0] |= 1 << (gpe.num % 8);
863                     }
864                 }
865             }
866             _ => {
867                 warn!("ACPIPM: Bad read from {}", info);
868             }
869         }
870     }
871 
write(&mut self, info: BusAccessInfo, data: &[u8])872     fn write(&mut self, info: BusAccessInfo, data: &[u8]) {
873         match info.offset as u16 {
874             // Accesses to the PM1 registers are done through byte or word accesses
875             PM1_STATUS..=PM1_STATUS_LAST => {
876                 if data.len() > std::mem::size_of::<u16>()
877                     || info.offset + data.len() as u64 > (PM1_STATUS_LAST + 1).into()
878                 {
879                     warn!("ACPIPM: bad write size: {}", data.len());
880                     return;
881                 }
882                 let offset = (info.offset - PM1_STATUS as u64) as usize;
883 
884                 let mut pm1 = self.pm1.lock();
885                 let mut v = pm1.status.to_ne_bytes();
886                 for (i, j) in (offset..offset + data.len()).enumerate() {
887                     #[cfg(feature = "direct")]
888                     for evt in self
889                         .direct_fixed_evts
890                         .iter()
891                         .filter(|evt| evt.bitshift / 8 == j as u16)
892                     {
893                         if data[i] & (1 << (evt.bitshift % 8)) != 0 {
894                             evt.clear();
895                         }
896                     }
897 
898                     v[j] &= !data[i];
899                 }
900                 pm1.status = u16::from_ne_bytes(v);
901             }
902             PM1_ENABLE..=PM1_ENABLE_LAST => {
903                 if data.len() > std::mem::size_of::<u16>()
904                     || info.offset + data.len() as u64 > (PM1_ENABLE_LAST + 1).into()
905                 {
906                     warn!("ACPIPM: bad write size: {}", data.len());
907                     return;
908                 }
909                 let offset = (info.offset - PM1_ENABLE as u64) as usize;
910 
911                 let mut pm1 = self.pm1.lock();
912                 let mut v = pm1.enable.to_ne_bytes();
913                 for (i, j) in (offset..offset + data.len()).enumerate() {
914                     #[cfg(feature = "direct")]
915                     for evt in self
916                         .direct_fixed_evts
917                         .iter_mut()
918                         .filter(|evt| evt.bitshift / 8 == j as u16)
919                     {
920                         if data[i] & (1 << (evt.bitshift % 8)) != 0 {
921                             evt.enable();
922                         } else {
923                             evt.disable();
924                         }
925                     }
926 
927                     v[j] = data[i];
928                 }
929                 pm1.enable = u16::from_ne_bytes(v);
930                 pm1.trigger_sci(&self.sci_evt);
931             }
932             PM1_CONTROL..=PM1_CONTROL_LAST => {
933                 if data.len() > std::mem::size_of::<u16>()
934                     || info.offset + data.len() as u64 > (PM1_CONTROL_LAST + 1).into()
935                 {
936                     warn!("ACPIPM: bad write size: {}", data.len());
937                     return;
938                 }
939                 let offset = (info.offset - PM1_CONTROL as u64) as usize;
940 
941                 let mut pm1 = self.pm1.lock();
942 
943                 let mut v = pm1.control.to_ne_bytes();
944                 for (i, j) in (offset..offset + data.len()).enumerate() {
945                     v[j] = data[i];
946                 }
947                 let val = u16::from_ne_bytes(v);
948 
949                 // SLP_EN is a write-only bit and reads to it always return a zero
950                 if (val & BITMASK_PM1CNT_SLEEP_ENABLE) != 0 {
951                     // only support S5 in direct mode
952                     #[cfg(feature = "direct")]
953                     if let Err(e) = self.exit_evt_wrtube.send::<VmEventType>(&VmEventType::Exit) {
954                         error!("ACPIPM: failed to trigger exit event: {}", e);
955                     }
956                     #[cfg(not(feature = "direct"))]
957                     match val & BITMASK_PM1CNT_SLEEP_TYPE {
958                         SLEEP_TYPE_S1 => {
959                             if let Err(e) = self.suspend_evt.signal() {
960                                 error!("ACPIPM: failed to trigger suspend event: {}", e);
961                             }
962                         }
963                         SLEEP_TYPE_S5 => {
964                             if let Err(e) =
965                                 self.exit_evt_wrtube.send::<VmEventType>(&VmEventType::Exit)
966                             {
967                                 error!("ACPIPM: failed to trigger exit event: {}", e);
968                             }
969                         }
970                         _ => error!(
971                             "ACPIPM: unknown SLP_TYP written: {}",
972                             (val & BITMASK_PM1CNT_SLEEP_TYPE) >> 10
973                         ),
974                     }
975                 }
976                 pm1.control = val & !BITMASK_PM1CNT_SLEEP_ENABLE;
977             }
978             // OSPM accesses GPE registers through byte accesses (regardless of their length)
979             GPE0_STATUS..=GPE0_STATUS_LAST => {
980                 if data.len() > std::mem::size_of::<u8>()
981                     || info.offset + data.len() as u64 > (GPE0_STATUS_LAST + 1).into()
982                 {
983                     warn!("ACPIPM: bad write size: {}", data.len());
984                     return;
985                 }
986                 let offset = (info.offset - GPE0_STATUS as u64) as usize;
987 
988                 #[cfg(feature = "direct")]
989                 for gpe in self
990                     .direct_gpe
991                     .iter()
992                     .filter(|gpe| gpe.num / 8 == offset as u32)
993                 {
994                     if data[0] & (1 << (gpe.num % 8)) != 0 {
995                         gpe.clear();
996                     }
997                 }
998 
999                 self.gpe0.lock().status[offset] &= !data[0];
1000             }
1001             GPE0_ENABLE..=GPE0_ENABLE_LAST => {
1002                 if data.len() > std::mem::size_of::<u8>()
1003                     || info.offset + data.len() as u64 > (GPE0_ENABLE_LAST + 1).into()
1004                 {
1005                     warn!("ACPIPM: bad write size: {}", data.len());
1006                     return;
1007                 }
1008                 let offset = (info.offset - GPE0_ENABLE as u64) as usize;
1009 
1010                 #[cfg(feature = "direct")]
1011                 for gpe in self
1012                     .direct_gpe
1013                     .iter_mut()
1014                     .filter(|gpe| gpe.num / 8 == offset as u32)
1015                 {
1016                     if data[0] & (1 << (gpe.num % 8)) != 0 {
1017                         gpe.enable();
1018                     } else {
1019                         gpe.disable();
1020                     }
1021                 }
1022 
1023                 let mut gpe = self.gpe0.lock();
1024                 gpe.enable[offset] = data[0];
1025                 gpe.trigger_sci(&self.sci_evt);
1026             }
1027             _ => {
1028                 warn!("ACPIPM: Bad write to {}", info);
1029             }
1030         };
1031     }
1032 }
1033 
1034 impl BusResumeDevice for ACPIPMResource {
resume_imminent(&mut self)1035     fn resume_imminent(&mut self) {
1036         self.pm1.lock().status |= BITMASK_PM1CNT_WAKE_STATUS;
1037     }
1038 }
1039 
1040 impl Aml for ACPIPMResource {
to_aml_bytes(&self, bytes: &mut Vec<u8>)1041     fn to_aml_bytes(&self, bytes: &mut Vec<u8>) {
1042         // S1
1043         aml::Name::new(
1044             "_S1_".into(),
1045             &aml::Package::new(vec![&aml::ONE, &aml::ONE, &aml::ZERO, &aml::ZERO]),
1046         )
1047         .to_aml_bytes(bytes);
1048 
1049         // S5
1050         aml::Name::new(
1051             "_S5_".into(),
1052             &aml::Package::new(vec![&aml::ZERO, &aml::ZERO, &aml::ZERO, &aml::ZERO]),
1053         )
1054         .to_aml_bytes(bytes);
1055     }
1056 }
1057 
1058 #[cfg(test)]
1059 mod tests {
1060     use base::SendTube;
1061     use base::Tube;
1062 
1063     use super::*;
1064     use crate::suspendable_tests;
1065 
get_evt_tube() -> SendTube1066     fn get_evt_tube() -> SendTube {
1067         let (vm_evt_wrtube, _) = Tube::directional_pair().unwrap();
1068         vm_evt_wrtube
1069     }
1070 
get_irq_evt() -> IrqLevelEvent1071     fn get_irq_evt() -> IrqLevelEvent {
1072         match crate::IrqLevelEvent::new() {
1073             Ok(evt) => evt,
1074             Err(e) => panic!(
1075                 "failed to create irqlevelevt: {} - panic. Can't test ACPI",
1076                 e
1077             ),
1078         }
1079     }
1080 
modify_device(acpi: &mut ACPIPMResource)1081     fn modify_device(acpi: &mut ACPIPMResource) {
1082         {
1083             let mut pm1 = acpi.pm1.lock();
1084             pm1.enable += 1;
1085         }
1086     }
1087 
1088     suspendable_tests!(
1089         acpi,
1090         ACPIPMResource::new(
1091             get_irq_evt(),
1092             #[cfg(feature = "direct")]
1093             None,
1094             Event::new().unwrap(),
1095             get_evt_tube(),
1096             None,
1097         ),
1098         modify_device
1099     );
1100 }
1101