/[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

Annotation of /trunk/vm.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 7 - (hide annotations)
Sat Oct 6 16:23:47 2007 UTC (11 years, 8 months ago) by dpavlin
Original Path: upstream/dynamips-0.2.7-RC1/vm.c
File MIME type: text/plain
File size: 23391 byte(s)
dynamips-0.2.7-RC1

1 dpavlin 1 /*
2 dpavlin 7 * Cisco router simulation platform.
3 dpavlin 1 * Copyright (c) 2005,2006 Christophe Fillot (cf@utc.fr)
4     *
5     * Virtual machine abstraction.
6     */
7    
8     #include <stdio.h>
9     #include <stdlib.h>
10     #include <string.h>
11     #include <unistd.h>
12 dpavlin 4 #include <errno.h>
13 dpavlin 1 #include <fcntl.h>
14     #include <sys/types.h>
15     #include <assert.h>
16    
17     #include "registry.h"
18     #include "device.h"
19     #include "pci_dev.h"
20     #include "pci_io.h"
21 dpavlin 7 #include "cpu.h"
22     #include "mips64_jit.h"
23 dpavlin 1 #include "vm.h"
24     #include "dev_vtty.h"
25    
26 dpavlin 7 #include MIPS64_ARCH_INC_FILE
27 dpavlin 1
28     #define DEBUG_VM 1
29    
30 dpavlin 7 #define VM_GLOCK() pthread_mutex_lock(&vm_global_lock)
31     #define VM_GUNLOCK() pthread_mutex_unlock(&vm_global_lock)
32    
33 dpavlin 1 /* Type of VM file naming (0=use VM name, 1=use instance ID) */
34     int vm_file_naming_type = 0;
35    
36 dpavlin 7 /* 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 dpavlin 1 /* Initialize a VM object */
46     void vm_object_init(vm_obj_t *obj)
47     {
48     memset(obj,0,sizeof(*obj));
49     }
50    
51     /* Add a VM object to an instance */
52     void vm_object_add(vm_instance_t *vm,vm_obj_t *obj)
53     {
54     obj->next = vm->vm_object_list;
55     obj->pprev = &vm->vm_object_list;
56    
57     if (vm->vm_object_list)
58     vm->vm_object_list->pprev = &obj->next;
59    
60     vm->vm_object_list = obj;
61     }
62    
63     /* Remove a VM object from an instance */
64     void vm_object_remove(vm_instance_t *vm,vm_obj_t *obj)
65     {
66     if (obj->next)
67     obj->next->pprev = obj->pprev;
68     *(obj->pprev) = obj->next;
69 dpavlin 4
70     obj->shutdown(vm,obj->data);
71 dpavlin 1 }
72    
73     /* Find an object given its name */
74     vm_obj_t *vm_object_find(vm_instance_t *vm,char *name)
75     {
76     vm_obj_t *obj;
77    
78     for(obj=vm->vm_object_list;obj;obj=obj->next)
79     if (!strcmp(obj->name,name))
80     return obj;
81    
82     return NULL;
83     }
84    
85     /* Check that a mandatory object is present */
86     int vm_object_check(vm_instance_t *vm,char *name)
87     {
88     return(vm_object_find(vm,name) ? 0 : -1);
89     }
90    
91     /* Shut down all objects of an instance */
92     void vm_object_free_list(vm_instance_t *vm)
93     {
94     vm_obj_t *obj,*next;
95    
96     for(obj=vm->vm_object_list;obj;obj=next) {
97     next = obj->next;
98    
99     if (obj->shutdown != NULL) {
100     #if DEBUG_VM
101     vm_log(vm,"VM_OBJECT","Shutdown of object \"%s\"\n",obj->name);
102     #endif
103     obj->shutdown(vm,obj->data);
104     }
105     }
106    
107     vm->vm_object_list = NULL;
108     }
109    
110     /* Dump the object list of an instance */
111     void vm_object_dump(vm_instance_t *vm)
112     {
113     vm_obj_t *obj;
114    
115     printf("VM \"%s\" (%u) object list:\n",vm->name,vm->instance_id);
116    
117     for(obj=vm->vm_object_list;obj;obj=obj->next) {
118     printf(" - %-15s [data=%p]\n",obj->name,obj->data);
119     }
120    
121     printf("\n");
122     }
123    
124     /* Get VM type */
125     char *vm_get_type(vm_instance_t *vm)
126     {
127     char *machine;
128    
129     switch(vm->type) {
130     case VM_TYPE_C3600:
131     machine = "c3600";
132     break;
133     case VM_TYPE_C7200:
134     machine = "c7200";
135     break;
136 dpavlin 4 case VM_TYPE_C2691:
137     machine = "c2691";
138     break;
139     case VM_TYPE_C3725:
140     machine = "c3725";
141     break;
142     case VM_TYPE_C3745:
143     machine = "c3745";
144     break;
145 dpavlin 7 case VM_TYPE_C2600:
146     machine = "c2600";
147     break;
148     case VM_TYPE_PPC32_TEST:
149     machine = "ppc32_test";
150     break;
151 dpavlin 1 default:
152     machine = "unknown";
153     break;
154     }
155    
156     return machine;
157     }
158    
159     /* Get platform type */
160     char *vm_get_platform_type(vm_instance_t *vm)
161     {
162     char *machine;
163    
164     switch(vm->type) {
165     case VM_TYPE_C3600:
166     machine = "C3600";
167     break;
168     case VM_TYPE_C7200:
169     machine = "C7200";
170 dpavlin 4 break;
171     case VM_TYPE_C2691:
172     machine = "C2691";
173 dpavlin 1 break;
174 dpavlin 4 case VM_TYPE_C3725:
175     machine = "C3725";
176     break;
177     case VM_TYPE_C3745:
178     machine = "C3745";
179     break;
180 dpavlin 7 case VM_TYPE_C2600:
181     machine = "C2600";
182     break;
183     case VM_TYPE_PPC32_TEST:
184     machine = "PPC32_TEST";
185     break;
186 dpavlin 1 default:
187     machine = "VM";
188     break;
189     }
190    
191     return machine;
192     }
193    
194 dpavlin 4 /* Get MAC address MSB */
195     u_int vm_get_mac_addr_msb(vm_instance_t *vm)
196     {
197     switch(vm->type) {
198     case VM_TYPE_C3600:
199     return(0xCC);
200    
201     case VM_TYPE_C7200:
202     return(0xCA);
203    
204     case VM_TYPE_C2691:
205     return(0xC0);
206    
207     case VM_TYPE_C3725:
208     return(0xC2);
209    
210     case VM_TYPE_C3745:
211     return(0xC4);
212    
213 dpavlin 7 case VM_TYPE_C2600:
214     return(0xC8);
215    
216 dpavlin 4 default:
217     return(0xC6);
218     }
219     }
220    
221 dpavlin 1 /* Generate a filename for use by the instance */
222     char *vm_build_filename(vm_instance_t *vm,char *name)
223     {
224     char *filename,*machine;
225    
226     machine = vm_get_type(vm);
227    
228     switch(vm_file_naming_type) {
229     case 1:
230     filename = dyn_sprintf("%s_i%u_%s",machine,vm->instance_id,name);
231     break;
232     case 0:
233     default:
234     filename = dyn_sprintf("%s_%s_%s",machine,vm->name,name);
235     break;
236     }
237    
238     assert(filename != NULL);
239     return filename;
240     }
241    
242     /* Erase lock file */
243     void vm_release_lock(vm_instance_t *vm,int erase)
244     {
245     if (vm->lock_fd != NULL) {
246     fclose(vm->lock_fd);
247     vm->lock_fd = NULL;
248     }
249    
250     if (vm->lock_file != NULL) {
251     if (erase)
252     unlink(vm->lock_file);
253     free(vm->lock_file);
254     vm->lock_file = NULL;
255     }
256     }
257    
258     /* Check that an instance lock file doesn't already exist */
259     int vm_get_lock(vm_instance_t *vm)
260     {
261     char pid_str[32];
262     struct flock lock;
263    
264     vm->lock_file = vm_build_filename(vm,"lock");
265    
266     if (!(vm->lock_fd = fopen(vm->lock_file,"w"))) {
267     fprintf(stderr,"Unable to create lock file \"%s\".\n",vm->lock_file);
268     return(-1);
269     }
270    
271     memset(&lock,0,sizeof(lock));
272     lock.l_type = F_WRLCK;
273     lock.l_whence = SEEK_SET;
274     lock.l_start = 0;
275     lock.l_len = 0;
276    
277     if (fcntl(fileno(vm->lock_fd),F_SETLK,&lock) == -1) {
278     if (fcntl(fileno(vm->lock_fd),F_GETLK,&lock) == 0) {
279     snprintf(pid_str,sizeof(pid_str),"%ld",(long)lock.l_pid);
280     } else {
281     strcpy(pid_str,"unknown");
282     }
283    
284     fprintf(stderr,
285     "\nAn emulator instance (PID %s) is already running with "
286     "identifier %u.\n"
287     "If this is not the case, please erase file \"%s\".\n\n",
288     pid_str,vm->instance_id,vm->lock_file);
289     vm_release_lock(vm,FALSE);
290     return(-1);
291     }
292    
293     /* write the emulator PID */
294     fprintf(vm->lock_fd,"%ld\n",(u_long)getpid());
295     return(0);
296     }
297    
298     /* Log a message */
299     void vm_flog(vm_instance_t *vm,char *module,char *format,va_list ap)
300     {
301     if (vm->log_fd)
302     m_flog(vm->log_fd,module,format,ap);
303     }
304    
305     /* Log a message */
306     void vm_log(vm_instance_t *vm,char *module,char *format,...)
307     {
308     va_list ap;
309    
310 dpavlin 7 if (vm->log_fd) {
311     va_start(ap,format);
312     vm_flog(vm,module,format,ap);
313     va_end(ap);
314     }
315 dpavlin 1 }
316    
317     /* Close the log file */
318     int vm_close_log(vm_instance_t *vm)
319     {
320     if (vm->log_fd)
321     fclose(vm->log_fd);
322    
323     free(vm->log_file);
324    
325     vm->log_file = NULL;
326     vm->log_fd = NULL;
327     return(0);
328     }
329    
330     /* Create the log file */
331     int vm_create_log(vm_instance_t *vm)
332     {
333 dpavlin 7 if (vm->log_file_enabled) {
334     vm_close_log(vm);
335 dpavlin 1
336 dpavlin 7 if (!(vm->log_file = vm_build_filename(vm,"log.txt")))
337     return(-1);
338 dpavlin 1
339 dpavlin 7 if (!(vm->log_fd = fopen(vm->log_file,"w"))) {
340     fprintf(stderr,"VM %s: unable to create log file '%s'\n",
341     vm->name,vm->log_file);
342     free(vm->log_file);
343     vm->log_file = NULL;
344     return(-1);
345     }
346 dpavlin 1 }
347    
348     return(0);
349     }
350    
351     /* Error message */
352     void vm_error(vm_instance_t *vm,char *format,...)
353     {
354     char buffer[2048];
355     va_list ap;
356    
357     va_start(ap,format);
358     vsnprintf(buffer,sizeof(buffer),format,ap);
359     va_end(ap);
360    
361     fprintf(stderr,"%s '%s': %s",vm_get_platform_type(vm),vm->name,buffer);
362     }
363    
364     /* Create a new VM instance */
365     vm_instance_t *vm_create(char *name,int instance_id,int machine_type)
366     {
367     vm_instance_t *vm;
368    
369     if (!(vm = malloc(sizeof(*vm)))) {
370     fprintf(stderr,"VM %s: unable to create new instance!\n",name);
371     return NULL;
372     }
373    
374     memset(vm,0,sizeof(*vm));
375     vm->instance_id = instance_id;
376     vm->type = machine_type;
377     vm->status = VM_STATUS_HALTED;
378     vm->jit_use = JIT_SUPPORT;
379     vm->vtty_con_type = VTTY_TYPE_TERM;
380     vm->vtty_aux_type = VTTY_TYPE_NONE;
381     vm->timer_irq_check_itv = VM_TIMER_IRQ_CHECK_ITV;
382 dpavlin 7 vm->log_file_enabled = TRUE;
383 dpavlin 1
384     if (!(vm->name = strdup(name))) {
385     fprintf(stderr,"VM %s: unable to store instance name!\n",name);
386     goto err_name;
387     }
388    
389     /* create lock file */
390     if (vm_get_lock(vm) == -1)
391     goto err_lock;
392    
393     /* create log file */
394     if (vm_create_log(vm) == -1)
395     goto err_log;
396    
397     if (registry_add(vm->name,OBJ_TYPE_VM,vm) == -1) {
398     fprintf(stderr,"VM: Unable to store instance '%s' in registry!\n",
399     vm->name);
400     goto err_reg_add;
401     }
402    
403     return vm;
404    
405     err_reg_add:
406     vm_close_log(vm);
407     err_log:
408     free(vm->lock_file);
409     err_lock:
410     free(vm->name);
411     err_name:
412     free(vm);
413     return NULL;
414     }
415    
416     /*
417     * Shutdown hardware resources used by a VM.
418     * The CPU must have been stopped.
419     */
420     int vm_hardware_shutdown(vm_instance_t *vm)
421     {
422     int i;
423    
424     if ((vm->status == VM_STATUS_HALTED) || !vm->cpu_group) {
425     vm_log(vm,"VM","trying to shutdown an inactive VM.\n");
426     return(-1);
427     }
428    
429     vm_log(vm,"VM","shutdown procedure engaged.\n");
430    
431     /* Mark the VM as halted */
432     vm->status = VM_STATUS_HALTED;
433    
434     /* Disable NVRAM operations */
435     vm->nvram_extract_config = NULL;
436     vm->nvram_push_config = NULL;
437    
438     /* Free the object list */
439     vm_object_free_list(vm);
440    
441     /* Free resources used by PCI busses */
442     vm_log(vm,"VM","removing PCI busses.\n");
443     pci_io_data_remove(vm,vm->pci_io_space);
444     pci_bus_remove(vm->pci_bus[0]);
445     pci_bus_remove(vm->pci_bus[1]);
446     vm->pci_bus[0] = vm->pci_bus[1] = NULL;
447    
448     /* Free the PCI bus pool */
449     for(i=0;i<VM_PCI_POOL_SIZE;i++) {
450     if (vm->pci_bus_pool[i] != NULL) {
451     pci_bus_remove(vm->pci_bus_pool[i]);
452     vm->pci_bus_pool[i] = NULL;
453     }
454     }
455    
456 dpavlin 7 /* Remove the IRQ routing vectors */
457     vm->set_irq = NULL;
458     vm->clear_irq = NULL;
459    
460 dpavlin 1 /* Delete the VTTY for Console and AUX ports */
461     vm_log(vm,"VM","deleting VTTY.\n");
462     vm_delete_vtty(vm);
463    
464     /* Delete system CPU group */
465     vm_log(vm,"VM","deleting system CPUs.\n");
466     cpu_group_delete(vm->cpu_group);
467     vm->cpu_group = NULL;
468     vm->boot_cpu = NULL;
469    
470     vm_log(vm,"VM","shutdown procedure completed.\n");
471     return(0);
472     }
473    
474     /* Free resources used by a VM */
475     void vm_free(vm_instance_t *vm)
476     {
477     if (vm != NULL) {
478     /* Free hardware resources */
479     vm_hardware_shutdown(vm);
480    
481     /* Close log file */
482     vm_close_log(vm);
483    
484     /* Remove the lock file */
485     vm_release_lock(vm,TRUE);
486    
487 dpavlin 7 /* Free all chunks */
488     vm_chunk_free_all(vm);
489    
490 dpavlin 1 /* Free various elements */
491 dpavlin 4 free(vm->ghost_ram_filename);
492 dpavlin 1 free(vm->sym_filename);
493     free(vm->ios_image);
494     free(vm->ios_config);
495     free(vm->rom_filename);
496     free(vm->name);
497     free(vm);
498     }
499     }
500    
501     /* Get an instance given a name */
502     vm_instance_t *vm_acquire(char *name)
503     {
504     return(registry_find(name,OBJ_TYPE_VM));
505     }
506    
507     /* Release a VM (decrement reference count) */
508     int vm_release(vm_instance_t *vm)
509     {
510     return(registry_unref(vm->name,OBJ_TYPE_VM));
511     }
512    
513 dpavlin 4 /* Initialize RAM */
514     int vm_ram_init(vm_instance_t *vm,m_uint64_t paddr)
515     {
516     m_uint32_t len;
517    
518     len = vm->ram_size * 1048576;
519    
520 dpavlin 7 if (vm->ghost_status == VM_GHOST_RAM_USE) {
521     return(dev_ram_ghost_init(vm,"ram",vm->sparse_mem,vm->ghost_ram_filename,
522     paddr,len));
523     }
524 dpavlin 4
525     return(dev_ram_init(vm,"ram",vm->ram_mmap,
526     (vm->ghost_status != VM_GHOST_RAM_GENERATE),
527 dpavlin 7 vm->ghost_ram_filename,vm->sparse_mem,paddr,len));
528 dpavlin 4 }
529    
530 dpavlin 1 /* Initialize VTTY */
531     int vm_init_vtty(vm_instance_t *vm)
532     {
533     /* Create Console and AUX ports */
534     vm->vtty_con = vtty_create(vm,"Console port",
535     vm->vtty_con_type,vm->vtty_con_tcp_port,
536     &vm->vtty_con_serial_option);
537    
538     vm->vtty_aux = vtty_create(vm,"AUX port",
539     vm->vtty_aux_type,vm->vtty_aux_tcp_port,
540     &vm->vtty_aux_serial_option);
541     return(0);
542     }
543    
544     /* Delete VTTY */
545     void vm_delete_vtty(vm_instance_t *vm)
546     {
547     vtty_delete(vm->vtty_con);
548     vtty_delete(vm->vtty_aux);
549     vm->vtty_con = vm->vtty_aux = NULL;
550     }
551    
552     /* Bind a device to a virtual machine */
553     int vm_bind_device(vm_instance_t *vm,struct vdevice *dev)
554     {
555     struct vdevice **cur;
556     u_int i;
557    
558     /*
559     * Add this device to the device array. The index in the device array
560     * is used by the MTS subsystem.
561     */
562 dpavlin 7 for(i=0;i<VM_DEVICE_MAX;i++)
563 dpavlin 1 if (!vm->dev_array[i])
564     break;
565    
566 dpavlin 7 if (i == VM_DEVICE_MAX) {
567 dpavlin 1 fprintf(stderr,"VM%u: vm_bind_device: device table full.\n",
568     vm->instance_id);
569     return(-1);
570     }
571    
572     vm->dev_array[i] = dev;
573     dev->id = i;
574    
575     /*
576     * Add it to the linked-list (devices are ordered by physical addresses).
577     */
578     for(cur=&vm->dev_list;*cur;cur=&(*cur)->next)
579     if ((*cur)->phys_addr > dev->phys_addr)
580     break;
581    
582     dev->next = *cur;
583     if (*cur) (*cur)->pprev = &dev->next;
584     dev->pprev = cur;
585     *cur = dev;
586     return(0);
587     }
588    
589     /* Unbind a device from a virtual machine */
590     int vm_unbind_device(vm_instance_t *vm,struct vdevice *dev)
591     {
592     u_int i;
593    
594     if (!dev->pprev)
595     return(-1);
596    
597     /* Remove the device from the linked list */
598     if (dev->next)
599     dev->next->pprev = dev->pprev;
600    
601     *(dev->pprev) = dev->next;
602    
603     /* Remove the device from the device array */
604 dpavlin 7 for(i=0;i<VM_DEVICE_MAX;i++)
605 dpavlin 1 if (vm->dev_array[i] == dev) {
606     vm->dev_array[i] = NULL;
607     break;
608     }
609    
610     /* Clear device list info */
611     dev->next = NULL;
612     dev->pprev = NULL;
613     return(0);
614     }
615    
616     /* Map a device at the specified physical address */
617     int vm_map_device(vm_instance_t *vm,struct vdevice *dev,m_uint64_t base_addr)
618     {
619     #if 0
620     /* Suspend VM activity */
621     vm_suspend(vm);
622    
623     if (cpu_group_sync_state(vm->cpu_group) == -1) {
624     fprintf(stderr,"VM%u: unable to sync with system CPUs.\n",
625     vm->instance_id);
626     return(-1);
627     }
628     #endif
629    
630     /* Unbind the device if it was already active */
631     vm_unbind_device(vm,dev);
632    
633     /* Map the device at the new base address and rebuild MTS */
634     dev->phys_addr = base_addr;
635     vm_bind_device(vm,dev);
636     cpu_group_rebuild_mts(vm->cpu_group);
637    
638     #if 0
639     vm_resume(vm);
640     #endif
641     return(0);
642     }
643    
644     /* Suspend a VM instance */
645     int vm_suspend(vm_instance_t *vm)
646     {
647     if (vm->status == VM_STATUS_RUNNING) {
648     cpu_group_save_state(vm->cpu_group);
649 dpavlin 7 cpu_group_set_state(vm->cpu_group,CPU_STATE_SUSPENDED);
650 dpavlin 1 vm->status = VM_STATUS_SUSPENDED;
651     }
652     return(0);
653     }
654    
655     /* Resume a VM instance */
656     int vm_resume(vm_instance_t *vm)
657     {
658     if (vm->status == VM_STATUS_SUSPENDED) {
659     cpu_group_restore_state(vm->cpu_group);
660     vm->status = VM_STATUS_RUNNING;
661     }
662     return(0);
663     }
664    
665     /* Stop an instance */
666     int vm_stop(vm_instance_t *vm)
667     {
668     cpu_group_stop_all_cpu(vm->cpu_group);
669     vm->status = VM_STATUS_SHUTDOWN;
670     return(0);
671     }
672    
673     /* Monitor an instance periodically */
674     void vm_monitor(vm_instance_t *vm)
675     {
676     while(vm->status != VM_STATUS_SHUTDOWN)
677     usleep(200000);
678     }
679    
680 dpavlin 7 /* 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 dpavlin 4 /* Open a VM file and map it in memory */
863     int vm_mmap_open_file(vm_instance_t *vm,char *name,
864     u_char **ptr,off_t *fsize)
865     {
866     char *filename;
867     int fd;
868    
869     if (!(filename = vm_build_filename(vm,name))) {
870     fprintf(stderr,"vm_mmap_open_file: unable to create filename (%s)\n",
871     name);
872     return(-1);
873     }
874    
875     if ((fd = memzone_open_file(filename,ptr,fsize)) == -1)
876     fprintf(stderr,"vm_mmap_open_file: unable to open file '%s' (%s)\n",
877     filename,strerror(errno));
878    
879     free(filename);
880     return(fd);
881     }
882    
883     /* Open/Create a VM file and map it in memory */
884     int vm_mmap_create_file(vm_instance_t *vm,char *name,size_t len,u_char **ptr)
885     {
886     char *filename;
887     int fd;
888    
889     if (!(filename = vm_build_filename(vm,name))) {
890     fprintf(stderr,"vm_mmap_create_file: unable to create filename (%s)\n",
891     name);
892     return(-1);
893     }
894    
895     if ((fd = memzone_create_file(filename,len,ptr)) == -1)
896     fprintf(stderr,"vm_mmap_create_file: unable to open file '%s' (%s)\n",
897     filename,strerror(errno));
898    
899     free(filename);
900     return(fd);
901     }
902    
903     /* Close a memory mapped file */
904     int vm_mmap_close_file(int fd,u_char *ptr,size_t len)
905     {
906     if (ptr != NULL)
907     munmap(ptr,len);
908    
909     if (fd != -1)
910     close(fd);
911    
912     return(0);
913     }
914    
915 dpavlin 1 /* Save the Cisco IOS configuration from NVRAM */
916     int vm_ios_save_config(vm_instance_t *vm)
917     {
918     char *output;
919     int res;
920    
921     if (!(output = vm_build_filename(vm,"ios_cfg.txt")))
922     return(-1);
923    
924     res = vm_nvram_extract_config(vm,output);
925     free(output);
926     return(res);
927     }
928    
929     /* Set Cisco IOS image to use */
930     int vm_ios_set_image(vm_instance_t *vm,char *ios_image)
931     {
932     char *str;
933    
934     if (!(str = strdup(ios_image)))
935     return(-1);
936    
937     if (vm->ios_image != NULL) {
938     free(vm->ios_image);
939     vm->ios_image = NULL;
940     }
941    
942     vm->ios_image = str;
943     return(0);
944     }
945    
946     /* Unset a Cisco IOS configuration file */
947     void vm_ios_unset_config(vm_instance_t *vm)
948     {
949     if (vm->ios_config != NULL) {
950     free(vm->ios_config);
951     vm->ios_config = NULL;
952     }
953     }
954    
955     /* Set Cisco IOS configuration file to use */
956     int vm_ios_set_config(vm_instance_t *vm,char *ios_config)
957     {
958     char *str;
959    
960     if (!(str = strdup(ios_config)))
961     return(-1);
962    
963     vm_ios_unset_config(vm);
964     vm->ios_config = str;
965     return(0);
966     }
967    
968     /* Extract IOS configuration from NVRAM and write it to a file */
969     int vm_nvram_extract_config(vm_instance_t *vm,char *filename)
970     {
971     char *cfg_buffer;
972     ssize_t cfg_len;
973     FILE *fd;
974    
975     if (!vm->nvram_extract_config)
976     return(-1);
977    
978     /* Extract the IOS configuration */
979     if (((cfg_len = vm->nvram_extract_config(vm,&cfg_buffer)) < 0) ||
980     (cfg_buffer == NULL))
981     return(-1);
982    
983     /* Write configuration to the specified filename */
984     if (!(fd = fopen(filename,"w"))) {
985     vm_error(vm,"unable to create file '%s'\n",filename);
986     free(cfg_buffer);
987     return(-1);
988     }
989    
990     fwrite(cfg_buffer,cfg_len,1,fd);
991    
992     fclose(fd);
993     free(cfg_buffer);
994     return(0);
995     }
996    
997     /* Read an IOS configuraton from a file and push it to NVRAM */
998     int vm_nvram_push_config(vm_instance_t *vm,char *filename)
999     {
1000     char *cfg_buffer;
1001     ssize_t len;
1002     int res;
1003    
1004     if (!vm->nvram_push_config)
1005     return(-1);
1006    
1007     /* Read configuration */
1008     if (((len = m_read_file(filename,&cfg_buffer)) <= 0) || !cfg_buffer)
1009     return(-1);
1010    
1011     /* Push it! */
1012     res = vm->nvram_push_config(vm,cfg_buffer,len);
1013     free(cfg_buffer);
1014     return(res);
1015     }
1016    
1017     /* Save general VM configuration into the specified file */
1018     void vm_save_config(vm_instance_t *vm,FILE *fd)
1019     {
1020     if (vm->ios_image)
1021     fprintf(fd,"vm set_ios %s %s\n",vm->name,vm->ios_image);
1022    
1023     fprintf(fd,"vm set_ram %s %u\n",vm->name,vm->ram_size);
1024     fprintf(fd,"vm set_nvram %s %u\n",vm->name,vm->nvram_size);
1025     fprintf(fd,"vm set_ram_mmap %s %u\n",vm->name,vm->ram_mmap);
1026     fprintf(fd,"vm set_clock_divisor %s %u\n",vm->name,vm->clock_divisor);
1027     fprintf(fd,"vm set_conf_reg %s 0x%4.4x\n",vm->name,vm->conf_reg_setup);
1028    
1029     if (vm->vtty_con_type == VTTY_TYPE_TCP)
1030     fprintf(fd,"vm set_con_tcp_port %s %d\n",vm->name,vm->vtty_con_tcp_port);
1031    
1032     if (vm->vtty_aux_type == VTTY_TYPE_TCP)
1033     fprintf(fd,"vm set_aux_tcp_port %s %d\n",vm->name,vm->vtty_aux_tcp_port);
1034     }

  ViewVC Help
Powered by ViewVC 1.1.26