Commit 5063d328 authored by yangxiangkai's avatar yangxiangkai
Browse files

virtcca feature: msi place modify

virtcca inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/IAQON6



--------------------------------

VirtCCA Coda Feature:
Msi place modify

Signed-off-by: default avatarXiangkai Yang <yangxiangkai@huawei.com>
Signed-off-by: default avatarJunbin Li <lijunbin4@huawei.com>
---
parent ad540a13
Loading
Loading
Loading
Loading
+3 −5
Original line number Diff line number Diff line
@@ -68,10 +68,7 @@ int virtcca_vfio_iommu_map(void *iommu, dma_addr_t iova,
int cvm_vfio_add_kvm_to_smmu_domain(struct file *filp, void *kv);
struct kvm *virtcca_arm_smmu_get_kvm(struct arm_smmu_domain *domain);
void kvm_get_arm_smmu_domain(struct kvm *kvm, struct list_head *smmu_domain_group_list);
struct arm_lpae_io_pgtable *virtcca_io_pgtable_get_data(void *ops);
struct io_pgtable_cfg *virtcca_io_pgtable_get_cfg(struct arm_lpae_io_pgtable *data);
struct iommu_group *cvm_vfio_file_iommu_group(struct file *file);
void *virtcca_io_pgtable_get_smmu_domain(struct arm_lpae_io_pgtable *data);

struct iommu_group *virtcca_vfio_file_iommu_group(struct file *file);

@@ -87,7 +84,8 @@ void g_cc_dev_table_init(void);

u32 virtcca_tmi_dev_attach(struct arm_smmu_domain *arm_smmu_domain, struct kvm *kvm);

struct iommu_dma_msi_page *virtcca_iommu_dma_get_msi_page(struct device *dev,
	phys_addr_t msi_addr, struct iommu_domain *domain);
void virtcca_iommu_dma_get_msi_page(void *cookie, dma_addr_t *iova, phys_addr_t *phys);

int virtcca_msi_map(struct vfio_pci_core_device *vdev);
#endif
#endif
+1 −0
Original line number Diff line number Diff line
@@ -226,6 +226,7 @@ u64 get_g_cc_dev_msi_addr(u32 sid)
	}
	return 0;
}
EXPORT_SYMBOL_GPL(get_g_cc_dev_msi_addr);

/**
 * set_g_cc_dev_msi_addr - Set the msi address of confidential device
+46 −6
Original line number Diff line number Diff line
@@ -28,8 +28,8 @@ int virtcca_map_pages(void *ops, unsigned long iova,
	struct kvm *kvm;
	u64 loader_start;
	u64 ram_size;
	struct arm_lpae_io_pgtable *data = virtcca_io_pgtable_get_data(ops);
	struct io_pgtable_cfg *cfg = virtcca_io_pgtable_get_cfg(data);
	struct io_pgtable *data = io_pgtable_ops_to_pgtable(ops);
	struct io_pgtable_cfg *cfg = &data->cfg;
	long iaext = (s64)iova >> cfg->ias;
	int ret = 0;
	struct arm_smmu_domain *smmu_domain = NULL;
@@ -46,7 +46,7 @@ int virtcca_map_pages(void *ops, unsigned long iova,
	if (!(iommu_prot & (IOMMU_READ | IOMMU_WRITE)))
		return 0;

	smmu_domain = (struct arm_smmu_domain *)virtcca_io_pgtable_get_smmu_domain(data);
	smmu_domain = (struct arm_smmu_domain *)(data->cookie);
	if (!smmu_domain)
		return -EINVAL;

@@ -92,8 +92,8 @@ size_t virtcca_unmap_pages(void *ops, unsigned long iova,
	size_t pgsize, size_t pgcount)
{
	struct kvm *kvm;
	struct arm_lpae_io_pgtable *data = virtcca_io_pgtable_get_data(ops);
	struct io_pgtable_cfg *cfg = virtcca_io_pgtable_get_cfg(data);
	struct io_pgtable *data = io_pgtable_ops_to_pgtable(ops);
	struct io_pgtable_cfg *cfg = &data->cfg;
	long iaext = (s64)iova >> cfg->ias;
	struct arm_smmu_domain *smmu_domain = NULL;

@@ -105,7 +105,7 @@ size_t virtcca_unmap_pages(void *ops, unsigned long iova,
	if (WARN_ON(iaext))
		return 0;

	smmu_domain = (struct arm_smmu_domain *)virtcca_io_pgtable_get_smmu_domain(data);
	smmu_domain = (struct arm_smmu_domain *)(data->cookie);
	if (!smmu_domain)
		return 0;

@@ -341,3 +341,43 @@ int virtcca_iommu_group_set_dev_msi_addr(struct iommu_group *iommu_group, unsign
	ret = iommu_group_for_each_dev(iommu_group, (void *)iova, virtcca_set_dev_msi_addr);
	return ret;
}

/**
 * virtcca_msi_map - Vfio driver mapping device side msi address
 * @vdev: Vfio pci core device
 *
 * Returns:
 * %0 if map success
 */
int virtcca_msi_map(struct vfio_pci_core_device *vdev)
{
	if (!is_virtcca_cvm_enable())
		return 0;

	int ret;
	dma_addr_t iova;
	phys_addr_t msi_addr;
	struct iommu_domain *domain = NULL;
	struct pci_dev *pdev = vdev->pdev;
	bool cc_dev = pdev == NULL ? false : is_cc_dev(pci_dev_id(pdev));
	int prot = IOMMU_WRITE | IOMMU_NOEXEC | IOMMU_MMIO;

	/*
	 * If the device is secure and has not done MSI address mapping,
	 * Mapping is required.
	 */
	if (cc_dev && !get_g_cc_dev_msi_addr(pci_dev_id(pdev))) {
		domain = iommu_get_domain_for_dev(&(pdev->dev));
		/* Get the MSI address of the device */
		virtcca_iommu_dma_get_msi_page((void *)domain->iova_cookie, &iova, &msi_addr);
		/* Release non-secure side device MSI address mapping */
		iommu_unmap(domain, iova, PAGE_SIZE);
		/* Mapping secure side MSI address */
		ret = virtcca_iommu_map(domain, iova, msi_addr, PAGE_SIZE, prot);
		if (ret)
			return ret;
	}

	return 0;
}
EXPORT_SYMBOL_GPL(virtcca_msi_map);
+15 −44
Original line number Diff line number Diff line
@@ -33,11 +33,6 @@

#include "dma-iommu.h"

#ifdef CONFIG_HISI_VIRTCCA_CODA
#include <asm/virtcca_cvm_host.h>
#include <asm/virtcca_coda.h>
#endif

struct iommu_dma_msi_page {
	struct list_head	list;
	dma_addr_t		iova;
@@ -1825,10 +1820,6 @@ static struct iommu_dma_msi_page *iommu_dma_get_msi_page(struct device *dev,
	int prot = IOMMU_WRITE | IOMMU_NOEXEC | IOMMU_MMIO;
	size_t size = cookie_msi_granule(cookie);

#ifdef CONFIG_HISI_VIRTCCA_CODA
	if (is_virtcca_cvm_enable() && domain->secure)
		return virtcca_iommu_dma_get_msi_page(dev, msi_addr, domain);
#endif
	msi_addr &= ~(phys_addr_t)(size - 1);
	list_for_each_entry(msi_page, &cookie->msi_page_list, list)
		if (msi_page->phys == msi_addr)
@@ -1924,42 +1915,22 @@ static int iommu_dma_init(void)
arch_initcall(iommu_dma_init);

#ifdef CONFIG_HISI_VIRTCCA_CODA
/* Virtcca map msi address */
struct iommu_dma_msi_page *virtcca_iommu_dma_get_msi_page(struct device *dev,
	phys_addr_t msi_addr, struct iommu_domain *domain)
/**
 * virtcca_iommu_dma_get_msi_page() - Traverse the MSI page list to obtain the last
 * MSI page
 * @cookie: Iommu dma cookie
 * @iova: Iova address
 * @phys: Physical address
 *
 */
void virtcca_iommu_dma_get_msi_page(void *cookie, dma_addr_t *iova, phys_addr_t *phys)
{
	struct iommu_dma_cookie *cookie = domain->iova_cookie;
	struct iommu_dma_msi_page *msi_page;
	dma_addr_t iova;
	int prot = IOMMU_WRITE | IOMMU_NOEXEC | IOMMU_MMIO;
	size_t size = cookie_msi_granule(cookie);

	msi_addr &= ~(phys_addr_t)(size - 1);
	list_for_each_entry(msi_page, &cookie->msi_page_list, list)
		if (msi_page->phys == msi_addr)
			return msi_page;

	msi_page = kzalloc(sizeof(*msi_page), GFP_KERNEL);
	if (!msi_page)
		return NULL;

	iova = iommu_dma_alloc_iova(domain, size, dma_get_mask(dev), dev);
	if (!iova)
		goto out_free_page;

	if (virtcca_iommu_map(domain, iova, msi_addr, size, prot))
		goto out_free_iova;

	INIT_LIST_HEAD(&msi_page->list);
	msi_page->phys = msi_addr;
	msi_page->iova = iova;
	list_add(&msi_page->list, &cookie->msi_page_list);
	return msi_page;
	struct iommu_dma_msi_page *msi_page = NULL;
	struct iommu_dma_cookie *dma_cookie = (struct iommu_dma_cookie *)cookie;

out_free_iova:
	iommu_dma_free_iova(cookie, iova, size, NULL);
out_free_page:
	kfree(msi_page);
	return NULL;
	msi_page = list_last_entry(&dma_cookie->msi_page_list, struct iommu_dma_msi_page, list);
	*iova = msi_page->iova;
	*phys = msi_page->phys;
}
EXPORT_SYMBOL_GPL(virtcca_iommu_dma_get_msi_page);
#endif
+0 −24
Original line number Diff line number Diff line
@@ -20,10 +20,6 @@

#include <asm/barrier.h>

#ifdef CONFIG_HISI_VIRTCCA_CODA
#include <asm/virtcca_coda.h>
#endif

#include "io-pgtable-arm.h"

#define ARM_LPAE_MAX_ADDR_BITS		52
@@ -1727,23 +1723,3 @@ static int __init arm_lpae_do_selftests(void)
}
subsys_initcall(arm_lpae_do_selftests);
#endif

#ifdef CONFIG_HISI_VIRTCCA_CODA
/* Obtain io pgtable data from io pgtable ops */
struct arm_lpae_io_pgtable *virtcca_io_pgtable_get_data(void *ops)
{
	return io_pgtable_ops_to_data((struct io_pgtable_ops *)ops);
}

/* Obtain io pgtable cfg from io pgtable data */
struct io_pgtable_cfg *virtcca_io_pgtable_get_cfg(struct arm_lpae_io_pgtable *data)
{
	return &data->iop.cfg;
}

/* Obtain smmu domain from io pgtable data */
void *virtcca_io_pgtable_get_smmu_domain(struct arm_lpae_io_pgtable *data)
{
	return data->iop.cookie;
}
#endif
Loading