Annotation of qemu/xen-all.c, revision 1.1.1.3

1.1       root        1: /*
                      2:  * Copyright (C) 2010       Citrix Ltd.
                      3:  *
                      4:  * This work is licensed under the terms of the GNU GPL, version 2.  See
                      5:  * the COPYING file in the top-level directory.
                      6:  *
1.1.1.3 ! root        7:  * Contributions after 2012-01-13 are licensed under the terms of the
        !             8:  * GNU GPL, version 2 or (at your option) any later version.
1.1       root        9:  */
                     10: 
                     11: #include <sys/mman.h>
                     12: 
                     13: #include "hw/pci.h"
                     14: #include "hw/pc.h"
                     15: #include "hw/xen_common.h"
                     16: #include "hw/xen_backend.h"
                     17: 
                     18: #include "range.h"
                     19: #include "xen-mapcache.h"
                     20: #include "trace.h"
1.1.1.3 ! root       21: #include "exec-memory.h"
1.1       root       22: 
                     23: #include <xen/hvm/ioreq.h>
                     24: #include <xen/hvm/params.h>
1.1.1.2   root       25: #include <xen/hvm/e820.h>
1.1       root       26: 
                     27: //#define DEBUG_XEN
                     28: 
                     29: #ifdef DEBUG_XEN
                     30: #define DPRINTF(fmt, ...) \
                     31:     do { fprintf(stderr, "xen: " fmt, ## __VA_ARGS__); } while (0)
                     32: #else
                     33: #define DPRINTF(fmt, ...) \
                     34:     do { } while (0)
                     35: #endif
                     36: 
1.1.1.3 ! root       37: static MemoryRegion ram_memory, ram_640k, ram_lo, ram_hi;
        !            38: static MemoryRegion *framebuffer;
        !            39: 
1.1       root       40: /* Compatibility with older version */
                     41: #if __XEN_LATEST_INTERFACE_VERSION__ < 0x0003020a
                     42: static inline uint32_t xen_vcpu_eport(shared_iopage_t *shared_page, int i)
                     43: {
                     44:     return shared_page->vcpu_iodata[i].vp_eport;
                     45: }
                     46: static inline ioreq_t *xen_vcpu_ioreq(shared_iopage_t *shared_page, int vcpu)
                     47: {
                     48:     return &shared_page->vcpu_iodata[vcpu].vp_ioreq;
                     49: }
                     50: #  define FMT_ioreq_size PRIx64
                     51: #else
                     52: static inline uint32_t xen_vcpu_eport(shared_iopage_t *shared_page, int i)
                     53: {
                     54:     return shared_page->vcpu_ioreq[i].vp_eport;
                     55: }
                     56: static inline ioreq_t *xen_vcpu_ioreq(shared_iopage_t *shared_page, int vcpu)
                     57: {
                     58:     return &shared_page->vcpu_ioreq[vcpu];
                     59: }
                     60: #  define FMT_ioreq_size "u"
                     61: #endif
1.1.1.3 ! root       62: #ifndef HVM_PARAM_BUFIOREQ_EVTCHN
        !            63: #define HVM_PARAM_BUFIOREQ_EVTCHN 26
        !            64: #endif
1.1       root       65: 
                     66: #define BUFFER_IO_MAX_DELAY  100
                     67: 
                     68: typedef struct XenPhysmap {
                     69:     target_phys_addr_t start_addr;
                     70:     ram_addr_t size;
1.1.1.3 ! root       71:     char *name;
1.1       root       72:     target_phys_addr_t phys_offset;
                     73: 
                     74:     QLIST_ENTRY(XenPhysmap) list;
                     75: } XenPhysmap;
                     76: 
                     77: typedef struct XenIOState {
                     78:     shared_iopage_t *shared_page;
                     79:     buffered_iopage_t *buffered_io_page;
                     80:     QEMUTimer *buffered_io_timer;
                     81:     /* the evtchn port for polling the notification, */
                     82:     evtchn_port_t *ioreq_local_port;
1.1.1.3 ! root       83:     /* evtchn local port for buffered io */
        !            84:     evtchn_port_t bufioreq_local_port;
1.1       root       85:     /* the evtchn fd for polling */
                     86:     XenEvtchn xce_handle;
                     87:     /* which vcpu we are serving */
                     88:     int send_vcpu;
                     89: 
                     90:     struct xs_handle *xenstore;
1.1.1.3 ! root       91:     MemoryListener memory_listener;
1.1       root       92:     QLIST_HEAD(, XenPhysmap) physmap;
1.1.1.3 ! root       93:     target_phys_addr_t free_phys_offset;
1.1       root       94:     const XenPhysmap *log_for_dirtybit;
                     95: 
                     96:     Notifier exit;
1.1.1.3 ! root       97:     Notifier suspend;
1.1       root       98: } XenIOState;
                     99: 
                    100: /* Xen specific function for piix pci */
                    101: 
                    102: int xen_pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num)
                    103: {
                    104:     return irq_num + ((pci_dev->devfn >> 3) << 2);
                    105: }
                    106: 
                    107: void xen_piix3_set_irq(void *opaque, int irq_num, int level)
                    108: {
                    109:     xc_hvm_set_pci_intx_level(xen_xc, xen_domid, 0, 0, irq_num >> 2,
                    110:                               irq_num & 3, level);
                    111: }
                    112: 
                    113: void xen_piix_pci_write_config_client(uint32_t address, uint32_t val, int len)
                    114: {
                    115:     int i;
                    116: 
                    117:     /* Scan for updates to PCI link routes (0x60-0x63). */
                    118:     for (i = 0; i < len; i++) {
                    119:         uint8_t v = (val >> (8 * i)) & 0xff;
                    120:         if (v & 0x80) {
                    121:             v = 0;
                    122:         }
                    123:         v &= 0xf;
                    124:         if (((address + i) >= 0x60) && ((address + i) <= 0x63)) {
                    125:             xc_hvm_set_pci_link_route(xen_xc, xen_domid, address + i - 0x60, v);
                    126:         }
                    127:     }
                    128: }
                    129: 
1.1.1.3 ! root      130: void xen_hvm_inject_msi(uint64_t addr, uint32_t data)
1.1       root      131: {
1.1.1.3 ! root      132:     xen_xc_hvm_inject_msi(xen_xc, xen_domid, addr, data);
        !           133: }
        !           134: 
        !           135: static void xen_suspend_notifier(Notifier *notifier, void *data)
        !           136: {
        !           137:     xc_set_hvm_param(xen_xc, xen_domid, HVM_PARAM_ACPI_S_STATE, 3);
1.1       root      138: }
                    139: 
                    140: /* Xen Interrupt Controller */
                    141: 
                    142: static void xen_set_irq(void *opaque, int irq, int level)
                    143: {
                    144:     xc_hvm_set_isa_irq_level(xen_xc, xen_domid, irq, level);
                    145: }
                    146: 
                    147: qemu_irq *xen_interrupt_controller_init(void)
                    148: {
                    149:     return qemu_allocate_irqs(xen_set_irq, NULL, 16);
                    150: }
                    151: 
                    152: /* Memory Ops */
                    153: 
                    154: static void xen_ram_init(ram_addr_t ram_size)
                    155: {
1.1.1.3 ! root      156:     MemoryRegion *sysmem = get_system_memory();
1.1       root      157:     ram_addr_t below_4g_mem_size, above_4g_mem_size = 0;
1.1.1.3 ! root      158:     ram_addr_t block_len;
1.1       root      159: 
1.1.1.3 ! root      160:     block_len = ram_size;
1.1.1.2   root      161:     if (ram_size >= HVM_BELOW_4G_RAM_END) {
                    162:         /* Xen does not allocate the memory continuously, and keep a hole at
                    163:          * HVM_BELOW_4G_MMIO_START of HVM_BELOW_4G_MMIO_LENGTH
                    164:          */
1.1.1.3 ! root      165:         block_len += HVM_BELOW_4G_MMIO_LENGTH;
1.1.1.2   root      166:     }
1.1.1.3 ! root      167:     memory_region_init_ram(&ram_memory, "xen.ram", block_len);
        !           168:     vmstate_register_ram_global(&ram_memory);
1.1       root      169: 
1.1.1.2   root      170:     if (ram_size >= HVM_BELOW_4G_RAM_END) {
                    171:         above_4g_mem_size = ram_size - HVM_BELOW_4G_RAM_END;
                    172:         below_4g_mem_size = HVM_BELOW_4G_RAM_END;
1.1       root      173:     } else {
                    174:         below_4g_mem_size = ram_size;
                    175:     }
                    176: 
1.1.1.3 ! root      177:     memory_region_init_alias(&ram_640k, "xen.ram.640k",
        !           178:                              &ram_memory, 0, 0xa0000);
        !           179:     memory_region_add_subregion(sysmem, 0, &ram_640k);
1.1.1.2   root      180:     /* Skip of the VGA IO memory space, it will be registered later by the VGA
                    181:      * emulated device.
                    182:      *
                    183:      * The area between 0xc0000 and 0x100000 will be used by SeaBIOS to load
                    184:      * the Options ROM, so it is registered here as RAM.
                    185:      */
1.1.1.3 ! root      186:     memory_region_init_alias(&ram_lo, "xen.ram.lo",
        !           187:                              &ram_memory, 0xc0000, below_4g_mem_size - 0xc0000);
        !           188:     memory_region_add_subregion(sysmem, 0xc0000, &ram_lo);
1.1       root      189:     if (above_4g_mem_size > 0) {
1.1.1.3 ! root      190:         memory_region_init_alias(&ram_hi, "xen.ram.hi",
        !           191:                                  &ram_memory, 0x100000000ULL,
        !           192:                                  above_4g_mem_size);
        !           193:         memory_region_add_subregion(sysmem, 0x100000000ULL, &ram_hi);
1.1       root      194:     }
                    195: }
                    196: 
1.1.1.3 ! root      197: void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size, MemoryRegion *mr)
1.1       root      198: {
                    199:     unsigned long nr_pfn;
                    200:     xen_pfn_t *pfn_list;
                    201:     int i;
                    202: 
1.1.1.3 ! root      203:     if (runstate_check(RUN_STATE_INMIGRATE)) {
        !           204:         /* RAM already populated in Xen */
        !           205:         fprintf(stderr, "%s: do not alloc "RAM_ADDR_FMT
        !           206:                 " bytes of ram at "RAM_ADDR_FMT" when runstate is INMIGRATE\n",
        !           207:                 __func__, size, ram_addr); 
        !           208:         return;
        !           209:     }
        !           210: 
        !           211:     if (mr == &ram_memory) {
        !           212:         return;
        !           213:     }
        !           214: 
1.1       root      215:     trace_xen_ram_alloc(ram_addr, size);
                    216: 
                    217:     nr_pfn = size >> TARGET_PAGE_BITS;
1.1.1.2   root      218:     pfn_list = g_malloc(sizeof (*pfn_list) * nr_pfn);
1.1       root      219: 
                    220:     for (i = 0; i < nr_pfn; i++) {
                    221:         pfn_list[i] = (ram_addr >> TARGET_PAGE_BITS) + i;
                    222:     }
                    223: 
                    224:     if (xc_domain_populate_physmap_exact(xen_xc, xen_domid, nr_pfn, 0, 0, pfn_list)) {
1.1.1.2   root      225:         hw_error("xen: failed to populate ram at " RAM_ADDR_FMT, ram_addr);
1.1       root      226:     }
                    227: 
1.1.1.2   root      228:     g_free(pfn_list);
1.1       root      229: }
                    230: 
                    231: static XenPhysmap *get_physmapping(XenIOState *state,
                    232:                                    target_phys_addr_t start_addr, ram_addr_t size)
                    233: {
                    234:     XenPhysmap *physmap = NULL;
                    235: 
                    236:     start_addr &= TARGET_PAGE_MASK;
                    237: 
                    238:     QLIST_FOREACH(physmap, &state->physmap, list) {
                    239:         if (range_covers_byte(physmap->start_addr, physmap->size, start_addr)) {
                    240:             return physmap;
                    241:         }
                    242:     }
                    243:     return NULL;
                    244: }
                    245: 
1.1.1.3 ! root      246: static target_phys_addr_t xen_phys_offset_to_gaddr(target_phys_addr_t start_addr,
        !           247:                                                    ram_addr_t size, void *opaque)
        !           248: {
        !           249:     target_phys_addr_t addr = start_addr & TARGET_PAGE_MASK;
        !           250:     XenIOState *xen_io_state = opaque;
        !           251:     XenPhysmap *physmap = NULL;
        !           252: 
        !           253:     QLIST_FOREACH(physmap, &xen_io_state->physmap, list) {
        !           254:         if (range_covers_byte(physmap->phys_offset, physmap->size, addr)) {
        !           255:             return physmap->start_addr;
        !           256:         }
        !           257:     }
        !           258: 
        !           259:     return start_addr;
        !           260: }
        !           261: 
1.1       root      262: #if CONFIG_XEN_CTRL_INTERFACE_VERSION >= 340
                    263: static int xen_add_to_physmap(XenIOState *state,
                    264:                               target_phys_addr_t start_addr,
                    265:                               ram_addr_t size,
1.1.1.3 ! root      266:                               MemoryRegion *mr,
        !           267:                               target_phys_addr_t offset_within_region)
1.1       root      268: {
                    269:     unsigned long i = 0;
                    270:     int rc = 0;
                    271:     XenPhysmap *physmap = NULL;
                    272:     target_phys_addr_t pfn, start_gpfn;
1.1.1.3 ! root      273:     target_phys_addr_t phys_offset = memory_region_get_ram_addr(mr);
        !           274:     char path[80], value[17];
1.1       root      275: 
                    276:     if (get_physmapping(state, start_addr, size)) {
                    277:         return 0;
                    278:     }
                    279:     if (size <= 0) {
                    280:         return -1;
                    281:     }
                    282: 
                    283:     /* Xen can only handle a single dirty log region for now and we want
                    284:      * the linear framebuffer to be that region.
                    285:      * Avoid tracking any regions that is not videoram and avoid tracking
                    286:      * the legacy vga region. */
1.1.1.3 ! root      287:     if (mr == framebuffer && start_addr > 0xbffff) {
        !           288:         goto go_physmap;
1.1       root      289:     }
                    290:     return -1;
                    291: 
                    292: go_physmap:
1.1.1.3 ! root      293:     DPRINTF("mapping vram to %llx - %llx\n", start_addr, start_addr + size);
1.1       root      294: 
                    295:     pfn = phys_offset >> TARGET_PAGE_BITS;
                    296:     start_gpfn = start_addr >> TARGET_PAGE_BITS;
                    297:     for (i = 0; i < size >> TARGET_PAGE_BITS; i++) {
                    298:         unsigned long idx = pfn + i;
                    299:         xen_pfn_t gpfn = start_gpfn + i;
                    300: 
                    301:         rc = xc_domain_add_to_physmap(xen_xc, xen_domid, XENMAPSPACE_gmfn, idx, gpfn);
                    302:         if (rc) {
                    303:             DPRINTF("add_to_physmap MFN %"PRI_xen_pfn" to PFN %"
                    304:                     PRI_xen_pfn" failed: %d\n", idx, gpfn, rc);
                    305:             return -rc;
                    306:         }
                    307:     }
                    308: 
1.1.1.2   root      309:     physmap = g_malloc(sizeof (XenPhysmap));
1.1       root      310: 
                    311:     physmap->start_addr = start_addr;
                    312:     physmap->size = size;
1.1.1.3 ! root      313:     physmap->name = (char *)mr->name;
1.1       root      314:     physmap->phys_offset = phys_offset;
                    315: 
                    316:     QLIST_INSERT_HEAD(&state->physmap, physmap, list);
                    317: 
                    318:     xc_domain_pin_memory_cacheattr(xen_xc, xen_domid,
                    319:                                    start_addr >> TARGET_PAGE_BITS,
                    320:                                    (start_addr + size) >> TARGET_PAGE_BITS,
                    321:                                    XEN_DOMCTL_MEM_CACHEATTR_WB);
1.1.1.3 ! root      322: 
        !           323:     snprintf(path, sizeof(path),
        !           324:             "/local/domain/0/device-model/%d/physmap/%"PRIx64"/start_addr",
        !           325:             xen_domid, (uint64_t)phys_offset);
        !           326:     snprintf(value, sizeof(value), "%"PRIx64, (uint64_t)start_addr);
        !           327:     if (!xs_write(state->xenstore, 0, path, value, strlen(value))) {
        !           328:         return -1;
        !           329:     }
        !           330:     snprintf(path, sizeof(path),
        !           331:             "/local/domain/0/device-model/%d/physmap/%"PRIx64"/size",
        !           332:             xen_domid, (uint64_t)phys_offset);
        !           333:     snprintf(value, sizeof(value), "%"PRIx64, (uint64_t)size);
        !           334:     if (!xs_write(state->xenstore, 0, path, value, strlen(value))) {
        !           335:         return -1;
        !           336:     }
        !           337:     if (mr->name) {
        !           338:         snprintf(path, sizeof(path),
        !           339:                 "/local/domain/0/device-model/%d/physmap/%"PRIx64"/name",
        !           340:                 xen_domid, (uint64_t)phys_offset);
        !           341:         if (!xs_write(state->xenstore, 0, path, mr->name, strlen(mr->name))) {
        !           342:             return -1;
        !           343:         }
        !           344:     }
        !           345: 
1.1       root      346:     return 0;
                    347: }
                    348: 
                    349: static int xen_remove_from_physmap(XenIOState *state,
                    350:                                    target_phys_addr_t start_addr,
                    351:                                    ram_addr_t size)
                    352: {
                    353:     unsigned long i = 0;
                    354:     int rc = 0;
                    355:     XenPhysmap *physmap = NULL;
                    356:     target_phys_addr_t phys_offset = 0;
                    357: 
                    358:     physmap = get_physmapping(state, start_addr, size);
                    359:     if (physmap == NULL) {
                    360:         return -1;
                    361:     }
                    362: 
                    363:     phys_offset = physmap->phys_offset;
                    364:     size = physmap->size;
                    365: 
                    366:     DPRINTF("unmapping vram to %llx - %llx, from %llx\n",
                    367:             phys_offset, phys_offset + size, start_addr);
                    368: 
                    369:     size >>= TARGET_PAGE_BITS;
                    370:     start_addr >>= TARGET_PAGE_BITS;
                    371:     phys_offset >>= TARGET_PAGE_BITS;
                    372:     for (i = 0; i < size; i++) {
                    373:         unsigned long idx = start_addr + i;
                    374:         xen_pfn_t gpfn = phys_offset + i;
                    375: 
                    376:         rc = xc_domain_add_to_physmap(xen_xc, xen_domid, XENMAPSPACE_gmfn, idx, gpfn);
                    377:         if (rc) {
                    378:             fprintf(stderr, "add_to_physmap MFN %"PRI_xen_pfn" to PFN %"
                    379:                     PRI_xen_pfn" failed: %d\n", idx, gpfn, rc);
                    380:             return -rc;
                    381:         }
                    382:     }
                    383: 
                    384:     QLIST_REMOVE(physmap, list);
                    385:     if (state->log_for_dirtybit == physmap) {
                    386:         state->log_for_dirtybit = NULL;
                    387:     }
                    388:     free(physmap);
                    389: 
                    390:     return 0;
                    391: }
                    392: 
                    393: #else
                    394: static int xen_add_to_physmap(XenIOState *state,
                    395:                               target_phys_addr_t start_addr,
                    396:                               ram_addr_t size,
1.1.1.3 ! root      397:                               MemoryRegion *mr,
        !           398:                               target_phys_addr_t offset_within_region)
1.1       root      399: {
                    400:     return -ENOSYS;
                    401: }
                    402: 
                    403: static int xen_remove_from_physmap(XenIOState *state,
                    404:                                    target_phys_addr_t start_addr,
                    405:                                    ram_addr_t size)
                    406: {
                    407:     return -ENOSYS;
                    408: }
                    409: #endif
                    410: 
1.1.1.3 ! root      411: static void xen_set_memory(struct MemoryListener *listener,
        !           412:                            MemoryRegionSection *section,
        !           413:                            bool add)
        !           414: {
        !           415:     XenIOState *state = container_of(listener, XenIOState, memory_listener);
        !           416:     target_phys_addr_t start_addr = section->offset_within_address_space;
        !           417:     ram_addr_t size = section->size;
        !           418:     bool log_dirty = memory_region_is_logging(section->mr);
1.1       root      419:     hvmmem_type_t mem_type;
                    420: 
1.1.1.3 ! root      421:     if (!memory_region_is_ram(section->mr)) {
1.1       root      422:         return;
                    423:     }
                    424: 
1.1.1.3 ! root      425:     if (!(section->mr != &ram_memory
        !           426:           && ( (log_dirty && add) || (!log_dirty && !add)))) {
        !           427:         return;
        !           428:     }
        !           429: 
        !           430:     trace_xen_client_set_memory(start_addr, size, log_dirty);
1.1       root      431: 
                    432:     start_addr &= TARGET_PAGE_MASK;
                    433:     size = TARGET_PAGE_ALIGN(size);
                    434: 
1.1.1.3 ! root      435:     if (add) {
        !           436:         if (!memory_region_is_rom(section->mr)) {
        !           437:             xen_add_to_physmap(state, start_addr, size,
        !           438:                                section->mr, section->offset_within_region);
        !           439:         } else {
        !           440:             mem_type = HVMMEM_ram_ro;
        !           441:             if (xc_hvm_set_mem_type(xen_xc, xen_domid, mem_type,
        !           442:                                     start_addr >> TARGET_PAGE_BITS,
        !           443:                                     size >> TARGET_PAGE_BITS)) {
        !           444:                 DPRINTF("xc_hvm_set_mem_type error, addr: "TARGET_FMT_plx"\n",
        !           445:                         start_addr);
        !           446:             }
1.1       root      447:         }
1.1.1.3 ! root      448:     } else {
1.1       root      449:         if (xen_remove_from_physmap(state, start_addr, size) < 0) {
                    450:             DPRINTF("physmapping does not exist at "TARGET_FMT_plx"\n", start_addr);
                    451:         }
                    452:     }
                    453: }
                    454: 
1.1.1.3 ! root      455: static void xen_begin(MemoryListener *listener)
        !           456: {
        !           457: }
        !           458: 
        !           459: static void xen_commit(MemoryListener *listener)
        !           460: {
        !           461: }
        !           462: 
        !           463: static void xen_region_add(MemoryListener *listener,
        !           464:                            MemoryRegionSection *section)
        !           465: {
        !           466:     xen_set_memory(listener, section, true);
        !           467: }
        !           468: 
        !           469: static void xen_region_del(MemoryListener *listener,
        !           470:                            MemoryRegionSection *section)
        !           471: {
        !           472:     xen_set_memory(listener, section, false);
        !           473: }
        !           474: 
        !           475: static void xen_region_nop(MemoryListener *listener,
        !           476:                            MemoryRegionSection *section)
        !           477: {
        !           478: }
        !           479: 
        !           480: static void xen_sync_dirty_bitmap(XenIOState *state,
        !           481:                                   target_phys_addr_t start_addr,
        !           482:                                   ram_addr_t size)
1.1       root      483: {
                    484:     target_phys_addr_t npages = size >> TARGET_PAGE_BITS;
                    485:     const int width = sizeof(unsigned long) * 8;
                    486:     unsigned long bitmap[(npages + width - 1) / width];
                    487:     int rc, i, j;
                    488:     const XenPhysmap *physmap = NULL;
                    489: 
                    490:     physmap = get_physmapping(state, start_addr, size);
                    491:     if (physmap == NULL) {
                    492:         /* not handled */
1.1.1.3 ! root      493:         return;
1.1       root      494:     }
                    495: 
                    496:     if (state->log_for_dirtybit == NULL) {
                    497:         state->log_for_dirtybit = physmap;
                    498:     } else if (state->log_for_dirtybit != physmap) {
1.1.1.3 ! root      499:         /* Only one range for dirty bitmap can be tracked. */
        !           500:         return;
1.1       root      501:     }
                    502: 
                    503:     rc = xc_hvm_track_dirty_vram(xen_xc, xen_domid,
                    504:                                  start_addr >> TARGET_PAGE_BITS, npages,
                    505:                                  bitmap);
1.1.1.3 ! root      506:     if (rc < 0) {
        !           507:         if (rc != -ENODATA) {
        !           508:             fprintf(stderr, "xen: track_dirty_vram failed (0x" TARGET_FMT_plx
        !           509:                     ", 0x" TARGET_FMT_plx "): %s\n",
        !           510:                     start_addr, start_addr + size, strerror(-rc));
        !           511:         }
        !           512:         return;
1.1       root      513:     }
                    514: 
                    515:     for (i = 0; i < ARRAY_SIZE(bitmap); i++) {
                    516:         unsigned long map = bitmap[i];
                    517:         while (map != 0) {
                    518:             j = ffsl(map) - 1;
                    519:             map &= ~(1ul << j);
1.1.1.3 ! root      520:             memory_region_set_dirty(framebuffer,
        !           521:                                     (i * width + j) * TARGET_PAGE_SIZE,
        !           522:                                     TARGET_PAGE_SIZE);
1.1       root      523:         };
                    524:     }
                    525: }
                    526: 
1.1.1.3 ! root      527: static void xen_log_start(MemoryListener *listener,
        !           528:                           MemoryRegionSection *section)
1.1       root      529: {
1.1.1.3 ! root      530:     XenIOState *state = container_of(listener, XenIOState, memory_listener);
1.1       root      531: 
1.1.1.3 ! root      532:     xen_sync_dirty_bitmap(state, section->offset_within_address_space,
        !           533:                           section->size);
1.1       root      534: }
                    535: 
1.1.1.3 ! root      536: static void xen_log_stop(MemoryListener *listener, MemoryRegionSection *section)
1.1       root      537: {
1.1.1.3 ! root      538:     XenIOState *state = container_of(listener, XenIOState, memory_listener);
1.1       root      539: 
                    540:     state->log_for_dirtybit = NULL;
                    541:     /* Disable dirty bit tracking */
1.1.1.3 ! root      542:     xc_hvm_track_dirty_vram(xen_xc, xen_domid, 0, 0, NULL);
1.1       root      543: }
                    544: 
1.1.1.3 ! root      545: static void xen_log_sync(MemoryListener *listener, MemoryRegionSection *section)
1.1       root      546: {
1.1.1.3 ! root      547:     XenIOState *state = container_of(listener, XenIOState, memory_listener);
1.1       root      548: 
1.1.1.3 ! root      549:     xen_sync_dirty_bitmap(state, section->offset_within_address_space,
        !           550:                           section->size);
1.1       root      551: }
                    552: 
1.1.1.3 ! root      553: static void xen_log_global_start(MemoryListener *listener)
1.1       root      554: {
                    555: }
                    556: 
1.1.1.3 ! root      557: static void xen_log_global_stop(MemoryListener *listener)
        !           558: {
        !           559: }
        !           560: 
        !           561: static void xen_eventfd_add(MemoryListener *listener,
        !           562:                             MemoryRegionSection *section,
        !           563:                             bool match_data, uint64_t data, int fd)
        !           564: {
        !           565: }
        !           566: 
        !           567: static void xen_eventfd_del(MemoryListener *listener,
        !           568:                             MemoryRegionSection *section,
        !           569:                             bool match_data, uint64_t data, int fd)
        !           570: {
        !           571: }
        !           572: 
        !           573: static MemoryListener xen_memory_listener = {
        !           574:     .begin = xen_begin,
        !           575:     .commit = xen_commit,
        !           576:     .region_add = xen_region_add,
        !           577:     .region_del = xen_region_del,
        !           578:     .region_nop = xen_region_nop,
1.1       root      579:     .log_start = xen_log_start,
                    580:     .log_stop = xen_log_stop,
1.1.1.3 ! root      581:     .log_sync = xen_log_sync,
        !           582:     .log_global_start = xen_log_global_start,
        !           583:     .log_global_stop = xen_log_global_stop,
        !           584:     .eventfd_add = xen_eventfd_add,
        !           585:     .eventfd_del = xen_eventfd_del,
        !           586:     .priority = 10,
1.1       root      587: };
                    588: 
                    589: /* VCPU Operations, MMIO, IO ring ... */
                    590: 
                    591: static void xen_reset_vcpu(void *opaque)
                    592: {
1.1.1.3 ! root      593:     CPUArchState *env = opaque;
1.1       root      594: 
                    595:     env->halted = 1;
                    596: }
                    597: 
                    598: void xen_vcpu_init(void)
                    599: {
1.1.1.3 ! root      600:     CPUArchState *first_cpu;
1.1       root      601: 
                    602:     if ((first_cpu = qemu_get_cpu(0))) {
                    603:         qemu_register_reset(xen_reset_vcpu, first_cpu);
                    604:         xen_reset_vcpu(first_cpu);
                    605:     }
1.1.1.3 ! root      606:     /* if rtc_clock is left to default (host_clock), disable it */
        !           607:     if (rtc_clock == host_clock) {
        !           608:         qemu_clock_enable(rtc_clock, false);
        !           609:     }
1.1       root      610: }
                    611: 
                    612: /* get the ioreq packets from share mem */
                    613: static ioreq_t *cpu_get_ioreq_from_shared_memory(XenIOState *state, int vcpu)
                    614: {
                    615:     ioreq_t *req = xen_vcpu_ioreq(state->shared_page, vcpu);
                    616: 
                    617:     if (req->state != STATE_IOREQ_READY) {
                    618:         DPRINTF("I/O request not ready: "
                    619:                 "%x, ptr: %x, port: %"PRIx64", "
                    620:                 "data: %"PRIx64", count: %" FMT_ioreq_size ", size: %" FMT_ioreq_size "\n",
                    621:                 req->state, req->data_is_ptr, req->addr,
                    622:                 req->data, req->count, req->size);
                    623:         return NULL;
                    624:     }
                    625: 
                    626:     xen_rmb(); /* see IOREQ_READY /then/ read contents of ioreq */
                    627: 
                    628:     req->state = STATE_IOREQ_INPROCESS;
                    629:     return req;
                    630: }
                    631: 
                    632: /* use poll to get the port notification */
                    633: /* ioreq_vec--out,the */
                    634: /* retval--the number of ioreq packet */
                    635: static ioreq_t *cpu_get_ioreq(XenIOState *state)
                    636: {
                    637:     int i;
                    638:     evtchn_port_t port;
                    639: 
                    640:     port = xc_evtchn_pending(state->xce_handle);
1.1.1.3 ! root      641:     if (port == state->bufioreq_local_port) {
        !           642:         qemu_mod_timer(state->buffered_io_timer,
        !           643:                 BUFFER_IO_MAX_DELAY + qemu_get_clock_ms(rt_clock));
        !           644:         return NULL;
        !           645:     }
        !           646: 
1.1       root      647:     if (port != -1) {
                    648:         for (i = 0; i < smp_cpus; i++) {
                    649:             if (state->ioreq_local_port[i] == port) {
                    650:                 break;
                    651:             }
                    652:         }
                    653: 
                    654:         if (i == smp_cpus) {
                    655:             hw_error("Fatal error while trying to get io event!\n");
                    656:         }
                    657: 
                    658:         /* unmask the wanted port again */
                    659:         xc_evtchn_unmask(state->xce_handle, port);
                    660: 
                    661:         /* get the io packet from shared memory */
                    662:         state->send_vcpu = i;
                    663:         return cpu_get_ioreq_from_shared_memory(state, i);
                    664:     }
                    665: 
                    666:     /* read error or read nothing */
                    667:     return NULL;
                    668: }
                    669: 
                    670: static uint32_t do_inp(pio_addr_t addr, unsigned long size)
                    671: {
                    672:     switch (size) {
                    673:         case 1:
                    674:             return cpu_inb(addr);
                    675:         case 2:
                    676:             return cpu_inw(addr);
                    677:         case 4:
                    678:             return cpu_inl(addr);
                    679:         default:
                    680:             hw_error("inp: bad size: %04"FMT_pioaddr" %lx", addr, size);
                    681:     }
                    682: }
                    683: 
                    684: static void do_outp(pio_addr_t addr,
                    685:         unsigned long size, uint32_t val)
                    686: {
                    687:     switch (size) {
                    688:         case 1:
                    689:             return cpu_outb(addr, val);
                    690:         case 2:
                    691:             return cpu_outw(addr, val);
                    692:         case 4:
                    693:             return cpu_outl(addr, val);
                    694:         default:
                    695:             hw_error("outp: bad size: %04"FMT_pioaddr" %lx", addr, size);
                    696:     }
                    697: }
                    698: 
                    699: static void cpu_ioreq_pio(ioreq_t *req)
                    700: {
                    701:     int i, sign;
                    702: 
                    703:     sign = req->df ? -1 : 1;
                    704: 
                    705:     if (req->dir == IOREQ_READ) {
                    706:         if (!req->data_is_ptr) {
                    707:             req->data = do_inp(req->addr, req->size);
                    708:         } else {
                    709:             uint32_t tmp;
                    710: 
                    711:             for (i = 0; i < req->count; i++) {
                    712:                 tmp = do_inp(req->addr, req->size);
                    713:                 cpu_physical_memory_write(req->data + (sign * i * req->size),
                    714:                         (uint8_t *) &tmp, req->size);
                    715:             }
                    716:         }
                    717:     } else if (req->dir == IOREQ_WRITE) {
                    718:         if (!req->data_is_ptr) {
                    719:             do_outp(req->addr, req->size, req->data);
                    720:         } else {
                    721:             for (i = 0; i < req->count; i++) {
                    722:                 uint32_t tmp = 0;
                    723: 
                    724:                 cpu_physical_memory_read(req->data + (sign * i * req->size),
                    725:                         (uint8_t*) &tmp, req->size);
                    726:                 do_outp(req->addr, req->size, tmp);
                    727:             }
                    728:         }
                    729:     }
                    730: }
                    731: 
                    732: static void cpu_ioreq_move(ioreq_t *req)
                    733: {
                    734:     int i, sign;
                    735: 
                    736:     sign = req->df ? -1 : 1;
                    737: 
                    738:     if (!req->data_is_ptr) {
                    739:         if (req->dir == IOREQ_READ) {
                    740:             for (i = 0; i < req->count; i++) {
                    741:                 cpu_physical_memory_read(req->addr + (sign * i * req->size),
                    742:                         (uint8_t *) &req->data, req->size);
                    743:             }
                    744:         } else if (req->dir == IOREQ_WRITE) {
                    745:             for (i = 0; i < req->count; i++) {
                    746:                 cpu_physical_memory_write(req->addr + (sign * i * req->size),
                    747:                         (uint8_t *) &req->data, req->size);
                    748:             }
                    749:         }
                    750:     } else {
1.1.1.2   root      751:         uint64_t tmp;
1.1       root      752: 
                    753:         if (req->dir == IOREQ_READ) {
                    754:             for (i = 0; i < req->count; i++) {
                    755:                 cpu_physical_memory_read(req->addr + (sign * i * req->size),
                    756:                         (uint8_t*) &tmp, req->size);
                    757:                 cpu_physical_memory_write(req->data + (sign * i * req->size),
                    758:                         (uint8_t*) &tmp, req->size);
                    759:             }
                    760:         } else if (req->dir == IOREQ_WRITE) {
                    761:             for (i = 0; i < req->count; i++) {
                    762:                 cpu_physical_memory_read(req->data + (sign * i * req->size),
                    763:                         (uint8_t*) &tmp, req->size);
                    764:                 cpu_physical_memory_write(req->addr + (sign * i * req->size),
                    765:                         (uint8_t*) &tmp, req->size);
                    766:             }
                    767:         }
                    768:     }
                    769: }
                    770: 
                    771: static void handle_ioreq(ioreq_t *req)
                    772: {
                    773:     if (!req->data_is_ptr && (req->dir == IOREQ_WRITE) &&
                    774:             (req->size < sizeof (target_ulong))) {
                    775:         req->data &= ((target_ulong) 1 << (8 * req->size)) - 1;
                    776:     }
                    777: 
                    778:     switch (req->type) {
                    779:         case IOREQ_TYPE_PIO:
                    780:             cpu_ioreq_pio(req);
                    781:             break;
                    782:         case IOREQ_TYPE_COPY:
                    783:             cpu_ioreq_move(req);
                    784:             break;
                    785:         case IOREQ_TYPE_TIMEOFFSET:
                    786:             break;
                    787:         case IOREQ_TYPE_INVALIDATE:
                    788:             xen_invalidate_map_cache();
                    789:             break;
                    790:         default:
                    791:             hw_error("Invalid ioreq type 0x%x\n", req->type);
                    792:     }
                    793: }
                    794: 
1.1.1.3 ! root      795: static int handle_buffered_iopage(XenIOState *state)
1.1       root      796: {
                    797:     buf_ioreq_t *buf_req = NULL;
                    798:     ioreq_t req;
                    799:     int qw;
                    800: 
                    801:     if (!state->buffered_io_page) {
1.1.1.3 ! root      802:         return 0;
1.1       root      803:     }
                    804: 
1.1.1.3 ! root      805:     memset(&req, 0x00, sizeof(req));
        !           806: 
1.1       root      807:     while (state->buffered_io_page->read_pointer != state->buffered_io_page->write_pointer) {
                    808:         buf_req = &state->buffered_io_page->buf_ioreq[
                    809:             state->buffered_io_page->read_pointer % IOREQ_BUFFER_SLOT_NUM];
                    810:         req.size = 1UL << buf_req->size;
                    811:         req.count = 1;
                    812:         req.addr = buf_req->addr;
                    813:         req.data = buf_req->data;
                    814:         req.state = STATE_IOREQ_READY;
                    815:         req.dir = buf_req->dir;
                    816:         req.df = 1;
                    817:         req.type = buf_req->type;
                    818:         req.data_is_ptr = 0;
                    819:         qw = (req.size == 8);
                    820:         if (qw) {
                    821:             buf_req = &state->buffered_io_page->buf_ioreq[
                    822:                 (state->buffered_io_page->read_pointer + 1) % IOREQ_BUFFER_SLOT_NUM];
                    823:             req.data |= ((uint64_t)buf_req->data) << 32;
                    824:         }
                    825: 
                    826:         handle_ioreq(&req);
                    827: 
                    828:         xen_mb();
                    829:         state->buffered_io_page->read_pointer += qw ? 2 : 1;
                    830:     }
1.1.1.3 ! root      831: 
        !           832:     return req.count;
1.1       root      833: }
                    834: 
                    835: static void handle_buffered_io(void *opaque)
                    836: {
                    837:     XenIOState *state = opaque;
                    838: 
1.1.1.3 ! root      839:     if (handle_buffered_iopage(state)) {
        !           840:         qemu_mod_timer(state->buffered_io_timer,
        !           841:                 BUFFER_IO_MAX_DELAY + qemu_get_clock_ms(rt_clock));
        !           842:     } else {
        !           843:         qemu_del_timer(state->buffered_io_timer);
        !           844:         xc_evtchn_unmask(state->xce_handle, state->bufioreq_local_port);
        !           845:     }
1.1       root      846: }
                    847: 
                    848: static void cpu_handle_ioreq(void *opaque)
                    849: {
                    850:     XenIOState *state = opaque;
                    851:     ioreq_t *req = cpu_get_ioreq(state);
                    852: 
                    853:     handle_buffered_iopage(state);
                    854:     if (req) {
                    855:         handle_ioreq(req);
                    856: 
                    857:         if (req->state != STATE_IOREQ_INPROCESS) {
                    858:             fprintf(stderr, "Badness in I/O request ... not in service?!: "
                    859:                     "%x, ptr: %x, port: %"PRIx64", "
                    860:                     "data: %"PRIx64", count: %" FMT_ioreq_size ", size: %" FMT_ioreq_size "\n",
                    861:                     req->state, req->data_is_ptr, req->addr,
                    862:                     req->data, req->count, req->size);
1.1.1.3 ! root      863:             destroy_hvm_domain(false);
1.1       root      864:             return;
                    865:         }
                    866: 
                    867:         xen_wmb(); /* Update ioreq contents /then/ update state. */
                    868: 
                    869:         /*
                    870:          * We do this before we send the response so that the tools
                    871:          * have the opportunity to pick up on the reset before the
                    872:          * guest resumes and does a hlt with interrupts disabled which
                    873:          * causes Xen to powerdown the domain.
                    874:          */
1.1.1.2   root      875:         if (runstate_is_running()) {
1.1       root      876:             if (qemu_shutdown_requested_get()) {
1.1.1.3 ! root      877:                 destroy_hvm_domain(false);
1.1       root      878:             }
                    879:             if (qemu_reset_requested_get()) {
                    880:                 qemu_system_reset(VMRESET_REPORT);
1.1.1.3 ! root      881:                 destroy_hvm_domain(true);
1.1       root      882:             }
                    883:         }
                    884: 
                    885:         req->state = STATE_IORESP_READY;
                    886:         xc_evtchn_notify(state->xce_handle, state->ioreq_local_port[state->send_vcpu]);
                    887:     }
                    888: }
                    889: 
                    890: static int store_dev_info(int domid, CharDriverState *cs, const char *string)
                    891: {
                    892:     struct xs_handle *xs = NULL;
                    893:     char *path = NULL;
                    894:     char *newpath = NULL;
                    895:     char *pts = NULL;
                    896:     int ret = -1;
                    897: 
                    898:     /* Only continue if we're talking to a pty. */
                    899:     if (strncmp(cs->filename, "pty:", 4)) {
                    900:         return 0;
                    901:     }
                    902:     pts = cs->filename + 4;
                    903: 
                    904:     /* We now have everything we need to set the xenstore entry. */
                    905:     xs = xs_open(0);
                    906:     if (xs == NULL) {
                    907:         fprintf(stderr, "Could not contact XenStore\n");
                    908:         goto out;
                    909:     }
                    910: 
                    911:     path = xs_get_domain_path(xs, domid);
                    912:     if (path == NULL) {
                    913:         fprintf(stderr, "xs_get_domain_path() error\n");
                    914:         goto out;
                    915:     }
                    916:     newpath = realloc(path, (strlen(path) + strlen(string) +
                    917:                 strlen("/tty") + 1));
                    918:     if (newpath == NULL) {
                    919:         fprintf(stderr, "realloc error\n");
                    920:         goto out;
                    921:     }
                    922:     path = newpath;
                    923: 
                    924:     strcat(path, string);
                    925:     strcat(path, "/tty");
                    926:     if (!xs_write(xs, XBT_NULL, path, pts, strlen(pts))) {
                    927:         fprintf(stderr, "xs_write for '%s' fail", string);
                    928:         goto out;
                    929:     }
                    930:     ret = 0;
                    931: 
                    932: out:
                    933:     free(path);
                    934:     xs_close(xs);
                    935: 
                    936:     return ret;
                    937: }
                    938: 
                    939: void xenstore_store_pv_console_info(int i, CharDriverState *chr)
                    940: {
                    941:     if (i == 0) {
                    942:         store_dev_info(xen_domid, chr, "/console");
                    943:     } else {
                    944:         char buf[32];
                    945:         snprintf(buf, sizeof(buf), "/device/console/%d", i);
                    946:         store_dev_info(xen_domid, chr, buf);
                    947:     }
                    948: }
                    949: 
1.1.1.2   root      950: static void xenstore_record_dm_state(struct xs_handle *xs, const char *state)
1.1       root      951: {
                    952:     char path[50];
                    953: 
1.1.1.2   root      954:     if (xs == NULL) {
                    955:         fprintf(stderr, "xenstore connection not initialized\n");
                    956:         exit(1);
                    957:     }
                    958: 
1.1       root      959:     snprintf(path, sizeof (path), "/local/domain/0/device-model/%u/state", xen_domid);
1.1.1.2   root      960:     if (!xs_write(xs, XBT_NULL, path, state, strlen(state))) {
1.1       root      961:         fprintf(stderr, "error recording dm state\n");
                    962:         exit(1);
                    963:     }
                    964: }
                    965: 
                    966: static void xen_main_loop_prepare(XenIOState *state)
                    967: {
                    968:     int evtchn_fd = -1;
                    969: 
                    970:     if (state->xce_handle != XC_HANDLER_INITIAL_VALUE) {
                    971:         evtchn_fd = xc_evtchn_fd(state->xce_handle);
                    972:     }
                    973: 
                    974:     state->buffered_io_timer = qemu_new_timer_ms(rt_clock, handle_buffered_io,
                    975:                                                  state);
                    976: 
                    977:     if (evtchn_fd != -1) {
                    978:         qemu_set_fd_handler(evtchn_fd, cpu_handle_ioreq, NULL, state);
                    979:     }
                    980: }
                    981: 
                    982: 
                    983: /* Initialise Xen */
                    984: 
1.1.1.2   root      985: static void xen_change_state_handler(void *opaque, int running,
                    986:                                      RunState state)
1.1       root      987: {
                    988:     if (running) {
1.1.1.2   root      989:         /* record state running */
                    990:         xenstore_record_dm_state(xenstore, "running");
                    991:     }
                    992: }
                    993: 
                    994: static void xen_hvm_change_state_handler(void *opaque, int running,
                    995:                                          RunState rstate)
                    996: {
                    997:     XenIOState *xstate = opaque;
                    998:     if (running) {
                    999:         xen_main_loop_prepare(xstate);
1.1       root     1000:     }
                   1001: }
                   1002: 
                   1003: static void xen_exit_notifier(Notifier *n, void *data)
                   1004: {
                   1005:     XenIOState *state = container_of(n, XenIOState, exit);
                   1006: 
                   1007:     xc_evtchn_close(state->xce_handle);
                   1008:     xs_daemon_close(state->xenstore);
                   1009: }
                   1010: 
                   1011: int xen_init(void)
                   1012: {
                   1013:     xen_xc = xen_xc_interface_open(0, 0, 0);
                   1014:     if (xen_xc == XC_HANDLER_INITIAL_VALUE) {
                   1015:         xen_be_printf(NULL, 0, "can't open xen interface\n");
                   1016:         return -1;
                   1017:     }
1.1.1.2   root     1018:     qemu_add_vm_change_state_handler(xen_change_state_handler, NULL);
1.1       root     1019: 
                   1020:     return 0;
                   1021: }
                   1022: 
1.1.1.3 ! root     1023: static void xen_read_physmap(XenIOState *state)
        !          1024: {
        !          1025:     XenPhysmap *physmap = NULL;
        !          1026:     unsigned int len, num, i;
        !          1027:     char path[80], *value = NULL;
        !          1028:     char **entries = NULL;
        !          1029: 
        !          1030:     snprintf(path, sizeof(path),
        !          1031:             "/local/domain/0/device-model/%d/physmap", xen_domid);
        !          1032:     entries = xs_directory(state->xenstore, 0, path, &num);
        !          1033:     if (entries == NULL)
        !          1034:         return;
        !          1035: 
        !          1036:     for (i = 0; i < num; i++) {
        !          1037:         physmap = g_malloc(sizeof (XenPhysmap));
        !          1038:         physmap->phys_offset = strtoull(entries[i], NULL, 16);
        !          1039:         snprintf(path, sizeof(path),
        !          1040:                 "/local/domain/0/device-model/%d/physmap/%s/start_addr",
        !          1041:                 xen_domid, entries[i]);
        !          1042:         value = xs_read(state->xenstore, 0, path, &len);
        !          1043:         if (value == NULL) {
        !          1044:             free(physmap);
        !          1045:             continue;
        !          1046:         }
        !          1047:         physmap->start_addr = strtoull(value, NULL, 16);
        !          1048:         free(value);
        !          1049: 
        !          1050:         snprintf(path, sizeof(path),
        !          1051:                 "/local/domain/0/device-model/%d/physmap/%s/size",
        !          1052:                 xen_domid, entries[i]);
        !          1053:         value = xs_read(state->xenstore, 0, path, &len);
        !          1054:         if (value == NULL) {
        !          1055:             free(physmap);
        !          1056:             continue;
        !          1057:         }
        !          1058:         physmap->size = strtoull(value, NULL, 16);
        !          1059:         free(value);
        !          1060: 
        !          1061:         snprintf(path, sizeof(path),
        !          1062:                 "/local/domain/0/device-model/%d/physmap/%s/name",
        !          1063:                 xen_domid, entries[i]);
        !          1064:         physmap->name = xs_read(state->xenstore, 0, path, &len);
        !          1065: 
        !          1066:         QLIST_INSERT_HEAD(&state->physmap, physmap, list);
        !          1067:     }
        !          1068:     free(entries);
        !          1069:     return;
        !          1070: }
        !          1071: 
1.1       root     1072: int xen_hvm_init(void)
                   1073: {
                   1074:     int i, rc;
                   1075:     unsigned long ioreq_pfn;
1.1.1.3 ! root     1076:     unsigned long bufioreq_evtchn;
1.1       root     1077:     XenIOState *state;
                   1078: 
1.1.1.2   root     1079:     state = g_malloc0(sizeof (XenIOState));
1.1       root     1080: 
                   1081:     state->xce_handle = xen_xc_evtchn_open(NULL, 0);
                   1082:     if (state->xce_handle == XC_HANDLER_INITIAL_VALUE) {
                   1083:         perror("xen: event channel open");
                   1084:         return -errno;
                   1085:     }
                   1086: 
                   1087:     state->xenstore = xs_daemon_open();
                   1088:     if (state->xenstore == NULL) {
                   1089:         perror("xen: xenstore open");
                   1090:         return -errno;
                   1091:     }
                   1092: 
                   1093:     state->exit.notify = xen_exit_notifier;
                   1094:     qemu_add_exit_notifier(&state->exit);
                   1095: 
1.1.1.3 ! root     1096:     state->suspend.notify = xen_suspend_notifier;
        !          1097:     qemu_register_suspend_notifier(&state->suspend);
        !          1098: 
1.1       root     1099:     xc_get_hvm_param(xen_xc, xen_domid, HVM_PARAM_IOREQ_PFN, &ioreq_pfn);
                   1100:     DPRINTF("shared page at pfn %lx\n", ioreq_pfn);
                   1101:     state->shared_page = xc_map_foreign_range(xen_xc, xen_domid, XC_PAGE_SIZE,
                   1102:                                               PROT_READ|PROT_WRITE, ioreq_pfn);
                   1103:     if (state->shared_page == NULL) {
                   1104:         hw_error("map shared IO page returned error %d handle=" XC_INTERFACE_FMT,
                   1105:                  errno, xen_xc);
                   1106:     }
                   1107: 
                   1108:     xc_get_hvm_param(xen_xc, xen_domid, HVM_PARAM_BUFIOREQ_PFN, &ioreq_pfn);
                   1109:     DPRINTF("buffered io page at pfn %lx\n", ioreq_pfn);
                   1110:     state->buffered_io_page = xc_map_foreign_range(xen_xc, xen_domid, XC_PAGE_SIZE,
                   1111:                                                    PROT_READ|PROT_WRITE, ioreq_pfn);
                   1112:     if (state->buffered_io_page == NULL) {
                   1113:         hw_error("map buffered IO page returned error %d", errno);
                   1114:     }
                   1115: 
1.1.1.2   root     1116:     state->ioreq_local_port = g_malloc0(smp_cpus * sizeof (evtchn_port_t));
1.1       root     1117: 
                   1118:     /* FIXME: how about if we overflow the page here? */
                   1119:     for (i = 0; i < smp_cpus; i++) {
                   1120:         rc = xc_evtchn_bind_interdomain(state->xce_handle, xen_domid,
                   1121:                                         xen_vcpu_eport(state->shared_page, i));
                   1122:         if (rc == -1) {
                   1123:             fprintf(stderr, "bind interdomain ioctl error %d\n", errno);
                   1124:             return -1;
                   1125:         }
                   1126:         state->ioreq_local_port[i] = rc;
                   1127:     }
                   1128: 
1.1.1.3 ! root     1129:     rc = xc_get_hvm_param(xen_xc, xen_domid, HVM_PARAM_BUFIOREQ_EVTCHN,
        !          1130:             &bufioreq_evtchn);
        !          1131:     if (rc < 0) {
        !          1132:         fprintf(stderr, "failed to get HVM_PARAM_BUFIOREQ_EVTCHN\n");
        !          1133:         return -1;
        !          1134:     }
        !          1135:     rc = xc_evtchn_bind_interdomain(state->xce_handle, xen_domid,
        !          1136:             (uint32_t)bufioreq_evtchn);
        !          1137:     if (rc == -1) {
        !          1138:         fprintf(stderr, "bind interdomain ioctl error %d\n", errno);
        !          1139:         return -1;
        !          1140:     }
        !          1141:     state->bufioreq_local_port = rc;
        !          1142: 
1.1       root     1143:     /* Init RAM management */
1.1.1.3 ! root     1144:     xen_map_cache_init(xen_phys_offset_to_gaddr, state);
1.1       root     1145:     xen_ram_init(ram_size);
                   1146: 
1.1.1.2   root     1147:     qemu_add_vm_change_state_handler(xen_hvm_change_state_handler, state);
1.1       root     1148: 
1.1.1.3 ! root     1149:     state->memory_listener = xen_memory_listener;
1.1       root     1150:     QLIST_INIT(&state->physmap);
1.1.1.3 ! root     1151:     memory_listener_register(&state->memory_listener, get_system_memory());
1.1       root     1152:     state->log_for_dirtybit = NULL;
                   1153: 
                   1154:     /* Initialize backend core & drivers */
                   1155:     if (xen_be_init() != 0) {
                   1156:         fprintf(stderr, "%s: xen backend core setup failed\n", __FUNCTION__);
                   1157:         exit(1);
                   1158:     }
                   1159:     xen_be_register("console", &xen_console_ops);
                   1160:     xen_be_register("vkbd", &xen_kbdmouse_ops);
                   1161:     xen_be_register("qdisk", &xen_blkdev_ops);
1.1.1.3 ! root     1162:     xen_read_physmap(state);
1.1       root     1163: 
                   1164:     return 0;
                   1165: }
                   1166: 
1.1.1.3 ! root     1167: void destroy_hvm_domain(bool reboot)
1.1       root     1168: {
                   1169:     XenXC xc_handle;
                   1170:     int sts;
                   1171: 
                   1172:     xc_handle = xen_xc_interface_open(0, 0, 0);
                   1173:     if (xc_handle == XC_HANDLER_INITIAL_VALUE) {
                   1174:         fprintf(stderr, "Cannot acquire xenctrl handle\n");
                   1175:     } else {
1.1.1.3 ! root     1176:         sts = xc_domain_shutdown(xc_handle, xen_domid,
        !          1177:                                  reboot ? SHUTDOWN_reboot : SHUTDOWN_poweroff);
1.1       root     1178:         if (sts != 0) {
1.1.1.3 ! root     1179:             fprintf(stderr, "xc_domain_shutdown failed to issue %s, "
        !          1180:                     "sts %d, %s\n", reboot ? "reboot" : "poweroff",
        !          1181:                     sts, strerror(errno));
1.1       root     1182:         } else {
1.1.1.3 ! root     1183:             fprintf(stderr, "Issued domain %d %s\n", xen_domid,
        !          1184:                     reboot ? "reboot" : "poweroff");
1.1       root     1185:         }
                   1186:         xc_interface_close(xc_handle);
                   1187:     }
                   1188: }
1.1.1.3 ! root     1189: 
        !          1190: void xen_register_framebuffer(MemoryRegion *mr)
        !          1191: {
        !          1192:     framebuffer = mr;
        !          1193: }

unix.superglobalmegacorp.com