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

📄 vm.c

📁 思科路由器仿真器,用来仿7200系列得,可以在电脑上模拟路由器
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Cisco router simulation platform. * Copyright (c) 2005,2006 Christophe Fillot (cf@utc.fr) * * Virtual machine abstraction. */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <errno.h>#include <fcntl.h>#include <sys/types.h>#include <assert.h>#include "registry.h"#include "device.h"#include "pci_dev.h"#include "pci_io.h"#include "cpu.h"#include "mips64_jit.h"#include "vm.h"#include "dev_vtty.h"#include MIPS64_ARCH_INC_FILE#define DEBUG_VM  1#define VM_GLOCK()   pthread_mutex_lock(&vm_global_lock)#define VM_GUNLOCK() pthread_mutex_unlock(&vm_global_lock)/* Type of VM file naming (0=use VM name, 1=use instance ID) */int vm_file_naming_type = 0;/* Platform list */static struct vm_platform_list *vm_platforms = NULL;/* Pool of ghost images */static vm_ghost_image_t *vm_ghost_pool = NULL;/* Global lock for VM manipulation */static pthread_mutex_t vm_global_lock = PTHREAD_MUTEX_INITIALIZER;/* Free all chunks used by a VM */static void vm_chunk_free_all(vm_instance_t *vm);/* Initialize a VM object */void vm_object_init(vm_obj_t *obj){   memset(obj,0,sizeof(*obj));}/* Add a VM object to an instance */void vm_object_add(vm_instance_t *vm,vm_obj_t *obj){   obj->next = vm->vm_object_list;   obj->pprev = &vm->vm_object_list;   if (vm->vm_object_list)      vm->vm_object_list->pprev = &obj->next;      vm->vm_object_list = obj;}/* Remove a VM object from an instance */void vm_object_remove(vm_instance_t *vm,vm_obj_t *obj){   if (obj->next)      obj->next->pprev = obj->pprev;   *(obj->pprev) = obj->next;   obj->shutdown(vm,obj->data);}/* Find an object given its name */vm_obj_t *vm_object_find(vm_instance_t *vm,char *name){   vm_obj_t *obj;   for(obj=vm->vm_object_list;obj;obj=obj->next)      if (!strcmp(obj->name,name))         return obj;   return NULL;}/* Check that a mandatory object is present */int vm_object_check(vm_instance_t *vm,char *name){   return(vm_object_find(vm,name) ? 0 : -1);}/* Shut down all objects of an instance */void vm_object_free_list(vm_instance_t *vm){   vm_obj_t *obj,*next;   for(obj=vm->vm_object_list;obj;obj=next) {      next = obj->next;      if (obj->shutdown != NULL) {#if DEBUG_VM         vm_log(vm,"VM_OBJECT","Shutdown of object \"%s\"\n",obj->name);#endif         obj->shutdown(vm,obj->data);      }   }   vm->vm_object_list = NULL;}/* Rebuild the object list pointers */static void vm_object_rebuild_list(vm_instance_t *vm){   vm_obj_t **obj;   for(obj=&vm->vm_object_list;*obj;obj=&(*obj)->next)      (*obj)->pprev = obj;}/* Dump the object list of an instance */void vm_object_dump(vm_instance_t *vm){   vm_obj_t *obj;   printf("VM \"%s\" (%u) object list:\n",vm->name,vm->instance_id);      for(obj=vm->vm_object_list;obj;obj=obj->next) {      printf("  - %-15s [data=%p]\n",obj->name,obj->data);   }   printf("\n");}/* Get VM type */char *vm_get_type(vm_instance_t *vm){   return vm->platform->name;}/* Get log name */static char *vm_get_log_name(vm_instance_t *vm){   if (vm->platform->log_name != NULL)      return vm->platform->log_name;   /* default value */   return "VM";}/* Get MAC address MSB */u_int vm_get_mac_addr_msb(vm_instance_t *vm){   if (vm->platform->get_mac_addr_msb != NULL)      return(vm->platform->get_mac_addr_msb());      /* default value */   return(0xC6);}/* Generate a filename for use by the instance */char *vm_build_filename(vm_instance_t *vm,char *name){   char *filename,*machine;   machine = vm_get_type(vm);   switch(vm_file_naming_type) {      case 1:         filename = dyn_sprintf("%s_i%u_%s",machine,vm->instance_id,name);         break;      case 0:      default:         filename = dyn_sprintf("%s_%s_%s",machine,vm->name,name);         break;   }   assert(filename != NULL);   return filename;}/* Erase lock file */void vm_release_lock(vm_instance_t *vm,int erase){   if (vm->lock_fd != NULL) {      fclose(vm->lock_fd);      vm->lock_fd = NULL;   }      if (vm->lock_file != NULL) {      if (erase)         unlink(vm->lock_file);      free(vm->lock_file);      vm->lock_file = NULL;   }}/* Check that an instance lock file doesn't already exist */int vm_get_lock(vm_instance_t *vm){   char pid_str[32];   struct flock lock;   vm->lock_file = vm_build_filename(vm,"lock");   if (!(vm->lock_fd = fopen(vm->lock_file,"w"))) {      fprintf(stderr,"Unable to create lock file \"%s\".\n",vm->lock_file);      return(-1);   }      memset(&lock,0,sizeof(lock));   lock.l_type   = F_WRLCK;   lock.l_whence = SEEK_SET;   lock.l_start  = 0;   lock.l_len    = 0;      if (fcntl(fileno(vm->lock_fd),F_SETLK,&lock) == -1) {      if (fcntl(fileno(vm->lock_fd),F_GETLK,&lock) == 0) {         snprintf(pid_str,sizeof(pid_str),"%ld",(long)lock.l_pid);      } else {         strcpy(pid_str,"unknown");      }      fprintf(stderr,              "\nAn emulator instance (PID %s) is already running with "              "identifier %u.\n"              "If this is not the case, please erase file \"%s\".\n\n",              pid_str,vm->instance_id,vm->lock_file);      vm_release_lock(vm,FALSE);      return(-1);   }   /* write the emulator PID */   fprintf(vm->lock_fd,"%ld\n",(u_long)getpid());   return(0);}/* Log a message */void vm_flog(vm_instance_t *vm,char *module,char *format,va_list ap){   if (vm->log_fd)      m_flog(vm->log_fd,module,format,ap);}/* Log a message */void vm_log(vm_instance_t *vm,char *module,char *format,...){    va_list ap;   if (vm->log_fd) {      va_start(ap,format);      vm_flog(vm,module,format,ap);      va_end(ap);   }}/* Close the log file */int vm_close_log(vm_instance_t *vm){   if (vm->log_fd)      fclose(vm->log_fd);   free(vm->log_file);   vm->log_file = NULL;   vm->log_fd = NULL;   return(0);}/* Create the log file */int vm_create_log(vm_instance_t *vm){   if (vm->log_file_enabled) {      vm_close_log(vm);      if (!(vm->log_file = vm_build_filename(vm,"log.txt")))         return(-1);      if (!(vm->log_fd = fopen(vm->log_file,"w"))) {         fprintf(stderr,"VM %s: unable to create log file '%s'\n",                 vm->name,vm->log_file);         free(vm->log_file);         vm->log_file = NULL;         return(-1);      }   }   return(0);}/* Error message */void vm_error(vm_instance_t *vm,char *format,...){    char buffer[2048];   va_list ap;   va_start(ap,format);   vsnprintf(buffer,sizeof(buffer),format,ap);   va_end(ap);   fprintf(stderr,"%s '%s': %s",vm_get_log_name(vm),vm->name,buffer);}/* Create a new VM instance */static vm_instance_t *vm_create(char *name,int instance_id,                                vm_platform_t *platform){   vm_instance_t *vm;   if (!(vm = malloc(sizeof(*vm)))) {      fprintf(stderr,"VM %s: unable to create new instance!\n",name);      return NULL;   }      memset(vm,0,sizeof(*vm));   if (!(vm->name = strdup(name))) {      fprintf(stderr,"VM %s: unable to store instance name!\n",name);      goto err_name;   }   vm->instance_id          = instance_id;   vm->platform             = platform;   vm->status               = VM_STATUS_HALTED;   vm->jit_use              = JIT_SUPPORT;   vm->exec_blk_direct_jump = TRUE;   vm->vtty_con_type        = VTTY_TYPE_TERM;   vm->vtty_aux_type        = VTTY_TYPE_NONE;   vm->timer_irq_check_itv  = VM_TIMER_IRQ_CHECK_ITV;   vm->log_file_enabled     = TRUE;   vm->rommon_vars.filename = vm_build_filename(vm,"rommon_vars");   if (!vm->rommon_vars.filename)      goto err_rommon;   /* XXX */   rommon_load_file(&vm->rommon_vars);   /* create lock file */   if (vm_get_lock(vm) == -1)      goto err_lock;      /* create log file */   if (vm_create_log(vm) == -1)      goto err_log;   if (registry_add(vm->name,OBJ_TYPE_VM,vm) == -1) {      fprintf(stderr,"VM: Unable to store instance '%s' in registry!\n",              vm->name);      goto err_reg_add;   }   return vm; err_reg_add:   vm_close_log(vm); err_log:   free(vm->lock_file); err_lock:   free(vm->rommon_vars.filename); err_rommon:   free(vm->name); err_name:   free(vm);   return NULL;}/*  * Shutdown hardware resources used by a VM. * The CPU must have been stopped. */int vm_hardware_shutdown(vm_instance_t *vm){     int i;   if ((vm->status == VM_STATUS_HALTED) || !vm->cpu_group) {      vm_log(vm,"VM","trying to shutdown an inactive VM.\n");      return(-1);   }   vm_log(vm,"VM","shutdown procedure engaged.\n");   /* Mark the VM as halted */   vm->status = VM_STATUS_HALTED;   /* Free the object list */   vm_object_free_list(vm);   /* Free resources used by PCI busses */   vm_log(vm,"VM","removing PCI busses.\n");   pci_io_data_remove(vm,vm->pci_io_space);   pci_bus_remove(vm->pci_bus[0]);   pci_bus_remove(vm->pci_bus[1]);   vm->pci_bus[0] = vm->pci_bus[1] = NULL;   /* Free the PCI bus pool */   for(i=0;i<VM_PCI_POOL_SIZE;i++) {      if (vm->pci_bus_pool[i] != NULL) {         pci_bus_remove(vm->pci_bus_pool[i]);         vm->pci_bus_pool[i] = NULL;      }   }        /* Remove the IRQ routing vectors */   vm->set_irq = NULL;   vm->clear_irq = NULL;   /* Delete the VTTY for Console and AUX ports */      vm_log(vm,"VM","deleting VTTY.\n");   vm_delete_vtty(vm);   /* Delete system CPU group */   vm_log(vm,"VM","deleting system CPUs.\n");   cpu_group_delete(vm->cpu_group);   vm->cpu_group = NULL;   vm->boot_cpu = NULL;   vm_log(vm,"VM","shutdown procedure completed.\n");   return(0);}/* Free resources used by a VM */void vm_free(vm_instance_t *vm){   if (vm != NULL) {      /* Free hardware resources */      vm_hardware_shutdown(vm);      /* Close log file */      vm_close_log(vm);      /* Remove the lock file */      vm_release_lock(vm,TRUE);      /* Free all chunks */      vm_chunk_free_all(vm);      /* Free various elements */      free(vm->rommon_vars.filename);      free(vm->ghost_ram_filename);      free(vm->sym_filename);      free(vm->ios_image);      free(vm->ios_config);      free(vm->rom_filename);      free(vm->name);      free(vm);   }}/* Get an instance given a name */vm_instance_t *vm_acquire(char *name){   return(registry_find(name,OBJ_TYPE_VM));}/* Release a VM (decrement reference count) */int vm_release(vm_instance_t *vm){   return(registry_unref(vm->name,OBJ_TYPE_VM));}/* Initialize RAM */int vm_ram_init(vm_instance_t *vm,m_uint64_t paddr){   m_uint32_t len;   len = vm->ram_size * 1048576;   if (vm->ghost_status == VM_GHOST_RAM_USE) {      return(dev_ram_ghost_init(vm,"ram",vm->sparse_mem,vm->ghost_ram_filename,                                paddr,len));   }   return(dev_ram_init(vm,"ram",vm->ram_mmap,                       (vm->ghost_status != VM_GHOST_RAM_GENERATE),                       vm->ghost_ram_filename,vm->sparse_mem,paddr,len));}/* Initialize VTTY */int vm_init_vtty(vm_instance_t *vm){   /* Create Console and AUX ports */   vm->vtty_con = vtty_create(vm,"Console port",                              vm->vtty_con_type,vm->vtty_con_tcp_port,                              &vm->vtty_con_serial_option);   vm->vtty_aux = vtty_create(vm,"AUX port",                              vm->vtty_aux_type,vm->vtty_aux_tcp_port,                              &vm->vtty_aux_serial_option);   return(0);}/* Delete VTTY */void vm_delete_vtty(vm_instance_t *vm){   vtty_delete(vm->vtty_con);   vtty_delete(vm->vtty_aux);   vm->vtty_con = vm->vtty_aux = NULL;}/* Bind a device to a virtual machine */int vm_bind_device(vm_instance_t *vm,struct vdevice *dev){   struct vdevice **cur;   u_int i;   /*     * Add this device to the device array. The index in the device array    * is used by the MTS subsystem.    */   for(i=0;i<VM_DEVICE_MAX;i++)      if (!vm->dev_array[i])         break;   if (i == VM_DEVICE_MAX) {      fprintf(stderr,"VM%u: vm_bind_device: device table full.\n",              vm->instance_id);      return(-1);   }   vm->dev_array[i] = dev;   dev->id = i;   /*    * Add it to the linked-list (devices are ordered by physical addresses).    */   for(cur=&vm->dev_list;*cur;cur=&(*cur)->next)      if ((*cur)->phys_addr > dev->phys_addr)         break;   dev->next = *cur;   if (*cur) (*cur)->pprev = &dev->next;   dev->pprev = cur;   *cur = dev;   return(0);}/* Unbind a device from a virtual machine */int vm_unbind_device(vm_instance_t *vm,struct vdevice *dev){   u_int i;   if (!dev || !dev->pprev)      return(-1);   /* Remove the device from the linked list */   if (dev->next)      dev->next->pprev = dev->pprev;   *(dev->pprev) = dev->next;   /* Remove the device from the device array */   for(i=0;i<VM_DEVICE_MAX;i++)      if (vm->dev_array[i] == dev) {         vm->dev_array[i] = NULL;         break;      }

⌨️ 快捷键说明

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