From nobody Fri Oct 2 02:36:27 2026 Received: from mail-wr1-f52.google.com (mail-wr1-f52.google.com [209.85.221.52]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 519CA46F4BE for ; Wed, 5 Aug 2026 15:02:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.52 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785942150; cv=none; b=YSugUogxtEyhSO+9i17xjw9unwWLW8Bg8BtTuOKKnwqMHC67XEHPo1x5PJ4lEqWT/nG/KnyDXN5+zsA8qFTOh+iDhNb939FclXbzC8fJoGNLUbuDmYmrLJprS9ODkgcBKdcOtWl8EDSL2eXMnhLeHkYranqZECnCOY8DmdFgiHE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785942150; c=relaxed/simple; bh=XjGEA+w8gpV2jQYN6R3+Kgx/wLLSx/0QslA0PACaxXU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=CqT5HvfDVAbVtJSraW+9QHJ5MVKLjf1iMoQs5/mjK15aaBw0BLg/MxlHHVDSRFqz8MNoH9zxCPLmRiZpm1KZZAMum0TvZFBnqBqNx3Qv/gKdjnRNG3bskyGi36WCklSJrzTHWLiA/iZ7JmeQAUQOwvjyhrihK/Fu1Q/BJ8IUJiM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org; spf=pass smtp.mailfrom=linaro.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b=K2Cr0bmo; arc=none smtp.client-ip=209.85.221.52 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linaro.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="K2Cr0bmo" Received: by mail-wr1-f52.google.com with SMTP id ffacd0b85a97d-47c6e9a694bso716340f8f.1 for ; Wed, 05 Aug 2026 08:02:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1785942146; x=1786546946; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=YdFUB2zH6KQ2jS1Qeu0n7oVNGn5pzmET1AhmT2Fra+g=; b=K2Cr0bmoPhlHcTx6kL2912yI2aB/PBx659e7uGML2yzv84YzRp1xTUi71yRt9FnPCX AlcXeptDwzssxXh4I0aYwTFpppgE9Hb00NBJSKGjkwl4AxRdq4+uZZyvFLkE053lidIt BQYziNJncB5j9dVmXpixDhdDYQ1ON1GFtmBOzjBdO6/bcmlHGeeESKDTavNUGkZe2Vo2 m9I3PFc24uCFvVj+SoSgb3/x31A0lQoGDXY0GT8w3EQb2jRBKbkxMb+dUDJDaeRYVWVq FpMg0YeK9+PR8Mfy5n6AKGcpPz6eORBrsoEQRC6vns47DeGrPkGHkn8xSvq/M510qplD Bl+Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785942146; x=1786546946; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=YdFUB2zH6KQ2jS1Qeu0n7oVNGn5pzmET1AhmT2Fra+g=; b=B/Px5PFWkDrGyzERkqGRLiqtGHs51IuYKgOAYBN+ST/pV7LszrCjngFAYoFNaUssC5 OA83rdkL0/ChJn6rr3h6bdFPmaKcIhjrMvlSusWGA3B+8Sdpf14lI1jrRsyR4DupjCR+ bCsppe65fatGe7rnPFOKZetbT7Qir/JJ7+cBJscb7VntPemzaBBiEyds8OZ3QRAiT3uc SWJDQ5LsuyVGiJzUtwshqFzTJDuvNzaa9kodOUnkwL00ERJW+92rG0evU0rqk7dwQHju PWcPqeojprFm6dJD5D42hcw7guth0NFPm1wUeMqI/y5g4S733tYY7/xGBCjzgK2IHLz6 P6hg== X-Forwarded-Encrypted: i=1; AHgh+Rrm5Fep1/c1HEk3BA94yMKuQ22OJXQqQbVqbjSgzsQCy7dEhryxBTdVvji9PQKh4eISk9Oo8BEBj9WHjOg=@vger.kernel.org X-Gm-Message-State: AOJu0Yz3y3TVywdQcbB+m8SCbjKArqdgPBqIOhFV0g7Aol7p+V7f8mXq IB7iyiGOfeHCf+DqKlBEte1Zt6HddQJOHsXEeNr7cdjnqwrzpOEahoBJX0wt70doNvQ= X-Gm-Gg: AR+sD12pn76HK/iOsvGKrpeCg6E0y6YzAYuuFRAZJklg6rQPA7ASiNKS7GQKLgvdzWh nRY2l1Q2PmplGxoxcAw97587LTla9laqEznvYBRugaV19/mLkK+3NhkOHTIWNKbi3lFPFrgxo0M YfzpLu2mBupEDcWRclLkiqey1bxnPPSg+CSXjYgIUXi2MFy1aJmvb92AH80HbShm0mPgmyLnlLM iyELn8EfVsC1Wj413EfW659cjUpw5jngXHJrx1EuFzMLwDyiU+JlOo1vw+E6letpx0iERHz9+9l W5iWx9ChlxbY/jH80P+O8rfnyOCjGbjB9TfRjTa1G3g91rXZgOFKY/VP8UfwTmCIqGiMQrBMwwu rHRg164ffGL9b8+ObC/P6h/ZMf39i3V45jYnl4xZC/1qKB+5JXeCMLWp0T1mYMarTtA3Dgz5/vW I87tuHTg2irD9vcmk5ZdJEqccE4ptoO9I6S8nRqA6fIF7+4vNFOzlR1fEi8OzFwDMLyCHHg0tLS zU= X-Received: by 2002:a05:600d:4448:20b0:495:5e3d:15e1 with SMTP id 5b1f17b1804b1-4994e7d21fdmr85868895e9.16.1785942146401; Wed, 05 Aug 2026 08:02:26 -0700 (PDT) Received: from pop-os.local ([37.18.141.193]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-47fec23ede6sm10308695f8f.30.2026.08.05.08.02.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 05 Aug 2026 08:02:25 -0700 (PDT) From: James Clark Date: Wed, 05 Aug 2026 16:01:51 +0100 Subject: [PATCH 1/3] perf: arm_spe: Factor aux output and flags out of buffer fault handler Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260805-james-spe-software-discard-v1-1-0ff0e44c4c92@linaro.org> References: <20260805-james-spe-software-discard-v1-0-0ff0e44c4c92@linaro.org> In-Reply-To: <20260805-james-spe-software-discard-v1-0-0ff0e44c4c92@linaro.org> To: Will Deacon , Mark Rutland , Leo Yan , Suzuki Poulose , Al Grant Cc: linux-arm-kernel@lists.infradead.org, linux-perf-users@vger.kernel.org, linux-kernel@vger.kernel.org, James Clark X-Mailer: b4 0.15.2 Software discard mode will still want to handle buffer faults, but doesn't have a real aux buffer to set flags or call perf_aux_output_end() on. Factor the aux buffer parts out of arm_spe_pmu_buf_get_fault_act() so it only decodes the fault, which better matches the name and can be used by the new mode later. This makes the arm_spe_pmu_stop() handling a bit simpler because it doesn't need to conditionally call arm_spe_perf_aux_output_end() anymore to handle the case when the fault handler didn't do it. No functional changes intended. Signed-off-by: James Clark --- drivers/perf/arm_spe_pmu.c | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/drivers/perf/arm_spe_pmu.c b/drivers/perf/arm_spe_pmu.c index dbd0da111639..10d28ad81256 100644 --- a/drivers/perf/arm_spe_pmu.c +++ b/drivers/perf/arm_spe_pmu.c @@ -677,11 +677,12 @@ static void arm_spe_pmu_disable_and_drain_local(void) =20 /* IRQ handling */ static enum arm_spe_pmu_buf_fault_action -arm_spe_pmu_buf_get_fault_act(struct perf_output_handle *handle) +arm_spe_pmu_buf_get_fault_act(u64 *aux_flags) { const char *err_str; u64 pmbsr; - enum arm_spe_pmu_buf_fault_action ret; + + *aux_flags =3D 0; =20 /* * Ensure new profiling data is visible to the CPU and any external @@ -703,12 +704,11 @@ arm_spe_pmu_buf_get_fault_act(struct perf_output_hand= le *handle) * flag to indicate that the last record is corrupted. */ if (FIELD_GET(PMBSR_EL1_DL, pmbsr)) - perf_aux_output_flag(handle, PERF_AUX_FLAG_TRUNCATED | - PERF_AUX_FLAG_PARTIAL); + *aux_flags |=3D PERF_AUX_FLAG_TRUNCATED | PERF_AUX_FLAG_PARTIAL; =20 /* Report collisions to userspace so that it can up the period */ if (FIELD_GET(PMBSR_EL1_COLL, pmbsr)) - perf_aux_output_flag(handle, PERF_AUX_FLAG_COLLISION); + *aux_flags |=3D PERF_AUX_FLAG_COLLISION; =20 /* We only expect buffer management events */ switch (FIELD_GET(PMBSR_EL1_EC, pmbsr)) { @@ -727,8 +727,7 @@ arm_spe_pmu_buf_get_fault_act(struct perf_output_handle= *handle) /* Buffer management event */ switch (FIELD_GET(PMBSR_EL1_BUF_BSC_MASK, pmbsr)) { case PMBSR_EL1_BUF_BSC_FULL: - ret =3D SPE_PMU_BUF_FAULT_ACT_OK; - goto out_stop; + return SPE_PMU_BUF_FAULT_ACT_OK; default: err_str =3D "Unknown buffer status code"; } @@ -738,11 +737,7 @@ arm_spe_pmu_buf_get_fault_act(struct perf_output_handl= e *handle) err_str, smp_processor_id(), pmbsr, read_sysreg_s(SYS_PMBPTR_EL1), read_sysreg_s(SYS_PMBLIMITR_EL1)); - ret =3D SPE_PMU_BUF_FAULT_ACT_FATAL; - -out_stop: - arm_spe_perf_aux_output_end(handle); - return ret; + return SPE_PMU_BUF_FAULT_ACT_FATAL; } =20 static irqreturn_t arm_spe_pmu_irq_handler(int irq, void *dev) @@ -750,14 +745,18 @@ static irqreturn_t arm_spe_pmu_irq_handler(int irq, v= oid *dev) struct perf_output_handle *handle =3D dev; struct perf_event *event =3D handle->event; enum arm_spe_pmu_buf_fault_action act; + u64 aux_flags; =20 if (!perf_get_aux(handle)) return IRQ_NONE; =20 - act =3D arm_spe_pmu_buf_get_fault_act(handle); + act =3D arm_spe_pmu_buf_get_fault_act(&aux_flags); if (act =3D=3D SPE_PMU_BUF_FAULT_ACT_SPURIOUS) return IRQ_NONE; =20 + perf_aux_output_flag(handle, aux_flags); + arm_spe_perf_aux_output_end(handle); + /* * Ensure perf callbacks have completed, which may disable the * profiling buffer in response to a TRUNCATION flag. @@ -927,6 +926,7 @@ static void arm_spe_pmu_stop(struct perf_event *event, = int flags) struct arm_spe_pmu *spe_pmu =3D to_spe_pmu(event->pmu); struct hw_perf_event *hwc =3D &event->hw; struct perf_output_handle *handle =3D this_cpu_ptr(spe_pmu->handle); + u64 aux_flags; =20 /* If we're already stopped, then nothing to do */ if (hwc->state & PERF_HES_STOPPED) @@ -944,10 +944,12 @@ static void arm_spe_pmu_stop(struct perf_event *event= , int flags) if (perf_get_aux(handle)) { enum arm_spe_pmu_buf_fault_action act; =20 - act =3D arm_spe_pmu_buf_get_fault_act(handle); - if (act =3D=3D SPE_PMU_BUF_FAULT_ACT_SPURIOUS) - arm_spe_perf_aux_output_end(handle); - else + act =3D arm_spe_pmu_buf_get_fault_act(&aux_flags); + perf_aux_output_flag(handle, aux_flags); + arm_spe_perf_aux_output_end(handle); + + /* Assume PMBSR only needs clearing for real faults */ + if (act !=3D SPE_PMU_BUF_FAULT_ACT_SPURIOUS) write_sysreg_s(0, SYS_PMBSR_EL1); } =20 --=20 2.43.0 From nobody Fri Oct 2 02:36:27 2026 Received: from mail-wr1-f48.google.com (mail-wr1-f48.google.com [209.85.221.48]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E950F46F48A for ; Wed, 5 Aug 2026 15:02:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.48 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785942150; cv=none; b=bOaUUrsxmBoY7u0xj9gTMEubz/Ltye3JAfHePITd3mdmSeEvZmyOodWIW30QkwDNM6jao+HM8kHkc6OLGVu3BjggDOC0VFiIy0V2KSPrOe2sZasnj9xGWutGsFZ85C13KIV2ZMyM5/LZ/DlVi4HtUQ8J9Z+IhqOk28vPG+kch1s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785942150; c=relaxed/simple; bh=YrfVnORDRZngBes7E8aE7nWhzjQkqGopSGj7UdhOOx4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=eH/hMqalZDULGSFKaVWLHa0FvbYZUVrOIpWLoUg1Gf7Bz3FL8KP85G1OFdChhsAYZK5NN3PYv0lt6YIgsImTp/RSFyS5akQbNrKw1lHsSbVGM56q0ZaBIsl5w30jiGXXG9rpWIZFjIKXoTI63+Un3il9gKJITbk4+dH22hKke9g= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org; spf=pass smtp.mailfrom=linaro.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b=nYLqGBq8; arc=none smtp.client-ip=209.85.221.48 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linaro.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="nYLqGBq8" Received: by mail-wr1-f48.google.com with SMTP id ffacd0b85a97d-47fde295992so902863f8f.0 for ; Wed, 05 Aug 2026 08:02:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1785942147; x=1786546947; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=Flg4QZQ4xZBxdFqtD7yG7JFgD80sYwr4xDNIvMLPrJw=; b=nYLqGBq8jO6MPTVD+r+waWgle9VThHPonhECbrYXIrQ1DrGmpKNTO1imQoldC46I9o B+pN5tr/+YZODUGGC7N9oXspseYreu5Xhg+BxB+gYsbVCDiu1YK1Fs3JRHO2tQEgw7M9 XVj87r6PE+r80nUaHJFcRYDBsjETDxK9SZrGlJw/ozgmhhChgP4vxhvuYue7l8mg3+fG sgYL5xBsYJvEMS11GbLqqOE7LO7kNHpvnxu+hIqnyCV1ZhtyfkFvOMvAchiV5WrIZ0IQ dJMoJKVOskqGHon1MgzcZGZImzn0ERJJ92BYUKLhl7MqiXLxRv6nGNknJPvgEo9HUagL WqGw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785942147; x=1786546947; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=Flg4QZQ4xZBxdFqtD7yG7JFgD80sYwr4xDNIvMLPrJw=; b=F/pVryXjUASCIUfbnk1J4AO21LvvT+FrEMPH97dvLjWmq88Svp4vo4/CCWLiBuiXYp NCD//6Z7ce6kUS8XNT/02CoMF6DVnupb2XrkR2ayrgiCfTwCLdnIm3l1SgYuDCL/kueV 8GizLCtuZm2Vw6P/oXiMgyevGoqdkJ741lfct5o78ZXFLbw3inopor9sjUN0sRMQG5DB aEGhtb3zqZSlrDfab+MTHhodItMERSyLtFuNTNO4AzkjiSDKLTdVKtBfeah4UlHiexeT v+jw3VEM3lQ6m1a9L2yQEE67BfA2i/qVJyZYVCcJeyhO0BdNGYjfK5LtgJ93V+BzjAUz Ermw== X-Forwarded-Encrypted: i=1; AHgh+Ro8h6NjEMWQgZ3l6N3q8qG+TUUXxSwuY1LMJePYKsG6P2CymfYooIx27palwpRMbXOGTjBrb9IrAewbp+o=@vger.kernel.org X-Gm-Message-State: AOJu0YzogBqDjRNKcffjbxdll/MHvRZqg2yAK2VU6BV8ut0ltwVIwZER meOIIuByARpuB/2tytseRUFklL3JoT6TJodo+HyMMLDbIj8fmh/b/vvxC0QSOecP+fI= X-Gm-Gg: AR+sD12594e9NQ8+2WaeeWG4wi3zDzKH8PS7+O7W3gxeAbfN5wNMvsAk2fnzpgcNDRN OTsS/eTyoOZmUIY4jWdhOxMwsSqpOxtYvTbcMy7SnjNQ+Fq7g2wfsl5Wgq0OMx3oEuZWO89Yvls BfBHsHkHHpJNFGrnnnA3gL2TTj5PQQPWwLI3EQTYnNsaAtX2VMGzkH0Y+I1gjKWPQShvHywSByZ Kv+z8RcnozhATsT4yg6F/HYiwt60Hl0bgrrYJVoziFsu5P6unjOExGKD99/j+UeXuuXjGHqmrli EjHaVnET3UAFi6AWMR2+m8OKgRUfcPUIkzxEkiXAmDBxxtrvYFQZ2okNYdAbxVMyk7Nma1Yb7Hq jOOpeNPQgSuGe0qllWU3/2dYXDQ50MclNPlPe5WLRF2Conm4z8jET6DnQdqAypslvUbJCTV7RxC lgOTG65tyW4l8U0clfax/aiAd8Vcn+qHx76uRyNpA2GF0ujEPWuEP24D3qnR2roqGT X-Received: by 2002:a5d:64e3:0:b0:47f:f002:3656 with SMTP id ffacd0b85a97d-47ff011797dmr8776881f8f.12.1785942147253; Wed, 05 Aug 2026 08:02:27 -0700 (PDT) Received: from pop-os.local ([37.18.141.193]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-47fec23ede6sm10308695f8f.30.2026.08.05.08.02.26 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 05 Aug 2026 08:02:26 -0700 (PDT) From: James Clark Date: Wed, 05 Aug 2026 16:01:52 +0100 Subject: [PATCH 2/3] perf: arm_spe: Factor HW discard mode out of arm_spe_perf_aux_output_begin() Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260805-james-spe-software-discard-v1-2-0ff0e44c4c92@linaro.org> References: <20260805-james-spe-software-discard-v1-0-0ff0e44c4c92@linaro.org> In-Reply-To: <20260805-james-spe-software-discard-v1-0-0ff0e44c4c92@linaro.org> To: Will Deacon , Mark Rutland , Leo Yan , Suzuki Poulose , Al Grant Cc: linux-arm-kernel@lists.infradead.org, linux-perf-users@vger.kernel.org, linux-kernel@vger.kernel.org, James Clark X-Mailer: b4 0.15.2 Discard mode doesn't call perf_aux_output_begin() or emit aux records, and enabling it never fails. We'll add a second discard mode in the next commit so it will be cleaner if there is a separate begin function just for discard mode. No functional changes intended. Signed-off-by: James Clark --- drivers/perf/arm_spe_pmu.c | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/drivers/perf/arm_spe_pmu.c b/drivers/perf/arm_spe_pmu.c index 10d28ad81256..562a1d3be39f 100644 --- a/drivers/perf/arm_spe_pmu.c +++ b/drivers/perf/arm_spe_pmu.c @@ -363,6 +363,11 @@ static const struct attribute_group *arm_spe_pmu_attr_= groups[] =3D { NULL, }; =20 +static bool arm_spe_discard_mode(struct perf_event *event) +{ + return ATTR_CFG_GET_FLD(&event->attr, discard); +} + /* Convert between user ABI and register values */ static u64 arm_spe_event_to_pmscr(struct perf_event *event) { @@ -609,18 +614,23 @@ static u64 arm_spe_pmu_next_off(struct perf_output_ha= ndle *handle) return limit; } =20 +static void arm_spe_pmu_begin_discard(struct perf_output_handle *handle, + struct perf_event *event) +{ + u64 limit; + + limit =3D FIELD_PREP(PMBLIMITR_EL1_FM, PMBLIMITR_EL1_FM_DISCARD); + limit |=3D PMBLIMITR_EL1_E; + + write_sysreg_s(limit, SYS_PMBLIMITR_EL1); +} + static int arm_spe_perf_aux_output_begin(struct perf_output_handle *handle, struct perf_event *event) { u64 base, limit; struct arm_spe_pmu_buf *buf; =20 - if (ATTR_CFG_GET_FLD(&event->attr, discard)) { - limit =3D FIELD_PREP(PMBLIMITR_EL1_FM, PMBLIMITR_EL1_FM_DISCARD); - limit |=3D PMBLIMITR_EL1_E; - goto out_write_limit; - } - /* Start a new aux session */ buf =3D perf_aux_output_begin(handle, event); if (!buf) { @@ -775,6 +785,12 @@ static irqreturn_t arm_spe_pmu_irq_handler(int irq, vo= id *dev) arm_spe_pmu_disable_and_drain_local(); break; case SPE_PMU_BUF_FAULT_ACT_OK: + if (arm_spe_discard_mode(event)) { + arm_spe_pmu_begin_discard(handle, event); + isb(); + break; + } + /* * We handled the fault (the buffer was full), so resume * profiling as long as we didn't detect truncation. @@ -864,7 +880,7 @@ static int arm_spe_pmu_event_init(struct perf_event *ev= ent) !(spe_pmu->features & SPE_PMU_FEAT_EFT)) return -EOPNOTSUPP; =20 - if (ATTR_CFG_GET_FLD(&event->attr, discard) && + if (arm_spe_discard_mode(event) && !(spe_pmu->features & SPE_PMU_FEAT_DISCARD)) return -EOPNOTSUPP; =20 @@ -884,7 +900,9 @@ static void arm_spe_pmu_start(struct perf_event *event,= int flags) struct perf_output_handle *handle =3D this_cpu_ptr(spe_pmu->handle); =20 hwc->state =3D 0; - if (arm_spe_perf_aux_output_begin(handle, event)) { + if (arm_spe_discard_mode(event)) { + arm_spe_pmu_begin_discard(handle, event); + } else if (arm_spe_perf_aux_output_begin(handle, event)) { arm_spe_pmu_stop(event, 0); return; } --=20 2.43.0 From nobody Fri Oct 2 02:36:27 2026 Received: from mail-wr1-f46.google.com (mail-wr1-f46.google.com [209.85.221.46]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3D25D40801B for ; Wed, 5 Aug 2026 15:02:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.46 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785942153; cv=none; b=t4BX8taKPUBKuuD/Q2EZgGja5GmfekA1QjxQPWOaKh05A1uz+B0xpzCkD9TZolr5dTYeiYo3gNN5Ki5ZiVItJAw9fA7XBTIZoR92UuV5sJg3YuU4YKFTFzN5omM4fA4N0WOf76LhlarVtEhg8p+xCDa2crHzdjhUCAwlkbmEwDs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785942153; c=relaxed/simple; bh=VH4YTMPA+h4gFcjeTLNCMEDNTFyTTnloH2eynxYw6wk=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=M1cqDjrO7rucmpZ7vbMbw6V3Ly77r4iuzGHsXTZaWKm2UhL6QMBARH6XSgptdT1X0MX2sMlVZq2nxAShWoyl7kdoScbml2ApJLltPiCvtK/3e7waqleTmMm6aevNnm+A+ygZXmSvHcvtPoqbUTAcsZxfteCLjDbHD8AK+ZTmDIQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org; spf=pass smtp.mailfrom=linaro.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b=xaO5rAoK; arc=none smtp.client-ip=209.85.221.46 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linaro.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="xaO5rAoK" Received: by mail-wr1-f46.google.com with SMTP id ffacd0b85a97d-47f7027ca11so746196f8f.3 for ; Wed, 05 Aug 2026 08:02:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1785942148; x=1786546948; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=Unst9+FN4mg5CbM6AsDlSUXG1OgVFlSrNMGKLNQM9fc=; b=xaO5rAoKIokRKS29hMu5ORnKf97qq0xMcmlaZ4Yuwil1Y95ZfuHKZxe6XmpG0R1Y3y m2vZiCYjAypQces7TKH5axIJX2/TFymCrXvtaIpvLpSPLtXa46Gk576UYKsPiNTWKDO0 cHRcbjNpJF5S3TNoIZkP41UDrP9pcfM2NXm4mU6+c3qnmaMLNvERTe9Ezn3OfIZPWjKy GzKAgcUiBnQmPZQCAJtJ/uSvybcwfJELyx8x+IPfCQdUlJz3cNVdVhM60YbOHeOPAYjW G2IoH7XHCWPaUj97Zf0N3cGRbPXPBD4ydneGUKsxXTIUx2SwrNMTlopP2BnCMIOVUxCE ZW+A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785942148; x=1786546948; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=Unst9+FN4mg5CbM6AsDlSUXG1OgVFlSrNMGKLNQM9fc=; b=HSL19soU5mZ7p5A2AYJ6SYSvYWeyiU+XAmc1rALSvdkW/EZW8pCLvVEdZyP3sIQyoj Z9e8ShC9Nj3teC8N20XnDL2gJFgI/W8UhntIYNVqPLN25C6OsSTbMd0ljhrZUi10M+aJ FSA8VxWJKcnLU0x2FqXQz8ZmwkaQgoG07Dr51asXu3pzGHbz6WvZtKxD8HhjEaiGejqY whgriUm2+6KZBgD/i4+KM0rbbwkmmlV/2jijykxjW/iFcrnmrYbgebzLLXRILKfp8OHx F8ol/Driwj2DOIeueSieRyjMJz83HUKnUTkLl624BHnsVYHGJX+XT1NLBJImkHJx1fbT WNdQ== X-Forwarded-Encrypted: i=1; AHgh+Rp+XblLKJ/4yop28KkZIN5YLfXKdBFFtggFkBpjCkEZ+TzogHXwKnKToWQiff88ic2KcoThtvOj6N0pF6Y=@vger.kernel.org X-Gm-Message-State: AOJu0YyA4l/7ze3KY2Hdwrwwo4LTtn2oRV2H8eSj3XhY3z6hzujT+EHq B7jd6IIKmRiUW+CvMlI3kbWJMoO883qlM+MA7jqqsgsCPkkOew+FnSI9xp1Aplk32PI= X-Gm-Gg: AR+sD100iLzvbxDlCJnB0yeRcF5sC89F9HzIm91CuNsphvB8CEd9soA6dovK92UQOUG V0KvfCXbdVLNJMyFGvkdN1VkSb8vHEDfkGNtSYC6ny8peFZ9mb/2k8yXq9kQ74AnP6M0Zmyn+D7 JdIZz0/dN3kIYNI9cmNQpEvoYvUI5FK9SgNl4619hVMjCQR+TKsA5e+VTjznuhCh2agQoezUyKZ 5+Rr6WVNkg5A0lU6hkzIbci5dGlByY1KBCOcFE8SDELuwocmqExagtgK3q1x85jFgHlBLsYyljl D1QKie7WznIpi5Uj62PveAn3+DAvcG9y05hHEJqTsPTFCWRhlKwD7lcRRvWChO8ftxXC09bk3pY wkxWR7Dvk6DR9dRAkuPXpNQnJJeEWE2qL25J1b/JE483JHdBnSEfPo4ojE3kBVxDRTpeGrGv7LV Mt8wD+iB1OOFtXuRGoy3BYAT6pm9H0S0w6qdyLHqRRPzF/mjT0Xm8kuCHt9737YURq X-Received: by 2002:a05:6000:41d0:b0:45e:73eb:5119 with SMTP id ffacd0b85a97d-47fec62ea74mr13867635f8f.22.1785942148094; Wed, 05 Aug 2026 08:02:28 -0700 (PDT) Received: from pop-os.local ([37.18.141.193]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-47fec23ede6sm10308695f8f.30.2026.08.05.08.02.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 05 Aug 2026 08:02:27 -0700 (PDT) From: James Clark Date: Wed, 05 Aug 2026 16:01:53 +0100 Subject: [PATCH 3/3] perf: arm_spe: Add support for a 'software' discard mode Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260805-james-spe-software-discard-v1-3-0ff0e44c4c92@linaro.org> References: <20260805-james-spe-software-discard-v1-0-0ff0e44c4c92@linaro.org> In-Reply-To: <20260805-james-spe-software-discard-v1-0-0ff0e44c4c92@linaro.org> To: Will Deacon , Mark Rutland , Leo Yan , Suzuki Poulose , Al Grant Cc: linux-arm-kernel@lists.infradead.org, linux-perf-users@vger.kernel.org, linux-kernel@vger.kernel.org, James Clark X-Mailer: b4 0.15.2 Currently discard mode needs hardware support, but we can get something that appears pretty similar to userspace by writing to a single page allocated by the driver and not emitting aux records. Remove the -EOPNOTSUPP, as now we use the same discard mode format attr as with HW support but fall back to the software version. Don't call perf_get_aux() in discard mode as it unconditionally dereferences a NULL event->rb when handle->event exists, which can now be true. Signed-off-by: James Clark --- drivers/perf/arm_spe_pmu.c | 160 +++++++++++++++++++++++++++++++++++++----= ---- 1 file changed, 134 insertions(+), 26 deletions(-) diff --git a/drivers/perf/arm_spe_pmu.c b/drivers/perf/arm_spe_pmu.c index 562a1d3be39f..093fa3cc5084 100644 --- a/drivers/perf/arm_spe_pmu.c +++ b/drivers/perf/arm_spe_pmu.c @@ -60,6 +60,7 @@ static bool get_spe_event_has_cx(struct perf_event *event) } =20 #define ARM_SPE_BUF_PAD_BYTE 0 +#define ARM_SPE_DISCARD_BUF_SIZE SZ_4M =20 struct arm_spe_pmu_buf { int nr_pages; @@ -67,6 +68,12 @@ struct arm_spe_pmu_buf { void *base; }; =20 +struct arm_spe_pmu_sw_discard_buf { + struct page *page; + void *base; + refcount_t refcount; +}; + struct arm_spe_pmu { struct pmu pmu; struct platform_device *pdev; @@ -85,7 +92,7 @@ struct arm_spe_pmu { #define SPE_PMU_FEAT_LDS (1UL << 4) #define SPE_PMU_FEAT_ERND (1UL << 5) #define SPE_PMU_FEAT_INV_FILT_EVT (1UL << 6) -#define SPE_PMU_FEAT_DISCARD (1UL << 7) +#define SPE_PMU_FEAT_HW_DISCARD (1UL << 7) #define SPE_PMU_FEAT_EFT (1UL << 8) #define SPE_PMU_FEAT_FDS (1UL << 9) #define SPE_PMU_FEAT_DEV_PROBED (1UL << 63) @@ -218,7 +225,8 @@ static const struct attribute_group arm_spe_pmu_cap_gro= up =3D { #define ATTR_CFG_FLD_store_filter_CFG config /* PMSFCR_EL1.ST */ #define ATTR_CFG_FLD_store_filter_LO 34 #define ATTR_CFG_FLD_store_filter_HI 34 -#define ATTR_CFG_FLD_discard_CFG config /* PMBLIMITR_EL1.FM =3D DISCARD */ +/* PMBLIMITR_EL1.FM =3D DISCARD, or scratch buffer if no HW support */ +#define ATTR_CFG_FLD_discard_CFG config #define ATTR_CFG_FLD_discard_LO 35 #define ATTR_CFG_FLD_discard_HI 35 #define ATTR_CFG_FLD_branch_filter_mask_CFG config /* PMSFCR_EL1.Bm */ @@ -309,9 +317,6 @@ static umode_t arm_spe_pmu_format_attr_is_visible(struc= t kobject *kobj, struct device *dev =3D kobj_to_dev(kobj); struct arm_spe_pmu *spe_pmu =3D dev_get_drvdata(dev); =20 - if (attr =3D=3D &format_attr_discard.attr && !(spe_pmu->features & SPE_PM= U_FEAT_DISCARD)) - return 0; - if (attr =3D=3D &format_attr_inv_event_filter.attr && !(spe_pmu->features= & SPE_PMU_FEAT_INV_FILT_EVT)) return 0; =20 @@ -368,6 +373,82 @@ static bool arm_spe_discard_mode(struct perf_event *ev= ent) return ATTR_CFG_GET_FLD(&event->attr, discard); } =20 +static bool arm_spe_uses_sw_discard_buf(struct perf_event *event) +{ + struct arm_spe_pmu *spe_pmu =3D to_spe_pmu(event->pmu); + + return arm_spe_discard_mode(event) && + !(spe_pmu->features & SPE_PMU_FEAT_HW_DISCARD); +} + +static void arm_spe_pmu_free_discard_buf(struct perf_event *event) +{ + struct arm_spe_pmu_sw_discard_buf *buf =3D event->pmu_private; + + event->pmu_private =3D NULL; + if (!refcount_dec_and_test(&buf->refcount)) + return; + + vunmap(buf->base); + __free_page(buf->page); + kfree(buf); +} + +/* + * Map a single page multiple times to make up ARM_SPE_DISCARD_BUF_SIZE. + * + * This reduces the number of interrupts that have to be serviced in softw= are + * discard mode, but at the same time only uses a page of memory. We don't= need + * to worry about samples being overwritten because they're never read. + */ +static int arm_spe_pmu_alloc_discard_buf(struct perf_event *event) +{ + int node =3D (event->cpu =3D=3D -1) ? -1 : cpu_to_node(event->cpu); + int nr_pages =3D ARM_SPE_DISCARD_BUF_SIZE / PAGE_SIZE; + struct arm_spe_pmu_sw_discard_buf *buf; + struct page **pglist; + int i; + + if (event->parent) { + buf =3D event->parent->pmu_private; + refcount_inc(&buf->refcount); + event->pmu_private =3D buf; + event->destroy =3D arm_spe_pmu_free_discard_buf; + return 0; + } + + buf =3D kzalloc_node(sizeof(*buf), GFP_KERNEL, node); + if (!buf) + return -ENOMEM; + + buf->page =3D alloc_pages_node(node, GFP_KERNEL, 0); + if (!buf->page) + goto out_free_buf; + + pglist =3D kvmalloc_array(nr_pages, sizeof(*pglist), GFP_KERNEL); + if (!pglist) + goto out_free_page; + + for (i =3D 0; i < nr_pages; i++) + pglist[i] =3D buf->page; + + buf->base =3D vmap(pglist, nr_pages, VM_MAP, PAGE_KERNEL); + kvfree(pglist); + if (!buf->base) + goto out_free_page; + + refcount_set(&buf->refcount, 1); + event->pmu_private =3D buf; + event->destroy =3D arm_spe_pmu_free_discard_buf; + return 0; + +out_free_page: + __free_page(buf->page); +out_free_buf: + kfree(buf); + return -ENOMEM; +} + /* Convert between user ABI and register values */ static u64 arm_spe_event_to_pmscr(struct perf_event *event) { @@ -617,10 +698,26 @@ static u64 arm_spe_pmu_next_off(struct perf_output_ha= ndle *handle) static void arm_spe_pmu_begin_discard(struct perf_output_handle *handle, struct perf_event *event) { - u64 limit; + struct arm_spe_pmu *spe_pmu =3D to_spe_pmu(event->pmu); + struct arm_spe_pmu_sw_discard_buf *discard_buf =3D event->pmu_private; + u64 base, limit; + + if (spe_pmu->features & SPE_PMU_FEAT_HW_DISCARD) { + limit =3D FIELD_PREP(PMBLIMITR_EL1_FM, PMBLIMITR_EL1_FM_DISCARD); + limit |=3D PMBLIMITR_EL1_E; + } else { + base =3D (u64) discard_buf->base; + limit =3D base + ARM_SPE_DISCARD_BUF_SIZE; + limit |=3D PMBLIMITR_EL1_E; + write_sysreg_s(base, SYS_PMBPTR_EL1); =20 - limit =3D FIELD_PREP(PMBLIMITR_EL1_FM, PMBLIMITR_EL1_FM_DISCARD); - limit |=3D PMBLIMITR_EL1_E; + /* + * Track the event so we can access the discard buffer through + * event->pmu_private. perf_aux_output_begin() normally handles + * this, but we can do it manually if that's not being used. + */ + handle->event =3D event; + } =20 write_sysreg_s(limit, SYS_PMBLIMITR_EL1); } @@ -757,15 +854,20 @@ static irqreturn_t arm_spe_pmu_irq_handler(int irq, v= oid *dev) enum arm_spe_pmu_buf_fault_action act; u64 aux_flags; =20 - if (!perf_get_aux(handle)) + if (!event) + return IRQ_NONE; + + if (!arm_spe_discard_mode(event) && !perf_get_aux(handle)) return IRQ_NONE; =20 act =3D arm_spe_pmu_buf_get_fault_act(&aux_flags); if (act =3D=3D SPE_PMU_BUF_FAULT_ACT_SPURIOUS) return IRQ_NONE; =20 - perf_aux_output_flag(handle, aux_flags); - arm_spe_perf_aux_output_end(handle); + if (!arm_spe_discard_mode(event)) { + perf_aux_output_flag(handle, aux_flags); + arm_spe_perf_aux_output_end(handle); + } =20 /* * Ensure perf callbacks have completed, which may disable the @@ -819,6 +921,7 @@ static irqreturn_t arm_spe_pmu_irq_handler(int irq, voi= d *dev) static int arm_spe_pmu_event_init(struct perf_event *event) { u64 reg; + int ret; struct perf_event_attr *attr =3D &event->attr; struct arm_spe_pmu *spe_pmu =3D to_spe_pmu(event->pmu); =20 @@ -880,14 +983,16 @@ static int arm_spe_pmu_event_init(struct perf_event *= event) !(spe_pmu->features & SPE_PMU_FEAT_EFT)) return -EOPNOTSUPP; =20 - if (arm_spe_discard_mode(event) && - !(spe_pmu->features & SPE_PMU_FEAT_DISCARD)) - return -EOPNOTSUPP; - set_spe_event_has_cx(event); reg =3D arm_spe_event_to_pmscr(event); - if (reg & (PMSCR_EL1_PA | PMSCR_EL1_PCT)) - return perf_allow_kernel(); + if (reg & (PMSCR_EL1_PA | PMSCR_EL1_PCT)) { + ret =3D perf_allow_kernel(); + if (ret) + return ret; + } + + if (arm_spe_uses_sw_discard_buf(event)) + return arm_spe_pmu_alloc_discard_buf(event); =20 return 0; } @@ -954,23 +1059,26 @@ static void arm_spe_pmu_stop(struct perf_event *even= t, int flags) arm_spe_pmu_disable_and_drain_local(); =20 if (flags & PERF_EF_UPDATE) { + enum arm_spe_pmu_buf_fault_action act; + /* * If there's a fault pending then ensure we contain it * to this buffer, since we might be on the context-switch * path. */ - if (perf_get_aux(handle)) { - enum arm_spe_pmu_buf_fault_action act; - - act =3D arm_spe_pmu_buf_get_fault_act(&aux_flags); + act =3D arm_spe_pmu_buf_get_fault_act(&aux_flags); + if (!arm_spe_discard_mode(event) && perf_get_aux(handle)) { perf_aux_output_flag(handle, aux_flags); arm_spe_perf_aux_output_end(handle); - - /* Assume PMBSR only needs clearing for real faults */ - if (act !=3D SPE_PMU_BUF_FAULT_ACT_SPURIOUS) - write_sysreg_s(0, SYS_PMBSR_EL1); + } else { + /* Discard mode tracks event outside of perf_aux_output_X() */ + handle->event =3D NULL; } =20 + /* Assume PMBSR only needs clearing for real faults */ + if (act !=3D SPE_PMU_BUF_FAULT_ACT_SPURIOUS) + write_sysreg_s(0, SYS_PMBSR_EL1); + /* * This may also contain ECOUNT, but nobody else should * be looking at period_left, since we forbid frequency @@ -1180,7 +1288,7 @@ static void __arm_spe_pmu_dev_probe(void *info) spe_pmu->features |=3D SPE_PMU_FEAT_ERND; =20 if (spe_pmu->pmsver >=3D ID_AA64DFR0_EL1_PMSVer_V1P2) - spe_pmu->features |=3D SPE_PMU_FEAT_DISCARD; + spe_pmu->features |=3D SPE_PMU_FEAT_HW_DISCARD; =20 if (FIELD_GET(PMSIDR_EL1_EFT, reg)) spe_pmu->features |=3D SPE_PMU_FEAT_EFT; --=20 2.43.0