s390/zcrypt: Fix kernel crash on systems without AP bus support
On systems without AP bus (e.g. KVM) the kernel crashes during init
calls when zcrypt is built-in:
kernel BUG at drivers/base/driver.c:153!
illegal operation: 0001 ilc:1 [#1] SMP
Modules linked in:
CPU: 1 PID: 1 Comm: swapper/0 Not tainted 4.2.0+ #221
task:
0000000010a40000 ti:
0000000010a48000 task.ti:
0000000010a48000
Krnl PSW :
0704c00180000000 0000000000592bd6(driver_register+0x106/0x140)
R:0 T:1 IO:1 EX:1 Key:0 M:1 W:0 P:0 AS:3 CC:0 PM:0 EA:3
0000000000000012 0000000000000000 0000000000c45328 0000000000c44e30
00000000009ef63c 000000000067f598 0000000000cf3c58 0000000000000000
000000000000007b 0000000000cb1030 0000000000000002 0000000000000000
0000000000ca8580 0000000010306700 00000000001001d8 0000000010a4bd88
Krnl Code:
0000000000592bc6:
f0b00004ebcf srp 4(12,%r0),3023(%r14),0
0000000000592bcc:
f0a0000407f4 srp 4(11,%r0),2036,0
#
0000000000592bd2:
a7f40001 brc 15,592bd4
>
0000000000592bd6:
e330d0000004 lg %r3,0(%r13)
0000000000592bdc:
c0200021edfd larl %r2,9d07d6
0000000000592be2:
c0e500126d8f brasl %r14,7e0700
0000000000592be8:
e330d0080004 lg %r3,8(%r13)
0000000000592bee:
a7f4ffab brc 15,592b44
Call Trace:
([<
00000000001001c8>] do_one_initcall+0x90/0x1d0)
[<
0000000000c6dd34>] kernel_init_freeable+0x1e4/0x2a0
[<
00000000007db53a>] kernel_init+0x2a/0x120
[<
00000000007e8ece>] kernel_thread_starter+0x6/0xc
[<
00000000007e8ec8>] kernel_thread_starter+0x0/0xc
Last Breaking-Event-Address:
[<
0000000000592bd2>] driver_register+0x102/0x140
When zcrypt is built as a module, the module loader ensures that the
driver modules cannot be loaded if the AP bus module returns an error
during initialisation. But if zcrypt and the driver are built-in, the
driver is getting initialised even if the AP bus initialisation
failed. The driver invokes ap_driver_register() during initialisation,
which then causes operations on uninitialised data structures to be
performed.
Explicitly protect ap_driver_register() by introducing an
"initialised" flag that gets set iff the AP bus initialisation was
successful. When the AP bus initialisation failed,
ap_driver_register() will error out with -ENODEV, causing the driver
initialisation to fail as well.
Test results:
1. Inside KVM (no AP bus), zcrypt built-in
Boots. /sys/bus/ap not present (expected).
2. Inside KVM (no AP bus), zcrypt as module
Boots. Loading zcrypt_cex4 fails because loading ap_bus fails
(expected).
3. On LPAR with CEX5, zcrypt built-in
Boots. /sys/bus/ap/devices/card* present but .../card*/type missing
(i.e. zcrypt_device_register() fails, unrelated issue).
4. On LPAR with CEX5, zcrypt as module
Boots. Loading zcrypt_cex4 successful,
/sys/bus/ap/devices/card*/type present. No further testing
(user-space functionality) was done.
Signed-off-by: Sascha Silbe <silbe@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>