/* * 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 "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