On Thu, May 19, 2011 at 5:12 PM, Avi Kivity <avi@xxxxxxxxxx> wrote: > The memory API separates the attributes of a memory region (its size, how > reads or writes are handled, dirty logging, and coalescing) from where it > is mapped and whether it is enabled. ÂThis allows a device to configure > a memory region once, then hand it off to its parent bus to map it according > to the bus configuration. > > Hierarchical registration also allows a device to compose a region out of > a number of sub-regions with different properties; for example some may be > RAM while others may be MMIO. > > Signed-off-by: Avi Kivity <avi@xxxxxxxxxx> > --- > Âmemory.h | Â142 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > Â1 files changed, 142 insertions(+), 0 deletions(-) > Âcreate mode 100644 memory.h > > diff --git a/memory.h b/memory.h > new file mode 100644 > index 0000000..77c5951 > --- /dev/null > +++ b/memory.h > @@ -0,0 +1,142 @@ > +#ifndef MEMORY_H > +#define MEMORY_H > + > +#include <stdint.h> > +#include <stdbool.h> > +#include "qemu-common.h" > +#include "cpu-common.h" > +#include "targphys.h" > +#include "qemu-queue.h" > + > +typedef struct MemoryRegionOps MemoryRegionOps; > +typedef struct MemoryRegion MemoryRegion; > + > +/* > + * Memory region callbacks > + */ > +struct MemoryRegionOps { > + Â Â/* Read from the memory region. @addr is relative to @mr; @size is > + Â Â * in bytes. */ > + Â Âuint64_t (*read)(MemoryRegion *mr, > + Â Â Â Â Â Â Â Â Â Â target_phys_addr_t addr, > + Â Â Â Â Â Â Â Â Â Â unsigned size); > + Â Â/* Write to the memory region. @addr is relative to @mr; @size is > + Â Â * in bytes. */ > + Â Âvoid (*write)(MemoryRegion *mr, > + Â Â Â Â Â Â Â Â Âtarget_phys_addr_t addr, > + Â Â Â Â Â Â Â Â Âuint64_t data, > + Â Â Â Â Â Â Â Â Âunsigned size); > + Â Â/* Guest-visible constraints: */ > + Â Âstruct { > + Â Â Â Â/* If nonzero, specify bounds on access sizes beyond which a machine > + Â Â Â Â * check is thrown. > + Â Â Â Â */ > + Â Â Â Âunsigned min_access_size; > + Â Â Â Âunsigned max_access_size; > + Â Â Â Â/* If true, unaligned accesses are supported. ÂOtherwise unaligned > + Â Â Â Â * accesses throw machine checks. > + Â Â Â Â */ > + Â Â Â Â bool unaligned; > + Â Â} valid; > + Â Â/* Internal implementation constraints: */ > + Â Âstruct { > + Â Â Â Â/* If nonzero, specifies the minimum size implemented. ÂSmaller sizes > + Â Â Â Â * will be rounded upwards and a partial result will be returned. > + Â Â Â Â */ > + Â Â Â Âunsigned min_access_size; > + Â Â Â Â/* If nonzero, specifies the maximum size implemented. ÂLarger sizes > + Â Â Â Â * will be done as a series of accesses with smaller sizes. > + Â Â Â Â */ > + Â Â Â Âunsigned max_access_size; > + Â Â Â Â/* If true, unaligned accesses are supported. ÂOtherwise all accesses > + Â Â Â Â * are converted to (possibly multiple) naturally aligned accesses. > + Â Â Â Â */ > + Â Â Â Â bool unaligned; > + Â Â} impl; > +}; > + > +typedef struct CoalescedMemoryRange CoalescedMemoryRange; > + > +struct CoalescedMemoryRange { > + Â Âtarget_phys_addr_t start; > + Â Âtarget_phys_addr_t size; > + Â ÂQTAILQ_ENTRY(coalesced_ranges) link; > +}; > + > +struct MemoryRegion { > + Â Â/* All fields are private - violators will be prosecuted */ > + Â Âconst MemoryRegionOps *ops; > + Â ÂMemoryRegion *parent; > + Â Âtarget_phys_addr_t size; > + Â Âtarget_phys_addr_t addr; > + Â Âram_addr_t ram_addr; > + Â Âunsigned priority; > + Â Âbool may_overlap; > + Â ÂQTAILQ_HEAD(subregions, MemoryRegion) subregions; > + Â ÂQTAILQ_ENTRY(subregions) subregions_link; > + Â ÂQTAILQ_HEAD(coalesced_ranges, CoalescedMemoryRange) coalesced; > +}; > + > +/* Initialize a memory region > + * > + * The region typically acts as a container for other memory regions. > + */ > +void memory_region_init(MemoryRegion *mr, > + Â Â Â Â Â Â Â Â Â Â Â Âtarget_phys_addr_t size); > +/* Initialize an I/O memory region. ÂAccesses into the region will be > + * cause the callbacks in @ops to be called. > + * > + * if @size is nonzero, subregions will be clipped to @size. > + */ > +void memory_region_init_io(MemoryRegion *mr, > + Â Â Â Â Â Â Â Â Â Â Â Â Â const MemoryRegionOps *ops, > + Â Â Â Â Â Â Â Â Â Â Â Â Â target_phys_addr_t size); > +/* Initialize an I/O memory region. ÂAccesses into the region will be > + * modify memory directly. > + */ > +void memory_region_init_ram(MemoryRegion *mr, > + Â Â Â Â Â Â Â Â Â Â Â Â Â Âtarget_phys_addr_t size); > +/* Initialize a RAM memory region. ÂAccesses into the region will be > + * modify memory in @ptr directly. > + */ > +void memory_region_init_ram_ptr(MemoryRegion *mr, > + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Âtarget_phys_addr_t size, > + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Âvoid *ptr); > +/* Destroy a memory region. ÂThe memory becomes inaccessible. */ > +void memory_region_destroy(MemoryRegion *mr); Doesn't the lower priority region become accessible instead in some cases? > +/* Sets an offset to be added to MemoryRegionOps callbacks. */ > +void memory_region_set_offset(MemoryRegion *mr, target_phys_addr_t offset); > +/* Turn loggging on or off for specified client (display, migration) */ g-- > +void memory_region_set_log(MemoryRegion *mr, bool log, unsigned client); > +/* Enable memory coalescing for the region. ÂMMIO ->write callbacks may be > + * delayed until a non-coalesced MMIO is issued. > + */ > +void memory_region_set_coalescing(MemoryRegion *mr); > +/* Enable memory coalescing for a sub-range of the region. ÂMMIO ->write > + * callbacks may be delayed until a non-coalesced MMIO is issued. > + */ > +void memory_region_add_coalescing(MemoryRegion *mr, > + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Âtarget_phys_addr_t offset, > + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Âtarget_phys_addr_t size); > +/* Disable MMIO coalescing for the region. */ > +void memory_region_clear_coalescing(MemoryRegion *mr); Perhaps the interface could be more generic, like +void memory_region_set_property(MemoryRegion *mr, unsigned flags); +void memory_region_clear_property(MemoryRegion *mr, unsigned flags); > + > +/* Add a sub-region at @offset. ÂThe sub-region may not overlap with other > + * subregions (except for those explicitly marked as overlapping) > + */ > +void memory_region_add_subregion(MemoryRegion *mr, > + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â target_phys_addr_t offset, > + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â MemoryRegion *subregion); > +/* Add a sub-region at @offset. ÂThe sun-region may overlap other subregions; Sunny regions? > + * conflicts are resolved by having a higher @priority hide a lower @priority. > + * Subregions without priority are taken as @priority 0. > + */ > +void memory_region_add_subregion_overlap(MemoryRegion *mr, > + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â target_phys_addr_t offset, > + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â MemoryRegion *subregion, > + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â unsigned priority); > +/* Remove a subregion. */ > +void memory_region_del_subregion(MemoryRegion *mr, > + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â MemoryRegion *subregion); What would the subregions be used for? -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html