Commit f7d98d18a01ece2863984d4fb5ae949b18b02715

Authored by Vasant Hegde
Committed by Benjamin Herrenschmidt
1 parent cb5b242c8c

powerpc/powernv: Call OPAL sync before kexec'ing

Its possible that OPAL may be writing to host memory during
kexec (like dump retrieve scenario). In this situation we might
end up corrupting host memory.

This patch makes OPAL sync call to make sure OPAL stops
writing to host memory before kexec'ing.

Signed-off-by: Vasant Hegde <hegdevasant@linux.vnet.ibm.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>

Showing 4 changed files with 23 additions and 2 deletions Side-by-side Diff

arch/powerpc/include/asm/opal.h
... ... @@ -156,6 +156,7 @@
156 156 #define OPAL_FLASH_UPDATE 78
157 157 #define OPAL_GET_MSG 85
158 158 #define OPAL_CHECK_ASYNC_COMPLETION 86
  159 +#define OPAL_SYNC_HOST_REBOOT 87
159 160  
160 161 #ifndef __ASSEMBLY__
161 162  
... ... @@ -828,6 +829,7 @@
828 829  
829 830 int64_t opal_get_msg(uint64_t buffer, size_t size);
830 831 int64_t opal_check_completion(uint64_t buffer, size_t size, uint64_t token);
  832 +int64_t opal_sync_host_reboot(void);
831 833  
832 834 /* Internal functions */
833 835 extern int early_init_dt_scan_opal(unsigned long node, const char *uname, int depth, void *data);
arch/powerpc/platforms/powernv/opal-wrappers.S
... ... @@ -128,4 +128,5 @@
128 128 OPAL_CALL(opal_update_flash, OPAL_FLASH_UPDATE);
129 129 OPAL_CALL(opal_get_msg, OPAL_GET_MSG);
130 130 OPAL_CALL(opal_check_completion, OPAL_CHECK_ASYNC_COMPLETION);
  131 +OPAL_CALL(opal_sync_host_reboot, OPAL_SYNC_HOST_REBOOT);
arch/powerpc/platforms/powernv/opal.c
... ... @@ -20,6 +20,7 @@
20 20 #include <linux/slab.h>
21 21 #include <linux/sched.h>
22 22 #include <linux/kobject.h>
  23 +#include <linux/delay.h>
23 24 #include <asm/opal.h>
24 25 #include <asm/firmware.h>
25 26 #include <asm/mce.h>
26 27  
27 28  
... ... @@ -482,11 +483,26 @@
482 483 void opal_shutdown(void)
483 484 {
484 485 unsigned int i;
  486 + long rc = OPAL_BUSY;
485 487  
  488 + /* First free interrupts, which will also mask them */
486 489 for (i = 0; i < opal_irq_count; i++) {
487 490 if (opal_irqs[i])
488 491 free_irq(opal_irqs[i], NULL);
489 492 opal_irqs[i] = 0;
  493 + }
  494 +
  495 + /*
  496 + * Then sync with OPAL which ensure anything that can
  497 + * potentially write to our memory has completed such
  498 + * as an ongoing dump retrieval
  499 + */
  500 + while (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT) {
  501 + rc = opal_sync_host_reboot();
  502 + if (rc == OPAL_BUSY)
  503 + opal_poll_events(NULL);
  504 + else
  505 + mdelay(10);
490 506 }
491 507 }
arch/powerpc/platforms/powernv/setup.c
... ... @@ -145,8 +145,10 @@
145 145 /* Let the PCI code clear up IODA tables */
146 146 pnv_pci_shutdown();
147 147  
148   - /* And unregister all OPAL interrupts so they don't fire
149   - * up while we kexec
  148 + /*
  149 + * Stop OPAL activity: Unregister all OPAL interrupts so they
  150 + * don't fire up while we kexec and make sure all potentially
  151 + * DMA'ing ops are complete (such as dump retrieval).
150 152 */
151 153 opal_shutdown();
152 154 }