Module Name: src
Committed By: maxv
Date: Wed Aug 26 16:32:03 UTC 2020
Modified Files:
src/sys/dev/nvmm/x86: nvmm_x86_svm.c nvmm_x86_vmx.c
Log Message:
nvmm-x86: improve the handling of RFLAGS.RF
- When injecting certain exceptions, set RF. For us to have an up-to-date
view of RFLAGS, we commit the state before the event.
- When advancing RIP, clear RF.
To generate a diff of this commit:
cvs rdiff -u -r1.72 -r1.73 src/sys/dev/nvmm/x86/nvmm_x86_svm.c
cvs rdiff -u -r1.73 -r1.74 src/sys/dev/nvmm/x86/nvmm_x86_vmx.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/dev/nvmm/x86/nvmm_x86_svm.c
diff -u src/sys/dev/nvmm/x86/nvmm_x86_svm.c:1.72 src/sys/dev/nvmm/x86/nvmm_x86_svm.c:1.73
--- src/sys/dev/nvmm/x86/nvmm_x86_svm.c:1.72 Wed Aug 26 16:29:19 2020
+++ src/sys/dev/nvmm/x86/nvmm_x86_svm.c Wed Aug 26 16:32:02 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: nvmm_x86_svm.c,v 1.72 2020/08/26 16:29:19 maxv Exp $ */
+/* $NetBSD: nvmm_x86_svm.c,v 1.73 2020/08/26 16:32:02 maxv Exp $ */
/*
* Copyright (c) 2018-2020 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nvmm_x86_svm.c,v 1.72 2020/08/26 16:29:19 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nvmm_x86_svm.c,v 1.73 2020/08/26 16:32:02 maxv Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -676,8 +676,22 @@ svm_event_waitexit_disable(struct nvmm_c
svm_vmcb_cache_flush(vmcb, VMCB_CTRL_VMCB_CLEAN_I);
}
+static inline bool
+svm_excp_has_rf(uint8_t vector)
+{
+ switch (vector) {
+ case 1: /* #DB */
+ case 4: /* #OF */
+ case 8: /* #DF */
+ case 18: /* #MC */
+ return false;
+ default:
+ return true;
+ }
+}
+
static inline int
-svm_event_has_error(uint8_t vector)
+svm_excp_has_error(uint8_t vector)
{
switch (vector) {
case 8: /* #DF */
@@ -717,7 +731,10 @@ svm_vcpu_inject(struct nvmm_cpu *vcpu)
return EINVAL;
if (vector == 3 || vector == 0)
return EINVAL;
- err = svm_event_has_error(vector);
+ if (svm_excp_has_rf(vector)) {
+ vmcb->state.rflags |= PSL_RF;
+ }
+ err = svm_excp_has_error(vector);
break;
case NVMM_VCPU_EVENT_INTR:
type = SVM_EVENT_TYPE_HW_INT;
@@ -790,6 +807,7 @@ svm_inkernel_advance(struct vmcb *vmcb)
* debugger.
*/
vmcb->state.rip = vmcb->ctrl.nrip;
+ vmcb->state.rflags &= ~PSL_RF;
vmcb->ctrl.intr &= ~VMCB_CTRL_INTR_SHADOW;
}
@@ -1473,11 +1491,12 @@ svm_vcpu_run(struct nvmm_machine *mach,
uint64_t machgen;
int hcpu;
+ svm_vcpu_state_commit(vcpu);
+ comm->state_cached = 0;
+
if (__predict_false(svm_vcpu_event_commit(vcpu) != 0)) {
return EINVAL;
}
- svm_vcpu_state_commit(vcpu);
- comm->state_cached = 0;
kpreempt_disable();
hcpu = cpu_number();
Index: src/sys/dev/nvmm/x86/nvmm_x86_vmx.c
diff -u src/sys/dev/nvmm/x86/nvmm_x86_vmx.c:1.73 src/sys/dev/nvmm/x86/nvmm_x86_vmx.c:1.74
--- src/sys/dev/nvmm/x86/nvmm_x86_vmx.c:1.73 Wed Aug 26 16:30:50 2020
+++ src/sys/dev/nvmm/x86/nvmm_x86_vmx.c Wed Aug 26 16:32:02 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: nvmm_x86_vmx.c,v 1.73 2020/08/26 16:30:50 maxv Exp $ */
+/* $NetBSD: nvmm_x86_vmx.c,v 1.74 2020/08/26 16:32:02 maxv Exp $ */
/*
* Copyright (c) 2018-2020 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nvmm_x86_vmx.c,v 1.73 2020/08/26 16:30:50 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nvmm_x86_vmx.c,v 1.74 2020/08/26 16:32:02 maxv Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -1038,8 +1038,22 @@ vmx_event_waitexit_disable(struct nvmm_c
vmx_vmwrite(VMCS_PROCBASED_CTLS, ctls1);
}
+static inline bool
+vmx_excp_has_rf(uint8_t vector)
+{
+ switch (vector) {
+ case 1: /* #DB */
+ case 4: /* #OF */
+ case 8: /* #DF */
+ case 18: /* #MC */
+ return false;
+ default:
+ return true;
+ }
+}
+
static inline int
-vmx_event_has_error(uint8_t vector)
+vmx_excp_has_error(uint8_t vector)
{
switch (vector) {
case 8: /* #DF */
@@ -1062,9 +1076,9 @@ vmx_vcpu_inject(struct nvmm_cpu *vcpu)
struct nvmm_comm_page *comm = vcpu->comm;
struct vmx_cpudata *cpudata = vcpu->cpudata;
int type = 0, err = 0, ret = EINVAL;
+ uint64_t rflags, info, error;
u_int evtype;
uint8_t vector;
- uint64_t info, error;
evtype = comm->event.type;
vector = comm->event.vector;
@@ -1079,8 +1093,12 @@ vmx_vcpu_inject(struct nvmm_cpu *vcpu)
goto out;
if (vector == 3 || vector == 0)
goto out;
+ if (vmx_excp_has_rf(vector)) {
+ rflags = vmx_vmread(VMCS_GUEST_RFLAGS);
+ vmx_vmwrite(VMCS_GUEST_RFLAGS, rflags | PSL_RF);
+ }
type = INTR_TYPE_HW_EXC;
- err = vmx_event_has_error(vector);
+ err = vmx_excp_has_error(vector);
break;
case NVMM_VCPU_EVENT_INTR:
type = INTR_TYPE_EXT_INT;
@@ -1151,16 +1169,21 @@ vmx_vcpu_event_commit(struct nvmm_cpu *v
static inline void
vmx_inkernel_advance(void)
{
- uint64_t rip, inslen, intstate;
+ uint64_t rip, inslen, intstate, rflags;
/*
* Maybe we should also apply single-stepping and debug exceptions.
* Matters for guest-ring3, because it can execute 'cpuid' under a
* debugger.
*/
+
inslen = vmx_vmread(VMCS_EXIT_INSTRUCTION_LENGTH);
rip = vmx_vmread(VMCS_GUEST_RIP);
vmx_vmwrite(VMCS_GUEST_RIP, rip + inslen);
+
+ rflags = vmx_vmread(VMCS_GUEST_RFLAGS);
+ vmx_vmwrite(VMCS_GUEST_RFLAGS, rflags & ~PSL_RF);
+
intstate = vmx_vmread(VMCS_GUEST_INTERRUPTIBILITY);
vmx_vmwrite(VMCS_GUEST_INTERRUPTIBILITY,
intstate & ~(INT_STATE_STI|INT_STATE_MOVSS));
@@ -2160,12 +2183,13 @@ vmx_vcpu_run(struct nvmm_machine *mach,
vmx_vmcs_enter(vcpu);
+ vmx_vcpu_state_commit(vcpu);
+ comm->state_cached = 0;
+
if (__predict_false(vmx_vcpu_event_commit(vcpu) != 0)) {
vmx_vmcs_leave(vcpu);
return EINVAL;
}
- vmx_vcpu_state_commit(vcpu);
- comm->state_cached = 0;
ci = curcpu();
hcpu = cpu_number();