diff mbox series

[v2] plugins: Expose physical addresses instead of device offsets

Message ID 20210309202802.211756-1-aaron@os.amperecomputing.com (mailing list archive)
State New, archived
Headers show
Series [v2] plugins: Expose physical addresses instead of device offsets | expand

Commit Message

Aaron Lindsay March 9, 2021, 8:28 p.m. UTC
This allows plugins to query for full virtual-to-physical address
translation for a given `qemu_plugin_hwaddr` and stops exposing the
offset within the device itself. As this change breaks the API,
QEMU_PLUGIN_VERSION is incremented.

Signed-off-by: Aaron Lindsay <aaron@os.amperecomputing.com>
---
 contrib/plugins/hotpages.c  |  2 +-
 contrib/plugins/hwprofile.c |  2 +-
 include/qemu/qemu-plugin.h  | 32 +++++++++++++++++++++++++-------
 plugins/api.c               | 17 ++++++++++++-----
 4 files changed, 39 insertions(+), 14 deletions(-)

Comments

Alex Bennée March 11, 2021, 10:29 a.m. UTC | #1
Aaron Lindsay <aaron@os.amperecomputing.com> writes:

> This allows plugins to query for full virtual-to-physical address
> translation for a given `qemu_plugin_hwaddr` and stops exposing the
> offset within the device itself. As this change breaks the API,
> QEMU_PLUGIN_VERSION is incremented.
>
> Signed-off-by: Aaron Lindsay <aaron@os.amperecomputing.com>

Queued to plugins/next, thanks.

> ---
>  contrib/plugins/hotpages.c  |  2 +-
>  contrib/plugins/hwprofile.c |  2 +-
>  include/qemu/qemu-plugin.h  | 32 +++++++++++++++++++++++++-------
>  plugins/api.c               | 17 ++++++++++++-----
>  4 files changed, 39 insertions(+), 14 deletions(-)
>
> diff --git a/contrib/plugins/hotpages.c b/contrib/plugins/hotpages.c
> index eacc678eac..bf53267532 100644
> --- a/contrib/plugins/hotpages.c
> +++ b/contrib/plugins/hotpages.c
> @@ -122,7 +122,7 @@ static void vcpu_haddr(unsigned int cpu_index, qemu_plugin_meminfo_t meminfo,
>          }
>      } else {
>          if (hwaddr && !qemu_plugin_hwaddr_is_io(hwaddr)) {
> -            page = (uint64_t) qemu_plugin_hwaddr_device_offset(hwaddr);
> +            page = (uint64_t) qemu_plugin_hwaddr_phys_addr(hwaddr);
>          } else {
>              page = vaddr;
>          }
> diff --git a/contrib/plugins/hwprofile.c b/contrib/plugins/hwprofile.c
> index 6dac1d5f85..faf216ac00 100644
> --- a/contrib/plugins/hwprofile.c
> +++ b/contrib/plugins/hwprofile.c
> @@ -201,7 +201,7 @@ static void vcpu_haddr(unsigned int cpu_index, qemu_plugin_meminfo_t meminfo,
>          return;
>      } else {
>          const char *name = qemu_plugin_hwaddr_device_name(hwaddr);
> -        uint64_t off = qemu_plugin_hwaddr_device_offset(hwaddr);
> +        uint64_t off = qemu_plugin_hwaddr_phys_addr(hwaddr);
>          bool is_write = qemu_plugin_mem_is_store(meminfo);
>          DeviceCounts *counts;
>  
> diff --git a/include/qemu/qemu-plugin.h b/include/qemu/qemu-plugin.h
> index c66507fe8f..3303dce862 100644
> --- a/include/qemu/qemu-plugin.h
> +++ b/include/qemu/qemu-plugin.h
> @@ -47,7 +47,7 @@ typedef uint64_t qemu_plugin_id_t;
>  
>  extern QEMU_PLUGIN_EXPORT int qemu_plugin_version;
>  
> -#define QEMU_PLUGIN_VERSION 0
> +#define QEMU_PLUGIN_VERSION 1
>  
>  typedef struct {
>      /* string describing architecture */
> @@ -307,8 +307,8 @@ bool qemu_plugin_mem_is_sign_extended(qemu_plugin_meminfo_t info);
>  bool qemu_plugin_mem_is_big_endian(qemu_plugin_meminfo_t info);
>  bool qemu_plugin_mem_is_store(qemu_plugin_meminfo_t info);
>  
> -/*
> - * qemu_plugin_get_hwaddr():
> +/**
> + * qemu_plugin_get_hwaddr() - return handle for memory operation
>   * @vaddr: the virtual address of the memory operation
>   *
>   * For system emulation returns a qemu_plugin_hwaddr handle to query
> @@ -323,12 +323,30 @@ struct qemu_plugin_hwaddr *qemu_plugin_get_hwaddr(qemu_plugin_meminfo_t info,
>                                                    uint64_t vaddr);
>  
>  /*
> - * The following additional queries can be run on the hwaddr structure
> - * to return information about it. For non-IO accesses the device
> - * offset will be into the appropriate block of RAM.
> + * The following additional queries can be run on the hwaddr structure to
> + * return information about it - namely whether it is for an IO access and the
> + * physical address associated with the access.
> + */
> +
> +/**
> + * qemu_plugin_hwaddr_is_io() - query whether memory operation is IO
> + * @haddr: address handle from qemu_plugin_get_hwaddr()
> + *
> + * Returns true if the handle's memory operation is to memory-mapped IO, or
> + * false if it is to RAM
>   */
>  bool qemu_plugin_hwaddr_is_io(const struct qemu_plugin_hwaddr *haddr);
> -uint64_t qemu_plugin_hwaddr_device_offset(const struct qemu_plugin_hwaddr *haddr);
> +
> +/**
> + * qemu_plugin_hwaddr_phys_addr() - query physical address for memory operation
> + * @haddr: address handle from qemu_plugin_get_hwaddr()
> + *
> + * Returns the physical address associated with the memory operation
> + *
> + * Note that the returned physical address may not be unique if you are dealing
> + * with multiple address spaces.
> + */
> +uint64_t qemu_plugin_hwaddr_phys_addr(const struct qemu_plugin_hwaddr *haddr);
>  
>  /*
>   * Returns a string representing the device. The string is valid for
> diff --git a/plugins/api.c b/plugins/api.c
> index 0b04380d57..3c7dc406e3 100644
> --- a/plugins/api.c
> +++ b/plugins/api.c
> @@ -40,6 +40,7 @@
>  #include "sysemu/sysemu.h"
>  #include "tcg/tcg.h"
>  #include "exec/exec-all.h"
> +#include "exec/ram_addr.h"
>  #include "disas/disas.h"
>  #include "plugin.h"
>  #ifndef CONFIG_USER_ONLY
> @@ -298,19 +299,25 @@ bool qemu_plugin_hwaddr_is_io(const struct qemu_plugin_hwaddr *haddr)
>  #endif
>  }
>  
> -uint64_t qemu_plugin_hwaddr_device_offset(const struct qemu_plugin_hwaddr *haddr)
> +uint64_t qemu_plugin_hwaddr_phys_addr(const struct qemu_plugin_hwaddr *haddr)
>  {
>  #ifdef CONFIG_SOFTMMU
>      if (haddr) {
>          if (!haddr->is_io) {
> -            ram_addr_t ram_addr = qemu_ram_addr_from_host((void *) haddr->v.ram.hostaddr);
> -            if (ram_addr == RAM_ADDR_INVALID) {
> +            RAMBlock *block;
> +            ram_addr_t offset;
> +            void *hostaddr = (void *) haddr->v.ram.hostaddr;
> +
> +            block = qemu_ram_block_from_host(hostaddr, false, &offset);
> +            if (!block) {
>                  error_report("Bad ram pointer %"PRIx64"", haddr->v.ram.hostaddr);
>                  abort();
>              }
> -            return ram_addr;
> +
> +            return block->offset + offset + block->mr->addr;
>          } else {
> -            return haddr->v.io.offset;
> +            MemoryRegionSection *mrs = haddr->v.io.section;
> +            return haddr->v.io.offset + mrs->mr->addr;
>          }
>      }
>  #endif
diff mbox series

Patch

diff --git a/contrib/plugins/hotpages.c b/contrib/plugins/hotpages.c
index eacc678eac..bf53267532 100644
--- a/contrib/plugins/hotpages.c
+++ b/contrib/plugins/hotpages.c
@@ -122,7 +122,7 @@  static void vcpu_haddr(unsigned int cpu_index, qemu_plugin_meminfo_t meminfo,
         }
     } else {
         if (hwaddr && !qemu_plugin_hwaddr_is_io(hwaddr)) {
-            page = (uint64_t) qemu_plugin_hwaddr_device_offset(hwaddr);
+            page = (uint64_t) qemu_plugin_hwaddr_phys_addr(hwaddr);
         } else {
             page = vaddr;
         }
diff --git a/contrib/plugins/hwprofile.c b/contrib/plugins/hwprofile.c
index 6dac1d5f85..faf216ac00 100644
--- a/contrib/plugins/hwprofile.c
+++ b/contrib/plugins/hwprofile.c
@@ -201,7 +201,7 @@  static void vcpu_haddr(unsigned int cpu_index, qemu_plugin_meminfo_t meminfo,
         return;
     } else {
         const char *name = qemu_plugin_hwaddr_device_name(hwaddr);
-        uint64_t off = qemu_plugin_hwaddr_device_offset(hwaddr);
+        uint64_t off = qemu_plugin_hwaddr_phys_addr(hwaddr);
         bool is_write = qemu_plugin_mem_is_store(meminfo);
         DeviceCounts *counts;
 
diff --git a/include/qemu/qemu-plugin.h b/include/qemu/qemu-plugin.h
index c66507fe8f..3303dce862 100644
--- a/include/qemu/qemu-plugin.h
+++ b/include/qemu/qemu-plugin.h
@@ -47,7 +47,7 @@  typedef uint64_t qemu_plugin_id_t;
 
 extern QEMU_PLUGIN_EXPORT int qemu_plugin_version;
 
-#define QEMU_PLUGIN_VERSION 0
+#define QEMU_PLUGIN_VERSION 1
 
 typedef struct {
     /* string describing architecture */
@@ -307,8 +307,8 @@  bool qemu_plugin_mem_is_sign_extended(qemu_plugin_meminfo_t info);
 bool qemu_plugin_mem_is_big_endian(qemu_plugin_meminfo_t info);
 bool qemu_plugin_mem_is_store(qemu_plugin_meminfo_t info);
 
-/*
- * qemu_plugin_get_hwaddr():
+/**
+ * qemu_plugin_get_hwaddr() - return handle for memory operation
  * @vaddr: the virtual address of the memory operation
  *
  * For system emulation returns a qemu_plugin_hwaddr handle to query
@@ -323,12 +323,30 @@  struct qemu_plugin_hwaddr *qemu_plugin_get_hwaddr(qemu_plugin_meminfo_t info,
                                                   uint64_t vaddr);
 
 /*
- * The following additional queries can be run on the hwaddr structure
- * to return information about it. For non-IO accesses the device
- * offset will be into the appropriate block of RAM.
+ * The following additional queries can be run on the hwaddr structure to
+ * return information about it - namely whether it is for an IO access and the
+ * physical address associated with the access.
+ */
+
+/**
+ * qemu_plugin_hwaddr_is_io() - query whether memory operation is IO
+ * @haddr: address handle from qemu_plugin_get_hwaddr()
+ *
+ * Returns true if the handle's memory operation is to memory-mapped IO, or
+ * false if it is to RAM
  */
 bool qemu_plugin_hwaddr_is_io(const struct qemu_plugin_hwaddr *haddr);
-uint64_t qemu_plugin_hwaddr_device_offset(const struct qemu_plugin_hwaddr *haddr);
+
+/**
+ * qemu_plugin_hwaddr_phys_addr() - query physical address for memory operation
+ * @haddr: address handle from qemu_plugin_get_hwaddr()
+ *
+ * Returns the physical address associated with the memory operation
+ *
+ * Note that the returned physical address may not be unique if you are dealing
+ * with multiple address spaces.
+ */
+uint64_t qemu_plugin_hwaddr_phys_addr(const struct qemu_plugin_hwaddr *haddr);
 
 /*
  * Returns a string representing the device. The string is valid for
diff --git a/plugins/api.c b/plugins/api.c
index 0b04380d57..3c7dc406e3 100644
--- a/plugins/api.c
+++ b/plugins/api.c
@@ -40,6 +40,7 @@ 
 #include "sysemu/sysemu.h"
 #include "tcg/tcg.h"
 #include "exec/exec-all.h"
+#include "exec/ram_addr.h"
 #include "disas/disas.h"
 #include "plugin.h"
 #ifndef CONFIG_USER_ONLY
@@ -298,19 +299,25 @@  bool qemu_plugin_hwaddr_is_io(const struct qemu_plugin_hwaddr *haddr)
 #endif
 }
 
-uint64_t qemu_plugin_hwaddr_device_offset(const struct qemu_plugin_hwaddr *haddr)
+uint64_t qemu_plugin_hwaddr_phys_addr(const struct qemu_plugin_hwaddr *haddr)
 {
 #ifdef CONFIG_SOFTMMU
     if (haddr) {
         if (!haddr->is_io) {
-            ram_addr_t ram_addr = qemu_ram_addr_from_host((void *) haddr->v.ram.hostaddr);
-            if (ram_addr == RAM_ADDR_INVALID) {
+            RAMBlock *block;
+            ram_addr_t offset;
+            void *hostaddr = (void *) haddr->v.ram.hostaddr;
+
+            block = qemu_ram_block_from_host(hostaddr, false, &offset);
+            if (!block) {
                 error_report("Bad ram pointer %"PRIx64"", haddr->v.ram.hostaddr);
                 abort();
             }
-            return ram_addr;
+
+            return block->offset + offset + block->mr->addr;
         } else {
-            return haddr->v.io.offset;
+            MemoryRegionSection *mrs = haddr->v.io.section;
+            return haddr->v.io.offset + mrs->mr->addr;
         }
     }
 #endif