Commit 5be413a6 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 's390-6.2-2' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux

Pull s390 fixes from Heiko Carstens:

 - Add various missing READ_ONCE() to cmpxchg() loops prevent the
   compiler from potentially generating incorrect code. This includes a
   rather large change to the s390 specific hardware sampling code and
   its current use of cmpxchg_double().

   Do the fix now to get it out of the way of Peter Zijlstra's
   cmpxchg128() work, and have something that can be backported. The
   added new code includes a private 128 bit cmpxchg variant which will
   be removed again after Peter's rework is available. Also note that
   this 128 bit cmpxchg variant is used to implement 128 bit
   READ_ONCE(), while strictly speaking it wouldn't be necessary, and
   _READ_ONCE() should also be sufficient; even though it isn't obvious
   for all converted locations that this is the case. Therefore use this
   implementation for for the sake of clarity and consistency for now.

 - Fix ipl report address handling to avoid kdump failures/hangs.

 - Fix misuse of #(el)if in kernel decompressor.

 - Define RUNTIME_DISCARD_EXIT to fix link error with GNU ld < 2.36,
   caused by the recently changed discard behaviour.

 - Make sure _edata and _end symbols are always page aligned.

 - The current header guard DEBUG_H in one of the s390 specific header
   files is too generic and conflicts with the ath9k wireless driver.
   Add an _ASM_S390_ prefix to the guard to make it unique.

 - Update defconfigs.

* tag 's390-6.2-2' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux:
  s390: update defconfigs
  KVM: s390: interrupt: use READ_ONCE() before cmpxchg()
  s390/percpu: add READ_ONCE() to arch_this_cpu_to_op_simple()
  s390/cpum_sf: add READ_ONCE() semantics to compare and swap loops
  s390/kexec: fix ipl report address for kdump
  s390: fix -Wundef warning for CONFIG_KERNEL_ZSTD
  s390: define RUNTIME_DISCARD_EXIT to fix link error with GNU ld < 2.36
  s390: expicitly align _edata and _end symbols on page boundary
  s390/debug: add _ASM_S390_ prefix to header guard
parents bad8c4a8 1ecf7bd9
...@@ -23,9 +23,9 @@ ...@@ -23,9 +23,9 @@
#define memmove memmove #define memmove memmove
#define memzero(s, n) memset((s), 0, (n)) #define memzero(s, n) memset((s), 0, (n))
#ifdef CONFIG_KERNEL_BZIP2 #if defined(CONFIG_KERNEL_BZIP2)
#define BOOT_HEAP_SIZE 0x400000 #define BOOT_HEAP_SIZE 0x400000
#elif CONFIG_KERNEL_ZSTD #elif defined(CONFIG_KERNEL_ZSTD)
#define BOOT_HEAP_SIZE 0x30000 #define BOOT_HEAP_SIZE 0x30000
#else #else
#define BOOT_HEAP_SIZE 0x10000 #define BOOT_HEAP_SIZE 0x10000
......
...@@ -190,7 +190,6 @@ CONFIG_NFT_CT=m ...@@ -190,7 +190,6 @@ CONFIG_NFT_CT=m
CONFIG_NFT_LOG=m CONFIG_NFT_LOG=m
CONFIG_NFT_LIMIT=m CONFIG_NFT_LIMIT=m
CONFIG_NFT_NAT=m CONFIG_NFT_NAT=m
CONFIG_NFT_OBJREF=m
CONFIG_NFT_REJECT=m CONFIG_NFT_REJECT=m
CONFIG_NFT_COMPAT=m CONFIG_NFT_COMPAT=m
CONFIG_NFT_HASH=m CONFIG_NFT_HASH=m
...@@ -569,6 +568,7 @@ CONFIG_INPUT_EVDEV=y ...@@ -569,6 +568,7 @@ CONFIG_INPUT_EVDEV=y
# CONFIG_INPUT_MOUSE is not set # CONFIG_INPUT_MOUSE is not set
# CONFIG_SERIO is not set # CONFIG_SERIO is not set
CONFIG_LEGACY_PTY_COUNT=0 CONFIG_LEGACY_PTY_COUNT=0
# CONFIG_LEGACY_TIOCSTI is not set
CONFIG_VIRTIO_CONSOLE=m CONFIG_VIRTIO_CONSOLE=m
CONFIG_HW_RANDOM_VIRTIO=m CONFIG_HW_RANDOM_VIRTIO=m
CONFIG_HANGCHECK_TIMER=m CONFIG_HANGCHECK_TIMER=m
...@@ -660,6 +660,7 @@ CONFIG_CONFIGFS_FS=m ...@@ -660,6 +660,7 @@ CONFIG_CONFIGFS_FS=m
CONFIG_ECRYPT_FS=m CONFIG_ECRYPT_FS=m
CONFIG_CRAMFS=m CONFIG_CRAMFS=m
CONFIG_SQUASHFS=m CONFIG_SQUASHFS=m
CONFIG_SQUASHFS_CHOICE_DECOMP_BY_MOUNT=y
CONFIG_SQUASHFS_XATTR=y CONFIG_SQUASHFS_XATTR=y
CONFIG_SQUASHFS_LZ4=y CONFIG_SQUASHFS_LZ4=y
CONFIG_SQUASHFS_LZO=y CONFIG_SQUASHFS_LZO=y
...@@ -705,6 +706,7 @@ CONFIG_SECURITY_LOCKDOWN_LSM_EARLY=y ...@@ -705,6 +706,7 @@ CONFIG_SECURITY_LOCKDOWN_LSM_EARLY=y
CONFIG_SECURITY_LANDLOCK=y CONFIG_SECURITY_LANDLOCK=y
CONFIG_INTEGRITY_SIGNATURE=y CONFIG_INTEGRITY_SIGNATURE=y
CONFIG_INTEGRITY_ASYMMETRIC_KEYS=y CONFIG_INTEGRITY_ASYMMETRIC_KEYS=y
CONFIG_INTEGRITY_PLATFORM_KEYRING=y
CONFIG_IMA=y CONFIG_IMA=y
CONFIG_IMA_DEFAULT_HASH_SHA256=y CONFIG_IMA_DEFAULT_HASH_SHA256=y
CONFIG_IMA_WRITE_POLICY=y CONFIG_IMA_WRITE_POLICY=y
...@@ -781,6 +783,7 @@ CONFIG_ZCRYPT=m ...@@ -781,6 +783,7 @@ CONFIG_ZCRYPT=m
CONFIG_PKEY=m CONFIG_PKEY=m
CONFIG_CRYPTO_PAES_S390=m CONFIG_CRYPTO_PAES_S390=m
CONFIG_CRYPTO_DEV_VIRTIO=m CONFIG_CRYPTO_DEV_VIRTIO=m
CONFIG_SYSTEM_BLACKLIST_KEYRING=y
CONFIG_CORDIC=m CONFIG_CORDIC=m
CONFIG_CRYPTO_LIB_CURVE25519=m CONFIG_CRYPTO_LIB_CURVE25519=m
CONFIG_CRYPTO_LIB_CHACHA20POLY1305=m CONFIG_CRYPTO_LIB_CHACHA20POLY1305=m
...@@ -848,7 +851,6 @@ CONFIG_PREEMPT_TRACER=y ...@@ -848,7 +851,6 @@ CONFIG_PREEMPT_TRACER=y
CONFIG_SCHED_TRACER=y CONFIG_SCHED_TRACER=y
CONFIG_FTRACE_SYSCALLS=y CONFIG_FTRACE_SYSCALLS=y
CONFIG_BLK_DEV_IO_TRACE=y CONFIG_BLK_DEV_IO_TRACE=y
CONFIG_BPF_KPROBE_OVERRIDE=y
CONFIG_HIST_TRIGGERS=y CONFIG_HIST_TRIGGERS=y
CONFIG_FTRACE_STARTUP_TEST=y CONFIG_FTRACE_STARTUP_TEST=y
# CONFIG_EVENT_TRACE_STARTUP_TEST is not set # CONFIG_EVENT_TRACE_STARTUP_TEST is not set
...@@ -870,7 +872,6 @@ CONFIG_FAIL_MAKE_REQUEST=y ...@@ -870,7 +872,6 @@ CONFIG_FAIL_MAKE_REQUEST=y
CONFIG_FAIL_IO_TIMEOUT=y CONFIG_FAIL_IO_TIMEOUT=y
CONFIG_FAIL_FUTEX=y CONFIG_FAIL_FUTEX=y
CONFIG_FAULT_INJECTION_DEBUG_FS=y CONFIG_FAULT_INJECTION_DEBUG_FS=y
CONFIG_FAIL_FUNCTION=y
CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y
CONFIG_LKDTM=m CONFIG_LKDTM=m
CONFIG_TEST_MIN_HEAP=y CONFIG_TEST_MIN_HEAP=y
......
...@@ -181,7 +181,6 @@ CONFIG_NFT_CT=m ...@@ -181,7 +181,6 @@ CONFIG_NFT_CT=m
CONFIG_NFT_LOG=m CONFIG_NFT_LOG=m
CONFIG_NFT_LIMIT=m CONFIG_NFT_LIMIT=m
CONFIG_NFT_NAT=m CONFIG_NFT_NAT=m
CONFIG_NFT_OBJREF=m
CONFIG_NFT_REJECT=m CONFIG_NFT_REJECT=m
CONFIG_NFT_COMPAT=m CONFIG_NFT_COMPAT=m
CONFIG_NFT_HASH=m CONFIG_NFT_HASH=m
...@@ -559,6 +558,7 @@ CONFIG_INPUT_EVDEV=y ...@@ -559,6 +558,7 @@ CONFIG_INPUT_EVDEV=y
# CONFIG_INPUT_MOUSE is not set # CONFIG_INPUT_MOUSE is not set
# CONFIG_SERIO is not set # CONFIG_SERIO is not set
CONFIG_LEGACY_PTY_COUNT=0 CONFIG_LEGACY_PTY_COUNT=0
# CONFIG_LEGACY_TIOCSTI is not set
CONFIG_VIRTIO_CONSOLE=m CONFIG_VIRTIO_CONSOLE=m
CONFIG_HW_RANDOM_VIRTIO=m CONFIG_HW_RANDOM_VIRTIO=m
CONFIG_HANGCHECK_TIMER=m CONFIG_HANGCHECK_TIMER=m
...@@ -645,6 +645,7 @@ CONFIG_CONFIGFS_FS=m ...@@ -645,6 +645,7 @@ CONFIG_CONFIGFS_FS=m
CONFIG_ECRYPT_FS=m CONFIG_ECRYPT_FS=m
CONFIG_CRAMFS=m CONFIG_CRAMFS=m
CONFIG_SQUASHFS=m CONFIG_SQUASHFS=m
CONFIG_SQUASHFS_CHOICE_DECOMP_BY_MOUNT=y
CONFIG_SQUASHFS_XATTR=y CONFIG_SQUASHFS_XATTR=y
CONFIG_SQUASHFS_LZ4=y CONFIG_SQUASHFS_LZ4=y
CONFIG_SQUASHFS_LZO=y CONFIG_SQUASHFS_LZO=y
...@@ -688,6 +689,7 @@ CONFIG_SECURITY_LOCKDOWN_LSM_EARLY=y ...@@ -688,6 +689,7 @@ CONFIG_SECURITY_LOCKDOWN_LSM_EARLY=y
CONFIG_SECURITY_LANDLOCK=y CONFIG_SECURITY_LANDLOCK=y
CONFIG_INTEGRITY_SIGNATURE=y CONFIG_INTEGRITY_SIGNATURE=y
CONFIG_INTEGRITY_ASYMMETRIC_KEYS=y CONFIG_INTEGRITY_ASYMMETRIC_KEYS=y
CONFIG_INTEGRITY_PLATFORM_KEYRING=y
CONFIG_IMA=y CONFIG_IMA=y
CONFIG_IMA_DEFAULT_HASH_SHA256=y CONFIG_IMA_DEFAULT_HASH_SHA256=y
CONFIG_IMA_WRITE_POLICY=y CONFIG_IMA_WRITE_POLICY=y
...@@ -766,6 +768,7 @@ CONFIG_ZCRYPT=m ...@@ -766,6 +768,7 @@ CONFIG_ZCRYPT=m
CONFIG_PKEY=m CONFIG_PKEY=m
CONFIG_CRYPTO_PAES_S390=m CONFIG_CRYPTO_PAES_S390=m
CONFIG_CRYPTO_DEV_VIRTIO=m CONFIG_CRYPTO_DEV_VIRTIO=m
CONFIG_SYSTEM_BLACKLIST_KEYRING=y
CONFIG_CORDIC=m CONFIG_CORDIC=m
CONFIG_PRIME_NUMBERS=m CONFIG_PRIME_NUMBERS=m
CONFIG_CRYPTO_LIB_CURVE25519=m CONFIG_CRYPTO_LIB_CURVE25519=m
...@@ -798,7 +801,6 @@ CONFIG_STACK_TRACER=y ...@@ -798,7 +801,6 @@ CONFIG_STACK_TRACER=y
CONFIG_SCHED_TRACER=y CONFIG_SCHED_TRACER=y
CONFIG_FTRACE_SYSCALLS=y CONFIG_FTRACE_SYSCALLS=y
CONFIG_BLK_DEV_IO_TRACE=y CONFIG_BLK_DEV_IO_TRACE=y
CONFIG_BPF_KPROBE_OVERRIDE=y
CONFIG_HIST_TRIGGERS=y CONFIG_HIST_TRIGGERS=y
CONFIG_SAMPLES=y CONFIG_SAMPLES=y
CONFIG_SAMPLE_TRACE_PRINTK=m CONFIG_SAMPLE_TRACE_PRINTK=m
......
...@@ -13,7 +13,6 @@ CONFIG_TUNE_ZEC12=y ...@@ -13,7 +13,6 @@ CONFIG_TUNE_ZEC12=y
# CONFIG_COMPAT is not set # CONFIG_COMPAT is not set
CONFIG_NR_CPUS=2 CONFIG_NR_CPUS=2
CONFIG_HZ_100=y CONFIG_HZ_100=y
# CONFIG_RELOCATABLE is not set
# CONFIG_CHSC_SCH is not set # CONFIG_CHSC_SCH is not set
# CONFIG_SCM_BUS is not set # CONFIG_SCM_BUS is not set
CONFIG_CRASH_DUMP=y CONFIG_CRASH_DUMP=y
...@@ -50,6 +49,7 @@ CONFIG_ZFCP=y ...@@ -50,6 +49,7 @@ CONFIG_ZFCP=y
# CONFIG_INPUT_KEYBOARD is not set # CONFIG_INPUT_KEYBOARD is not set
# CONFIG_INPUT_MOUSE is not set # CONFIG_INPUT_MOUSE is not set
# CONFIG_SERIO is not set # CONFIG_SERIO is not set
# CONFIG_LEGACY_TIOCSTI is not set
# CONFIG_HVC_IUCV is not set # CONFIG_HVC_IUCV is not set
# CONFIG_HW_RANDOM_S390 is not set # CONFIG_HW_RANDOM_S390 is not set
# CONFIG_HMC_DRV is not set # CONFIG_HMC_DRV is not set
......
...@@ -131,8 +131,7 @@ struct hws_combined_entry { ...@@ -131,8 +131,7 @@ struct hws_combined_entry {
struct hws_diag_entry diag; /* Diagnostic-sampling data entry */ struct hws_diag_entry diag; /* Diagnostic-sampling data entry */
} __packed; } __packed;
struct hws_trailer_entry { union hws_trailer_header {
union {
struct { struct {
unsigned int f:1; /* 0 - Block Full Indicator */ unsigned int f:1; /* 0 - Block Full Indicator */
unsigned int a:1; /* 1 - Alert request control */ unsigned int a:1; /* 1 - Alert request control */
...@@ -140,10 +139,13 @@ struct hws_trailer_entry { ...@@ -140,10 +139,13 @@ struct hws_trailer_entry {
unsigned int :29; /* 3 - 31: Reserved */ unsigned int :29; /* 3 - 31: Reserved */
unsigned int bsdes:16; /* 32-47: size of basic SDE */ unsigned int bsdes:16; /* 32-47: size of basic SDE */
unsigned int dsdes:16; /* 48-63: size of diagnostic SDE */ unsigned int dsdes:16; /* 48-63: size of diagnostic SDE */
unsigned long long overflow; /* 64 - Overflow Count */
}; };
unsigned long long flags; /* 0 - 63: All indicators */ __uint128_t val;
}; };
unsigned long long overflow; /* 64 - sample Overflow count */
struct hws_trailer_entry {
union hws_trailer_header header; /* 0 - 15 Flags + Overflow Count */
unsigned char timestamp[16]; /* 16 - 31 timestamp */ unsigned char timestamp[16]; /* 16 - 31 timestamp */
unsigned long long reserved1; /* 32 -Reserved */ unsigned long long reserved1; /* 32 -Reserved */
unsigned long long reserved2; /* */ unsigned long long reserved2; /* */
...@@ -290,14 +292,11 @@ static inline unsigned long sample_rate_to_freq(struct hws_qsi_info_block *qsi, ...@@ -290,14 +292,11 @@ static inline unsigned long sample_rate_to_freq(struct hws_qsi_info_block *qsi,
return USEC_PER_SEC * qsi->cpu_speed / rate; return USEC_PER_SEC * qsi->cpu_speed / rate;
} }
#define SDB_TE_ALERT_REQ_MASK 0x4000000000000000UL
#define SDB_TE_BUFFER_FULL_MASK 0x8000000000000000UL
/* Return TOD timestamp contained in an trailer entry */ /* Return TOD timestamp contained in an trailer entry */
static inline unsigned long long trailer_timestamp(struct hws_trailer_entry *te) static inline unsigned long long trailer_timestamp(struct hws_trailer_entry *te)
{ {
/* TOD in STCKE format */ /* TOD in STCKE format */
if (te->t) if (te->header.t)
return *((unsigned long long *) &te->timestamp[1]); return *((unsigned long long *) &te->timestamp[1]);
/* TOD in STCK format */ /* TOD in STCK format */
......
...@@ -4,8 +4,8 @@ ...@@ -4,8 +4,8 @@
* *
* Copyright IBM Corp. 1999, 2020 * Copyright IBM Corp. 1999, 2020
*/ */
#ifndef DEBUG_H #ifndef _ASM_S390_DEBUG_H
#define DEBUG_H #define _ASM_S390_DEBUG_H
#include <linux/string.h> #include <linux/string.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
...@@ -487,4 +487,4 @@ void debug_register_static(debug_info_t *id, int pages_per_area, int nr_areas); ...@@ -487,4 +487,4 @@ void debug_register_static(debug_info_t *id, int pages_per_area, int nr_areas);
#endif /* MODULE */ #endif /* MODULE */
#endif /* DEBUG_H */ #endif /* _ASM_S390_DEBUG_H */
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
pcp_op_T__ *ptr__; \ pcp_op_T__ *ptr__; \
preempt_disable_notrace(); \ preempt_disable_notrace(); \
ptr__ = raw_cpu_ptr(&(pcp)); \ ptr__ = raw_cpu_ptr(&(pcp)); \
prev__ = *ptr__; \ prev__ = READ_ONCE(*ptr__); \
do { \ do { \
old__ = prev__; \ old__ = prev__; \
new__ = old__ op (val); \ new__ = old__ op (val); \
......
...@@ -187,8 +187,6 @@ static int kexec_file_add_ipl_report(struct kimage *image, ...@@ -187,8 +187,6 @@ static int kexec_file_add_ipl_report(struct kimage *image,
data->memsz = ALIGN(data->memsz, PAGE_SIZE); data->memsz = ALIGN(data->memsz, PAGE_SIZE);
buf.mem = data->memsz; buf.mem = data->memsz;
if (image->type == KEXEC_TYPE_CRASH)
buf.mem += crashk_res.start;
ptr = (void *)ipl_cert_list_addr; ptr = (void *)ipl_cert_list_addr;
end = ptr + ipl_cert_list_size; end = ptr + ipl_cert_list_size;
...@@ -225,6 +223,9 @@ static int kexec_file_add_ipl_report(struct kimage *image, ...@@ -225,6 +223,9 @@ static int kexec_file_add_ipl_report(struct kimage *image,
data->kernel_buf + offsetof(struct lowcore, ipl_parmblock_ptr); data->kernel_buf + offsetof(struct lowcore, ipl_parmblock_ptr);
*lc_ipl_parmblock_ptr = (__u32)buf.mem; *lc_ipl_parmblock_ptr = (__u32)buf.mem;
if (image->type == KEXEC_TYPE_CRASH)
buf.mem += crashk_res.start;
ret = kexec_add_buffer(&buf); ret = kexec_add_buffer(&buf);
out: out:
return ret; return ret;
......
...@@ -163,14 +163,15 @@ static void free_sampling_buffer(struct sf_buffer *sfb) ...@@ -163,14 +163,15 @@ static void free_sampling_buffer(struct sf_buffer *sfb)
static int alloc_sample_data_block(unsigned long *sdbt, gfp_t gfp_flags) static int alloc_sample_data_block(unsigned long *sdbt, gfp_t gfp_flags)
{ {
unsigned long sdb, *trailer; struct hws_trailer_entry *te;
unsigned long sdb;
/* Allocate and initialize sample-data-block */ /* Allocate and initialize sample-data-block */
sdb = get_zeroed_page(gfp_flags); sdb = get_zeroed_page(gfp_flags);
if (!sdb) if (!sdb)
return -ENOMEM; return -ENOMEM;
trailer = trailer_entry_ptr(sdb); te = (struct hws_trailer_entry *)trailer_entry_ptr(sdb);
*trailer = SDB_TE_ALERT_REQ_MASK; te->header.a = 1;
/* Link SDB into the sample-data-block-table */ /* Link SDB into the sample-data-block-table */
*sdbt = sdb; *sdbt = sdb;
...@@ -1206,7 +1207,7 @@ static void hw_collect_samples(struct perf_event *event, unsigned long *sdbt, ...@@ -1206,7 +1207,7 @@ static void hw_collect_samples(struct perf_event *event, unsigned long *sdbt,
"%s: Found unknown" "%s: Found unknown"
" sampling data entry: te->f %i" " sampling data entry: te->f %i"
" basic.def %#4x (%p)\n", __func__, " basic.def %#4x (%p)\n", __func__,
te->f, sample->def, sample); te->header.f, sample->def, sample);
/* Sample slot is not yet written or other record. /* Sample slot is not yet written or other record.
* *
* This condition can occur if the buffer was reused * This condition can occur if the buffer was reused
...@@ -1217,7 +1218,7 @@ static void hw_collect_samples(struct perf_event *event, unsigned long *sdbt, ...@@ -1217,7 +1218,7 @@ static void hw_collect_samples(struct perf_event *event, unsigned long *sdbt,
* that are not full. Stop processing if the first * that are not full. Stop processing if the first
* invalid format was detected. * invalid format was detected.
*/ */
if (!te->f) if (!te->header.f)
break; break;
} }
...@@ -1227,6 +1228,16 @@ static void hw_collect_samples(struct perf_event *event, unsigned long *sdbt, ...@@ -1227,6 +1228,16 @@ static void hw_collect_samples(struct perf_event *event, unsigned long *sdbt,
} }
} }
static inline __uint128_t __cdsg(__uint128_t *ptr, __uint128_t old, __uint128_t new)
{
asm volatile(
" cdsg %[old],%[new],%[ptr]\n"
: [old] "+d" (old), [ptr] "+QS" (*ptr)
: [new] "d" (new)
: "memory", "cc");
return old;
}
/* hw_perf_event_update() - Process sampling buffer /* hw_perf_event_update() - Process sampling buffer
* @event: The perf event * @event: The perf event
* @flush_all: Flag to also flush partially filled sample-data-blocks * @flush_all: Flag to also flush partially filled sample-data-blocks
...@@ -1243,10 +1254,11 @@ static void hw_collect_samples(struct perf_event *event, unsigned long *sdbt, ...@@ -1243,10 +1254,11 @@ static void hw_collect_samples(struct perf_event *event, unsigned long *sdbt,
*/ */
static void hw_perf_event_update(struct perf_event *event, int flush_all) static void hw_perf_event_update(struct perf_event *event, int flush_all)
{ {
unsigned long long event_overflow, sampl_overflow, num_sdb;
union hws_trailer_header old, prev, new;
struct hw_perf_event *hwc = &event->hw; struct hw_perf_event *hwc = &event->hw;
struct hws_trailer_entry *te; struct hws_trailer_entry *te;
unsigned long *sdbt; unsigned long *sdbt;
unsigned long long event_overflow, sampl_overflow, num_sdb, te_flags;
int done; int done;
/* /*
...@@ -1266,25 +1278,25 @@ static void hw_perf_event_update(struct perf_event *event, int flush_all) ...@@ -1266,25 +1278,25 @@ static void hw_perf_event_update(struct perf_event *event, int flush_all)
te = (struct hws_trailer_entry *) trailer_entry_ptr(*sdbt); te = (struct hws_trailer_entry *) trailer_entry_ptr(*sdbt);
/* Leave loop if no more work to do (block full indicator) */ /* Leave loop if no more work to do (block full indicator) */
if (!te->f) { if (!te->header.f) {
done = 1; done = 1;
if (!flush_all) if (!flush_all)
break; break;
} }
/* Check the sample overflow count */ /* Check the sample overflow count */
if (te->overflow) if (te->header.overflow)
/* Account sample overflows and, if a particular limit /* Account sample overflows and, if a particular limit
* is reached, extend the sampling buffer. * is reached, extend the sampling buffer.
* For details, see sfb_account_overflows(). * For details, see sfb_account_overflows().
*/ */
sampl_overflow += te->overflow; sampl_overflow += te->header.overflow;
/* Timestamps are valid for full sample-data-blocks only */ /* Timestamps are valid for full sample-data-blocks only */
debug_sprintf_event(sfdbg, 6, "%s: sdbt %#lx " debug_sprintf_event(sfdbg, 6, "%s: sdbt %#lx "
"overflow %llu timestamp %#llx\n", "overflow %llu timestamp %#llx\n",
__func__, (unsigned long)sdbt, te->overflow, __func__, (unsigned long)sdbt, te->header.overflow,
(te->f) ? trailer_timestamp(te) : 0ULL); (te->header.f) ? trailer_timestamp(te) : 0ULL);
/* Collect all samples from a single sample-data-block and /* Collect all samples from a single sample-data-block and
* flag if an (perf) event overflow happened. If so, the PMU * flag if an (perf) event overflow happened. If so, the PMU
...@@ -1294,12 +1306,16 @@ static void hw_perf_event_update(struct perf_event *event, int flush_all) ...@@ -1294,12 +1306,16 @@ static void hw_perf_event_update(struct perf_event *event, int flush_all)
num_sdb++; num_sdb++;
/* Reset trailer (using compare-double-and-swap) */ /* Reset trailer (using compare-double-and-swap) */
/* READ_ONCE() 16 byte header */
prev.val = __cdsg(&te->header.val, 0, 0);
do { do {
te_flags = te->flags & ~SDB_TE_BUFFER_FULL_MASK; old.val = prev.val;
te_flags |= SDB_TE_ALERT_REQ_MASK; new.val = prev.val;
} while (!cmpxchg_double(&te->flags, &te->overflow, new.f = 0;
te->flags, te->overflow, new.a = 1;
te_flags, 0ULL)); new.overflow = 0;
prev.val = __cdsg(&te->header.val, old.val, new.val);
} while (prev.val != old.val);
/* Advance to next sample-data-block */ /* Advance to next sample-data-block */
sdbt++; sdbt++;
...@@ -1384,7 +1400,7 @@ static void aux_output_end(struct perf_output_handle *handle) ...@@ -1384,7 +1400,7 @@ static void aux_output_end(struct perf_output_handle *handle)
range_scan = AUX_SDB_NUM_ALERT(aux); range_scan = AUX_SDB_NUM_ALERT(aux);
for (i = 0, idx = aux->head; i < range_scan; i++, idx++) { for (i = 0, idx = aux->head; i < range_scan; i++, idx++) {
te = aux_sdb_trailer(aux, idx); te = aux_sdb_trailer(aux, idx);
if (!(te->flags & SDB_TE_BUFFER_FULL_MASK)) if (!te->header.f)
break; break;
} }
/* i is num of SDBs which are full */ /* i is num of SDBs which are full */
...@@ -1392,7 +1408,7 @@ static void aux_output_end(struct perf_output_handle *handle) ...@@ -1392,7 +1408,7 @@ static void aux_output_end(struct perf_output_handle *handle)
/* Remove alert indicators in the buffer */ /* Remove alert indicators in the buffer */
te = aux_sdb_trailer(aux, aux->alert_mark); te = aux_sdb_trailer(aux, aux->alert_mark);
te->flags &= ~SDB_TE_ALERT_REQ_MASK; te->header.a = 0;
debug_sprintf_event(sfdbg, 6, "%s: SDBs %ld range %ld head %ld\n", debug_sprintf_event(sfdbg, 6, "%s: SDBs %ld range %ld head %ld\n",
__func__, i, range_scan, aux->head); __func__, i, range_scan, aux->head);
...@@ -1437,9 +1453,9 @@ static int aux_output_begin(struct perf_output_handle *handle, ...@@ -1437,9 +1453,9 @@ static int aux_output_begin(struct perf_output_handle *handle,
idx = aux->empty_mark + 1; idx = aux->empty_mark + 1;
for (i = 0; i < range_scan; i++, idx++) { for (i = 0; i < range_scan; i++, idx++) {
te = aux_sdb_trailer(aux, idx); te = aux_sdb_trailer(aux, idx);
te->flags &= ~(SDB_TE_BUFFER_FULL_MASK | te->header.f = 0;
SDB_TE_ALERT_REQ_MASK); te->header.a = 0;
te->overflow = 0; te->header.overflow = 0;
} }
/* Save the position of empty SDBs */ /* Save the position of empty SDBs */
aux->empty_mark = aux->head + range - 1; aux->empty_mark = aux->head + range - 1;
...@@ -1448,7 +1464,7 @@ static int aux_output_begin(struct perf_output_handle *handle, ...@@ -1448,7 +1464,7 @@ static int aux_output_begin(struct perf_output_handle *handle,
/* Set alert indicator */ /* Set alert indicator */
aux->alert_mark = aux->head + range/2 - 1; aux->alert_mark = aux->head + range/2 - 1;
te = aux_sdb_trailer(aux, aux->alert_mark); te = aux_sdb_trailer(aux, aux->alert_mark);
te->flags = te->flags | SDB_TE_ALERT_REQ_MASK; te->header.a = 1;
/* Reset hardware buffer head */ /* Reset hardware buffer head */
head = AUX_SDB_INDEX(aux, aux->head); head = AUX_SDB_INDEX(aux, aux->head);
...@@ -1475,14 +1491,17 @@ static int aux_output_begin(struct perf_output_handle *handle, ...@@ -1475,14 +1491,17 @@ static int aux_output_begin(struct perf_output_handle *handle,
static bool aux_set_alert(struct aux_buffer *aux, unsigned long alert_index, static bool aux_set_alert(struct aux_buffer *aux, unsigned long alert_index,
unsigned long long *overflow) unsigned long long *overflow)
{ {
unsigned long long orig_overflow, orig_flags, new_flags; union hws_trailer_header old, prev, new;
struct hws_trailer_entry *te; struct hws_trailer_entry *te;
te = aux_sdb_trailer(aux, alert_index); te = aux_sdb_trailer(aux, alert_index);
/* READ_ONCE() 16 byte header */
prev.val = __cdsg(&te->header.val, 0, 0);
do { do {
orig_flags = te->flags; old.val = prev.val;
*overflow = orig_overflow = te->overflow; new.val = prev.val;
if (orig_flags & SDB_TE_BUFFER_FULL_MASK) { *overflow = old.overflow;
if (old.f) {
/* /*
* SDB is already set by hardware. * SDB is already set by hardware.
* Abort and try to set somewhere * Abort and try to set somewhere
...@@ -1490,10 +1509,10 @@ static bool aux_set_alert(struct aux_buffer *aux, unsigned long alert_index, ...@@ -1490,10 +1509,10 @@ static bool aux_set_alert(struct aux_buffer *aux, unsigned long alert_index,
*/ */
return false; return false;
} }
new_flags = orig_flags | SDB_TE_ALERT_REQ_MASK; new.a = 1;
} while (!cmpxchg_double(&te->flags, &te->overflow, new.overflow = 0;
orig_flags, orig_overflow, prev.val = __cdsg(&te->header.val, old.val, new.val);
new_flags, 0ULL)); } while (prev.val != old.val);
return true; return true;
} }
...@@ -1522,8 +1541,9 @@ static bool aux_set_alert(struct aux_buffer *aux, unsigned long alert_index, ...@@ -1522,8 +1541,9 @@ static bool aux_set_alert(struct aux_buffer *aux, unsigned long alert_index,
static bool aux_reset_buffer(struct aux_buffer *aux, unsigned long range, static bool aux_reset_buffer(struct aux_buffer *aux, unsigned long range,
unsigned long long *overflow) unsigned long long *overflow)
{ {
unsigned long long orig_overflow, orig_flags, new_flags;
unsigned long i, range_scan, idx, idx_old; unsigned long i, range_scan, idx, idx_old;
union hws_trailer_header old, prev, new;
unsigned long long orig_overflow;
struct hws_trailer_entry *te; struct hws_trailer_entry *te;
debug_sprintf_event(sfdbg, 6, "%s: range %ld head %ld alert %ld " debug_sprintf_event(sfdbg, 6, "%s: range %ld head %ld alert %ld "
...@@ -1554,17 +1574,20 @@ static bool aux_reset_buffer(struct aux_buffer *aux, unsigned long range, ...@@ -1554,17 +1574,20 @@ static bool aux_reset_buffer(struct aux_buffer *aux, unsigned long range,
idx_old = idx = aux->empty_mark + 1; idx_old = idx = aux->empty_mark + 1;
for (i = 0; i < range_scan; i++, idx++) { for (i = 0; i < range_scan; i++, idx++) {
te = aux_sdb_trailer(aux, idx); te = aux_sdb_trailer(aux, idx);
/* READ_ONCE() 16 byte header */
prev.val = __cdsg(&te->header.val, 0, 0);
do { do {
orig_flags = te->flags; old.val = prev.val;
orig_overflow = te->overflow; new.val = prev.val;
new_flags = orig_flags & ~SDB_TE_BUFFER_FULL_MASK; orig_overflow = old.overflow;
new.f = 0;
new.overflow = 0;
if (idx == aux->alert_mark) if (idx == aux->alert_mark)
new_flags |= SDB_TE_ALERT_REQ_MASK; new.a = 1;
else else
new_flags &= ~SDB_TE_ALERT_REQ_MASK; new.a = 0;
} while (!cmpxchg_double(&te->flags, &te->overflow, prev.val = __cdsg(&te->header.val, old.val, new.val);
orig_flags, orig_overflow, } while (prev.val != old.val);
new_flags, 0ULL));
*overflow += orig_overflow; *overflow += orig_overflow;
} }
......
...@@ -17,6 +17,8 @@ ...@@ -17,6 +17,8 @@
/* Handle ro_after_init data on our own. */ /* Handle ro_after_init data on our own. */
#define RO_AFTER_INIT_DATA #define RO_AFTER_INIT_DATA
#define RUNTIME_DISCARD_EXIT
#define EMITS_PT_NOTE #define EMITS_PT_NOTE
#include <asm-generic/vmlinux.lds.h> #include <asm-generic/vmlinux.lds.h>
...@@ -79,6 +81,7 @@ SECTIONS ...@@ -79,6 +81,7 @@ SECTIONS
_end_amode31_refs = .; _end_amode31_refs = .;
} }
. = ALIGN(PAGE_SIZE);
_edata = .; /* End of data section */ _edata = .; /* End of data section */
/* will be freed after init */ /* will be freed after init */
...@@ -193,6 +196,7 @@ SECTIONS ...@@ -193,6 +196,7 @@ SECTIONS
BSS_SECTION(PAGE_SIZE, 4 * PAGE_SIZE, PAGE_SIZE) BSS_SECTION(PAGE_SIZE, 4 * PAGE_SIZE, PAGE_SIZE)
. = ALIGN(PAGE_SIZE);
_end = . ; _end = . ;
/* /*
......
...@@ -83,8 +83,9 @@ static int sca_inject_ext_call(struct kvm_vcpu *vcpu, int src_id) ...@@ -83,8 +83,9 @@ static int sca_inject_ext_call(struct kvm_vcpu *vcpu, int src_id)
struct esca_block *sca = vcpu->kvm->arch.sca; struct esca_block *sca = vcpu->kvm->arch.sca;
union esca_sigp_ctrl *sigp_ctrl = union esca_sigp_ctrl *sigp_ctrl =
&(sca->cpu[vcpu->vcpu_id].sigp_ctrl); &(sca->cpu[vcpu->vcpu_id].sigp_ctrl);
union esca_sigp_ctrl new_val = {0}, old_val = *sigp_ctrl; union esca_sigp_ctrl new_val = {0}, old_val;
old_val = READ_ONCE(*sigp_ctrl);
new_val.scn = src_id; new_val.scn = src_id;
new_val.c = 1; new_val.c = 1;
old_val.c = 0; old_val.c = 0;
...@@ -95,8 +96,9 @@ static int sca_inject_ext_call(struct kvm_vcpu *vcpu, int src_id) ...@@ -95,8 +96,9 @@ static int sca_inject_ext_call(struct kvm_vcpu *vcpu, int src_id)
struct bsca_block *sca = vcpu->kvm->arch.sca; struct bsca_block *sca = vcpu->kvm->arch.sca;
union bsca_sigp_ctrl *sigp_ctrl = union bsca_sigp_ctrl *sigp_ctrl =
&(sca->cpu[vcpu->vcpu_id].sigp_ctrl); &(sca->cpu[vcpu->vcpu_id].sigp_ctrl);
union bsca_sigp_ctrl new_val = {0}, old_val = *sigp_ctrl; union bsca_sigp_ctrl new_val = {0}, old_val;
old_val = READ_ONCE(*sigp_ctrl);
new_val.scn = src_id; new_val.scn = src_id;
new_val.c = 1; new_val.c = 1;
old_val.c = 0; old_val.c = 0;
...@@ -126,16 +128,18 @@ static void sca_clear_ext_call(struct kvm_vcpu *vcpu) ...@@ -126,16 +128,18 @@ static void sca_clear_ext_call(struct kvm_vcpu *vcpu)
struct esca_block *sca = vcpu->kvm->arch.sca; struct esca_block *sca = vcpu->kvm->arch.sca;
union esca_sigp_ctrl *sigp_ctrl = union esca_sigp_ctrl *sigp_ctrl =
&(sca->cpu[vcpu->vcpu_id].sigp_ctrl); &(sca->cpu[vcpu->vcpu_id].sigp_ctrl);
union esca_sigp_ctrl old = *sigp_ctrl; union esca_sigp_ctrl old;
old = READ_ONCE(*sigp_ctrl);
expect = old.value; expect = old.value;
rc = cmpxchg(&sigp_ctrl->value, old.value, 0); rc = cmpxchg(&sigp_ctrl->value, old.value, 0);
} else { } else {
struct bsca_block *sca = vcpu->kvm->arch.sca; struct bsca_block *sca = vcpu->kvm->arch.sca;
union bsca_sigp_ctrl *sigp_ctrl = union bsca_sigp_ctrl *sigp_ctrl =
&(sca->cpu[vcpu->vcpu_id].sigp_ctrl); &(sca->cpu[vcpu->vcpu_id].sigp_ctrl);
union bsca_sigp_ctrl old = *sigp_ctrl; union bsca_sigp_ctrl old;
old = READ_ONCE(*sigp_ctrl);
expect = old.value; expect = old.value;
rc = cmpxchg(&sigp_ctrl->value, old.value, 0); rc = cmpxchg(&sigp_ctrl->value, old.value, 0);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment