From nobody Sat Jul 25 01:34:42 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.16]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1C5C33AE187; Tue, 21 Jul 2026 06:32:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.16 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784615538; cv=none; b=eFHSDv63GRlKcJqip2AbUc/opR1tfIG2d3TrzcFD3ZNeTCUp9cyzmXQekeIw7dZ839GG4fZB/07QHYCtNAvZAP9iQSLLQGtYl8wbqLdBuuj8+C+1hAKZjC4Fw6LP/omd3yec+nE2XXCBXh6luT8cFiMEETcg8c4H1zZIX5+P1Mg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784615538; c=relaxed/simple; bh=8cpKhrCK9gw82VF0FFxZYauT4DDIOkEo40eB+1f6qpo=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=RXMJSmGDBLoYHpSZYDxNASllI6R9arxzmI4N7AHyTuW5F8cGuo7lVo66rxXpZ00V1oGSfqEMerxoN7Xt4s4+w3HlBnHSaZNnTr2TUNQ4HiK+gR0lqv66qW+ebaEpBSrWyb1XRHa5jZ1zNSGjED3cVHRWtD9NBPNzqgGA+PbNP4w= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=pass smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=UswFzRvA; arc=none smtp.client-ip=192.198.163.16 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="UswFzRvA" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1784615536; x=1816151536; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=8cpKhrCK9gw82VF0FFxZYauT4DDIOkEo40eB+1f6qpo=; b=UswFzRvAp+VATwYJ+5mLTw6xRWCMcBZpnVF9vSi5VpcfRku/+CquiH4N du+5K/Qc+pkfV4t+0hjZhGFVHO75RHtj0N4CqY8YT+G2WJeAh+xTOi0TW yJ2qiH3J+YDlZcTymGWaygPT/Eo4ZGGkQ+E/PPCk1YIxMDdYGOh+pj55E V/0TFy67FNA0P5VbXQ5t7Ge0I8RFAPuDT9TDw0Z6nwU3RxSXDZHkDk1EL E7s1p0oSFJUvU+NL9VMDIKdMCMQDfxg6kxXiplp1iwl5Y7HD38+FgGIPx WyJG7LcOFFpeE6OGw+4kZbanEe7I+NmEA8i/rQoWR/nbu2WOev8jaPJpk A==; X-CSE-ConnectionGUID: gAhrw5+zTWuyb9kuMJJzNA== X-CSE-MsgGUID: DswhrpQEQaiRlPU0M1wjBg== X-IronPort-AV: E=McAfee;i="6800,10657,11852"; a="72740264" X-IronPort-AV: E=Sophos;i="6.25,176,1779174000"; d="scan'208";a="72740264" Received: from fmviesa004.fm.intel.com ([10.60.135.144]) by fmvoesa110.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Jul 2026 23:32:16 -0700 X-CSE-ConnectionGUID: fPDG/F9USCumxgOt9CCiOQ== X-CSE-MsgGUID: Z4AlacV9SrGIiYjKWCAihg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.25,176,1779174000"; d="scan'208";a="259655650" Received: from spr.sh.intel.com ([10.112.229.196]) by fmviesa004.fm.intel.com with ESMTP; 20 Jul 2026 23:32:09 -0700 From: Dapeng Mi To: Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Thomas Gleixner , Dave Hansen , Ian Rogers , Adrian Hunter , Jiri Olsa , Alexander Shishkin , Andi Kleen , Eranian Stephane Cc: Mark Rutland , broonie@kernel.org, Ravi Bangoria , linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org, Zide Chen , Falcon Thomas , Dapeng Mi , Xudong Hao , Dapeng Mi Subject: [Patch v10 01/23] perf/x86: Move hybrid PMU initialization before x86_pmu_starting_cpu() Date: Tue, 21 Jul 2026 14:24:44 +0800 Message-Id: <20260721062506.3745816-2-dapeng1.mi@linux.intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260721062506.3745816-1-dapeng1.mi@linux.intel.com> References: <20260721062506.3745816-1-dapeng1.mi@linux.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The current approach initializes hybrid PMU structures immediately before registering them. This is risky as it can lead to key fields, such as 'capabilities', being inadvertently overwritten. Although no issues have arisen so far, this method is not ideal. It makes the PMU structure fields susceptible to being overwritten, especially with future changes that might initialize fields like 'capabilities' within init_hybrid_pmu() called by x86_pmu_starting_cpu(). To mitigate this potential problem, move the default hybrid structure initialization before calling x86_pmu_starting_cpu(). Signed-off-by: Dapeng Mi --- arch/x86/events/core.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c index 8b3ea0adb965..75358a297222 100644 --- a/arch/x86/events/core.c +++ b/arch/x86/events/core.c @@ -2218,8 +2218,20 @@ static int __init init_hw_perf_events(void) =20 pmu.attr_update =3D x86_pmu.attr_update; =20 - if (!is_hybrid()) + if (!is_hybrid()) { x86_pmu_show_pmu_cap(NULL); + } else { + int i; + + /* + * Init default ops. + * Must be called before registering x86_pmu_starting_cpu(), + * otherwise some key PMU fields, e.g., capabilities + * initialized in x86_pmu_starting_cpu(), would be overwritten. + */ + for (i =3D 0; i < x86_pmu.num_hybrid_pmus; i++) + x86_pmu.hybrid_pmu[i].pmu =3D pmu; + } =20 if (!x86_pmu.read) x86_pmu.read =3D _x86_pmu_read; @@ -2266,7 +2278,6 @@ static int __init init_hw_perf_events(void) for (i =3D 0; i < x86_pmu.num_hybrid_pmus; i++) { hybrid_pmu =3D &x86_pmu.hybrid_pmu[i]; =20 - hybrid_pmu->pmu =3D pmu; hybrid_pmu->pmu.type =3D -1; hybrid_pmu->pmu.attr_update =3D x86_pmu.attr_update; hybrid_pmu->pmu.capabilities |=3D PERF_PMU_CAP_EXTENDED_HW_TYPE; --=20 2.34.1 From nobody Sat Jul 25 01:34:42 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.16]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4CCA3419FD4; Tue, 21 Jul 2026 06:32:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.16 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784615542; cv=none; b=Pjgv56c0ohHQlrKAZh062p7zzS4oxV1ed7HeoAySk6TuVFwJcXv7qw3KfnpEvgIeSJWfqxEtGGRE+mCwAuNNKFlZD59kYvv3dIYiH+JO8gmTrYIMALs01mLVvuOPtx+oaO/3C7mNjxyo3bMgtsFnx10vLETXVflKuYHEbvPQimY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784615542; c=relaxed/simple; bh=0lNT5yftw18dwlrvi6a8udt0a8PlwqGLOszwsYa/RJs=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=FIedStFG3Q4M+fgD14siANYYtSl1kQ2nBaI94ygLQCGw5nRPHG7bzXoJlSOxpcb0Jc4lE1SrnH+bRdBwb4Yw+3qnXfs+FPkEdusqftjJpnoul5LTuiyQyG+Oah06J4l326W1F6hhwbRWQ38dbKr2M068BrRMWWyZzV9/dJiR6jg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=pass smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=DLJ7SiJe; arc=none smtp.client-ip=192.198.163.16 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="DLJ7SiJe" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1784615541; x=1816151541; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=0lNT5yftw18dwlrvi6a8udt0a8PlwqGLOszwsYa/RJs=; b=DLJ7SiJePezV4fldTHmrwE2ObA9/ZtV01NKVVhGAcpXk0WK5Gvu/z2cM CERBAyoy+aX1ru4wybFyLlIc3CpdOWw51XrGcPTdG0kiT8AFR7SQWR2hW SX+deuSFp8D14CCFIsd1bI96/5rLCEZIo4cGVrNNvITHnRPgbuambY6Hd 6LA4YNcgeprfLtR/1qBEtrGG3YoejI8dMTZF8hbXLFUkVcg5GyPgrJutj z+L5wsoN1bxKbhjekE9TtsQ+cvRh8fxGzFkTw4TLdWdl9w6p7ZppQkWu7 IWjebp7O3fPxt5UvwpQoskwlpoqWUpU9NZsMN8ABkPaUNTb35UlqTxV7A w==; X-CSE-ConnectionGUID: 7zaPV/cMQKGQ0QNtsQd6lw== X-CSE-MsgGUID: t1ppfp3/QrOPKNOwczdIew== X-IronPort-AV: E=McAfee;i="6800,10657,11852"; a="72740273" X-IronPort-AV: E=Sophos;i="6.25,176,1779174000"; d="scan'208";a="72740273" Received: from fmviesa004.fm.intel.com ([10.60.135.144]) by fmvoesa110.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Jul 2026 23:32:21 -0700 X-CSE-ConnectionGUID: 1AVDdOQcTfS7z3fh8DQSNw== X-CSE-MsgGUID: P5DIj1ZUSAe1vae0mFQyYQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.25,176,1779174000"; d="scan'208";a="259655710" Received: from spr.sh.intel.com ([10.112.229.196]) by fmviesa004.fm.intel.com with ESMTP; 20 Jul 2026 23:32:16 -0700 From: Dapeng Mi To: Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Thomas Gleixner , Dave Hansen , Ian Rogers , Adrian Hunter , Jiri Olsa , Alexander Shishkin , Andi Kleen , Eranian Stephane Cc: Mark Rutland , broonie@kernel.org, Ravi Bangoria , linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org, Zide Chen , Falcon Thomas , Dapeng Mi , Xudong Hao , Dapeng Mi Subject: [Patch v10 02/23] perf/x86/intel: Enable large PEBS sampling for XMMs Date: Tue, 21 Jul 2026 14:24:45 +0800 Message-Id: <20260721062506.3745816-3-dapeng1.mi@linux.intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260721062506.3745816-1-dapeng1.mi@linux.intel.com> References: <20260721062506.3745816-1-dapeng1.mi@linux.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Modern PEBS hardware supports directly sampling XMM registers, then large PEBS can be enabled for XMM registers just like other GPRs. Reported-by: Xudong Hao Signed-off-by: Dapeng Mi --- arch/x86/events/intel/core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c index 726b39b9bba9..ee62b24d3fdf 100644 --- a/arch/x86/events/intel/core.c +++ b/arch/x86/events/intel/core.c @@ -4723,7 +4723,8 @@ static unsigned long intel_pmu_large_pebs_flags(struc= t perf_event *event) flags &=3D ~PERF_SAMPLE_REGS_USER; if (event->attr.sample_regs_user & ~PEBS_GP_REGS) flags &=3D ~PERF_SAMPLE_REGS_USER; - if (event->attr.sample_regs_intr & ~PEBS_GP_REGS) + if (event->attr.sample_regs_intr & + ~(PEBS_GP_REGS | PERF_REG_EXTENDED_MASK)) flags &=3D ~PERF_SAMPLE_REGS_INTR; return flags; } --=20 2.34.1 From nobody Sat Jul 25 01:34:42 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.16]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AAB113EDE7C; Tue, 21 Jul 2026 06:32:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.16 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784615548; cv=none; b=YxvXf55cCjnbWeCHE7FYVMqxvXRqdizHov/ZqmwTCNkDNXltsYi8TYgyrTmfVvoh15Km9KTVrI0rZ0uV5nQScykvqKa87pYOkNU7aFEuQ3BH4DW3Wsk/7eZL6sz24Lqo4h/BOHZ+SKe6ts8y7jUVoXQUhErfN69HnZIOgE4Sns8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784615548; c=relaxed/simple; bh=YbHRkkn496VMoLY29m74DxK+lyVy8p8q0O68g31Nauw=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=XBtYJV2Y0FzFDS74OP9UY/oOYzantFBzy3YhTsLy/ji7+EpemRWjtSXi5tZfQbJm+gJwX1BLo3xobCn1SFPg6y04bxADY2B6eupJZiVckzH4tWjUYu5p/PvydkjqgKPems9NjNekOiw+BWy5n1RRPmjzhYqZqjqaRO1euSVfPgY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=pass smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=PcelUWRe; arc=none smtp.client-ip=192.198.163.16 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="PcelUWRe" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1784615547; x=1816151547; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=YbHRkkn496VMoLY29m74DxK+lyVy8p8q0O68g31Nauw=; b=PcelUWReZgRXFxWSUky9bGar/gpo/N0AnONvO487axPGtJ5dA7gv2dDr d97rE1PBJnEuroTku7gn9Cx2VVyAiI9yDFA0TkzVB5wAqNcEKg/aBexwM c2AofC7ZnlJF5B7z3r1lD7iIhEnOzPD8+b7fMTguoqfn94zRqAkWJd8aw 3VFtqwDWlHoGAd03fGHrBqg0h0i2/dsdLV31kp/JQ/j5K2jydVUYWBp+o 4Os8ewyxQlSAkIB3G1Er2IaPnOq8VSGbkdDK2Ad+cu4kyY0D18Dup0TYc vrnlyx3pcx7htUtbruJihQDMDEEHC07sm9MFKyum4Kdhzx9cHHOwOFbMM g==; X-CSE-ConnectionGUID: DtHd44+iTfqBJvOV6d/FtA== X-CSE-MsgGUID: 6zuIrgn9T9GQvLvDzi+dCQ== X-IronPort-AV: E=McAfee;i="6800,10657,11852"; a="72740282" X-IronPort-AV: E=Sophos;i="6.25,176,1779174000"; d="scan'208";a="72740282" Received: from fmviesa004.fm.intel.com ([10.60.135.144]) by fmvoesa110.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Jul 2026 23:32:26 -0700 X-CSE-ConnectionGUID: oGrO48dBRhOZU4fEEK6W6Q== X-CSE-MsgGUID: b0sSWx9fStKiCuqGiL1Jrg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.25,176,1779174000"; d="scan'208";a="259655781" Received: from spr.sh.intel.com ([10.112.229.196]) by fmviesa004.fm.intel.com with ESMTP; 20 Jul 2026 23:32:21 -0700 From: Dapeng Mi To: Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Thomas Gleixner , Dave Hansen , Ian Rogers , Adrian Hunter , Jiri Olsa , Alexander Shishkin , Andi Kleen , Eranian Stephane Cc: Mark Rutland , broonie@kernel.org, Ravi Bangoria , linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org, Zide Chen , Falcon Thomas , Dapeng Mi , Xudong Hao , Dapeng Mi Subject: [Patch v10 03/23] perf/x86/intel: Convert x86_perf_regs to per-cpu variables Date: Tue, 21 Jul 2026 14:24:46 +0800 Message-Id: <20260721062506.3745816-4-dapeng1.mi@linux.intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260721062506.3745816-1-dapeng1.mi@linux.intel.com> References: <20260721062506.3745816-1-dapeng1.mi@linux.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Currently, the drain_pebs() helpers, e.g., intel_pmu_drain_arch_pebs() define an on-stack x86_perf_regs. Upcoming patches will add new fields like *ymm_regs and *zmm_regs to the x86_perf_regs structure to support sampling for these SIMD registers. This would increase the stack size consumed by these helpers, potentially triggering the warning: "the frame size of 1048 bytes is larger than 1024 bytes [-Wframe-larger-than=3D]". To eliminate this warning, convert x86_perf_regs to per-cpu variables. Please note drain_pebs() can't be interrupted by other NMIs since either it's already in NMI context or PMU is already disabled. Signed-off-by: Dapeng Mi --- arch/x86/events/intel/ds.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/arch/x86/events/intel/ds.c b/arch/x86/events/intel/ds.c index 7f8b98d1837d..9355744a9258 100644 --- a/arch/x86/events/intel/ds.c +++ b/arch/x86/events/intel/ds.c @@ -2910,6 +2910,8 @@ __intel_pmu_pebs_last_event(struct perf_event *event, } } =20 +static DEFINE_PER_CPU(struct x86_perf_regs, x86_pebs_regs); + static __always_inline void __intel_pmu_pebs_events(struct perf_event *event, struct pt_regs *iregs, @@ -2919,8 +2921,8 @@ __intel_pmu_pebs_events(struct perf_event *event, setup_fn setup_sample) { struct cpu_hw_events *cpuc =3D this_cpu_ptr(&cpu_hw_events); - struct x86_perf_regs perf_regs; - struct pt_regs *regs =3D &perf_regs.regs; + struct x86_perf_regs *perf_regs =3D this_cpu_ptr(&x86_pebs_regs); + struct pt_regs *regs =3D &perf_regs->regs; void *at =3D get_next_pebs_record_by_bit(base, top, bit); int cnt =3D count; =20 @@ -3168,8 +3170,8 @@ static void intel_pmu_drain_pebs_icl(struct pt_regs *= iregs, struct perf_sample_d void *last[INTEL_PMC_IDX_FIXED + MAX_FIXED_PEBS_EVENTS]; struct cpu_hw_events *cpuc =3D this_cpu_ptr(&cpu_hw_events); struct debug_store *ds =3D cpuc->ds; - struct x86_perf_regs perf_regs; - struct pt_regs *regs =3D &perf_regs.regs; + struct x86_perf_regs *perf_regs =3D this_cpu_ptr(&x86_pebs_regs); + struct pt_regs *regs =3D &perf_regs->regs; struct pebs_basic *basic; void *base, *at, *top; u64 mask; @@ -3219,8 +3221,8 @@ static void intel_pmu_drain_arch_pebs(struct pt_regs = *iregs, void *last[INTEL_PMC_IDX_FIXED + MAX_FIXED_PEBS_EVENTS]; struct cpu_hw_events *cpuc =3D this_cpu_ptr(&cpu_hw_events); union arch_pebs_index index; - struct x86_perf_regs perf_regs; - struct pt_regs *regs =3D &perf_regs.regs; + struct x86_perf_regs *perf_regs =3D this_cpu_ptr(&x86_pebs_regs); + struct pt_regs *regs =3D &perf_regs->regs; void *base, *at, *top; u64 mask; =20 --=20 2.34.1 From nobody Sat Jul 25 01:34:42 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.16]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 55A7F413D62; Tue, 21 Jul 2026 06:32:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.16 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784615554; cv=none; b=JXk8ZA4NM1x9DBEN6PXh1CNwkAe384Xp0FK5nX2xRs68fa86a10p5FgvQDLThcdBbtnIb5j4fpvHwDDnTCYnOsZ2mRJY9IkIK7v1Kbzk3z0cVI+ismHtENFxdvOtDXmbASGzBH0GV2kb+rPdVXPadoG+akYwT7L9xvwWP88yOL0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784615554; c=relaxed/simple; bh=ODdCfcnf+PcxO/VMXKuOJemzmwCTDoWQpoXLxo0Y3Gs=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=UzlY7ZLKD4i3EofVUPeKRF9uwLCJu2nD8dWhvR4CMNJRJ127NrY3bhFNkxwOHkGWZsnnqUB5rpuAL+DWaUBE5lrFYZoV2KUf1JBNgkuUJ5UD0aLEqlF1wBbqizDN2HZ/h2UO0fP15tdmea6M88f6zQmDeycuKrQx766SSKBlBxA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=pass smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=m7NtoA+f; arc=none smtp.client-ip=192.198.163.16 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="m7NtoA+f" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1784615552; x=1816151552; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=ODdCfcnf+PcxO/VMXKuOJemzmwCTDoWQpoXLxo0Y3Gs=; b=m7NtoA+fcAjVjoda8ZxYND5LhpvofmQJZ/5mQ7zG65AxTk3KqclCbRc4 AcIlvgQ2oE+968AfUFHnUjkHcebVUgEIPEhd5Txy3fdwtRM14tHRQaIRe mVwK9IGhL1jJrTuniXVGNSY+QI1w8DYt8MIOaKjr+6zuWXgLbdO69/PLw HCfnO/F5SI490NQgV7ZMHAfF4Z3GywSvQr8q5iHWFCwwQA3XBJDTNqFBi aYQVM9qQMzFCrEsnY8M/qyAFu6ElYr3AwnD17Vjfc0VI/vhAjhjB4lemf uv7HeLbFh0yVbfiPsIGCd/FMIRzyFn6Y6oOjpKLtOFPlUi8pSQ5QzzE5o w==; X-CSE-ConnectionGUID: WYNjm25GThyVT5nArw2OnA== X-CSE-MsgGUID: zAljDoPOSmqbAjNgOnx2Jg== X-IronPort-AV: E=McAfee;i="6800,10657,11852"; a="72740295" X-IronPort-AV: E=Sophos;i="6.25,176,1779174000"; d="scan'208";a="72740295" Received: from fmviesa004.fm.intel.com ([10.60.135.144]) by fmvoesa110.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Jul 2026 23:32:32 -0700 X-CSE-ConnectionGUID: J7zmDqUbSJirG4Ul8EcQYA== X-CSE-MsgGUID: G5XYwOX5QYCLqnPSMsVnPg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.25,176,1779174000"; d="scan'208";a="259655842" Received: from spr.sh.intel.com ([10.112.229.196]) by fmviesa004.fm.intel.com with ESMTP; 20 Jul 2026 23:32:27 -0700 From: Dapeng Mi To: Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Thomas Gleixner , Dave Hansen , Ian Rogers , Adrian Hunter , Jiri Olsa , Alexander Shishkin , Andi Kleen , Eranian Stephane Cc: Mark Rutland , broonie@kernel.org, Ravi Bangoria , linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org, Zide Chen , Falcon Thomas , Dapeng Mi , Xudong Hao , Dapeng Mi Subject: [Patch v10 04/23] perf: Eliminate duplicate arch-specific function definitions Date: Tue, 21 Jul 2026 14:24:47 +0800 Message-Id: <20260721062506.3745816-5-dapeng1.mi@linux.intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260721062506.3745816-1-dapeng1.mi@linux.intel.com> References: <20260721062506.3745816-1-dapeng1.mi@linux.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Define default common __weak functions for perf_reg_value(), perf_reg_validate(), perf_reg_abi() and perf_get_regs_user(). This helps to eliminate the duplicated arch-specific definitions. No function changes intended. Signed-off-by: Dapeng Mi --- arch/arm/kernel/perf_regs.c | 6 ------ arch/arm64/kernel/perf_regs.c | 6 ------ arch/csky/kernel/perf_regs.c | 6 ------ arch/loongarch/kernel/perf_regs.c | 6 ------ arch/mips/kernel/perf_regs.c | 6 ------ arch/parisc/kernel/perf_regs.c | 6 ------ arch/riscv/kernel/perf_regs.c | 6 ------ arch/x86/kernel/perf_regs.c | 6 ------ include/linux/perf_regs.h | 32 ++++++------------------------- kernel/events/core.c | 22 +++++++++++++++++++++ 10 files changed, 28 insertions(+), 74 deletions(-) diff --git a/arch/arm/kernel/perf_regs.c b/arch/arm/kernel/perf_regs.c index 0529f90395c9..d575a4c3ca56 100644 --- a/arch/arm/kernel/perf_regs.c +++ b/arch/arm/kernel/perf_regs.c @@ -31,9 +31,3 @@ u64 perf_reg_abi(struct task_struct *task) return PERF_SAMPLE_REGS_ABI_32; } =20 -void perf_get_regs_user(struct perf_regs *regs_user, - struct pt_regs *regs) -{ - regs_user->regs =3D task_pt_regs(current); - regs_user->abi =3D perf_reg_abi(current); -} diff --git a/arch/arm64/kernel/perf_regs.c b/arch/arm64/kernel/perf_regs.c index b4eece3eb17d..70e2f13f587f 100644 --- a/arch/arm64/kernel/perf_regs.c +++ b/arch/arm64/kernel/perf_regs.c @@ -98,9 +98,3 @@ u64 perf_reg_abi(struct task_struct *task) return PERF_SAMPLE_REGS_ABI_64; } =20 -void perf_get_regs_user(struct perf_regs *regs_user, - struct pt_regs *regs) -{ - regs_user->regs =3D task_pt_regs(current); - regs_user->abi =3D perf_reg_abi(current); -} diff --git a/arch/csky/kernel/perf_regs.c b/arch/csky/kernel/perf_regs.c index 09b7f88a2d6a..94601f37b596 100644 --- a/arch/csky/kernel/perf_regs.c +++ b/arch/csky/kernel/perf_regs.c @@ -31,9 +31,3 @@ u64 perf_reg_abi(struct task_struct *task) return PERF_SAMPLE_REGS_ABI_32; } =20 -void perf_get_regs_user(struct perf_regs *regs_user, - struct pt_regs *regs) -{ - regs_user->regs =3D task_pt_regs(current); - regs_user->abi =3D perf_reg_abi(current); -} diff --git a/arch/loongarch/kernel/perf_regs.c b/arch/loongarch/kernel/perf= _regs.c index 263ac4ab5af6..8dd604f01745 100644 --- a/arch/loongarch/kernel/perf_regs.c +++ b/arch/loongarch/kernel/perf_regs.c @@ -45,9 +45,3 @@ u64 perf_reg_value(struct pt_regs *regs, int idx) return regs->regs[idx]; } =20 -void perf_get_regs_user(struct perf_regs *regs_user, - struct pt_regs *regs) -{ - regs_user->regs =3D task_pt_regs(current); - regs_user->abi =3D perf_reg_abi(current); -} diff --git a/arch/mips/kernel/perf_regs.c b/arch/mips/kernel/perf_regs.c index e686780d1647..7736d3c5ebd2 100644 --- a/arch/mips/kernel/perf_regs.c +++ b/arch/mips/kernel/perf_regs.c @@ -60,9 +60,3 @@ u64 perf_reg_value(struct pt_regs *regs, int idx) return (s64)v; /* Sign extend if 32-bit. */ } =20 -void perf_get_regs_user(struct perf_regs *regs_user, - struct pt_regs *regs) -{ - regs_user->regs =3D task_pt_regs(current); - regs_user->abi =3D perf_reg_abi(current); -} diff --git a/arch/parisc/kernel/perf_regs.c b/arch/parisc/kernel/perf_regs.c index 10a1a5f06a18..b9fe1f2fcb9b 100644 --- a/arch/parisc/kernel/perf_regs.c +++ b/arch/parisc/kernel/perf_regs.c @@ -53,9 +53,3 @@ u64 perf_reg_abi(struct task_struct *task) return PERF_SAMPLE_REGS_ABI_64; } =20 -void perf_get_regs_user(struct perf_regs *regs_user, - struct pt_regs *regs) -{ - regs_user->regs =3D task_pt_regs(current); - regs_user->abi =3D perf_reg_abi(current); -} diff --git a/arch/riscv/kernel/perf_regs.c b/arch/riscv/kernel/perf_regs.c index fd304a248de6..3bba8deababb 100644 --- a/arch/riscv/kernel/perf_regs.c +++ b/arch/riscv/kernel/perf_regs.c @@ -35,9 +35,3 @@ u64 perf_reg_abi(struct task_struct *task) #endif } =20 -void perf_get_regs_user(struct perf_regs *regs_user, - struct pt_regs *regs) -{ - regs_user->regs =3D task_pt_regs(current); - regs_user->abi =3D perf_reg_abi(current); -} diff --git a/arch/x86/kernel/perf_regs.c b/arch/x86/kernel/perf_regs.c index 624703af80a1..81204cb7f723 100644 --- a/arch/x86/kernel/perf_regs.c +++ b/arch/x86/kernel/perf_regs.c @@ -100,12 +100,6 @@ u64 perf_reg_abi(struct task_struct *task) return PERF_SAMPLE_REGS_ABI_32; } =20 -void perf_get_regs_user(struct perf_regs *regs_user, - struct pt_regs *regs) -{ - regs_user->regs =3D task_pt_regs(current); - regs_user->abi =3D perf_reg_abi(current); -} #else /* CONFIG_X86_64 */ #define REG_NOSUPPORT ((1ULL << PERF_REG_X86_DS) | \ (1ULL << PERF_REG_X86_ES) | \ diff --git a/include/linux/perf_regs.h b/include/linux/perf_regs.h index f632c5725f16..144bcc3ff19f 100644 --- a/include/linux/perf_regs.h +++ b/include/linux/perf_regs.h @@ -9,6 +9,12 @@ struct perf_regs { struct pt_regs *regs; }; =20 +u64 perf_reg_value(struct pt_regs *regs, int idx); +int perf_reg_validate(u64 mask); +u64 perf_reg_abi(struct task_struct *task); +void perf_get_regs_user(struct perf_regs *regs_user, + struct pt_regs *regs); + #ifdef CONFIG_HAVE_PERF_REGS #include =20 @@ -16,35 +22,9 @@ struct perf_regs { #define PERF_REG_EXTENDED_MASK 0 #endif =20 -u64 perf_reg_value(struct pt_regs *regs, int idx); -int perf_reg_validate(u64 mask); -u64 perf_reg_abi(struct task_struct *task); -void perf_get_regs_user(struct perf_regs *regs_user, - struct pt_regs *regs); #else =20 #define PERF_REG_EXTENDED_MASK 0 =20 -static inline u64 perf_reg_value(struct pt_regs *regs, int idx) -{ - return 0; -} - -static inline int perf_reg_validate(u64 mask) -{ - return mask ? -ENOSYS : 0; -} - -static inline u64 perf_reg_abi(struct task_struct *task) -{ - return PERF_SAMPLE_REGS_ABI_NONE; -} - -static inline void perf_get_regs_user(struct perf_regs *regs_user, - struct pt_regs *regs) -{ - regs_user->regs =3D task_pt_regs(current); - regs_user->abi =3D perf_reg_abi(current); -} #endif /* CONFIG_HAVE_PERF_REGS */ #endif /* _LINUX_PERF_REGS_H */ diff --git a/kernel/events/core.c b/kernel/events/core.c index b282de3e7d7c..770c4b1330c7 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -7807,6 +7807,28 @@ unsigned long perf_instruction_pointer(struct perf_e= vent *event, 0 : perf_arch_instruction_pointer(regs); } =20 +u64 __weak perf_reg_value(struct pt_regs *regs, int idx) +{ + return 0; +} + +int __weak perf_reg_validate(u64 mask) +{ + return mask ? -ENOSYS : 0; +} + +u64 __weak perf_reg_abi(struct task_struct *task) +{ + return PERF_SAMPLE_REGS_ABI_NONE; +} + +void __weak perf_get_regs_user(struct perf_regs *regs_user, + struct pt_regs *regs) +{ + regs_user->regs =3D task_pt_regs(current); + regs_user->abi =3D perf_reg_abi(current); +} + static void perf_output_sample_regs(struct perf_output_handle *handle, struct pt_regs *regs, u64 mask) --=20 2.34.1 From nobody Sat Jul 25 01:34:42 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.16]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DB5F73A874B; Tue, 21 Jul 2026 06:32:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.16 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784615561; cv=none; b=JhJcmZUV0l7O1pn53xbL1WlgYj+O4I8JmYEkXh7NJ6GMW6rEb3gUpccV7F0wSypDvgBGkrVqj6EUnqBkqX+ehDh872V1Lyoy9yM4IAbK5CDaaL0ARJEfEDCj7HSSSaCqIZ2glsZiUZGyaVz+OWbiylkjE5dzb4OLbEURc82rJxo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784615561; c=relaxed/simple; bh=sm5pwEFZcPUk1k9wG+3OIN8I0e2VwsfYDE+wjRlQikM=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=s5tQGxBOMxNnrbJmMAEbZbP8BR61wSRO1xkEYp8ZK8xoaezqWa43N7FY6aP7Mcvf6g/GHMg7+3/5oypKve2kMyQ0sED/rfuhKNVWE1/f5qoOirzSqDizoHoE32Xv2dGg1Kj/W+/69uK3khYeaX1JOENKZrNEri1v1RWCRrf1qeU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=pass smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=Adj/oicr; arc=none smtp.client-ip=192.198.163.16 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="Adj/oicr" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1784615560; x=1816151560; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=sm5pwEFZcPUk1k9wG+3OIN8I0e2VwsfYDE+wjRlQikM=; b=Adj/oicrmjEyaucvRxyEz1CvR+zYNLOUxMbKqm9nRSrjlfesMJVsDbRn mH+3CJ984ZWHBsHoMjNBFGjFEfKimBk/Xa0OTHBA9/WoSz/tGImH3p/bO +rGg3X2LHKTDsy0ekI3G2LarqP5R26CKe84DBLNM8GtCkOTsaloGcLFUM dxilt8YHbdcKh9cmDljqsx3AZ/ZtFf7i6Qdffb+IjacpYupDDBqkgwNZC 6FSF6Nv1ya3LLnORUfGn3pJWLPRTIs/ELM1GOiYb7CNV9dUCQyAG1kn/L pwnntKdP3fMKWu6nl2bZxJ90UGU8BcJyvklvbTGF9WiCiZOq8QD2U2kCD Q==; X-CSE-ConnectionGUID: vAi4xxPiSXOxuQDXHLtwBA== X-CSE-MsgGUID: EEQhXll4Suiya3GHqucDUA== X-IronPort-AV: E=McAfee;i="6800,10657,11852"; a="72740309" X-IronPort-AV: E=Sophos;i="6.25,176,1779174000"; d="scan'208";a="72740309" Received: from fmviesa004.fm.intel.com ([10.60.135.144]) by fmvoesa110.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Jul 2026 23:32:39 -0700 X-CSE-ConnectionGUID: ajwo34vwT/6syPZmXv6Obw== X-CSE-MsgGUID: OjXDzINUSe+XUqJU+dMY6g== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.25,176,1779174000"; d="scan'208";a="259655911" Received: from spr.sh.intel.com ([10.112.229.196]) by fmviesa004.fm.intel.com with ESMTP; 20 Jul 2026 23:32:32 -0700 From: Dapeng Mi To: Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Thomas Gleixner , Dave Hansen , Ian Rogers , Adrian Hunter , Jiri Olsa , Alexander Shishkin , Andi Kleen , Eranian Stephane Cc: Mark Rutland , broonie@kernel.org, Ravi Bangoria , linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org, Zide Chen , Falcon Thomas , Dapeng Mi , Xudong Hao , Dapeng Mi , Kan Liang Subject: [Patch v10 05/23] perf/x86: Use x86_perf_regs in NMI handlers Date: Tue, 21 Jul 2026 14:24:48 +0800 Message-Id: <20260721062506.3745816-6-dapeng1.mi@linux.intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260721062506.3745816-1-dapeng1.mi@linux.intel.com> References: <20260721062506.3745816-1-dapeng1.mi@linux.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Support for sampling additional register state in NMI context (e.g. vector registers and SSP) requires an x86-specific register container. The generic pt_regs structure cannot represent all of the required x86 register data, so switch x86 NMI handlers to x86_perf_regs. pt_regs is still passed to x86_pmu_handle_irq(), so there is no functional change to existing handling. AMD IBS NMI handling does not use x86_pmu_handle_irq(), so this conversion does not apply to IBS. IBS support for extended register sampling can be added separately in follow-up patches. Co-developed-by: Kan Liang Signed-off-by: Kan Liang Signed-off-by: Dapeng Mi --- arch/x86/events/core.c | 5 ++++- arch/x86/xen/pmu.c | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c index 75358a297222..3368270c0ad1 100644 --- a/arch/x86/events/core.c +++ b/arch/x86/events/core.c @@ -1800,9 +1800,11 @@ void perf_put_guest_lvtpc(void) EXPORT_SYMBOL_FOR_KVM(perf_put_guest_lvtpc); #endif /* CONFIG_PERF_GUEST_MEDIATED_PMU */ =20 +static DEFINE_PER_CPU(struct x86_perf_regs, x86_intr_regs); static int perf_event_nmi_handler(unsigned int cmd, struct pt_regs *regs) { + struct x86_perf_regs *x86_regs =3D this_cpu_ptr(&x86_intr_regs); u64 start_clock; u64 finish_clock; int ret; @@ -1826,7 +1828,8 @@ perf_event_nmi_handler(unsigned int cmd, struct pt_re= gs *regs) return NMI_DONE; =20 start_clock =3D sched_clock(); - ret =3D static_call(x86_pmu_handle_irq)(regs); + x86_regs->regs =3D *regs; + ret =3D static_call(x86_pmu_handle_irq)(&x86_regs->regs); finish_clock =3D sched_clock(); =20 perf_sample_event_took(finish_clock - start_clock); diff --git a/arch/x86/xen/pmu.c b/arch/x86/xen/pmu.c index 5f50a3ee08f5..3f4dd3f50f56 100644 --- a/arch/x86/xen/pmu.c +++ b/arch/x86/xen/pmu.c @@ -456,12 +456,14 @@ static void xen_convert_regs(const struct xen_pmu_reg= s *xen_regs, } } =20 +static DEFINE_PER_CPU(struct x86_perf_regs, x86_xen_intr_regs); irqreturn_t xen_pmu_irq_handler(int irq, void *dev_id) { int err, ret =3D IRQ_NONE; struct pt_regs regs =3D {0}; const struct xen_pmu_data *xenpmu_data =3D get_xenpmu_data(); uint8_t xenpmu_flags =3D get_xenpmu_flags(); + struct x86_perf_regs *x86_regs =3D this_cpu_ptr(&x86_xen_intr_regs); =20 if (!xenpmu_data) { pr_warn_once("%s: pmudata not initialized\n", __func__); @@ -472,7 +474,8 @@ irqreturn_t xen_pmu_irq_handler(int irq, void *dev_id) xenpmu_flags | XENPMU_IRQ_PROCESSING; xen_convert_regs(&xenpmu_data->pmu.r.regs, ®s, xenpmu_data->pmu.pmu_flags); - if (x86_pmu.handle_irq(®s)) + x86_regs->regs =3D regs; + if (x86_pmu.handle_irq(&x86_regs->regs)) ret =3D IRQ_HANDLED; =20 /* Write out cached context to HW */ --=20 2.34.1 From nobody Sat Jul 25 01:34:42 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.16]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7BCC1179A3; Tue, 21 Jul 2026 06:32:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.16 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784615568; cv=none; b=H4f7OhfYDsSSydqxvY+o6bud/yAUPunHHgJpq07mkjK26el28QOgNIwXO6XiGcVz6Ea10oh0YciR6BqxkYhCHEFb+pVkX7+1CUB9YKhbi+WNfz/2pDMk3fk5FbHiFV4S1h6TVjU4ekhq71f/7Fpu/6vEv2i2Ga5GnfSC9pvYtCE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784615568; c=relaxed/simple; bh=VfW7PvtvPvI+U4KGhAdfHFi9quVPDdJyE9fvh0ueUnE=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=cIm9bHG92s62r/rEH1/iYAg3fXsIMZEZ1uv/o5IW0a52ln/zwbxzPsfk11YWZF++bvgasN0jHZFHT71u9T9JIL4q6/R7JPNY6CmjPF0uWcmPB1/Difzb4WPEM6EkbiPb7jflC/karxR3pc1jc2wvCWP3Z8O+ZAYU6qEigoIkDdU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=pass smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=iSV5xR2t; arc=none smtp.client-ip=192.198.163.16 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="iSV5xR2t" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1784615567; x=1816151567; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=VfW7PvtvPvI+U4KGhAdfHFi9quVPDdJyE9fvh0ueUnE=; b=iSV5xR2t7tVz6XmW9PBpHmk1RX/yBq33FktrGlfKuHJtQMB/8uZjR1Bh 54qilBQi7LH8QlENu9YEV1jnoUKq9TT2hLugO9D887pKN2NwfyhxXLFZi T6GMd0BH2SUZqymSVHKXXjrD1ajy2qyQxHgdu8ZUPJdZu5xkVIB/EfhJy ZnQaQp52KuAVasp0dxg/JgMiz8RqEbH7E+sAvN22nBLfJkjdJd+OYa2AP KNqoTw/0zzK0SYe+7fmnypcGsY/n8qwcnYel4WtQH4sijsdkvauN+zjXO JmOCSpTAhhdjx56FxipG5vf+kEn0DP7mm5wPaO5ACy2DPjIJXk7YV1BAn w==; X-CSE-ConnectionGUID: BBiDq8ycQkKrhoAkeRcZjA== X-CSE-MsgGUID: x5zdxCJCR2u2nr4B+LqWFA== X-IronPort-AV: E=McAfee;i="6800,10657,11852"; a="72740324" X-IronPort-AV: E=Sophos;i="6.25,176,1779174000"; d="scan'208";a="72740324" Received: from fmviesa004.fm.intel.com ([10.60.135.144]) by fmvoesa110.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Jul 2026 23:32:47 -0700 X-CSE-ConnectionGUID: yBOw8XeTTDas0ovOi+cH7A== X-CSE-MsgGUID: 2+8A9cJNRGCfoW3ZcbFqpg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.25,176,1779174000"; d="scan'208";a="259655964" Received: from spr.sh.intel.com ([10.112.229.196]) by fmviesa004.fm.intel.com with ESMTP; 20 Jul 2026 23:32:39 -0700 From: Dapeng Mi To: Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Thomas Gleixner , Dave Hansen , Ian Rogers , Adrian Hunter , Jiri Olsa , Alexander Shishkin , Andi Kleen , Eranian Stephane Cc: Mark Rutland , broonie@kernel.org, Ravi Bangoria , linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org, Zide Chen , Falcon Thomas , Dapeng Mi , Xudong Hao , Kan Liang , Dapeng Mi Subject: [Patch v10 06/23] x86/fpu/xstate: Add xsaves_nmi() helper Date: Tue, 21 Jul 2026 14:24:49 +0800 Message-Id: <20260721062506.3745816-7-dapeng1.mi@linux.intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260721062506.3745816-1-dapeng1.mi@linux.intel.com> References: <20260721062506.3745816-1-dapeng1.mi@linux.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Kan Liang Add xsaves_nmi() to save supported xsave states in NMI handler. This function is similar to xsaves(), but should only be called within the NMI handler. This function returns the actual register contents at the moment the NMI occurs. Currently the perf subsystem is the sole user of this helper. It uses this function to snapshot SIMD (XMM/YMM/ZMM) and APX eGPRs registers which would be added in subsequent patches. Signed-off-by: Kan Liang Signed-off-by: Dapeng Mi --- arch/x86/include/asm/fpu/xstate.h | 1 + arch/x86/kernel/fpu/xstate.c | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/arch/x86/include/asm/fpu/xstate.h b/arch/x86/include/asm/fpu/x= state.h index 7a7dc9d56027..38fa8ff26559 100644 --- a/arch/x86/include/asm/fpu/xstate.h +++ b/arch/x86/include/asm/fpu/xstate.h @@ -110,6 +110,7 @@ int xfeature_size(int xfeature_nr); =20 void xsaves(struct xregs_state *xsave, u64 mask); void xrstors(struct xregs_state *xsave, u64 mask); +void xsaves_nmi(struct xregs_state *xsave, u64 mask); =20 int xfd_enable_feature(u64 xfd_err); =20 diff --git a/arch/x86/kernel/fpu/xstate.c b/arch/x86/kernel/fpu/xstate.c index a7b6524a9dea..d39c01546dee 100644 --- a/arch/x86/kernel/fpu/xstate.c +++ b/arch/x86/kernel/fpu/xstate.c @@ -1474,6 +1474,29 @@ void xrstors(struct xregs_state *xstate, u64 mask) WARN_ON_ONCE(err); } =20 +/** + * xsaves_nmi - Save selected components to a kernel xstate buffer in NMI + * @xstate: Pointer to the buffer + * @mask: Feature mask to select the components to save + * + * This function is similar to xsaves(), but should only be called within + * the NMI handler. This function returns the actual register contents at + * the moment the NMI occurs. + * + * Currently, the perf subsystem is the sole user of this helper. It uses + * the function to snapshot SIMD (XMM/YMM/ZMM) and APX eGPRs registers. + */ +void xsaves_nmi(struct xregs_state *xstate, u64 mask) +{ + int err; + + if (!in_nmi()) + return; + + XSTATE_OP(XSAVES, xstate, (u32)mask, (u32)(mask >> 32), err); + WARN_ON_ONCE(err); +} + #if IS_ENABLED(CONFIG_KVM) void fpstate_clear_xstate_component(struct fpstate *fpstate, unsigned int = xfeature) { --=20 2.34.1 From nobody Sat Jul 25 01:34:42 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.11]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6F2E442D75E; Tue, 21 Jul 2026 06:32:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.11 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784615574; cv=none; b=ckbUe2E/8mgFMMo5cano5BhO85bi6i7lRUugzr6OQNVHNlpXzCpH3GRm+lsMAu/3M0oD2hRHahJ+8L5NAPJZJOzTZoCpxjthvVmFYwxNYuh2XtBzZ5MKQYbc5LE3qaPBzK479d3ITXNIQIh7Os1j7XkenVVpInkiwJjYPU5r6A0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784615574; c=relaxed/simple; bh=nC74cNfjP2+EsKrsD4m63iGzVE8gu+HzDH11FE4a1d8=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=mMIh11xrte5giiPAnJ/qyKsvTFdGQTvK0Effczc3YTboXqC0wj5HQIXB/OmQ4wq1c/qzPVO8coDouc9URhEd4hIBrhhLwD9bR7m7483mAs+npTmlKeMUTOjYjZ2QHza+YZvo75z/LjzmHjEXNCa5dhZqduHoSr+FsD9BDuGcbFM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=pass smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=KsWjxonw; arc=none smtp.client-ip=198.175.65.11 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="KsWjxonw" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1784615573; x=1816151573; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=nC74cNfjP2+EsKrsD4m63iGzVE8gu+HzDH11FE4a1d8=; b=KsWjxonw9U+NYnlAxckLcPrxgNBKu+VzTmJT4qr9KuPSEF6av/MU8F8a n9O7wS2XNtxDAoV4ClfydGrckIrdJJbcdAAWU4kkTnrLU2ycu7VLVxvso 0bFwvs4iRE+a6c4dy4hHuFJbE9L8lZVYDaLQUu3tCKhD9QsWGENde4HOQ klGybBQ7UD55y7083ftL9v2oeDOR9XvZf1NS90O1IZLpdvLP1oI0renAC DCZv0hVNYe8p1emUYpJkbhyVcJ/VYX84KhUKhpCULajl94otJV9aOj+3y tzNN7yMIykSxWFZn6GR+nlwomgoBUBFWAMGTksLya022KviviFPCWZ/bk g==; X-CSE-ConnectionGUID: 4O5ykRaBRvey2cg0o1LvBg== X-CSE-MsgGUID: chR4UQUvRCaXwdsL+sHRGw== X-IronPort-AV: E=McAfee;i="6800,10657,11852"; a="95565414" X-IronPort-AV: E=Sophos;i="6.25,176,1779174000"; d="scan'208";a="95565414" Received: from fmviesa004.fm.intel.com ([10.60.135.144]) by orvoesa103.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Jul 2026 23:32:53 -0700 X-CSE-ConnectionGUID: 2Mai+FVMTTW80jk+WNvqIg== X-CSE-MsgGUID: 44DQub42R4K/X9e/p/9nlA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.25,176,1779174000"; d="scan'208";a="259655979" Received: from spr.sh.intel.com ([10.112.229.196]) by fmviesa004.fm.intel.com with ESMTP; 20 Jul 2026 23:32:47 -0700 From: Dapeng Mi To: Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Thomas Gleixner , Dave Hansen , Ian Rogers , Adrian Hunter , Jiri Olsa , Alexander Shishkin , Andi Kleen , Eranian Stephane Cc: Mark Rutland , broonie@kernel.org, Ravi Bangoria , linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org, Zide Chen , Falcon Thomas , Dapeng Mi , Xudong Hao , Dapeng Mi Subject: [Patch v10 07/23] x86/fpu: Add update_fpu_state_and_flag() helper Date: Tue, 21 Jul 2026 14:24:50 +0800 Message-Id: <20260721062506.3745816-8-dapeng1.mi@linux.intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260721062506.3745816-1-dapeng1.mi@linux.intel.com> References: <20260721062506.3745816-1-dapeng1.mi@linux.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add update_fpu_state_and_flag() as suggested by Peter and Dave. The helper saves user FPU state and then sets TIF_NEED_FPU_LOAD, ensuring the task FPU state is saved whenever the flag is set. Subsequent patches will use this guarantee in NMI context by checking TIF_NEED_FPU_LOAD before retrieving user FPU state from the saved task FPU state. Also add barrier() in the host/guest FPU state switch path and move clearing of fpu->__task_fpstate after switching back to host state. So fpu->__task_fpstate is always observed as host FPU state when non-NULL. Link: https://lore.kernel.org/all/20251204154721.GB2619703@noisy.programmin= g.kicks-ass.net/ Signed-off-by: Dapeng Mi --- arch/x86/include/asm/fpu/sched.h | 5 +++-- arch/x86/kernel/fpu/core.c | 33 ++++++++++++++++++++++++++------ 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/arch/x86/include/asm/fpu/sched.h b/arch/x86/include/asm/fpu/sc= hed.h index 89004f4ca208..dcb2fa5f06d6 100644 --- a/arch/x86/include/asm/fpu/sched.h +++ b/arch/x86/include/asm/fpu/sched.h @@ -10,6 +10,8 @@ #include =20 extern void save_fpregs_to_fpstate(struct fpu *fpu); +extern void update_fpu_state_and_flag(struct fpu *fpu, + struct task_struct *task); extern void fpu__drop(struct task_struct *tsk); extern int fpu_clone(struct task_struct *dst, u64 clone_flags, bool minim= al, unsigned long shstk_addr); @@ -36,8 +38,7 @@ static inline void switch_fpu(struct task_struct *old, in= t cpu) !(old->flags & (PF_KTHREAD | PF_USER_WORKER))) { struct fpu *old_fpu =3D x86_task_fpu(old); =20 - set_tsk_thread_flag(old, TIF_NEED_FPU_LOAD); - save_fpregs_to_fpstate(old_fpu); + update_fpu_state_and_flag(old_fpu, old); /* * The save operation preserved register state, so the * fpu_fpregs_owner_ctx is still @old_fpu. Store the diff --git a/arch/x86/kernel/fpu/core.c b/arch/x86/kernel/fpu/core.c index 584fb9913be4..9e029b2f8937 100644 --- a/arch/x86/kernel/fpu/core.c +++ b/arch/x86/kernel/fpu/core.c @@ -213,6 +213,19 @@ void restore_fpregs_from_fpstate(struct fpstate *fpsta= te, u64 mask) } } =20 +/* + * Save the FPU register state in fpu->fpstate->regs and set + * TIF_NEED_FPU_LOAD subsequently. + * + * Must be called with fpregs_lock() held, ensuring flag + * TIF_NEED_FPU_LOAD is set last. + */ +void update_fpu_state_and_flag(struct fpu *fpu, struct task_struct *task) +{ + save_fpregs_to_fpstate(fpu); + set_tsk_thread_flag(task, TIF_NEED_FPU_LOAD); +} + void fpu_reset_from_exception_fixup(void) { restore_fpregs_from_fpstate(&init_fpstate, XFEATURE_MASK_FPSTATE); @@ -383,13 +396,13 @@ int fpu_swap_kvm_fpstate(struct fpu_guest *guest_fpu,= bool enter_guest) =20 /* Swap fpstate */ if (enter_guest) { - fpu->__task_fpstate =3D cur_fps; + WRITE_ONCE(fpu->__task_fpstate, cur_fps); + barrier(); fpu->fpstate =3D guest_fps; guest_fps->in_use =3D true; } else { guest_fps->in_use =3D false; fpu->fpstate =3D fpu->__task_fpstate; - fpu->__task_fpstate =3D NULL; } =20 cur_fps =3D fpu->fpstate; @@ -406,6 +419,16 @@ int fpu_swap_kvm_fpstate(struct fpu_guest *guest_fpu, = bool enter_guest) xfd_update_state(cur_fps); } =20 + /* + * Clear fpu->__task_fpstate after switching back to host state. + * A non-NULL __task_fpstate means guest state is still resident in + * hardware; reset it only once host state has been restored. + */ + if (!enter_guest) { + barrier(); + WRITE_ONCE(fpu->__task_fpstate, NULL); + } + fpregs_mark_activate(); fpregs_unlock(); return 0; @@ -481,10 +504,8 @@ void kernel_fpu_begin_mask(unsigned int kfpu_mask) this_cpu_write(kernel_fpu_allowed, false); =20 if (!(current->flags & (PF_KTHREAD | PF_USER_WORKER)) && - !test_thread_flag(TIF_NEED_FPU_LOAD)) { - set_thread_flag(TIF_NEED_FPU_LOAD); - save_fpregs_to_fpstate(x86_task_fpu(current)); - } + !test_thread_flag(TIF_NEED_FPU_LOAD)) + update_fpu_state_and_flag(x86_task_fpu(current), current); __cpu_invalidate_fpregs_state(); =20 /* Put sane initial values into the control registers. */ --=20 2.34.1 From nobody Sat Jul 25 01:34:42 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.11]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8CC2A4252A0; Tue, 21 Jul 2026 06:32:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.11 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784615580; cv=none; b=XwBMmSQPW1vpZQP01gfqPcQHTUoQGyMvI9Q1uDPt+9twsA3b7uV6C+1575dxYKtexKq/FBm9jwryspVB+n9cy/RDX/3F2BPjYgTNTmuxx4UxRzF3U6GrpnDZNeHmy9wZvcK0CT4dhTXip+vBMhl75fuJgmOlLFjfl2frSuh/ofU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784615580; c=relaxed/simple; bh=v3iMP1VKCgvyvF9VbXliT0PXbMARsiTfffnP7hrmTA4=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=sAqg+yPu53Xbc9vLkm4vo0mFVcQXJuSeWAUdZ9wbLs3MO1x21KlB6EBFb16d7Apz3XmfNm/ViVliXWAWmN6WS5kXwP4orIzAUMtTCjudSFMEUjzNba7jrzc01bFwCNfrY5D7rWX3dMnxNpQ9/SJ584RpwlaDP0csjK0+r9F6Y1w= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=pass smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=hFXBOfqy; arc=none smtp.client-ip=198.175.65.11 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="hFXBOfqy" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1784615580; x=1816151580; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=v3iMP1VKCgvyvF9VbXliT0PXbMARsiTfffnP7hrmTA4=; b=hFXBOfqyfIXC3vzSiDV+a41srMcgIq8YiCzd18qe3fRnObFN7W++S1Sv AvR1/CRjQu7m+XRrc9cUSKxcTRWxrGLuTlU9KirUJQ7/LskgYY+QJ7ept zeaS2gM3LBWOjLbRVw0WPPV+76tiy3jOzlRCR29WV0N2vrV322TiV+VYU mixOY7JH2zomfFe0+YJTwUlMjI0UUhtZiDRphtqeISmXS2BVIzdAR/hT5 Lgq7fG5kmG2HtqUSj2oLbjcL+LfhZK15qEJ+t97GY4XPqvNeaRDo01Nvt 2dMY8fHn1PwjYAGXHYa7tb+Eaf1NIduwxzG8SLVoB8d/3nTq+1SpNL001 w==; X-CSE-ConnectionGUID: Sz2K5L79QCKi73ZsPo2nBQ== X-CSE-MsgGUID: RYIg/rLOQjeHchBoMIg3kQ== X-IronPort-AV: E=McAfee;i="6800,10657,11852"; a="95565425" X-IronPort-AV: E=Sophos;i="6.25,176,1779174000"; d="scan'208";a="95565425" Received: from fmviesa004.fm.intel.com ([10.60.135.144]) by orvoesa103.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Jul 2026 23:32:59 -0700 X-CSE-ConnectionGUID: eUeiAvtOSgKkn4KH+sH7+A== X-CSE-MsgGUID: iDrQN6d8ToeFlOxoT79ndw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.25,176,1779174000"; d="scan'208";a="259655993" Received: from spr.sh.intel.com ([10.112.229.196]) by fmviesa004.fm.intel.com with ESMTP; 20 Jul 2026 23:32:53 -0700 From: Dapeng Mi To: Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Thomas Gleixner , Dave Hansen , Ian Rogers , Adrian Hunter , Jiri Olsa , Alexander Shishkin , Andi Kleen , Eranian Stephane Cc: Mark Rutland , broonie@kernel.org, Ravi Bangoria , linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org, Zide Chen , Falcon Thomas , Dapeng Mi , Xudong Hao , Kan Liang , Dapeng Mi Subject: [Patch v10 08/23] perf: Move and enhance has_extended_regs() for arch-specific use Date: Tue, 21 Jul 2026 14:24:51 +0800 Message-Id: <20260721062506.3745816-9-dapeng1.mi@linux.intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260721062506.3745816-1-dapeng1.mi@linux.intel.com> References: <20260721062506.3745816-1-dapeng1.mi@linux.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Kan Liang Move has_extended_regs() to include/linux/perf_event.h so it can be used by arch-specific code. While moving it, enhance the check logic and rename it to event_has_extended_regs() to match existing perf event helper naming. Signed-off-by: Kan Liang Signed-off-by: Dapeng Mi --- include/linux/perf_event.h | 10 ++++++++++ kernel/events/core.c | 8 +------- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index 48d851fbd8ea..fb38affa7352 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -1534,6 +1534,16 @@ perf_event__output_id_sample(struct perf_event *even= t, extern void perf_log_lost_samples(struct perf_event *event, u64 lost); =20 +static inline bool event_has_extended_regs(struct perf_event *event) +{ + struct perf_event_attr *attr =3D &event->attr; + + return ((attr->sample_type & PERF_SAMPLE_REGS_USER) && + (attr->sample_regs_user & PERF_REG_EXTENDED_MASK)) || + ((attr->sample_type & PERF_SAMPLE_REGS_INTR) && + (attr->sample_regs_intr & PERF_REG_EXTENDED_MASK)); +} + static inline bool event_has_any_exclude_flag(struct perf_event *event) { struct perf_event_attr *attr =3D &event->attr; diff --git a/kernel/events/core.c b/kernel/events/core.c index 770c4b1330c7..7848e9ac06ca 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -13116,12 +13116,6 @@ int perf_pmu_unregister(struct pmu *pmu) } EXPORT_SYMBOL_GPL(perf_pmu_unregister); =20 -static inline bool has_extended_regs(struct perf_event *event) -{ - return (event->attr.sample_regs_user & PERF_REG_EXTENDED_MASK) || - (event->attr.sample_regs_intr & PERF_REG_EXTENDED_MASK); -} - static int perf_try_init_event(struct pmu *pmu, struct perf_event *event) { struct perf_event_context *ctx =3D NULL; @@ -13156,7 +13150,7 @@ static int perf_try_init_event(struct pmu *pmu, str= uct perf_event *event) goto err_pmu; =20 if (!(pmu->capabilities & PERF_PMU_CAP_EXTENDED_REGS) && - has_extended_regs(event)) { + event_has_extended_regs(event)) { ret =3D -EOPNOTSUPP; goto err_destroy; } --=20 2.34.1 From nobody Sat Jul 25 01:34:42 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.11]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EE63840BCB0; Tue, 21 Jul 2026 06:33:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.11 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784615587; cv=none; b=bLPenCfyMp1+1Ine7W3jhKBJPyQ4ja4s4rgbSjPIe6Eyx6Z1QwUOKzCprxLOsZ3oQHNOPNZBVSAmK0ozuFpxza+i2berjCdr16ZvnbDPsLNiSoOJ5sA6p1jXSZcu4uch4v1iLLeKkfwuUXyCLkBIJfjV/2qZY9zF7Gqj9RxX420= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784615587; c=relaxed/simple; bh=q7EfxZhxk9GaeSrbQBbNNUxLXU7Pe+i2cmbda4q+0wk=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=qvNBsxVVmyQv5qD5MFcaeKcbZYxsxi2RsH8CZP1QVEEhBDZwz31EQpvgXkr5142oPmH+yCycWHXFrsuvkXZ/4NKP01R8qoV07I5nbP9sd/977MI3XPSI0MrDM1Ra00EDw264iUTVr4MuryaBcpMWmYTErbF7lKbuMbietYGntL4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=pass smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=N0/c48u/; arc=none smtp.client-ip=198.175.65.11 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="N0/c48u/" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1784615586; x=1816151586; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=q7EfxZhxk9GaeSrbQBbNNUxLXU7Pe+i2cmbda4q+0wk=; b=N0/c48u/hyQKIHuG6f4hYw7VeWJz5/zreGXW4VmlRp27f82luDIqzz/r aXYZ34ZJP7aRHtimMhmrGa6AwFeB/YEZezRSsHd41EEyiMlDSHeBb9YB2 tV4AAZ/cg+uWT/m0l6MEdSAzWhxragDrpAhPQvGLfiCD1NtwrNcQdHVur Za1kb6b8nxsZRMQl9DT1DHJFVcrLYLbWaeeN0TEeQMYvYQyvMQZ5F+pYR vz3GTkg0W8KbcJABew+wJimQLez1SlfpxODajx/Rxgg/uR846RmYcYN2f itbE1OrZsFz+Z4q0W6s49p2N+5QDnK5WDVL1nQfVZaS+ELqbszVtItt51 w==; X-CSE-ConnectionGUID: dGurNPAgR+evP8nkIx1MAw== X-CSE-MsgGUID: 06hWn7MbQdS7sihWr4HSzA== X-IronPort-AV: E=McAfee;i="6800,10657,11852"; a="95565441" X-IronPort-AV: E=Sophos;i="6.25,176,1779174000"; d="scan'208";a="95565441" Received: from fmviesa004.fm.intel.com ([10.60.135.144]) by orvoesa103.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Jul 2026 23:33:06 -0700 X-CSE-ConnectionGUID: 51fSS27kQK+lpoJu88UBvw== X-CSE-MsgGUID: hJurwxPgTOqVnbZJxMuigg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.25,176,1779174000"; d="scan'208";a="259656011" Received: from spr.sh.intel.com ([10.112.229.196]) by fmviesa004.fm.intel.com with ESMTP; 20 Jul 2026 23:32:59 -0700 From: Dapeng Mi To: Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Thomas Gleixner , Dave Hansen , Ian Rogers , Adrian Hunter , Jiri Olsa , Alexander Shishkin , Andi Kleen , Eranian Stephane Cc: Mark Rutland , broonie@kernel.org, Ravi Bangoria , linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org, Zide Chen , Falcon Thomas , Dapeng Mi , Xudong Hao , Dapeng Mi Subject: [Patch v10 09/23] perf/x86/intel: Centralize PERF_PMU_CAP_EXTENDED_REGS updates Date: Tue, 21 Jul 2026 14:24:52 +0800 Message-Id: <20260721062506.3745816-10-dapeng1.mi@linux.intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260721062506.3745816-1-dapeng1.mi@linux.intel.com> References: <20260721062506.3745816-1-dapeng1.mi@linux.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" PERF_PMU_CAP_EXTENDED_REGS is currently updated in multiple paths: intel_ds_pebs_init() and __intel_update_pmu_caps() for adaptive and architectural PEBS. This split makes the capability flow harder to reason about and is awkward for upcoming XSAVES-based SIMD register sampling, which also needs consistent capability setup and validation. Refactor the update logic into a single helper, __intel_update_pmu_xregs_caps(), so adaptive and architectural PEBS share one implementation. Call this helper from intel_update_pmu_caps() to keep PMU capability handling centralized in one place and avoid duplicated or conflicting updates. Signed-off-by: Dapeng Mi --- arch/x86/events/intel/core.c | 16 ++++++++-------- arch/x86/events/intel/ds.c | 1 - 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c index ee62b24d3fdf..aecaa109c31e 100644 --- a/arch/x86/events/intel/core.c +++ b/arch/x86/events/intel/core.c @@ -6187,11 +6187,14 @@ static inline bool intel_pmu_broken_perf_cap(void) return false; } =20 -static inline void __intel_update_pmu_caps(struct pmu *pmu) +static inline void __intel_update_pmu_xregs_caps(struct pmu *pmu) { struct pmu *dest_pmu =3D pmu ? pmu : x86_get_pmu(smp_processor_id()); + u64 caps =3D hybrid(pmu, arch_pebs_cap).caps; =20 - if (hybrid(pmu, arch_pebs_cap).caps & ARCH_PEBS_VECR_XMM) + if ((x86_pmu.arch_pebs && (caps & ARCH_PEBS_VECR_XMM)) || + (!x86_pmu.arch_pebs && x86_pmu.intel_cap.pebs_format >=3D 4 && + x86_pmu.intel_cap.pebs_baseline)) dest_pmu->capabilities |=3D PERF_PMU_CAP_EXTENDED_REGS; } =20 @@ -6263,12 +6266,10 @@ static void update_pmu_cap_from_perfmonext(struct p= mu *pmu) hybrid(pmu, arch_pebs_cap).counters =3D pebs_mask; hybrid(pmu, arch_pebs_cap).pdists =3D pdists_mask; =20 - if (WARN_ON((pebs_mask | pdists_mask) & ~cntrs_mask)) { + if (WARN_ON((pebs_mask | pdists_mask) & ~cntrs_mask)) x86_pmu.arch_pebs =3D 0; - } else { - __intel_update_pmu_caps(pmu); + else __intel_update_large_pebs_flags(pmu); - } } else { WARN_ON(x86_pmu.arch_pebs =3D=3D 1); x86_pmu.arch_pebs =3D 0; @@ -6292,6 +6293,7 @@ static void intel_update_pmu_caps(struct pmu *pmu) hybrid_pmu(pmu)->pmu_type =3D=3D hybrid_big) hybrid(pmu, intel_cap).perf_metrics =3D 1; } + __intel_update_pmu_xregs_caps(pmu); } =20 static void intel_pmu_check_hybrid_pmus(struct x86_hybrid_pmu *pmu) @@ -6445,8 +6447,6 @@ static void intel_pmu_cpu_starting(int cpu) } } =20 - __intel_update_pmu_caps(cpuc->pmu); - if (!cpuc->shared_regs) return; =20 diff --git a/arch/x86/events/intel/ds.c b/arch/x86/events/intel/ds.c index 9355744a9258..d50d9de6c17f 100644 --- a/arch/x86/events/intel/ds.c +++ b/arch/x86/events/intel/ds.c @@ -3389,7 +3389,6 @@ static void __init intel_ds_pebs_init(void) x86_pmu.flags |=3D PMU_FL_PEBS_ALL; x86_pmu.pebs_capable =3D ~0ULL; pebs_qual =3D "-baseline"; - x86_get_pmu(smp_processor_id())->capabilities |=3D PERF_PMU_CAP_EXTEND= ED_REGS; } else { /* Only basic record supported */ x86_pmu.large_pebs_flags &=3D --=20 2.34.1 From nobody Sat Jul 25 01:34:42 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.11]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B8C194302F0; Tue, 21 Jul 2026 06:33:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.11 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784615595; cv=none; b=VF5g+yuwXw1dNZ8tjgDTgatydqCm8G1QPxXZsUd2ORRCd2hxzyBXxZ/3orPF9OqEKGevcIlGxitXWTgiaLwpf8LD7I69YUZXLn9/vvky8eGF/RGo84Leyk6zrDFWdHIQVXbXtBmV5xMzRSXbNY4vwCecsF1fYPRf4FzvSlX5O5M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784615595; c=relaxed/simple; bh=70FSeAQPZTU7mN5A8g6KnE5O2gN52BTyqJu4LEhRNtU=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=uVD6MatvWHPcalDcN48zCoIlOW/EI61Uhe/zoa0vd1KCyQ6tK4Ma4RuErqpjf7x5Tb4KSErHoIQW4DNjDwXJ/oVxHOxDp+d77LvJD/lgOmdwmJoALyh8xsAV4R0YSeq9e7jWYs5lZ/OdCAHKt72uTobH0KGDhdgtY+QvFiWmG7E= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=pass smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=J0lixj/D; arc=none smtp.client-ip=198.175.65.11 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="J0lixj/D" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1784615594; x=1816151594; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=70FSeAQPZTU7mN5A8g6KnE5O2gN52BTyqJu4LEhRNtU=; b=J0lixj/DAJVbgiFqehTff+kyR/qoZzY22AumBr7+WAy7tnvWbM6tEw5O bXblYnUwjFGpXsJFEmBJKI2rrQSRvJKLNzlBR5rAAUY16Ai7dydcfpIjC mK4Dr+GpKUAFni02rtCm8hEEpTm0PC6tMqFQakIAgOebujFQ8rPY/OoT9 wYNc+eaFCftRTt8Gwu9U9s0ZHjttMa/MZWjiUgqamVJAE5+9YgvsZskze ziAEnE6kgguuD4LStq5ejGMDSRR54dkDm502Fezciblnoo1U13elXiYKi co4Pqlizkfaa+Kv98R8zzOk4VxsYwzzuHb/xfZNzGTh6UHdonJhxX6Fkn Q==; X-CSE-ConnectionGUID: 3C1EL1qWRJW/x2RxVMMCKw== X-CSE-MsgGUID: YVrLdpbSSRKe6FqbI+5I6g== X-IronPort-AV: E=McAfee;i="6800,10657,11852"; a="95565454" X-IronPort-AV: E=Sophos;i="6.25,176,1779174000"; d="scan'208";a="95565454" Received: from fmviesa004.fm.intel.com ([10.60.135.144]) by orvoesa103.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Jul 2026 23:33:13 -0700 X-CSE-ConnectionGUID: +JK4ftc2QEuPM8f+gHiiEQ== X-CSE-MsgGUID: sEHgyoUsT9WTy8WLlWcQLA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.25,176,1779174000"; d="scan'208";a="259656034" Received: from spr.sh.intel.com ([10.112.229.196]) by fmviesa004.fm.intel.com with ESMTP; 20 Jul 2026 23:33:06 -0700 From: Dapeng Mi To: Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Thomas Gleixner , Dave Hansen , Ian Rogers , Adrian Hunter , Jiri Olsa , Alexander Shishkin , Andi Kleen , Eranian Stephane Cc: Mark Rutland , broonie@kernel.org, Ravi Bangoria , linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org, Zide Chen , Falcon Thomas , Dapeng Mi , Xudong Hao , Dapeng Mi , Kan Liang Subject: [Patch v10 10/23] perf/x86: Enable XMM register sampling for non-PEBS events Date: Tue, 21 Jul 2026 14:24:53 +0800 Message-Id: <20260721062506.3745816-11-dapeng1.mi@linux.intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260721062506.3745816-1-dapeng1.mi@linux.intel.com> References: <20260721062506.3745816-1-dapeng1.mi@linux.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Previously, XMM register sampling was only available for PEBS events starting from Icelake. Extend the support to non-PEBS events using the xsaves instruction, thereby completing the feature set. To implement this, a 64-byte aligned buffer is required. A per-CPU ext_regs_buf is introduced to store SIMD and other registers, with an approximate size of 2K. The buffer is allocated using kzalloc_node(), ensuring natural and 64-byte alignment for all kmalloc() allocations with powers of 2. XMM sampling for non-PEBS events is supported in the REGS_INTR case. Support for REGS_USER will be added in a subsequent patch. For PEBS events, XMM register sampling data is directly retrieved from PEBS records. Future support for additional vector registers (YMM/ZMM/OPMASK) is planned. An ext_regs_mask is added to track the supported vector register groups. Co-developed-by: Kan Liang Signed-off-by: Kan Liang Signed-off-by: Dapeng Mi --- arch/x86/events/core.c | 185 ++++++++++++++++++++++++++++-- arch/x86/events/intel/core.c | 24 +++- arch/x86/events/intel/ds.c | 8 +- arch/x86/events/perf_event.h | 13 +++ arch/x86/include/asm/fpu/xstate.h | 2 + arch/x86/include/asm/perf_event.h | 5 +- arch/x86/kernel/fpu/xstate.c | 2 +- 7 files changed, 219 insertions(+), 20 deletions(-) diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c index 3368270c0ad1..1c3e2bfa2673 100644 --- a/arch/x86/events/core.c +++ b/arch/x86/events/core.c @@ -408,6 +408,53 @@ set_ext_hw_attr(struct hw_perf_event *hwc, struct perf= _event *event) return x86_pmu_extra_regs(val, event); } =20 +static DEFINE_PER_CPU(struct xregs_state *, ext_regs_buf); + +static void release_ext_regs_buffers(void) +{ + int cpu; + + if (!x86_pmu.ext_regs_mask) + return; + + for_each_possible_cpu(cpu) { + kfree(per_cpu(ext_regs_buf, cpu)); + per_cpu(ext_regs_buf, cpu) =3D NULL; + } +} + +static void reserve_ext_regs_buffers(void) +{ + bool compacted =3D cpu_feature_enabled(X86_FEATURE_XCOMPACTED); + unsigned int size; + int cpu; + + if (!x86_pmu.ext_regs_mask) + return; + + /* Add 64 bytes to satisfy the XSAVE area's 64-byte alignment. */ + size =3D xstate_calculate_size(x86_pmu.ext_regs_mask, compacted) + 64; + + for_each_possible_cpu(cpu) { + per_cpu(ext_regs_buf, cpu) =3D kzalloc_node(size, GFP_KERNEL, + cpu_to_node(cpu)); + if (WARN_ON_ONCE(!per_cpu(ext_regs_buf, cpu))) + goto err; + } + + return; + +err: + release_ext_regs_buffers(); +} + +static inline struct xregs_state *get_ext_regs_buf(int cpu) +{ + void *buf =3D per_cpu(ext_regs_buf, cpu); + + return buf ? PTR_ALIGN(buf, 64) : NULL; +} + int x86_reserve_hardware(void) { int err =3D 0; @@ -420,6 +467,7 @@ int x86_reserve_hardware(void) } else { reserve_ds_buffers(); reserve_lbr_buffers(); + reserve_ext_regs_buffers(); } } if (!err) @@ -436,6 +484,7 @@ void x86_release_hardware(void) release_pmc_hardware(); release_ds_buffers(); release_lbr_buffers(); + release_ext_regs_buffers(); mutex_unlock(&pmc_reserve_mutex); } } @@ -653,18 +702,31 @@ int x86_pmu_hw_config(struct perf_event *event) return -EINVAL; } =20 - /* sample_regs_user never support XMM registers */ - if (unlikely(event->attr.sample_regs_user & PERF_REG_EXTENDED_MASK)) - return -EINVAL; - /* - * Besides the general purpose registers, XMM registers may - * be collected in PEBS on some platforms, e.g. Icelake - */ - if (unlikely(event->attr.sample_regs_intr & PERF_REG_EXTENDED_MASK)) { - if (!(event->pmu->capabilities & PERF_PMU_CAP_EXTENDED_REGS)) - return -EINVAL; + if (event->attr.sample_type & PERF_SAMPLE_REGS_INTR) { + /* + * Besides the general purpose registers, XMM registers may + * be collected as well. + */ + if (event->attr.sample_regs_intr & PERF_REG_EXTENDED_MASK) { + if (!(event->pmu->capabilities & PERF_PMU_CAP_EXTENDED_REGS)) + return -EINVAL; + + if (event->attr.precise_ip) { + u64 caps =3D hybrid(event->pmu, arch_pebs_cap).caps; =20 - if (!event->attr.precise_ip) + if (x86_pmu.arch_pebs && !(caps & ARCH_PEBS_VECR_XMM)) + return -EINVAL; + if (!x86_pmu.arch_pebs && !x86_pmu.intel_cap.pebs_baseline) + return -EINVAL; + } + if (!get_ext_regs_buf(raw_smp_processor_id())) + return -ENOMEM; + } + } + + if (event->attr.sample_type & PERF_SAMPLE_REGS_USER) { + /* XMM registers sampling for REGS_USER is not supported yet. */ + if (event->attr.sample_regs_user & PERF_REG_EXTENDED_MASK) return -EINVAL; } =20 @@ -1717,6 +1779,107 @@ static void x86_pmu_del(struct perf_event *event, i= nt flags) static_call_cond(x86_pmu_del)(event); } =20 +void x86_pmu_clear_perf_regs(struct pt_regs *regs) +{ + struct x86_perf_regs *perf_regs =3D container_of(regs, struct x86_perf_re= gs, regs); + + perf_regs->xmm_regs =3D NULL; +} + +static void update_perf_regs(struct x86_perf_regs *perf_regs, + struct xregs_state *xsave, u64 bitmap) +{ + u64 mask; + + if (!xsave) + return; + + /* Restrict to features actually saved by XSAVES */ + mask =3D bitmap & xsave->header.xfeatures; + + if (mask & XFEATURE_MASK_SSE) + perf_regs->xmm_space =3D xsave->i387.xmm_space; +} + +/* + * The x86 specific variant of perf_sample_regs_intr(). + * It would be extended to add more SIMD registers sampling support + * in later patches. + */ +static void x86_pmu_update_regs_intr(struct perf_event *event, + struct perf_sample_data *data, + struct pt_regs *regs, + bool exclude_kernel) +{ + if (exclude_kernel && !user_mode(regs)) { + data->regs_intr.regs =3D NULL; + data->regs_intr.abi =3D PERF_SAMPLE_REGS_ABI_NONE; + } else { + data->regs_intr.regs =3D regs; + data->regs_intr.abi =3D perf_reg_abi(current); + } + + data->dyn_size +=3D sizeof(u64); + if (data->regs_intr.regs) { + data->dyn_size +=3D hweight64(event->attr.sample_regs_intr) * + sizeof(u64); + } + + /* + * Set PERF_SAMPLE_REGS_INTR to bypass perf_sample_regs_intr() call + * in perf_prepare_sample() function. + */ + data->sample_flags |=3D PERF_SAMPLE_REGS_INTR; +} + +static void x86_pmu_sample_xregs(struct perf_event *event, + struct perf_sample_data *data, + bool from_pebs) +{ + struct xregs_state *xsave =3D get_ext_regs_buf(smp_processor_id()); + u64 sample_type =3D event->attr.sample_type; + struct x86_perf_regs *perf_regs; + u64 intr_mask =3D 0; + + if (WARN_ON_ONCE(!xsave) || !in_nmi()) + return; + + if ((sample_type & PERF_SAMPLE_REGS_INTR) && data->regs_intr.regs) { + if (event->attr.sample_regs_intr & PERF_REG_EXTENDED_MASK) + intr_mask |=3D XFEATURE_MASK_SSE; + + intr_mask &=3D x86_pmu.ext_regs_mask; + intr_mask =3D from_pebs ? 0 : intr_mask; + } + + if (intr_mask) { + perf_regs =3D container_of(data->regs_intr.regs, + struct x86_perf_regs, regs); + xsave->header.xfeatures =3D 0; + xsaves_nmi(xsave, intr_mask); + update_perf_regs(perf_regs, xsave, intr_mask); + } +} + +void x86_pmu_update_perf_regs(struct perf_event *event, + struct perf_sample_data *data, + struct pt_regs *regs, + bool from_pebs) +{ + u64 sample_type =3D event->attr.sample_type; + + if (!((sample_type & PERF_SAMPLE_REGS_INTR) && + (event->attr.sample_regs_intr & PERF_REG_EXTENDED_MASK))) + return; + + if (sample_type & PERF_SAMPLE_REGS_INTR) { + x86_pmu_update_regs_intr(event, data, regs, + event->attr.exclude_kernel); + } + + x86_pmu_sample_xregs(event, data, from_pebs); +} + int x86_pmu_handle_irq(struct pt_regs *regs) { struct perf_sample_data data; diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c index aecaa109c31e..24f3f49f3953 100644 --- a/arch/x86/events/intel/core.c +++ b/arch/x86/events/intel/core.c @@ -3949,6 +3949,9 @@ static int handle_pmi_common(struct pt_regs *regs, u6= 4 status) if (has_branch_stack(event)) intel_pmu_lbr_save_brstack(&data, cpuc, event); =20 + x86_pmu_clear_perf_regs(regs); + x86_pmu_update_perf_regs(event, &data, regs, false); + perf_event_overflow(event, &data, regs); } =20 @@ -6190,12 +6193,23 @@ static inline bool intel_pmu_broken_perf_cap(void) static inline void __intel_update_pmu_xregs_caps(struct pmu *pmu) { struct pmu *dest_pmu =3D pmu ? pmu : x86_get_pmu(smp_processor_id()); - u64 caps =3D hybrid(pmu, arch_pebs_cap).caps; =20 - if ((x86_pmu.arch_pebs && (caps & ARCH_PEBS_VECR_XMM)) || - (!x86_pmu.arch_pebs && x86_pmu.intel_cap.pebs_format >=3D 4 && - x86_pmu.intel_cap.pebs_baseline)) - dest_pmu->capabilities |=3D PERF_PMU_CAP_EXTENDED_REGS; + /* Only support the extension when XSAVES is available. */ + if (!boot_cpu_has(X86_FEATURE_XSAVES)) + return; + + if (!boot_cpu_has(X86_FEATURE_XMM) || + !cpu_has_xfeatures(XFEATURE_MASK_SSE, NULL)) + return; + + /* + * On current hybrid platforms, P-cores and E-cores expose the same + * XSAVE feature set. Therefore, using the global x86_pmu.ext_regs_mask + * is sufficient to represent the hardware-supported XSAVE features. + */ + x86_pmu.ext_regs_mask |=3D XFEATURE_MASK_SSE; + + dest_pmu->capabilities |=3D PERF_PMU_CAP_EXTENDED_REGS; } =20 static inline void __intel_update_large_pebs_flags(struct pmu *pmu) diff --git a/arch/x86/events/intel/ds.c b/arch/x86/events/intel/ds.c index d50d9de6c17f..208584b32878 100644 --- a/arch/x86/events/intel/ds.c +++ b/arch/x86/events/intel/ds.c @@ -2508,7 +2508,7 @@ static void setup_pebs_adaptive_sample_data(struct pe= rf_event *event, return; =20 perf_regs =3D container_of(regs, struct x86_perf_regs, regs); - perf_regs->xmm_regs =3D NULL; + x86_pmu_clear_perf_regs(regs); =20 format_group =3D basic->format_group; =20 @@ -2593,6 +2593,8 @@ static void setup_pebs_adaptive_sample_data(struct pe= rf_event *event, next_record +=3D nr * sizeof(u64); } =20 + x86_pmu_update_perf_regs(event, data, regs, true); + WARN_ONCE(next_record !=3D __pebs + basic->format_size, "PEBS record size %u, expected %llu, config %llx\n", basic->format_size, @@ -2625,7 +2627,7 @@ static void setup_arch_pebs_sample_data(struct perf_e= vent *event, return; =20 perf_regs =3D container_of(regs, struct x86_perf_regs, regs); - perf_regs->xmm_regs =3D NULL; + x86_pmu_clear_perf_regs(regs); =20 __setup_perf_sample_data(event, iregs, data); =20 @@ -2727,6 +2729,8 @@ static void setup_arch_pebs_sample_data(struct perf_e= vent *event, at =3D at + header->size; goto again; } + + x86_pmu_update_perf_regs(event, data, regs, true); } =20 static inline void * diff --git a/arch/x86/events/perf_event.h b/arch/x86/events/perf_event.h index fa381110f7a7..c2b0df0051b8 100644 --- a/arch/x86/events/perf_event.h +++ b/arch/x86/events/perf_event.h @@ -1028,6 +1028,12 @@ struct x86_pmu { struct extra_reg *extra_regs; unsigned int flags; =20 + /* + * Extended regs, e.g., vector registers + * Utilize the same format as the XFEATURE_MASK_* + */ + u64 ext_regs_mask; + /* * Intel host/guest support (KVM) */ @@ -1315,6 +1321,13 @@ void x86_pmu_enable_event(struct perf_event *event); =20 int x86_pmu_handle_irq(struct pt_regs *regs); =20 +void x86_pmu_clear_perf_regs(struct pt_regs *regs); + +void x86_pmu_update_perf_regs(struct perf_event *event, + struct perf_sample_data *data, + struct pt_regs *regs, + bool from_pebs); + void x86_pmu_show_pmu_cap(struct pmu *pmu); =20 static inline int x86_pmu_num_counters(struct pmu *pmu) diff --git a/arch/x86/include/asm/fpu/xstate.h b/arch/x86/include/asm/fpu/x= state.h index 38fa8ff26559..19dec5f0b1c7 100644 --- a/arch/x86/include/asm/fpu/xstate.h +++ b/arch/x86/include/asm/fpu/xstate.h @@ -112,6 +112,8 @@ void xsaves(struct xregs_state *xsave, u64 mask); void xrstors(struct xregs_state *xsave, u64 mask); void xsaves_nmi(struct xregs_state *xsave, u64 mask); =20 +unsigned int xstate_calculate_size(u64 xfeatures, bool compacted); + int xfd_enable_feature(u64 xfd_err); =20 #ifdef CONFIG_X86_64 diff --git a/arch/x86/include/asm/perf_event.h b/arch/x86/include/asm/perf_= event.h index 1eb13673e889..619e0ae915e1 100644 --- a/arch/x86/include/asm/perf_event.h +++ b/arch/x86/include/asm/perf_event.h @@ -728,7 +728,10 @@ extern void perf_events_lapic_init(void); struct pt_regs; struct x86_perf_regs { struct pt_regs regs; - u64 *xmm_regs; + union { + u64 *xmm_regs; + u32 *xmm_space; /* for xsaves */ + }; }; =20 extern unsigned long perf_arch_instruction_pointer(struct pt_regs *regs); diff --git a/arch/x86/kernel/fpu/xstate.c b/arch/x86/kernel/fpu/xstate.c index d39c01546dee..3e7f5fb5bfaf 100644 --- a/arch/x86/kernel/fpu/xstate.c +++ b/arch/x86/kernel/fpu/xstate.c @@ -587,7 +587,7 @@ static bool __init check_xstate_against_struct(int nr) return true; } =20 -static unsigned int xstate_calculate_size(u64 xfeatures, bool compacted) +unsigned int xstate_calculate_size(u64 xfeatures, bool compacted) { unsigned int topmost =3D fls64(xfeatures) - 1; unsigned int offset, i; --=20 2.34.1 From nobody Sat Jul 25 01:34:42 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.11]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 075B8409295; Tue, 21 Jul 2026 06:33:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.11 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784615601; cv=none; b=dgRiBVyeEYmo6afWT1XUKUKmQ+pvjPtkARd0NDXthzdMCD6C376z36TlR+q19p0mT6Bo8iNU0EXW8inDSHSowPJlPRha5V3IxmOd23yySSwhwW6qUJgnOA19gdVCbt3T5ZzIML5LBCAd3aDmF+c19JwSf8pkYjD7og6rI/GvWGU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784615601; c=relaxed/simple; bh=nLHL2uGp/1+lEU6lvplxg9YMBoQqJyGdlZbTwEA0Wy4=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=jO6i5SRrnRC4d2VPk74JtejflCQ2QavxAaUCG/slIvplPIb/pUTEwhGGiUhA5whVqb2xdDxTNWrM9LJuuMjKRlU6wVprIx629LM/na0r6Tw2WPn51MEFCi1RtaY8GCk7+0hAZ6I4yfA7e/AEX8P3T1D0mCL6Pt8y3nUg6J8ifxQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=pass smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=TspcSZCB; arc=none smtp.client-ip=198.175.65.11 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="TspcSZCB" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1784615600; x=1816151600; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=nLHL2uGp/1+lEU6lvplxg9YMBoQqJyGdlZbTwEA0Wy4=; b=TspcSZCBTcSzxmg0UBsn/HAgJ7gLWgomCkUdzNmCJT6jHALMiWKGo1/V TygEx8gP4Yf5VKKZolVOsuvJ2A6h9uiyO9HmZ6XJGTebshCMecC7utzx6 7zEq+FJaU10GomPPzsPsFw64wVk/ijmpbTNd1fdi6uO/zVcDhtAk3RWaX Y1UCyQjdaMQuZB/x8WGCQvGpe9zycyM67tK+qvhHBw46B652zPg25Onq3 jWUy9hBLzQ/v+lGvxu4smKUxjsURPol2OwiEJWMk3GXoxFAcLBaqJAFhw U7hEAZukFHO1joDcluwJVTPRlxhHYIqqLmyzXSYaUhrq4X3nPCcKvPzsg g==; X-CSE-ConnectionGUID: H7WttqA7TpqaU31+i0yf+g== X-CSE-MsgGUID: MPfJrwghRgmHYg7P+vekLw== X-IronPort-AV: E=McAfee;i="6800,10657,11852"; a="95565460" X-IronPort-AV: E=Sophos;i="6.25,176,1779174000"; d="scan'208";a="95565460" Received: from fmviesa004.fm.intel.com ([10.60.135.144]) by orvoesa103.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Jul 2026 23:33:20 -0700 X-CSE-ConnectionGUID: o6D+uUVFSba2lVycvKDqzA== X-CSE-MsgGUID: DkP84GDSQl2ho/84CCQMRw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.25,176,1779174000"; d="scan'208";a="259656047" Received: from spr.sh.intel.com ([10.112.229.196]) by fmviesa004.fm.intel.com with ESMTP; 20 Jul 2026 23:33:13 -0700 From: Dapeng Mi To: Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Thomas Gleixner , Dave Hansen , Ian Rogers , Adrian Hunter , Jiri Olsa , Alexander Shishkin , Andi Kleen , Eranian Stephane Cc: Mark Rutland , broonie@kernel.org, Ravi Bangoria , linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org, Zide Chen , Falcon Thomas , Dapeng Mi , Xudong Hao , Dapeng Mi , Kan Liang Subject: [Patch v10 11/23] perf/x86: Enable XMM register sampling for REGS_USER case Date: Tue, 21 Jul 2026 14:24:54 +0800 Message-Id: <20260721062506.3745816-12-dapeng1.mi@linux.intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260721062506.3745816-1-dapeng1.mi@linux.intel.com> References: <20260721062506.3745816-1-dapeng1.mi@linux.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Support XMM register sampling for the REGS_USER case. To handle simultaneous sampling of XMM registers for both REGS_INTR and REGS_USER cases, a per-CPU x86_user_regs is introduced to store REGS_USER-specific XMM registers. This prevents REGS_USER-specific XMM register data from being overwritten by REGS_INTR-specific data if they share the same x86_perf_regs structure. To sample user-space XMM registers, the x86_pmu_update_user_xregs() helper function is added. It checks if the user-space FPU state has been cached into task FPU state. If so, the user-space XMM register data can be directly retrieved from the cached task FPU state, as the corresponding hardware registers have been cleared or switched to kernel-space state or guest state. Otherwise, the data could be read from the hardware registers using the xsaves instruction. For PEBS events, x86_pmu_update_user_xregs() checks if the PEBS-sampled XMM register data belongs to user-space. If so, no further action is needed. Otherwise, the user-space XMM register data needs to be re-sampled using the same method as for non-PEBS events. Co-developed-by: Kan Liang Signed-off-by: Kan Liang Signed-off-by: Dapeng Mi --- arch/x86/events/core.c | 154 ++++++++++++++++++++++++++++++++--- arch/x86/events/intel/core.c | 6 +- arch/x86/events/intel/ds.c | 5 +- 3 files changed, 147 insertions(+), 18 deletions(-) diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c index 1c3e2bfa2673..20140643e21c 100644 --- a/arch/x86/events/core.c +++ b/arch/x86/events/core.c @@ -702,12 +702,12 @@ int x86_pmu_hw_config(struct perf_event *event) return -EINVAL; } =20 - if (event->attr.sample_type & PERF_SAMPLE_REGS_INTR) { + if (event->attr.sample_type & (PERF_SAMPLE_REGS_INTR | PERF_SAMPLE_REGS_U= SER)) { /* * Besides the general purpose registers, XMM registers may * be collected as well. */ - if (event->attr.sample_regs_intr & PERF_REG_EXTENDED_MASK) { + if (event_has_extended_regs(event)) { if (!(event->pmu->capabilities & PERF_PMU_CAP_EXTENDED_REGS)) return -EINVAL; =20 @@ -724,12 +724,6 @@ int x86_pmu_hw_config(struct perf_event *event) } } =20 - if (event->attr.sample_type & PERF_SAMPLE_REGS_USER) { - /* XMM registers sampling for REGS_USER is not supported yet. */ - if (event->attr.sample_regs_user & PERF_REG_EXTENDED_MASK) - return -EINVAL; - } - return x86_setup_perfctr(event); } =20 @@ -1832,14 +1826,129 @@ static void x86_pmu_update_regs_intr(struct perf_e= vent *event, data->sample_flags |=3D PERF_SAMPLE_REGS_INTR; } =20 +static DEFINE_PER_CPU(struct x86_perf_regs, x86_user_regs); + +static void x86_pmu_get_regs_user(struct perf_sample_data *data, + struct pt_regs *regs) +{ + struct x86_perf_regs *x86_regs_user =3D this_cpu_ptr(&x86_user_regs); + struct perf_regs regs_user; + + x86_pmu_clear_perf_regs(&x86_regs_user->regs); + + perf_get_regs_user(®s_user, regs); + data->regs_user.abi =3D regs_user.abi; + if (regs_user.regs) { + x86_regs_user->regs =3D *regs_user.regs; + data->regs_user.regs =3D &x86_regs_user->regs; + } else { + data->regs_user.regs =3D NULL; + } +} + +/* + * The x86 specific variant of perf_sample_regs_user(). + * Update data->regs_user fields for extended registers (e.g., SIMD). + */ +static void x86_pmu_update_regs_user(struct perf_event *event, + struct perf_sample_data *data, + struct pt_regs *regs) +{ + struct x86_perf_regs *x86_regs_user =3D this_cpu_ptr(&x86_user_regs); + struct perf_event_attr *attr =3D &event->attr; + struct x86_perf_regs *perf_regs; + + /* + * PERF_SAMPLE_REGS_INTR and PERF_SAMPLE_REGS_USER can both be + * requested for one event. Keep user regs in a separate x86_perf_regs + * instance, so intr-reg collection does not overwrite user-reg data. + */ + if (user_mode(regs)) { + x86_pmu_clear_perf_regs(&x86_regs_user->regs); + perf_regs =3D container_of(regs, struct x86_perf_regs, regs); + /* Copy all sampled regs data to x86_regs_user. */ + *x86_regs_user =3D *perf_regs; + data->regs_user.regs =3D &x86_regs_user->regs; + data->regs_user.abi =3D perf_reg_abi(current); + } else if (is_user_task(current)) { + x86_pmu_get_regs_user(data, regs); + } else { + data->regs_user.abi =3D PERF_SAMPLE_REGS_ABI_NONE; + data->regs_user.regs =3D NULL; + } + + data->dyn_size +=3D sizeof(u64); + if (data->regs_user.regs) + data->dyn_size +=3D hweight64(attr->sample_regs_user) * sizeof(u64); + + /* + * Set PERF_SAMPLE_REGS_USER to bypass perf_sample_regs_user() call + * in perf_prepare_sample() function. + */ + data->sample_flags |=3D PERF_SAMPLE_REGS_USER; +} + +/* + * This function retrieves cached user-space fpu registers (XMM/YMM/ZMM). + * If TIF_NEED_FPU_LOAD is set or PMI hits into guest, it indicates that + * the user-space FPU state is cached. Otherwise, the data should be read + * directly from the hardware registers. + */ +static inline u64 x86_pmu_update_user_xregs(struct perf_sample_data *data, + struct pt_regs *regs, + u64 mask, bool from_pebs) +{ + struct x86_perf_regs *perf_regs; + struct xregs_state *xsave; + struct fpu *fpu; + struct fpstate *fps; + u64 user_mask =3D mask; + + if (!is_user_task(current)) + return 0; + + if (data->regs_user.abi =3D=3D PERF_SAMPLE_REGS_ABI_NONE) + return 0; + + /* + * If PEBS hits kernel space, need to re-sample extended + * registers for user space. + */ + if (user_mode(regs)) + user_mask =3D from_pebs ? 0 : mask; + + fpu =3D x86_task_fpu(current); + fps =3D READ_ONCE(fpu->__task_fpstate); + /* + * If fpu->__task_fpstate is set, it points to the cached user + * FPU state (e.g. with KVM guest-state swapping). Otherwise, + * when TIF_NEED_FPU_LOAD is set, fpu->fpstate holds the cached + * user state. If neither is true, the user state is live in hardware. + */ + if (user_mask && (test_thread_flag(TIF_NEED_FPU_LOAD) || fps)) { + perf_regs =3D container_of(data->regs_user.regs, + struct x86_perf_regs, regs); + if (!fps) + fps =3D fpu->fpstate; + xsave =3D &fps->regs.xsave; + + update_perf_regs(perf_regs, xsave, user_mask); + return 0; + } + + return user_mask; +} + static void x86_pmu_sample_xregs(struct perf_event *event, struct perf_sample_data *data, + struct pt_regs *regs, bool from_pebs) { struct xregs_state *xsave =3D get_ext_regs_buf(smp_processor_id()); u64 sample_type =3D event->attr.sample_type; struct x86_perf_regs *perf_regs; u64 intr_mask =3D 0; + u64 user_mask =3D 0; =20 if (WARN_ON_ONCE(!xsave) || !in_nmi()) return; @@ -1852,13 +1961,31 @@ static void x86_pmu_sample_xregs(struct perf_event = *event, intr_mask =3D from_pebs ? 0 : intr_mask; } =20 + if ((sample_type & PERF_SAMPLE_REGS_USER) && data->regs_user.regs) { + if (event->attr.sample_regs_user & PERF_REG_EXTENDED_MASK) + user_mask |=3D XFEATURE_MASK_SSE; + + user_mask &=3D x86_pmu.ext_regs_mask; + user_mask =3D x86_pmu_update_user_xregs(data, regs, + user_mask, from_pebs); + } + + if (user_mask | intr_mask) { + xsave->header.xfeatures =3D 0; + xsaves_nmi(xsave, user_mask | intr_mask); + } + if (intr_mask) { perf_regs =3D container_of(data->regs_intr.regs, struct x86_perf_regs, regs); - xsave->header.xfeatures =3D 0; - xsaves_nmi(xsave, intr_mask); update_perf_regs(perf_regs, xsave, intr_mask); } + + if (user_mask) { + perf_regs =3D container_of(data->regs_user.regs, + struct x86_perf_regs, regs); + update_perf_regs(perf_regs, xsave, user_mask); + } } =20 void x86_pmu_update_perf_regs(struct perf_event *event, @@ -1868,16 +1995,17 @@ void x86_pmu_update_perf_regs(struct perf_event *ev= ent, { u64 sample_type =3D event->attr.sample_type; =20 - if (!((sample_type & PERF_SAMPLE_REGS_INTR) && - (event->attr.sample_regs_intr & PERF_REG_EXTENDED_MASK))) + if (!event_has_extended_regs(event)) return; =20 if (sample_type & PERF_SAMPLE_REGS_INTR) { x86_pmu_update_regs_intr(event, data, regs, event->attr.exclude_kernel); } + if (sample_type & PERF_SAMPLE_REGS_USER) + x86_pmu_update_regs_user(event, data, regs); =20 - x86_pmu_sample_xregs(event, data, from_pebs); + x86_pmu_sample_xregs(event, data, regs, from_pebs); } =20 int x86_pmu_handle_irq(struct pt_regs *regs) diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c index 24f3f49f3953..dbf143eb3547 100644 --- a/arch/x86/events/intel/core.c +++ b/arch/x86/events/intel/core.c @@ -4719,15 +4719,15 @@ static void intel_pebs_aliases_skl(struct perf_even= t *event) static unsigned long intel_pmu_large_pebs_flags(struct perf_event *event) { unsigned long flags =3D x86_pmu.large_pebs_flags; + u64 gprs_mask =3D PEBS_GP_REGS | PERF_REG_EXTENDED_MASK; =20 if (event->attr.use_clockid) flags &=3D ~PERF_SAMPLE_TIME; if (!event->attr.exclude_kernel) flags &=3D ~PERF_SAMPLE_REGS_USER; - if (event->attr.sample_regs_user & ~PEBS_GP_REGS) + if (event->attr.sample_regs_user & ~gprs_mask) flags &=3D ~PERF_SAMPLE_REGS_USER; - if (event->attr.sample_regs_intr & - ~(PEBS_GP_REGS | PERF_REG_EXTENDED_MASK)) + if (event->attr.sample_regs_intr & ~gprs_mask) flags &=3D ~PERF_SAMPLE_REGS_INTR; return flags; } diff --git a/arch/x86/events/intel/ds.c b/arch/x86/events/intel/ds.c index 208584b32878..841b5a2ed89b 100644 --- a/arch/x86/events/intel/ds.c +++ b/arch/x86/events/intel/ds.c @@ -1726,8 +1726,7 @@ static u64 pebs_update_adaptive_cfg(struct perf_event= *event) if (gprs || (attr->precise_ip < 2) || tsx_weight) pebs_data_cfg |=3D PEBS_DATACFG_GP; =20 - if ((sample_type & PERF_SAMPLE_REGS_INTR) && - (attr->sample_regs_intr & PERF_REG_EXTENDED_MASK)) + if (event_has_extended_regs(event)) pebs_data_cfg |=3D PEBS_DATACFG_XMMS; =20 if (sample_type & PERF_SAMPLE_BRANCH_STACK) { @@ -2930,6 +2929,8 @@ __intel_pmu_pebs_events(struct perf_event *event, void *at =3D get_next_pebs_record_by_bit(base, top, bit); int cnt =3D count; =20 + x86_pmu_clear_perf_regs(regs); + if (!iregs) iregs =3D &dummy_iregs; =20 --=20 2.34.1 From nobody Sat Jul 25 01:34:42 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.11]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1C235414DDB; Tue, 21 Jul 2026 06:33:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.11 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784615609; cv=none; b=MGQ1ebUetWHDmNwTY99K9KuTC1upkAzjXQYcdvjMsgRoXJktED5Bfr8hiIgDqdxiUDJ9E42TGrS5AwiHbfhIoAoRJzkHi2017E0GXBTefYohA6H8zpYi1tqD7SkuKz3LzWnDSFWI3IdAK2J+IRzsZBzkhhZfqT92G5KB2LaMJHg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784615609; c=relaxed/simple; bh=wD9ZykwT3oOAX5Uv9pUxInfHRstbJCddayqq9g0kg1U=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=q/HfBLLc7vz+CruSbqYOYflkR3DMNknsXV8L78b94uNC+01dfTy2d+YjqAakFCXxadUaLqDxWTBNsANBVCY1QRw1SpNSZPXWwnt9jWzsnczN44ZwtvZgikrSkXrpKeqFNr/28rEFU7KSfZ2ZXZ4jfHAJ5yGjFFlLYDjSlnKmJcA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=pass smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=P0V+E2ea; arc=none smtp.client-ip=198.175.65.11 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="P0V+E2ea" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1784615608; x=1816151608; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=wD9ZykwT3oOAX5Uv9pUxInfHRstbJCddayqq9g0kg1U=; b=P0V+E2eakNa21pMr6IiY7UBPggKhbUREqmDqrEZAIN/QwhWAAg1cbATh DhGtMnUzjr3H1bvYpIc7pPLcqStDLfvoV3LjGCCEssCAMKtMrARQ6zvxA SULlD2kSHVu0W8GbSTsoVkh9H24utXPz/HYuJ0AZHawRJ7zpjCrtHW23w 3kU3TRYizeg9s3EsZeix8MWLg3O8dAwXD87YeaJEKYrmqxmuMhMWej9ty +MB8taQhRehWiesmYhbmEbKtYWkbe3xrVRxcVNlHflBeBDOpp5zMncvbl jSOYvI83N8eiIuRODYarKhXbNHA+h7P09CIGLQrpz5bxEEMiiHO+Tm0Lu g==; X-CSE-ConnectionGUID: 5GJaKbpBShSVZaInSpDm9w== X-CSE-MsgGUID: y6D8HeRZSx2HhBOl/1S4OQ== X-IronPort-AV: E=McAfee;i="6800,10657,11852"; a="95565469" X-IronPort-AV: E=Sophos;i="6.25,176,1779174000"; d="scan'208";a="95565469" Received: from fmviesa004.fm.intel.com ([10.60.135.144]) by orvoesa103.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Jul 2026 23:33:28 -0700 X-CSE-ConnectionGUID: cmhwg/h9SNmsxkvV08zM/g== X-CSE-MsgGUID: bYBa6I3ESEqghjmEaAncXg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.25,176,1779174000"; d="scan'208";a="259656058" Received: from spr.sh.intel.com ([10.112.229.196]) by fmviesa004.fm.intel.com with ESMTP; 20 Jul 2026 23:33:20 -0700 From: Dapeng Mi To: Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Thomas Gleixner , Dave Hansen , Ian Rogers , Adrian Hunter , Jiri Olsa , Alexander Shishkin , Andi Kleen , Eranian Stephane Cc: Mark Rutland , broonie@kernel.org, Ravi Bangoria , linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org, Zide Chen , Falcon Thomas , Dapeng Mi , Xudong Hao , Kan Liang , Dapeng Mi Subject: [Patch v10 12/23] perf: Add sampling support for SIMD registers Date: Tue, 21 Jul 2026 14:24:55 +0800 Message-Id: <20260721062506.3745816-13-dapeng1.mi@linux.intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260721062506.3745816-1-dapeng1.mi@linux.intel.com> References: <20260721062506.3745816-1-dapeng1.mi@linux.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Kan Liang Users may be interested in sampling SIMD registers during profiling. The current sample_regs_* structure does not have sufficient space for all SIMD registers. To address this, new attribute fields sample_simd_{pred,vec}_reg_* are added to struct perf_event_attr to represent the SIMD registers that are expected to be sampled. Currently, the perf/x86 code supports XMM registers in sample_regs_*. To unify the configuration of SIMD registers and ensure a consistent method for configuring XMM and other SIMD registers, a new event attribute field, sample_simd_regs_enabled, is introduced. When sample_simd_regs_enabled is set, it indicates that all SIMD registers, including XMM, will be represented by the newly introduced sample_simd_{pred|vec}_reg_* fields. The original XMM space in sample_regs_* is reserved for future uses. Since SIMD registers are wider than 64 bits, a new output format is introduced. The number and width of SIMD registers are dumped first, followed by the register values. The number and width are based on the user's configuration. A new ABI, PERF_SAMPLE_REGS_ABI_SIMD, is added to indicate the new format. The enum perf_sample_regs_abi is now a bitmap. This change should not impact existing tools, as the version and bitmap remain the same for values 1 and 2. Additionally, two new __weak functions are introduced: - perf_simd_reg_value(): Retrieves the value of the requested SIMD register. - perf_simd_reg_validate(): Validates the configuration of the SIMD registers. A new flag, PERF_PMU_CAP_SIMD_REGS, is added to indicate that the PMU supports SIMD register dumping. An error is generated if sample_simd_{pred|vec}_reg_* is mistakenly set for a PMU that does not support this capability. Suggested-by: Peter Zijlstra (Intel) Signed-off-by: Kan Liang Co-developed-by: Dapeng Mi Signed-off-by: Dapeng Mi --- include/linux/perf_event.h | 12 +++ include/linux/perf_regs.h | 4 + include/uapi/linux/perf_event.h | 49 ++++++++++- kernel/events/core.c | 141 +++++++++++++++++++++++++++++--- 4 files changed, 192 insertions(+), 14 deletions(-) diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index fb38affa7352..c4e330c121d2 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -306,6 +306,7 @@ struct perf_event_pmu_context; #define PERF_PMU_CAP_AUX_PAUSE 0x0200 #define PERF_PMU_CAP_AUX_PREFER_LARGE 0x0400 #define PERF_PMU_CAP_MEDIATED_VPMU 0x0800 +#define PERF_PMU_CAP_SIMD_REGS 0x1000 =20 /** * pmu::scope @@ -1534,6 +1535,17 @@ perf_event__output_id_sample(struct perf_event *even= t, extern void perf_log_lost_samples(struct perf_event *event, u64 lost); =20 +static inline bool event_has_simd_regs(struct perf_event *event) +{ + struct perf_event_attr *attr =3D &event->attr; + + if (!(event->attr.sample_type & + (PERF_SAMPLE_REGS_INTR | PERF_SAMPLE_REGS_USER))) + return false; + + return attr->sample_simd_regs_enabled !=3D 0; +} + static inline bool event_has_extended_regs(struct perf_event *event) { struct perf_event_attr *attr =3D &event->attr; diff --git a/include/linux/perf_regs.h b/include/linux/perf_regs.h index 144bcc3ff19f..518f28c6a7d4 100644 --- a/include/linux/perf_regs.h +++ b/include/linux/perf_regs.h @@ -14,6 +14,10 @@ int perf_reg_validate(u64 mask); u64 perf_reg_abi(struct task_struct *task); void perf_get_regs_user(struct perf_regs *regs_user, struct pt_regs *regs); +int perf_simd_reg_validate(u16 vec_qwords, u64 vec_mask, + u16 pred_qwords, u32 pred_mask); +u64 perf_simd_reg_value(struct pt_regs *regs, int idx, + u16 qwords_idx, bool pred); =20 #ifdef CONFIG_HAVE_PERF_REGS #include diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_even= t.h index fd10aa8d697f..c49fc76292f7 100644 --- a/include/uapi/linux/perf_event.h +++ b/include/uapi/linux/perf_event.h @@ -314,8 +314,9 @@ enum { */ enum perf_sample_regs_abi { PERF_SAMPLE_REGS_ABI_NONE =3D 0, - PERF_SAMPLE_REGS_ABI_32 =3D 1, - PERF_SAMPLE_REGS_ABI_64 =3D 2, + PERF_SAMPLE_REGS_ABI_32 =3D (1 << 0), + PERF_SAMPLE_REGS_ABI_64 =3D (1 << 1), + PERF_SAMPLE_REGS_ABI_SIMD =3D (1 << 2), }; =20 /* @@ -383,6 +384,7 @@ enum perf_event_read_format { #define PERF_ATTR_SIZE_VER7 128 /* Add: sig_data */ #define PERF_ATTR_SIZE_VER8 136 /* Add: config3 */ #define PERF_ATTR_SIZE_VER9 144 /* add: config4 */ +#define PERF_ATTR_SIZE_VER10 176 /* Add: sample_simd_{vec|pred}_reg_* */ =20 /* * 'struct perf_event_attr' contains various attributes that define @@ -547,6 +549,29 @@ struct perf_event_attr { =20 __u64 config3; /* extension of config2 */ __u64 config4; /* extension of config3 */ + + /* + * Defines the sampling SIMD/PRED(predicate) registers bitmap and + * qwords (8 bytes) length. + * + * sample_simd_regs_enabled !=3D 0 indicates there are SIMD/PRED + * registers to be sampled, the SIMD/PRED registers bitmap and + * qwords length are represented in + * sample_simd_{vec|pred}_reg_{intr|user} and + * sample_simd_{vec|pred}_reg_qwords fields separately. + * + * sample_simd_regs_enabled =3D=3D 0 indicates no SIMD/PRED registers + * are sampled. + */ + __u16 sample_simd_regs_enabled; + __u16 sample_simd_pred_reg_qwords; + __u16 sample_simd_vec_reg_qwords; + __u16 __reserved_4; + + __u32 sample_simd_pred_reg_intr; + __u32 sample_simd_pred_reg_user; + __u64 sample_simd_vec_reg_intr; + __u64 sample_simd_vec_reg_user; }; =20 /* @@ -1020,7 +1045,15 @@ enum perf_event_type { * } && PERF_SAMPLE_BRANCH_STACK * * { u64 abi; # enum perf_sample_regs_abi - * u64 regs[weight(mask)]; } && PERF_SAMPLE_REGS_USER + * u64 regs[weight(mask)]; + * struct { + * u64 nr_vectors; # 0 ... weight(sample_simd_vec_reg_user) + * u64 vector_qwords; # 0 ... sample_simd_vec_reg_qwords + * u64 nr_pred; # 0 ... weight(sample_simd_pred_reg_user) + * u64 pred_qwords; # 0 ... sample_simd_pred_reg_qwords + * u64 data[nr_vectors * vector_qwords + nr_pred * pred_qwords]; + * } && (abi & PERF_SAMPLE_REGS_ABI_SIMD) + * } && PERF_SAMPLE_REGS_USER * * { u64 size; * char data[size]; @@ -1047,7 +1080,15 @@ enum perf_event_type { * { u64 data_src; } && PERF_SAMPLE_DATA_SRC * { u64 transaction; } && PERF_SAMPLE_TRANSACTION * { u64 abi; # enum perf_sample_regs_abi - * u64 regs[weight(mask)]; } && PERF_SAMPLE_REGS_INTR + * u64 regs[weight(mask)]; + * struct { + * u64 nr_vectors; # 0 ... weight(sample_simd_vec_reg_intr) + * u64 vector_qwords; # 0 ... sample_simd_vec_reg_qwords + * u64 nr_pred; # 0 ... weight(sample_simd_pred_reg_intr) + * u64 pred_qwords; # 0 ... sample_simd_pred_reg_qwords + * u64 data[nr_vectors * vector_qwords + nr_pred * pred_qwords]; + * } && (abi & PERF_SAMPLE_REGS_ABI_SIMD) + * } && PERF_SAMPLE_REGS_INTR * { u64 phys_addr;} && PERF_SAMPLE_PHYS_ADDR * { u64 cgroup;} && PERF_SAMPLE_CGROUP * { u64 data_page_size;} && PERF_SAMPLE_DATA_PAGE_SIZE diff --git a/kernel/events/core.c b/kernel/events/core.c index 7848e9ac06ca..5fcbdbc1e56c 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -7829,22 +7829,60 @@ void __weak perf_get_regs_user(struct perf_regs *re= gs_user, regs_user->abi =3D perf_reg_abi(current); } =20 +#define word_for_each_set_bit(bit, val) \ + for (unsigned long long __v =3D (val); \ + __v && ((bit =3D __builtin_ctzll(__v)), 1); \ + __v &=3D __v - 1) + static void perf_output_sample_regs(struct perf_output_handle *handle, struct pt_regs *regs, u64 mask) { int bit; - DECLARE_BITMAP(_mask, 64); - - bitmap_from_u64(_mask, mask); - for_each_set_bit(bit, _mask, sizeof(mask) * BITS_PER_BYTE) { - u64 val; =20 - val =3D perf_reg_value(regs, bit); + word_for_each_set_bit(bit, mask) { + u64 val =3D perf_reg_value(regs, bit); perf_output_put(handle, val); } } =20 +static void +perf_output_sample_simd_regs(struct perf_output_handle *handle, + struct perf_event *event, + struct pt_regs *regs, + u64 mask, u32 pred_mask) +{ + u64 pred_qwords =3D event->attr.sample_simd_pred_reg_qwords; + u64 vec_qwords =3D event->attr.sample_simd_vec_reg_qwords; + u64 nr_vectors =3D hweight64(mask); + u64 nr_pred =3D hweight32(pred_mask); + int bit; + + perf_output_put(handle, nr_vectors); + perf_output_put(handle, vec_qwords); + perf_output_put(handle, nr_pred); + perf_output_put(handle, pred_qwords); + + if (nr_vectors) { + word_for_each_set_bit(bit, mask) { + for (int i =3D 0; i < vec_qwords; i++) { + u64 val =3D perf_simd_reg_value(regs, bit, + i, false); + perf_output_put(handle, val); + } + } + } + if (nr_pred) { + word_for_each_set_bit(bit, pred_mask) { + for (int i =3D 0; i < pred_qwords; i++) { + u64 val =3D perf_simd_reg_value(regs, bit, + i, true); + perf_output_put(handle, val); + } + } + } +} + static void perf_sample_regs_user(struct perf_regs *regs_user, struct pt_regs *regs) { @@ -7878,6 +7916,17 @@ static void perf_sample_regs_intr(struct perf_regs *= regs_intr, } } =20 +int __weak perf_simd_reg_validate(u16 vec_qwords, u64 vec_mask, + u16 pred_qwords, u32 pred_mask) +{ + return -EINVAL; +} + +u64 __weak perf_simd_reg_value(struct pt_regs *regs, int idx, + u16 qwords_idx, bool pred) +{ + return 0; +} =20 /* * Get remaining task size from user stack pointer. @@ -8408,10 +8457,17 @@ void perf_output_sample(struct perf_output_handle *= handle, perf_output_put(handle, abi); =20 if (abi) { - u64 mask =3D event->attr.sample_regs_user; + struct perf_event_attr *attr =3D &event->attr; + u64 mask =3D attr->sample_regs_user; perf_output_sample_regs(handle, data->regs_user.regs, mask); + if (abi & PERF_SAMPLE_REGS_ABI_SIMD) { + perf_output_sample_simd_regs(handle, event, + data->regs_user.regs, + attr->sample_simd_vec_reg_user, + attr->sample_simd_pred_reg_user); + } } } =20 @@ -8439,11 +8495,18 @@ void perf_output_sample(struct perf_output_handle *= handle, perf_output_put(handle, abi); =20 if (abi) { - u64 mask =3D event->attr.sample_regs_intr; + struct perf_event_attr *attr =3D &event->attr; + u64 mask =3D attr->sample_regs_intr; =20 perf_output_sample_regs(handle, data->regs_intr.regs, mask); + if (abi & PERF_SAMPLE_REGS_ABI_SIMD) { + perf_output_sample_simd_regs(handle, event, + data->regs_intr.regs, + attr->sample_simd_vec_reg_intr, + attr->sample_simd_pred_reg_intr); + } } } =20 @@ -8646,6 +8709,29 @@ static __always_inline u64 __cond_set(u64 flags, u64= s, u64 d) return d * !!(flags & s); } =20 +static u64 perf_update_xregs_size(struct perf_event *event, bool intr) +{ + u16 pred_qwords =3D event->attr.sample_simd_pred_reg_qwords; + u16 vec_qwords =3D event->attr.sample_simd_vec_reg_qwords; + u64 pred_mask; + u64 mask; + int size; + + if (intr) { + mask =3D event->attr.sample_simd_vec_reg_intr; + pred_mask =3D event->attr.sample_simd_pred_reg_intr; + } else { + mask =3D event->attr.sample_simd_vec_reg_user; + pred_mask =3D event->attr.sample_simd_pred_reg_user; + } + + size =3D sizeof(u64) * 4; + size +=3D (hweight64(mask) * vec_qwords + + hweight64(pred_mask) * pred_qwords) * sizeof(u64); + + return size; +} + void perf_prepare_sample(struct perf_sample_data *data, struct perf_event *event, struct pt_regs *regs) @@ -8708,7 +8794,12 @@ void perf_prepare_sample(struct perf_sample_data *da= ta, =20 if (data->regs_user.regs) { u64 mask =3D event->attr.sample_regs_user; + size +=3D hweight64(mask) * sizeof(u64); + if (event_has_simd_regs(event)) { + size +=3D perf_update_xregs_size(event, false); + data->regs_user.abi |=3D PERF_SAMPLE_REGS_ABI_SIMD; + } } =20 data->dyn_size +=3D size; @@ -8773,6 +8864,10 @@ void perf_prepare_sample(struct perf_sample_data *da= ta, u64 mask =3D event->attr.sample_regs_intr; =20 size +=3D hweight64(mask) * sizeof(u64); + if (event_has_simd_regs(event)) { + size +=3D perf_update_xregs_size(event, true); + data->regs_intr.abi |=3D PERF_SAMPLE_REGS_ABI_SIMD; + } } =20 data->dyn_size +=3D size; @@ -13149,6 +13244,12 @@ static int perf_try_init_event(struct pmu *pmu, st= ruct perf_event *event) if (ret) goto err_pmu; =20 + if (!(pmu->capabilities & PERF_PMU_CAP_SIMD_REGS) && + event_has_simd_regs(event)) { + ret =3D -EOPNOTSUPP; + goto err_destroy; + } + if (!(pmu->capabilities & PERF_PMU_CAP_EXTENDED_REGS) && event_has_extended_regs(event)) { ret =3D -EOPNOTSUPP; @@ -13645,7 +13746,8 @@ static int perf_copy_attr(struct perf_event_attr __= user *uattr, =20 attr->size =3D size; =20 - if (attr->__reserved_1 || attr->__reserved_2 || attr->__reserved_3) + if (attr->__reserved_1 || attr->__reserved_2 || + attr->__reserved_3 || attr->__reserved_4) return -EINVAL; =20 if (attr->sample_type & ~(PERF_SAMPLE_MAX-1)) @@ -13694,6 +13796,14 @@ static int perf_copy_attr(struct perf_event_attr _= _user *uattr, ret =3D perf_reg_validate(attr->sample_regs_user); if (ret) return ret; + if (attr->sample_simd_regs_enabled) { + ret =3D perf_simd_reg_validate(attr->sample_simd_vec_reg_qwords, + attr->sample_simd_vec_reg_user, + attr->sample_simd_pred_reg_qwords, + attr->sample_simd_pred_reg_user); + if (ret) + return ret; + } } =20 if (attr->sample_type & PERF_SAMPLE_STACK_USER) { @@ -13714,8 +13824,19 @@ static int perf_copy_attr(struct perf_event_attr _= _user *uattr, if (!attr->sample_max_stack) attr->sample_max_stack =3D sysctl_perf_event_max_stack; =20 - if (attr->sample_type & PERF_SAMPLE_REGS_INTR) + if (attr->sample_type & PERF_SAMPLE_REGS_INTR) { ret =3D perf_reg_validate(attr->sample_regs_intr); + if (ret) + return ret; + if (attr->sample_simd_regs_enabled) { + ret =3D perf_simd_reg_validate(attr->sample_simd_vec_reg_qwords, + attr->sample_simd_vec_reg_intr, + attr->sample_simd_pred_reg_qwords, + attr->sample_simd_pred_reg_intr); + if (ret) + return ret; + } + } =20 #ifndef CONFIG_CGROUP_PERF if (attr->sample_type & PERF_SAMPLE_CGROUP) --=20 2.34.1 From nobody Sat Jul 25 01:34:42 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.11]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 74CD1432E75; Tue, 21 Jul 2026 06:33:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.11 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784615617; cv=none; b=OU/OFY7hjdkLc34vcatZk90CDKO/SOKpxwcQXWaQYHC+aiJ7mzUUiLmKjk/9BoVVYUqejm8VEAqsUQ3w1HDdlvGT7+lNY4aWIKxJUBQv5ILWSfAd9x971iLlOveAF3AGqII5pNd19ARLLlIWlIghzRX2udprYIKKEMMJOOBtPtE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784615617; c=relaxed/simple; bh=nxk8ZobF0sY8dIk9ySXxjgVM5BzFi43tOsjrJqeffQE=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=sRwatjo2MXZR6QyERffeGx1j1aEGJfEgwIdkVsgWXPZ2qPGwgoMGINxVnaVdt/QnQBmpMI3Fvu8lGgzqBrOoLpYW6x93gQ+Ii6JoFNItBDnHOIQXInBzA+jlKp8eaRVQYBk/A0ow8KY0J/M2y7A0nf09PJBXpo583sMOxyDXX6Q= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=pass smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=NDp+ejYh; arc=none smtp.client-ip=198.175.65.11 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="NDp+ejYh" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1784615615; x=1816151615; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=nxk8ZobF0sY8dIk9ySXxjgVM5BzFi43tOsjrJqeffQE=; b=NDp+ejYhbffIJDRxpmXXtt3dLsDCShEHRzsjOcdZuSeGxvhSSgPOXj+z yWnh8Hgn0qcQ5eHfZao4gyGbgka9ErR59kTDwIJoblUvWOKQy6k166qqo 1zqYTjUn2OKdWH5g/nLepp9FafFyIKdrYddXqsXDrTGA7blYU8taEu/+o fATkjGBqgMIAe40QVApA0Kj0wwh8OTz4rHEW2GWIbyhGMZ/7xWAMo0/no 9POUYEBGlr45GGBY1/tMshbUpWcjKGUTlMSN+3Hy+uY08zOgvu9cCSFdq FAOmkkVOxT/BOGvvh5ZoxIS47wabgqS830Lyq9n7QsXAbN9O93+ninvnN g==; X-CSE-ConnectionGUID: otjpLSlFTnWsjHrMmw1n4w== X-CSE-MsgGUID: HF5O8tr1TRi1MaDk3UOGjg== X-IronPort-AV: E=McAfee;i="6800,10657,11852"; a="95565476" X-IronPort-AV: E=Sophos;i="6.25,176,1779174000"; d="scan'208";a="95565476" Received: from fmviesa004.fm.intel.com ([10.60.135.144]) by orvoesa103.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Jul 2026 23:33:35 -0700 X-CSE-ConnectionGUID: 48y/bjShQHyH7wVpKNH0WA== X-CSE-MsgGUID: nXAR//SGRFunXYszvpN1Ig== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.25,176,1779174000"; d="scan'208";a="259656071" Received: from spr.sh.intel.com ([10.112.229.196]) by fmviesa004.fm.intel.com with ESMTP; 20 Jul 2026 23:33:28 -0700 From: Dapeng Mi To: Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Thomas Gleixner , Dave Hansen , Ian Rogers , Adrian Hunter , Jiri Olsa , Alexander Shishkin , Andi Kleen , Eranian Stephane Cc: Mark Rutland , broonie@kernel.org, Ravi Bangoria , linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org, Zide Chen , Falcon Thomas , Dapeng Mi , Xudong Hao , Dapeng Mi , Kan Liang Subject: [Patch v10 13/23] perf/x86: Support XMM sampling using sample_simd_vec_reg_* fields Date: Tue, 21 Jul 2026 14:24:56 +0800 Message-Id: <20260721062506.3745816-14-dapeng1.mi@linux.intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260721062506.3745816-1-dapeng1.mi@linux.intel.com> References: <20260721062506.3745816-1-dapeng1.mi@linux.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Support sampling of XMM registers using the sample_simd_vec_reg_* fields. When sample_simd_regs_enabled is set, the original XMM space in the sample_regs_* field is treated as reserved. An INVAL error will be reported to user space if any bit is set in the original XMM space while sample_simd_regs_enabled is set. The perf_reg_value function requires ABI information to understand the layout of sample_regs. To accommodate this, a new abi field is introduced in the struct x86_perf_regs to represent ABI information. Additionally, the x86 specific perf_simd_reg_value() function is implemented to retrieve the XMM register values. XMM sampling will be enabled in a subsequent patch that sets PERF_PMU_CAP_SIMD_REGS. Co-developed-by: Kan Liang Signed-off-by: Kan Liang Signed-off-by: Dapeng Mi --- arch/x86/events/core.c | 84 +++++++++++++++++++++++---- arch/x86/events/intel/ds.c | 6 +- arch/x86/events/perf_event.h | 36 ++++++++++++ arch/x86/include/asm/perf_event.h | 1 + arch/x86/include/uapi/asm/perf_regs.h | 15 +++++ arch/x86/kernel/perf_regs.c | 75 +++++++++++++++++++++++- include/linux/perf_event.h | 1 + kernel/events/core.c | 2 +- 8 files changed, 204 insertions(+), 16 deletions(-) diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c index 20140643e21c..f85163b95cfc 100644 --- a/arch/x86/events/core.c +++ b/arch/x86/events/core.c @@ -632,6 +632,34 @@ int x86_pmu_max_precise(struct pmu *pmu) return precise; } =20 +static int pebs_simd_regs_validate(struct perf_event *event) +{ + u64 caps =3D hybrid(event->pmu, arch_pebs_cap).caps; + + if (event_needs_xmm(event) && + !x86_pmu.arch_pebs && !x86_pmu.intel_cap.pebs_baseline) + return -EINVAL; + if (event_needs_xmm(event) && + x86_pmu.arch_pebs && !(caps & ARCH_PEBS_VECR_XMM)) + return -EINVAL; + + return 0; +} + +static int event_simd_regs_validate(struct perf_event *event) +{ + if (!get_ext_regs_buf(raw_smp_processor_id())) + return -ENOMEM; + /* sample_simd_regs_enabled repurposes legacy XMM reg-mask slots. */ + if (event_has_extended_regs(event)) + return -EINVAL; + if (event_needs_xmm(event) && + !(x86_pmu.ext_regs_mask & XFEATURE_MASK_SSE)) + return -EINVAL; + + return 0; +} + int x86_pmu_hw_config(struct perf_event *event) { if (event->attr.precise_ip) { @@ -703,11 +731,21 @@ int x86_pmu_hw_config(struct perf_event *event) } =20 if (event->attr.sample_type & (PERF_SAMPLE_REGS_INTR | PERF_SAMPLE_REGS_U= SER)) { - /* - * Besides the general purpose registers, XMM registers may - * be collected as well. - */ - if (event_has_extended_regs(event)) { + int ret; + + if (event->attr.sample_simd_regs_enabled) { + if (!(event->pmu->capabilities & PERF_PMU_CAP_SIMD_REGS)) + return -EINVAL; + + if (event->attr.precise_ip) { + ret =3D pebs_simd_regs_validate(event); + if (ret) + return ret; + } + ret =3D event_simd_regs_validate(event); + if (ret) + return ret; + } else if (event_has_extended_regs(event)) { if (!(event->pmu->capabilities & PERF_PMU_CAP_EXTENDED_REGS)) return -EINVAL; =20 @@ -721,6 +759,8 @@ int x86_pmu_hw_config(struct perf_event *event) } if (!get_ext_regs_buf(raw_smp_processor_id())) return -ENOMEM; + if (!(x86_pmu.ext_regs_mask & XFEATURE_MASK_SSE)) + return -EINVAL; } } =20 @@ -1777,6 +1817,7 @@ void x86_pmu_clear_perf_regs(struct pt_regs *regs) { struct x86_perf_regs *perf_regs =3D container_of(regs, struct x86_perf_re= gs, regs); =20 + perf_regs->abi =3D PERF_SAMPLE_REGS_ABI_NONE; perf_regs->xmm_regs =3D NULL; } =20 @@ -1797,14 +1838,15 @@ static void update_perf_regs(struct x86_perf_regs *= perf_regs, =20 /* * The x86 specific variant of perf_sample_regs_intr(). - * It would be extended to add more SIMD registers sampling support - * in later patches. + * Update data->regs_intr fields for extended registers (e.g., SIMD). */ static void x86_pmu_update_regs_intr(struct perf_event *event, struct perf_sample_data *data, struct pt_regs *regs, bool exclude_kernel) { + struct x86_perf_regs *perf_regs; + if (exclude_kernel && !user_mode(regs)) { data->regs_intr.regs =3D NULL; data->regs_intr.abi =3D PERF_SAMPLE_REGS_ABI_NONE; @@ -1817,6 +1859,14 @@ static void x86_pmu_update_regs_intr(struct perf_eve= nt *event, if (data->regs_intr.regs) { data->dyn_size +=3D hweight64(event->attr.sample_regs_intr) * sizeof(u64); + if (event_has_simd_regs(event)) { + data->dyn_size +=3D perf_update_xregs_size(event, true); + data->regs_intr.abi |=3D PERF_SAMPLE_REGS_ABI_SIMD; + } + + perf_regs =3D container_of(data->regs_intr.regs, + struct x86_perf_regs, regs); + perf_regs->abi =3D data->regs_intr.abi; } =20 /* @@ -1878,8 +1928,15 @@ static void x86_pmu_update_regs_user(struct perf_eve= nt *event, } =20 data->dyn_size +=3D sizeof(u64); - if (data->regs_user.regs) + if (data->regs_user.regs) { data->dyn_size +=3D hweight64(attr->sample_regs_user) * sizeof(u64); + if (event_has_simd_regs(event)) { + data->dyn_size +=3D perf_update_xregs_size(event, false); + data->regs_user.abi |=3D PERF_SAMPLE_REGS_ABI_SIMD; + } + + x86_regs_user->abi =3D data->regs_user.abi; + } =20 /* * Set PERF_SAMPLE_REGS_USER to bypass perf_sample_regs_user() call @@ -1954,7 +2011,7 @@ static void x86_pmu_sample_xregs(struct perf_event *e= vent, return; =20 if ((sample_type & PERF_SAMPLE_REGS_INTR) && data->regs_intr.regs) { - if (event->attr.sample_regs_intr & PERF_REG_EXTENDED_MASK) + if (__event_needs_xmm(event, PERF_SAMPLE_REGS_INTR)) intr_mask |=3D XFEATURE_MASK_SSE; =20 intr_mask &=3D x86_pmu.ext_regs_mask; @@ -1962,7 +2019,7 @@ static void x86_pmu_sample_xregs(struct perf_event *e= vent, } =20 if ((sample_type & PERF_SAMPLE_REGS_USER) && data->regs_user.regs) { - if (event->attr.sample_regs_user & PERF_REG_EXTENDED_MASK) + if (__event_needs_xmm(event, PERF_SAMPLE_REGS_USER)) user_mask |=3D XFEATURE_MASK_SSE; =20 user_mask &=3D x86_pmu.ext_regs_mask; @@ -1995,7 +2052,12 @@ void x86_pmu_update_perf_regs(struct perf_event *eve= nt, { u64 sample_type =3D event->attr.sample_type; =20 - if (!event_has_extended_regs(event)) + if (!(sample_type & + (PERF_SAMPLE_REGS_INTR | PERF_SAMPLE_REGS_USER))) + return; + + if (!event_needs_xmm(event) && + !event_has_simd_regs(event)) return; =20 if (sample_type & PERF_SAMPLE_REGS_INTR) { diff --git a/arch/x86/events/intel/ds.c b/arch/x86/events/intel/ds.c index 841b5a2ed89b..eb61eae9226d 100644 --- a/arch/x86/events/intel/ds.c +++ b/arch/x86/events/intel/ds.c @@ -1726,8 +1726,10 @@ static u64 pebs_update_adaptive_cfg(struct perf_even= t *event) if (gprs || (attr->precise_ip < 2) || tsx_weight) pebs_data_cfg |=3D PEBS_DATACFG_GP; =20 - if (event_has_extended_regs(event)) - pebs_data_cfg |=3D PEBS_DATACFG_XMMS; + if (sample_type & (PERF_SAMPLE_REGS_INTR | PERF_SAMPLE_REGS_USER)) { + if (event_needs_xmm(event)) + pebs_data_cfg |=3D PEBS_DATACFG_XMMS; + } =20 if (sample_type & PERF_SAMPLE_BRANCH_STACK) { /* diff --git a/arch/x86/events/perf_event.h b/arch/x86/events/perf_event.h index c2b0df0051b8..23c5907e8b85 100644 --- a/arch/x86/events/perf_event.h +++ b/arch/x86/events/perf_event.h @@ -147,6 +147,42 @@ static inline bool is_acr_self_reload_event(struct per= f_event *event) return test_bit(hwc->idx, (unsigned long *)&hwc->config1); } =20 +static inline bool __event_needs_xmm(struct perf_event *event, u64 sample_= type) +{ + if (event->attr.sample_simd_regs_enabled) { + if (event->attr.sample_simd_vec_reg_qwords < PERF_X86_XMM_QWORDS) + return false; + + if ((sample_type & PERF_SAMPLE_REGS_USER) && + (event->attr.sample_type & PERF_SAMPLE_REGS_USER) && + (event->attr.sample_simd_vec_reg_user > 0)) + return true; + + if ((sample_type & PERF_SAMPLE_REGS_INTR) && + (event->attr.sample_type & PERF_SAMPLE_REGS_INTR) && + (event->attr.sample_simd_vec_reg_intr > 0)) + return true; + } else { + if ((sample_type & PERF_SAMPLE_REGS_USER) && + (event->attr.sample_type & PERF_SAMPLE_REGS_USER) && + (event->attr.sample_regs_user & PERF_REG_EXTENDED_MASK)) + return true; + + if ((sample_type & PERF_SAMPLE_REGS_INTR) && + (event->attr.sample_type & PERF_SAMPLE_REGS_INTR) && + (event->attr.sample_regs_intr & PERF_REG_EXTENDED_MASK)) + return true; + } + + return false; +} + +static inline bool event_needs_xmm(struct perf_event *event) +{ + return __event_needs_xmm(event, + PERF_SAMPLE_REGS_INTR | PERF_SAMPLE_REGS_USER); +} + struct amd_nb { int nb_id; /* NorthBridge id */ int refcnt; /* reference count */ diff --git a/arch/x86/include/asm/perf_event.h b/arch/x86/include/asm/perf_= event.h index 619e0ae915e1..a2b2123d008e 100644 --- a/arch/x86/include/asm/perf_event.h +++ b/arch/x86/include/asm/perf_event.h @@ -728,6 +728,7 @@ extern void perf_events_lapic_init(void); struct pt_regs; struct x86_perf_regs { struct pt_regs regs; + u64 abi; union { u64 *xmm_regs; u32 *xmm_space; /* for xsaves */ diff --git a/arch/x86/include/uapi/asm/perf_regs.h b/arch/x86/include/uapi/= asm/perf_regs.h index 7c9d2bb3833b..edb35408e4cc 100644 --- a/arch/x86/include/uapi/asm/perf_regs.h +++ b/arch/x86/include/uapi/asm/perf_regs.h @@ -2,6 +2,8 @@ #ifndef _ASM_X86_PERF_REGS_H #define _ASM_X86_PERF_REGS_H =20 +#include + enum perf_event_x86_regs { PERF_REG_X86_AX, PERF_REG_X86_BX, @@ -55,4 +57,17 @@ enum perf_event_x86_regs { =20 #define PERF_REG_EXTENDED_MASK (~((1ULL << PERF_REG_X86_XMM0) - 1)) =20 +enum { + PERF_X86_SIMD_XMM_REGS =3D 16, + PERF_X86_SIMD_VEC_REGS_MAX =3D PERF_X86_SIMD_XMM_REGS, +}; + +#define PERF_X86_SIMD_VEC_MASK __GENMASK_ULL(PERF_X86_SIMD_VEC_REGS_MAX - = 1, 0) + +enum { + /* 1 qword =3D 8 bytes */ + PERF_X86_XMM_QWORDS =3D 2, + PERF_X86_SIMD_QWORDS_MAX =3D PERF_X86_XMM_QWORDS, +}; + #endif /* _ASM_X86_PERF_REGS_H */ diff --git a/arch/x86/kernel/perf_regs.c b/arch/x86/kernel/perf_regs.c index 81204cb7f723..bccf0fc27511 100644 --- a/arch/x86/kernel/perf_regs.c +++ b/arch/x86/kernel/perf_regs.c @@ -63,6 +63,9 @@ u64 perf_reg_value(struct pt_regs *regs, int idx) =20 if (idx >=3D PERF_REG_X86_XMM0 && idx < PERF_REG_X86_XMM_MAX) { perf_regs =3D container_of(regs, struct x86_perf_regs, regs); + /* SIMD registers are moved to dedicated sample_simd_vec_reg */ + if (perf_regs->abi & PERF_SAMPLE_REGS_ABI_SIMD) + return 0; if (!perf_regs->xmm_regs) return 0; return perf_regs->xmm_regs[idx - PERF_REG_X86_XMM0]; @@ -74,6 +77,72 @@ u64 perf_reg_value(struct pt_regs *regs, int idx) return regs_get_register(regs, pt_regs_offset[idx]); } =20 +u64 perf_simd_reg_value(struct pt_regs *regs, int idx, + u16 qwords_idx, bool pred) +{ + struct x86_perf_regs *perf_regs =3D + container_of(regs, struct x86_perf_regs, regs); + + if (!(perf_regs->abi & PERF_SAMPLE_REGS_ABI_SIMD)) + return 0; + + if (pred) + return 0; + + if (WARN_ON_ONCE(idx >=3D PERF_X86_SIMD_VEC_REGS_MAX || + qwords_idx >=3D PERF_X86_SIMD_QWORDS_MAX)) + return 0; + + if (qwords_idx < PERF_X86_XMM_QWORDS) { + if (!perf_regs->xmm_regs) + return 0; + return perf_regs->xmm_regs[idx * PERF_X86_XMM_QWORDS + + qwords_idx]; + } + + return 0; +} + +int perf_simd_reg_validate(u16 vec_qwords, u64 vec_mask, + u16 pred_qwords, u32 pred_mask) +{ + unsigned long mask; + u64 size; + + if (!vec_qwords && !pred_qwords) { + if (vec_mask || pred_mask) + return -EINVAL; + } + + if (vec_qwords) { + if (vec_qwords !=3D PERF_X86_XMM_QWORDS) + return -EINVAL; + if (vec_mask & ~PERF_X86_SIMD_VEC_MASK) + return -EINVAL; + /* Only full-register sampling is allowed. */ + mask =3D vec_mask; + if (vec_qwords =3D=3D PERF_X86_XMM_QWORDS && mask && + !bitmap_full(&mask, PERF_X86_SIMD_XMM_REGS)) + return -EINVAL; + } + + /* PRED registers are not supported yet. */ + if (pred_qwords) + return -EINVAL; + + size =3D sizeof(u64) * 4; + size +=3D (hweight64(vec_mask) * vec_qwords + + hweight32(pred_mask) * pred_qwords) * sizeof(u64); + /* + * INTR_REGS and USR_REGS could be sampled simultaneously, + * so roughly restrict the size to half of U16_MAX. + */ + if (size >=3D U16_MAX / 2) + return -EINVAL; + + return 0; +} + #define PERF_REG_X86_RESERVED (((1ULL << PERF_REG_X86_XMM0) - 1) & \ ~((1ULL << PERF_REG_X86_MAX) - 1)) =20 @@ -89,7 +158,8 @@ u64 perf_reg_value(struct pt_regs *regs, int idx) =20 int perf_reg_validate(u64 mask) { - if (!mask || (mask & (REG_NOSUPPORT | PERF_REG_X86_RESERVED))) + /* The mask could be 0 if only the SIMD registers are interested */ + if (mask & (REG_NOSUPPORT | PERF_REG_X86_RESERVED)) return -EINVAL; =20 return 0; @@ -108,7 +178,8 @@ u64 perf_reg_abi(struct task_struct *task) =20 int perf_reg_validate(u64 mask) { - if (!mask || (mask & (REG_NOSUPPORT | PERF_REG_X86_RESERVED))) + /* The mask could be 0 if only the SIMD registers are interested */ + if (mask & (REG_NOSUPPORT | PERF_REG_X86_RESERVED)) return -EINVAL; =20 return 0; diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index c4e330c121d2..e40d60ccab9e 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -1485,6 +1485,7 @@ static inline void perf_clear_branch_entry_bitfields(= struct perf_branch_entry *b br->reserved =3D 0; } =20 +extern u64 perf_update_xregs_size(struct perf_event *event, bool intr); extern void perf_output_sample(struct perf_output_handle *handle, struct perf_event_header *header, struct perf_sample_data *data, diff --git a/kernel/events/core.c b/kernel/events/core.c index 5fcbdbc1e56c..8f0018f061bd 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -8709,7 +8709,7 @@ static __always_inline u64 __cond_set(u64 flags, u64 = s, u64 d) return d * !!(flags & s); } =20 -static u64 perf_update_xregs_size(struct perf_event *event, bool intr) +u64 perf_update_xregs_size(struct perf_event *event, bool intr) { u16 pred_qwords =3D event->attr.sample_simd_pred_reg_qwords; u16 vec_qwords =3D event->attr.sample_simd_vec_reg_qwords; --=20 2.34.1 From nobody Sat Jul 25 01:34:42 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.11]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 23498433022; Tue, 21 Jul 2026 06:33:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.11 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784615623; cv=none; b=WgnGTqyqqhbFQT9sFidDr3JmJAClXc989MI9WWxxhiEtmRqk3kWGqKt1TjxH7uyuoX1K8ChRHnlgvqH7cVB6b3FIaBkmWqgU8rLe95ZDorQrZ/jb6QITHwW5md3wlPgjztCyKBwQXCSHhF/Afg12HUd42NE12mlPg0Xa0dHgRLk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784615623; c=relaxed/simple; bh=N8X3dFNKXCrsuVRTXjtyz/tr6AKJiycMVMdHieYv8QA=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=nRij6WaNkNxpbpoYfL6Il2o4L+t4zYnS5Glf+XZYQQFs6X0Geml0ChH4pprtegjT9Beq6zvpeWongHlW2MFg+bLi7xNbdQpXgLLxGXRWGxvw2lBV8252RJL59wrvYtUd2z2GaCHEB4jME5nS8OYCtQY0GS+A1O7ULC91MUcnhHo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=pass smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=GgB6iw5v; arc=none smtp.client-ip=198.175.65.11 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="GgB6iw5v" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1784615622; x=1816151622; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=N8X3dFNKXCrsuVRTXjtyz/tr6AKJiycMVMdHieYv8QA=; b=GgB6iw5vrCVenyCHSPO4uap/D2pnxXgcf6VsbexDoit5zYU+g6w6C/Vq LViKFhIDIuybt1mItazfzwFfdZ5Scz7e6Uvhl7CKH9OO2kW3VnsF0ssV1 O+pge3hANXiFJkMN8f8TkTSBxZ/ToSwuv3mF13Sz69Y4gI/xgFUEYG6C6 rSAQgsc0Vdl+oE+HN4WjyEC8tFYYWZks5osysu8zLCSFlDgdo8j3zkPuk DJ79ZPzoiyfzZ0bBGg9XvV8VYJ8qtpnzv/zuQ7x54/Cu0KhFL2uLSZT5m Imyt8lNOK4T43H5igu+XxvwpN/qpFvgJdVZEBjZ37H489jaEVNUL0yIDw g==; X-CSE-ConnectionGUID: /Qt8Uwy9T1qZjpu5Dg79kQ== X-CSE-MsgGUID: wfpRB3GLQiCjpdAT+Uzkag== X-IronPort-AV: E=McAfee;i="6800,10657,11852"; a="95565487" X-IronPort-AV: E=Sophos;i="6.25,176,1779174000"; d="scan'208";a="95565487" Received: from fmviesa004.fm.intel.com ([10.60.135.144]) by orvoesa103.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Jul 2026 23:33:42 -0700 X-CSE-ConnectionGUID: NkgpIswHQYKi+oLdcdSl2A== X-CSE-MsgGUID: gk0Njrf8SV2S9FDhysX/Ng== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.25,176,1779174000"; d="scan'208";a="259656085" Received: from spr.sh.intel.com ([10.112.229.196]) by fmviesa004.fm.intel.com with ESMTP; 20 Jul 2026 23:33:35 -0700 From: Dapeng Mi To: Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Thomas Gleixner , Dave Hansen , Ian Rogers , Adrian Hunter , Jiri Olsa , Alexander Shishkin , Andi Kleen , Eranian Stephane Cc: Mark Rutland , broonie@kernel.org, Ravi Bangoria , linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org, Zide Chen , Falcon Thomas , Dapeng Mi , Xudong Hao , Dapeng Mi , Kan Liang Subject: [Patch v10 14/23] perf/x86: Support YMM sampling using sample_simd_vec_reg_* fields Date: Tue, 21 Jul 2026 14:24:57 +0800 Message-Id: <20260721062506.3745816-15-dapeng1.mi@linux.intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260721062506.3745816-1-dapeng1.mi@linux.intel.com> References: <20260721062506.3745816-1-dapeng1.mi@linux.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Support sampling of YMM registers via the sample_simd_vec_reg_* fields. Each YMM register consists of 4 u64 words, assembled from two halves: XMM (the lower 2 u64 words) and YMMH (the upper 2 u64 words). Although both XMM and YMMH data can be retrieved with a single xsaves instruction, they are stored in separate locations. The perf_simd_reg_value() function is responsible for assembling these halves into a complete YMM register for output to userspace. Additionally, sample_simd_vec_reg_qwords should be set to 4 to indicate YMM sampling. YMM sampling will be enabled in a subsequent patch that sets PERF_PMU_CAP_SIMD_REGS. Co-developed-by: Kan Liang Signed-off-by: Kan Liang Signed-off-by: Dapeng Mi --- arch/x86/events/core.c | 29 +++++++++++++++++++++------ arch/x86/events/perf_event.h | 26 ++++++++++++++++++++++++ arch/x86/include/asm/perf_event.h | 4 ++++ arch/x86/include/uapi/asm/perf_regs.h | 6 ++++-- arch/x86/kernel/perf_regs.c | 13 +++++++++++- 5 files changed, 69 insertions(+), 9 deletions(-) diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c index f85163b95cfc..3039a311e733 100644 --- a/arch/x86/events/core.c +++ b/arch/x86/events/core.c @@ -642,6 +642,9 @@ static int pebs_simd_regs_validate(struct perf_event *e= vent) if (event_needs_xmm(event) && x86_pmu.arch_pebs && !(caps & ARCH_PEBS_VECR_XMM)) return -EINVAL; + /* PEBS does not support YMM registers sampling yet. */ + if (event_needs_ymm(event)) + return -EINVAL; =20 return 0; } @@ -656,6 +659,9 @@ static int event_simd_regs_validate(struct perf_event *= event) if (event_needs_xmm(event) && !(x86_pmu.ext_regs_mask & XFEATURE_MASK_SSE)) return -EINVAL; + if (event_needs_ymm(event) && + !(x86_pmu.ext_regs_mask & XFEATURE_MASK_YMM)) + return -EINVAL; =20 return 0; } @@ -1819,6 +1825,7 @@ void x86_pmu_clear_perf_regs(struct pt_regs *regs) =20 perf_regs->abi =3D PERF_SAMPLE_REGS_ABI_NONE; perf_regs->xmm_regs =3D NULL; + perf_regs->ymmh_regs =3D NULL; } =20 static void update_perf_regs(struct x86_perf_regs *perf_regs, @@ -1834,6 +1841,8 @@ static void update_perf_regs(struct x86_perf_regs *pe= rf_regs, =20 if (mask & XFEATURE_MASK_SSE) perf_regs->xmm_space =3D xsave->i387.xmm_space; + if (mask & XFEATURE_MASK_YMM) + perf_regs->ymmh =3D get_xsave_addr(xsave, XFEATURE_YMM); } =20 /* @@ -1996,6 +2005,18 @@ static inline u64 x86_pmu_update_user_xregs(struct p= erf_sample_data *data, return user_mask; } =20 +static u64 get_simd_sample_mask(struct perf_event *event, u64 sample_type) +{ + u64 mask =3D 0; + + if (__event_needs_xmm(event, sample_type)) + mask |=3D XFEATURE_MASK_SSE; + if (__event_needs_ymm(event, sample_type)) + mask |=3D XFEATURE_MASK_YMM; + + return mask; +} + static void x86_pmu_sample_xregs(struct perf_event *event, struct perf_sample_data *data, struct pt_regs *regs, @@ -2011,17 +2032,13 @@ static void x86_pmu_sample_xregs(struct perf_event = *event, return; =20 if ((sample_type & PERF_SAMPLE_REGS_INTR) && data->regs_intr.regs) { - if (__event_needs_xmm(event, PERF_SAMPLE_REGS_INTR)) - intr_mask |=3D XFEATURE_MASK_SSE; - + intr_mask |=3D get_simd_sample_mask(event, PERF_SAMPLE_REGS_INTR); intr_mask &=3D x86_pmu.ext_regs_mask; intr_mask =3D from_pebs ? 0 : intr_mask; } =20 if ((sample_type & PERF_SAMPLE_REGS_USER) && data->regs_user.regs) { - if (__event_needs_xmm(event, PERF_SAMPLE_REGS_USER)) - user_mask |=3D XFEATURE_MASK_SSE; - + user_mask |=3D get_simd_sample_mask(event, PERF_SAMPLE_REGS_USER); user_mask &=3D x86_pmu.ext_regs_mask; user_mask =3D x86_pmu_update_user_xregs(data, regs, user_mask, from_pebs); diff --git a/arch/x86/events/perf_event.h b/arch/x86/events/perf_event.h index 23c5907e8b85..01de7799f907 100644 --- a/arch/x86/events/perf_event.h +++ b/arch/x86/events/perf_event.h @@ -183,6 +183,32 @@ static inline bool event_needs_xmm(struct perf_event *= event) PERF_SAMPLE_REGS_INTR | PERF_SAMPLE_REGS_USER); } =20 +static inline bool __event_needs_ymm(struct perf_event *event, u64 sample_= type) +{ + if (!event->attr.sample_simd_regs_enabled) + return false; + if (event->attr.sample_simd_vec_reg_qwords < PERF_X86_YMM_QWORDS) + return false; + + if ((sample_type & PERF_SAMPLE_REGS_USER) && + (event->attr.sample_type & PERF_SAMPLE_REGS_USER) && + (event->attr.sample_simd_vec_reg_user > 0)) + return true; + + if ((sample_type & PERF_SAMPLE_REGS_INTR) && + (event->attr.sample_type & PERF_SAMPLE_REGS_INTR) && + (event->attr.sample_simd_vec_reg_intr > 0)) + return true; + + return false; +} + +static inline bool event_needs_ymm(struct perf_event *event) +{ + return __event_needs_ymm(event, + PERF_SAMPLE_REGS_INTR | PERF_SAMPLE_REGS_USER); +} + struct amd_nb { int nb_id; /* NorthBridge id */ int refcnt; /* reference count */ diff --git a/arch/x86/include/asm/perf_event.h b/arch/x86/include/asm/perf_= event.h index a2b2123d008e..da77845e1f02 100644 --- a/arch/x86/include/asm/perf_event.h +++ b/arch/x86/include/asm/perf_event.h @@ -733,6 +733,10 @@ struct x86_perf_regs { u64 *xmm_regs; u32 *xmm_space; /* for xsaves */ }; + union { + u64 *ymmh_regs; + struct ymmh_struct *ymmh; + }; }; =20 extern unsigned long perf_arch_instruction_pointer(struct pt_regs *regs); diff --git a/arch/x86/include/uapi/asm/perf_regs.h b/arch/x86/include/uapi/= asm/perf_regs.h index edb35408e4cc..d544f6d79871 100644 --- a/arch/x86/include/uapi/asm/perf_regs.h +++ b/arch/x86/include/uapi/asm/perf_regs.h @@ -59,7 +59,8 @@ enum perf_event_x86_regs { =20 enum { PERF_X86_SIMD_XMM_REGS =3D 16, - PERF_X86_SIMD_VEC_REGS_MAX =3D PERF_X86_SIMD_XMM_REGS, + PERF_X86_SIMD_YMM_REGS =3D 16, + PERF_X86_SIMD_VEC_REGS_MAX =3D PERF_X86_SIMD_YMM_REGS, }; =20 #define PERF_X86_SIMD_VEC_MASK __GENMASK_ULL(PERF_X86_SIMD_VEC_REGS_MAX - = 1, 0) @@ -67,7 +68,8 @@ enum { enum { /* 1 qword =3D 8 bytes */ PERF_X86_XMM_QWORDS =3D 2, - PERF_X86_SIMD_QWORDS_MAX =3D PERF_X86_XMM_QWORDS, + PERF_X86_YMM_QWORDS =3D 4, + PERF_X86_SIMD_QWORDS_MAX =3D PERF_X86_YMM_QWORDS, }; =20 #endif /* _ASM_X86_PERF_REGS_H */ diff --git a/arch/x86/kernel/perf_regs.c b/arch/x86/kernel/perf_regs.c index bccf0fc27511..0076974498ee 100644 --- a/arch/x86/kernel/perf_regs.c +++ b/arch/x86/kernel/perf_regs.c @@ -77,6 +77,8 @@ u64 perf_reg_value(struct pt_regs *regs, int idx) return regs_get_register(regs, pt_regs_offset[idx]); } =20 +#define PERF_X86_YMMH_QWORDS (PERF_X86_YMM_QWORDS / 2) + u64 perf_simd_reg_value(struct pt_regs *regs, int idx, u16 qwords_idx, bool pred) { @@ -98,6 +100,11 @@ u64 perf_simd_reg_value(struct pt_regs *regs, int idx, return 0; return perf_regs->xmm_regs[idx * PERF_X86_XMM_QWORDS + qwords_idx]; + } else if (qwords_idx < PERF_X86_YMM_QWORDS) { + if (!perf_regs->ymmh_regs) + return 0; + return perf_regs->ymmh_regs[idx * PERF_X86_YMMH_QWORDS + + qwords_idx - PERF_X86_XMM_QWORDS]; } =20 return 0; @@ -115,7 +122,8 @@ int perf_simd_reg_validate(u16 vec_qwords, u64 vec_mask, } =20 if (vec_qwords) { - if (vec_qwords !=3D PERF_X86_XMM_QWORDS) + if (vec_qwords !=3D PERF_X86_XMM_QWORDS && + vec_qwords !=3D PERF_X86_YMM_QWORDS) return -EINVAL; if (vec_mask & ~PERF_X86_SIMD_VEC_MASK) return -EINVAL; @@ -124,6 +132,9 @@ int perf_simd_reg_validate(u16 vec_qwords, u64 vec_mask, if (vec_qwords =3D=3D PERF_X86_XMM_QWORDS && mask && !bitmap_full(&mask, PERF_X86_SIMD_XMM_REGS)) return -EINVAL; + if (vec_qwords =3D=3D PERF_X86_YMM_QWORDS && mask && + !bitmap_full(&mask, PERF_X86_SIMD_YMM_REGS)) + return -EINVAL; } =20 /* PRED registers are not supported yet. */ --=20 2.34.1 From nobody Sat Jul 25 01:34:42 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.11]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D8D1241DE0E; Tue, 21 Jul 2026 06:33:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.11 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784615631; cv=none; b=h5c+f8214Hvxt+oYl0QmlpbuHrHwj2530wRhI43Ulj13NOWLW2TP56B9Gl4h3KhzuVIzjXVJii9XqbfXVLqQ3Oq4FYKE7kbuugmZLW8BA6I+33B4g1Y7nh3LRlnElnwChEcWm9zcwRl4TmVKNLQz9ZGp0ChA5Hi1t6pE9MEfUaQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784615631; c=relaxed/simple; bh=9ePV5Z6b+35fNuJr5NUdWv0cAnC0DEeQTKMQFKJxwQc=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=egv356zN3aTcuJjPqXoPBAd1Zhz+kLPTrgEj2yRvxMvlA5dvSWHlaWOkMlNQ9ekVaOTfagt0nVzRr0TL4j+Rg1goAxEV31VCXF7tbmTcrarrHDaEJD44OrRuZUItkpFa3Sru3Kzeaj2tAgtjQP/B2Esc8CzEG53l4n/Tthkr3+0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=pass smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=M47zTDT8; arc=none smtp.client-ip=198.175.65.11 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="M47zTDT8" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1784615630; x=1816151630; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=9ePV5Z6b+35fNuJr5NUdWv0cAnC0DEeQTKMQFKJxwQc=; b=M47zTDT8ble9WlhS7NSSZ2xZZI0dPjtGgmVkmUDrVZxDg/iaJGiOp9H0 GHJUSaFgvJ1NN5P/Wlo/Hd4nxDu5TEv0x0nRrOJA2ER2Fok+gDitT266u vAhzqbWwsjvZgZOPfpYtY4YzxGrfYVEjh3wLzGhhUdNpxPlermhElL8Lv 3Nl+5e3V9Q6Hir1VLlFVH38qwBwjnNVThwrsJ17XVUU1dVnIJczpLq56E MQ0UTzkWtYLJXrlepx+sVrXriktsrVgdt7EVMytVS4FPwksOmhcLNEiSk +kcmw63NQ4ZqxC1fGYj3i7QvZkPQPKjHGTjTykmk2XpqXNYxhQPX1MwQ5 Q==; X-CSE-ConnectionGUID: 4n0dfhzjTx6fCsvGXgauHw== X-CSE-MsgGUID: RYryV3zmQN2oVS6RVj/4SQ== X-IronPort-AV: E=McAfee;i="6800,10657,11852"; a="95565491" X-IronPort-AV: E=Sophos;i="6.25,176,1779174000"; d="scan'208";a="95565491" Received: from fmviesa004.fm.intel.com ([10.60.135.144]) by orvoesa103.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Jul 2026 23:33:49 -0700 X-CSE-ConnectionGUID: EK66ZekyROaTAL3bJhAVxg== X-CSE-MsgGUID: 3IFoXg3XRw+xzTSeeq54UQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.25,176,1779174000"; d="scan'208";a="259656111" Received: from spr.sh.intel.com ([10.112.229.196]) by fmviesa004.fm.intel.com with ESMTP; 20 Jul 2026 23:33:42 -0700 From: Dapeng Mi To: Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Thomas Gleixner , Dave Hansen , Ian Rogers , Adrian Hunter , Jiri Olsa , Alexander Shishkin , Andi Kleen , Eranian Stephane Cc: Mark Rutland , broonie@kernel.org, Ravi Bangoria , linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org, Zide Chen , Falcon Thomas , Dapeng Mi , Xudong Hao , Dapeng Mi , Kan Liang Subject: [Patch v10 15/23] perf/x86: Support ZMM sampling using sample_simd_vec_reg_* fields Date: Tue, 21 Jul 2026 14:24:58 +0800 Message-Id: <20260721062506.3745816-16-dapeng1.mi@linux.intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260721062506.3745816-1-dapeng1.mi@linux.intel.com> References: <20260721062506.3745816-1-dapeng1.mi@linux.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Support sampling of ZMM registers via the sample_simd_vec_reg_* fields. Each ZMM register consists of 8 u64 words. Current x86 hardware supports up to 32 ZMM registers. For ZMM registers from ZMM0 to ZMM15, they are assembled from three parts: XMM (the lower 2 u64 words), YMMH (the middle 2 u64 words), and ZMMH (the upper 4 u64 words). The perf_simd_reg_value() function is responsible for assembling these three parts into a complete ZMM register for output to userspace. For ZMM registers ZMM16 to ZMM31, each register can be read as a whole and directly outputted to userspace. Additionally, sample_simd_vec_reg_qwords should be set to 8 to indicate ZMM sampling. ZMM sampling will be enabled in a subsequent patch that sets PERF_PMU_CAP_SIMD_REGS. Co-developed-by: Kan Liang Signed-off-by: Kan Liang Signed-off-by: Dapeng Mi --- arch/x86/events/core.c | 22 ++++++++++- arch/x86/events/perf_event.h | 54 +++++++++++++++++++++++++++ arch/x86/include/asm/perf_event.h | 8 ++++ arch/x86/include/uapi/asm/perf_regs.h | 8 +++- arch/x86/kernel/perf_regs.c | 19 +++++++++- 5 files changed, 106 insertions(+), 5 deletions(-) diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c index 3039a311e733..b0e3f1b9fa19 100644 --- a/arch/x86/events/core.c +++ b/arch/x86/events/core.c @@ -642,8 +642,10 @@ static int pebs_simd_regs_validate(struct perf_event *= event) if (event_needs_xmm(event) && x86_pmu.arch_pebs && !(caps & ARCH_PEBS_VECR_XMM)) return -EINVAL; - /* PEBS does not support YMM registers sampling yet. */ - if (event_needs_ymm(event)) + /* PEBS does not support YMM/ZMM registers sampling yet. */ + if (event_needs_ymm(event) || + event_needs_low16_zmm(event) || + event_needs_high16_zmm(event)) return -EINVAL; =20 return 0; @@ -662,6 +664,12 @@ static int event_simd_regs_validate(struct perf_event = *event) if (event_needs_ymm(event) && !(x86_pmu.ext_regs_mask & XFEATURE_MASK_YMM)) return -EINVAL; + if (event_needs_low16_zmm(event) && + !(x86_pmu.ext_regs_mask & XFEATURE_MASK_ZMM_Hi256)) + return -EINVAL; + if (event_needs_high16_zmm(event) && + !(x86_pmu.ext_regs_mask & XFEATURE_MASK_Hi16_ZMM)) + return -EINVAL; =20 return 0; } @@ -1826,6 +1834,8 @@ void x86_pmu_clear_perf_regs(struct pt_regs *regs) perf_regs->abi =3D PERF_SAMPLE_REGS_ABI_NONE; perf_regs->xmm_regs =3D NULL; perf_regs->ymmh_regs =3D NULL; + perf_regs->zmmh_regs =3D NULL; + perf_regs->h16zmm_regs =3D NULL; } =20 static void update_perf_regs(struct x86_perf_regs *perf_regs, @@ -1843,6 +1853,10 @@ static void update_perf_regs(struct x86_perf_regs *p= erf_regs, perf_regs->xmm_space =3D xsave->i387.xmm_space; if (mask & XFEATURE_MASK_YMM) perf_regs->ymmh =3D get_xsave_addr(xsave, XFEATURE_YMM); + if (mask & XFEATURE_MASK_ZMM_Hi256) + perf_regs->zmmh =3D get_xsave_addr(xsave, XFEATURE_ZMM_Hi256); + if (mask & XFEATURE_MASK_Hi16_ZMM) + perf_regs->h16zmm =3D get_xsave_addr(xsave, XFEATURE_Hi16_ZMM); } =20 /* @@ -2013,6 +2027,10 @@ static u64 get_simd_sample_mask(struct perf_event *e= vent, u64 sample_type) mask |=3D XFEATURE_MASK_SSE; if (__event_needs_ymm(event, sample_type)) mask |=3D XFEATURE_MASK_YMM; + if (__event_needs_low16_zmm(event, sample_type)) + mask |=3D XFEATURE_MASK_ZMM_Hi256; + if (__event_needs_high16_zmm(event, sample_type)) + mask |=3D XFEATURE_MASK_Hi16_ZMM; =20 return mask; } diff --git a/arch/x86/events/perf_event.h b/arch/x86/events/perf_event.h index 01de7799f907..f59551200f18 100644 --- a/arch/x86/events/perf_event.h +++ b/arch/x86/events/perf_event.h @@ -209,6 +209,60 @@ static inline bool event_needs_ymm(struct perf_event *= event) PERF_SAMPLE_REGS_INTR | PERF_SAMPLE_REGS_USER); } =20 +static inline bool __event_needs_low16_zmm(struct perf_event *event, + u64 sample_type) +{ + if (!event->attr.sample_simd_regs_enabled) + return false; + if (event->attr.sample_simd_vec_reg_qwords < PERF_X86_ZMM_QWORDS) + return false; + + if ((sample_type & PERF_SAMPLE_REGS_USER) && + (event->attr.sample_type & PERF_SAMPLE_REGS_USER) && + (event->attr.sample_simd_vec_reg_user > 0)) + return true; + + if ((sample_type & PERF_SAMPLE_REGS_INTR) && + (event->attr.sample_type & PERF_SAMPLE_REGS_INTR) && + (event->attr.sample_simd_vec_reg_intr > 0)) + return true; + + return false; +} + +static inline bool event_needs_low16_zmm(struct perf_event *event) +{ + return __event_needs_low16_zmm(event, + PERF_SAMPLE_REGS_INTR | PERF_SAMPLE_REGS_USER); +} + +static inline bool __event_needs_high16_zmm(struct perf_event *event, + u64 sample_type) +{ + if (!event->attr.sample_simd_regs_enabled) + return false; + if (event->attr.sample_simd_vec_reg_qwords < PERF_X86_ZMM_QWORDS) + return false; + + if ((sample_type & PERF_SAMPLE_REGS_USER) && + (event->attr.sample_type & PERF_SAMPLE_REGS_USER) && + (fls64(event->attr.sample_simd_vec_reg_user) > PERF_X86_H16ZMM_BASE)) + return true; + + if ((sample_type & PERF_SAMPLE_REGS_INTR) && + (event->attr.sample_type & PERF_SAMPLE_REGS_INTR) && + (fls64(event->attr.sample_simd_vec_reg_intr) > PERF_X86_H16ZMM_BASE)) + return true; + + return false; +} + +static inline bool event_needs_high16_zmm(struct perf_event *event) +{ + return __event_needs_high16_zmm(event, + PERF_SAMPLE_REGS_INTR | PERF_SAMPLE_REGS_USER); +} + struct amd_nb { int nb_id; /* NorthBridge id */ int refcnt; /* reference count */ diff --git a/arch/x86/include/asm/perf_event.h b/arch/x86/include/asm/perf_= event.h index da77845e1f02..75394c4e8bc3 100644 --- a/arch/x86/include/asm/perf_event.h +++ b/arch/x86/include/asm/perf_event.h @@ -737,6 +737,14 @@ struct x86_perf_regs { u64 *ymmh_regs; struct ymmh_struct *ymmh; }; + union { + u64 *zmmh_regs; + struct avx_512_zmm_uppers_state *zmmh; + }; + union { + u64 *h16zmm_regs; + struct avx_512_hi16_state *h16zmm; + }; }; =20 extern unsigned long perf_arch_instruction_pointer(struct pt_regs *regs); diff --git a/arch/x86/include/uapi/asm/perf_regs.h b/arch/x86/include/uapi/= asm/perf_regs.h index d544f6d79871..b88d0b6822fd 100644 --- a/arch/x86/include/uapi/asm/perf_regs.h +++ b/arch/x86/include/uapi/asm/perf_regs.h @@ -60,16 +60,20 @@ enum perf_event_x86_regs { enum { PERF_X86_SIMD_XMM_REGS =3D 16, PERF_X86_SIMD_YMM_REGS =3D 16, - PERF_X86_SIMD_VEC_REGS_MAX =3D PERF_X86_SIMD_YMM_REGS, + PERF_X86_SIMD_ZMM_REGS =3D 32, + PERF_X86_SIMD_VEC_REGS_MAX =3D PERF_X86_SIMD_ZMM_REGS, }; =20 #define PERF_X86_SIMD_VEC_MASK __GENMASK_ULL(PERF_X86_SIMD_VEC_REGS_MAX - = 1, 0) =20 +#define PERF_X86_H16ZMM_BASE 16 + enum { /* 1 qword =3D 8 bytes */ PERF_X86_XMM_QWORDS =3D 2, PERF_X86_YMM_QWORDS =3D 4, - PERF_X86_SIMD_QWORDS_MAX =3D PERF_X86_YMM_QWORDS, + PERF_X86_ZMM_QWORDS =3D 8, + PERF_X86_SIMD_QWORDS_MAX =3D PERF_X86_ZMM_QWORDS, }; =20 #endif /* _ASM_X86_PERF_REGS_H */ diff --git a/arch/x86/kernel/perf_regs.c b/arch/x86/kernel/perf_regs.c index 0076974498ee..93370d465786 100644 --- a/arch/x86/kernel/perf_regs.c +++ b/arch/x86/kernel/perf_regs.c @@ -78,6 +78,7 @@ u64 perf_reg_value(struct pt_regs *regs, int idx) } =20 #define PERF_X86_YMMH_QWORDS (PERF_X86_YMM_QWORDS / 2) +#define PERF_X86_ZMMH_QWORDS (PERF_X86_ZMM_QWORDS / 2) =20 u64 perf_simd_reg_value(struct pt_regs *regs, int idx, u16 qwords_idx, bool pred) @@ -95,6 +96,13 @@ u64 perf_simd_reg_value(struct pt_regs *regs, int idx, qwords_idx >=3D PERF_X86_SIMD_QWORDS_MAX)) return 0; =20 + if (idx >=3D PERF_X86_H16ZMM_BASE) { + if (!perf_regs->h16zmm_regs) + return 0; + return perf_regs->h16zmm_regs[(idx - PERF_X86_H16ZMM_BASE) * + PERF_X86_ZMM_QWORDS + qwords_idx]; + } + if (qwords_idx < PERF_X86_XMM_QWORDS) { if (!perf_regs->xmm_regs) return 0; @@ -105,6 +113,11 @@ u64 perf_simd_reg_value(struct pt_regs *regs, int idx, return 0; return perf_regs->ymmh_regs[idx * PERF_X86_YMMH_QWORDS + qwords_idx - PERF_X86_XMM_QWORDS]; + } else if (qwords_idx < PERF_X86_ZMM_QWORDS) { + if (!perf_regs->zmmh_regs) + return 0; + return perf_regs->zmmh_regs[idx * PERF_X86_ZMMH_QWORDS + + qwords_idx - PERF_X86_YMM_QWORDS]; } =20 return 0; @@ -123,7 +136,8 @@ int perf_simd_reg_validate(u16 vec_qwords, u64 vec_mask, =20 if (vec_qwords) { if (vec_qwords !=3D PERF_X86_XMM_QWORDS && - vec_qwords !=3D PERF_X86_YMM_QWORDS) + vec_qwords !=3D PERF_X86_YMM_QWORDS && + vec_qwords !=3D PERF_X86_ZMM_QWORDS) return -EINVAL; if (vec_mask & ~PERF_X86_SIMD_VEC_MASK) return -EINVAL; @@ -135,6 +149,9 @@ int perf_simd_reg_validate(u16 vec_qwords, u64 vec_mask, if (vec_qwords =3D=3D PERF_X86_YMM_QWORDS && mask && !bitmap_full(&mask, PERF_X86_SIMD_YMM_REGS)) return -EINVAL; + if (vec_qwords =3D=3D PERF_X86_ZMM_QWORDS && mask && + !bitmap_full(&mask, PERF_X86_SIMD_ZMM_REGS)) + return -EINVAL; } =20 /* PRED registers are not supported yet. */ --=20 2.34.1 From nobody Sat Jul 25 01:34:42 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.11]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BFB74433BDC; Tue, 21 Jul 2026 06:33:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.11 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784615638; cv=none; b=CYrqr58iJP8tKL5eMofVEqEcd4+vQ3jQKRxrtpwPh597l4DSCFOoh3iSLrvN7vvrX4vjTXHnzH/LJVwvYOj5OPqA5cEyYoK3TExwYuiifvLCyC33jUpEwjcUc7FGmxMqzARhDm9rX2sQutWKHjPp7es9hMGcHuNJNlFix+vHq50= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784615638; c=relaxed/simple; bh=dJYR2H6e+XdgfQGiTqTbV4LwDrKwVzXz8Oa7pfbTFug=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=l3LdcxK7N5y6hC5SFPT0MhOeQykm9A5Pqjm86k/ulheohVLWinB7NF+bLfHClJjRb6wvit8Q4sVvqYo4rnv9S47meYRcWa8dBc/p6aRlrfSjxfcvwyvwWuPB1u4MfAA4OmrfKEBMo1+Z5MDTVIQpwsy01GURn97YaHzVzyVHc/c= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=pass smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=bi8nCMkQ; arc=none smtp.client-ip=198.175.65.11 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="bi8nCMkQ" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1784615637; x=1816151637; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=dJYR2H6e+XdgfQGiTqTbV4LwDrKwVzXz8Oa7pfbTFug=; b=bi8nCMkQJfshJNCdmQ26+cWo8TFfG3+U2UYnZCQPXceseWo3K2OloJSF NN1dWXefGp4zNHeefFXpLb4EzHOeP725Ib0HxXLrq051PZbM7Ep+neFW5 Jm+sMqSCYkGRv/uaHFGJnuX436+bk27b+bUFhod64Gzg0IQHoToK10fw7 csiruUqZOlwwg9NVJuUJp5IguR/H0emSNi4t+eWTdDK2RvI82zSdqtDu/ nhJULIAELI6BdJOGoUtHfOL6Y0DmFAsiyj243ERHwtlOi7MwSRSVHW1Bm qNJlTWr7vXrKj3/TY7g69ny33F3FBW3+bwkZ+olsxGAVUNQ9URglcoUPD w==; X-CSE-ConnectionGUID: nHszGKV3QoyJBH9mU7IMzQ== X-CSE-MsgGUID: Yffq4kx2RBiDtRipdXj8uQ== X-IronPort-AV: E=McAfee;i="6800,10657,11852"; a="95565505" X-IronPort-AV: E=Sophos;i="6.25,176,1779174000"; d="scan'208";a="95565505" Received: from fmviesa004.fm.intel.com ([10.60.135.144]) by orvoesa103.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Jul 2026 23:33:56 -0700 X-CSE-ConnectionGUID: 5sct0bY2SzCeY1bLVEH4Bg== X-CSE-MsgGUID: mhLcQXvsSsypabGRRo8RsQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.25,176,1779174000"; d="scan'208";a="259656142" Received: from spr.sh.intel.com ([10.112.229.196]) by fmviesa004.fm.intel.com with ESMTP; 20 Jul 2026 23:33:49 -0700 From: Dapeng Mi To: Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Thomas Gleixner , Dave Hansen , Ian Rogers , Adrian Hunter , Jiri Olsa , Alexander Shishkin , Andi Kleen , Eranian Stephane Cc: Mark Rutland , broonie@kernel.org, Ravi Bangoria , linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org, Zide Chen , Falcon Thomas , Dapeng Mi , Xudong Hao , Dapeng Mi , Kan Liang Subject: [Patch v10 16/23] perf/x86: Support OPMASK sampling using sample_simd_pred_reg_* fields Date: Tue, 21 Jul 2026 14:24:59 +0800 Message-Id: <20260721062506.3745816-17-dapeng1.mi@linux.intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260721062506.3745816-1-dapeng1.mi@linux.intel.com> References: <20260721062506.3745816-1-dapeng1.mi@linux.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Support sampling of OPMASK registers via the sample_simd_pred_reg_* fields. Each OPMASK register consists of 1 u64 word. Current x86 hardware supports 8 OPMASK registers. The perf_simd_reg_value() function is responsible for outputting OPMASK value to userspace. Additionally, sample_simd_pred_reg_qwords should be set to 1 to indicate OPMASK sampling. OPMASK sampling will be enabled in a subsequent patch that sets PERF_PMU_CAP_SIMD_REGS. Co-developed-by: Kan Liang Signed-off-by: Kan Liang Signed-off-by: Dapeng Mi --- arch/x86/events/core.c | 13 +++++++++++-- arch/x86/events/perf_event.h | 27 +++++++++++++++++++++++++++ arch/x86/include/asm/perf_event.h | 4 ++++ arch/x86/include/uapi/asm/perf_regs.h | 5 +++++ arch/x86/kernel/perf_regs.c | 24 +++++++++++++++++++----- 5 files changed, 66 insertions(+), 7 deletions(-) diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c index b0e3f1b9fa19..9bfb1810a9fe 100644 --- a/arch/x86/events/core.c +++ b/arch/x86/events/core.c @@ -642,10 +642,11 @@ static int pebs_simd_regs_validate(struct perf_event = *event) if (event_needs_xmm(event) && x86_pmu.arch_pebs && !(caps & ARCH_PEBS_VECR_XMM)) return -EINVAL; - /* PEBS does not support YMM/ZMM registers sampling yet. */ + /* PEBS does not support YMM/ZMM/OPMASK registers sampling yet. */ if (event_needs_ymm(event) || event_needs_low16_zmm(event) || - event_needs_high16_zmm(event)) + event_needs_high16_zmm(event) || + event_needs_opmask(event)) return -EINVAL; =20 return 0; @@ -670,6 +671,9 @@ static int event_simd_regs_validate(struct perf_event *= event) if (event_needs_high16_zmm(event) && !(x86_pmu.ext_regs_mask & XFEATURE_MASK_Hi16_ZMM)) return -EINVAL; + if (event_needs_opmask(event) && + !(x86_pmu.ext_regs_mask & XFEATURE_MASK_OPMASK)) + return -EINVAL; =20 return 0; } @@ -1836,6 +1840,7 @@ void x86_pmu_clear_perf_regs(struct pt_regs *regs) perf_regs->ymmh_regs =3D NULL; perf_regs->zmmh_regs =3D NULL; perf_regs->h16zmm_regs =3D NULL; + perf_regs->opmask_regs =3D NULL; } =20 static void update_perf_regs(struct x86_perf_regs *perf_regs, @@ -1857,6 +1862,8 @@ static void update_perf_regs(struct x86_perf_regs *pe= rf_regs, perf_regs->zmmh =3D get_xsave_addr(xsave, XFEATURE_ZMM_Hi256); if (mask & XFEATURE_MASK_Hi16_ZMM) perf_regs->h16zmm =3D get_xsave_addr(xsave, XFEATURE_Hi16_ZMM); + if (mask & XFEATURE_MASK_OPMASK) + perf_regs->opmask =3D get_xsave_addr(xsave, XFEATURE_OPMASK); } =20 /* @@ -2031,6 +2038,8 @@ static u64 get_simd_sample_mask(struct perf_event *ev= ent, u64 sample_type) mask |=3D XFEATURE_MASK_ZMM_Hi256; if (__event_needs_high16_zmm(event, sample_type)) mask |=3D XFEATURE_MASK_Hi16_ZMM; + if (__event_needs_opmask(event, sample_type)) + mask |=3D XFEATURE_MASK_OPMASK; =20 return mask; } diff --git a/arch/x86/events/perf_event.h b/arch/x86/events/perf_event.h index f59551200f18..e6365438bb3d 100644 --- a/arch/x86/events/perf_event.h +++ b/arch/x86/events/perf_event.h @@ -263,6 +263,33 @@ static inline bool event_needs_high16_zmm(struct perf_= event *event) PERF_SAMPLE_REGS_INTR | PERF_SAMPLE_REGS_USER); } =20 +static inline bool __event_needs_opmask(struct perf_event *event, + u64 sample_type) +{ + if (!event->attr.sample_simd_regs_enabled) + return false; + if (event->attr.sample_simd_pred_reg_qwords !=3D PERF_X86_OPMASK_QWORDS) + return false; + + if ((sample_type & PERF_SAMPLE_REGS_USER) && + (event->attr.sample_type & PERF_SAMPLE_REGS_USER) && + (event->attr.sample_simd_pred_reg_user > 0)) + return true; + + if ((sample_type & PERF_SAMPLE_REGS_INTR) && + (event->attr.sample_type & PERF_SAMPLE_REGS_INTR) && + (event->attr.sample_simd_pred_reg_intr > 0)) + return true; + + return false; +} + +static inline bool event_needs_opmask(struct perf_event *event) +{ + return __event_needs_opmask(event, + PERF_SAMPLE_REGS_INTR | PERF_SAMPLE_REGS_USER); +} + struct amd_nb { int nb_id; /* NorthBridge id */ int refcnt; /* reference count */ diff --git a/arch/x86/include/asm/perf_event.h b/arch/x86/include/asm/perf_= event.h index 75394c4e8bc3..49112e097e99 100644 --- a/arch/x86/include/asm/perf_event.h +++ b/arch/x86/include/asm/perf_event.h @@ -745,6 +745,10 @@ struct x86_perf_regs { u64 *h16zmm_regs; struct avx_512_hi16_state *h16zmm; }; + union { + u64 *opmask_regs; + struct avx_512_opmask_state *opmask; + }; }; =20 extern unsigned long perf_arch_instruction_pointer(struct pt_regs *regs); diff --git a/arch/x86/include/uapi/asm/perf_regs.h b/arch/x86/include/uapi/= asm/perf_regs.h index b88d0b6822fd..61aec60623f1 100644 --- a/arch/x86/include/uapi/asm/perf_regs.h +++ b/arch/x86/include/uapi/asm/perf_regs.h @@ -62,14 +62,19 @@ enum { PERF_X86_SIMD_YMM_REGS =3D 16, PERF_X86_SIMD_ZMM_REGS =3D 32, PERF_X86_SIMD_VEC_REGS_MAX =3D PERF_X86_SIMD_ZMM_REGS, + + PERF_X86_SIMD_OPMASK_REGS =3D 8, + PERF_X86_SIMD_PRED_REGS_MAX =3D PERF_X86_SIMD_OPMASK_REGS, }; =20 +#define PERF_X86_SIMD_PRED_MASK __GENMASK(PERF_X86_SIMD_PRED_REGS_MAX - 1,= 0) #define PERF_X86_SIMD_VEC_MASK __GENMASK_ULL(PERF_X86_SIMD_VEC_REGS_MAX - = 1, 0) =20 #define PERF_X86_H16ZMM_BASE 16 =20 enum { /* 1 qword =3D 8 bytes */ + PERF_X86_OPMASK_QWORDS =3D 1, PERF_X86_XMM_QWORDS =3D 2, PERF_X86_YMM_QWORDS =3D 4, PERF_X86_ZMM_QWORDS =3D 8, diff --git a/arch/x86/kernel/perf_regs.c b/arch/x86/kernel/perf_regs.c index 93370d465786..87297da5e44b 100644 --- a/arch/x86/kernel/perf_regs.c +++ b/arch/x86/kernel/perf_regs.c @@ -89,8 +89,14 @@ u64 perf_simd_reg_value(struct pt_regs *regs, int idx, if (!(perf_regs->abi & PERF_SAMPLE_REGS_ABI_SIMD)) return 0; =20 - if (pred) - return 0; + if (pred) { + if (WARN_ON_ONCE(idx >=3D PERF_X86_SIMD_PRED_REGS_MAX || + qwords_idx >=3D PERF_X86_OPMASK_QWORDS)) + return 0; + if (!perf_regs->opmask_regs) + return 0; + return perf_regs->opmask_regs[idx]; + } =20 if (WARN_ON_ONCE(idx >=3D PERF_X86_SIMD_VEC_REGS_MAX || qwords_idx >=3D PERF_X86_SIMD_QWORDS_MAX)) @@ -154,9 +160,17 @@ int perf_simd_reg_validate(u16 vec_qwords, u64 vec_mas= k, return -EINVAL; } =20 - /* PRED registers are not supported yet. */ - if (pred_qwords) - return -EINVAL; + if (pred_qwords) { + if (pred_qwords !=3D PERF_X86_OPMASK_QWORDS) + return -EINVAL; + if (pred_mask & ~PERF_X86_SIMD_PRED_MASK) + return -EINVAL; + /* Only full-register sampling is allowed. */ + mask =3D pred_mask; + if (pred_qwords =3D=3D PERF_X86_OPMASK_QWORDS && mask && + !bitmap_full(&mask, PERF_X86_SIMD_OPMASK_REGS)) + return -EINVAL; + } =20 size =3D sizeof(u64) * 4; size +=3D (hweight64(vec_mask) * vec_qwords + --=20 2.34.1 From nobody Sat Jul 25 01:34:42 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.11]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9CDF7434E23; Tue, 21 Jul 2026 06:34:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.11 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784615644; cv=none; b=cngSy6wexgMidrSsEvtgt7Mvpkjz9ag4j2N0DcP8RWKd7whE/8nijyTpd/t+x5FFdx42eRgWReqca/39Erui3jBfL+H5kHvVE/jHOIhdsEMc227Ak0zqqOdiobnQLn+MGilei4/GQjSeNs5O3kWf5j9hJHatj04Qg70DbS1L49s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784615644; c=relaxed/simple; bh=vXfypQMrut1DdLL+DtHpfL8ea1oWMWk1CyBxQehvkDc=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=aF8OhOvdEr0hq78kpS5M9zwNcfyztQ05i80Hfrc64fM/quIfpuBMNaoua+60U9WwvO47AcNBWIhcRUdOZl4Qm08lewJDOQt0nCytQ+usZzjxDwdf2eLFoRAOQGseFz0bIMMD/+BHKYTOwJkLt/r5K5BIEVblwGIThbJkvmFjO+c= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=pass smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=I98ucbZo; arc=none smtp.client-ip=198.175.65.11 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="I98ucbZo" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1784615643; x=1816151643; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=vXfypQMrut1DdLL+DtHpfL8ea1oWMWk1CyBxQehvkDc=; b=I98ucbZovAvszWf+dbtprhzWthZ8423Z4m64sBKl2IGVWD7TZU0VZ9CH p/10A26OOd8GrqQ6aE6WjVi3Wod7MAvETwNvikFcEa0wJzUZpjRcOSKf1 5csaBsv1Dvi12uSQaNkMxXR5z+hnW7d41TevxunGCVKWduvVhei/JaaZx fhZdHBaGub2aTIQiIKzd4xDz2hLCtX0XBKHtzFGU+naYT3Yo7f14KEPtz n6KvM8ccJAMqRFB1zsuuddJNOL6MdlBgKtiEd8nV9EGp3retWxykSmxej ubhtfxdDd5ICO+oCz5BBv+40ijr6tlorI46Aeb2gJuuiPY2a6N1k32hgt w==; X-CSE-ConnectionGUID: KiS/y1NDQTSpCTvhodykdA== X-CSE-MsgGUID: cGB7khGIR+meLMO7VmevIA== X-IronPort-AV: E=McAfee;i="6800,10657,11852"; a="95565528" X-IronPort-AV: E=Sophos;i="6.25,176,1779174000"; d="scan'208";a="95565528" Received: from fmviesa004.fm.intel.com ([10.60.135.144]) by orvoesa103.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Jul 2026 23:34:02 -0700 X-CSE-ConnectionGUID: MwE0frdcSpWlE+Ss3GnNGg== X-CSE-MsgGUID: jq8JZrrSRnCPmkCVqy684g== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.25,176,1779174000"; d="scan'208";a="259656158" Received: from spr.sh.intel.com ([10.112.229.196]) by fmviesa004.fm.intel.com with ESMTP; 20 Jul 2026 23:33:57 -0700 From: Dapeng Mi To: Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Thomas Gleixner , Dave Hansen , Ian Rogers , Adrian Hunter , Jiri Olsa , Alexander Shishkin , Andi Kleen , Eranian Stephane Cc: Mark Rutland , broonie@kernel.org, Ravi Bangoria , linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org, Zide Chen , Falcon Thomas , Dapeng Mi , Xudong Hao , Dapeng Mi Subject: [Patch v10 17/23] perf: Enhance perf_reg_validate() with simd_enabled argument Date: Tue, 21 Jul 2026 14:25:00 +0800 Message-Id: <20260721062506.3745816-18-dapeng1.mi@linux.intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260721062506.3745816-1-dapeng1.mi@linux.intel.com> References: <20260721062506.3745816-1-dapeng1.mi@linux.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The upcoming patch will support x86 APX eGPRs sampling by using the reclaimed XMM register space to represent eGPRs in sample_regs_* fields. To differentiate between XMM and eGPRs in sample_regs_* fields, an additional argument, simd_enabled, is introduced to the perf_reg_validate() helper. If simd_enabled is set to 1, it indicates that eGPRs are represented in sample_regs_* fields for the x86 platform; otherwise, XMM registers are represented. Signed-off-by: Dapeng Mi --- arch/arm/kernel/perf_regs.c | 2 +- arch/arm64/kernel/perf_regs.c | 2 +- arch/csky/kernel/perf_regs.c | 2 +- arch/loongarch/kernel/perf_regs.c | 2 +- arch/mips/kernel/perf_regs.c | 2 +- arch/parisc/kernel/perf_regs.c | 2 +- arch/powerpc/perf/perf_regs.c | 2 +- arch/riscv/kernel/perf_regs.c | 2 +- arch/s390/kernel/perf_regs.c | 2 +- arch/x86/kernel/perf_regs.c | 4 ++-- include/linux/perf_regs.h | 2 +- kernel/events/core.c | 8 +++++--- 12 files changed, 17 insertions(+), 15 deletions(-) diff --git a/arch/arm/kernel/perf_regs.c b/arch/arm/kernel/perf_regs.c index d575a4c3ca56..838d701adf4d 100644 --- a/arch/arm/kernel/perf_regs.c +++ b/arch/arm/kernel/perf_regs.c @@ -18,7 +18,7 @@ u64 perf_reg_value(struct pt_regs *regs, int idx) =20 #define REG_RESERVED (~((1ULL << PERF_REG_ARM_MAX) - 1)) =20 -int perf_reg_validate(u64 mask) +int perf_reg_validate(u64 mask, bool simd_enabled) { if (!mask || mask & REG_RESERVED) return -EINVAL; diff --git a/arch/arm64/kernel/perf_regs.c b/arch/arm64/kernel/perf_regs.c index 70e2f13f587f..71a3e0238de4 100644 --- a/arch/arm64/kernel/perf_regs.c +++ b/arch/arm64/kernel/perf_regs.c @@ -77,7 +77,7 @@ u64 perf_reg_value(struct pt_regs *regs, int idx) =20 #define REG_RESERVED (~((1ULL << PERF_REG_ARM64_MAX) - 1)) =20 -int perf_reg_validate(u64 mask) +int perf_reg_validate(u64 mask, bool simd_enabled) { u64 reserved_mask =3D REG_RESERVED; =20 diff --git a/arch/csky/kernel/perf_regs.c b/arch/csky/kernel/perf_regs.c index 94601f37b596..c932a96afc56 100644 --- a/arch/csky/kernel/perf_regs.c +++ b/arch/csky/kernel/perf_regs.c @@ -18,7 +18,7 @@ u64 perf_reg_value(struct pt_regs *regs, int idx) =20 #define REG_RESERVED (~((1ULL << PERF_REG_CSKY_MAX) - 1)) =20 -int perf_reg_validate(u64 mask) +int perf_reg_validate(u64 mask, bool simd_enabled) { if (!mask || mask & REG_RESERVED) return -EINVAL; diff --git a/arch/loongarch/kernel/perf_regs.c b/arch/loongarch/kernel/perf= _regs.c index 8dd604f01745..164514f40ae0 100644 --- a/arch/loongarch/kernel/perf_regs.c +++ b/arch/loongarch/kernel/perf_regs.c @@ -25,7 +25,7 @@ u64 perf_reg_abi(struct task_struct *tsk) } #endif /* CONFIG_32BIT */ =20 -int perf_reg_validate(u64 mask) +int perf_reg_validate(u64 mask, bool simd_enabled) { if (!mask) return -EINVAL; diff --git a/arch/mips/kernel/perf_regs.c b/arch/mips/kernel/perf_regs.c index 7736d3c5ebd2..00a5201dbd5d 100644 --- a/arch/mips/kernel/perf_regs.c +++ b/arch/mips/kernel/perf_regs.c @@ -28,7 +28,7 @@ u64 perf_reg_abi(struct task_struct *tsk) } #endif /* CONFIG_32BIT */ =20 -int perf_reg_validate(u64 mask) +int perf_reg_validate(u64 mask, bool simd_enabled) { if (!mask) return -EINVAL; diff --git a/arch/parisc/kernel/perf_regs.c b/arch/parisc/kernel/perf_regs.c index b9fe1f2fcb9b..4f21aab5405c 100644 --- a/arch/parisc/kernel/perf_regs.c +++ b/arch/parisc/kernel/perf_regs.c @@ -34,7 +34,7 @@ u64 perf_reg_value(struct pt_regs *regs, int idx) =20 #define REG_RESERVED (~((1ULL << PERF_REG_PARISC_MAX) - 1)) =20 -int perf_reg_validate(u64 mask) +int perf_reg_validate(u64 mask, bool simd_enabled) { if (!mask || mask & REG_RESERVED) return -EINVAL; diff --git a/arch/powerpc/perf/perf_regs.c b/arch/powerpc/perf/perf_regs.c index 350dccb0143c..a01d8a903640 100644 --- a/arch/powerpc/perf/perf_regs.c +++ b/arch/powerpc/perf/perf_regs.c @@ -125,7 +125,7 @@ u64 perf_reg_value(struct pt_regs *regs, int idx) return regs_get_register(regs, pt_regs_offset[idx]); } =20 -int perf_reg_validate(u64 mask) +int perf_reg_validate(u64 mask, bool simd_enabled) { if (!mask || mask & REG_RESERVED) return -EINVAL; diff --git a/arch/riscv/kernel/perf_regs.c b/arch/riscv/kernel/perf_regs.c index 3bba8deababb..1ecc8760b88b 100644 --- a/arch/riscv/kernel/perf_regs.c +++ b/arch/riscv/kernel/perf_regs.c @@ -18,7 +18,7 @@ u64 perf_reg_value(struct pt_regs *regs, int idx) =20 #define REG_RESERVED (~((1ULL << PERF_REG_RISCV_MAX) - 1)) =20 -int perf_reg_validate(u64 mask) +int perf_reg_validate(u64 mask, bool simd_enabled) { if (!mask || mask & REG_RESERVED) return -EINVAL; diff --git a/arch/s390/kernel/perf_regs.c b/arch/s390/kernel/perf_regs.c index 7b305f1456f8..6496fd23c540 100644 --- a/arch/s390/kernel/perf_regs.c +++ b/arch/s390/kernel/perf_regs.c @@ -34,7 +34,7 @@ u64 perf_reg_value(struct pt_regs *regs, int idx) =20 #define REG_RESERVED (~((1UL << PERF_REG_S390_MAX) - 1)) =20 -int perf_reg_validate(u64 mask) +int perf_reg_validate(u64 mask, bool simd_enabled) { if (!mask || mask & REG_RESERVED) return -EINVAL; diff --git a/arch/x86/kernel/perf_regs.c b/arch/x86/kernel/perf_regs.c index 87297da5e44b..494e06501210 100644 --- a/arch/x86/kernel/perf_regs.c +++ b/arch/x86/kernel/perf_regs.c @@ -198,7 +198,7 @@ int perf_simd_reg_validate(u16 vec_qwords, u64 vec_mask, (1ULL << PERF_REG_X86_R14) | \ (1ULL << PERF_REG_X86_R15)) =20 -int perf_reg_validate(u64 mask) +int perf_reg_validate(u64 mask, bool simd_enabled) { /* The mask could be 0 if only the SIMD registers are interested */ if (mask & (REG_NOSUPPORT | PERF_REG_X86_RESERVED)) @@ -218,7 +218,7 @@ u64 perf_reg_abi(struct task_struct *task) (1ULL << PERF_REG_X86_FS) | \ (1ULL << PERF_REG_X86_GS)) =20 -int perf_reg_validate(u64 mask) +int perf_reg_validate(u64 mask, bool simd_enabled) { /* The mask could be 0 if only the SIMD registers are interested */ if (mask & (REG_NOSUPPORT | PERF_REG_X86_RESERVED)) diff --git a/include/linux/perf_regs.h b/include/linux/perf_regs.h index 518f28c6a7d4..09dbc2fc3859 100644 --- a/include/linux/perf_regs.h +++ b/include/linux/perf_regs.h @@ -10,7 +10,7 @@ struct perf_regs { }; =20 u64 perf_reg_value(struct pt_regs *regs, int idx); -int perf_reg_validate(u64 mask); +int perf_reg_validate(u64 mask, bool simd_enabled); u64 perf_reg_abi(struct task_struct *task); void perf_get_regs_user(struct perf_regs *regs_user, struct pt_regs *regs); diff --git a/kernel/events/core.c b/kernel/events/core.c index 8f0018f061bd..6eaa1bb2e4fd 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -7812,7 +7812,7 @@ u64 __weak perf_reg_value(struct pt_regs *regs, int i= dx) return 0; } =20 -int __weak perf_reg_validate(u64 mask) +int __weak perf_reg_validate(u64 mask, bool simd_enabled) { return mask ? -ENOSYS : 0; } @@ -13793,7 +13793,8 @@ static int perf_copy_attr(struct perf_event_attr __= user *uattr, } =20 if (attr->sample_type & PERF_SAMPLE_REGS_USER) { - ret =3D perf_reg_validate(attr->sample_regs_user); + ret =3D perf_reg_validate(attr->sample_regs_user, + attr->sample_simd_regs_enabled); if (ret) return ret; if (attr->sample_simd_regs_enabled) { @@ -13825,7 +13826,8 @@ static int perf_copy_attr(struct perf_event_attr __= user *uattr, attr->sample_max_stack =3D sysctl_perf_event_max_stack; =20 if (attr->sample_type & PERF_SAMPLE_REGS_INTR) { - ret =3D perf_reg_validate(attr->sample_regs_intr); + ret =3D perf_reg_validate(attr->sample_regs_intr, + attr->sample_simd_regs_enabled); if (ret) return ret; if (attr->sample_simd_regs_enabled) { --=20 2.34.1 From nobody Sat Jul 25 01:34:42 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.11]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8836142E8F8; Tue, 21 Jul 2026 06:34:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.11 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784615652; cv=none; b=WHY5YXeBtT5BWFwcLhUbgNqBLX3mI4ts9n5P7D7s2DtB+jb2t2bYTW/mYdlIziqw3vop3bVh8eGVmz/3foJFTNGEOKORxR/LMR3zoriFvmZfzIX/xiSycu1LZqs1sQInIaJGEC6XfKZr5kS+LAeTNtlbnuOJLKE8O8iivzQBfXg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784615652; c=relaxed/simple; bh=E+iwbE7IIqqiPfepEc5+InvGmkQDebc4q9YD4gTbuhM=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=tMxiR+XbpxqujcKSfSi1p4SDhETqZCz3ljgp//df5XGyi0zQUBmgx1PY+gSfX2P7051zeHGdlOEwroG/sK6OGePb7sqZLI/PuyKWDKYNmVRpr8vLJLG9mEcHPCyr7FkuvGUINgBANpIpTNIbca9EC5j9ojbjlIKHO4RGyfYB3ZE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=pass smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=E9xbXHIR; arc=none smtp.client-ip=198.175.65.11 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="E9xbXHIR" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1784615651; x=1816151651; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=E+iwbE7IIqqiPfepEc5+InvGmkQDebc4q9YD4gTbuhM=; b=E9xbXHIRLqu/aGDYl80XSEvCCWABO7U1i6yabh5c7ihXmKcGWokx/qhZ EYrvBm7Yw8eiRX7EVXV9+BjU7sSrfZfxd5Sv7+qqN1Gj9LZUDqG6Ij79T As5ENo/PXzjFxjfrFOcrLSgTpIWmYn4o0vx5zAyNNaVZQPuo7aO3F3jRF DpY4AzLQWgChbR2MZ/oq75CdCos+liT7rLPzZdMLpCkc9TXM/qKgZTQYh 3NP2N7qaW1zpDD42qOHFy+LDTZSC5chBe7R5P6adynpWzjV5ZaUfUGzji c6l7NavkxeRB+FLjM1KxhmUiq+dOisUnD21UiXW4iaMUOdz8Mhq+wUWW4 A==; X-CSE-ConnectionGUID: EKsQTIDqQam0nWXaSMJPIQ== X-CSE-MsgGUID: aptaaZPMRh6SbawP4H3OBg== X-IronPort-AV: E=McAfee;i="6800,10657,11852"; a="95565543" X-IronPort-AV: E=Sophos;i="6.25,176,1779174000"; d="scan'208";a="95565543" Received: from fmviesa004.fm.intel.com ([10.60.135.144]) by orvoesa103.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Jul 2026 23:34:10 -0700 X-CSE-ConnectionGUID: ti+3wmcXSECoMrPjktLicQ== X-CSE-MsgGUID: GEtt0fRHS/KxHArN/MWHIg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.25,176,1779174000"; d="scan'208";a="259656193" Received: from spr.sh.intel.com ([10.112.229.196]) by fmviesa004.fm.intel.com with ESMTP; 20 Jul 2026 23:34:02 -0700 From: Dapeng Mi To: Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Thomas Gleixner , Dave Hansen , Ian Rogers , Adrian Hunter , Jiri Olsa , Alexander Shishkin , Andi Kleen , Eranian Stephane Cc: Mark Rutland , broonie@kernel.org, Ravi Bangoria , linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org, Zide Chen , Falcon Thomas , Dapeng Mi , Xudong Hao , Dapeng Mi , Kan Liang Subject: [Patch v10 18/23] perf/x86: Support eGPRs sampling using sample_regs_* fields Date: Tue, 21 Jul 2026 14:25:01 +0800 Message-Id: <20260721062506.3745816-19-dapeng1.mi@linux.intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260721062506.3745816-1-dapeng1.mi@linux.intel.com> References: <20260721062506.3745816-1-dapeng1.mi@linux.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Support sampling of APX eGPRs (R16 ~ R31) via the sample_regs_* fields. To sample eGPRs, the sample_simd_regs_enabled field must be set. This allows the spare space (reclaimed from the original XMM space) in the sample_regs_* fields to be used for representing eGPRs. The perf_reg_value() function needs to check if the PERF_SAMPLE_REGS_ABI_SIMD flag is set first, and then determine whether to output eGPRs or legacy XMM registers to userspace. The perf_reg_validate() function first checks the simd_enabled argument to determine if the eGPRs bitmap is represented in sample_regs_* fields. It then validates the eGPRs bitmap accordingly. Currently, eGPRs sampling is only supported on the x86_64 architecture, as APX is only available on x86_64 platforms. APX eGPRs sampling will be enabled in a subsequent patch that sets PERF_PMU_CAP_SIMD_REGS. Suggested-by: Peter Zijlstra (Intel) Co-developed-by: Kan Liang Signed-off-by: Kan Liang Signed-off-by: Dapeng Mi --- arch/x86/events/core.c | 25 +++++++++++--- arch/x86/events/intel/core.c | 10 ++++-- arch/x86/events/perf_event.h | 25 ++++++++++++++ arch/x86/include/asm/perf_event.h | 4 +++ arch/x86/include/uapi/asm/perf_regs.h | 26 ++++++++++++++ arch/x86/kernel/perf_regs.c | 50 +++++++++++++++++---------- 6 files changed, 115 insertions(+), 25 deletions(-) diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c index 9bfb1810a9fe..9cd79ac5570e 100644 --- a/arch/x86/events/core.c +++ b/arch/x86/events/core.c @@ -642,11 +642,12 @@ static int pebs_simd_regs_validate(struct perf_event = *event) if (event_needs_xmm(event) && x86_pmu.arch_pebs && !(caps & ARCH_PEBS_VECR_XMM)) return -EINVAL; - /* PEBS does not support YMM/ZMM/OPMASK registers sampling yet. */ + /* PEBS does not support YMM/ZMM/OPMASK/eGPR registers sampling yet. */ if (event_needs_ymm(event) || event_needs_low16_zmm(event) || event_needs_high16_zmm(event) || - event_needs_opmask(event)) + event_needs_opmask(event) || + event_needs_egprs(event)) return -EINVAL; =20 return 0; @@ -654,10 +655,21 @@ static int pebs_simd_regs_validate(struct perf_event = *event) =20 static int event_simd_regs_validate(struct perf_event *event) { + u64 reserved =3D ~GENMASK_ULL(PERF_REG_MISC_MAX - 1, 0); + if (!get_ext_regs_buf(raw_smp_processor_id())) return -ENOMEM; - /* sample_simd_regs_enabled repurposes legacy XMM reg-mask slots. */ - if (event_has_extended_regs(event)) + /* + * The XMM space in the perf_event_x86_regs is reclaimed + * for eGPRs and other general registers. + */ + if (((event->attr.sample_type & PERF_SAMPLE_REGS_INTR) && + (event->attr.sample_regs_intr & reserved)) || + ((event->attr.sample_type & PERF_SAMPLE_REGS_USER) && + (event->attr.sample_regs_user & reserved))) + return -EINVAL; + if (event_needs_egprs(event) && + !(x86_pmu.ext_regs_mask & XFEATURE_MASK_APX)) return -EINVAL; if (event_needs_xmm(event) && !(x86_pmu.ext_regs_mask & XFEATURE_MASK_SSE)) @@ -1841,6 +1853,7 @@ void x86_pmu_clear_perf_regs(struct pt_regs *regs) perf_regs->zmmh_regs =3D NULL; perf_regs->h16zmm_regs =3D NULL; perf_regs->opmask_regs =3D NULL; + perf_regs->egpr_regs =3D NULL; } =20 static void update_perf_regs(struct x86_perf_regs *perf_regs, @@ -1864,6 +1877,8 @@ static void update_perf_regs(struct x86_perf_regs *pe= rf_regs, perf_regs->h16zmm =3D get_xsave_addr(xsave, XFEATURE_Hi16_ZMM); if (mask & XFEATURE_MASK_OPMASK) perf_regs->opmask =3D get_xsave_addr(xsave, XFEATURE_OPMASK); + if (mask & XFEATURE_MASK_APX) + perf_regs->egpr =3D get_xsave_addr(xsave, XFEATURE_APX); } =20 /* @@ -2040,6 +2055,8 @@ static u64 get_simd_sample_mask(struct perf_event *ev= ent, u64 sample_type) mask |=3D XFEATURE_MASK_Hi16_ZMM; if (__event_needs_opmask(event, sample_type)) mask |=3D XFEATURE_MASK_OPMASK; + if (__event_needs_egprs(event, sample_type)) + mask |=3D XFEATURE_MASK_APX; =20 return mask; } diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c index dbf143eb3547..fd6d20db4dc7 100644 --- a/arch/x86/events/intel/core.c +++ b/arch/x86/events/intel/core.c @@ -4719,15 +4719,19 @@ static void intel_pebs_aliases_skl(struct perf_even= t *event) static unsigned long intel_pmu_large_pebs_flags(struct perf_event *event) { unsigned long flags =3D x86_pmu.large_pebs_flags; - u64 gprs_mask =3D PEBS_GP_REGS | PERF_REG_EXTENDED_MASK; + u64 gprs_mask =3D event->attr.sample_simd_regs_enabled ? + PEBS_GP_REGS | PERF_X86_EGPRS_MASK : + PEBS_GP_REGS | PERF_REG_EXTENDED_MASK; =20 if (event->attr.use_clockid) flags &=3D ~PERF_SAMPLE_TIME; if (!event->attr.exclude_kernel) flags &=3D ~PERF_SAMPLE_REGS_USER; - if (event->attr.sample_regs_user & ~gprs_mask) + if ((event->attr.sample_type & PERF_SAMPLE_REGS_USER) && + (event->attr.sample_regs_user & ~gprs_mask)) flags &=3D ~PERF_SAMPLE_REGS_USER; - if (event->attr.sample_regs_intr & ~gprs_mask) + if ((event->attr.sample_type & PERF_SAMPLE_REGS_INTR) && + (event->attr.sample_regs_intr & ~gprs_mask)) flags &=3D ~PERF_SAMPLE_REGS_INTR; return flags; } diff --git a/arch/x86/events/perf_event.h b/arch/x86/events/perf_event.h index e6365438bb3d..899584cdbdd3 100644 --- a/arch/x86/events/perf_event.h +++ b/arch/x86/events/perf_event.h @@ -290,6 +290,31 @@ static inline bool event_needs_opmask(struct perf_even= t *event) PERF_SAMPLE_REGS_INTR | PERF_SAMPLE_REGS_USER); } =20 +static inline bool __event_needs_egprs(struct perf_event *event, + u64 sample_type) +{ + if (!event->attr.sample_simd_regs_enabled) + return false; + + if ((sample_type & PERF_SAMPLE_REGS_USER) && + (event->attr.sample_type & PERF_SAMPLE_REGS_USER) && + (event->attr.sample_regs_user & PERF_X86_EGPRS_MASK)) + return true; + + if ((sample_type & PERF_SAMPLE_REGS_INTR) && + (event->attr.sample_type & PERF_SAMPLE_REGS_INTR) && + (event->attr.sample_regs_intr & PERF_X86_EGPRS_MASK)) + return true; + + return false; +} + +static inline bool event_needs_egprs(struct perf_event *event) +{ + return __event_needs_egprs(event, + PERF_SAMPLE_REGS_INTR | PERF_SAMPLE_REGS_USER); +} + struct amd_nb { int nb_id; /* NorthBridge id */ int refcnt; /* reference count */ diff --git a/arch/x86/include/asm/perf_event.h b/arch/x86/include/asm/perf_= event.h index 49112e097e99..bc05f8c17464 100644 --- a/arch/x86/include/asm/perf_event.h +++ b/arch/x86/include/asm/perf_event.h @@ -749,6 +749,10 @@ struct x86_perf_regs { u64 *opmask_regs; struct avx_512_opmask_state *opmask; }; + union { + u64 *egpr_regs; + struct apx_state *egpr; + }; }; =20 extern unsigned long perf_arch_instruction_pointer(struct pt_regs *regs); diff --git a/arch/x86/include/uapi/asm/perf_regs.h b/arch/x86/include/uapi/= asm/perf_regs.h index 61aec60623f1..977831bd7a9d 100644 --- a/arch/x86/include/uapi/asm/perf_regs.h +++ b/arch/x86/include/uapi/asm/perf_regs.h @@ -29,9 +29,34 @@ enum perf_event_x86_regs { PERF_REG_X86_R13, PERF_REG_X86_R14, PERF_REG_X86_R15, + /* + * The eGPRs and XMM have overlaps. Only one can be used + * at a time. The ABI PERF_SAMPLE_REGS_ABI_SIMD is used to + * distinguish which one is used. If PERF_SAMPLE_REGS_ABI_SIMD + * is set, then eGPRs is used, otherwise, XMM is used. + * + * Extended GPRs (eGPRs) + */ + PERF_REG_X86_R16, + PERF_REG_X86_R17, + PERF_REG_X86_R18, + PERF_REG_X86_R19, + PERF_REG_X86_R20, + PERF_REG_X86_R21, + PERF_REG_X86_R22, + PERF_REG_X86_R23, + PERF_REG_X86_R24, + PERF_REG_X86_R25, + PERF_REG_X86_R26, + PERF_REG_X86_R27, + PERF_REG_X86_R28, + PERF_REG_X86_R29, + PERF_REG_X86_R30, + PERF_REG_X86_R31, /* These are the limits for the GPRs. */ PERF_REG_X86_32_MAX =3D PERF_REG_X86_GS + 1, PERF_REG_X86_64_MAX =3D PERF_REG_X86_R15 + 1, + PERF_REG_MISC_MAX =3D PERF_REG_X86_R31 + 1, =20 /* These all need two bits set because they are 128bit */ PERF_REG_X86_XMM0 =3D 32, @@ -56,6 +81,7 @@ enum perf_event_x86_regs { }; =20 #define PERF_REG_EXTENDED_MASK (~((1ULL << PERF_REG_X86_XMM0) - 1)) +#define PERF_X86_EGPRS_MASK __GENMASK_ULL(PERF_REG_X86_R31, PERF_REG_X86_R= 16) =20 enum { PERF_X86_SIMD_XMM_REGS =3D 16, diff --git a/arch/x86/kernel/perf_regs.c b/arch/x86/kernel/perf_regs.c index 494e06501210..7d4233ed859c 100644 --- a/arch/x86/kernel/perf_regs.c +++ b/arch/x86/kernel/perf_regs.c @@ -61,14 +61,24 @@ u64 perf_reg_value(struct pt_regs *regs, int idx) { struct x86_perf_regs *perf_regs; =20 - if (idx >=3D PERF_REG_X86_XMM0 && idx < PERF_REG_X86_XMM_MAX) { + if (idx > PERF_REG_X86_R15) { perf_regs =3D container_of(regs, struct x86_perf_regs, regs); - /* SIMD registers are moved to dedicated sample_simd_vec_reg */ - if (perf_regs->abi & PERF_SAMPLE_REGS_ABI_SIMD) + if (perf_regs->abi =3D=3D PERF_SAMPLE_REGS_ABI_NONE) return 0; - if (!perf_regs->xmm_regs) - return 0; - return perf_regs->xmm_regs[idx - PERF_REG_X86_XMM0]; + + if (perf_regs->abi & PERF_SAMPLE_REGS_ABI_SIMD) { + if (idx <=3D PERF_REG_X86_R31) { + if (!perf_regs->egpr_regs) + return 0; + return perf_regs->egpr_regs[idx - PERF_REG_X86_R16]; + } + } else { + if (idx >=3D PERF_REG_X86_XMM0 && idx < PERF_REG_X86_XMM_MAX) { + if (!perf_regs->xmm_regs) + return 0; + return perf_regs->xmm_regs[idx - PERF_REG_X86_XMM0]; + } + } } =20 if (WARN_ON_ONCE(idx >=3D ARRAY_SIZE(pt_regs_offset))) @@ -185,23 +195,22 @@ int perf_simd_reg_validate(u16 vec_qwords, u64 vec_ma= sk, return 0; } =20 -#define PERF_REG_X86_RESERVED (((1ULL << PERF_REG_X86_XMM0) - 1) & \ - ~((1ULL << PERF_REG_X86_MAX) - 1)) +#define PERF_REG_X86_RESERVED (GENMASK_ULL(PERF_REG_X86_XMM0 - 1, PERF_REG= _X86_AX) & \ + ~GENMASK_ULL(PERF_REG_X86_R15, PERF_REG_X86_AX)) +#define PERF_REG_X86_EXT_RESERVED (~GENMASK_ULL(PERF_REG_MISC_MAX - 1, PER= F_REG_X86_AX)) =20 #ifdef CONFIG_X86_32 -#define REG_NOSUPPORT ((1ULL << PERF_REG_X86_R8) | \ - (1ULL << PERF_REG_X86_R9) | \ - (1ULL << PERF_REG_X86_R10) | \ - (1ULL << PERF_REG_X86_R11) | \ - (1ULL << PERF_REG_X86_R12) | \ - (1ULL << PERF_REG_X86_R13) | \ - (1ULL << PERF_REG_X86_R14) | \ - (1ULL << PERF_REG_X86_R15)) +#define REG_NOSUPPORT GENMASK_ULL(PERF_REG_X86_R15, PERF_REG_X86_R8) =20 int perf_reg_validate(u64 mask, bool simd_enabled) { + if (!simd_enabled && + (!mask || (mask & (REG_NOSUPPORT | PERF_REG_X86_RESERVED)))) + return -EINVAL; + /* The mask could be 0 if only the SIMD registers are interested */ - if (mask & (REG_NOSUPPORT | PERF_REG_X86_RESERVED)) + if (simd_enabled && + (mask & ~GENMASK_ULL(PERF_REG_X86_GS, PERF_REG_X86_AX))) return -EINVAL; =20 return 0; @@ -220,8 +229,13 @@ u64 perf_reg_abi(struct task_struct *task) =20 int perf_reg_validate(u64 mask, bool simd_enabled) { + if (!simd_enabled && + (!mask || (mask & (REG_NOSUPPORT | PERF_REG_X86_RESERVED)))) + return -EINVAL; + /* The mask could be 0 if only the SIMD registers are interested */ - if (mask & (REG_NOSUPPORT | PERF_REG_X86_RESERVED)) + if (simd_enabled && + (mask & (REG_NOSUPPORT | PERF_REG_X86_EXT_RESERVED))) return -EINVAL; =20 return 0; --=20 2.34.1 From nobody Sat Jul 25 01:34:42 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.11]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 91F6A435ABA; Tue, 21 Jul 2026 06:34:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.11 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784615660; cv=none; b=rYRXYWgrAM7LL/3nc+V9VpijtWu9yGThvSJ+aHnMAUHNwx4cHzxB61elzLG7nsqq45dDr7PuCWxxGWRLfD+xRbe7TwdGKcb0dm6swjUv2yprS5UauqSMguGSK4OmnwEugaSAZ9xmc4o2pLZgzW5Mw7Fo7/zsLW28WhrGrP+WJPI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784615660; c=relaxed/simple; bh=Q9c4BHV0NUJdSfMdMHMBJssvnrGsC8DjAYXoaKPixXY=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=um/mdF9W8siXN5CEUwgF+WVDojD7mMAJwADy46mn85oldzbTtu1ZKh3Qv3SpEfcPEhh3ufPQRrcHyGqQ+G056+ZqsKKC7PoDkS25Jrm8/6ut1T5xhInevZgE4GrBjE3BmSpqJeO4ZRSsm4zyYFO+e8H0PPd0yHRN8Zos5lgH8gc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=pass smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=YpvqZBJy; arc=none smtp.client-ip=198.175.65.11 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="YpvqZBJy" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1784615659; x=1816151659; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=Q9c4BHV0NUJdSfMdMHMBJssvnrGsC8DjAYXoaKPixXY=; b=YpvqZBJytsmxdFhjvjJTYdGxG3w4pDc+YhGtcH4U8IA/deSyjsqMxf7h a6MgzMWjfczB1Ol5U2Haanz0t7zpDmJFU0KTjfySbMn/gNElELz6QtVJ8 qiORhbvRgqQYi1030Mwmr3O7LTyZELRtqg6kx6LXt0I9Jy64x9yzp7Ppi RtQTz3hX+uRDHqfk6p9xObJCDFxdRksShDr/5BPjqBnjGmyu8G7uiz5h4 DOrwyRv7rHcPEcoaoznhgfa0eM7Y+2RFLQCIocXoGX3AmyzQNfhUfROao tYmAouBhnSJubOyrgvks2DRNEbg3RZA5yzj4W1XAn0fcBnD9e3ni0DwbH Q==; X-CSE-ConnectionGUID: 5Yp0eIZKRLSJHCxhSeeDZA== X-CSE-MsgGUID: hIPYWpyURKu24xqit7Retw== X-IronPort-AV: E=McAfee;i="6800,10657,11852"; a="95565566" X-IronPort-AV: E=Sophos;i="6.25,176,1779174000"; d="scan'208";a="95565566" Received: from fmviesa004.fm.intel.com ([10.60.135.144]) by orvoesa103.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Jul 2026 23:34:18 -0700 X-CSE-ConnectionGUID: 9iNbYuVDTH+ttcZMgXY1hg== X-CSE-MsgGUID: UlIruHJeQe6dtI5lmlze4Q== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.25,176,1779174000"; d="scan'208";a="259656217" Received: from spr.sh.intel.com ([10.112.229.196]) by fmviesa004.fm.intel.com with ESMTP; 20 Jul 2026 23:34:10 -0700 From: Dapeng Mi To: Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Thomas Gleixner , Dave Hansen , Ian Rogers , Adrian Hunter , Jiri Olsa , Alexander Shishkin , Andi Kleen , Eranian Stephane Cc: Mark Rutland , broonie@kernel.org, Ravi Bangoria , linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org, Zide Chen , Falcon Thomas , Dapeng Mi , Xudong Hao , Dapeng Mi , Kan Liang Subject: [Patch v10 19/23] perf/x86: Support SSP sampling using sample_regs_* fields Date: Tue, 21 Jul 2026 14:25:02 +0800 Message-Id: <20260721062506.3745816-20-dapeng1.mi@linux.intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260721062506.3745816-1-dapeng1.mi@linux.intel.com> References: <20260721062506.3745816-1-dapeng1.mi@linux.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Support sampling of CET SSP register via the sample_regs_* fields. To sample SSP, the sample_simd_regs_enabled field must be set. This allows the spare space (reclaimed from the original XMM space) in the sample_regs_* fields to be used for representing SSP. Similar to eGPRs sampling, the perf_reg_value() function needs to check if the PERF_SAMPLE_REGS_ABI_SIMD flag is set first, and then determine whether to output SSP or legacy XMM registers to userspace. Additionally, arch-PEBS supports sampling SSP, which is placed into the GPRs group. Also enables arch-PEBS-based SSP sampling. Currently, SSP sampling is only supported on the x86_64 architecture, as CET is only available on x86_64 platforms. SSP sampling will be enabled in a subsequent patch that sets PERF_PMU_CAP_SIMD_REGS. Co-developed-by: Kan Liang Signed-off-by: Kan Liang Signed-off-by: Dapeng Mi --- arch/x86/events/core.c | 15 +++++++++++++++ arch/x86/events/intel/core.c | 3 ++- arch/x86/events/intel/ds.c | 13 +++++++++++-- arch/x86/events/perf_event.h | 25 +++++++++++++++++++++++++ arch/x86/include/asm/perf_event.h | 1 + arch/x86/include/uapi/asm/perf_regs.h | 7 ++++--- arch/x86/kernel/perf_regs.c | 5 +++++ 7 files changed, 63 insertions(+), 6 deletions(-) diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c index 9cd79ac5570e..caa5a0fb3ed8 100644 --- a/arch/x86/events/core.c +++ b/arch/x86/events/core.c @@ -642,6 +642,10 @@ static int pebs_simd_regs_validate(struct perf_event *= event) if (event_needs_xmm(event) && x86_pmu.arch_pebs && !(caps & ARCH_PEBS_VECR_XMM)) return -EINVAL; + + if (event_needs_ssp(event) && + !(x86_pmu.arch_pebs && (caps & ARCH_PEBS_GPR))) + return -EINVAL; /* PEBS does not support YMM/ZMM/OPMASK/eGPR registers sampling yet. */ if (event_needs_ymm(event) || event_needs_low16_zmm(event) || @@ -671,6 +675,9 @@ static int event_simd_regs_validate(struct perf_event *= event) if (event_needs_egprs(event) && !(x86_pmu.ext_regs_mask & XFEATURE_MASK_APX)) return -EINVAL; + if (event_needs_ssp(event) && + !(x86_pmu.ext_regs_mask & XFEATURE_MASK_CET_USER)) + return -EINVAL; if (event_needs_xmm(event) && !(x86_pmu.ext_regs_mask & XFEATURE_MASK_SSE)) return -EINVAL; @@ -1854,11 +1861,13 @@ void x86_pmu_clear_perf_regs(struct pt_regs *regs) perf_regs->h16zmm_regs =3D NULL; perf_regs->opmask_regs =3D NULL; perf_regs->egpr_regs =3D NULL; + perf_regs->ssp =3D NULL; } =20 static void update_perf_regs(struct x86_perf_regs *perf_regs, struct xregs_state *xsave, u64 bitmap) { + struct cet_user_state *cet; u64 mask; =20 if (!xsave) @@ -1879,6 +1888,10 @@ static void update_perf_regs(struct x86_perf_regs *p= erf_regs, perf_regs->opmask =3D get_xsave_addr(xsave, XFEATURE_OPMASK); if (mask & XFEATURE_MASK_APX) perf_regs->egpr =3D get_xsave_addr(xsave, XFEATURE_APX); + if (mask & XFEATURE_MASK_CET_USER) { + cet =3D get_xsave_addr(xsave, XFEATURE_CET_USER); + perf_regs->ssp =3D cet ? &cet->user_ssp : NULL; + } } =20 /* @@ -2057,6 +2070,8 @@ static u64 get_simd_sample_mask(struct perf_event *ev= ent, u64 sample_type) mask |=3D XFEATURE_MASK_OPMASK; if (__event_needs_egprs(event, sample_type)) mask |=3D XFEATURE_MASK_APX; + if (__event_needs_ssp(event, sample_type)) + mask |=3D XFEATURE_MASK_CET_USER; =20 return mask; } diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c index fd6d20db4dc7..809ef2515b10 100644 --- a/arch/x86/events/intel/core.c +++ b/arch/x86/events/intel/core.c @@ -4720,7 +4720,8 @@ static unsigned long intel_pmu_large_pebs_flags(struc= t perf_event *event) { unsigned long flags =3D x86_pmu.large_pebs_flags; u64 gprs_mask =3D event->attr.sample_simd_regs_enabled ? - PEBS_GP_REGS | PERF_X86_EGPRS_MASK : + PEBS_GP_REGS | PERF_X86_EGPRS_MASK | + BIT_ULL(PERF_REG_X86_SSP) : PEBS_GP_REGS | PERF_REG_EXTENDED_MASK; =20 if (event->attr.use_clockid) diff --git a/arch/x86/events/intel/ds.c b/arch/x86/events/intel/ds.c index eb61eae9226d..3277bd72e0a8 100644 --- a/arch/x86/events/intel/ds.c +++ b/arch/x86/events/intel/ds.c @@ -1700,6 +1700,7 @@ static u64 pebs_update_adaptive_cfg(struct perf_event= *event) u64 sample_type =3D attr->sample_type; u64 pebs_data_cfg =3D 0; bool gprs, tsx_weight; + u64 xgprs_mask; =20 if (!(sample_type & ~(PERF_SAMPLE_IP|PERF_SAMPLE_TIME)) && attr->precise_ip > 1) @@ -1714,10 +1715,13 @@ static u64 pebs_update_adaptive_cfg(struct perf_eve= nt *event) * + precise_ip < 2 for the non event IP * + For RTM TSX weight we need GPRs for the abort code. */ + xgprs_mask =3D event->attr.sample_simd_regs_enabled ? + PEBS_GP_REGS | BIT_ULL(PERF_REG_X86_SSP) : + PEBS_GP_REGS; gprs =3D ((sample_type & PERF_SAMPLE_REGS_INTR) && - (attr->sample_regs_intr & PEBS_GP_REGS)) || + (attr->sample_regs_intr & xgprs_mask)) || ((sample_type & PERF_SAMPLE_REGS_USER) && - (attr->sample_regs_user & PEBS_GP_REGS)); + (attr->sample_regs_user & xgprs_mask)); =20 tsx_weight =3D (sample_type & PERF_SAMPLE_WEIGHT_TYPE) && ((attr->config & INTEL_ARCH_EVENT_MASK) =3D=3D @@ -2666,6 +2670,11 @@ static void setup_arch_pebs_sample_data(struct perf_= event *event, __setup_pebs_gpr_group(event, regs, (struct pebs_gprs *)gprs, sample_type); + + /* Currently only user space mode enables SSP. */ + if (user_mode(regs) && (sample_type & + (PERF_SAMPLE_REGS_INTR | PERF_SAMPLE_REGS_USER))) + perf_regs->ssp =3D &gprs->ssp; } =20 if (header->aux) { diff --git a/arch/x86/events/perf_event.h b/arch/x86/events/perf_event.h index 899584cdbdd3..eca7fab86b9b 100644 --- a/arch/x86/events/perf_event.h +++ b/arch/x86/events/perf_event.h @@ -315,6 +315,31 @@ static inline bool event_needs_egprs(struct perf_event= *event) PERF_SAMPLE_REGS_INTR | PERF_SAMPLE_REGS_USER); } =20 +static inline bool __event_needs_ssp(struct perf_event *event, + u64 sample_type) +{ + if (!event->attr.sample_simd_regs_enabled) + return false; + + if ((sample_type & PERF_SAMPLE_REGS_USER) && + (event->attr.sample_type & PERF_SAMPLE_REGS_USER) && + (event->attr.sample_regs_user & BIT_ULL(PERF_REG_X86_SSP))) + return true; + + if ((sample_type & PERF_SAMPLE_REGS_INTR) && + (event->attr.sample_type & PERF_SAMPLE_REGS_INTR) && + (event->attr.sample_regs_intr & BIT_ULL(PERF_REG_X86_SSP))) + return true; + + return false; +} + +static inline bool event_needs_ssp(struct perf_event *event) +{ + return __event_needs_ssp(event, + PERF_SAMPLE_REGS_INTR | PERF_SAMPLE_REGS_USER); +} + struct amd_nb { int nb_id; /* NorthBridge id */ int refcnt; /* reference count */ diff --git a/arch/x86/include/asm/perf_event.h b/arch/x86/include/asm/perf_= event.h index bc05f8c17464..4302ef39c42e 100644 --- a/arch/x86/include/asm/perf_event.h +++ b/arch/x86/include/asm/perf_event.h @@ -753,6 +753,7 @@ struct x86_perf_regs { u64 *egpr_regs; struct apx_state *egpr; }; + u64 *ssp; }; =20 extern unsigned long perf_arch_instruction_pointer(struct pt_regs *regs); diff --git a/arch/x86/include/uapi/asm/perf_regs.h b/arch/x86/include/uapi/= asm/perf_regs.h index 977831bd7a9d..faaa82df688d 100644 --- a/arch/x86/include/uapi/asm/perf_regs.h +++ b/arch/x86/include/uapi/asm/perf_regs.h @@ -30,10 +30,10 @@ enum perf_event_x86_regs { PERF_REG_X86_R14, PERF_REG_X86_R15, /* - * The eGPRs and XMM have overlaps. Only one can be used + * The eGPRs/SSP and XMM have overlaps. Only one can be used * at a time. The ABI PERF_SAMPLE_REGS_ABI_SIMD is used to * distinguish which one is used. If PERF_SAMPLE_REGS_ABI_SIMD - * is set, then eGPRs is used, otherwise, XMM is used. + * is set, then eGPRs/SSP is used, otherwise, XMM is used. * * Extended GPRs (eGPRs) */ @@ -53,10 +53,11 @@ enum perf_event_x86_regs { PERF_REG_X86_R29, PERF_REG_X86_R30, PERF_REG_X86_R31, + PERF_REG_X86_SSP, /* These are the limits for the GPRs. */ PERF_REG_X86_32_MAX =3D PERF_REG_X86_GS + 1, PERF_REG_X86_64_MAX =3D PERF_REG_X86_R15 + 1, - PERF_REG_MISC_MAX =3D PERF_REG_X86_R31 + 1, + PERF_REG_MISC_MAX =3D PERF_REG_X86_SSP + 1, =20 /* These all need two bits set because they are 128bit */ PERF_REG_X86_XMM0 =3D 32, diff --git a/arch/x86/kernel/perf_regs.c b/arch/x86/kernel/perf_regs.c index 7d4233ed859c..f8952f7c36cc 100644 --- a/arch/x86/kernel/perf_regs.c +++ b/arch/x86/kernel/perf_regs.c @@ -72,6 +72,11 @@ u64 perf_reg_value(struct pt_regs *regs, int idx) return 0; return perf_regs->egpr_regs[idx - PERF_REG_X86_R16]; } + if (idx =3D=3D PERF_REG_X86_SSP) { + if (!perf_regs->ssp) + return 0; + return *perf_regs->ssp; + } } else { if (idx >=3D PERF_REG_X86_XMM0 && idx < PERF_REG_X86_XMM_MAX) { if (!perf_regs->xmm_regs) --=20 2.34.1 From nobody Sat Jul 25 01:34:42 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.11]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 29EDA435A8A; Tue, 21 Jul 2026 06:34:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.11 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784615668; cv=none; b=f6ZraKz+pdVjvyhOgGt4sZfE0p9UCBu+0EWk6ztVVO5DM3X5ZtXv3/UmTa/NDODM6hnupLJb+SncW98poBQNEJxQiek5ygw7fcmWjpotuCMb9c0w8IXIPituYf7njkh85cjhmdme08Sx21PC/iHUfn0KcpECezaKf9R6j+bOSmM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784615668; c=relaxed/simple; bh=83r90lwv+qO87IZJ94rtwC/rZxsSNb/CRtSZIamGDRM=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=hLkbEADLpsOxome5q/RAahj60XibJ9Ald0M79HBumy2RbBhiB663kuz1RWWqkV7lrCFgE+7qKoTdIPnqXIogP7tl3JJUnmSs/3qCKptbn/i0e59b3487NvDiAxSilORmO1KYyDlVzKaHv5HWxU35U4SjDlHDTjINh/9PDNFXIkE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=pass smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=YfcDEHQp; arc=none smtp.client-ip=198.175.65.11 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="YfcDEHQp" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1784615665; x=1816151665; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=83r90lwv+qO87IZJ94rtwC/rZxsSNb/CRtSZIamGDRM=; b=YfcDEHQpdkRxiWVCbwjilj6yrTVFkXYyWJBZ8SLiZrppJubXKLcmwPfn Q/fPIJ9+MNNVuXZfTz58na1Xerfr3uYKsAZMB+HdB63YtbXd0/wpFEX81 mj1hv68mZ/sXQIkfSblUI8JGhj4BeD/cXa+zXUbLlzM9SREtItlyYN8fR /tgXdeL8JbMEvr69iYnzxpfccmwyq415C2cclXPW5KXZye0rfCSWLmon6 N8mbj3j7xdI624XvJWxhN9iHBaJVS1c3ycwfnG/glmhKBKYiZ/k3t+Ybt 0em9c1Iz7E24fp3bn8UlVcTvvKcjHbZw596fCnX9JDLN9qkuASqPzM2iq w==; X-CSE-ConnectionGUID: OpM90qI7RFqtb+8GKnnCnw== X-CSE-MsgGUID: odBklry5QRmHMfElYC6bIw== X-IronPort-AV: E=McAfee;i="6800,10657,11852"; a="95565574" X-IronPort-AV: E=Sophos;i="6.25,176,1779174000"; d="scan'208";a="95565574" Received: from fmviesa004.fm.intel.com ([10.60.135.144]) by orvoesa103.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Jul 2026 23:34:25 -0700 X-CSE-ConnectionGUID: y2TgCjdtQb+KkD+MfTCAHw== X-CSE-MsgGUID: jS5WDHu8Spu1DA3udmIGTQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.25,176,1779174000"; d="scan'208";a="259656236" Received: from spr.sh.intel.com ([10.112.229.196]) by fmviesa004.fm.intel.com with ESMTP; 20 Jul 2026 23:34:18 -0700 From: Dapeng Mi To: Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Thomas Gleixner , Dave Hansen , Ian Rogers , Adrian Hunter , Jiri Olsa , Alexander Shishkin , Andi Kleen , Eranian Stephane Cc: Mark Rutland , broonie@kernel.org, Ravi Bangoria , linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org, Zide Chen , Falcon Thomas , Dapeng Mi , Xudong Hao , Dapeng Mi Subject: [Patch v10 20/23] perf/x86/intel: Support arch-PEBS based SIMD/eGPRs sampling Date: Tue, 21 Jul 2026 14:25:03 +0800 Message-Id: <20260721062506.3745816-21-dapeng1.mi@linux.intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260721062506.3745816-1-dapeng1.mi@linux.intel.com> References: <20260721062506.3745816-1-dapeng1.mi@linux.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Support arch-PEBS based SIMD/eGPRs/SSP registers sampling. Arch-PEBS supports sampling all of these registers. SIMD and eGPR registers are placed into the XSAVE-Enabled Registers (XER) group with the layout described below. Field Name Registers Used Size XSTATE_BV XINUSE for groups 8 B Reserved Reserved 8 B SSER XMM0-XMM15 16 regs * 16 B =3D 256 B YMMHIR Upper 128 bits of YMM0-YMM15 16 regs * 16 B =3D 256 B EGPR R16-R31 16 regs * 8 B =3D 128 B OPMASKR K0-K7 8 regs * 8 B =3D 64 B ZMMHIR Upper 256 bits of ZMM0-ZMM15 16 regs * 32 B =3D 512 B Hi16ZMMR ZMM16-ZMM31 16 regs * 64 B =3D 1024 B Memory space in the output buffer is allocated for these sub-groups as long as the corresponding Format.XER[55:49] bits in the PEBS record header are set. However, the arch-PEBS hardware engine does not write the sub-group if it is not used (in INIT state). In such cases, the corresponding bit in the XSTATE_BV bitmap is set to 0. Therefore, the XSTATE_BV field is checked to determine if the register data is actually written for each PEBS record. If not, the register data is not outputted to userspace. Additionally, the MSRs IA32_PMC_{GPn|FXm}_CFG_C.[55:49] bits are used to manage which types of these registers need to be sampled. Arch-PEBS based SIMD/eGPRs sampling will be enabled in a subsequent patch that sets PERF_PMU_CAP_SIMD_REGS. Signed-off-by: Dapeng Mi --- arch/x86/events/core.c | 20 ++++++--- arch/x86/events/intel/core.c | 15 +++++++ arch/x86/events/intel/ds.c | 67 +++++++++++++++++++++++++++++-- arch/x86/include/asm/msr-index.h | 7 ++++ arch/x86/include/asm/perf_event.h | 8 +++- 5 files changed, 106 insertions(+), 11 deletions(-) diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c index caa5a0fb3ed8..11799acd8c54 100644 --- a/arch/x86/events/core.c +++ b/arch/x86/events/core.c @@ -646,12 +646,20 @@ static int pebs_simd_regs_validate(struct perf_event = *event) if (event_needs_ssp(event) && !(x86_pmu.arch_pebs && (caps & ARCH_PEBS_GPR))) return -EINVAL; - /* PEBS does not support YMM/ZMM/OPMASK/eGPR registers sampling yet. */ - if (event_needs_ymm(event) || - event_needs_low16_zmm(event) || - event_needs_high16_zmm(event) || - event_needs_opmask(event) || - event_needs_egprs(event)) + if (event_needs_ymm(event) && + !(x86_pmu.arch_pebs && (caps & ARCH_PEBS_VECR_YMMH))) + return -EINVAL; + if (event_needs_egprs(event) && + !(x86_pmu.arch_pebs && (caps & ARCH_PEBS_VECR_EGPRS))) + return -EINVAL; + if (event_needs_opmask(event) && + !(x86_pmu.arch_pebs && (caps & ARCH_PEBS_VECR_OPMASK))) + return -EINVAL; + if (event_needs_low16_zmm(event) && + !(x86_pmu.arch_pebs && (caps & ARCH_PEBS_VECR_ZMMH))) + return -EINVAL; + if (event_needs_high16_zmm(event) && + !(x86_pmu.arch_pebs && (caps & ARCH_PEBS_VECR_H16ZMM))) return -EINVAL; =20 return 0; diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c index 809ef2515b10..4eeb08352f4c 100644 --- a/arch/x86/events/intel/core.c +++ b/arch/x86/events/intel/core.c @@ -3498,6 +3498,21 @@ static void intel_pmu_enable_event_ext(struct perf_e= vent *event) if (pebs_data_cfg & PEBS_DATACFG_XMMS) ext |=3D ARCH_PEBS_VECR_XMM & cap.caps; =20 + if (pebs_data_cfg & PEBS_DATACFG_YMMHS) + ext |=3D ARCH_PEBS_VECR_YMMH & cap.caps; + + if (pebs_data_cfg & PEBS_DATACFG_EGPRS) + ext |=3D ARCH_PEBS_VECR_EGPRS & cap.caps; + + if (pebs_data_cfg & PEBS_DATACFG_OPMASKS) + ext |=3D ARCH_PEBS_VECR_OPMASK & cap.caps; + + if (pebs_data_cfg & PEBS_DATACFG_ZMMHS) + ext |=3D ARCH_PEBS_VECR_ZMMH & cap.caps; + + if (pebs_data_cfg & PEBS_DATACFG_H16ZMMS) + ext |=3D ARCH_PEBS_VECR_H16ZMM & cap.caps; + if (pebs_data_cfg & PEBS_DATACFG_LBRS) ext |=3D ARCH_PEBS_LBR & cap.caps; =20 diff --git a/arch/x86/events/intel/ds.c b/arch/x86/events/intel/ds.c index 3277bd72e0a8..ff6125ec8458 100644 --- a/arch/x86/events/intel/ds.c +++ b/arch/x86/events/intel/ds.c @@ -1733,6 +1733,16 @@ static u64 pebs_update_adaptive_cfg(struct perf_even= t *event) if (sample_type & (PERF_SAMPLE_REGS_INTR | PERF_SAMPLE_REGS_USER)) { if (event_needs_xmm(event)) pebs_data_cfg |=3D PEBS_DATACFG_XMMS; + if (x86_pmu.arch_pebs && event_needs_ymm(event)) + pebs_data_cfg |=3D PEBS_DATACFG_YMMHS; + if (x86_pmu.arch_pebs && event_needs_low16_zmm(event)) + pebs_data_cfg |=3D PEBS_DATACFG_ZMMHS; + if (x86_pmu.arch_pebs && event_needs_high16_zmm(event)) + pebs_data_cfg |=3D PEBS_DATACFG_H16ZMMS; + if (x86_pmu.arch_pebs && event_needs_opmask(event)) + pebs_data_cfg |=3D PEBS_DATACFG_OPMASKS; + if (x86_pmu.arch_pebs && event_needs_egprs(event)) + pebs_data_cfg |=3D PEBS_DATACFG_EGPRS; } =20 if (sample_type & PERF_SAMPLE_BRANCH_STACK) { @@ -2687,14 +2697,63 @@ static void setup_arch_pebs_sample_data(struct perf= _event *event, meminfo->tsx_tuning, ax); } =20 - if (header->xmm) { + if (header->xmm || header->ymmh || header->egpr || + header->opmask || header->zmmh || header->h16zmm) { + struct arch_pebs_xer_header *xer_header =3D next_record; struct pebs_xmm *xmm; + struct ymmh_struct *ymmh; + struct avx_512_zmm_uppers_state *zmmh; + struct avx_512_hi16_state *h16zmm; + struct avx_512_opmask_state *opmask; + struct apx_state *egpr; =20 next_record +=3D sizeof(struct arch_pebs_xer_header); =20 - xmm =3D next_record; - perf_regs->xmm_regs =3D xmm->xmm; - next_record =3D xmm + 1; + if (header->xmm) { + xmm =3D next_record; + /* + * Only output XMM regs to user space when arch-PEBS + * really writes data into xstate area. + */ + if (xer_header->xstate & XFEATURE_MASK_SSE) + perf_regs->xmm_regs =3D xmm->xmm; + next_record =3D xmm + 1; + } + + if (header->ymmh) { + ymmh =3D next_record; + if (xer_header->xstate & XFEATURE_MASK_YMM) + perf_regs->ymmh =3D ymmh; + next_record =3D ymmh + 1; + } + + if (header->egpr) { + egpr =3D next_record; + if (xer_header->xstate & XFEATURE_MASK_APX) + perf_regs->egpr =3D egpr; + next_record =3D egpr + 1; + } + + if (header->opmask) { + opmask =3D next_record; + if (xer_header->xstate & XFEATURE_MASK_OPMASK) + perf_regs->opmask =3D opmask; + next_record =3D opmask + 1; + } + + if (header->zmmh) { + zmmh =3D next_record; + if (xer_header->xstate & XFEATURE_MASK_ZMM_Hi256) + perf_regs->zmmh =3D zmmh; + next_record =3D zmmh + 1; + } + + if (header->h16zmm) { + h16zmm =3D next_record; + if (xer_header->xstate & XFEATURE_MASK_Hi16_ZMM) + perf_regs->h16zmm =3D h16zmm; + next_record =3D h16zmm + 1; + } } =20 if (header->lbr) { diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-in= dex.h index 18c4be75e927..9c26d4075c5f 100644 --- a/arch/x86/include/asm/msr-index.h +++ b/arch/x86/include/asm/msr-index.h @@ -350,6 +350,13 @@ #define ARCH_PEBS_LBR_SHIFT 40 #define ARCH_PEBS_LBR (0x3ull << ARCH_PEBS_LBR_SHIFT) #define ARCH_PEBS_VECR_XMM BIT_ULL(49) +#define ARCH_PEBS_VECR_YMMH BIT_ULL(50) +#define ARCH_PEBS_VECR_EGPRS BIT_ULL(51) +#define ARCH_PEBS_VECR_OPMASK BIT_ULL(53) +#define ARCH_PEBS_VECR_ZMMH BIT_ULL(54) +#define ARCH_PEBS_VECR_H16ZMM BIT_ULL(55) +#define ARCH_PEBS_VECR_EXT_SHIFT 49 +#define ARCH_PEBS_VECR_EXT (0x7full << ARCH_PEBS_VECR_EXT_SHIFT) #define ARCH_PEBS_GPR BIT_ULL(61) #define ARCH_PEBS_AUX BIT_ULL(62) #define ARCH_PEBS_EN BIT_ULL(63) diff --git a/arch/x86/include/asm/perf_event.h b/arch/x86/include/asm/perf_= event.h index 4302ef39c42e..12f7db8c57b4 100644 --- a/arch/x86/include/asm/perf_event.h +++ b/arch/x86/include/asm/perf_event.h @@ -150,6 +150,11 @@ #define PEBS_DATACFG_LBRS BIT_ULL(3) #define PEBS_DATACFG_CNTR BIT_ULL(4) #define PEBS_DATACFG_METRICS BIT_ULL(5) +#define PEBS_DATACFG_YMMHS BIT_ULL(6) +#define PEBS_DATACFG_OPMASKS BIT_ULL(7) +#define PEBS_DATACFG_ZMMHS BIT_ULL(8) +#define PEBS_DATACFG_H16ZMMS BIT_ULL(9) +#define PEBS_DATACFG_EGPRS BIT_ULL(10) #define PEBS_DATACFG_LBR_SHIFT 24 #define PEBS_DATACFG_CNTR_SHIFT 32 #define PEBS_DATACFG_CNTR_MASK GENMASK_ULL(15, 0) @@ -547,7 +552,8 @@ struct arch_pebs_header { rsvd3:7, xmm:1, ymmh:1, - rsvd4:2, + egpr:1, + rsvd4:1, opmask:1, zmmh:1, h16zmm:1, --=20 2.34.1 From nobody Sat Jul 25 01:34:42 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.11]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5AAA82FF669; Tue, 21 Jul 2026 06:34:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.11 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784615676; cv=none; b=Zdam1zYErsqJCF2vmrldUXa63nadzPaV4m4E0xT1VK2F1x/jHlE8nlPuHfqgwKiGkZeGLEAHPCqV19XWLA+G/A8Av4abg7Ec+qQTH+NH7hnCi1RcgANgOtA4oR+enDUbSnyXnQ+XIxKsZ5H/mTr8frmhTvSg57ohQk/AVbGEotQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784615676; c=relaxed/simple; bh=UwLDz3og7P9oeQnFXqwNrNhI6ciuTdzOaGMUIbiB5Ys=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=GTbblStsdgbosAzwmast8xRNrLYj374LdCdzaSkvgEox+8Y/2jRdakjfsgad7X+S3GiXnPUNxYmYi/njB/08U2OpRhj9pu6v1zxQKOrGlfpSU7RDSYk2pHWyFX8JTjSOnk5ggFzBgG6CfvcIfVjnE0m3hxqjWfGG8CJJ8WXZNiY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=pass smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=jjK1tyMj; arc=none smtp.client-ip=198.175.65.11 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="jjK1tyMj" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1784615673; x=1816151673; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=UwLDz3og7P9oeQnFXqwNrNhI6ciuTdzOaGMUIbiB5Ys=; b=jjK1tyMjkqy64poDOFDuiCFXqwXIQ3zAwiCX6nsFvtEEWpneecUqgpn/ sKmXOMa0RemxCdbadudNrPPK5oM2WNx4QwOMRSL22I/05pZGwHNfN0C1X 4a5Lkvg4nevLUqjtHqD6MiGfibhvyQsOQJob3H5yrBNY3hjy1uBmjOAxO hdfqWnR3wbFPQZfJga7vlceIYH3tTPHwG5g0L4zsFKFjp5uTPX3NPRlQ9 hM98u2epC4warUue7nDAt6CN2xLOI+Zxbxo2uQgjzD4XbobnBqQrPZgHr W6TeuhOi6sV9E8b1yy3wHrfogKNbO4prKCQgUY7NVMgCh+3uCc1UFJ27N A==; X-CSE-ConnectionGUID: hpoyR9QMRra6aVGHAmye+Q== X-CSE-MsgGUID: +DLTHaLHTbqtp1hmUlCb3A== X-IronPort-AV: E=McAfee;i="6800,10657,11852"; a="95565580" X-IronPort-AV: E=Sophos;i="6.25,176,1779174000"; d="scan'208";a="95565580" Received: from fmviesa004.fm.intel.com ([10.60.135.144]) by orvoesa103.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Jul 2026 23:34:30 -0700 X-CSE-ConnectionGUID: ZWeuz6cFQu6CMcN3QgCxYQ== X-CSE-MsgGUID: SAEHvIi1SeexTiyqi9Fiyg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.25,176,1779174000"; d="scan'208";a="259656250" Received: from spr.sh.intel.com ([10.112.229.196]) by fmviesa004.fm.intel.com with ESMTP; 20 Jul 2026 23:34:25 -0700 From: Dapeng Mi To: Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Thomas Gleixner , Dave Hansen , Ian Rogers , Adrian Hunter , Jiri Olsa , Alexander Shishkin , Andi Kleen , Eranian Stephane Cc: Mark Rutland , broonie@kernel.org, Ravi Bangoria , linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org, Zide Chen , Falcon Thomas , Dapeng Mi , Xudong Hao , Dapeng Mi , Kan Liang Subject: [Patch v10 21/23] perf/x86/intel: Advertise PERF_PMU_CAP_SIMD_REGS capability Date: Tue, 21 Jul 2026 14:25:04 +0800 Message-Id: <20260721062506.3745816-22-dapeng1.mi@linux.intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260721062506.3745816-1-dapeng1.mi@linux.intel.com> References: <20260721062506.3745816-1-dapeng1.mi@linux.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Set PERF_PMU_CAP_SIMD_REGS once XSAVES-backed extended state beyond XMM is available for sampling, e.g. YMM, ZMM, OPMASK, eGPRs, or SSP. Keep backward compatibility unchanged. When only XMM sampling is available, continue to expose only PERF_PMU_CAP_EXTENDED_REGS. Expose PERF_PMU_CAP_SIMD_REGS only when additional SIMD/predicate register state is supported. Co-developed-by: Kan Liang Signed-off-by: Kan Liang Signed-off-by: Dapeng Mi --- arch/x86/events/intel/core.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c index 4eeb08352f4c..5d1f00f3aa47 100644 --- a/arch/x86/events/intel/core.c +++ b/arch/x86/events/intel/core.c @@ -6229,7 +6229,27 @@ static inline void __intel_update_pmu_xregs_caps(str= uct pmu *pmu) */ x86_pmu.ext_regs_mask |=3D XFEATURE_MASK_SSE; =20 + if (boot_cpu_has(X86_FEATURE_AVX) && + cpu_has_xfeatures(XFEATURE_MASK_YMM, NULL)) + x86_pmu.ext_regs_mask |=3D XFEATURE_MASK_YMM; + if (boot_cpu_has(X86_FEATURE_APX) && + cpu_has_xfeatures(XFEATURE_MASK_APX, NULL)) + x86_pmu.ext_regs_mask |=3D XFEATURE_MASK_APX; + if (boot_cpu_has(X86_FEATURE_AVX512F)) { + if (cpu_has_xfeatures(XFEATURE_MASK_OPMASK, NULL)) + x86_pmu.ext_regs_mask |=3D XFEATURE_MASK_OPMASK; + if (cpu_has_xfeatures(XFEATURE_MASK_ZMM_Hi256, NULL)) + x86_pmu.ext_regs_mask |=3D XFEATURE_MASK_ZMM_Hi256; + if (cpu_has_xfeatures(XFEATURE_MASK_Hi16_ZMM, NULL)) + x86_pmu.ext_regs_mask |=3D XFEATURE_MASK_Hi16_ZMM; + } + if (cpu_feature_enabled(X86_FEATURE_USER_SHSTK) && + cpu_has_xfeatures(XFEATURE_MASK_CET_USER, NULL)) + x86_pmu.ext_regs_mask |=3D XFEATURE_MASK_CET_USER; + dest_pmu->capabilities |=3D PERF_PMU_CAP_EXTENDED_REGS; + if (x86_pmu.ext_regs_mask > XFEATURE_MASK_SSE) + dest_pmu->capabilities |=3D PERF_PMU_CAP_SIMD_REGS; } =20 static inline void __intel_update_large_pebs_flags(struct pmu *pmu) --=20 2.34.1 From nobody Sat Jul 25 01:34:42 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.11]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 70A20439913; Tue, 21 Jul 2026 06:34:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.11 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784615682; cv=none; b=nAVsKkUPcgXPgIlCbHm1Nr4jICpn3TTvG/WcfpMKvZBxEBWaVj8hJ64wERT8Lsspr64d3Cd/3O24nuzfGFcH7y/B4gIe7THQankafmzpHbg5IoJjwM7cew2FR52SjRcadvqx/VgzD0CUgYcKXfSNDwmfA5Zakm5bicuzH1XCohw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784615682; c=relaxed/simple; bh=8TW4qwTvwYEa4MxsNbLzjjnPUu+MFlCf8o4ZYkG1tCs=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=sfr9PKLaXQugfsMMSLPrijxx4MyXPXlIy3q44LECi6maXpsFGa6RqGnj6DinmdCluiNcEe1xQh12fmk/k6cxu4MvT7vjch049WVSsxoZEgwaOLsuyJU4DrvUuZX2ngiDkAPa0DI3H8u4axjpLF35WFUWiWgPZ0t8X3RPlvPmff0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=pass smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=EB/g25cg; arc=none smtp.client-ip=198.175.65.11 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="EB/g25cg" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1784615677; x=1816151677; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=8TW4qwTvwYEa4MxsNbLzjjnPUu+MFlCf8o4ZYkG1tCs=; b=EB/g25cgNt0VcFKEAFeurfJe5srVKTRo1NrdDucO15WUQ0In+RtSoqpF MZXeE+g3/kqS0cWwftBfOq5HvTP17VqFhvFWUxQOxMsoxt1z7rkiF6v59 j1HvSpLoFiRAuDkUP3pmaoDFIkX0A/qxyc2nqMzTsHL8uCj7hYBypeTCm DpC7ke0KGGr8o3esXmUTlcc5wJM/OojGqhmzbEk5loz1QT3QzqU5BWeWK 9CwhxoadePG939uaDlbVLz5bj0uQdRHgiNpWrK+wKpn5aNYyqPGuksVVM 7+IY+2S6opvBmUWcu48c1u5oc821kx88SnjEMXvkxLtS7gnmaTDZQvNAT w==; X-CSE-ConnectionGUID: yt9WWC8USXuhd61thUqbJA== X-CSE-MsgGUID: yEjKz1IcQ4uCpgCcTw69Bg== X-IronPort-AV: E=McAfee;i="6800,10657,11852"; a="95565587" X-IronPort-AV: E=Sophos;i="6.25,176,1779174000"; d="scan'208";a="95565587" Received: from fmviesa004.fm.intel.com ([10.60.135.144]) by orvoesa103.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Jul 2026 23:34:36 -0700 X-CSE-ConnectionGUID: 9Z6ZThrHTKCSpZJvL6kTkQ== X-CSE-MsgGUID: XLxfkoqyTveeFnVCzmF0vw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.25,176,1779174000"; d="scan'208";a="259656267" Received: from spr.sh.intel.com ([10.112.229.196]) by fmviesa004.fm.intel.com with ESMTP; 20 Jul 2026 23:34:30 -0700 From: Dapeng Mi To: Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Thomas Gleixner , Dave Hansen , Ian Rogers , Adrian Hunter , Jiri Olsa , Alexander Shishkin , Andi Kleen , Eranian Stephane Cc: Mark Rutland , broonie@kernel.org, Ravi Bangoria , linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org, Zide Chen , Falcon Thomas , Dapeng Mi , Xudong Hao , Dapeng Mi Subject: [Patch v10 22/23] perf/x86: Activate back-to-back NMI detection for arch-PEBS induced NMIs Date: Tue, 21 Jul 2026 14:25:05 +0800 Message-Id: <20260721062506.3745816-23-dapeng1.mi@linux.intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260721062506.3745816-1-dapeng1.mi@linux.intel.com> References: <20260721062506.3745816-1-dapeng1.mi@linux.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" When two or more identical PEBS events with the same sampling period are programmed on a mix of PDIST and non-PDIST counters, multiple back-to-back NMIs can be triggered. The Linux PMI handler processes the first NMI and clears the GLOBAL_STATUS MSR. If a second NMI is triggered immediately after the first, it is recognized as a "suspicious NMI" because no bits are set in the GLOBAL_STATUS MSR (cleared by the first NMI). This issue does not lead to PEBS data corruption or data loss, but it does result in an annoying warning message. The current NMI handler supports back-to-back NMI detection, but it requires the PMI handler to return the count of actually processed events, which the PEBS handler does not currently do. Thus, modify the PEBS handlers to return the count of actually processed events, thereby activating back-to-back NMI detection and avoiding the "suspicious NMI" warning. Suggested-by: Andi Kleen Signed-off-by: Dapeng Mi --- arch/x86/events/core.c | 2 +- arch/x86/events/intel/core.c | 31 +++++++++++++++++--------- arch/x86/events/intel/ds.c | 43 ++++++++++++++++++++++++------------ arch/x86/events/perf_event.h | 2 +- 4 files changed, 51 insertions(+), 27 deletions(-) diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c index 11799acd8c54..ef9b8df2e1f7 100644 --- a/arch/x86/events/core.c +++ b/arch/x86/events/core.c @@ -93,7 +93,7 @@ DEFINE_STATIC_CALL_NULL(x86_pmu_stop_scheduling, *x86_p= mu.stop_scheduling); =20 DEFINE_STATIC_CALL_NULL(x86_pmu_sched_task, *x86_pmu.sched_task); =20 -DEFINE_STATIC_CALL_NULL(x86_pmu_drain_pebs, *x86_pmu.drain_pebs); +DEFINE_STATIC_CALL_RET0(x86_pmu_drain_pebs, *x86_pmu.drain_pebs); DEFINE_STATIC_CALL_NULL(x86_pmu_pebs_aliases, *x86_pmu.pebs_aliases); =20 DEFINE_STATIC_CALL_NULL(x86_pmu_filter, *x86_pmu.filter); diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c index 5d1f00f3aa47..2d2bbadbfc9f 100644 --- a/arch/x86/events/intel/core.c +++ b/arch/x86/events/intel/core.c @@ -3784,8 +3784,8 @@ static void intel_pmu_reset(void) * * The contents and other behavior of the guest event do not matter. */ -static void x86_pmu_handle_guest_pebs(struct pt_regs *regs, - struct perf_sample_data *data) +static int x86_pmu_handle_guest_pebs(struct pt_regs *regs, + struct perf_sample_data *data) { struct cpu_hw_events *cpuc =3D this_cpu_ptr(&cpu_hw_events); u64 guest_pebs_idxs =3D cpuc->pebs_enabled & ~cpuc->intel_ctrl_host_mask; @@ -3793,11 +3793,11 @@ static void x86_pmu_handle_guest_pebs(struct pt_reg= s *regs, int bit; =20 if (!unlikely(perf_guest_state())) - return; + return 0; =20 if (!x86_pmu.pebs_ept || !x86_pmu.pebs_active || !guest_pebs_idxs) - return; + return 0; =20 for_each_set_bit(bit, (unsigned long *)&guest_pebs_idxs, X86_PMC_IDX_MAX)= { event =3D cpuc->events[bit]; @@ -3807,9 +3807,14 @@ static void x86_pmu_handle_guest_pebs(struct pt_regs= *regs, perf_sample_data_init(data, 0, event->hw.last_period); perf_event_overflow(event, data, regs); =20 - /* Inject one fake event is enough. */ - break; + /* + * Inject one fake event is enough. + * Returning 1 to inform PMI is handled. + */ + return 1; } + + return 0; } =20 static int handle_pmi_common(struct pt_regs *regs, u64 status) @@ -3858,9 +3863,11 @@ static int handle_pmi_common(struct pt_regs *regs, u= 64 status) if (__test_and_clear_bit(GLOBAL_STATUS_BUFFER_OVF_BIT, (unsigned long *)&= status)) { u64 pebs_enabled =3D cpuc->pebs_enabled; =20 - handled++; - x86_pmu_handle_guest_pebs(regs, &data); - static_call(x86_pmu_drain_pebs)(regs, &data); + handled +=3D x86_pmu_handle_guest_pebs(regs, &data); + handled +=3D static_call(x86_pmu_drain_pebs)(regs, &data); + /* Ensure no "suspicious NMI" warning for empty PEBS buffer. */ + if (!handled) + handled++; =20 /* * PMI throttle may be triggered, which stops the PEBS event. @@ -3887,8 +3894,10 @@ static int handle_pmi_common(struct pt_regs *regs, u= 64 status) */ if (__test_and_clear_bit(GLOBAL_STATUS_ARCH_PEBS_THRESHOLD_BIT, (unsigned long *)&status)) { - handled++; - static_call(x86_pmu_drain_pebs)(regs, &data); + handled +=3D static_call(x86_pmu_drain_pebs)(regs, &data); + /* Ensure no "suspicious NMI" warning for empty PEBS buffer. */ + if (!handled) + handled++; =20 if (cpuc->events[INTEL_PMC_IDX_FIXED_SLOTS] && is_pebs_counter_event_group(cpuc->events[INTEL_PMC_IDX_FIXED_SLOTS])) diff --git a/arch/x86/events/intel/ds.c b/arch/x86/events/intel/ds.c index ff6125ec8458..d830a3fdd964 100644 --- a/arch/x86/events/intel/ds.c +++ b/arch/x86/events/intel/ds.c @@ -3014,7 +3014,7 @@ __intel_pmu_pebs_events(struct perf_event *event, __intel_pmu_pebs_last_event(event, iregs, regs, data, at, count, setup_sa= mple); } =20 -static void intel_pmu_drain_pebs_core(struct pt_regs *iregs, struct perf_s= ample_data *data) +static int intel_pmu_drain_pebs_core(struct pt_regs *iregs, struct perf_sa= mple_data *data) { struct cpu_hw_events *cpuc =3D this_cpu_ptr(&cpu_hw_events); struct debug_store *ds =3D cpuc->ds; @@ -3023,7 +3023,7 @@ static void intel_pmu_drain_pebs_core(struct pt_regs = *iregs, struct perf_sample_ int n; =20 if (!x86_pmu.pebs_active) - return; + return 0; =20 at =3D (struct pebs_record_core *)(unsigned long)ds->pebs_buffer_base; top =3D (struct pebs_record_core *)(unsigned long)ds->pebs_index; @@ -3034,22 +3034,25 @@ static void intel_pmu_drain_pebs_core(struct pt_reg= s *iregs, struct perf_sample_ ds->pebs_index =3D ds->pebs_buffer_base; =20 if (!test_bit(0, cpuc->active_mask)) - return; + return 0; =20 WARN_ON_ONCE(!event); =20 if (!event->attr.precise_ip) - return; + return 0; =20 n =3D top - at; if (n <=3D 0) { if (event->hw.flags & PERF_X86_EVENT_AUTO_RELOAD) intel_pmu_save_and_restart_reload(event, 0); - return; + return 0; } =20 __intel_pmu_pebs_events(event, iregs, data, at, top, 0, n, setup_pebs_fixed_sample_data); + + /* PMC0 only */ + return 1; } =20 static void intel_pmu_pebs_event_update_no_drain(struct cpu_hw_events *cpu= c, u64 mask) @@ -3072,7 +3075,7 @@ static void intel_pmu_pebs_event_update_no_drain(stru= ct cpu_hw_events *cpuc, u64 } } =20 -static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs, struct perf_sa= mple_data *data) +static int intel_pmu_drain_pebs_nhm(struct pt_regs *iregs, struct perf_sam= ple_data *data) { struct cpu_hw_events *cpuc =3D this_cpu_ptr(&cpu_hw_events); struct debug_store *ds =3D cpuc->ds; @@ -3081,11 +3084,12 @@ static void intel_pmu_drain_pebs_nhm(struct pt_regs= *iregs, struct perf_sample_d short counts[INTEL_PMC_IDX_FIXED + MAX_FIXED_PEBS_EVENTS] =3D {}; short error[INTEL_PMC_IDX_FIXED + MAX_FIXED_PEBS_EVENTS] =3D {}; int max_pebs_events =3D intel_pmu_max_num_pebs(NULL); + u64 events_bitmap =3D 0; int bit, i, size; u64 mask; =20 if (!x86_pmu.pebs_active) - return; + return 0; =20 base =3D (struct pebs_record_nhm *)(unsigned long)ds->pebs_buffer_base; top =3D (struct pebs_record_nhm *)(unsigned long)ds->pebs_index; @@ -3101,7 +3105,7 @@ static void intel_pmu_drain_pebs_nhm(struct pt_regs *= iregs, struct perf_sample_d =20 if (unlikely(base >=3D top)) { intel_pmu_pebs_event_update_no_drain(cpuc, mask); - return; + return 0; } =20 for (at =3D base; at < top; at +=3D x86_pmu.pebs_record_size) { @@ -3165,6 +3169,7 @@ static void intel_pmu_drain_pebs_nhm(struct pt_regs *= iregs, struct perf_sample_d if ((counts[bit] =3D=3D 0) && (error[bit] =3D=3D 0)) continue; =20 + events_bitmap |=3D BIT_ULL(bit); event =3D cpuc->events[bit]; if (WARN_ON_ONCE(!event)) continue; @@ -3186,6 +3191,8 @@ static void intel_pmu_drain_pebs_nhm(struct pt_regs *= iregs, struct perf_sample_d setup_pebs_fixed_sample_data); } } + + return hweight64(events_bitmap); } =20 static __always_inline void @@ -3239,7 +3246,7 @@ __intel_pmu_handle_last_pebs_record(struct pt_regs *i= regs, =20 } =20 -static void intel_pmu_drain_pebs_icl(struct pt_regs *iregs, struct perf_sa= mple_data *data) +static int intel_pmu_drain_pebs_icl(struct pt_regs *iregs, struct perf_sam= ple_data *data) { short counts[INTEL_PMC_IDX_FIXED + MAX_FIXED_PEBS_EVENTS] =3D {}; void *last[INTEL_PMC_IDX_FIXED + MAX_FIXED_PEBS_EVENTS]; @@ -3249,10 +3256,11 @@ static void intel_pmu_drain_pebs_icl(struct pt_regs= *iregs, struct perf_sample_d struct pt_regs *regs =3D &perf_regs->regs; struct pebs_basic *basic; void *base, *at, *top; + u64 events_bitmap =3D 0; u64 mask; =20 if (!x86_pmu.pebs_active) - return; + return 0; =20 base =3D (struct pebs_basic *)(unsigned long)ds->pebs_buffer_base; top =3D (struct pebs_basic *)(unsigned long)ds->pebs_index; @@ -3265,7 +3273,7 @@ static void intel_pmu_drain_pebs_icl(struct pt_regs *= iregs, struct perf_sample_d =20 if (unlikely(base >=3D top)) { intel_pmu_pebs_event_update_no_drain(cpuc, mask); - return; + return 0; } =20 if (!iregs) @@ -3280,6 +3288,7 @@ static void intel_pmu_drain_pebs_icl(struct pt_regs *= iregs, struct perf_sample_d continue; =20 pebs_status =3D mask & basic->applicable_counters; + events_bitmap |=3D pebs_status; __intel_pmu_handle_pebs_record(iregs, regs, data, at, pebs_status, counts, last, setup_pebs_adaptive_sample_data); @@ -3287,10 +3296,12 @@ static void intel_pmu_drain_pebs_icl(struct pt_regs= *iregs, struct perf_sample_d =20 __intel_pmu_handle_last_pebs_record(iregs, regs, data, mask, counts, last, setup_pebs_adaptive_sample_data); + + return hweight64(events_bitmap); } =20 -static void intel_pmu_drain_arch_pebs(struct pt_regs *iregs, - struct perf_sample_data *data) +static int intel_pmu_drain_arch_pebs(struct pt_regs *iregs, + struct perf_sample_data *data) { short counts[INTEL_PMC_IDX_FIXED + MAX_FIXED_PEBS_EVENTS] =3D {}; void *last[INTEL_PMC_IDX_FIXED + MAX_FIXED_PEBS_EVENTS]; @@ -3299,13 +3310,14 @@ static void intel_pmu_drain_arch_pebs(struct pt_reg= s *iregs, struct x86_perf_regs *perf_regs =3D this_cpu_ptr(&x86_pebs_regs); struct pt_regs *regs =3D &perf_regs->regs; void *base, *at, *top; + u64 events_bitmap =3D 0; u64 mask; =20 rdmsrq(MSR_IA32_PEBS_INDEX, index.whole); =20 if (unlikely(!index.wr)) { intel_pmu_pebs_event_update_no_drain(cpuc, X86_PMC_IDX_MAX); - return; + return 0; } =20 base =3D cpuc->pebs_vaddr; @@ -3344,6 +3356,7 @@ static void intel_pmu_drain_arch_pebs(struct pt_regs = *iregs, =20 basic =3D at + sizeof(struct arch_pebs_header); pebs_status =3D mask & basic->applicable_counters; + events_bitmap |=3D pebs_status; __intel_pmu_handle_pebs_record(iregs, regs, data, at, pebs_status, counts, last, setup_arch_pebs_sample_data); @@ -3363,6 +3376,8 @@ static void intel_pmu_drain_arch_pebs(struct pt_regs = *iregs, __intel_pmu_handle_last_pebs_record(iregs, regs, data, mask, counts, last, setup_arch_pebs_sample_data); + + return hweight64(events_bitmap); } =20 static void __init intel_arch_pebs_init(void) diff --git a/arch/x86/events/perf_event.h b/arch/x86/events/perf_event.h index eca7fab86b9b..bb34aab53d05 100644 --- a/arch/x86/events/perf_event.h +++ b/arch/x86/events/perf_event.h @@ -1145,7 +1145,7 @@ struct x86_pmu { int pebs_record_size; int pebs_buffer_size; u64 pebs_events_mask; - void (*drain_pebs)(struct pt_regs *regs, struct perf_sample_data *data); + int (*drain_pebs)(struct pt_regs *regs, struct perf_sample_data *data); struct event_constraint *pebs_constraints; void (*pebs_aliases)(struct perf_event *event); u64 (*pebs_latency_data)(struct perf_event *event, u64 status); --=20 2.34.1 From nobody Sat Jul 25 01:34:42 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.11]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2C07243B6C5; Tue, 21 Jul 2026 06:34:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.11 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784615688; cv=none; b=BVUPQFVYuXt3jwJmUYOw5ho45WRW58JmKhx+DXz3OX3NwaCyxhlOSIllqQIhy9vMaN1d5+GbBzFxYdgSVy5suEEJtn3i6bHIAcXeuUiZ7+bYvvTPL4fjYzOSdeLfHLdOmGpiLXbcpNEsrPIhYNdQbJSnwKgGyvib1RfWB6C7UHs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784615688; c=relaxed/simple; bh=I835WRYpB4Pu5sbQiT87MMyKY3wKrBUqi4sjxd9755s=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=YxZ3WznIjdhkAu2xSWRDkd1WTsoLnJOWCI2z2z0fu+oS9lBbb4R+SdN9/Dme7WUQQI0qX3k6WEV2VH+b4TfJHTu8ky2vaTxZ/KUOTwrOilSDektUW7jbzKSvHnCJ++NKgSSADfZvBt6m6W0+0oE5c7PA3A+iHQugNLWy51oCoqo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=pass smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=LTq5WNmv; arc=none smtp.client-ip=198.175.65.11 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="LTq5WNmv" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1784615684; x=1816151684; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=I835WRYpB4Pu5sbQiT87MMyKY3wKrBUqi4sjxd9755s=; b=LTq5WNmvCAk5x9oGhB7y9lEs1KmMyq5xfbuLNhN1RAR8w1wLJXMm40Tw FfqiOrer+lvxhkBWQQE0+/ZDakwKbixUa5sPb8L2zTh85NH/WjsP3gatB LIWRb/qRBCqbWyA9rZqDusRbw5kKionN8l4wcMwQiWIaLIQgThiDJgPTX VlL9kPCwPqPfyK3mmvXaeHg4Xmdhw/cHg0LgZCZhj/jSGOdibD50ZqWyr DrA6pQsZu9bc3eiQYiKdi7DEPmJRmwpMvwa2lxuXs0kGXBeoMh0qeJql+ 3d5kD87bV2onojbkFcEtmli8aW6e0zCTKNnIsky/kQuRq5Sq3TweCsuub w==; X-CSE-ConnectionGUID: EoLFTVLsT7i8S3pudPb46Q== X-CSE-MsgGUID: Q1xuNAJzSReIGg8HiQcovQ== X-IronPort-AV: E=McAfee;i="6800,10657,11852"; a="95565591" X-IronPort-AV: E=Sophos;i="6.25,176,1779174000"; d="scan'208";a="95565591" Received: from fmviesa004.fm.intel.com ([10.60.135.144]) by orvoesa103.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Jul 2026 23:34:41 -0700 X-CSE-ConnectionGUID: bzV48n8LQK+y0fpzqc82qQ== X-CSE-MsgGUID: kxoaMnPnTweNdnCZZABwxQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.25,176,1779174000"; d="scan'208";a="259656283" Received: from spr.sh.intel.com ([10.112.229.196]) by fmviesa004.fm.intel.com with ESMTP; 20 Jul 2026 23:34:36 -0700 From: Dapeng Mi To: Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Thomas Gleixner , Dave Hansen , Ian Rogers , Adrian Hunter , Jiri Olsa , Alexander Shishkin , Andi Kleen , Eranian Stephane Cc: Mark Rutland , broonie@kernel.org, Ravi Bangoria , linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org, Zide Chen , Falcon Thomas , Dapeng Mi , Xudong Hao , Dapeng Mi Subject: [Patch v10 23/23] perf/x86/intel: Add sanity check for PEBS record/fragment size Date: Tue, 21 Jul 2026 14:25:06 +0800 Message-Id: <20260721062506.3745816-24-dapeng1.mi@linux.intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260721062506.3745816-1-dapeng1.mi@linux.intel.com> References: <20260721062506.3745816-1-dapeng1.mi@linux.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Prevent potential infinite loops by adding a sanity check for the corrupted PEBS record or fragment size which could happen in theory. If a corrupted PEBS fragment is detected, the entire PEBS record including the corrupted fragment and all subsequent records will be dropped and a NULL PEBS record is reported to user space. This ensures the integrity of PEBS data and prevents infinite loops in setup_arch_pebs_sample_data() again. Please note software has no way to figure out which events are impacted by the corrupted record, so the last record of each event would be discarded for all events if corrupted record is detected even though it may be a well-formed record for some events. Signed-off-by: Dapeng Mi --- arch/x86/events/intel/ds.c | 77 ++++++++++++++++++++++++++++---------- 1 file changed, 58 insertions(+), 19 deletions(-) diff --git a/arch/x86/events/intel/ds.c b/arch/x86/events/intel/ds.c index d830a3fdd964..c0ff381fac00 100644 --- a/arch/x86/events/intel/ds.c +++ b/arch/x86/events/intel/ds.c @@ -2650,6 +2650,9 @@ static void setup_arch_pebs_sample_data(struct perf_e= vent *event, =20 again: header =3D at; + if (!header->size) + return; + next_record =3D at + sizeof(struct arch_pebs_header); if (header->basic) { struct arch_pebs_basic *basic =3D next_record; @@ -2923,13 +2926,21 @@ __intel_pmu_pebs_last_event(struct perf_event *even= t, struct pt_regs *iregs, struct pt_regs *regs, struct perf_sample_data *data, - void *at, - int count, + void *at, int count, bool corrupted, setup_fn setup_sample) { struct hw_perf_event *hwc =3D &event->hw; =20 - setup_sample(event, iregs, at, data, regs); + /* Skip parsing corrupted PEBS record. */ + if (corrupted) { + /* Clear stale register states in previous records. */ + memset(regs, 0, sizeof(*regs)); + x86_pmu_clear_perf_regs(regs); + perf_sample_data_init(data, 0, event->hw.last_period); + } else { + setup_sample(event, iregs, at, data, regs); + } + if (iregs =3D=3D &dummy_iregs) { /* * The PEBS records may be drained in the non-overflow context, @@ -2947,12 +2958,16 @@ __intel_pmu_pebs_last_event(struct perf_event *even= t, } =20 if (hwc->flags & PERF_X86_EVENT_AUTO_RELOAD) { - if ((is_pebs_counter_event_group(event))) { - /* - * The value of each sample has been updated when setup - * the corresponding sample data. - */ - perf_event_update_userpage(event); + if (is_pebs_counter_event_group(event)) { + if (corrupted) { + intel_pmu_save_and_restart_reload(event, 1); + } else { + /* + * The value of each sample has been updated + * when setup the corresponding sample data. + */ + perf_event_update_userpage(event); + } } else { /* * Now, auto-reload is only enabled in fixed period mode. @@ -2976,7 +2991,7 @@ __intel_pmu_pebs_last_event(struct perf_event *event, * counters-snapshotting record, only needs to set the new * period for the counter. */ - if (is_pebs_counter_event_group(event)) + if (is_pebs_counter_event_group(event) && !corrupted) static_call(x86_pmu_set_period)(event); else intel_pmu_save_and_restart(event); @@ -3005,13 +3020,15 @@ __intel_pmu_pebs_events(struct perf_event *event, iregs =3D &dummy_iregs; =20 while (cnt > 1) { - __intel_pmu_pebs_event(event, iregs, regs, data, at, setup_sample); + __intel_pmu_pebs_event(event, iregs, regs, data, + at, setup_sample); at +=3D cpuc->pebs_record_size; at =3D get_next_pebs_record_by_bit(at, top, bit); cnt--; } =20 - __intel_pmu_pebs_last_event(event, iregs, regs, data, at, count, setup_sa= mple); + __intel_pmu_pebs_last_event(event, iregs, regs, data, at, + count, false, setup_sample); } =20 static int intel_pmu_drain_pebs_core(struct pt_regs *iregs, struct perf_sa= mple_data *data) @@ -3227,23 +3244,28 @@ static __always_inline void __intel_pmu_handle_last_pebs_record(struct pt_regs *iregs, struct pt_regs *regs, struct perf_sample_data *data, - u64 mask, short *counts, void **last, + u64 mask, short *counts, + void **last, bool corrupted, setup_fn setup_sample) { struct cpu_hw_events *cpuc =3D this_cpu_ptr(&cpu_hw_events); struct perf_event *event; + bool handled =3D false; int bit; =20 for_each_set_bit(bit, (unsigned long *)&mask, X86_PMC_IDX_MAX) { if (!counts[bit]) continue; =20 + handled =3D true; event =3D cpuc->events[bit]; - __intel_pmu_pebs_last_event(event, iregs, regs, data, last[bit], - counts[bit], setup_sample); + counts[bit], corrupted, setup_sample); } =20 + /* All records are corrupted, reset sampling period. */ + if (!handled) + intel_pmu_pebs_event_update_no_drain(cpuc, mask); } =20 static int intel_pmu_drain_pebs_icl(struct pt_regs *iregs, struct perf_sam= ple_data *data) @@ -3257,6 +3279,7 @@ static int intel_pmu_drain_pebs_icl(struct pt_regs *i= regs, struct perf_sample_da struct pebs_basic *basic; void *base, *at, *top; u64 events_bitmap =3D 0; + bool corrupted =3D false; u64 mask; =20 if (!x86_pmu.pebs_active) @@ -3284,6 +3307,10 @@ static int intel_pmu_drain_pebs_icl(struct pt_regs *= iregs, struct perf_sample_da u64 pebs_status; =20 basic =3D at; + if (WARN_ON_ONCE(!basic->format_size)) { + corrupted =3D true; + break; + } if (basic->format_size !=3D cpuc->pebs_record_size) continue; =20 @@ -3295,7 +3322,7 @@ static int intel_pmu_drain_pebs_icl(struct pt_regs *i= regs, struct perf_sample_da } =20 __intel_pmu_handle_last_pebs_record(iregs, regs, data, mask, counts, last, - setup_pebs_adaptive_sample_data); + corrupted, setup_pebs_adaptive_sample_data); =20 return hweight64(events_bitmap); } @@ -3311,6 +3338,7 @@ static int intel_pmu_drain_arch_pebs(struct pt_regs *= iregs, struct pt_regs *regs =3D &perf_regs->regs; void *base, *at, *top; u64 events_bitmap =3D 0; + bool corrupted =3D false; u64 mask; =20 rdmsrq(MSR_IA32_PEBS_INDEX, index.whole); @@ -3345,8 +3373,10 @@ static int intel_pmu_drain_arch_pebs(struct pt_regs = *iregs, =20 header =3D at; =20 - if (WARN_ON_ONCE(!header->size)) - break; + if (WARN_ON_ONCE(!header->size)) { + corrupted =3D true; + goto done; + } =20 /* 1st fragment or single record must have basic group */ if (!header->basic) { @@ -3366,15 +3396,24 @@ static int intel_pmu_drain_arch_pebs(struct pt_regs= *iregs, if (!header->size) break; at +=3D header->size; + if (WARN_ON_ONCE(at >=3D top)) { + corrupted =3D true; + goto done; + } header =3D at; } =20 /* Skip last fragment or the single record */ at +=3D header->size; + if (WARN_ON_ONCE(at > top)) { + corrupted =3D true; + goto done; + } } =20 +done: __intel_pmu_handle_last_pebs_record(iregs, regs, data, mask, - counts, last, + counts, last, corrupted, setup_arch_pebs_sample_data); =20 return hweight64(events_bitmap); --=20 2.34.1