* [PATCH 0/5] hvf: stability fixes for HVF
@ 2019-11-21 22:54 Cameron Esfahani via
2019-11-21 22:54 ` [PATCH 1/5] hvf: non-RAM, non-ROMD memory ranges are now correctly mapped in Cameron Esfahani via
` (6 more replies)
0 siblings, 7 replies; 8+ messages in thread
From: Cameron Esfahani via @ 2019-11-21 22:54 UTC (permalink / raw)
To: qemu-devel; +Cc: pbonzini
The following patches fix stability issues with running QEMU on Apple
Hypervisor Framework (HVF):
- non-RAM, non-ROMD areas need to trap so accesses can be correctly
emulated.
- Current TSC synchronization implementation is insufficient: when
running with more than 1 core, TSC values can go backwards. Until
a correct implementation can be written, remove calls to
hv_vm_sync_tsc(). Pass through TSC to guest OS.
- Fix REX emulation in relation to legacy prefixes.
- More correctly match SDM when setting CR0 and PDPTE registers.
- Save away exception type as well as vector in hvf_store_events() so
they can be correctly reinjected in hvf_inject_interrupts(). Under
heavy loads, exceptions got misrouted.
Cameron Esfahani (5):
hvf: non-RAM, non-ROMD memory ranges are now correctly mapped in
hvf: remove TSC synchronization code because it isn't fully complete
hvf: correctly handle REX prefix in relation to legacy prefixes
hvf: more accurately match SDM when setting CR0 and PDPTE registers
hvf: save away type as well as vector so we can reinject them
target/i386/hvf/hvf.c | 74 +++++++++++++++++++++++++-----------
target/i386/hvf/vmx.h | 18 +++++----
target/i386/hvf/x86_decode.c | 55 ++++++++++++++-------------
target/i386/hvf/x86_decode.h | 16 ++++----
target/i386/hvf/x86_emu.c | 3 --
target/i386/hvf/x86hvf.c | 26 +++++--------
6 files changed, 108 insertions(+), 84 deletions(-)
--
2.24.0
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 1/5] hvf: non-RAM, non-ROMD memory ranges are now correctly mapped in
2019-11-21 22:54 [PATCH 0/5] hvf: stability fixes for HVF Cameron Esfahani via
@ 2019-11-21 22:54 ` Cameron Esfahani via
2019-11-21 22:54 ` [PATCH 2/5] hvf: remove TSC synchronization code because it isn't fully complete Cameron Esfahani via
` (5 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Cameron Esfahani via @ 2019-11-21 22:54 UTC (permalink / raw)
To: qemu-devel; +Cc: pbonzini
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>
---
target/i386/hvf/hvf.c | 47 +++++++++++++++++++++++++++----------------
1 file changed, 30 insertions(+), 17 deletions(-)
diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c
index 231732aaf7..60c995470b 100644
--- a/target/i386/hvf/hvf.c
+++ b/target/i386/hvf/hvf.c
@@ -107,14 +107,14 @@ static void assert_hvf_ok(hv_return_t ret)
}
/* 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;
int x;
for (x = 0; x < hvf_state->num_slots; ++x) {
slot = &hvf_state->slots[x];
if (slot->size && start < (slot->start + slot->size) &&
- end > slot->start) {
+ (start + size) > slot->start) {
return slot;
}
}
@@ -129,12 +129,10 @@ struct mac_slot {
};
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;
- hv_memory_flags_t flags;
hv_return_t ret;
macslot = &mac_slots[slot->slot_id];
@@ -151,8 +149,6 @@ static int do_hvf_set_memory(hvf_slot *slot)
return 0;
}
- flags = HV_MEMORY_READ | HV_MEMORY_WRITE | HV_MEMORY_EXEC;
-
macslot->present = 1;
macslot->gpa_start = slot->start;
macslot->size = slot->size;
@@ -165,14 +161,22 @@ void hvf_set_phys_mem(MemoryRegionSection *section, bool add)
{
hvf_slot *mem;
MemoryRegion *area = section->mr;
+ bool writeable = !area->readonly && !area->rom_device;
+ hv_memory_flags_t flags;
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(
section->offset_within_address_space,
- section->offset_within_address_space + int128_get64(section->size));
+ int128_get64(section->size));
if (mem && add) {
if (mem->size == int128_get64(section->size) &&
@@ -186,8 +190,8 @@ void hvf_set_phys_mem(MemoryRegionSection *section, bool add)
/* Region needs to be reset. set the size to 0 and remap it. */
if (mem) {
mem->size = 0;
- if (do_hvf_set_memory(mem)) {
- error_report("Failed to reset overlapping slot");
+ if (do_hvf_set_memory(mem, 0)) {
+ error_report("Failed to reset overlapping slot\n");
abort();
}
}
@@ -196,6 +200,11 @@ void hvf_set_phys_mem(MemoryRegionSection *section, bool add)
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. */
int x;
@@ -216,8 +225,8 @@ void hvf_set_phys_mem(MemoryRegionSection *section, bool add)
mem->start = section->offset_within_address_space;
mem->region = area;
- if (do_hvf_set_memory(mem)) {
- error_report("Error registering new memory slot");
+ if (do_hvf_set_memory(mem, flags)) {
+ error_report("Error registering new memory slot\n");
abort();
}
}
@@ -345,7 +354,11 @@ static bool ept_emulation_fault(hvf_slot *slot, uint64_t gpa, uint64_t ept_qual)
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)
@@ -354,7 +367,7 @@ static void hvf_set_dirty_tracking(MemoryRegionSection *section, bool on)
slot = hvf_find_overlap_slot(
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 */
if (on) {
@@ -720,7 +733,7 @@ int hvf_vcpu_exec(CPUState *cpu)
ret = EXCP_INTERRUPT;
break;
}
- /* Need to check if MMIO or unmmaped fault */
+ /* Need to check if MMIO or unmapped fault */
case EXIT_REASON_EPT_FAULT:
{
hvf_slot *slot;
@@ -731,7 +744,7 @@ int hvf_vcpu_exec(CPUState *cpu)
vmx_set_nmi_blocking(cpu);
}
- slot = hvf_find_overlap_slot(gpa, gpa);
+ slot = hvf_find_overlap_slot(gpa, 1);
/* mmio */
if (ept_emulation_fault(slot, gpa, exit_qual)) {
struct x86_decode decode;
--
2.24.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 2/5] hvf: remove TSC synchronization code because it isn't fully complete
2019-11-21 22:54 [PATCH 0/5] hvf: stability fixes for HVF Cameron Esfahani via
2019-11-21 22:54 ` [PATCH 1/5] hvf: non-RAM, non-ROMD memory ranges are now correctly mapped in Cameron Esfahani via
@ 2019-11-21 22:54 ` Cameron Esfahani via
2019-11-21 22:54 ` [PATCH 3/5] hvf: correctly handle REX prefix in relation to legacy prefixes Cameron Esfahani via
` (4 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Cameron Esfahani via @ 2019-11-21 22:54 UTC (permalink / raw)
To: qemu-devel; +Cc: pbonzini
The existing code in QEMU's HVF support to attempt to synchronize TSC
across multiple cores is not sufficient. TSC value on other cores
can go backwards. Until implementation is fixed, remove calls to
hv_vm_sync_tsc(). Pass through TSC to guest OS.
Signed-off-by: Cameron Esfahani <dirty@apple.com>
---
target/i386/hvf/hvf.c | 3 +--
target/i386/hvf/x86_emu.c | 3 ---
target/i386/hvf/x86hvf.c | 4 ----
3 files changed, 1 insertion(+), 9 deletions(-)
diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c
index 60c995470b..fda0273ba1 100644
--- a/target/i386/hvf/hvf.c
+++ b/target/i386/hvf/hvf.c
@@ -511,7 +511,6 @@ void hvf_reset_vcpu(CPUState *cpu) {
wreg(cpu->hvf_fd, HV_X86_R8 + i, 0x0);
}
- hv_vm_sync_tsc(0);
hv_vcpu_invalidate_tlb(cpu->hvf_fd);
hv_vcpu_flush(cpu->hvf_fd);
}
@@ -605,7 +604,7 @@ int hvf_init_vcpu(CPUState *cpu)
hv_vcpu_enable_native_msr(cpu->hvf_fd, MSR_GSBASE, 1);
hv_vcpu_enable_native_msr(cpu->hvf_fd, MSR_KERNELGSBASE, 1);
hv_vcpu_enable_native_msr(cpu->hvf_fd, MSR_TSC_AUX, 1);
- /*hv_vcpu_enable_native_msr(cpu->hvf_fd, MSR_IA32_TSC, 1);*/
+ hv_vcpu_enable_native_msr(cpu->hvf_fd, MSR_IA32_TSC, 1);
hv_vcpu_enable_native_msr(cpu->hvf_fd, MSR_IA32_SYSENTER_CS, 1);
hv_vcpu_enable_native_msr(cpu->hvf_fd, MSR_IA32_SYSENTER_EIP, 1);
hv_vcpu_enable_native_msr(cpu->hvf_fd, MSR_IA32_SYSENTER_ESP, 1);
diff --git a/target/i386/hvf/x86_emu.c b/target/i386/hvf/x86_emu.c
index 1b04bd7e94..3df767209d 100644
--- a/target/i386/hvf/x86_emu.c
+++ b/target/i386/hvf/x86_emu.c
@@ -772,9 +772,6 @@ void simulate_wrmsr(struct CPUState *cpu)
switch (msr) {
case MSR_IA32_TSC:
- /* if (!osx_is_sierra())
- wvmcs(cpu->hvf_fd, VMCS_TSC_OFFSET, data - rdtscp());
- hv_vm_sync_tsc(data);*/
break;
case MSR_IA32_APICBASE:
cpu_set_apic_base(X86_CPU(cpu)->apic_state, data);
diff --git a/target/i386/hvf/x86hvf.c b/target/i386/hvf/x86hvf.c
index e0ea02d631..1485b95776 100644
--- a/target/i386/hvf/x86hvf.c
+++ b/target/i386/hvf/x86hvf.c
@@ -152,10 +152,6 @@ void hvf_put_msrs(CPUState *cpu_state)
hv_vcpu_write_msr(cpu_state->hvf_fd, MSR_GSBASE, env->segs[R_GS].base);
hv_vcpu_write_msr(cpu_state->hvf_fd, MSR_FSBASE, env->segs[R_FS].base);
-
- /* if (!osx_is_sierra())
- wvmcs(cpu_state->hvf_fd, VMCS_TSC_OFFSET, env->tsc - rdtscp());*/
- hv_vm_sync_tsc(env->tsc);
}
--
2.24.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 3/5] hvf: correctly handle REX prefix in relation to legacy prefixes
2019-11-21 22:54 [PATCH 0/5] hvf: stability fixes for HVF Cameron Esfahani via
2019-11-21 22:54 ` [PATCH 1/5] hvf: non-RAM, non-ROMD memory ranges are now correctly mapped in Cameron Esfahani via
2019-11-21 22:54 ` [PATCH 2/5] hvf: remove TSC synchronization code because it isn't fully complete Cameron Esfahani via
@ 2019-11-21 22:54 ` Cameron Esfahani via
2019-11-21 22:54 ` [PATCH 4/5] hvf: more accurately match SDM when setting CR0 and PDPTE registers Cameron Esfahani via
` (3 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Cameron Esfahani via @ 2019-11-21 22:54 UTC (permalink / raw)
To: qemu-devel; +Cc: pbonzini
In real x86 processors, the REX prefix must come after legacy prefixes.
REX before legacy is ignored. Update the HVF emulation code to properly
handle this. Fix some spelling errors in constants. Fix some decoder
table initialization issues found by Coverity.
Signed-off-by: Cameron Esfahani <dirty@apple.com>
---
target/i386/hvf/x86_decode.c | 55 +++++++++++++++++++-----------------
target/i386/hvf/x86_decode.h | 16 +++++------
2 files changed, 37 insertions(+), 34 deletions(-)
diff --git a/target/i386/hvf/x86_decode.c b/target/i386/hvf/x86_decode.c
index 822fa1866e..e2806f7967 100644
--- a/target/i386/hvf/x86_decode.c
+++ b/target/i386/hvf/x86_decode.c
@@ -122,7 +122,8 @@ static void decode_rax(CPUX86State *env, struct x86_decode *decode,
{
op->type = X86_VAR_REG;
op->reg = R_EAX;
- op->ptr = get_reg_ref(env, op->reg, decode->rex.rex, 0,
+ /* Since reg is always AX, REX prefix has no impact. */
+ op->ptr = get_reg_ref(env, op->reg, false, 0,
decode->operand_size);
}
@@ -1687,40 +1688,35 @@ calc_addr:
}
}
-target_ulong get_reg_ref(CPUX86State *env, int reg, int rex, int is_extended,
+target_ulong get_reg_ref(CPUX86State *env, int reg, int rex_present, int is_extended,
int size)
{
target_ulong ptr = 0;
- int which = 0;
if (is_extended) {
reg |= R_R8;
}
-
switch (size) {
case 1:
- if (is_extended || reg < 4 || rex) {
- which = 1;
+ if (is_extended || reg < 4 || rex_present) {
ptr = (target_ulong)&RL(env, reg);
} else {
- which = 2;
ptr = (target_ulong)&RH(env, reg - 4);
}
break;
default:
- which = 3;
ptr = (target_ulong)&RRX(env, reg);
break;
}
return ptr;
}
-target_ulong get_reg_val(CPUX86State *env, int reg, int rex, int is_extended,
+target_ulong get_reg_val(CPUX86State *env, int reg, int rex_present, int is_extended,
int size)
{
target_ulong val = 0;
- memcpy(&val, (void *)get_reg_ref(env, reg, rex, is_extended, size), size);
+ memcpy(&val, (void *)get_reg_ref(env, reg, rex_present, is_extended, size), size);
return val;
}
@@ -1853,28 +1849,35 @@ void calc_modrm_operand(CPUX86State *env, struct x86_decode *decode,
static void decode_prefix(CPUX86State *env, struct x86_decode *decode)
{
while (1) {
+ /* REX prefix must come after legacy prefixes. REX before legacy is ignored.
+ Clear rex to simulate this. */
uint8_t byte = decode_byte(env, decode);
switch (byte) {
case PREFIX_LOCK:
decode->lock = byte;
+ decode->rex.rex = 0;
break;
case PREFIX_REPN:
case PREFIX_REP:
decode->rep = byte;
+ decode->rex.rex = 0;
break;
- case PREFIX_CS_SEG_OVEERIDE:
- case PREFIX_SS_SEG_OVEERIDE:
- case PREFIX_DS_SEG_OVEERIDE:
- case PREFIX_ES_SEG_OVEERIDE:
- case PREFIX_FS_SEG_OVEERIDE:
- case PREFIX_GS_SEG_OVEERIDE:
+ case PREFIX_CS_SEG_OVERRIDE:
+ case PREFIX_SS_SEG_OVERRIDE:
+ case PREFIX_DS_SEG_OVERRIDE:
+ case PREFIX_ES_SEG_OVERRIDE:
+ case PREFIX_FS_SEG_OVERRIDE:
+ case PREFIX_GS_SEG_OVERRIDE:
decode->segment_override = byte;
+ decode->rex.rex = 0;
break;
case PREFIX_OP_SIZE_OVERRIDE:
decode->op_size_override = byte;
+ decode->rex.rex = 0;
break;
case PREFIX_ADDR_SIZE_OVERRIDE:
decode->addr_size_override = byte;
+ decode->rex.rex = 0;
break;
case PREFIX_REX ... (PREFIX_REX + 0xf):
if (x86_is_long_mode(env_cpu(env))) {
@@ -2111,14 +2114,14 @@ void init_decoder()
{
int i;
- for (i = 0; i < ARRAY_SIZE(_decode_tbl2); i++) {
- memcpy(_decode_tbl1, &invl_inst, sizeof(invl_inst));
+ for (i = 0; i < ARRAY_SIZE(_decode_tbl1); i++) {
+ memcpy(&_decode_tbl1[i], &invl_inst, sizeof(invl_inst));
}
for (i = 0; i < ARRAY_SIZE(_decode_tbl2); i++) {
- memcpy(_decode_tbl2, &invl_inst, sizeof(invl_inst));
+ memcpy(&_decode_tbl2[i], &invl_inst, sizeof(invl_inst));
}
for (i = 0; i < ARRAY_SIZE(_decode_tbl3); i++) {
- memcpy(_decode_tbl3, &invl_inst, sizeof(invl_inst_x87));
+ memcpy(&_decode_tbl3[i], &invl_inst_x87, sizeof(invl_inst_x87));
}
for (i = 0; i < ARRAY_SIZE(_1op_inst); i++) {
@@ -2167,22 +2170,22 @@ target_ulong decode_linear_addr(CPUX86State *env, struct x86_decode *decode,
target_ulong addr, X86Seg seg)
{
switch (decode->segment_override) {
- case PREFIX_CS_SEG_OVEERIDE:
+ case PREFIX_CS_SEG_OVERRIDE:
seg = R_CS;
break;
- case PREFIX_SS_SEG_OVEERIDE:
+ case PREFIX_SS_SEG_OVERRIDE:
seg = R_SS;
break;
- case PREFIX_DS_SEG_OVEERIDE:
+ case PREFIX_DS_SEG_OVERRIDE:
seg = R_DS;
break;
- case PREFIX_ES_SEG_OVEERIDE:
+ case PREFIX_ES_SEG_OVERRIDE:
seg = R_ES;
break;
- case PREFIX_FS_SEG_OVEERIDE:
+ case PREFIX_FS_SEG_OVERRIDE:
seg = R_FS;
break;
- case PREFIX_GS_SEG_OVEERIDE:
+ case PREFIX_GS_SEG_OVERRIDE:
seg = R_GS;
break;
default:
diff --git a/target/i386/hvf/x86_decode.h b/target/i386/hvf/x86_decode.h
index bc574a7a44..e50ae34adf 100644
--- a/target/i386/hvf/x86_decode.h
+++ b/target/i386/hvf/x86_decode.h
@@ -27,12 +27,12 @@ typedef enum x86_prefix {
PREFIX_REPN = 0xf2,
PREFIX_REP = 0xf3,
/* group 2 */
- PREFIX_CS_SEG_OVEERIDE = 0x2e,
- PREFIX_SS_SEG_OVEERIDE = 0x36,
- PREFIX_DS_SEG_OVEERIDE = 0x3e,
- PREFIX_ES_SEG_OVEERIDE = 0x26,
- PREFIX_FS_SEG_OVEERIDE = 0x64,
- PREFIX_GS_SEG_OVEERIDE = 0x65,
+ PREFIX_CS_SEG_OVERRIDE = 0x2e,
+ PREFIX_SS_SEG_OVERRIDE = 0x36,
+ PREFIX_DS_SEG_OVERRIDE = 0x3e,
+ PREFIX_ES_SEG_OVERRIDE = 0x26,
+ PREFIX_FS_SEG_OVERRIDE = 0x64,
+ PREFIX_GS_SEG_OVERRIDE = 0x65,
/* group 3 */
PREFIX_OP_SIZE_OVERRIDE = 0x66,
/* group 4 */
@@ -303,9 +303,9 @@ uint64_t sign(uint64_t val, int size);
uint32_t decode_instruction(CPUX86State *env, struct x86_decode *decode);
-target_ulong get_reg_ref(CPUX86State *env, int reg, int rex, int is_extended,
+target_ulong get_reg_ref(CPUX86State *env, int reg, int rex_present, int is_extended,
int size);
-target_ulong get_reg_val(CPUX86State *env, int reg, int rex, int is_extended,
+target_ulong get_reg_val(CPUX86State *env, int reg, int rex_present, int is_extended,
int size);
void calc_modrm_operand(CPUX86State *env, struct x86_decode *decode,
struct x86_decode_op *op);
--
2.24.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 4/5] hvf: more accurately match SDM when setting CR0 and PDPTE registers
2019-11-21 22:54 [PATCH 0/5] hvf: stability fixes for HVF Cameron Esfahani via
` (2 preceding siblings ...)
2019-11-21 22:54 ` [PATCH 3/5] hvf: correctly handle REX prefix in relation to legacy prefixes Cameron Esfahani via
@ 2019-11-21 22:54 ` Cameron Esfahani via
2019-11-21 22:54 ` [PATCH 5/5] hvf: save away type as well as vector so we can reinject them Cameron Esfahani via
` (2 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Cameron Esfahani via @ 2019-11-21 22:54 UTC (permalink / raw)
To: qemu-devel; +Cc: pbonzini
More accurately match SDM when setting CR0 and PDPTE registers.
Clear PDPTE registers when resetting vcpus.
Signed-off-by: Cameron Esfahani <dirty@apple.com>
---
target/i386/hvf/hvf.c | 8 ++++++++
target/i386/hvf/vmx.h | 18 ++++++++++--------
2 files changed, 18 insertions(+), 8 deletions(-)
diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c
index fda0273ba1..7f6ebd2e50 100644
--- a/target/i386/hvf/hvf.c
+++ b/target/i386/hvf/hvf.c
@@ -434,12 +434,20 @@ static MemoryListener hvf_memory_listener = {
};
void hvf_reset_vcpu(CPUState *cpu) {
+ uint64_t pdpte[4] = {0, 0, 0, 0};
+ int i;
/* TODO: this shouldn't be needed; there is already a call to
* cpu_synchronize_all_post_reset in vl.c
*/
wvmcs(cpu->hvf_fd, VMCS_ENTRY_CTLS, 0);
wvmcs(cpu->hvf_fd, VMCS_GUEST_IA32_EFER, 0);
+
+ /* Initialize PDPTE */
+ for (i = 0; i < 4; i++) {
+ wvmcs(cpu->hvf_fd, VMCS_GUEST_PDPTE0 + i * 2, pdpte[i]);
+ }
+
macvm_set_cr0(cpu->hvf_fd, 0x60000010);
wvmcs(cpu->hvf_fd, VMCS_CR4_MASK, CR4_VMXE_MASK);
diff --git a/target/i386/hvf/vmx.h b/target/i386/hvf/vmx.h
index 5dc52ecad6..eb8894cd58 100644
--- a/target/i386/hvf/vmx.h
+++ b/target/i386/hvf/vmx.h
@@ -121,6 +121,7 @@ static inline void macvm_set_cr0(hv_vcpuid_t vcpu, uint64_t cr0)
uint64_t pdpte[4] = {0, 0, 0, 0};
uint64_t efer = rvmcs(vcpu, VMCS_GUEST_IA32_EFER);
uint64_t old_cr0 = rvmcs(vcpu, VMCS_GUEST_CR0);
+ uint64_t mask = CR0_PG | CR0_CD | CR0_NW | CR0_NE | CR0_ET;
if ((cr0 & CR0_PG) && (rvmcs(vcpu, VMCS_GUEST_CR4) & CR4_PAE) &&
!(efer & MSR_EFER_LME)) {
@@ -128,18 +129,15 @@ static inline void macvm_set_cr0(hv_vcpuid_t vcpu, uint64_t cr0)
rvmcs(vcpu, VMCS_GUEST_CR3) & ~0x1f,
MEMTXATTRS_UNSPECIFIED,
(uint8_t *)pdpte, 32, 0);
+ /* Only set PDPTE when appropriate. */
+ for (i = 0; i < 4; i++) {
+ wvmcs(vcpu, VMCS_GUEST_PDPTE0 + i * 2, pdpte[i]);
+ }
}
- for (i = 0; i < 4; i++) {
- wvmcs(vcpu, VMCS_GUEST_PDPTE0 + i * 2, pdpte[i]);
- }
-
- wvmcs(vcpu, VMCS_CR0_MASK, CR0_CD | CR0_NE | CR0_PG);
+ wvmcs(vcpu, VMCS_CR0_MASK, mask);
wvmcs(vcpu, VMCS_CR0_SHADOW, cr0);
- cr0 &= ~CR0_CD;
- wvmcs(vcpu, VMCS_GUEST_CR0, cr0 | CR0_NE | CR0_ET);
-
if (efer & MSR_EFER_LME) {
if (!(old_cr0 & CR0_PG) && (cr0 & CR0_PG)) {
enter_long_mode(vcpu, cr0, efer);
@@ -149,6 +147,10 @@ static inline void macvm_set_cr0(hv_vcpuid_t vcpu, uint64_t cr0)
}
}
+ /* Filter new CR0 after we are finished examining it above. */
+ cr0 = (cr0 & ~(mask & ~CR0_PG));
+ wvmcs(vcpu, VMCS_GUEST_CR0, cr0 | CR0_NE | CR0_ET);
+
hv_vcpu_invalidate_tlb(vcpu);
hv_vcpu_flush(vcpu);
}
--
2.24.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 5/5] hvf: save away type as well as vector so we can reinject them
2019-11-21 22:54 [PATCH 0/5] hvf: stability fixes for HVF Cameron Esfahani via
` (3 preceding siblings ...)
2019-11-21 22:54 ` [PATCH 4/5] hvf: more accurately match SDM when setting CR0 and PDPTE registers Cameron Esfahani via
@ 2019-11-21 22:54 ` Cameron Esfahani via
2019-11-22 0:02 ` [PATCH 0/5] hvf: stability fixes for HVF no-reply
2019-11-24 12:17 ` Lukas Straub
6 siblings, 0 replies; 8+ messages in thread
From: Cameron Esfahani via @ 2019-11-21 22:54 UTC (permalink / raw)
To: qemu-devel; +Cc: pbonzini
Save away type as well as vector in hvf_store_events() so we can
correctly reinject both in hvf_inject_interrupts().
Make sure to clear ins_len and has_error_code when ins_len isn't
valid and error_code isn't set.
Signed-off-by: Cameron Esfahani <dirty@apple.com>
---
target/i386/hvf/hvf.c | 16 ++++++++++++----
target/i386/hvf/x86hvf.c | 22 ++++++++++------------
2 files changed, 22 insertions(+), 16 deletions(-)
diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c
index 7f6ebd2e50..818591ceee 100644
--- a/target/i386/hvf/hvf.c
+++ b/target/i386/hvf/hvf.c
@@ -634,14 +634,16 @@ static void hvf_store_events(CPUState *cpu, uint32_t ins_len, uint64_t idtvec_in
switch (idtvec_info & VMCS_IDT_VEC_TYPE) {
case VMCS_IDT_VEC_HWINTR:
case VMCS_IDT_VEC_SWINTR:
- env->interrupt_injected = idtvec_info & VMCS_IDT_VEC_VECNUM;
+ /* Save away the event type as well so we can inject the correct type. */
+ env->interrupt_injected = idtvec_info & (VMCS_IDT_VEC_TYPE | VMCS_IDT_VEC_VECNUM);
break;
case VMCS_IDT_VEC_NMI:
env->nmi_injected = true;
break;
case VMCS_IDT_VEC_HWEXCEPTION:
case VMCS_IDT_VEC_SWEXCEPTION:
- env->exception_nr = idtvec_info & VMCS_IDT_VEC_VECNUM;
+ /* Save away the event type as well so we can inject the correct type. */
+ env->exception_nr = idtvec_info & (VMCS_IDT_VEC_TYPE | VMCS_IDT_VEC_VECNUM);
env->exception_injected = 1;
break;
case VMCS_IDT_VEC_PRIV_SWEXCEPTION:
@@ -651,10 +653,16 @@ static void hvf_store_events(CPUState *cpu, uint32_t ins_len, uint64_t idtvec_in
if ((idtvec_info & VMCS_IDT_VEC_TYPE) == VMCS_IDT_VEC_SWEXCEPTION ||
(idtvec_info & VMCS_IDT_VEC_TYPE) == VMCS_IDT_VEC_SWINTR) {
env->ins_len = ins_len;
+ } else {
+ /* Make sure to clear ins_len when it isn't valid. */
+ env->ins_len = 0;
}
- if (idtvec_info & VMCS_INTR_DEL_ERRCODE) {
+ if (idtvec_info & VMCS_IDT_VEC_ERRCODE_VALID) {
env->has_error_code = true;
env->error_code = rvmcs(cpu->hvf_fd, VMCS_IDT_VECTORING_ERROR);
+ } else {
+ /* Make sure to clear has_error_code when error_code isn't valid. */
+ env->has_error_code = false;
}
}
if ((rvmcs(cpu->hvf_fd, VMCS_GUEST_INTERRUPTIBILITY) &
@@ -935,7 +943,7 @@ int hvf_vcpu_exec(CPUState *cpu)
macvm_set_rip(cpu, rip + ins_len);
break;
case VMX_REASON_VMCALL:
- env->exception_nr = EXCP0D_GPF;
+ env->exception_nr = VMCS_INTR_T_HWEXCEPTION | EXCP0D_GPF;
env->exception_injected = 1;
env->has_error_code = true;
env->error_code = 0;
diff --git a/target/i386/hvf/x86hvf.c b/target/i386/hvf/x86hvf.c
index 1485b95776..f9187cee3f 100644
--- a/target/i386/hvf/x86hvf.c
+++ b/target/i386/hvf/x86hvf.c
@@ -345,8 +345,6 @@ void vmx_clear_int_window_exiting(CPUState *cpu)
~VMCS_PRI_PROC_BASED_CTLS_INT_WINDOW_EXITING);
}
-#define NMI_VEC 2
-
bool hvf_inject_interrupts(CPUState *cpu_state)
{
X86CPU *x86cpu = X86_CPU(cpu_state);
@@ -356,17 +354,15 @@ bool hvf_inject_interrupts(CPUState *cpu_state)
uint64_t intr_type;
bool have_event = true;
if (env->interrupt_injected != -1) {
- vector = env->interrupt_injected;
- intr_type = VMCS_INTR_T_SWINTR;
+ /* Type and vector are both saved in interrupt_injected. */
+ vector = env->interrupt_injected & VMCS_IDT_VEC_VECNUM;
+ intr_type = env->interrupt_injected & VMCS_IDT_VEC_TYPE;
} else if (env->exception_nr != -1) {
- vector = env->exception_nr;
- if (vector == EXCP03_INT3 || vector == EXCP04_INTO) {
- intr_type = VMCS_INTR_T_SWEXCEPTION;
- } else {
- intr_type = VMCS_INTR_T_HWEXCEPTION;
- }
+ /* Type and vector are both saved in exception_nr. */
+ vector = env->exception_nr & VMCS_IDT_VEC_VECNUM;
+ intr_type = env->exception_nr & VMCS_IDT_VEC_TYPE;
} else if (env->nmi_injected) {
- vector = NMI_VEC;
+ vector = EXCP02_NMI;
intr_type = VMCS_INTR_T_NMI;
} else {
have_event = false;
@@ -390,6 +386,8 @@ bool hvf_inject_interrupts(CPUState *cpu_state)
if (env->has_error_code) {
wvmcs(cpu_state->hvf_fd, VMCS_ENTRY_EXCEPTION_ERROR,
env->error_code);
+ /* Make sure to indicate that VMCS_ENTRY_EXCEPTION_ERROR is valid */
+ info |= VMCS_INTR_DEL_ERRCODE;
}
/*printf("reinject %lx err %d\n", info, err);*/
wvmcs(cpu_state->hvf_fd, VMCS_ENTRY_INTR_INFO, info);
@@ -399,7 +397,7 @@ bool hvf_inject_interrupts(CPUState *cpu_state)
if (cpu_state->interrupt_request & CPU_INTERRUPT_NMI) {
if (!(env->hflags2 & HF2_NMI_MASK) && !(info & VMCS_INTR_VALID)) {
cpu_state->interrupt_request &= ~CPU_INTERRUPT_NMI;
- info = VMCS_INTR_VALID | VMCS_INTR_T_NMI | NMI_VEC;
+ info = VMCS_INTR_VALID | VMCS_INTR_T_NMI | EXCP02_NMI;
wvmcs(cpu_state->hvf_fd, VMCS_ENTRY_INTR_INFO, info);
} else {
vmx_set_nmi_window_exiting(cpu_state);
--
2.24.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH 0/5] hvf: stability fixes for HVF
2019-11-21 22:54 [PATCH 0/5] hvf: stability fixes for HVF Cameron Esfahani via
` (4 preceding siblings ...)
2019-11-21 22:54 ` [PATCH 5/5] hvf: save away type as well as vector so we can reinject them Cameron Esfahani via
@ 2019-11-22 0:02 ` no-reply
2019-11-24 12:17 ` Lukas Straub
6 siblings, 0 replies; 8+ messages in thread
From: no-reply @ 2019-11-22 0:02 UTC (permalink / raw)
To: qemu-devel; +Cc: pbonzini, qemu-devel
Patchew URL: https://patchew.org/QEMU/cover.1574375668.git.dirty@apple.com/
Hi,
This series seems to have some coding style problems. See output below for
more information:
Subject: [PATCH 0/5] hvf: stability fixes for HVF
Type: series
Message-id: cover.1574375668.git.dirty@apple.com
=== TEST SCRIPT BEGIN ===
#!/bin/bash
git rev-parse base > /dev/null || exit 0
git config --local diff.renamelimit 0
git config --local diff.renames True
git config --local diff.algorithm histogram
./scripts/checkpatch.pl --mailback base..
=== TEST SCRIPT END ===
Switched to a new branch 'test'
e1d1679 hvf: save away type as well as vector so we can reinject them
b201a1b hvf: more accurately match SDM when setting CR0 and PDPTE registers
995bd07 hvf: correctly handle REX prefix in relation to legacy prefixes
3ebb7cf hvf: remove TSC synchronization code because it isn't fully complete
5a99e4f hvf: non-RAM, non-ROMD memory ranges are now correctly mapped in
=== OUTPUT BEGIN ===
1/5 Checking commit 5a99e4fc4643 (hvf: non-RAM, non-ROMD memory ranges are now correctly mapped in)
WARNING: Block comments use a leading /* on a separate line
#72: FILE: target/i386/hvf/hvf.c:171:
+ /* If the memory device is not in romd_mode, then we actually want
WARNING: Block comments use a trailing */ on a separate line
#73: FILE: target/i386/hvf/hvf.c:172:
+ * to remove the hvf memory slot so all accesses will trap. */
ERROR: Error messages should not contain newlines
#92: FILE: target/i386/hvf/hvf.c:194:
+ error_report("Failed to reset overlapping slot\n");
WARNING: line over 80 characters
#100: FILE: target/i386/hvf/hvf.c:203:
+ if (area->readonly || (!memory_region_is_ram(area) && memory_region_is_romd(area)))
ERROR: braces {} are necessary for all arms of this statement
#100: FILE: target/i386/hvf/hvf.c:203:
+ if (area->readonly || (!memory_region_is_ram(area) && memory_region_is_romd(area)))
[...]
+ else
[...]
ERROR: Error messages should not contain newlines
#115: FILE: target/i386/hvf/hvf.c:229:
+ error_report("Error registering new memory slot\n");
ERROR: braces {} are necessary for all arms of this statement
#124: FILE: target/i386/hvf/hvf.c:357:
+ if (!slot)
[...]
ERROR: line over 90 characters
#126: FILE: target/i386/hvf/hvf.c:359:
+ if (!memory_region_is_ram(slot->region) && !(read && memory_region_is_romd(slot->region)))
ERROR: braces {} are necessary for all arms of this statement
#126: FILE: target/i386/hvf/hvf.c:359:
+ if (!memory_region_is_ram(slot->region) && !(read && memory_region_is_romd(slot->region)))
[...]
total: 6 errors, 3 warnings, 128 lines checked
Patch 1/5 has style problems, please review. If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
2/5 Checking commit 3ebb7cf4ab7f (hvf: remove TSC synchronization code because it isn't fully complete)
3/5 Checking commit 995bd07ed756 (hvf: correctly handle REX prefix in relation to legacy prefixes)
WARNING: line over 80 characters
#34: FILE: target/i386/hvf/x86_decode.c:1691:
+target_ulong get_reg_ref(CPUX86State *env, int reg, int rex_present, int is_extended,
WARNING: line over 80 characters
#65: FILE: target/i386/hvf/x86_decode.c:1715:
+target_ulong get_reg_val(CPUX86State *env, int reg, int rex_present, int is_extended,
WARNING: line over 80 characters
#70: FILE: target/i386/hvf/x86_decode.c:1719:
+ memcpy(&val, (void *)get_reg_ref(env, reg, rex_present, is_extended, size), size);
WARNING: line over 80 characters
#78: FILE: target/i386/hvf/x86_decode.c:1852:
+ /* REX prefix must come after legacy prefixes. REX before legacy is ignored.
WARNING: Block comments use a leading /* on a separate line
#78: FILE: target/i386/hvf/x86_decode.c:1852:
+ /* REX prefix must come after legacy prefixes. REX before legacy is ignored.
WARNING: Block comments use * on subsequent lines
#79: FILE: target/i386/hvf/x86_decode.c:1853:
+ /* REX prefix must come after legacy prefixes. REX before legacy is ignored.
+ Clear rex to simulate this. */
WARNING: Block comments use a trailing */ on a separate line
#79: FILE: target/i386/hvf/x86_decode.c:1853:
+ Clear rex to simulate this. */
WARNING: line over 80 characters
#192: FILE: target/i386/hvf/x86_decode.h:306:
+target_ulong get_reg_ref(CPUX86State *env, int reg, int rex_present, int is_extended,
WARNING: line over 80 characters
#195: FILE: target/i386/hvf/x86_decode.h:308:
+target_ulong get_reg_val(CPUX86State *env, int reg, int rex_present, int is_extended,
total: 0 errors, 9 warnings, 169 lines checked
Patch 3/5 has style problems, please review. If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
4/5 Checking commit b201a1b3b822 (hvf: more accurately match SDM when setting CR0 and PDPTE registers)
5/5 Checking commit e1d16795b97a (hvf: save away type as well as vector so we can reinject them)
WARNING: line over 80 characters
#25: FILE: target/i386/hvf/hvf.c:637:
+ /* Save away the event type as well so we can inject the correct type. */
ERROR: line over 90 characters
#26: FILE: target/i386/hvf/hvf.c:638:
+ env->interrupt_injected = idtvec_info & (VMCS_IDT_VEC_TYPE | VMCS_IDT_VEC_VECNUM);
WARNING: line over 80 characters
#34: FILE: target/i386/hvf/hvf.c:645:
+ /* Save away the event type as well so we can inject the correct type. */
WARNING: line over 80 characters
#35: FILE: target/i386/hvf/hvf.c:646:
+ env->exception_nr = idtvec_info & (VMCS_IDT_VEC_TYPE | VMCS_IDT_VEC_VECNUM);
WARNING: line over 80 characters
#108: FILE: target/i386/hvf/x86hvf.c:389:
+ /* Make sure to indicate that VMCS_ENTRY_EXCEPTION_ERROR is valid */
total: 1 errors, 4 warnings, 91 lines checked
Patch 5/5 has style problems, please review. If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
=== OUTPUT END ===
Test command exited with code: 1
The full log is available at
http://patchew.org/logs/cover.1574375668.git.dirty@apple.com/testing.checkpatch/?type=message.
---
Email generated automatically by Patchew [https://patchew.org/].
Please send your feedback to patchew-devel@redhat.com
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 0/5] hvf: stability fixes for HVF
2019-11-21 22:54 [PATCH 0/5] hvf: stability fixes for HVF Cameron Esfahani via
` (5 preceding siblings ...)
2019-11-22 0:02 ` [PATCH 0/5] hvf: stability fixes for HVF no-reply
@ 2019-11-24 12:17 ` Lukas Straub
6 siblings, 0 replies; 8+ messages in thread
From: Lukas Straub @ 2019-11-24 12:17 UTC (permalink / raw)
To: qemu-devel; +Cc: pbonzini, Cameron Esfahani
On Thu, 21 Nov 2019 14:54:49 -0800
Cameron Esfahani via <qemu-devel@nongnu.org> wrote:
> The following patches fix stability issues with running QEMU on Apple
> Hypervisor Framework (HVF):
> - non-RAM, non-ROMD areas need to trap so accesses can be correctly
> emulated.
> - Current TSC synchronization implementation is insufficient: when
> running with more than 1 core, TSC values can go backwards. Until
> a correct implementation can be written, remove calls to
> hv_vm_sync_tsc(). Pass through TSC to guest OS.
> - Fix REX emulation in relation to legacy prefixes.
> - More correctly match SDM when setting CR0 and PDPTE registers.
> - Save away exception type as well as vector in hvf_store_events() so
> they can be correctly reinjected in hvf_inject_interrupts(). Under
> heavy loads, exceptions got misrouted.
>
> Cameron Esfahani (5):
> hvf: non-RAM, non-ROMD memory ranges are now correctly mapped in
> hvf: remove TSC synchronization code because it isn't fully complete
> hvf: correctly handle REX prefix in relation to legacy prefixes
> hvf: more accurately match SDM when setting CR0 and PDPTE registers
> hvf: save away type as well as vector so we can reinject them
>
> target/i386/hvf/hvf.c | 74 +++++++++++++++++++++++++-----------
> target/i386/hvf/vmx.h | 18 +++++----
> target/i386/hvf/x86_decode.c | 55 ++++++++++++++-------------
> target/i386/hvf/x86_decode.h | 16 ++++----
> target/i386/hvf/x86_emu.c | 3 --
> target/i386/hvf/x86hvf.c | 26 +++++--------
> 6 files changed, 108 insertions(+), 84 deletions(-)
>
Hi,
I can't comment on your code, but simply resend this as v2 with the
checkpatch.pl errors fixed. You can run checkpatch.pl locally before
posting (scripts/checkpatch.pl).
Regards,
Lukas Straub
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2019-11-24 12:21 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2019-11-21 22:54 [PATCH 0/5] hvf: stability fixes for HVF Cameron Esfahani via
2019-11-21 22:54 ` [PATCH 1/5] hvf: non-RAM, non-ROMD memory ranges are now correctly mapped in Cameron Esfahani via
2019-11-21 22:54 ` [PATCH 2/5] hvf: remove TSC synchronization code because it isn't fully complete Cameron Esfahani via
2019-11-21 22:54 ` [PATCH 3/5] hvf: correctly handle REX prefix in relation to legacy prefixes Cameron Esfahani via
2019-11-21 22:54 ` [PATCH 4/5] hvf: more accurately match SDM when setting CR0 and PDPTE registers Cameron Esfahani via
2019-11-21 22:54 ` [PATCH 5/5] hvf: save away type as well as vector so we can reinject them Cameron Esfahani via
2019-11-22 0:02 ` [PATCH 0/5] hvf: stability fixes for HVF no-reply
2019-11-24 12:17 ` Lukas Straub
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).