ANDROID: virt: gunyah-guest: Add gunyah-guest

Add a Gunyah protected guest driver. A Gunyah protected guest needs to
be hypervisor-aware to relinquish pages to the host/owner for
virtio-balloon. In the Android Virtualization Framework model, the
host/owner VM, not the hypervisor, owns the virtio devices. The
hypervisor is unaware about the virtio device and thus the guest needs
to inform the hypervisor that the host can access guest-private memory.

Bug: 395833312
Change-Id: I082dff22d12453005728d229b87ef11a8dce9c6b
Signed-off-by: Elliot Berman <elliot.berman@oss.qualcomm.com>
Signed-off-by: Prakruthi Deepak Heragu <quic_pheragu@quicinc.com>
This commit is contained in:
Elliot Berman
2025-01-24 14:34:19 -08:00
committed by Todd Kjos
parent 8e6a22ec5d
commit 29fc73bbf2
5 changed files with 96 additions and 0 deletions
+2
View File
@@ -11,6 +11,8 @@ source "drivers/virt/coco/efi_secret/Kconfig"
source "drivers/virt/coco/pkvm-guest/Kconfig"
source "drivers/virt/coco/gunyah-guest/Kconfig"
source "drivers/virt/coco/sev-guest/Kconfig"
source "drivers/virt/coco/tdx-guest/Kconfig"
+1
View File
@@ -5,5 +5,6 @@
obj-$(CONFIG_TSM_REPORTS) += tsm.o
obj-$(CONFIG_EFI_SECRET) += efi_secret/
obj-$(CONFIG_ARM_PKVM_GUEST) += pkvm-guest/
obj-$(CONFIG_GUNYAH_GUEST) += gunyah-guest/
obj-$(CONFIG_SEV_GUEST) += sev-guest/
obj-$(CONFIG_INTEL_TDX_GUEST) += tdx-guest/
+12
View File
@@ -0,0 +1,12 @@
config GUNYAH_GUEST
bool "Gunyah protected guest driver"
depends on ARM64
select ARCH_HAS_MEM_RELINQUISH
select GUNYAH_HYPERCALLS
help
Protected guests running under the Gunyah hypervisor
are isolated from the host and must issue hypercalls to enable
interaction with virtual devices. This driver implements
support for probing and issuing these hypercalls.
If unsure, say 'N'.
+2
View File
@@ -0,0 +1,2 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_GUNYAH_GUEST) += gunyah-guest.o
@@ -0,0 +1,79 @@
// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved. */
#include <linux/gunyah.h>
#include <linux/init.h>
#include <linux/virtio_balloon.h>
#include <asm/hypervisor.h>
#define ADDRSPACE_INFO_AREA_ROOTVM_ADDRSPACE_CAP ((uint16_t)0)
struct addrspace_info_area_rootvm_addrspace_cap {
u64 addrspace_cap;
u32 rights;
u32 res0;
};
static u64 our_addrspace_capid;
#ifdef CONFIG_VIRTIO_BALLOON_HYP_OPS
static void gunyah_page_relinquish(struct page *page, unsigned int nr)
{
/* Release page to Host, so unlock and sanitize */
u64 flags = BIT_ULL(GUNYAH_ADDRSPC_MODIFY_FLAG_UNLOCK_BIT) |
BIT_ULL(GUNYAH_ADDRSPC_MODIFY_FLAG_SANITIZE_BIT);
phys_addr_t phys, end;
int ret = 0;
phys = page_to_phys(page);
end = phys + PAGE_SIZE * nr;
while (phys < end) {
ret = gunyah_hypercall_addrspc_modify_pages(our_addrspace_capid,
phys, PAGE_SIZE, flags);
if (ret)
pr_err_ratelimited("Failed to relinquish page: %016llx %d\n", phys, ret);
phys += PAGE_SIZE;
}
}
static void gunyah_post_page_relinquish_tlb_inv(void)
{
/* Release page to Host, so unlock and sanitize */
int ret = 0;
ret = gunyah_hypercall_addrspc_modify_pages(our_addrspace_capid, 0, 0, 0);
if (ret)
pr_err_ratelimited("Failed to flush tlb: %d\n", ret);
}
static struct virtio_balloon_hyp_ops gunyah_virtio_balloon_hyp_ops = {
.page_relinquish = gunyah_page_relinquish,
.post_page_relinquish_tlb_inv = gunyah_post_page_relinquish_tlb_inv
};
#endif
static int __init gunyah_guest_init(void)
{
struct addrspace_info_area_rootvm_addrspace_cap *info;
size_t size;
info = gunyah_get_info(GUNYAH_INFO_OWNER_ROOTVM, ADDRSPACE_INFO_AREA_ROOTVM_ADDRSPACE_CAP,
&size);
if (IS_ERR(info))
return PTR_ERR(info);
if (size != sizeof(*info))
return -EINVAL;
our_addrspace_capid = info->addrspace_cap;
#ifdef CONFIG_VIRTIO_BALLOON_HYP_OPS
virtio_balloon_hyp_ops = &gunyah_virtio_balloon_hyp_ops;
#endif
return 0;
}
core_initcall_sync(gunyah_guest_init);