fault-injection-developer Mailing List for Fault Injection Test Harness (Page 7)
Status: Alpha
Brought to you by:
rustyl
You can subscribe to this list here.
2002 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
(1) |
Jul
|
Aug
(13) |
Sep
(2) |
Oct
(49) |
Nov
(69) |
Dec
(70) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2003 |
Jan
(64) |
Feb
(41) |
Mar
(25) |
Apr
(18) |
May
(5) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2004 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
(1) |
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2006 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
(3) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2007 |
Jan
|
Feb
|
Mar
|
Apr
|
May
(1) |
Jun
(1) |
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2008 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
(1) |
Oct
(1) |
Nov
|
Dec
|
2009 |
Jan
(1) |
Feb
(2) |
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2011 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(1) |
Nov
|
Dec
|
2014 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(1) |
Nov
(1) |
Dec
|
2015 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(2) |
2016 |
Jan
(2) |
Feb
(5) |
Mar
(2) |
Apr
(1) |
May
(1) |
Jun
(1) |
Jul
(2) |
Aug
(1) |
Sep
|
Oct
|
Nov
|
Dec
|
2017 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(4) |
Nov
|
Dec
|
From: Rusty L. <ru...@li...> - 2003-01-03 22:53:51
|
Before, I had envisioned a trigger being created for a 'type' of interceptor, not a specific interceptor. This allows for many-to-one relationship between interceptors and triggers, and also allows triggers and interceptors to be install independent of each other. Your proposal infers a one-to-one relationship between triggers and interceptors and requires interceptors to be installed before triggers are installed. So... is this an unexpected side effect or an unstated assumption? Don't get me wrong. I'm not sure that I am against formalizing a one-to-one relation, but we need for this to not just be an undocumented side effect, but an up front design decision so we are all working towards the same goal. Specifically: What SHOULD be our relationship between triggers and interceptors? a. one trigger associated with one interceptor b. one trigger associated with many interceptors What SHOULD be our relationship between triggers and code segments? a. one trigger associated with one code segment b. one trigger associated with many code segments My opinion: I think we could keep a fairly simple yet flexible design by choosing (a) a single trigger always be associated with a single interceptor, and (b) allow for multiple code segments to be attached to any given trigger. In fact we could totally drop the whole notion of an interceptor 'type' and push all policy statements like 'it does not make sense to associate code segment A with interceptor B' to user space. ----- Original Message ----- From: "Zhuang, Louis" <lou...@in...> To: "FITHML (E-mail)" <fau...@so...> Cc: "Lynch, Rusty" <rus...@in...> Sent: Thursday, January 02, 2003 7:29 PM Subject: [Fault-injection-developer] [RFC] command in '/sys/triggers/ctl' is changed > Based on suggestion from Kevin, I found fi_core is better to attach > trigger with interceptors by *name*. So I'd like to change the ctl command > as following > echo "add <trigger_name> <interceptor_type> .... " > /sys/triggers/ctl > || > \/ > echo "add <trigger_name> <interceptor_name> .... " > /sys/triggers/ctl > > > > ------------------------------------------------------- > This sf.net email is sponsored by:ThinkGeek > Welcome to geek heaven. > http://thinkgeek.com/sf > _______________________________________________ > Fault-injection-developer mailing list > Fau...@li... > https://lists.sourceforge.net/lists/listinfo/fault-injection-developer |
From: Zhuang, L. <lou...@in...> - 2003-01-03 06:49:55
|
Documentation/fault_injection.txt | 195 --- arch/i386/kernel/fi/Makefile | 7 arch/i386/kernel/fi/aslt/Makefile | 10 arch/i386/kernel/fi/aslt/fi_aslt.c | 244 ---- arch/i386/kernel/fi/pf/Makefile | 10 arch/i386/kernel/fi/pf/fi_pf.h | 85 - arch/i386/kernel/fi/pf/pf.c | 295 ----- arch/i386/kernel/fi/pf/pf_in.c | 456 -------- arch/i386/kernel/fi/pf/pf_region.c | 210 --- arch/i386/kernel/fi/pf/pf_utils.c | 81 - drivers/char/fi/dbp/fi_dbp.h | 88 - drivers/char/fi_mock_interceptor.c | 148 -- drivers/char/fi_test.c | 169 --- drivers/char/kprobes_printk.c | 298 ----- include/asm-i386/fi.h | 11 include/linux/fi/fi.h | 121 -- include/linux/fi/fi_interface.h | 61 - include/linux/fi/fi_internal.h | 49 include/linux/fi_internal.h | 35 kernel/fi_core.c | 693 ------------ kernel/fi_dm.c | 534 --------- Documentation/fault_injection.txt | 197 +++ REPORTING-BUGS | 2 arch/i386/Kconfig | 254 +++- arch/i386/kernel/Makefile | 12 arch/i386/kernel/entry.S | 22 arch/i386/kernel/fi/Makefile | 13 arch/i386/kernel/fi/aslt/Makefile | 10 arch/i386/kernel/fi/aslt/fi_aslt.c | 244 ++++ arch/i386/kernel/fi/pf/Makefile | 18 arch/i386/kernel/fi/pf/fi_pf.h | 87 + arch/i386/kernel/fi/pf/pf.c | 1215 +++++++++++++--------- arch/i386/kernel/fi/pf/pf_in.c | 502 ++++++++- arch/i386/kernel/fi/pf/pf_region.c | 212 +++ arch/i386/kernel/fi/pf/pf_utils.c | 99 + arch/i386/kernel/i386_ksyms.c | 6 arch/i386/kernel/kirq.c | 240 ++++ arch/i386/kernel/kmmio.c | 240 +++- arch/i386/kernel/kprobes.c | 160 ++ arch/i386/kernel/traps.c | 56 - arch/i386/mm/fault.c | 14 drivers/char/Makefile | 7 drivers/char/fi/Makefile | 20 drivers/char/fi/dbp/Makefile | 9 drivers/char/fi/dbp/fi_dbp.c | 766 +++++++++++++- drivers/char/fi/dbp/fi_dbp.h | 89 + drivers/char/fi/fi_core.c | 1121 ++++++++++++++++++-- drivers/char/fi/fi_irq.c | 305 +++++ drivers/char/fi/fi_mock_cs.c | 45 drivers/char/fi/fi_mock_interceptor.c | 178 ++- drivers/char/fi/fi_sample_cs.c | 75 + drivers/char/fi/fi_test.c | 337 ++++-- drivers/char/fi/pf/Makefile | 10 drivers/char/fi/pf/fi_pf.h | 128 +- drivers/char/fi/pf/pf.c | 324 +++++ drivers/char/fi/pf/pf_in.c | 463 ++++++++ drivers/char/fi/pf/pf_utils.c | 88 + drivers/char/fi_mock_interceptor.c | 148 ++ drivers/char/fi_test.c | 941 ++++++++++------- drivers/char/kprobes_printk.c | 298 +++++ include/asm-i386/fi.h | 15 include/asm-i386/kirq.h | 59 + include/asm-i386/kmmio.h | 35 include/asm-i386/kprobes.h | 34 include/linux/fi.h | 193 +++ include/linux/fi/fi.h | 185 ++- include/linux/fi/fi_interface.h | 113 +- include/linux/fi/fi_internal.h | 153 +- include/linux/fi_internal.h | 65 - include/linux/kmmio.h | 68 + include/linux/kprobes.h | 60 + include/linux/module.h | 3 kernel/Makefile | 12 kernel/fi_core.c | 1851 ++++++++++++++++++++++------------ kernel/fi_dm.c | 548 +++++++++- kernel/kmmio.c | 173 ++- kernel/kprobes.c | 89 + kernel/module.c | 54 lib/vsprintf.c | 1 79 files changed, 10478 insertions(+), 5988 deletions(-) through these ChangeSets: <st...@ma...> (03/01/03 1.911.4.41) Remove fi_internal.h <st...@ma...> (03/01/03 1.911.49.1) Combin fi_get_module and fi_put_module into get_module and Remove fi_dbp.h <lo...@ha...> (03/01/03 1.911.4.39) merge fi_internal.h into fi.h <st...@ma...> (03/01/03 1.911.14.3) Move kirq_list to kirq.c <st...@ma...> (02/12/31 1.911.4.37) module.c: Clean fi_dbp infrastructure <st...@ma...> (02/12/31 1.911.4.36) Remove interceptor type <lo...@ha...> (02/12/31 1.911.4.34) fix bug -- forget reset 'field_width' in vsscanf() <st...@ma...> (02/12/31 1.911.45.1) Bug fix for fi_dbp <lo...@ha...> (02/12/31 1.911.4.33) fix redundant warning when echo into "cs/trigger" <lo...@ha...> (02/12/31 1.911.4.32) remove interceptor_type. now echo "add <tri_name> <interceptor_name> ..." > ctl <lo...@ha...> (02/12/31 1.911.4.31) fix command process in trigger_ctl_store() <lo...@ha...> (02/12/31 1.911.4.30) fi_execute_trigger(..., type, ...) type 0:READ, 1:WRITE <lo...@ha...> (02/12/31 1.911.4.29) fix return value check in arm_trigger <lo...@ha...> (02/12/30 1.911.27.4) arch/i386/kernel/kmmio.c fix error judgement in telling if the page fault is caused by kmmio. //shy kernel/kmmio.c fix bug in kmalloc GFP_KERNEL in spin_lock_irq <st...@ma...> (02/12/30 1.911.4.26) Bug fix for fi_dbp <st...@ma...> (02/12/30 1.911.4.25) Change name : "attach" -> "ctl" <st...@ma...> (02/12/27 1.911.4.24) fix warning. <lo...@ha...> (02/12/27 1.911.27.3) fix risk condition in unarm_code_segment <lo...@ha...> (02/12/27 1.911.27.2) refine trigger/<tri_name>/[opcode|operand] display <st...@ma...> (02/12/27 1.911.4.23) Add FI_DBP <lo...@ha...> (02/12/27 1.911.27.1) fix bug on fi_exit() <st...@ma...> (02/12/27 1.911.4.22) Split fi_find_module into fi_get_moudule and fi_put_module <st...@ma...> (02/12/27 1.911.4.21) Add FI_DBP infrastructure <st...@ma...> (02/12/26 1.911.4.20) Fix print issues. Add check to intercept timer's irq. <st...@ma...> (02/12/26 1.911.4.19) Bug fix for fi_irq <st...@ma...> (02/12/26 1.911.15.1) Add fi_irq <st...@ma...> (02/12/26 1.911.14.2) Add dispatch_kirq <lo...@ha...> (02/12/26 1.911.4.16) clean code <lo...@ha...> (02/12/26 1.911.4.15) replace deprecated MODULE_PARM with module_param <lo...@ha...> (02/12/25 1.865.64.23) * control 'mocks' by FI_MOCKS option. * add fi_sample_cs.c * add kmmio_invert_map function <lo...@ha...> (02/12/24 1.865.64.22) * refactor del_trigger (using find_trigger_by_name) * refactor fi_execute_trigger (breaking down small functions) <lo...@ha...> (02/12/24 1.865.64.21) drivers/char/fi/fi_core.c * fix a bug * add code segment support drivers/char/fi/fi_mock_cs.c reduce name length <lo...@ha...> (02/12/24 1.865.64.20) add mock_code_segment file <lo...@ha...> (02/12/24 1.865.64.19) * add code segment subsystem * add fi_mock_code_segment * clean some extern declarations in .c <st...@ma...> (02/12/24 1.865.64.18) Cleanup code <st...@ma...> (02/12/24 1.865.64.17) Make fi_test use sysfs <lo...@ha...> (02/12/23 1.865.64.16) use container_of instead of type cost in pf.c <lo...@ha...> (02/12/23 1.865.64.15) remove unused enum value in pf <lo...@ha...> (02/12/23 1.865.64.14) fix symbol export <lo...@ha...> (02/12/23 1.865.64.13) refine header files <lo...@ha...> (02/12/21 1.865.74.1) concentrate FITH files into driver/char/fi <st...@ma...> (02/12/21 1.865.72.1) kirq.c: Refine printk message and fix register fail bug. <rusty@penguin.(none)> (02/12/20 1.865.64.10) fixed a mistake in last merge <rusty@penguin.(none)> (02/12/20 1.865.68.1) * Added a new interceptor just for the purpose of testing fi_core.c * Added support for interceptor attributes * Added a new interceptor unregistration function to fi_core <lo...@ha...> (02/12/20 1.865.61.7) change PDEBUG/PERROR to dbg/err <st...@ma...> (02/12/20 1.865.64.6) Remove enabled file <lo...@ha...> (02/12/20 1.865.61.6) remove fi_enable <st...@ma...> (02/12/20 1.865.64.4) Refind config file <lo...@ha...> (02/12/20 1.865.61.5) modulized fi_core and fi_pf <st...@ma...> (02/12/20 1.865.54.3) Refine config file. <lo...@ha...> (02/12/20 1.865.61.4) fix copyright <lo...@ha...> (02/12/20 1.865.61.3) fix code style <lo...@ha...> (02/12/20 1.865.61.2) add corrupt in REG_READ <lo...@ha...> (02/12/19 1.865.61.1) fix stupid not-initing kmmio_page_table <st...@ma...> (02/12/19 1.865.42.9) Remove /sys/fault-injcetion/enabled <lo...@ha...> (02/12/19 1.865.42.8) fix copyright declaration <lo...@ha...> (02/12/19 1.865.42.7) * reconstruct code to use kmmio * delete unused member in kmmio_probe * remove pf_region.c * reconstruct code to use kmmio * fix misuse PAGE_HASH_TABLE <st...@ma...> (02/12/19 1.865.57.6) kobject_init will be invoked in kobject_register. <st...@ma...> (02/12/19 1.865.57.5) Add IRQ interceptor's infrastructure (KIRQ). <lo...@ha...> (02/12/19 1.865.42.4) flush tlb in suitable place <rusty@penguin.(none)> (02/12/18 1.865.57.4) dropping doc file <rusty@penguin.(none)> (02/12/18 1.865.57.3) minimal changeset to remove the kprobes_printk.c file <rusty@penguin.(none)> (02/12/18 1.865.57.2) These changes include a removal of a personal hack of mine in my own tree, and various work to move execute_trigger from an interceptor to the core. <st...@ma...> (02/12/18 1.865.54.2) Fix stupid bug. <lo...@ha...> (02/12/18 1.865.42.3) add kmmio mechanism. *NO TEST AT ALL* <st...@st...> (02/12/18 1.865.54.1) Add KIRQ Support <rusty@penguin.(none)> (02/12/17 1.865.8.16) Added a documentation file and then a few more printk's to the test driver <lo...@ha...> (02/12/17 1.865.26.2) remove Rules.mak in appended Makefile <rusty@penguin.(none)> (02/12/16 1.865.8.15) This changeset merges changes for a new implementation of the fault injection core, and the kprobes printk driver. <te...@ha...> (02/12/13 1.865.8.14) pf.c: add more debug info about 'removed region' pf_region.c: fix dark X bug. <te...@ha...> (02/12/13 1.865.8.13) Add FI_DEBUG, clean some awful stuffs... <st...@ma...> (02/12/12 1.865.8.12) Cleanup fi_test.c <lo...@ha...> (02/12/12 1.865.8.11) fi.h: remove FIIOC_QUERY_PHYADDR ioctl remove unused statements pf_utils.c, fi_pf.h: change 'line' to virt pf.c: fix TABLE_FULL error handling change 'line' to virt <lo...@ha...> (02/12/12 1.865.8.10) pf.c: fix invalid condition <st...@ma...> (02/12/11 1.865.8.9) Remove unused varible. <st...@ma...> (02/12/11 1.865.12.1) Buf fix. Remove fi_line_to_phy <ru...@st...> (02/12/11 1.865.11.1) Further cleanup of the test driver used for demonstraiting <st...@ma...> (02/12/11 1.865.10.1) Remove aslt <lo...@ha...> (02/12/11 1.865.8.5) fix symbol&name issues <ru...@st...> (02/12/10 1.865.8.4) This patchset adds fault injection capabilites to the Linux kernel <ru...@st...> (02/12/10 1.865.8.3) Adding last piece of kprobes, traps.c hooks <rusty@penguin.(none)> (02/12/10 1.865.8.2) Adding the kprobes patch submitted to lkml for the 2.5.50-bk2 tree <lm...@wo...> (02/12/10 1.865.8.1) TEST, TEST, TEST, TEST. Ignore, debugging BK logging. |
From: Wang, S. <sta...@in...> - 2003-01-03 05:55:41
|
============================================================================ = This is the root directory for fault injection. Fault injection contains the following: fi_core.c : Core fault injection code. EXPORT_SYMBOL_GPL(fi_register_interceptor); EXPORT_SYMBOL_GPL(fi_unregister_interceptor); EXPORT_SYMBOL_GPL(fi_register_code_segment); EXPORT_SYMBOL_GPL(fi_unregister_code_segment); EXPORT_SYMBOL_GPL(fi_execute_trigger); EXPORT_SYMBOL_GPL(fi_debug); internal_testing/ : Proper place to add any code created for the purpose of testing the fault injection core code (not to to actually implement 'fault injection testing') * Current test code includes - mock interceptor : a simple interceptor implementation that can adds a 'trip' file to the specific trigger's sysfs directory to enable the trigger to be tripped via command line. - mock code segment: a simple code segment implementation that can report what values when the code segment is called. interceptors/ : Proper place to add any interceptor implementations. * Current interceptors are - pf : 'page fault' interceptor for intercepting MMIO - dbp : 'dynamic binary patch' interceptor for intercepting PIO cs/ : Proper place to add any code segment implementations * Current code segments are - sample : A sample code segment to demonstrate 'kmmio_invert_map' What is an 'interceptor'? ------------------------- An interceptor is a component that knows how to intercept some specific type of kernel level event or action to enable the fault injection core to 'hook' into event or action and take some action. An interceptor is one level higher then a normal kernel hook. For example an interceptor could be written to utilize kprobes, where the kprobe is tripped every time a specific address is executed, but the interceptor might contain some additional logic to decide if the specific event or action was happening. Life cycle of an interceptor ---------------------------- ( Startup ) ---------------- | Initialization | ---------------- || || || \/ ----------------------------------------------- | (call into fi_core) fi_register_interceptor() | ----------------------------------------------- (User starts using the interceptor) -------------------------------- | Fault injection core creates | | a trigger that references this | | interceptor | -------------------------------- || \/ -------------- | arm(trigger) | ------------ -------------- || | || | \/ | --------------------------------------- |___ | take what ever action is required | | to hook into the low level event. | | This could be with kprobes, or kmmio, | | or whatever | --------------------------------------- (Event happens) ----------------------------- | Low level hook is triggered | ----------------------------- || \/ ---------------------------------------- | (call into fi_core) fi_execute_trigger | ---------------------------------------- (User stops using the interceptor) ----------------------------------------------- | Fault injection core removes the trigger that | | references this interceptor | ----------------------------------------------- || \/ ----------------- | disarm(trigger) | --------- ----------------- || | || | \/ | --------------------------------------- |___ | take what ever action is required | | to remove the level hooks we added | | when we first armed the interceptor | --------------------------------------- What is a 'code segment'? ------------------------- A code segment is a segment of code ;-) Driver developer writes it to afflict the driver. A code segment can be attached to a trigger and suppress the original opcodes in the trigger. When the trigger is qualified to act, the code segment will be called instead of trigger's opcodes. Life cycle of a code segment ---------------------------- ( Startup ) ---------------- | Initialization | ---------------- || || || \/ ------------------------------------------------ | (call into fi_core) fi_register_code_segment() | ------------------------------------------------ (User starts using the code segment) -------------------------------- | User attach the code segment | | with a trigger. | -------------------------------- || \/ ------------------------------------------ | (fi_core) arm_code_segment(cs, tri_name) | ------------------------------------------ (Event happens) -------------------------------------- | An interceptor triggers a trigger | | which is attched with a code segment | -------------------------------------- || \/ ---------------------------------------- | (call into fi_core) fi_execute_trigger | ---------------------------------------- || \/ ------------------------------ | (code segment) cs->execute() | ------------------------------ (User stops using the code segment) ------------------------------------ | User deattach relationship between | | trigger and code segment | ------------------------------------ || \/ ---------------------------------- | (fi_core) unarm_code_segment(cs) | ---------------------------------- ------------------------------------------------------- This sf.net email is sponsored by:ThinkGeek Welcome to geek heaven. http://thinkgeek.com/sf _______________________________________________ Fault-injection-developer mailing list Fau...@li... https://lists.sourceforge.net/lists/listinfo/fault-injection-developer |
From: Zhuang, L. <lou...@in...> - 2003-01-03 05:44:39
|
============================================================================ = This is the root directory for fault injection. Fault injection contains the following: fi_core.c : Core fault injection code. EXPORT_SYMBOL_GPL(fi_register_interceptor); EXPORT_SYMBOL_GPL(fi_unregister_interceptor); EXPORT_SYMBOL_GPL(fi_register_code_segment); EXPORT_SYMBOL_GPL(fi_unregister_code_segment); EXPORT_SYMBOL_GPL(fi_execute_trigger); EXPORT_SYMBOL_GPL(fi_debug); internal_testing/ : Proper place to add any code created for the purpose of testing the fault injection core code (not to to actually implement 'fault injection testing') * Current test code includes - mock interceptor : a simple interceptor implementation that can adds a 'trip' file to the specific trigger's sysfs directory to enable the trigger to be tripped via command line. - mock code segment: a simple code segment implementation that can report what values when the code segment is called. interceptors/ : Proper place to add any interceptor implementations. * Current interceptors are - pf : 'page fault' interceptor for intercepting MMIO - dbp : ??? cs/ : Proper place to add any code segment implementations * Current code segments are - sample : A sample code segment to demonstrate 'kmmio_invert_map' What is an 'interceptor'? ------------------------- An interceptor is a component that knows how to intercept some specific type of kernel level event or action to enable the fault injection core to 'hook' into event or action and take some action. An interceptor is one level higher then a normal kernel hook. For example an interceptor could be written to utilize kprobes, where the kprobe is tripped every time a specific address is executed, but the interceptor might contain some additional logic to decide if the specific event or action was happening. Life cycle of an interceptor ---------------------------- ( Startup ) ---------------- | Initialization | ---------------- || || || \/ ----------------------------------------------- | (call into fi_core) fi_register_interceptor() | ----------------------------------------------- (User starts using the interceptor) -------------------------------- | Fault injection core creates | | a trigger that references this | | interceptor | -------------------------------- || \/ -------------- | arm(trigger) | ------------ -------------- || | || | \/ | --------------------------------------- |___ | take what ever action is required | | to hook into the low level event. | | This could be with kprobes, or kmmio, | | or whatever | --------------------------------------- (Event happens) ----------------------------- | Low level hook is triggered | ----------------------------- || \/ ---------------------------------------- | (call into fi_core) fi_execute_trigger | ---------------------------------------- (User stops using the interceptor) ----------------------------------------------- | Fault injection core removes the trigger that | | references this interceptor | ----------------------------------------------- || \/ ----------------- | disarm(trigger) | --------- ----------------- || | || | \/ | --------------------------------------- |___ | take what ever action is required | | to remove the level hooks we added | | when we first armed the interceptor | --------------------------------------- What is a 'code segment'? ------------------------- A code segment is a segment of code ;-) Driver developer writes it to afflict the driver. A code segment can be attached to a trigger and suppress the original opcodes in the trigger. When the trigger is qualified to act, the code segment will be called instead of trigger's opcodes. Life cycle of a code segment ---------------------------- ( Startup ) ---------------- | Initialization | ---------------- || || || \/ ------------------------------------------------ | (call into fi_core) fi_register_code_segment() | ------------------------------------------------ (User starts using the code segment) -------------------------------- | User attach the code segment | | with a trigger. | -------------------------------- || \/ ------------------------------------------ | (fi_core) arm_code_segment(cs, tri_name) | ------------------------------------------ (Event happens) -------------------------------------- | An interceptor triggers a trigger | | which is attched with a code segment | -------------------------------------- || \/ ---------------------------------------- | (call into fi_core) fi_execute_trigger | ---------------------------------------- || \/ ------------------------------ | (code segment) cs->execute() | ------------------------------ (User stops using the code segment) ------------------------------------ | User deattach relationship between | | trigger and code segment | ------------------------------------ || \/ ---------------------------------- | (fi_core) unarm_code_segment(cs) | ---------------------------------- ------------------------------------------------------- This sf.net email is sponsored by:ThinkGeek Welcome to geek heaven. http://thinkgeek.com/sf _______________________________________________ Fault-injection-developer mailing list Fau...@li... https://lists.sourceforge.net/lists/listinfo/fault-injection-developer |
From: Zhuang, L. <lou...@in...> - 2003-01-03 03:31:26
|
Based on suggestion from Kevin, I found fi_core is better to attach trigger with interceptors by *name*. So I'd like to change the ctl command as following echo "add <trigger_name> <interceptor_type> .... " > /sys/triggers/ctl || \/ echo "add <trigger_name> <interceptor_name> .... " > /sys/triggers/ctl |
From: Zhuang, L. <lou...@in...> - 2003-01-03 03:06:29
|
============================================================================ = This is the root directory for fault injection. Fault injection contains the following: fi_core.c : Core fault injection code. EXPORT_SYMBOL_GPL(fi_register_interceptor); EXPORT_SYMBOL_GPL(fi_unregister_interceptor); EXPORT_SYMBOL_GPL(fi_register_code_segment); EXPORT_SYMBOL_GPL(fi_unregister_code_segment); EXPORT_SYMBOL_GPL(fi_execute_trigger); EXPORT_SYMBOL_GPL(fi_debug); internal_testing/ : Proper place to add any code created for the purpose of testing the fault injection core code (not to to actually implement 'fault injection testing') * Current test code includes - mock interceptor : a simple interceptor implementation that can adds a 'trip' file to the specific trigger's sysfs directory to enable the trigger to be tripped via command line. - mock code segment: a simple code segment implementation that can report what values when the code segment is called. interceptors/ : Proper place to add any interceptor implementations. * Current interceptors are - pf : 'page fault' interceptor for intercepting MMIO - dbp : ??? cs/ : Proper place to add any code segment implementations * Current code segments are - sample : A sample code segment to demonstrate 'kmmio_invert_map' What is an 'interceptor'? ------------------------- An interceptor is a component that knows how to intercept some specific type of kernel level event or action to enable the fault injection core to 'hook' into event or action and take some action. An interceptor is one level higher then a normal kernel hook. For example an interceptor could be written to utilize kprobes, where the kprobe is tripped every time a specific address is executed, but the interceptor might contain some additional logic to decide if the specific event or action was happening. Life cycle of an interceptor ---------------------------- ( Startup ) ---------------- | Initialization | ---------------- || || || \/ ----------------------------------------------- | (call into fi_core) fi_register_interceptor() | ----------------------------------------------- (User starts using the interceptor) -------------------------------- | Fault injection core creates | | a trigger that references this | | interceptor | -------------------------------- || \/ -------------- | arm(trigger) | ------------ -------------- || | || | \/ | --------------------------------------- |___ | take what ever action is required | | to hook into the low level event. | | This could be with kprobes, or kmmio, | | or whatever | --------------------------------------- (Event happens) ----------------------------- | Low level hook is triggered | ----------------------------- || \/ ---------------------------------------- | (call into fi_core) fi_execute_trigger | ---------------------------------------- (User stops using the interceptor) ----------------------------------------------- | Fault injection core removes the trigger that | | references this interceptor | ----------------------------------------------- || \/ ----------------- | disarm(trigger) | --------- ----------------- || | || | \/ | --------------------------------------- |___ | take what ever action is required | | to remove the level hooks we added | | when we first armed the interceptor | --------------------------------------- What is a 'code segment'? ------------------------- A code segment is a segment of code ;-) Driver developer writes it to afflict the driver. A code segment can be attached to a trigger and suppress the original opcodes in the trigger. When the trigger is qualified to act, the code segment will be called instead of trigger's opcodes. Life cycle of a code segment ---------------------------- ( Startup ) ---------------- | Initialization | ---------------- || || || \/ ------------------------------------------------ | (call into fi_core) fi_register_code_segment() | ------------------------------------------------ (User starts using the code segment) -------------------------------- | User attach the code segment | | with a trigger. | -------------------------------- || \/ ------------------------------------------ | (fi_core) arm_code_segment(cs, tri_name) | ------------------------------------------ (Event happens) -------------------------------------- | An interceptor triggers a trigger | | which is attched with a code segment | -------------------------------------- || \/ ---------------------------------------- | (call into fi_core) fi_execute_trigger | ---------------------------------------- || \/ ------------------------------ | (code segment) cs->execute() | ------------------------------ (User stops using the code segment) ------------------------------------ | User deattach relationship between | | trigger and code segment | ------------------------------------ || \/ ---------------------------------- | (fi_core) unarm_code_segment(cs) | ---------------------------------- ------------------------------------------------------- This sf.net email is sponsored by:ThinkGeek Welcome to geek heaven. http://thinkgeek.com/sf _______________________________________________ Fault-injection-developer mailing list Fau...@li... https://lists.sourceforge.net/lists/listinfo/fault-injection-developer |
From: Zhuang, L. <lou...@in...> - 2003-01-03 01:53:51
|
The name of DBP came from FITH white paper and I got the name from = James... It is a too long history to remember. Any better name? -----Original Message----- From: Wang, Stanley [mailto:sta...@in...] Sent: Friday, January 03, 2003 9:18 AM To: 'Rusty Lynch'; fau...@so... Subject: RE: [Fault-injection-developer] Back from holidays with a new = REA DME Description for fi_dbp :) Thanks. > -----Original Message----- > From: Rusty Lynch [mailto:ru...@li...] > Sent: 2003=E5=B9=B41=E6=9C=883=E6=97=A5 7:10 > To: fau...@so... > Subject: [Fault-injection-developer] Back from holidays with > a new README > interceptors/ : Proper place to add any interceptor implementations. > * Current interceptors are > - pf : 'page fault' interceptor for intercepting MMIO > - dbp : ??? dbp: "Dynamic Binary Patch" interceptor for intercepting PIO ------------------------------------------------------- This sf.net email is sponsored by:ThinkGeek Welcome to geek heaven. http://thinkgeek.com/sf _______________________________________________ Fault-injection-developer mailing list Fau...@li... https://lists.sourceforge.net/lists/listinfo/fault-injection-developer |
From: Wang, S. <sta...@in...> - 2003-01-03 01:20:45
|
Description for fi_dbp :) Thanks. > -----Original Message----- > From: Rusty Lynch [mailto:ru...@li...] > Sent: 2003=E5=B9=B41=E6=9C=883=E6=97=A5 7:10 > To: fau...@so... > Subject: [Fault-injection-developer] Back from holidays with=20 > a new README > interceptors/ : Proper place to add any interceptor implementations. > * Current interceptors are > - pf : 'page fault' interceptor for intercepting MMIO > - dbp : ??? dbp: "Dynamic Binary Patch" interceptor for intercepting PIO |
From: Zhuang, L. <lou...@in...> - 2003-01-03 01:02:08
|
Welcome back, Rusty! Happy New Year to you and all coworkers in the mailing list! Your README is really good and clarifies many things. So... let me clarify two files too ;->. 1. 'fi_mock_cs.c' is the simplest code segment and do nothing but printk. It should be in '/cs' directory. 2. 'fi_sample_cs.c' is another sample code segment. It should be in '/cs' directory. It demonstrates the usage of a new function in kmmio. The 'kmmio_invert_map' can make the virtual page point to the specified physics address. The function is not relative with kmmio really except using some inline functions in arch/i386/kernel/kmmio.c. So I put the function into that file. Maybe I should found a better position and name for the function. - Louis -----Original Message----- From: Rusty Lynch [mailto:ru...@li...] Sent: Friday, January 03, 2003 7:10 AM To: fau...@so... Subject: [Fault-injection-developer] Back from holidays with a new README I'm back from a nice long vacation with lots of new code to review. Hmm... looking around I first notice that we have done a little bit of file location shuffling. Things are starting to get a little confusing, so I think it is a good time to add a simple README. Also, since we have been adding more implementation files we really need to follow some common schema for what files should be placed where. Checkout the following README file. I spells out a file schema and also lays down the framework for documenting concepts like interceptors. Also, if we are really going to create a 'fi' directory containing all fault injection implementation code, then it makes more sense to create a drivers/fi/ directory instead of a drivers/char/fi/directory. After all, fi is not really a char device. -rustyl ============================================================================ = This is the root directory for fault injection. Fault injection contains the following: fi_core.c : Core fault injection code. EXPORT_SYMBOL_GPL(fi_register_interceptor); EXPORT_SYMBOL_GPL(fi_unregister_interceptor); EXPORT_SYMBOL_GPL(fi_register_code_segment); EXPORT_SYMBOL_GPL(fi_unregister_code_segment); EXPORT_SYMBOL_GPL(fi_execute_trigger); EXPORT_SYMBOL_GPL(fi_debug); internal_testing/ : Proper place to add any code created for the purpose of testing the fault injection core code (not to to actually implement 'fault injection testing') * Current test code includes - mock interceptor : a simple interceptor implementation that can be configured to represent any interceptor type, and adds a 'trip' file to the specific trigger's sysfs directory to enable the trigger to be tripped via command line. - mock code segment : a simple code segment implementation that ??? interceptors/ : Proper place to add any interceptor implementations. * Current interceptors are - pf : 'page fault' interceptor for intercepting MMIO - dbp : ??? cs/ : Proper place to add any code segment implementations * Current code segments are - sample : ??? What is an 'interceptor'? ------------------------- An interceptor is a component that knows how to intercept some specific type of kernel level event or action to enable the fault injection core to 'hook' into event or action and take some action. An interceptor is one level higher then a normal kernel hook. For example an interceptor could be written to utilize kprobes, where the kprobe is tripped every time a specific address is executed, but the interceptor might contain some additional logic to decide if the specific event or action was happening. Life cycle of an interceptor ---------------------------- ( Startup ) ---------------- | Initialization | ---------------------------- ---------------- || || | \/ || | ------------------------------------------ || | | initialize a 'interceptor' kernel object | || ------- | with function pointers for the fault | || | injection core to interface with this | || | interceptor | || ------------------------------------------ || || || \/ ----------------------------------------------- | (call into fi_core) fi_register_interceptor() | ----------------------------------------------- (User starts using the interceptor) -------------------------------- | Fault injection core creates | | a trigger that references this | | interceptor | -------------------------------- || \/ -------------- | arm(trigger) | ------------ -------------- || | || | \/ | --------------------------------------- |___ | take what ever action is required | | to hook into the low level event. | | This could be with kprobes, or kmmio, | | or whatever | --------------------------------------- (Event happens) ----------------------------- | Low level hook is triggered | ----------------------------- || \/ ---------------------------------------- | (call into fi_core) fi_execute_trigger | ---------------------------------------- (User stops using the interceptor) ----------------------------------------------- | Fault injection core removes the trigger that | | references this interceptor | ----------------------------------------------- || \/ ----------------- | disarm(trigger) | --------- ----------------- || | || | \/ | --------------------------------------- |___ | take what ever action is required | | to remove the level hooks we added | | when we first armed the interceptor | --------------------------------------- What is a 'code segment'? ------------------------- Life cycle of a code segment ---------------------------- ------------------------------------------------------- This sf.net email is sponsored by:ThinkGeek Welcome to geek heaven. http://thinkgeek.com/sf _______________________________________________ Fault-injection-developer mailing list Fau...@li... https://lists.sourceforge.net/lists/listinfo/fault-injection-developer |
From: Wang, S. <sta...@in...> - 2003-01-03 00:54:52
|
Sorry for lacking description for it :) > I would like to build PIO interceptor on a base of Kprobes. > I'll illustrate the workflow of them. > The one (whose name is "DBP") based on Kprobes: > Registration/Unregistration: > wp_register =20 > core -------------------->dbp_register--------------> register_kprobe >=20 > wp_unregister =20 > core -------------------->dbp_unregister--------------> = unregister_kprobe >=20 >=20 > Fault injection: > =20 > there is write fault > do_int3----------------->dbp_pre_kprobe_handler-------------------------= ->co > re-------------->(inject write fault) >=20 > do_debug------------->dbp_post_kpobe_handler-------------------------->c= ore- > -------------- > ------->inject read fault or restore context for injected write fault >=20 > pros: > 1. As many breakpoints as you wish :) >=20 > cons: > 1. A user mode utility is needed for finding all IO related = instructions > out. > 2. And we need to export the symbol "modules" for locating the wanted > instructions. =20 The utility(fi_attach) for fi_dbp is responsible for finding and = locating all PIO=20 instruction in a loaded kernel module. fi_attach useage: ./fi_attach $module_name You could use /sys/fault_injection/interceptors/dbp_interceptor/ctl = directly also: echo "attach $module_name $instruction_counter" > ctl echo "add $instruction_addr" > ctl echo "add $instruction_addr" > ctl echo "add $instruction_addr" > ctl echo "add $instruction_addr" > ctl =20 | | | | echo "end" > ctl When you want to detach the module from fi_dbp: echo "detach $module_name" > ctl That's all :) Thanks. > -----Original Message----- > From: Rusty Lynch [mailto:ru...@li...] > Sent: 2003=C4=EA1=D4=C23=C8=D5 8:28 > To: Wang, Stanley; fau...@li... > Subject: Re: [Fault-injection-developer] RFC: fi_dbp >=20 >=20 > Wow, I could use a trail of bread crumbs to lead me through this = code. > How about at least giving some basic information at the top=20 > of fi_dbp.c > like: >=20 > * What does dbp mean? > * How is this interceptor used?=20 > * What is this extra 'ctl' file for? Maybe explain the whole=20 > attaching,=20 > adding, detaching cycle. >=20 > -rustyl >=20 |
From: Rusty L. <ru...@li...> - 2003-01-03 00:28:13
|
Wow, I could use a trail of bread crumbs to lead me through this code. How about at least giving some basic information at the top of fi_dbp.c like: * What does dbp mean? * How is this interceptor used? * What is this extra 'ctl' file for? Maybe explain the whole attaching, adding, detaching cycle. -rustyl |
From: Rusty L. <ru...@li...> - 2003-01-02 23:45:44
|
I found another problem when I tried to compile you latest fi_irq.c code that uses kirq. This header file is declaring kirq_list, so that multiple object files attempt to include this header file (which I see if I try to build fi_irq.c into the kernel) then the compile fails because multiple instances of kirq_list are created. You can fix this by moving > +struct kirq kirq_list[NR_IRQS] = > + { [0 ... NR_IRQS-1] = { NULL, NULL, NULL}}; > + to kirq.c -rustyl > diff -Nru a/include/asm-i386/kirq.h b/include/asm-i386/kirq.h > --- /dev/null Wed Dec 31 16:00:00 1969 > +++ b/include/asm-i386/kirq.h Fri Dec 20 14:24:01 2002 > @@ -0,0 +1,28 @@ > +#ifndef _ASM_KIRQ_H > +#define _ASM_KIRQ_H > + > +#include <linux/errno.h> > + > +/* Define return value for kirq handler. */ > +#define KIRQ_CONTINUE 0 > +#define KIRQ_SKIP 1 > + > +struct kirq; > +typedef int (*kirq_handler_t)(struct kirq *, int, void *, struct pt_regs > *); > +struct kirq { > + void *dev_id; > + void (*isr)(int, void *, struct pt_regs *); > + kirq_handler_t handler; > +}; > + > +struct kirq kirq_list[NR_IRQS] = > + { [0 ... NR_IRQS-1] = { NULL, NULL, NULL}}; > + > +#ifdef CONFIG_KIRQ > +extern int register_kirq(int irq, char *devname, kirq_handler_t handler); > +extern int unregister_kirq(int irq); > +#else > +int register_kirq(int irq, char *devname, kirq_handler_t handler) { return > -ENOSYS; } > +int unregister_kirq(int irq) {} > +#endif /*CONFIG_KIRQ*/ > +#endif /*_ASM_KIRQ_H*/ |
From: Rusty L. <ru...@li...> - 2003-01-02 23:22:18
|
Is there a good reason for having both a fi.h and a fi_internal.h? I know we use to expose a header file for user space apps to use back when user/kernel interaction happened with ioctls, but now there is no reason any non-kernel code would need to use our header file. -rustyl |
From: Rusty L. <ru...@li...> - 2003-01-02 23:10:20
|
I'm back from a nice long vacation with lots of new code to review. Hmm... looking around I first notice that we have done a little bit of file location shuffling. Things are starting to get a little confusing, so I think it is a good time to add a simple README. Also, since we have been adding more implementation files we really need to follow some common schema for what files should be placed where. Checkout the following README file. I spells out a file schema and also lays down the framework for documenting concepts like interceptors. Also, if we are really going to create a 'fi' directory containing all fault injection implementation code, then it makes more sense to create a drivers/fi/ directory instead of a drivers/char/fi/directory. After all, fi is not really a char device. -rustyl ============================================================================= This is the root directory for fault injection. Fault injection contains the following: fi_core.c : Core fault injection code. EXPORT_SYMBOL_GPL(fi_register_interceptor); EXPORT_SYMBOL_GPL(fi_unregister_interceptor); EXPORT_SYMBOL_GPL(fi_register_code_segment); EXPORT_SYMBOL_GPL(fi_unregister_code_segment); EXPORT_SYMBOL_GPL(fi_execute_trigger); EXPORT_SYMBOL_GPL(fi_debug); internal_testing/ : Proper place to add any code created for the purpose of testing the fault injection core code (not to to actually implement 'fault injection testing') * Current test code includes - mock interceptor : a simple interceptor implementation that can be configured to represent any interceptor type, and adds a 'trip' file to the specific trigger's sysfs directory to enable the trigger to be tripped via command line. - mock code segment : a simple code segment implementation that ??? interceptors/ : Proper place to add any interceptor implementations. * Current interceptors are - pf : 'page fault' interceptor for intercepting MMIO - dbp : ??? cs/ : Proper place to add any code segment implementations * Current code segments are - sample : ??? What is an 'interceptor'? ------------------------- An interceptor is a component that knows how to intercept some specific type of kernel level event or action to enable the fault injection core to 'hook' into event or action and take some action. An interceptor is one level higher then a normal kernel hook. For example an interceptor could be written to utilize kprobes, where the kprobe is tripped every time a specific address is executed, but the interceptor might contain some additional logic to decide if the specific event or action was happening. Life cycle of an interceptor ---------------------------- ( Startup ) ---------------- | Initialization | ---------------------------- ---------------- || || | \/ || | ------------------------------------------ || | | initialize a 'interceptor' kernel object | || ------- | with function pointers for the fault | || | injection core to interface with this | || | interceptor | || ------------------------------------------ || || || \/ ----------------------------------------------- | (call into fi_core) fi_register_interceptor() | ----------------------------------------------- (User starts using the interceptor) -------------------------------- | Fault injection core creates | | a trigger that references this | | interceptor | -------------------------------- || \/ -------------- | arm(trigger) | ------------ -------------- || | || | \/ | --------------------------------------- |___ | take what ever action is required | | to hook into the low level event. | | This could be with kprobes, or kmmio, | | or whatever | --------------------------------------- (Event happens) ----------------------------- | Low level hook is triggered | ----------------------------- || \/ ---------------------------------------- | (call into fi_core) fi_execute_trigger | ---------------------------------------- (User stops using the interceptor) ----------------------------------------------- | Fault injection core removes the trigger that | | references this interceptor | ----------------------------------------------- || \/ ----------------- | disarm(trigger) | --------- ----------------- || | || | \/ | --------------------------------------- |___ | take what ever action is required | | to remove the level hooks we added | | when we first armed the interceptor | --------------------------------------- What is a 'code segment'? ------------------------- Life cycle of a code segment ---------------------------- |
From: Wang, S. <sta...@in...> - 2002-12-31 10:12:44
|
Hi, folks Here is utility for fi_dbp: Compile : gcc -lbfd -ldisasm -o fi_attach fi_attach.c Use: fi_attach $module.ko (after insmod the $module.ko) #include <stdio.h> #include <bfd.h> #include <libdis.h> #define CTL "/sys/fault_injection/interceptors/dbp_interceptor/ctl" int main(int argc, char **argv) { bfd *f; asection *sec, *mod; unsigned char *s; struct instr ins; char **matching; FILE * fp; int i; int counter=0; unsigned long addr[10000]; bfd_byte *data = 0; bfd_byte *modname = 0; unsigned int pos = 0; unsigned int size = 0; bfd_init(); bfd_set_default_target("elf32-i386"); f = bfd_openr(argv[1], "elf32-i386"); if (f == NULL) { fprintf(stderr, "bfd_openr ERROR!\n"); return 0; } if (bfd_check_format_matches (f, bfd_object, &matching)){ sec = bfd_get_section_by_name(f, ".text"); if (sec == NULL) { fprintf(stderr, "bfd_get_section_by_name ERROR!\n"); goto err; } mod = bfd_get_section_by_name(f, ".gnu.linkonce.modname"); if (mod == NULL) { fprintf(stderr, "bfd_get_section_by_name ERROR!\n"); goto err; } } else { fprintf(stderr, "Isn't bdf_object file!\n"); goto err; } data = (bfd_byte *) xmalloc ((size_t) bfd_section_size (f, sec)); bfd_get_section_contents (f, sec, (PTR) data, 0, bfd_section_size (f, sec)); modname = (bfd_byte *) xmalloc ((size_t) bfd_section_size (f, mod)); bfd_get_section_contents (f, mod, (PTR) modname, 0, bfd_section_size (f, mod)); s = data; disassemble_init(0,INTEL_SYNTAX); while(pos < sec->_raw_size) { size = disassemble_address(s+pos, &ins); if ( size > 0 ) { if (!strcmp(ins.mnemonic, "in") || !strcmp(ins.mnemonic, "out")) { addr[counter++] = pos; } pos += size; } else { fprintf(stderr, "ERROR!\n"); return -1; } } disassemble_cleanup(); fp = fopen (CTL, "w+"); fprintf(fp, "attach %s %i\n", (char *)modname, counter); fclose(fp); for (i=0;i<counter;i++) { fp = fopen (CTL, "w+"); fprintf(fp, "add %i\n", addr[i]); fclose(fp); } fp = fopen (CTL, "w+"); fprintf(fp, "end\n"); fclose(fp); err: bfd_close(f); return 0; } 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 |
From: Wang, S. <sta...@in...> - 2002-12-31 10:10:33
|
Hi, folks Here is the fi_dbp: # 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.961 -> 1.977 # drivers/char/fi/Makefile 1.9 -> 1.10 # (new) -> 1.1 drivers/char/fi/dbp/Makefile # (new) -> 1.1 drivers/char/fi/dbp/fi_dbp.h # (new) -> 1.5 drivers/char/fi/dbp/fi_dbp.c # # The following is the BitKeeper ChangeSet Log # -------------------------------------------- # 02/12/27 st...@ma... 1.964 # Add FI_DBP # -------------------------------------------- # 02/12/30 st...@ma... 1.966 # Change name : "attach" -> "ctl" # -------------------------------------------- # 02/12/30 st...@ma... 1.967 # Bug fix for fi_dbp # -------------------------------------------- # 02/12/30 st...@ma... 1.968 # Merge bk://fau...@fa.../linux-2.5 # into manticore.sh.intel.com:/home/stanley/fi-bkbits # -------------------------------------------- # 02/12/31 st...@ma... 1.968.1.1 # Bug fix for fi_dbp # -------------------------------------------- # 02/12/31 st...@ma... 1.976 # Merge bk://fau...@fa.../linux-2.5 # into manticore.sh.intel.com:/home/stanley/fi-bkbits # -------------------------------------------- # 02/12/31 st...@ma... 1.977 # Remove interceptor type # -------------------------------------------- # diff -Nru a/drivers/char/fi/Makefile b/drivers/char/fi/Makefile --- a/drivers/char/fi/Makefile Tue Dec 31 17:43:41 2002 +++ b/drivers/char/fi/Makefile Tue Dec 31 17:43:41 2002 @@ -3,6 +3,7 @@ # obj-y += pf/ +obj-y += dbp/ EXTRA_AFLAGS := -traditional diff -Nru a/drivers/char/fi/dbp/Makefile b/drivers/char/fi/dbp/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/char/fi/dbp/Makefile Tue Dec 31 17:43:41 2002 @@ -0,0 +1,9 @@ +# +# Makefile for the linux kernel. +# +export-objs = fi_dbp.o + +obj-$(CONFIG_FI_DBP) += fi_dbp.o + + +EXTRA_AFLAGS := -traditional diff -Nru a/drivers/char/fi/dbp/fi_dbp.c b/drivers/char/fi/dbp/fi_dbp.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/char/fi/dbp/fi_dbp.c Tue Dec 31 17:43:41 2002 @@ -0,0 +1,630 @@ +/************************************************************************** **** + * 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_dbp.c,v 1.9 2002/11/19 08:03:04 brlock Exp $ + * Copyright by Intel Crop., 2002 + * Stanley Wang (sta...@in...) + * + */ + +/** + * @file dbp.c + */ + +#include <linux/config.h> +#include <linux/version.h> + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/types.h> +#include <linux/errno.h> +#include <linux/sched.h> +#include <linux/irq.h> +#include <linux/interrupt.h> +#include <linux/spinlock.h> +#include <linux/mm.h> +#include <linux/slab.h> +#include <asm/atomic.h> +#include <asm/debugreg.h> +#include <asm/uaccess.h> +#include <linux/smp.h> +#include <linux/kprobes.h> + +#include "fi_dbp.h" + +static int dbp_arm(struct trigger *t) +{ + unsigned long flags; + int i=0; + + if ( t->wp.type& (~FI_WPTYPE_ALL_MASK) ) { + err("Reason: %s\n", "/* There are reserved bits in use*/"); + return -EINVAL; + } + if (!is_IO(t->wp.type)) { + err("Reason: %s\n", "/* Isn't I/O access*/"); + return -EINVAL; + } + if ( (unsigned int)t->wp.addr>0xffff ) { + err("Reason: %s\n", "/* beyond 64k IO space*/"); + return -EINVAL; + } + + + /* Make sure there are no the same wp or id */ + for (i=0; i<MAX_WP; i++){ + if (t->wp.addr==wp_tb[i].wp.addr) { + err("Reason: %s\n", "/*there are same wp*/"); + return -EINVAL; + } + } + +find_empty_wp: + /* find empty item in wp_tb */ + for (i=0; i<MAX_WP; i++){ + if (wp_tb[i].wp.addr==0){ + break; + } + } + if (i>=MAX_WP) return -EINVAL; + + /*LOCK! NOTICE!!!*/ + spin_lock_irqsave(&wp_tb[i].lock, flags); + if (wp_tb[i].wp.addr!=0) { + //if there is some one who changed the wp before we lock it + spin_unlock_irqrestore(&wp_tb[i].lock, flags); + goto find_empty_wp; + } + + /* register this wp into wp_tb*/ + wp_tb[i].wp.addr = t->wp.addr; + wp_tb[i].wp.type = t->wp.type; + wp_tb[i].trigger = t; + + /* UNLOCK! NOTICE!!! */ + spin_unlock_irqrestore(&wp_tb[i].lock, flags); + return 0; +} + +void dbp_disarm(struct trigger *t) +{ + unsigned long flags; + int i = 0; + +find_wp_by_addr: + for (i=0; i<MAX_WP; i++) { + if (wp_tb[i].wp.addr == t->wp.addr) { + break; + } + } + if (i>=MAX_WP) return ; + + /* LOCK */ + spin_lock_irqsave(&wp_tb[i].lock, flags); + if (wp_tb[i].wp.addr!=t->wp.addr) { + spin_unlock_irqrestore(&wp_tb[i].lock, flags); + goto find_wp_by_addr; + } + + wp_tb[i].wp.addr = 0; + wp_tb[i].wp.type = 0; + wp_tb[i].trigger = NULL; + /* UNLOCK */ + spin_unlock_irqrestore(&wp_tb[i].lock, flags); + return; +} + +void dbp_corrupt(__u32 dirty, void *data) +{ + unsigned long mask = ((struct corrupt*)data)->mask; + *(((struct corrupt*)data)->preg) &= ~mask; + *(((struct corrupt*)data)->preg) |= (dirty&mask); + dbg("corrupt data to:%#lX\n", dirty&mask); + return; +} + +int get_IO_opcode(struct opcode *op, struct pt_regs *regs) +{ + unsigned char *p; + int flag_16=0; + + p = (unsigned char*)(regs->eip); + if (*p == PREFIX_16) { + flag_16 = 1; /*word*/ + p++; + } + switch(*p) { + case 0xec: + op->port = regs->edx; + op->write = 0; + op->len = 1; /*byte*/ + op->inst_len = 1; + dbg("OPCODE: %lX\n",*(unsigned long*)p); + return 0; + case 0xed: + op->port = regs->edx; + op->write = 0; + if (flag_16) { + op->len = 2; /*word*/ + op->inst_len = 2; + } else { + op->len = 4; /*double word*/ + op->inst_len = 1; + } + dbg("OPCODE: %lX\n",*(unsigned long*)p); + return 0; + case 0xee: + op->port = regs->edx; + op->write = 1; + op->len = 1; /*byte*/ + op->inst_len = 1; + dbg("OPCODE: %lX\n",*(unsigned long*)p); + return 0; + case 0xef: + op->port = regs->edx; + op->write = 1; + if (flag_16) { + op->len = 2; /*word*/ + op->inst_len = 2; + } else { + op->len = 4; /*double word*/ + op->inst_len = 1; + } + dbg("OPCODE: %lX\n",*(unsigned long*)p); + return 0; + case 0xe4: + op->port = *(++p); + op->write = 0; + op->len = 1; /*byte*/ + op->inst_len = 2; + dbg("OPCODE: %lX\n",*(unsigned long*)p); + return 0; + case 0xe5: + op->port = *(++p); + op->write = 0; + if (flag_16) { + op->len = 2; /*word*/ + op->inst_len = 3; + } else { + op->len = 4; /*double word*/ + op->inst_len = 2; + } + dbg("OPCODE: %lX\n",*(unsigned long*)p); + return 0; + case 0xe6: + op->port = *(++p); + op->write = 1; + op->len = 1; /*byte*/ + op->inst_len = 2; + dbg("OPCODE: %lX\n",*(unsigned long*)p); + return 0; + case 0xe7: + op->port = *(++p); + op->write = 1; + if (flag_16) { + op->len = 2; /*word*/ + op->inst_len = 3; + } else { + op->len = 4; /*double word*/ + op->inst_len = 2; + } + dbg("OPCODE: %lX\n",*(unsigned long*)p); + return 0; + default: + err("Can't analyze IO opcode! @%s\n", __FILE__); + return -EINVAL; + } + + dbg("OPCODE: %lX\n",*(unsigned long*)p); + return 0; +} + +void pre_probe_handler(struct kprobe *kprobe, struct pt_regs * regs) +{ + struct opcode op; + struct corrupt crpt; + int i; + unsigned long origin; + int cpu = smp_processor_id(); + + dbg("Enter pre_probe_handler, Instruction @ %lX\n",(unsigned long)(regs->eip - 1)); + + *kprobe->addr = kprobe->opcode; /*restore the original opcode*/ + regs->eip = (unsigned long)kprobe->addr; /*back step*/ + + i = get_IO_opcode(&op, regs); + if ( i < 0 ) { + err("Can't analyze opcode! @%s\n", __FILE__); + goto exit; + } + + regs->eip += 1; + + which_inst[cpu].op.port = op.port; + which_inst[cpu].op.write = op.write; + which_inst[cpu].op.inst_len = op.inst_len; + which_inst[cpu].value = regs->eax; + + i=0; + +find_wp_by_addr: + i=find_wp((unsigned long)(op.port));/*XXX*/ + if (i>=MAX_WP) { + /*not watched by me*/ + which_inst[cpu].reason = REASON_NOTME; + goto exit; + } + /*LOCK!*/ + spin_lock(&wp_tb[i].lock); + if (wp_tb[i].wp.addr!=(unsigned long)(op.port)) { + //there are others who modify this wp + spin_unlock(&wp_tb[i].lock); + goto find_wp_by_addr; + } + if (op.write){ + if (!is_write(wp_tb[i].wp.type)) { + spin_unlock(&wp_tb[i].lock); + which_inst[cpu].reason = REASON_NOTME; + goto exit; + } + }else if (!is_read(wp_tb[i].wp.type)) { + spin_unlock(&wp_tb[i].lock); + which_inst[cpu].reason = REASON_NOTME; + goto exit; + } + + which_inst[cpu].op.len = access_len(wp_tb[i].wp.type); + which_inst[cpu].wp_tab_id = i; + + if (op.write) { + /*inject write fault*/ + crpt.preg = &(regs->eax); + switch (which_inst[cpu].op.len) { + case 1: + crpt.mask =0xFF; + break; + case 2: + crpt.mask =0xFFFF; + break; + case 4: + crpt.mask =0xFFFFFFFF; + break; + default: + err("Wrong length!@%s\n", __FILE__); + break; + } + origin = (regs->eax)&crpt.mask; + fi_execute_trigger(wp_tb[i].trigger, &dbp_interceptor, origin, \ + op.len, op.write, &crpt); + /*UNLOCK*/ + spin_unlock(&wp_tb[i].lock); + which_inst[cpu].reason = REASON_WRITE; + }else { + /*inject read fault*/ + which_inst[cpu].reason = REASON_READ; + } + +exit: + return; +} + +void post_probe_handler(struct kprobe *kprobe, struct pt_regs *regs, unsigned long flags) +{ + unsigned long origin; + struct corrupt crpt; + int cpu; + + cpu = smp_processor_id(); + + dbg("Enter post_probe_handler @CPU%d\n", smp_processor_id()); + + switch (which_inst[cpu].reason) { + case REASON_WRITE: + regs->eax = which_inst[cpu].value; + case REASON_NOTME: + which_inst[cpu].reason = -1; + break; + case REASON_READ: + which_inst[cpu].reason = -1; + + crpt.preg = &(regs->eax); + if(which_inst[cpu].op.len == 1) { + crpt.mask =0xFF; + } + if(which_inst[cpu].op.len == 2) { + crpt.mask =0xFFFF; + } + if(which_inst[cpu].op.len == 4) { + crpt.mask =0xFFFFFFFF; + } + if(which_inst[cpu].op.len > 4 || which_inst[cpu].op. len < 1) { + err("Wrong length!@%s\n", __FILE__); + } + origin = (regs->eax)&crpt.mask; + fi_execute_trigger(wp_tb[which_inst[cpu].wp_tab_id]. trigger, \ + &dbp_interceptor,origin, which_inst[cpu].op.len, \ + which_inst[cpu].op.write, &crpt); + /*UNLOCK*/ + spin_unlock(&wp_tb[which_inst[cpu].wp_tab_id].lock); + break; + default: + return; + } + return ; +} + +int attach_module(const char *page) +{ + int num=0; + int i=0; + char tmp[16]; + + for(i=0;i<MAX_MOD;i++){ + if(inst_tab[i].counter <= 0) { + break; + } + } + if(i > MAX_MOD) { + return -EINVAL; + } + + num = sscanf(page, "%15s %s %d", tmp, inst_tab[i].modname, &inst_tab[i].counter); + if (num != 3) { + err("Invalid command format, translated no commands\n"); + goto err; + } + + if (inst_tab[i].counter == 0) { + err("Needn't to attach %s\n", inst_tab[i].modname); + goto err; + } + + inst_tab[i].kprobes = (struct kprobe*)kmalloc(inst_tab[i].counter*(sizeof(struct kprobe)), GFP_KERNEL); + if(inst_tab[i].kprobes == NULL) { + err("No memory @ %s\n", __FUNCTION__); + goto err; + } + + mod_index = i; + ins_index = 0; + return 0; +err: + inst_tab[i].modname[0] = '\0'; + inst_tab[i].counter = 0; + return -EINVAL; +} + +void add_ins(const char *page) +{ + char tmp[16]; + int num=0; + unsigned long addr=0; + struct module *mod; + + num = sscanf(page, "%15s %lu", tmp, &addr); + if (num != 2) { + err("Invalid command format, translated no commands\n"); + return; + } + if (ins_index > inst_tab[mod_index].counter - 1) { + err("Exceed address table!\n"); + return; + } + mod = fi_get_module((const char *)(inst_tab[mod_index].modname)); + if (!mod) { + err("Can not get module, not be loaded?\n"); + return; + } + dbg("module_core:%#lx\toff_set:%ld\n",(unsigned long)mod->module_core, addr); + inst_tab[mod_index].kprobes[ins_index].addr = (kprobe_opcode_t *)(addr + mod->module_core); + inst_tab[mod_index].kprobes[ins_index].pre_handler = pre_probe_handler; + inst_tab[mod_index].kprobes[ins_index].post_handler = post_probe_handler; + inst_tab[mod_index].kprobes[ins_index].fault_handler = NULL; + if ( register_kprobe(&(inst_tab[mod_index].kprobes[ins_index])) < 0 ) + { + err("register_kprobe failed @ %s\n", __FUNCTION__); + return; + } + fi_put_module(); + ins_index++; + return; +} +int detach_module(const char *page) +{ + int num=0; + int i=0; + int j=0; + char tmp[16]; + char modname[256]; + + num = sscanf(page, "%15s %s", tmp, modname); + if (num != 2) { + err("Invalid command format, translated no commands\n"); + return 0; + } + + for(i=0;i<MAX_MOD;i++){ + if(!strcmp(inst_tab[i].modname, modname)) { + break; + } + } + if(i > MAX_MOD) { + return -EINVAL; + } + + for(j=0;j<inst_tab[i].counter;j++) { + unregister_kprobe(&(inst_tab[i].kprobes[j])); + } + inst_tab[i].counter = 0; + inst_tab[i].modname[0] = '\0'; + if (inst_tab[i].kprobes) + { + kfree(inst_tab[i].kprobes); + } + return 0; +} + +static ssize_t ctl_show(struct interceptor * p, char * page, + size_t count, loff_t off) +{ + int i=0; + int n=0; + int j; + if (off) + return 0; + n += sprintf (page, "Module\tInstructions\n"); + while (inst_tab[i].modname[0]!='\0' && i < MAX_MOD) { + n += sprintf (page+n, "%s\t%d\n", inst_tab[i].modname, inst_tab[i].counter); + for(j=0;j<inst_tab[i].counter;j++){ + n += sprintf (page+n, "addr:\t%#lx\n", (unsigned long)inst_tab[i].kprobes[j].addr); + } + i++; + } + return n; +} + +static ssize_t ctl_store(struct interceptor * p, const char * page, + size_t count, loff_t off) +{ + char ctl[16]; + int num; + + if (off) + return 0; + + num = sscanf(page, "%15s", ctl); + if (!num) { + err("Invalid command format, translated no commands\n"); + return count; + } + + if (!strncmp(ctl, "add", 3)) { + down(&dbp_sem); + if (!in_used) { + up(&dbp_sem); + err("Use attach first.\n"); + return count; + } + add_ins(page); + up(&dbp_sem); + return count; + } + + if (!strncmp(ctl, "attach", 6)) { + down(&dbp_sem); + if (in_used) { + up(&dbp_sem); + err("FI_DBP is busy.(Attaching %s)\n", inst_tab[mod_index].modname); + return count; + } + if(attach_module(page)==0) + in_used++; + up(&dbp_sem); + return count; + } + + if (!strncmp(ctl, "end", 3)) { + down(&dbp_sem); + if (!in_used) { + up(&dbp_sem); + err("No attaching action to be ended.\n"); + return count; + } + in_used--; + up(&dbp_sem); + return count; + } + + if (!strncmp(ctl, "detach", 6)) { + down(&dbp_sem); + if (in_used) { + up(&dbp_sem); + err("FI_DBP is busy.(Attaching %s)\n", inst_tab[mod_index].modname); + return count; + } + detach_module(page); + up(&dbp_sem); + return count; + } + err("Unknow command %s\n", page); + return count; +} + +static struct interceptor_attribute attr_ctl = { + .attr = { .name = "ctl", .mode = 0644 }, + .show = ctl_show, + .store = ctl_store, +}; + +static struct interceptor dbp_interceptor = { + .kobj = {.name = "dbp_interceptor"}, + .arm = dbp_arm, + .disarm = dbp_disarm, + .corrupt = dbp_corrupt +}; + +static int __init dbp_start(void) +{ + int i; + + if (fi_register_interceptor(&dbp_interceptor)) { + dbg("Failed to register DBP Interceptor"); + return -EINVAL; + } + + sysfs_create_file(&dbp_interceptor.kobj, &attr_ctl.attr); + + for (i=0;i<MAX_MOD;i++) { + inst_tab[i].modname[0]='\0'; + } + + EXPORT_NO_SYMBOLS; + return 0; +} + +static void __exit dbp_stop(void) +{ + int i; + int j; + + for(i=0;i<MAX_MOD;i++) + { + for(j=0;j<inst_tab[i].counter;j++) { + unregister_kprobe(&(inst_tab[i].kprobes[j])); + } + inst_tab[i].counter = 0; + inst_tab[i].modname[0] = '\0'; + if (inst_tab[i].kprobes) + { + kfree(inst_tab[i].kprobes); + } + } + sysfs_remove_file(&dbp_interceptor.kobj, &attr_ctl.attr); + fi_unregister_interceptor(&dbp_interceptor); + return; +} + +module_init(dbp_start); +module_exit(dbp_stop); + +MODULE_AUTHOR("Stanley Wang"); +MODULE_DESCRIPTION("DBP component for FI."); +MODULE_LICENSE("GPL"); diff -Nru a/drivers/char/fi/dbp/fi_dbp.h b/drivers/char/fi/dbp/fi_dbp.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/char/fi/dbp/fi_dbp.h Tue Dec 31 17:43:41 2002 @@ -0,0 +1,88 @@ +#ifndef __FI_DBP_H +#define __FI_DBP_H + +#include <linux/fi_internal.h> +#include <linux/fi.h> +#include <asm/processor.h> + +#define MAX_WP 32 +#define MAX_MOD 16 + +/*define reason of entering do_debug*/ +#define REASON_NOTME 0 +#define REASON_READ 1 +#define REASON_WRITE 2 + +#define PREFIX_16 0x66 + +static DECLARE_MUTEX(dbp_sem); +static int in_used; +static int mod_index; +static int ins_index; +static struct interceptor dbp_interceptor; + + +struct inst_rec_header { + char modname[256]; + int counter; + struct kprobe *kprobes; +}inst_tab[MAX_MOD] = {[0 ... MAX_MOD-1] = {"",0,NULL}}; + +struct { + struct watchpoint wp; + struct trigger *trigger; + spinlock_t lock; +}wp_tb[MAX_WP] = { [0 ... MAX_WP-1] = {{0,0}, NULL, SPIN_LOCK_UNLOCKED}}; + +struct opcode { + unsigned int port; + unsigned int write; + unsigned int len; /*0:byte 1:word 2:double word*/ + unsigned int inst_len; +}; + +struct corrupt { + unsigned long *preg; + unsigned long mask; +}; + +struct { + int reason; + int wp_tab_id; + unsigned long value; + unsigned char cancel_opcode; + struct inst_rec *inst; + struct opcode op; +}which_inst[NR_CPUS] = {[0 ... NR_CPUS-1] = {-1, -1, 0, 0, NULL, {0, 0, 0, 0}}}; + + +static int dbp_arm(struct trigger *t); +void dbp_disarm(struct trigger *t); +void dbp_corrupt(__u32 dirty, void *data); +int get_IO_opcode(struct opcode *op, struct pt_regs *regs); + +int attach_module(const char *page); +int detach_module(const char *page); +void add_ins(const char *page); + + + + +inline int find_wp(unsigned long addr){ + int i=0; + + for (i=0; i<MAX_WP; i++) { + if (addr == wp_tb[i].wp.addr) { + break; + } + } + return i; +}; + +void post_probe_handler(struct kprobe *, struct pt_regs *, unsigned long); +void pre_probe_handler(struct kprobe *, struct pt_regs *); +void rmmod_exit(struct module *); + +extern struct module *fi_get_module(const char *name); +extern void fi_put_module(void); +#endif /*__FI_DBP_H*/ 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 |
From: Wang, S. <sta...@in...> - 2002-12-31 10:09:30
|
Hi, folks Here is fi_dbp infrastructure: # 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.961 -> 1.977 # arch/i386/Kconfig 1.28 -> 1.30 # kernel/module.c 1.32 -> 1.35 # The following is the BitKeeper ChangeSet Log # -------------------------------------------- # 02/12/27 st...@ma... 1.962 # Add FI_DBP infrastructure # -------------------------------------------- # 02/12/27 st...@ma... 1.963 # Split fi_find_module into fi_get_moudule and fi_put_module # -------------------------------------------- # 02/12/27 st...@ma... 1.965 # fix warning. # -------------------------------------------- diff -Nru a/arch/i386/Kconfig b/arch/i386/Kconfig --- a/arch/i386/Kconfig Tue Dec 31 17:43:41 2002 +++ b/arch/i386/Kconfig Tue Dec 31 17:43:41 2002 @@ -1567,6 +1567,22 @@ If in doubt, say N. +config FI_DBP + tristate "Fault Injection Dynamic Binary Patch (EXPERIMENTAL)" + depends on FI + help + This component adds the ability for Fault Injection to intercept + int3'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 normal PIO access. + + 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_dbp.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_IRQ tristate "Fault Injection Irq Interceptor (EXPERIMENTAL)" depends on KIRQ diff -Nru a/kernel/module.c b/kernel/module.c --- a/kernel/module.c Tue Dec 31 17:43:41 2002 +++ b/kernel/module.c Tue Dec 31 17:43:41 2002 @@ -1412,3 +1412,19 @@ /* Obsolete lvalue for broken code which asks about usage */ int module_dummy_usage = 1; EXPORT_SYMBOL(module_dummy_usage); + +#if defined(CONFIG_FI_DBP) || defined(CONFIG_FI_DBP_MODULE) +struct module *fi_get_module(const char *name) +{ + down(&module_mutex); + return find_module(name); +} +void fi_put_module(void) +{ + up(&module_mutex); +} +EXPORT_SYMBOL_GPL(fi_get_module); +EXPORT_SYMBOL_GPL(fi_put_module); +#endif 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 |
From: Zhuang, L. <lou...@in...> - 2002-12-27 07:43:18
|
You are very welcome to contribute efforts here. ;-) > Hello. > > I read your patch which added the caller of Code Segment. > I have a little comment. > > In your patch, pf_page_fault() injects a fault value > at set_ins_reg_val() or set_ins_imm_val() > after calling the Code Segment by fi_execute_trigger(). > However, fi_execute_trigger() injects another fault value itself. if there is a code segment attached with trigger, fi_execute_trigger will return immediately after call into the code segment. > > I think that fault inject code should be out of > fi_execute_trigger() and > fi_execute_trigger() should call just the Code Segment. You are right! But much time simply operations such as SET, AND etc. are enough. It is why there are some shortcuts in fi_execute_trigger. Could you show me a better way? - Louis |
From: <y-...@jp...> - 2002-12-27 07:21:35
|
Hello. I read your patch which added the caller of Code Segment. I have a little comment. In your patch, pf_page_fault() injects a fault value at set_ins_reg_val() or set_ins_imm_val() after calling the Code Segment by fi_execute_trigger(). However, fi_execute_trigger() injects another fault value itself. I think that fault inject code should be out of fi_execute_trigger() and fi_execute_trigger() should call just the Code Segment. Thanks. ---------------- Yasunori Goto |
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 |
From: Wang, S. <sta...@in...> - 2002-12-26 10:38:15
|
Hi, folks, Here is the lastest KIRQ patch, I add a dispatch function. # 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.954 -> 1.956 # arch/i386/Kconfig 1.14 -> 1.16 # arch/i386/kernel/Makefile 1.31 -> 1.32 # (new) -> 1.6 arch/i386/kernel/kirq.c # (new) -> 1.4 include/asm-i386/kirq.h # # The following is the BitKeeper ChangeSet Log # -------------------------------------------- # 02/12/26 st...@ma... 1.955 # 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.956 # Add dispatch_kirq # -------------------------------------------- # diff -Nru a/arch/i386/Kconfig b/arch/i386/Kconfig --- a/arch/i386/Kconfig Thu Dec 26 18:29:23 2002 +++ b/arch/i386/Kconfig Thu Dec 26 18:29:23 2002 @@ -1544,6 +1544,14 @@ best used in conjunction with the NMI watchdog so that spinlock deadlocks are also debuggable. +config KIRQ + bool "Kernel Irq interceptor for X86(experimental)" + depends on DEBUG_KERNEL && EXPERIMENTAL + help + This option enable an IRQ interceptor. You can get the control + before any specified ISR is executing and decide whether it + should be executing through "register_kirq/unregister_kirq". + config DEBUG_HIGHMEM bool "Highmem debugging" depends on DEBUG_KERNEL && HIGHMEM diff -Nru a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile --- a/arch/i386/kernel/Makefile Thu Dec 26 18:29:23 2002 +++ b/arch/i386/kernel/Makefile Thu Dec 26 18:29:23 2002 @@ -4,7 +4,7 @@ EXTRA_TARGETS := head.o init_task.o -export-objs := mca.o i386_ksyms.o time.o +export-objs := mca.o i386_ksyms.o time.o kirq.o obj-y := process.o semaphore.o signal.o entry.o traps.o irq.o vm86.o \ ptrace.o i8259.o ioport.o ldt.o setup.o time.o sys_i386.o \ @@ -29,6 +29,7 @@ obj-$(CONFIG_PROFILING) += profile.o obj-$(CONFIG_EDD) += edd.o obj-$(CONFIG_MODULES) += module.o +obj-$(CONFIG_KIRQ) += kirq.o obj-y += sysenter.o EXTRA_AFLAGS := -traditional diff -Nru a/arch/i386/kernel/kirq.c b/arch/i386/kernel/kirq.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/i386/kernel/kirq.c Thu Dec 26 18:29:23 2002 @@ -0,0 +1,120 @@ +/* Support for kernel irq interceptor. + (C) 2002 Stanley Wang <sta...@in...>. +*/ + +#include <linux/config.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/spinlock.h> +#include <linux/mm.h> +#include <linux/slab.h> +#include <linux/irq.h> +#include <linux/interrupt.h> +#include <asm/kirq.h> + +void kirq_handler(int irq, void *dev_id, struct pt_regs *regs) +{ + int i; + struct kirq *p = kirq_list + irq; + if (p->handler != NULL){ + i = (*(p->handler))(p, irq, dev_id, regs); + if ( i == 0 ) + (*(p->isr))(irq, dev_id, regs); + }else{ + printk(KERN_ERR "%s: Dropping unexpected interrupt #%i\n", + __FUNCTION__, irq); + } + return; +} + +int register_kirq(int irq, char *devname, kirq_handler_t handler) +{ + struct irqaction *action; + irq_desc_t *desc = irq_desc + irq; + struct kirq *p = kirq_list + irq; + unsigned long flags; + + if (handler == NULL) { + printk(KERN_ERR "%s: Missing handler!\n", __FUNCTION__); + return -EINVAL; + } + + if (p->handler) { + printk(KERN_ERR "%s: KIRQ was regitsered already!\n", __FUNCTION__); + return -EINVAL; + } + + spin_lock_irqsave(&desc->lock,flags); + + action = desc->action; + while (action) { + if (strcmp(action->name,devname)) { + action = action->next; + }else{ + break; + } + } + + if (!action) { + spin_unlock_irqrestore(&desc->lock,flags); + return -1; + } + + p->isr = action->handler; + p->handler = handler; + p->dev_id = action->dev_id; + + action->handler = kirq_handler; + + spin_unlock_irqrestore(&desc->lock,flags); + + return 0; +} + +int unregister_kirq(int irq) +{ + struct irqaction *action; + irq_desc_t *desc = irq_desc + irq; + struct kirq *p = kirq_list + irq; + unsigned long flags; + + spin_lock_irqsave(&desc->lock,flags); + + action = desc->action; + while ( action && action->dev_id != p->dev_id) { + action = action->next; + } + + if (!action) { + printk(KERN_ERR "%s: Unregister KIRQ failed!\n", __FUNCTION__); + spin_unlock_irqrestore(&desc->lock,flags); + return -1; + } + + action->handler = p->isr; + + p->isr = NULL; + p->handler = NULL; + p->dev_id = NULL; + + spin_unlock_irqrestore(&desc->lock,flags); + + return 0; +} + +void dispatch_kirq(int irq, struct pt_regs *regs) +{ + struct kirq *p = kirq_list + irq; + if (p->isr != NULL){ + (*(p->isr))(irq, p->dev_id, regs); + }else{ + printk(KERN_ERR "%s: Dropping wrong interrupt #%i\n", + __FUNCTION__, irq); + } + return; +} + +EXPORT_SYMBOL_GPL(register_kirq); +EXPORT_SYMBOL_GPL(unregister_kirq); +EXPORT_SYMBOL_GPL(dispatch_kirq); + diff -Nru a/include/asm-i386/kirq.h b/include/asm-i386/kirq.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/include/asm-i386/kirq.h Thu Dec 26 18:29:23 2002 @@ -0,0 +1,30 @@ +#ifndef _ASM_KIRQ_H +#define _ASM_KIRQ_H + +#include <linux/errno.h> + +/* Define return value for kirq handler. */ +#define KIRQ_CONTINUE 0 +#define KIRQ_SKIP 1 + +struct kirq; +typedef int (*kirq_handler_t)(struct kirq *, int, void *, struct pt_regs *); +struct kirq { + void *dev_id; + void (*isr)(int, void *, struct pt_regs *); + kirq_handler_t handler; +}; + +struct kirq kirq_list[NR_IRQS] = + { [0 ... NR_IRQS-1] = { NULL, NULL, NULL}}; + +#ifdef CONFIG_KIRQ +extern int register_kirq(int irq, char *devname, kirq_handler_t handler); +extern int unregister_kirq(int irq); +extern void dispatch_kirq(int irq, struct pt_regs* regs); +#else +int register_kirq(int irq, char *devname, kirq_handler_t handler) { return -ENOSYS; } +int unregister_kirq(int irq) { return -ENOSYS; } +void dispatch_kirq(int irq, struct pt_regs* regs) {} +#endif /*CONFIG_KIRQ*/ +#endif /*_ASM_KIRQ_H*/ 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 |
From: Wang, S. <sta...@in...> - 2002-12-25 08:32:10
|
Request for name of irq interceptor :) Any name? Thanks. 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 |
From: Zhuang, L. <lou...@in...> - 2002-12-25 00:32:38
|
Dear all, I ask for your comments again. ;-) following patch is the code segment implementation with a mock code segment sample. you can try it by following steps: 1. 'bk pull http://fault-injection.bkbits.net/linux-2.5' 2. install the kernel and modules (NOTE, you need new modutils by Rusty Russell) 3. modprobe fi_mock_cs 4. modprobe fi_mock_interceptor 5. mount -tsysfs none /sys 6. add a trigger (echo "add test MMIO 1000 c 0 0 0 0 0 0 0 1 4 0" > /sys/fault-injection/triggers/ctl ) 7. attach trigger with code_segment (echo "test" > /sys/fault-injection/code-segments/mock/trigger) 8. trigger the mock interception (echo "1" > /sys/fault-injection/triggers/test/trip) - Louis # 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.918 -> 1.922 # drivers/char/fi/pf/pf.c 1.17 -> 1.18 # arch/i386/Kconfig 1.25 -> 1.26 # drivers/char/fi/Makefile 1.6 -> 1.7 # drivers/char/fi/fi_core.c 1.19 -> 1.22 # include/linux/fi.h 1.5 -> 1.6 # drivers/char/fi/fi_mock_interceptor.c 1.2 -> 1.4 # (new) -> 1.2 drivers/char/fi/fi_mock_cs.c # # The following is the BitKeeper ChangeSet Log # -------------------------------------------- # 02/12/24 lo...@ha... 1.919 # * add code segment subsystem # * add fi_mock_code_segment # * clean some extern declarations in .c # -------------------------------------------- # 02/12/24 lo...@ha... 1.920 # add mock_code_segment file # -------------------------------------------- # 02/12/24 lo...@ha... 1.921 # drivers/char/fi/fi_core.c # * fix a bug # * add code segment support # drivers/char/fi/fi_mock_cs.c # reduce name length # -------------------------------------------- # 02/12/24 lo...@ha... 1.922 # * refactor del_trigger (using find_trigger_by_name) # * refactor fi_execute_trigger (breaking down small functions) # -------------------------------------------- # diff -Nru a/arch/i386/Kconfig b/arch/i386/Kconfig --- a/arch/i386/Kconfig Tue Dec 24 16:57:18 2002 +++ b/arch/i386/Kconfig Tue Dec 24 16:57:18 2002 @@ -1596,6 +1596,17 @@ If in doubt say N. +config FI_MOCK_CODE_SEGMENT + tristate "Fault Injection Mock Code Segment (EXPERIMENTAL)" + depends on FI + help + This is a mock or fake code segment created for the sole purpose of + exercising the fault injection core code. The omly reason a person + would want to build this component is to learn to write code segment + himself/herself. + + If in doubt say N + config DEBUG_STACKOVERFLOW bool "Check for stack overflows" depends on DEBUG_KERNEL diff -Nru a/drivers/char/fi/Makefile b/drivers/char/fi/Makefile --- a/drivers/char/fi/Makefile Tue Dec 24 16:57:18 2002 +++ b/drivers/char/fi/Makefile Tue Dec 24 16:57:18 2002 @@ -9,5 +9,5 @@ obj-$(CONFIG_FI) += fi_core.o obj-$(CONFIG_FI_TEST) += fi_test.o obj-$(CONFIG_FI_MOCK_INTERCEPTOR) += fi_mock_interceptor.o - +obj-$(CONFIG_FI_MOCK_CODE_SEGMENT) += fi_mock_cs.o export-objs := fi_core.o diff -Nru a/drivers/char/fi/fi_core.c b/drivers/char/fi/fi_core.c --- a/drivers/char/fi/fi_core.c Tue Dec 24 16:57:18 2002 +++ b/drivers/char/fi/fi_core.c Tue Dec 24 16:57:18 2002 @@ -67,6 +67,21 @@ static struct trigger_attribute trigger_attr_count; static struct trigger_attribute trigger_attr_type; +static inline struct trigger *find_trigger_by_name(const char *name) +{ + struct list_head * entry; + struct trigger * t; + + list_for_each(entry,&trigger_subsys.list) { + t = to_trigger(entry); + if (!strncmp(t->kobj.name, name, KOBJ_NAME_LEN)) { + dbg("comparing %s to %s", t->kobj.name, name); + return t; + } + } + return NULL; +} + static inline void create_trigger_files(struct trigger *t) { sysfs_create_file(&t->kobj, &trigger_attr_wp.attr); @@ -163,24 +178,51 @@ static inline ssize_t del_trigger(struct trigger *t) { - struct list_head * entry; struct trigger * n; - list_for_each(entry,&trigger_subsys.list) { - n = to_trigger(entry); - if (!strncmp(n->kobj.name, t->kobj.name, KOBJ_NAME_LEN)) { - dbg("comparing %s to %s", n->kobj.name, t->kobj.name); - unarm_trigger(n); - remove_trigger_files(n); - kobject_unregister(&n->kobj); - return 0; - } + n = find_trigger_by_name(t->kobj.name); + if (n) { + unarm_trigger(n); + remove_trigger_files(n); + kobject_unregister(&n->kobj); + return 0; } err("trigger %s does not exist", t->kobj.name); return -EINVAL; } +static struct code_segment_attribute code_segment_attr_trigger; + +static inline void create_code_segment_files(struct code_segment *cs) +{ + sysfs_create_file(&cs->kobj, &code_segment_attr_trigger.attr); +} + +static inline void remove_code_segment_files(struct code_segment *cs) +{ + sysfs_remove_file(&cs->kobj, &code_segment_attr_trigger.attr); +} + +static inline void arm_code_segment(struct code_segment *cs, struct trigger *t) +{ + kobject_get(&t->kobj); + kobject_get(&cs->kobj); + cs->tri = t; + t->cs = cs; +} + +static inline void unarm_code_segment(struct code_segment *cs) +{ + struct trigger *t; + + t = cs->tri; + t->cs = NULL; + cs->tri = NULL; + kobject_put(&cs->kobj); + kobject_put(&t->kobj); +} + /* * =========================================================== * <>-- Toplevel Containing Subsystem (fi_subsys) --<> @@ -544,6 +586,125 @@ .parent = &fi_subsys, }; +/* + * =============================================================== + * <>-- Code Segment Containing Subsystem (code_segment_subsys) --<> + * --------------------------------------------------------------- + */ +static ssize_t code_segment_attr_show(struct kobject * kobj, + struct attribute * attr, + char * page, size_t count, + loff_t off) +{ + struct code_segment * cs = container_of(kobj,struct code_segment,kobj); + struct code_segment_attribute * a = + container_of(attr,struct code_segment_attribute,attr); + + dbg("about to call show function for %s", a->attr.name); + return a->show ? a->show(cs,page,count,off) : 0; +} + +static ssize_t code_segment_attr_store(struct kobject * kobj, + struct attribute * attr, + const char * page, + size_t count, + loff_t off) +{ + struct code_segment * cs = container_of(kobj,struct code_segment,kobj); + struct code_segment_attribute * a = + container_of(attr,struct code_segment_attribute,attr); + + dbg("about to call store function for %s", a->attr.name); + return a->store ? a->store(cs,page,count,off) : 0; +}; + +static struct sysfs_ops code_segment_sysfs_ops = { + .show = code_segment_attr_show, + .store = code_segment_attr_store, +}; + +static struct subsystem code_segment_subsys = { + .kobj = { .name = "code_segments" }, + .sysfs_ops = &code_segment_sysfs_ops, + .parent = &fi_subsys, +}; + +static ssize_t code_segment_trigger_show(struct code_segment *cs, + char * page, size_t count, + loff_t off) +{ + if (off) return 0; + if (cs->tri) return snprintf(page,count,"%s\n",cs->tri->kobj.name); + return snprintf(page,count,"%s\n","(not attached yet)"); +} + +static ssize_t code_segment_trigger_store(struct code_segment *cs, + const char * page, size_t count, + loff_t off) +{ + struct trigger *t; + char tri_name[KOBJ_NAME_LEN]; + sscanf(page, "%s", tri_name); + dbg("Try to find %s trigger", tri_name); + t = find_trigger_by_name(tri_name); + if(t) { + arm_code_segment(cs, t); + } else { + unarm_code_segment(cs); + } + return count; +} + +static struct code_segment_attribute code_segment_attr_trigger = { + .attr = { .name = "trigger", .mode = 0644 }, + .show = code_segment_trigger_show, + .store= code_segment_trigger_store +}; + +/* + * =============================================================== + * <>-- Others ;) --<> + * --------------------------------------------------------------- + */ + +static inline int is_in_random(int hertz) +{ + int tmp; + if (hertz==0 || hertz==1) return 1; + get_random_bytes(&tmp, sizeof(tmp)); + return (tmp < 0xFFFFFFFF/hertz); +} + +static inline int is_in_range(int data, int min, int max, int bitmask) +{ + int tmp; + if (min==0 && max==0) return 1; + tmp = data & (~bitmask); + if ( min<=tmp && tmp<max) return 1; + return 0; +} + +static inline int is_ready(struct trigger *t, unsigned int val) +{ + if ( is_in_random(t->hertz) + && is_in_range(val, t->min, t->max, t->bitmask)) { + return 1; + } + return 0; +} + +static inline int is_in_count(int count, int skip, int stop) +{ + if (skip >= count) return 0; + if (stop!=0 && (stop+skip) <count) return 0; + return 1; +} + +static inline int protect_bits(int new, int orig, int bitmask) +{ + return (new&(~bitmask)) | (orig&bitmask); +} + void fi_execute_trigger(struct trigger *t, struct interceptor *i, __u32 val, int len, int type, void *data) { @@ -551,38 +712,25 @@ if (!t) { err("Unable to execute null trigger"); - goto exit; + return; } - get_random_bytes(&tmp, sizeof(tmp)); - if (t->hertz==0) {t->hertz=1;};//divid is not 0! - if (tmp >= 0xFFFFFFFF/t->hertz){ - dbg("rnd=%d, HERZ=%d", tmp, t->hertz); - goto exit; - } - - tmp = val & (~t->bitmask); - if (t->min>tmp || tmp>=t->max){ - dbg("min=%d, max=%d, val=%d", t->min, t->max, val); - if(!(t->min==0 && t->max==0)) - goto exit; - } + if(!is_ready(t,val)) return; /* increase count only when all conditions have passed */ atomic_inc(&t->count); - if (t->skip >= atomic_read(&t->count)){ - dbg("count=%d, skip=%d", atomic_read(&t->count), t->skip); - goto exit; - } - - if ( t->stop!=0 && (t->stop < (atomic_read(&t->count)-t->skip)) ) { - dbg("count=%d, stop=%d", atomic_read(&t->count), t->stop); - goto exit; - } + if(!is_in_count(atomic_read(&t->count), t->skip, t->stop)) return; dbg("count=%d, skip=%d, min=%d, max=%d, val=%d", atomic_read(&t->count), t->skip, t->min, t->max, val); + + if (t->cs) { + t->cs->execute_trigger(t, i, val, len, type, data); + return; + } + + //legacy trigger logic code tmp = val; switch (t->opcode){ case TRIGGER_OPCODE_NOTHING: @@ -620,9 +768,8 @@ } exit_for: - val = (val & (t->protection)) | (tmp & (~t->protection)); + val = protect_bits(tmp, val, t->protection); - exit: i->corrupt(val, data); return; } @@ -648,6 +795,27 @@ kobject_unregister(&i->kobj); } +int fi_register_code_segment(struct code_segment *cs) +{ + if (!is_initialized) + fi_init(); + + dbg("registering code segment %s", cs->kobj.name); + cs->kobj.subsys = &code_segment_subsys; + if (kobject_register(&cs->kobj)) { + err("Unable to register kobject"); + return -EINVAL; + } + create_code_segment_files(cs); + return 0; +} + +void fi_unregister_code_segment(struct code_segment *cs) +{ + remove_code_segment_files(cs); + kobject_unregister(&cs->kobj); +} + static int __init fi_init(void) { down(&fi_sem); @@ -659,6 +827,7 @@ dbg("initializing fault injection core"); subsystem_register(&fi_subsys); subsys_create_file(&fi_subsys,&fi_subsys_attr_debug); + subsystem_register(&code_segment_subsys); subsystem_register(&interceptor_subsys); subsystem_register(&trigger_subsys); subsys_create_file(&trigger_subsys,&trigger_subsys_attr_ctl); @@ -674,6 +843,7 @@ subsys_remove_file(&trigger_subsys,&trigger_subsys_attr_ctl); subsystem_unregister(&trigger_subsys); subsystem_unregister(&interceptor_subsys); + subsystem_register(&code_segment_subsys); subsys_remove_file(&fi_subsys,&fi_subsys_attr_debug); subsystem_unregister(&fi_subsys); } @@ -684,6 +854,8 @@ EXPORT_SYMBOL_GPL(fi_register_interceptor); EXPORT_SYMBOL_GPL(fi_unregister_interceptor); +EXPORT_SYMBOL_GPL(fi_register_code_segment); +EXPORT_SYMBOL_GPL(fi_unregister_code_segment); EXPORT_SYMBOL_GPL(fi_execute_trigger); EXPORT_SYMBOL_GPL(fi_debug); diff -Nru a/drivers/char/fi/fi_mock_cs.c b/drivers/char/fi/fi_mock_cs.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/char/fi/fi_mock_cs.c Tue Dec 24 16:57:18 2002 @@ -0,0 +1,42 @@ +/* Copyright (C) 2002 Louis Zhuang <lou...@in...> */ +#include <linux/module.h> +#include <linux/init.h> +#include <linux/slab.h> +#include <linux/kobject.h> +#include <linux/fi.h> +#include <linux/fi_internal.h> + +#define DRIVER_AUTHOR "Louis Zhuang <lou...@in...>" +#define DRIVER_DESC "Fault Injection Mock Code Segment" + +void mock_execute(struct trigger *t, struct interceptor *i, + __u32 val, int len, int type, void *data) +{ + info("tri=%s, intcpt=%s, val=%i, len=%i, type=%i, data=%p", + t->kobj.name, i->kobj.name, val, len, type, + data); +} + +static struct code_segment mock_code_segment = { + .execute_trigger = mock_execute, + .kobj = {.name="mock"} +}; + +static int __init mock_init(void) +{ + if (fi_register_code_segment(&mock_code_segment)) { + err("Failed to register Mock Code Segment\n"); + return -EINVAL; + } + return 0; +} + +static void __exit mock_exit(void) +{ + fi_unregister_code_segment(&mock_code_segment); +} +module_init(mock_init); +module_exit(mock_exit); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); diff -Nru a/drivers/char/fi/fi_mock_interceptor.c b/drivers/char/fi/fi_mock_interceptor.c --- a/drivers/char/fi/fi_mock_interceptor.c Tue Dec 24 16:57:18 2002 +++ b/drivers/char/fi/fi_mock_interceptor.c Tue Dec 24 16:57:18 2002 @@ -44,10 +44,6 @@ #define trace(format, arg...) \ printk(KERN_INFO "%s(" format ")\n", __FUNCTION__ , ## arg) -extern int fi_register_interceptor(struct interceptor *); -extern int fi_unregister_interceptor(struct interceptor *); -extern void fi_execute_trigger(struct trigger*,struct interceptor*, - __u32,int,int,void*); static struct interceptor mock_interceptor; @@ -120,7 +116,7 @@ mock_interceptor.type = mock_type; kobject_init(&mock_interceptor.kobj); - if (!fi_register_interceptor(&mock_interceptor)) { + if (fi_register_interceptor(&mock_interceptor)) { dbg("Failed to register Mock Interceptor"); /* FIXME!! For some reason kobject_register */ diff -Nru a/drivers/char/fi/pf/pf.c b/drivers/char/fi/pf/pf.c --- a/drivers/char/fi/pf/pf.c Tue Dec 24 16:57:18 2002 +++ b/drivers/char/fi/pf/pf.c Tue Dec 24 16:57:18 2002 @@ -269,8 +269,6 @@ .corrupt = &corrupt }; -extern int fi_register_interceptor(struct interceptor *); -extern int fi_unregister_interceptor(struct interceptor *); static int __init pf_init(void) { return fi_register_interceptor(&pf_interceptor); diff -Nru a/include/linux/fi.h b/include/linux/fi.h --- a/include/linux/fi.h Tue Dec 24 16:57:18 2002 +++ b/include/linux/fi.h Tue Dec 24 16:57:18 2002 @@ -60,6 +60,19 @@ INTERCEPTOR_TYPE_PIO=2, } interceptor_type_t; +struct trigger; +struct interceptor; +struct code_segment { + void (*execute_trigger) (struct trigger *t, + struct interceptor *i, + __u32 val, + int len, + int type, + void *data); + struct trigger *tri; + struct kobject kobj; +}; + struct trigger { struct watchpoint wp; __u32 bitmask; @@ -71,6 +84,7 @@ int hertz; int registered; trigger_opcode_t opcode; + struct code_segment *cs; int operand; atomic_t count; interceptor_type_t type; @@ -88,10 +102,10 @@ struct kobject kobj; }; -struct interceptor_attribute { +struct code_segment_attribute { struct attribute attr; - ssize_t (*show) (struct interceptor *,char *,size_t,loff_t); - ssize_t (*store)(struct interceptor *,const char *,size_t, loff_t); + ssize_t (*show) (struct code_segment *,char *,size_t,loff_t); + ssize_t (*store) (struct code_segment *,const char *,size_t,loff_t); }; struct trigger_attribute { @@ -99,6 +113,20 @@ ssize_t (*show) (struct trigger *,char *,size_t,loff_t); ssize_t (*store)(struct trigger *,const char *,size_t,loff_t); }; + +struct interceptor_attribute { + struct attribute attr; + ssize_t (*show) (struct interceptor *,char *,size_t,loff_t); + ssize_t (*store)(struct interceptor *,const char *,size_t, loff_t); +}; + + +extern int fi_register_interceptor(struct interceptor *); +extern void fi_unregister_interceptor(struct interceptor *i); +extern int fi_register_code_segment(struct code_segment *); +extern void fi_unregister_code_segment(struct code_segment *); +extern void fi_execute_trigger(struct trigger *t, struct interceptor *i, + __u32 val, int len, int type, void *data); #endif /* __KERNEL__ */ #endif /* _FAULT_INJECTION_H */ |
From: Zhuang, L. <lou...@in...> - 2002-12-23 01:31:42
|
> File & VM system latencies in microseconds - smaller is better > -------------------------------------------------------------- > Host OS 0K File 10K File Mmap Prot Page > Create Delete Create Delete Latency Fault Fault > --------- ------------- ------ ------ ------ ------ ------- ----- ----- > 52-pure Linux 2.5.52 92.5 46.0 225.6 75.3 2053.0 0.885 2.00000 > cs@1901 Linux 2.5.52 93.4 46.5 229.2 77.1 2063.0 0.765 2.00000 > cs@1907 Linux 2.5.52 91.8 44.9 221.6 75.1 2010.0 0.852 2.00000 hmm, does this result mean the difference is submersed in white noise? Maybe we should do benchmarks many times to reduce statistics difference. |
From: Zhuang, L. <lou...@in...> - 2002-12-23 01:28:55
|
> File & VM system latencies in microseconds - smaller is better > -------------------------------------------------------------- > Host OS 0K File 10K File Mmap Prot Page > Create Delete Create Delete Latency Fault Fault > --------- ------------- ------ ------ ------ ------ ------- ----- ----- > 52-pure Linux 2.5.52 92.5 46.0 225.6 75.3 2053.0 0.885 2.00000 > cs@1901 Linux 2.5.52 93.4 46.5 229.2 77.1 2063.0 0.765 2.00000 > cs@1907 Linux 2.5.52 91.8 44.9 221.6 75.1 2010.0 0.852 2.00000 hmm, does this result mean the difference is submersed in white noise? Maybe we should dobenchmatks many times to reduce statistics difference. |