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 |
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 --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
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(-)