ANDROID: KVM: arm64: iommu: Add memcache for guest pvIOMMU
Guest pvIOMMU would need memory for page tables, this is done through the host donating pages to the guest, and will be owned by the hypervisor as the guest has no direct access (or knowledge) of the IOMMU page tables. This is done through a new memcache per vcpu dedicated for each vcpu. And the requests for memory will be communiacted via kvm_hyp_req and fullfilled by the IOMMU driver or with a default function. Bug: 357781595 Bug: 348382247 Bug: 236685427 Change-Id: I8a32072dc21879165e7921dad83f312447360539 Signed-off-by: Mostafa Saleh <smostafa@google.com>
This commit is contained in:
committed by
Carlos Llamas
parent
b0fccd926d
commit
9dabecc2a2
@@ -915,6 +915,9 @@ struct kvm_vcpu_arch {
|
||||
/* Per-vcpu CCSIDR override or NULL */
|
||||
u32 *ccsidr;
|
||||
|
||||
/* mem cache for pvIOMMU usage in guests. */
|
||||
struct kvm_hyp_memcache iommu_mc;
|
||||
|
||||
/* PAGE_SIZE bound list of requests from the hypervisor to the host. */
|
||||
struct kvm_hyp_req *hyp_reqs;
|
||||
};
|
||||
@@ -1716,6 +1719,8 @@ struct kvm_iommu_driver {
|
||||
int (*get_device_iommu_num_ids)(struct device *dev);
|
||||
int (*get_device_iommu_id)(struct device *dev, u32 id,
|
||||
pkvm_handle_t *out_iommu, u32 *out_sid);
|
||||
void *(*guest_alloc)(void *flags, unsigned long order);
|
||||
void (*guest_free)(void *addr, void *flags, unsigned long order);
|
||||
ANDROID_KABI_RESERVE(1);
|
||||
ANDROID_KABI_RESERVE(2);
|
||||
ANDROID_KABI_RESERVE(3);
|
||||
@@ -1737,6 +1742,9 @@ pkvm_handle_t kvm_get_iommu_id_by_of(struct device_node *np);
|
||||
int pkvm_iommu_suspend(struct device *dev);
|
||||
int pkvm_iommu_resume(struct device *dev);
|
||||
|
||||
int kvm_iommu_guest_alloc_mc(struct kvm_hyp_memcache *mc, u32 pgsize, u32 nr_pages);
|
||||
void kvm_iommu_guest_free_mc(struct kvm_hyp_memcache *mc);
|
||||
|
||||
struct kvm_iommu_sg {
|
||||
phys_addr_t phys;
|
||||
size_t pgsize;
|
||||
@@ -1760,4 +1768,13 @@ int kvm_iommu_device_id(struct device *dev, u32 idx,
|
||||
pkvm_handle_t *out_iommu, u32 *out_sid);
|
||||
#define __KVM_HAVE_ARCH_ASSIGNED_DEVICE_GROUP
|
||||
|
||||
static inline phys_addr_t kvm_host_pa(void *addr)
|
||||
{
|
||||
return __pa(addr);
|
||||
}
|
||||
|
||||
static inline void *kvm_host_va(phys_addr_t phys)
|
||||
{
|
||||
return __va(phys);
|
||||
}
|
||||
#endif /* __ARM64_KVM_HOST_H__ */
|
||||
|
||||
@@ -388,6 +388,9 @@ static int handle_hyp_req_mem(struct kvm_vcpu *vcpu,
|
||||
atomic64_add(nr_pages << PAGE_SHIFT, &kvm->stat.protected_hyp_mem);
|
||||
|
||||
return ret;
|
||||
case REQ_MEM_DEST_HYP_IOMMU:
|
||||
return kvm_iommu_guest_alloc_mc(&vcpu->arch.iommu_mc,
|
||||
req->mem.sz_alloc, req->mem.nr_pages);
|
||||
};
|
||||
|
||||
pr_warn("Unknown kvm_hyp_req mem dest: %d\n", req->mem.dest);
|
||||
|
||||
@@ -142,3 +142,24 @@ int kvm_iommu_device_id(struct device *dev, u32 idx,
|
||||
return -ENODEV;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(kvm_iommu_device_id);
|
||||
|
||||
int kvm_iommu_guest_alloc_mc(struct kvm_hyp_memcache *mc, u32 pgsize, u32 nr_pages)
|
||||
{
|
||||
u8 order = get_order(pgsize);
|
||||
|
||||
/* Driver might have dedicated allocator especially if it needs large pages. */
|
||||
if (iommu_driver && iommu_driver->guest_alloc && iommu_driver->guest_free)
|
||||
return __topup_hyp_memcache(mc, nr_pages, iommu_driver->guest_alloc,
|
||||
kvm_host_pa, 0, order);
|
||||
|
||||
return topup_hyp_memcache(mc, nr_pages, order);
|
||||
}
|
||||
|
||||
void kvm_iommu_guest_free_mc(struct kvm_hyp_memcache *mc)
|
||||
{
|
||||
if (iommu_driver && iommu_driver->guest_alloc && iommu_driver->guest_free)
|
||||
__free_hyp_memcache(mc, iommu_driver->guest_free,
|
||||
kvm_host_va, 0);
|
||||
else
|
||||
free_hyp_memcache(mc);
|
||||
}
|
||||
|
||||
@@ -280,16 +280,6 @@ static int kvm_host_page_count(void *addr)
|
||||
return page_count(virt_to_page(addr));
|
||||
}
|
||||
|
||||
static phys_addr_t kvm_host_pa(void *addr)
|
||||
{
|
||||
return __pa(addr);
|
||||
}
|
||||
|
||||
static void *kvm_host_va(phys_addr_t phys)
|
||||
{
|
||||
return __va(phys);
|
||||
}
|
||||
|
||||
static void clean_dcache_guest_page(void *va, size_t size)
|
||||
{
|
||||
__clean_dcache_guest_page(va, size);
|
||||
|
||||
@@ -434,6 +434,8 @@ out_free:
|
||||
kvm_unshare_hyp(hyp_reqs, hyp_reqs + 1);
|
||||
host_vcpu->arch.hyp_reqs = NULL;
|
||||
free_page((unsigned long)hyp_reqs);
|
||||
|
||||
kvm_iommu_guest_free_mc(&host_vcpu->arch.iommu_mc);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user