From: Tianyu Lan <hidden> Date: 2021-05-30 15:06:42
From: Tianyu Lan <redacted>
Hyper-V provides two kinds of Isolation VMs. VBS(Virtualization-based
security) and AMD SEV-SNP unenlightened Isolation VMs. This patchset
is to add support for these Isolation VM support in Linux.
The memory of these vms are encrypted and host can't access guest
memory directly. Hyper-V provides new host visibility hvcall and
the guest needs to call new hvcall to mark memory visible to host
before sharing memory with host. For security, all network/storage
stack memory should not be shared with host and so there is bounce
buffer requests.
Vmbus channel ring buffer already plays bounce buffer role because
all data from/to host needs to copy from/to between the ring buffer
and IO stack memory. So mark vmbus channel ring buffer visible.
There are two exceptions - packets sent by vmbus_sendpacket_
pagebuffer() and vmbus_sendpacket_mpb_desc(). These packets
contains IO stack memory address and host will access these memory.
So add allocation bounce buffer support in vmbus for these packets.
For SNP isolation VM, guest needs to access the shared memory via
extra address space which is specified by Hyper-V CPUID HYPERV_CPUID_
ISOLATION_CONFIG. The access physical address of the shared memory
should be bounce buffer memory GPA plus with shared_gpa_boundary
reported by CPUID.
Change since v2:
- Remove not UIO driver in Isolation VM patch
- Use vmap_pfn() to replace ioremap_page_range function in
order to avoid exposing symbol ioremap_page_range() and
ioremap_page_range()
- Call hv set mem host visibility hvcall in set_memory_encrypted/decrypted()
- Enable swiotlb force mode instead of adding Hyper-V dma map/unmap hook
- Fix code style
Tianyu Lan (11):
x86/HV: Initialize GHCB page in Isolation VM
x86/HV: Initialize shared memory boundary in the Isolation VM.
x86/Hyper-V: Add new hvcall guest address host visibility support
HV: Add Write/Read MSR registers via ghcb
HV: Add ghcb hvcall support for SNP VM
HV/Vmbus: Add SNP support for VMbus channel initiate message
HV/Vmbus: Initialize VMbus ring buffer for Isolation VM
swiotlb: Add bounce buffer remap address setting function
HV/IOMMU: Enable swiotlb bounce buffer for Isolation VM
HV/Netvsc: Add Isolation VM support for netvsc driver
HV/Storvsc: Add Isolation VM support for storvsc driver
arch/x86/hyperv/Makefile | 2 +-
arch/x86/hyperv/hv_init.c | 70 +++++--
arch/x86/hyperv/ivm.c | 300 +++++++++++++++++++++++++++++
arch/x86/include/asm/hyperv-tlfs.h | 24 +++
arch/x86/include/asm/mshyperv.h | 85 +++++++-
arch/x86/kernel/cpu/mshyperv.c | 5 +
arch/x86/mm/pat/set_memory.c | 10 +-
arch/x86/xen/pci-swiotlb-xen.c | 3 +-
drivers/hv/Kconfig | 1 +
drivers/hv/channel.c | 48 ++++-
drivers/hv/connection.c | 68 ++++++-
drivers/hv/hv.c | 122 ++++++++----
drivers/hv/hyperv_vmbus.h | 3 +
drivers/hv/ring_buffer.c | 84 ++++++--
drivers/hv/vmbus_drv.c | 3 +
drivers/iommu/hyperv-iommu.c | 81 ++++++++
drivers/net/hyperv/hyperv_net.h | 6 +
drivers/net/hyperv/netvsc.c | 125 +++++++++++-
drivers/net/hyperv/rndis_filter.c | 3 +
drivers/scsi/storvsc_drv.c | 63 +++++-
include/asm-generic/hyperv-tlfs.h | 1 +
include/asm-generic/mshyperv.h | 18 +-
include/linux/hyperv.h | 16 ++
include/linux/swiotlb.h | 5 +
kernel/dma/swiotlb.c | 14 +-
25 files changed, 1062 insertions(+), 98 deletions(-)
create mode 100644 arch/x86/hyperv/ivm.c
--
2.25.1
From: Tianyu Lan <hidden> Date: 2021-05-30 15:06:46
From: Tianyu Lan <redacted>
Hyper-V exposes GHCB page via SEV ES GHCB MSR for SNP guest
to communicate with hypervisor. Map GHCB page for all
cpus to read/write MSR register and submit hvcall request
via GHCB.
Signed-off-by: Tianyu Lan <redacted>
---
arch/x86/hyperv/hv_init.c | 60 ++++++++++++++++++++++++++++++---
arch/x86/include/asm/mshyperv.h | 2 ++
include/asm-generic/mshyperv.h | 2 ++
3 files changed, 60 insertions(+), 4 deletions(-)
@@ -60,6 +60,9 @@ static int hv_cpu_init(unsigned int cpu)structhv_vp_assist_page**hvp=&hv_vp_assist_page[smp_processor_id()];void**input_arg;structpage*pg;+u64ghcb_gpa;+void*ghcb_va;+void**ghcb_base;/* hv_cpu_init() can be called with IRQs disabled from hv_resume() */pg=alloc_pages(irqs_disabled()?GFP_ATOMIC:GFP_KERNEL,hv_root_partition?1:0);
@@ -106,6 +109,17 @@ static int hv_cpu_init(unsigned int cpu)wrmsrl(HV_X64_MSR_VP_ASSIST_PAGE,val);}+if(ms_hyperv.ghcb_base){+rdmsrl(MSR_AMD64_SEV_ES_GHCB,ghcb_gpa);++ghcb_va=ioremap_cache(ghcb_gpa,HV_HYP_PAGE_SIZE);+if(!ghcb_va)+return-ENOMEM;++ghcb_base=(void**)this_cpu_ptr(ms_hyperv.ghcb_base);+*ghcb_base=ghcb_va;+}+return0;}
@@ -201,6 +215,7 @@ static int hv_cpu_die(unsigned int cpu)unsignedlongflags;void**input_arg;void*pg;+void**ghcb_va=NULL;local_irq_save(flags);input_arg=(void**)this_cpu_ptr(hyperv_pcpu_input_arg);
@@ -214,6 +229,13 @@ static int hv_cpu_die(unsigned int cpu)*output_arg=NULL;}+if(ms_hyperv.ghcb_base){+ghcb_va=(void**)this_cpu_ptr(ms_hyperv.ghcb_base);+if(*ghcb_va)+iounmap(*ghcb_va);+*ghcb_va=NULL;+}+local_irq_restore(flags);free_pages((unsignedlong)pg,hv_root_partition?1:0);
@@ -615,6 +659,14 @@ bool hv_is_isolation_supported(void)}EXPORT_SYMBOL_GPL(hv_is_isolation_supported);+DEFINE_STATIC_KEY_FALSE(isolation_type_snp);++boolhv_isolation_type_snp(void)+{+returnstatic_branch_unlikely(&isolation_type_snp);+}+EXPORT_SYMBOL_GPL(hv_isolation_type_snp);+/* Bit mask of the extended capability to query: see HV_EXT_CAPABILITY_xxx */boolhv_query_ext_cap(u64cap_query){
From: Tianyu Lan <hidden> Date: 2021-05-30 15:06:56
From: Tianyu Lan <redacted>
Hyper-V also exposes shared memory boundary via cpuid
HYPERV_CPUID_ISOLATION_CONFIG and store it in the
shared_gpa_boundary of ms_hyperv struct. This prepares
to share memory with host for SNP guest.
Signed-off-by: Tianyu Lan <redacted>
---
arch/x86/kernel/cpu/mshyperv.c | 2 ++
include/asm-generic/mshyperv.h | 12 +++++++++++-
2 files changed, 13 insertions(+), 1 deletion(-)
@@ -320,6 +320,8 @@ static void __init ms_hyperv_init_platform(void)if(ms_hyperv.priv_high&HV_ISOLATION){ms_hyperv.isolation_config_a=cpuid_eax(HYPERV_CPUID_ISOLATION_CONFIG);ms_hyperv.isolation_config_b=cpuid_ebx(HYPERV_CPUID_ISOLATION_CONFIG);+ms_hyperv.shared_gpa_boundary=+(u64)1<<ms_hyperv.shared_gpa_boundary_bits;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);
@@ -561,4 +572,17 @@ enum hv_interrupt_type {#include<asm-generic/hyperv-tlfs.h>+/* All input parameters should be in single page. */+#define HV_MAX_MODIFY_GPA_REP_COUNT \+((PAGE_SIZE/sizeof(u64))-2)++/* HvCallModifySparseGpaPageHostVisibility hypercall */+structhv_gpa_range_for_visibility{+u64partition_id;+u32host_visibility:2;+u32reserved0:30;+u32reserved1;+u64gpa_page_list[HV_MAX_MODIFY_GPA_REP_COUNT];+}__packed;+#endif
@@ -1986,8 +1988,14 @@ static int __set_memory_enc_dec(unsigned long addr, int numpages, bool enc)intret;/* Nothing to do if memory encryption is not active */-if(!mem_encrypt_active())+if(hv_is_isolation_supported()){+returnhv_set_mem_host_visibility((void*)addr,+numpages*HV_HYP_PAGE_SIZE,+enc?VMBUS_PAGE_NOT_VISIBLE+:VMBUS_PAGE_VISIBLE_READ_WRITE);+}elseif(!mem_encrypt_active()){return0;+}/* Should not be working on unaligned addresses */if(WARN_ONCE(addr&~PAGE_MASK,"misaligned address: %#lx\n",addr))
@@ -465,7 +466,7 @@ static int __vmbus_establish_gpadl(struct vmbus_channel *channel,structlist_head*curr;u32next_gpadl_handle;unsignedlongflags;-intret=0;+intret=0,index;next_gpadl_handle=(atomic_inc_return(&vmbus_connection.next_gpadl_handle)-1);
@@ -474,6 +475,13 @@ static int __vmbus_establish_gpadl(struct vmbus_channel *channel,if(ret)returnret;+ret=set_memory_decrypted((unsignedlong)kbuffer,+HVPFN_UP(size));+if(ret){+pr_warn("Failed to set host visibility.\n");+returnret;+}+init_completion(&msginfo->waitevent);msginfo->waiting_channel=channel;
@@ -539,6 +547,15 @@ static int __vmbus_establish_gpadl(struct vmbus_channel *channel,/* At this point, we received the gpadl created msg */*gpadl_handle=gpadlmsg->gpadl;+if(type==HV_GPADL_BUFFER)+index=0;+else+index=channel->gpadl_range[1].gpadlhandle?2:1;++channel->gpadl_range[index].size=size;+channel->gpadl_range[index].buffer=kbuffer;+channel->gpadl_range[index].gpadlhandle=*gpadl_handle;+cleanup:spin_lock_irqsave(&vmbus_connection.channelmsg_lock,flags);list_del(&msginfo->msglistentry);
@@ -549,6 +566,11 @@ static int __vmbus_establish_gpadl(struct vmbus_channel *channel,}kfree(msginfo);++if(ret)+set_memory_encrypted((unsignedlong)kbuffer,+HVPFN_UP(size));+returnret;}
@@ -811,7 +833,7 @@ int vmbus_teardown_gpadl(struct vmbus_channel *channel, u32 gpadl_handle)structvmbus_channel_gpadl_teardown*msg;structvmbus_channel_msginfo*info;unsignedlongflags;-intret;+intret,i;info=kzalloc(sizeof(*info)+sizeof(structvmbus_channel_gpadl_teardown),GFP_KERNEL);
@@ -859,6 +881,18 @@ int vmbus_teardown_gpadl(struct vmbus_channel *channel, u32 gpadl_handle)spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock,flags);kfree(info);++/* Find gpadl buffer virtual address and size. */+for(i=0;i<VMBUS_GPADL_RANGE_COUNT;i++)+if(channel->gpadl_range[i].gpadlhandle==gpadl_handle)+break;++if(set_memory_encrypted((unsignedlong)channel->gpadl_range[i].buffer,+HVPFN_UP(channel->gpadl_range[i].size)))+pr_warn("Fail to set mem host visibility.\n");++channel->gpadl_range[i].gpadlhandle=0;+returnret;}EXPORT_SYMBOL_GPL(vmbus_teardown_gpadl);
From: Tianyu Lan <hidden> Date: 2021-05-30 15:06:57
From: Tianyu Lan <redacted>
Hyper-V provides GHCB protocol to write Synthetic Interrupt
Controller MSR registers and these registers are emulated by
Hypervisor rather than paravisor in VMPL0.
Hyper-V requests to write SINTx MSR registers twice(once via
GHCB and once via wrmsr instruction emulated by paravisor including
the proxy bit 21). Guest OS ID MSR also needs to be set via GHCB.
Signed-off-by: Tianyu Lan <redacted>
---
arch/x86/hyperv/hv_init.c | 26 +------
arch/x86/hyperv/ivm.c | 125 ++++++++++++++++++++++++++++++++
arch/x86/include/asm/mshyperv.h | 78 +++++++++++++++++++-
arch/x86/kernel/cpu/mshyperv.c | 3 +
drivers/hv/hv.c | 114 +++++++++++++++++++----------
include/asm-generic/mshyperv.h | 4 +-
6 files changed, 287 insertions(+), 63 deletions(-)
@@ -472,6 +472,9 @@ void __init hyperv_init(void)ghcb_base=(void**)this_cpu_ptr(ms_hyperv.ghcb_base);*ghcb_base=ghcb_va;++/* Hyper-V requires to write guest os id via ghcb in SNP IVM. */+hv_ghcb_msr_write(HV_X64_MSR_GUEST_OS_ID,guest_id);}rdmsrl(HV_X64_MSR_HYPERCALL,hypercall_msr.as_uint64);
@@ -564,6 +567,7 @@ void hyperv_cleanup(void)/* Reset our OS id */wrmsrl(HV_X64_MSR_GUEST_OS_ID,0);+hv_ghcb_msr_write(HV_X64_MSR_GUEST_OS_ID,0);/**Resethypercallpagereferencebeforeresetthepage,
@@ -645,28 +649,6 @@ bool hv_is_hibernation_supported(void)}EXPORT_SYMBOL_GPL(hv_is_hibernation_supported);-enumhv_isolation_typehv_get_isolation_type(void)-{-if(!(ms_hyperv.priv_high&HV_ISOLATION))-returnHV_ISOLATION_TYPE_NONE;-returnFIELD_GET(HV_ISOLATION_TYPE,ms_hyperv.isolation_config_b);-}-EXPORT_SYMBOL_GPL(hv_get_isolation_type);--boolhv_is_isolation_supported(void)-{-returnhv_get_isolation_type()!=HV_ISOLATION_TYPE_NONE;-}-EXPORT_SYMBOL_GPL(hv_is_isolation_supported);--DEFINE_STATIC_KEY_FALSE(isolation_type_snp);--boolhv_isolation_type_snp(void)-{-returnstatic_branch_unlikely(&isolation_type_snp);-}-EXPORT_SYMBOL_GPL(hv_isolation_type_snp);-/* Bit mask of the extended capability to query: see HV_EXT_CAPABILITY_xxx */boolhv_query_ext_cap(u64cap_query){
@@ -6,12 +6,137 @@*TianyuLan<Tianyu.Lan@microsoft.com>*/+#include<linux/types.h>+#include<linux/bitfield.h>#include<linux/hyperv.h>#include<linux/types.h>#include<linux/bitfield.h>#include<asm/io.h>+#include<asm/svm.h>+#include<asm/sev-es.h>#include<asm/mshyperv.h>+unionhv_ghcb{+structghcbghcb;+}__packed__aligned(PAGE_SIZE);++voidhv_ghcb_msr_write(u64msr,u64value)+{+unionhv_ghcb*hv_ghcb;+void**ghcb_base;+unsignedlongflags;++if(!ms_hyperv.ghcb_base)+return;++local_irq_save(flags);+ghcb_base=(void**)this_cpu_ptr(ms_hyperv.ghcb_base);+hv_ghcb=(unionhv_ghcb*)*ghcb_base;+if(!hv_ghcb){+local_irq_restore(flags);+return;+}++memset(hv_ghcb,0x00,HV_HYP_PAGE_SIZE);++hv_ghcb->ghcb.protocol_version=1;+hv_ghcb->ghcb.ghcb_usage=0;++ghcb_set_sw_exit_code(&hv_ghcb->ghcb,SVM_EXIT_MSR);+ghcb_set_rcx(&hv_ghcb->ghcb,msr);+ghcb_set_rax(&hv_ghcb->ghcb,lower_32_bits(value));+ghcb_set_rdx(&hv_ghcb->ghcb,value>>32);+ghcb_set_sw_exit_info_1(&hv_ghcb->ghcb,1);+ghcb_set_sw_exit_info_2(&hv_ghcb->ghcb,0);++VMGEXIT();++if((hv_ghcb->ghcb.save.sw_exit_info_1&0xffffffff)==1)+pr_warn("Fail to write msr via ghcb %llx.\n",msr);++local_irq_restore(flags);+}++voidhv_ghcb_msr_read(u64msr,u64*value)+{+unionhv_ghcb*hv_ghcb;+void**ghcb_base;+unsignedlongflags;++if(!ms_hyperv.ghcb_base)+return;++local_irq_save(flags);+ghcb_base=(void**)this_cpu_ptr(ms_hyperv.ghcb_base);+hv_ghcb=(unionhv_ghcb*)*ghcb_base;+if(!hv_ghcb){+local_irq_restore(flags);+return;+}++memset(hv_ghcb,0x00,HV_HYP_PAGE_SIZE);+hv_ghcb->ghcb.protocol_version=1;+hv_ghcb->ghcb.ghcb_usage=0;++ghcb_set_sw_exit_code(&hv_ghcb->ghcb,SVM_EXIT_MSR);+ghcb_set_rcx(&hv_ghcb->ghcb,msr);+ghcb_set_sw_exit_info_1(&hv_ghcb->ghcb,0);+ghcb_set_sw_exit_info_2(&hv_ghcb->ghcb,0);++VMGEXIT();++if((hv_ghcb->ghcb.save.sw_exit_info_1&0xffffffff)==1)+pr_warn("Fail to read msr via ghcb %llx.\n",msr);+else+*value=(u64)lower_32_bits(hv_ghcb->ghcb.save.rax)+|((u64)lower_32_bits(hv_ghcb->ghcb.save.rdx)<<32);+local_irq_restore(flags);+}++voidhv_sint_rdmsrl_ghcb(u64msr,u64*value)+{+hv_ghcb_msr_read(msr,value);+}+EXPORT_SYMBOL_GPL(hv_sint_rdmsrl_ghcb);++voidhv_sint_wrmsrl_ghcb(u64msr,u64value)+{+hv_ghcb_msr_write(msr,value);++/* Write proxy bit vua wrmsrl instruction. */+if(msr>=HV_X64_MSR_SINT0&&msr<=HV_X64_MSR_SINT15)+wrmsrl(msr,value|1<<20);+}+EXPORT_SYMBOL_GPL(hv_sint_wrmsrl_ghcb);++voidhv_signal_eom_ghcb(void)+{+hv_sint_wrmsrl_ghcb(HV_X64_MSR_EOM,0);+}+EXPORT_SYMBOL_GPL(hv_signal_eom_ghcb);++enumhv_isolation_typehv_get_isolation_type(void)+{+if(!(ms_hyperv.priv_high&HV_ISOLATION))+returnHV_ISOLATION_TYPE_NONE;+returnFIELD_GET(HV_ISOLATION_TYPE,ms_hyperv.isolation_config_b);+}+EXPORT_SYMBOL_GPL(hv_get_isolation_type);++boolhv_is_isolation_supported(void)+{+returnhv_get_isolation_type()!=HV_ISOLATION_TYPE_NONE;+}+EXPORT_SYMBOL_GPL(hv_is_isolation_supported);++DEFINE_STATIC_KEY_FALSE(isolation_type_snp);++boolhv_isolation_type_snp(void)+{+returnstatic_branch_unlikely(&isolation_type_snp);+}+EXPORT_SYMBOL_GPL(hv_isolation_type_snp);+/**hv_mark_gpa_visibility-Setpagesvisibletohostviahvcall.*
@@ -325,6 +325,9 @@ 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)+static_branch_enable(&isolation_type_snp);}if(ms_hyperv.hints&HV_X64_ENLIGHTENED_VMCS_RECOMMENDED){
@@ -199,26 +213,43 @@ void hv_synic_enable_regs(unsigned int cpu)unionhv_synic_scontrolsctrl;/* Setup the Synic's message page */-simp.as_uint64=hv_get_register(HV_REGISTER_SIMP);+hv_get_simp(simp.as_uint64);simp.simp_enabled=1;-simp.base_simp_gpa=virt_to_phys(hv_cpu->synic_message_page)->>HV_HYP_PAGE_SHIFT;-hv_set_register(HV_REGISTER_SIMP,simp.as_uint64);+if(hv_isolation_type_snp()){+hv_cpu->synic_message_page+=ioremap_cache(simp.base_simp_gpa<<HV_HYP_PAGE_SHIFT,+HV_HYP_PAGE_SIZE);+if(!hv_cpu->synic_message_page)+pr_err("Fail to map syinc message page.\n");+}else{+simp.base_simp_gpa=virt_to_phys(hv_cpu->synic_message_page)+>>HV_HYP_PAGE_SHIFT;+}++hv_set_simp(simp.as_uint64);/* Setup the Synic's event page */-siefp.as_uint64=hv_get_register(HV_REGISTER_SIEFP);+hv_get_siefp(siefp.as_uint64);siefp.siefp_enabled=1;-siefp.base_siefp_gpa=virt_to_phys(hv_cpu->synic_event_page)->>HV_HYP_PAGE_SHIFT;-hv_set_register(HV_REGISTER_SIEFP,siefp.as_uint64);+if(hv_isolation_type_snp()){+hv_cpu->synic_event_page=+ioremap_cache(siefp.base_siefp_gpa<<HV_HYP_PAGE_SHIFT,+HV_HYP_PAGE_SIZE);++if(!hv_cpu->synic_event_page)+pr_err("Fail to map syinc event page.\n");+}else{+siefp.base_siefp_gpa=virt_to_phys(hv_cpu->synic_event_page)+>>HV_HYP_PAGE_SHIFT;+}+hv_set_siefp(siefp.as_uint64);/* Setup the shared SINT. */if(vmbus_irq!=-1)enable_percpu_irq(vmbus_irq,0);-shared_sint.as_uint64=hv_get_register(HV_REGISTER_SINT0+-VMBUS_MESSAGE_SINT);+hv_get_synint_state(VMBUS_MESSAGE_SINT,shared_sint.as_uint64);shared_sint.vector=vmbus_interrupt;shared_sint.masked=false;
@@ -233,14 +264,12 @@ void hv_synic_enable_regs(unsigned int cpu)#elseshared_sint.auto_eoi=0;#endif-hv_set_register(HV_REGISTER_SINT0+VMBUS_MESSAGE_SINT,-shared_sint.as_uint64);+hv_set_synint_state(VMBUS_MESSAGE_SINT,shared_sint.as_uint64);/* Enable the global synic bit */-sctrl.as_uint64=hv_get_register(HV_REGISTER_SCONTROL);+hv_get_synic_state(sctrl.as_uint64);sctrl.enable=1;--hv_set_register(HV_REGISTER_SCONTROL,sctrl.as_uint64);+hv_set_synic_state(sctrl.as_uint64);}inthv_synic_init(unsignedintcpu)
@@ -262,32 +291,39 @@ void hv_synic_disable_regs(unsigned int cpu)unionhv_synic_siefpsiefp;unionhv_synic_scontrolsctrl;-shared_sint.as_uint64=hv_get_register(HV_REGISTER_SINT0+-VMBUS_MESSAGE_SINT);-+hv_get_synint_state(VMBUS_MESSAGE_SINT,shared_sint.as_uint64);shared_sint.masked=1;+hv_set_synint_state(VMBUS_MESSAGE_SINT,shared_sint.as_uint64);+/* Need to correctly cleanup in the case of SMP!!! *//* Disable the interrupt */-hv_set_register(HV_REGISTER_SINT0+VMBUS_MESSAGE_SINT,-shared_sint.as_uint64);+hv_get_simp(simp.as_uint64);-simp.as_uint64=hv_get_register(HV_REGISTER_SIMP);+/*+*InIsolationVM,simandsiefpagesareallocatedby+*paravisor.Thesepagesalsowillbeusedbykdump+*kernel.Sojustresetenablebithereandkeeppage+*addresses.+*/simp.simp_enabled=0;-simp.base_simp_gpa=0;+if(!hv_isolation_type_snp())+simp.base_simp_gpa=0;-hv_set_register(HV_REGISTER_SIMP,simp.as_uint64);+hv_set_simp(simp.as_uint64);-siefp.as_uint64=hv_get_register(HV_REGISTER_SIEFP);+hv_get_siefp(siefp.as_uint64);siefp.siefp_enabled=0;-siefp.base_siefp_gpa=0;-hv_set_register(HV_REGISTER_SIEFP,siefp.as_uint64);+if(!hv_isolation_type_snp())+siefp.base_siefp_gpa=0;++hv_set_siefp(siefp.as_uint64);/* Disable the global synic bit */-sctrl.as_uint64=hv_get_register(HV_REGISTER_SCONTROL);+hv_get_synic_state(sctrl.as_uint64);sctrl.enable=0;-hv_set_register(HV_REGISTER_SCONTROL,sctrl.as_uint64);+hv_set_synic_state(sctrl.as_uint64);if(vmbus_irq!=-1)disable_percpu_irq(vmbus_irq);
@@ -97,7 +97,13 @@ int hv_post_message(union hv_connection_id connection_id,aligned_msg->payload_size=payload_size;memcpy((void*)aligned_msg->payload,payload,payload_size);-status=hv_do_hypercall(HVCALL_POST_MESSAGE,aligned_msg,NULL);+if(hv_isolation_type_snp())+status=hv_ghcb_hypercall(HVCALL_POST_MESSAGE,+(void*)aligned_msg,NULL,+sizeof(structhv_input_post_message));+else+status=hv_do_hypercall(HVCALL_POST_MESSAGE,+aligned_msg,NULL);/* Preemption must remain disabled until after the hypercall*sosomeotherthreadcan'tgetscheduledontothiscpuand
From: Tianyu Lan <hidden> Date: 2021-05-30 15:07:06
From: Tianyu Lan <redacted>
The monitor pages in the CHANNELMSG_INITIATE_CONTACT are shared
with host and so it's necessary to use hvcall to set them visible
to host. In Isolation VM with AMD SEV SNP, the access address
should be in the extra space which is above shared gpa boundary.
So remap these pages into the extra address(pa + shared_gpa_boundary).
Signed-off-by: Tianyu Lan <redacted>
---
drivers/hv/connection.c | 62 +++++++++++++++++++++++++++++++++++++++
drivers/hv/hyperv_vmbus.h | 1 +
2 files changed, 63 insertions(+)
From: Tianyu Lan <hidden> Date: 2021-05-30 15:07:09
From: Tianyu Lan <redacted>
VMbus ring buffer are shared with host and it's need to
be accessed via extra address space of Isolation VM with
SNP support. This patch is to map the ring buffer
address in extra address space via ioremap(). HV host
visibility hvcall smears data in the ring buffer and
so reset the ring buffer memory to zero after calling
visibility hvcall.
Signed-off-by: Tianyu Lan <redacted>
---
drivers/hv/Kconfig | 1 +
drivers/hv/channel.c | 10 +++++
drivers/hv/hyperv_vmbus.h | 2 +
drivers/hv/ring_buffer.c | 84 ++++++++++++++++++++++++++++++---------
4 files changed, 79 insertions(+), 18 deletions(-)
@@ -707,6 +707,16 @@ static int __vmbus_open(struct vmbus_channel *newchannel,if(err)gotoerror_clean_ring;+err=hv_ringbuffer_post_init(&newchannel->outbound,+page,send_pages);+if(err)+gotoerror_free_gpadl;++err=hv_ringbuffer_post_init(&newchannel->inbound,+&page[send_pages],recv_pages);+if(err)+gotoerror_free_gpadl;+/* Create and init the channel open message */open_info=kzalloc(sizeof(*open_info)+sizeof(structvmbus_channel_open_channel),
@@ -179,43 +181,89 @@ void hv_ringbuffer_pre_init(struct vmbus_channel *channel)mutex_init(&channel->outbound.ring_buffer_mutex);}-/* Initialize the ring buffer. */-inthv_ringbuffer_init(structhv_ring_buffer_info*ring_info,-structpage*pages,u32page_cnt,u32max_pkt_size)+inthv_ringbuffer_post_init(structhv_ring_buffer_info*ring_info,+structpage*pages,u32page_cnt){+u64physic_addr=page_to_pfn(pages)<<PAGE_SHIFT;+unsignedlong*pfns_wraparound;+void*vaddr;inti;-structpage**pages_wraparound;-BUILD_BUG_ON((sizeof(structhv_ring_buffer)!=PAGE_SIZE));+if(!hv_isolation_type_snp())+return0;++physic_addr+=ms_hyperv.shared_gpa_boundary;/**Firstpageholdsstructhv_ring_buffer,dowraparoundmappingfor*therest.*/-pages_wraparound=kcalloc(page_cnt*2-1,sizeof(structpage*),+pfns_wraparound=kcalloc(page_cnt*2-1,sizeof(unsignedlong),GFP_KERNEL);-if(!pages_wraparound)+if(!pfns_wraparound)return-ENOMEM;-pages_wraparound[0]=pages;+pfns_wraparound[0]=physic_addr>>PAGE_SHIFT;for(i=0;i<2*(page_cnt-1);i++)-pages_wraparound[i+1]=&pages[i%(page_cnt-1)+1];--ring_info->ring_buffer=(structhv_ring_buffer*)-vmap(pages_wraparound,page_cnt*2-1,VM_MAP,PAGE_KERNEL);--kfree(pages_wraparound);+pfns_wraparound[i+1]=(physic_addr>>PAGE_SHIFT)++i%(page_cnt-1)+1;--if(!ring_info->ring_buffer)+vaddr=vmap_pfn(pfns_wraparound,page_cnt*2-1,PAGE_KERNEL_IO);+kfree(pfns_wraparound);+if(!vaddr)return-ENOMEM;-ring_info->ring_buffer->read_index=-ring_info->ring_buffer->write_index=0;+/* Clean memory after setting host visibility. */+memset((void*)vaddr,0x00,page_cnt*PAGE_SIZE);++ring_info->ring_buffer=(structhv_ring_buffer*)vaddr;+ring_info->ring_buffer->read_index=0;+ring_info->ring_buffer->write_index=0;/* Set the feature bit for enabling flow control. */ring_info->ring_buffer->feature_bits.value=1;+return0;+}++/* Initialize the ring buffer. */+inthv_ringbuffer_init(structhv_ring_buffer_info*ring_info,+structpage*pages,u32page_cnt,u32max_pkt_size)+{+inti;+structpage**pages_wraparound;++BUILD_BUG_ON((sizeof(structhv_ring_buffer)!=PAGE_SIZE));++if(!hv_isolation_type_snp()){+/*+*Firstpageholdsstructhv_ring_buffer,dowraparoundmappingfor+*therest.+*/+pages_wraparound=kcalloc(page_cnt*2-1,sizeof(structpage*),+GFP_KERNEL);+if(!pages_wraparound)+return-ENOMEM;++pages_wraparound[0]=pages;+for(i=0;i<2*(page_cnt-1);i++)+pages_wraparound[i+1]=&pages[i%(page_cnt-1)+1];++ring_info->ring_buffer=(structhv_ring_buffer*)+vmap(pages_wraparound,page_cnt*2-1,VM_MAP,PAGE_KERNEL);++kfree(pages_wraparound);++if(!ring_info->ring_buffer)+return-ENOMEM;++ring_info->ring_buffer->read_index=+ring_info->ring_buffer->write_index=0;++/* Set the feature bit for enabling flow control. */+ring_info->ring_buffer->feature_bits.value=1;+}+ring_info->ring_size=page_cnt<<PAGE_SHIFT;ring_info->ring_size_div10_reciprocal=reciprocal_value(ring_info->ring_size/10);
From: Tianyu Lan <hidden> Date: 2021-05-30 15:07:12
From: Tianyu Lan <redacted>
Hyper-V 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.
ioremap_cache() can't use in the hyperv_iommu_swiotlb_init() which
is too early place and remap bounce buffer in the hyperv_iommu_swiotlb_
later_init().
Signed-off-by: Tianyu Lan <redacted>
---
arch/x86/xen/pci-swiotlb-xen.c | 3 +-
drivers/hv/vmbus_drv.c | 3 ++
drivers/iommu/hyperv-iommu.c | 81 ++++++++++++++++++++++++++++++++++
include/linux/hyperv.h | 1 +
4 files changed, 87 insertions(+), 1 deletion(-)
From: Tianyu Lan <hidden> Date: 2021-05-30 15:07:18
From: Tianyu Lan <redacted>
In Isolation VM, all shared memory with host needs to mark visible
to host via hvcall. vmbus_establish_gpadl() has already done it for
netvsc rx/tx ring buffer. The page buffer used by vmbus_sendpacket_
pagebuffer() still need to handle. Use DMA API to map/umap these
memory during sending/receiving packet and Hyper-V DMA ops callback
will use swiotlb function to allocate bounce buffer and copy data
from/to bounce buffer.
Signed-off-by: Tianyu Lan <redacted>
---
drivers/net/hyperv/hyperv_net.h | 6 ++
drivers/net/hyperv/netvsc.c | 125 ++++++++++++++++++++++++++++--
drivers/net/hyperv/rndis_filter.c | 3 +
include/linux/hyperv.h | 5 ++
4 files changed, 133 insertions(+), 6 deletions(-)
@@ -1074,6 +1075,7 @@ struct netvsc_device {/* Receive buffer allocated by us but manages by NetVSP */void*recv_buf;+void*recv_original_buf;u32recv_buf_size;/* allocated bytes */u32recv_buf_gpadl_handle;u32recv_section_cnt;
@@ -1082,6 +1084,8 @@ struct netvsc_device {/* Send buffer allocated by us */void*send_buf;+void*send_original_buf;+u32send_buf_size;u32send_buf_gpadl_handle;u32send_section_cnt;u32send_section_size;
@@ -338,8 +351,10 @@ static int netvsc_init_buf(struct hv_device *device,structnet_device*ndev=hv_get_drvdata(device);structnvsp_message*init_packet;unsignedintbuf_size;+unsignedlong*pfns;size_tmap_words;inti,ret=0;+void*vaddr;/* Get receive buffer area. */buf_size=device_info->recv_sections*device_info->recv_section_size;
@@ -375,6 +390,21 @@ static int netvsc_init_buf(struct hv_device *device,gotocleanup;}+if(hv_isolation_type_snp()){+pfns=kcalloc(buf_size/HV_HYP_PAGE_SIZE,sizeof(unsignedlong),+GFP_KERNEL);+for(i=0;i<buf_size/HV_HYP_PAGE_SIZE;i++)+pfns[i]=virt_to_hvpfn(net_device->recv_buf+i*HV_HYP_PAGE_SIZE)++(ms_hyperv.shared_gpa_boundary>>HV_HYP_PAGE_SHIFT);++vaddr=vmap_pfn(pfns,buf_size/HV_HYP_PAGE_SIZE,PAGE_KERNEL_IO);+kfree(pfns);+if(!vaddr)+gotocleanup;+net_device->recv_original_buf=net_device->recv_buf;+net_device->recv_buf=vaddr;+}+/* Notify the NetVsp of the gpadl handle */init_packet=&net_device->channel_init_pkt;memset(init_packet,0,sizeof(structnvsp_message));
@@ -477,6 +507,23 @@ static int netvsc_init_buf(struct hv_device *device,gotocleanup;}+if(hv_isolation_type_snp()){+pfns=kcalloc(buf_size/HV_HYP_PAGE_SIZE,sizeof(unsignedlong),+GFP_KERNEL);++for(i=0;i<buf_size/HV_HYP_PAGE_SIZE;i++)+pfns[i]=virt_to_hvpfn(net_device->send_buf+i*HV_HYP_PAGE_SIZE)++(ms_hyperv.shared_gpa_boundary>>HV_HYP_PAGE_SHIFT);++vaddr=vmap_pfn(pfns,buf_size/HV_HYP_PAGE_SIZE,PAGE_KERNEL_IO);+kfree(pfns);+if(!vaddr)+gotocleanup;++net_device->send_original_buf=net_device->send_buf;+net_device->send_buf=vaddr;+}+/* Notify the NetVsp of the gpadl handle */init_packet=&net_device->channel_init_pkt;memset(init_packet,0,sizeof(structnvsp_message));
@@ -767,7 +814,7 @@ static void netvsc_send_tx_complete(struct net_device *ndev,/* Notify the layer above us */if(likely(skb)){-conststructhv_netvsc_packet*packet+structhv_netvsc_packet*packet=(structhv_netvsc_packet*)skb->cb;u32send_index=packet->send_buf_index;structnetvsc_stats*tx_stats;
From: Tianyu Lan <hidden> Date: 2021-05-30 15:07:23
From: Tianyu Lan <redacted>
For Hyper-V isolation VM with AMD SEV SNP, the bounce buffer(shared memory)
needs to be accessed via extra address space(e.g address above bit39).
Hyper-V code may remap extra address space outside of swiotlb. swiotlb_
bounce() needs to use remap virtual address to copy data from/to bounce
buffer. Add new interface swiotlb_set_bounce_remap() to do that.
Signed-off-by: Tianyu Lan <redacted>
---
include/linux/swiotlb.h | 5 +++++
kernel/dma/swiotlb.c | 14 +++++++++++++-
2 files changed, 18 insertions(+), 1 deletion(-)
From: Tianyu Lan <hidden> Date: 2021-05-30 15:07:27
From: Tianyu Lan <redacted>
In Isolation VM, all shared memory with host needs to mark visible
to host via hvcall. vmbus_establish_gpadl() has already done it for
storvsc rx/tx ring buffer. The page buffer used by vmbus_sendpacket_
mpb_desc() still need to handle. Use DMA API to map/umap these
memory during sending/receiving packet and Hyper-V DMA ops callback
will use swiotlb function to allocate bounce buffer and copy data
from/to bounce buffer.
Signed-off-by: Tianyu Lan <redacted>
---
drivers/scsi/storvsc_drv.c | 63 +++++++++++++++++++++++++++++++++++---
1 file changed, 58 insertions(+), 5 deletions(-)
@@ -1867,13 +1913,20 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd)put_cpu();if(ret==-EAGAIN){-if(payload_sz>sizeof(cmd_request->mpb))-kfree(payload);/* no more space */-returnSCSI_MLQUEUE_DEVICE_BUSY;+ret=SCSI_MLQUEUE_DEVICE_BUSY;+gotofree_dma_range;}return0;++free_dma_range:+kfree(cmd_request->dma_range);++free_payload:+if(payload_sz>sizeof(cmd_request->mpb))+kfree(payload);+returnret;}staticstructscsi_host_templatescsi_driver={
@@ -1986,8 +1988,14 @@ static int __set_memory_enc_dec(unsigned long addr, int numpages, bool enc)intret;/* Nothing to do if memory encryption is not active */-if(!mem_encrypt_active())+if(hv_is_isolation_supported()){+returnhv_set_mem_host_visibility((void*)addr,+numpages*HV_HYP_PAGE_SIZE,+enc?VMBUS_PAGE_NOT_VISIBLE+:VMBUS_PAGE_VISIBLE_READ_WRITE);
Put all this gunk in a hv-specific function somewhere in hv-land which
you only call from here. This way you probably won't even need to export
hv_set_mem_host_visibility() and so on...
Thx.
--
Regards/Gruss,
Boris.
https://people.kernel.org/tglx/notes-about-netiquette
@@ -1986,8 +1988,14 @@ static int __set_memory_enc_dec(unsigned long addr, int numpages, bool enc)intret;/* Nothing to do if memory encryption is not active */-if(!mem_encrypt_active())+if(hv_is_isolation_supported()){+returnhv_set_mem_host_visibility((void*)addr,+numpages*HV_HYP_PAGE_SIZE,+enc?VMBUS_PAGE_NOT_VISIBLE+:VMBUS_PAGE_VISIBLE_READ_WRITE);
Put all this gunk in a hv-specific function somewhere in hv-land which
you only call from here. This way you probably won't even need to export
hv_set_mem_host_visibility() and so on...
Hyper-V allocates its own swiotlb bounce buffer and the default
swiotlb buffer should not be allocated. swiotlb_init() in
pci_swiotlb_init() is to allocate default swiotlb buffer.
To achieve this, put hyperv_swiotlb_detect() as the first entry in the
iommu_table_entry list. The detect loop in the pci_iommu_alloc() will
exit once hyperv_swiotlb_detect() is called in Hyper-V VM and other
iommu_table_entry callback will not be called.
Hyper-V allocates its own swiotlb bounce buffer and the default
swiotlb buffer should not be allocated. swiotlb_init() in pci_swiotlb_init() is to allocate default swiotlb buffer.
To achieve this, put hyperv_swiotlb_detect() as the first entry in the iommu_table_entry list. The detect loop in the pci_iommu_alloc() will exit once hyperv_swiotlb_detect() is called in Hyper-V VM and other iommu_table_entry callback will not be called.
Right. But pci_xen_swiotlb_detect() will only do something for Xen PV guests, and those guests don't run on hyperV. It's either xen_pv_domain() (i.e. hypervisor_is_type(X86_HYPER_XEN_PV)) or hypervisor_is_type(X86_HYPER_MS_HYPERV) but never both. So I don't think there needs to be a dependency between the two callbacks.
-boris
Hyper-V allocates its own swiotlb bounce buffer and the default
swiotlb buffer should not be allocated. swiotlb_init() in pci_swiotlb_init() is to allocate default swiotlb buffer.
To achieve this, put hyperv_swiotlb_detect() as the first entry in the iommu_table_entry list. The detect loop in the pci_iommu_alloc() will exit once hyperv_swiotlb_detect() is called in Hyper-V VM and other iommu_table_entry callback will not be called.
Right. But pci_xen_swiotlb_detect() will only do something for Xen PV guests, and those guests don't run on hyperV. It's either xen_pv_domain() (i.e. hypervisor_is_type(X86_HYPER_XEN_PV)) or hypervisor_is_type(X86_HYPER_MS_HYPERV) but never both. So I don't think there needs to be a dependency between the two callbacks.
Yes, the dependency is between hyperv_swiotlb_detect() and
pci_swiotlb_detect_override()/pci_swiotlb_detect_4gb(). Now
pci_swiotlb_detect_override() and pci_swiotlb_detect_4gb() depends on
pci_xen_swiotlb_detect(). To keep dependency between
hyperv_swiotlb_detect() and pci_swiotlb_detect_override/4gb(), make
pci_xen_swiotlb_detect() depends on hyperv_swiotlb_detect() and just to
keep order in the IOMMU table. Current iommu_table_entry only has one
depend callback and this is why I put xen depends on hyperv detect function.
Thanks.
From: Boris Ostrovsky <boris.ostrovsky@oracle.com> Date: 2021-06-03 17:07:22
On 6/3/21 11:37 AM, Tianyu Lan wrote:
Yes, the dependency is between hyperv_swiotlb_detect() and
pci_swiotlb_detect_override()/pci_swiotlb_detect_4gb(). Now
pci_swiotlb_detect_override() and pci_swiotlb_detect_4gb() depends on
pci_xen_swiotlb_detect(). To keep dependency between
hyperv_swiotlb_detect() and pci_swiotlb_detect_override/4gb(), make pci_xen_swiotlb_detect() depends on hyperv_swiotlb_detect() and just to
keep order in the IOMMU table. Current iommu_table_entry only has one
depend callback and this is why I put xen depends on hyperv detect function.
From: Christoph Hellwig <hch@lst.de> Date: 2021-06-07 06:41:54
On Sun, May 30, 2021 at 11:06:18AM -0400, Tianyu Lan wrote:
+ if (ms_hyperv.ghcb_base) {
+ rdmsrl(MSR_AMD64_SEV_ES_GHCB, ghcb_gpa);
+
+ ghcb_va = ioremap_cache(ghcb_gpa, HV_HYP_PAGE_SIZE);
+ if (!ghcb_va)
+ return -ENOMEM;
Can you explain this a bit more? We've very much deprecated
ioremap_cache in favor of memremap. Why yo you need a __iomem address
here? Why do we need the remap here at all?
Does the data structure at this address not have any types that we
could use a struct for?
From: Christoph Hellwig <hch@lst.de> Date: 2021-06-07 06:43:19
On Sun, May 30, 2021 at 11:06:25AM -0400, Tianyu Lan wrote:
From: Tianyu Lan <redacted>
For Hyper-V isolation VM with AMD SEV SNP, the bounce buffer(shared memory)
needs to be accessed via extra address space(e.g address above bit39).
Hyper-V code may remap extra address space outside of swiotlb. swiotlb_
bounce() needs to use remap virtual address to copy data from/to bounce
buffer. Add new interface swiotlb_set_bounce_remap() to do that.
Why can't you use the bus_dma_region ranges to remap to your preferred
address?
From: Christoph Hellwig <hch@lst.de> Date: 2021-06-07 06:44:59
Honestly, we really need to do away with the concept of hypervisor-
specific swiotlb allocations and just add a hypervisor hook to remap the
"main" buffer. That should remove a lot of code and confusion not just
for Xen but also any future addition like hyperv.
This probably wnats a helper to make the thing more readable. But who
came up with this fucked up communication protocol where the host needs
to map random pfns into a contigous range? Sometime I really have to
wonder what crack the hyper-v people take when comparing this to the
relatively sane approach others take.
+ for (i = 0; i < page_count; i++)
+ dma_unmap_single(&hv_dev->device, packet->dma_range[i].dma,
+ packet->dma_range[i].mapping_size,
+ DMA_TO_DEVICE);
+
+ kfree(packet->dma_range);
Any reason this isn't simply using a struct scatterlist?
+ for (i = 0; i < page_count; i++) {
+ char *src = phys_to_virt((pb[i].pfn << HV_HYP_PAGE_SHIFT)
+ + pb[i].offset);
+ u32 len = pb[i].len;
+
+ dma = dma_map_single(&hv_dev->device, src, len,
+ DMA_TO_DEVICE);
dma_map_single can only be used on page baked memory, and if this is
using page backed memory you wouldn't need to do thee phys_to_virt
tricks. Can someone explain the mess here in more detail?
From: Tianyu Lan <hidden> Date: 2021-06-07 08:16:09
Hi Christoph:
Thanks for your review.
On 6/7/2021 2:41 PM, Christoph Hellwig wrote:
On Sun, May 30, 2021 at 11:06:18AM -0400, Tianyu Lan wrote:
quoted
+ if (ms_hyperv.ghcb_base) {
+ rdmsrl(MSR_AMD64_SEV_ES_GHCB, ghcb_gpa);
+
+ ghcb_va = ioremap_cache(ghcb_gpa, HV_HYP_PAGE_SIZE);
+ if (!ghcb_va)
+ return -ENOMEM;
Can you explain this a bit more? We've very much deprecated
ioremap_cache in favor of memremap. Why yo you need a __iomem address
here? Why do we need the remap here at all? >
GHCB physical address is an address in extra address space which is
above shared gpa boundary reported by Hyper-V CPUID. The addresses below
shared gpa boundary treated as encrypted and the one above is treated as
decrypted. System memory is remapped in the extra address space and it
starts from the boundary. The shared memory with host needs to use
address in the extra address(pa + shared_gpa_boundary) in Linux guest.
Here is to map ghcb page for the communication operations with
Hypervisor(e.g, hypercall and read/write MSR) via GHCB page.
memremap() will go through iomem_resource list and the address in extra
address space will not be in the list. So I used ioremap_cache(). I will
memremap() instead of ioremap() here.
Does the data structure at this address not have any types that we
could use a struct for?
The struct will be added in the following patch. I will refresh the
following patch and use the struct hv_ghcb for the mapped point.
From: Tianyu Lan <hidden> Date: 2021-06-07 14:57:39
On 6/7/2021 2:43 PM, Christoph Hellwig wrote:
On Sun, May 30, 2021 at 11:06:25AM -0400, Tianyu Lan wrote:
quoted
From: Tianyu Lan <redacted>
For Hyper-V isolation VM with AMD SEV SNP, the bounce buffer(shared memory)
needs to be accessed via extra address space(e.g address above bit39).
Hyper-V code may remap extra address space outside of swiotlb. swiotlb_
bounce() needs to use remap virtual address to copy data from/to bounce
buffer. Add new interface swiotlb_set_bounce_remap() to do that.
Why can't you use the bus_dma_region ranges to remap to your preferred
address?
Thanks for your suggestion.
These addresses in extra address space works as system memory mirror.
The shared memory with host in Isolation VM needs to be accessed via
extra address space which is above shared gpa boundary. During
initializing swiotlb bounce buffer pool, only address bellow shared gpa
boundary can be accepted by swiotlb API because it is treated as system
memory and managed by memory management. This is why Hyper-V swiotlb
bounce buffer pool needs to be allocated in Hyper-V code and map
associated physical address in extra address space. The patch target is
to add the new interface to set start virtual address of bounce buffer
pool and let swiotlb boucne buffer copy function to use right virtual
address for extra address space.
bus_dma_region is to translate cpu physical address to dma address.
It can't modify the virtual address of bounce buffer pool and let
swiotlb code to copy data with right address. If some thing missed,
please correct me.
Thanks.
This probably wnats a helper to make the thing more readable. But who
came up with this fucked up communication protocol where the host needs
to map random pfns into a contigous range? Sometime I really have to
wonder what crack the hyper-v people take when comparing this to the
relatively sane approach others take.
Agree. Will add a helper function.
quoted
+ for (i = 0; i < page_count; i++)
+ dma_unmap_single(&hv_dev->device, packet->dma_range[i].dma,
+ packet->dma_range[i].mapping_size,
+ DMA_TO_DEVICE);
+
+ kfree(packet->dma_range);
Any reason this isn't simply using a struct scatterlist?
I will have a look. Thanks to reminder scatterlist.
quoted
+ for (i = 0; i < page_count; i++) {
+ char *src = phys_to_virt((pb[i].pfn << HV_HYP_PAGE_SHIFT)
+ + pb[i].offset);
+ u32 len = pb[i].len;
+
+ dma = dma_map_single(&hv_dev->device, src, len,
+ DMA_TO_DEVICE);
dma_map_single can only be used on page baked memory, and if this is
using page backed memory you wouldn't need to do thee phys_to_virt
tricks. Can someone explain the mess here in more detail?
Sorry. Could you elaborate the issue? These pages in the pb array are
not allocated by DMA API and using dma_map_single() here is to map these
pages' address to bounce buffer physical address.
On Sun, May 30, 2021 at 11:06:18AM -0400, Tianyu Lan wrote:
quoted hunk
From: Tianyu Lan <redacted>
Hyper-V exposes GHCB page via SEV ES GHCB MSR for SNP guest
to communicate with hypervisor. Map GHCB page for all
cpus to read/write MSR register and submit hvcall request
via GHCB.
Signed-off-by: Tianyu Lan <redacted>
---
arch/x86/hyperv/hv_init.c | 60 ++++++++++++++++++++++++++++++---
arch/x86/include/asm/mshyperv.h | 2 ++
include/asm-generic/mshyperv.h | 2 ++
3 files changed, 60 insertions(+), 4 deletions(-)
@@ -60,6 +60,9 @@ static int hv_cpu_init(unsigned int cpu)structhv_vp_assist_page**hvp=&hv_vp_assist_page[smp_processor_id()];void**input_arg;structpage*pg;+u64ghcb_gpa;+void*ghcb_va;+void**ghcb_base;
Any reason you can't reuse the SEV-ES support code in the Linux kernel?
It already has code to setup GHCBs for all vCPUs.
I see that you don't need #VC handling in your SNP VMs because of the
paravisor running underneath it, but just re-using the GHCB setup code
shouldn't be too hard.
Regards,
Joerg
This is not safe to use from NMI context. You need at least some
checking or WARN_ON/assertion/whatever to catch cases where this is
violated. Otherwise it will result in some hard to debug bug reports.
Regards,
Joerg
Also not NMI-safe. When you re-use the existing GHCB setup code from
from SEV-ES code, you can also use sev_es_get/put_ghcb() which takes
care of re-using a GHCB already in use.
Regards,
Joerg
Why do we need both flags and the enum? I don't see HV_MAP_GPA_* being
used anywhere and VMBUS_PAGE_VISIBLE_READ_WRITE looks like
HV_MAP_GPA_READABLE | HV_MAP_GPA_WRITABLE.
As this is used to communicate with the host, I'd suggest to avoid using
enum and just use flags everywhere.
quoted hunk
/*
* Declare the MSR used to setup pages used to communicate with the hypervisor.
*/
@@ -561,4 +572,17 @@ enum hv_interrupt_type { #include <asm-generic/hyperv-tlfs.h>+/* All input parameters should be in single page. */+#define HV_MAX_MODIFY_GPA_REP_COUNT \+ ((PAGE_SIZE / sizeof(u64)) - 2)++/* HvCallModifySparseGpaPageHostVisibility hypercall */+struct hv_gpa_range_for_visibility {+ u64 partition_id;+ u32 host_visibility:2;+ u32 reserved0:30;+ u32 reserved1;+ u64 gpa_page_list[HV_MAX_MODIFY_GPA_REP_COUNT];+} __packed;+ #endif
@@ -1986,8 +1988,14 @@ static int __set_memory_enc_dec(unsigned long addr, int numpages, bool enc)intret;/* Nothing to do if memory encryption is not active */-if(!mem_encrypt_active())+if(hv_is_isolation_supported()){+returnhv_set_mem_host_visibility((void*)addr,+numpages*HV_HYP_PAGE_SIZE,+enc?VMBUS_PAGE_NOT_VISIBLE+:VMBUS_PAGE_VISIBLE_READ_WRITE);+}elseif(!mem_encrypt_active()){return0;+}/* Should not be working on unaligned addresses */if(WARN_ONCE(addr&~PAGE_MASK,"misaligned address: %#lx\n",addr))
@@ -465,7 +466,7 @@ static int __vmbus_establish_gpadl(struct vmbus_channel *channel,structlist_head*curr;u32next_gpadl_handle;unsignedlongflags;-intret=0;+intret=0,index;next_gpadl_handle=(atomic_inc_return(&vmbus_connection.next_gpadl_handle)-1);
@@ -474,6 +475,13 @@ static int __vmbus_establish_gpadl(struct vmbus_channel *channel,if(ret)returnret;+ret=set_memory_decrypted((unsignedlong)kbuffer,+HVPFN_UP(size));+if(ret){+pr_warn("Failed to set host visibility.\n");+returnret;+}+init_completion(&msginfo->waitevent);msginfo->waiting_channel=channel;
@@ -539,6 +547,15 @@ static int __vmbus_establish_gpadl(struct vmbus_channel *channel,/* At this point, we received the gpadl created msg */*gpadl_handle=gpadlmsg->gpadl;+if(type==HV_GPADL_BUFFER)+index=0;+else+index=channel->gpadl_range[1].gpadlhandle?2:1;++channel->gpadl_range[index].size=size;+channel->gpadl_range[index].buffer=kbuffer;+channel->gpadl_range[index].gpadlhandle=*gpadl_handle;+cleanup:spin_lock_irqsave(&vmbus_connection.channelmsg_lock,flags);list_del(&msginfo->msglistentry);
@@ -549,6 +566,11 @@ static int __vmbus_establish_gpadl(struct vmbus_channel *channel,}kfree(msginfo);++if(ret)+set_memory_encrypted((unsignedlong)kbuffer,+HVPFN_UP(size));+returnret;}
@@ -811,7 +833,7 @@ int vmbus_teardown_gpadl(struct vmbus_channel *channel, u32 gpadl_handle)structvmbus_channel_gpadl_teardown*msg;structvmbus_channel_msginfo*info;unsignedlongflags;-intret;+intret,i;info=kzalloc(sizeof(*info)+sizeof(structvmbus_channel_gpadl_teardown),GFP_KERNEL);
@@ -859,6 +881,18 @@ int vmbus_teardown_gpadl(struct vmbus_channel *channel, u32 gpadl_handle)spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock,flags);kfree(info);++/* Find gpadl buffer virtual address and size. */+for(i=0;i<VMBUS_GPADL_RANGE_COUNT;i++)+if(channel->gpadl_range[i].gpadlhandle==gpadl_handle)+break;++if(set_memory_encrypted((unsignedlong)channel->gpadl_range[i].buffer,+HVPFN_UP(channel->gpadl_range[i].size)))+pr_warn("Fail to set mem host visibility.\n");++channel->gpadl_range[i].gpadlhandle=0;+returnret;}EXPORT_SYMBOL_GPL(vmbus_teardown_gpadl);
From: Tianyu Lan <redacted>
In Isolation VM, all shared memory with host needs to mark visible
to host via hvcall. vmbus_establish_gpadl() has already done it for
netvsc rx/tx ring buffer. The page buffer used by vmbus_sendpacket_
pagebuffer() still need to handle. Use DMA API to map/umap these
memory during sending/receiving packet and Hyper-V DMA ops callback
will use swiotlb function to allocate bounce buffer and copy data
from/to bounce buffer.
Signed-off-by: Tianyu Lan <redacted>
---
drivers/net/hyperv/hyperv_net.h | 6 ++
drivers/net/hyperv/netvsc.c | 125 ++++++++++++++++++++++++++++--
drivers/net/hyperv/rndis_filter.c | 3 +
include/linux/hyperv.h | 5 ++
4 files changed, 133 insertions(+), 6 deletions(-)
@@ -1074,6 +1075,7 @@ struct netvsc_device {/* Receive buffer allocated by us but manages by NetVSP */void*recv_buf;+void*recv_original_buf;u32recv_buf_size;/* allocated bytes */u32recv_buf_gpadl_handle;u32recv_section_cnt;
@@ -1082,6 +1084,8 @@ struct netvsc_device {/* Send buffer allocated by us */void*send_buf;+void*send_original_buf;+u32send_buf_size;u32send_buf_gpadl_handle;u32send_section_cnt;u32send_section_size;
@@ -338,8 +351,10 @@ static int netvsc_init_buf(struct hv_device *device,structnet_device*ndev=hv_get_drvdata(device);structnvsp_message*init_packet;unsignedintbuf_size;+unsignedlong*pfns;size_tmap_words;inti,ret=0;+void*vaddr;/* Get receive buffer area. */buf_size=device_info->recv_sections*device_info->recv_section_size;
@@ -375,6 +390,21 @@ static int netvsc_init_buf(struct hv_device *device,gotocleanup;}+if(hv_isolation_type_snp()){+pfns=kcalloc(buf_size/HV_HYP_PAGE_SIZE,sizeof(unsignedlong),+GFP_KERNEL);+for(i=0;i<buf_size/HV_HYP_PAGE_SIZE;i++)+pfns[i]=virt_to_hvpfn(net_device->recv_buf+i*HV_HYP_PAGE_SIZE)++(ms_hyperv.shared_gpa_boundary>>HV_HYP_PAGE_SHIFT);++vaddr=vmap_pfn(pfns,buf_size/HV_HYP_PAGE_SIZE,PAGE_KERNEL_IO);+kfree(pfns);+if(!vaddr)+gotocleanup;+net_device->recv_original_buf=net_device->recv_buf;+net_device->recv_buf=vaddr;+}+/* Notify the NetVsp of the gpadl handle */init_packet=&net_device->channel_init_pkt;memset(init_packet,0,sizeof(structnvsp_message));
@@ -477,6 +507,23 @@ static int netvsc_init_buf(struct hv_device *device,gotocleanup;}+if(hv_isolation_type_snp()){+pfns=kcalloc(buf_size/HV_HYP_PAGE_SIZE,sizeof(unsignedlong),+GFP_KERNEL);++for(i=0;i<buf_size/HV_HYP_PAGE_SIZE;i++)+pfns[i]=virt_to_hvpfn(net_device->send_buf+i*HV_HYP_PAGE_SIZE)++(ms_hyperv.shared_gpa_boundary>>HV_HYP_PAGE_SHIFT);++vaddr=vmap_pfn(pfns,buf_size/HV_HYP_PAGE_SIZE,PAGE_KERNEL_IO);+kfree(pfns);+if(!vaddr)+gotocleanup;++net_device->send_original_buf=net_device->send_buf;+net_device->send_buf=vaddr;+}+/* Notify the NetVsp of the gpadl handle */init_packet=&net_device->channel_init_pkt;memset(init_packet,0,sizeof(structnvsp_message));
@@ -767,7 +814,7 @@ static void netvsc_send_tx_complete(struct net_device *ndev,/* Notify the layer above us */if(likely(skb)){-conststructhv_netvsc_packet*packet+structhv_netvsc_packet*packet=(structhv_netvsc_packet*)skb->cb;u32send_index=packet->send_buf_index;structnetvsc_stats*tx_stats;
From: Tianyu Lan <hidden> Date: 2021-06-10 14:14:02
Hi Joerg:
Thanks for your review.
On 6/9/2021 8:38 PM, Joerg Roedel wrote:
On Sun, May 30, 2021 at 11:06:18AM -0400, Tianyu Lan wrote:
quoted
From: Tianyu Lan <redacted>
Hyper-V exposes GHCB page via SEV ES GHCB MSR for SNP guest
to communicate with hypervisor. Map GHCB page for all
cpus to read/write MSR register and submit hvcall request
via GHCB.
Signed-off-by: Tianyu Lan <redacted>
---
arch/x86/hyperv/hv_init.c | 60 ++++++++++++++++++++++++++++++---
arch/x86/include/asm/mshyperv.h | 2 ++
include/asm-generic/mshyperv.h | 2 ++
3 files changed, 60 insertions(+), 4 deletions(-)
@@ -60,6 +60,9 @@ static int hv_cpu_init(unsigned int cpu)structhv_vp_assist_page**hvp=&hv_vp_assist_page[smp_processor_id()];void**input_arg;structpage*pg;+u64ghcb_gpa;+void*ghcb_va;+void**ghcb_base;
Any reason you can't reuse the SEV-ES support code in the Linux kernel?
It already has code to setup GHCBs for all vCPUs.
I see that you don't need #VC handling in your SNP VMs because of the
paravisor running underneath it, but just re-using the GHCB setup code
shouldn't be too hard.
Thanks for your suggestion. I will have a try to use SEV-ES code.
This is not safe to use from NMI context. You need at least some
checking or WARN_ON/assertion/whatever to catch cases where this is
violated. Otherwise it will result in some hard to debug bug reports.
Nice catch. Will update in the next version.
Thanks.
Why do we need both flags and the enum? I don't see HV_MAP_GPA_* being
used anywhere and VMBUS_PAGE_VISIBLE_READ_WRITE looks like
HV_MAP_GPA_READABLE | HV_MAP_GPA_WRITABLE.
As this is used to communicate with the host, I'd suggest to avoid using
enum and just use flags everywhere.
Nice catch. Will update in the next version.
Thanks.
From: Tianyu Lan <hidden> Date: 2021-06-10 14:25:43
On 6/7/2021 10:56 PM, Tianyu Lan wrote:
On 6/7/2021 2:43 PM, Christoph Hellwig wrote:
quoted
On Sun, May 30, 2021 at 11:06:25AM -0400, Tianyu Lan wrote:
quoted
From: Tianyu Lan <redacted>
For Hyper-V isolation VM with AMD SEV SNP, the bounce buffer(shared
memory)
needs to be accessed via extra address space(e.g address above bit39).
Hyper-V code may remap extra address space outside of swiotlb. swiotlb_
bounce() needs to use remap virtual address to copy data from/to bounce
buffer. Add new interface swiotlb_set_bounce_remap() to do that.
Why can't you use the bus_dma_region ranges to remap to your preferred
address?
Thanks for your suggestion.
These addresses in extra address space works as system memory mirror.
The shared memory with host in Isolation VM needs to be accessed via
extra address space which is above shared gpa boundary. During
initializing swiotlb bounce buffer pool, only address bellow shared gpa
boundary can be accepted by swiotlb API because it is treated as system
memory and managed by memory management. This is why Hyper-V swiotlb
bounce buffer pool needs to be allocated in Hyper-V code and map
associated physical address in extra address space. The patch target is
to add the new interface to set start virtual address of bounce buffer
pool and let swiotlb boucne buffer copy function to use right virtual
address for extra address space.
bus_dma_region is to translate cpu physical address to dma address.
It can't modify the virtual address of bounce buffer pool and let
swiotlb code to copy data with right address. If some thing missed,
please correct me.
Hi Christoph:
Sorry to bother you. Could you have a look at my previous reply?
I try figuring out the right way.
Thanks.
From: Christoph Hellwig <hch@lst.de> Date: 2021-06-14 07:09:14
On Mon, Jun 07, 2021 at 11:21:20PM +0800, Tianyu Lan wrote:
quoted
dma_map_single can only be used on page baked memory, and if this is
using page backed memory you wouldn't need to do thee phys_to_virt
tricks. Can someone explain the mess here in more detail?
Sorry. Could you elaborate the issue? These pages in the pb array are not
allocated by DMA API and using dma_map_single() here is to map these pages'
address to bounce buffer physical address.
dma_map_single just calls dma_map_page using virt_to_page. So this
can't work on addresses not in the kernel linear mapping.
From: Christoph Hellwig <hch@lst.de> Date: 2021-06-14 07:12:35
On Mon, Jun 07, 2021 at 10:56:47PM +0800, Tianyu Lan wrote:
These addresses in extra address space works as system memory mirror. The
shared memory with host in Isolation VM needs to be accessed via extra
address space which is above shared gpa boundary.
From: Tom Lendacky <thomas.lendacky@amd.com> Date: 2021-06-14 13:29:42
On 6/14/21 2:12 AM, Christoph Hellwig wrote:
On Mon, Jun 07, 2021 at 10:56:47PM +0800, Tianyu Lan wrote:
quoted
These addresses in extra address space works as system memory mirror. The
shared memory with host in Isolation VM needs to be accessed via extra
address space which is above shared gpa boundary.
Why?
IIUC, this is using the vTOM feature of SEV-SNP. When this feature is
enabled for a VMPL level, any physical memory addresses below vTOM are
considered private/encrypted and any physical memory addresses above vTOM
are considered shared/unencrypted. With this option, you don't need a
fully enlightened guest that sets and clears page table encryption bits.
You just need the DMA buffers to be allocated in the proper range above vTOM.
See the section on "Virtual Machine Privilege Levels" in
https://www.amd.com/system/files/TechDocs/SEV-SNP-strengthening-vm-isolation-with-integrity-protection-and-more.pdf.
Thanks,
Tom
From: Tianyu Lan <hidden> Date: 2021-06-14 13:37:26
On 6/14/2021 3:12 PM, Christoph Hellwig wrote:
On Mon, Jun 07, 2021 at 10:56:47PM +0800, Tianyu Lan wrote:
quoted
These addresses in extra address space works as system memory mirror. The
shared memory with host in Isolation VM needs to be accessed via extra
address space which is above shared gpa boundary.
Why?
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. Using vTOM to
separate memory in this way avoids the need to augment the standard x86
page tables with C-bit markings, simplifying guest OS software.
From: Tianyu Lan <hidden> Date: 2021-06-14 13:43:20
On 6/14/2021 9:37 PM, Tianyu Lan wrote:
On 6/14/2021 3:12 PM, Christoph Hellwig wrote:
quoted
On Mon, Jun 07, 2021 at 10:56:47PM +0800, Tianyu Lan wrote:
quoted
These addresses in extra address space works as system memory mirror.
The
shared memory with host in Isolation VM needs to be accessed via extra
address space which is above shared gpa boundary.
Why?
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. Using vTOM to
separate memory in this way avoids the need to augment the standard x86
page tables with C-bit markings, simplifying guest OS software.
From: Robin Murphy <robin.murphy@arm.com> Date: 2021-06-14 13:50:12
On 2021-06-07 07:43, Christoph Hellwig wrote:
On Sun, May 30, 2021 at 11:06:25AM -0400, Tianyu Lan wrote:
quoted
From: Tianyu Lan <redacted>
For Hyper-V isolation VM with AMD SEV SNP, the bounce buffer(shared memory)
needs to be accessed via extra address space(e.g address above bit39).
Hyper-V code may remap extra address space outside of swiotlb. swiotlb_
bounce() needs to use remap virtual address to copy data from/to bounce
buffer. Add new interface swiotlb_set_bounce_remap() to do that.
Why can't you use the bus_dma_region ranges to remap to your preferred
address?
FWIW, I think a better generalisation for this would be allowing
set_memory_decrypted() to return an address rather than implicitly
operating in-place, and hide all the various hypervisor hooks behind that.
Robin.
From: Tianyu Lan <hidden> Date: 2021-06-14 14:05:32
On 6/14/2021 3:09 PM, Christoph Hellwig wrote:
On Mon, Jun 07, 2021 at 11:21:20PM +0800, Tianyu Lan wrote:
quoted
quoted
dma_map_single can only be used on page baked memory, and if this is
using page backed memory you wouldn't need to do thee phys_to_virt
tricks. Can someone explain the mess here in more detail?
Sorry. Could you elaborate the issue? These pages in the pb array are not
allocated by DMA API and using dma_map_single() here is to map these pages'
address to bounce buffer physical address.
dma_map_single just calls dma_map_page using virt_to_page. So this
can't work on addresses not in the kernel linear mapping.
The pages in the hv_page_buffer array here are in the kernel linear
mapping. The packet sent to host will contain an array which contains
transaction data. In the isolation VM, data in the these pages needs to
be copied to bounce buffer and so call dma_map_single() here to map
these data pages with bounce buffer. The vmbus has ring buffer where the
send/receive packets are copied to/from. The ring buffer has been
remapped to the extra space above shared gpa boundary/vTom during
probing Netvsc driver and so not call dma map function for vmbus ring
buffer.
From: Christoph Hellwig <hch@lst.de> Date: 2021-06-14 15:33:07
On Mon, Jun 14, 2021 at 02:49:51PM +0100, Robin Murphy wrote:
FWIW, I think a better generalisation for this would be allowing
set_memory_decrypted() to return an address rather than implicitly
operating in-place, and hide all the various hypervisor hooks behind that.
Yes, something like that would be a good idea. As-is
set_memory_decrypted is a pretty horribly API anyway due to passing
the address as void, and taking a size parameter while it works in units
of pages. So I'd very much welcome a major overhaul of this API.
From: Christoph Hellwig <hch@lst.de> Date: 2021-06-14 15:33:49
On Mon, Jun 14, 2021 at 10:04:06PM +0800, Tianyu Lan wrote:
The pages in the hv_page_buffer array here are in the kernel linear
mapping. The packet sent to host will contain an array which contains
transaction data. In the isolation VM, data in the these pages needs to be
copied to bounce buffer and so call dma_map_single() here to map these data
pages with bounce buffer. The vmbus has ring buffer where the send/receive
packets are copied to/from. The ring buffer has been remapped to the extra
space above shared gpa boundary/vTom during probing Netvsc driver and so
not call dma map function for vmbus ring
buffer.
So why do we have all that PFN magic instead of using struct page or
the usual kernel I/O buffers that contain a page pointer?
From: Tianyu Lan <hidden> Date: 2021-06-15 14:31:49
On 6/14/2021 11:33 PM, Christoph Hellwig wrote:
On Mon, Jun 14, 2021 at 10:04:06PM +0800, Tianyu Lan wrote:
quoted
The pages in the hv_page_buffer array here are in the kernel linear
mapping. The packet sent to host will contain an array which contains
transaction data. In the isolation VM, data in the these pages needs to be
copied to bounce buffer and so call dma_map_single() here to map these data
pages with bounce buffer. The vmbus has ring buffer where the send/receive
packets are copied to/from. The ring buffer has been remapped to the extra
space above shared gpa boundary/vTom during probing Netvsc driver and so
not call dma map function for vmbus ring
buffer.
So why do we have all that PFN magic instead of using struct page or
the usual kernel I/O buffers that contain a page pointer?
These PFNs originally is part of Hyper-V protocol data and will be sent
to host. Host accepts these GFN and copy data from/to guest memory. The
translation from va to pa is done by caller that populates the
hv_page_buffer array. I will try calling dma map function before
populating struct hv_page_buffer and this can avoid redundant
translation between PA and VA.
From: Tianyu Lan <hidden> Date: 2021-06-15 15:25:14
On 6/14/2021 11:32 PM, Christoph Hellwig wrote:
On Mon, Jun 14, 2021 at 02:49:51PM +0100, Robin Murphy wrote:
quoted
FWIW, I think a better generalisation for this would be allowing
set_memory_decrypted() to return an address rather than implicitly
operating in-place, and hide all the various hypervisor hooks behind that.
Yes, something like that would be a good idea. As-is
set_memory_decrypted is a pretty horribly API anyway due to passing
the address as void, and taking a size parameter while it works in units
of pages. So I'd very much welcome a major overhaul of this API.
Hi Christoph and Robin:
Thanks for your suggestion. I will try this idea in the next version.
Besides make the address translation into set_memory_
decrypted() and return address, do you want to make other changes to the
API in order to make it more reasonable(e.g size parameter)?
Thanks
From: Tianyu Lan <hidden> Date: 2021-07-12 09:40:39
Hi Christoph and Robin:
I introduced new interface set_memory_decrypted_map() to hide all
the hypervisor code behind it in the latest version. In current generic
code, only swiotlb bounce buffer needs to be decrypted and remapped in
the same time and so keep set_memory_decrypted(). If there were more
requests of set_memory_decrypted_map() for other platform, we may
replace set_memory_decrypted() step by step. Please have a look.
https://lkml.org/lkml/2021/7/7/570
Thanks.
On 6/15/2021 11:24 PM, Tianyu Lan wrote:
On 6/14/2021 11:32 PM, Christoph Hellwig wrote:
quoted
On Mon, Jun 14, 2021 at 02:49:51PM +0100, Robin Murphy wrote:
quoted
FWIW, I think a better generalisation for this would be allowing
set_memory_decrypted() to return an address rather than implicitly
operating in-place, and hide all the various hypervisor hooks behind
that.
Yes, something like that would be a good idea. As-is
set_memory_decrypted is a pretty horribly API anyway due to passing
the address as void, and taking a size parameter while it works in units
of pages. So I'd very much welcome a major overhaul of this API.
Hi Christoph and Robin:
Thanks for your suggestion. I will try this idea in the next
version. Besides make the address translation into set_memory_
decrypted() and return address, do you want to make other changes to the
API in order to make it more reasonable(e.g size parameter)?
Thanks