From: Amit S. <ami...@qu...> - 2007-11-07 19:44:40
|
This kernel module injects IRQs specified on the command line via the passthrough parameter This doesn't handle shared interrupts. These patches don't yet work with the in-kernel apic, so you have to use -no-kvm-irqchip. These will soon be overridden by a new mechanism that utilises the in-kernel apic. Signed-off-by: Amit Shah <ami...@qu...> --- Makefile | 10 ++- irqhook/Kbuild | 3 + irqhook/Makefile | 25 ++++++ irqhook/irqhook_main.c | 217 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 251 insertions(+), 4 deletions(-) create mode 100644 irqhook/Kbuild create mode 100644 irqhook/Makefile create mode 100644 irqhook/irqhook_main.c diff --git a/Makefile b/Makefile index 776ff01..4ba6221 100644 --- a/Makefile +++ b/Makefile @@ -5,13 +5,13 @@ DESTDIR= rpmrelease = devel -.PHONY: kernel user libkvm qemu bios clean +.PHONY: kernel irqhook user libkvm qemu bios clean -all: $(if $(WANT_MODULE), kernel) user libkvm qemu +all: $(if $(WANT_MODULE), kernel irqhook) user libkvm qemu kcmd = $(if $(WANT_MODULE),,@\#) -qemu kernel user libkvm: +qemu kernel user irqhook libkvm: $(MAKE) -C $@ qemu: libkvm @@ -42,6 +42,7 @@ install-rpm: install: $(kcmd)make -C kernel DESTDIR="$(DESTDIR)" install + $(kcmd)make -C irqhook DESTDIR="$(DESTDIR)" install make -C libkvm DESTDIR="$(DESTDIR)" install make -C qemu DESTDIR="$(DESTDIR)" install @@ -62,13 +63,14 @@ srpm: tar czf SOURCES/user.tar.gz user tar czf SOURCES/libkvm.tar.gz libkvm tar czf SOURCES/kernel.tar.gz kernel + tar czf SOURCES/irqhook.tar.gz irqhook tar czf SOURCES/scripts.tar.gz scripts cp Makefile configure kvm_stat SOURCES rpmbuild --define="_topdir $$(pwd)" -bs $(tmpspec) $(RM) $(tmpspec) clean: - for i in $(if $(WANT_MODULE), kernel) user libkvm qemu; do \ + for i in $(if $(WANT_MODULE), kernel irqhook) user libkvm qemu; do \ make -C $$i clean; \ done rm -f config.mak user/config.mak diff --git a/irqhook/Kbuild b/irqhook/Kbuild new file mode 100644 index 0000000..9af75a4 --- /dev/null +++ b/irqhook/Kbuild @@ -0,0 +1,3 @@ +EXTRA_CFLAGS := -I$(src)/include +obj-m := irqhook.o +irqhook-objs := irqhook_main.o diff --git a/irqhook/Makefile b/irqhook/Makefile new file mode 100644 index 0000000..3b1d851 --- /dev/null +++ b/irqhook/Makefile @@ -0,0 +1,25 @@ +include ../config.mak + +KVERREL = $(patsubst /lib/modules/%/build,%,$(KERNELDIR)) + +DESTDIR= + +INSTALLDIR = $(patsubst %/build,%/extra,$(KERNELDIR)) + +rpmrelease = devel + +LINUX = ../linux-2.6 + +all:: + $(MAKE) -C $(KERNELDIR) M=`pwd` "$$@" + +#sync: +# rsync --exclude='*.mod.c' "$(LINUX)"/drivers/irqhook/*.[ch] . + +install: + mkdir -p $(DESTDIR)/$(INSTALLDIR) + cp *.ko $(DESTDIR)/$(INSTALLDIR) + /sbin/depmod -a + +clean: + $(MAKE) -C $(KERNELDIR) M=`pwd` $@ diff --git a/irqhook/irqhook_main.c b/irqhook/irqhook_main.c new file mode 100644 index 0000000..812b714 --- /dev/null +++ b/irqhook/irqhook_main.c @@ -0,0 +1,217 @@ +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/fs.h> +#include <linux/bitmap.h> +#include <linux/interrupt.h> +#include <linux/spinlock.h> +#include <linux/miscdevice.h> +#include <linux/pci.h> + +#include <asm/uaccess.h> + +#define irqh_VERSION "0.0.1" +#define irqh_MODULE_NAME "irqhook" +#define irqh_DRIVER_NAME irqh_MODULE_NAME " HW IRQ hook " irqh_VERSION + +// based on earlier proprietary Tutis code; this modified version goes under GPL +MODULE_AUTHOR("Nir Peleg - Tutis"); +MODULE_DESCRIPTION("IRQ hook driver"); +MODULE_LICENSE("GPL"); + +//#define irqh_DEBUG /* define to enable copious debugging info */ + +#ifdef irqh_DEBUG +#define DPRINTK(fmt, args...) printk("<1>" "%s: " fmt, __FUNCTION__ , ## args) +#else +#define DPRINTK(fmt, args...) +#endif + +#define ERROR(fmt, args...) printk("<1>" "%s: " fmt, __FUNCTION__ , ## args) + +static spinlock_t irqh_lock; +static wait_queue_head_t irqh_proc_list; + +enum {NINTR = 256}; + +static DECLARE_BITMAP(pending, NINTR); +static DECLARE_BITMAP(handled, NINTR); + +#define irqh_on(which, bit) test_bit(bit, which) +#define irqh_set(which, bit) set_bit(bit, which) +#define irqh_clear(which, bit) clear_bit(bit, which) +#define irqh_ffs(which) find_first_bit(which, NINTR) + +static irqreturn_t +irqh_interrupt(int irq, void *p) +{ + unsigned long flags; + + DPRINTK("interrupt: %d\n", irq); + if (!irqh_on(handled, irq)) + return IRQ_HANDLED; + spin_lock_irqsave(&irqh_lock, flags); + irqh_set(pending, irq); + wake_up_interruptible(&irqh_proc_list); + spin_unlock_irqrestore(&irqh_lock, flags); + disable_irq_nosync(irq); + return IRQ_HANDLED; +} + +static ssize_t +irqh_dev_write(struct file *fp, const char *buf, size_t size, loff_t *offp) +{ + int n, device, func, devfn; + char arg[32], *cp, *cp1; + struct pci_dev *pdp = 0; + + DPRINTK("ENTER\n"); + if ((fp->f_mode & FMODE_WRITE) == 0 || size > sizeof arg) + return -EINVAL; + + if (size >= sizeof arg || copy_from_user(arg, buf, size)) + return -EFAULT; + arg[size] = 0; + cp = arg + (arg[0] == '+' || arg[0] == '-'); + n = simple_strtol(cp, &cp1, 0); + if (*cp1 == ':') { + device = simple_strtol(cp1+1, &cp1, 0); + func = simple_strtol(cp1+1, NULL, 0); + DPRINTK("PCI dev %d:%d.%d\n", n, device, func); + devfn = PCI_DEVFN(device, func); + for_each_pci_dev(pdp) { + if (pdp->bus->number == n && pdp->devfn == devfn) { + n = pdp->irq; + goto found; + } + } + ERROR("PCI device not found\n"); + return -ENOENT; + } + found: + DPRINTK("IRQ %d\n", n); + if (arg[0] == '+') { + if (pdp) { + if (pci_enable_device(pdp)) + ERROR("device not enabled\n"); + if ((unsigned)(n = pdp->irq) >= NINTR) { + ERROR("device has invalid IRQ set\n"); + return -EINVAL; + } + } + if (irqh_on(handled, n)) + return -EBUSY; + if (request_irq(n, irqh_interrupt, IRQF_SHARED, irqh_MODULE_NAME, (void *)irqh_interrupt)) { + ERROR("request_irq failed\n"); + return -EIO; + } + printk("Bound machine irq %d\n", n); + irqh_set(handled, n); + goto done; + } + if ((unsigned)n >= NINTR) + return -EINVAL; + if (arg[0] == '-') { + if (pdp) + pci_disable_device(pdp); + free_irq(n, (void *)irqh_interrupt); + irqh_clear(handled, n); + } else + enable_irq(n); + + done: + DPRINTK("DONE\n"); + return size; +} + +static ssize_t +irqh_dev_read(struct file *fp, char *buf, size_t size, loff_t *offp) +{ + char b[20]; + int m = -ERESTARTSYS, n; + + DECLARE_WAITQUEUE(wait, current); + + DPRINTK("ENTER\n"); + if ((fp->f_mode & FMODE_READ) == 0) + return -EINVAL; + spin_lock_irq(&irqh_lock); + while (!signal_pending(current)) { + if ((n = irqh_ffs(pending)) < NINTR) { + if ((m = sprintf(b, "%d", n) + 1) > size) + m = size; + if (copy_to_user(buf, b, m)) + m = -EFAULT; + else + irqh_clear(pending, n); + break; + } + if (fp->f_flags & O_NONBLOCK) { + m = -EWOULDBLOCK; + break; + } + add_wait_queue(&irqh_proc_list, &wait); + set_current_state(TASK_INTERRUPTIBLE); + spin_unlock_irq(&irqh_lock); + schedule(); + spin_lock_irq(&irqh_lock); + current->state = TASK_RUNNING; + remove_wait_queue(&irqh_proc_list, &wait); + } + spin_unlock_irq(&irqh_lock); + return m; +} + +static struct file_operations irqh_chrdev_ops = { + owner: THIS_MODULE, + read: irqh_dev_read, + write: irqh_dev_write, +}; + +#define irqh_MISCDEV_MINOR MISC_DYNAMIC_MINOR + +static struct miscdevice irqh_miscdev = { + irqh_MISCDEV_MINOR, + irqh_MODULE_NAME, + &irqh_chrdev_ops, +}; + +static int __init +irqh_init(void) +{ + int rc; + + DPRINTK("ENTER\n"); + + if (rc = misc_register(&irqh_miscdev)) { + printk(KERN_ERR irqh_MODULE_NAME ": " "cannot register misc device\n"); + DPRINTK("EXIT, returning %d\n", rc); + return rc; + } + + printk(KERN_INFO irqh_DRIVER_NAME " loaded\n"); + + init_waitqueue_head(&irqh_proc_list); + spin_lock_init(&irqh_lock); + + DPRINTK("EXIT, returning 0\n"); + return 0; +} + +static void __exit +irqh_cleanup(void) +{ + int n; + + DPRINTK("ENTER\n"); + + while ((n = irqh_ffs(handled)) < NINTR) { + irqh_clear(handled, n); + free_irq(n, (void *)irqh_interrupt); + } + misc_deregister (&irqh_miscdev); + + DPRINTK("EXIT\n"); +} + +module_init (irqh_init); +module_exit (irqh_cleanup); -- 1.5.3 |
From: Hollis B. <ho...@us...> - 2007-11-07 20:02:33
|
I'm sorry these comments aren't substantive, but please watch your whitespace... On Wed, 2007-11-07 at 21:45 +0200, Amit Shah wrote: > diff --git a/qemu/Makefile b/qemu/Makefile > index 053c88c..3e599f3 100644 > --- a/qemu/Makefile > +++ b/qemu/Makefile > @@ -37,7 +37,7 @@ qemu-img$(EXESUF): qemu-img.c cutils.c block.c > block-raw.c block-cow.c block-qco > dyngen$(EXESUF): dyngen.c > $(HOST_CC) $(CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) -o $@ $^ > > -clean: > +clean: > # avoid old build problems by removing potentially incorrect old > files > rm -f config.mak config.h op-i386.h opc-i386.h gen-op-i386.h > op-arm.h opc-arm.h gen-op-arm.h > rm -f *.o *.a $(TOOLS) dyngen$(EXESUF) TAGS cscope.* *.pod *~ > */*~ Extra space. > @@ -88,8 +88,8 @@ endif > test speed test2: all > $(MAKE) -C tests $@ > > -TAGS: > - etags *.[ch] tests/*.[ch] > +TAGS: > + etags *.[ch] tests/*.[ch] hw/passthrough/*.[ch] > > cscope: > rm -f ./cscope.* Another extra space. > diff --git a/qemu/exec.c b/qemu/exec.c > index 3e588d5..7a21ca5 100644 > --- a/qemu/exec.c > +++ b/qemu/exec.c > @@ -2484,6 +2484,7 @@ int cpu_register_io_memory(int io_index, > if (io_mem_nb >= IO_MEM_NB_ENTRIES) > return -1; > io_index = io_mem_nb++; > + fprintf(stderr, "iomem index %d out of %d\n", io_index, > IO_MEM_NB_ENTRIES); > } else { > if (io_index >= IO_MEM_NB_ENTRIES) > return -1; Bad indentation. I didn't check the rest of your patches for this, so you should skim them... -- Hollis Blanchard IBM Linux Technology Center |
From: Amit S. <ami...@qu...> - 2007-11-08 06:13:24
|
On Thursday 08 November 2007 01:31:32 Hollis Blanchard wrote: > I'm sorry these comments aren't substantive, but please watch your > whitespace... Hi Hollis, Thanks for going through this. We know about these issues; the userspace is kind of messy since it's collected from various sources and we are urging the people who have done this to provide good patches. These aren't ready yet for inclusion, we've sent them out to get comments on the overall solution for PCI passthrough. > On Wed, 2007-11-07 at 21:45 +0200, Amit Shah wrote: > > diff --git a/qemu/Makefile b/qemu/Makefile > > index 053c88c..3e599f3 100644 > > --- a/qemu/Makefile > > +++ b/qemu/Makefile > > @@ -37,7 +37,7 @@ qemu-img$(EXESUF): qemu-img.c cutils.c block.c > > block-raw.c block-cow.c block-qco > > dyngen$(EXESUF): dyngen.c > > $(HOST_CC) $(CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) -o $@ $^ > > > > -clean: > > +clean: > > # avoid old build problems by removing potentially incorrect old > > files > > rm -f config.mak config.h op-i386.h opc-i386.h gen-op-i386.h > > op-arm.h opc-arm.h gen-op-arm.h > > rm -f *.o *.a $(TOOLS) dyngen$(EXESUF) TAGS cscope.* *.pod *~ > > */*~ > > Extra space. > > > @@ -88,8 +88,8 @@ endif > > test speed test2: all > > $(MAKE) -C tests $@ > > > > -TAGS: > > - etags *.[ch] tests/*.[ch] > > +TAGS: > > + etags *.[ch] tests/*.[ch] hw/passthrough/*.[ch] > > > > cscope: > > rm -f ./cscope.* > > Another extra space. > > > diff --git a/qemu/exec.c b/qemu/exec.c > > index 3e588d5..7a21ca5 100644 > > --- a/qemu/exec.c > > +++ b/qemu/exec.c > > @@ -2484,6 +2484,7 @@ int cpu_register_io_memory(int io_index, > > if (io_mem_nb >= IO_MEM_NB_ENTRIES) > > return -1; > > io_index = io_mem_nb++; > > + fprintf(stderr, "iomem index %d out of %d\n", io_index, > > IO_MEM_NB_ENTRIES); > > } else { > > if (io_index >= IO_MEM_NB_ENTRIES) > > return -1; > > Bad indentation. > > I didn't check the rest of your patches for this, so you should skim > them... |