#include "exec/cpu-common.h"
#include "exec/hwaddr.h"
#include "exec/memattrs.h"
+#include "exec/memop.h"
#include "exec/ramlist.h"
+#include "qemu/bswap.h"
#include "qemu/queue.h"
#include "qemu/int128.h"
#include "qemu/notify.h"
#include "qom/object.h"
#include "qemu/rcu.h"
-#include "hw/qdev-core.h"
#define RAM_ADDR_INVALID (~(ram_addr_t)0)
OBJECT_GET_CLASS(IOMMUMemoryRegionClass, (obj), \
TYPE_IOMMU_MEMORY_REGION)
+extern bool global_dirty_log;
+
typedef struct MemoryRegionOps MemoryRegionOps;
typedef struct MemoryRegionMmio MemoryRegionMmio;
};
typedef struct IOMMUNotifier IOMMUNotifier;
+/* RAM is pre-allocated and passed into qemu_ram_alloc_from_ptr */
+#define RAM_PREALLOC (1 << 0)
+
+/* RAM is mmap-ed with MAP_SHARED */
+#define RAM_SHARED (1 << 1)
+
+/* Only a portion of RAM (used_length) is actually used, and migrated.
+ * This used_length size can change across reboots.
+ */
+#define RAM_RESIZEABLE (1 << 2)
+
+/* UFFDIO_ZEROPAGE is available on this RAMBlock to atomically
+ * zero the page and wake waiting processes.
+ * (Set during postcopy)
+ */
+#define RAM_UF_ZEROPAGE (1 << 3)
+
+/* RAM can be migrated */
+#define RAM_MIGRATABLE (1 << 4)
+
+/* RAM is a persistent kind memory */
+#define RAM_PMEM (1 << 5)
+
static inline void iommu_notifier_init(IOMMUNotifier *n, IOMMUNotify fn,
IOMMUNotifierFlag flags,
hwaddr start, hwaddr end,
*/
bool unaligned;
} impl;
-
- /* If .read and .write are not present, old_mmio may be used for
- * backwards compatibility with old mmio registration
- */
- const MemoryRegionMmio old_mmio;
};
+typedef struct MemoryRegionClass {
+ /* private */
+ ObjectClass parent_class;
+} MemoryRegionClass;
+
+
enum IOMMUMemoryRegionAttr {
IOMMU_ATTR_SPAPR_TCE_FD
};
*/
typedef struct IOMMUMemoryRegionClass {
/* private */
- struct DeviceClass parent_class;
+ MemoryRegionClass parent_class;
/*
* Return a TLB entry that contains a given address.
bool ram;
bool subpage;
bool readonly; /* For RAM regions */
+ bool nonvolatile;
bool rom_device;
bool flush_coalesced_mmio;
bool global_locking;
MemoryRegion *alias;
hwaddr alias_offset;
int32_t priority;
- QTAILQ_HEAD(subregions, MemoryRegion) subregions;
+ QTAILQ_HEAD(, MemoryRegion) subregions;
QTAILQ_ENTRY(MemoryRegion) subregions_link;
- QTAILQ_HEAD(coalesced_ranges, CoalescedMemoryRange) coalesced;
+ QTAILQ_HEAD(, CoalescedMemoryRange) coalesced;
const char *name;
unsigned ioeventfd_nb;
MemoryRegionIoeventfd *ioeventfds;
void (*log_stop)(MemoryListener *listener, MemoryRegionSection *section,
int old, int new);
void (*log_sync)(MemoryListener *listener, MemoryRegionSection *section);
+ void (*log_clear)(MemoryListener *listener, MemoryRegionSection *section);
void (*log_global_start)(MemoryListener *listener);
void (*log_global_stop)(MemoryListener *listener);
+ void (*log_global_after_sync)(MemoryListener *listener);
void (*eventfd_add)(MemoryListener *listener, MemoryRegionSection *section,
bool match_data, uint64_t data, EventNotifier *e);
void (*eventfd_del)(MemoryListener *listener, MemoryRegionSection *section,
bool match_data, uint64_t data, EventNotifier *e);
- void (*coalesced_mmio_add)(MemoryListener *listener, MemoryRegionSection *section,
+ void (*coalesced_io_add)(MemoryListener *listener, MemoryRegionSection *section,
hwaddr addr, hwaddr len);
- void (*coalesced_mmio_del)(MemoryListener *listener, MemoryRegionSection *section,
+ void (*coalesced_io_del)(MemoryListener *listener, MemoryRegionSection *section,
hwaddr addr, hwaddr len);
/* Lower = earlier (during add), later (during del) */
unsigned priority;
int ioeventfd_nb;
struct MemoryRegionIoeventfd *ioeventfds;
- QTAILQ_HEAD(memory_listeners_as, MemoryListener) listeners;
+ QTAILQ_HEAD(, MemoryListener) listeners;
QTAILQ_ENTRY(AddressSpace) address_spaces_link;
};
* @offset_within_address_space: the address of the first byte of the section
* relative to the region's address space
* @readonly: writes to this section are ignored
+ * @nonvolatile: this section is non-volatile
*/
struct MemoryRegionSection {
MemoryRegion *mr;
Int128 size;
hwaddr offset_within_address_space;
bool readonly;
+ bool nonvolatile;
};
/**
uint64_t length,
void *host),
Error **errp);
-#ifdef __linux__
+#ifdef CONFIG_POSIX
+
/**
* memory_region_init_ram_from_file: Initialize RAM memory region with a
* mmap-ed backend.
* @size: size of the region.
* @align: alignment of the region base address; if 0, the default alignment
* (getpagesize()) will be used.
- * @share: %true if memory must be mmaped with the MAP_SHARED flag
+ * @ram_flags: Memory region features:
+ * - RAM_SHARED: memory must be mmaped with the MAP_SHARED flag
+ * - RAM_PMEM: the memory is persistent memory
+ * Other bits are ignored now.
* @path: the path in which to allocate the RAM.
* @errp: pointer to Error*, to store an error if it happens.
*
const char *name,
uint64_t size,
uint64_t align,
- bool share,
+ uint32_t ram_flags,
const char *path,
Error **errp);
/**
* memory_region_is_ram: check whether a memory region is random access
*
- * Returns %true is a memory region is random access.
+ * Returns %true if a memory region is random access.
*
* @mr: the memory region being queried
*/
/**
* memory_region_is_ram_device: check whether a memory region is a ram device
*
- * Returns %true is a memory region is a device backed ram region
+ * Returns %true if a memory region is a device backed ram region
*
* @mr: the memory region being queried
*/
*/
void memory_region_iommu_replay(IOMMUMemoryRegion *iommu_mr, IOMMUNotifier *n);
-/**
- * memory_region_iommu_replay_all: replay existing IOMMU translations
- * to all the notifiers registered.
- *
- * Note: this is not related to record-and-replay functionality.
- *
- * @iommu_mr: the memory region to observe
- */
-void memory_region_iommu_replay_all(IOMMUMemoryRegion *iommu_mr);
-
/**
* memory_region_unregister_iommu_notifier: unregister a notifier for
* changes to IOMMU translation entries.
/**
* memory_region_is_rom: check whether a memory region is ROM
*
- * Returns %true is a memory region is read-only memory.
+ * Returns %true if a memory region is read-only memory.
*
* @mr: the memory region being queried
*/
return mr->ram && mr->readonly;
}
+/**
+ * memory_region_is_nonvolatile: check whether a memory region is non-volatile
+ *
+ * Returns %true is a memory region is non-volatile memory.
+ *
+ * @mr: the memory region being queried
+ */
+static inline bool memory_region_is_nonvolatile(MemoryRegion *mr)
+{
+ return mr->nonvolatile;
+}
/**
* memory_region_get_fd: Get a file descriptor backing a RAM memory region.
*/
void memory_region_set_log(MemoryRegion *mr, bool log, unsigned client);
-/**
- * memory_region_get_dirty: Check whether a range of bytes is dirty
- * for a specified client.
- *
- * Checks whether a range of bytes has been written to since the last
- * call to memory_region_reset_dirty() with the same @client. Dirty logging
- * must be enabled.
- *
- * @mr: the memory region being queried.
- * @addr: the address (relative to the start of the region) being queried.
- * @size: the size of the range being queried.
- * @client: the user of the logging information; %DIRTY_MEMORY_MIGRATION or
- * %DIRTY_MEMORY_VGA.
- */
-bool memory_region_get_dirty(MemoryRegion *mr, hwaddr addr,
- hwaddr size, unsigned client);
-
/**
* memory_region_set_dirty: Mark a range of bytes as dirty in a memory region.
*
void memory_region_set_dirty(MemoryRegion *mr, hwaddr addr,
hwaddr size);
+/**
+ * memory_region_clear_dirty_bitmap - clear dirty bitmap for memory range
+ *
+ * This function is called when the caller wants to clear the remote
+ * dirty bitmap of a memory range within the memory region. This can
+ * be used by e.g. KVM to manually clear dirty log when
+ * KVM_CAP_MANUAL_DIRTY_LOG_PROTECT is declared support by the host
+ * kernel.
+ *
+ * @mr: the memory region to clear the dirty log upon
+ * @start: start address offset within the memory region
+ * @len: length of the memory region to clear dirty bitmap
+ */
+void memory_region_clear_dirty_bitmap(MemoryRegion *mr, hwaddr start,
+ hwaddr len);
+
/**
* memory_region_snapshot_and_clear_dirty: Get a snapshot of the dirty
* bitmap and clear it.
void memory_region_reset_dirty(MemoryRegion *mr, hwaddr addr,
hwaddr size, unsigned client);
+/**
+ * memory_region_flush_rom_device: Mark a range of pages dirty and invalidate
+ * TBs (for self-modifying code).
+ *
+ * The MemoryRegionOps->write() callback of a ROM device must use this function
+ * to mark byte ranges that have been modified internally, such as by directly
+ * accessing the memory returned by memory_region_get_ram_ptr().
+ *
+ * This function marks the range dirty and invalidates TBs so that TCG can
+ * detect self-modifying code.
+ *
+ * @mr: the region being flushed.
+ * @addr: the start, relative to the start of the region, of the range being
+ * flushed.
+ * @size: the size, in bytes, of the range being flushed.
+ */
+void memory_region_flush_rom_device(MemoryRegion *mr, hwaddr addr, hwaddr size);
+
/**
* memory_region_set_readonly: Turn a memory region read-only (or read-write)
*
*/
void memory_region_set_readonly(MemoryRegion *mr, bool readonly);
+/**
+ * memory_region_set_nonvolatile: Turn a memory region non-volatile
+ *
+ * Allows a memory region to be marked as non-volatile.
+ * only useful on RAM regions.
+ *
+ * @mr: the region being updated.
+ * @nonvolatile: whether rhe region is to be non-volatile.
+ */
+void memory_region_set_nonvolatile(MemoryRegion *mr, bool nonvolatile);
+
/**
* memory_region_rom_device_set_romd: enable/disable ROMD mode
*
*/
void memory_global_dirty_log_sync(void);
+/**
+ * memory_global_dirty_log_sync: synchronize the dirty log for all memory
+ *
+ * Synchronizes the vCPUs with a thread that is reading the dirty bitmap.
+ * This function must be called after the dirty log bitmap is cleared, and
+ * before dirty guest memory pages are read. If you are using
+ * #DirtyBitmapSnapshot, memory_region_snapshot_and_clear_dirty() takes
+ * care of doing this.
+ */
+void memory_global_after_dirty_log_sync(void);
+
/**
* memory_region_transaction_begin: Start a transaction.
*
*/
void memory_global_dirty_log_stop(void);
-void mtree_info(fprintf_function mon_printf, void *f, bool flatview,
- bool dispatch_tree, bool owner);
+void mtree_info(bool flatview, bool dispatch_tree, bool owner);
/**
* memory_region_dispatch_read: perform a read directly to the specified
* @mr: #MemoryRegion to access
* @addr: address within that region
* @pval: pointer to uint64_t which the data is written to
- * @size: size of the access in bytes
+ * @op: size, sign, and endianness of the memory operation
* @attrs: memory transaction attributes to use for the access
*/
MemTxResult memory_region_dispatch_read(MemoryRegion *mr,
hwaddr addr,
uint64_t *pval,
- unsigned size,
+ MemOp op,
MemTxAttrs attrs);
/**
* memory_region_dispatch_write: perform a write directly to the specified
* @mr: #MemoryRegion to access
* @addr: address within that region
* @data: data to write
- * @size: size of the access in bytes
+ * @op: size, sign, and endianness of the memory operation
* @attrs: memory transaction attributes to use for the access
*/
MemTxResult memory_region_dispatch_write(MemoryRegion *mr,
hwaddr addr,
uint64_t data,
- unsigned size,
+ MemOp op,
MemTxAttrs attrs);
/**
*/
void address_space_destroy(AddressSpace *as);
+/**
+ * address_space_remove_listeners: unregister all listeners of an address space
+ *
+ * Removes all callbacks previously registered with memory_listener_register()
+ * for @as.
+ *
+ * @as: an initialized #AddressSpace
+ */
+void address_space_remove_listeners(AddressSpace *as);
+
/**
* address_space_rw: read from or write to an address space.
*
*/
MemTxResult address_space_rw(AddressSpace *as, hwaddr addr,
MemTxAttrs attrs, uint8_t *buf,
- int len, bool is_write);
+ hwaddr len, bool is_write);
/**
* address_space_write: write to address space.
*/
MemTxResult address_space_write(AddressSpace *as, hwaddr addr,
MemTxAttrs attrs,
- const uint8_t *buf, int len);
+ const uint8_t *buf, hwaddr len);
+
+/**
+ * address_space_write_rom: write to address space, including ROM.
+ *
+ * This function writes to the specified address space, but will
+ * write data to both ROM and RAM. This is used for non-guest
+ * writes like writes from the gdb debug stub or initial loading
+ * of ROM contents.
+ *
+ * Note that portions of the write which attempt to write data to
+ * a device will be silently ignored -- only real RAM and ROM will
+ * be written to.
+ *
+ * Return a MemTxResult indicating whether the operation succeeded
+ * or failed (eg unassigned memory, device rejected the transaction,
+ * IOMMU fault).
+ *
+ * @as: #AddressSpace to be accessed
+ * @addr: address within that address space
+ * @attrs: memory transaction attributes
+ * @buf: buffer with the data transferred
+ * @len: the number of bytes to write
+ */
+MemTxResult address_space_write_rom(AddressSpace *as, hwaddr addr,
+ MemTxAttrs attrs,
+ const uint8_t *buf, hwaddr len);
/* address_space_ld*: load from an address space
* address_space_st*: store to an address space
* @is_write: indicates the transfer direction
* @attrs: memory attributes
*/
-bool address_space_access_valid(AddressSpace *as, hwaddr addr, int len,
+bool address_space_access_valid(AddressSpace *as, hwaddr addr, hwaddr len,
bool is_write, MemTxAttrs attrs);
/* address_space_map: map a physical memory region into a host virtual address
/* Internal functions, part of the implementation of address_space_read. */
MemTxResult address_space_read_full(AddressSpace *as, hwaddr addr,
- MemTxAttrs attrs, uint8_t *buf, int len);
+ MemTxAttrs attrs, uint8_t *buf, hwaddr len);
MemTxResult flatview_read_continue(FlatView *fv, hwaddr addr,
MemTxAttrs attrs, uint8_t *buf,
- int len, hwaddr addr1, hwaddr l,
+ hwaddr len, hwaddr addr1, hwaddr l,
MemoryRegion *mr);
void *qemu_map_ram_ptr(RAMBlock *ram_block, ram_addr_t addr);
/* Internal functions, part of the implementation of address_space_read_cached
* and address_space_write_cached. */
void address_space_read_cached_slow(MemoryRegionCache *cache,
- hwaddr addr, void *buf, int len);
+ hwaddr addr, void *buf, hwaddr len);
void address_space_write_cached_slow(MemoryRegionCache *cache,
- hwaddr addr, const void *buf, int len);
+ hwaddr addr, const void *buf, hwaddr len);
static inline bool memory_access_is_direct(MemoryRegion *mr, bool is_write)
{
static inline __attribute__((__always_inline__))
MemTxResult address_space_read(AddressSpace *as, hwaddr addr,
MemTxAttrs attrs, uint8_t *buf,
- int len)
+ hwaddr len)
{
MemTxResult result = MEMTX_OK;
hwaddr l, addr1;
*/
static inline void
address_space_read_cached(MemoryRegionCache *cache, hwaddr addr,
- void *buf, int len)
+ void *buf, hwaddr len)
{
assert(addr < cache->len && len <= cache->len - addr);
if (likely(cache->ptr)) {
*/
static inline void
address_space_write_cached(MemoryRegionCache *cache, hwaddr addr,
- void *buf, int len)
+ void *buf, hwaddr len)
{
assert(addr < cache->len && len <= cache->len - addr);
if (likely(cache->ptr)) {
}
}
+/* enum device_endian to MemOp. */
+MemOp devend_memop(enum device_endian end);
+
#endif
#endif