ANDROID: KVM: arm64: Donate device MMIO before assignment
Implement new KVM arch functions to donate/reclaim devices/groups. Bug: 357781595 Bug: 348382247 Change-Id: Ida0066127d6019cec505309e41525c4ba0f56292 Signed-off-by: Mostafa Saleh <smostafa@google.com>
This commit is contained in:
@@ -1709,4 +1709,6 @@ static inline void kvm_iommu_sg_free(struct kvm_iommu_sg *sg, unsigned int nents
|
||||
int kvm_iommu_share_hyp_sg(struct kvm_iommu_sg *sg, unsigned int nents);
|
||||
int kvm_iommu_unshare_hyp_sg(struct kvm_iommu_sg *sg, unsigned int nents);
|
||||
|
||||
#define __KVM_HAVE_ARCH_ASSIGNED_DEVICE_GROUP
|
||||
|
||||
#endif /* __ARM64_KVM_HOST_H__ */
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/iommu.h>
|
||||
#include <linux/kmemleak.h>
|
||||
#include <linux/kvm_host.h>
|
||||
#include <linux/memblock.h>
|
||||
@@ -14,6 +15,7 @@
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_fdt.h>
|
||||
#include <linux/of_reserved_mem.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/sort.h>
|
||||
|
||||
#include <asm/kvm_host.h>
|
||||
@@ -1424,3 +1426,104 @@ int __pkvm_topup_hyp_alloc_mgt_gfp(unsigned long id, unsigned long nr_pages,
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(__pkvm_topup_hyp_alloc_mgt_gfp);
|
||||
|
||||
static int __pkvm_donate_resource(struct resource *r)
|
||||
{
|
||||
if (!PAGE_ALIGNED(resource_size(r)) || !PAGE_ALIGNED(r->start))
|
||||
return -EINVAL;
|
||||
|
||||
return kvm_call_hyp_nvhe(__pkvm_host_donate_hyp_mmio,
|
||||
__phys_to_pfn(r->start),
|
||||
resource_size(r) >> PAGE_SHIFT);
|
||||
|
||||
}
|
||||
|
||||
static int __pkvm_reclaim_resource(struct resource *r)
|
||||
{
|
||||
if (!PAGE_ALIGNED(resource_size(r)) || !PAGE_ALIGNED(r->start))
|
||||
return -EINVAL;
|
||||
|
||||
return kvm_call_hyp_nvhe(__pkvm_host_reclaim_hyp_mmio,
|
||||
__phys_to_pfn(r->start),
|
||||
resource_size(r) >> PAGE_SHIFT);
|
||||
}
|
||||
|
||||
static int __pkvm_arch_assign_device(struct device *dev, void *data)
|
||||
{
|
||||
struct platform_device *pdev;
|
||||
struct resource *r;
|
||||
int index = 0;
|
||||
int ret = 0;
|
||||
|
||||
if (!dev_is_platform(dev))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
pdev = to_platform_device(dev);
|
||||
|
||||
while ((r = platform_get_resource(pdev, IORESOURCE_MEM, index++))) {
|
||||
ret = __pkvm_donate_resource(r);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
while (index--) {
|
||||
r = platform_get_resource(pdev, IORESOURCE_MEM, index);
|
||||
__pkvm_reclaim_resource(r);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __pkvm_arch_reclaim_device(struct device *dev, void *data)
|
||||
{
|
||||
struct platform_device *pdev;
|
||||
struct resource *r;
|
||||
int index = 0;
|
||||
|
||||
pdev = to_platform_device(dev);
|
||||
|
||||
while ((r = platform_get_resource(pdev, IORESOURCE_MEM, index++)))
|
||||
__pkvm_reclaim_resource(r);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int kvm_arch_assign_device(struct device *dev)
|
||||
{
|
||||
if (!is_protected_kvm_enabled())
|
||||
return 0;
|
||||
|
||||
return __pkvm_arch_assign_device(dev, NULL);
|
||||
}
|
||||
|
||||
int kvm_arch_assign_group(struct iommu_group *group)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!is_protected_kvm_enabled())
|
||||
return 0;
|
||||
|
||||
ret = iommu_group_for_each_dev(group, NULL, __pkvm_arch_assign_device);
|
||||
|
||||
if (ret)
|
||||
iommu_group_for_each_dev(group, NULL, __pkvm_arch_reclaim_device);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void kvm_arch_reclaim_device(struct device *dev)
|
||||
{
|
||||
if (!is_protected_kvm_enabled())
|
||||
return;
|
||||
|
||||
__pkvm_arch_reclaim_device(dev, NULL);
|
||||
}
|
||||
|
||||
void kvm_arch_reclaim_group(struct iommu_group *group)
|
||||
{
|
||||
if (!is_protected_kvm_enabled())
|
||||
return;
|
||||
|
||||
iommu_group_for_each_dev(group, NULL, __pkvm_arch_reclaim_device);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user