memory: Add RAM_PROTECTED flag to skip IOMMU mappings

Add a new RAMBlock flag to denote "protected" memory, i.e. memory that
looks and acts like RAM but is inaccessible via normal mechanisms,
including DMA.  Use the flag to skip protected memory regions when
mapping RAM for DMA in VFIO.

Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
Signed-off-by: Yang Zhong <yang.zhong@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Sean Christopherson 2021-07-19 19:21:04 +08:00 committed by Paolo Bonzini
parent ba0fa56bc0
commit 56918a126a
4 changed files with 22 additions and 2 deletions

View File

@ -562,6 +562,7 @@ static bool vfio_listener_skipped_section(MemoryRegionSection *section)
{ {
return (!memory_region_is_ram(section->mr) && return (!memory_region_is_ram(section->mr) &&
!memory_region_is_iommu(section->mr)) || !memory_region_is_iommu(section->mr)) ||
memory_region_is_protected(section->mr) ||
/* /*
* Sizing an enabled 64-bit BAR can cause spurious mappings to * Sizing an enabled 64-bit BAR can cause spurious mappings to
* addresses in the upper part of the 64-bit address space. These * addresses in the upper part of the 64-bit address space. These

View File

@ -190,6 +190,9 @@ typedef struct IOMMUTLBEvent {
*/ */
#define RAM_NORESERVE (1 << 7) #define RAM_NORESERVE (1 << 7)
/* RAM that isn't accessible through normal means. */
#define RAM_PROTECTED (1 << 8)
static inline void iommu_notifier_init(IOMMUNotifier *n, IOMMUNotify fn, static inline void iommu_notifier_init(IOMMUNotifier *n, IOMMUNotify fn,
IOMMUNotifierFlag flags, IOMMUNotifierFlag flags,
hwaddr start, hwaddr end, hwaddr start, hwaddr end,
@ -1267,7 +1270,7 @@ void memory_region_init_ram_from_file(MemoryRegion *mr,
* @name: the name of the region. * @name: the name of the region.
* @size: size of the region. * @size: size of the region.
* @ram_flags: RamBlock flags. Supported flags: RAM_SHARED, RAM_PMEM, * @ram_flags: RamBlock flags. Supported flags: RAM_SHARED, RAM_PMEM,
* RAM_NORESERVE. * RAM_NORESERVE, RAM_PROTECTED.
* @fd: the fd to mmap. * @fd: the fd to mmap.
* @offset: offset within the file referenced by fd * @offset: offset within the file referenced by fd
* @errp: pointer to Error*, to store an error if it happens. * @errp: pointer to Error*, to store an error if it happens.
@ -1568,6 +1571,16 @@ static inline bool memory_region_is_romd(MemoryRegion *mr)
return mr->rom_device && mr->romd_mode; return mr->rom_device && mr->romd_mode;
} }
/**
* memory_region_is_protected: check whether a memory region is protected
*
* Returns %true if a memory region is protected RAM and cannot be accessed
* via standard mechanisms, e.g. DMA.
*
* @mr: the memory region being queried
*/
bool memory_region_is_protected(MemoryRegion *mr);
/** /**
* memory_region_get_iommu: check whether a memory region is an iommu * memory_region_get_iommu: check whether a memory region is an iommu
* *

View File

@ -1811,6 +1811,11 @@ bool memory_region_is_ram_device(MemoryRegion *mr)
return mr->ram_device; return mr->ram_device;
} }
bool memory_region_is_protected(MemoryRegion *mr)
{
return mr->ram && (mr->ram_block->flags & RAM_PROTECTED);
}
uint8_t memory_region_get_dirty_log_mask(MemoryRegion *mr) uint8_t memory_region_get_dirty_log_mask(MemoryRegion *mr)
{ {
uint8_t mask = mr->dirty_log_mask; uint8_t mask = mr->dirty_log_mask;

View File

@ -2055,7 +2055,8 @@ RAMBlock *qemu_ram_alloc_from_fd(ram_addr_t size, MemoryRegion *mr,
int64_t file_size, file_align; int64_t file_size, file_align;
/* Just support these ram flags by now. */ /* Just support these ram flags by now. */
assert((ram_flags & ~(RAM_SHARED | RAM_PMEM | RAM_NORESERVE)) == 0); assert((ram_flags & ~(RAM_SHARED | RAM_PMEM | RAM_NORESERVE |
RAM_PROTECTED)) == 0);
if (xen_enabled()) { if (xen_enabled()) {
error_setg(errp, "-mem-path not supported with Xen"); error_setg(errp, "-mem-path not supported with Xen");