1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Watchdog driver for z/VM and LPAR using the diag 288 interface. 4 * 5 * Under z/VM, expiration of the watchdog will send a "system restart" command 6 * to CP. 7 * 8 * The command can be altered using the module parameter "cmd". This is 9 * not recommended because it's only supported on z/VM but not whith LPAR. 10 * 11 * On LPAR, the watchdog will always trigger a system restart. the module 12 * paramter cmd is meaningless here. 13 * 14 * 15 * Copyright IBM Corp. 2004, 2013 16 * Author(s): Arnd Bergmann (arndb@de.ibm.com) 17 * Philipp Hachtmann (phacht@de.ibm.com) 18 * 19 */ 20 21 #define KMSG_COMPONENT "diag288_wdt" 22 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt 23 24 #include <linux/init.h> 25 #include <linux/kernel.h> 26 #include <linux/module.h> 27 #include <linux/moduleparam.h> 28 #include <linux/slab.h> 29 #include <linux/watchdog.h> 30 #include <asm/machine.h> 31 #include <asm/ebcdic.h> 32 #include <asm/diag.h> 33 #include <linux/io.h> 34 35 #define MAX_CMDLEN 240 36 #define DEFAULT_CMD "SYSTEM RESTART" 37 38 #define MIN_INTERVAL 15 /* Minimal time supported by diag88 */ 39 #define MAX_INTERVAL 3600 /* One hour should be enough - pure estimation */ 40 41 #define WDT_DEFAULT_TIMEOUT 30 42 43 /* Function codes - init, change, cancel */ 44 #define WDT_FUNC_INIT 0 45 #define WDT_FUNC_CHANGE 1 46 #define WDT_FUNC_CANCEL 2 47 #define WDT_FUNC_CONCEAL 0x80000000 48 49 /* Action codes for LPAR watchdog */ 50 #define LPARWDT_RESTART 0 51 52 static char wdt_cmd[MAX_CMDLEN] = DEFAULT_CMD; 53 static bool conceal_on; 54 static bool nowayout_info = WATCHDOG_NOWAYOUT; 55 56 MODULE_LICENSE("GPL"); 57 MODULE_AUTHOR("Arnd Bergmann <arndb@de.ibm.com>"); 58 MODULE_AUTHOR("Philipp Hachtmann <phacht@de.ibm.com>"); 59 60 MODULE_DESCRIPTION("System z diag288 Watchdog Timer"); 61 62 module_param_string(cmd, wdt_cmd, MAX_CMDLEN, 0644); 63 MODULE_PARM_DESC(cmd, "CP command that is run when the watchdog triggers (z/VM only)"); 64 65 module_param_named(conceal, conceal_on, bool, 0644); 66 MODULE_PARM_DESC(conceal, "Enable the CONCEAL CP option while the watchdog is active (z/VM only)"); 67 68 module_param_named(nowayout, nowayout_info, bool, 0444); 69 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default = CONFIG_WATCHDOG_NOWAYOUT)"); 70 71 MODULE_ALIAS("vmwatchdog"); 72 73 static char *cmd_buf; 74 75 static int diag288(unsigned int func, unsigned int timeout, 76 unsigned long action, unsigned int len) 77 { 78 union register_pair r1 = { .even = func, .odd = timeout, }; 79 union register_pair r3 = { .even = action, .odd = len, }; 80 int err; 81 82 diag_stat_inc(DIAG_STAT_X288); 83 84 err = -EINVAL; 85 asm volatile( 86 " diag %[r1],%[r3],0x288\n" 87 "0: la %[err],0\n" 88 "1:\n" 89 EX_TABLE(0b, 1b) 90 : [err] "+d" (err) 91 : [r1] "d" (r1.pair), [r3] "d" (r3.pair) 92 : "cc", "memory"); 93 return err; 94 } 95 96 static int diag288_str(unsigned int func, unsigned int timeout, char *cmd) 97 { 98 ssize_t len; 99 100 len = strscpy(cmd_buf, cmd, MAX_CMDLEN); 101 if (len < 0) 102 return len; 103 ASCEBC(cmd_buf, MAX_CMDLEN); 104 EBC_TOUPPER(cmd_buf, MAX_CMDLEN); 105 106 return diag288(func, timeout, virt_to_phys(cmd_buf), len); 107 } 108 109 static int wdt_start(struct watchdog_device *dev) 110 { 111 int ret; 112 unsigned int func; 113 114 if (machine_is_vm()) { 115 func = conceal_on ? (WDT_FUNC_INIT | WDT_FUNC_CONCEAL) 116 : WDT_FUNC_INIT; 117 ret = diag288_str(func, dev->timeout, wdt_cmd); 118 WARN_ON(ret != 0); 119 } else { 120 ret = diag288(WDT_FUNC_INIT, dev->timeout, LPARWDT_RESTART, 0); 121 } 122 123 if (ret) { 124 pr_err("The watchdog cannot be activated\n"); 125 return ret; 126 } 127 return 0; 128 } 129 130 static int wdt_stop(struct watchdog_device *dev) 131 { 132 return diag288(WDT_FUNC_CANCEL, 0, 0, 0); 133 } 134 135 static int wdt_ping(struct watchdog_device *dev) 136 { 137 int ret; 138 unsigned int func; 139 140 if (machine_is_vm()) { 141 /* 142 * It seems to be ok to z/VM to use the init function to 143 * retrigger the watchdog. On LPAR WDT_FUNC_CHANGE must 144 * be used when the watchdog is running. 145 */ 146 func = conceal_on ? (WDT_FUNC_INIT | WDT_FUNC_CONCEAL) 147 : WDT_FUNC_INIT; 148 149 ret = diag288_str(func, dev->timeout, wdt_cmd); 150 WARN_ON(ret != 0); 151 } else { 152 ret = diag288(WDT_FUNC_CHANGE, dev->timeout, 0, 0); 153 } 154 155 if (ret) 156 pr_err("The watchdog timer cannot be started or reset\n"); 157 return ret; 158 } 159 160 static int wdt_set_timeout(struct watchdog_device * dev, unsigned int new_to) 161 { 162 dev->timeout = new_to; 163 return wdt_ping(dev); 164 } 165 166 static const struct watchdog_ops wdt_ops = { 167 .owner = THIS_MODULE, 168 .start = wdt_start, 169 .stop = wdt_stop, 170 .ping = wdt_ping, 171 .set_timeout = wdt_set_timeout, 172 }; 173 174 static const struct watchdog_info wdt_info = { 175 .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, 176 .firmware_version = 0, 177 .identity = "z Watchdog", 178 }; 179 180 static struct watchdog_device wdt_dev = { 181 .parent = NULL, 182 .info = &wdt_info, 183 .ops = &wdt_ops, 184 .bootstatus = 0, 185 .timeout = WDT_DEFAULT_TIMEOUT, 186 .min_timeout = MIN_INTERVAL, 187 .max_timeout = MAX_INTERVAL, 188 }; 189 190 static int __init diag288_init(void) 191 { 192 int ret; 193 194 watchdog_set_nowayout(&wdt_dev, nowayout_info); 195 196 if (machine_is_vm()) { 197 cmd_buf = kmalloc(MAX_CMDLEN, GFP_KERNEL); 198 if (!cmd_buf) { 199 pr_err("The watchdog cannot be initialized\n"); 200 return -ENOMEM; 201 } 202 203 ret = diag288_str(WDT_FUNC_INIT, MIN_INTERVAL, "BEGIN"); 204 if (ret != 0) { 205 pr_err("The watchdog cannot be initialized\n"); 206 kfree(cmd_buf); 207 return -EINVAL; 208 } 209 } else { 210 if (diag288(WDT_FUNC_INIT, WDT_DEFAULT_TIMEOUT, 211 LPARWDT_RESTART, 0)) { 212 pr_err("The watchdog cannot be initialized\n"); 213 return -EINVAL; 214 } 215 } 216 217 if (diag288(WDT_FUNC_CANCEL, 0, 0, 0)) { 218 pr_err("The watchdog cannot be deactivated\n"); 219 return -EINVAL; 220 } 221 222 return watchdog_register_device(&wdt_dev); 223 } 224 225 static void __exit diag288_exit(void) 226 { 227 watchdog_unregister_device(&wdt_dev); 228 kfree(cmd_buf); 229 } 230 231 module_init(diag288_init); 232 module_exit(diag288_exit); 233