Re: NMI handling rework for x86

Corey Minyard (cminyard@mvista.com)
Fri, 15 Nov 2002 13:35:16 -0600


This is a multi-part message in MIME format.
--------------060405060906010902040905
Content-Type: text/plain; charset=us-ascii; format=flowed
Content-Transfer-Encoding: 7bit

John Levon wrote:

>>I have also created a kernel module that loops requesting and releasing
>>the NMI, and counting the number of NMIs that actually get hit by the
>>handler that is installed.. This is on a dual 2.8GHZ Pentium 4 machine
>>with hyperthreading (so 4 processors, sort of). I have six processes
>>doing the request/release and some other processes eating CPU on each
>>processor. This has been running for almost three hours, about
>>10,000,000 NMIs have occurred (around 1000/sec). Around 4700 NMIs have
>>been caught by the handler, meaning that it was a close race between the
>>removal and the NMI occurring. So it looks good.
>>
>>
>
>Can you send me the test module so I don't have to bother writing one
>myself ?
>
>I'll try to test this weekend
>
Certainly. It's attached.

Thanks,

-Corey

--------------060405060906010902040905
Content-Type: text/plain;
name="test_nmi.c"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="test_nmi.c"

#include <linux/config.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/nmi.h>
#include <linux/notifier.h>
#include <asm/atomic.h>

static atomic_t nmi_count = ATOMIC_INIT(0);
static atomic_t request_count = ATOMIC_INIT(0);

static int
do_nmi(void *dev_id, struct pt_regs *regs, int cpu, int handled)
{
atomic_inc(&nmi_count);
return NOTIFY_DONE;
}

static ssize_t do_read(struct file *file,
char *buf,
size_t count,
loff_t *ppos)
{
int rv;
long last_jiffies = jiffies;
struct nmi_handler nmi_handler =
{
.link = LIST_HEAD_INIT(nmi_handler.link),
.dev_name = "nmi_test",
.dev_id = NULL,
.handler = do_nmi,
.priority = 0, /* Call us last. */
};

printk("NMI test: start test\n");

for (;;) {
if (signal_pending(current))
return -ERESTARTSYS;

rv = request_nmi(&nmi_handler);
if (rv) {
printk(KERN_WARNING
"NMI test: Can't register nmi handler\n");
return rv;
}

// set_current_state(TASK_INTERRUPTIBLE);
// schedule_timeout(1);

release_nmi(&nmi_handler);

atomic_inc(&request_count);
if ((jiffies - last_jiffies) >= HZ) {
last_jiffies = jiffies;
printk("NMIs = %d, requests=%d\n",
atomic_read(&nmi_count),
atomic_read(&request_count));
}
}
return 0;
}

static int do_open(struct inode *ino, struct file *filep)
{
return 0;
}

static int do_close(struct inode *ino, struct file *filep)
{
printk("NMI test: in close\n");
return 0;
}

static struct file_operations nmi_test_fops = {
.owner = THIS_MODULE,
.read = do_read,
.write = NULL,
.ioctl = NULL,
.open = do_open,
.release = do_close,
};

static struct miscdevice nmi_test_miscdev = {
130,
"nmi_test",
&nmi_test_fops
};

static int __init nmi_test_init(void)
{
int rv;

rv = misc_register(&nmi_test_miscdev);
if (rv < 0) {
printk("NMI test: Unable to register misc device\n");
return rv;
}

printk(KERN_INFO "NMI test by "
"Corey Minyard (minyard@mvista.com)\n");

return 0;
}

static void __exit nmi_test_exit(void)
{
/* Make sure no one can call us any more. */
misc_deregister(&nmi_test_miscdev);
}
module_exit(nmi_test_exit);
module_init(nmi_test_init);
MODULE_LICENSE("GPL");

--------------060405060906010902040905--

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/