ANDROID: KVM: Define mem_relinquish interface for releasing memory to a hypervisor.
On PKVM/ARM64 this uses the ARM SMCCC relinquish hypercall when available. Memory relinquish interface is used by both memory ballooning and by page reporting. It must be built if either is specified. Bug: 357781595 Change-Id: Ifa85b641a48f348a2364cf8c6b06b6417f1eeedb Signed-off-by: Keir Fraser <keirf@google.com>
This commit is contained in:
@@ -1517,6 +1517,9 @@ config RELR
|
||||
config ARCH_HAS_MEM_ENCRYPT
|
||||
bool
|
||||
|
||||
config ARCH_HAS_MEM_RELINQUISH
|
||||
bool
|
||||
|
||||
config ARCH_HAS_CC_PLATFORM
|
||||
bool
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
config ARM_PKVM_GUEST
|
||||
bool "Arm pKVM protected guest driver"
|
||||
depends on ARM64
|
||||
select ARCH_HAS_MEM_RELINQUISH
|
||||
help
|
||||
Protected guests running under the pKVM hypervisor on arm64
|
||||
are isolated from the host and must issue hypercalls to enable
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <linux/array_size.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/mem_encrypt.h>
|
||||
#include <linux/mem_relinquish.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/pgtable.h>
|
||||
|
||||
@@ -99,20 +100,40 @@ static int mmio_guard_ioremap_hook(phys_addr_t phys, size_t size,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MEMORY_RELINQUISH
|
||||
|
||||
static bool mem_relinquish_available;
|
||||
|
||||
void page_relinquish(struct page *page)
|
||||
{
|
||||
phys_addr_t phys, end;
|
||||
u32 func_id = ARM_SMCCC_VENDOR_HYP_KVM_MEM_RELINQUISH_FUNC_ID;
|
||||
|
||||
if (!mem_relinquish_available)
|
||||
return;
|
||||
|
||||
phys = page_to_phys(page);
|
||||
end = phys + PAGE_SIZE;
|
||||
|
||||
while (phys < end) {
|
||||
struct arm_smccc_res res;
|
||||
|
||||
arm_smccc_1_1_invoke(func_id, phys, 0, 0, &res);
|
||||
BUG_ON(res.a0 != SMCCC_RET_SUCCESS);
|
||||
|
||||
phys += pkvm_granule;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(page_relinquish);
|
||||
|
||||
#endif
|
||||
|
||||
void pkvm_init_hyp_services(void)
|
||||
{
|
||||
int i;
|
||||
struct arm_smccc_res res;
|
||||
const u32 funcs[] = {
|
||||
ARM_SMCCC_KVM_FUNC_HYP_MEMINFO,
|
||||
ARM_SMCCC_KVM_FUNC_MEM_SHARE,
|
||||
ARM_SMCCC_KVM_FUNC_MEM_UNSHARE,
|
||||
};
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(funcs); ++i) {
|
||||
if (!kvm_arm_hyp_service_available(funcs[i]))
|
||||
return;
|
||||
}
|
||||
if (!kvm_arm_hyp_service_available(ARM_SMCCC_KVM_FUNC_HYP_MEMINFO))
|
||||
return;
|
||||
|
||||
arm_smccc_1_1_invoke(ARM_SMCCC_VENDOR_HYP_KVM_HYP_MEMINFO_FUNC_ID,
|
||||
0, 0, 0, &res);
|
||||
@@ -120,8 +141,16 @@ void pkvm_init_hyp_services(void)
|
||||
return;
|
||||
|
||||
pkvm_granule = res.a0;
|
||||
arm64_mem_crypt_ops_register(&pkvm_crypt_ops);
|
||||
|
||||
if (kvm_arm_hyp_service_available(ARM_SMCCC_KVM_FUNC_MEM_SHARE) &&
|
||||
kvm_arm_hyp_service_available(ARM_SMCCC_KVM_FUNC_MEM_UNSHARE))
|
||||
arm64_mem_crypt_ops_register(&pkvm_crypt_ops);
|
||||
|
||||
if (kvm_arm_hyp_service_available(ARM_SMCCC_KVM_FUNC_MMIO_GUARD_MAP))
|
||||
arm64_ioremap_prot_hook_register(&mmio_guard_ioremap_hook);
|
||||
|
||||
#ifdef CONFIG_MEMORY_RELINQUISH
|
||||
if (kvm_arm_hyp_service_available(ARM_SMCCC_KVM_FUNC_MEM_RELINQUISH))
|
||||
mem_relinquish_available = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (C) 2022 Google LLC
|
||||
* Author: Keir Fraser <keirf@google.com>
|
||||
*/
|
||||
|
||||
#ifndef __MEM_RELINQUISH_H__
|
||||
#define __MEM_RELINQUISH_H__
|
||||
|
||||
struct page;
|
||||
|
||||
#ifdef CONFIG_MEMORY_RELINQUISH
|
||||
|
||||
void page_relinquish(struct page *page);
|
||||
|
||||
#else /* !CONFIG_MEMORY_RELINQUISH */
|
||||
|
||||
static inline void page_relinquish(struct page *page) { }
|
||||
|
||||
#endif /* CONFIG_MEMORY_RELINQUISH */
|
||||
|
||||
#endif /* __MEM_RELINQUISH_H__ */
|
||||
@@ -613,6 +613,13 @@ config SPLIT_PMD_PTLOCKS
|
||||
config MEMORY_BALLOON
|
||||
bool
|
||||
|
||||
#
|
||||
# support for memory relinquish
|
||||
config MEMORY_RELINQUISH
|
||||
def_bool y
|
||||
depends on ARCH_HAS_MEM_RELINQUISH
|
||||
depends on MEMORY_BALLOON || PAGE_REPORTING
|
||||
|
||||
#
|
||||
# support for memory balloon compaction
|
||||
config BALLOON_COMPACTION
|
||||
|
||||
Reference in New Issue
Block a user