📄 vm.c
字号:
/* Clear device list info */ dev->next = NULL; dev->pprev = NULL; return(0);}/* Map a device at the specified physical address */int vm_map_device(vm_instance_t *vm,struct vdevice *dev,m_uint64_t base_addr){#if 0 /* Suspend VM activity */ vm_suspend(vm); if (cpu_group_sync_state(vm->cpu_group) == -1) { fprintf(stderr,"VM%u: unable to sync with system CPUs.\n", vm->instance_id); return(-1); }#endif /* Unbind the device if it was already active */ vm_unbind_device(vm,dev); /* Map the device at the new base address and rebuild MTS */ dev->phys_addr = base_addr; vm_bind_device(vm,dev); cpu_group_rebuild_mts(vm->cpu_group);#if 0 vm_resume(vm);#endif return(0);}/* Suspend a VM instance */int vm_suspend(vm_instance_t *vm){ if (vm->status == VM_STATUS_RUNNING) { cpu_group_save_state(vm->cpu_group); cpu_group_set_state(vm->cpu_group,CPU_STATE_SUSPENDED); vm->status = VM_STATUS_SUSPENDED; } return(0);}/* Resume a VM instance */int vm_resume(vm_instance_t *vm){ if (vm->status == VM_STATUS_SUSPENDED) { cpu_group_restore_state(vm->cpu_group); vm->status = VM_STATUS_RUNNING; } return(0);}/* Stop an instance */int vm_stop(vm_instance_t *vm){ cpu_group_stop_all_cpu(vm->cpu_group); vm->status = VM_STATUS_SHUTDOWN; return(0);}/* Monitor an instance periodically */void vm_monitor(vm_instance_t *vm){ while(vm->status != VM_STATUS_SHUTDOWN) usleep(200000);}/* Create a new chunk */static vm_chunk_t *vm_chunk_create(vm_instance_t *vm){ vm_chunk_t *chunk; size_t area_len; if (!(chunk = malloc(sizeof(*chunk)))) return NULL; area_len = VM_CHUNK_AREA_SIZE * VM_PAGE_SIZE; if (!(chunk->area = m_memalign(VM_PAGE_SIZE,area_len))) { free(chunk); return NULL; } chunk->page_alloc = 0; chunk->page_total = VM_CHUNK_AREA_SIZE; chunk->next = vm->chunks; vm->chunks = chunk; return chunk;}/* Free a chunk */static void vm_chunk_free(vm_chunk_t *chunk){ free(chunk->area); free(chunk);}/* Free all chunks used by a VM */static void vm_chunk_free_all(vm_instance_t *vm){ vm_chunk_t *chunk,*next; for(chunk=vm->chunks;chunk;chunk=next) { next = chunk->next; vm_chunk_free(chunk); } vm->chunks = NULL;}/* Allocate an host page */void *vm_alloc_host_page(vm_instance_t *vm){ vm_chunk_t *chunk = vm->chunks; void *ptr; if (!chunk || (chunk->page_alloc == chunk->page_total)) { chunk = vm_chunk_create(vm); if (!chunk) return NULL; } ptr = chunk->area + (chunk->page_alloc * VM_PAGE_SIZE); chunk->page_alloc++; return(ptr);}/* Free resources used by a ghost image */static void vm_ghost_image_free(vm_ghost_image_t *img){ if (img) { if (img->fd != -1) { close(img->fd); if (img->area_ptr != NULL) munmap(img->area_ptr,img->file_size); } free(img->filename); free(img); }}/* Find a specified ghost image in the pool */static vm_ghost_image_t *vm_ghost_image_find(char *filename){ vm_ghost_image_t *img; for(img=vm_ghost_pool;img;img=img->next) if (!strcmp(img->filename,filename)) return img; return NULL;}/* Load a new ghost image */static vm_ghost_image_t *vm_ghost_image_load(char *filename){ vm_ghost_image_t *img; if (!(img = calloc(1,sizeof(*img)))) return NULL; img->fd = -1; if (!(img->filename = strdup(filename))) { vm_ghost_image_free(img); return NULL; } img->fd = memzone_open_file(img->filename,&img->area_ptr,&img->file_size); if (img->fd == -1) { vm_ghost_image_free(img); return NULL; } m_log("GHOST","loaded ghost image %s (fd=%d) at addr=%p (size=0x%llx)\n", img->filename,img->fd,img->area_ptr,(long long)img->file_size); return img;}/* Get a ghost image */int vm_ghost_image_get(char *filename,u_char **ptr,int *fd){ vm_ghost_image_t *img; VM_GLOCK(); /* Do we already have this image in the pool ? */ if ((img = vm_ghost_image_find(filename)) != NULL) { img->ref_count++; *ptr = img->area_ptr; *fd = img->fd; VM_GUNLOCK(); return(0); } /* Load the ghost file and add it into the pool */ if (!(img = vm_ghost_image_load(filename))) { VM_GUNLOCK(); fprintf(stderr,"Unable to load ghost image %s\n",filename); return(-1); } img->ref_count = 1; *ptr = img->area_ptr; *fd = img->fd; img->next = vm_ghost_pool; vm_ghost_pool = img; VM_GUNLOCK(); return(0);}/* Release a ghost image */int vm_ghost_image_release(int fd){ vm_ghost_image_t **img,*next; VM_GLOCK(); for(img=&vm_ghost_pool;*img;img=&(*img)->next) { if ((*img)->fd == fd) { assert((*img)->ref_count > 0); (*img)->ref_count--; if ((*img)->ref_count == 0) { m_log("GHOST","unloaded ghost image %s (fd=%d) at " "addr=%p (size=0x%llx)\n", (*img)->filename,(*img)->fd,(*img)->area_ptr, (long long)(*img)->file_size); next = (*img)->next; vm_ghost_image_free(*img); *img = next; } VM_GUNLOCK(); return(0); } } VM_GUNLOCK(); return(-1);}/* Open a VM file and map it in memory */int vm_mmap_open_file(vm_instance_t *vm,char *name, u_char **ptr,off_t *fsize){ char *filename; int fd; if (!(filename = vm_build_filename(vm,name))) { fprintf(stderr,"vm_mmap_open_file: unable to create filename (%s)\n", name); return(-1); } if ((fd = memzone_open_file(filename,ptr,fsize)) == -1) fprintf(stderr,"vm_mmap_open_file: unable to open file '%s' (%s)\n", filename,strerror(errno)); free(filename); return(fd);}/* Open/Create a VM file and map it in memory */int vm_mmap_create_file(vm_instance_t *vm,char *name,size_t len,u_char **ptr){ char *filename; int fd; if (!(filename = vm_build_filename(vm,name))) { fprintf(stderr,"vm_mmap_create_file: unable to create filename (%s)\n", name); return(-1); } if ((fd = memzone_create_file(filename,len,ptr)) == -1) fprintf(stderr,"vm_mmap_create_file: unable to open file '%s' (%s)\n", filename,strerror(errno)); free(filename); return(fd);}/* Close a memory mapped file */int vm_mmap_close_file(int fd,u_char *ptr,size_t len){ if (ptr != NULL) munmap(ptr,len); if (fd != -1) close(fd); return(0);}/* Save the Cisco IOS configuration from NVRAM */int vm_ios_save_config(vm_instance_t *vm){ char *output; int res; if (!(output = vm_build_filename(vm,"ios_cfg.txt"))) return(-1); res = vm_nvram_extract_config(vm,output); free(output); return(res);}/* Set Cisco IOS image to use */int vm_ios_set_image(vm_instance_t *vm,char *ios_image){ char *str; if (!(str = strdup(ios_image))) return(-1); if (vm->ios_image != NULL) { free(vm->ios_image); vm->ios_image = NULL; } vm->ios_image = str; return(0);}/* Unset a Cisco IOS configuration file */void vm_ios_unset_config(vm_instance_t *vm){ if (vm->ios_config != NULL) { free(vm->ios_config); vm->ios_config = NULL; }}/* Set Cisco IOS configuration file to use */int vm_ios_set_config(vm_instance_t *vm,char *ios_config){ char *str; if (!(str = strdup(ios_config))) return(-1); vm_ios_unset_config(vm); vm->ios_config = str; return(0); }/* Extract IOS configuration from NVRAM and write it to a file */int vm_nvram_extract_config(vm_instance_t *vm,char *filename){ u_char *cfg_buffer; ssize_t cfg_len; FILE *fd; if (!vm->platform->nvram_extract_config) return(-1); /* Extract the IOS configuration */ if (((cfg_len = vm->platform->nvram_extract_config(vm,&cfg_buffer)) < 0) || (cfg_buffer == NULL)) return(-1); /* Write configuration to the specified filename */ if (!(fd = fopen(filename,"w"))) { vm_error(vm,"unable to create file '%s'\n",filename); free(cfg_buffer); return(-1); } fwrite(cfg_buffer,cfg_len,1,fd); fclose(fd); free(cfg_buffer); return(0);}/* Read an IOS configuraton from a file and push it to NVRAM */int vm_nvram_push_config(vm_instance_t *vm,char *filename){ u_char *cfg_buffer; ssize_t len; int res; if (!vm->platform->nvram_push_config) return(-1); /* Read configuration */ if (((len = m_read_file(filename,&cfg_buffer)) <= 0) || !cfg_buffer) return(-1); /* Push it! */ res = vm->platform->nvram_push_config(vm,cfg_buffer,len); free(cfg_buffer); return(res);}/* Save general VM configuration into the specified file */void vm_save_config(vm_instance_t *vm,FILE *fd){ fprintf(fd,"vm create %s %u %s\n", vm->name,vm->instance_id,vm->platform->name); if (vm->ios_image) fprintf(fd,"vm set_ios %s %s\n",vm->name,vm->ios_image); fprintf(fd,"vm set_ram %s %u\n",vm->name,vm->ram_size); fprintf(fd,"vm set_nvram %s %u\n",vm->name,vm->nvram_size); fprintf(fd,"vm set_ram_mmap %s %u\n",vm->name,vm->ram_mmap); fprintf(fd,"vm set_clock_divisor %s %u\n",vm->name,vm->clock_divisor); fprintf(fd,"vm set_conf_reg %s 0x%4.4x\n",vm->name,vm->conf_reg_setup); if (vm->vtty_con_type == VTTY_TYPE_TCP) fprintf(fd,"vm set_con_tcp_port %s %d\n",vm->name,vm->vtty_con_tcp_port); if (vm->vtty_aux_type == VTTY_TYPE_TCP) fprintf(fd,"vm set_aux_tcp_port %s %d\n",vm->name,vm->vtty_aux_tcp_port); /* Save slot config */ vm_slot_save_all_config(vm,fd);}/* Find a platform */vm_platform_t *vm_platform_find(char *name){ struct vm_platform_list *p; for(p=vm_platforms;p;p=p->next) if (!strcmp(p->platform->name,name)) return(p->platform); return NULL;}/* Find a platform given its CLI name */vm_platform_t *vm_platform_find_cli_name(char *name){ struct vm_platform_list *p; for(p=vm_platforms;p;p=p->next) if (!strcmp(p->platform->cli_name,name)) return(p->platform); return NULL;}/* Register a platform */int vm_platform_register(vm_platform_t *platform){ struct vm_platform_list *p; if (vm_platform_find(platform->name) != NULL) { fprintf(stderr,"vm_platform_register: platform '%s' already exists.\n", platform->name); return(-1); } if (!(p = malloc(sizeof(*p)))) { fprintf(stderr,"vm_platform_register: unable to record platform.\n"); return(-1); } p->platform = platform; p->next = vm_platforms; vm_platforms = p; return(0);}/* Create an instance of the specified type */vm_instance_t *vm_create_instance(char *name,int instance_id,char *type){ vm_platform_t *platform; vm_instance_t *vm = NULL; if (!(platform = vm_platform_find(type))) { fprintf(stderr,"VM %s: unknown platform '%s'\n",name,type); goto error; } /* Create a generic VM instance */ if (!(vm = vm_create(name,instance_id,platform))) goto error; /* Initialize specific parts */ if (vm->platform->create_instance(vm) == -1) goto error; return vm; error: fprintf(stderr,"VM %s: unable to create instance!\n",name); vm_free(vm); return NULL;}/* Free resources used by a VM instance */static int vm_reg_delete_instance(void *data,void *arg){ vm_instance_t *vm = data; return(vm->platform->delete_instance(vm));}/* Delete a VM instance */int vm_delete_instance(char *name){ return(registry_delete_if_unused(name,OBJ_TYPE_VM, vm_reg_delete_instance,NULL));}/* Initialize a VM instance */int vm_init_instance(vm_instance_t *vm){ return(vm->platform->init_instance(vm));}/* Stop a VM instance */int vm_stop_instance(vm_instance_t *vm){ return(vm->platform->stop_instance(vm));}/* Delete all VM instances */int vm_delete_all_instances(void){ return(registry_delete_type(OBJ_TYPE_VM,vm_reg_delete_instance,NULL));}/* Save configurations of all VM instances */static void vm_reg_save_config(registry_entry_t *entry,void *opt,int *err){ vm_instance_t *vm = entry->data; FILE *fd = opt; vm_save_config(vm,fd); /* Save specific platform options */ if (vm->platform->save_config != NULL) vm->platform->save_config(vm,fd);}/* Save all VM configs */int vm_save_config_all(FILE *fd){ registry_foreach_type(OBJ_TYPE_VM,vm_reg_save_config,fd,NULL); return(0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -