1 /*
2  * Watchdog implementation based on z/VM Watchdog Timer API
3  *
4  * Copyright IBM Corp. 2004,2009
5  *
6  * The user space watchdog daemon can use this driver as
7  * /dev/vmwatchdog to have z/VM execute the specified CP
8  * command when the timeout expires. The default command is
9  * "IPL", which which cause an immediate reboot.
10  */
11 #define KMSG_COMPONENT "vmwatchdog"
12 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
13 
14 #include <linux/init.h>
15 #include <linux/fs.h>
16 #include <linux/kernel.h>
17 #include <linux/miscdevice.h>
18 #include <linux/module.h>
19 #include <linux/moduleparam.h>
20 #include <linux/slab.h>
21 #include <linux/suspend.h>
22 #include <linux/watchdog.h>
23 
24 #include <asm/ebcdic.h>
25 #include <asm/io.h>
26 #include <asm/uaccess.h>
27 
28 #define MAX_CMDLEN 240
29 #define MIN_INTERVAL 15
30 static char vmwdt_cmd[MAX_CMDLEN] = "IPL";
31 static bool vmwdt_conceal;
32 
33 static bool vmwdt_nowayout = WATCHDOG_NOWAYOUT;
34 
35 MODULE_LICENSE("GPL");
36 MODULE_AUTHOR("Arnd Bergmann <arndb@de.ibm.com>");
37 MODULE_DESCRIPTION("z/VM Watchdog Timer");
38 module_param_string(cmd, vmwdt_cmd, MAX_CMDLEN, 0644);
39 MODULE_PARM_DESC(cmd, "CP command that is run when the watchdog triggers");
40 module_param_named(conceal, vmwdt_conceal, bool, 0644);
41 MODULE_PARM_DESC(conceal, "Enable the CONCEAL CP option while the watchdog "
42 		" is active");
43 module_param_named(nowayout, vmwdt_nowayout, bool, 0);
44 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started"
45 		" (default=CONFIG_WATCHDOG_NOWAYOUT)");
46 MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
47 
48 static unsigned int vmwdt_interval = 60;
49 static unsigned long vmwdt_is_open;
50 static int vmwdt_expect_close;
51 
52 static DEFINE_MUTEX(vmwdt_mutex);
53 
54 #define VMWDT_OPEN	0	/* devnode is open or suspend in progress */
55 #define VMWDT_RUNNING	1	/* The watchdog is armed */
56 
57 enum vmwdt_func {
58 	/* function codes */
59 	wdt_init   = 0,
60 	wdt_change = 1,
61 	wdt_cancel = 2,
62 	/* flags */
63 	wdt_conceal = 0x80000000,
64 };
65 
__diag288(enum vmwdt_func func,unsigned int timeout,char * cmd,size_t len)66 static int __diag288(enum vmwdt_func func, unsigned int timeout,
67 			    char *cmd, size_t len)
68 {
69 	register unsigned long __func asm("2") = func;
70 	register unsigned long __timeout asm("3") = timeout;
71 	register unsigned long __cmdp asm("4") = virt_to_phys(cmd);
72 	register unsigned long __cmdl asm("5") = len;
73 	int err;
74 
75 	err = -EINVAL;
76 	asm volatile(
77 		"	diag	%1,%3,0x288\n"
78 		"0:	la	%0,0\n"
79 		"1:\n"
80 		EX_TABLE(0b,1b)
81 		: "+d" (err) : "d"(__func), "d"(__timeout),
82 		  "d"(__cmdp), "d"(__cmdl) : "1", "cc");
83 	return err;
84 }
85 
vmwdt_keepalive(void)86 static int vmwdt_keepalive(void)
87 {
88 	/* we allocate new memory every time to avoid having
89 	 * to track the state. static allocation is not an
90 	 * option since that might not be contiguous in real
91 	 * storage in case of a modular build */
92 	static char *ebc_cmd;
93 	size_t len;
94 	int ret;
95 	unsigned int func;
96 
97 	ebc_cmd = kmalloc(MAX_CMDLEN, GFP_KERNEL);
98 	if (!ebc_cmd)
99 		return -ENOMEM;
100 
101 	len = strlcpy(ebc_cmd, vmwdt_cmd, MAX_CMDLEN);
102 	ASCEBC(ebc_cmd, MAX_CMDLEN);
103 	EBC_TOUPPER(ebc_cmd, MAX_CMDLEN);
104 
105 	func = vmwdt_conceal ? (wdt_init | wdt_conceal) : wdt_init;
106 	set_bit(VMWDT_RUNNING, &vmwdt_is_open);
107 	ret = __diag288(func, vmwdt_interval, ebc_cmd, len);
108 	WARN_ON(ret != 0);
109 	kfree(ebc_cmd);
110 	return ret;
111 }
112 
vmwdt_disable(void)113 static int vmwdt_disable(void)
114 {
115 	int ret = __diag288(wdt_cancel, 0, "", 0);
116 	WARN_ON(ret != 0);
117 	clear_bit(VMWDT_RUNNING, &vmwdt_is_open);
118 	return ret;
119 }
120 
vmwdt_probe(void)121 static int __init vmwdt_probe(void)
122 {
123 	/* there is no real way to see if the watchdog is supported,
124 	 * so we try initializing it with a NOP command ("BEGIN")
125 	 * that won't cause any harm even if the following disable
126 	 * fails for some reason */
127 	static char __initdata ebc_begin[] = {
128 		194, 197, 199, 201, 213
129 	};
130 	if (__diag288(wdt_init, 15, ebc_begin, sizeof(ebc_begin)) != 0)
131 		return -EINVAL;
132 	return vmwdt_disable();
133 }
134 
vmwdt_open(struct inode * i,struct file * f)135 static int vmwdt_open(struct inode *i, struct file *f)
136 {
137 	int ret;
138 	if (test_and_set_bit(VMWDT_OPEN, &vmwdt_is_open))
139 		return -EBUSY;
140 	ret = vmwdt_keepalive();
141 	if (ret)
142 		clear_bit(VMWDT_OPEN, &vmwdt_is_open);
143 	return ret ? ret : nonseekable_open(i, f);
144 }
145 
vmwdt_close(struct inode * i,struct file * f)146 static int vmwdt_close(struct inode *i, struct file *f)
147 {
148 	if (vmwdt_expect_close == 42)
149 		vmwdt_disable();
150 	vmwdt_expect_close = 0;
151 	clear_bit(VMWDT_OPEN, &vmwdt_is_open);
152 	return 0;
153 }
154 
155 static struct watchdog_info vmwdt_info = {
156 	.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
157 	.firmware_version = 0,
158 	.identity = "z/VM Watchdog Timer",
159 };
160 
__vmwdt_ioctl(unsigned int cmd,unsigned long arg)161 static int __vmwdt_ioctl(unsigned int cmd, unsigned long arg)
162 {
163 	switch (cmd) {
164 	case WDIOC_GETSUPPORT:
165 		if (copy_to_user((void __user *)arg, &vmwdt_info,
166 					sizeof(vmwdt_info)))
167 			return -EFAULT;
168 		return 0;
169 	case WDIOC_GETSTATUS:
170 	case WDIOC_GETBOOTSTATUS:
171 		return put_user(0, (int __user *)arg);
172 	case WDIOC_GETTEMP:
173 		return -EINVAL;
174 	case WDIOC_SETOPTIONS:
175 		{
176 			int options, ret;
177 			if (get_user(options, (int __user *)arg))
178 				return -EFAULT;
179 			ret = -EINVAL;
180 			if (options & WDIOS_DISABLECARD) {
181 				ret = vmwdt_disable();
182 				if (ret)
183 					return ret;
184 			}
185 			if (options & WDIOS_ENABLECARD) {
186 				ret = vmwdt_keepalive();
187 			}
188 			return ret;
189 		}
190 	case WDIOC_GETTIMEOUT:
191 		return put_user(vmwdt_interval, (int __user *)arg);
192 	case WDIOC_SETTIMEOUT:
193 		{
194 			int interval;
195 			if (get_user(interval, (int __user *)arg))
196 				return -EFAULT;
197 			if (interval < MIN_INTERVAL)
198 				return -EINVAL;
199 			vmwdt_interval = interval;
200 		}
201 		return vmwdt_keepalive();
202 	case WDIOC_KEEPALIVE:
203 		return vmwdt_keepalive();
204 	}
205 	return -EINVAL;
206 }
207 
vmwdt_ioctl(struct file * f,unsigned int cmd,unsigned long arg)208 static long vmwdt_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
209 {
210 	int rc;
211 
212 	mutex_lock(&vmwdt_mutex);
213 	rc = __vmwdt_ioctl(cmd, arg);
214 	mutex_unlock(&vmwdt_mutex);
215 	return (long) rc;
216 }
217 
vmwdt_write(struct file * f,const char __user * buf,size_t count,loff_t * ppos)218 static ssize_t vmwdt_write(struct file *f, const char __user *buf,
219 				size_t count, loff_t *ppos)
220 {
221 	if(count) {
222 		if (!vmwdt_nowayout) {
223 			size_t i;
224 
225 			/* note: just in case someone wrote the magic character
226 			 * five months ago... */
227 			vmwdt_expect_close = 0;
228 
229 			for (i = 0; i != count; i++) {
230 				char c;
231 				if (get_user(c, buf+i))
232 					return -EFAULT;
233 				if (c == 'V')
234 					vmwdt_expect_close = 42;
235 			}
236 		}
237 		/* someone wrote to us, we should restart timer */
238 		vmwdt_keepalive();
239 	}
240 	return count;
241 }
242 
vmwdt_resume(void)243 static int vmwdt_resume(void)
244 {
245 	clear_bit(VMWDT_OPEN, &vmwdt_is_open);
246 	return NOTIFY_DONE;
247 }
248 
249 /*
250  * It makes no sense to go into suspend while the watchdog is running.
251  * Depending on the memory size, the watchdog might trigger, while we
252  * are still saving the memory.
253  * We reuse the open flag to ensure that suspend and watchdog open are
254  * exclusive operations
255  */
vmwdt_suspend(void)256 static int vmwdt_suspend(void)
257 {
258 	if (test_and_set_bit(VMWDT_OPEN, &vmwdt_is_open)) {
259 		pr_err("The system cannot be suspended while the watchdog"
260 			" is in use\n");
261 		return notifier_from_errno(-EBUSY);
262 	}
263 	if (test_bit(VMWDT_RUNNING, &vmwdt_is_open)) {
264 		clear_bit(VMWDT_OPEN, &vmwdt_is_open);
265 		pr_err("The system cannot be suspended while the watchdog"
266 			" is running\n");
267 		return notifier_from_errno(-EBUSY);
268 	}
269 	return NOTIFY_DONE;
270 }
271 
272 /*
273  * This function is called for suspend and resume.
274  */
vmwdt_power_event(struct notifier_block * this,unsigned long event,void * ptr)275 static int vmwdt_power_event(struct notifier_block *this, unsigned long event,
276 			     void *ptr)
277 {
278 	switch (event) {
279 	case PM_POST_HIBERNATION:
280 	case PM_POST_SUSPEND:
281 		return vmwdt_resume();
282 	case PM_HIBERNATION_PREPARE:
283 	case PM_SUSPEND_PREPARE:
284 		return vmwdt_suspend();
285 	default:
286 		return NOTIFY_DONE;
287 	}
288 }
289 
290 static struct notifier_block vmwdt_power_notifier = {
291 	.notifier_call = vmwdt_power_event,
292 };
293 
294 static const struct file_operations vmwdt_fops = {
295 	.open    = &vmwdt_open,
296 	.release = &vmwdt_close,
297 	.unlocked_ioctl = &vmwdt_ioctl,
298 	.write   = &vmwdt_write,
299 	.owner   = THIS_MODULE,
300 	.llseek  = noop_llseek,
301 };
302 
303 static struct miscdevice vmwdt_dev = {
304 	.minor      = WATCHDOG_MINOR,
305 	.name       = "watchdog",
306 	.fops       = &vmwdt_fops,
307 };
308 
vmwdt_init(void)309 static int __init vmwdt_init(void)
310 {
311 	int ret;
312 
313 	ret = vmwdt_probe();
314 	if (ret)
315 		return ret;
316 	ret = register_pm_notifier(&vmwdt_power_notifier);
317 	if (ret)
318 		return ret;
319 	/*
320 	 * misc_register() has to be the last action in module_init(), because
321 	 * file operations will be available right after this.
322 	 */
323 	ret = misc_register(&vmwdt_dev);
324 	if (ret) {
325 		unregister_pm_notifier(&vmwdt_power_notifier);
326 		return ret;
327 	}
328 	return 0;
329 }
330 module_init(vmwdt_init);
331 
vmwdt_exit(void)332 static void __exit vmwdt_exit(void)
333 {
334 	unregister_pm_notifier(&vmwdt_power_notifier);
335 	misc_deregister(&vmwdt_dev);
336 }
337 module_exit(vmwdt_exit);
338