[Fault-injection-developer] Re:[PATCH] 47-kp2-fi2-dm3 features
Status: Alpha
Brought to you by:
rustyl
|
From: Rusty L. <ru...@li...> - 2002-11-27 02:57:28
|
> diff -Nur -X /home/louis/dontdiff 47-kp-fi/arch/i386/Kconfig 47-kp-fi-dm/arch/i386/Kconfig
> --- 47-kp-fi/arch/i386/Kconfig Mon Nov 25 15:15:40 2002
> +++ 47-kp-fi-dm/arch/i386/Kconfig Tue Nov 26 13:44:03 2002
> @@ -1577,6 +1577,13 @@
> Say Y here if you want to enable Fault Injection (FI) mechanism.
> The FI can monitor MMIO/IO access in kernel.
>
> +config FI_DM
> + tristate "Fault Injection Decision Maker"
> + depends on FI
> + help
> + Only support M here. It is a bug to be fixed. Decision Maker is to
> + control interceptors how/what to inject.
> +
If you want the choices to be module or nothing, then just code it that way.
Also please add a more descriptive comment for this component. Keep
in mind that the world will be stumbling across this option while
trying to configure a kernel, and would like to know something more then
the name of the module.
>
> config DEBUG_STACKOVERFLOW
> bool "Check for stack overflows"
> depends on DEBUG_KERNEL
> diff -Nur -X /home/louis/dontdiff 47-kp-fi/include/linux/fi/fi.h 47-kp-fi-dm/include/linux/fi/fi.h
> --- 47-kp-fi/include/linux/fi/fi.h Thu Jan 1 08:00:00 1970
> +++ 47-kp-fi-dm/include/linux/fi/fi.h Tue Nov 26 13:44:53 2002
> @@ -0,0 +1,189 @@
> +/******************************************************************************
> + * Fault Injection Test harness (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.
> + *
> + ******************************************************************************
> + */
> +
> +/* $Id: fi.h,v 1.3 2002/11/15 03:05:04 brlock Exp $
> + * Copyright by Intel Crop., 2002
> + * Louis Zhuang (lou...@in...)
> + *
> + */
> +
> +/** @file fi.h
> + * Fault Injection Test Harness Head File
> + * This file defines common data struct/type used by fi modules and command line tools.
> + */
> +#ifndef __FI_H
> +#define __FI_H
> +#define FI_VERSION "$Id: fi.h,v 1.3 2002/11/15 03:05:04 brlock Exp $"
> +
> +#include <asm/types.h>
> +#include <asm/atomic.h>
> +
> +/**
> + * define uniform watchpoint structure.
> + */
> +#define FI_WPTYPE_MMIO 4
> +#define FI_WPTYPE_READ 8
> +#define FI_WPTYPE_WRITE 16
> +#define FI_WPTYPE_EXEC 32
> +
> +#define FI_WPTYPE_LEN_MASK 3
> +#define FI_WPTYPE_ALL_MASK ( FI_WPTYPE_MMIO \
> + | FI_WPTYPE_READ \
> + | FI_WPTYPE_WRITE \
> + | FI_WPTYPE_EXEC \
> + | FI_WPTYPE_LEN_MASK \
> + )
> +
> +struct watchpoint{
> + /*address intercepted.*/
> + unsigned long addr;
> + /**
> + * intercepted type.
> + * bit 0-1 2^N bytes leng.
> + * bit 2 IO-space IO/MMIO
> + * bit 3 Read
> + * bit 4 Write
> + * bit 5 Execute(not implementation yet)
> + * XXX: you can not register the same address with IO and MMIO,
> + * but MMIO seldom uses low 64k space, so it is not a problem in fact.*/
> + unsigned int type;
> +};
Use 8-char indents (see Documentation/CodingStyle)
ditto on the rest of the file.
> +
> +#define WP_LEN(wp) (1<<((unsigned long)(wp.type)&3))
> +
> +#if 0
> +/**
> + * Define utitlty watchpoint inline function.
> + */
> +inline struct watchpoint WP(void *addr, int type) {
> + struct watchpoint wp;
> + wp.addr = addr;
> + wp.type =type;
> + return wp;
> +};
> +#endif
> +
Get rid of personal hacks.
> +
> +/** max number of triggers */
> +#define MAX_OP_PER_TRIGGER 4
> +#define MAX_TRIGGER_PER_FAULTSET 16
> +#define MAX_FAULTSET 16
> +struct fi_trigger{
> + /**
> + * This part contains properties of the trigger. It is seldom changed after initialization.
> + */
> + /**watchpoint which can trigger*/
> + struct watchpoint wp;
> +
> + /**bitmask for which you really care. 0-unmasked; 1-masked*/
> + __u32 bitmask;
> +
> + /**baseline you want to trigger after masked*/
> + int min;
> +
> + /**topline you want to trigger after masked
> + * XXX: it is CLOSED region. min<=val<=max*/
> + int max;
> +
> + /**trigger can start to work after skip times*/
> + int skip;
> +
> + /**trigger can stop after work stop times*/
> + int stop;
> +
> + /**bitmask for protection*/
> + int protection;
> +
> + /**HZ for random error*/
> + int hertz;
> +
> + /***/
> + struct {
> + /**0 - nothing; 1 - SET; 2 - AND; 3 - OR; 4 - NOT; 5 - XOR*/
> + enum{ FI_NOTHING=0, FI_SET=1, FI_AND=2, FI_OR=3, FI_NOT=4, FI_XOR=5, FI_NAND =6, FI_NOR=7, FI_ADD=8, FI_SUB=9,
> + }opcode;
> + int operand;
> + }ops[MAX_OP_PER_TRIGGER];
> +
> +
> + /**
> + * This part is statistic of the trigger. It should reflect the status of the trigger.
> + */
> + /*Whether the trigger is registerd*/
> + int registered;
> + /**times that is triggered*/
> + atomic_t count;
> +};
> +
> +
> +struct fi_faultset{
> + /***/
> + struct fi_trigger trigger_tb[MAX_TRIGGER_PER_FAULTSET];
> +
> + /**status: 0 - noused; 1 - enable; 2 - disable*/
> + enum {
> + NOUSED=0, ENABLED=1, DISABLED=2
> + }stat;
> +
> + char modname[256];
> +
> + /**more...*/
> +};
> +
> +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];
> + char modname[256];
> + void *id;
> +};
> +
> +struct fi_ins_record {
> + unsigned char *addr; /* Instruction's virtual address */
> + unsigned char opcode; /* The original opcode */
> +};
> +
> +struct fi_ins_record_header {
> + char modname[256];
> + int counter;
> + struct fi_ins_record inst[0];
> +};
> +
> +/*Define IOCTL number*/
> +#define FI_IOCTL_BASE 'F'
> +#define FIIOC_INSERT _IOW(FI_IOCTL_BASE, 0, struct fi_faultset)
> +#define FIIOC_REMOVE _IOW(FI_IOCTL_BASE, 1, int)
> +#define FIIOC_ENABLE _IOW(FI_IOCTL_BASE, 2, int)
> +#define FIIOC_DISABLE _IOW(FI_IOCTL_BASE, 3, int)
> +#define FIIOC_SET_IRQ_FAULTSET _IOW(FI_IOCTL_BASE, 4, struct fi_irq_faultset)
> +#define FIIOC_CLEAR_IRQ_FAULTSET _IO(FI_IOCTL_BASE, 5)
> +#define FIIOC_QUERY_PHYADDR _IOWR(FI_IOCTL_BASE, 6, unsigned long)
> +#define FIIOC_TRANS_INST _IOW(FI_IOCTL_BASE, 7, struct fi_ins_record_header)
> +#define FIIOC_QUERY_INTCPT _IO(FI_IOCTL_BASE, 8)
> +
> +#if 0
> +/** this is switch for fi*/
> +extern int g_fiIsEnabled;
> +#endif
> +
> +#endif/*__FI_H*/
> diff -Nur -X /home/louis/dontdiff 47-kp-fi/include/linux/fi/fi_interface.h 47-kp-fi-dm/include/linux/fi/fi_interface.h
> --- 47-kp-fi/include/linux/fi/fi_interface.h Thu Jan 1 08:00:00 1970
> +++ 47-kp-fi-dm/include/linux/fi/fi_interface.h Tue Nov 26 13:44:53 2002
> @@ -0,0 +1,160 @@
> +/******************************************************************************
> + * Fault Injection Test harness (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.
> + *
> + ******************************************************************************
> + */
> +
> +/* $Id: fi_interface.h,v 1.1.1.1 2002/11/12 05:56:30 brlock Exp $
> + * Copyright by Intel Crop., 2002
> + * Louis Zhuang (lou...@in...)
> + *
> + */
> +
> +/**
> + * @file interfaces.h
> + * This file defines interfaces among components.
> + */
> +#ifndef __FI_INTERFACE_H
> +#define __FI_INTERFACE_H
> +
> +#include <linux/fi/fi.h>
> +
> +
> +/**
> + * A interface exports to another component for callback.
> + */
> +struct iInterceptHook{
> + /**
> + * trigger a process of IO access interceptor
> + * @param wp the watchpoint which triggers the callback.
> + * @param len the length of resource access
> + * @param type 0 read, 1 write
> + * @param data XXX:context of the trigger.
> + * impl of trigger must send it back in corrput interface.
> + */
> + void (*trigger) (int id, __u32 val, int len, int type, void *data);
> +};
> +
Ahh! dOntDoThat! Follow the Documentation/CodingStyle for nameing
of things. As soon as lkml sees a name like iInterceptHook
the result will be
windows code ==> /dev/null
> +
> +/**
> + * A interface between Interceptor and DM components in order to
> + * intercept resource accesses.
> + */
> +struct iIntercept{
> + /**
> + * Register a watchpoint which will be triggered when access based on this address.
> + * @param wp the intercepted watchpoint
> + * @param id calling should assign a id to this wp.
> + * @param hook ptr can be used to call back process function.
> + * @param return 0 successful;
> + * -EFI_INVALID if wp is invaild;
> + * -EFI_REGISTERED if wp has been registered
> + * -EFI_TABFULL if wp table is full
> + */
> + int (*wp_register) (struct watchpoint wp,
> + int id,
> + struct iInterceptHook *hook,
> + char *modname);
> +
> + /**
> + * Unregister a watchpoint
> + * @param return 0 successful
> + * -EFI_NOTFOUND there is not the id.
> + */
> + int (*wp_unregister)(int id, char *modname);
> +
> + /**
> + * corrput access in requirement
> + */
> + int (*corrupt) (int id, __u32 dirty, void *data);
> +};
> +
> +
> +/**
> + * trigger a process of IRQ interceptor
> + */
> +struct iIRQHook{
> + /**
> + * callback for IRQ interceptor
> + */
> + void (*event) (int num, void *id, void *regs);
> +};
> +
> +
> +/**
> + * A interface to intercept IRQ
> + *
> + * any snatched IRQ event will be called into hook interface. And hook
> + * interface should in turn call dispatch event to invoke real driver's
> + * IRQ handler.
> + *
> + * And DM can also hook on other IRQ source and dispatch event into driver's
> + * handler in order to implement suprious IRQ event.
> + */
> +struct iIRQ{
> + /**
> + * Snatch a IRQ handler from IRQ chain.
> + * @param hook hook interface for this IRQ handler
> + * @param num IRQ number
> + * @param id id for shared IRQ device
> + */
> + int (*irq_snatch) (struct iIRQHook *hook, int num, char *devname, void** dev_id, char *modname);
> + int (*irq_unload) (int num, char *devname);
> + /**
> + * dispatch a fake IRQ event into handler
> + */
> + int (*dispatch) (int num, void *id, void *regs);
> +};
> +
> +/**
> + * A interface between fi_dbp and DM components in order to
> + * transfer information.
> + */
> +struct iGetinfo{
> + /**
> + * Transfer all information of the replaced IO instructions to fi_dbp.
> + * @param header data structure header of all the IO instructions.
> + * @param return 0 successful;
> + * -ENOMEM if kmalloc failed
> + * -EFI_TABFULL if wp table is full
> + */
> + int (*getinfo) (struct fi_ins_record_header *header);
> +};
> +
> +/**
> + * A interface for translating address between linear address and physical address.
> + */
> +struct iAslt{
> + /**
> + * Translate address bwteen linear address and physical address.
> + * @param header data structure header of all the IO instructions.
> + * @param return 0 failed;
> + * phy_addr if found.
> + */
> + unsigned long (*fi_line_to_phy) (unsigned long line_addr);
> +
> + /**
> + * Check if the wp is pending.
> + * @param wp the intercepted watchpoin.
> + * @param return 0 enable;
> + * 1 pending.
> + */
> + int (*check_wp) (struct watchpoint wp);
> +};
> +
> +#endif/*__FI_INTERFACE_H*/
> diff -Nur -X /home/louis/dontdiff 47-kp-fi/include/linux/fi/fi_internal.h 47-kp-fi-dm/include/linux/fi/fi_internal.h
> --- 47-kp-fi/include/linux/fi/fi_internal.h Thu Jan 1 08:00:00 1970
> +++ 47-kp-fi-dm/include/linux/fi/fi_internal.h Tue Nov 26 13:44:53 2002
> @@ -0,0 +1,126 @@
> +/******************************************************************************
> + * Fault Injection Test harness (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.
> + *
> + ******************************************************************************
> + */
> +
> +/* $Id: fi_internal.h,v 1.1.1.1 2002/11/12 05:56:30 brlock Exp $
> + * Copyright by Intel Crop., 2002
> + * Louis Zhuang (lou...@in...)
> + *
> + */
> +
> +/** @file fi_internal.h
> + * This is a FI internal header file to define some internal utilities.
> + */
> +#ifndef __FI_INTERNAL_H
> +#define __FI_INTERNAL_H
> +
> +#ifndef PREFIX_NAME
> +#define PREFIX_NAME "FI_DEFAULT"
> +#endif
> +extern long globalcounter;
> +
> +/*define help macro to debug */
> +/*XXX there should use eventlog in future */
> +#ifdef FI_DEBUG
> +# ifdef __KERNEL__
> +# define PDEBUG(fmt, args...) printk(KERN_DEBUG PREFIX_NAME ": %ld :cpu[%d] " __func__ ": " fmt, globalcounter++, smp_processor_id(), ##args)
> +# else
> +# define PDEBUG(fmt, args...) fprintf(stderr, fmt, ##args)
> +# endif
> +#else
> +# define PDEBUG(fmt, args...)
> +#endif
> +
> +#ifdef __KERNEL__
> +# define PINFO(fmt, args...) printk(KERN_INFO PREFIX_NAME ": %ld :%s:" fmt, globalcounter++, __func__, ##args)
> +#else
> +# define PINFO(fmt, args...) fprintf(stderr, fmt, ##args)
> +#endif
> +
> +#ifdef __KERNEL__
> +# define PERROR(fmt, args...) printk(KERN_ERR PREFIX_NAME ": %ld :%s:" fmt, globalcounter++, __func__, ##args)
> +#else
> +# define PERROR(fmt, args...) fprintf(stderr, fmt, ##args)
> +#endif
> +
> +/*define some macros*/
> +#define FI_MAJOR 0
> +
> +#define FI_ID(fs_num, tri_num) (fs_num<<16|tri_num)
> +#define FI_FS_NUM(id) (id>>16)
> +#define FI_TRI_NUM(id) (id&0xffff)
> +
> +/*define macros for error code.*/
> +#define EFI_SUCCESS 0
> +#define EFI_INVALID 1
> +#define EFI_REGISTERED 2
> +#define EFI_TABFULL 3
> +#define EFI_NOTFOUND 4
> +
> +/*define macros for WP type*/
> +inline static int is_MMIO(int type) { return (type&0x04)?1:0; };
> +inline static int is_IO(int type) { return (type&0x04)?0:1; };
> +inline static int is_read(int type) { return (type&0x08)?1:0; };
> +inline static int is_write(int type) { return (type&0x10)?1:0; };
> +inline static int is_execute(int type) { return (type&0x20)?1:0; };
> +inline static int access_len(int type) { return 1UL<<(type&0x03);};
> +
> +/*Some functions for find and lock specific kernel module*/
> +extern struct module *module_list;
> +static inline struct module *find_module(const char *name)
> +{
> + struct module *mod;
> +
> + for (mod = module_list; mod ; mod = mod->next) {
> + if (mod->flags & MOD_DELETED)
> + continue;
> + if (!strcmp(mod->name, name))
> + break;
> + }
> +
> + return mod;
> +}
> +
> +static inline int fi_lock_module(char *modname)
> +{
> + struct module *mod;
> +
> + mod = find_module(modname);
> + if (mod == NULL)
> + return -EEXIST;
> + __MOD_INC_USE_COUNT(mod);
> + PDEBUG("Lock module:%s! @%s\n", modname, __FILE__);
> + return EFI_SUCCESS;
> +}
> +
> +static inline int fi_unlock_module(char *modname)
> +{
> + struct module *mod;
> +
> + mod = find_module(modname);
> + if (mod == NULL)
> + return -EEXIST;
> + PDEBUG("Unlock module:%s! @%s\n", modname, __FILE__);
> + __MOD_DEC_USE_COUNT(mod);
> + return EFI_SUCCESS;
> +}
> +
> +
> +#endif/*__FI_INTERNAL_H*/
> diff -Nur -X /home/louis/dontdiff 47-kp-fi/kernel/Makefile 47-kp-fi-dm/kernel/Makefile
> --- 47-kp-fi/kernel/Makefile Mon Nov 25 15:16:27 2002
> +++ 47-kp-fi-dm/kernel/Makefile Mon Nov 25 15:40:23 2002
> @@ -22,6 +22,7 @@
> obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o
> obj-$(CONFIG_SOFTWARE_SUSPEND) += suspend.o
> obj-$(CONFIG_KPROBES) += kprobes.o
> +obj-$(CONFIG_FI_DM) += fi_dm.o
>
> ifneq ($(CONFIG_IA64),y)
> # According to Alan Modra <al...@li...>, the -fno-omit-frame-pointer is
> diff -Nur -X /home/louis/dontdiff 47-kp-fi/kernel/fi_dm.c 47-kp-fi-dm/kernel/fi_dm.c
> --- 47-kp-fi/kernel/fi_dm.c Thu Jan 1 08:00:00 1970
> +++ 47-kp-fi-dm/kernel/fi_dm.c Tue Nov 26 13:44:54 2002
> @@ -0,0 +1,594 @@
> +/******************************************************************************
> + * Fault Injection Test harness (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.
> + *
> + ******************************************************************************
> + */
> +
> +/* $Id: dm_core.c,v 1.3 2002/11/14 07:11:37 brlock Exp $
> + * Copyright by Intel Crop., 2002
> + * Louis Zhuang (lou...@in...)
> + */
> +/**
> + * @file dm_core.c
> + */
> +
> +#include <linux/config.h>
> +#include <linux/version.h>
> +
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/init.h>
> +#include <linux/version.h>
> +#include <asm/system.h>
> +#include <asm/uaccess.h>
> +#include <asm/io.h>
> +#include <asm/atomic.h>
> +#include <asm/debugreg.h>
> +#include <asm/desc.h>
> +#include <linux/ioport.h>
> +#include <asm/page.h>
> +#include <asm/pgtable.h>
> +#include <asm/pgalloc.h>
> +#include <linux/sched.h>
> +#include <asm/system.h>
> +#include <linux/vmalloc.h>
> +#include <linux/proc_fs.h>
> +#include <linux/random.h>
> +#include <linux/highmem.h>
> +#include <linux/kprobes.h>
> +
> +#define PREFIX_NAME "FI"
> +#include <linux/fi/fi.h>
> +#include <linux/fi/fi_internal.h>
> +#include <linux/fi/fi_interface.h>
> +
> +#define MAX_MOD 16
> +
> +#define MODULE_NAME "fi_dm"
> +#define MODULE_VERSION "0.1"
> +
> +static int insert_faultset(struct fi_faultset *fs);
> +static int remove_faultset(int index);
> +static int enable_faultset(int index);
> +static int disable_faultset(int index);
> +
> +
> +long globalcounter=0;
> +static struct fi_faultset fs_tb[MAX_FAULTSET];
> +static struct iIntercept *intcpt = NULL;
> +
> +#define ASLT_INTERFACE "fi.interceptor.aslt.iIntercept"
> +#define ASLT_MODULE "fi_aslt"
> +
> +void dm_trigger(int id, __u32 val, int len, int type, void *data){
> + int fs_num= FI_FS_NUM(id);
> + int tri_num=FI_TRI_NUM(id);
> + int tmp=0, i=0;
> + struct fi_trigger *tri = NULL;
> + __u32 old = val;
> +
> + PDEBUG("entry, id=%#x, val=%#x, len=%d, type=%d, data=%#x\n",
> + id, val, len, type, data);
> + if (fs_num>=MAX_FAULTSET || fs_num<0
> + || tri_num>=MAX_TRIGGER_PER_FAULTSET || tri_num<0){
> + PERROR(":error id number %d\n", id);
> + goto exit;
> + }
> +
> + tri = &fs_tb[fs_num].trigger_tb[tri_num];
> +
> + if (!tri->registered){
> + PERROR("Should not trigger an unregistered wp %d!?\n", id);
> + }
> +
> +
> + get_random_bytes(&tmp, sizeof(tmp));
> + if (tri->hertz==0) {tri->hertz=1;};//divid is not 0!
> + if (tmp >= 0xFFFFFFFF/tri->hertz){
> + PDEBUG("rnd=%d, HERZ=%d\n", tmp, tri->hertz);
> + goto exit;
> + }
> +
> + tmp = val & (~tri->bitmask);
> + if (tri->min>tmp || tmp>=tri->max){
> + PDEBUG("min=%d, max=%d, val=%d\n", tri->min, tri->max, val);
> + if(!(tri->min==0 && tri->max==0))
> + goto exit;
> + }
> +
> + // Increase count only when passing all conditions
> + atomic_inc(&tri->count);
> +
> + if (tri->skip >= atomic_read(&tri->count)){
> + PDEBUG("count=%d, skip=%d\n", atomic_read(&tri->count), tri->skip);
> + goto exit;
> + }
> +
> + if ( tri->stop!=0 && (tri->stop < (atomic_read(&tri->count)-tri->skip)) ) {
> + PDEBUG("count=%d, stop=%d\n", atomic_read(&tri->count), tri->stop);
> + goto exit;
> + }
> +
> + PDEBUG("count=%d, skip=%d, min=%d, max=%d, val=%d\n",
> + atomic_read(&tri->count), tri->skip, tri->min, tri->max, val);
> + tmp = val;
> + for (i=0; i<MAX_OP_PER_TRIGGER; i++) {
> + switch (tri->ops[i].opcode){
> + case FI_NOTHING:
> + goto exit_for;
> + case FI_SET:
> + tmp = tri->ops[i].operand;
> + break;
> + case FI_AND:
> + tmp &= tri->ops[i].operand;
> + break;
> + case FI_OR:
> + tmp |= tri->ops[i].operand;
> + break;
> + case FI_NOT:
> + tmp = ~tmp;
> + break;
> + case FI_XOR:
> + tmp ^= tri->ops[i].operand;
> + break;
> + case FI_NAND:
> + tmp = ~(tmp & tri->ops[i].operand);
> + break;
> + case FI_NOR:
> + tmp = ~(tmp | tri->ops[i].operand);
> + break;
> + case FI_ADD:
> + tmp = tmp + tri->ops[i].operand;
> + break;
> + case FI_SUB:
> + tmp = tmp - tri->ops[i].operand;
> + break;
> + default:
> + PERROR("Not recognized opcode%d\n", tri->ops[i].opcode);
> + break;
> + }
> + }
> + exit_for:
> + val = (val & (tri->protection)) | (tmp & (~tri->protection));
> +
> + exit:
> +
> + PINFO("id=%#x, val=%#x, old=%#x, len=%d, type=%d, data=%p\n",
> + id, val, old, len, type, data);
> + intcpt->corrupt(id, val, data);
> + return;
> +}
> +
> +static struct iInterceptHook intcpt_hook[1] = {
> + {
> + trigger: dm_trigger
> + }
> +};
> +
> +
> +/*manipulate fault set*/
> +static int insert_faultset(struct fi_faultset *fs){
> + int rv=0;
> + int i=0;
> +
> + for (i=0; i<MAX_FAULTSET; i++) {
> + if (fs_tb[i].stat == NOUSED) break;
> + }
> + if (i < MAX_FAULTSET) {
> + int rv1;
> + copy_from_user(&fs_tb[i], fs, sizeof(fs_tb[i]));
> + fs_tb[i].stat = DISABLED;
> + rv = i;
> + PDEBUG("modname: %s\n", fs_tb[i].modname);
> + PINFO("insert #%d fs\n", i);
> + rv1 = enable_faultset(i);
> + if(rv1<0) {
> + PERROR("can not enable faultset# %d\n", i);
> + }
> + }else{
> + rv = -ENOSPC;
> + }
> + return rv;
> +}
> +
> +static int remove_faultset(int index){
> + int rv=0;
> +
> + if (index<0 || index>=MAX_FAULTSET || fs_tb[index].stat == NOUSED) {
> + rv = -EPERM;
> + goto exit1;
> + }
> +
> + if (index>=0 && index<MAX_FAULTSET && fs_tb[index].stat == ENABLED) {
> + disable_faultset(index);
> + }
> +
> + if (index<0 || index>=MAX_FAULTSET || fs_tb[index].stat == ENABLED) {
> + PERROR("can not remove #%d fs when it is enabled\n", index);
> + rv = -EPERM;
> + }else{
> + fs_tb[index].stat = NOUSED;
> + }
> + PINFO("remove #%d fs\n", index);
> + exit1:
> + return rv;
> +}
> +
> +static int enable_faultset(int index){
> + int rv=0;
> + int i=0;
> + int id_high;
> + struct fi_faultset *fs;
> +
> + PDEBUG("trying to enable faultset# %d\n", index);
> +
> + if (index<0 || index>= MAX_FAULTSET || fs_tb[index].stat != DISABLED) {
> + rv = -EINVAL;
> + goto exit;
> + }
> +
> + id_high = index<<16;
> + fs = &fs_tb[index];
> + /*register all wp into interceptor component*/
> + for (i=0; i<MAX_TRIGGER_PER_FAULTSET && (fs->trigger_tb[i].wp.addr); i++){
> + PDEBUG("register WP, id=%d, hook=%p\n", id_high+i, intcpt_hook);
> + atomic_set(&fs->trigger_tb[i].count, 0);
> + fs->trigger_tb[i].registered = 1;
> + rv = intcpt->wp_register(fs->trigger_tb[i].wp, id_high+i, intcpt_hook, fs->modname);
> +
> + if (rv<0) {
> + fs->trigger_tb[i].registered = 0;
> + PERROR("can not register WP, id = %d\n", id_high+i);
> + continue; //goto exit;//XXX: I should remove registered trigger
> + }
> + fs->stat = ENABLED;
> + }
> + if (fs->stat == DISABLED) {
> + PERROR("none of trigger can be active, enable faultset failed!\n");
> + goto exit;
> + }
> + PINFO("enable #%d fs\n", index);
> + rv = 0;
> + exit:
> + return rv;
> +}
> +
> +static int disable_faultset(int index){
> + int rv=0;
> + int i=0;
> + int id_high=0;
> + struct fi_faultset *fs;
> +
> + PDEBUG("trying to disable faultset# %d\n", index);
> + if(index<0 || index>MAX_FAULTSET || fs_tb[index].stat!=ENABLED) {
> + rv=-EINVAL;
> + goto exit;
> + }
> +
> + id_high=index<<16;
> + fs = &fs_tb[index];
> +
> + for (i=0; i<MAX_TRIGGER_PER_FAULTSET && (fs->trigger_tb[i].wp.addr); i++){
> + rv = intcpt->wp_unregister(id_high+i, fs->modname);
> + if (rv>=0) {
> + fs->trigger_tb[i].registered = 0;
> + }else{
> + PERROR("can not unregister wp, id=%d\n", id_high+i);
> + }
> + }
> + fs->stat = DISABLED;
> + PINFO("disable #%d fs\n", index);
> + rv = 0;
> + exit:
> + return rv;
> +}
> +/*END OF fault set functions*/
> +
> +
> +static int fi_ioctl(struct inode *inode, struct file *file,
> + unsigned int cmd, unsigned long arg){
> + int rv=0;
> + int i=0;
> + unsigned long addr;
> + struct iGetinfo *p = NULL;
> + struct iAslt *q = NULL;
> +
> + switch (cmd){
> + default:
> + rv = -ENOTTY;
> + break;
> + case FIIOC_INSERT:
> + rv = insert_faultset((struct fi_faultset *)arg);
> + break;
> + case FIIOC_REMOVE:
> + get_user(i, (int *)arg);
> + rv = remove_faultset(i);
> + break;
> + case FIIOC_ENABLE:
> + get_user(i, (int *)arg);
> + rv = enable_faultset(i);
> + break;
> + case FIIOC_DISABLE:
> + get_user(i, (int *)arg);
> + rv = disable_faultset(i);
> + break;
> + case FIIOC_QUERY_PHYADDR:
> + q = (struct iAslt *)inter_module_get_request("fi.interceptor.aslt.iLine_to_phy", "fi_aslt");
> + if(q != NULL) {
> + get_user(addr, (unsigned long *)arg);
> + addr = q->fi_line_to_phy(addr);
> + put_user(addr, (unsigned long *)arg);
> + inter_module_put("fi.interceptor.aslt.iLine_to_phy");
> + }else{
> + PERROR("Can not get fi_line_to_phy! @%s\n", __FILE__);
> + }
> + break;
> + case FIIOC_TRANS_INST:
> + rv = -1;
> + p = (struct iGetinfo *)inter_module_get_request("fi.interceptor.dbp.iGetinfo", "fi_dbp");
> + if(p != NULL) {
> + rv = p->getinfo((struct fi_ins_record_header *)arg);
> + inter_module_put("fi.interceptor.dbp.iGetinfo");
> + } else {
> + PERROR("Can not get fi.interceptor.dbp.iGetinfo! @%s\n", __FILE__);
> + }
> + break;
> + case FIIOC_QUERY_INTCPT:
> + rv = 0;
> + break;
> + };
> + return rv;
> +};
> +
> +static spinlock_t counter_lock = SPIN_LOCK_UNLOCKED;
> +static int counter=0;
> +
> +static int fi_open(struct inode *inode, struct file *file){
> + int rv=0;
> +
> + spin_lock(&counter_lock);
> + if (counter) {
> + rv = -1;
> + goto out;
> + }
> + counter++;
> + MOD_INC_USE_COUNT;
> + out:
> + spin_unlock(&counter_lock);
> + return rv;
> +}
> +
> +
> +static int fi_release(struct inode *inode, struct file *file){
> + spin_lock(&counter_lock);
> + counter--;
> + MOD_DEC_USE_COUNT;
> + spin_unlock(&counter_lock);
> + return 0;
> +}
> +
> +static int dump_faultset(struct fi_faultset *fs, char *buf){
> + int i=0, n=0, k=0;
> + int rv=0;
> + struct iAslt *q=NULL;
> + static char *op_name[]={
> + "NOTHING", "SET", "AND", "OR", "NOT", "XOR", "NAND", "NOR", "ADD", "SUB",
> + };
> +
> + if (fs->stat == NOUSED){
> + n += sprintf(buf+n, "This faultset is not used!\n");
> + goto exit1;
> + }
> +
> + q = (struct iAslt *)inter_module_get_request("fi.interceptor.aslt.iLine_to_phy", "fi_aslt");
> + if(q == NULL) {
> + PERROR("Can not get check_wp! @%s\n", __FILE__);
> + return rv;
> + }
> +
> + n += sprintf( buf+n, "This will dump fault set information, stat=%d\n",
> + fs->stat);
> + n += sprintf( buf+n, "The faultset is %s\n",
> + (fs->stat==ENABLED)? "ENABLED" :
> + ((fs->stat==DISABLED)? "DISABLED":
> + "UNKNOWN!"));
> + for(i=0; i<MAX_TRIGGER_PER_FAULTSET; i++){
> + int j=0;
> + struct fi_trigger *tri;
> +
> + tri = &fs->trigger_tb[i];
> + if (tri->wp.addr==NULL) break;
> + n += sprintf(buf+n, "watchpoint #%d phy_addr=%#lx, type=%#x, len=%d\n",
> + i, tri->wp.addr, tri->wp.type, access_len(tri->wp.type));
> + n += sprintf(buf+n, "bitmask=%#x, min=%#x, max=%#x, skip=%d, "
> + "stop=%d, protection=%#x, Hertz=%#x\n",
> + tri->bitmask, tri->min, tri->max, tri->skip,
> + tri->stop, tri->protection, tri->hertz);
> +
> + n += sprintf(buf+n, "ops list\n");
> + for(j=0; j<MAX_OP_PER_TRIGGER; j++){
> + char *name;
> + if (tri->ops[j].opcode==FI_NOTHING) break;
> + n += sprintf(buf+n, "opcode=%s, operand=%#x\n",
> + op_name[tri->ops[j].opcode], tri->ops[j].operand);
> + }
> +
> + if (is_MMIO(tri->wp.type)) {
> + k = q->check_wp(tri->wp);
> + n += sprintf(buf+n, "watchpoint status:%s\n",
> + (tri->registered==1) ?
> + ((k==1) ? "PENDING" : "ENABLED") :
> + "DISABLED");
> + } else {
> + n += sprintf(buf+n, "watchpoint status:%s\n",
> + (tri->registered==1) ? "ENABLED" : "DISABLED");
> + }
> +
> + n += sprintf(buf+n, "-----------------\n");
> + }
> +
> + inter_module_put("fi.interceptor.aslt.iLine_to_phy");
> +
> + exit1:
> + n += sprintf(buf+n, "\n");
> + rv = n;
> + return rv;
> +}
> +
> +static int fi_proc_read( char* page, char **start, off_t off, int count, int *eof, void *data){
> + return dump_faultset((struct fi_faultset *)data, page);
> +};
> +
> +static int fi_proc_write( struct file *file, const char *buffer, unsigned long count, void *data){
> + return 0;//dummy now :-)
> +};
> +
> +static int fi_gc_read( char* page, char **start, off_t off, int count, int *eof, void *data) {
> + int n=0;
> +
> + n = sprintf(page, "%ld", globalcounter);
> + return ((n>0)?n:0);
> +};
> +
> +static struct file_operations fi_fops[1]={
> + {
> + owner: THIS_MODULE,
> + ioctl: fi_ioctl,
> + open: fi_open,
> + release: fi_release
> + }
> +};
> +
> +
> +static struct proc_dir_entry *root_entry;
> +static struct proc_dir_entry *fs_entry;
> +static struct proc_dir_entry *gc_entry;
> +static int fi_major = FI_MAJOR;
> +
> +static int __init fi_dm_init(void){
> + int i=0 ;
> + int rv=0;
> +
> + PDEBUG("FI version: %s\n", FI_VERSION);
> +
> + /*Setup proc file*/
> + root_entry = proc_mkdir(MODULE_NAME, NULL);
> + if (!root_entry){
> + PERROR("can not register proc %s\n", MODULE_NAME);
> + rv = -ENOMEM;
> + goto exit1;
> + }
> + root_entry->owner=THIS_MODULE;
> +
> + for (i=0; i<MAX_FAULTSET; i++){
> + char name[20];
> +
> + sprintf(name, "fs%d", i);
> + fs_entry = create_proc_entry(name, 0644, root_entry);
> + if (!fs_entry){
> + PERROR("can not register proc %s\n", name);
> + rv = -ENOMEM;
> + goto exit2;
> + }
> + fs_entry->owner = THIS_MODULE;
> + fs_entry->read_proc = fi_proc_read;
> + fs_entry->write_proc= fi_proc_write;
> + fs_entry->data = &fs_tb[i];
> + }
> +
> + gc_entry = create_proc_entry("globalcounter", 0644, root_entry);
> + if (gc_entry==NULL) {
> + PERROR("can not register proc %s\n", "globalcounter");
> + rv = -ENOMEM;
> + goto exit3;
> + }
> + gc_entry->owner = THIS_MODULE;
> + gc_entry->read_proc = fi_gc_read;
> +
> + intcpt= (struct iIntercept *)inter_module_get_request(ASLT_INTERFACE, ASLT_MODULE);
> + if (intcpt == NULL) {
> + PERROR("Can not get interface : aslt @%s\n", __FILE__);
> + rv = -1;
> + goto exit4;
> + }
> +
> + rv = register_chrdev(fi_major, MODULE_NAME, fi_fops);
> + if (rv<0){
> + PERROR("can not register device, major=%d\n", fi_major);
> + goto exit5;
> + }
> + if (fi_major==0) fi_major = rv;/*dynamic alloc major number*/
> + PDEBUG("Setup IOCTL as char device, major=%d\n", fi_major);
> +
> + /*clear fs_tb */
> + memset(fs_tb, 0, sizeof(fs_tb));
> + EXPORT_NO_SYMBOLS;
> + return 0;
> +
> + exit5:
> + inter_module_put(ASLT_INTERFACE);
> + exit4:
> + remove_proc_entry("globalcounter", root_entry);
> + exit3:
> +
> + i=MAX_FAULTSET;/* error happen above 2, you must clear ALL entries*/
> + exit2:
> + i--;
> + for (;i>=0;i--){
> + char name[20];
> +
> + sprintf(name, "fs%d", i);
> + remove_proc_entry(name, root_entry);
> + }
> + remove_proc_entry(MODULE_NAME, NULL);
> + exit1:
> + return rv;
> +};
> +
> +
> +static void __exit fi_dm_cleanup(void){
> + int i=0;
> +
> + inter_module_put(ASLT_INTERFACE);
> +
> + unregister_chrdev(fi_major, MODULE_NAME);
> +
> + /*unregister proc files*/
> + remove_proc_entry("globalcounter", root_entry);
> + for (i=MAX_FAULTSET-1;i>=0;i--){
> + char name[20];
> +
> + sprintf(name, "fs%d", i);
> + remove_proc_entry(name, root_entry);
> + }
> + remove_proc_entry(MODULE_NAME, NULL);
> +
> + /* remove all faultset */
> + for(i=0; i<MAX_FAULTSET; i++) {
> + remove_faultset(i);
> + }
> +
> +};
> +
> +
> +module_init(fi_dm_init);
> +module_exit(fi_dm_cleanup);
> +MODULE_AUTHOR("Louis Zhuang");
> +MODULE_DESCRIPTION("Decision Maker component for FI");
> +MODULE_LICENSE("GPL");
> +
> Binary files 47-kp-fi/scripts/kconfig/conf and 47-kp-fi-dm/scripts/kconfig/conf differ
>
Read over your patch before sending it out. Messages like these
should not be in the patch file.
|