[Fault-injection-developer] RFC: FI_IRQ
Status: Alpha
Brought to you by:
rustyl
From: Wang, S. <sta...@in...> - 2002-12-26 10:41:51
|
Hi, folks I implemented the irq interceptor(FI_IRQ) base on Louis' prototype :) Just add sysfs interface(shamelessly copy from Rusty :) for it. Here is the patch: # This is a BitKeeper generated patch for the following project: # Project Name: Linux kernel tree # This patch format is intended for GNU patch command version 2.5 or higher. # This patch includes the following deltas: # ChangeSet 1.957 -> 1.961 # arch/i386/Kconfig 1.27 -> 1.28 # drivers/char/fi/Makefile 1.8 -> 1.9 # include/linux/fi.h 1.6 -> 1.7 # (new) -> 1.3 drivers/char/fi/fi_irq.c # # The following is the BitKeeper ChangeSet Log # -------------------------------------------- # 02/12/26 st...@ma... 1.954.1.1 # Merge manticore.sh.intel.com:/home/stanley/linux-2.5 # into manticore.sh.intel.com:/home/stanley/work/2.5-kirq # -------------------------------------------- # 02/12/26 st...@ma... 1.954.1.2 # Add dispatch_kirq # -------------------------------------------- # 02/12/26 st...@ma... 1.956.1.1 # Add fi_irq # -------------------------------------------- # 02/12/26 st...@ma... 1.958 # Merge bk://fau...@fa.../linux-2.5 # into manticore.sh.intel.com:/home/stanley/fi-bkbits # -------------------------------------------- # 02/12/26 st...@ma... 1.959 # Merge st...@ma...:/home/stanley/work/2.5-kirq # into manticore.sh.intel.com:/home/stanley/fi-bkbits # -------------------------------------------- # 02/12/26 st...@ma... 1.960 # Bug fix for fi_irq # -------------------------------------------- # 02/12/26 st...@ma... 1.961 # Fix print issues. # Add check to intercept timer's irq. # -------------------------------------------- # diff -Nru a/arch/i386/Kconfig b/arch/i386/Kconfig --- a/arch/i386/Kconfig Thu Dec 26 18:23:43 2002 +++ b/arch/i386/Kconfig Thu Dec 26 18:23:43 2002 @@ -1567,6 +1567,24 @@ If in doubt, say N. +config FI_IRQ + tristate "Fault Injection Irq Interceptor (EXPERIMENTAL)" + depends on KIRQ + depends on FI + help + This component adds the ability for Fault Injection to intercept + specified irq's handler. When combined with the core fault + injection infrastructure and a user space tool chain, it + will be possible to create test cases that inject fault into + driver's isr. + + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called fi_irq.o. If you want to compile it as + a module, say M here and read <file:Documentation/modules.txt>. + + If in doubt, say N. + config FI_TEST tristate "Fault Injection Test Driver (EXPERIMENTAL)" depends on FI diff -Nru a/drivers/char/fi/Makefile b/drivers/char/fi/Makefile --- a/drivers/char/fi/Makefile Thu Dec 26 18:23:43 2002 +++ b/drivers/char/fi/Makefile Thu Dec 26 18:23:43 2002 @@ -7,6 +7,7 @@ EXTRA_AFLAGS := -traditional obj-$(CONFIG_FI) += fi_core.o +obj-$(CONFIG_FI_IRQ) += fi_irq.o obj-$(CONFIG_FI_TEST) += fi_test.o obj-$(CONFIG_FI_MOCKS) += fi_mock_interceptor.o fi_mock_cs.o fi_sample_cs.o export-objs := fi_core.o diff -Nru a/drivers/char/fi/fi_irq.c b/drivers/char/fi/fi_irq.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/char/fi/fi_irq.c Thu Dec 26 18:23:43 2002 @@ -0,0 +1,253 @@ +/************************************************************************** **** + * Fault Injection Test harness Irq Interceptor(FI) + * Copyright (C) Intel Crop. + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + **************************************************************************** ** + * Contributors: + * Louis Zhuang <lou...@in...> + * Stanley Wang <sta...@in...> + * Rusty Lynch <rus...@in...> + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/interrupt.h> + +#include <linux/fi_internal.h> +#include <linux/fi.h> +#include <asm/kirq.h> + +struct fi_irq_faultset{ + int irq_spurious_hertz;//0 means never do this + int irq_delay_hertz; + int irq_delay_time;//0 means lost + int num; + char devname[80]; +}; + +static DECLARE_MUTEX(irq_sem); +static int in_used=0; +static struct fi_irq_faultset irq_fs[1]; + +static int irq_spurious_count=0; +static int irq_delay_count=0; +static int irq_delay_time_count=0; +static atomic_t irq_delay_num=ATOMIC_INIT(0); +int fi_irq_handler(struct kirq *k, int num, void *id, struct pt_regs *regs) +{ + if (num == 0) { //it is timer interrupt + dispatch_kirq(num, regs);//dispatch timer first + + if (irq_fs->irq_spurious_hertz){ + irq_spurious_count++; + if (irq_spurious_count>=irq_fs->irq_spurious_hertz){ + irq_spurious_count=0; + dispatch_kirq(irq_fs->num, regs); + info("dispatch a spurious %s interrupt, num# %d\n", irq_fs->devname, irq_fs->num); + } + } + + if (atomic_read(&irq_delay_num)) { + irq_delay_time_count++; + if (irq_delay_time_count>=irq_fs->irq_delay_time) { + irq_delay_time_count=0; + atomic_dec(&irq_delay_num); + dispatch_kirq(irq_fs->num, regs); + info("dispatch a delayed %s interrupt, num# %d\n", irq_fs->devname, irq_fs->num); + } + } + }else if (num == irq_fs->num) { //it is fake_irq + if (irq_fs->irq_delay_hertz) { + irq_delay_count++; + if (irq_delay_count>=irq_fs->irq_delay_hertz) { + if (irq_fs->irq_delay_time){ + //FIXME:add spin lock + atomic_inc(&irq_delay_num); + info("announce a delayed %s interrupt, num# %d, jiffies: %ld\n", + irq_fs->devname, num, jiffies); + }else{ + info("announce a lost %s interrupt, num# %d\n", irq_fs->devname, num); + } + irq_delay_count=0; + + } else { + dispatch_kirq(num, regs);//dispatch timer first + } + } else { + dispatch_kirq(num, regs);//dispatch timer first + } + }else{ + err("error interrupt! num# %d\n", num); + } + return 1; +} + + +static int set_irq_faultset(struct fi_irq_faultset *f) { + int rv=0; + + strncpy(irq_fs->devname, f->devname, 80); + irq_fs->num = f->num; + irq_fs->irq_spurious_hertz = f->irq_spurious_hertz; + irq_fs->irq_delay_hertz = f->irq_delay_hertz; + irq_fs->irq_delay_time = f->irq_delay_time; + + if ( register_kirq(irq_fs->num, irq_fs->devname, fi_irq_handler) != 0) { + dbg("set irq faultset fail@%s, irq=%d, devname=%s, handler=%p\n", + __FUNCTION__, irq_fs->num, irq_fs->devname, fi_irq_handler); + rv = -EINVAL; + goto exit; + } + if ( register_kirq(0, "timer", fi_irq_handler) != 0) { + dbg("set irq faultset fail@%s, irq=0, devname=timer, handler=%p\n", + __FUNCTION__, fi_irq_handler); + rv = -EINVAL; + } + +exit: + return rv; +}; +static void clear_irq_faultset(void) +{ + unregister_kirq(0); + unregister_kirq(irq_fs->num); + + irq_fs->num =0; + irq_fs->irq_spurious_hertz =0; + irq_fs->irq_delay_hertz =0; + irq_fs->irq_delay_time =0; + + /* clear vars used by fi_irq_handler */ + irq_spurious_count=0; + irq_delay_count=0; + irq_delay_time_count=0; + atomic_set(&irq_delay_num, 0); +}; + +static ssize_t ctl_show(struct interceptor * p, char * page, + size_t count, loff_t off) +{ + return off ? 0 : snprintf(page,count,"IRQ Faultset:\n \ + Device Name = %s\n \ + IRQ number = %d\n \ + Spurious Hertz = %d\n \ + Delay Hertz = %d\n \ + Delay Time = %d\n\n", irq_fs->num ? \ + irq_fs->devname : "(NULL)", \ + irq_fs->num, irq_fs->irq_spurious_hertz, \ + irq_fs->irq_delay_hertz, \ + irq_fs->irq_delay_time); +} + +static ssize_t ctl_store(struct interceptor * p, const char * page, + size_t count, loff_t off) +{ + char ctl[16]; + int num; + int error=0; + int ret = 0; + struct fi_irq_faultset tmp; + + if (off) + return 0; + + /* 3 4 5 6 7 8 */ + /* ctl irq dn sh dh dt */ + num = sscanf(page,"%15s %i %s %i %i %i", + ctl, /* 3 */ + &tmp.num, /* 4 */ + tmp.devname, /* 5 */ + &tmp.irq_spurious_hertz, /* 6 */ + &tmp.irq_delay_hertz, /* 7 */ + &tmp.irq_delay_time); /* 8 */ + if (!num) { + err("Invalid command format, translated no commands"); + error = -EINVAL; + goto Done; + } + + if (!strcmp(ctl,"add") && num == 6){ + if (tmp.num == 0) { + err("Intercept Timer IRQ is not permitted!\n"); + goto Done; + } + down(&irq_sem); + if ((in_used == 0) && ((error = set_irq_faultset(&tmp)) == 0)) { + in_used++; + up(&irq_sem); + } else { + err("Wrong IRQ faultset OR IRQ_INTERCEPTOR is in used!\n"); + up(&irq_sem); + } + } else if (!strcmp(ctl,"del") && num == 1) { + down(&irq_sem); + if (in_used == 1) { + clear_irq_faultset(); + in_used--; + up(&irq_sem); + } else { + err("IRQ_INTERCEPTOR is not in used!\nNO irq faultset to remove.\n"); + up(&irq_sem); + } + } else { + err("Invalid command format: %s, %i tokens found",ctl,num); + error = -EINVAL; + } + ret = error ? error : count; + Done: + return ret; +} + +static struct interceptor_attribute attr_ctl = { + .attr = { .name = "ctl", .mode = 0644 }, + .show = ctl_show, + .store = ctl_store +}; + +static struct interceptor irq_interceptor = { + .kobj = {.name = "irq_interceptor"}, + .arm = NULL, + .disarm = NULL, + .corrupt = NULL +}; + +static int __init fi_irq_init(void) +{ + irq_interceptor.type = INTERCEPTOR_TYPE_IRQ; + if (fi_register_interceptor(&irq_interceptor)) { + dbg("Failed to register irq Interceptor"); + return -EINVAL; + } + + sysfs_create_file(&irq_interceptor.kobj, &attr_ctl.attr); + return 0; +} + +static void __exit fi_irq_exit (void) +{ + sysfs_remove_file(&irq_interceptor.kobj, &attr_ctl.attr); + fi_unregister_interceptor(&irq_interceptor); +} + +module_init(fi_irq_init); +module_exit(fi_irq_exit); + + +MODULE_DESCRIPTION("Implementation for inject fault into IRQ"); +MODULE_LICENSE("GPL"); + diff -Nru a/include/linux/fi.h b/include/linux/fi.h --- a/include/linux/fi.h Thu Dec 26 18:23:43 2002 +++ b/include/linux/fi.h Thu Dec 26 18:23:43 2002 @@ -58,6 +58,7 @@ INTERCEPTOR_TYPE_UNKNOWN=0, INTERCEPTOR_TYPE_MMIO=1, INTERCEPTOR_TYPE_PIO=2, + INTERCEPTOR_TYPE_IRQ=3, } interceptor_type_t; struct trigger; Your Sincerely, Stanley Wang SW Engineer, Intel Corporation. Intel China Software Lab. Tel: 021-52574545 ext. 1171 iNet: 8-752-1171 Opinions expressed are those of the author and do not represent Intel Corporation |