blob: dc99303f05833a947b6ca370459bd99cc249cfed [file] [log] [blame]
Andrew Walbranba47d1d2022-12-14 15:21:44 +00001// Copyright 2022, 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 hypervisor.
16
17use crate::smccc::{self, checked_hvc64, checked_hvc64_expect_zero};
18use log::info;
19
Andrew Walbran41ebe932022-12-14 15:22:30 +000020const ARM_SMCCC_KVM_FUNC_HYP_MEMINFO: u32 = 0xc6000002;
21const ARM_SMCCC_KVM_FUNC_MEM_SHARE: u32 = 0xc6000003;
22const ARM_SMCCC_KVM_FUNC_MEM_UNSHARE: u32 = 0xc6000004;
Andrew Walbranba47d1d2022-12-14 15:21:44 +000023const VENDOR_HYP_KVM_MMIO_GUARD_INFO_FUNC_ID: u32 = 0xc6000005;
24const VENDOR_HYP_KVM_MMIO_GUARD_ENROLL_FUNC_ID: u32 = 0xc6000006;
25const VENDOR_HYP_KVM_MMIO_GUARD_MAP_FUNC_ID: u32 = 0xc6000007;
26const VENDOR_HYP_KVM_MMIO_GUARD_UNMAP_FUNC_ID: u32 = 0xc6000008;
27
Andrew Walbran41ebe932022-12-14 15:22:30 +000028/// Queries the memory protection parameters for a protected virtual machine.
29///
30/// Returns the memory protection granule size in bytes.
31pub fn hyp_meminfo() -> smccc::Result<u64> {
32 let args = [0u64; 17];
33 checked_hvc64(ARM_SMCCC_KVM_FUNC_HYP_MEMINFO, args)
34}
35
36/// Shares a region of memory with the KVM host, granting it read, write and execute permissions.
37/// The size of the region is equal to the memory protection granule returned by [`hyp_meminfo`].
38pub fn mem_share(base_ipa: u64) -> smccc::Result<()> {
39 let mut args = [0u64; 17];
40 args[0] = base_ipa;
41
42 checked_hvc64_expect_zero(ARM_SMCCC_KVM_FUNC_MEM_SHARE, args)
43}
44
45/// Revokes access permission from the KVM host to a memory region previously shared with
46/// [`mem_share`]. The size of the region is equal to the memory protection granule returned by
47/// [`hyp_meminfo`].
48pub fn mem_unshare(base_ipa: u64) -> smccc::Result<()> {
49 let mut args = [0u64; 17];
50 args[0] = base_ipa;
51
52 checked_hvc64_expect_zero(ARM_SMCCC_KVM_FUNC_MEM_UNSHARE, args)
53}
54
Andrew Walbranba47d1d2022-12-14 15:21:44 +000055pub fn mmio_guard_info() -> smccc::Result<u64> {
56 let args = [0u64; 17];
57
58 checked_hvc64(VENDOR_HYP_KVM_MMIO_GUARD_INFO_FUNC_ID, args)
59}
60
61pub fn mmio_guard_enroll() -> smccc::Result<()> {
62 let args = [0u64; 17];
63
64 checked_hvc64_expect_zero(VENDOR_HYP_KVM_MMIO_GUARD_ENROLL_FUNC_ID, args)
65}
66
67pub fn mmio_guard_map(ipa: u64) -> smccc::Result<()> {
68 let mut args = [0u64; 17];
69 args[0] = ipa;
70
71 // TODO(b/253586500): pKVM currently returns a i32 instead of a i64.
72 let is_i32_error_code = |n| u32::try_from(n).ok().filter(|v| (*v as i32) < 0).is_some();
73 match checked_hvc64_expect_zero(VENDOR_HYP_KVM_MMIO_GUARD_MAP_FUNC_ID, args) {
74 Err(smccc::Error::Unexpected(e)) if is_i32_error_code(e) => {
75 info!("Handled a pKVM bug by interpreting the MMIO_GUARD_MAP return value as i32");
76 match e as u32 as i32 {
77 -1 => Err(smccc::Error::NotSupported),
78 -2 => Err(smccc::Error::NotRequired),
79 -3 => Err(smccc::Error::InvalidParameter),
80 ret => Err(smccc::Error::Unknown(ret as i64)),
81 }
82 }
83 res => res,
84 }
85}
86
87pub fn mmio_guard_unmap(ipa: u64) -> smccc::Result<()> {
88 let mut args = [0u64; 17];
89 args[0] = ipa;
90
91 // TODO(b/251426790): pKVM currently returns NOT_SUPPORTED for SUCCESS.
92 match checked_hvc64_expect_zero(VENDOR_HYP_KVM_MMIO_GUARD_UNMAP_FUNC_ID, args) {
93 Err(smccc::Error::NotSupported) | Ok(_) => Ok(()),
94 x => x,
95 }
96}