[RFC V2 PATCH 9/12] swiotlb: Add bounce buffer remap address setting function

From: Tianyu Lan
Date: Tue Apr 13 2021 - 11:23:04 EST


From: Tianyu Lan <Tianyu.Lan@xxxxxxxxxxxxx>

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 <Tianyu.Lan@xxxxxxxxxxxxx>
---
include/linux/swiotlb.h | 5 +++++
kernel/dma/swiotlb.c | 13 ++++++++++++-
2 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h
index d9c9fc9ca5d2..3ccd08116683 100644
--- a/include/linux/swiotlb.h
+++ b/include/linux/swiotlb.h
@@ -82,8 +82,13 @@ unsigned int swiotlb_max_segment(void);
size_t swiotlb_max_mapping_size(struct device *dev);
bool is_swiotlb_active(void);
void __init swiotlb_adjust_size(unsigned long new_size);
+void swiotlb_set_bounce_remap(unsigned char *vaddr);
#else
#define swiotlb_force SWIOTLB_NO_FORCE
+static inline void swiotlb_set_bounce_remap(unsigned char *vaddr)
+{
+}
+
static inline bool is_swiotlb_buffer(phys_addr_t paddr)
{
return false;
diff --git a/kernel/dma/swiotlb.c b/kernel/dma/swiotlb.c
index 7c42df6e6100..5fd2db6aa149 100644
--- a/kernel/dma/swiotlb.c
+++ b/kernel/dma/swiotlb.c
@@ -94,6 +94,7 @@ static unsigned int io_tlb_index;
* not be bounced (unless SWIOTLB_FORCE is set).
*/
static unsigned int max_segment;
+static unsigned char *swiotlb_bounce_remap_addr;

/*
* We need to save away the original address corresponding to a mapped entry
@@ -421,6 +422,11 @@ void __init swiotlb_exit(void)
swiotlb_cleanup();
}

+void swiotlb_set_bounce_remap(unsigned char *vaddr)
+{
+ swiotlb_bounce_remap_addr = vaddr;
+}
+
/*
* Bounce: copy the swiotlb buffer from or back to the original dma location
*/
@@ -428,7 +434,12 @@ static void swiotlb_bounce(phys_addr_t orig_addr, phys_addr_t tlb_addr,
size_t size, enum dma_data_direction dir)
{
unsigned long pfn = PFN_DOWN(orig_addr);
- unsigned char *vaddr = phys_to_virt(tlb_addr);
+ unsigned char *vaddr;
+
+ if (swiotlb_bounce_remap_addr)
+ vaddr = swiotlb_bounce_remap_addr + tlb_addr - io_tlb_start;
+ else
+ vaddr = phys_to_virt(tlb_addr);

if (PageHighMem(pfn_to_page(pfn))) {
/* The buffer does not have a mapping. Map it in and copy */
--
2.25.1