qemu/include/exec/ramlist.h
<<
>>
Prefs
   1#ifndef RAMLIST_H
   2#define RAMLIST_H
   3
   4#include "qemu/queue.h"
   5#include "qemu/thread.h"
   6#include "qemu/rcu.h"
   7#include "qemu/rcu_queue.h"
   8
   9typedef struct RAMBlockNotifier RAMBlockNotifier;
  10
  11#define DIRTY_MEMORY_VGA       0
  12#define DIRTY_MEMORY_CODE      1
  13#define DIRTY_MEMORY_MIGRATION 2
  14#define DIRTY_MEMORY_NUM       3        /* num of dirty bits */
  15
  16/* The dirty memory bitmap is split into fixed-size blocks to allow growth
  17 * under RCU.  The bitmap for a block can be accessed as follows:
  18 *
  19 *   rcu_read_lock();
  20 *
  21 *   DirtyMemoryBlocks *blocks =
  22 *       qatomic_rcu_read(&ram_list.dirty_memory[DIRTY_MEMORY_MIGRATION]);
  23 *
  24 *   ram_addr_t idx = (addr >> TARGET_PAGE_BITS) / DIRTY_MEMORY_BLOCK_SIZE;
  25 *   unsigned long *block = blocks.blocks[idx];
  26 *   ...access block bitmap...
  27 *
  28 *   rcu_read_unlock();
  29 *
  30 * Remember to check for the end of the block when accessing a range of
  31 * addresses.  Move on to the next block if you reach the end.
  32 *
  33 * Organization into blocks allows dirty memory to grow (but not shrink) under
  34 * RCU.  When adding new RAMBlocks requires the dirty memory to grow, a new
  35 * DirtyMemoryBlocks array is allocated with pointers to existing blocks kept
  36 * the same.  Other threads can safely access existing blocks while dirty
  37 * memory is being grown.  When no threads are using the old DirtyMemoryBlocks
  38 * anymore it is freed by RCU (but the underlying blocks stay because they are
  39 * pointed to from the new DirtyMemoryBlocks).
  40 */
  41#define DIRTY_MEMORY_BLOCK_SIZE ((ram_addr_t)256 * 1024 * 8)
  42typedef struct {
  43    struct rcu_head rcu;
  44    unsigned long *blocks[];
  45} DirtyMemoryBlocks;
  46
  47typedef struct RAMList {
  48    QemuMutex mutex;
  49    RAMBlock *mru_block;
  50    /* RCU-enabled, writes protected by the ramlist lock. */
  51    QLIST_HEAD(, RAMBlock) blocks;
  52    DirtyMemoryBlocks *dirty_memory[DIRTY_MEMORY_NUM];
  53    uint32_t version;
  54    QLIST_HEAD(, RAMBlockNotifier) ramblock_notifiers;
  55} RAMList;
  56extern RAMList ram_list;
  57
  58/* Should be holding either ram_list.mutex, or the RCU lock. */
  59#define  INTERNAL_RAMBLOCK_FOREACH(block)  \
  60    QLIST_FOREACH_RCU(block, &ram_list.blocks, next)
  61/* Never use the INTERNAL_ version except for defining other macros */
  62#define RAMBLOCK_FOREACH(block) INTERNAL_RAMBLOCK_FOREACH(block)
  63
  64void qemu_mutex_lock_ramlist(void);
  65void qemu_mutex_unlock_ramlist(void);
  66
  67struct RAMBlockNotifier {
  68    void (*ram_block_added)(RAMBlockNotifier *n, void *host, size_t size,
  69                            size_t max_size);
  70    void (*ram_block_removed)(RAMBlockNotifier *n, void *host, size_t size,
  71                              size_t max_size);
  72    void (*ram_block_resized)(RAMBlockNotifier *n, void *host, size_t old_size,
  73                              size_t new_size);
  74    QLIST_ENTRY(RAMBlockNotifier) next;
  75};
  76
  77void ram_block_notifier_add(RAMBlockNotifier *n);
  78void ram_block_notifier_remove(RAMBlockNotifier *n);
  79void ram_block_notify_add(void *host, size_t size, size_t max_size);
  80void ram_block_notify_remove(void *host, size_t size, size_t max_size);
  81void ram_block_notify_resize(void *host, size_t old_size, size_t new_size);
  82
  83void ram_block_dump(Monitor *mon);
  84
  85#endif /* RAMLIST_H */
  86