Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

+107 -73
+2 -2
arch/s390/boot/decompressor.c
··· 23 23 #define memmove memmove 24 24 #define memzero(s, n) memset((s), 0, (n)) 25 25 26 - #ifdef CONFIG_KERNEL_BZIP2 26 + #if defined(CONFIG_KERNEL_BZIP2) 27 27 #define BOOT_HEAP_SIZE 0x400000 28 - #elif CONFIG_KERNEL_ZSTD 28 + #elif defined(CONFIG_KERNEL_ZSTD) 29 29 #define BOOT_HEAP_SIZE 0x30000 30 30 #else 31 31 #define BOOT_HEAP_SIZE 0x10000
+4 -3
arch/s390/configs/debug_defconfig
··· 190 190 CONFIG_NFT_LOG=m 191 191 CONFIG_NFT_LIMIT=m 192 192 CONFIG_NFT_NAT=m 193 - CONFIG_NFT_OBJREF=m 194 193 CONFIG_NFT_REJECT=m 195 194 CONFIG_NFT_COMPAT=m 196 195 CONFIG_NFT_HASH=m ··· 568 569 # CONFIG_INPUT_MOUSE is not set 569 570 # CONFIG_SERIO is not set 570 571 CONFIG_LEGACY_PTY_COUNT=0 572 + # CONFIG_LEGACY_TIOCSTI is not set 571 573 CONFIG_VIRTIO_CONSOLE=m 572 574 CONFIG_HW_RANDOM_VIRTIO=m 573 575 CONFIG_HANGCHECK_TIMER=m ··· 660 660 CONFIG_ECRYPT_FS=m 661 661 CONFIG_CRAMFS=m 662 662 CONFIG_SQUASHFS=m 663 + CONFIG_SQUASHFS_CHOICE_DECOMP_BY_MOUNT=y 663 664 CONFIG_SQUASHFS_XATTR=y 664 665 CONFIG_SQUASHFS_LZ4=y 665 666 CONFIG_SQUASHFS_LZO=y ··· 706 705 CONFIG_SECURITY_LANDLOCK=y 707 706 CONFIG_INTEGRITY_SIGNATURE=y 708 707 CONFIG_INTEGRITY_ASYMMETRIC_KEYS=y 708 + CONFIG_INTEGRITY_PLATFORM_KEYRING=y 709 709 CONFIG_IMA=y 710 710 CONFIG_IMA_DEFAULT_HASH_SHA256=y 711 711 CONFIG_IMA_WRITE_POLICY=y ··· 783 781 CONFIG_PKEY=m 784 782 CONFIG_CRYPTO_PAES_S390=m 785 783 CONFIG_CRYPTO_DEV_VIRTIO=m 784 + CONFIG_SYSTEM_BLACKLIST_KEYRING=y 786 785 CONFIG_CORDIC=m 787 786 CONFIG_CRYPTO_LIB_CURVE25519=m 788 787 CONFIG_CRYPTO_LIB_CHACHA20POLY1305=m ··· 851 848 CONFIG_SCHED_TRACER=y 852 849 CONFIG_FTRACE_SYSCALLS=y 853 850 CONFIG_BLK_DEV_IO_TRACE=y 854 - CONFIG_BPF_KPROBE_OVERRIDE=y 855 851 CONFIG_HIST_TRIGGERS=y 856 852 CONFIG_FTRACE_STARTUP_TEST=y 857 853 # CONFIG_EVENT_TRACE_STARTUP_TEST is not set ··· 872 870 CONFIG_FAIL_IO_TIMEOUT=y 873 871 CONFIG_FAIL_FUTEX=y 874 872 CONFIG_FAULT_INJECTION_DEBUG_FS=y 875 - CONFIG_FAIL_FUNCTION=y 876 873 CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y 877 874 CONFIG_LKDTM=m 878 875 CONFIG_TEST_MIN_HEAP=y
+4 -2
arch/s390/configs/defconfig
··· 181 181 CONFIG_NFT_LOG=m 182 182 CONFIG_NFT_LIMIT=m 183 183 CONFIG_NFT_NAT=m 184 - CONFIG_NFT_OBJREF=m 185 184 CONFIG_NFT_REJECT=m 186 185 CONFIG_NFT_COMPAT=m 187 186 CONFIG_NFT_HASH=m ··· 558 559 # CONFIG_INPUT_MOUSE is not set 559 560 # CONFIG_SERIO is not set 560 561 CONFIG_LEGACY_PTY_COUNT=0 562 + # CONFIG_LEGACY_TIOCSTI is not set 561 563 CONFIG_VIRTIO_CONSOLE=m 562 564 CONFIG_HW_RANDOM_VIRTIO=m 563 565 CONFIG_HANGCHECK_TIMER=m ··· 645 645 CONFIG_ECRYPT_FS=m 646 646 CONFIG_CRAMFS=m 647 647 CONFIG_SQUASHFS=m 648 + CONFIG_SQUASHFS_CHOICE_DECOMP_BY_MOUNT=y 648 649 CONFIG_SQUASHFS_XATTR=y 649 650 CONFIG_SQUASHFS_LZ4=y 650 651 CONFIG_SQUASHFS_LZO=y ··· 689 688 CONFIG_SECURITY_LANDLOCK=y 690 689 CONFIG_INTEGRITY_SIGNATURE=y 691 690 CONFIG_INTEGRITY_ASYMMETRIC_KEYS=y 691 + CONFIG_INTEGRITY_PLATFORM_KEYRING=y 692 692 CONFIG_IMA=y 693 693 CONFIG_IMA_DEFAULT_HASH_SHA256=y 694 694 CONFIG_IMA_WRITE_POLICY=y ··· 768 766 CONFIG_PKEY=m 769 767 CONFIG_CRYPTO_PAES_S390=m 770 768 CONFIG_CRYPTO_DEV_VIRTIO=m 769 + CONFIG_SYSTEM_BLACKLIST_KEYRING=y 771 770 CONFIG_CORDIC=m 772 771 CONFIG_PRIME_NUMBERS=m 773 772 CONFIG_CRYPTO_LIB_CURVE25519=m ··· 801 798 CONFIG_SCHED_TRACER=y 802 799 CONFIG_FTRACE_SYSCALLS=y 803 800 CONFIG_BLK_DEV_IO_TRACE=y 804 - CONFIG_BPF_KPROBE_OVERRIDE=y 805 801 CONFIG_HIST_TRIGGERS=y 806 802 CONFIG_SAMPLES=y 807 803 CONFIG_SAMPLE_TRACE_PRINTK=m
+1 -1
arch/s390/configs/zfcpdump_defconfig
··· 13 13 # CONFIG_COMPAT is not set 14 14 CONFIG_NR_CPUS=2 15 15 CONFIG_HZ_100=y 16 - # CONFIG_RELOCATABLE is not set 17 16 # CONFIG_CHSC_SCH is not set 18 17 # CONFIG_SCM_BUS is not set 19 18 CONFIG_CRASH_DUMP=y ··· 49 50 # CONFIG_INPUT_KEYBOARD is not set 50 51 # CONFIG_INPUT_MOUSE is not set 51 52 # CONFIG_SERIO is not set 53 + # CONFIG_LEGACY_TIOCSTI is not set 52 54 # CONFIG_HVC_IUCV is not set 53 55 # CONFIG_HW_RANDOM_S390 is not set 54 56 # CONFIG_HMC_DRV is not set
+15 -16
arch/s390/include/asm/cpu_mf.h
··· 131 131 struct hws_diag_entry diag; /* Diagnostic-sampling data entry */ 132 132 } __packed; 133 133 134 - struct hws_trailer_entry { 135 - union { 136 - struct { 137 - unsigned int f:1; /* 0 - Block Full Indicator */ 138 - unsigned int a:1; /* 1 - Alert request control */ 139 - unsigned int t:1; /* 2 - Timestamp format */ 140 - unsigned int :29; /* 3 - 31: Reserved */ 141 - unsigned int bsdes:16; /* 32-47: size of basic SDE */ 142 - unsigned int dsdes:16; /* 48-63: size of diagnostic SDE */ 143 - }; 144 - unsigned long long flags; /* 0 - 63: All indicators */ 134 + union hws_trailer_header { 135 + struct { 136 + unsigned int f:1; /* 0 - Block Full Indicator */ 137 + unsigned int a:1; /* 1 - Alert request control */ 138 + unsigned int t:1; /* 2 - Timestamp format */ 139 + unsigned int :29; /* 3 - 31: Reserved */ 140 + unsigned int bsdes:16; /* 32-47: size of basic SDE */ 141 + unsigned int dsdes:16; /* 48-63: size of diagnostic SDE */ 142 + unsigned long long overflow; /* 64 - Overflow Count */ 145 143 }; 146 - unsigned long long overflow; /* 64 - sample Overflow count */ 144 + __uint128_t val; 145 + }; 146 + 147 + struct hws_trailer_entry { 148 + union hws_trailer_header header; /* 0 - 15 Flags + Overflow Count */ 147 149 unsigned char timestamp[16]; /* 16 - 31 timestamp */ 148 150 unsigned long long reserved1; /* 32 -Reserved */ 149 151 unsigned long long reserved2; /* */ ··· 292 290 return USEC_PER_SEC * qsi->cpu_speed / rate; 293 291 } 294 292 295 - #define SDB_TE_ALERT_REQ_MASK 0x4000000000000000UL 296 - #define SDB_TE_BUFFER_FULL_MASK 0x8000000000000000UL 297 - 298 293 /* Return TOD timestamp contained in an trailer entry */ 299 294 static inline unsigned long long trailer_timestamp(struct hws_trailer_entry *te) 300 295 { 301 296 /* TOD in STCKE format */ 302 - if (te->t) 297 + if (te->header.t) 303 298 return *((unsigned long long *) &te->timestamp[1]); 304 299 305 300 /* TOD in STCK format */
+3 -3
arch/s390/include/asm/debug.h
··· 4 4 * 5 5 * Copyright IBM Corp. 1999, 2020 6 6 */ 7 - #ifndef DEBUG_H 8 - #define DEBUG_H 7 + #ifndef _ASM_S390_DEBUG_H 8 + #define _ASM_S390_DEBUG_H 9 9 10 10 #include <linux/string.h> 11 11 #include <linux/spinlock.h> ··· 487 487 488 488 #endif /* MODULE */ 489 489 490 - #endif /* DEBUG_H */ 490 + #endif /* _ASM_S390_DEBUG_H */
+1 -1
arch/s390/include/asm/percpu.h
··· 31 31 pcp_op_T__ *ptr__; \ 32 32 preempt_disable_notrace(); \ 33 33 ptr__ = raw_cpu_ptr(&(pcp)); \ 34 - prev__ = *ptr__; \ 34 + prev__ = READ_ONCE(*ptr__); \ 35 35 do { \ 36 36 old__ = prev__; \ 37 37 new__ = old__ op (val); \
+3 -2
arch/s390/kernel/machine_kexec_file.c
··· 187 187 188 188 data->memsz = ALIGN(data->memsz, PAGE_SIZE); 189 189 buf.mem = data->memsz; 190 - if (image->type == KEXEC_TYPE_CRASH) 191 - buf.mem += crashk_res.start; 192 190 193 191 ptr = (void *)ipl_cert_list_addr; 194 192 end = ptr + ipl_cert_list_size; ··· 222 224 lc_ipl_parmblock_ptr = 223 225 data->kernel_buf + offsetof(struct lowcore, ipl_parmblock_ptr); 224 226 *lc_ipl_parmblock_ptr = (__u32)buf.mem; 227 + 228 + if (image->type == KEXEC_TYPE_CRASH) 229 + buf.mem += crashk_res.start; 225 230 226 231 ret = kexec_add_buffer(&buf); 227 232 out:
+62 -39
arch/s390/kernel/perf_cpum_sf.c
··· 163 163 164 164 static int alloc_sample_data_block(unsigned long *sdbt, gfp_t gfp_flags) 165 165 { 166 - unsigned long sdb, *trailer; 166 + struct hws_trailer_entry *te; 167 + unsigned long sdb; 167 168 168 169 /* Allocate and initialize sample-data-block */ 169 170 sdb = get_zeroed_page(gfp_flags); 170 171 if (!sdb) 171 172 return -ENOMEM; 172 - trailer = trailer_entry_ptr(sdb); 173 - *trailer = SDB_TE_ALERT_REQ_MASK; 173 + te = (struct hws_trailer_entry *)trailer_entry_ptr(sdb); 174 + te->header.a = 1; 174 175 175 176 /* Link SDB into the sample-data-block-table */ 176 177 *sdbt = sdb; ··· 1207 1206 "%s: Found unknown" 1208 1207 " sampling data entry: te->f %i" 1209 1208 " basic.def %#4x (%p)\n", __func__, 1210 - te->f, sample->def, sample); 1209 + te->header.f, sample->def, sample); 1211 1210 /* Sample slot is not yet written or other record. 1212 1211 * 1213 1212 * This condition can occur if the buffer was reused ··· 1218 1217 * that are not full. Stop processing if the first 1219 1218 * invalid format was detected. 1220 1219 */ 1221 - if (!te->f) 1220 + if (!te->header.f) 1222 1221 break; 1223 1222 } 1224 1223 ··· 1226 1225 sample->def = 0; 1227 1226 sample++; 1228 1227 } 1228 + } 1229 + 1230 + static inline __uint128_t __cdsg(__uint128_t *ptr, __uint128_t old, __uint128_t new) 1231 + { 1232 + asm volatile( 1233 + " cdsg %[old],%[new],%[ptr]\n" 1234 + : [old] "+d" (old), [ptr] "+QS" (*ptr) 1235 + : [new] "d" (new) 1236 + : "memory", "cc"); 1237 + return old; 1229 1238 } 1230 1239 1231 1240 /* hw_perf_event_update() - Process sampling buffer ··· 1254 1243 */ 1255 1244 static void hw_perf_event_update(struct perf_event *event, int flush_all) 1256 1245 { 1246 + unsigned long long event_overflow, sampl_overflow, num_sdb; 1247 + union hws_trailer_header old, prev, new; 1257 1248 struct hw_perf_event *hwc = &event->hw; 1258 1249 struct hws_trailer_entry *te; 1259 1250 unsigned long *sdbt; 1260 - unsigned long long event_overflow, sampl_overflow, num_sdb, te_flags; 1261 1251 int done; 1262 1252 1263 1253 /* ··· 1278 1266 te = (struct hws_trailer_entry *) trailer_entry_ptr(*sdbt); 1279 1267 1280 1268 /* Leave loop if no more work to do (block full indicator) */ 1281 - if (!te->f) { 1269 + if (!te->header.f) { 1282 1270 done = 1; 1283 1271 if (!flush_all) 1284 1272 break; 1285 1273 } 1286 1274 1287 1275 /* Check the sample overflow count */ 1288 - if (te->overflow) 1276 + if (te->header.overflow) 1289 1277 /* Account sample overflows and, if a particular limit 1290 1278 * is reached, extend the sampling buffer. 1291 1279 * For details, see sfb_account_overflows(). 1292 1280 */ 1293 - sampl_overflow += te->overflow; 1281 + sampl_overflow += te->header.overflow; 1294 1282 1295 1283 /* Timestamps are valid for full sample-data-blocks only */ 1296 1284 debug_sprintf_event(sfdbg, 6, "%s: sdbt %#lx " 1297 1285 "overflow %llu timestamp %#llx\n", 1298 - __func__, (unsigned long)sdbt, te->overflow, 1299 - (te->f) ? trailer_timestamp(te) : 0ULL); 1286 + __func__, (unsigned long)sdbt, te->header.overflow, 1287 + (te->header.f) ? trailer_timestamp(te) : 0ULL); 1300 1288 1301 1289 /* Collect all samples from a single sample-data-block and 1302 1290 * flag if an (perf) event overflow happened. If so, the PMU ··· 1306 1294 num_sdb++; 1307 1295 1308 1296 /* Reset trailer (using compare-double-and-swap) */ 1297 + /* READ_ONCE() 16 byte header */ 1298 + prev.val = __cdsg(&te->header.val, 0, 0); 1309 1299 do { 1310 - te_flags = te->flags & ~SDB_TE_BUFFER_FULL_MASK; 1311 - te_flags |= SDB_TE_ALERT_REQ_MASK; 1312 - } while (!cmpxchg_double(&te->flags, &te->overflow, 1313 - te->flags, te->overflow, 1314 - te_flags, 0ULL)); 1300 + old.val = prev.val; 1301 + new.val = prev.val; 1302 + new.f = 0; 1303 + new.a = 1; 1304 + new.overflow = 0; 1305 + prev.val = __cdsg(&te->header.val, old.val, new.val); 1306 + } while (prev.val != old.val); 1315 1307 1316 1308 /* Advance to next sample-data-block */ 1317 1309 sdbt++; ··· 1400 1384 range_scan = AUX_SDB_NUM_ALERT(aux); 1401 1385 for (i = 0, idx = aux->head; i < range_scan; i++, idx++) { 1402 1386 te = aux_sdb_trailer(aux, idx); 1403 - if (!(te->flags & SDB_TE_BUFFER_FULL_MASK)) 1387 + if (!te->header.f) 1404 1388 break; 1405 1389 } 1406 1390 /* i is num of SDBs which are full */ ··· 1408 1392 1409 1393 /* Remove alert indicators in the buffer */ 1410 1394 te = aux_sdb_trailer(aux, aux->alert_mark); 1411 - te->flags &= ~SDB_TE_ALERT_REQ_MASK; 1395 + te->header.a = 0; 1412 1396 1413 1397 debug_sprintf_event(sfdbg, 6, "%s: SDBs %ld range %ld head %ld\n", 1414 1398 __func__, i, range_scan, aux->head); ··· 1453 1437 idx = aux->empty_mark + 1; 1454 1438 for (i = 0; i < range_scan; i++, idx++) { 1455 1439 te = aux_sdb_trailer(aux, idx); 1456 - te->flags &= ~(SDB_TE_BUFFER_FULL_MASK | 1457 - SDB_TE_ALERT_REQ_MASK); 1458 - te->overflow = 0; 1440 + te->header.f = 0; 1441 + te->header.a = 0; 1442 + te->header.overflow = 0; 1459 1443 } 1460 1444 /* Save the position of empty SDBs */ 1461 1445 aux->empty_mark = aux->head + range - 1; ··· 1464 1448 /* Set alert indicator */ 1465 1449 aux->alert_mark = aux->head + range/2 - 1; 1466 1450 te = aux_sdb_trailer(aux, aux->alert_mark); 1467 - te->flags = te->flags | SDB_TE_ALERT_REQ_MASK; 1451 + te->header.a = 1; 1468 1452 1469 1453 /* Reset hardware buffer head */ 1470 1454 head = AUX_SDB_INDEX(aux, aux->head); ··· 1491 1475 static bool aux_set_alert(struct aux_buffer *aux, unsigned long alert_index, 1492 1476 unsigned long long *overflow) 1493 1477 { 1494 - unsigned long long orig_overflow, orig_flags, new_flags; 1478 + union hws_trailer_header old, prev, new; 1495 1479 struct hws_trailer_entry *te; 1496 1480 1497 1481 te = aux_sdb_trailer(aux, alert_index); 1482 + /* READ_ONCE() 16 byte header */ 1483 + prev.val = __cdsg(&te->header.val, 0, 0); 1498 1484 do { 1499 - orig_flags = te->flags; 1500 - *overflow = orig_overflow = te->overflow; 1501 - if (orig_flags & SDB_TE_BUFFER_FULL_MASK) { 1485 + old.val = prev.val; 1486 + new.val = prev.val; 1487 + *overflow = old.overflow; 1488 + if (old.f) { 1502 1489 /* 1503 1490 * SDB is already set by hardware. 1504 1491 * Abort and try to set somewhere ··· 1509 1490 */ 1510 1491 return false; 1511 1492 } 1512 - new_flags = orig_flags | SDB_TE_ALERT_REQ_MASK; 1513 - } while (!cmpxchg_double(&te->flags, &te->overflow, 1514 - orig_flags, orig_overflow, 1515 - new_flags, 0ULL)); 1493 + new.a = 1; 1494 + new.overflow = 0; 1495 + prev.val = __cdsg(&te->header.val, old.val, new.val); 1496 + } while (prev.val != old.val); 1516 1497 return true; 1517 1498 } 1518 1499 ··· 1541 1522 static bool aux_reset_buffer(struct aux_buffer *aux, unsigned long range, 1542 1523 unsigned long long *overflow) 1543 1524 { 1544 - unsigned long long orig_overflow, orig_flags, new_flags; 1545 1525 unsigned long i, range_scan, idx, idx_old; 1526 + union hws_trailer_header old, prev, new; 1527 + unsigned long long orig_overflow; 1546 1528 struct hws_trailer_entry *te; 1547 1529 1548 1530 debug_sprintf_event(sfdbg, 6, "%s: range %ld head %ld alert %ld " ··· 1574 1554 idx_old = idx = aux->empty_mark + 1; 1575 1555 for (i = 0; i < range_scan; i++, idx++) { 1576 1556 te = aux_sdb_trailer(aux, idx); 1557 + /* READ_ONCE() 16 byte header */ 1558 + prev.val = __cdsg(&te->header.val, 0, 0); 1577 1559 do { 1578 - orig_flags = te->flags; 1579 - orig_overflow = te->overflow; 1580 - new_flags = orig_flags & ~SDB_TE_BUFFER_FULL_MASK; 1560 + old.val = prev.val; 1561 + new.val = prev.val; 1562 + orig_overflow = old.overflow; 1563 + new.f = 0; 1564 + new.overflow = 0; 1581 1565 if (idx == aux->alert_mark) 1582 - new_flags |= SDB_TE_ALERT_REQ_MASK; 1566 + new.a = 1; 1583 1567 else 1584 - new_flags &= ~SDB_TE_ALERT_REQ_MASK; 1585 - } while (!cmpxchg_double(&te->flags, &te->overflow, 1586 - orig_flags, orig_overflow, 1587 - new_flags, 0ULL)); 1568 + new.a = 0; 1569 + prev.val = __cdsg(&te->header.val, old.val, new.val); 1570 + } while (prev.val != old.val); 1588 1571 *overflow += orig_overflow; 1589 1572 } 1590 1573
+4
arch/s390/kernel/vmlinux.lds.S
··· 17 17 /* Handle ro_after_init data on our own. */ 18 18 #define RO_AFTER_INIT_DATA 19 19 20 + #define RUNTIME_DISCARD_EXIT 21 + 20 22 #define EMITS_PT_NOTE 21 23 22 24 #include <asm-generic/vmlinux.lds.h> ··· 81 79 _end_amode31_refs = .; 82 80 } 83 81 82 + . = ALIGN(PAGE_SIZE); 84 83 _edata = .; /* End of data section */ 85 84 86 85 /* will be freed after init */ ··· 196 193 197 194 BSS_SECTION(PAGE_SIZE, 4 * PAGE_SIZE, PAGE_SIZE) 198 195 196 + . = ALIGN(PAGE_SIZE); 199 197 _end = . ; 200 198 201 199 /*
+8 -4
arch/s390/kvm/interrupt.c
··· 83 83 struct esca_block *sca = vcpu->kvm->arch.sca; 84 84 union esca_sigp_ctrl *sigp_ctrl = 85 85 &(sca->cpu[vcpu->vcpu_id].sigp_ctrl); 86 - union esca_sigp_ctrl new_val = {0}, old_val = *sigp_ctrl; 86 + union esca_sigp_ctrl new_val = {0}, old_val; 87 87 88 + old_val = READ_ONCE(*sigp_ctrl); 88 89 new_val.scn = src_id; 89 90 new_val.c = 1; 90 91 old_val.c = 0; ··· 96 95 struct bsca_block *sca = vcpu->kvm->arch.sca; 97 96 union bsca_sigp_ctrl *sigp_ctrl = 98 97 &(sca->cpu[vcpu->vcpu_id].sigp_ctrl); 99 - union bsca_sigp_ctrl new_val = {0}, old_val = *sigp_ctrl; 98 + union bsca_sigp_ctrl new_val = {0}, old_val; 100 99 100 + old_val = READ_ONCE(*sigp_ctrl); 101 101 new_val.scn = src_id; 102 102 new_val.c = 1; 103 103 old_val.c = 0; ··· 128 126 struct esca_block *sca = vcpu->kvm->arch.sca; 129 127 union esca_sigp_ctrl *sigp_ctrl = 130 128 &(sca->cpu[vcpu->vcpu_id].sigp_ctrl); 131 - union esca_sigp_ctrl old = *sigp_ctrl; 129 + union esca_sigp_ctrl old; 132 130 131 + old = READ_ONCE(*sigp_ctrl); 133 132 expect = old.value; 134 133 rc = cmpxchg(&sigp_ctrl->value, old.value, 0); 135 134 } else { 136 135 struct bsca_block *sca = vcpu->kvm->arch.sca; 137 136 union bsca_sigp_ctrl *sigp_ctrl = 138 137 &(sca->cpu[vcpu->vcpu_id].sigp_ctrl); 139 - union bsca_sigp_ctrl old = *sigp_ctrl; 138 + union bsca_sigp_ctrl old; 140 139 140 + old = READ_ONCE(*sigp_ctrl); 141 141 expect = old.value; 142 142 rc = cmpxchg(&sigp_ctrl->value, old.value, 0); 143 143 }