Message ID | 1366067974-5413-4-git-send-email-scottwood@freescale.com |
---|---|
State | New |
Headers | show |
On 16 April 2013 00:19, Scott Wood <scottwood@freescale.com> wrote: > This is useful for when a user of the memory region API needs to > communicate the absolute bus address to something outside QEMU > (in particular, KVM). > > Signed-off-by: Scott Wood <scottwood@freescale.com> > --- > TODO: Use add/del memory listeners later in the patchset, which would > eliminate the need for this patch. Yes, please do. > +/* memory_region_to_address: Find the full address of the start of the > + * given #MemoryRegion, ignoring aliases. There is no guarantee > + * that the #MemoryRegion is actually visible at this address, if > + * there are overlapping regions. > + * > + * @mr: #MemoryRegion being queried > + * @asp: if non-NULL, returns the #AddressSpace @mr is mapped in, if any > + */ > +hwaddr memory_region_to_address(MemoryRegion *mr, AddressSpace **asp); A MemoryRegion can appear in more than one AddressSpace (or none at all), so I don't think this is a very clearly defined API to put in the memory API itself. (It's ok to make that kind of assumption as a user of the memory APIs for particular cases, eg in how a memory listener callback function behaves. But we shouldn't be baking those assumptions into new API functions.) thanks -- PMM
On 17 April 2013 01:10, Scott Wood <scottwood@freescale.com> wrote: > On 04/16/2013 03:25:50 AM, Peter Maydell wrote: >> A MemoryRegion can appear in more than one AddressSpace (or none at all), >> so I don't think this is a very clearly defined API to put in the >> memory API itself. (It's ok to make that kind of assumption as a user >> of the memory APIs for particular cases, eg in how a memory listener >> callback function behaves. But we shouldn't be baking those assumptions >> into new API functions.) > I'm not sure how it's different from memory_region_to_address_space in that > regard, other than its ability to gracefully handle the "or none at all" > case. memory_region_to_address_space() is an internal function used by a couple of functions -- it's passed "a top level (ie parentless) region", not an arbitrary region [semantically, anyway]. > How does it work to be in more than one AddressSpace, if there's a parent > chain? More than one "as" with the same "as->root"? Or are you referring > to aliases? Yes, I had aliases in mind. Ignoring aliases isn't really very doable since you can't control whether somebody else has taken an alias of you. thanks -- PMM
diff --git a/include/exec/memory.h b/include/exec/memory.h index 2322732..b800391 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -892,6 +892,15 @@ void *address_space_map(AddressSpace *as, hwaddr addr, void address_space_unmap(AddressSpace *as, void *buffer, hwaddr len, int is_write, hwaddr access_len); +/* memory_region_to_address: Find the full address of the start of the + * given #MemoryRegion, ignoring aliases. There is no guarantee + * that the #MemoryRegion is actually visible at this address, if + * there are overlapping regions. + * + * @mr: #MemoryRegion being queried + * @asp: if non-NULL, returns the #AddressSpace @mr is mapped in, if any + */ +hwaddr memory_region_to_address(MemoryRegion *mr, AddressSpace **asp); #endif diff --git a/memory.c b/memory.c index 75ca281..5d3b13d 100644 --- a/memory.c +++ b/memory.c @@ -453,21 +453,51 @@ const IORangeOps memory_region_iorange_ops = { .destructor = memory_region_iorange_destructor, }; -static AddressSpace *memory_region_to_address_space(MemoryRegion *mr) +static AddressSpace *memory_region_root_to_address_space(MemoryRegion *mr) { AddressSpace *as; - while (mr->parent) { - mr = mr->parent; - } QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) { if (mr == as->root) { return as; } } + + return NULL; +} + +static AddressSpace *memory_region_to_address_space(MemoryRegion *mr) +{ + AddressSpace *as; + + while (mr->parent) { + mr = mr->parent; + } + + as = memory_region_root_to_address_space(mr); + if (as) { + return as; + } + abort(); } +hwaddr memory_region_to_address(MemoryRegion *mr, AddressSpace **asp) +{ + hwaddr addr = mr->addr; + + while (mr->parent) { + mr = mr->parent; + addr += mr->addr; + } + + if (asp) { + *asp = memory_region_root_to_address_space(mr); + } + + return addr; +} + /* Render a memory region into the global view. Ranges in @view obscure * ranges in @mr. */
This is useful for when a user of the memory region API needs to communicate the absolute bus address to something outside QEMU (in particular, KVM). Signed-off-by: Scott Wood <scottwood@freescale.com> --- TODO: Use add/del memory listeners later in the patchset, which would eliminate the need for this patch. --- include/exec/memory.h | 9 +++++++++ memory.c | 38 ++++++++++++++++++++++++++++++++++---- 2 files changed, 43 insertions(+), 4 deletions(-)