diff --git a/drivers/virt/coco/Kconfig b/drivers/virt/coco/Kconfig index d9ff676bf48d..a8c8e17d4ba2 100644 --- a/drivers/virt/coco/Kconfig +++ b/drivers/virt/coco/Kconfig @@ -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" diff --git a/drivers/virt/coco/Makefile b/drivers/virt/coco/Makefile index b69c30c1c720..0f48d0b18f1b 100644 --- a/drivers/virt/coco/Makefile +++ b/drivers/virt/coco/Makefile @@ -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/ diff --git a/drivers/virt/coco/gunyah-guest/Kconfig b/drivers/virt/coco/gunyah-guest/Kconfig new file mode 100644 index 000000000000..7e5ce657ab81 --- /dev/null +++ b/drivers/virt/coco/gunyah-guest/Kconfig @@ -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'. diff --git a/drivers/virt/coco/gunyah-guest/Makefile b/drivers/virt/coco/gunyah-guest/Makefile new file mode 100644 index 000000000000..0d71d1156737 --- /dev/null +++ b/drivers/virt/coco/gunyah-guest/Makefile @@ -0,0 +1,2 @@ +# SPDX-License-Identifier: GPL-2.0-only +obj-$(CONFIG_GUNYAH_GUEST) += gunyah-guest.o diff --git a/drivers/virt/coco/gunyah-guest/gunyah-guest.c b/drivers/virt/coco/gunyah-guest/gunyah-guest.c new file mode 100644 index 000000000000..b6c758eddc25 --- /dev/null +++ b/drivers/virt/coco/gunyah-guest/gunyah-guest.c @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved. */ + +#include +#include +#include + +#include + +#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);