• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2023, The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 //! Wrappers around calls to the GenieZone hypervisor.
16 
17 use core::fmt::{self, Display, Formatter};
18 
19 use super::{Hypervisor, MemSharingHypervisor, MmioGuardedHypervisor};
20 use crate::{
21     hyp::{Error, Result},
22     memory::page_4kb_of,
23 };
24 
25 use smccc::{
26     error::{positive_or_error_64, success_or_error_64},
27     hvc64,
28 };
29 use uuid::{uuid, Uuid};
30 
31 pub(super) struct GeniezoneHypervisor;
32 
33 const ARM_SMCCC_GZVM_FUNC_HYP_MEMINFO: u32 = 0xc6000002;
34 const ARM_SMCCC_GZVM_FUNC_MEM_SHARE: u32 = 0xc6000003;
35 const ARM_SMCCC_GZVM_FUNC_MEM_UNSHARE: u32 = 0xc6000004;
36 
37 const VENDOR_HYP_GZVM_MMIO_GUARD_INFO_FUNC_ID: u32 = 0xc6000005;
38 const VENDOR_HYP_GZVM_MMIO_GUARD_ENROLL_FUNC_ID: u32 = 0xc6000006;
39 const VENDOR_HYP_GZVM_MMIO_GUARD_MAP_FUNC_ID: u32 = 0xc6000007;
40 const VENDOR_HYP_GZVM_MMIO_GUARD_UNMAP_FUNC_ID: u32 = 0xc6000008;
41 
42 impl GeniezoneHypervisor {
43     // We generate this uuid by ourselves to identify GenieZone hypervisor
44     // and share the same identification along with guest VMs.
45     // The previous uuid was removed due to duplication elsewhere.
46     pub const UUID: Uuid = uuid!("7e134ed0-3b82-488d-8cee-69c19211dbe7");
47 }
48 
49 /// Error from a GenieZone HVC call.
50 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
51 pub enum GeniezoneError {
52     /// The call is not supported by the implementation.
53     NotSupported,
54     /// The call is not required to implement.
55     NotRequired,
56     /// One of the call parameters has a invalid value.
57     InvalidParameter,
58     /// There was an unexpected return value.
59     Unknown(i64),
60 }
61 
62 impl From<i64> for GeniezoneError {
from(value: i64) -> Self63     fn from(value: i64) -> Self {
64         match value {
65             -1 => GeniezoneError::NotSupported,
66             -2 => GeniezoneError::NotRequired,
67             -3 => GeniezoneError::InvalidParameter,
68             _ => GeniezoneError::Unknown(value),
69         }
70     }
71 }
72 
73 impl From<i32> for GeniezoneError {
from(value: i32) -> Self74     fn from(value: i32) -> Self {
75         i64::from(value).into()
76     }
77 }
78 
79 impl Display for GeniezoneError {
fmt(&self, f: &mut Formatter) -> fmt::Result80     fn fmt(&self, f: &mut Formatter) -> fmt::Result {
81         match self {
82             Self::NotSupported => write!(f, "GenieZone call not supported"),
83             Self::NotRequired => write!(f, "GenieZone call not required"),
84             Self::InvalidParameter => write!(f, "GenieZone call received invalid value"),
85             Self::Unknown(e) => write!(f, "Unknown return value from GenieZone {} ({0:#x})", e),
86         }
87     }
88 }
89 
90 impl Hypervisor for GeniezoneHypervisor {
as_mmio_guard(&self) -> Option<&dyn MmioGuardedHypervisor>91     fn as_mmio_guard(&self) -> Option<&dyn MmioGuardedHypervisor> {
92         Some(self)
93     }
94 
as_mem_sharer(&self) -> Option<&dyn MemSharingHypervisor>95     fn as_mem_sharer(&self) -> Option<&dyn MemSharingHypervisor> {
96         Some(self)
97     }
98 }
99 
100 impl MmioGuardedHypervisor for GeniezoneHypervisor {
enroll(&self) -> Result<()>101     fn enroll(&self) -> Result<()> {
102         let args = [0u64; 17];
103         match success_or_error_64(hvc64(VENDOR_HYP_GZVM_MMIO_GUARD_ENROLL_FUNC_ID, args)[0]) {
104             Ok(()) => Ok(()),
105             Err(GeniezoneError::NotSupported) | Err(GeniezoneError::NotRequired) => {
106                 Err(Error::MmioGuardNotSupported)
107             }
108             Err(e) => Err(Error::GeniezoneError(e, VENDOR_HYP_GZVM_MMIO_GUARD_ENROLL_FUNC_ID)),
109         }
110     }
111 
map(&self, addr: usize) -> Result<()>112     fn map(&self, addr: usize) -> Result<()> {
113         let mut args = [0u64; 17];
114         args[0] = page_4kb_of(addr).try_into().unwrap();
115 
116         checked_hvc64_expect_zero(VENDOR_HYP_GZVM_MMIO_GUARD_MAP_FUNC_ID, args)
117     }
118 
unmap(&self, addr: usize) -> Result<()>119     fn unmap(&self, addr: usize) -> Result<()> {
120         let mut args = [0u64; 17];
121         args[0] = page_4kb_of(addr).try_into().unwrap();
122 
123         checked_hvc64_expect_zero(VENDOR_HYP_GZVM_MMIO_GUARD_UNMAP_FUNC_ID, args)
124     }
125 
granule(&self) -> Result<usize>126     fn granule(&self) -> Result<usize> {
127         let args = [0u64; 17];
128         let granule = checked_hvc64(VENDOR_HYP_GZVM_MMIO_GUARD_INFO_FUNC_ID, args)?;
129         Ok(granule.try_into().unwrap())
130     }
131 }
132 
133 impl MemSharingHypervisor for GeniezoneHypervisor {
share(&self, base_ipa: u64) -> Result<()>134     fn share(&self, base_ipa: u64) -> Result<()> {
135         let mut args = [0u64; 17];
136         args[0] = base_ipa;
137 
138         checked_hvc64_expect_zero(ARM_SMCCC_GZVM_FUNC_MEM_SHARE, args)
139     }
140 
unshare(&self, base_ipa: u64) -> Result<()>141     fn unshare(&self, base_ipa: u64) -> Result<()> {
142         let mut args = [0u64; 17];
143         args[0] = base_ipa;
144 
145         checked_hvc64_expect_zero(ARM_SMCCC_GZVM_FUNC_MEM_UNSHARE, args)
146     }
147 
granule(&self) -> Result<usize>148     fn granule(&self) -> Result<usize> {
149         let args = [0u64; 17];
150         let granule = checked_hvc64(ARM_SMCCC_GZVM_FUNC_HYP_MEMINFO, args)?;
151         Ok(granule.try_into().unwrap())
152     }
153 }
154 
checked_hvc64_expect_zero(function: u32, args: [u64; 17]) -> Result<()>155 fn checked_hvc64_expect_zero(function: u32, args: [u64; 17]) -> Result<()> {
156     success_or_error_64(hvc64(function, args)[0]).map_err(|e| Error::GeniezoneError(e, function))
157 }
158 
checked_hvc64(function: u32, args: [u64; 17]) -> Result<u64>159 fn checked_hvc64(function: u32, args: [u64; 17]) -> Result<u64> {
160     positive_or_error_64(hvc64(function, args)[0]).map_err(|e| Error::GeniezoneError(e, function))
161 }
162