Diff for /qemu/xen-all.c between versions 1.1.1.2 and 1.1.1.3

version 1.1.1.2, 2018/04/24 19:17:40 version 1.1.1.3, 2018/04/24 19:34:57
Line 4 Line 4
  * This work is licensed under the terms of the GNU GPL, version 2.  See   * This work is licensed under the terms of the GNU GPL, version 2.  See
  * the COPYING file in the top-level directory.   * the COPYING file in the top-level directory.
  *   *
    * Contributions after 2012-01-13 are licensed under the terms of the
    * GNU GPL, version 2 or (at your option) any later version.
  */   */
   
 #include <sys/mman.h>  #include <sys/mman.h>
Line 16 Line 18
 #include "range.h"  #include "range.h"
 #include "xen-mapcache.h"  #include "xen-mapcache.h"
 #include "trace.h"  #include "trace.h"
   #include "exec-memory.h"
   
 #include <xen/hvm/ioreq.h>  #include <xen/hvm/ioreq.h>
 #include <xen/hvm/params.h>  #include <xen/hvm/params.h>
Line 31 Line 34
     do { } while (0)      do { } while (0)
 #endif  #endif
   
   static MemoryRegion ram_memory, ram_640k, ram_lo, ram_hi;
   static MemoryRegion *framebuffer;
   
 /* Compatibility with older version */  /* Compatibility with older version */
 #if __XEN_LATEST_INTERFACE_VERSION__ < 0x0003020a  #if __XEN_LATEST_INTERFACE_VERSION__ < 0x0003020a
 static inline uint32_t xen_vcpu_eport(shared_iopage_t *shared_page, int i)  static inline uint32_t xen_vcpu_eport(shared_iopage_t *shared_page, int i)
Line 53  static inline ioreq_t *xen_vcpu_ioreq(sh Line 59  static inline ioreq_t *xen_vcpu_ioreq(sh
 }  }
 #  define FMT_ioreq_size "u"  #  define FMT_ioreq_size "u"
 #endif  #endif
   #ifndef HVM_PARAM_BUFIOREQ_EVTCHN
   #define HVM_PARAM_BUFIOREQ_EVTCHN 26
   #endif
   
 #define BUFFER_IO_MAX_DELAY  100  #define BUFFER_IO_MAX_DELAY  100
   
 typedef struct XenPhysmap {  typedef struct XenPhysmap {
     target_phys_addr_t start_addr;      target_phys_addr_t start_addr;
     ram_addr_t size;      ram_addr_t size;
       char *name;
     target_phys_addr_t phys_offset;      target_phys_addr_t phys_offset;
   
     QLIST_ENTRY(XenPhysmap) list;      QLIST_ENTRY(XenPhysmap) list;
Line 70  typedef struct XenIOState { Line 80  typedef struct XenIOState {
     QEMUTimer *buffered_io_timer;      QEMUTimer *buffered_io_timer;
     /* the evtchn port for polling the notification, */      /* the evtchn port for polling the notification, */
     evtchn_port_t *ioreq_local_port;      evtchn_port_t *ioreq_local_port;
       /* evtchn local port for buffered io */
       evtchn_port_t bufioreq_local_port;
     /* the evtchn fd for polling */      /* the evtchn fd for polling */
     XenEvtchn xce_handle;      XenEvtchn xce_handle;
     /* which vcpu we are serving */      /* which vcpu we are serving */
     int send_vcpu;      int send_vcpu;
   
     struct xs_handle *xenstore;      struct xs_handle *xenstore;
     CPUPhysMemoryClient client;      MemoryListener memory_listener;
     QLIST_HEAD(, XenPhysmap) physmap;      QLIST_HEAD(, XenPhysmap) physmap;
       target_phys_addr_t free_phys_offset;
     const XenPhysmap *log_for_dirtybit;      const XenPhysmap *log_for_dirtybit;
   
     Notifier exit;      Notifier exit;
       Notifier suspend;
 } XenIOState;  } XenIOState;
   
 /* Xen specific function for piix pci */  /* Xen specific function for piix pci */
Line 113  void xen_piix_pci_write_config_client(ui Line 127  void xen_piix_pci_write_config_client(ui
     }      }
 }  }
   
 void xen_cmos_set_s3_resume(void *opaque, int irq, int level)  void xen_hvm_inject_msi(uint64_t addr, uint32_t data)
 {  {
     pc_cmos_set_s3_resume(opaque, irq, level);      xen_xc_hvm_inject_msi(xen_xc, xen_domid, addr, data);
     if (level) {  }
         xc_set_hvm_param(xen_xc, xen_domid, HVM_PARAM_ACPI_S_STATE, 3);  
     }  static void xen_suspend_notifier(Notifier *notifier, void *data)
   {
       xc_set_hvm_param(xen_xc, xen_domid, HVM_PARAM_ACPI_S_STATE, 3);
 }  }
   
 /* Xen Interrupt Controller */  /* Xen Interrupt Controller */
Line 137  qemu_irq *xen_interrupt_controller_init( Line 153  qemu_irq *xen_interrupt_controller_init(
   
 static void xen_ram_init(ram_addr_t ram_size)  static void xen_ram_init(ram_addr_t ram_size)
 {  {
     RAMBlock *new_block;      MemoryRegion *sysmem = get_system_memory();
     ram_addr_t below_4g_mem_size, above_4g_mem_size = 0;      ram_addr_t below_4g_mem_size, above_4g_mem_size = 0;
       ram_addr_t block_len;
   
     new_block = g_malloc0(sizeof (*new_block));      block_len = ram_size;
     pstrcpy(new_block->idstr, sizeof (new_block->idstr), "xen.ram");  
     new_block->host = NULL;  
     new_block->offset = 0;  
     new_block->length = ram_size;  
     if (ram_size >= HVM_BELOW_4G_RAM_END) {      if (ram_size >= HVM_BELOW_4G_RAM_END) {
         /* Xen does not allocate the memory continuously, and keep a hole at          /* Xen does not allocate the memory continuously, and keep a hole at
          * HVM_BELOW_4G_MMIO_START of HVM_BELOW_4G_MMIO_LENGTH           * HVM_BELOW_4G_MMIO_START of HVM_BELOW_4G_MMIO_LENGTH
          */           */
         new_block->length += HVM_BELOW_4G_MMIO_LENGTH;          block_len += HVM_BELOW_4G_MMIO_LENGTH;
     }      }
       memory_region_init_ram(&ram_memory, "xen.ram", block_len);
     QLIST_INSERT_HEAD(&ram_list.blocks, new_block, next);      vmstate_register_ram_global(&ram_memory);
   
     ram_list.phys_dirty = g_realloc(ram_list.phys_dirty,  
                                        new_block->length >> TARGET_PAGE_BITS);  
     memset(ram_list.phys_dirty + (new_block->offset >> TARGET_PAGE_BITS),  
            0xff, new_block->length >> TARGET_PAGE_BITS);  
   
     if (ram_size >= HVM_BELOW_4G_RAM_END) {      if (ram_size >= HVM_BELOW_4G_RAM_END) {
         above_4g_mem_size = ram_size - HVM_BELOW_4G_RAM_END;          above_4g_mem_size = ram_size - HVM_BELOW_4G_RAM_END;
Line 166  static void xen_ram_init(ram_addr_t ram_ Line 174  static void xen_ram_init(ram_addr_t ram_
         below_4g_mem_size = ram_size;          below_4g_mem_size = ram_size;
     }      }
   
     cpu_register_physical_memory(0, 0xa0000, 0);      memory_region_init_alias(&ram_640k, "xen.ram.640k",
                                &ram_memory, 0, 0xa0000);
       memory_region_add_subregion(sysmem, 0, &ram_640k);
     /* Skip of the VGA IO memory space, it will be registered later by the VGA      /* Skip of the VGA IO memory space, it will be registered later by the VGA
      * emulated device.       * emulated device.
      *       *
      * The area between 0xc0000 and 0x100000 will be used by SeaBIOS to load       * The area between 0xc0000 and 0x100000 will be used by SeaBIOS to load
      * the Options ROM, so it is registered here as RAM.       * the Options ROM, so it is registered here as RAM.
      */       */
     cpu_register_physical_memory(0xc0000, below_4g_mem_size - 0xc0000,      memory_region_init_alias(&ram_lo, "xen.ram.lo",
                                  0xc0000);                               &ram_memory, 0xc0000, below_4g_mem_size - 0xc0000);
       memory_region_add_subregion(sysmem, 0xc0000, &ram_lo);
     if (above_4g_mem_size > 0) {      if (above_4g_mem_size > 0) {
         cpu_register_physical_memory(0x100000000ULL, above_4g_mem_size,          memory_region_init_alias(&ram_hi, "xen.ram.hi",
                                      0x100000000ULL);                                   &ram_memory, 0x100000000ULL,
                                    above_4g_mem_size);
           memory_region_add_subregion(sysmem, 0x100000000ULL, &ram_hi);
     }      }
 }  }
   
 void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size)  void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size, MemoryRegion *mr)
 {  {
     unsigned long nr_pfn;      unsigned long nr_pfn;
     xen_pfn_t *pfn_list;      xen_pfn_t *pfn_list;
     int i;      int i;
   
       if (runstate_check(RUN_STATE_INMIGRATE)) {
           /* RAM already populated in Xen */
           fprintf(stderr, "%s: do not alloc "RAM_ADDR_FMT
                   " bytes of ram at "RAM_ADDR_FMT" when runstate is INMIGRATE\n",
                   __func__, size, ram_addr); 
           return;
       }
   
       if (mr == &ram_memory) {
           return;
       }
   
     trace_xen_ram_alloc(ram_addr, size);      trace_xen_ram_alloc(ram_addr, size);
   
     nr_pfn = size >> TARGET_PAGE_BITS;      nr_pfn = size >> TARGET_PAGE_BITS;
Line 218  static XenPhysmap *get_physmapping(XenIO Line 243  static XenPhysmap *get_physmapping(XenIO
     return NULL;      return NULL;
 }  }
   
   static target_phys_addr_t xen_phys_offset_to_gaddr(target_phys_addr_t start_addr,
                                                      ram_addr_t size, void *opaque)
   {
       target_phys_addr_t addr = start_addr & TARGET_PAGE_MASK;
       XenIOState *xen_io_state = opaque;
       XenPhysmap *physmap = NULL;
   
       QLIST_FOREACH(physmap, &xen_io_state->physmap, list) {
           if (range_covers_byte(physmap->phys_offset, physmap->size, addr)) {
               return physmap->start_addr;
           }
       }
   
       return start_addr;
   }
   
 #if CONFIG_XEN_CTRL_INTERFACE_VERSION >= 340  #if CONFIG_XEN_CTRL_INTERFACE_VERSION >= 340
 static int xen_add_to_physmap(XenIOState *state,  static int xen_add_to_physmap(XenIOState *state,
                               target_phys_addr_t start_addr,                                target_phys_addr_t start_addr,
                               ram_addr_t size,                                ram_addr_t size,
                               target_phys_addr_t phys_offset)                                MemoryRegion *mr,
                                 target_phys_addr_t offset_within_region)
 {  {
     unsigned long i = 0;      unsigned long i = 0;
     int rc = 0;      int rc = 0;
     XenPhysmap *physmap = NULL;      XenPhysmap *physmap = NULL;
     target_phys_addr_t pfn, start_gpfn;      target_phys_addr_t pfn, start_gpfn;
     RAMBlock *block;      target_phys_addr_t phys_offset = memory_region_get_ram_addr(mr);
       char path[80], value[17];
   
     if (get_physmapping(state, start_addr, size)) {      if (get_physmapping(state, start_addr, size)) {
         return 0;          return 0;
Line 241  static int xen_add_to_physmap(XenIOState Line 284  static int xen_add_to_physmap(XenIOState
      * the linear framebuffer to be that region.       * the linear framebuffer to be that region.
      * Avoid tracking any regions that is not videoram and avoid tracking       * Avoid tracking any regions that is not videoram and avoid tracking
      * the legacy vga region. */       * the legacy vga region. */
     QLIST_FOREACH(block, &ram_list.blocks, next) {      if (mr == framebuffer && start_addr > 0xbffff) {
         if (!strcmp(block->idstr, "vga.vram") && block->offset == phys_offset          goto go_physmap;
                 && start_addr > 0xbffff) {  
             goto go_physmap;  
         }  
     }      }
     return -1;      return -1;
   
 go_physmap:  go_physmap:
     DPRINTF("mapping vram to %llx - %llx, from %llx\n",      DPRINTF("mapping vram to %llx - %llx\n", start_addr, start_addr + size);
             start_addr, start_addr + size, phys_offset);  
   
     pfn = phys_offset >> TARGET_PAGE_BITS;      pfn = phys_offset >> TARGET_PAGE_BITS;
     start_gpfn = start_addr >> TARGET_PAGE_BITS;      start_gpfn = start_addr >> TARGET_PAGE_BITS;
Line 271  go_physmap: Line 310  go_physmap:
   
     physmap->start_addr = start_addr;      physmap->start_addr = start_addr;
     physmap->size = size;      physmap->size = size;
       physmap->name = (char *)mr->name;
     physmap->phys_offset = phys_offset;      physmap->phys_offset = phys_offset;
   
     QLIST_INSERT_HEAD(&state->physmap, physmap, list);      QLIST_INSERT_HEAD(&state->physmap, physmap, list);
Line 279  go_physmap: Line 319  go_physmap:
                                    start_addr >> TARGET_PAGE_BITS,                                     start_addr >> TARGET_PAGE_BITS,
                                    (start_addr + size) >> TARGET_PAGE_BITS,                                     (start_addr + size) >> TARGET_PAGE_BITS,
                                    XEN_DOMCTL_MEM_CACHEATTR_WB);                                     XEN_DOMCTL_MEM_CACHEATTR_WB);
   
       snprintf(path, sizeof(path),
               "/local/domain/0/device-model/%d/physmap/%"PRIx64"/start_addr",
               xen_domid, (uint64_t)phys_offset);
       snprintf(value, sizeof(value), "%"PRIx64, (uint64_t)start_addr);
       if (!xs_write(state->xenstore, 0, path, value, strlen(value))) {
           return -1;
       }
       snprintf(path, sizeof(path),
               "/local/domain/0/device-model/%d/physmap/%"PRIx64"/size",
               xen_domid, (uint64_t)phys_offset);
       snprintf(value, sizeof(value), "%"PRIx64, (uint64_t)size);
       if (!xs_write(state->xenstore, 0, path, value, strlen(value))) {
           return -1;
       }
       if (mr->name) {
           snprintf(path, sizeof(path),
                   "/local/domain/0/device-model/%d/physmap/%"PRIx64"/name",
                   xen_domid, (uint64_t)phys_offset);
           if (!xs_write(state->xenstore, 0, path, mr->name, strlen(mr->name))) {
               return -1;
           }
       }
   
     return 0;      return 0;
 }  }
   
Line 330  static int xen_remove_from_physmap(XenIO Line 394  static int xen_remove_from_physmap(XenIO
 static int xen_add_to_physmap(XenIOState *state,  static int xen_add_to_physmap(XenIOState *state,
                               target_phys_addr_t start_addr,                                target_phys_addr_t start_addr,
                               ram_addr_t size,                                ram_addr_t size,
                               target_phys_addr_t phys_offset)                                MemoryRegion *mr,
                                 target_phys_addr_t offset_within_region)
 {  {
     return -ENOSYS;      return -ENOSYS;
 }  }
Line 343  static int xen_remove_from_physmap(XenIO Line 408  static int xen_remove_from_physmap(XenIO
 }  }
 #endif  #endif
   
 static void xen_client_set_memory(struct CPUPhysMemoryClient *client,  static void xen_set_memory(struct MemoryListener *listener,
                                   target_phys_addr_t start_addr,                             MemoryRegionSection *section,
                                   ram_addr_t size,                             bool add)
                                   ram_addr_t phys_offset,  {
                                   bool log_dirty)      XenIOState *state = container_of(listener, XenIOState, memory_listener);
 {      target_phys_addr_t start_addr = section->offset_within_address_space;
     XenIOState *state = container_of(client, XenIOState, client);      ram_addr_t size = section->size;
     ram_addr_t flags = phys_offset & ~TARGET_PAGE_MASK;      bool log_dirty = memory_region_is_logging(section->mr);
     hvmmem_type_t mem_type;      hvmmem_type_t mem_type;
   
     if (!(start_addr != phys_offset      if (!memory_region_is_ram(section->mr)) {
           && ( (log_dirty && flags < IO_MEM_UNASSIGNED)  
                || (!log_dirty && flags == IO_MEM_UNASSIGNED)))) {  
         return;          return;
     }      }
   
     trace_xen_client_set_memory(start_addr, size, phys_offset, log_dirty);      if (!(section->mr != &ram_memory
             && ( (log_dirty && add) || (!log_dirty && !add)))) {
           return;
       }
   
       trace_xen_client_set_memory(start_addr, size, log_dirty);
   
     start_addr &= TARGET_PAGE_MASK;      start_addr &= TARGET_PAGE_MASK;
     size = TARGET_PAGE_ALIGN(size);      size = TARGET_PAGE_ALIGN(size);
     phys_offset &= TARGET_PAGE_MASK;  
   
     switch (flags) {      if (add) {
     case IO_MEM_RAM:          if (!memory_region_is_rom(section->mr)) {
         xen_add_to_physmap(state, start_addr, size, phys_offset);              xen_add_to_physmap(state, start_addr, size,
         break;                                 section->mr, section->offset_within_region);
     case IO_MEM_ROM:          } else {
         mem_type = HVMMEM_ram_ro;              mem_type = HVMMEM_ram_ro;
         if (xc_hvm_set_mem_type(xen_xc, xen_domid, mem_type,              if (xc_hvm_set_mem_type(xen_xc, xen_domid, mem_type,
                                 start_addr >> TARGET_PAGE_BITS,                                      start_addr >> TARGET_PAGE_BITS,
                                 size >> TARGET_PAGE_BITS)) {                                      size >> TARGET_PAGE_BITS)) {
             DPRINTF("xc_hvm_set_mem_type error, addr: "TARGET_FMT_plx"\n",                  DPRINTF("xc_hvm_set_mem_type error, addr: "TARGET_FMT_plx"\n",
                     start_addr);                          start_addr);
               }
         }          }
         break;      } else {
     case IO_MEM_UNASSIGNED:  
         if (xen_remove_from_physmap(state, start_addr, size) < 0) {          if (xen_remove_from_physmap(state, start_addr, size) < 0) {
             DPRINTF("physmapping does not exist at "TARGET_FMT_plx"\n", start_addr);              DPRINTF("physmapping does not exist at "TARGET_FMT_plx"\n", start_addr);
         }          }
         break;  
     }      }
 }  }
   
 static int xen_sync_dirty_bitmap(XenIOState *state,  static void xen_begin(MemoryListener *listener)
                                  target_phys_addr_t start_addr,  {
                                  ram_addr_t size)  }
   
   static void xen_commit(MemoryListener *listener)
   {
   }
   
   static void xen_region_add(MemoryListener *listener,
                              MemoryRegionSection *section)
   {
       xen_set_memory(listener, section, true);
   }
   
   static void xen_region_del(MemoryListener *listener,
                              MemoryRegionSection *section)
   {
       xen_set_memory(listener, section, false);
   }
   
   static void xen_region_nop(MemoryListener *listener,
                              MemoryRegionSection *section)
   {
   }
   
   static void xen_sync_dirty_bitmap(XenIOState *state,
                                     target_phys_addr_t start_addr,
                                     ram_addr_t size)
 {  {
     target_phys_addr_t npages = size >> TARGET_PAGE_BITS;      target_phys_addr_t npages = size >> TARGET_PAGE_BITS;
     target_phys_addr_t vram_offset = 0;  
     const int width = sizeof(unsigned long) * 8;      const int width = sizeof(unsigned long) * 8;
     unsigned long bitmap[(npages + width - 1) / width];      unsigned long bitmap[(npages + width - 1) / width];
     int rc, i, j;      int rc, i, j;
Line 400  static int xen_sync_dirty_bitmap(XenIOSt Line 490  static int xen_sync_dirty_bitmap(XenIOSt
     physmap = get_physmapping(state, start_addr, size);      physmap = get_physmapping(state, start_addr, size);
     if (physmap == NULL) {      if (physmap == NULL) {
         /* not handled */          /* not handled */
         return -1;          return;
     }      }
   
     if (state->log_for_dirtybit == NULL) {      if (state->log_for_dirtybit == NULL) {
         state->log_for_dirtybit = physmap;          state->log_for_dirtybit = physmap;
     } else if (state->log_for_dirtybit != physmap) {      } else if (state->log_for_dirtybit != physmap) {
         return -1;          /* Only one range for dirty bitmap can be tracked. */
           return;
     }      }
     vram_offset = physmap->phys_offset;  
   
     rc = xc_hvm_track_dirty_vram(xen_xc, xen_domid,      rc = xc_hvm_track_dirty_vram(xen_xc, xen_domid,
                                  start_addr >> TARGET_PAGE_BITS, npages,                                   start_addr >> TARGET_PAGE_BITS, npages,
                                  bitmap);                                   bitmap);
     if (rc) {      if (rc < 0) {
         return rc;          if (rc != -ENODATA) {
               fprintf(stderr, "xen: track_dirty_vram failed (0x" TARGET_FMT_plx
                       ", 0x" TARGET_FMT_plx "): %s\n",
                       start_addr, start_addr + size, strerror(-rc));
           }
           return;
     }      }
   
     for (i = 0; i < ARRAY_SIZE(bitmap); i++) {      for (i = 0; i < ARRAY_SIZE(bitmap); i++) {
Line 422  static int xen_sync_dirty_bitmap(XenIOSt Line 517  static int xen_sync_dirty_bitmap(XenIOSt
         while (map != 0) {          while (map != 0) {
             j = ffsl(map) - 1;              j = ffsl(map) - 1;
             map &= ~(1ul << j);              map &= ~(1ul << j);
             cpu_physical_memory_set_dirty(vram_offset + (i * width + j) * TARGET_PAGE_SIZE);              memory_region_set_dirty(framebuffer,
                                       (i * width + j) * TARGET_PAGE_SIZE,
                                       TARGET_PAGE_SIZE);
         };          };
     }      }
   
     return 0;  
 }  }
   
 static int xen_log_start(CPUPhysMemoryClient *client, target_phys_addr_t phys_addr, ram_addr_t size)  static void xen_log_start(MemoryListener *listener,
                             MemoryRegionSection *section)
 {  {
     XenIOState *state = container_of(client, XenIOState, client);      XenIOState *state = container_of(listener, XenIOState, memory_listener);
   
     return xen_sync_dirty_bitmap(state, phys_addr, size);      xen_sync_dirty_bitmap(state, section->offset_within_address_space,
                             section->size);
 }  }
   
 static int xen_log_stop(CPUPhysMemoryClient *client, target_phys_addr_t phys_addr, ram_addr_t size)  static void xen_log_stop(MemoryListener *listener, MemoryRegionSection *section)
 {  {
     XenIOState *state = container_of(client, XenIOState, client);      XenIOState *state = container_of(listener, XenIOState, memory_listener);
   
     state->log_for_dirtybit = NULL;      state->log_for_dirtybit = NULL;
     /* Disable dirty bit tracking */      /* Disable dirty bit tracking */
     return xc_hvm_track_dirty_vram(xen_xc, xen_domid, 0, 0, NULL);      xc_hvm_track_dirty_vram(xen_xc, xen_domid, 0, 0, NULL);
 }  }
   
 static int xen_client_sync_dirty_bitmap(struct CPUPhysMemoryClient *client,  static void xen_log_sync(MemoryListener *listener, MemoryRegionSection *section)
                                         target_phys_addr_t start_addr,  
                                         target_phys_addr_t end_addr)  
 {  {
     XenIOState *state = container_of(client, XenIOState, client);      XenIOState *state = container_of(listener, XenIOState, memory_listener);
   
     return xen_sync_dirty_bitmap(state, start_addr, end_addr - start_addr);      xen_sync_dirty_bitmap(state, section->offset_within_address_space,
                             section->size);
 }  }
   
 static int xen_client_migration_log(struct CPUPhysMemoryClient *client,  static void xen_log_global_start(MemoryListener *listener)
                                     int enable)  
 {  {
     return 0;  
 }  }
   
 static CPUPhysMemoryClient xen_cpu_phys_memory_client = {  static void xen_log_global_stop(MemoryListener *listener)
     .set_memory = xen_client_set_memory,  {
     .sync_dirty_bitmap = xen_client_sync_dirty_bitmap,  }
     .migration_log = xen_client_migration_log,  
   static void xen_eventfd_add(MemoryListener *listener,
                               MemoryRegionSection *section,
                               bool match_data, uint64_t data, int fd)
   {
   }
   
   static void xen_eventfd_del(MemoryListener *listener,
                               MemoryRegionSection *section,
                               bool match_data, uint64_t data, int fd)
   {
   }
   
   static MemoryListener xen_memory_listener = {
       .begin = xen_begin,
       .commit = xen_commit,
       .region_add = xen_region_add,
       .region_del = xen_region_del,
       .region_nop = xen_region_nop,
     .log_start = xen_log_start,      .log_start = xen_log_start,
     .log_stop = xen_log_stop,      .log_stop = xen_log_stop,
       .log_sync = xen_log_sync,
       .log_global_start = xen_log_global_start,
       .log_global_stop = xen_log_global_stop,
       .eventfd_add = xen_eventfd_add,
       .eventfd_del = xen_eventfd_del,
       .priority = 10,
 };  };
   
 /* VCPU Operations, MMIO, IO ring ... */  /* VCPU Operations, MMIO, IO ring ... */
   
 static void xen_reset_vcpu(void *opaque)  static void xen_reset_vcpu(void *opaque)
 {  {
     CPUState *env = opaque;      CPUArchState *env = opaque;
   
     env->halted = 1;      env->halted = 1;
 }  }
   
 void xen_vcpu_init(void)  void xen_vcpu_init(void)
 {  {
     CPUState *first_cpu;      CPUArchState *first_cpu;
   
     if ((first_cpu = qemu_get_cpu(0))) {      if ((first_cpu = qemu_get_cpu(0))) {
         qemu_register_reset(xen_reset_vcpu, first_cpu);          qemu_register_reset(xen_reset_vcpu, first_cpu);
         xen_reset_vcpu(first_cpu);          xen_reset_vcpu(first_cpu);
     }      }
       /* if rtc_clock is left to default (host_clock), disable it */
       if (rtc_clock == host_clock) {
           qemu_clock_enable(rtc_clock, false);
       }
 }  }
   
 /* get the ioreq packets from share mem */  /* get the ioreq packets from share mem */
Line 516  static ioreq_t *cpu_get_ioreq(XenIOState Line 638  static ioreq_t *cpu_get_ioreq(XenIOState
     evtchn_port_t port;      evtchn_port_t port;
   
     port = xc_evtchn_pending(state->xce_handle);      port = xc_evtchn_pending(state->xce_handle);
       if (port == state->bufioreq_local_port) {
           qemu_mod_timer(state->buffered_io_timer,
                   BUFFER_IO_MAX_DELAY + qemu_get_clock_ms(rt_clock));
           return NULL;
       }
   
     if (port != -1) {      if (port != -1) {
         for (i = 0; i < smp_cpus; i++) {          for (i = 0; i < smp_cpus; i++) {
             if (state->ioreq_local_port[i] == port) {              if (state->ioreq_local_port[i] == port) {
Line 664  static void handle_ioreq(ioreq_t *req) Line 792  static void handle_ioreq(ioreq_t *req)
     }      }
 }  }
   
 static void handle_buffered_iopage(XenIOState *state)  static int handle_buffered_iopage(XenIOState *state)
 {  {
     buf_ioreq_t *buf_req = NULL;      buf_ioreq_t *buf_req = NULL;
     ioreq_t req;      ioreq_t req;
     int qw;      int qw;
   
     if (!state->buffered_io_page) {      if (!state->buffered_io_page) {
         return;          return 0;
     }      }
   
       memset(&req, 0x00, sizeof(req));
   
     while (state->buffered_io_page->read_pointer != state->buffered_io_page->write_pointer) {      while (state->buffered_io_page->read_pointer != state->buffered_io_page->write_pointer) {
         buf_req = &state->buffered_io_page->buf_ioreq[          buf_req = &state->buffered_io_page->buf_ioreq[
             state->buffered_io_page->read_pointer % IOREQ_BUFFER_SLOT_NUM];              state->buffered_io_page->read_pointer % IOREQ_BUFFER_SLOT_NUM];
Line 698  static void handle_buffered_iopage(XenIO Line 828  static void handle_buffered_iopage(XenIO
         xen_mb();          xen_mb();
         state->buffered_io_page->read_pointer += qw ? 2 : 1;          state->buffered_io_page->read_pointer += qw ? 2 : 1;
     }      }
   
       return req.count;
 }  }
   
 static void handle_buffered_io(void *opaque)  static void handle_buffered_io(void *opaque)
 {  {
     XenIOState *state = opaque;      XenIOState *state = opaque;
   
     handle_buffered_iopage(state);      if (handle_buffered_iopage(state)) {
     qemu_mod_timer(state->buffered_io_timer,          qemu_mod_timer(state->buffered_io_timer,
                    BUFFER_IO_MAX_DELAY + qemu_get_clock_ms(rt_clock));                  BUFFER_IO_MAX_DELAY + qemu_get_clock_ms(rt_clock));
       } else {
           qemu_del_timer(state->buffered_io_timer);
           xc_evtchn_unmask(state->xce_handle, state->bufioreq_local_port);
       }
 }  }
   
 static void cpu_handle_ioreq(void *opaque)  static void cpu_handle_ioreq(void *opaque)
Line 724  static void cpu_handle_ioreq(void *opaqu Line 860  static void cpu_handle_ioreq(void *opaqu
                     "data: %"PRIx64", count: %" FMT_ioreq_size ", size: %" FMT_ioreq_size "\n",                      "data: %"PRIx64", count: %" FMT_ioreq_size ", size: %" FMT_ioreq_size "\n",
                     req->state, req->data_is_ptr, req->addr,                      req->state, req->data_is_ptr, req->addr,
                     req->data, req->count, req->size);                      req->data, req->count, req->size);
             destroy_hvm_domain();              destroy_hvm_domain(false);
             return;              return;
         }          }
   
Line 738  static void cpu_handle_ioreq(void *opaqu Line 874  static void cpu_handle_ioreq(void *opaqu
          */           */
         if (runstate_is_running()) {          if (runstate_is_running()) {
             if (qemu_shutdown_requested_get()) {              if (qemu_shutdown_requested_get()) {
                 destroy_hvm_domain();                  destroy_hvm_domain(false);
             }              }
             if (qemu_reset_requested_get()) {              if (qemu_reset_requested_get()) {
                 qemu_system_reset(VMRESET_REPORT);                  qemu_system_reset(VMRESET_REPORT);
                   destroy_hvm_domain(true);
             }              }
         }          }
   
Line 836  static void xen_main_loop_prepare(XenIOS Line 973  static void xen_main_loop_prepare(XenIOS
   
     state->buffered_io_timer = qemu_new_timer_ms(rt_clock, handle_buffered_io,      state->buffered_io_timer = qemu_new_timer_ms(rt_clock, handle_buffered_io,
                                                  state);                                                   state);
     qemu_mod_timer(state->buffered_io_timer, qemu_get_clock_ms(rt_clock));  
   
     if (evtchn_fd != -1) {      if (evtchn_fd != -1) {
         qemu_set_fd_handler(evtchn_fd, cpu_handle_ioreq, NULL, state);          qemu_set_fd_handler(evtchn_fd, cpu_handle_ioreq, NULL, state);
Line 884  int xen_init(void) Line 1020  int xen_init(void)
     return 0;      return 0;
 }  }
   
   static void xen_read_physmap(XenIOState *state)
   {
       XenPhysmap *physmap = NULL;
       unsigned int len, num, i;
       char path[80], *value = NULL;
       char **entries = NULL;
   
       snprintf(path, sizeof(path),
               "/local/domain/0/device-model/%d/physmap", xen_domid);
       entries = xs_directory(state->xenstore, 0, path, &num);
       if (entries == NULL)
           return;
   
       for (i = 0; i < num; i++) {
           physmap = g_malloc(sizeof (XenPhysmap));
           physmap->phys_offset = strtoull(entries[i], NULL, 16);
           snprintf(path, sizeof(path),
                   "/local/domain/0/device-model/%d/physmap/%s/start_addr",
                   xen_domid, entries[i]);
           value = xs_read(state->xenstore, 0, path, &len);
           if (value == NULL) {
               free(physmap);
               continue;
           }
           physmap->start_addr = strtoull(value, NULL, 16);
           free(value);
   
           snprintf(path, sizeof(path),
                   "/local/domain/0/device-model/%d/physmap/%s/size",
                   xen_domid, entries[i]);
           value = xs_read(state->xenstore, 0, path, &len);
           if (value == NULL) {
               free(physmap);
               continue;
           }
           physmap->size = strtoull(value, NULL, 16);
           free(value);
   
           snprintf(path, sizeof(path),
                   "/local/domain/0/device-model/%d/physmap/%s/name",
                   xen_domid, entries[i]);
           physmap->name = xs_read(state->xenstore, 0, path, &len);
   
           QLIST_INSERT_HEAD(&state->physmap, physmap, list);
       }
       free(entries);
       return;
   }
   
 int xen_hvm_init(void)  int xen_hvm_init(void)
 {  {
     int i, rc;      int i, rc;
     unsigned long ioreq_pfn;      unsigned long ioreq_pfn;
       unsigned long bufioreq_evtchn;
     XenIOState *state;      XenIOState *state;
   
     state = g_malloc0(sizeof (XenIOState));      state = g_malloc0(sizeof (XenIOState));
Line 907  int xen_hvm_init(void) Line 1093  int xen_hvm_init(void)
     state->exit.notify = xen_exit_notifier;      state->exit.notify = xen_exit_notifier;
     qemu_add_exit_notifier(&state->exit);      qemu_add_exit_notifier(&state->exit);
   
       state->suspend.notify = xen_suspend_notifier;
       qemu_register_suspend_notifier(&state->suspend);
   
     xc_get_hvm_param(xen_xc, xen_domid, HVM_PARAM_IOREQ_PFN, &ioreq_pfn);      xc_get_hvm_param(xen_xc, xen_domid, HVM_PARAM_IOREQ_PFN, &ioreq_pfn);
     DPRINTF("shared page at pfn %lx\n", ioreq_pfn);      DPRINTF("shared page at pfn %lx\n", ioreq_pfn);
     state->shared_page = xc_map_foreign_range(xen_xc, xen_domid, XC_PAGE_SIZE,      state->shared_page = xc_map_foreign_range(xen_xc, xen_domid, XC_PAGE_SIZE,
Line 937  int xen_hvm_init(void) Line 1126  int xen_hvm_init(void)
         state->ioreq_local_port[i] = rc;          state->ioreq_local_port[i] = rc;
     }      }
   
       rc = xc_get_hvm_param(xen_xc, xen_domid, HVM_PARAM_BUFIOREQ_EVTCHN,
               &bufioreq_evtchn);
       if (rc < 0) {
           fprintf(stderr, "failed to get HVM_PARAM_BUFIOREQ_EVTCHN\n");
           return -1;
       }
       rc = xc_evtchn_bind_interdomain(state->xce_handle, xen_domid,
               (uint32_t)bufioreq_evtchn);
       if (rc == -1) {
           fprintf(stderr, "bind interdomain ioctl error %d\n", errno);
           return -1;
       }
       state->bufioreq_local_port = rc;
   
     /* Init RAM management */      /* Init RAM management */
     xen_map_cache_init();      xen_map_cache_init(xen_phys_offset_to_gaddr, state);
     xen_ram_init(ram_size);      xen_ram_init(ram_size);
   
     qemu_add_vm_change_state_handler(xen_hvm_change_state_handler, state);      qemu_add_vm_change_state_handler(xen_hvm_change_state_handler, state);
   
     state->client = xen_cpu_phys_memory_client;      state->memory_listener = xen_memory_listener;
     QLIST_INIT(&state->physmap);      QLIST_INIT(&state->physmap);
     cpu_register_phys_memory_client(&state->client);      memory_listener_register(&state->memory_listener, get_system_memory());
     state->log_for_dirtybit = NULL;      state->log_for_dirtybit = NULL;
   
     /* Initialize backend core & drivers */      /* Initialize backend core & drivers */
Line 956  int xen_hvm_init(void) Line 1159  int xen_hvm_init(void)
     xen_be_register("console", &xen_console_ops);      xen_be_register("console", &xen_console_ops);
     xen_be_register("vkbd", &xen_kbdmouse_ops);      xen_be_register("vkbd", &xen_kbdmouse_ops);
     xen_be_register("qdisk", &xen_blkdev_ops);      xen_be_register("qdisk", &xen_blkdev_ops);
       xen_read_physmap(state);
   
     return 0;      return 0;
 }  }
   
 void destroy_hvm_domain(void)  void destroy_hvm_domain(bool reboot)
 {  {
     XenXC xc_handle;      XenXC xc_handle;
     int sts;      int sts;
Line 969  void destroy_hvm_domain(void) Line 1173  void destroy_hvm_domain(void)
     if (xc_handle == XC_HANDLER_INITIAL_VALUE) {      if (xc_handle == XC_HANDLER_INITIAL_VALUE) {
         fprintf(stderr, "Cannot acquire xenctrl handle\n");          fprintf(stderr, "Cannot acquire xenctrl handle\n");
     } else {      } else {
         sts = xc_domain_shutdown(xc_handle, xen_domid, SHUTDOWN_poweroff);          sts = xc_domain_shutdown(xc_handle, xen_domid,
                                    reboot ? SHUTDOWN_reboot : SHUTDOWN_poweroff);
         if (sts != 0) {          if (sts != 0) {
             fprintf(stderr, "? xc_domain_shutdown failed to issue poweroff, "              fprintf(stderr, "xc_domain_shutdown failed to issue %s, "
                     "sts %d, %s\n", sts, strerror(errno));                      "sts %d, %s\n", reboot ? "reboot" : "poweroff",
                       sts, strerror(errno));
         } else {          } else {
             fprintf(stderr, "Issued domain %d poweroff\n", xen_domid);              fprintf(stderr, "Issued domain %d %s\n", xen_domid,
                       reboot ? "reboot" : "poweroff");
         }          }
         xc_interface_close(xc_handle);          xc_interface_close(xc_handle);
     }      }
 }  }
   
   void xen_register_framebuffer(MemoryRegion *mr)
   {
       framebuffer = mr;
   }

Removed from v.1.1.1.2  
changed lines
  Added in v.1.1.1.3


unix.superglobalmegacorp.com