Romain Malmain aa67fcae61 Syx Snapshot rework
- Most of the tables are now GHashtable instances
- Snapshot correctness checking
- Simplified API
- More callbacks to catch more dirty pages
2023-11-21 10:39:42 +01:00

152 lines
3.8 KiB
C

/*
* SYX Snapshot
*
* A speed-oriented snapshot mechanism.
*
* TODO: complete documentation.
*/
#pragma once
#include "qemu/osdep.h"
#include "qom/object.h"
#include "sysemu/sysemu.h"
#include "device-save.h"
#include "../syx-misc.h"
/**
* Saved ramblock
*/
typedef struct SyxSnapshotRAMBlock {
uint8_t* ram; // RAM block
uint64_t used_length; // Length of the ram block
} SyxSnapshotRAMBlock;
/**
* A root snapshot representation.
*/
typedef struct SyxSnapshotRoot {
GHashTable* rbs_snapshot; // hash map: H(rb) -> SyxSnapshotRAMBlock
DeviceSaveState* dss;
} SyxSnapshotRoot;
/**
* A list of dirty pages with their old data.
*/
typedef struct SyxSnapshotDirtyPage {
ram_addr_t offset_within_rb;
uint8_t* data;
} SyxSnapshotDirtyPage;
typedef struct SyxSnapshotDirtyPageList {
SyxSnapshotDirtyPage* dirty_pages;
uint64_t length;
} SyxSnapshotDirtyPageList;
/**
* A snapshot increment. It is used to quickly
* save a VM state.
*/
typedef struct SyxSnapshotIncrement {
// Back to root snapshot if NULL
struct SyxSnapshotIncrement* parent;
DeviceSaveState* dss;
GHashTable* rbs_dirty_pages; // hash map: H(rb) -> SyxSnapshotDirtyPageList
} SyxSnapshotIncrement;
/**
* A snapshot. It is the main object used in this API to
* handle snapshotting.
*/
typedef struct SyxSnapshot {
SyxSnapshotRoot root_snapshot;
SyxSnapshotIncrement* last_incremental_snapshot;
GHashTable* rbs_dirty_list; // hash map: H(rb) -> GHashTable(offset_within_ramblock). Filled lazily.
} SyxSnapshot;
typedef struct SyxSnapshotTracker {
SyxSnapshot** tracked_snapshots;
uint64_t length;
uint64_t capacity;
} SyxSnapshotTracker;
typedef struct SyxSnapshotState {
bool is_enabled;
uint64_t page_size;
uint64_t page_mask;
// Actively tracked snapshots. Their dirty lists will
// be updated at each dirty access
SyxSnapshotTracker tracked_snapshots;
} SyxSnapshotState;
void syx_snapshot_init(void);
//
// Snapshot API
//
SyxSnapshot* syx_snapshot_new(bool track, DeviceSnapshotKind kind, char** devices);
void syx_snapshot_free(SyxSnapshot* snapshot);
void syx_snapshot_root_restore(SyxSnapshot* snapshot);
uint64_t syx_snapshot_check_memory_consistency(SyxSnapshot* snapshot);
// Push the current RAM state and saves it
void syx_snapshot_increment_push(SyxSnapshot* snapshot, DeviceSnapshotKind kind, char** devices);
// Restores the last push. Restores the root snapshot if no incremental snapshot is present.
void syx_snapshot_increment_pop(SyxSnapshot* snapshot);
void syx_snapshot_increment_restore_last(SyxSnapshot* snapshot);
//
// Snapshot tracker API
//
SyxSnapshotTracker syx_snapshot_tracker_init(void);
void syx_snapshot_track(SyxSnapshotTracker* tracker, SyxSnapshot* snapshot);
void syx_snapshot_stop_track(SyxSnapshotTracker* tracker, SyxSnapshot* snapshot);
//
// Misc functions
//
bool syx_snapshot_is_enabled(void);
//
// Dirty list API
//
void syx_snapshot_dirty_list_add_hostaddr(void* host_addr);
void syx_snapshot_dirty_list_add_hostaddr_range(void* host_addr, uint64_t len);
/**
* @brief Add a dirty physical address to the list
*
* @param paddr The physical address to add
*/
void syx_snapshot_dirty_list_add_paddr(hwaddr paddr);
/**
* @brief Same as syx_snapshot_dirty_list_add. The difference
* being that it has been specially compiled for full context
* saving so that it can be called from anywhere, even in
* extreme environments where SystemV ABI is not respected.
* It was created with tcg-target.inc.c environment in
* mind.
*
* @param dummy A dummy argument. it is to comply with
* tcg-target.inc.c specific environment.
* @param host_addr The host address where the dirty page is located.
*/
void syx_snapshot_dirty_list_add_tcg_target(uint64_t dummy, void* host_addr);