/[dynamips]/upstream/dynamips-0.2.7-RC1/device.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/device.c

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

upstream/dynamips-0.2.6-RC5/device.c revision 6 by dpavlin, Sat Oct 6 16:09:07 2007 UTC upstream/dynamips-0.2.7-RC1/device.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    
# Line 12  Line 12 
12  #include <sys/stat.h>  #include <sys/stat.h>
13  #include <sys/mman.h>  #include <sys/mman.h>
14  #include <fcntl.h>  #include <fcntl.h>
15    #include <assert.h>
16    
 #include "mips64.h"  
17  #include "cpu.h"  #include "cpu.h"
18    #include "vm.h"
19  #include "dynamips.h"  #include "dynamips.h"
20  #include "memory.h"  #include "memory.h"
21  #include "device.h"  #include "device.h"
 #include "cp0.h"  
22    
23  #define DEBUG_DEV_ACCESS  0  #define DEBUG_DEV_ACCESS  0
24    
25  /* Get device by ID */  /* Get device by ID */
26  struct vdevice *dev_get_by_id(vm_instance_t *vm,u_int dev_id)  struct vdevice *dev_get_by_id(vm_instance_t *vm,u_int dev_id)
27  {  {
28     if (!vm || (dev_id >= MIPS64_DEVICE_MAX))     if (!vm || (dev_id >= VM_DEVICE_MAX))
29        return NULL;        return NULL;
30    
31     return(vm->dev_array[dev_id]);     return(vm->dev_array[dev_id]);
# Line 113  struct vdevice *dev_create(char *name) Line 113  struct vdevice *dev_create(char *name)
113  /* Remove a device */  /* Remove a device */
114  void dev_remove(vm_instance_t *vm,struct vdevice *dev)  void dev_remove(vm_instance_t *vm,struct vdevice *dev)
115  {  {
116     if (dev != NULL) {     if (dev == NULL)
117        vm_unbind_device(vm,dev);        return;
118    
119       vm_unbind_device(vm,dev);
120                
121        vm_log(vm,"DEVICE",     vm_log(vm,"DEVICE",
122               "Removal of device %s, fd=%d, host_addr=0x%llx, flags=%d\n",            "Removal of device %s, fd=%d, host_addr=0x%llx, flags=%d\n",
123               dev->name,dev->fd,(m_uint64_t)dev->host_addr,dev->flags);            dev->name,dev->fd,(m_uint64_t)dev->host_addr,dev->flags);
   
       if (dev->fd != -1) {  
          /* Unmap memory mapped file */  
          if (dev->host_addr && !(dev->flags & VDEVICE_FLAG_REMAP)) {  
             if (dev->flags & VDEVICE_FLAG_SYNC) {  
                msync((void *)dev->host_addr,dev->phys_len,  
                      MS_SYNC|MS_INVALIDATE);  
             }  
   
             vm_log(vm,"MMAP","unmapping of device '%s', "  
                    "fd=%d, host_addr=0x%llx, len=0x%x\n",  
                    dev->name,dev->fd,(m_uint64_t)dev->host_addr,dev->phys_len);  
             munmap((void *)dev->host_addr,dev->phys_len);  
          }  
124    
125           if (dev->flags & VDEVICE_FLAG_SYNC)     if (dev->flags & VDEVICE_FLAG_REMAP) {
126              fsync(dev->fd);        dev_init(dev);
127          return;
128       }
129    
130           close(dev->fd);     if (dev->flags & VDEVICE_FLAG_SPARSE) {
131        } else {        dev_sparse_shutdown(dev);
132           /* Use of malloc'ed host memory: free it */  
133           if (dev->host_addr && !(dev->flags & VDEVICE_FLAG_REMAP))        if (dev->flags & VDEVICE_FLAG_GHOST) {
134              free((void *)dev->host_addr);           vm_ghost_image_release(dev->fd);
135             dev_init(dev);
136             return;
137        }        }
138       }
139    
140        /* reinitialize the device to a clean state */     if (dev->fd != -1) {
141        dev_init(dev);        /* Unmap memory mapped file */
142          if (dev->host_addr) {
143             if (dev->flags & VDEVICE_FLAG_SYNC) {
144                msync((void *)dev->host_addr,dev->phys_len,
145                      MS_SYNC|MS_INVALIDATE);
146             }
147            
148             vm_log(vm,"MMAP","unmapping of device '%s', "
149                    "fd=%d, host_addr=0x%llx, len=0x%x\n",
150                    dev->name,dev->fd,(m_uint64_t)dev->host_addr,dev->phys_len);
151             munmap((void *)dev->host_addr,dev->phys_len);
152          }
153          
154          if (dev->flags & VDEVICE_FLAG_SYNC)
155             fsync(dev->fd);
156    
157          close(dev->fd);
158       } else {
159          /* Use of malloc'ed host memory: free it */
160          if (dev->host_addr)
161             free((void *)dev->host_addr);
162     }     }
163    
164       /* reinitialize the device to a clean state */
165       dev_init(dev);
166  }  }
167    
168  /* Show properties of a device */  /* Show properties of a device */
# Line 173  void dev_show_list(vm_instance_t *vm) Line 189  void dev_show_list(vm_instance_t *vm)
189  }  }
190    
191  /* device access function */  /* device access function */
192  void *dev_access(cpu_mips_t *cpu,u_int dev_id,m_uint32_t offset,  void *dev_access(cpu_gen_t *cpu,u_int dev_id,m_uint32_t offset,
193                   u_int op_size,u_int op_type,m_uint64_t *data)                   u_int op_size,u_int op_type,m_uint64_t *data)
194  {  {
195     struct vdevice *dev = cpu->vm->dev_array[dev_id];     struct vdevice *dev = cpu->vm->dev_array[dev_id];
# Line 204  struct vdevice *dev_remap(char *name,str Line 220  struct vdevice *dev_remap(char *name,str
220     if (!(dev = dev_create(name)))     if (!(dev = dev_create(name)))
221        return NULL;        return NULL;
222    
223     dev->phys_addr = paddr;     dev->phys_addr  = paddr;
224     dev->phys_len  = len;     dev->phys_len   = len;
225     dev->flags     = orig->flags | VDEVICE_FLAG_REMAP;     dev->flags      = orig->flags | VDEVICE_FLAG_REMAP;
226     dev->fd        = orig->fd;     dev->fd         = orig->fd;
227     dev->host_addr = orig->host_addr;     dev->host_addr  = orig->host_addr;
228     dev->handler   = orig->handler;     dev->handler    = orig->handler;
229       dev->sparse_map = orig->sparse_map;
230     return dev;     return dev;
231  }  }
232    
233  /* Create a RAM device */  /* Create a RAM device */
234  struct vdevice *dev_create_ram(vm_instance_t *vm,char *name,char *filename,  struct vdevice *dev_create_ram(vm_instance_t *vm,char *name,
235                                   int sparse,char *filename,
236                                 m_uint64_t paddr,m_uint32_t len)                                 m_uint64_t paddr,m_uint32_t len)
237  {  {
238     struct vdevice *dev;     struct vdevice *dev;
# Line 227  struct vdevice *dev_create_ram(vm_instan Line 245  struct vdevice *dev_create_ram(vm_instan
245     dev->phys_len = len;     dev->phys_len = len;
246     dev->flags = VDEVICE_FLAG_CACHING;     dev->flags = VDEVICE_FLAG_CACHING;
247    
248     if (filename) {     if (!sparse) {
249        dev->fd = memzone_create_file(filename,dev->phys_len,&ram_ptr);        if (filename) {
250             dev->fd = memzone_create_file(filename,dev->phys_len,&ram_ptr);
251        if (dev->fd == -1) {  
252           perror("dev_create_ram: mmap");           if (dev->fd == -1) {
253                perror("dev_create_ram: mmap");
254                free(dev);
255                return NULL;
256             }
257          
258             dev->host_addr = (m_iptr_t)ram_ptr;
259          } else {
260             dev->host_addr = (m_iptr_t)m_memalign(4096,dev->phys_len);
261          }
262      
263          if (!dev->host_addr) {
264           free(dev);           free(dev);
265           return NULL;           return NULL;
266        }        }
         
       dev->host_addr = (m_iptr_t)ram_ptr;  
267     } else {     } else {
268        dev->host_addr = (m_iptr_t)m_memalign(4096,dev->phys_len);        dev_sparse_init(dev);
    }  
     
    if (!dev->host_addr) {  
       free(dev);  
       return NULL;  
269     }     }
270    
271     vm_bind_device(vm,dev);     vm_bind_device(vm,dev);
# Line 252  struct vdevice *dev_create_ram(vm_instan Line 274  struct vdevice *dev_create_ram(vm_instan
274    
275  /* Create a ghosted RAM device */  /* Create a ghosted RAM device */
276  struct vdevice *  struct vdevice *
277  dev_create_ghost_ram(vm_instance_t *vm,char *name,char *filename,  dev_create_ghost_ram(vm_instance_t *vm,char *name,int sparse,char *filename,
278                       m_uint64_t paddr,m_uint32_t len)                       m_uint64_t paddr,m_uint32_t len)
279  {  {
280     struct vdevice *dev;     struct vdevice *dev;
# Line 263  dev_create_ghost_ram(vm_instance_t *vm,c Line 285  dev_create_ghost_ram(vm_instance_t *vm,c
285    
286     dev->phys_addr = paddr;     dev->phys_addr = paddr;
287     dev->phys_len = len;     dev->phys_len = len;
288     dev->flags = VDEVICE_FLAG_CACHING;     dev->flags = VDEVICE_FLAG_CACHING|VDEVICE_FLAG_GHOST;
289    
290     dev->fd = memzone_open_cow_file(filename,dev->phys_len,&ram_ptr);     if (!sparse) {
291     if (dev->fd == -1) {        dev->fd = memzone_open_cow_file(filename,dev->phys_len,&ram_ptr);
292        perror("dev_create_ghost_ram: mmap");        if (dev->fd == -1) {
293        free(dev);           perror("dev_create_ghost_ram: mmap");
294        return NULL;           free(dev);
295     }           return NULL;
296          }
297          
298          if (!(dev->host_addr = (m_iptr_t)ram_ptr)) {
299             free(dev);
300             return NULL;
301          }
302       } else {
303          if (vm_ghost_image_get(filename,&ram_ptr,&dev->fd) == -1) {
304             free(dev);
305             return NULL;
306          }
307    
308     if (!(dev->host_addr = (m_iptr_t)ram_ptr)) {        dev->host_addr = (m_iptr_t)ram_ptr;
309        free(dev);        dev_sparse_init(dev);
       return NULL;  
310     }     }
311    
312     vm_bind_device(vm,dev);     vm_bind_device(vm,dev);
# Line 294  struct vdevice *dev_create_ram_alias(vm_ Line 326  struct vdevice *dev_create_ram_alias(vm_
326        return NULL;        return NULL;
327     }     }
328    
    if (orig_dev->fd == -1) {  
       fprintf(stderr,"VM%u: dev_create_ram_alias: device %s has no FD.\n",  
               vm->instance_id,orig_dev->name);  
       return NULL;  
    }  
   
329     if (!(dev = dev_remap(name,orig_dev,paddr,len))) {     if (!(dev = dev_remap(name,orig_dev,paddr,len))) {
330        fprintf(stderr,"VM%u: dev_create_ram_alias: unable to create "        fprintf(stderr,"VM%u: dev_create_ram_alias: unable to create "
331                "new device %s.\n",vm->instance_id,name);                "new device %s.\n",vm->instance_id,name);
# Line 310  struct vdevice *dev_create_ram_alias(vm_ Line 336  struct vdevice *dev_create_ram_alias(vm_
336     return dev;     return dev;
337  }  }
338    
339    /* Initialize a sparse device */
340    int dev_sparse_init(struct vdevice *dev)
341    {
342       u_int i,nr_pages;
343       size_t len;
344    
345       /* create the sparse mapping */
346       nr_pages = normalize_size(dev->phys_len,VM_PAGE_SIZE,VM_PAGE_SHIFT);
347       len = nr_pages * sizeof(m_iptr_t);
348    
349       if (!(dev->sparse_map = malloc(len)))
350          return(-1);
351    
352       if (!dev->host_addr) {
353          memset(dev->sparse_map,0,len);
354       } else {
355          for(i=0;i<nr_pages;i++)
356             dev->sparse_map[i] = dev->host_addr + (i << VM_PAGE_SHIFT);
357       }
358    
359       dev->flags |= VDEVICE_FLAG_SPARSE;
360       return(0);
361    }
362    
363    /* Shutdown sparse device structures */
364    int dev_sparse_shutdown(struct vdevice *dev)
365    {
366       if (!(dev->flags & VDEVICE_FLAG_SPARSE))
367          return(-1);
368    
369       free(dev->sparse_map);
370       dev->sparse_map = NULL;
371       return(0);
372    }
373    
374    /* Show info about a sparse device */
375    int dev_sparse_show_info(struct vdevice *dev)
376    {
377       u_int i,nr_pages,dirty_pages;
378    
379       printf("Sparse information for device '%s':\n",dev->name);
380    
381       if (!(dev->flags & VDEVICE_FLAG_SPARSE)) {
382          printf("This is not a sparse device.\n");
383          return(-1);
384       }
385    
386       if (!dev->sparse_map) {
387          printf("No sparse map.\n");
388          return(-1);
389       }
390    
391       nr_pages = normalize_size(dev->phys_len,VM_PAGE_SIZE,VM_PAGE_SHIFT);
392       dirty_pages = 0;
393      
394       for(i=0;i<nr_pages;i++)
395          if (dev->sparse_map[i] & VDEVICE_PTE_DIRTY)
396             dirty_pages++;
397    
398       printf("%u dirty pages on a total of %u pages.\n",dirty_pages,nr_pages);
399       return(0);
400    }
401    
402    /* Get an host address for a sparse device */
403    m_iptr_t dev_sparse_get_host_addr(vm_instance_t *vm,struct vdevice *dev,
404                                      m_uint64_t paddr,u_int op_type,int *cow)
405    {
406       m_iptr_t ptr,ptr_new;
407       u_int offset;
408    
409       offset = (paddr - dev->phys_addr) >> VM_PAGE_SHIFT;
410       ptr = dev->sparse_map[offset];
411       *cow = 0;
412    
413       /*
414        * If the device is not in COW mode, allocate a host page if the physical
415        * page is requested for the first time.
416        */
417       if (!dev->host_addr) {
418          if (!(ptr & VDEVICE_PTE_DIRTY)) {
419             ptr = (m_iptr_t)vm_alloc_host_page(vm);
420             assert(ptr);
421    
422             dev->sparse_map[offset] = ptr | VDEVICE_PTE_DIRTY;
423             return(ptr);
424          }
425    
426          return(ptr & VM_PAGE_MASK);
427       }
428    
429       /*
430        * We have a "ghost" base. We apply the copy-on-write (COW) mechanism
431        * ourselves.
432        */
433       if (ptr & VDEVICE_PTE_DIRTY)
434          return(ptr & VM_PAGE_MASK);
435    
436       if (op_type == MTS_READ) {
437          *cow = 1;
438          return(ptr & VM_PAGE_MASK);
439       }
440    
441       /* Write attempt on a "ghost" page. Duplicate it */
442       ptr_new = (m_iptr_t)vm_alloc_host_page(vm);
443       assert(ptr_new);
444    
445       memcpy((void *)ptr_new,(void *)(ptr & VM_PAGE_MASK),VM_PAGE_SIZE);
446       dev->sparse_map[offset] = ptr_new | VDEVICE_PTE_DIRTY;
447       return(ptr_new);
448    }
449    
450  /* dummy console handler */  /* dummy console handler */
451  static void *dummy_console_handler(cpu_mips_t *cpu,struct vdevice *dev,  static void *dummy_console_handler(cpu_gen_t *cpu,struct vdevice *dev,
452                                     m_uint32_t offset,u_int op_size,                                     m_uint32_t offset,u_int op_size,
453                                     u_int op_type,m_uint64_t *data)                                     u_int op_type,m_uint64_t *data)
454  {  {

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

  ViewVC Help
Powered by ViewVC 1.1.26