Skip to content

Commit

Permalink
swiotlb: Add a new cc-swiotlb implementation for Confidential VMs
Browse files Browse the repository at this point in the history
Under COnfidential COmputing (CoCo) scenarios, the VMM cannot access
guest memory directly but requires the guest to explicitly mark the
memory as shared (decrypted). To make the streaming DMA mappings work,
the current implementation relays on legacy SWIOTLB to bounce the DMA
buffer between private (encrypted) and shared (decrypted) memory.

However, the legacy swiotlb is designed for compatibility rather than
efficiency and CoCo purpose, which will inevitably introduce some
unnecessary restrictions.
1. Fixed immutable swiotlb size cannot accommodate to requirements of
   multiple devices. And 1GiB (current maximum size) of swiotlb in our
   testbed cannot afford multiple disks reads/writes simultaneously.
2. Fixed immutable IO_TLB_SIZE (2KiB) cannot satisfy various kinds of
   devices. At the moment, the minimal size of a swiotlb buffer is 2KiB,
   which will waste memory on small network packets (under 512 bytes)
   and decrease efficiency on a large block (up to 256KiB) size
   reads/writes of disks. And it is hard to have a trade-off on legacy
   swiotlb to rule them all.
3. The legacy swiotlb cannot efficiently support larger swiotlb buffers.
   In the worst case, the current implementation requires a full scan of
   the entire swiotlb buffer, which can cause severe performance hits.

Instead of keeping "infecting" the legacy swiotlb code with CoCo logic,
this patch tries to introduce a new cc-swiotlb for Confidential VMs.

Confidential VMs usually have reasonable modern devices (virtio devices,
NVME, etc.), which can access memory above 4GiB, cc-swiotlb could
allocate TLB buffers dynamically on-demand, and this design solves
problem 1.

In addition, the cc-swiotlb manages TLB buffers by different sizes
(512B, 2KiB, 4KiB, 16KiB, and 512KiB), which solves problems 2 and 3.

Signed-off-by: GuoRui.Yu <GuoRui.Yu@linux.alibaba.com>
  • Loading branch information
GuoRui.Yu authored and intel-lab-lkp committed Jan 28, 2023
1 parent 1f158ef commit 9345d2c
Show file tree
Hide file tree
Showing 15 changed files with 537 additions and 15 deletions.
3 changes: 2 additions & 1 deletion arch/x86/Kconfig
Expand Up @@ -31,7 +31,7 @@ config X86_64
select HAVE_ARCH_SOFT_DIRTY
select MODULES_USE_ELF_RELA
select NEED_DMA_MAP_STATE
select SWIOTLB
select SWIOTLB if !X86_MEM_ENCRYPT
select ARCH_HAS_ELFCORE_COMPAT
select ZONE_DMA32

Expand Down Expand Up @@ -1535,6 +1535,7 @@ config X86_CPA_STATISTICS
config X86_MEM_ENCRYPT
select ARCH_HAS_FORCE_DMA_UNENCRYPTED
select DYNAMIC_PHYSICAL_MASK
select SWIOTLB if !CC_SWIOTLB
def_bool n

config AMD_MEM_ENCRYPT
Expand Down
2 changes: 1 addition & 1 deletion arch/x86/include/asm/iommu.h
Expand Up @@ -11,7 +11,7 @@ extern int iommu_detected;
extern int iommu_merge;
extern int panic_on_overflow;

#ifdef CONFIG_SWIOTLB
#if defined(CONFIG_SWIOTLB) || defined(CONFIG_CC_SWIOTLB)
extern bool x86_swiotlb_enable;
#else
#define x86_swiotlb_enable false
Expand Down
6 changes: 3 additions & 3 deletions arch/x86/kernel/pci-dma.c
Expand Up @@ -37,7 +37,7 @@ int no_iommu __read_mostly;
/* Set this to 1 if there is a HW IOMMU in the system */
int iommu_detected __read_mostly = 0;

#ifdef CONFIG_SWIOTLB
#if defined(CONFIG_SWIOTLB) || defined(CONFIG_CC_SWIOTLB)
bool x86_swiotlb_enable;
static unsigned int x86_swiotlb_flags;

Expand Down Expand Up @@ -169,7 +169,7 @@ static __init int iommu_setup(char *p)
disable_dac_quirk = true;
return 1;
}
#ifdef CONFIG_SWIOTLB
#if defined(CONFIG_SWIOTLB) || defined(CONFIG_CC_SWIOTLB)
if (!strncmp(p, "soft", 4))
x86_swiotlb_enable = true;
#endif
Expand All @@ -192,7 +192,7 @@ static int __init pci_iommu_init(void)
{
x86_init.iommu.iommu_init();

#ifdef CONFIG_SWIOTLB
#if defined(CONFIG_SWIOTLB) || defined(CONFIG_CC_SWIOTLB)
/* An IOMMU turned us off. */
if (x86_swiotlb_enable) {
pr_info("PCI-DMA: Using software bounce buffering for IO (SWIOTLB)\n");
Expand Down
2 changes: 1 addition & 1 deletion drivers/base/core.c
Expand Up @@ -2955,7 +2955,7 @@ void device_initialize(struct device *dev)
defined(CONFIG_ARCH_HAS_SYNC_DMA_FOR_CPU_ALL)
dev->dma_coherent = dma_default_coherent;
#endif
#ifdef CONFIG_SWIOTLB
#if defined(CONFIG_SWIOTLB) || defined(CONFIG_CC_SWIOTLB)
dev->dma_io_tlb_mem = &io_tlb_default_mem;
#endif
}
Expand Down
2 changes: 1 addition & 1 deletion drivers/iommu/amd/Kconfig
Expand Up @@ -2,7 +2,7 @@
# AMD IOMMU support
config AMD_IOMMU
bool "AMD IOMMU support"
select SWIOTLB
select SWIOTLB if !X86_MEM_ENCRYPT
select PCI_MSI
select PCI_ATS
select PCI_PRI
Expand Down
2 changes: 1 addition & 1 deletion drivers/iommu/dma-iommu.c
Expand Up @@ -519,7 +519,7 @@ static bool dev_is_untrusted(struct device *dev)

static bool dev_use_swiotlb(struct device *dev)
{
return IS_ENABLED(CONFIG_SWIOTLB) && dev_is_untrusted(dev);
return (IS_ENABLED(CONFIG_SWIOTLB) || IS_ENABLED(CONFIG_CC_SWIOTLB)) && dev_is_untrusted(dev);
}

/**
Expand Down
2 changes: 1 addition & 1 deletion drivers/iommu/intel/Kconfig
Expand Up @@ -17,7 +17,7 @@ config INTEL_IOMMU
select IOMMU_IOVA
select NEED_DMA_MAP_STATE
select DMAR_TABLE
select SWIOTLB
select SWIOTLB if !X86_MEM_ENCRYPT
select IOASID
select PCI_ATS
select PCI_PRI
Expand Down
2 changes: 1 addition & 1 deletion include/linux/device.h
Expand Up @@ -607,7 +607,7 @@ struct device {
struct cma *cma_area; /* contiguous memory area for dma
allocations */
#endif
#ifdef CONFIG_SWIOTLB
#if defined(CONFIG_SWIOTLB) || defined(CONFIG_CC_SWIOTLB)
struct io_tlb_mem *dma_io_tlb_mem;
#endif
/* arch specific additions */
Expand Down
19 changes: 18 additions & 1 deletion include/linux/swiotlb.h
Expand Up @@ -106,6 +106,23 @@ struct io_tlb_mem {
struct io_tlb_area *areas;
struct io_tlb_slot *slots;
};
#elif defined(CONFIG_CC_SWIOTLB)

/**
* struct io_tlb_mem - io tlb memory pool descriptor
*
* @force_bounce: %true if swiotlb bouncing is forced
* @mapping: the mapping relations between the END address of backing memory and
* original DMA address.
*/
struct io_tlb_mem {
bool force_bounce;
struct xarray* mapping;
struct dentry *debugfs;
};
#endif

#if defined(CONFIG_SWIOTLB) || defined(CONFIG_CC_SWIOTLB)
extern struct io_tlb_mem io_tlb_default_mem;

bool is_swiotlb_buffer(struct device *dev, phys_addr_t paddr);
Expand Down Expand Up @@ -155,7 +172,7 @@ static inline bool is_swiotlb_active(struct device *dev)
static inline void swiotlb_adjust_size(unsigned long size)
{
}
#endif /* CONFIG_SWIOTLB */
#endif /* CONFIG_SWIOTLB || CONFIG_CC_SWIOTLB */

extern void swiotlb_print_info(void);

Expand Down
10 changes: 10 additions & 0 deletions kernel/dma/Kconfig
Expand Up @@ -78,8 +78,18 @@ config ARCH_HAS_FORCE_DMA_UNENCRYPTED

config SWIOTLB
bool
depends on !CC_SWIOTLB
select NEED_DMA_MAP_STATE

config CC_SWIOTLB
bool "Enable cc-swiotlb for Confidential VMs"
default n
select NEED_DMA_MAP_STATE
help
This enables a cc-swiotlb implementation for Confidential VMs,
which allows allocating the SWIOTLB buffer allocation on runtime.
If unsure, say "n".

config DMA_RESTRICTED_POOL
bool "DMA Restricted Pool"
depends on OF && OF_RESERVED_MEM && SWIOTLB
Expand Down
1 change: 1 addition & 0 deletions kernel/dma/Makefile
Expand Up @@ -7,6 +7,7 @@ obj-$(CONFIG_DMA_CMA) += contiguous.o
obj-$(CONFIG_DMA_DECLARE_COHERENT) += coherent.o
obj-$(CONFIG_DMA_API_DEBUG) += debug.o
obj-$(CONFIG_SWIOTLB) += swiotlb.o common-swiotlb.o
obj-$(CONFIG_CC_SWIOTLB) += cc-swiotlb.o common-swiotlb.o
obj-$(CONFIG_DMA_COHERENT_POOL) += pool.o
obj-$(CONFIG_MMU) += remap.o
obj-$(CONFIG_DMA_MAP_BENCHMARK) += map_benchmark.o

0 comments on commit 9345d2c

Please sign in to comment.