Merge tag 's390-6.2-2' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 12 Jan 2023 23:09:20 +0000 (17:09 -0600)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 12 Jan 2023 23:09:20 +0000 (17:09 -0600)
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

arch/s390/boot/decompressor.c
arch/s390/configs/debug_defconfig
arch/s390/configs/defconfig
arch/s390/configs/zfcpdump_defconfig
arch/s390/include/asm/cpu_mf.h
arch/s390/include/asm/debug.h
arch/s390/include/asm/percpu.h
arch/s390/kernel/machine_kexec_file.c
arch/s390/kernel/perf_cpum_sf.c
arch/s390/kernel/vmlinux.lds.S
arch/s390/kvm/interrupt.c

index e27c214..8dcd7af 100644 (file)
@@ -23,9 +23,9 @@
 #define memmove memmove
 #define memzero(s, n) memset((s), 0, (n))
 
-#ifdef CONFIG_KERNEL_BZIP2
+#if defined(CONFIG_KERNEL_BZIP2)
 #define BOOT_HEAP_SIZE 0x400000
-#elif CONFIG_KERNEL_ZSTD
+#elif defined(CONFIG_KERNEL_ZSTD)
 #define BOOT_HEAP_SIZE 0x30000
 #else
 #define BOOT_HEAP_SIZE 0x10000
index a7b4e1d..74b35ec 100644 (file)
@@ -190,7 +190,6 @@ CONFIG_NFT_CT=m
 CONFIG_NFT_LOG=m
 CONFIG_NFT_LIMIT=m
 CONFIG_NFT_NAT=m
-CONFIG_NFT_OBJREF=m
 CONFIG_NFT_REJECT=m
 CONFIG_NFT_COMPAT=m
 CONFIG_NFT_HASH=m
@@ -569,6 +568,7 @@ CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
 CONFIG_LEGACY_PTY_COUNT=0
+# CONFIG_LEGACY_TIOCSTI is not set
 CONFIG_VIRTIO_CONSOLE=m
 CONFIG_HW_RANDOM_VIRTIO=m
 CONFIG_HANGCHECK_TIMER=m
@@ -660,6 +660,7 @@ CONFIG_CONFIGFS_FS=m
 CONFIG_ECRYPT_FS=m
 CONFIG_CRAMFS=m
 CONFIG_SQUASHFS=m
+CONFIG_SQUASHFS_CHOICE_DECOMP_BY_MOUNT=y
 CONFIG_SQUASHFS_XATTR=y
 CONFIG_SQUASHFS_LZ4=y
 CONFIG_SQUASHFS_LZO=y
@@ -705,6 +706,7 @@ CONFIG_SECURITY_LOCKDOWN_LSM_EARLY=y
 CONFIG_SECURITY_LANDLOCK=y
 CONFIG_INTEGRITY_SIGNATURE=y
 CONFIG_INTEGRITY_ASYMMETRIC_KEYS=y
+CONFIG_INTEGRITY_PLATFORM_KEYRING=y
 CONFIG_IMA=y
 CONFIG_IMA_DEFAULT_HASH_SHA256=y
 CONFIG_IMA_WRITE_POLICY=y
@@ -781,6 +783,7 @@ CONFIG_ZCRYPT=m
 CONFIG_PKEY=m
 CONFIG_CRYPTO_PAES_S390=m
 CONFIG_CRYPTO_DEV_VIRTIO=m
+CONFIG_SYSTEM_BLACKLIST_KEYRING=y
 CONFIG_CORDIC=m
 CONFIG_CRYPTO_LIB_CURVE25519=m
 CONFIG_CRYPTO_LIB_CHACHA20POLY1305=m
@@ -848,7 +851,6 @@ CONFIG_PREEMPT_TRACER=y
 CONFIG_SCHED_TRACER=y
 CONFIG_FTRACE_SYSCALLS=y
 CONFIG_BLK_DEV_IO_TRACE=y
-CONFIG_BPF_KPROBE_OVERRIDE=y
 CONFIG_HIST_TRIGGERS=y
 CONFIG_FTRACE_STARTUP_TEST=y
 # CONFIG_EVENT_TRACE_STARTUP_TEST is not set
@@ -870,7 +872,6 @@ CONFIG_FAIL_MAKE_REQUEST=y
 CONFIG_FAIL_IO_TIMEOUT=y
 CONFIG_FAIL_FUTEX=y
 CONFIG_FAULT_INJECTION_DEBUG_FS=y
-CONFIG_FAIL_FUNCTION=y
 CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y
 CONFIG_LKDTM=m
 CONFIG_TEST_MIN_HEAP=y
index 2bc2d0f..cec7126 100644 (file)
@@ -181,7 +181,6 @@ CONFIG_NFT_CT=m
 CONFIG_NFT_LOG=m
 CONFIG_NFT_LIMIT=m
 CONFIG_NFT_NAT=m
-CONFIG_NFT_OBJREF=m
 CONFIG_NFT_REJECT=m
 CONFIG_NFT_COMPAT=m
 CONFIG_NFT_HASH=m
@@ -559,6 +558,7 @@ CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
 CONFIG_LEGACY_PTY_COUNT=0
+# CONFIG_LEGACY_TIOCSTI is not set
 CONFIG_VIRTIO_CONSOLE=m
 CONFIG_HW_RANDOM_VIRTIO=m
 CONFIG_HANGCHECK_TIMER=m
@@ -645,6 +645,7 @@ CONFIG_CONFIGFS_FS=m
 CONFIG_ECRYPT_FS=m
 CONFIG_CRAMFS=m
 CONFIG_SQUASHFS=m
+CONFIG_SQUASHFS_CHOICE_DECOMP_BY_MOUNT=y
 CONFIG_SQUASHFS_XATTR=y
 CONFIG_SQUASHFS_LZ4=y
 CONFIG_SQUASHFS_LZO=y
@@ -688,6 +689,7 @@ CONFIG_SECURITY_LOCKDOWN_LSM_EARLY=y
 CONFIG_SECURITY_LANDLOCK=y
 CONFIG_INTEGRITY_SIGNATURE=y
 CONFIG_INTEGRITY_ASYMMETRIC_KEYS=y
+CONFIG_INTEGRITY_PLATFORM_KEYRING=y
 CONFIG_IMA=y
 CONFIG_IMA_DEFAULT_HASH_SHA256=y
 CONFIG_IMA_WRITE_POLICY=y
@@ -766,6 +768,7 @@ CONFIG_ZCRYPT=m
 CONFIG_PKEY=m
 CONFIG_CRYPTO_PAES_S390=m
 CONFIG_CRYPTO_DEV_VIRTIO=m
+CONFIG_SYSTEM_BLACKLIST_KEYRING=y
 CONFIG_CORDIC=m
 CONFIG_PRIME_NUMBERS=m
 CONFIG_CRYPTO_LIB_CURVE25519=m
@@ -798,7 +801,6 @@ CONFIG_STACK_TRACER=y
 CONFIG_SCHED_TRACER=y
 CONFIG_FTRACE_SYSCALLS=y
 CONFIG_BLK_DEV_IO_TRACE=y
-CONFIG_BPF_KPROBE_OVERRIDE=y
 CONFIG_HIST_TRIGGERS=y
 CONFIG_SAMPLES=y
 CONFIG_SAMPLE_TRACE_PRINTK=m
index ae14ab0..a9c0c81 100644 (file)
@@ -13,7 +13,6 @@ CONFIG_TUNE_ZEC12=y
 # CONFIG_COMPAT is not set
 CONFIG_NR_CPUS=2
 CONFIG_HZ_100=y
-# CONFIG_RELOCATABLE is not set
 # CONFIG_CHSC_SCH is not set
 # CONFIG_SCM_BUS is not set
 CONFIG_CRASH_DUMP=y
@@ -50,6 +49,7 @@ CONFIG_ZFCP=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+# CONFIG_LEGACY_TIOCSTI is not set
 # CONFIG_HVC_IUCV is not set
 # CONFIG_HW_RANDOM_S390 is not set
 # CONFIG_HMC_DRV is not set
index feaba12..efa103b 100644 (file)
@@ -131,19 +131,21 @@ struct hws_combined_entry {
        struct hws_diag_entry   diag;   /* Diagnostic-sampling data entry */
 } __packed;
 
-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 */
-               };
-               unsigned long long flags;       /* 0 - 63: All indicators     */
+union hws_trailer_header {
+       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 overflow; /* 64 - Overflow Count   */
        };
-       unsigned long long overflow;     /* 64 - sample Overflow count        */
+       __uint128_t val;
+};
+
+struct hws_trailer_entry {
+       union hws_trailer_header header; /* 0 - 15 Flags + Overflow Count     */
        unsigned char timestamp[16];     /* 16 - 31 timestamp                 */
        unsigned long long reserved1;    /* 32 -Reserved                      */
        unsigned long long reserved2;    /*                                   */
@@ -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;
 }
 
-#define SDB_TE_ALERT_REQ_MASK  0x4000000000000000UL
-#define SDB_TE_BUFFER_FULL_MASK 0x8000000000000000UL
-
 /* Return TOD timestamp contained in an trailer entry */
 static inline unsigned long long trailer_timestamp(struct hws_trailer_entry *te)
 {
        /* TOD in STCKE format */
-       if (te->t)
+       if (te->header.t)
                return *((unsigned long long *) &te->timestamp[1]);
 
        /* TOD in STCK format */
index 77f2426..ac665b9 100644 (file)
@@ -4,8 +4,8 @@
  *
  *    Copyright IBM Corp. 1999, 2020
  */
-#ifndef DEBUG_H
-#define DEBUG_H
+#ifndef _ASM_S390_DEBUG_H
+#define _ASM_S390_DEBUG_H
 
 #include <linux/string.h>
 #include <linux/spinlock.h>
@@ -487,4 +487,4 @@ void debug_register_static(debug_info_t *id, int pages_per_area, int nr_areas);
 
 #endif /* MODULE */
 
-#endif /* DEBUG_H */
+#endif /* _ASM_S390_DEBUG_H */
index cb5fc06..081837b 100644 (file)
@@ -31,7 +31,7 @@
        pcp_op_T__ *ptr__;                                              \
        preempt_disable_notrace();                                      \
        ptr__ = raw_cpu_ptr(&(pcp));                                    \
-       prev__ = *ptr__;                                                \
+       prev__ = READ_ONCE(*ptr__);                                     \
        do {                                                            \
                old__ = prev__;                                         \
                new__ = old__ op (val);                                 \
index fc6d5f5..2df94d3 100644 (file)
@@ -187,8 +187,6 @@ static int kexec_file_add_ipl_report(struct kimage *image,
 
        data->memsz = ALIGN(data->memsz, PAGE_SIZE);
        buf.mem = data->memsz;
-       if (image->type == KEXEC_TYPE_CRASH)
-               buf.mem += crashk_res.start;
 
        ptr = (void *)ipl_cert_list_addr;
        end = ptr + ipl_cert_list_size;
@@ -225,6 +223,9 @@ static int kexec_file_add_ipl_report(struct kimage *image,
                data->kernel_buf + offsetof(struct lowcore, ipl_parmblock_ptr);
        *lc_ipl_parmblock_ptr = (__u32)buf.mem;
 
+       if (image->type == KEXEC_TYPE_CRASH)
+               buf.mem += crashk_res.start;
+
        ret = kexec_add_buffer(&buf);
 out:
        return ret;
index 332a499..ce886a0 100644 (file)
@@ -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)
 {
-       unsigned long sdb, *trailer;
+       struct hws_trailer_entry *te;
+       unsigned long sdb;
 
        /* Allocate and initialize sample-data-block */
        sdb = get_zeroed_page(gfp_flags);
        if (!sdb)
                return -ENOMEM;
-       trailer = trailer_entry_ptr(sdb);
-       *trailer = SDB_TE_ALERT_REQ_MASK;
+       te = (struct hws_trailer_entry *)trailer_entry_ptr(sdb);
+       te->header.a = 1;
 
        /* Link SDB into the sample-data-block-table */
        *sdbt = sdb;
@@ -1206,7 +1207,7 @@ static void hw_collect_samples(struct perf_event *event, unsigned long *sdbt,
                                            "%s: Found unknown"
                                            " sampling data entry: te->f %i"
                                            " 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.
                         *
                         * 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,
                         * that are not full.  Stop processing if the first
                         * invalid format was detected.
                         */
-                       if (!te->f)
+                       if (!te->header.f)
                                break;
                }
 
@@ -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
  * @event:     The perf event
  * @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,
  */
 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 hws_trailer_entry *te;
        unsigned long *sdbt;
-       unsigned long long event_overflow, sampl_overflow, num_sdb, te_flags;
        int done;
 
        /*
@@ -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);
 
                /* Leave loop if no more work to do (block full indicator) */
-               if (!te->f) {
+               if (!te->header.f) {
                        done = 1;
                        if (!flush_all)
                                break;
                }
 
                /* Check the sample overflow count */
-               if (te->overflow)
+               if (te->header.overflow)
                        /* Account sample overflows and, if a particular limit
                         * is reached, extend the sampling buffer.
                         * For details, see sfb_account_overflows().
                         */
-                       sampl_overflow += te->overflow;
+                       sampl_overflow += te->header.overflow;
 
                /* Timestamps are valid for full sample-data-blocks only */
                debug_sprintf_event(sfdbg, 6, "%s: sdbt %#lx "
                                    "overflow %llu timestamp %#llx\n",
-                                   __func__, (unsigned long)sdbt, te->overflow,
-                                   (te->f) ? trailer_timestamp(te) : 0ULL);
+                                   __func__, (unsigned long)sdbt, te->header.overflow,
+                                   (te->header.f) ? trailer_timestamp(te) : 0ULL);
 
                /* Collect all samples from a single sample-data-block and
                 * 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)
                num_sdb++;
 
                /* Reset trailer (using compare-double-and-swap) */
+               /* READ_ONCE() 16 byte header */
+               prev.val = __cdsg(&te->header.val, 0, 0);
                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));
+                       old.val = prev.val;
+                       new.val = prev.val;
+                       new.f = 0;
+                       new.a = 1;
+                       new.overflow = 0;
+                       prev.val = __cdsg(&te->header.val, old.val, new.val);
+               } while (prev.val != old.val);
 
                /* Advance to next sample-data-block */
                sdbt++;
@@ -1384,7 +1400,7 @@ static void aux_output_end(struct perf_output_handle *handle)
        range_scan = AUX_SDB_NUM_ALERT(aux);
        for (i = 0, idx = aux->head; i < range_scan; i++, idx++) {
                te = aux_sdb_trailer(aux, idx);
-               if (!(te->flags & SDB_TE_BUFFER_FULL_MASK))
+               if (!te->header.f)
                        break;
        }
        /* i is num of SDBs which are full */
@@ -1392,7 +1408,7 @@ static void aux_output_end(struct perf_output_handle *handle)
 
        /* Remove alert indicators in the buffer */
        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",
                            __func__, i, range_scan, aux->head);
@@ -1437,9 +1453,9 @@ static int aux_output_begin(struct perf_output_handle *handle,
                idx = aux->empty_mark + 1;
                for (i = 0; i < range_scan; i++, idx++) {
                        te = aux_sdb_trailer(aux, idx);
-                       te->flags &= ~(SDB_TE_BUFFER_FULL_MASK |
-                                      SDB_TE_ALERT_REQ_MASK);
-                       te->overflow = 0;
+                       te->header.f = 0;
+                       te->header.a = 0;
+                       te->header.overflow = 0;
                }
                /* Save the position of empty SDBs */
                aux->empty_mark = aux->head + range - 1;
@@ -1448,7 +1464,7 @@ static int aux_output_begin(struct perf_output_handle *handle,
        /* Set alert indicator */
        aux->alert_mark = aux->head + range/2 - 1;
        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 */
        head = AUX_SDB_INDEX(aux, aux->head);
@@ -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,
                          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;
 
        te = aux_sdb_trailer(aux, alert_index);
+       /* READ_ONCE() 16 byte header */
+       prev.val = __cdsg(&te->header.val, 0, 0);
        do {
-               orig_flags = te->flags;
-               *overflow = orig_overflow = te->overflow;
-               if (orig_flags & SDB_TE_BUFFER_FULL_MASK) {
+               old.val = prev.val;
+               new.val = prev.val;
+               *overflow = old.overflow;
+               if (old.f) {
                        /*
                         * SDB is already set by hardware.
                         * Abort and try to set somewhere
@@ -1490,10 +1509,10 @@ static bool aux_set_alert(struct aux_buffer *aux, unsigned long alert_index,
                         */
                        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.a = 1;
+               new.overflow = 0;
+               prev.val = __cdsg(&te->header.val, old.val, new.val);
+       } while (prev.val != old.val);
        return true;
 }
 
@@ -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,
                             unsigned long long *overflow)
 {
-       unsigned long long orig_overflow, orig_flags, new_flags;
        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;
 
        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,
        idx_old = idx = aux->empty_mark + 1;
        for (i = 0; i < range_scan; i++, idx++) {
                te = aux_sdb_trailer(aux, idx);
+               /* READ_ONCE() 16 byte header */
+               prev.val = __cdsg(&te->header.val, 0, 0);
                do {
-                       orig_flags = te->flags;
-                       orig_overflow = te->overflow;
-                       new_flags = orig_flags & ~SDB_TE_BUFFER_FULL_MASK;
+                       old.val = prev.val;
+                       new.val = prev.val;
+                       orig_overflow = old.overflow;
+                       new.f = 0;
+                       new.overflow = 0;
                        if (idx == aux->alert_mark)
-                               new_flags |= SDB_TE_ALERT_REQ_MASK;
+                               new.a = 1;
                        else
-                               new_flags &= ~SDB_TE_ALERT_REQ_MASK;
-               } while (!cmpxchg_double(&te->flags, &te->overflow,
-                                        orig_flags, orig_overflow,
-                                        new_flags, 0ULL));
+                               new.a = 0;
+                       prev.val = __cdsg(&te->header.val, old.val, new.val);
+               } while (prev.val != old.val);
                *overflow += orig_overflow;
        }
 
index 5ea3830..cbf9c1b 100644 (file)
@@ -17,6 +17,8 @@
 /* Handle ro_after_init data on our own. */
 #define RO_AFTER_INIT_DATA
 
+#define RUNTIME_DISCARD_EXIT
+
 #define EMITS_PT_NOTE
 
 #include <asm-generic/vmlinux.lds.h>
@@ -79,6 +81,7 @@ SECTIONS
                _end_amode31_refs = .;
        }
 
+       . = ALIGN(PAGE_SIZE);
        _edata = .;             /* End of data section */
 
        /* will be freed after init */
@@ -193,6 +196,7 @@ SECTIONS
 
        BSS_SECTION(PAGE_SIZE, 4 * PAGE_SIZE, PAGE_SIZE)
 
+       . = ALIGN(PAGE_SIZE);
        _end = . ;
 
        /*
index 1dae78d..ab26aa5 100644 (file)
@@ -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;
                union esca_sigp_ctrl *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.c = 1;
                old_val.c = 0;
@@ -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;
                union bsca_sigp_ctrl *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.c = 1;
                old_val.c = 0;
@@ -126,16 +128,18 @@ static void sca_clear_ext_call(struct kvm_vcpu *vcpu)
                struct esca_block *sca = vcpu->kvm->arch.sca;
                union esca_sigp_ctrl *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;
                rc = cmpxchg(&sigp_ctrl->value, old.value, 0);
        } else {
                struct bsca_block *sca = vcpu->kvm->arch.sca;
                union bsca_sigp_ctrl *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;
                rc = cmpxchg(&sigp_ctrl->value, old.value, 0);
        }