[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20221219154119.352918965@infradead.org>
Date: Mon, 19 Dec 2022 16:35:33 +0100
From: Peter Zijlstra <peterz@...radead.org>
To: torvalds@...ux-foundation.org
Cc: corbet@....net, will@...nel.org, peterz@...radead.org,
boqun.feng@...il.com, mark.rutland@....com,
catalin.marinas@....com, dennis@...nel.org, tj@...nel.org,
cl@...ux.com, hca@...ux.ibm.com, gor@...ux.ibm.com,
agordeev@...ux.ibm.com, borntraeger@...ux.ibm.com,
svens@...ux.ibm.com, Herbert Xu <herbert@...dor.apana.org.au>,
davem@...emloft.net, tglx@...utronix.de, mingo@...hat.com,
bp@...en8.de, dave.hansen@...ux.intel.com, x86@...nel.org,
hpa@...or.com, joro@...tes.org, suravee.suthikulpanit@....com,
robin.murphy@....com, dwmw2@...radead.org,
baolu.lu@...ux.intel.com, Arnd Bergmann <arnd@...db.de>,
penberg@...nel.org, rientjes@...gle.com, iamjoonsoo.kim@....com,
Andrew Morton <akpm@...ux-foundation.org>, vbabka@...e.cz,
roman.gushchin@...ux.dev, 42.hyeyoo@...il.com,
linux-doc@...r.kernel.org, linux-kernel@...r.kernel.org,
linux-mm@...ck.org, linux-s390@...r.kernel.org,
linux-crypto@...r.kernel.org, iommu@...ts.linux.dev,
linux-arch@...r.kernel.org
Subject: [RFC][PATCH 08/12] s390: Replace cmpxchg_double() with cmpxchg128()
In order to depricate cmpxchg_double(), replace all its usage with
cmpxchg128().
Signed-off-by: Peter Zijlstra (Intel) <peterz@...radead.org>
---
arch/s390/include/asm/cpu_mf.h | 29 ++++++++++++-----
arch/s390/kernel/perf_cpum_sf.c | 65 +++++++++++++++++++++++++---------------
2 files changed, 63 insertions(+), 31 deletions(-)
--- a/arch/s390/include/asm/cpu_mf.h
+++ b/arch/s390/include/asm/cpu_mf.h
@@ -131,19 +131,32 @@ struct hws_combined_entry {
struct hws_diag_entry diag; /* Diagnostic-sampling data entry */
} __packed;
+union hws_flags_and_overflow {
+ struct {
+ unsigned long flags;
+ unsigned long overflow;
+ };
+ u128 full;
+};
+
struct hws_trailer_entry {
union {
struct {
- unsigned int f:1; /* 0 - Block Full Indicator */
- unsigned int a:1; /* 1 - Alert request control */
- unsigned int t:1; /* 2 - Timestamp format */
- unsigned int :29; /* 3 - 31: Reserved */
- unsigned int bsdes:16; /* 32-47: size of basic SDE */
- unsigned int dsdes:16; /* 48-63: size of diagnostic SDE */
+ union {
+ struct {
+ unsigned int f:1; /* 0 - Block Full Indicator */
+ unsigned int a:1; /* 1 - Alert request control */
+ unsigned int t:1; /* 2 - Timestamp format */
+ unsigned int :29; /* 3 - 31: Reserved */
+ unsigned int bsdes:16; /* 32-47: size of basic SDE */
+ unsigned int dsdes:16; /* 48-63: size of diagnostic SDE */
+ };
+ unsigned long long flags; /* 0 - 63: All indicators */
+ };
+ unsigned long long overflow; /* 64 - sample Overflow count */
};
- unsigned long long flags; /* 0 - 63: All indicators */
+ union hws_flags_and_overflow flags_and_overflow;
};
- unsigned long long overflow; /* 64 - sample Overflow count */
unsigned char timestamp[16]; /* 16 - 31 timestamp */
unsigned long long reserved1; /* 32 -Reserved */
unsigned long long reserved2; /* */
--- a/arch/s390/kernel/perf_cpum_sf.c
+++ b/arch/s390/kernel/perf_cpum_sf.c
@@ -1227,6 +1227,8 @@ static void hw_collect_samples(struct pe
}
}
+typedef union hws_flags_and_overflow fao_t;
+
/* hw_perf_event_update() - Process sampling buffer
* @event: The perf event
* @flush_all: Flag to also flush partially filled sample-data-blocks
@@ -1243,10 +1245,11 @@ static void hw_collect_samples(struct pe
*/
static void hw_perf_event_update(struct perf_event *event, int flush_all)
{
+ unsigned long long event_overflow, sampl_overflow, num_sdb;
struct hw_perf_event *hwc = &event->hw;
struct hws_trailer_entry *te;
+ fao_t old_fao, new_fao;
unsigned long *sdbt;
- unsigned long long event_overflow, sampl_overflow, num_sdb, te_flags;
int done;
/*
@@ -1294,12 +1297,16 @@ static void hw_perf_event_update(struct
num_sdb++;
/* Reset trailer (using compare-double-and-swap) */
+ old_fao = te->flags_and_overflow;
do {
- te_flags = te->flags & ~SDB_TE_BUFFER_FULL_MASK;
- te_flags |= SDB_TE_ALERT_REQ_MASK;
- } while (!cmpxchg_double(&te->flags, &te->overflow,
- te->flags, te->overflow,
- te_flags, 0ULL));
+ new_fao = (fao_t){
+ .flags = old_fao.flags,
+ .overflow = 0,
+ };
+ new_fao.flags &= ~SDB_TE_BUFFER_FULL_MASK;
+ new_fao.flags |= SDB_TE_ALERT_REQ_MASK;
+ } while (!try_cmpxchg128(&te->flags_and_overflow.full,
+ &old_fao.full, new_fao.full));
/* Advance to next sample-data-block */
sdbt++;
@@ -1475,14 +1482,19 @@ static int aux_output_begin(struct perf_
static bool aux_set_alert(struct aux_buffer *aux, unsigned long alert_index,
unsigned long long *overflow)
{
- unsigned long long orig_overflow, orig_flags, new_flags;
struct hws_trailer_entry *te;
+ fao_t old_fao, new_fao;
te = aux_sdb_trailer(aux, alert_index);
+
+ old_fao = te->flags_and_overflow;
do {
- orig_flags = te->flags;
- *overflow = orig_overflow = te->overflow;
- if (orig_flags & SDB_TE_BUFFER_FULL_MASK) {
+ new_fao = (fao_t){
+ .flags = old_fao.flags,
+ .overflow = 0,
+ };
+ *overflow = old_fao.overflow;
+ if (new_fao.flags & SDB_TE_BUFFER_FULL_MASK) {
/*
* SDB is already set by hardware.
* Abort and try to set somewhere
@@ -1490,10 +1502,11 @@ static bool aux_set_alert(struct aux_buf
*/
return false;
}
- new_flags = orig_flags | SDB_TE_ALERT_REQ_MASK;
- } while (!cmpxchg_double(&te->flags, &te->overflow,
- orig_flags, orig_overflow,
- new_flags, 0ULL));
+ new_fao.flags |= SDB_TE_ALERT_REQ_MASK;
+
+ } while (!try_cmpxchg128(&te->flags_and_overflow.full,
+ &old_fao.full, new_fao.full));
+
return true;
}
@@ -1522,9 +1535,10 @@ static bool aux_set_alert(struct aux_buf
static bool aux_reset_buffer(struct aux_buffer *aux, unsigned long range,
unsigned long long *overflow)
{
- unsigned long long orig_overflow, orig_flags, new_flags;
unsigned long i, range_scan, idx, idx_old;
+ unsigned long long orig_overflow;
struct hws_trailer_entry *te;
+ fao_t old_fao, new_fao;
debug_sprintf_event(sfdbg, 6, "%s: range %ld head %ld alert %ld "
"empty %ld\n", __func__, range, aux->head,
@@ -1554,17 +1568,22 @@ static bool aux_reset_buffer(struct aux_
idx_old = idx = aux->empty_mark + 1;
for (i = 0; i < range_scan; i++, idx++) {
te = aux_sdb_trailer(aux, idx);
+
+ old_fao = te->flags_and_overflow;
do {
- orig_flags = te->flags;
- orig_overflow = te->overflow;
- new_flags = orig_flags & ~SDB_TE_BUFFER_FULL_MASK;
+ new_fao = (fao_t){
+ .flags = old_fao.flags,
+ .overflow = 0,
+ };
+ orig_overflow = old_fao.overflow;
+ new_fao.flags &= ~SDB_TE_BUFFER_FULL_MASK;
if (idx == aux->alert_mark)
- new_flags |= SDB_TE_ALERT_REQ_MASK;
+ new_fao.flags |= SDB_TE_ALERT_REQ_MASK;
else
- new_flags &= ~SDB_TE_ALERT_REQ_MASK;
- } while (!cmpxchg_double(&te->flags, &te->overflow,
- orig_flags, orig_overflow,
- new_flags, 0ULL));
+ new_fao.flags &= ~SDB_TE_ALERT_REQ_MASK;
+ } while (!try_cmpxchg128(&te->flags_and_overflow.full,
+ &old_fao.full, new_fao.full));
+
*overflow += orig_overflow;
}
Powered by blists - more mailing lists