
From: yxk <yangxiangkai@huawei.com> virtcca inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IBWQ24 -------------------------------- Add adapted lpi support for virtcca cvm guest. Signed-off-by: yxk <yangxiangkai@huawei.com> Signed-off-by: hjx_gitff <hejingxian@huawei.com> Signed-off-by: Yiwei Zhuang <zhuangyiwei@huawei.com> Signed-off-by: Cai Xinchen <caixinchen1@huawei.com> --- arch/arm64/include/asm/virtcca_cvm_guest.h | 8 ++++ arch/arm64/kernel/virtcca_cvm_guest.c | 52 ++++++++++++++++++++++ drivers/base/core.c | 2 + drivers/irqchip/irq-gic-v3-its.c | 11 +++++ drivers/virtio/virtio_mmio.c | 3 +- drivers/virtio/virtio_pci_common.c | 2 + drivers/virtio/virtio_pci_common.h | 1 + include/linux/virtcca_cvm_domain.h | 12 ++++- 8 files changed, 89 insertions(+), 2 deletions(-) diff --git a/arch/arm64/include/asm/virtcca_cvm_guest.h b/arch/arm64/include/asm/virtcca_cvm_guest.h index c1ac1a9cd537..a074bd65dab9 100644 --- a/arch/arm64/include/asm/virtcca_cvm_guest.h +++ b/arch/arm64/include/asm/virtcca_cvm_guest.h @@ -20,6 +20,13 @@ extern void virtcca_cvm_tsi_init(void); extern void swiotlb_unmap_notify(unsigned long paddr, unsigned long size); +extern void virtcca_its_init(void); + +extern struct page *virtcca_its_alloc_shared_pages_node(int node, gfp_t gfp, + unsigned int order); + +extern void virtcca_its_free_shared_pages(void *addr, int order); + #else static inline int set_cvm_memory_encrypted(unsigned long addr, int numpages) @@ -42,5 +49,6 @@ static inline void __init swiotlb_cvm_update_mem_attributes(void) {} static inline void virtcca_cvm_tsi_init(void) {} static inline void swiotlb_unmap_notify(unsigned long paddr, unsigned long size) {} + #endif /* CONFIG_HISI_VIRTCCA_GUEST */ #endif /* __VIRTCCA_CVM_GUEST_H */ diff --git a/arch/arm64/kernel/virtcca_cvm_guest.c b/arch/arm64/kernel/virtcca_cvm_guest.c index 2d4a26a297b6..da2c4a17f837 100644 --- a/arch/arm64/kernel/virtcca_cvm_guest.c +++ b/arch/arm64/kernel/virtcca_cvm_guest.c @@ -7,6 +7,7 @@ #include <linux/module.h> #include <linux/sched.h> #include <linux/vmalloc.h> +#include <linux/swiotlb.h> #include <asm/cacheflush.h> #include <asm/set_memory.h> @@ -69,6 +70,7 @@ bool is_virtcca_cvm_world(void) { return cvm_guest_enable && static_branch_likely(&cvm_tsi_present); } +EXPORT_SYMBOL_GPL(is_virtcca_cvm_world); static int change_page_range_cvm(pte_t *ptep, unsigned long addr, void *data) { @@ -120,9 +122,59 @@ int set_cvm_memory_decrypted(unsigned long addr, int numpages) return __set_memory_encrypted(addr, numpages, false); } +/* + * struct io_tlb_no_swiotlb_mem - whether use the + * bounce buffer mechanism or not + * @for_alloc: %true if the pool is used for memory allocation. + * Here it is set to %false, to force devices to use direct dma operations. + * + * @force_bounce: %true if swiotlb bouncing is forced. + * Here it is set to %false, to force devices to use direct dma operations. + */ +static struct io_tlb_mem io_tlb_no_swiotlb_mem = { + .for_alloc = false, + .force_bounce = false, +}; + +void enable_swiotlb_for_cvm_dev(struct device *dev, bool enable) +{ + if (!is_virtcca_cvm_world()) + return; + + if (enable) + swiotlb_dev_init(dev); + else + dev->dma_io_tlb_mem = &io_tlb_no_swiotlb_mem; +} +EXPORT_SYMBOL_GPL(enable_swiotlb_for_cvm_dev); + void swiotlb_unmap_notify(unsigned long paddr, unsigned long size) { struct arm_smccc_res res; arm_smccc_1_1_smc(SMC_TSI_SEC_MEM_UNMAP, paddr, size, &res); } + +static struct device cvm_alloc_device; + +void __init virtcca_its_init(void) +{ + if (is_virtcca_cvm_world()) { + device_initialize(&cvm_alloc_device); + enable_swiotlb_for_cvm_dev(&cvm_alloc_device, true); + } +} + +struct page *virtcca_its_alloc_shared_pages_node(int node, gfp_t gfp, + unsigned int order) +{ + return swiotlb_alloc(&cvm_alloc_device, (1 << order) * PAGE_SIZE); +} + +void virtcca_its_free_shared_pages(void *addr, int order) +{ + if (order < 0) + return; + + swiotlb_free(&cvm_alloc_device, (struct page *)addr, (1 << order) * PAGE_SIZE); +} diff --git a/drivers/base/core.c b/drivers/base/core.c index 21bbcacf7820..4c8094dd8fe5 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -32,6 +32,7 @@ #include <linux/swiotlb.h> #include <linux/sysfs.h> #include <linux/dma-map-ops.h> /* for dma_default_coherent */ +#include <linux/virtcca_cvm_domain.h> #include "base.h" #include "physical_location.h" @@ -3145,6 +3146,7 @@ void device_initialize(struct device *dev) dev->dma_coherent = dma_default_coherent; #endif swiotlb_dev_init(dev); + enable_swiotlb_for_cvm_dev(dev, false); } EXPORT_SYMBOL_GPL(device_initialize); diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index 8542679627dd..92fd29a1990f 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c @@ -32,6 +32,7 @@ #include <linux/set_memory.h> #include <linux/slab.h> #include <linux/syscore_ops.h> +#include <linux/virtcca_cvm_domain.h> #include <linux/irqchip.h> #include <linux/irqchip/arm-gic-v3.h> @@ -393,6 +394,9 @@ static struct page *its_alloc_pages_node(int node, gfp_t gfp, struct page *page; int ret = 0; + if (virtcca_cvm_domain()) + return virtcca_its_alloc_shared_pages_node(node, gfp, order); + page = alloc_pages_node(node, gfp, order); if (!page) @@ -418,6 +422,11 @@ static struct page *its_alloc_pages(gfp_t gfp, unsigned int order) static void its_free_pages(void *addr, unsigned int order) { + if (virtcca_cvm_domain()) { + virtcca_its_free_shared_pages(addr, order); + return; + } + /* * If the memory cannot be encrypted again then we must leak the pages. * set_memory_encrypted() will already have WARNed. @@ -6227,6 +6236,8 @@ int __init its_init(struct fwnode_handle *handle, struct rdists *rdists, #endif int err; + virtcca_its_init(); + itt_pool = gen_pool_create(get_order(ITS_ITT_ALIGN), -1); if (!itt_pool) return -ENOMEM; diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c index 59892a31cf76..fb4abd2afc46 100644 --- a/drivers/virtio/virtio_mmio.c +++ b/drivers/virtio/virtio_mmio.c @@ -70,7 +70,7 @@ #include <linux/virtio_config.h> #include <uapi/linux/virtio_mmio.h> #include <linux/virtio_ring.h> - +#include <linux/virtcca_cvm_domain.h> /* The alignment to use between consumer and producer parts of vring. @@ -619,6 +619,7 @@ static int virtio_mmio_probe(struct platform_device *pdev) unsigned long magic; int rc; + enable_swiotlb_for_cvm_dev(&pdev->dev, true); vm_dev = kzalloc(sizeof(*vm_dev), GFP_KERNEL); if (!vm_dev) return -ENOMEM; diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c index 64dfa54d702f..95d9a3aed68c 100644 --- a/drivers/virtio/virtio_pci_common.c +++ b/drivers/virtio/virtio_pci_common.c @@ -525,6 +525,8 @@ static int virtio_pci_probe(struct pci_dev *pci_dev, struct virtio_pci_device *vp_dev, *reg_dev = NULL; int rc; + enable_swiotlb_for_cvm_dev(&pci_dev->dev, true); + /* allocate our structure and fill it out */ vp_dev = kzalloc(sizeof(struct virtio_pci_device), GFP_KERNEL); if (!vp_dev) diff --git a/drivers/virtio/virtio_pci_common.h b/drivers/virtio/virtio_pci_common.h index 4b773bd7c58c..0f0e19f94d30 100644 --- a/drivers/virtio/virtio_pci_common.h +++ b/drivers/virtio/virtio_pci_common.h @@ -29,6 +29,7 @@ #include <linux/virtio_pci_modern.h> #include <linux/highmem.h> #include <linux/spinlock.h> +#include <linux/virtcca_cvm_domain.h> struct virtio_pci_vq_info { /* the actual virtqueue */ diff --git a/include/linux/virtcca_cvm_domain.h b/include/linux/virtcca_cvm_domain.h index 62dbb88db5fd..9a24a031d12c 100644 --- a/include/linux/virtcca_cvm_domain.h +++ b/include/linux/virtcca_cvm_domain.h @@ -14,7 +14,7 @@ static inline bool virtcca_cvm_domain(void) return is_virtcca_cvm_world(); } -void enable_swiotlb_for_cvm_dev(struct device *dev, bool enable); +extern void enable_swiotlb_for_cvm_dev(struct device *dev, bool enable); #else static inline bool virtcca_cvm_domain(void) @@ -24,6 +24,16 @@ static inline bool virtcca_cvm_domain(void) static inline void enable_swiotlb_for_cvm_dev(struct device *dev, bool enable) {} +static inline void virtcca_its_init(void) {} + +static inline struct page *virtcca_its_alloc_shared_pages_node(int node, gfp_t gfp, + unsigned int order) +{ + return NULL; +} + +static inline void virtcca_its_free_shared_pages(void *addr, int order) {} + #endif #ifdef CONFIG_HISI_VIRTCCA_HOST -- 2.18.0.huawei.25