ANDROID: Define mem_relinquish interface for releasing memory to a hypervisor.

On PKVM/ARM64 this uses the ARM SMCCC relinquish hypercall when available.

Bug: 240239989
Change-Id: Ifa85b641a48f348a2364cf8c6b06b6417f1eeedb
Signed-off-by: Keir Fraser <keirf@google.com>
Signed-off-by: Quentin Perret <qperret@google.com>
This commit is contained in:
Keir Fraser
2022-05-26 14:22:34 +00:00
committed by Quentin Perret
parent 4fc49028bb
commit 102dcecb67
8 changed files with 102 additions and 0 deletions

View File

@@ -1316,6 +1316,9 @@ config RELR
config ARCH_HAS_MEM_ENCRYPT
bool
config ARCH_HAS_MEM_RELINQUISH
bool
config ARCH_HAS_CC_PLATFORM
bool

View File

@@ -33,6 +33,7 @@ config ARM64
select ARCH_HAS_KEEPINITRD
select ARCH_HAS_MEMBARRIER_SYNC_CORE
select ARCH_HAS_MEM_ENCRYPT
select ARCH_HAS_MEM_RELINQUISH
select ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE
select ARCH_HAS_PTE_DEVMAP
select ARCH_HAS_PTE_SPECIAL

View File

@@ -10,4 +10,10 @@ void kvm_arm_init_hyp_services(void);
void kvm_init_memshare_services(void);
void kvm_init_ioremap_services(void);
#ifdef CONFIG_MEMORY_BALLOON
void kvm_init_memrelinquish_services(void);
#else
static inline void kvm_init_memrelinquish_services(void) {}
#endif
#endif

View File

@@ -0,0 +1,12 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (C) 2022 Google LLC
* Author: Keir Fraser <keirf@google.com>
*/
#ifndef __ASM_MEM_RELINQUISH_H
#define __ASM_MEM_RELINQUISH_H
void page_relinquish(struct page *page);
#endif /* __ASM_MEM_RELINQUISH_H */

View File

@@ -445,4 +445,5 @@ void kvm_arm_init_hyp_services(void)
{
kvm_init_ioremap_services();
kvm_init_memshare_services();
kvm_init_memrelinquish_services();
}

View File

@@ -3,6 +3,7 @@ obj-y := dma-mapping.o extable.o fault.o init.o \
cache.o copypage.o flush.o \
ioremap.o mem_encrypt.o mmap.o pgd.o mmu.o \
context.o proc.o pageattr.o
obj-$(CONFIG_MEMORY_BALLOON) += mem_relinquish.o
obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
obj-$(CONFIG_PTDUMP_CORE) += ptdump.o
obj-$(CONFIG_PTDUMP_DEBUGFS) += ptdump_debugfs.o

View File

@@ -0,0 +1,58 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (C) 2022 Google LLC
* Author: Keir Fraser <keirf@google.com>
*/
#include <linux/arm-smccc.h>
#include <linux/memory.h>
#include <linux/mm.h>
#include <linux/types.h>
#include <asm/hypervisor.h>
static unsigned long memshare_granule_sz;
void kvm_init_memrelinquish_services(void)
{
int i;
struct arm_smccc_res res;
const u32 funcs[] = {
ARM_SMCCC_KVM_FUNC_HYP_MEMINFO,
ARM_SMCCC_KVM_FUNC_MEM_RELINQUISH,
};
for (i = 0; i < ARRAY_SIZE(funcs); ++i) {
if (!kvm_arm_hyp_service_available(funcs[i]))
return;
}
arm_smccc_1_1_invoke(ARM_SMCCC_VENDOR_HYP_KVM_HYP_MEMINFO_FUNC_ID,
0, 0, 0, &res);
if (res.a0 > PAGE_SIZE) /* Includes error codes */
return;
memshare_granule_sz = res.a0;
}
void page_relinquish(struct page *page)
{
phys_addr_t phys, end;
u32 func_id = ARM_SMCCC_VENDOR_HYP_KVM_MEM_RELINQUISH_FUNC_ID;
if (!memshare_granule_sz)
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 += memshare_granule_sz;
}
}
EXPORT_SYMBOL_GPL(page_relinquish);

View File

@@ -0,0 +1,20 @@
/* 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__
#ifdef CONFIG_ARCH_HAS_MEM_RELINQUISH
#include <asm/mem_relinquish.h>
#else /* !CONFIG_ARCH_HAS_MEM_RELINQUISH */
static inline void page_relinquish(struct page *page) { }
#endif /* CONFIG_ARCH_HAS_MEM_RELINQUISH */
#endif /* __MEM_RELINQUISH_H__ */