xref: /aosp_15_r20/external/crosvm/devices/src/pmc_virt.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2023 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker 
5*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::Arc;
6*bb4ee6a4SAndroid Build Coastguard Worker 
7*bb4ee6a4SAndroid Build Coastguard Worker use acpi_tables::aml;
8*bb4ee6a4SAndroid Build Coastguard Worker use acpi_tables::aml::Aml;
9*bb4ee6a4SAndroid Build Coastguard Worker use base::warn;
10*bb4ee6a4SAndroid Build Coastguard Worker use sync::Condvar;
11*bb4ee6a4SAndroid Build Coastguard Worker use sync::Mutex;
12*bb4ee6a4SAndroid Build Coastguard Worker 
13*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::CrosvmDeviceId;
14*bb4ee6a4SAndroid Build Coastguard Worker use crate::BusAccessInfo;
15*bb4ee6a4SAndroid Build Coastguard Worker use crate::BusDevice;
16*bb4ee6a4SAndroid Build Coastguard Worker use crate::DeviceId;
17*bb4ee6a4SAndroid Build Coastguard Worker use crate::Suspendable;
18*bb4ee6a4SAndroid Build Coastguard Worker 
19*bb4ee6a4SAndroid Build Coastguard Worker /// PMC Virt MMIO offset
20*bb4ee6a4SAndroid Build Coastguard Worker const PMC_RESERVED1: u32 = 0;
21*bb4ee6a4SAndroid Build Coastguard Worker const _PMC_RESERVED2: u32 = 0x4;
22*bb4ee6a4SAndroid Build Coastguard Worker const _PMC_RESERVED3: u32 = 0x8;
23*bb4ee6a4SAndroid Build Coastguard Worker const _PMC_RESERVED4: u32 = 0xc;
24*bb4ee6a4SAndroid Build Coastguard Worker 
25*bb4ee6a4SAndroid Build Coastguard Worker pub const VPMC_VIRT_MMIO_SIZE: u64 = 0x10;
26*bb4ee6a4SAndroid Build Coastguard Worker 
27*bb4ee6a4SAndroid Build Coastguard Worker pub struct VirtualPmc {
28*bb4ee6a4SAndroid Build Coastguard Worker     mmio_base: u64,
29*bb4ee6a4SAndroid Build Coastguard Worker     guest_suspended_cvar: Arc<(Mutex<bool>, Condvar)>,
30*bb4ee6a4SAndroid Build Coastguard Worker }
31*bb4ee6a4SAndroid Build Coastguard Worker 
32*bb4ee6a4SAndroid Build Coastguard Worker impl VirtualPmc {
new(mmio_base: u64, guest_suspended_cvar: Arc<(Mutex<bool>, Condvar)>) -> Self33*bb4ee6a4SAndroid Build Coastguard Worker     pub fn new(mmio_base: u64, guest_suspended_cvar: Arc<(Mutex<bool>, Condvar)>) -> Self {
34*bb4ee6a4SAndroid Build Coastguard Worker         VirtualPmc {
35*bb4ee6a4SAndroid Build Coastguard Worker             mmio_base,
36*bb4ee6a4SAndroid Build Coastguard Worker             guest_suspended_cvar,
37*bb4ee6a4SAndroid Build Coastguard Worker         }
38*bb4ee6a4SAndroid Build Coastguard Worker     }
39*bb4ee6a4SAndroid Build Coastguard Worker }
40*bb4ee6a4SAndroid Build Coastguard Worker 
handle_s2idle_request(guest_suspended_cvar: &Arc<(Mutex<bool>, Condvar)>)41*bb4ee6a4SAndroid Build Coastguard Worker fn handle_s2idle_request(guest_suspended_cvar: &Arc<(Mutex<bool>, Condvar)>) {
42*bb4ee6a4SAndroid Build Coastguard Worker     // Wake up blocked thread on condvar, which is awaiting non-privileged guest suspension to
43*bb4ee6a4SAndroid Build Coastguard Worker     // finish.
44*bb4ee6a4SAndroid Build Coastguard Worker     let (lock, cvar) = &**guest_suspended_cvar;
45*bb4ee6a4SAndroid Build Coastguard Worker     let mut guest_suspended = lock.lock();
46*bb4ee6a4SAndroid Build Coastguard Worker     *guest_suspended = true;
47*bb4ee6a4SAndroid Build Coastguard Worker 
48*bb4ee6a4SAndroid Build Coastguard Worker     cvar.notify_one();
49*bb4ee6a4SAndroid Build Coastguard Worker }
50*bb4ee6a4SAndroid Build Coastguard Worker 
51*bb4ee6a4SAndroid Build Coastguard Worker impl BusDevice for VirtualPmc {
device_id(&self) -> DeviceId52*bb4ee6a4SAndroid Build Coastguard Worker     fn device_id(&self) -> DeviceId {
53*bb4ee6a4SAndroid Build Coastguard Worker         CrosvmDeviceId::VirtualPmc.into()
54*bb4ee6a4SAndroid Build Coastguard Worker     }
debug_label(&self) -> String55*bb4ee6a4SAndroid Build Coastguard Worker     fn debug_label(&self) -> String {
56*bb4ee6a4SAndroid Build Coastguard Worker         "PmcVirt".to_owned()
57*bb4ee6a4SAndroid Build Coastguard Worker     }
58*bb4ee6a4SAndroid Build Coastguard Worker 
read(&mut self, info: BusAccessInfo, data: &mut [u8])59*bb4ee6a4SAndroid Build Coastguard Worker     fn read(&mut self, info: BusAccessInfo, data: &mut [u8]) {
60*bb4ee6a4SAndroid Build Coastguard Worker         if data.len() != std::mem::size_of::<u32>() {
61*bb4ee6a4SAndroid Build Coastguard Worker             warn!(
62*bb4ee6a4SAndroid Build Coastguard Worker                 "{}: unsupported read length {}, only support 4bytes read",
63*bb4ee6a4SAndroid Build Coastguard Worker                 self.debug_label(),
64*bb4ee6a4SAndroid Build Coastguard Worker                 data.len()
65*bb4ee6a4SAndroid Build Coastguard Worker             );
66*bb4ee6a4SAndroid Build Coastguard Worker             return;
67*bb4ee6a4SAndroid Build Coastguard Worker         }
68*bb4ee6a4SAndroid Build Coastguard Worker 
69*bb4ee6a4SAndroid Build Coastguard Worker         warn!("{}: unsupported read address {}", self.debug_label(), info);
70*bb4ee6a4SAndroid Build Coastguard Worker     }
71*bb4ee6a4SAndroid Build Coastguard Worker 
write(&mut self, info: BusAccessInfo, data: &[u8])72*bb4ee6a4SAndroid Build Coastguard Worker     fn write(&mut self, info: BusAccessInfo, data: &[u8]) {
73*bb4ee6a4SAndroid Build Coastguard Worker         if data.len() != std::mem::size_of::<u32>() {
74*bb4ee6a4SAndroid Build Coastguard Worker             warn!(
75*bb4ee6a4SAndroid Build Coastguard Worker                 "{}: unsupported write length {}, only support 4bytes write",
76*bb4ee6a4SAndroid Build Coastguard Worker                 self.debug_label(),
77*bb4ee6a4SAndroid Build Coastguard Worker                 data.len()
78*bb4ee6a4SAndroid Build Coastguard Worker             );
79*bb4ee6a4SAndroid Build Coastguard Worker             return;
80*bb4ee6a4SAndroid Build Coastguard Worker         }
81*bb4ee6a4SAndroid Build Coastguard Worker 
82*bb4ee6a4SAndroid Build Coastguard Worker         match info.offset as u32 {
83*bb4ee6a4SAndroid Build Coastguard Worker             PMC_RESERVED1 => {
84*bb4ee6a4SAndroid Build Coastguard Worker                 handle_s2idle_request(&self.guest_suspended_cvar);
85*bb4ee6a4SAndroid Build Coastguard Worker             }
86*bb4ee6a4SAndroid Build Coastguard Worker             _ => {
87*bb4ee6a4SAndroid Build Coastguard Worker                 warn!("{}: Bad write to address {}", self.debug_label(), info);
88*bb4ee6a4SAndroid Build Coastguard Worker             }
89*bb4ee6a4SAndroid Build Coastguard Worker         };
90*bb4ee6a4SAndroid Build Coastguard Worker     }
91*bb4ee6a4SAndroid Build Coastguard Worker }
92*bb4ee6a4SAndroid Build Coastguard Worker 
93*bb4ee6a4SAndroid Build Coastguard Worker impl Aml for VirtualPmc {
to_aml_bytes(&self, bytes: &mut Vec<u8>)94*bb4ee6a4SAndroid Build Coastguard Worker     fn to_aml_bytes(&self, bytes: &mut Vec<u8>) {
95*bb4ee6a4SAndroid Build Coastguard Worker         let vpmc_uuid = "9ea49ba3-434a-49a6-be30-37cc55c4d397";
96*bb4ee6a4SAndroid Build Coastguard Worker         aml::Device::new(
97*bb4ee6a4SAndroid Build Coastguard Worker             "VPMC".into(),
98*bb4ee6a4SAndroid Build Coastguard Worker             vec![
99*bb4ee6a4SAndroid Build Coastguard Worker                 &aml::Name::new("_CID".into(), &aml::EISAName::new("PNP0D80")),
100*bb4ee6a4SAndroid Build Coastguard Worker                 &aml::Name::new("_HID".into(), &"HYPE0001"),
101*bb4ee6a4SAndroid Build Coastguard Worker                 &aml::Name::new("UUID".into(), &aml::Uuid::new(vpmc_uuid)),
102*bb4ee6a4SAndroid Build Coastguard Worker                 &aml::OpRegion::new(
103*bb4ee6a4SAndroid Build Coastguard Worker                     "VREG".into(),
104*bb4ee6a4SAndroid Build Coastguard Worker                     aml::OpRegionSpace::SystemMemory,
105*bb4ee6a4SAndroid Build Coastguard Worker                     &self.mmio_base,
106*bb4ee6a4SAndroid Build Coastguard Worker                     &(16_u32),
107*bb4ee6a4SAndroid Build Coastguard Worker                 ),
108*bb4ee6a4SAndroid Build Coastguard Worker                 &aml::Field::new(
109*bb4ee6a4SAndroid Build Coastguard Worker                     "VREG".into(),
110*bb4ee6a4SAndroid Build Coastguard Worker                     aml::FieldAccessType::DWord,
111*bb4ee6a4SAndroid Build Coastguard Worker                     aml::FieldLockRule::Lock,
112*bb4ee6a4SAndroid Build Coastguard Worker                     aml::FieldUpdateRule::Preserve,
113*bb4ee6a4SAndroid Build Coastguard Worker                     vec![aml::FieldEntry::Named(*b"RSV1", 32)],
114*bb4ee6a4SAndroid Build Coastguard Worker                 ),
115*bb4ee6a4SAndroid Build Coastguard Worker                 &aml::Method::new(
116*bb4ee6a4SAndroid Build Coastguard Worker                     "_DSM".into(),
117*bb4ee6a4SAndroid Build Coastguard Worker                     4,
118*bb4ee6a4SAndroid Build Coastguard Worker                     true,
119*bb4ee6a4SAndroid Build Coastguard Worker                     vec![
120*bb4ee6a4SAndroid Build Coastguard Worker                         &aml::If::new(
121*bb4ee6a4SAndroid Build Coastguard Worker                             &aml::Equal::new(&aml::Arg(0), &aml::Name::new_field_name("UUID")),
122*bb4ee6a4SAndroid Build Coastguard Worker                             vec![
123*bb4ee6a4SAndroid Build Coastguard Worker                                 &aml::If::new(
124*bb4ee6a4SAndroid Build Coastguard Worker                                     &aml::Equal::new(&aml::Arg(2), &aml::ZERO),
125*bb4ee6a4SAndroid Build Coastguard Worker                                     vec![&aml::Return::new(&aml::BufferData::new(vec![3]))],
126*bb4ee6a4SAndroid Build Coastguard Worker                                 ),
127*bb4ee6a4SAndroid Build Coastguard Worker                                 &aml::If::new(
128*bb4ee6a4SAndroid Build Coastguard Worker                                     &aml::Equal::new(&aml::Arg(2), &aml::ONE),
129*bb4ee6a4SAndroid Build Coastguard Worker                                     vec![&aml::Store::new(
130*bb4ee6a4SAndroid Build Coastguard Worker                                         &aml::Name::new_field_name("RSV1"),
131*bb4ee6a4SAndroid Build Coastguard Worker                                         &0x3_usize,
132*bb4ee6a4SAndroid Build Coastguard Worker                                     )],
133*bb4ee6a4SAndroid Build Coastguard Worker                                 ),
134*bb4ee6a4SAndroid Build Coastguard Worker                             ],
135*bb4ee6a4SAndroid Build Coastguard Worker                         ),
136*bb4ee6a4SAndroid Build Coastguard Worker                         &aml::Return::new(&aml::BufferData::new(vec![3])),
137*bb4ee6a4SAndroid Build Coastguard Worker                     ],
138*bb4ee6a4SAndroid Build Coastguard Worker                 ),
139*bb4ee6a4SAndroid Build Coastguard Worker             ],
140*bb4ee6a4SAndroid Build Coastguard Worker         )
141*bb4ee6a4SAndroid Build Coastguard Worker         .to_aml_bytes(bytes);
142*bb4ee6a4SAndroid Build Coastguard Worker     }
143*bb4ee6a4SAndroid Build Coastguard Worker }
144*bb4ee6a4SAndroid Build Coastguard Worker 
145*bb4ee6a4SAndroid Build Coastguard Worker impl Suspendable for VirtualPmc {}
146