mirror of https://github.com/proxmox/mirror_qemu
hvf: non-RAM, non-ROMD memory ranges are now correctly mapped in
If an area is non-RAM and non-ROMD, then remove mappings so accesses will trap and can be emulated. Change hvf_find_overlap_slot() to take a size instead of an end address: it wouldn't return a slot because callers would pass the same address for start and end. Don't always map area as read/write/execute, respect area flags. Signed-off-by: Cameron Esfahani <dirty@apple.com> Message-Id: <1d8476c8f86959273fbdf23c86f8b4b611f5e2e1.1574625592.git.dirty@apple.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>master
parent
c6f3215ffa
commit
fbafbb6db7
|
@ -107,14 +107,14 @@ static void assert_hvf_ok(hv_return_t ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Memory slots */
|
/* Memory slots */
|
||||||
hvf_slot *hvf_find_overlap_slot(uint64_t start, uint64_t end)
|
hvf_slot *hvf_find_overlap_slot(uint64_t start, uint64_t size)
|
||||||
{
|
{
|
||||||
hvf_slot *slot;
|
hvf_slot *slot;
|
||||||
int x;
|
int x;
|
||||||
for (x = 0; x < hvf_state->num_slots; ++x) {
|
for (x = 0; x < hvf_state->num_slots; ++x) {
|
||||||
slot = &hvf_state->slots[x];
|
slot = &hvf_state->slots[x];
|
||||||
if (slot->size && start < (slot->start + slot->size) &&
|
if (slot->size && start < (slot->start + slot->size) &&
|
||||||
end > slot->start) {
|
(start + size) > slot->start) {
|
||||||
return slot;
|
return slot;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -129,12 +129,10 @@ struct mac_slot {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mac_slot mac_slots[32];
|
struct mac_slot mac_slots[32];
|
||||||
#define ALIGN(x, y) (((x) + (y) - 1) & ~((y) - 1))
|
|
||||||
|
|
||||||
static int do_hvf_set_memory(hvf_slot *slot)
|
static int do_hvf_set_memory(hvf_slot *slot, hv_memory_flags_t flags)
|
||||||
{
|
{
|
||||||
struct mac_slot *macslot;
|
struct mac_slot *macslot;
|
||||||
hv_memory_flags_t flags;
|
|
||||||
hv_return_t ret;
|
hv_return_t ret;
|
||||||
|
|
||||||
macslot = &mac_slots[slot->slot_id];
|
macslot = &mac_slots[slot->slot_id];
|
||||||
|
@ -151,8 +149,6 @@ static int do_hvf_set_memory(hvf_slot *slot)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
flags = HV_MEMORY_READ | HV_MEMORY_WRITE | HV_MEMORY_EXEC;
|
|
||||||
|
|
||||||
macslot->present = 1;
|
macslot->present = 1;
|
||||||
macslot->gpa_start = slot->start;
|
macslot->gpa_start = slot->start;
|
||||||
macslot->size = slot->size;
|
macslot->size = slot->size;
|
||||||
|
@ -165,14 +161,24 @@ void hvf_set_phys_mem(MemoryRegionSection *section, bool add)
|
||||||
{
|
{
|
||||||
hvf_slot *mem;
|
hvf_slot *mem;
|
||||||
MemoryRegion *area = section->mr;
|
MemoryRegion *area = section->mr;
|
||||||
|
bool writeable = !area->readonly && !area->rom_device;
|
||||||
|
hv_memory_flags_t flags;
|
||||||
|
|
||||||
if (!memory_region_is_ram(area)) {
|
if (!memory_region_is_ram(area)) {
|
||||||
return;
|
if (writeable) {
|
||||||
|
return;
|
||||||
|
} else if (!memory_region_is_romd(area)) {
|
||||||
|
/*
|
||||||
|
* If the memory device is not in romd_mode, then we actually want
|
||||||
|
* to remove the hvf memory slot so all accesses will trap.
|
||||||
|
*/
|
||||||
|
add = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mem = hvf_find_overlap_slot(
|
mem = hvf_find_overlap_slot(
|
||||||
section->offset_within_address_space,
|
section->offset_within_address_space,
|
||||||
section->offset_within_address_space + int128_get64(section->size));
|
int128_get64(section->size));
|
||||||
|
|
||||||
if (mem && add) {
|
if (mem && add) {
|
||||||
if (mem->size == int128_get64(section->size) &&
|
if (mem->size == int128_get64(section->size) &&
|
||||||
|
@ -186,7 +192,7 @@ void hvf_set_phys_mem(MemoryRegionSection *section, bool add)
|
||||||
/* Region needs to be reset. set the size to 0 and remap it. */
|
/* Region needs to be reset. set the size to 0 and remap it. */
|
||||||
if (mem) {
|
if (mem) {
|
||||||
mem->size = 0;
|
mem->size = 0;
|
||||||
if (do_hvf_set_memory(mem)) {
|
if (do_hvf_set_memory(mem, 0)) {
|
||||||
error_report("Failed to reset overlapping slot");
|
error_report("Failed to reset overlapping slot");
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
@ -196,6 +202,13 @@ void hvf_set_phys_mem(MemoryRegionSection *section, bool add)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (area->readonly ||
|
||||||
|
(!memory_region_is_ram(area) && memory_region_is_romd(area))) {
|
||||||
|
flags = HV_MEMORY_READ | HV_MEMORY_EXEC;
|
||||||
|
} else {
|
||||||
|
flags = HV_MEMORY_READ | HV_MEMORY_WRITE | HV_MEMORY_EXEC;
|
||||||
|
}
|
||||||
|
|
||||||
/* Now make a new slot. */
|
/* Now make a new slot. */
|
||||||
int x;
|
int x;
|
||||||
|
|
||||||
|
@ -216,7 +229,7 @@ void hvf_set_phys_mem(MemoryRegionSection *section, bool add)
|
||||||
mem->start = section->offset_within_address_space;
|
mem->start = section->offset_within_address_space;
|
||||||
mem->region = area;
|
mem->region = area;
|
||||||
|
|
||||||
if (do_hvf_set_memory(mem)) {
|
if (do_hvf_set_memory(mem, flags)) {
|
||||||
error_report("Error registering new memory slot");
|
error_report("Error registering new memory slot");
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
@ -345,7 +358,14 @@ static bool ept_emulation_fault(hvf_slot *slot, uint64_t gpa, uint64_t ept_qual)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return !slot;
|
if (!slot) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!memory_region_is_ram(slot->region) &&
|
||||||
|
!(read && memory_region_is_romd(slot->region))) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hvf_set_dirty_tracking(MemoryRegionSection *section, bool on)
|
static void hvf_set_dirty_tracking(MemoryRegionSection *section, bool on)
|
||||||
|
@ -354,7 +374,7 @@ static void hvf_set_dirty_tracking(MemoryRegionSection *section, bool on)
|
||||||
|
|
||||||
slot = hvf_find_overlap_slot(
|
slot = hvf_find_overlap_slot(
|
||||||
section->offset_within_address_space,
|
section->offset_within_address_space,
|
||||||
section->offset_within_address_space + int128_get64(section->size));
|
int128_get64(section->size));
|
||||||
|
|
||||||
/* protect region against writes; begin tracking it */
|
/* protect region against writes; begin tracking it */
|
||||||
if (on) {
|
if (on) {
|
||||||
|
@ -720,7 +740,7 @@ int hvf_vcpu_exec(CPUState *cpu)
|
||||||
ret = EXCP_INTERRUPT;
|
ret = EXCP_INTERRUPT;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* Need to check if MMIO or unmmaped fault */
|
/* Need to check if MMIO or unmapped fault */
|
||||||
case EXIT_REASON_EPT_FAULT:
|
case EXIT_REASON_EPT_FAULT:
|
||||||
{
|
{
|
||||||
hvf_slot *slot;
|
hvf_slot *slot;
|
||||||
|
@ -731,7 +751,7 @@ int hvf_vcpu_exec(CPUState *cpu)
|
||||||
vmx_set_nmi_blocking(cpu);
|
vmx_set_nmi_blocking(cpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
slot = hvf_find_overlap_slot(gpa, gpa);
|
slot = hvf_find_overlap_slot(gpa, 1);
|
||||||
/* mmio */
|
/* mmio */
|
||||||
if (ept_emulation_fault(slot, gpa, exit_qual)) {
|
if (ept_emulation_fault(slot, gpa, exit_qual)) {
|
||||||
struct x86_decode decode;
|
struct x86_decode decode;
|
||||||
|
|
Loading…
Reference in New Issue