powerpc/powernv: Interface to register/unregister opal dump region
authorVasant Hegde <hegdevasant@linux.vnet.ibm.com>
Sat, 9 Aug 2014 05:45:45 +0000 (11:15 +0530)
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>
Wed, 13 Aug 2014 05:13:45 +0000 (15:13 +1000)
PowerNV platform is capable of capturing host memory region when system
crashes (because of host/firmware). We have new OPAL API to register/
unregister memory region to be captured when system crashes.

This patch adds support for new API. Also during boot time we register
kernel log buffer and unregister before doing kexec.

Signed-off-by: Vasant Hegde <hegdevasant@linux.vnet.ibm.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
arch/powerpc/include/asm/opal.h
arch/powerpc/platforms/powernv/opal-wrappers.S
arch/powerpc/platforms/powernv/opal.c

index b2f8ce1fd0d742fc0b2f500feff4f965b255a09c..86055e598269ebc9c4ba2c52ea3b6f59a27599e2 100644 (file)
@@ -149,6 +149,8 @@ struct opal_sg_list {
 #define OPAL_DUMP_INFO2                                94
 #define OPAL_PCI_EEH_FREEZE_SET                        97
 #define OPAL_HANDLE_HMI                                98
+#define OPAL_REGISTER_DUMP_REGION              101
+#define OPAL_UNREGISTER_DUMP_REGION            102
 
 #ifndef __ASSEMBLY__
 
@@ -920,6 +922,8 @@ int64_t opal_set_param(uint64_t token, uint32_t param_id, uint64_t buffer,
                uint64_t length);
 int64_t opal_sensor_read(uint32_t sensor_hndl, int token, __be32 *sensor_data);
 int64_t opal_handle_hmi(void);
+int64_t opal_register_dump_region(uint32_t id, uint64_t start, uint64_t end);
+int64_t opal_unregister_dump_region(uint32_t id);
 
 /* Internal functions */
 extern int early_init_dt_scan_opal(unsigned long node, const char *uname,
@@ -974,6 +978,13 @@ struct opal_sg_list *opal_vmalloc_to_sg_list(void *vmalloc_addr,
                                             unsigned long vmalloc_size);
 void opal_free_sg_list(struct opal_sg_list *sg);
 
+/*
+ * Dump region ID range usable by the OS
+ */
+#define OPAL_DUMP_REGION_HOST_START            0x80
+#define OPAL_DUMP_REGION_LOG_BUF               0x80
+#define OPAL_DUMP_REGION_HOST_END              0xFF
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* __OPAL_H */
index a328be44880f850e39a699d3c11ab30d586bf448..2e6ce1b8dc8ffcdd0d21cd86034c9e86e745880b 100644 (file)
@@ -245,3 +245,5 @@ OPAL_CALL(opal_sensor_read,                 OPAL_SENSOR_READ);
 OPAL_CALL(opal_get_param,                      OPAL_GET_PARAM);
 OPAL_CALL(opal_set_param,                      OPAL_SET_PARAM);
 OPAL_CALL(opal_handle_hmi,                     OPAL_HANDLE_HMI);
+OPAL_CALL(opal_register_dump_region,           OPAL_REGISTER_DUMP_REGION);
+OPAL_CALL(opal_unregister_dump_region,         OPAL_UNREGISTER_DUMP_REGION);
index f0a01a46a57d12b33f3ec2f6fe853ec59b4a0b64..b44eec3e8dbd8dbfb43873af73f006d20081b314 100644 (file)
@@ -605,6 +605,24 @@ static int opal_sysfs_init(void)
        return 0;
 }
 
+static void __init opal_dump_region_init(void)
+{
+       void *addr;
+       uint64_t size;
+       int rc;
+
+       /* Register kernel log buffer */
+       addr = log_buf_addr_get();
+       size = log_buf_len_get();
+       rc = opal_register_dump_region(OPAL_DUMP_REGION_LOG_BUF,
+                                      __pa(addr), size);
+       /* Don't warn if this is just an older OPAL that doesn't
+        * know about that call
+        */
+       if (rc && rc != OPAL_UNSUPPORTED)
+               pr_warn("DUMP: Failed to register kernel log buffer. "
+                       "rc = %d\n", rc);
+}
 static int __init opal_init(void)
 {
        struct device_node *np, *consoles;
@@ -654,6 +672,8 @@ static int __init opal_init(void)
        /* Create "opal" kobject under /sys/firmware */
        rc = opal_sysfs_init();
        if (rc == 0) {
+               /* Setup dump region interface */
+               opal_dump_region_init();
                /* Setup error log interface */
                rc = opal_elog_init();
                /* Setup code update interface */
@@ -694,6 +714,9 @@ void opal_shutdown(void)
                else
                        mdelay(10);
        }
+
+       /* Unregister memory dump region */
+       opal_unregister_dump_region(OPAL_DUMP_REGION_LOG_BUF);
 }
 
 /* Export this so that test modules can use it */