Currently pseries_kexec_cpu_down() skips unregistering vpa, slb_shadow and
dtl areas during a crash and kexec shutdown path. It was done to avoid
doing an HCALL while crashing. However recently Anushree reported that
during kernel crash while the kdump kernel was coming up, Hypervisor
reported invalid values for 'vpa.yield_count' while it dispatching L2-KVM
Guest vcpus. The error manifested as debug build Hypervisor assert
triggering to indicate possible VPA corruption.

Looking at the kexec cpu offline path it was discovered that during crash
kernel doesn't unregister the VPA/SLB-Shadow/DTL area with
Hypervisor. Instead it re-allocates and re-registers these areas
for cpus during boot. During kexec boot the previously allocated areas
can get overwritten with new content without hypervisor knowledge. This
creates a small window where while kexec kernel boots and the L2-VCPUs are
being dispatched, Hypervisor may try to read/write to a wrong memory area
which previously belonged to older VPA.

Fix this possible race and memory corruption by updating
pseries_kexec_cpu_down() to also unregister vpa,slb_shadow & dtl areas
during a kernel crash.

Signed-off-by: Vaibhav Jain <[email protected]>
Tested-by: Anushree Mathur <[email protected]>
---
 arch/powerpc/platforms/pseries/kexec.c | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/arch/powerpc/platforms/pseries/kexec.c 
b/arch/powerpc/platforms/pseries/kexec.c
index 431be156ca9b..29f7c97ff193 100644
--- a/arch/powerpc/platforms/pseries/kexec.c
+++ b/arch/powerpc/platforms/pseries/kexec.c
@@ -20,12 +20,15 @@
 void pseries_kexec_cpu_down(int crash_shutdown, int secondary)
 {
        /*
-        * Don't risk a hypervisor call if we're crashing
-        * XXX: Why? The hypervisor is not crashing. It might be better
-        * to at least attempt unregister to avoid the hypervisor stepping
-        * on our memory.
+        * Ensure vpa/slb_shadow/dtl cleanup even while we are crashing.
+        * Why? The hypervisor is not crashing so at least attempt unregister to
+        * avoid the hypervisor stepping on our memory. If hypervisor or kexec
+        * kernel steps on the old memory allocated to these areas before the
+        * new kexec-kernel happens to allocate and register new areas,
+        * the hypervisor will see invalid content which may cause
+        * unexpected behavior.
         */
-       if (firmware_has_feature(FW_FEATURE_SPLPAR) && !crash_shutdown) {
+       if (firmware_has_feature(FW_FEATURE_SPLPAR)) {
                int ret;
                int cpu = smp_processor_id();
                int hwcpu = hard_smp_processor_id();
-- 
2.55.0


Reply via email to