[Fault-injection-developer] [PATCH 4/4] pagefault interceptor modules patch against 2.5.47 + kprobe
Status: Alpha
Brought to you by:
rustyl
|
From: Zhuang, L. <lou...@in...> - 2002-11-25 10:18:24
|
The pagefault interceptor can catch MMIO access by placing 'page absent bit'
in PTE and handle the pagefault execption.
FITH user space utility can be downloaded in http://prdownloads.sourceforge.
net/fault-injection/fith-mini-8.tgz?download
diff -Nur -X dontdiff linux-2.5-kp-fi-dm/linux-2.5.47/arch/i386/Kconfig
linux-2.5-kp-fi-dm-intcpts/linux-2.5.47/arch/i386/Kconfig
--- linux-2.5-kp-fi-dm/linux-2.5.47/arch/i386/Kconfig Mon Nov 25 15:42:12
2002
+++ linux-2.5-kp-fi-dm-intcpts/linux-2.5.47/arch/i386/Kconfig Mon Nov 25
17:06:12 2002
@@ -1584,6 +1584,12 @@
Only support M here. It is a bug to be fixed. Decision Maker is to
control interceptors how/what to inject.
+config FI_PF
+ tristate "Pagefault interceptor"
+ depends on FI_DM
+ help
+ The interceptor can catch MMIO access by page-absent execption.
+
config DEBUG_STACKOVERFLOW
bool "Check for stack overflows"
depends on DEBUG_KERNEL
diff -Nur -X dontdiff
linux-2.5-kp-fi-dm/linux-2.5.47/arch/i386/kernel/Makefile
linux-2.5-kp-fi-dm-intcpts/linux-2.5.47/arch/i386/kernel/Makefile
--- linux-2.5-kp-fi-dm/linux-2.5.47/arch/i386/kernel/Makefile Mon Nov 25
15:42:12 2002
+++ linux-2.5-kp-fi-dm-intcpts/linux-2.5.47/arch/i386/kernel/Makefile Mon
Nov 25 17:06:12 2002
@@ -12,6 +12,7 @@
obj-y += cpu/
obj-y += timers/
+obj-y += fi/
obj-$(CONFIG_X86_BIOS_REBOOT) += reboot.o
obj-$(CONFIG_MCA) += mca.o
obj-$(CONFIG_X86_MSR) += msr.o
diff -Nur -X dontdiff
linux-2.5-kp-fi-dm/linux-2.5.47/arch/i386/kernel/fi/Makefile
linux-2.5-kp-fi-dm-intcpts/linux-2.5.47/arch/i386/kernel/fi/Makefile
--- linux-2.5-kp-fi-dm/linux-2.5.47/arch/i386/kernel/fi/Makefile Thu
Jan 1 08:00:00 1970
+++
linux-2.5-kp-fi-dm-intcpts/linux-2.5.47/arch/i386/kernel/fi/Makefile Mon
Nov 25 17:06:12 2002
@@ -0,0 +1,10 @@
+#
+# Makefile for the linux kernel.
+#
+
+obj-y += pf/
+obj-y += aslt/
+
+EXTRA_AFLAGS := -traditional
+
+include $(TOPDIR)/Rules.make
diff -Nur -X dontdiff
linux-2.5-kp-fi-dm/linux-2.5.47/arch/i386/kernel/fi/aslt/Makefile
linux-2.5-kp-fi-dm-intcpts/linux-2.5.47/arch/i386/kernel/fi/aslt/Makefile
--- linux-2.5-kp-fi-dm/linux-2.5.47/arch/i386/kernel/fi/aslt/Makefile Thu
Jan 1 08:00:00 1970
+++
linux-2.5-kp-fi-dm-intcpts/linux-2.5.47/arch/i386/kernel/fi/aslt/Makefile
Mon Nov 25 17:18:49 2002
@@ -0,0 +1,10 @@
+#
+# Makefile for the linux kernel.
+#
+export-objs := fi_aslt.o
+obj-$(CONFIG_FI_PF) += fi_aslt.o
+
+
+EXTRA_AFLAGS := -traditional
+
+include $(TOPDIR)/Rules.make
diff -Nur -X dontdiff
linux-2.5-kp-fi-dm/linux-2.5.47/arch/i386/kernel/fi/aslt/fi_aslt.c
linux-2.5-kp-fi-dm-intcpts/linux-2.5.47/arch/i386/kernel/fi/aslt/fi_aslt.c
--- linux-2.5-kp-fi-dm/linux-2.5.47/arch/i386/kernel/fi/aslt/fi_aslt.c Thu
Jan 1 08:00:00 1970
+++
linux-2.5-kp-fi-dm-intcpts/linux-2.5.47/arch/i386/kernel/fi/aslt/fi_aslt.c
Mon Nov 25 17:18:49 2002
@@ -0,0 +1,282 @@
+/**************************************************************************
****
+ * 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: aslt.c,v 1.3 2002/11/14 07:11:40 brlock Exp $
+ * Copyright by Intel Crop., 2002
+ * Stanley Wang (sta...@in...)
+ */
+
+/**
+ * @file aslt.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/signal.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/string.h>
+#include <linux/ioport.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <asm/io.h>
+#include <linux/highmem.h>
+#include <asm/pgtable.h>
+
+
+#define PREFIX_NAME "FI_ASLT"
+#include <linux/fi/fi.h>
+#include <linux/fi/fi_interface.h>
+#include <linux/fi/fi_internal.h>
+
+#define COMPONENT_NAME "fi.interceptor.aslt"
+#define INTERFACE_NAME COMPONENT_NAME ".iIntercept"
+#define LINE_TO_PHY COMPONENT_NAME ".iLine_to_phy"
+
+#define PF_COMPONENT_NAME "fi.interceptor.pf"
+#define PF_INTERFACE_NAME PF_COMPONENT_NAME ".iIntercept"
+#define PF_INTERCEPTOR_MODULE "fi_pf"
+
+#define MAX_WP 32
+
+long globalcounter=0;
+int aslt_register(struct watchpoint wp, int id, struct iInterceptHook
*hook, char *modname);
+int aslt_unregister(int id, char *modname);
+void * fi_ioremap(unsigned long phys_addr, unsigned long size, unsigned
long flags);
+unsigned long fi_line_to_phy(unsigned long line_addr);
+unsigned long fi_phy_to_line(unsigned long phy_addr);
+int check_wp(struct watchpoint wp);
+
+/* Store all wps */
+static struct{
+ struct watchpoint wp;
+ int id;
+ struct iInterceptHook * hook;
+ char modname[256];
+}wp_tb[MAX_WP] = { [0 ... MAX_WP-1] = {
+ wp: {0,0},
+ id: -1,
+ hook: NULL }
+};
+
+static struct iIntercept intcpt[1] = {
+ {
+ wp_register: aslt_register,
+ wp_unregister: aslt_unregister,
+ corrupt: NULL,
+ }
+};
+
+static struct iAslt aslt[1] = {
+ {
+ fi_line_to_phy: fi_line_to_phy,
+ check_wp: check_wp,
+ }
+};
+
+static struct iIntercept *pf_intcpt=NULL;
+
+inline int find_wp(const void *addr, unsigned long len){
+ int i=0;
+
+ for (i=0; i<MAX_WP; i++) {
+ if (wp_tb[i].hook == NULL) continue;
+ if ( wp_tb[i].wp.addr >= addr && wp_tb[i].wp.addr < addr +
len ) {
+ break;
+ }
+ }
+ return i;
+};
+
+
+void * fi_ioremap(unsigned long phys_addr, unsigned long size, unsigned
long flags)
+{
+ void *line_addr;
+ int idx;
+ int rv;
+ unsigned long offset;
+
+ line_addr = __ioremap(phys_addr, size, flags);
+
+ PDEBUG("Linear address: %#lX\n", (unsigned long)line_addr);
+
+ while ((idx = find_wp((void *)phys_addr, size)) < MAX_WP){
+ offset = (unsigned long)(wp_tb[idx].wp.addr) - phys_addr;
+ wp_tb[idx].wp.addr = (void *)((unsigned long)line_addr +
offset);
+ rv = pf_intcpt->wp_register(wp_tb[idx].wp, wp_tb[idx].id,
wp_tb[idx].hook, wp_tb[idx].modname);
+ if (rv < 0) {
+ PERROR("Register fault set fail! @%s\n", __FILE__);
+ }
+ wp_tb[idx].hook = NULL;
+ wp_tb[idx].id = -1;
+ wp_tb[idx].wp.addr = 0;
+ wp_tb[idx].wp.type = 0;
+ (wp_tb[idx].modname)[0] = '\0';
+ }
+ return line_addr;
+}
+
+unsigned long fi_line_to_phy(unsigned long line_addr) {
+ pgd_t *pgd;
+ pmd_t *pmd;
+ pte_t *pte;
+ unsigned long phy_addr;
+
+ pgd = pgd_offset_k(line_addr);
+ if ( !(pgd_val(*pgd)&_PAGE_PRESENT) ) {
+ PERROR("Linear address is not present! @%s\n", __FILE__);
+ return 0;
+ };
+ pmd = pmd_offset(pgd, line_addr);
+ if (pmd_large(*pmd)) {
+ pte = (pte_t *)pmd;
+ } else {
+ pte = pte_offset_kernel(pmd, line_addr);
+ }
+ phy_addr = (pte_val(*pte)&PAGE_MASK) | (line_addr&(~PAGE_MASK));
+ return phy_addr;
+};
+
+unsigned long fi_phy_to_line(unsigned long phy_addr) {
+ pgd_t *pgd;
+ pmd_t *pmd;
+ pte_t *pte;
+ unsigned long line_addr;
+
+ for (line_addr=VMALLOC_START; line_addr<VMALLOC_END;
+ line_addr+=PAGE_SIZE ) {
+ pgd = pgd_offset_k(line_addr);
+ if ( !(pgd_val(*pgd)&_PAGE_PRESENT) ) {
+ continue;
+ };
+ pmd = pmd_offset(pgd, line_addr);
+ if (pmd_large(*pmd)) {
+ pte = (pte_t *)pmd;
+ } else {
+ pte = pte_offset_kernel(pmd, line_addr);
+ }
+ if ( (pte_val(*pte)&PAGE_MASK) == (phy_addr&PAGE_MASK) ) {
+ return line_addr + (phy_addr&(~PAGE_MASK));
+ };
+ }
+ return 0; //can not find the line address
+};
+
+int check_wp(struct watchpoint wp)
+{
+ int idx;
+
+ idx = find_wp(wp.addr, 1);
+ if (idx < MAX_WP) {
+ return 1; /*found*/
+ }
+ return 0;
+}
+
+int aslt_register(struct watchpoint wp, int id, struct iInterceptHook
*hook, char *modname)
+{
+ void *line_addr;
+ int idx;
+
+ line_addr = (void *)fi_phy_to_line((unsigned long)(wp.addr));
+ if (line_addr != 0) {
+ wp.addr = line_addr;
+ return pf_intcpt->wp_register(wp, id, hook, modname);
+ } else {
+ PDEBUG("Address is not present, delay register until
\"insmod\"! @%s\n", __FILE__);
+ idx = find_wp(wp.addr, 1);
+ if (idx < MAX_WP) {
+ PDEBUG("Address is duplicated, fail! @%s\n",
__FILE__);
+ return -EFI_INVALID;
+ }
+ for (idx=0; idx<MAX_WP; idx++){
+ if (wp_tb[idx].hook == NULL){
+ break;
+ }
+ }
+ if (idx>=MAX_WP) return -EFI_TABFULL;
+
+ wp_tb[idx].hook = hook;
+ wp_tb[idx].id = id;
+ wp_tb[idx].wp.addr = wp.addr;
+ wp_tb[idx].wp.type = wp.type;
+ if (modname != NULL)
+ strncpy(wp_tb[idx].modname, modname,
sizeof(wp_tb[idx].modname));
+ }
+ return EFI_SUCCESS;
+}
+
+int aslt_unregister (int id, char *modname)
+{
+ int idx;
+
+ for (idx=0;idx<MAX_WP;idx++) {
+ if (wp_tb[idx].id == id)
+ break;
+ }
+ if (idx >= MAX_WP)
+ return pf_intcpt->wp_unregister(id, modname);
+
+ wp_tb[idx].hook = NULL;
+ wp_tb[idx].id = -1;
+ wp_tb[idx].wp.addr = 0;
+ wp_tb[idx].wp.type = 0;
+ return EFI_SUCCESS;
+}
+
+static int __init aslt_start(void)
+{
+ pf_intcpt = (struct iIntercept
*)inter_module_get_request(PF_INTERFACE_NAME, PF_INTERCEPTOR_MODULE);
+ if (pf_intcpt != NULL) {
+// intcpt[0].wp_unregister = pf_intcpt->wp_unregister;
+ intcpt[0].corrupt = pf_intcpt->corrupt;
+ inter_module_register(INTERFACE_NAME, THIS_MODULE, intcpt);
+ } else {
+ PERROR("Can not get interface %s!\n", PF_INTERFACE_NAME);
+ return -1;
+ }
+
+ inter_module_register(LINE_TO_PHY, THIS_MODULE, aslt);
+
+ return 0;
+}
+
+static void __exit aslt_stop(void)
+{
+ inter_module_unregister(LINE_TO_PHY);
+ inter_module_unregister(INTERFACE_NAME);
+ inter_module_put(PF_INTERFACE_NAME);
+}
+
+module_init(aslt_start);
+module_exit(aslt_stop);
+
+EXPORT_SYMBOL_NOVERS(fi_ioremap);
+
+MODULE_AUTHOR("Stanley Wang");
+MODULE_DESCRIPTION("ASLT component for FI.");
+MODULE_LICENSE("GPL");
+
diff -Nur -X dontdiff
linux-2.5-kp-fi-dm/linux-2.5.47/arch/i386/kernel/fi/pf/Makefile
linux-2.5-kp-fi-dm-intcpts/linux-2.5.47/arch/i386/kernel/fi/pf/Makefile
--- linux-2.5-kp-fi-dm/linux-2.5.47/arch/i386/kernel/fi/pf/Makefile Thu
Jan 1 08:00:00 1970
+++
linux-2.5-kp-fi-dm-intcpts/linux-2.5.47/arch/i386/kernel/fi/pf/Makefile Mon
Nov 25 17:06:12 2002
@@ -0,0 +1,11 @@
+#
+# Makefile for the linux kernel.
+#
+
+obj-$(CONFIG_FI_PF) += fi_pf.o
+fi_pf-objs := pf_interface.o pf.o pf_in.o pf_region.o
+
+
+EXTRA_AFLAGS := -traditional
+
+include $(TOPDIR)/Rules.make
diff -Nur -X dontdiff
linux-2.5-kp-fi-dm/linux-2.5.47/arch/i386/kernel/fi/pf/fi_pf.h
linux-2.5-kp-fi-dm-intcpts/linux-2.5.47/arch/i386/kernel/fi/pf/fi_pf.h
--- linux-2.5-kp-fi-dm/linux-2.5.47/arch/i386/kernel/fi/pf/fi_pf.h Thu
Jan 1 08:00:00 1970
+++
linux-2.5-kp-fi-dm-intcpts/linux-2.5.47/arch/i386/kernel/fi/pf/fi_pf.h Mon
Nov 25 17:19:10 2002
@@ -0,0 +1,81 @@
+/**************************************************************************
****
+ * 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.
+ *
+
****************************************************************************
**
+ */
+
+#ifndef __PF_H_
+#define __PF_H_
+
+
+#define PF_MAJOR 1
+#define PF_MINOR 1
+#define PF_PATCH 0
+
+
+/*
+ * Delcare typedefs
+ */
+enum reason_type{
+ NOT_ME = 0, /* page fault is not in regions */
+ NOTHING = 1, /* access others point in regions */
+ REG_READ = 2, /* read from addr to reg */
+ REG_WRITE = 3, /* write from reg to addr */
+ IMM_WRITE = 4, /* write from imm to addr */
+ OTHERS = 5 /* Other instructions can not intercept */
+};
+
+/*
+ * Declare functions in pf_interface.c
+ */
+void register_pf_interface(void);
+void unregister_pf_interface(void);
+
+
+/*
+ * Declare functions in pf_region.c
+ */
+void pf_lock_region_irqsave(unsigned long *flags);
+void pf_lock_region(void);
+void pf_unlock_region_irqrestore(unsigned long flags);
+void pf_unlock_region(void);
+int pf_find_region(unsigned long addr);
+int pf_add_region(unsigned long addr);
+void pf_release_region(int ri);
+int pf_is_removed_regions(unsigned long addr);
+void pf_clr_pte_bits(unsigned long addr, unsigned long bitmask);
+void pf_set_pte_bits(unsigned long addr, unsigned long bitmask);
+/*
+ * Declare functions in pf_in.c
+ */
+enum reason_type get_ins_type(unsigned long ins_addr);
+unsigned int get_ins_width(unsigned long ins_addr);
+unsigned long get_ins_reg_val(unsigned long ins_addr, struct pt_regs
*regs);
+void set_ins_reg_val(unsigned long addr, struct pt_regs *regs, unsigned
long val);
+unsigned long get_ins_imm_val(unsigned long ins_addr);
+void set_ins_imm_val(unsigned long ins_addr, unsigned long val);
+
+
+/*
+ * Declare functions in pf.c
+ */
+int pf_register(struct watchpoint wp, int id, struct iInterceptHook *hook,
char *modname);
+int pf_unregister(int id, char *modname);
+int pf_corrupt(int id, __u32 dirty, void *data);
+
+#endif//__PF_H_
diff -Nur -X dontdiff
linux-2.5-kp-fi-dm/linux-2.5.47/arch/i386/kernel/fi/pf/pf.c
linux-2.5-kp-fi-dm-intcpts/linux-2.5.47/arch/i386/kernel/fi/pf/pf.c
--- linux-2.5-kp-fi-dm/linux-2.5.47/arch/i386/kernel/fi/pf/pf.c Thu Jan 1
08:00:00 1970
+++ linux-2.5-kp-fi-dm-intcpts/linux-2.5.47/arch/i386/kernel/fi/pf/pf.c Mon
Nov 25 17:19:41 2002
@@ -0,0 +1,449 @@
+/**************************************************************************
****
+ * 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: pf.c,v 1.2 2002/11/14 06:19:49 yzhuang Exp $
+ * Copyright by Intel Crop., 2002
+ * Louis Zhuang (lou...@in...)
+ */
+
+/**
+ * @file pf.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/signal.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/fcntl.h>
+#include <linux/ptrace.h>
+#include <linux/ioport.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <asm/pgalloc.h>
+#include <asm/io.h>
+#include <asm/tlbflush.h>
+
+#include <asm/fi.h>
+
+#define PREFIX_NAME "FI_PF"
+#include <linux/fi/fi.h>
+#include <linux/fi/fi_interface.h>
+#include <linux/fi/fi_internal.h>
+
+#include "fi_pf.h"
+
+long globalcounter=0;
+
+#define MAX_WP 32
+
+/* Store all wps */
+static struct{
+ int page_index;
+ struct watchpoint wp;
+ int id;
+ struct iInterceptHook * hook;
+}wp_tb[MAX_WP] = { [0 ... MAX_WP-1] = {
+ wp: {0,0},
+ id: -1,
+ hook: NULL }
+};
+
+static void fi_do_flush_tlb_ipi(void* addr) {
+ __flush_tlb_one(addr);
+};
+static void fi_flush_tlb_all(unsigned long addr) {
+ if ((smp_call_function(fi_do_flush_tlb_ipi,(void*)addr,1,1))!=0) {
+ PERROR("can not flush tlb\n");
+ }
+ __flush_tlb_one(addr);
+};
+
+int pf_register(struct watchpoint wp, int id, struct iInterceptHook *hook,
char *modname){
+ unsigned long flags;
+ int wi=0; //watchpoint index
+ int ri=0; //region index
+ int rv=0;
+
+ /* Make sure that wp is vaild */
+ if ( hook==NULL ) {
+ PERROR("Reason: %s\n", "/* There are no callback */");
+ return -EFI_INVALID;
+ }
+ if ( wp.type& (~FI_WPTYPE_ALL_MASK) ) {
+ PERROR("Reason: %s\n", "/* There are reserved bits in
use*/");
+ return -EFI_INVALID;
+ }
+ if ( is_IO(wp.type) && (unsigned int)wp.addr>0xffff ) {
+ PERROR("Reason: %s\n", "/* beyond 64k IO space*/");
+ return -EFI_INVALID;
+ }
+
+ pf_lock_region_irqsave(&flags);//lock regions
+
+ /* Make sure there are no the same wp or id */
+ for (wi=0; wi<MAX_WP; wi++) {
+ if (wp_tb[wi].hook==NULL) continue;
+ if ((id==wp_tb[wi].id) || (wp.addr==wp_tb[wi].wp.addr)) {
+ PERROR("Reason: %s\n", "/* there are same wp or id
*/");
+ rv = -EFI_REGISTERED;
+ goto err1;
+ }
+ }
+
+ ri = pf_add_region((unsigned long)wp.addr);
+ if (ri<0) {
+ PERROR("can not add this region, %p\n", wp.addr);
+ goto err;
+ }
+
+ /* find empty item in wp_tb */
+ for (wi=0; wi<MAX_WP; wi++){
+ if (wp_tb[wi].hook==NULL){
+ break;
+ }
+ }
+ if (wi>=MAX_WP) {
+ rv = -EFI_TABFULL;
+ goto err1;
+ }
+
+ /* register this wp into wp_tb*/
+ wp_tb[wi].wp.addr = wp.addr;
+ wp_tb[wi].wp.type = wp.type;
+ wp_tb[wi].id = id;
+ wp_tb[wi].hook = hook;
+
+ if(modname != NULL)
+ fi_lock_module(modname);
+
+ PDEBUG("register WP: index=%d, addr=0X%p, type=0x%x, id=%d,
hook=0x%p\n",
+ wi, wp_tb[wi].wp.addr, wp_tb[wi].wp.type,
+ wp_tb[wi].id, wp_tb[wi].hook);
+ err1:
+ err:
+ pf_unlock_region_irqrestore(flags);
+ fi_flush_tlb_all((unsigned long)wp.addr);
+ return rv;
+};
+
+
+int pf_unregister(int id, char *modname) {
+ unsigned long flags;
+ int wi=0;
+ int ri=0;
+ int rv=0;
+
+ pf_lock_region_irqsave(&flags);
+
+ /* find the id */
+ for (wi=0; wi<MAX_WP; wi++) {
+ if (wp_tb[wi].hook!=NULL && wp_tb[wi].id == id) {
+ break;
+ }
+ }
+ if (wi>=MAX_WP) {
+ rv = -EFI_NOTFOUND;
+ goto err;
+ }
+
+ ri = pf_find_region((unsigned long)wp_tb[wi].wp.addr);
+ if (ri>=0) {
+ pf_release_region(ri);
+ }else{
+ PERROR("can not release region #%d\n", ri);
+ }
+
+ wp_tb[wi].wp.addr = 0;
+ wp_tb[wi].wp.type = 0;
+ wp_tb[wi].id = -1;
+ wp_tb[wi].hook = 0;
+
+ if (modname != NULL)
+ fi_unlock_module(modname);
+ err:
+ pf_unlock_region_irqrestore(flags);
+ return rv;
+};
+
+
+/**
+ * This is a KEY data structure. When interceptor triggers DM
+ * and then DM call iAction method. iAction remembers this corrupted data.
+ * Then DM returns to Interceptor and Interceptor returns corrupted data
+ * to intercepted access.
+ */
+struct fi_corrupt{
+ __u32 corrupted_data;
+};
+
+int pf_corrupt(int id, __u32 dirty, void *data){
+ ((struct fi_corrupt *)data)->corrupted_data = dirty;
+ return 0;
+};
+
+
+inline static int find_wp(unsigned long addr){
+ int i=0;
+
+ for (i=0; i<MAX_WP; i++) {
+ if (wp_tb[i].hook == NULL) continue;
+ if (addr == (unsigned long)wp_tb[i].wp.addr) {
+ break;
+ }
+ }
+ return i;
+};
+
+
+/*
+ * Handle page fault exception and debug exception
+ */
+struct {
+ unsigned long addr;
+ unsigned long eip;
+ enum reason_type type;
+ unsigned long val;
+ int index;
+}pf_reason[NR_CPUS] = { [0 ... NR_CPUS-1] = {0, 0, NOT_ME, 0, 0} };
+
+static unsigned long crpt_mask[] =
+{ 0x000000FF, 0x0000FFFF, 0x00FFFFFF, 0xFFFFFFFF};
+
+int pf_do_page_fault(struct pt_regs * regs, unsigned long address) {
+ unsigned long cpu = smp_processor_id();
+ struct fi_corrupt crpt;
+ int i;
+ int ins_len, crpt_len;
+
+ pf_lock_region(); //lock it!
+ if (pf_find_region(address)<0) {
+ if (pf_is_removed_regions(address)) {
+ pf_unlock_region();
+ return 1;
+ } else {
+ goto not_me;
+ }
+ }
+
+ pf_reason[cpu].type = NOTHING;
+ pf_reason[cpu].addr = address;
+ pf_reason[cpu].eip = regs->eip;
+
+ i = find_wp(address);
+ if (i>=MAX_WP) {
+ PDEBUG("address=%#08lx is not watched, cpuid=%ld,
type=%d\n",
+ address, cpu, pf_reason[cpu].type);
+ goto out;
+ }
+
+ /* We find a wp for this pagefault */
+ pf_reason[cpu].index= i;
+ pf_reason[cpu].type = get_ins_type(pf_reason[cpu].eip);
+
+ PDEBUG("address=%#08lx is watched, cpuid=%ld, type=%d\n",
+ address, cpu, pf_reason[cpu].type);
+
+ switch (pf_reason[cpu].type) {
+ case OTHERS:
+ PDEBUG("Hmm? Can not analyze the instruction,
*eip=0x%08lx\n",
+ *(unsigned long *)pf_reason[cpu].eip);
+ break;
+ case REG_WRITE:
+ PDEBUG("reg_write instruction eip=0x%08lx\n",
+ pf_reason[cpu].eip);
+ if (is_write(wp_tb[i].wp.type)) {
+
+ ins_len = get_ins_width(pf_reason[cpu].eip);
+ pf_reason[cpu].val = get_ins_reg_val(pf_reason[cpu].
eip, regs);
+
+ crpt_len = (WP_LEN(wp_tb[i].wp)<ins_len)?
+ WP_LEN(wp_tb[i].wp):ins_len;
+ crpt.corrupted_data =
+ pf_reason[cpu].val & crpt_mask[crpt_len-1];
+ ( *(wp_tb[i].hook->trigger) )( wp_tb[i].id,
crpt.corrupted_data,
+ crpt_len, 0, &crpt);
+
+ set_ins_reg_val(pf_reason[cpu].eip, regs,
+ (crpt.corrupted_data&crpt_mask[crpt_
len-1])
+ |
(pf_reason[cpu].val&(~crpt_mask[crpt_len-1])));
+ }
+ break;
+ case IMM_WRITE:
+ PDEBUG("imm_write instruction eip=0x%08lx\n",
+ pf_reason[cpu].eip);
+ if (is_write(wp_tb[i].wp.type)) {
+
+ ins_len = get_ins_width(pf_reason[cpu].eip);
+ pf_reason[cpu].val = get_ins_imm_val(pf_reason[cpu].
eip);
+
+ crpt_len = (WP_LEN(wp_tb[i].wp)<ins_len)?
+ WP_LEN(wp_tb[i].wp):ins_len;
+ crpt.corrupted_data = pf_reason[cpu].val &
crpt_mask[crpt_len-1];
+ ( *(wp_tb[i].hook->trigger) )( wp_tb[i].id,
crpt.corrupted_data,
+ crpt_len, 0, &crpt);
+
+ set_ins_imm_val(pf_reason[cpu].eip,
+ (crpt.corrupted_data&crpt_mask[crpt_
len-1])
+ |
(pf_reason[cpu].val&(~crpt_mask[crpt_len-1])));
+ }
+ break;
+ case REG_READ:
+ PDEBUG("reg_read instruction eip=0x%08lx\n",
+ pf_reason[cpu].eip);
+ /* we should trigger it in do_debug*/
+ break;
+ default:
+ PERROR("error when getting instruction eip=0x%08lx\n",
+ pf_reason[cpu].eip);
+ break;
+ }
+
+ out:
+ /* set TF */
+ regs->eflags |= X86_EFLAGS_TF;
+
+ /* clean page fault and tlb ONLY on this cpu */
+ pf_set_pte_bits(pf_reason[cpu].addr, _PAGE_PRESENT);
+
+ //__flush_tlb_one(pf_reason[cpu].addr);
+
+ //NOTICE!!! we hold region lock and wp_tb lock now, release it in
do_debug
+ return 1;
+ not_me:
+ pf_reason[cpu].type = NOT_ME;
+ pf_unlock_region();
+ return 0;
+};
+
+int pf_do_debug(unsigned long condition, struct pt_regs * regs) {
+ unsigned long cpu = smp_processor_id();
+ struct fi_corrupt crpt;
+ int ins_len, crpt_len;
+
+ /*
+ * DProbes make do_debug disallow irq. So we are safty from irq now.
+ */
+
+ PDEBUG("cpuid=%ld, type=%d\n", cpu, pf_reason[cpu].type);
+ if (pf_reason[cpu].type == NOT_ME) goto not_me;
+
+ switch (pf_reason[cpu].type) {
+ case OTHERS:
+ PDEBUG("can not analyze the instruction cond=0x%08lx\n",
condition);
+ break;
+ case REG_WRITE:
+ PDEBUG( "restore regval after reg_write corrupting,
val=0x%08lx\n",
+ pf_reason[cpu].val);
+ if (is_write(wp_tb[pf_reason[cpu].index].wp.type)) {
+ set_ins_reg_val(pf_reason[cpu].eip, regs,
pf_reason[cpu].val);
+ }
+ break;
+ case IMM_WRITE:
+ PDEBUG("restore immval after imm_write corrputing,
val=0x%08lx\n",
+ pf_reason[cpu].val);
+ if (is_write(wp_tb[pf_reason[cpu].index].wp.type)) {
+ set_ins_imm_val(pf_reason[cpu].eip,
pf_reason[cpu].val);
+ }
+ break;
+ case REG_READ:
+ PDEBUG("corrupt reg after reg_read! cond=0x%08lx\n",
condition);
+
+ if (is_read(wp_tb[pf_reason[cpu].index].wp.type)) {
+
+ ins_len = get_ins_width(pf_reason[cpu].eip);
+ pf_reason[cpu].val = get_ins_reg_val(pf_reason[cpu].
eip, regs);
+
+ crpt_len =
(WP_LEN(wp_tb[pf_reason[cpu].index].wp)<ins_len)?
+ WP_LEN(wp_tb[pf_reason[cpu].index].wp):ins_l
en;
+ crpt.corrupted_data = pf_reason[cpu].val &
crpt_mask[crpt_len-1];
+ ( *(wp_tb[pf_reason[cpu].index].hook->trigger) )(
+ wp_tb[pf_reason[cpu].index].id,
crpt.corrupted_data,
+ crpt_len, 0, &crpt);
+
+ set_ins_reg_val(pf_reason[cpu].eip, regs,
+ (crpt.corrupted_data&crpt_mask[crpt_
len-1])
+ |
(pf_reason[cpu].val&(~crpt_mask[crpt_len-1])));
+ }
+ break;
+ case NOTHING:
+ PDEBUG("just restore page fault! address=%#08lx\n",
pf_reason[cpu].addr);
+ break;
+ case NOT_ME:
+ default:
+ PERROR("should never reach here! cond=0x%08lx\n",
condition);
+ break;
+ }
+ pf_reason[cpu].type = NOT_ME;
+
+ exit:
+ /* clear TF */
+ regs->eflags &= ~X86_EFLAGS_TF;
+ /* clean page fault and tlb ONLY on this cpu */
+ pf_clr_pte_bits(pf_reason[cpu].addr, _PAGE_PRESENT);
+
+ __flush_tlb_one(pf_reason[cpu].addr);
+
+ //Release lock which is locked in do_page_fault
+ pf_unlock_region();
+ return 1;
+
+ not_me:
+ return 0;
+};
+
+
+/*
+ * Initialize/Uninitialize modules
+ */
+static int __init fi_pf_init(void) {
+ int rv=0;
+
+ register_pf_interface();
+ fi_post_page_fault=pf_do_debug;
+ fi_page_fault=pf_do_page_fault;
+
+ PINFO("FI Pagefault interceptor v%d.%d.%d loaded.\n", PF_MAJOR,
PF_MINOR, PF_PATCH);
+ EXPORT_NO_SYMBOLS;
+ return 0;
+};
+
+static void __exit fi_pf_cleanup(void) {
+ fi_page_fault=NULL;
+ fi_post_page_fault=NULL;
+ unregister_pf_interface();
+};
+
+module_init(fi_pf_init);
+module_exit(fi_pf_cleanup);
+MODULE_AUTHOR("Louis Zhuang");
+MODULE_DESCRIPTION("Pagefault interceptor component for FI");
+MODULE_LICENSE("GPL");
diff -Nur -X dontdiff
linux-2.5-kp-fi-dm/linux-2.5.47/arch/i386/kernel/fi/pf/pf_in.c
linux-2.5-kp-fi-dm-intcpts/linux-2.5.47/arch/i386/kernel/fi/pf/pf_in.c
--- linux-2.5-kp-fi-dm/linux-2.5.47/arch/i386/kernel/fi/pf/pf_in.c Thu
Jan 1 08:00:00 1970
+++
linux-2.5-kp-fi-dm-intcpts/linux-2.5.47/arch/i386/kernel/fi/pf/pf_in.c Mon
Nov 25 17:20:03 2002
@@ -0,0 +1,443 @@
+/**************************************************************************
****
+ * 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: pf_in.c,v 1.1.1.1 2002/11/12 05:56:32 brlock Exp $
+ * Copyright by Intel Crop., 2002
+ * Louis Zhuang (lou...@in...)
+ */
+
+/**
+ * @file pf_hooks.c
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/fcntl.h>
+#include <linux/ioport.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <asm/io.h>
+
+#define PREFIX_NAME "FI_PF"
+#include <linux/fi/fi.h>
+#include <linux/fi/fi_interface.h>
+#include <linux/fi/fi_internal.h>
+
+#include "fi_pf.h"
+
+#define NR_ELEMENTS(array) (sizeof(array)/sizeof(array[0]))
+
+/* IA32 Manual 3, 2-1 */
+static unsigned char prefix_codes[] = {
+ 0xF0, 0xF2, 0xF3, 0x2E, 0x36, 0x3E, 0x26, 0x64,
+ 0x65, 0x2E, 0x3E, 0x66, 0x67
+};
+int skip_prefix(unsigned char *addr, int *shorted) {
+ int i=0;
+ unsigned char *p=addr;
+ *shorted=0;
+
+ restart:
+ for (i=0; i<NR_ELEMENTS(prefix_codes); i++) {
+ if (*p == prefix_codes[i]){
+ if (*p == 0x66) *shorted = 1;
+ p++;
+ goto restart;
+ }
+ }
+ return p-addr;
+};
+
+int get_opcode(unsigned char *addr, unsigned int *opcode) {
+ int rv;
+ if (*addr == 0x0F){/*0x0F is extension instruction*/
+ *opcode = *(unsigned short*)addr;
+ rv=2;
+ }else{
+ *opcode = *addr;
+ rv=1;
+ }
+ return rv;
+};
+
+/* IA32 Manual 3, 3-432*/
+static unsigned int reg_rop[] = {0x8A, 0x8B, 0xB60F, 0xB70F, 0xBE0F,
0xBF0F};
+static unsigned int reg_wop[] = {0x88, 0x89};
+static unsigned int imm_wop[] = {0xC6, 0xC7};
+
+enum reason_type get_ins_type(unsigned long ins_addr) {
+ unsigned int opcode;
+ unsigned char *p;
+ int shorted=0;
+ int i=0;
+ enum reason_type rv=OTHERS;
+
+ p = (unsigned char *)ins_addr;
+ p += skip_prefix(p, &shorted);
+ p += get_opcode(p, &opcode);
+
+ for (i=0; i<NR_ELEMENTS(reg_rop); i++) {
+ if (reg_rop[i]==opcode) {
+ rv = REG_READ;
+ goto exit;
+ }
+ }
+
+ for (i=0; i<NR_ELEMENTS(reg_wop); i++) {
+ if (reg_wop[i]==opcode) {
+ rv = REG_WRITE;
+ goto exit;
+ }
+ }
+
+ for (i=0; i<NR_ELEMENTS(imm_wop); i++) {
+ if (imm_wop[i]==opcode) {
+ rv = IMM_WRITE;
+ goto exit;
+ }
+ }
+
+ exit:
+ return rv;
+};
+
+/* IA32 Manual 3, 3-432*/
+static unsigned int w8[] = {0x88, 0x8A, 0xC6};
+static unsigned int w32[]= {0x89, 0x8B, 0xC7, 0xB60F, 0xB70F, 0xBE0F,
0xBF0F};
+unsigned int get_ins_width(unsigned long ins_addr) {
+ unsigned int opcode;
+ unsigned char *p;
+ int shorted=0;
+ int i=0;
+
+ p = (unsigned char *)ins_addr;
+ p += skip_prefix(p, &shorted);
+ p += get_opcode(p, &opcode);
+
+ for (i=0; i<NR_ELEMENTS(w8); i++) {
+ if (w8[i]==opcode) {
+ return 1;
+ }
+ }
+ for (i=0; i<NR_ELEMENTS(w32); i++) {
+ if (w32[i]==opcode) {
+ if (shorted) {
+ return 2;
+ } else {
+ return 4;
+ }
+ }
+ }
+
+ PERROR("Unknow opcode=0x%02x\n", opcode);
+ return 0;
+};
+/* define register ident in mod/rm byte after undefine it in ptrace*/
+#undef EAX
+#define EAX 0
+#define ECX 1
+#define EDX 2
+#undef EBX
+#define EBX 3
+#define ESP 4
+#define EBP 5
+#undef ESI
+#define ESI 6
+#undef EDI
+#define EDI 7
+
+#define AL 0
+#define CL 1
+#define DL 2
+#define BL 3
+#define AH 4
+#define CH 5
+#define DH 6
+#define BH 7
+unsigned char *get_reg_w8(int no, struct pt_regs *regs){
+ unsigned char *rv=NULL;
+
+ switch (no) {
+ case AL:
+ rv = (unsigned char *)®s->eax;
+ break;
+ case BL:
+ rv = (unsigned char *)®s->ebx;
+ break;
+ case CL:
+ rv = (unsigned char *)®s->ecx;
+ break;
+ case DL:
+ rv = (unsigned char *)®s->edx;
+ break;
+ case AH:
+ rv = 1+(unsigned char *)®s->eax;
+ break;
+ case BH:
+ rv = 1+(unsigned char *)®s->ebx;
+ break;
+ case CH:
+ rv = 1+(unsigned char *)®s->ecx;
+ break;
+ case DH:
+ rv = 1+(unsigned char *)®s->edx;
+ break;
+ default:
+ PERROR("Error reg no# %d\n", no);
+ break;
+ }
+ return rv;
+};
+
+unsigned long *get_reg_w32(int no, struct pt_regs *regs){
+ unsigned long *rv=NULL;
+
+ switch (no) {
+ case EAX:
+ rv = ®s->eax;
+ break;
+ case EBX:
+ rv = ®s->ebx;
+ break;
+ case ECX:
+ rv = ®s->ecx;
+ break;
+ case EDX:
+ rv = ®s->edx;
+ break;
+ case ESP:
+ rv = ®s->esp;
+ break;
+ case EBP:
+ rv = ®s->ebp;
+ break;
+ case ESI:
+ rv = ®s->esi;
+ break;
+ case EDI:
+ rv = ®s->edi;
+ break;
+ default:
+ PERROR("Error reg no# %d\n", no);
+ }
+ return rv;
+};
+
+unsigned long get_ins_reg_val(unsigned long ins_addr, struct pt_regs *regs)
{
+ unsigned int opcode;
+ unsigned char mod_rm;
+ int reg;
+ unsigned char *p;
+ int shorted=0;
+ int i=0;
+ unsigned long rv;
+
+ p = (unsigned char *)ins_addr;
+ p += skip_prefix(p, &shorted);
+ p += get_opcode(p, &opcode);
+ for (i=0; i<NR_ELEMENTS(reg_rop); i++) {
+ if (reg_rop[i]==opcode) {
+ rv = REG_READ;
+ goto do_work;
+ }
+ }
+
+ for (i=0; i<NR_ELEMENTS(reg_wop); i++) {
+ if (reg_wop[i]==opcode) {
+ rv = REG_WRITE;
+ goto do_work;
+ }
+ }
+ PERROR("Not a register instruction, opcode=0x%02x\n", opcode);
+ goto err;
+ do_work:
+ mod_rm = *p;
+ reg = (mod_rm>>3)&0x7;
+ if (get_ins_width(ins_addr)==1) {
+ return *get_reg_w8(reg, regs);
+ }else if (get_ins_width(ins_addr)==2) {
+ return *(unsigned short*)get_reg_w32(reg, regs);
+ }else if (get_ins_width(ins_addr)==4) {
+ return *get_reg_w32(reg, regs);
+ }else{
+ PERROR("Error width# %d\n", reg);
+ goto err;
+ }
+ err:
+ return 0;
+};
+
+
+void set_ins_reg_val(unsigned long ins_addr, struct pt_regs *regs, unsigned
long val) {
+ unsigned int opcode;
+ unsigned char mod_rm;
+ int reg;
+ unsigned char *p;
+ int shorted=0;
+ int i=0;
+ unsigned long rv;
+
+ p= (unsigned char *)ins_addr;
+ p += skip_prefix(p, &shorted);
+ p += get_opcode(p, &opcode);
+ for (i=0; i<NR_ELEMENTS(reg_rop); i++) {
+ if (reg_rop[i]==opcode) {
+ rv = REG_READ;
+ goto do_work;
+ }
+ }
+
+ for (i=0; i<NR_ELEMENTS(reg_wop); i++) {
+ if (reg_wop[i]==opcode) {
+ rv = REG_WRITE;
+ goto do_work;
+ }
+ }
+ PERROR("Not a register instruction, opcode=0x%02x\n", opcode);
+ goto err;
+ do_work:
+ mod_rm = *p;
+ reg = (mod_rm>>3)&0x7;
+ if (get_ins_width(ins_addr)==1) {
+ *get_reg_w8(reg, regs) = val;
+ }else if (get_ins_width(ins_addr)==2) {
+ *(unsigned short*)get_reg_w32(reg, regs) = val;
+ }else if (get_ins_width(ins_addr)==4) {
+ *get_reg_w32(reg, regs) = val;
+ }else{
+ PERROR("Error width, reg=%d\n", reg);
+ goto err;
+ }
+ err:
+ return;
+
+};
+
+unsigned long get_ins_imm_val(unsigned long ins_addr) {
+ unsigned int opcode;
+ unsigned char mod_rm;
+ unsigned char mod;
+ unsigned char *p;
+ int shorted=0;
+ int i=0;
+ unsigned long rv;
+
+ p= (unsigned char *)ins_addr;
+ p += skip_prefix(p, &shorted);
+ p += get_opcode(p, &opcode);
+ for (i=0; i<NR_ELEMENTS(imm_wop); i++) {
+ if (imm_wop[i]==opcode) {
+ rv = IMM_WRITE;
+ goto do_work;
+ }
+ }
+ PERROR("Not a imm instruction, opcode=0x%02x\n", opcode);
+ goto err;
+ do_work:
+ mod_rm = *p;
+ mod = mod_rm>>6;
+ p++;
+ switch (mod) {
+ case 0:
+ break;
+ case 1:
+ p += 1;
+ break;
+ case 2:
+ p += 4;
+ case 3:
+ default:
+ PERROR("it is not a memory access instruction,
rm_mod=0x%02x\n", mod_rm);
+ }
+ if (get_ins_width(ins_addr)==1) {
+ return *(unsigned char *)p;
+ }else if (get_ins_width(ins_addr)==2) {
+ return *(unsigned short*)p;
+ }else if (get_ins_width(ins_addr)==4) {
+ return *(unsigned long*)p;
+ }else{
+ PERROR("Error width%s\n", ".");
+ goto err;
+ }
+ err:
+ return 0;
+};
+
+void set_ins_imm_val(unsigned long ins_addr, unsigned long val) {
+ unsigned int opcode;
+ unsigned char mod_rm;
+ unsigned char mod;
+ unsigned char *p;
+ int shorted=0;
+ int i=0;
+ unsigned long rv;
+
+ p= (unsigned char *)ins_addr;
+ p += skip_prefix(p, &shorted);
+ p += get_opcode(p, &opcode);
+ for (i=0; i<NR_ELEMENTS(imm_wop); i++) {
+ if (imm_wop[i]==opcode) {
+ rv = IMM_WRITE;
+ goto do_work;
+ }
+ }
+ PERROR("Not a imm instruction, opcode=0x%02x\n", opcode);
+ goto err;
+ do_work:
+ mod_rm = *p;
+ mod = mod_rm>>6;
+ p++;
+ switch (mod) {
+ case 0:
+ break;
+ case 1:
+ p += 1;
+ break;
+ case 2:
+ p += 4;
+ break;
+ case 3:
+ default:
+ PERROR("it is not a memory access instruction,
rm_mod=0x%02x\n", mod_rm);
+ }
+ if (get_ins_width(ins_addr)==1) {
+ *(unsigned char *)p = val;
+ }else if (get_ins_width(ins_addr)==2) {
+ *(unsigned short*)p = val;
+ }else if (get_ins_width(ins_addr)==4) {
+ *(unsigned long*)p = val;
+ }else{
+ PERROR("Error width%s\n", ".");
+ goto err;
+ }
+ err:
+ return;
+};
diff -Nur -X dontdiff
linux-2.5-kp-fi-dm/linux-2.5.47/arch/i386/kernel/fi/pf/pf_interface.c
linux-2.5-kp-fi-dm-intcpts/linux-2.5.47/arch/i386/kernel/fi/pf/pf_interface.
c
---
linux-2.5-kp-fi-dm/linux-2.5.47/arch/i386/kernel/fi/pf/pf_interface.c Thu
Jan 1 08:00:00 1970
+++
linux-2.5-kp-fi-dm-intcpts/linux-2.5.47/arch/i386/kernel/fi/pf/pf_interface.
c Mon Nov 25 17:20:21 2002
@@ -0,0 +1,81 @@
+/**************************************************************************
****
+ * 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: pf_interface.c,v 1.1.1.1 2002/11/12 05:56:32 brlock Exp $
+ * Copyright by Intel Crop., 2002
+ * Louis Zhuang (lou...@in...)
+ */
+
+/**
+ * @file pf_interface.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/signal.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/fcntl.h>
+#include <linux/ptrace.h>
+#include <linux/ioport.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <asm/io.h>
+
+#define PREFIX_NAME "FI_PF"
+#include <linux/fi/fi.h>
+#include <linux/fi/fi_interface.h>
+#include <linux/fi/fi_internal.h>
+
+#include "fi_pf.h"
+
+
+#define COMPONENT_NAME "fi.interceptor.pf"
+#define INTERFACE_NAME COMPONENT_NAME ".iIntercept"
+
+static struct iIntercept intcpt[1] = {
+ {
+ wp_register: pf_register,
+ wp_unregister: pf_unregister,
+ corrupt: pf_corrupt,
+ }
+};
+
+
+void register_pf_interface(void) {
+ inter_module_register(INTERFACE_NAME, THIS_MODULE, intcpt);
+ PDEBUG("register interface: %s\n", INTERFACE_NAME);
+};
+
+void unregister_pf_interface(void) {
+ inter_module_unregister(INTERFACE_NAME);
+ PDEBUG("unregister interface: %s\n", INTERFACE_NAME);
+};
diff -Nur -X dontdiff
linux-2.5-kp-fi-dm/linux-2.5.47/arch/i386/kernel/fi/pf/pf_region.c
linux-2.5-kp-fi-dm-intcpts/linux-2.5.47/arch/i386/kernel/fi/pf/pf_region.c
--- linux-2.5-kp-fi-dm/linux-2.5.47/arch/i386/kernel/fi/pf/pf_region.c Thu
Jan 1 08:00:00 1970
+++
linux-2.5-kp-fi-dm-intcpts/linux-2.5.47/arch/i386/kernel/fi/pf/pf_region.c
Mon Nov 25 17:20:31 2002
@@ -0,0 +1,212 @@
+/**************************************************************************
****
+ * 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: pf_region.c,v 1.2 2002/11/14 06:19:49 yzhuang Exp $
+ * Copyright by Intel Crop., 2002
+ * Louis Zhuang (lou...@in...)
+ */
+
+/**
+ * @file pf_utils.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/signal.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/fcntl.h>
+#include <linux/ptrace.h>
+#include <linux/ioport.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <asm/delay.h>
+#include <asm/io.h>
+#include <asm/pgalloc.h>
+
+#define PREFIX_NAME "FI_PF"
+#include <linux/fi/fi.h>
+#include <linux/fi/fi_interface.h>
+#include <linux/fi/fi_internal.h>
+
+#include "fi_pf.h"
+
+#define MAX_REGION 32
+
+/* Store all pages which we intercept, other page info can be found
+ * in page directory entry */
+static struct{
+ unsigned long addr;
+ int count;//count==0 is criterion of empty region
+}region[MAX_REGION] = { [0 ... MAX_REGION-1] = {0, 0} };
+static spinlock_t region_lock = SPIN_LOCK_UNLOCKED;
+
+
+static unsigned long removed_region[MAX_REGION] = {
+ [0 ... MAX_REGION-1] = 0
+};
+
+
+static int is_in_region(int i, unsigned long addr) {
+ if ( region[i].count!=0
+ && (addr&PAGE_MASK)==(region[i].addr&PAGE_MASK)) {
+ return 1;
+ }else{
+ return 0;
+ }
+};
+
+static pte_t *get_pte(unsigned long address) {
+ pgd_t *pgd = pgd_offset_k(address);
+ pmd_t *pmd = pmd_offset(pgd, address);
+ if (pmd_large(*pmd))
+ return (pte_t *)pmd;
+ return pte_offset_kernel(pmd, address);
+};
+
+/**
+ * Set/Clear pte bits
+ */
+void pf_clr_pte_bits(unsigned long addr, unsigned long bitmask) {
+ pte_t *pte;
+ pte = get_pte(addr);
+ set_pte( pte, __pte( pte_val(*pte) & ~bitmask) );
+};
+
+void pf_set_pte_bits(unsigned long addr, unsigned long bitmask) {
+ pte_t *pte;
+ pte = get_pte(addr);
+ set_pte( pte, __pte( pte_val(*pte) | bitmask) );
+};
+
+/**
+ * lock_region_irqsave lock the region (that means lock all regions
access).
+ * @param flags the saved flags.
+ */
+void pf_lock_region_irqsave(unsigned long *flags) {
+ spin_lock_irqsave(®ion_lock, *flags);
+};
+void pf_lock_region(void) {
+ spin_lock(®ion_lock);
+};
+
+/**
+ * unlock region which is locked by lock_region_irqsave.
+ * @param flags restoring flags.
+ */
+void pf_unlock_region_irqrestore(unsigned long flags) {
+ spin_unlock_irqrestore(®ion_lock, flags);
+};
+void pf_unlock_region(void) {
+ spin_unlock(®ion_lock);
+};
+
+/* find region in region table
+ * @return < 0 error, no region is found,
+ * >=0 the region index.
+ * @param addr the address which is in region.
+ */
+int pf_find_region(unsigned long addr) {
+ int i=0;
+
+ for (i=0; i<MAX_REGION; i++) {
+ if (is_in_region(i, addr)) {
+ break;
+ }
+ }
+
+ if (i<MAX_REGION) {
+ return i;
+ }else{
+ return -1;//region is not locked!
+ }
+};
+
+/**
+ * increase region count and add region for the addr
+ * if the region is not here.
+ * @return <0 can not add the region
+ * >0 region index
+ * @param addr adding address
+ */
+int pf_add_region(unsigned long addr) {
+ int i=0;
+
+ for (i=0; i<MAX_REGION; i++) {
+ if (is_in_region(i, addr)) {
+ region[i].count++;
+ goto out;
+ }
+ }
+
+ //if there is not this region. create one.
+ for (i=0; i<MAX_REGION; i++) {
+ if (region[i].count==0) {
+ region[i].count= 1;
+ region[i].addr = addr&PAGE_MASK;
+ pf_clr_pte_bits(region[i].addr, _PAGE_PRESENT);
+// flush_tlb_all();
+ goto out;
+ }
+ }
+ err:
+ return -1;
+ out:
+ return i;
+};
+
+/**
+ * release region. when count meet zero, set present in page table.
+ * move this into garbage.
+ */
+void pf_release_region(int ri) {
+ static int removed_pos=0;
+
+ region[ri].count--;
+ if (region[ri].count==0) {
+ pf_set_pte_bits(region[ri].addr, _PAGE_PRESENT);
+ removed_region[removed_pos] = region[ri].addr;
+ removed_pos++;
+ removed_pos %= MAX_REGION;
+ }else if (region[ri].count<0) {
+ PERROR("remove region, count=%d\n", region[ri].count);
+ }
+};
+
+int pf_is_removed_regions(unsigned long addr) {
+ int i=0;
+ for (i=0; i<MAX_REGION; i++) {
+ if (removed_region[i]==(addr&PAGE_MASK)) {
+ return 1;
+ }
+ }
+ return 0;
+};
|