/[dynamips]/trunk/vm.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /trunk/vm.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

upstream/dynamips-0.2.6-RC5/vm.c revision 6 by dpavlin, Sat Oct 6 16:09:07 2007 UTC upstream/dynamips-0.2.8-RC1/vm.c revision 11 by dpavlin, Sat Oct 6 16:33:40 2007 UTC
# Line 1  Line 1 
1  /*  /*
2   * Cisco 7200 (Predator) simulation platform.   * Cisco router simulation platform.
3   * Copyright (c) 2005,2006 Christophe Fillot (cf@utc.fr)   * Copyright (c) 2005,2006 Christophe Fillot (cf@utc.fr)
4   *   *
5   * Virtual machine abstraction.   * Virtual machine abstraction.
  *  
  * TODO: IRQ Routing.  
6   */   */
7    
8  #include <stdio.h>  #include <stdio.h>
# Line 20  Line 18 
18  #include "device.h"  #include "device.h"
19  #include "pci_dev.h"  #include "pci_dev.h"
20  #include "pci_io.h"  #include "pci_io.h"
21    #include "cpu.h"
22    #include "mips64_jit.h"
23  #include "vm.h"  #include "vm.h"
24  #include "dev_vtty.h"  #include "dev_vtty.h"
25    
26  #include ARCH_INC_FILE  #include MIPS64_ARCH_INC_FILE
27    
28  #define DEBUG_VM  1  #define DEBUG_VM  1
29    
30    #define VM_GLOCK()   pthread_mutex_lock(&vm_global_lock)
31    #define VM_GUNLOCK() pthread_mutex_unlock(&vm_global_lock)
32    
33  /* Type of VM file naming (0=use VM name, 1=use instance ID) */  /* Type of VM file naming (0=use VM name, 1=use instance ID) */
34  int vm_file_naming_type = 0;  int vm_file_naming_type = 0;
35    
36    /* Platform list */
37    static struct vm_platform_list *vm_platforms = NULL;
38    
39    /* Pool of ghost images */
40    static vm_ghost_image_t *vm_ghost_pool = NULL;
41    
42    /* Global lock for VM manipulation */
43    static pthread_mutex_t vm_global_lock = PTHREAD_MUTEX_INITIALIZER;
44    
45    /* Free all chunks used by a VM */
46    static void vm_chunk_free_all(vm_instance_t *vm);
47    
48  /* Initialize a VM object */  /* Initialize a VM object */
49  void vm_object_init(vm_obj_t *obj)  void vm_object_init(vm_obj_t *obj)
50  {  {
# Line 95  void vm_object_free_list(vm_instance_t * Line 110  void vm_object_free_list(vm_instance_t *
110     vm->vm_object_list = NULL;     vm->vm_object_list = NULL;
111  }  }
112    
113    /* Rebuild the object list pointers */
114    static void vm_object_rebuild_list(vm_instance_t *vm)
115    {
116       vm_obj_t **obj;
117    
118       for(obj=&vm->vm_object_list;*obj;obj=&(*obj)->next)
119          (*obj)->pprev = obj;
120    }
121    
122  /* Dump the object list of an instance */  /* Dump the object list of an instance */
123  void vm_object_dump(vm_instance_t *vm)  void vm_object_dump(vm_instance_t *vm)
124  {  {
# Line 112  void vm_object_dump(vm_instance_t *vm) Line 136  void vm_object_dump(vm_instance_t *vm)
136  /* Get VM type */  /* Get VM type */
137  char *vm_get_type(vm_instance_t *vm)  char *vm_get_type(vm_instance_t *vm)
138  {  {
139     char *machine;     return vm->platform->name;
   
    switch(vm->type) {  
       case VM_TYPE_C3600:  
          machine = "c3600";  
          break;  
       case VM_TYPE_C7200:  
          machine = "c7200";  
          break;  
       case VM_TYPE_C2691:  
          machine = "c2691";  
          break;  
       case VM_TYPE_C3725:  
          machine = "c3725";  
          break;  
      case VM_TYPE_C3745:  
          machine = "c3745";  
          break;  
       default:  
          machine = "unknown";  
          break;  
    }  
   
    return machine;  
140  }  }
141    
142  /* Get platform type */  /* Get log name */
143  char *vm_get_platform_type(vm_instance_t *vm)  static char *vm_get_log_name(vm_instance_t *vm)
144  {  {
145     char *machine;     if (vm->platform->log_name != NULL)
146          return vm->platform->log_name;
147    
148     switch(vm->type) {     /* default value */
149        case VM_TYPE_C3600:     return "VM";
          machine = "C3600";  
          break;  
       case VM_TYPE_C7200:  
          machine = "C7200";  
          break;      
       case VM_TYPE_C2691:  
          machine = "C2691";  
          break;  
       case VM_TYPE_C3725:  
          machine = "C3725";  
          break;  
       case VM_TYPE_C3745:  
          machine = "C3745";  
          break;  
       default:  
          machine = "VM";  
          break;  
    }  
   
    return machine;  
150  }  }
151    
152  /* Get MAC address MSB */  /* Get MAC address MSB */
153  u_int vm_get_mac_addr_msb(vm_instance_t *vm)  u_int vm_get_mac_addr_msb(vm_instance_t *vm)
154  {  {
155     switch(vm->type) {     if (vm->platform->get_mac_addr_msb != NULL)
156        case VM_TYPE_C3600:        return(vm->platform->get_mac_addr_msb());
157           return(0xCC);    
158       /* default value */
159        case VM_TYPE_C7200:     return(0xC6);
          return(0xCA);  
   
       case VM_TYPE_C2691:  
          return(0xC0);  
   
       case VM_TYPE_C3725:  
          return(0xC2);  
   
       case VM_TYPE_C3745:  
          return(0xC4);  
   
       default:  
          return(0xC6);  
    }  
160  }  }
161    
162  /* Generate a filename for use by the instance */  /* Generate a filename for use by the instance */
# Line 280  void vm_log(vm_instance_t *vm,char *modu Line 248  void vm_log(vm_instance_t *vm,char *modu
248  {  {
249     va_list ap;     va_list ap;
250    
251     va_start(ap,format);     if (vm->log_fd) {
252     vm_flog(vm,module,format,ap);        va_start(ap,format);
253     va_end(ap);        vm_flog(vm,module,format,ap);
254          va_end(ap);
255       }
256  }  }
257    
258  /* Close the log file */  /* Close the log file */
# Line 301  int vm_close_log(vm_instance_t *vm) Line 271  int vm_close_log(vm_instance_t *vm)
271  /* Create the log file */  /* Create the log file */
272  int vm_create_log(vm_instance_t *vm)  int vm_create_log(vm_instance_t *vm)
273  {  {
274     vm_close_log(vm);     if (vm->log_file_enabled) {
275          vm_close_log(vm);
276    
277     if (!(vm->log_file = vm_build_filename(vm,"log.txt")))        if (!(vm->log_file = vm_build_filename(vm,"log.txt")))
278        return(-1);           return(-1);
279    
280     if (!(vm->log_fd = fopen(vm->log_file,"w"))) {        if (!(vm->log_fd = fopen(vm->log_file,"w"))) {
281        fprintf(stderr,"VM %s: unable to create log file '%s'\n",           fprintf(stderr,"VM %s: unable to create log file '%s'\n",
282                vm->name,vm->log_file);                   vm->name,vm->log_file);
283        free(vm->log_file);           free(vm->log_file);
284        vm->log_file = NULL;           vm->log_file = NULL;
285        return(-1);           return(-1);
286          }
287     }     }
288    
289     return(0);     return(0);
# Line 327  void vm_error(vm_instance_t *vm,char *fo Line 299  void vm_error(vm_instance_t *vm,char *fo
299     vsnprintf(buffer,sizeof(buffer),format,ap);     vsnprintf(buffer,sizeof(buffer),format,ap);
300     va_end(ap);     va_end(ap);
301    
302     fprintf(stderr,"%s '%s': %s",vm_get_platform_type(vm),vm->name,buffer);     fprintf(stderr,"%s '%s': %s",vm_get_log_name(vm),vm->name,buffer);
303  }  }
304    
305  /* Create a new VM instance */  /* Create a new VM instance */
306  vm_instance_t *vm_create(char *name,int instance_id,int machine_type)  static vm_instance_t *vm_create(char *name,int instance_id,
307                                    vm_platform_t *platform)
308  {  {
309     vm_instance_t *vm;     vm_instance_t *vm;
310    
# Line 341  vm_instance_t *vm_create(char *name,int Line 314  vm_instance_t *vm_create(char *name,int
314     }     }
315        
316     memset(vm,0,sizeof(*vm));     memset(vm,0,sizeof(*vm));
    vm->instance_id    = instance_id;  
    vm->type           = machine_type;  
    vm->status         = VM_STATUS_HALTED;  
    vm->jit_use        = JIT_SUPPORT;  
    vm->vtty_con_type  = VTTY_TYPE_TERM;  
    vm->vtty_aux_type  = VTTY_TYPE_NONE;  
    vm->timer_irq_check_itv = VM_TIMER_IRQ_CHECK_ITV;  
317    
318     if (!(vm->name = strdup(name))) {     if (!(vm->name = strdup(name))) {
319        fprintf(stderr,"VM %s: unable to store instance name!\n",name);        fprintf(stderr,"VM %s: unable to store instance name!\n",name);
320        goto err_name;        goto err_name;
321     }     }
322    
323       vm->instance_id          = instance_id;
324       vm->platform             = platform;
325       vm->status               = VM_STATUS_HALTED;
326       vm->jit_use              = JIT_SUPPORT;
327       vm->exec_blk_direct_jump = TRUE;
328       vm->vtty_con_type        = VTTY_TYPE_TERM;
329       vm->vtty_aux_type        = VTTY_TYPE_NONE;
330       vm->timer_irq_check_itv  = VM_TIMER_IRQ_CHECK_ITV;
331       vm->log_file_enabled     = TRUE;
332       vm->rommon_vars.filename = vm_build_filename(vm,"rommon_vars");
333    
334       if (!vm->rommon_vars.filename)
335          goto err_rommon;
336    
337       /* XXX */
338       rommon_load_file(&vm->rommon_vars);
339    
340     /* create lock file */     /* create lock file */
341     if (vm_get_lock(vm) == -1)     if (vm_get_lock(vm) == -1)
342        goto err_lock;        goto err_lock;
# Line 375  vm_instance_t *vm_create(char *name,int Line 358  vm_instance_t *vm_create(char *name,int
358   err_log:   err_log:
359     free(vm->lock_file);     free(vm->lock_file);
360   err_lock:   err_lock:
361       free(vm->rommon_vars.filename);
362     err_rommon:
363     free(vm->name);     free(vm->name);
364   err_name:   err_name:
365     free(vm);     free(vm);
# Line 399  int vm_hardware_shutdown(vm_instance_t * Line 384  int vm_hardware_shutdown(vm_instance_t *
384     /* Mark the VM as halted */     /* Mark the VM as halted */
385     vm->status = VM_STATUS_HALTED;     vm->status = VM_STATUS_HALTED;
386    
    /* Disable NVRAM operations */  
    vm->nvram_extract_config = NULL;  
    vm->nvram_push_config = NULL;  
   
387     /* Free the object list */     /* Free the object list */
388     vm_object_free_list(vm);     vm_object_free_list(vm);
389    
# Line 421  int vm_hardware_shutdown(vm_instance_t * Line 402  int vm_hardware_shutdown(vm_instance_t *
402        }        }
403     }         }    
404    
405       /* Remove the IRQ routing vectors */
406       vm->set_irq = NULL;
407       vm->clear_irq = NULL;
408    
409     /* Delete the VTTY for Console and AUX ports */       /* Delete the VTTY for Console and AUX ports */  
410     vm_log(vm,"VM","deleting VTTY.\n");     vm_log(vm,"VM","deleting VTTY.\n");
411     vm_delete_vtty(vm);     vm_delete_vtty(vm);
# Line 448  void vm_free(vm_instance_t *vm) Line 433  void vm_free(vm_instance_t *vm)
433        /* Remove the lock file */        /* Remove the lock file */
434        vm_release_lock(vm,TRUE);        vm_release_lock(vm,TRUE);
435    
436          /* Free all chunks */
437          vm_chunk_free_all(vm);
438    
439        /* Free various elements */        /* Free various elements */
440          free(vm->rommon_vars.filename);
441        free(vm->ghost_ram_filename);        free(vm->ghost_ram_filename);
442        free(vm->sym_filename);        free(vm->sym_filename);
443        free(vm->ios_image);        free(vm->ios_image);
# Line 478  int vm_ram_init(vm_instance_t *vm,m_uint Line 467  int vm_ram_init(vm_instance_t *vm,m_uint
467    
468     len = vm->ram_size * 1048576;     len = vm->ram_size * 1048576;
469    
470     if (vm->ghost_status == VM_GHOST_RAM_USE)     if (vm->ghost_status == VM_GHOST_RAM_USE) {
471        return(dev_ram_ghost_init(vm,"ram",vm->ghost_ram_filename,paddr,len));        return(dev_ram_ghost_init(vm,"ram",vm->sparse_mem,vm->ghost_ram_filename,
472                                    paddr,len));
473       }
474    
475     return(dev_ram_init(vm,"ram",vm->ram_mmap,     return(dev_ram_init(vm,"ram",vm->ram_mmap,
476                         (vm->ghost_status != VM_GHOST_RAM_GENERATE),                         (vm->ghost_status != VM_GHOST_RAM_GENERATE),
477                         vm->ghost_ram_filename,paddr,len));                         vm->ghost_ram_filename,vm->sparse_mem,paddr,len));
478  }  }
479    
480  /* Initialize VTTY */  /* Initialize VTTY */
# Line 518  int vm_bind_device(vm_instance_t *vm,str Line 509  int vm_bind_device(vm_instance_t *vm,str
509      * Add this device to the device array. The index in the device array      * Add this device to the device array. The index in the device array
510      * is used by the MTS subsystem.      * is used by the MTS subsystem.
511      */      */
512     for(i=0;i<MIPS64_DEVICE_MAX;i++)     for(i=0;i<VM_DEVICE_MAX;i++)
513        if (!vm->dev_array[i])        if (!vm->dev_array[i])
514           break;           break;
515    
516     if (i == MIPS64_DEVICE_MAX) {     if (i == VM_DEVICE_MAX) {
517        fprintf(stderr,"VM%u: vm_bind_device: device table full.\n",        fprintf(stderr,"VM%u: vm_bind_device: device table full.\n",
518                vm->instance_id);                vm->instance_id);
519        return(-1);        return(-1);
# Line 550  int vm_unbind_device(vm_instance_t *vm,s Line 541  int vm_unbind_device(vm_instance_t *vm,s
541  {  {
542     u_int i;     u_int i;
543    
544     if (!dev->pprev)     if (!dev || !dev->pprev)
545        return(-1);        return(-1);
546    
547     /* Remove the device from the linked list */     /* Remove the device from the linked list */
# Line 560  int vm_unbind_device(vm_instance_t *vm,s Line 551  int vm_unbind_device(vm_instance_t *vm,s
551     *(dev->pprev) = dev->next;     *(dev->pprev) = dev->next;
552    
553     /* Remove the device from the device array */     /* Remove the device from the device array */
554     for(i=0;i<MIPS64_DEVICE_MAX;i++)     for(i=0;i<VM_DEVICE_MAX;i++)
555        if (vm->dev_array[i] == dev) {        if (vm->dev_array[i] == dev) {
556           vm->dev_array[i] = NULL;           vm->dev_array[i] = NULL;
557           break;           break;
# Line 600  int vm_map_device(vm_instance_t *vm,stru Line 591  int vm_map_device(vm_instance_t *vm,stru
591     return(0);     return(0);
592  }  }
593    
 /* Set an IRQ for a VM */  
 void vm_set_irq(vm_instance_t *vm,u_int irq)  
 {  
    if (vm->boot_cpu->irq_disable) {  
       vm->boot_cpu->irq_pending = 0;  
       return;  
    }  
   
    /* TODO: IRQ routing */  
    mips64_set_irq(vm->boot_cpu,irq);  
   
    if (vm->boot_cpu->irq_idle_preempt[irq])  
       mips64_idle_break_wait(vm->boot_cpu);  
 }  
   
 /* Clear an IRQ for a VM */  
 void vm_clear_irq(vm_instance_t *vm,u_int irq)  
 {  
    /* TODO: IRQ routing */  
    mips64_clear_irq(vm->boot_cpu,irq);  
 }  
   
594  /* Suspend a VM instance */  /* Suspend a VM instance */
595  int vm_suspend(vm_instance_t *vm)  int vm_suspend(vm_instance_t *vm)
596  {  {
597     if (vm->status == VM_STATUS_RUNNING) {     if (vm->status == VM_STATUS_RUNNING) {
598        cpu_group_save_state(vm->cpu_group);        cpu_group_save_state(vm->cpu_group);
599        cpu_group_set_state(vm->cpu_group,MIPS_CPU_SUSPENDED);        cpu_group_set_state(vm->cpu_group,CPU_STATE_SUSPENDED);
600        vm->status = VM_STATUS_SUSPENDED;        vm->status = VM_STATUS_SUSPENDED;
601     }     }
602     return(0);     return(0);
# Line 658  void vm_monitor(vm_instance_t *vm) Line 627  void vm_monitor(vm_instance_t *vm)
627        usleep(200000);        usleep(200000);
628  }  }
629    
630    /* Create a new chunk */
631    static vm_chunk_t *vm_chunk_create(vm_instance_t *vm)
632    {
633       vm_chunk_t *chunk;
634       size_t area_len;
635      
636       if (!(chunk = malloc(sizeof(*chunk))))
637          return NULL;
638    
639       area_len = VM_CHUNK_AREA_SIZE * VM_PAGE_SIZE;
640    
641       if (!(chunk->area = m_memalign(VM_PAGE_SIZE,area_len))) {
642          free(chunk);
643          return NULL;
644       }
645    
646       chunk->page_alloc = 0;
647       chunk->page_total = VM_CHUNK_AREA_SIZE;
648    
649       chunk->next = vm->chunks;
650       vm->chunks = chunk;
651       return chunk;
652    }
653    
654    /* Free a chunk */
655    static void vm_chunk_free(vm_chunk_t *chunk)
656    {
657       free(chunk->area);
658       free(chunk);
659    }
660    
661    /* Free all chunks used by a VM */
662    static void vm_chunk_free_all(vm_instance_t *vm)
663    {
664       vm_chunk_t *chunk,*next;
665    
666       for(chunk=vm->chunks;chunk;chunk=next) {
667          next = chunk->next;
668          vm_chunk_free(chunk);
669       }
670    
671       vm->chunks = NULL;
672    }
673    
674    /* Allocate an host page */
675    void *vm_alloc_host_page(vm_instance_t *vm)
676    {
677       vm_chunk_t *chunk = vm->chunks;
678       void *ptr;
679    
680       if (!chunk || (chunk->page_alloc == chunk->page_total)) {
681          chunk = vm_chunk_create(vm);
682          if (!chunk) return NULL;
683       }
684    
685       ptr = chunk->area + (chunk->page_alloc * VM_PAGE_SIZE);
686       chunk->page_alloc++;
687       return(ptr);
688    }
689    
690    /* Free resources used by a ghost image */
691    static void vm_ghost_image_free(vm_ghost_image_t *img)
692    {
693       if (img) {
694          if (img->fd != -1) {
695             close(img->fd);
696    
697             if (img->area_ptr != NULL)
698                munmap(img->area_ptr,img->file_size);
699          }
700    
701          free(img->filename);
702          free(img);
703       }
704    }
705    
706    /* Find a specified ghost image in the pool */
707    static vm_ghost_image_t *vm_ghost_image_find(char *filename)
708    {
709       vm_ghost_image_t *img;
710    
711       for(img=vm_ghost_pool;img;img=img->next)
712          if (!strcmp(img->filename,filename))
713             return img;
714    
715       return NULL;
716    }
717    
718    /* Load a new ghost image */
719    static vm_ghost_image_t *vm_ghost_image_load(char *filename)
720    {
721       vm_ghost_image_t *img;
722    
723       if (!(img = calloc(1,sizeof(*img))))
724          return NULL;
725    
726       img->fd = -1;
727    
728       if (!(img->filename = strdup(filename))) {
729          vm_ghost_image_free(img);
730          return NULL;
731       }
732    
733       img->fd = memzone_open_file(img->filename,&img->area_ptr,&img->file_size);
734    
735       if (img->fd == -1) {
736          vm_ghost_image_free(img);
737          return NULL;
738       }
739    
740       m_log("GHOST","loaded ghost image %s (fd=%d) at addr=%p (size=0x%llx)\n",
741             img->filename,img->fd,img->area_ptr,(long long)img->file_size);
742            
743       return img;
744    }
745    
746    /* Get a ghost image */
747    int vm_ghost_image_get(char *filename,u_char **ptr,int *fd)
748    {
749       vm_ghost_image_t *img;
750    
751       VM_GLOCK();
752    
753       /* Do we already have this image in the pool ? */
754       if ((img = vm_ghost_image_find(filename)) != NULL) {
755          img->ref_count++;
756          *ptr = img->area_ptr;
757          *fd  = img->fd;
758          VM_GUNLOCK();
759          return(0);
760       }
761    
762       /* Load the ghost file and add it into the pool */
763       if (!(img = vm_ghost_image_load(filename))) {
764          VM_GUNLOCK();
765          fprintf(stderr,"Unable to load ghost image %s\n",filename);
766          return(-1);
767       }
768      
769       img->ref_count = 1;
770       *ptr = img->area_ptr;
771       *fd  = img->fd;
772    
773       img->next = vm_ghost_pool;
774       vm_ghost_pool = img;  
775       VM_GUNLOCK();
776       return(0);
777    }
778    
779    /* Release a ghost image */
780    int vm_ghost_image_release(int fd)
781    {
782       vm_ghost_image_t **img,*next;
783    
784       VM_GLOCK();
785    
786       for(img=&vm_ghost_pool;*img;img=&(*img)->next) {
787          if ((*img)->fd == fd) {
788             assert((*img)->ref_count > 0);
789    
790             (*img)->ref_count--;
791    
792             if ((*img)->ref_count == 0) {
793                m_log("GHOST","unloaded ghost image %s (fd=%d) at "
794                      "addr=%p (size=0x%llx)\n",
795                      (*img)->filename,(*img)->fd,(*img)->area_ptr,
796                      (long long)(*img)->file_size);
797    
798                next = (*img)->next;
799                vm_ghost_image_free(*img);
800                *img = next;
801             }
802    
803             VM_GUNLOCK();
804             return(0);
805          }
806       }
807      
808       VM_GUNLOCK();
809       return(-1);
810    }
811    
812  /* Open a VM file and map it in memory */  /* Open a VM file and map it in memory */
813  int vm_mmap_open_file(vm_instance_t *vm,char *name,  int vm_mmap_open_file(vm_instance_t *vm,char *name,
814                        u_char **ptr,off_t *fsize)                        u_char **ptr,off_t *fsize)
# Line 767  int vm_ios_set_config(vm_instance_t *vm, Line 918  int vm_ios_set_config(vm_instance_t *vm,
918  /* Extract IOS configuration from NVRAM and write it to a file */  /* Extract IOS configuration from NVRAM and write it to a file */
919  int vm_nvram_extract_config(vm_instance_t *vm,char *filename)  int vm_nvram_extract_config(vm_instance_t *vm,char *filename)
920  {  {
921     char *cfg_buffer;     u_char *cfg_buffer;
922     ssize_t cfg_len;     ssize_t cfg_len;
923     FILE *fd;     FILE *fd;
924    
925     if (!vm->nvram_extract_config)     if (!vm->platform->nvram_extract_config)
926        return(-1);        return(-1);
927    
928     /* Extract the IOS configuration */     /* Extract the IOS configuration */
929     if (((cfg_len = vm->nvram_extract_config(vm,&cfg_buffer)) < 0) ||     if (((cfg_len = vm->platform->nvram_extract_config(vm,&cfg_buffer)) < 0) ||
930         (cfg_buffer == NULL))         (cfg_buffer == NULL))
931        return(-1);        return(-1);
932    
# Line 796  int vm_nvram_extract_config(vm_instance_ Line 947  int vm_nvram_extract_config(vm_instance_
947  /* Read an IOS configuraton from a file and push it to NVRAM */  /* Read an IOS configuraton from a file and push it to NVRAM */
948  int vm_nvram_push_config(vm_instance_t *vm,char *filename)  int vm_nvram_push_config(vm_instance_t *vm,char *filename)
949  {  {
950     char *cfg_buffer;     u_char *cfg_buffer;
951     ssize_t len;     ssize_t len;
952     int res;     int res;
953    
954     if (!vm->nvram_push_config)     if (!vm->platform->nvram_push_config)
955        return(-1);        return(-1);
956    
957     /* Read configuration */     /* Read configuration */
# Line 808  int vm_nvram_push_config(vm_instance_t * Line 959  int vm_nvram_push_config(vm_instance_t *
959        return(-1);        return(-1);
960    
961     /* Push it! */     /* Push it! */
962     res = vm->nvram_push_config(vm,cfg_buffer,len);     res = vm->platform->nvram_push_config(vm,cfg_buffer,len);
963     free(cfg_buffer);     free(cfg_buffer);
964     return(res);     return(res);
965  }  }
# Line 816  int vm_nvram_push_config(vm_instance_t * Line 967  int vm_nvram_push_config(vm_instance_t *
967  /* Save general VM configuration into the specified file */  /* Save general VM configuration into the specified file */
968  void vm_save_config(vm_instance_t *vm,FILE *fd)  void vm_save_config(vm_instance_t *vm,FILE *fd)
969  {  {
970       fprintf(fd,"vm create %s %u %s\n",
971               vm->name,vm->instance_id,vm->platform->name);
972    
973     if (vm->ios_image)     if (vm->ios_image)
974        fprintf(fd,"vm set_ios %s %s\n",vm->name,vm->ios_image);        fprintf(fd,"vm set_ios %s %s\n",vm->name,vm->ios_image);
975    
# Line 830  void vm_save_config(vm_instance_t *vm,FI Line 984  void vm_save_config(vm_instance_t *vm,FI
984    
985     if (vm->vtty_aux_type == VTTY_TYPE_TCP)     if (vm->vtty_aux_type == VTTY_TYPE_TCP)
986        fprintf(fd,"vm set_aux_tcp_port %s %d\n",vm->name,vm->vtty_aux_tcp_port);        fprintf(fd,"vm set_aux_tcp_port %s %d\n",vm->name,vm->vtty_aux_tcp_port);
987    
988       /* Save slot config */
989       vm_slot_save_all_config(vm,fd);
990    }
991    
992    /* Find a platform */
993    vm_platform_t *vm_platform_find(char *name)
994    {
995       struct vm_platform_list *p;
996    
997       for(p=vm_platforms;p;p=p->next)
998          if (!strcmp(p->platform->name,name))
999             return(p->platform);
1000    
1001       return NULL;
1002    }
1003    
1004    /* Find a platform given its CLI name */
1005    vm_platform_t *vm_platform_find_cli_name(char *name)
1006    {
1007       struct vm_platform_list *p;
1008    
1009       for(p=vm_platforms;p;p=p->next)
1010          if (!strcmp(p->platform->cli_name,name))
1011             return(p->platform);
1012    
1013       return NULL;
1014    }
1015    
1016    /* Register a platform */
1017    int vm_platform_register(vm_platform_t *platform)
1018    {
1019       struct vm_platform_list *p;
1020    
1021       if (vm_platform_find(platform->name) != NULL) {
1022          fprintf(stderr,"vm_platform_register: platform '%s' already exists.\n",
1023                  platform->name);
1024          return(-1);
1025       }
1026    
1027       if (!(p = malloc(sizeof(*p)))) {
1028          fprintf(stderr,"vm_platform_register: unable to record platform.\n");
1029          return(-1);
1030       }
1031    
1032       p->platform = platform;
1033       p->next = vm_platforms;
1034       vm_platforms = p;
1035       return(0);
1036    }
1037    
1038    /* Create an instance of the specified type */
1039    vm_instance_t *vm_create_instance(char *name,int instance_id,char *type)
1040    {
1041       vm_platform_t *platform;
1042       vm_instance_t *vm = NULL;
1043    
1044       if (!(platform = vm_platform_find(type))) {
1045          fprintf(stderr,"VM %s: unknown platform '%s'\n",name,type);
1046          goto error;
1047       }
1048    
1049       /* Create a generic VM instance */
1050       if (!(vm = vm_create(name,instance_id,platform)))
1051          goto error;
1052    
1053       /* Initialize specific parts */
1054       if (vm->platform->create_instance(vm) == -1)
1055          goto error;
1056    
1057       return vm;
1058    
1059     error:
1060       fprintf(stderr,"VM %s: unable to create instance!\n",name);
1061       vm_free(vm);
1062       return NULL;
1063    }
1064    
1065    /* Free resources used by a VM instance */
1066    static int vm_reg_delete_instance(void *data,void *arg)
1067    {
1068       vm_instance_t *vm = data;
1069       return(vm->platform->delete_instance(vm));
1070    }
1071    
1072    /* Delete a VM instance */
1073    int vm_delete_instance(char *name)
1074    {
1075       return(registry_delete_if_unused(name,OBJ_TYPE_VM,
1076                                        vm_reg_delete_instance,NULL));
1077    }
1078    
1079    /* Initialize a VM instance */
1080    int vm_init_instance(vm_instance_t *vm)
1081    {
1082       return(vm->platform->init_instance(vm));
1083    }
1084    
1085    /* Stop a VM instance */
1086    int vm_stop_instance(vm_instance_t *vm)
1087    {
1088       return(vm->platform->stop_instance(vm));
1089    }
1090    
1091    /* Delete all VM instances */
1092    int vm_delete_all_instances(void)
1093    {
1094       return(registry_delete_type(OBJ_TYPE_VM,vm_reg_delete_instance,NULL));
1095    }
1096    
1097    /* Save configurations of all VM instances */
1098    static void vm_reg_save_config(registry_entry_t *entry,void *opt,int *err)
1099    {
1100       vm_instance_t *vm = entry->data;
1101       FILE *fd = opt;
1102      
1103       vm_save_config(vm,fd);
1104    
1105       /* Save specific platform options */
1106       if (vm->platform->save_config != NULL)
1107          vm->platform->save_config(vm,fd);
1108    }
1109    
1110    /* Save all VM configs */
1111    int vm_save_config_all(FILE *fd)
1112    {  
1113       registry_foreach_type(OBJ_TYPE_VM,vm_reg_save_config,fd,NULL);
1114       return(0);
1115  }  }

Legend:
Removed from v.6  
changed lines
  Added in v.11

  ViewVC Help
Powered by ViewVC 1.1.26