111 lines
3.2 KiB
C
111 lines
3.2 KiB
C
|
/*
|
||
|
* QEMU Hyper-V Dynamic Memory Protocol driver
|
||
|
*
|
||
|
* Copyright (C) 2020-2023 Oracle and/or its affiliates.
|
||
|
*
|
||
|
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||
|
* See the COPYING file in the top-level directory.
|
||
|
*/
|
||
|
|
||
|
#ifndef HW_HYPERV_HV_BALLOON_OUR_RANGE_MEMSLOTS_H
|
||
|
#define HW_HYPERV_HV_BALLOON_OUR_RANGE_MEMSLOTS_H
|
||
|
|
||
|
#include "qemu/osdep.h"
|
||
|
|
||
|
#include "exec/memory.h"
|
||
|
#include "qom/object.h"
|
||
|
#include "hv-balloon-page_range_tree.h"
|
||
|
|
||
|
/* OurRange */
|
||
|
#define OUR_RANGE(ptr) ((OurRange *)(ptr))
|
||
|
|
||
|
/* "our range" means the memory range owned by this driver (for hot-adding) */
|
||
|
typedef struct OurRange {
|
||
|
PageRange range;
|
||
|
|
||
|
/* How many pages were hot-added to the guest */
|
||
|
uint64_t added;
|
||
|
|
||
|
/* Pages at the end not currently usable */
|
||
|
uint64_t unusable_tail;
|
||
|
|
||
|
/* Memory removed from the guest */
|
||
|
PageRangeTree removed_guest, removed_both;
|
||
|
} OurRange;
|
||
|
|
||
|
static inline uint64_t our_range_get_remaining_start(OurRange *our_range)
|
||
|
{
|
||
|
return our_range->range.start + our_range->added;
|
||
|
}
|
||
|
|
||
|
static inline uint64_t our_range_get_remaining_size(OurRange *our_range)
|
||
|
{
|
||
|
return our_range->range.count - our_range->added - our_range->unusable_tail;
|
||
|
}
|
||
|
|
||
|
void hvb_our_range_mark_added(OurRange *our_range, uint64_t additional_size);
|
||
|
|
||
|
static inline void our_range_mark_remaining_unusable(OurRange *our_range)
|
||
|
{
|
||
|
our_range->unusable_tail = our_range->range.count - our_range->added;
|
||
|
}
|
||
|
|
||
|
static inline PageRangeTree our_range_get_removed_tree(OurRange *our_range,
|
||
|
bool both)
|
||
|
{
|
||
|
if (both) {
|
||
|
return our_range->removed_both;
|
||
|
} else {
|
||
|
return our_range->removed_guest;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static inline bool our_range_is_removed_tree_empty(OurRange *our_range,
|
||
|
bool both)
|
||
|
{
|
||
|
if (both) {
|
||
|
return page_range_tree_is_empty(our_range->removed_both);
|
||
|
} else {
|
||
|
return page_range_tree_is_empty(our_range->removed_guest);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void hvb_our_range_clear_removed_trees(OurRange *our_range);
|
||
|
|
||
|
/* OurRangeMemslots */
|
||
|
typedef struct OurRangeMemslotsSlots {
|
||
|
/* Nominal size of each memslot (the last one might be smaller) */
|
||
|
uint64_t size_each;
|
||
|
|
||
|
/* Slots array and its element count */
|
||
|
MemoryRegion *slots;
|
||
|
unsigned int count;
|
||
|
|
||
|
/* How many slots are currently mapped */
|
||
|
unsigned int mapped_count;
|
||
|
} OurRangeMemslotsSlots;
|
||
|
|
||
|
typedef struct OurRangeMemslots {
|
||
|
OurRange range;
|
||
|
|
||
|
/* Memslots covering our range */
|
||
|
OurRangeMemslotsSlots slots;
|
||
|
|
||
|
MemoryRegion *mr;
|
||
|
} OurRangeMemslots;
|
||
|
|
||
|
OurRangeMemslots *hvb_our_range_memslots_new(uint64_t addr,
|
||
|
MemoryRegion *parent_mr,
|
||
|
MemoryRegion *backing_mr,
|
||
|
Object *memslot_owner,
|
||
|
unsigned int memslot_count,
|
||
|
uint64_t memslot_size);
|
||
|
void hvb_our_range_memslots_free(OurRangeMemslots *our_range);
|
||
|
|
||
|
G_DEFINE_AUTOPTR_CLEANUP_FUNC(OurRangeMemslots, hvb_our_range_memslots_free)
|
||
|
|
||
|
void hvb_our_range_memslots_ensure_mapped_additional(OurRangeMemslots *our_range,
|
||
|
uint64_t additional_map_size);
|
||
|
|
||
|
#endif
|