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