/[dynamips]/upstream/dynamips-0.2.7-RC1/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 /upstream/dynamips-0.2.7-RC1/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-RC1/vm.c revision 7 by dpavlin, Sat Oct 6 16:23:47 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 130  char *vm_get_type(vm_instance_t *vm) Line 142  char *vm_get_type(vm_instance_t *vm)
142       case VM_TYPE_C3745:       case VM_TYPE_C3745:
143           machine = "c3745";           machine = "c3745";
144           break;           break;
145         case VM_TYPE_C2600:
146             machine = "c2600";
147             break;
148         case VM_TYPE_PPC32_TEST:
149             machine = "ppc32_test";
150             break;
151        default:        default:
152           machine = "unknown";           machine = "unknown";
153           break;           break;
# Line 159  char *vm_get_platform_type(vm_instance_t Line 177  char *vm_get_platform_type(vm_instance_t
177        case VM_TYPE_C3745:        case VM_TYPE_C3745:
178           machine = "C3745";           machine = "C3745";
179           break;           break;
180          case VM_TYPE_C2600:
181             machine = "C2600";
182             break;
183         case VM_TYPE_PPC32_TEST:
184             machine = "PPC32_TEST";
185             break;
186        default:        default:
187           machine = "VM";           machine = "VM";
188           break;           break;
# Line 186  u_int vm_get_mac_addr_msb(vm_instance_t Line 210  u_int vm_get_mac_addr_msb(vm_instance_t
210        case VM_TYPE_C3745:        case VM_TYPE_C3745:
211           return(0xC4);           return(0xC4);
212    
213          case VM_TYPE_C2600:
214             return(0xC8);
215    
216        default:        default:
217           return(0xC6);           return(0xC6);
218     }     }
# Line 280  void vm_log(vm_instance_t *vm,char *modu Line 307  void vm_log(vm_instance_t *vm,char *modu
307  {  {
308     va_list ap;     va_list ap;
309    
310     va_start(ap,format);     if (vm->log_fd) {
311     vm_flog(vm,module,format,ap);        va_start(ap,format);
312     va_end(ap);        vm_flog(vm,module,format,ap);
313          va_end(ap);
314       }
315  }  }
316    
317  /* Close the log file */  /* Close the log file */
# Line 301  int vm_close_log(vm_instance_t *vm) Line 330  int vm_close_log(vm_instance_t *vm)
330  /* Create the log file */  /* Create the log file */
331  int vm_create_log(vm_instance_t *vm)  int vm_create_log(vm_instance_t *vm)
332  {  {
333     vm_close_log(vm);     if (vm->log_file_enabled) {
334          vm_close_log(vm);
335    
336     if (!(vm->log_file = vm_build_filename(vm,"log.txt")))        if (!(vm->log_file = vm_build_filename(vm,"log.txt")))
337        return(-1);           return(-1);
338    
339     if (!(vm->log_fd = fopen(vm->log_file,"w"))) {        if (!(vm->log_fd = fopen(vm->log_file,"w"))) {
340        fprintf(stderr,"VM %s: unable to create log file '%s'\n",           fprintf(stderr,"VM %s: unable to create log file '%s'\n",
341                vm->name,vm->log_file);                   vm->name,vm->log_file);
342        free(vm->log_file);           free(vm->log_file);
343        vm->log_file = NULL;           vm->log_file = NULL;
344        return(-1);           return(-1);
345          }
346     }     }
347    
348     return(0);     return(0);
# Line 348  vm_instance_t *vm_create(char *name,int Line 379  vm_instance_t *vm_create(char *name,int
379     vm->vtty_con_type  = VTTY_TYPE_TERM;     vm->vtty_con_type  = VTTY_TYPE_TERM;
380     vm->vtty_aux_type  = VTTY_TYPE_NONE;     vm->vtty_aux_type  = VTTY_TYPE_NONE;
381     vm->timer_irq_check_itv = VM_TIMER_IRQ_CHECK_ITV;     vm->timer_irq_check_itv = VM_TIMER_IRQ_CHECK_ITV;
382       vm->log_file_enabled = TRUE;
383    
384     if (!(vm->name = strdup(name))) {     if (!(vm->name = strdup(name))) {
385        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 453  int vm_hardware_shutdown(vm_instance_t *
453        }        }
454     }         }    
455    
456       /* Remove the IRQ routing vectors */
457       vm->set_irq = NULL;
458       vm->clear_irq = NULL;
459    
460     /* Delete the VTTY for Console and AUX ports */       /* Delete the VTTY for Console and AUX ports */  
461     vm_log(vm,"VM","deleting VTTY.\n");     vm_log(vm,"VM","deleting VTTY.\n");
462     vm_delete_vtty(vm);     vm_delete_vtty(vm);
# Line 448  void vm_free(vm_instance_t *vm) Line 484  void vm_free(vm_instance_t *vm)
484        /* Remove the lock file */        /* Remove the lock file */
485        vm_release_lock(vm,TRUE);        vm_release_lock(vm,TRUE);
486    
487          /* Free all chunks */
488          vm_chunk_free_all(vm);
489    
490        /* Free various elements */        /* Free various elements */
491        free(vm->ghost_ram_filename);        free(vm->ghost_ram_filename);
492        free(vm->sym_filename);        free(vm->sym_filename);
# Line 478  int vm_ram_init(vm_instance_t *vm,m_uint Line 517  int vm_ram_init(vm_instance_t *vm,m_uint
517    
518     len = vm->ram_size * 1048576;     len = vm->ram_size * 1048576;
519    
520     if (vm->ghost_status == VM_GHOST_RAM_USE)     if (vm->ghost_status == VM_GHOST_RAM_USE) {
521        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,
522                                    paddr,len));
523       }
524    
525     return(dev_ram_init(vm,"ram",vm->ram_mmap,     return(dev_ram_init(vm,"ram",vm->ram_mmap,
526                         (vm->ghost_status != VM_GHOST_RAM_GENERATE),                         (vm->ghost_status != VM_GHOST_RAM_GENERATE),
527                         vm->ghost_ram_filename,paddr,len));                         vm->ghost_ram_filename,vm->sparse_mem,paddr,len));
528  }  }
529    
530  /* Initialize VTTY */  /* Initialize VTTY */
# Line 518  int vm_bind_device(vm_instance_t *vm,str Line 559  int vm_bind_device(vm_instance_t *vm,str
559      * 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
560      * is used by the MTS subsystem.      * is used by the MTS subsystem.
561      */      */
562     for(i=0;i<MIPS64_DEVICE_MAX;i++)     for(i=0;i<VM_DEVICE_MAX;i++)
563        if (!vm->dev_array[i])        if (!vm->dev_array[i])
564           break;           break;
565    
566     if (i == MIPS64_DEVICE_MAX) {     if (i == VM_DEVICE_MAX) {
567        fprintf(stderr,"VM%u: vm_bind_device: device table full.\n",        fprintf(stderr,"VM%u: vm_bind_device: device table full.\n",
568                vm->instance_id);                vm->instance_id);
569        return(-1);        return(-1);
# Line 560  int vm_unbind_device(vm_instance_t *vm,s Line 601  int vm_unbind_device(vm_instance_t *vm,s
601     *(dev->pprev) = dev->next;     *(dev->pprev) = dev->next;
602    
603     /* Remove the device from the device array */     /* Remove the device from the device array */
604     for(i=0;i<MIPS64_DEVICE_MAX;i++)     for(i=0;i<VM_DEVICE_MAX;i++)
605        if (vm->dev_array[i] == dev) {        if (vm->dev_array[i] == dev) {
606           vm->dev_array[i] = NULL;           vm->dev_array[i] = NULL;
607           break;           break;
# Line 600  int vm_map_device(vm_instance_t *vm,stru Line 641  int vm_map_device(vm_instance_t *vm,stru
641     return(0);     return(0);
642  }  }
643    
 /* 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);  
 }  
   
644  /* Suspend a VM instance */  /* Suspend a VM instance */
645  int vm_suspend(vm_instance_t *vm)  int vm_suspend(vm_instance_t *vm)
646  {  {
647     if (vm->status == VM_STATUS_RUNNING) {     if (vm->status == VM_STATUS_RUNNING) {
648        cpu_group_save_state(vm->cpu_group);        cpu_group_save_state(vm->cpu_group);
649        cpu_group_set_state(vm->cpu_group,MIPS_CPU_SUSPENDED);        cpu_group_set_state(vm->cpu_group,CPU_STATE_SUSPENDED);
650        vm->status = VM_STATUS_SUSPENDED;        vm->status = VM_STATUS_SUSPENDED;
651     }     }
652     return(0);     return(0);
# Line 658  void vm_monitor(vm_instance_t *vm) Line 677  void vm_monitor(vm_instance_t *vm)
677        usleep(200000);        usleep(200000);
678  }  }
679    
680    /* Create a new chunk */
681    static vm_chunk_t *vm_chunk_create(vm_instance_t *vm)
682    {
683       vm_chunk_t *chunk;
684       size_t area_len;
685      
686       if (!(chunk = malloc(sizeof(*chunk))))
687          return NULL;
688    
689       area_len = VM_CHUNK_AREA_SIZE * VM_PAGE_SIZE;
690    
691       if (!(chunk->area = m_memalign(VM_PAGE_SIZE,area_len))) {
692          free(chunk);
693          return NULL;
694       }
695    
696       chunk->page_alloc = 0;
697       chunk->page_total = VM_CHUNK_AREA_SIZE;
698    
699       chunk->next = vm->chunks;
700       vm->chunks = chunk;
701       return chunk;
702    }
703    
704    /* Free a chunk */
705    static void vm_chunk_free(vm_chunk_t *chunk)
706    {
707       free(chunk->area);
708       free(chunk);
709    }
710    
711    /* Free all chunks used by a VM */
712    static void vm_chunk_free_all(vm_instance_t *vm)
713    {
714       vm_chunk_t *chunk,*next;
715    
716       for(chunk=vm->chunks;chunk;chunk=next) {
717          next = chunk->next;
718          vm_chunk_free(chunk);
719       }
720    
721       vm->chunks = NULL;
722    }
723    
724    /* Allocate an host page */
725    void *vm_alloc_host_page(vm_instance_t *vm)
726    {
727       vm_chunk_t *chunk = vm->chunks;
728       void *ptr;
729    
730       if (!chunk || (chunk->page_alloc == chunk->page_total)) {
731          chunk = vm_chunk_create(vm);
732          if (!chunk) return NULL;
733       }
734    
735       ptr = chunk->area + (chunk->page_alloc * VM_PAGE_SIZE);
736       chunk->page_alloc++;
737       return(ptr);
738    }
739    
740    /* Free resources used by a ghost image */
741    static void vm_ghost_image_free(vm_ghost_image_t *img)
742    {
743       if (img) {
744          if (img->fd != -1) {
745             close(img->fd);
746    
747             if (img->area_ptr != NULL)
748                munmap(img->area_ptr,img->file_size);
749          }
750    
751          free(img->filename);
752          free(img);
753       }
754    }
755    
756    /* Find a specified ghost image in the pool */
757    static vm_ghost_image_t *vm_ghost_image_find(char *filename)
758    {
759       vm_ghost_image_t *img;
760    
761       for(img=vm_ghost_pool;img;img=img->next)
762          if (!strcmp(img->filename,filename))
763             return img;
764    
765       return NULL;
766    }
767    
768    /* Load a new ghost image */
769    static vm_ghost_image_t *vm_ghost_image_load(char *filename)
770    {
771       vm_ghost_image_t *img;
772    
773       if (!(img = calloc(1,sizeof(*img))))
774          return NULL;
775    
776       img->fd = -1;
777    
778       if (!(img->filename = strdup(filename))) {
779          vm_ghost_image_free(img);
780          return NULL;
781       }
782    
783       img->fd = memzone_open_file(img->filename,&img->area_ptr,&img->file_size);
784    
785       if (img->fd == -1) {
786          vm_ghost_image_free(img);
787          return NULL;
788       }
789    
790       m_log("GHOST","loaded ghost image %s (fd=%d) at addr=%p (size=0x%llx)\n",
791             img->filename,img->fd,img->area_ptr,(long long)img->file_size);
792            
793       return img;
794    }
795    
796    /* Get a ghost image */
797    int vm_ghost_image_get(char *filename,u_char **ptr,int *fd)
798    {
799       vm_ghost_image_t *img;
800    
801       VM_GLOCK();
802    
803       /* Do we already have this image in the pool ? */
804       if ((img = vm_ghost_image_find(filename)) != NULL) {
805          img->ref_count++;
806          *ptr = img->area_ptr;
807          *fd  = img->fd;
808          VM_GUNLOCK();
809          return(0);
810       }
811    
812       /* Load the ghost file and add it into the pool */
813       if (!(img = vm_ghost_image_load(filename))) {
814          VM_GUNLOCK();
815          fprintf(stderr,"Unable to load ghost image %s\n",filename);
816          return(-1);
817       }
818      
819       img->ref_count = 1;
820       *ptr = img->area_ptr;
821       *fd  = img->fd;
822    
823       img->next = vm_ghost_pool;
824       vm_ghost_pool = img;  
825       VM_GUNLOCK();
826       return(0);
827    }
828    
829    /* Release a ghost image */
830    int vm_ghost_image_release(int fd)
831    {
832       vm_ghost_image_t **img,*next;
833    
834       VM_GLOCK();
835    
836       for(img=&vm_ghost_pool;*img;img=&(*img)->next) {
837          if ((*img)->fd == fd) {
838             assert((*img)->ref_count > 0);
839    
840             (*img)->ref_count--;
841    
842             if ((*img)->ref_count == 0) {
843                m_log("GHOST","unloaded ghost image %s (fd=%d) at "
844                      "addr=%p (size=0x%llx)\n",
845                      (*img)->filename,(*img)->fd,(*img)->area_ptr,
846                      (long long)(*img)->file_size);
847    
848                next = (*img)->next;
849                vm_ghost_image_free(*img);
850                *img = next;
851             }
852    
853             VM_GUNLOCK();
854             return(0);
855          }
856       }
857      
858       VM_GUNLOCK();
859       return(-1);
860    }
861    
862  /* Open a VM file and map it in memory */  /* Open a VM file and map it in memory */
863  int vm_mmap_open_file(vm_instance_t *vm,char *name,  int vm_mmap_open_file(vm_instance_t *vm,char *name,
864                        u_char **ptr,off_t *fsize)                        u_char **ptr,off_t *fsize)

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

  ViewVC Help
Powered by ViewVC 1.1.26