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

📄 registry.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.  * *//***************************************************************** * $File$ *  * The registry should hold three types of "special" addresses: *   Backdoor functions *   Backdoor variables *   I/O device ranges *  * $Author: bosch $ * $Date: 1998/02/10 00:28:32 $ *****************************************************************/#include <stdlib.h>#include "cpu_interface.h"#include "simtypes.h"#include "simutil.h"#include "list.h"#include "sim_error.h"#include "simutil.h"#include "registry.h"#include "sim.h"#include "syslimits.h"#define MAX_FUNCS         1023  /* max. func. entries */#define MAX_ENTRIES_CPU   32    /* max. range entries per CPU */#define MAX_ENTRIES       SIM_MAXCPUS*MAX_ENTRIES_CPU/* Just for registering backdoor functions */typedef struct FuncEntry FuncEntry;struct FuncEntry {   bool present;   uint64 tag;   void (*func)(void);};static FuncEntry funcRegistry[MAX_FUNCS];/* For registering backdoor and I/O data ranges */typedef struct entry Entry;struct entry {   VA start;   VA end;   uint flag;   void *data; /* This is either a function or a data pointer */   char *name; /* Name, only used for debugging */};static Entry  registry[MAX_ENTRIES]; /* range registry */static int    numEntries = 0;        /* number of entries */static int    complete   = 0;        /* still adding entries if == 0 */static Entry* lastEntry;             /* pointer to last entry accessed */static VA minAddress;static VA maxAddress;static uint simFuncCount;/***************************************************************** * Registry initialization *****************************************************************/void RegistryInit(void){   int i;   minAddress = (VA)-1LL;   maxAddress = 0;   for (i=0; i < MAX_FUNCS; i++) {      funcRegistry[i].func = NULL;      funcRegistry[i].present = FALSE;   }   lastEntry = registry;      numEntries = 0;}/***************************************************************** * This procedure just allows you to register functions with the * registry with no regard as to what address they are placed at.  * They will end up being dereferenced in the kernel, caught by  * the simulators, and then the corresponding function will be * executed in the backdoor. All functions will be called with * normal parameter lists, so I kept the arg type as void. *****************************************************************/void RegistryAddSimFunction(void *ptr, void *func){   uint hash;   simFuncCount++;   ASSERT(simFuncCount < MAX_FUNCS);   hash = PTR_TO_UINT64(ptr) % MAX_FUNCS;   while (funcRegistry[hash].present) {      if (funcRegistry[hash].tag == PTR_TO_UINT64(ptr)) {                  CPUPrint("REGISTRY: OVERRIDE  %#x as %#x entry %d\n",                   funcRegistry[hash].func, funcRegistry[hash].tag, hash);         break;      }      hash = (hash + 1) % MAX_FUNCS;   }   funcRegistry[hash].func = (void (*) (void))func;   funcRegistry[hash].tag =  PTR_TO_UINT64(ptr);   funcRegistry[hash].present = TRUE;   SIM_DEBUG(('b', "REGISTRY: ADDED %#x as %#x entry %d\n",               func, ptr, hash));}void *RegistryGetSimFunction(VA address){   uint hash;   hash = (uint)address % MAX_FUNCS;   while (funcRegistry[hash].tag != (uint)address) {      if (funcRegistry[hash].present != TRUE) {         /* fell off the end of the list.  CPU model should          * give a bus error to the processor since this          * is unmapped memory.          */         return NULL;      }      hash = (hash + 1) % MAX_FUNCS;   }   SIM_DEBUG(('b', "BDOOR %lld getfunc: 0x%llx\n",	      (Reg64)CPUVec.CycleCount(0), (Reg64)address));   return (void *)funcRegistry[hash].func;}/***************************************************************** * Add a chunk of the virtual address space to the registry along  * with flags and an optional function that can be executed when this * range is addressed. The flag indicates whether this reference * should be treated as a function or just read uncached as data. ****************************************************************/intRegistryAddRange(VA start, VA size, uint flag, void *data, char *name){   VA end = start + size;      register Entry *ptr;   register Entry *endPtr = registry + numEntries;   ASSERT(size > 0);   ASSERT(!complete);   /* Check for overlap. */   for (ptr = registry; ptr < endPtr; ptr++) {      if ((end <= ptr->start) || (start >= ptr->end))          continue;      CPUError("Overlap in call to RegistryAddRange\n");   }   ASSERT(numEntries < MAX_ENTRIES);   ptr = endPtr;   numEntries++;   ptr->start = start;   ptr->end = start + size;   ptr->flag = flag;   ptr->data = data;   ptr->name = SaveString(name);   if (start < minAddress) minAddress = start;   if (start > maxAddress) maxAddress = start+size;   /* Report the registery update (PZ) */   CPUPrint("Registering region [%#08lx, %#08lx) for %s.\n", 	    (long)start, (long)(start + size), name);   return 0;}/***************************************************************** * Function for comparing registry entries. Assumes the * entries don't overlap. ****************************************************************/static intentry_compare(const void* ep1, const void* ep2){  Entry *e1 = (Entry*) ep1;  Entry *e2 = (Entry*) ep2;  if (e1->start == e2->start && e1->end == e2->end) return 0;  if (e1->end <= e2->start)                         return -1;  if (e2->end <= e1->start)                         return 1;  ASSERT(0);  return 0; /* keep compiler happy */}static intelem_compare(const void* xp, const void* ep){  VA     x = *(VA *)xp;  Entry* e = (Entry*)ep;  if (e->start <= x && x < e->end) return 0;  if (e->end <= x)                 return 1;  else                             return -1;}/***************************************************************** * Signals that all ranges have been added to the registry. * The registry will be sorted, so that we can use fast binary * search in RegistryIsInRange. ****************************************************************/voidRegistryComplete(void){  ASSERT(!complete);  /* sort registry */  qsort(registry, numEntries, sizeof(Entry), entry_compare);  complete = 1;}/***************************************************************** * Given a virtual address, this procedure determines if it is * in the special range of addresses. These addresses can be  * set to be DATA or FUNCTIONS and the returned flag determines  * which is intended. *****************************************************************/boolRegistryIsInRange(VA addr, void **data, uint *flag){   register Entry *ptr;   VA vAddr;   ASSERT(complete && numEntries > 0);   /* Check cache of last entry */   if ((addr >= lastEntry->start) && (addr < lastEntry->end)) {      /* Found a registered address! */      *flag = lastEntry->flag;      if (*flag == REG_FUNC)         *data = (char *)lastEntry->data;      else         *data = ((char*)lastEntry->data) + (addr - lastEntry->start);      SIM_DEBUG(('b', "BDOOR %lld inRange: 0x%llx (%s) to 0x%x\n",                 (Reg64)CPUVec.CycleCount(0), (Reg64)addr,		 lastEntry->name, *data));      return TRUE;   }      if ((addr < minAddress) || (addr > maxAddress)) {      return FALSE;   }   /* use binary search on registry -- it's sorted */   vAddr = addr;   ptr = bsearch((void*)&vAddr,		 registry, numEntries, sizeof(Entry),		 elem_compare);   if (!ptr) return FALSE; /* not found */   ASSERT(addr >= ptr->start && addr < ptr->end);   /* Found a registered address! */   *flag = ptr->flag;   if (*flag == REG_FUNC)     *data = (char *)ptr->data;   else     *data = ((char*)ptr->data) + (addr - ptr->start);   lastEntry = ptr;   SIM_DEBUG(('b', "BDOOR %lld inRange: 0x%llx (%s) to 0x%x\n",              (Reg64)CPUVec.CycleCount(0), (Reg64)addr,	      lastEntry->name, *data));   return TRUE;}/***************************************************************** * Given a virtual address, this procedure determines the address * that the kernel should use to access it. *****************************************************************/VARegistryReverseMap(void *data){   register Entry *ptr;   register Entry *endPtr = registry + numEntries;#if !(defined(sgi) && defined(_ABIN32))   for (ptr = registry; ptr < endPtr; ptr++) {      int size = ptr->end - ptr->start;      if ((data >= ptr->data) && ((char *)data < (char *)ptr->data+size)) {         return ptr->start + ((char *)data - (char *)ptr->data);      }   }#else   /* Workaround for an SGI compiler bug - The "real" version of this code    * crashes the compiler. */   for (ptr = registry; ; ptr++) {      int size = ptr->end - ptr->start;      if ((data >= ptr->data) && ((char *)data < (char *)ptr->data+size)) {         return ptr->start + ((char *)data - (char *)ptr->data);      }      if ( ptr < endPtr) break;   }#endif   return (VA)0;}voidRegistryDumpEntries(void){   Entry *ptr;   Entry *endPtr = registry + numEntries;   for (ptr = registry; ptr < endPtr; ptr++) {      SIM_DEBUG(('b', "REGISTRY: %#llx - %#llx : (%#llx) : %s (%s)\n",		  (Reg64)ptr->start, (Reg64)ptr->end, (Reg64)ptr->data,		  ptr->name, (ptr->flag == REG_DATA)? "data":"func"));   }}

⌨️ 快捷键说明

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