The Linux Kernel Mailing List
 help / color / mirror / Atom feed
* Interrupt handling
@ 2003-10-16 13:16 Sanil K
  2003-10-16 13:51 ` Richard B. Johnson
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Sanil K @ 2003-10-16 13:16 UTC (permalink / raw)
  To: linux-kernel

Hi all,

This may be a generic problem as far as a driver is concerned.

We need to handle an interrupt and inform the user space on the event and
pass the data correspodning to the event.

The event can be informed through SIGNAL and the signal handler can be
invoked in the user space. Then again for data, we need to have the
"copy_to_user" mechanism .

Is there any other effective mechanism(s) to handle the interrupt. I mean
we need to convey the event and or data to the user space(prefer -
asynchronously).

Please share your views.

Sanil.


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Interrupt handling
  2003-10-16 13:16 Interrupt handling Sanil K
@ 2003-10-16 13:51 ` Richard B. Johnson
  2003-10-16 19:55   ` Maciej Zenczykowski
  2003-10-16 18:53 ` George Anzinger
  2003-10-16 19:08 ` Tom Zanussi
  2 siblings, 1 reply; 6+ messages in thread
From: Richard B. Johnson @ 2003-10-16 13:51 UTC (permalink / raw)
  To: Sanil K; +Cc: Linux kernel

On Thu, 16 Oct 2003, Sanil K wrote:

> Hi all,
>
> This may be a generic problem as far as a driver is concerned.
>
> We need to handle an interrupt and inform the user space on the event and
> pass the data correspodning to the event.
>
> The event can be informed through SIGNAL and the signal handler can be
> invoked in the user space. Then again for data, we need to have the
> "copy_to_user" mechanism .
>

poll() / select() are the usual methods. User code sleeps in
select() or poll() and an interrupt occurs (before/after, doesn't
matter). Driver  code gets the data into a interrupt-safe buffer
then executes wake_up_interruptible() from its ISR. This will cause
the caller, sleeping in poll() to wake up as soon as the
ISR is complete.

The user then, checking poll status and flags, knows that
data are available, the user calls read() to get the data.

It is possible for a user-space program to memory-map
an interrupt-safe (locked in place) data area and have
the ISR write its data to this area. However, one still
needs some kind of synchronization to know when the
data have been received and are complete.

The memory-map idea has security problems, though.
If the area ever gets unmapped (the user exits), a
fatal error could occur in kernel mode within the
ISR. In general, it's always best to allocate an
interrupt-safe buffer within the driver (module),
that is guaranteed to persist as long as the driver
is installed. This ultimately means that a copy
operation is necessary.

Memory-to-memory copy is real fast now days. The
copy_to_user() is just memcpy() with a trap mechanism
that can save the kernel from a user-induced seg-fault.
The actual trap is hardware-induced in ix86 machines
and therefore adds no overhead to the normal copy operation.

> Is there any other effective mechanism(s) to handle the interrupt. I mean
> we need to convey the event and or data to the user space(prefer -
> asynchronously).
>
> Please share your views.
>
> Sanil.

Cheers,
Dick Johnson
Penguin : Linux version 2.4.22 on an i686 machine (797.90 BogoMips).
            Note 96.31% of all statistics are fiction.



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Interrupt handling
  2003-10-16 13:16 Interrupt handling Sanil K
  2003-10-16 13:51 ` Richard B. Johnson
@ 2003-10-16 18:53 ` George Anzinger
  2003-10-16 19:08 ` Tom Zanussi
  2 siblings, 0 replies; 6+ messages in thread
From: George Anzinger @ 2003-10-16 18:53 UTC (permalink / raw)
  To: Sanil K; +Cc: linux-kernel

Sanil K wrote:
> Hi all,
> 
> This may be a generic problem as far as a driver is concerned.
> 
> We need to handle an interrupt and inform the user space on the event and
> pass the data correspodning to the event.
> 
> The event can be informed through SIGNAL and the signal handler can be
> invoked in the user space. Then again for data, we need to have the
> "copy_to_user" mechanism .
> 
> Is there any other effective mechanism(s) to handle the interrupt. I mean
> we need to convey the event and or data to the user space(prefer -
> asynchronously).
> 
IF the amount of data is small, say a word or two or less, you can use the 
siginfo and a realtime signal.  This will get the data at the same time as the 
signal.  If you prefer to avoid the overhead of the signal, you can do 
sigwaitinfo() which avoids the floating point save/restore, but does require the 
task to wait (i.e. is not asynchronous).




-- 
George Anzinger   george@mvista.com
High-res-timers:  http://sourceforge.net/projects/high-res-timers/
Preemption patch: http://www.kernel.org/pub/linux/kernel/people/rml


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Interrupt handling
  2003-10-16 13:16 Interrupt handling Sanil K
  2003-10-16 13:51 ` Richard B. Johnson
  2003-10-16 18:53 ` George Anzinger
@ 2003-10-16 19:08 ` Tom Zanussi
  2 siblings, 0 replies; 6+ messages in thread
From: Tom Zanussi @ 2003-10-16 19:08 UTC (permalink / raw)
  To: Sanil K; +Cc: linux-kernel

[-- Attachment #1: Type: text/plain, Size: 2298 bytes --]

Sanil K wrote:
> Hi all,
> 
> This may be a generic problem as far as a driver is concerned.
> 
> We need to handle an interrupt and inform the user space on the event and
> pass the data correspodning to the event.
> 
> The event can be informed through SIGNAL and the signal handler can be
> invoked in the user space. Then again for data, we need to have the
> "copy_to_user" mechanism .
> 
> Is there any other effective mechanism(s) to handle the interrupt. I mean
> we need to convey the event and or data to the user space(prefer -
> asynchronously).
> 
> Please share your views.
> 

Hi.

You could use relayfs to do this; it was designed with this type of 
thing in mind - basically you use it to create a kernel buffer that you 
can write into from your module and then access the data using a file in 
the relayfs file system.  You can use read() or mmap() to access the 
data, depending on your needs.

If you just need to do this for debugging purposes, then the following 
patch to the relayfs version I posted on this list a couple of weeks ago 
might be of use, or you can use it as an example and do something 
similar in your own code.  Here's a link to the relayfs posting this 
patch needs to be applied to:

http://marc.theaimsgroup.com/?l=linux-kernel&m=106556134715271&w=2

Apply the attached patch on top of that, and then use klog() or 
klog_raw() to write to the buffer and from user space read() from 
/mnt/relay/klog, or similar depending on where you mounted relayfs.

If you expect to generate a lot of data, then it might be better to use 
mmap() to get at it.  For an example of this, you can look at the most 
recent version of the Linux Trace Toolkit I posted to the ltt and 
ltt-dev mailing lists around the same time.

Hope this helps,

Tom

Note:  this patch is based on a patch kindly contributed by Hubertus 
Franke, but I've added and changed things - in any case all 
responsibility for any problems with this code are mine alone.  Please 
send all comments/questions to me.  Thanks.


> Sanil.
> 
> -
> 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/
> 



[-- Attachment #2: klog1.patch --]
[-- Type: text/plain, Size: 7993 bytes --]

diff -urpN -X dontdiff linux-2.6.0-test6.prev/fs/Kconfig linux-2.6.0-test6.cur/fs/Kconfig
--- linux-2.6.0-test6.prev/fs/Kconfig	Thu Oct 16 11:13:53 2003
+++ linux-2.6.0-test6.cur/fs/Kconfig	Thu Oct 16 11:17:20 2003
@@ -899,8 +899,8 @@ config RELAYFS_FS
 	  an efficient mechanism for tools and facilities to relay large
 	  amounts of data from kernel space to user space.  It's not useful
 	  on its own, and should only be enabled if other facilities that
-	  need it are enabled, such as for example dynamic printk or the
-	  Linux Trace Toolkit.
+	  need it are enabled, such as for example klog or the Linux Trace
+	  Toolkit.
 
 	  See <file:Documentation/filesystems/relayfs.txt> for further
 	  information.
@@ -911,6 +911,36 @@ config RELAYFS_FS
 	  module, say M here and read <file:Documentation/modules.txt>.
 
 	  If unsure, say N.
+
+config KLOG_CHANNEL
+	bool "Enable klog debugging support"
+	depends on RELAYFS_FS
+	help
+	  If you say Y to this, a relayfs channel named klog will be created
+	  in the root of the relayfs file system.  You can write to the klog
+	  channel using klog() or klog_raw() from within the kernel or
+	  kernel modules, and read from the klog channel by mounting relayfs
+	  and using read(2) to read from it (or using cat).  If you're not  
+	  sure, say N.
+
+config KLOG_CHANNEL_AUTOENABLE
+	bool "Enable klog logging on startup"
+	depends on KLOG_CHANNEL
+	default y
+	help
+	  If you say Y to this, the klog channel will be automatically enabled
+	  on startup.  Otherwise, to turn klog logging on, you need use
+	  sysctl (kernel.klog_enabled).  This option is used in cases where
+	  you don't actually want the channel to be written to until it's
+	  enabled.  If you're not sure, say Y.
+
+config KLOG_CHANNEL_SHIFT
+	depends on KLOG_CHANNEL
+	int "klog debugging channel size (16 => 64KB, 22 => 4MB)"
+	range 16 22
+	default 21
+	help
+	  Select klog debugging channel size as a power of 2.
 
 endmenu
 
diff -urpN -X dontdiff linux-2.6.0-test6.prev/fs/relayfs/Makefile linux-2.6.0-test6.cur/fs/relayfs/Makefile
--- linux-2.6.0-test6.prev/fs/relayfs/Makefile	Thu Oct 16 11:13:53 2003
+++ linux-2.6.0-test6.cur/fs/relayfs/Makefile	Thu Oct 16 11:17:20 2003
@@ -3,5 +3,6 @@
 #
 
 obj-$(CONFIG_RELAYFS_FS) += relayfs.o
+obj-$(CONFIG_KLOG_CHANNEL) += klog.o
 
 relayfs-objs := relay.o relay_lockless.o relay_locking.o inode.o
diff -urpN -X dontdiff linux-2.6.0-test6.prev/fs/relayfs/inode.c linux-2.6.0-test6.cur/fs/relayfs/inode.c
--- linux-2.6.0-test6.prev/fs/relayfs/inode.c	Thu Oct 16 11:13:53 2003
+++ linux-2.6.0-test6.cur/fs/relayfs/inode.c	Thu Oct 16 11:17:20 2003
@@ -551,10 +551,17 @@ static struct file_system_type relayfs_f
 	.kill_sb	= kill_litter_super,
 };
 
+extern int create_klog_channel(void);
+
 static int __init 
 init_relayfs_fs(void)
 {
-	return register_filesystem(&relayfs_fs_type);
+	int err = register_filesystem(&relayfs_fs_type);
+#ifdef CONFIG_KLOG_CHANNEL
+	if (!err)
+		create_klog_channel();
+#endif
+	return err;
 }
 
 static void __exit 
diff -urpN -X dontdiff linux-2.6.0-test6.prev/fs/relayfs/klog.c linux-2.6.0-test6.cur/fs/relayfs/klog.c
--- linux-2.6.0-test6.prev/fs/relayfs/klog.c	Wed Dec 31 18:00:00 1969
+++ linux-2.6.0-test6.cur/fs/relayfs/klog.c	Thu Oct 16 11:52:47 2003
@@ -0,0 +1,116 @@
+/*
+ * KLOG		Generic Logging facility built upon the relayfs infrastructure
+ *
+ * Authors:	Hubertus Franke  (frankeh@us.ibm.com)
+ *		Tom Zanussi  (zanussi@us.ibm.com)
+ *
+ *		Please direct all questions/comments to zanussi@us.ibm.com
+ *
+ *		Copyright (C) 2003, IBM Corp
+ *
+ *		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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/smp_lock.h>
+#include <linux/console.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/config.h>
+#include <linux/delay.h>
+#include <linux/smp.h>
+#include <linux/relayfs_fs.h>
+#include <linux/klog.h>
+
+#ifdef KLOG_CHANNEL_AUTOENABLE
+int klog_enabled = 1;
+#else
+int klog_enabled = 0;
+#endif
+EXPORT_SYMBOL(klog_enabled);
+
+int klog_channel = -1;
+
+static char buf[NR_CPUS][KLOG_BUF_SIZE];
+
+/**
+ *	klog - write a formatted string into the klog channel
+ *	@fmt: format string
+ *
+ *	Returns number of bytes written, negative number on failure.
+ */
+int klog(const char *fmt, ...)
+{
+	va_list args;
+	int len, err;
+	char *cbuf;
+	unsigned long flags;
+	
+	if (!klog_enabled || klog_channel < 0) 
+		return 0;
+
+	local_irq_save(flags);
+	cbuf = buf[smp_processor_id()];
+
+	va_start(args, fmt);
+	len = vsnprintf(cbuf, KLOG_BUF_SIZE, fmt, args);
+	va_end(args);
+	
+	err = relay_write(klog_channel, cbuf, len, -1);
+	local_irq_restore(flags);
+
+	return err;
+}
+
+/**
+ *	klog_raw - directly write into the klog channel
+ *	@buf: buffer containing data to write
+ *	@len: # bytes to write
+ *
+ *	Returns number of bytes written, negative number on failure.
+ */
+int klog_raw(const char *buf,int len)
+{
+	int err = 0;
+	
+	if (klog_enabled && klog_channel >= 0)
+		err = relay_write(klog_channel, buf, len, -1);
+
+	return err;
+}
+
+/* internal - creates channel file /mnt/relay/klog */
+int create_klog_channel(void)
+{
+	u32 bufsize, nbufs;
+
+	u32 channel_flags = RELAY_DELIVERY_PACKET | RELAY_USAGE_GLOBAL;
+	channel_flags |= RELAY_SCHEME_ANY | RELAY_TIMESTAMP_ANY;
+	
+	bufsize = 1 << (CONFIG_KLOG_CHANNEL_SHIFT - 2); /* size of sub-buffers */
+	nbufs = 4;
+
+	klog_channel = relay_open("klog",
+				  bufsize,
+				  nbufs,
+				  channel_flags,
+				  NULL,
+				  0,
+				  0,
+				  0,
+				  0,
+				  0);
+
+	if (klog_channel < 0)
+		printk("klog channel creation failed, errcode: %d\n", klog_channel);
+	else
+		printk("klog channel created (%u bytes)\n", 1 << CONFIG_KLOG_CHANNEL_SHIFT);
+
+	return klog_channel;
+}
+
+EXPORT_SYMBOL(klog);
+EXPORT_SYMBOL(klog_raw);
diff -urpN -X dontdiff linux-2.6.0-test6.prev/include/linux/klog.h linux-2.6.0-test6.cur/include/linux/klog.h
--- linux-2.6.0-test6.prev/include/linux/klog.h	Wed Dec 31 18:00:00 1969
+++ linux-2.6.0-test6.cur/include/linux/klog.h	Thu Oct 16 11:41:01 2003
@@ -0,0 +1,29 @@
+/*
+ * KLOG		Generic Logging facility built upon the relayfs infrastructure
+ *
+ * Authors:	Hubertus Frankeh  (frankeh@us.ibm.com)
+ *		Tom Zanussi  (zanussi@us.ibm.com)
+ *
+ *		Please direct all questions/comments to zanussi@us.ibm.com
+ *
+ *		Copyright (C) 2003, IBM Corp
+ *
+ *
+ *		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.
+ */
+
+#ifndef _LINUX_KLOG_H
+#define _LINUX_KLOG_H
+
+extern int klog_channel;
+
+#define KLOG_BUF_SIZE (512)     /* maximum size of formatting buffer for klog
+				 * beyond which truncation will take place */
+
+int klog(const char *fmt, ...);
+int klog_raw(const char *buf,int len); 
+
+#endif	/* _LINUX_KLOG_H */
diff -urpN -X dontdiff linux-2.6.0-test6.prev/kernel/sysctl.c linux-2.6.0-test6.cur/kernel/sysctl.c
--- linux-2.6.0-test6.prev/kernel/sysctl.c	Sat Sep 27 19:50:09 2003
+++ linux-2.6.0-test6.cur/kernel/sysctl.c	Thu Oct 16 11:17:20 2003
@@ -93,6 +93,7 @@ extern int pwrsw_enabled;
 extern int unaligned_enabled;
 #endif
 
+extern int klog_enabled;
 #ifdef CONFIG_ARCH_S390
 #ifdef CONFIG_MATHEMU
 extern int sysctl_ieee_emulation_warnings;
@@ -577,6 +578,14 @@ static ctl_table kern_table[] = {
 		.ctl_name	= KERN_PANIC_ON_OOPS,
 		.procname	= "panic_on_oops",
 		.data		= &panic_on_oops,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec,
+	},
+	{
+		.ctl_name	= 100, // just make up a number
+		.procname	= "klog_enabled",
+		.data		= &klog_enabled,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
 		.proc_handler	= &proc_dointvec,

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Interrupt handling
  2003-10-16 13:51 ` Richard B. Johnson
@ 2003-10-16 19:55   ` Maciej Zenczykowski
  2003-10-16 20:10     ` Richard B. Johnson
  0 siblings, 1 reply; 6+ messages in thread
From: Maciej Zenczykowski @ 2003-10-16 19:55 UTC (permalink / raw)
  To: Richard B. Johnson; +Cc: Sanil K, Linux kernel

On Thu, 16 Oct 2003, Richard B. Johnson wrote:

> The memory-map idea has security problems, though.
> If the area ever gets unmapped (the user exits), a
> fatal error could occur in kernel mode within the
> ISR. In general, it's always best to allocate an
> interrupt-safe buffer within the driver (module),
> that is guaranteed to persist as long as the driver
> is installed. This ultimately means that a copy
> operation is necessary.
> 
> Memory-to-memory copy is real fast now days. The
> copy_to_user() is just memcpy() with a trap mechanism
> that can save the kernel from a user-induced seg-fault.
> The actual trap is hardware-induced in ix86 machines
> and therefore adds no overhead to the normal copy operation.

Is there any reason why we couldn't via kernel routine let user space 
access read-only certain pages of kernel memory?  I.e. having the 
userspace function call the driver to map into it's (user) address space a 
read-only mapping of the drivers (kernel) private r/w area?
If I'm not mistaken this is doable on x86 hardware isn't it?

Cheers,
MaZe.


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Interrupt handling
  2003-10-16 19:55   ` Maciej Zenczykowski
@ 2003-10-16 20:10     ` Richard B. Johnson
  0 siblings, 0 replies; 6+ messages in thread
From: Richard B. Johnson @ 2003-10-16 20:10 UTC (permalink / raw)
  To: Maciej Zenczykowski; +Cc: Sanil K, Linux kernel

On Thu, 16 Oct 2003, Maciej Zenczykowski wrote:

> On Thu, 16 Oct 2003, Richard B. Johnson wrote:
>
> > The memory-map idea has security problems, though.
> > If the area ever gets unmapped (the user exits), a
> > fatal error could occur in kernel mode within the
> > ISR. In general, it's always best to allocate an
> > interrupt-safe buffer within the driver (module),
> > that is guaranteed to persist as long as the driver
> > is installed. This ultimately means that a copy
> > operation is necessary.
> >
> > Memory-to-memory copy is real fast now days. The
> > copy_to_user() is just memcpy() with a trap mechanism
> > that can save the kernel from a user-induced seg-fault.
> > The actual trap is hardware-induced in ix86 machines
> > and therefore adds no overhead to the normal copy operation.
>
> Is there any reason why we couldn't via kernel routine let user space
> access read-only certain pages of kernel memory?  I.e. having the
> userspace function call the driver to map into it's (user) address space a
> read-only mapping of the drivers (kernel) private r/w area?
> If I'm not mistaken this is doable on x86 hardware isn't it?
>
> Cheers,
> MaZe.
>
No reason. From user-space, using mmap, you can read the screen-memory
at 0xb8000, for instance, ........
-d b8000
000B8000  63 09 64 09 72 09 6F 09-6D 09 20 07 20 07 20 07   c.d.r.o.m. . . .
000B8010  20 07 20 07 20 07 20 07-20 07 20 07 20 07 20 07    . . . . . . . .
[SNIPPED]

You can look access many kernel areas that way. The probem is:

(1) When are new data available, and how much.
(2) How do you keep it from being overwritten by the next interrupt
    before it's been read.

These, and other, problems are why there are 'standard' ways of doing
things.

Cheers,
Dick Johnson
Penguin : Linux version 2.4.22 on an i686 machine (797.90 BogoMips).
            Note 96.31% of all statistics are fiction.



^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2003-10-16 20:13 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2003-10-16 13:16 Interrupt handling Sanil K
2003-10-16 13:51 ` Richard B. Johnson
2003-10-16 19:55   ` Maciej Zenczykowski
2003-10-16 20:10     ` Richard B. Johnson
2003-10-16 18:53 ` George Anzinger
2003-10-16 19:08 ` Tom Zanussi

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox