Exemplo n.º 1
0
/* Full PV mode suspension. */
static void
xctrl_suspend()
{
	int i, j, k, fpp, suspend_cancelled;
	unsigned long max_pfn, start_info_mfn;

	EVENTHANDLER_INVOKE(power_suspend);

#ifdef SMP
	struct thread *td;
	cpuset_t map;
	u_int cpuid;

	/*
	 * Bind us to CPU 0 and stop any other VCPUs.
	 */
	td = curthread;
	thread_lock(td);
	sched_bind(td, 0);
	thread_unlock(td);
	cpuid = PCPU_GET(cpuid);
	KASSERT(cpuid == 0, ("xen_suspend: not running on cpu 0"));

	map = all_cpus;
	CPU_CLR(cpuid, &map);
	CPU_NAND(&map, &stopped_cpus);
	if (!CPU_EMPTY(&map))
		stop_cpus(map);
#endif

	/*
	 * Be sure to hold Giant across DEVICE_SUSPEND/RESUME since non-MPSAFE
	 * drivers need this.
	 */
	mtx_lock(&Giant);
	if (DEVICE_SUSPEND(root_bus) != 0) {
		mtx_unlock(&Giant);
		printf("%s: device_suspend failed\n", __func__);
#ifdef SMP
		if (!CPU_EMPTY(&map))
			restart_cpus(map);
#endif
		return;
	}
	mtx_unlock(&Giant);

	local_irq_disable();

	xencons_suspend();
	gnttab_suspend();
	intr_suspend();

	max_pfn = HYPERVISOR_shared_info->arch.max_pfn;

	void *shared_info = HYPERVISOR_shared_info;
	HYPERVISOR_shared_info = NULL;
	pmap_kremove((vm_offset_t) shared_info);
	PT_UPDATES_FLUSH();

	xen_start_info->store_mfn = MFNTOPFN(xen_start_info->store_mfn);
	xen_start_info->console.domU.mfn = MFNTOPFN(xen_start_info->console.domU.mfn);

	/*
	 * We'll stop somewhere inside this hypercall. When it returns,
	 * we'll start resuming after the restore.
	 */
	start_info_mfn = VTOMFN(xen_start_info);
	pmap_suspend();
	suspend_cancelled = HYPERVISOR_suspend(start_info_mfn);
	pmap_resume();

	pmap_kenter_ma((vm_offset_t) shared_info, xen_start_info->shared_info);
	HYPERVISOR_shared_info = shared_info;

	HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list =
		VTOMFN(xen_pfn_to_mfn_frame_list_list);
  
	fpp = PAGE_SIZE/sizeof(unsigned long);
	for (i = 0, j = 0, k = -1; i < max_pfn; i += fpp, j++) {
		if ((j % fpp) == 0) {
			k++;
			xen_pfn_to_mfn_frame_list_list[k] = 
				VTOMFN(xen_pfn_to_mfn_frame_list[k]);
			j = 0;
		}
		xen_pfn_to_mfn_frame_list[k][j] = 
			VTOMFN(&xen_phys_machine[i]);
	}
	HYPERVISOR_shared_info->arch.max_pfn = max_pfn;

	gnttab_resume();
	intr_resume(suspend_cancelled != 0);
	local_irq_enable();
	xencons_resume();

#ifdef CONFIG_SMP
	for_each_cpu(i)
		vcpu_prepare(i);

#endif

	/* 
	 * Only resume xenbus /after/ we've prepared our VCPUs; otherwise
	 * the VCPU hotplug callback can race with our vcpu_prepare
	 */
	mtx_lock(&Giant);
	DEVICE_RESUME(root_bus);
	mtx_unlock(&Giant);

#ifdef SMP
	thread_lock(curthread);
	sched_unbind(curthread);
	thread_unlock(curthread);
	if (!CPU_EMPTY(&map))
		restart_cpus(map);
#endif
	EVENTHANDLER_INVOKE(power_resume);
}
Exemplo n.º 2
0
/*
 * Initialize the BIOS32 interface.
 */
void
bios32_init(void)
{
#if 0	/* XXXfvdl need to set up compatibility segment for this */
	paddr_t entry = 0;
	void *p;
	unsigned char cksum;
	int i;

	for (p = (void *)ISA_HOLE_VADDR(BIOS32_START);
	     p < (void *)ISA_HOLE_VADDR(BIOS32_END);
	     p += 16) {
		if (*(int *)p != BIOS32_MAKESIG('_', '3', '2', '_'))
			continue;

		cksum = 0;
		for (i = 0; i < 16; i++)
			cksum += *(unsigned char *)(p + i);
		if (cksum != 0)
			continue;

		if (*(p + 9) != 1)
			continue;

		entry = *(uint32_t *)(p + 4);

		aprint_verbose("BIOS32 rev. %d found at 0x%lx\n",
		    *(p + 8), entry);

		if (entry < BIOS32_START ||
		    entry >= BIOS32_END) {
			aprint_error("BIOS32 entry point outside "
			    "allowable range\n");
			entry = 0;
		}
		break;
	}

	if (entry != 0) {
		bios32_entry.offset = (void *)ISA_HOLE_VADDR(entry);
		bios32_entry.segment = GSEL(GCODE_SEL, SEL_KPL);
	}
#endif
	uint8_t *p;
	int i;

	/* see if we have SMBIOS extentions */
	for (p = ISA_HOLE_VADDR(SMBIOS_START);
	    p < (uint8_t *)ISA_HOLE_VADDR(SMBIOS_END); p+= 16) {
		struct smbhdr * sh = (struct smbhdr *)p;
		uint8_t chksum;
		vaddr_t eva;
		paddr_t pa, end;

		if (sh->sig != BIOS32_MAKESIG('_', 'S', 'M', '_'))
			continue;
		i = sh->len;
		for (chksum = 0; i--; )
			chksum += p[i];
		if (chksum != 0)
			continue;
		p += 0x10;
		if (p[0] != '_' && p[1] != 'D' && p[2] != 'M' &&
		    p[3] != 'I' && p[4] != '_')
			continue;
		for (chksum = 0, i = 0xf; i--; )
			chksum += p[i];
		if (chksum != 0)
			continue;

		pa = trunc_page(sh->addr);
		end = round_page(sh->addr + sh->size);
		eva = uvm_km_alloc(kernel_map, end - pa, 0, UVM_KMF_VAONLY);
		if (eva == 0)
			break;

		smbios_entry.addr = (uint8_t *)(eva +
		    (sh->addr & PGOFSET));
		smbios_entry.len = sh->size;
		smbios_entry.mjr = sh->majrev;
		smbios_entry.min = sh->minrev;
		smbios_entry.count = sh->count;

    		for (; pa < end; pa+= NBPG, eva+= NBPG)
#ifdef XEN
			pmap_kenter_ma(eva, pa, VM_PROT_READ, 0);
#else
			pmap_kenter_pa(eva, pa, VM_PROT_READ, 0);
#endif
		pmap_update(pmap_kernel());

		aprint_debug("SMBIOS rev. %d.%d @ 0x%lx (%d entries)\n",
			    sh->majrev, sh->minrev, (u_long)sh->addr,
			    sh->count);

		break;
	}
}