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