[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH 09/11] x86: Fix merging of new status bits into %dr6
The current logic used to update %dr6 when injecting #DB is buggy. The architectural behaviour is to overwrite B{0..3} (rather than accumulate) and accumulate all other bits. Introduce a new merge_dr6() helper, which also takes care of handing RTM correctly. Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx> --- CC: Jan Beulich <JBeulich@xxxxxxxx> CC: Wei Liu <wei.liu2@xxxxxxxxxx> CC: Roger Pau Monné <roger.pau@xxxxxxxxxx> CC: Jun Nakajima <jun.nakajima@xxxxxxxxx> CC: Kevin Tian <kevin.tian@xxxxxxxxx> CC: Boris Ostrovsky <boris.ostrovsky@xxxxxxxxxx> CC: Suravee Suthikulpanit <suravee.suthikulpanit@xxxxxxx> CC: Brian Woods <brian.woods@xxxxxxx> --- xen/arch/x86/hvm/svm/svm.c | 3 ++- xen/arch/x86/hvm/vmx/vmx.c | 3 ++- xen/arch/x86/pv/traps.c | 3 ++- xen/include/asm-x86/debugreg.h | 26 +++++++++++++++++++++++++- 4 files changed, 31 insertions(+), 4 deletions(-) diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c index df5f9ed..b1efa5e 100644 --- a/xen/arch/x86/hvm/svm/svm.c +++ b/xen/arch/x86/hvm/svm/svm.c @@ -1447,7 +1447,8 @@ static void svm_inject_event(const struct x86_event *event) * Item 2 is done by hardware when injecting a #DB exception. */ __restore_debug_registers(vmcb, curr); - vmcb_set_dr6(vmcb, vmcb_get_dr6(vmcb) | event->pending_dbg); + vmcb_set_dr6(vmcb, merge_dr6(vmcb_get_dr6(vmcb), event->pending_dbg, + curr->domain->arch.cpuid->feat.rtm)); /* fall through */ case TRAP_int3: diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c index f59ef88..82ef3aa 100644 --- a/xen/arch/x86/hvm/vmx/vmx.c +++ b/xen/arch/x86/hvm/vmx/vmx.c @@ -1791,7 +1791,8 @@ static void vmx_inject_event(const struct x86_event *event) * All actions are left up to the hypervisor to perform. */ __restore_debug_registers(curr); - write_debugreg(6, read_debugreg(6) | event->pending_dbg); + write_debugreg(6, merge_dr6(read_debugreg(6), event->pending_dbg, + curr->domain->arch.cpuid->feat.rtm)); if ( !nestedhvm_vcpu_in_guestmode(curr) || !nvmx_intercepts_exception(curr, TRAP_debug, _event.error_code) ) diff --git a/xen/arch/x86/pv/traps.c b/xen/arch/x86/pv/traps.c index 7d48d83..c2955ea 100644 --- a/xen/arch/x86/pv/traps.c +++ b/xen/arch/x86/pv/traps.c @@ -86,7 +86,8 @@ void pv_inject_event(const struct x86_event *event) break; case TRAP_debug: - curr->arch.dr6 |= event->pending_dbg; + curr->arch.dr6 = merge_dr6(curr->arch.dr6, event->pending_dbg, + curr->domain->arch.cpuid->feat.rtm); /* Fallthrough */ default: diff --git a/xen/include/asm-x86/debugreg.h b/xen/include/asm-x86/debugreg.h index 8df566b..f6b361e 100644 --- a/xen/include/asm-x86/debugreg.h +++ b/xen/include/asm-x86/debugreg.h @@ -23,6 +23,12 @@ #define X86_DR6_BT (1u << 15) /* Task switch */ #define X86_DR6_RTM (1u << 16) /* #DB/#BP in RTM region */ +#define X86_DR6_BP_MASK \ + (X86_DR6_B0 | X86_DR6_B1 | X86_DR6_B2 | X86_DR6_B3) + +#define X86_DR6_KNOWN_MASK \ + (X86_DR6_BP_MASK | X86_DR6_BD | X86_DR6_BS | X86_DR6_BT | X86_DR6_RTM) + #define DR_TRAP0 (0x1) /* db0 */ #define DR_TRAP1 (0x2) /* db1 */ #define DR_TRAP2 (0x4) /* db2 */ @@ -30,7 +36,6 @@ #define DR_STEP (0x4000) /* single-step */ #define DR_SWITCH (0x8000) /* task switch */ #define DR_NOT_RTM (0x10000) /* clear: #BP inside RTM region */ -#define DR_STATUS_RESERVED_ONE 0xffff0ff0ul /* Reserved, read as one */ #define X86_DR6_DEFAULT 0xffff0ff0ul /* Default %dr6 value. */ @@ -103,6 +108,25 @@ static inline unsigned long adjust_dr6_rsvd(unsigned long dr6, bool rtm) return dr6; } +static inline unsigned long merge_dr6(unsigned long dr6, unsigned long new, + bool rtm) +{ + /* Flip dr6 to have positive polarity. */ + dr6 ^= X86_DR6_DEFAULT; + + /* Sanity check that only known values are passed in. */ + ASSERT(!(dr6 & ~X86_DR6_KNOWN_MASK)); + ASSERT(!(new & ~X86_DR6_KNOWN_MASK)); + + /* Breakpoints 0-3 overridden. BD, BS, BT and RTM accumulate. */ + dr6 = (dr6 & ~X86_DR6_BP_MASK) | new; + + /* Flip dr6 back to having default polarity. */ + dr6 ^= X86_DR6_DEFAULT; + + return adjust_dr6_rsvd(dr6, rtm); +} + static inline unsigned long adjust_dr7_rsvd(unsigned long dr7, bool rtm) { /* -- 2.1.4 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/mailman/listinfo/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |