Re: [PATCH v10 1/2] vfio: move implement of vfio_get_xlat_addr() to memory.c

2022-11-02 Thread Michael S. Tsirkin
On Mon, Oct 31, 2022 at 08:57:01PM +0800, Cindy Lu wrote:
> - Move the implement vfio_get_xlat_addr to softmmu/memory.c, and
>   change the name to memory_get_xlat_addr(). So we can use this
>   function on other devices, such as vDPA device.
> - Add a new function vfio_get_xlat_addr in vfio/common.c, and it will check
>   whether the memory is backed by a discard manager. then device can
>   have its own warning.
> 
> Signed-off-by: Cindy Lu 

This is in my tree now, pls note this if you repost so
I don't get confused.

> ---
>  hw/vfio/common.c  | 66 +++
>  include/exec/memory.h |  4 +++
>  softmmu/memory.c  | 72 +++
>  3 files changed, 81 insertions(+), 61 deletions(-)
> 
> diff --git a/hw/vfio/common.c b/hw/vfio/common.c
> index ace9562a9b..6bc02b32c8 100644
> --- a/hw/vfio/common.c
> +++ b/hw/vfio/common.c
> @@ -578,45 +578,11 @@ static bool 
> vfio_listener_skipped_section(MemoryRegionSection *section)
>  static bool vfio_get_xlat_addr(IOMMUTLBEntry *iotlb, void **vaddr,
> ram_addr_t *ram_addr, bool *read_only)
>  {
> -MemoryRegion *mr;
> -hwaddr xlat;
> -hwaddr len = iotlb->addr_mask + 1;
> -bool writable = iotlb->perm & IOMMU_WO;
> -
> -/*
> - * The IOMMU TLB entry we have just covers translation through
> - * this IOMMU to its immediate target.  We need to translate
> - * it the rest of the way through to memory.
> - */
> -mr = address_space_translate(_space_memory,
> - iotlb->translated_addr,
> - , , writable,
> - MEMTXATTRS_UNSPECIFIED);
> -if (!memory_region_is_ram(mr)) {
> -error_report("iommu map to non memory area %"HWADDR_PRIx"",
> - xlat);
> -return false;
> -} else if (memory_region_has_ram_discard_manager(mr)) {
> -RamDiscardManager *rdm = memory_region_get_ram_discard_manager(mr);
> -MemoryRegionSection tmp = {
> -.mr = mr,
> -.offset_within_region = xlat,
> -.size = int128_make64(len),
> -};
> -
> -/*
> - * Malicious VMs can map memory into the IOMMU, which is expected
> - * to remain discarded. vfio will pin all pages, populating memory.
> - * Disallow that. vmstate priorities make sure any RamDiscardManager
> - * were already restored before IOMMUs are restored.
> - */
> -if (!ram_discard_manager_is_populated(rdm, )) {
> -error_report("iommu map to discarded memory (e.g., unplugged via"
> - " virtio-mem): %"HWADDR_PRIx"",
> - iotlb->translated_addr);
> -return false;
> -}
> +bool ret, mr_has_discard_manager;
>  
> +ret = memory_get_xlat_addr(iotlb, vaddr, ram_addr, read_only,
> +   _has_discard_manager);
> +if (ret && mr_has_discard_manager) {
>  /*
>   * Malicious VMs might trigger discarding of IOMMU-mapped memory. The
>   * pages will remain pinned inside vfio until unmapped, resulting in 
> a
> @@ -635,29 +601,7 @@ static bool vfio_get_xlat_addr(IOMMUTLBEntry *iotlb, 
> void **vaddr,
>   " intended via an IOMMU. It's possible to mitigate "
>   " by setting/adjusting RLIMIT_MEMLOCK.");
>  }
> -
> -/*
> - * Translation truncates length to the IOMMU page size,
> - * check that it did not truncate too much.
> - */
> -if (len & iotlb->addr_mask) {
> -error_report("iommu has granularity incompatible with target AS");
> -return false;
> -}
> -
> -if (vaddr) {
> -*vaddr = memory_region_get_ram_ptr(mr) + xlat;
> -}
> -
> -if (ram_addr) {
> -*ram_addr = memory_region_get_ram_addr(mr) + xlat;
> -}
> -
> -if (read_only) {
> -*read_only = !writable || mr->readonly;
> -}
> -
> -return true;
> +return ret;
>  }
>  
>  static void vfio_iommu_map_notify(IOMMUNotifier *n, IOMMUTLBEntry *iotlb)
> diff --git a/include/exec/memory.h b/include/exec/memory.h
> index bfb1de8eea..d1e79c39dc 100644
> --- a/include/exec/memory.h
> +++ b/include/exec/memory.h
> @@ -713,6 +713,10 @@ void 
> ram_discard_manager_register_listener(RamDiscardManager *rdm,
>  void ram_discard_manager_unregister_listener(RamDiscardManager *rdm,
>   RamDiscardListener *rdl);
>  
> +bool memory_get_xlat_addr(IOMMUTLBEntry *iotlb, void **vaddr,
> +  ram_addr_t *ram_addr, bool *read_only,
> +  bool *mr_has_discard_manager);
> +
>  typedef struct CoalescedMemoryRange CoalescedMemoryRange;
>  typedef struct MemoryRegionIoeventfd MemoryRegionIoeventfd;
>  
> diff --git a/softmmu/memory.c b/softmmu/memory.c
> index 7ba2048836..bc0be3f62c 100644
> --- 

[PATCH v10 1/2] vfio: move implement of vfio_get_xlat_addr() to memory.c

2022-10-31 Thread Cindy Lu
- Move the implement vfio_get_xlat_addr to softmmu/memory.c, and
  change the name to memory_get_xlat_addr(). So we can use this
  function on other devices, such as vDPA device.
- Add a new function vfio_get_xlat_addr in vfio/common.c, and it will check
  whether the memory is backed by a discard manager. then device can
  have its own warning.

Signed-off-by: Cindy Lu 
---
 hw/vfio/common.c  | 66 +++
 include/exec/memory.h |  4 +++
 softmmu/memory.c  | 72 +++
 3 files changed, 81 insertions(+), 61 deletions(-)

diff --git a/hw/vfio/common.c b/hw/vfio/common.c
index ace9562a9b..6bc02b32c8 100644
--- a/hw/vfio/common.c
+++ b/hw/vfio/common.c
@@ -578,45 +578,11 @@ static bool 
vfio_listener_skipped_section(MemoryRegionSection *section)
 static bool vfio_get_xlat_addr(IOMMUTLBEntry *iotlb, void **vaddr,
ram_addr_t *ram_addr, bool *read_only)
 {
-MemoryRegion *mr;
-hwaddr xlat;
-hwaddr len = iotlb->addr_mask + 1;
-bool writable = iotlb->perm & IOMMU_WO;
-
-/*
- * The IOMMU TLB entry we have just covers translation through
- * this IOMMU to its immediate target.  We need to translate
- * it the rest of the way through to memory.
- */
-mr = address_space_translate(_space_memory,
- iotlb->translated_addr,
- , , writable,
- MEMTXATTRS_UNSPECIFIED);
-if (!memory_region_is_ram(mr)) {
-error_report("iommu map to non memory area %"HWADDR_PRIx"",
- xlat);
-return false;
-} else if (memory_region_has_ram_discard_manager(mr)) {
-RamDiscardManager *rdm = memory_region_get_ram_discard_manager(mr);
-MemoryRegionSection tmp = {
-.mr = mr,
-.offset_within_region = xlat,
-.size = int128_make64(len),
-};
-
-/*
- * Malicious VMs can map memory into the IOMMU, which is expected
- * to remain discarded. vfio will pin all pages, populating memory.
- * Disallow that. vmstate priorities make sure any RamDiscardManager
- * were already restored before IOMMUs are restored.
- */
-if (!ram_discard_manager_is_populated(rdm, )) {
-error_report("iommu map to discarded memory (e.g., unplugged via"
- " virtio-mem): %"HWADDR_PRIx"",
- iotlb->translated_addr);
-return false;
-}
+bool ret, mr_has_discard_manager;
 
+ret = memory_get_xlat_addr(iotlb, vaddr, ram_addr, read_only,
+   _has_discard_manager);
+if (ret && mr_has_discard_manager) {
 /*
  * Malicious VMs might trigger discarding of IOMMU-mapped memory. The
  * pages will remain pinned inside vfio until unmapped, resulting in a
@@ -635,29 +601,7 @@ static bool vfio_get_xlat_addr(IOMMUTLBEntry *iotlb, void 
**vaddr,
  " intended via an IOMMU. It's possible to mitigate "
  " by setting/adjusting RLIMIT_MEMLOCK.");
 }
-
-/*
- * Translation truncates length to the IOMMU page size,
- * check that it did not truncate too much.
- */
-if (len & iotlb->addr_mask) {
-error_report("iommu has granularity incompatible with target AS");
-return false;
-}
-
-if (vaddr) {
-*vaddr = memory_region_get_ram_ptr(mr) + xlat;
-}
-
-if (ram_addr) {
-*ram_addr = memory_region_get_ram_addr(mr) + xlat;
-}
-
-if (read_only) {
-*read_only = !writable || mr->readonly;
-}
-
-return true;
+return ret;
 }
 
 static void vfio_iommu_map_notify(IOMMUNotifier *n, IOMMUTLBEntry *iotlb)
diff --git a/include/exec/memory.h b/include/exec/memory.h
index bfb1de8eea..d1e79c39dc 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -713,6 +713,10 @@ void 
ram_discard_manager_register_listener(RamDiscardManager *rdm,
 void ram_discard_manager_unregister_listener(RamDiscardManager *rdm,
  RamDiscardListener *rdl);
 
+bool memory_get_xlat_addr(IOMMUTLBEntry *iotlb, void **vaddr,
+  ram_addr_t *ram_addr, bool *read_only,
+  bool *mr_has_discard_manager);
+
 typedef struct CoalescedMemoryRange CoalescedMemoryRange;
 typedef struct MemoryRegionIoeventfd MemoryRegionIoeventfd;
 
diff --git a/softmmu/memory.c b/softmmu/memory.c
index 7ba2048836..bc0be3f62c 100644
--- a/softmmu/memory.c
+++ b/softmmu/memory.c
@@ -33,6 +33,7 @@
 #include "qemu/accel.h"
 #include "hw/boards.h"
 #include "migration/vmstate.h"
+#include "exec/address-spaces.h"
 
 //#define DEBUG_UNASSIGNED
 
@@ -2121,6 +2122,77 @@ void 
ram_discard_manager_unregister_listener(RamDiscardManager *rdm,
 rdmc->unregister_listener(rdm, rdl);
 }
 
+/* Called with rcu_read_lock held.  */