static int xpv_drv_init(void) { if (xpv_feature(XPVF_HYPERCALLS) < 0 || xpv_feature(XPVF_SHARED_INFO) < 0) return (-1); /* Set up the grant tables. */ gnttab_init(); /* Set up event channel support */ if (ec_init() != 0) return (-1); /* Set up xenbus */ xb_addr = vmem_alloc(heap_arena, MMU_PAGESIZE, VM_SLEEP); xs_early_init(); xs_domu_init(); /* Set up for suspend/resume/migrate */ xen_shutdown_tq = taskq_create("shutdown_taskq", 1, maxclsyspri - 1, 1, 1, TASKQ_PREPOPULATE); shutdown_watch.node = "control/shutdown"; shutdown_watch.callback = xen_shutdown_handler; if (register_xenbus_watch(&shutdown_watch)) cmn_err(CE_WARN, "Failed to set shutdown watcher"); return (0); }
static int __gnttab_init(void) { /* Delay grant-table initialization in the PV on HVM case */ if (xen_hvm_domain()) return 0; if (!xen_pv_domain()) return -ENODEV; return gnttab_init(); }
static int xenbus_probe(device_t dev) { int err = 0; DPRINTK(""); /* Initialize the interface to xenstore. */ err = xs_init(); if (err) { log(LOG_WARNING, "XENBUS: Error initializing xenstore comms: %i\n", err); return (ENXIO); } err = gnttab_init(); if (err) { log(LOG_WARNING, "XENBUS: Error initializing grant table: %i\n", err); return (ENXIO); } device_set_desc(dev, "Xen Devices"); return (0); }
static int __devinit platform_pci_init(struct pci_dev *pdev, const struct pci_device_id *ent) { int i, ret; long ioaddr; long mmio_addr, mmio_len; unsigned int max_nr_gframes; i = pci_enable_device(pdev); if (i) return i; ioaddr = pci_resource_start(pdev, 0); mmio_addr = pci_resource_start(pdev, 1); mmio_len = pci_resource_len(pdev, 1); if (mmio_addr == 0 || ioaddr == 0) { dev_err(&pdev->dev, "no resources found\n"); ret = -ENOENT; goto pci_out; } ret = pci_request_region(pdev, 1, DRV_NAME); if (ret < 0) goto pci_out; ret = pci_request_region(pdev, 0, DRV_NAME); if (ret < 0) goto mem_out; platform_mmio = mmio_addr; platform_mmiolen = mmio_len; if (!xen_have_vector_callback) { ret = xen_allocate_irq(pdev); if (ret) { dev_warn(&pdev->dev, "request_irq failed err=%d\n", ret); goto out; } callback_via = get_callback_via(pdev); ret = xen_set_callback_via(callback_via); if (ret) { dev_warn(&pdev->dev, "Unable to set the evtchn callback " "err=%d\n", ret); goto out; } } max_nr_gframes = gnttab_max_grant_frames(); xen_hvm_resume_frames = alloc_xen_mmio(PAGE_SIZE * max_nr_gframes); ret = gnttab_init(); if (ret) goto out; xenbus_probe(NULL); return 0; out: pci_release_region(pdev, 0); mem_out: pci_release_region(pdev, 1); pci_out: pci_disable_device(pdev); return ret; }
static int __init xen_guest_init(void) { struct xen_add_to_physmap xatp; static struct shared_info *shared_info_page = 0; struct device_node *node; int len; const char *s = NULL; const char *version = NULL; const char *xen_prefix = "xen,xen-"; struct resource res; node = of_find_compatible_node(NULL, NULL, "xen,xen"); if (!node) { pr_debug("No Xen support\n"); return 0; } s = of_get_property(node, "compatible", &len); if (strlen(xen_prefix) + 3 < len && !strncmp(xen_prefix, s, strlen(xen_prefix))) version = s + strlen(xen_prefix); if (version == NULL) { pr_debug("Xen version not found\n"); return 0; } if (of_address_to_resource(node, GRANT_TABLE_PHYSADDR, &res)) return 0; xen_hvm_resume_frames = res.start >> PAGE_SHIFT; xen_events_irq = irq_of_parse_and_map(node, 0); pr_info("Xen %s support found, events_irq=%d gnttab_frame_pfn=%lx\n", version, xen_events_irq, xen_hvm_resume_frames); xen_domain_type = XEN_HVM_DOMAIN; xen_setup_features(); if (xen_feature(XENFEAT_dom0)) xen_start_info->flags |= SIF_INITDOMAIN|SIF_PRIVILEGED; else xen_start_info->flags &= ~(SIF_INITDOMAIN|SIF_PRIVILEGED); if (!shared_info_page) shared_info_page = (struct shared_info *) get_zeroed_page(GFP_KERNEL); if (!shared_info_page) { pr_err("not enough memory\n"); return -ENOMEM; } xatp.domid = DOMID_SELF; xatp.idx = 0; xatp.space = XENMAPSPACE_shared_info; xatp.gpfn = __pa(shared_info_page) >> PAGE_SHIFT; if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp)) BUG(); HYPERVISOR_shared_info = (struct shared_info *)shared_info_page; /* xen_vcpu is a pointer to the vcpu_info struct in the shared_info * page, we use it in the event channel upcall and in some pvclock * related functions. * The shared info contains exactly 1 CPU (the boot CPU). The guest * is required to use VCPUOP_register_vcpu_info to place vcpu info * for secondary CPUs as they are brought up. * For uniformity we use VCPUOP_register_vcpu_info even on cpu0. */ xen_vcpu_info = __alloc_percpu(sizeof(struct vcpu_info), sizeof(struct vcpu_info)); if (xen_vcpu_info == NULL) return -ENOMEM; gnttab_init(); if (!xen_initial_domain()) xenbus_probe(NULL); return 0; }