aboutsummaryrefslogtreecommitdiffstats
path: root/Documentation/virtual
diff options
context:
space:
mode:
authorLiu Yu-B13201 <Yu.Liu@freescale.com>2012-07-03 01:48:52 -0400
committerAlexander Graf <agraf@suse.de>2012-10-05 17:38:37 -0400
commit9202e07636f0c4858ba6c30773a3f160b2b5659a (patch)
tree8dc71ab432097c3cfbad47157d66788e02d1f219 /Documentation/virtual
parent784bafac79e7646e56f40998a6dde0e1ed5595f8 (diff)
KVM: PPC: Add support for ePAPR idle hcall in host kernel
And add a new flag definition in kvm_ppc_pvinfo to indicate whether the host supports the EV_IDLE hcall. Signed-off-by: Liu Yu <yu.liu@freescale.com> [stuart.yoder@freescale.com: cleanup,fixes for conditions allowing idle] Signed-off-by: Stuart Yoder <stuart.yoder@freescale.com> [agraf: fix typo] Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'Documentation/virtual')
-rw-r--r--Documentation/virtual/kvm/api.txt7
1 files changed, 5 insertions, 2 deletions
diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
index f6ec3a92e621..170afb1fbc2e 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -1194,12 +1194,15 @@ struct kvm_ppc_pvinfo {
1194This ioctl fetches PV specific information that need to be passed to the guest 1194This ioctl fetches PV specific information that need to be passed to the guest
1195using the device tree or other means from vm context. 1195using the device tree or other means from vm context.
1196 1196
1197For now the only implemented piece of information distributed here is an array 1197The hcall array defines 4 instructions that make up a hypercall.
1198of 4 instructions that make up a hypercall.
1199 1198
1200If any additional field gets added to this structure later on, a bit for that 1199If any additional field gets added to this structure later on, a bit for that
1201additional piece of information will be set in the flags bitmap. 1200additional piece of information will be set in the flags bitmap.
1202 1201
1202The flags bitmap is defined as:
1203
1204 /* the host supports the ePAPR idle hcall
1205 #define KVM_PPC_PVINFO_FLAGS_EV_IDLE (1<<0)
1203 1206
12044.48 KVM_ASSIGN_PCI_DEVICE 12074.48 KVM_ASSIGN_PCI_DEVICE
1205 1208
4 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454
/*
 *	Wdt977	0.03:	A Watchdog Device for Netwinder W83977AF chip
 *
 *	(c) Copyright 1998 Rebel.com (Woody Suwalski <woody@netwinder.org>)
 *
 *			-----------------------
 *
 *	This program is free software; you can redistribute it and/or
 *	modify it under the terms of the GNU General Public License
 *	as published by the Free Software Foundation; either version
 *	2 of the License, or (at your option) any later version.
 *
 *			-----------------------
 *      14-Dec-2001 Matt Domsch <Matt_Domsch@dell.com>
 *           Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
 *	19-Dec-2001 Woody Suwalski: Netwinder fixes, ioctl interface
 *	06-Jan-2002 Woody Suwalski: For compatibility, convert all timeouts
 *				    from minutes to seconds.
 *      07-Jul-2003 Daniele Bellucci: Audit return code of misc_register in
 *                                    nwwatchdog_init.
 */

#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/config.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/init.h>
#include <linux/watchdog.h>
#include <linux/notifier.h>
#include <linux/reboot.h>

#include <asm/io.h>
#include <asm/system.h>
#include <asm/mach-types.h>
#include <asm/uaccess.h>

#define PFX "Wdt977: "
#define WATCHDOG_MINOR	130

#define	DEFAULT_TIMEOUT	60			/* default timeout in seconds */

static	int timeout = DEFAULT_TIMEOUT;
static	int timeoutM;				/* timeout in minutes */
static	unsigned long timer_alive;
static	int testmode;
static	char expect_close;

module_param(timeout, int, 0);
MODULE_PARM_DESC(timeout,"Watchdog timeout in seconds (60..15300), default=" __MODULE_STRING(DEFAULT_TIMEOUT) ")");
module_param(testmode, int, 0);
MODULE_PARM_DESC(testmode,"Watchdog testmode (1 = no reboot), default=0");

static int nowayout = WATCHDOG_NOWAYOUT;
module_param(nowayout, int, 0);
MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");

/*
 * Start the watchdog
 */

static int wdt977_start(void)
{
	/* unlock the SuperIO chip */
	outb(0x87,0x370);
	outb(0x87,0x370);

	/* select device Aux2 (device=8) and set watchdog regs F2, F3 and F4
	 * F2 has the timeout in minutes
	 * F3 could be set to the POWER LED blink (with GP17 set to PowerLed)
	 *   at timeout, and to reset timer on kbd/mouse activity (not impl.)
	 * F4 is used to just clear the TIMEOUT'ed state (bit 0)
	 */
	outb(0x07,0x370);
	outb(0x08,0x371);
	outb(0xF2,0x370);
	outb(timeoutM,0x371);
	outb(0xF3,0x370);
	outb(0x00,0x371);	/* another setting is 0E for kbd/mouse/LED */
	outb(0xF4,0x370);
	outb(0x00,0x371);

	/* at last select device Aux1 (dev=7) and set GP16 as a watchdog output */
	/* in test mode watch the bit 1 on F4 to indicate "triggered" */
	if (!testmode)
	{
		outb(0x07,0x370);
		outb(0x07,0x371);
		outb(0xE6,0x370);
		outb(0x08,0x371);
	}

	/* lock the SuperIO chip */
	outb(0xAA,0x370);

	printk(KERN_INFO PFX "activated.\n");

	return 0;
}

/*
 * Stop the watchdog
 */

static int wdt977_stop(void)
{
	/* unlock the SuperIO chip */
	outb(0x87,0x370);
	outb(0x87,0x370);

	/* select device Aux2 (device=8) and set watchdog regs F2,F3 and F4
	* F3 is reset to its default state
	* F4 can clear the TIMEOUT'ed state (bit 0) - back to default
	* We can not use GP17 as a PowerLed, as we use its usage as a RedLed
	*/
	outb(0x07,0x370);
	outb(0x08,0x371);
	outb(0xF2,0x370);
	outb(0xFF,0x371);
	outb(0xF3,0x370);
	outb(0x00,0x371);
	outb(0xF4,0x370);
	outb(0x00,0x371);
	outb(0xF2,0x370);
	outb(0x00,0x371);

	/* at last select device Aux1 (dev=7) and set GP16 as a watchdog output */
	outb(0x07,0x370);
	outb(0x07,0x371);
	outb(0xE6,0x370);
	outb(0x08,0x371);

	/* lock the SuperIO chip */
	outb(0xAA,0x370);

	printk(KERN_INFO PFX "shutdown.\n");

	return 0;
}

/*
 * Send a keepalive ping to the watchdog
 * This is done by simply re-writing the timeout to reg. 0xF2
 */

static int wdt977_keepalive(void)
{
	/* unlock the SuperIO chip */
	outb(0x87,0x370);
	outb(0x87,0x370);

	/* select device Aux2 (device=8) and kicks watchdog reg F2 */
	/* F2 has the timeout in minutes */
	outb(0x07,0x370);
	outb(0x08,0x371);
	outb(0xF2,0x370);
	outb(timeoutM,0x371);

	/* lock the SuperIO chip */
	outb(0xAA,0x370);

	return 0;
}

/*
 * Set the watchdog timeout value
 */

static int wdt977_set_timeout(int t)
{
	int tmrval;

	/* convert seconds to minutes, rounding up */
	tmrval = (t + 59) / 60;

	if (machine_is_netwinder()) {
		/* we have a hw bug somewhere, so each 977 minute is actually only 30sec
		 *  this limits the max timeout to half of device max of 255 minutes...
		 */
		tmrval += tmrval;
	}

	if ((tmrval < 1) || (tmrval > 255))
		return -EINVAL;

	/* timeout is the timeout in seconds, timeoutM is the timeout in minutes) */
	timeout = t;
	timeoutM = tmrval;
	return 0;
}

/*
 * Get the watchdog status
 */

static int wdt977_get_status(int *status)
{
	int new_status;

	*status=0;

	/* unlock the SuperIO chip */
	outb(0x87,0x370);
	outb(0x87,0x370);

	/* select device Aux2 (device=8) and read watchdog reg F4 */
	outb(0x07,0x370);
	outb(0x08,0x371);
	outb(0xF4,0x370);
	new_status = inb(0x371);

	/* lock the SuperIO chip */
	outb(0xAA,0x370);

	if (new_status & 1)
		*status |= WDIOF_CARDRESET;

	return 0;
}


/*
 *	/dev/watchdog handling
 */

static int wdt977_open(struct inode *inode, struct file *file)
{
	/* If the watchdog is alive we don't need to start it again */
	if( test_and_set_bit(0,&timer_alive) )
		return -EBUSY;

	if (nowayout)
		__module_get(THIS_MODULE);

	wdt977_start();
	return nonseekable_open(inode, file);
}

static int wdt977_release(struct inode *inode, struct file *file)
{
	/*
	 *	Shut off the timer.
	 * 	Lock it in if it's a module and we set nowayout
	 */
	if (expect_close == 42)
	{
		wdt977_stop();
		clear_bit(0,&timer_alive);
	} else {
		printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n");
		wdt977_keepalive();
	}
	expect_close = 0;
	return 0;
}


/*
 *      wdt977_write:
 *      @file: file handle to the watchdog
 *      @buf: buffer to write (unused as data does not matter here
 *      @count: count of bytes
 *      @ppos: pointer to the position to write. No seeks allowed
 *
 *      A write to a watchdog device is defined as a keepalive signal. Any
 *      write of data will do, as we we don't define content meaning.
 */

static ssize_t wdt977_write(struct file *file, const char __user *buf,
			    size_t count, loff_t *ppos)
{
	if (count) {
		if (!nowayout) {
			size_t i;

			/* In case it was set long ago */
			expect_close = 0;

			for (i = 0; i != count; i++) {
				char c;
				if (get_user(c, buf + i))
					return -EFAULT;
				if (c == 'V')
					expect_close = 42;