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

📄 memory.c

📁 思科路由器仿真器,用来仿7200系列得,可以在电脑上模拟路由器-Cisco router simulator, used to fake a 7200 series can be simulated
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Cisco 7200 (Predator) simulation platform. * Copyright (c) 2005,2006 Christophe Fillot (cf@utc.fr) */#define _GNU_SOURCE#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/mman.h>#include <fcntl.h>#include <assert.h>#include "mips64.h"#include "dynamips.h"#include "memory.h"#include "device.h"#include "cpu.h"#include "cp0.h"#include "vm.h"/* Record a memory access */void memlog_rec_access(cpu_mips_t *cpu,m_uint64_t vaddr,m_uint64_t data,                       m_uint32_t op_size,m_uint32_t op_type){   memlog_access_t *acc;   acc = &cpu->memlog_array[cpu->memlog_pos];   acc->pc      = cpu->pc;   acc->vaddr   = vaddr;   acc->data    = data;   acc->op_size = op_size;   acc->op_type = op_type;   acc->data_valid = (op_type == MTS_WRITE);   cpu->memlog_pos = (cpu->memlog_pos + 1) & (MEMLOG_COUNT - 1);}/* Show the latest memory accesses */void memlog_dump(cpu_mips_t *cpu){   memlog_access_t *acc;   char s_data[64];   u_int i,pos;      for(i=0;i<MEMLOG_COUNT;i++) {      pos = cpu->memlog_pos + i;      pos &= (MEMLOG_COUNT-1);      acc = &cpu->memlog_array[pos];      if (cpu->pc) {         if (acc->data_valid)            snprintf(s_data,sizeof(s_data),"0x%llx",acc->data);         else            snprintf(s_data,sizeof(s_data),"XXXXXXXX");         printf("CPU%u: pc=0x%8.8llx, vaddr=0x%8.8llx, "                "size=%u, type=%s, data=%s\n",                cpu->id,acc->pc,acc->vaddr,acc->op_size,                (acc->op_type == MTS_READ) ? "read " : "write",                s_data);      }   }}/* Update the data obtained by a read access */void memlog_update_read(cpu_mips_t *cpu,m_iptr_t raddr){   memlog_access_t *acc;   acc = &cpu->memlog_array[(cpu->memlog_pos-1) & (MEMLOG_COUNT-1)];   if (acc->op_type == MTS_READ)    {      switch(acc->op_size) {         case 1:            acc->data = *(m_uint8_t *)raddr;            break;         case 2:            acc->data = vmtoh16(*(m_uint16_t *)raddr);            break;         case 4:            acc->data = vmtoh32(*(m_uint32_t *)raddr);            break;         case 8:            acc->data = vmtoh64(*(m_uint64_t *)raddr);            break;      }      acc->data_valid = TRUE;   }}/* MTS access with special access mask */void mts_access_special(cpu_mips_t *cpu,m_uint64_t vaddr,m_uint32_t mask,                        u_int op_code,u_int op_type,u_int op_size,                        m_uint64_t *data,u_int *exc){   switch(mask) {      case MTS_ACC_U:#if DEBUG_MTS_ACC_U         if (op_type == MTS_READ)            cpu_log(cpu,"MTS","read  access to undefined address 0x%llx at "                    "pc=0x%llx (size=%u)\n",vaddr,cpu->pc,op_size);         else            cpu_log(cpu,"MTS","write access to undefined address 0x%llx at "                    "pc=0x%llx, value=0x%8.8llx (size=%u)\n",                    vaddr,cpu->pc,*data,op_size);#endif         if (op_type == MTS_READ)            *data = 0;         break;      case MTS_ACC_T:         if (op_code != MIPS_MEMOP_LOOKUP) {#if DEBUG_MTS_ACC_T            cpu_log(cpu,"MTS","TLB exception for address 0x%llx at pc=0x%llx "                    "(%s access, size=%u)\n",                    vaddr,cpu->pc,(op_type == MTS_READ) ?                     "read":"write",op_size);            mips64_dump_regs(cpu);#if MEMLOG_ENABLE            memlog_dump(cpu);#endif#endif            cpu->cp0.reg[MIPS_CP0_BADVADDR] = vaddr;            if (op_type == MTS_READ)               mips64_trigger_exception(cpu,MIPS_CP0_CAUSE_TLB_LOAD,0);            else               mips64_trigger_exception(cpu,MIPS_CP0_CAUSE_TLB_SAVE,0);         }                  *exc = 1;         break;      case MTS_ACC_AE:         if (op_code != MIPS_MEMOP_LOOKUP) {#if DEBUG_MTS_ACC_AE            cpu_log(cpu,"MTS","AE exception for address 0x%llx at pc=0x%llx "                    "(%s access)\n",                    vaddr,cpu->pc,(op_type == MTS_READ) ? "read":"write");#endif            cpu->cp0.reg[MIPS_CP0_BADVADDR] = vaddr;            if (op_type == MTS_READ)               mips64_trigger_exception(cpu,MIPS_CP0_CAUSE_ADDR_LOAD,0);            else               mips64_trigger_exception(cpu,MIPS_CP0_CAUSE_ADDR_SAVE,0);         }         *exc = 1;         break;   }}/* === MTS for 64-bit address space ======================================= */#define MTS_ADDR_SIZE      64#define MTS_PROTO(name)    mts64_##name#define MTS_PROTO_UP(name) MTS64_##name#include "mips_mts.c"/* === MTS for 32-bit address space ======================================= */#define MTS_ADDR_SIZE      32#define MTS_PROTO(name)    mts32_##name#define MTS_PROTO_UP(name) MTS32_##name#include "mips_mts.c"/* === Specific operations for MTS64 ====================================== *//* MTS64 slow lookup */static forced_inline mts64_entry_t *mts64_slow_lookup(cpu_mips_t *cpu,m_uint64_t vaddr,                                 u_int op_code,u_int op_size,                                 u_int op_type,m_uint64_t *data,                                 u_int *exc){   m_uint32_t hash_bucket,zone,sub_zone,cca;   mts64_entry_t *entry,new_entry;   mts_map_t map;   map.tlb_index = -1;   hash_bucket = MTS64_HASH(vaddr);   entry = cpu->mts_cache[hash_bucket];   zone = vaddr >> 40;#if DEBUG_MTS_STATS   cpu->mts_misses++;#endif   switch(zone) {      case 0x000000:   /* xkuseg */      case 0x400000:   /* xksseg */      case 0xc00000:   /* xkseg */         /* trigger TLB exception if no matching entry found */         if (!cp0_tlb_lookup(cpu,vaddr,&map))            goto err_tlb;         if (!mts64_map(cpu,vaddr,&map,&new_entry))            goto err_undef;         break;      case 0xffffff:         sub_zone  = (vaddr >> 29) & 0x7FF;         switch(sub_zone) {            case 0x7fc:   /* ckseg0 */               map.vaddr  = sign_extend(MIPS_KSEG0_BASE,32);               map.paddr  = 0;               map.len    = MIPS_KSEG0_SIZE;               map.cached = TRUE;               if (!mts64_map(cpu,vaddr,&map,&new_entry))                  goto err_undef;               break;            case 0x7fd:   /* ckseg1 */               map.vaddr  = sign_extend(MIPS_KSEG1_BASE,32);               map.paddr  = 0;               map.len    = MIPS_KSEG1_SIZE;               map.cached = FALSE;               if (!mts64_map(cpu,vaddr,&map,&new_entry))                  goto err_undef;               break;            case 0x7fe:   /* cksseg */            case 0x7ff:   /* ckseg3 */               /* trigger TLB exception if no matching entry found */               if (!cp0_tlb_lookup(cpu,vaddr,&map))                  goto err_tlb;               if (!mts64_map(cpu,vaddr,&map,&new_entry))                  goto err_undef;               break;            default:               /* Invalid zone: generate Address Error (AE) exception */               goto err_address;         }         break;            /* xkphys */      case 0x800000:      case 0x880000:      case 0x900000:      case 0x980000:      case 0xa00000:      case 0xa80000:      case 0xb00000:      case 0xb80000:         cca = (vaddr >> MIPS64_XKPHYS_CCA_SHIFT) & 0x03;         map.cached = mips64_cca_cached(cca);         map.vaddr  = vaddr & MIPS64_XKPHYS_ZONE_MASK;         map.paddr  = 0;         map.len    = MIPS64_XKPHYS_PHYS_SIZE;         if (!mts64_map(cpu,vaddr,&map,&new_entry))            goto err_undef;         break;      default:         /* Invalid zone: generate Address Error (AE) exception */         goto err_address;   }   /* Get a new entry if necessary */   if (!entry) {      entry = mts64_alloc_entry(cpu);      entry->pself = entry->pprev = NULL;      entry->next = NULL;      /* Store the entry in hash table for future use */      cpu->mts_cache[hash_bucket] = entry;   } else {      /* Remove the entry from the reverse map list */      if (entry->pprev) {         if (entry->next)            entry->next->pprev = entry->pprev;         *(entry->pprev) = entry->next;      }   }   /* Add this entry to the reverse map list */   if (map.tlb_index != -1) {      entry->pself = (mts64_entry_t **)&cpu->mts_cache[hash_bucket];      entry->next  = cpu->mts_rmap[map.tlb_index];      entry->pprev = (mts64_entry_t **)&cpu->mts_rmap[map.tlb_index];      if (entry->next)         entry->next->pprev = &entry->next;      cpu->mts_rmap[map.tlb_index] = entry;   }   /* Fill the new entry or replace the previous */   entry->phys_page = new_entry.phys_page;   entry->start  = new_entry.start;   entry->mask   = new_entry.mask;   entry->action = new_entry.action;   return entry; err_undef:   mts_access_special(cpu,vaddr,MTS_ACC_U,op_code,op_type,op_size,data,exc);   return NULL; err_address:   mts_access_special(cpu,vaddr,MTS_ACC_AE,op_code,op_type,op_size,data,exc);   return NULL; err_tlb:   mts_access_special(cpu,vaddr,MTS_ACC_T,op_code,op_type,op_size,data,exc);   return NULL;}/* MTS64 access */static forced_inline void *mts64_access(cpu_mips_t *cpu,m_uint64_t vaddr,                                        u_int op_code,u_int op_size,                                        u_int op_type,m_uint64_t *data,                                        u_int *exc){   m_uint32_t hash_bucket;   mts64_entry_t *entry;   m_iptr_t haddr;   u_int dev_id;#if MEMLOG_ENABLE   /* Record the memory access */   memlog_rec_access(cpu,vaddr,*data,op_size,op_type);#endif   *exc = 0;   hash_bucket = MTS64_HASH(vaddr);   entry = cpu->mts_cache[hash_bucket];#if DEBUG_MTS_STATS   cpu->mts_lookups++;#endif   /* Slow lookup if nothing found in cache */   if (unlikely((!entry) ||        unlikely((vaddr & sign_extend(entry->mask,32)) != entry->start)))    {      entry = mts64_slow_lookup(cpu,vaddr,op_code,op_size,op_type,data,exc);      if (!entry) return NULL;   }   /* Device access */   if (unlikely(entry->action & MTS_DEV_MASK)) {      dev_id = (entry->action & MTS_DEVID_MASK) >> MTS_DEVID_SHIFT;      haddr = entry->action & MTS_DEVOFF_MASK;      haddr += vaddr - entry->start;#if DEBUG_MTS_DEV      cpu_log(cpu,"MTS64",              "device access: vaddr=0x%llx, pc=0x%llx, dev_offset=0x%x\n",              vaddr,cpu->pc,haddr);#endif      return(dev_access_fast(cpu,dev_id,haddr,op_size,op_type,data));   }   /* Raw memory access */   haddr = entry->action & MTS_ADDR_MASK;   haddr += vaddr - entry->start;#if MEMLOG_ENABLE   memlog_update_read(cpu,haddr);#endif   return((void *)haddr);}/* MTS64 virtual address to physical page translation */static fastcall int mts64_translate(cpu_mips_t *cpu,m_uint64_t vaddr,                                    m_uint32_t *phys_page){      m_uint32_t hash_bucket,offset;   mts64_entry_t *entry;   m_uint64_t data = 0;   u_int exc = 0;      hash_bucket = MTS64_HASH(vaddr);   entry = cpu->mts_cache[hash_bucket];   /* Slow lookup if nothing found in cache */   if (unlikely((!entry) ||        unlikely((vaddr & sign_extend(entry->mask,32)) != entry->start)))    {      entry = mts64_slow_lookup(cpu,vaddr,MIPS_MEMOP_LOOKUP,4,MTS_READ,                                &data,&exc);      if (!entry)         return(-1);   }   offset = vaddr - entry->start;   *phys_page = entry->phys_page + (offset >> MIPS_MIN_PAGE_SHIFT);   return(0);}

⌨️ 快捷键说明

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