Received: by 2002:a05:6a10:8c0a:0:0:0:0 with SMTP id go10csp1317422pxb; Thu, 28 Jan 2021 13:18:44 -0800 (PST) X-Google-Smtp-Source: ABdhPJz62P3LV/MQ1oWGmz6Zp+JfnGk4qR3L5wHhZdmuRhDT4rtCyOwpDMmp2dXshqULoa3VLtUm X-Received: by 2002:a17:906:828a:: with SMTP id h10mr1432387ejx.274.1611868723829; Thu, 28 Jan 2021 13:18:43 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1611868723; cv=none; d=google.com; s=arc-20160816; b=B71Z4/W3WM5Y403TPCXME9qLfR3S3QQLCzjFvYjHR0PEzzCIid829Q0hwIOK6R15z+ NCq0bxjeotLJ5fGmdFhEJL87XL3eW/lCzETu+agBy+yvPryFN1RAxt8TFMzFP1YOFP6P 4uYXdurkPTWEX5ObJBiLFw65uDiBoqPtfzQBdHullw7us3S8VsGGi3Pa8GBz6653BOfb haDuZ6hZ5r5bV+YPcqqS+pcAoKHDgCGF6u9bm7YZjhX+1Ju52uJBDOYl6UwpF67fYZv3 5bf1N5aMM4/CzyDfK7qFy1CF/yMbDOpGTSjBR0koTmA5wruVPVMRUdA8RUPOKX1y4AzL 6CuQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:in-reply-to:content-disposition:mime-version :references:message-id:subject:cc:to:from:date:dkim-signature; bh=vFXdrprJYXLFSPP8UE1ua7upEFkQkB4P+OBl0fVN1/w=; b=P/fDn4Wxt5EnNcvecejsjScAXLVPCNHTFthW6NzOD5HYj4+RE9d1QTtrbZrVUMCion 0Mvb0I9sCi/CVPNMh8iEXMl8uZZ2NrRmV8YC703tOhQpQFm2jAbbrGq3k6UwmfaPtZwo 6jE/s4OVZX0a3IJP43vQXqxhHobUhKCmDtHX0ecxwBybcfaDWnOUIwXVaaGWN4SGXI/y EJSRpZ96HAQ4946ffWwNGw8G/16GTUIz8HNcKvn6TRqyb8pDp6sL+C7a0Zi2GhN7tSFR Vah/AJD7wmPOGaIYwVMji4qGmehszzWngyolGhuEBlWv8Z6tnVBkjE15vE4mLrGYM718 uawQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@infradead.org header.s=casper.20170209 header.b=ZWuUotXO; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id l17si3114379ejq.589.2021.01.28.13.18.19; Thu, 28 Jan 2021 13:18:43 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@infradead.org header.s=casper.20170209 header.b=ZWuUotXO; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231301AbhA1VRd (ORCPT + 99 others); Thu, 28 Jan 2021 16:17:33 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45918 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231339AbhA1VR1 (ORCPT ); Thu, 28 Jan 2021 16:17:27 -0500 Received: from casper.infradead.org (casper.infradead.org [IPv6:2001:8b0:10b:1236::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B18A4C061573 for ; Thu, 28 Jan 2021 13:16:47 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=casper.20170209; h=In-Reply-To:Content-Type:MIME-Version: References:Message-ID:Subject:Cc:To:From:Date:Sender:Reply-To: Content-Transfer-Encoding:Content-ID:Content-Description; bh=vFXdrprJYXLFSPP8UE1ua7upEFkQkB4P+OBl0fVN1/w=; b=ZWuUotXO8UZSCJ6GuCbVCNcbho zI3CCKZPFNJBK0yVdakT5lVAnp0ywyNSTXtWQPXfcdxfNHiU+NABEMVn7hKt+E+yZEPcYjcet5tts O3GDoSP47nuYMZ2i/B9d6Fg+6n+12RUrEnnevNpzW4/EfgUZIj3+2c5ol6djuFFCXlAopmmEYmhGc FkamGzDhVwHdVpOpmnt/e+niMVlqu1MIktl/Q/AuS5I3Xo9yMNPg2jjDk+Rg86XcOg+E++2XTrBYf GQWlJqoKGEscsbQOGhEkcxWfbiY5Khf5IuKOivRgBUPy91VLUpycbP9xCMg715YUskW/zVqvlFFuO ETNL8USQ==; Received: from j217100.upc-j.chello.nl ([24.132.217.100] helo=worktop.programming.kicks-ass.net) by casper.infradead.org with esmtpsa (Exim 4.94 #2 (Red Hat Linux)) id 1l5EeU-008zZK-GN; Thu, 28 Jan 2021 21:16:31 +0000 Received: by worktop.programming.kicks-ass.net (Postfix, from userid 1000) id 6B650986584; Thu, 28 Jan 2021 22:16:27 +0100 (CET) Date: Thu, 28 Jan 2021 22:16:27 +0100 From: Peter Zijlstra To: x86@kernel.org, tdevries@suse.de Cc: linux-kernel@vger.kernel.org, andrew.cooper3@citrix.com, Frederic Weisbecker Subject: [PATCH v2] x86/debug: Fix DR6 handling Message-ID: <20210128211627.GB4348@worktop.programming.kicks-ass.net> References: MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Tom reported that one of the GDB test-cases failed, and Boris bisected it to commit: d53d9bc0cf78 ("x86/debug: Change thread.debugreg6 to thread.virtual_dr6") The debugging session led us to commit: 6c0aca288e72 ("x86: Ignore trap bits on single step exceptions") It turns out that TF and data breakpoints are both traps and will be merged, while instruction breakpoints are faults and will not be merged. This means 6c0aca288e72 is wrong, we only need to exclude TF and instruction breakpoints while we can merge TF and data breakpoints. Fixes: d53d9bc0cf78 ("x86/debug: Change thread.debugreg6 to thread.virtual_dr6") Fixes: 6c0aca288e72 ("x86: Ignore trap bits on single step exceptions") Reported-by: Tom de Vries Bisected-by: Borislav Petkov Signed-off-by: Peter Zijlstra (Intel) --- arch/x86/kernel/hw_breakpoint.c | 39 ++++++++++++++++++--------------------- 1 file changed, 18 insertions(+), 21 deletions(-) --- a/arch/x86/kernel/hw_breakpoint.c +++ b/arch/x86/kernel/hw_breakpoint.c @@ -491,15 +491,12 @@ static int hw_breakpoint_handler(struct struct perf_event *bp; unsigned long *dr6_p; unsigned long dr6; + bool bpx; /* The DR6 value is pointed by args->err */ dr6_p = (unsigned long *)ERR_PTR(args->err); dr6 = *dr6_p; - /* If it's a single step, TRAP bits are random */ - if (dr6 & DR_STEP) - return NOTIFY_DONE; - /* Do an early return if no trap bits are set in DR6 */ if ((dr6 & DR_TRAP_BITS) == 0) return NOTIFY_DONE; @@ -509,28 +506,29 @@ static int hw_breakpoint_handler(struct if (likely(!(dr6 & (DR_TRAP0 << i)))) continue; + bp = this_cpu_read(bp_per_reg[i]); + if (!bp) + continue; + + bpx = bp->hw.info.type == X86_BREAKPOINT_EXECUTE; + /* - * The counter may be concurrently released but that can only - * occur from a call_rcu() path. We can then safely fetch - * the breakpoint, use its callback, touch its counter - * while we are in an rcu_read_lock() path. + * TF and data breakpoints are traps and can be merged, however + * instruction breakpoints are faults and will be raised + * separately. + * + * However DR6 can indicate both TF and instruction + * breakpoints. In that case take TF as that has precedence and + * delay the instruction breakpoint for the next exception. */ - rcu_read_lock(); + if (bpx && (dr6 & DR_STEP)) + continue; - bp = this_cpu_read(bp_per_reg[i]); /* * Reset the 'i'th TRAP bit in dr6 to denote completion of * exception handling */ (*dr6_p) &= ~(DR_TRAP0 << i); - /* - * bp can be NULL due to lazy debug register switching - * or due to concurrent perf counter removing. - */ - if (!bp) { - rcu_read_unlock(); - break; - } perf_bp_event(bp, args->regs); @@ -538,11 +536,10 @@ static int hw_breakpoint_handler(struct * Set up resume flag to avoid breakpoint recursion when * returning back to origin. */ - if (bp->hw.info.type == X86_BREAKPOINT_EXECUTE) + if (bpx) args->regs->flags |= X86_EFLAGS_RF; - - rcu_read_unlock(); } + /* * Further processing in do_debug() is needed for a) user-space * breakpoints (to generate signals) and b) when the system has