lkml.org 
[lkml]   [2021]   [Sep]   [15]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    /
    From
    SubjectRE: [PATCH V5 10/12] hyperv/IOMMU: Enable swiotlb bounce buffer for Isolation VM
    Date
    From: Tianyu Lan <ltykernel@gmail.com> Sent: Tuesday, September 14, 2021 6:39 AM
    >
    > hyperv Isolation VM requires bounce buffer support to copy
    > data from/to encrypted memory and so enable swiotlb force
    > mode to use swiotlb bounce buffer for DMA transaction.
    >
    > In Isolation VM with AMD SEV, the bounce buffer needs to be
    > accessed via extra address space which is above shared_gpa_boundary
    > (E.G 39 bit address line) reported by Hyper-V CPUID ISOLATION_CONFIG.
    > The access physical address will be original physical address +
    > shared_gpa_boundary. The shared_gpa_boundary in the AMD SEV SNP
    > spec is called virtual top of memory(vTOM). Memory addresses below
    > vTOM are automatically treated as private while memory above
    > vTOM is treated as shared.
    >
    > Hyper-V initalizes swiotlb bounce buffer and default swiotlb
    > needs to be disabled. pci_swiotlb_detect_override() and
    > pci_swiotlb_detect_4gb() enable the default one. To override
    > the setting, hyperv_swiotlb_detect() needs to run before
    > these detect functions which depends on the pci_xen_swiotlb_
    > init(). Make pci_xen_swiotlb_init() depends on the hyperv_swiotlb
    > _detect() to keep the order.
    >
    > Swiotlb bounce buffer code calls set_memory_decrypted()
    > to mark bounce buffer visible to host and map it in extra
    > address space via memremap. Populate the shared_gpa_boundary
    > (vTOM) via swiotlb_unencrypted_base variable.
    >
    > The map function memremap() can't work in the early place
    > hyperv_iommu_swiotlb_init() and so initialize swiotlb bounce
    > buffer in the hyperv_iommu_swiotlb_later_init().
    >
    > Signed-off-by: Tianyu Lan <Tianyu.Lan@microsoft.com>
    > ---
    > Change since v4:
    > * Use swiotlb_unencrypted_base variable to pass shared_gpa_
    > boundary and map bounce buffer inside swiotlb code.
    >
    > Change since v3:
    > * Get hyperv bounce bufffer size via default swiotlb
    > bounce buffer size function and keep default size as
    > same as the one in the AMD SEV VM.
    > ---
    > arch/x86/include/asm/mshyperv.h | 2 ++
    > arch/x86/mm/mem_encrypt.c | 3 +-
    > arch/x86/xen/pci-swiotlb-xen.c | 3 +-
    > drivers/hv/vmbus_drv.c | 3 ++
    > drivers/iommu/hyperv-iommu.c | 60 +++++++++++++++++++++++++++++++++
    > include/linux/hyperv.h | 1 +
    > 6 files changed, 70 insertions(+), 2 deletions(-)
    >
    > diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h
    > index 165423e8b67a..2d22f29f90c9 100644
    > --- a/arch/x86/include/asm/mshyperv.h
    > +++ b/arch/x86/include/asm/mshyperv.h
    > @@ -182,6 +182,8 @@ int hv_map_ioapic_interrupt(int ioapic_id, bool level, int vcpu, int vector,
    > struct hv_interrupt_entry *entry);
    > int hv_unmap_ioapic_interrupt(int ioapic_id, struct hv_interrupt_entry *entry);
    > int hv_set_mem_host_visibility(unsigned long addr, int numpages, bool visible);
    > +void *hv_map_memory(void *addr, unsigned long size);
    > +void hv_unmap_memory(void *addr);

    Aren't these two declarations now spurious?

    > void hv_ghcb_msr_write(u64 msr, u64 value);
    > void hv_ghcb_msr_read(u64 msr, u64 *value);
    > #else /* CONFIG_HYPERV */
    > diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c
    > index ff08dc463634..e2db0b8ed938 100644
    > --- a/arch/x86/mm/mem_encrypt.c
    > +++ b/arch/x86/mm/mem_encrypt.c
    > @@ -30,6 +30,7 @@
    > #include <asm/processor-flags.h>
    > #include <asm/msr.h>
    > #include <asm/cmdline.h>
    > +#include <asm/mshyperv.h>
    >
    > #include "mm_internal.h"
    >
    > @@ -202,7 +203,7 @@ void __init sev_setup_arch(void)
    > phys_addr_t total_mem = memblock_phys_mem_size();
    > unsigned long size;
    >
    > - if (!sev_active())
    > + if (!sev_active() && !hv_is_isolation_supported())
    > return;
    >
    > /*
    > diff --git a/arch/x86/xen/pci-swiotlb-xen.c b/arch/x86/xen/pci-swiotlb-xen.c
    > index 54f9aa7e8457..43bd031aa332 100644
    > --- a/arch/x86/xen/pci-swiotlb-xen.c
    > +++ b/arch/x86/xen/pci-swiotlb-xen.c
    > @@ -4,6 +4,7 @@
    >
    > #include <linux/dma-map-ops.h>
    > #include <linux/pci.h>
    > +#include <linux/hyperv.h>
    > #include <xen/swiotlb-xen.h>
    >
    > #include <asm/xen/hypervisor.h>
    > @@ -91,6 +92,6 @@ int pci_xen_swiotlb_init_late(void)
    > EXPORT_SYMBOL_GPL(pci_xen_swiotlb_init_late);
    >
    > IOMMU_INIT_FINISH(pci_xen_swiotlb_detect,
    > - NULL,
    > + hyperv_swiotlb_detect,
    > pci_xen_swiotlb_init,
    > NULL);
    > diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
    > index 392c1ac4f819..b0be287e9a32 100644
    > --- a/drivers/hv/vmbus_drv.c
    > +++ b/drivers/hv/vmbus_drv.c
    > @@ -23,6 +23,7 @@
    > #include <linux/cpu.h>
    > #include <linux/sched/task_stack.h>
    >
    > +#include <linux/dma-map-ops.h>
    > #include <linux/delay.h>
    > #include <linux/notifier.h>
    > #include <linux/panic_notifier.h>
    > @@ -2078,6 +2079,7 @@ struct hv_device *vmbus_device_create(const guid_t *type,
    > return child_device_obj;
    > }
    >
    > +static u64 vmbus_dma_mask = DMA_BIT_MASK(64);
    > /*
    > * vmbus_device_register - Register the child device
    > */
    > @@ -2118,6 +2120,7 @@ int vmbus_device_register(struct hv_device *child_device_obj)
    > }
    > hv_debug_add_dev_dir(child_device_obj);
    >
    > + child_device_obj->device.dma_mask = &vmbus_dma_mask;
    > return 0;
    >
    > err_kset_unregister:
    > diff --git a/drivers/iommu/hyperv-iommu.c b/drivers/iommu/hyperv-iommu.c
    > index e285a220c913..a8ac2239de0f 100644
    > --- a/drivers/iommu/hyperv-iommu.c
    > +++ b/drivers/iommu/hyperv-iommu.c
    > @@ -13,14 +13,22 @@
    > #include <linux/irq.h>
    > #include <linux/iommu.h>
    > #include <linux/module.h>
    > +#include <linux/hyperv.h>
    > +#include <linux/io.h>
    >
    > #include <asm/apic.h>
    > #include <asm/cpu.h>
    > #include <asm/hw_irq.h>
    > #include <asm/io_apic.h>
    > +#include <asm/iommu.h>
    > +#include <asm/iommu_table.h>
    > #include <asm/irq_remapping.h>
    > #include <asm/hypervisor.h>
    > #include <asm/mshyperv.h>
    > +#include <asm/swiotlb.h>
    > +#include <linux/dma-map-ops.h>
    > +#include <linux/dma-direct.h>
    > +#include <linux/set_memory.h>
    >
    > #include "irq_remapping.h"
    >
    > @@ -36,6 +44,9 @@
    > static cpumask_t ioapic_max_cpumask = { CPU_BITS_NONE };
    > static struct irq_domain *ioapic_ir_domain;
    >
    > +static unsigned long hyperv_io_tlb_size;
    > +static void *hyperv_io_tlb_start;
    > +
    > static int hyperv_ir_set_affinity(struct irq_data *data,
    > const struct cpumask *mask, bool force)
    > {
    > @@ -337,4 +348,53 @@ static const struct irq_domain_ops hyperv_root_ir_domain_ops = {
    > .free = hyperv_root_irq_remapping_free,
    > };
    >
    > +static void __init hyperv_iommu_swiotlb_init(void)
    > +{
    > + /*
    > + * Allocate Hyper-V swiotlb bounce buffer at early place
    > + * to reserve large contiguous memory.
    > + */
    > + hyperv_io_tlb_size = swiotlb_size_or_default();
    > + hyperv_io_tlb_start = memblock_alloc(
    > + hyperv_io_tlb_size, PAGE_SIZE);
    > +
    > + if (!hyperv_io_tlb_start) {
    > + pr_warn("Fail to allocate Hyper-V swiotlb buffer.\n");
    > + return;
    > + }
    > +}
    > +
    > +int __init hyperv_swiotlb_detect(void)
    > +{
    > + if (!hypervisor_is_type(X86_HYPER_MS_HYPERV))
    > + return 0;
    > +
    > + if (!hv_is_isolation_supported())
    > + return 0;
    > +
    > + /*
    > + * Enable swiotlb force mode in Isolation VM to
    > + * use swiotlb bounce buffer for dma transaction.
    > + */
    > + swiotlb_unencrypted_base = ms_hyperv.shared_gpa_boundary;
    > + swiotlb_force = SWIOTLB_FORCE;
    > + return 1;
    > +}
    > +
    > +static void __init hyperv_iommu_swiotlb_later_init(void)
    > +{
    > + /*
    > + * Swiotlb bounce buffer needs to be mapped in extra address
    > + * space. Map function doesn't work in the early place and so
    > + * call swiotlb_late_init_with_tbl() here.
    > + */
    > + if (swiotlb_late_init_with_tbl(hyperv_io_tlb_start,
    > + hyperv_io_tlb_size >> IO_TLB_SHIFT))
    > + panic("Fail to initialize hyperv swiotlb.\n");
    > +}
    > +
    > +IOMMU_INIT_FINISH(hyperv_swiotlb_detect,
    > + NULL, hyperv_iommu_swiotlb_init,
    > + hyperv_iommu_swiotlb_later_init);
    > +
    > #endif
    > diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
    > index a9e0bc3b1511..bb1a1519b93a 100644
    > --- a/include/linux/hyperv.h
    > +++ b/include/linux/hyperv.h
    > @@ -1739,6 +1739,7 @@ int hyperv_write_cfg_blk(struct pci_dev *dev, void *buf, unsigned int len,
    > int hyperv_reg_block_invalidate(struct pci_dev *dev, void *context,
    > void (*block_invalidate)(void *context,
    > u64 block_mask));
    > +int __init hyperv_swiotlb_detect(void);
    >
    > struct hyperv_pci_block_ops {
    > int (*read_block)(struct pci_dev *dev, void *buf, unsigned int buf_len,
    > --
    > 2.25.1

    \
     
     \ /
      Last update: 2021-09-15 17:44    [W:3.892 / U:0.124 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site