1*99a4706aSMaciej S. Szmigiero /*
2*99a4706aSMaciej S. Szmigiero  * QEMU Hyper-V Dynamic Memory Protocol driver
3*99a4706aSMaciej S. Szmigiero  *
4*99a4706aSMaciej S. Szmigiero  * Copyright (C) 2020-2023 Oracle and/or its affiliates.
5*99a4706aSMaciej S. Szmigiero  *
6*99a4706aSMaciej S. Szmigiero  * This work is licensed under the terms of the GNU GPL, version 2 or later.
7*99a4706aSMaciej S. Szmigiero  * See the COPYING file in the top-level directory.
8*99a4706aSMaciej S. Szmigiero  */
9*99a4706aSMaciej S. Szmigiero 
10*99a4706aSMaciej S. Szmigiero #ifndef HW_HYPERV_HV_BALLOON_OUR_RANGE_MEMSLOTS_H
11*99a4706aSMaciej S. Szmigiero #define HW_HYPERV_HV_BALLOON_OUR_RANGE_MEMSLOTS_H
12*99a4706aSMaciej S. Szmigiero 
13*99a4706aSMaciej S. Szmigiero #include "qemu/osdep.h"
14*99a4706aSMaciej S. Szmigiero 
15*99a4706aSMaciej S. Szmigiero #include "exec/memory.h"
16*99a4706aSMaciej S. Szmigiero #include "qom/object.h"
17*99a4706aSMaciej S. Szmigiero #include "hv-balloon-page_range_tree.h"
18*99a4706aSMaciej S. Szmigiero 
19*99a4706aSMaciej S. Szmigiero /* OurRange */
20*99a4706aSMaciej S. Szmigiero #define OUR_RANGE(ptr) ((OurRange *)(ptr))
21*99a4706aSMaciej S. Szmigiero 
22*99a4706aSMaciej S. Szmigiero /* "our range" means the memory range owned by this driver (for hot-adding) */
23*99a4706aSMaciej S. Szmigiero typedef struct OurRange {
24*99a4706aSMaciej S. Szmigiero     PageRange range;
25*99a4706aSMaciej S. Szmigiero 
26*99a4706aSMaciej S. Szmigiero     /* How many pages were hot-added to the guest */
27*99a4706aSMaciej S. Szmigiero     uint64_t added;
28*99a4706aSMaciej S. Szmigiero 
29*99a4706aSMaciej S. Szmigiero     /* Pages at the end not currently usable */
30*99a4706aSMaciej S. Szmigiero     uint64_t unusable_tail;
31*99a4706aSMaciej S. Szmigiero 
32*99a4706aSMaciej S. Szmigiero     /* Memory removed from the guest */
33*99a4706aSMaciej S. Szmigiero     PageRangeTree removed_guest, removed_both;
34*99a4706aSMaciej S. Szmigiero } OurRange;
35*99a4706aSMaciej S. Szmigiero 
our_range_get_remaining_start(OurRange * our_range)36*99a4706aSMaciej S. Szmigiero static inline uint64_t our_range_get_remaining_start(OurRange *our_range)
37*99a4706aSMaciej S. Szmigiero {
38*99a4706aSMaciej S. Szmigiero     return our_range->range.start + our_range->added;
39*99a4706aSMaciej S. Szmigiero }
40*99a4706aSMaciej S. Szmigiero 
our_range_get_remaining_size(OurRange * our_range)41*99a4706aSMaciej S. Szmigiero static inline uint64_t our_range_get_remaining_size(OurRange *our_range)
42*99a4706aSMaciej S. Szmigiero {
43*99a4706aSMaciej S. Szmigiero     return our_range->range.count - our_range->added - our_range->unusable_tail;
44*99a4706aSMaciej S. Szmigiero }
45*99a4706aSMaciej S. Szmigiero 
46*99a4706aSMaciej S. Szmigiero void hvb_our_range_mark_added(OurRange *our_range, uint64_t additional_size);
47*99a4706aSMaciej S. Szmigiero 
our_range_mark_remaining_unusable(OurRange * our_range)48*99a4706aSMaciej S. Szmigiero static inline void our_range_mark_remaining_unusable(OurRange *our_range)
49*99a4706aSMaciej S. Szmigiero {
50*99a4706aSMaciej S. Szmigiero     our_range->unusable_tail = our_range->range.count - our_range->added;
51*99a4706aSMaciej S. Szmigiero }
52*99a4706aSMaciej S. Szmigiero 
our_range_get_removed_tree(OurRange * our_range,bool both)53*99a4706aSMaciej S. Szmigiero static inline PageRangeTree our_range_get_removed_tree(OurRange *our_range,
54*99a4706aSMaciej S. Szmigiero                                                        bool both)
55*99a4706aSMaciej S. Szmigiero {
56*99a4706aSMaciej S. Szmigiero     if (both) {
57*99a4706aSMaciej S. Szmigiero         return our_range->removed_both;
58*99a4706aSMaciej S. Szmigiero     } else {
59*99a4706aSMaciej S. Szmigiero         return our_range->removed_guest;
60*99a4706aSMaciej S. Szmigiero     }
61*99a4706aSMaciej S. Szmigiero }
62*99a4706aSMaciej S. Szmigiero 
our_range_is_removed_tree_empty(OurRange * our_range,bool both)63*99a4706aSMaciej S. Szmigiero static inline bool our_range_is_removed_tree_empty(OurRange *our_range,
64*99a4706aSMaciej S. Szmigiero                                                    bool both)
65*99a4706aSMaciej S. Szmigiero {
66*99a4706aSMaciej S. Szmigiero     if (both) {
67*99a4706aSMaciej S. Szmigiero         return page_range_tree_is_empty(our_range->removed_both);
68*99a4706aSMaciej S. Szmigiero     } else {
69*99a4706aSMaciej S. Szmigiero         return page_range_tree_is_empty(our_range->removed_guest);
70*99a4706aSMaciej S. Szmigiero     }
71*99a4706aSMaciej S. Szmigiero }
72*99a4706aSMaciej S. Szmigiero 
73*99a4706aSMaciej S. Szmigiero void hvb_our_range_clear_removed_trees(OurRange *our_range);
74*99a4706aSMaciej S. Szmigiero 
75*99a4706aSMaciej S. Szmigiero /* OurRangeMemslots */
76*99a4706aSMaciej S. Szmigiero typedef struct OurRangeMemslotsSlots {
77*99a4706aSMaciej S. Szmigiero     /* Nominal size of each memslot (the last one might be smaller) */
78*99a4706aSMaciej S. Szmigiero     uint64_t size_each;
79*99a4706aSMaciej S. Szmigiero 
80*99a4706aSMaciej S. Szmigiero     /* Slots array and its element count */
81*99a4706aSMaciej S. Szmigiero     MemoryRegion *slots;
82*99a4706aSMaciej S. Szmigiero     unsigned int count;
83*99a4706aSMaciej S. Szmigiero 
84*99a4706aSMaciej S. Szmigiero     /* How many slots are currently mapped */
85*99a4706aSMaciej S. Szmigiero     unsigned int mapped_count;
86*99a4706aSMaciej S. Szmigiero } OurRangeMemslotsSlots;
87*99a4706aSMaciej S. Szmigiero 
88*99a4706aSMaciej S. Szmigiero typedef struct OurRangeMemslots {
89*99a4706aSMaciej S. Szmigiero     OurRange range;
90*99a4706aSMaciej S. Szmigiero 
91*99a4706aSMaciej S. Szmigiero     /* Memslots covering our range */
92*99a4706aSMaciej S. Szmigiero     OurRangeMemslotsSlots slots;
93*99a4706aSMaciej S. Szmigiero 
94*99a4706aSMaciej S. Szmigiero     MemoryRegion *mr;
95*99a4706aSMaciej S. Szmigiero } OurRangeMemslots;
96*99a4706aSMaciej S. Szmigiero 
97*99a4706aSMaciej S. Szmigiero OurRangeMemslots *hvb_our_range_memslots_new(uint64_t addr,
98*99a4706aSMaciej S. Szmigiero                                              MemoryRegion *parent_mr,
99*99a4706aSMaciej S. Szmigiero                                              MemoryRegion *backing_mr,
100*99a4706aSMaciej S. Szmigiero                                              Object *memslot_owner,
101*99a4706aSMaciej S. Szmigiero                                              unsigned int memslot_count,
102*99a4706aSMaciej S. Szmigiero                                              uint64_t memslot_size);
103*99a4706aSMaciej S. Szmigiero void hvb_our_range_memslots_free(OurRangeMemslots *our_range);
104*99a4706aSMaciej S. Szmigiero 
105*99a4706aSMaciej S. Szmigiero G_DEFINE_AUTOPTR_CLEANUP_FUNC(OurRangeMemslots, hvb_our_range_memslots_free)
106*99a4706aSMaciej S. Szmigiero 
107*99a4706aSMaciej S. Szmigiero void hvb_our_range_memslots_ensure_mapped_additional(OurRangeMemslots *our_range,
108*99a4706aSMaciej S. Szmigiero                                                      uint64_t additional_map_size);
109*99a4706aSMaciej S. Szmigiero 
110*99a4706aSMaciej S. Szmigiero #endif
111