2 * fault-model.c -- fault injection code for drivers
4 * Copyright (C) 2003 Mike Swift
5 * Copyright (c) 1999 Wee Teck Ng
7 * The source code in this file can be freely used, adapted,
8 * and redistributed in source or binary form, so long as an
9 * acknowledgment appears in derived source files. No warranty
10 * is attached; * we cannot take responsibility for errors or
17 * Fault injector for testing the usefulness of NOOKS
19 * Adapted from the SWIFI tools used by Wee Teck Ng to evaluate the RIO
20 * file cache at the University of Michigan
25 * This tool can inject faults into modules, whether they are loaded into a
26 * nook or loaded into the kernel (for comparison testing).
28 * There are several classes of faults emulated:
29 * - Corruption of text
31 * - simulated programming faults
32 * - skip initialization (immediate write to EBP-x)
33 * - remove instruction (replace with NOP)
34 * - incorrect source/destination (corrupted)
35 * - remove jmp or rep instruction
36 * - change address computation for memory access (not stack)
37 * - change termination condition for loop (change repeat to repeat
38 * -while equal, change condition to !condition
39 - remove instructions loading registers from arguments (ebp+x)
41 * - Corruption of stack
42 * - Corruption of heap
48 #include <linux/kernel.h>
49 #include <linux/kallsyms.h>
50 #include <linux/module.h>
52 #include <linux/slab.h>
53 #include <linux/vmalloc.h>
54 #include <linux/smp_lock.h>
55 #include <asm/uaccess.h>
56 #include <asm/delay.h>
66 #define CRASH_INTERVAL 8192
68 #define P50 0x3fffffff /* 50% of max rand */
69 #define P94 0x7851eb84 /* 94% of max rand */
72 unsigned long randomSeed
=0; /* random number */
73 unsigned long injectFault
=1; /* inject fault ? */
74 unsigned long diskTest
=0; /* run disk test instead of rio */
75 unsigned long faultInjected
=0; /* has fault been injected? */
76 unsigned long crashInterval
=0; /* interval between injecting fault */
77 unsigned long crashCount
=0; /* number of times fault is injected */
78 unsigned long faultType
;
79 unsigned long numFaults
;
80 char *crashAddr
=0; /* track current malloc */
82 int text_fault(char *mod_name
, pswifi_result_t res
);
83 int stack_fault(pswifi_result_t res
);
84 int heap_fault(pswifi_result_t res
);
85 int direct_fault(int fault_address
, int fault_content
, pswifi_result_t res
);
86 int direct_fault1(int fault_address
, int fault_content
, pswifi_result_t res
);
92 #define PDEBUG(fmt, args...) \
94 printk( KERN_ALERT "SWIFI: " fmt, ## args); \
98 #define PDEBUG(args) /* (printf args) */
107 get_mod_name(const char *user_name
, char **buf
)
112 page
= __get_free_page(GFP_KERNEL
);
116 retval
= strncpy_from_user((char *)page
, user_name
, PAGE_SIZE
);
118 if (retval
< PAGE_SIZE
) {
122 retval
= -ENAMETOOLONG
;
131 put_mod_name(char *buf
)
133 free_page((unsigned long)buf
);
138 sys_inject_fault(char * module_name
,
139 unsigned long argFaultType
,
140 unsigned long argRandomSeed
,
141 unsigned long argNumFaults
,
142 pswifi_result_t result_record
,
143 unsigned long argInjectFault
)
146 unsigned long fault_address
= 0;
147 unsigned long fault_data
= 0 ;
148 char * kern_name
= NULL
;
150 struct module
* mod
= NULL
;
153 pswifi_result_t res
= NULL
;
155 if (argNumFaults
> SWIFI_MAX_FAULTS
) {
159 res
= (pswifi_result_t
) malloc((1+argNumFaults
) * sizeof(swifi_result_t
));
164 memset(res
, 0, (1 + argNumFaults
) * sizeof(swifi_result_t
));
167 // Capture the name of the module from usermode
171 result
= get_mod_name(module_name
, &kern_name
);
177 kern_name
= module_name
;
185 for (mod
= module_list
; mod
; mod
= mod
->next
) {
186 if (strcmp(kern_name
, mod
->name
) == 0) {
198 numFaults
= argNumFaults
;
199 faultType
= argFaultType
;
200 randomSeed
= argRandomSeed
;
201 injectFault
= argInjectFault
;
204 if(faultType
>=DISK_TEST
) {
205 faultType
=faultType
-DISK_TEST
;
208 if(faultType
==STATS
) {
210 extern long time_vmp
, n_vmp
;
211 extern long time_pmp
, n_pmp
;
213 PDEBUG("# vm_map_protect=%ld, total cycle=%ld\n", n_vmp
, time_vmp
);
214 PDEBUG("# pmap_protect=%ld, total cycle=%ld\n", n_pmp
, time_pmp
);
218 } else if (faultType
== DIRECT_FAULT
) {
219 fault_address
= numFaults
;
220 fault_data
= randomSeed
;
221 PDEBUG(("sys inject fault, type %ld, addr=%lx, flip bit%lx\n",
222 faultType
, fault_address
, fault_data
));
223 } else if (faultType
== DIRECT_FAULT1
) {
224 fault_address
= numFaults
;
225 fault_data
= randomSeed
;
226 PDEBUG(("sys inject fault, type %ld, addr=%lx, zero bytes %lx\n",
227 faultType
, fault_address
, fault_data
));
229 PDEBUG(("sys inject fault, type %ld, seed=%ld, fault=%ld\n",
230 faultType
, randomSeed
, numFaults
));
235 /* set warm reboot, leave RAM unchanged
236 * 0 : don't inject fault
237 * 1 : run POST, wipe out memory
238 * 2 : don't test memory
239 * 3 : don't change memory (doesn't work)
240 * 4 : don't sync registry
243 /* default number of faults is 5 */
244 if(numFaults
<=0 || numFaults
>100) numFaults
=5;
249 result
= text_fault(module_name
, res
);
252 result
= stack_fault(res
);
255 result
= heap_fault(res
);
264 case INTERFACE_FAULT
:
266 result
= text_fault(module_name
, res
);
272 crashInterval
=CRASH_INTERVAL
; /* interval between crash */
276 crashInterval
=CRASH_INTERVAL
; /* interval between crash */
279 panic("testing panic");
282 /* case WP_FAULT: page_reg_fault(random()); break; */
285 direct_fault(fault_address
, fault_data
, res
);
290 result
= direct_fault1(fault_address
, fault_data
, res
);
294 /* case PAGE_REG_DUMP: rio_dump(); break; */
302 /* case CPU_RESET_FAULT: cpu_reset(); break; */;
305 /* test writing to kernel text. freebsd currently do a COW on a
306 * write to kernel text.
308 unsigned long *addr1
, *addr2
;
310 addr1
= (unsigned long *) 0xf0212000;
311 addr2
= (unsigned long *) 0xf0212010;
312 PDEBUG(("%p=%lx, %p=%lx\n", addr1
, *addr1
, addr2
, *addr2
));
314 __asm__ ("movl $0xf0212000, %eax\n\t" \
315 "movl $6, 0(%eax)\n\t" \
316 "movl $6, 4(%eax)\n\t");
318 /* Not implemented on MINIX */
320 addr1
= (unsigned long *) 0xf0212000;
321 addr2
= (unsigned long *) 0xf0212010;
322 PDEBUG(("after injecting fault\n"));
323 PDEBUG(("%p=%lx, %p=%lx\n", addr1
, *addr1
, addr2
, *addr2
));
329 PDEBUG(("Debugger fault"));
331 __asm__ ("movl %cr4, %ecx\n\t" \
332 "movl $42, %ecx; .byte 0x0f, 0x32\n\t" \
333 "movl $377, %ecx; .byte 0x0f, 0x32\n\t");
335 /* Not implemented on MINIX */
339 default: PDEBUG(("unknown fault type %ld\n", faultType
)); break;
341 if (copy_to_user(result_record
, res
, argNumFaults
* sizeof(swifi_result_t
))) {
346 if (kern_name
!= NULL
) {
347 put_mod_name(kern_name
);
361 PDEBUG(("entering into while 1 loop\n"));
364 PDEBUG(("delay %4d secs, cpl=0x%x, ipend=0x%x\n", i
+=5, 20, 30));
372 int direct_fault(int fault_address
, int fault_content
, pswifi_result_t res
)
378 addr
= (unsigned long *) (PAGE_OFFSET
+ fault_address
);
380 PDEBUG(("%p:0x%lx => ", addr
, *addr
));
382 flip_bit
= 1 << fault_content
;
384 res
[0].address
= (unsigned long) addr
;
386 res
[0].new = (*addr
) ^ flip_bit
;
389 *addr
= (*addr
) ^ flip_bit
;
391 PDEBUG(("%lx\n", *addr
));
395 int direct_fault1(int fault_address
, int fault_content
, pswifi_result_t res
)
397 unsigned long *addr
, data
;
400 addr
= (unsigned long *) (PAGE_OFFSET
+ fault_address
);
402 PDEBUG(("%p:%lx => ", addr
, *addr
));
406 if(fault_content
==1) {
407 data
= data
& 0xffffff00;
408 data
= data
| 0x00000090;
409 } else if(fault_content
==2) {
410 data
= data
& 0xffff0000;
411 data
= data
| 0x00009090;
412 } else if(fault_content
==3) {
413 data
= data
& 0xff000000;
414 data
= data
| 0x00909090;
415 } else if(fault_content
==4) {
418 res
[0].address
= (unsigned long) addr
;
425 PDEBUG(("%lx\n", *addr
));
435 #include <linux/sched.h>
438 #define MAX_NUM_TASKS 20
443 struct task_struct
* task
= NULL
, *result
= NULL
;
445 i
= 1 + (random() % MAX_NUM_TASKS
);
451 read_lock(&tasklist_lock
);
453 for_each_task(task
) {
460 read_unlock(&tasklist_lock
);
462 } while ((i
> 0) && (i
!= j
));
468 stack_fault(pswifi_result_t res
)
470 unsigned long *addr
, size
, taddr
;
473 struct task_struct
*task
= NULL
;
475 while(count
< numFaults
) {
481 size
= (unsigned long) task
+ TASK_SIZE
- task
->thread
.esp
;
483 PDEBUG(("stack range=%lx-%lx\n",
484 (unsigned long) task
->thread
.esp
,
485 (unsigned long) task
+ TASK_SIZE
));
487 addr
= (unsigned long *) ((long) task
->thread
.esp
+
488 (random()&~0x3)%size
);
489 taddr
=(unsigned long) addr
;
490 flip_bit
= random() & 0x1f;
491 PDEBUG(("%lx:%lx flip bit %d => ", taddr
, *addr
, flip_bit
));
492 flip_bit
= 1 << flip_bit
;
493 res
[count
].address
= taddr
;
494 res
[count
].old
= *addr
;
495 res
[count
].new = (*addr
) ^ flip_bit
;
497 *addr
= ((*addr
)^flip_bit
);
499 PDEBUG(("%lx\n", *addr
));
508 // Instead of dealing with heaps directly, we look at the area cache of pages
509 // and vm pages and find an address there.
513 int heap_fault(pswifi_result_t res
)
516 unsigned long *addr
, taddr
;
520 struct list_head
*next
;
522 addr
= (unsigned long *) (map
->address
+ (random()&~0xf)%map
->size
);
524 taddr
=(unsigned long) addr
;
525 flip_bit
= random() & 0x1f;
526 PDEBUG("heap range=%lx-%lx ", map
->address
, map
->address
+ map
->size
);
527 PDEBUG("%lx:%lx flip bit %d => ", taddr
, *addr
, flip_bit
);
528 flip_bit
= 1 << flip_bit
;
529 res
[count
].address
= taddr
;
530 res
[count
].old
= *addr
;
531 res
[count
].new = (*addr
) ^ flip_bit
;
534 *addr
= ((*addr
)^flip_bit
);
536 PDEBUG("%lx\n", *addr
);
538 } while (count
< numFaults
);
546 do_fault_copy_from_user (void *kaddr
, const void *udaddr
, unsigned long len
,
547 unsigned long (* copy_fn
) (void *, const void *, unsigned long))
549 unsigned int prob
, i
=0;
551 if ( faultInjected
&& (faultType
==BCOPY_FAULT
) ) {
553 if (++crashCount
== crashInterval
) {
557 crashInterval
= CRASH_INTERVAL
+ (random() & FI_MASK
);
559 if (prob
< P50
) { /* corrupt 1 QW */
561 } else if (prob
< P94
) { /* corrupt 2 - 1024 QW */
564 i
= random() & 0x3fe;
566 } else { /* corrupt 2-4 pages */
569 i
= random() & 0xc00;
572 PDEBUG(("copyin: %p to %p, len=%ld overrun=%d, Intvl=%ld, inj=%ld\n",
573 udaddr
, kaddr
, len
, i
, crashInterval
, faultInjected
));
574 if (faultInjected
++ <numFaults
) {
581 return(copy_fn(kaddr
, udaddr
, len
));
583 return(copy_fn(kaddr
, udaddr
, len
));
588 do_fault_copy_to_user(void *udaddr
, const void *kaddr
, unsigned long len
,
589 unsigned long (* copy_fn
) (void *,
593 unsigned int prob
, i
=0;
595 if( faultInjected
&& (faultType
==BCOPY_FAULT
) ){
597 if (crashCount
== crashInterval
) {
600 crashInterval
= CRASH_INTERVAL
+ (random() & FI_MASK
);
602 if ( prob
< P50
) { /* corrupt 1 QW */
604 } else if(prob
< P94
) { /* corrupt 2 - 1024 QW */
607 i
= random() & 0x3fe;
612 i
= random() & 0xc00;
615 PDEBUG(("copyout: %p to %p, len=%ld overrun=%d, Intvl=%ld, inj=%ld\n",
616 kaddr
, udaddr
, len
, i
, crashInterval
, faultInjected
));
617 if (faultInjected
++ <numFaults
) {
624 return(copy_fn(udaddr
, kaddr
, len
));
626 return(copy_fn(udaddr
, kaddr
, len
));
631 swifi___generic_copy_from_user (void *kaddr
, void *udaddr
, unsigned long len
)
633 return(do_fault_copy_from_user(kaddr
,
636 __generic_copy_from_user
));
640 swifi___generic_copy_to_user(void *udaddr
, void *kaddr
, unsigned long len
)
642 return(do_fault_copy_to_user(udaddr
,
645 __generic_copy_to_user
));
651 swifi_memcpy_fn (void *to
, void *from
, size_t len
)
653 unsigned int prob
, i
=0;
655 if( faultInjected
&& (faultType
==BCOPY_FAULT
) ) {
657 if (crashCount
== crashInterval
) {
660 crashInterval
= CRASH_INTERVAL
+ (random() & FI_MASK
);
662 if (prob
< P50
) { /* corrupt 1 QW */
664 } else if (prob
< P94
) { /* corrupt 2 - 1024 QW */
667 i
= random() & 0x3fe;
669 } else { /* corrupt 2-4 pages */
672 i
= random() & 0xc00;
676 PDEBUG(("memcpy: %p to %p, len=%d overrun=%d, Intvl=%ld, inj=%ld\n",
677 from
, to
, len
, i
, crashInterval
, faultInjected
));
678 if(faultInjected
++ <numFaults
) len
+=i
;
679 else faultInjected
=0;
682 return(memcpy(to
, from
, len
));
684 return(memcpy(to
, from
, len
));
689 swifi_memmove_fn (void *to
, void *from
, size_t len
)
691 unsigned int prob
, i
=0;
693 if( faultInjected
&& (faultType
==BCOPY_FAULT
) ) {
695 if (crashCount
== crashInterval
) {
698 crashInterval
= CRASH_INTERVAL
+ (random() & FI_MASK
);
700 if (prob
< P50
) { /* corrupt 1 QW */
702 } else if (prob
< P94
) { /* corrupt 2 - 1024 QW */
705 i
= random() & 0x3fe;
707 } else { /* corrupt 2-4 pages */
710 i
= random() & 0xc00;
714 PDEBUG(("memmove: %p to %p, len=%d overrun=%d, Intvl=%ld, inj=%ld\n",
715 from
, to
, len
, i
, crashInterval
, faultInjected
));
716 if(faultInjected
++ <numFaults
) len
+=i
;
717 else faultInjected
=0;
720 return(memmove(to
, from
, len
));
722 return(memmove(to
, from
, len
));
727 memmove_fn(void *to
, void *from
, size_t len
)
729 return(memmove(to
, from
, len
));
735 memcpy_fn(void *to
, void *from
, size_t len
)
737 return(memcpy(to
, from
, len
));
744 do_fault_kfree(void *addr
, void (* kfree_fn
)(const void *))
746 if(addr
== crashAddr
) {
749 if (faultInjected
&& (faultType
==FREE_FAULT
||
750 faultType
==MEM_LEAK_FAULT
)) {
752 if(crashCount
>=crashInterval
) {
754 /* alternate between premature freeing and non-free */
757 PDEBUG(("malloc : freeing %p prematurely\n",
764 crashInterval
= CRASH_INTERVAL
+ (random()&FI_MASK
);
765 if (faultInjected
++ > numFaults
) {
770 PDEBUG(("free: don't free %p\n", addr
));
771 if(faultInjected
++ > numFaults
) {
774 if(faultType
==FREE_FAULT
) {
778 crashInterval
= CRASH_INTERVAL
+ (random()&FI_MASK
);
788 swifi_kfree(const void *addr
)
790 do_fault_kfree((void *) addr
, kfree
);
795 void do_vfree(const void * addr
)
797 vfree((void *) addr
);
802 swifi_vfree(void *addr
)
804 do_fault_kfree(addr
, do_vfree
);
811 do_fault_kmalloc(size_t size
,
813 void * (* kmalloc_fn
)(size_t size
, int flags
))
815 if (faultInjected
&& (faultType
==ALLOC_FAULT
)) {
817 if(crashCount
>=crashInterval
) {
818 PDEBUG(("kmalloc : returning null\n"));
820 crashInterval
= CRASH_INTERVAL
+ (random()&FI_MASK
);
821 if (faultInjected
++ > numFaults
) {
829 return(kmalloc_fn(size
, flags
));
835 swifi_kmalloc(size_t size
, int flags
)
837 return(do_fault_kmalloc(size
, flags
, kmalloc
));
843 void * do_fault_vmalloc(unsigned long size
,
846 void * (*vmalloc_fn
)(unsigned long size
,
850 if (faultInjected
&& (faultType
==ALLOC_FAULT
)) {
852 if(crashCount
>=crashInterval
) {
853 PDEBUG(("vmalloc : returning null\n"));
855 crashInterval
= CRASH_INTERVAL
+ (random()&FI_MASK
);
856 if (faultInjected
++ > numFaults
) {
863 return(vmalloc_fn(size
, gfp_mask
, prot
));
867 swifi___vmalloc(unsigned long size
, int gfp_mask
, pgprot_t prot
)
869 return(do_fault_vmalloc(size
, gfp_mask
, prot
, __vmalloc
));
875 typedef struct section_callback
{
876 const char * module_name
;
877 const char * section_name
;
878 unsigned long sec_start
;
879 unsigned long sec_end
;
880 } section_callback_t
;
883 text_section_callback(void *token
,
890 section_callback_t
* info
= (section_callback_t
*) token
;
892 if ((strcmp(modname
, info
->module_name
) == 0) &&
893 (strcmp(secname
, info
->section_name
) == 0)) {
894 info
->sec_start
= secstart
;
895 info
->sec_end
= secend
;
903 int text_fault(char *mod_name
, pswifi_result_t res
)
905 unsigned long *addr
, text_size
, offset
, page
, taddr
;
906 unsigned long btext
, etext
;
908 int count
, flip_bit
=0, len
, rc
;
911 struct module
* module
;
912 section_callback_t info
;
915 #define MAX_NUM_MODULES 10
917 /* inject faults into text space */
919 for(count
=0; count
<numFaults
; count
++) {
920 int i
= 1 + (random() % MAX_NUM_MODULES
);
927 info
.module_name
= module
->name
;
928 info
.module_name
= "<module-name>";
929 info
.section_name
= ".text";
931 kallsyms_sections(&info
, text_section_callback
);
932 if (info
.sec_start
== 0 ) {
937 load_nlist(mod_name
, &btext
, &etext
);
940 btext
= info
.sec_start
;
941 etext
= info
.sec_end
;
943 text_size
= etext
- btext
;
945 PDEBUG(("text=%lx-%lx, size=%lx\n", btext
, etext
, text_size
));
947 addr
= (unsigned long *)
948 (btext
+ ((unsigned long) (random()&~0xf) % text_size
));
950 /* now the tricky part */
952 taddr
=(unsigned long) addr
;
953 if( faultType
==INIT_FAULT
||
954 faultType
==NOP_FAULT
||
955 faultType
==DST_FAULT
||
956 faultType
==SRC_FAULT
||
957 faultType
==BRANCH_FAULT
||
958 faultType
==PTR_FAULT
||
959 faultType
==LOOP_FAULT
||
960 faultType
==INTERFACE_FAULT
||
961 faultType
==IRQ_FAULT
) {
962 addr
= (unsigned long *) find_faulty_instr(taddr
, faultType
, &len
);
963 /* do it over again if we can't find the right instruction */
970 printf("len = %d\n", len
);
972 PDEBUG(("target addr=%lx, instr addr=%p, %lx=>", taddr
, addr
,
973 text_read_ul(addr
)));
975 offset
= (unsigned long) addr
&PAGE_MASK
;
976 page
= (unsigned long) addr
&~PAGE_MASK
;
978 /* it doesn't matter what we used here to unprotect page,
979 * as this routine will not be in production code.
982 res
[count
].address
= taddr
;
983 res
[count
].old
= text_read_ul(addr
);
984 res
[count
].new = text_read_ul(addr
);
986 if (faultType
==TEXT_FAULT
) {
988 flip_bit
= random() & 0x1f;
989 PDEBUG(("flip bit %d => ", flip_bit
));
990 flip_bit
= 1 << flip_bit
;
992 res
[count
].new = text_read_ul(addr
) ^ flip_bit
;
995 text_write_ul(addr
, text_read_ul(addr
)^flip_bit
);
998 } else if (faultType
==NOP_FAULT
||
999 faultType
==INIT_FAULT
||
1000 faultType
==BRANCH_FAULT
||
1001 faultType
==INTERFACE_FAULT
||
1002 faultType
==IRQ_FAULT
) {
1003 c
= (unsigned char *) addr
;
1005 for (j
= 0; j
< len
; j
++) {
1006 /* replace these bytes with NOP (*c=NOP) */
1007 if (j
< sizeof(unsigned long)) {
1008 ((unsigned char *) &res
[count
].new)[j
] = NOP
;
1011 text_write_ub(c
, NOP
);
1016 } else if (faultType
==DST_FAULT
|| faultType
==SRC_FAULT
) {
1017 /* skip thru the prefix and opcode, and flip bits in following bytes */
1019 c
=(unsigned char *) addr
;
1021 switch (text_read_ub(c
)) {
1022 case 0x66: case 0x67: case 0x26: case 0x36:
1023 case 0x2e: case 0x3e: case 0x64: case 0x65:
1024 case 0xf0: case 0xf2: case 0xf3:
1035 if(text_read_ub(c
)>=0xd8 && text_read_ub(c
)<=0xdf) {
1036 /* don't mess with fp instruction, yet.
1037 * but there shouldn't be any fp instr in kernel.
1039 PDEBUG(("floating point instruction, bailing out\n"));
1042 } else if(text_read_ub(c
)==0x0f) {
1045 if(text_read_ub(c
)==0x0f) {
1049 len
= len
-((long) c
- (long) addr
);
1052 printf("tex_fault: len = %d\n", len
);
1061 "text_fault: bad length at address %p, c = %p, fault type %ld\n",
1062 addr
, c
, faultType
);
1064 for (i
= 0; i
<16; i
++)
1065 printf(" 0x%02x", text_read_ub((char *)addr
+i
));
1070 flip_bit
= random() % (len
*8);
1071 PDEBUG(("flip bit %d (len=%d) => ", flip_bit
, len
));
1072 for(j
=0; j
<len
; j
++) {
1073 /* go to the right byte */
1075 flip_bit
= 1 << flip_bit
;
1077 if (j
< sizeof(unsigned long)) {
1078 ((unsigned char *) &res
[count
].new)[j
] =
1079 (text_read_ub(c
) ^ flip_bit
);
1084 text_write_ub(c
, (text_read_ub(c
)^flip_bit
));
1090 flip_bit
= flip_bit
-8;
1092 } else if(faultType
==PTR_FAULT
) {
1093 /* 5f) ptr: if instruction has regmodrm byte (i_has_modrm),
1094 * flip 1 bit in lower byte (0x0f) or any bit in following
1095 * bytes (sib, imm or disp).
1098 c
=(unsigned char *) addr
;
1100 switch (text_read_ub(c
)) {
1101 case 0x66: case 0x67: case 0x26: case 0x36:
1102 case 0x2e: case 0x3e: case 0x64: case 0x65:
1103 case 0xf0: case 0xf2: case 0xf3:
1114 if(text_read_ub(c
)>=0xd8 && text_read_ub(c
)<=0xdf) {
1115 /* don't mess with fp instruction, yet */
1116 PDEBUG(("floating point instruction, bailing out\n"));
1119 } else if(text_read_ub(c
)==0x0f) {
1122 if(text_read_ub(c
)==0x0f) {
1126 len
= len
-((long) c
- (long) addr
);
1127 flip_bit
= random() % (len
*8-4);
1128 PDEBUG(("flip bit %d (len=%d) => ", flip_bit
, len
));
1130 /* mod/rm byte is special */
1133 flip_bit
= 1 << flip_bit
;
1135 rc
= c
- (unsigned char *) addr
;
1136 if (rc
< sizeof(unsigned long)) {
1137 ((unsigned char *) &res
[count
].new)[rc
] = text_read_ub(c
) ^ flip_bit
;
1141 text_write_ub(c
, text_read_ub(c
)^flip_bit
);
1146 flip_bit
=flip_bit
-4;
1148 for(j
=1; j
<len
; j
++) {
1149 /* go to the right byte */
1151 flip_bit
= 1 << flip_bit
;
1153 rc
= (c
- (unsigned char *) addr
);
1154 if (rc
< sizeof(unsigned long)) {
1155 ((unsigned char *) &res
[count
].new)[rc
] =
1156 text_read_ub(c
) ^ flip_bit
;
1160 text_write_ub(c
, text_read_ub(c
)^flip_bit
);
1166 flip_bit
= flip_bit
-8;
1168 } else if(faultType
==LOOP_FAULT
) {
1169 c
=(unsigned char *) addr
;
1170 /* replace rep with repe, and vice versa */
1171 if(text_read_ub(c
)==0xf3) {
1172 if (j
< sizeof(unsigned long)) {
1173 ((unsigned char *) &res
[count
].new)[j
] = NOP
;
1176 rc
= (c
- (unsigned char *) addr
);
1177 if (rc
< sizeof(unsigned long)) {
1178 ((unsigned char *) &res
[count
].new)[rc
] = 0xf2;
1182 text_write_ub(c
, 0xf2);
1184 } else if(text_read_ub(c
)==0xf2) {
1185 rc
= (c
- (unsigned char *) addr
);
1186 if (rc
< sizeof(unsigned long)) {
1187 ((unsigned char *) &res
[count
].new)[rc
] = 0xf3;
1191 text_write_ub(c
, 0xf3);
1193 } else if( (text_read_ub(c
)&0xf0)==0x70 ) {
1194 /* if we've jxx imm8 instruction,
1195 * incl even byte instruction, eg jo (70) to jno (71)
1196 * decl odd byte instruction, eg jnle (7f) to jle (7e)
1198 if(text_read_ub(c
)%2 == 0) {
1199 rc
= (c
- (unsigned char *) addr
);
1200 if (rc
< sizeof(unsigned long)) {
1201 ((unsigned char *) &res
[count
].new)[rc
] = text_read_ub(c
) + 1;
1206 text_write_ub(c
, text_read_ub(c
)+1);
1210 rc
= (c
- (unsigned char *) addr
);
1211 if (rc
< sizeof(unsigned long)) {
1212 ((unsigned char *) &res
[count
].new)[rc
] = text_read_ub(c
) - 1;
1217 text_write_ub(c
, text_read_ub(c
)-1);
1220 } else if(text_read_ub(c
)==0x66 || text_read_ub(c
)==0x67) {
1221 /* override prefix */
1223 } else if(text_read_ub(c
++)==0xf && (text_read_ub(c
)&0xf0)==0x80 ) {
1224 /* if we've jxx imm16/32 instruction,
1225 * incl even byte instruction, eg jo (80) to jno (81)
1226 * decl odd byte instruction, eg jnle (8f) to jle (8e)
1228 if(text_read_ub(c
)%2 == 0) {
1229 rc
= (c
- (unsigned char *) addr
);
1230 if (rc
< sizeof(unsigned long)) {
1231 ((unsigned char *) &res
[count
].new)[rc
] = text_read_ub(c
) + 1;
1235 text_write_ub(c
, text_read_ub(c
)+1);
1238 rc
= (c
- (unsigned char *) addr
);
1239 if (rc
< sizeof(unsigned long)) {
1240 ((unsigned char *) &res
[count
].new)[rc
] = text_read_ub(c
) -1;
1245 text_write_ub(c
, text_read_ub(c
)-1);
1251 PDEBUG(("%lx\n", text_read_ul(addr
)));
1257 #else /* CONFIG_SWIFI */
1260 sys_inject_fault(char * module_name
,
1261 unsigned long argFaultType
,
1262 unsigned long argRandomSeed
,
1263 unsigned long argNumFaults
,
1264 pswifi_result_t result_record
,
1265 unsigned long do_inject
)
1270 #endif /* CONFIG_SWIFI */