Commit 9a3ecd5e authored by Chenyi Qiang's avatar Chenyi Qiang Committed by Paolo Bonzini

KVM: X86: Rename DR6_INIT to DR6_ACTIVE_LOW

DR6_INIT contains the 1-reserved bits as well as the bit that is cleared
to 0 when the condition (e.g. RTM) happens. The value can be used to
initialize dr6 and also be the XOR mask between the #DB exit
qualification (or payload) and DR6.

Concerning that DR6_INIT is used as initial value only once, rename it
to DR6_ACTIVE_LOW and apply it in other places, which would make the
incoming changes for bus lock debug exception more simple.
Signed-off-by: default avatarChenyi Qiang <chenyi.qiang@intel.com>
Message-Id: <20210202090433.13441-2-chenyi.qiang@intel.com>
[Define DR6_FIXED_1 from DR6_ACTIVE_LOW and DR6_VOLATILE. - Paolo]
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent f88d4f2f
...@@ -203,9 +203,17 @@ enum x86_intercept_stage; ...@@ -203,9 +203,17 @@ enum x86_intercept_stage;
#define DR6_BS (1 << 14) #define DR6_BS (1 << 14)
#define DR6_BT (1 << 15) #define DR6_BT (1 << 15)
#define DR6_RTM (1 << 16) #define DR6_RTM (1 << 16)
#define DR6_FIXED_1 0xfffe0ff0 /*
#define DR6_INIT 0xffff0ff0 * DR6_ACTIVE_LOW combines fixed-1 and active-low bits.
* We can regard all the bits in DR6_FIXED_1 as active_low bits;
* they will never be 0 for now, but when they are defined
* in the future it will require no code change.
*
* DR6_ACTIVE_LOW is also used as the init/reset value for DR6.
*/
#define DR6_ACTIVE_LOW 0xffff0ff0
#define DR6_VOLATILE 0x0001e00f #define DR6_VOLATILE 0x0001e00f
#define DR6_FIXED_1 (DR6_ACTIVE_LOW & ~DR6_VOLATILE)
#define DR7_BP_EN_MASK 0x000000ff #define DR7_BP_EN_MASK 0x000000ff
#define DR7_GE (1 << 9) #define DR7_GE (1 << 9)
......
...@@ -4329,7 +4329,7 @@ static int check_dr_read(struct x86_emulate_ctxt *ctxt) ...@@ -4329,7 +4329,7 @@ static int check_dr_read(struct x86_emulate_ctxt *ctxt)
ctxt->ops->get_dr(ctxt, 6, &dr6); ctxt->ops->get_dr(ctxt, 6, &dr6);
dr6 &= ~DR_TRAP_BITS; dr6 &= ~DR_TRAP_BITS;
dr6 |= DR6_BD | DR6_RTM; dr6 |= DR6_BD | DR6_ACTIVE_LOW;
ctxt->ops->set_dr(ctxt, 6, dr6); ctxt->ops->set_dr(ctxt, 6, dr6);
return emulate_db(ctxt); return emulate_db(ctxt);
} }
......
...@@ -392,7 +392,7 @@ static void nested_prepare_vmcb_save(struct vcpu_svm *svm, struct vmcb *vmcb12) ...@@ -392,7 +392,7 @@ static void nested_prepare_vmcb_save(struct vcpu_svm *svm, struct vmcb *vmcb12)
svm->vmcb->save.rsp = vmcb12->save.rsp; svm->vmcb->save.rsp = vmcb12->save.rsp;
svm->vmcb->save.rip = vmcb12->save.rip; svm->vmcb->save.rip = vmcb12->save.rip;
svm->vmcb->save.dr7 = vmcb12->save.dr7 | DR7_FIXED_1; svm->vmcb->save.dr7 = vmcb12->save.dr7 | DR7_FIXED_1;
svm->vcpu.arch.dr6 = vmcb12->save.dr6 | DR6_FIXED_1 | DR6_RTM; svm->vcpu.arch.dr6 = vmcb12->save.dr6 | DR6_ACTIVE_LOW;
svm->vmcb->save.cpl = vmcb12->save.cpl; svm->vmcb->save.cpl = vmcb12->save.cpl;
} }
......
...@@ -1865,7 +1865,7 @@ static void svm_sync_dirty_debug_regs(struct kvm_vcpu *vcpu) ...@@ -1865,7 +1865,7 @@ static void svm_sync_dirty_debug_regs(struct kvm_vcpu *vcpu)
get_debugreg(vcpu->arch.db[2], 2); get_debugreg(vcpu->arch.db[2], 2);
get_debugreg(vcpu->arch.db[3], 3); get_debugreg(vcpu->arch.db[3], 3);
/* /*
* We cannot reset svm->vmcb->save.dr6 to DR6_FIXED_1|DR6_RTM here, * We cannot reset svm->vmcb->save.dr6 to DR6_ACTIVE_LOW here,
* because db_interception might need it. We can do it before vmentry. * because db_interception might need it. We can do it before vmentry.
*/ */
vcpu->arch.dr6 = svm->vmcb->save.dr6; vcpu->arch.dr6 = svm->vmcb->save.dr6;
...@@ -1916,7 +1916,7 @@ static int db_interception(struct vcpu_svm *svm) ...@@ -1916,7 +1916,7 @@ static int db_interception(struct vcpu_svm *svm)
if (!(svm->vcpu.guest_debug & if (!(svm->vcpu.guest_debug &
(KVM_GUESTDBG_SINGLESTEP | KVM_GUESTDBG_USE_HW_BP)) && (KVM_GUESTDBG_SINGLESTEP | KVM_GUESTDBG_USE_HW_BP)) &&
!svm->nmi_singlestep) { !svm->nmi_singlestep) {
u32 payload = (svm->vmcb->save.dr6 ^ DR6_RTM) & ~DR6_FIXED_1; u32 payload = svm->vmcb->save.dr6 ^ DR6_ACTIVE_LOW;
kvm_queue_exception_p(&svm->vcpu, DB_VECTOR, payload); kvm_queue_exception_p(&svm->vcpu, DB_VECTOR, payload);
return 1; return 1;
} }
...@@ -3783,7 +3783,7 @@ static __no_kcsan fastpath_t svm_vcpu_run(struct kvm_vcpu *vcpu) ...@@ -3783,7 +3783,7 @@ static __no_kcsan fastpath_t svm_vcpu_run(struct kvm_vcpu *vcpu)
if (unlikely(svm->vcpu.arch.switch_db_regs & KVM_DEBUGREG_WONT_EXIT)) if (unlikely(svm->vcpu.arch.switch_db_regs & KVM_DEBUGREG_WONT_EXIT))
svm_set_dr6(svm, vcpu->arch.dr6); svm_set_dr6(svm, vcpu->arch.dr6);
else else
svm_set_dr6(svm, DR6_FIXED_1 | DR6_RTM); svm_set_dr6(svm, DR6_ACTIVE_LOW);
clgi(); clgi();
kvm_load_guest_xsave_state(vcpu); kvm_load_guest_xsave_state(vcpu);
......
...@@ -411,8 +411,8 @@ static int nested_vmx_check_exception(struct kvm_vcpu *vcpu, unsigned long *exit ...@@ -411,8 +411,8 @@ static int nested_vmx_check_exception(struct kvm_vcpu *vcpu, unsigned long *exit
if (nr == DB_VECTOR) { if (nr == DB_VECTOR) {
if (!has_payload) { if (!has_payload) {
payload = vcpu->arch.dr6; payload = vcpu->arch.dr6;
payload &= ~(DR6_FIXED_1 | DR6_BT); payload &= ~DR6_BT;
payload ^= DR6_RTM; payload ^= DR6_ACTIVE_LOW;
} }
*exit_qual = payload; *exit_qual = payload;
} else } else
......
...@@ -4876,7 +4876,7 @@ static int handle_exception_nmi(struct kvm_vcpu *vcpu) ...@@ -4876,7 +4876,7 @@ static int handle_exception_nmi(struct kvm_vcpu *vcpu)
kvm_queue_exception_p(vcpu, DB_VECTOR, dr6); kvm_queue_exception_p(vcpu, DB_VECTOR, dr6);
return 1; return 1;
} }
kvm_run->debug.arch.dr6 = dr6 | DR6_FIXED_1 | DR6_RTM; kvm_run->debug.arch.dr6 = dr6 | DR6_ACTIVE_LOW;
kvm_run->debug.arch.dr7 = vmcs_readl(GUEST_DR7); kvm_run->debug.arch.dr7 = vmcs_readl(GUEST_DR7);
fallthrough; fallthrough;
case BP_VECTOR: case BP_VECTOR:
...@@ -5120,7 +5120,7 @@ static int handle_dr(struct kvm_vcpu *vcpu) ...@@ -5120,7 +5120,7 @@ static int handle_dr(struct kvm_vcpu *vcpu)
* guest debugging itself. * guest debugging itself.
*/ */
if (vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP) { if (vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP) {
vcpu->run->debug.arch.dr6 = DR6_BD | DR6_RTM | DR6_FIXED_1; vcpu->run->debug.arch.dr6 = DR6_BD | DR6_ACTIVE_LOW;
vcpu->run->debug.arch.dr7 = dr7; vcpu->run->debug.arch.dr7 = dr7;
vcpu->run->debug.arch.pc = kvm_get_linear_rip(vcpu); vcpu->run->debug.arch.pc = kvm_get_linear_rip(vcpu);
vcpu->run->debug.arch.exception = DB_VECTOR; vcpu->run->debug.arch.exception = DB_VECTOR;
......
...@@ -486,19 +486,24 @@ void kvm_deliver_exception_payload(struct kvm_vcpu *vcpu) ...@@ -486,19 +486,24 @@ void kvm_deliver_exception_payload(struct kvm_vcpu *vcpu)
*/ */
vcpu->arch.dr6 &= ~DR_TRAP_BITS; vcpu->arch.dr6 &= ~DR_TRAP_BITS;
/* /*
* DR6.RTM is set by all #DB exceptions that don't clear it. * In order to reflect the #DB exception payload in guest
* dr6, three components need to be considered: active low
* bit, FIXED_1 bits and active high bits (e.g. DR6_BD,
* DR6_BS and DR6_BT)
* DR6_ACTIVE_LOW contains the FIXED_1 and active low bits.
* In the target guest dr6:
* FIXED_1 bits should always be set.
* Active low bits should be cleared if 1-setting in payload.
* Active high bits should be set if 1-setting in payload.
*
* Note, the payload is compatible with the pending debug
* exceptions/exit qualification under VMX, that active_low bits
* are active high in payload.
* So they need to be flipped for DR6.
*/ */
vcpu->arch.dr6 |= DR6_RTM; vcpu->arch.dr6 |= DR6_ACTIVE_LOW;
vcpu->arch.dr6 |= payload; vcpu->arch.dr6 |= payload;
/* vcpu->arch.dr6 ^= payload & DR6_ACTIVE_LOW;
* Bit 16 should be set in the payload whenever the #DB
* exception should clear DR6.RTM. This makes the payload
* compatible with the pending debug exceptions under VMX.
* Though not currently documented in the SDM, this also
* makes the payload compatible with the exit qualification
* for #DB exceptions under VMX.
*/
vcpu->arch.dr6 ^= payload & DR6_RTM;
/* /*
* The #DB payload is defined as compatible with the 'pending * The #DB payload is defined as compatible with the 'pending
...@@ -7211,7 +7216,7 @@ static int kvm_vcpu_do_singlestep(struct kvm_vcpu *vcpu) ...@@ -7211,7 +7216,7 @@ static int kvm_vcpu_do_singlestep(struct kvm_vcpu *vcpu)
struct kvm_run *kvm_run = vcpu->run; struct kvm_run *kvm_run = vcpu->run;
if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP) { if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP) {
kvm_run->debug.arch.dr6 = DR6_BS | DR6_FIXED_1 | DR6_RTM; kvm_run->debug.arch.dr6 = DR6_BS | DR6_ACTIVE_LOW;
kvm_run->debug.arch.pc = kvm_get_linear_rip(vcpu); kvm_run->debug.arch.pc = kvm_get_linear_rip(vcpu);
kvm_run->debug.arch.exception = DB_VECTOR; kvm_run->debug.arch.exception = DB_VECTOR;
kvm_run->exit_reason = KVM_EXIT_DEBUG; kvm_run->exit_reason = KVM_EXIT_DEBUG;
...@@ -7255,7 +7260,7 @@ static bool kvm_vcpu_check_breakpoint(struct kvm_vcpu *vcpu, int *r) ...@@ -7255,7 +7260,7 @@ static bool kvm_vcpu_check_breakpoint(struct kvm_vcpu *vcpu, int *r)
vcpu->arch.eff_db); vcpu->arch.eff_db);
if (dr6 != 0) { if (dr6 != 0) {
kvm_run->debug.arch.dr6 = dr6 | DR6_FIXED_1 | DR6_RTM; kvm_run->debug.arch.dr6 = dr6 | DR6_ACTIVE_LOW;
kvm_run->debug.arch.pc = eip; kvm_run->debug.arch.pc = eip;
kvm_run->debug.arch.exception = DB_VECTOR; kvm_run->debug.arch.exception = DB_VECTOR;
kvm_run->exit_reason = KVM_EXIT_DEBUG; kvm_run->exit_reason = KVM_EXIT_DEBUG;
...@@ -10118,7 +10123,7 @@ void kvm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event) ...@@ -10118,7 +10123,7 @@ void kvm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
memset(vcpu->arch.db, 0, sizeof(vcpu->arch.db)); memset(vcpu->arch.db, 0, sizeof(vcpu->arch.db));
kvm_update_dr0123(vcpu); kvm_update_dr0123(vcpu);
vcpu->arch.dr6 = DR6_INIT; vcpu->arch.dr6 = DR6_ACTIVE_LOW;
vcpu->arch.dr7 = DR7_FIXED_1; vcpu->arch.dr7 = DR7_FIXED_1;
kvm_update_dr7(vcpu); kvm_update_dr7(vcpu);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment