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: Chenyi 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: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
f88d4f2f28
commit
9a3ecd5e2a
@ -203,9 +203,17 @@ enum x86_intercept_stage;
|
||||
#define DR6_BS (1 << 14)
|
||||
#define DR6_BT (1 << 15)
|
||||
#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_FIXED_1 (DR6_ACTIVE_LOW & ~DR6_VOLATILE)
|
||||
|
||||
#define DR7_BP_EN_MASK 0x000000ff
|
||||
#define DR7_GE (1 << 9)
|
||||
|
@ -4329,7 +4329,7 @@ static int check_dr_read(struct x86_emulate_ctxt *ctxt)
|
||||
|
||||
ctxt->ops->get_dr(ctxt, 6, &dr6);
|
||||
dr6 &= ~DR_TRAP_BITS;
|
||||
dr6 |= DR6_BD | DR6_RTM;
|
||||
dr6 |= DR6_BD | DR6_ACTIVE_LOW;
|
||||
ctxt->ops->set_dr(ctxt, 6, dr6);
|
||||
return emulate_db(ctxt);
|
||||
}
|
||||
|
@ -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.rip = vmcb12->save.rip;
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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[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.
|
||||
*/
|
||||
vcpu->arch.dr6 = svm->vmcb->save.dr6;
|
||||
@ -1916,7 +1916,7 @@ static int db_interception(struct vcpu_svm *svm)
|
||||
if (!(svm->vcpu.guest_debug &
|
||||
(KVM_GUESTDBG_SINGLESTEP | KVM_GUESTDBG_USE_HW_BP)) &&
|
||||
!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);
|
||||
return 1;
|
||||
}
|
||||
@ -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))
|
||||
svm_set_dr6(svm, vcpu->arch.dr6);
|
||||
else
|
||||
svm_set_dr6(svm, DR6_FIXED_1 | DR6_RTM);
|
||||
svm_set_dr6(svm, DR6_ACTIVE_LOW);
|
||||
|
||||
clgi();
|
||||
kvm_load_guest_xsave_state(vcpu);
|
||||
|
@ -411,8 +411,8 @@ static int nested_vmx_check_exception(struct kvm_vcpu *vcpu, unsigned long *exit
|
||||
if (nr == DB_VECTOR) {
|
||||
if (!has_payload) {
|
||||
payload = vcpu->arch.dr6;
|
||||
payload &= ~(DR6_FIXED_1 | DR6_BT);
|
||||
payload ^= DR6_RTM;
|
||||
payload &= ~DR6_BT;
|
||||
payload ^= DR6_ACTIVE_LOW;
|
||||
}
|
||||
*exit_qual = payload;
|
||||
} else
|
||||
|
@ -4876,7 +4876,7 @@ static int handle_exception_nmi(struct kvm_vcpu *vcpu)
|
||||
kvm_queue_exception_p(vcpu, DB_VECTOR, dr6);
|
||||
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);
|
||||
fallthrough;
|
||||
case BP_VECTOR:
|
||||
@ -5120,7 +5120,7 @@ static int handle_dr(struct kvm_vcpu *vcpu)
|
||||
* guest debugging itself.
|
||||
*/
|
||||
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.pc = kvm_get_linear_rip(vcpu);
|
||||
vcpu->run->debug.arch.exception = DB_VECTOR;
|
||||
|
@ -486,19 +486,24 @@ void kvm_deliver_exception_payload(struct kvm_vcpu *vcpu)
|
||||
*/
|
||||
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;
|
||||
/*
|
||||
* 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;
|
||||
vcpu->arch.dr6 ^= payload & DR6_ACTIVE_LOW;
|
||||
|
||||
/*
|
||||
* The #DB payload is defined as compatible with the 'pending
|
||||
@ -7211,7 +7216,7 @@ static int kvm_vcpu_do_singlestep(struct kvm_vcpu *vcpu)
|
||||
struct kvm_run *kvm_run = vcpu->run;
|
||||
|
||||
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.exception = DB_VECTOR;
|
||||
kvm_run->exit_reason = KVM_EXIT_DEBUG;
|
||||
@ -7255,7 +7260,7 @@ static bool kvm_vcpu_check_breakpoint(struct kvm_vcpu *vcpu, int *r)
|
||||
vcpu->arch.eff_db);
|
||||
|
||||
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.exception = DB_VECTOR;
|
||||
kvm_run->exit_reason = KVM_EXIT_DEBUG;
|
||||
@ -10118,7 +10123,7 @@ void kvm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
|
||||
|
||||
memset(vcpu->arch.db, 0, sizeof(vcpu->arch.db));
|
||||
kvm_update_dr0123(vcpu);
|
||||
vcpu->arch.dr6 = DR6_INIT;
|
||||
vcpu->arch.dr6 = DR6_ACTIVE_LOW;
|
||||
vcpu->arch.dr7 = DR7_FIXED_1;
|
||||
kvm_update_dr7(vcpu);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user