Instead of having a fixed limit of 32 slots, we allow the number of slots to expand. Currently there does not seem to be a need to add a limit, but if the allocation fails, we will abort. The KVM backend was used for inspiration here.
Signed-off-by: Joelle van Dyne <[email protected]> --- include/system/hvf_int.h | 12 ++++++- accel/hvf/hvf-all.c | 78 ++++++++++++++++++++++++++++++---------- 2 files changed, 71 insertions(+), 19 deletions(-) diff --git a/include/system/hvf_int.h b/include/system/hvf_int.h index 3d2be4092e..1d2616595c 100644 --- a/include/system/hvf_int.h +++ b/include/system/hvf_int.h @@ -27,6 +27,7 @@ typedef hv_vcpuid_t hvf_vcpuid; /* hvf_slot flags */ #define HVF_SLOT_LOG (1 << 0) +/* Represent memory logically mapped by QEMU */ typedef struct hvf_slot { uint64_t start; uint64_t size; @@ -36,6 +37,14 @@ typedef struct hvf_slot { MemoryRegion *region; } hvf_slot; +/* Represent memory currently mapped in HVF */ +typedef struct hvf_mac_slot { + int present; + uint64_t size; + uint64_t gpa_start; + uint64_t gva; +} hvf_mac_slot; + typedef struct hvf_vcpu_caps { uint64_t vmx_cap_pinbased; uint64_t vmx_cap_procbased; @@ -48,7 +57,8 @@ typedef struct hvf_vcpu_caps { struct HVFState { AccelState parent_obj; - hvf_slot slots[32]; + hvf_slot *slots; + hvf_mac_slot *mac_slots; int num_slots; hvf_vcpu_caps *hvf_caps; diff --git a/accel/hvf/hvf-all.c b/accel/hvf/hvf-all.c index 0a4b498e83..367ff4fd40 100644 --- a/accel/hvf/hvf-all.c +++ b/accel/hvf/hvf-all.c @@ -21,14 +21,8 @@ bool hvf_allowed; -struct mac_slot { - int present; - uint64_t size; - uint64_t gpa_start; - uint64_t gva; -}; - -struct mac_slot mac_slots[32]; +/* Default num of memslots to be allocated when VM starts */ +#define HVF_MEMSLOTS_NUM_ALLOC_DEFAULT 32 const char *hvf_return_string(hv_return_t ret) { @@ -58,12 +52,60 @@ void assert_hvf_ok_impl(hv_return_t ret, const char *file, unsigned int line, abort(); } +static bool hvf_slots_grow(HVFState *state, unsigned int num_slots_new) +{ + unsigned int i, cur = state->num_slots; + hvf_slot *slots; + hvf_mac_slot *mac_slots; + + assert(num_slots_new > cur); + if (cur == 0) { + slots = g_new0(hvf_slot, num_slots_new); + if (!slots) { + return false; + } + mac_slots = g_new0(hvf_mac_slot, num_slots_new); + if (!mac_slots) { + g_free(slots); + return false; + } + } else { + slots = g_renew(hvf_slot, state->slots, num_slots_new); + if (!slots) { + return false; + } + mac_slots = g_renew(hvf_mac_slot, state->mac_slots, num_slots_new); + if (!mac_slots) { + /* save allocated slots but not new size */ + state->slots = slots; + return false; + } + /* + * g_renew() doesn't initialize extended buffers, however hvf + * memslots require fields to be zero-initialized. E.g. pointers, + * memory_size field, etc. + */ + memset(&slots[cur], 0x0, sizeof(slots[0]) * (num_slots_new - cur)); + memset(&mac_slots[cur], 0x0, sizeof(mac_slots[0]) * (num_slots_new - cur)); + } + + for (i = cur; i < num_slots_new; i++) { + slots[i].slot_id = i; + } + + state->slots = slots; + state->mac_slots = mac_slots; + state->num_slots = num_slots_new; + + return true; +} + static int do_hvf_set_memory(hvf_slot *slot, hv_memory_flags_t flags) { - struct mac_slot *macslot; + hvf_mac_slot *macslot; hv_return_t ret; - macslot = &mac_slots[slot->slot_id]; + macslot = &hvf_state->mac_slots[slot->slot_id]; if (macslot->present) { if (macslot->size != slot->size) { @@ -160,8 +202,11 @@ static void hvf_set_phys_mem(MemoryRegionSection *section, bool add) } if (x == hvf_state->num_slots) { - error_report("No free slots"); - abort(); + if (!hvf_slots_grow(hvf_state, hvf_state->num_slots * 2)) { + error_report("Cannot allocate any more slots"); + abort(); + } + mem = &hvf_state->slots[x]; } mem->size = int128_get64(section->size); @@ -250,11 +295,11 @@ static MemoryListener hvf_memory_listener = { static int hvf_accel_init(AccelState *as, MachineState *ms) { - int x; hv_return_t ret; HVFState *s = HVF_STATE(as); int pa_range = 36; MachineClass *mc = MACHINE_GET_CLASS(ms); + bool success; if (mc->hvf_get_physical_address_range) { pa_range = mc->hvf_get_physical_address_range(ms); @@ -271,11 +316,8 @@ static int hvf_accel_init(AccelState *as, MachineState *ms) } assert_hvf_ok(ret); - s->num_slots = ARRAY_SIZE(s->slots); - for (x = 0; x < s->num_slots; ++x) { - s->slots[x].size = 0; - s->slots[x].slot_id = x; - } + success = hvf_slots_grow(s, HVF_MEMSLOTS_NUM_ALLOC_DEFAULT); + assert(success); QTAILQ_INIT(&s->hvf_sw_breakpoints); -- 2.41.0
