Skip to content

Commit 38988c3

Browse files
gerald-schaeferhcahca
authored andcommitted
s390/extmem: Add workaround for DCSS unload diag
When calling the diag for DCSS unload on a non-IPL CPU, the sclp maximum memory detection on the next IPL would falsely return the end of the previously loaded DCSS. This is because of an issue in z/VM, so work around it by always calling the diag for DCSS unload on IPL CPU 0. That CPU cannot be set offline, so the dcss_diag() call can directly be scheduled to CPU 0. The wrong maximum memory value returned by sclp would only affect KASAN kernels. When a DCSS within the falsely reported extra memory range is loaded and accessed again, it would result in a kernel crash: Unable to handle kernel pointer dereference in virtual kernel address space Failing address: 001c0000a3ffe000 TEID: 001c0000a3ffe803 Fault in home space mode while using kernel ASCE. AS:000000039955400b R2:00000003fe3b400b R3:000000037a2a8007 S:0000000000000020 Oops: 0010 ilc:3 [#1]SMP [...] CPU: 2 UID: 0 PID: 1563 Comm: mount Kdump: loaded Not tainted 6.15.0-rc5-11546-g3ea93fb3d026-dirty #7 NONE Hardware name: IBM 3931 A01 704 (z/VM 7.4.0) Krnl PSW : 0704c00180000000 000da6f2b338faf2 (kasan_check_range+0x172/0x310) R:0 T:1 IO:1 EX:1 Key:0 M:1 W:0 P:0 AS:3 CC:0 PM:0 RI:0 EA:3 Krnl GPRS: 0000000000000040 001c0000a3ffe000 000000051fff0000 0000000000001000 0000000000000000 000da6f233380ff6 00000000000001f8 0000000000000000 001c0000a3ffe200 0000000000000040 001c0000a3ffe200 0000000000000200 000003ff97a2cfa8 0000000000000000 0000000000000010 000da672b58af070 Krnl Code: 000da6f2b338fae2: 41101008 la %r1,8(%r1) 000da6f2b338fae6: eca100268064 cgrj %r10,%r1,8,000da6f2b338fb32 #000da6f2b338faec: ebe00002000c srlg %r14,%r0,2 >000da6f2b338faf2: e3b010000002 ltg %r11,0(%r1) 000da6f2b338faf8: a77400a8 brc 7,000da6f2b338fc48 000da6f2b338fafc: 41b01008 la %r11,8(%r1) 000da6f2b338fb00: b904001b lgr %r1,%r11 000da6f2b338fb04: e3a0b0000002 ltg %r10,0(%r11) Call Trace: [<000da6f2b338faf2>] kasan_check_range+0x172/0x310 [<000da6f2b3390b3c>] __asan_memcpy+0x3c/0x90 [<000da6f233380ff6>] dcssblk_submit_bio+0x3a6/0x620 [dcssblk] [<000da6f2b3eb403c>] __submit_bio+0x25c/0x4a0 [<000da6f2b3eb43bc>] __submit_bio_noacct+0x13c/0x450 [<000da6f2b3eb4bde>] submit_bio_noacct_nocheck+0x50e/0x620 [<000da6f2b34f4978>] mpage_readahead+0x318/0x3f0 [<000da6f2b31edbe6>] read_pages+0x156/0x740 [<000da6f2b31ee594>] page_cache_ra_unbounded+0x3c4/0x610 [<000da6f2b31ef094>] force_page_cache_ra+0x1f4/0x2d0 [<000da6f2b31d092e>] filemap_get_pages+0x2ce/0xaa0 [<000da6f2b31d1428>] filemap_read+0x328/0x9a0 [<000da6f2b3e9b7e8>] blkdev_read_iter+0x228/0x3b0 [<000da6f2b340f7a6>] vfs_read+0x5b6/0x7f0 [<000da6f2b34110be>] ksys_read+0x10e/0x1e0 [<000da6f2b4e7acb2>] __do_syscall+0x122/0x1f0 [<000da6f2b4e93ffe>] system_call+0x6e/0x90 Last Breaking-Event-Address: [<000da6f2b338faac>] kasan_check_range+0x12c/0x310 Kernel panic - not syncing: Fatal exception: panic_on_oops Reviewed-by: Heiko Carstens <[email protected]> Signed-off-by: Gerald Schaefer <[email protected]> Signed-off-by: Heiko Carstens <[email protected]>
1 parent 31026ed commit 38988c3

File tree

1 file changed

+16
-2
lines changed

1 file changed

+16
-2
lines changed

arch/s390/mm/extmem.c

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -530,6 +530,14 @@ segment_modify_shared (char *name, int do_nonshared)
530530
return rc;
531531
}
532532

533+
static void __dcss_diag_purge_on_cpu_0(void *data)
534+
{
535+
struct dcss_segment *seg = (struct dcss_segment *)data;
536+
unsigned long dummy;
537+
538+
dcss_diag(&purgeseg_scode, seg->dcss_name, &dummy, &dummy);
539+
}
540+
533541
/*
534542
* Decrease the use count of a DCSS segment and remove
535543
* it from the address space if nobody is using it
@@ -538,7 +546,6 @@ segment_modify_shared (char *name, int do_nonshared)
538546
void
539547
segment_unload(char *name)
540548
{
541-
unsigned long dummy;
542549
struct dcss_segment *seg;
543550

544551
if (!machine_is_vm())
@@ -556,7 +563,14 @@ segment_unload(char *name)
556563
kfree(seg->res);
557564
vmem_remove_mapping(seg->start_addr, seg->end - seg->start_addr + 1);
558565
list_del(&seg->list);
559-
dcss_diag(&purgeseg_scode, seg->dcss_name, &dummy, &dummy);
566+
/*
567+
* Workaround for z/VM issue, where calling the DCSS unload diag on
568+
* a non-IPL CPU would cause bogus sclp maximum memory detection on
569+
* next IPL.
570+
* IPL CPU 0 cannot be set offline, so the dcss_diag() call can
571+
* directly be scheduled to that CPU.
572+
*/
573+
smp_call_function_single(0, __dcss_diag_purge_on_cpu_0, seg, 1);
560574
kfree(seg);
561575
out_unlock:
562576
mutex_unlock(&dcss_lock);

0 commit comments

Comments
 (0)