/[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.7/vm.c revision 10 by dpavlin, Sat Oct 6 16:29:14 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    /* Pool of ghost images */
37    static vm_ghost_image_t *vm_ghost_pool = NULL;
38    
39    /* Global lock for VM manipulation */
40    static pthread_mutex_t vm_global_lock = PTHREAD_MUTEX_INITIALIZER;
41    
42    /* Free all chunks used by a VM */
43    static void vm_chunk_free_all(vm_instance_t *vm);
44    
45  /* Initialize a VM object */  /* Initialize a VM object */
46  void vm_object_init(vm_obj_t *obj)  void vm_object_init(vm_obj_t *obj)
47  {  {
# Line 95  void vm_object_free_list(vm_instance_t * Line 107  void vm_object_free_list(vm_instance_t *
107     vm->vm_object_list = NULL;     vm->vm_object_list = NULL;
108  }  }
109    
110    /* Rebuild the object list pointers */
111    static void vm_object_rebuild_list(vm_instance_t *vm)
112    {
113       vm_obj_t **obj;
114    
115       for(obj=&vm->vm_object_list;*obj;obj=&(*obj)->next)
116          (*obj)->pprev = obj;
117    }
118    
119  /* Dump the object list of an instance */  /* Dump the object list of an instance */
120  void vm_object_dump(vm_instance_t *vm)  void vm_object_dump(vm_instance_t *vm)
121  {  {
# Line 130  char *vm_get_type(vm_instance_t *vm) Line 151  char *vm_get_type(vm_instance_t *vm)
151       case VM_TYPE_C3745:       case VM_TYPE_C3745:
152           machine = "c3745";           machine = "c3745";
153           break;           break;
154         case VM_TYPE_C2600:
155             machine = "c2600";
156             break;
157         case VM_TYPE_MSFC1:
158             machine = "msfc1";
159             break;
160         case VM_TYPE_PPC32_TEST:
161             machine = "ppc32_test";
162             break;
163        default:        default:
164           machine = "unknown";           machine = "unknown";
165           break;           break;
# Line 159  char *vm_get_platform_type(vm_instance_t Line 189  char *vm_get_platform_type(vm_instance_t
189        case VM_TYPE_C3745:        case VM_TYPE_C3745:
190           machine = "C3745";           machine = "C3745";
191           break;           break;
192          case VM_TYPE_C2600:
193             machine = "C2600";
194             break;
195          case VM_TYPE_MSFC1:
196             machine = "MSFC1";
197             break;
198          case VM_TYPE_PPC32_TEST:
199             machine = "PPC32_TEST";
200             break;
201        default:        default:
202           machine = "VM";           machine = "VM";
203           break;           break;
# Line 186  u_int vm_get_mac_addr_msb(vm_instance_t Line 225  u_int vm_get_mac_addr_msb(vm_instance_t
225        case VM_TYPE_C3745:        case VM_TYPE_C3745:
226           return(0xC4);           return(0xC4);
227    
228          case VM_TYPE_C2600:
229             return(0xC8);
230    
231        default:        default:
232           return(0xC6);           return(0xC6);
233     }     }
# Line 280  void vm_log(vm_instance_t *vm,char *modu Line 322  void vm_log(vm_instance_t *vm,char *modu
322  {  {
323     va_list ap;     va_list ap;
324    
325     va_start(ap,format);     if (vm->log_fd) {
326     vm_flog(vm,module,format,ap);        va_start(ap,format);
327     va_end(ap);        vm_flog(vm,module,format,ap);
328          va_end(ap);
329       }
330  }  }
331    
332  /* Close the log file */  /* Close the log file */
# Line 301  int vm_close_log(vm_instance_t *vm) Line 345  int vm_close_log(vm_instance_t *vm)
345  /* Create the log file */  /* Create the log file */
346  int vm_create_log(vm_instance_t *vm)  int vm_create_log(vm_instance_t *vm)
347  {  {
348     vm_close_log(vm);     if (vm->log_file_enabled) {
349          vm_close_log(vm);
350    
351     if (!(vm->log_file = vm_build_filename(vm,"log.txt")))        if (!(vm->log_file = vm_build_filename(vm,"log.txt")))
352        return(-1);           return(-1);
353    
354     if (!(vm->log_fd = fopen(vm->log_file,"w"))) {        if (!(vm->log_fd = fopen(vm->log_file,"w"))) {
355        fprintf(stderr,"VM %s: unable to create log file '%s'\n",           fprintf(stderr,"VM %s: unable to create log file '%s'\n",
356                vm->name,vm->log_file);                   vm->name,vm->log_file);
357        free(vm->log_file);           free(vm->log_file);
358        vm->log_file = NULL;           vm->log_file = NULL;
359        return(-1);           return(-1);
360          }
361     }     }
362    
363     return(0);     return(0);
# Line 341  vm_instance_t *vm_create(char *name,int Line 387  vm_instance_t *vm_create(char *name,int
387     }     }
388        
389     memset(vm,0,sizeof(*vm));     memset(vm,0,sizeof(*vm));
390     vm->instance_id    = instance_id;     vm->instance_id          = instance_id;
391     vm->type           = machine_type;     vm->type                 = machine_type;
392     vm->status         = VM_STATUS_HALTED;     vm->status               = VM_STATUS_HALTED;
393     vm->jit_use        = JIT_SUPPORT;     vm->jit_use              = JIT_SUPPORT;
394     vm->vtty_con_type  = VTTY_TYPE_TERM;     vm->exec_blk_direct_jump = TRUE;
395     vm->vtty_aux_type  = VTTY_TYPE_NONE;     vm->vtty_con_type        = VTTY_TYPE_TERM;
396     vm->timer_irq_check_itv = VM_TIMER_IRQ_CHECK_ITV;     vm->vtty_aux_type        = VTTY_TYPE_NONE;
397       vm->timer_irq_check_itv  = VM_TIMER_IRQ_CHECK_ITV;
398       vm->log_file_enabled     = TRUE;
399    
400     if (!(vm->name = strdup(name))) {     if (!(vm->name = strdup(name))) {
401        fprintf(stderr,"VM %s: unable to store instance name!\n",name);        fprintf(stderr,"VM %s: unable to store instance name!\n",name);
# Line 421  int vm_hardware_shutdown(vm_instance_t * Line 469  int vm_hardware_shutdown(vm_instance_t *
469        }        }
470     }         }    
471    
472       /* Remove the IRQ routing vectors */
473       vm->set_irq = NULL;
474       vm->clear_irq = NULL;
475    
476     /* Delete the VTTY for Console and AUX ports */       /* Delete the VTTY for Console and AUX ports */  
477     vm_log(vm,"VM","deleting VTTY.\n");     vm_log(vm,"VM","deleting VTTY.\n");
478     vm_delete_vtty(vm);     vm_delete_vtty(vm);
# Line 448  void vm_free(vm_instance_t *vm) Line 500  void vm_free(vm_instance_t *vm)
500        /* Remove the lock file */        /* Remove the lock file */
501        vm_release_lock(vm,TRUE);        vm_release_lock(vm,TRUE);
502    
503          /* Free all chunks */
504          vm_chunk_free_all(vm);
505    
506        /* Free various elements */        /* Free various elements */
507        free(vm->ghost_ram_filename);        free(vm->ghost_ram_filename);
508        free(vm->sym_filename);        free(vm->sym_filename);
# Line 478  int vm_ram_init(vm_instance_t *vm,m_uint Line 533  int vm_ram_init(vm_instance_t *vm,m_uint
533    
534     len = vm->ram_size * 1048576;     len = vm->ram_size * 1048576;
535    
536     if (vm->ghost_status == VM_GHOST_RAM_USE)     if (vm->ghost_status == VM_GHOST_RAM_USE) {
537        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,
538                                    paddr,len));
539       }
540    
541     return(dev_ram_init(vm,"ram",vm->ram_mmap,     return(dev_ram_init(vm,"ram",vm->ram_mmap,
542                         (vm->ghost_status != VM_GHOST_RAM_GENERATE),                         (vm->ghost_status != VM_GHOST_RAM_GENERATE),
543                         vm->ghost_ram_filename,paddr,len));                         vm->ghost_ram_filename,vm->sparse_mem,paddr,len));
544  }  }
545    
546  /* Initialize VTTY */  /* Initialize VTTY */
# Line 518  int vm_bind_device(vm_instance_t *vm,str Line 575  int vm_bind_device(vm_instance_t *vm,str
575      * 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
576      * is used by the MTS subsystem.      * is used by the MTS subsystem.
577      */      */
578     for(i=0;i<MIPS64_DEVICE_MAX;i++)     for(i=0;i<VM_DEVICE_MAX;i++)
579        if (!vm->dev_array[i])        if (!vm->dev_array[i])
580           break;           break;
581    
582     if (i == MIPS64_DEVICE_MAX) {     if (i == VM_DEVICE_MAX) {
583        fprintf(stderr,"VM%u: vm_bind_device: device table full.\n",        fprintf(stderr,"VM%u: vm_bind_device: device table full.\n",
584                vm->instance_id);                vm->instance_id);
585        return(-1);        return(-1);
# Line 550  int vm_unbind_device(vm_instance_t *vm,s Line 607  int vm_unbind_device(vm_instance_t *vm,s
607  {  {
608     u_int i;     u_int i;
609    
610     if (!dev->pprev)     if (!dev || !dev->pprev)
611        return(-1);        return(-1);
612    
613     /* 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 617  int vm_unbind_device(vm_instance_t *vm,s
617     *(dev->pprev) = dev->next;     *(dev->pprev) = dev->next;
618    
619     /* Remove the device from the device array */     /* Remove the device from the device array */
620     for(i=0;i<MIPS64_DEVICE_MAX;i++)     for(i=0;i<VM_DEVICE_MAX;i++)
621        if (vm->dev_array[i] == dev) {        if (vm->dev_array[i] == dev) {
622           vm->dev_array[i] = NULL;           vm->dev_array[i] = NULL;
623           break;           break;
# Line 600  int vm_map_device(vm_instance_t *vm,stru Line 657  int vm_map_device(vm_instance_t *vm,stru
657     return(0);     return(0);
658  }  }
659    
 /* 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);  
 }  
   
660  /* Suspend a VM instance */  /* Suspend a VM instance */
661  int vm_suspend(vm_instance_t *vm)  int vm_suspend(vm_instance_t *vm)
662  {  {
663     if (vm->status == VM_STATUS_RUNNING) {     if (vm->status == VM_STATUS_RUNNING) {
664        cpu_group_save_state(vm->cpu_group);        cpu_group_save_state(vm->cpu_group);
665        cpu_group_set_state(vm->cpu_group,MIPS_CPU_SUSPENDED);        cpu_group_set_state(vm->cpu_group,CPU_STATE_SUSPENDED);
666        vm->status = VM_STATUS_SUSPENDED;        vm->status = VM_STATUS_SUSPENDED;
667     }     }
668     return(0);     return(0);
# Line 658  void vm_monitor(vm_instance_t *vm) Line 693  void vm_monitor(vm_instance_t *vm)
693        usleep(200000);        usleep(200000);
694  }  }
695    
696    /* Create a new chunk */
697    static vm_chunk_t *vm_chunk_create(vm_instance_t *vm)
698    {
699       vm_chunk_t *chunk;
700       size_t area_len;
701      
702       if (!(chunk = malloc(sizeof(*chunk))))
703          return NULL;
704    
705       area_len = VM_CHUNK_AREA_SIZE * VM_PAGE_SIZE;
706    
707       if (!(chunk->area = m_memalign(VM_PAGE_SIZE,area_len))) {
708          free(chunk);
709          return NULL;
710       }
711    
712       chunk->page_alloc = 0;
713       chunk->page_total = VM_CHUNK_AREA_SIZE;
714    
715       chunk->next = vm->chunks;
716       vm->chunks = chunk;
717       return chunk;
718    }
719    
720    /* Free a chunk */
721    static void vm_chunk_free(vm_chunk_t *chunk)
722    {
723       free(chunk->area);
724       free(chunk);
725    }
726    
727    /* Free all chunks used by a VM */
728    static void vm_chunk_free_all(vm_instance_t *vm)
729    {
730       vm_chunk_t *chunk,*next;
731    
732       for(chunk=vm->chunks;chunk;chunk=next) {
733          next = chunk->next;
734          vm_chunk_free(chunk);
735       }
736    
737       vm->chunks = NULL;
738    }
739    
740    /* Allocate an host page */
741    void *vm_alloc_host_page(vm_instance_t *vm)
742    {
743       vm_chunk_t *chunk = vm->chunks;
744       void *ptr;
745    
746       if (!chunk || (chunk->page_alloc == chunk->page_total)) {
747          chunk = vm_chunk_create(vm);
748          if (!chunk) return NULL;
749       }
750    
751       ptr = chunk->area + (chunk->page_alloc * VM_PAGE_SIZE);
752       chunk->page_alloc++;
753       return(ptr);
754    }
755    
756    /* Free resources used by a ghost image */
757    static void vm_ghost_image_free(vm_ghost_image_t *img)
758    {
759       if (img) {
760          if (img->fd != -1) {
761             close(img->fd);
762    
763             if (img->area_ptr != NULL)
764                munmap(img->area_ptr,img->file_size);
765          }
766    
767          free(img->filename);
768          free(img);
769       }
770    }
771    
772    /* Find a specified ghost image in the pool */
773    static vm_ghost_image_t *vm_ghost_image_find(char *filename)
774    {
775       vm_ghost_image_t *img;
776    
777       for(img=vm_ghost_pool;img;img=img->next)
778          if (!strcmp(img->filename,filename))
779             return img;
780    
781       return NULL;
782    }
783    
784    /* Load a new ghost image */
785    static vm_ghost_image_t *vm_ghost_image_load(char *filename)
786    {
787       vm_ghost_image_t *img;
788    
789       if (!(img = calloc(1,sizeof(*img))))
790          return NULL;
791    
792       img->fd = -1;
793    
794       if (!(img->filename = strdup(filename))) {
795          vm_ghost_image_free(img);
796          return NULL;
797       }
798    
799       img->fd = memzone_open_file(img->filename,&img->area_ptr,&img->file_size);
800    
801       if (img->fd == -1) {
802          vm_ghost_image_free(img);
803          return NULL;
804       }
805    
806       m_log("GHOST","loaded ghost image %s (fd=%d) at addr=%p (size=0x%llx)\n",
807             img->filename,img->fd,img->area_ptr,(long long)img->file_size);
808            
809       return img;
810    }
811    
812    /* Get a ghost image */
813    int vm_ghost_image_get(char *filename,u_char **ptr,int *fd)
814    {
815       vm_ghost_image_t *img;
816    
817       VM_GLOCK();
818    
819       /* Do we already have this image in the pool ? */
820       if ((img = vm_ghost_image_find(filename)) != NULL) {
821          img->ref_count++;
822          *ptr = img->area_ptr;
823          *fd  = img->fd;
824          VM_GUNLOCK();
825          return(0);
826       }
827    
828       /* Load the ghost file and add it into the pool */
829       if (!(img = vm_ghost_image_load(filename))) {
830          VM_GUNLOCK();
831          fprintf(stderr,"Unable to load ghost image %s\n",filename);
832          return(-1);
833       }
834      
835       img->ref_count = 1;
836       *ptr = img->area_ptr;
837       *fd  = img->fd;
838    
839       img->next = vm_ghost_pool;
840       vm_ghost_pool = img;  
841       VM_GUNLOCK();
842       return(0);
843    }
844    
845    /* Release a ghost image */
846    int vm_ghost_image_release(int fd)
847    {
848       vm_ghost_image_t **img,*next;
849    
850       VM_GLOCK();
851    
852       for(img=&vm_ghost_pool;*img;img=&(*img)->next) {
853          if ((*img)->fd == fd) {
854             assert((*img)->ref_count > 0);
855    
856             (*img)->ref_count--;
857    
858             if ((*img)->ref_count == 0) {
859                m_log("GHOST","unloaded ghost image %s (fd=%d) at "
860                      "addr=%p (size=0x%llx)\n",
861                      (*img)->filename,(*img)->fd,(*img)->area_ptr,
862                      (long long)(*img)->file_size);
863    
864                next = (*img)->next;
865                vm_ghost_image_free(*img);
866                *img = next;
867             }
868    
869             VM_GUNLOCK();
870             return(0);
871          }
872       }
873      
874       VM_GUNLOCK();
875       return(-1);
876    }
877    
878  /* Open a VM file and map it in memory */  /* Open a VM file and map it in memory */
879  int vm_mmap_open_file(vm_instance_t *vm,char *name,  int vm_mmap_open_file(vm_instance_t *vm,char *name,
880                        u_char **ptr,off_t *fsize)                        u_char **ptr,off_t *fsize)

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

  ViewVC Help
Powered by ViewVC 1.1.26