From: Tianyu Lan <ltykernel@xxxxxxxxx> Sent: Monday, December 6, 2021 11:56 PM > > 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. > > 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 > (e.g ms_hyperv_init_platform()) and so call swiotlb_update_mem_ > attributes() in the hyperv_init(). > > Signed-off-by: Tianyu Lan <Tianyu.Lan@xxxxxxxxxxxxx> > --- > Change since v4: > * Remove Hyper-V IOMMU IOMMU_INIT_FINISH related functions > and set SWIOTLB_FORCE and swiotlb_unencrypted_base in the > ms_hyperv_init_platform(). Call swiotlb_update_mem_attributes() > in the hyperv_init(). > > Change since v3: > * Add comment in pci-swiotlb-xen.c to explain why add > dependency between hyperv_swiotlb_detect() and pci_ > xen_swiotlb_detect(). > * Return directly when fails to allocate Hyper-V swiotlb > buffer in the hyperv_iommu_swiotlb_init(). > --- > arch/x86/hyperv/hv_init.c | 10 ++++++++++ > arch/x86/kernel/cpu/mshyperv.c | 11 ++++++++++- > include/linux/hyperv.h | 8 ++++++++ > 3 files changed, 28 insertions(+), 1 deletion(-) > > diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c > index 24f4a06ac46a..9e18a280f89d 100644 > --- a/arch/x86/hyperv/hv_init.c > +++ b/arch/x86/hyperv/hv_init.c > @@ -28,6 +28,7 @@ > #include <linux/syscore_ops.h> > #include <clocksource/hyperv_timer.h> > #include <linux/highmem.h> > +#include <linux/swiotlb.h> > > int hyperv_init_cpuhp; > u64 hv_current_partition_id = ~0ull; > @@ -502,6 +503,15 @@ void __init hyperv_init(void) > > /* Query the VMs extended capability once, so that it can be cached. */ > hv_query_ext_cap(0); > + > + /* > + * Swiotlb bounce buffer needs to be mapped in extra address > + * space. Map function doesn't work in the early place and so > + * call swiotlb_update_mem_attributes() here. > + */ > + if (hv_is_isolation_supported()) > + swiotlb_update_mem_attributes(); > + > return; > > clean_guest_os_id: > diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c > index 4794b716ec79..baf3a0873552 100644 > --- a/arch/x86/kernel/cpu/mshyperv.c > +++ b/arch/x86/kernel/cpu/mshyperv.c > @@ -18,6 +18,7 @@ > #include <linux/kexec.h> > #include <linux/i8253.h> > #include <linux/random.h> > +#include <linux/swiotlb.h> > #include <asm/processor.h> > #include <asm/hypervisor.h> > #include <asm/hyperv-tlfs.h> > @@ -319,8 +320,16 @@ static void __init ms_hyperv_init_platform(void) > pr_info("Hyper-V: Isolation Config: Group A 0x%x, Group B 0x%x\n", > ms_hyperv.isolation_config_a, ms_hyperv.isolation_config_b); > > - if (hv_get_isolation_type() == HV_ISOLATION_TYPE_SNP) > + if (hv_get_isolation_type() == HV_ISOLATION_TYPE_SNP) { > static_branch_enable(&isolation_type_snp); > + swiotlb_unencrypted_base = ms_hyperv.shared_gpa_boundary; > + } > + > + /* > + * Enable swiotlb force mode in Isolation VM to > + * use swiotlb bounce buffer for dma transaction. > + */ > + swiotlb_force = SWIOTLB_FORCE; I'm good with this approach that directly updates the swiotlb settings here rather than in IOMMU initialization code. It's a lot more straightforward. However, there's an issue if building for X86_32 without PAE, in that the swiotlb module may not be built, resulting in compile and link errors. The swiotlb.h file needs to be updated to provide a stub function for swiotlb_update_mem_attributes(). swiotlb_unencrypted_base probably needs wrapper functions to get/set it, which can be stubs when CONFIG_SWIOTLB is not set. swiotlb_force is a bit of a mess in that it already has a stub definition that assumes it will only be read, and not set. A bit of thinking will be needed to sort that out. > } > > if (hv_max_functions_eax >= HYPERV_CPUID_NESTED_FEATURES) { > diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h > index b823311eac79..1f037e114dc8 100644 > --- a/include/linux/hyperv.h > +++ b/include/linux/hyperv.h > @@ -1726,6 +1726,14 @@ 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)); > +#if IS_ENABLED(CONFIG_HYPERV) > +int __init hyperv_swiotlb_detect(void); > +#else > +static inline int __init hyperv_swiotlb_detect(void) > +{ > + return 0; > +} > +#endif I don't think hyperv_swiotlb_detect() is used any longer, so this change should be dropped. > > struct hyperv_pci_block_ops { > int (*read_block)(struct pci_dev *dev, void *buf, unsigned int buf_len, > -- > 2.25.1