⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 smash_insts.c

📁 一个用在mips体系结构中的操作系统
💻 C
字号:
/* * Copyright (C) 1996-1998 by the Board of Trustees *    of Leland Stanford Junior University. *  * This file is part of the SimOS distribution.  * See LICENSE file for terms of the license.  * *//* * smashinst.c * * A function to be called from tcl when it is time to * smash an instruction at a given address for fault injection * experiments. * * We do this in C since we need to decompose instructions to * figure out what to do. * * Let tcl pass us the address to smash and the random number that * controls what we do, so the experiments are repeatable if needed. */#include <stdlib.h>#include "simtypes.h"#include "cpu.h"#include "cpu_interface.h"#include "mips_arch.h"#include "stdio.h"#include "sim_error.h"#include "string.h"#include "math.h"/* how random number is interpreted. * modify dest of ALU op: change register * modify dest of branch op: change < to <= */struct randomsmash {   uint fill             : 23;   uint regnum           : 5;   /* random register number */   uint modify_or_delete : 2;   /* 1,2,3 = modify instr, 0 = delete it */   uint source_or_dest   : 1;   /* 1 = modify source, 0 = modify dest */   uint rs_or_rt         : 1;   /* 1 = modify source rs, 0 = mod source rt */};#define DELETE_INST    0#define MODIFY_DEST    0#define MODIFY_SOURCE  0typedef enum {change_none,               change_rs,               change_rt,               change_rd} changetype;#if !defined __alpha && !defined __linuxextern long random(void);#endifResultsmashinst(int dosmash, int cpunum, VA addr, int rnd, char* errbuf){   uint  op;         /* extracted instruction opcode */   uint nreg;   Inst instr = 0;      #ifdef PRINT_INSTRUCTIONS   Inst orig_instr = 0;#endif   Result r = SUCCESS;   struct randomsmash* smashtype = (struct randomsmash*) &rnd;   changetype ct = change_none;   uint64 field0;   char fnamebuf[64];   strncpy(fnamebuf, errbuf, 63);   r = CPUVec.GetMemory(cpunum, addr, INST_SIZE, (char*) &instr);#ifdef PRINT_INSTRUCTIONS   orig_instr = instr;#endif   if (r != SUCCESS) {      sprintf(errbuf, "Can't read instruction at address 0x%llx", (Reg64)addr);      return FAILURE;   }   if (instr == 0) {      /* can't do anything to a nop */      goto retry;   }   if (smashtype->modify_or_delete == DELETE_INST) {      instr = 0;      goto writeback;   }   /* going to modify the inst if possible */   op = MAJOR_OP(instr);   if (op == spec_op) {      uint specialFunc = FUNC(instr);      switch(specialFunc) {                  case add_op:      case addu_op:      case and_op:      case nor_op:      case or_op:      case sll_op:      case sllv_op:      case slt_op:      case sltu_op:      case sra_op:      case srav_op:      case srl_op:      case srlv_op:      case sub_op:       case subu_op:      case xor_op:         if (smashtype->source_or_dest == MODIFY_DEST)            ct = change_rd;         else            ct = (smashtype->rs_or_rt) ? change_rs : change_rt;         break;      case div_op:      case divu_op:      case mult_op:      case multu_op:         ct = (smashtype->rs_or_rt) ? change_rs : change_rt;         break;      case mfhi_op:      case mflo_op:         ct = change_rd;         break;      case mthi_op:      case mtlo_op:         ct = change_rs;         break;      case break_op:      case sync_op:      case jr_op:      case jalr_op:       case syscall_op:          goto retry;      default:         CPUWarning("Illegal inst at %#x on CPU %d\n", addr, cpunum);         ASSERT(0);         break;      }   } else {                        /* Not SPECIAL */      if (op == bcond_op) {          if (smashtype->source_or_dest == MODIFY_SOURCE) {            ct = change_rs;         } else {            uint bcondFunc   = RT(instr);            int newop = -1;            switch(bcondFunc) {            case bgez_op:               newop = bgtz_op;               break;            case bgezl_op:               newop = bgtzl_op;               break;            case bltz_op:               newop = blez_op;               break;            case bltzl_op:               newop = blezl_op;               break;               /* there are no off-by-one branch-and-link.  Luckily                * the kernel doesn't use these ops much                */            case bgezal_op:               bcondFunc = bltzal_op;               break;            case bgezall_op:               bcondFunc = bltzall_op;               break;            case bltzal_op:               bcondFunc = bgezal_op;               break;            case bltzall_op:               bcondFunc = bgezall_op;               break;            default:               CPUWarning("Illegal inst at %#x on CPU %d\n", addr, cpunum);               ASSERT(0);               break;            }            if (newop != -1) {               instr = (newop << 26) | RS(instr) | IMMED(instr);            } else {               instr = (bcond_op << 26) | (RS(instr) << 21)                  | (bcondFunc << 16) | IMMED(instr);            }         }      } else { /* Not a SPECIAL or REGIMM instruction */         switch(op) {         case addi_op:         case addiu_op:         case andi_op:         case slti_op:         case sltiu_op:         case xori_op:            ct = (smashtype->source_or_dest == MODIFY_DEST)                  ? change_rt : change_rs;            break;         case beq_op:            if ((RS(instr) == 0) && (RT(instr) == 0)) {               /* this is a b in disguise */               goto retry;            }            /* FALL THROUGH */         case beql_op:         case bne_op:         case bnel_op:            if (smashtype->source_or_dest == MODIFY_SOURCE) {               ct = (smashtype->rs_or_rt) ? change_rs : change_rt;            } else {               uint newop = 0;               switch (op) {               case beq_op:  newop = bne_op;  break;               case beql_op: newop = bnel_op; break;               case bne_op:  newop = beq_op;  break;               case bnel_op: newop = beql_op; break;               }               instr = (newop << 26) | TARGET(instr);            }            break;         case bgtz_op:         case bgtzl_op:         case blez_op:         case blezl_op:            if (smashtype->source_or_dest == MODIFY_SOURCE) {               ct = change_rs;            } else {               uint bcondFunc = 0;               switch (op) {               case bgtz_op:  bcondFunc = bgez_op;  break;               case bgtzl_op: bcondFunc = bgezl_op;  break;               case blez_op:  bcondFunc = bltz_op;  break;               case blezl_op: bcondFunc = bltzl_op;  break;               }               instr = (bcond_op << 26) | (RS(instr) << 21)                  | (bcondFunc << 16) | IMMED(instr);            }            break;         case cache_op:         case j_op:         case jal_op:          case pref_op:         case lui_op:         case ori_op:            goto retry;            /* pointer base register in rs, dest is rt */         case lb_op:         case lbu_op:         case lh_op:         case lhu_op:         case ll_op:          case lw_op:         case ld_op:          case ldc2_op:         case lwl_op:         case lwr_op:            goto retry;   /* don't handle loads/stores yet */            /* rs is base, rt is dest in coprocessor 1 */         case lwc1_op:         case ldc1_op:            goto retry;            /* rs is base, rt is source of data to store */         case sb_op:         case sh_op:         case sc_op:          case sw_op:         case sd_op:         case sdc2_op:         case swc2_op:         case swl_op:         case swr_op:            goto retry;            /* rs is base, rt is source in coproc 1 */         case sdc1_op:         case swc1_op:            goto retry;         case cop0_op:         case cop1_op:            goto retry;         }      }   }   nreg = smashtype->regnum;   switch (ct) {   case change_none:      break;   case change_rs:      if (nreg == RS(instr)) {         nreg = (nreg + 1) % 32;      }      instr =          (MAJOR_OP(instr) << 26)          | (nreg << 21)         | (RT(instr) << 16)         | IMMED(instr);      break;   case change_rt:      if (nreg == RT(instr)) {         nreg = (nreg + 1) % 32;      }      instr =          (MAJOR_OP(instr) << 26)          | (RS(instr) << 21)         | (nreg << 16)         | IMMED(instr);      break;   case change_rd:      if (nreg == RD(instr)) {         nreg = (nreg + 1) % 32;      }      instr =          (MAJOR_OP(instr) << 26)          | (RS(instr) << 21)         | (RT(instr) << 16)         | (nreg << 11)         | (instr & 0x7ff);      break;   }writeback:   if (dosmash) {      r = CPUVec.PutMemory(cpunum, addr, INST_SIZE, (char*) &instr);      if (r != SUCCESS) {         sprintf(errbuf, "Can't write instruction at address 0x%llx", (Reg64)addr);         return FAILURE;      }      field0 = CPUVec.CycleCount(cpunum);   } else {      field0 = random();   }#ifdef PRINT_INSTRUCTIONS   {      extern void SprintInstruction(Inst inst, char* buf);      sprintf(errbuf, "0x%x 0x%x %s (", addr, rnd, fnamebuf);      SprintInstruction(orig_instr, errbuf+strlen(errbuf));      sprintf(errbuf+strlen(errbuf), ") -> (");      SprintInstruction(instr, errbuf+strlen(errbuf));      CPUPrint("%lld %s %s)\n", field0,               dosmash ? "SMASH" : "testSMASH",               errbuf);   }#else   CPUPrint("%lld %s 0x%x 0x%x %s\n", field0,            dosmash ? "SMASH" : "testSMASH",            addr, rnd, fnamebuf);#endif   sprintf(errbuf, "OK");   return SUCCESS;retry:   /* no modification possible on this instr.  tell TCL no go. */   sprintf(errbuf, "RETRY");   return FAILURE;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -