Esempio n. 1
0
int
acpi_sleep_machdep(struct acpi_softc *sc, int state)
{
	ACPI_STATUS	status;

	if (sc->acpi_wakeaddr == 0ul)
		return (-1);	/* couldn't alloc wake memory */

#ifdef SMP
	suspcpus = all_cpus;
	CPU_CLR(PCPU_GET(cpuid), &suspcpus);
#endif

	if (acpi_resume_beep != 0)
		timer_spkr_acquire();

	AcpiSetFirmwareWakingVector(WAKECODE_PADDR(sc));

	intr_suspend();

	if (savectx(susppcbs[0])) {
		fpususpend(suspfpusave[0]);
#ifdef SMP
		if (!CPU_EMPTY(&suspcpus) &&
		    suspend_cpus(suspcpus) == 0) {
			device_printf(sc->acpi_dev, "Failed to suspend APs\n");
			return (0);	/* couldn't sleep */
		}
#endif

		WAKECODE_FIXUP(resume_beep, uint8_t, (acpi_resume_beep != 0));
		WAKECODE_FIXUP(reset_video, uint8_t, (acpi_reset_video != 0));

		WAKECODE_FIXUP(wakeup_pcb, struct pcb *, susppcbs[0]);
		WAKECODE_FIXUP(wakeup_fpusave, void *, suspfpusave[0]);
		WAKECODE_FIXUP(wakeup_gdt, uint16_t,
		    susppcbs[0]->pcb_gdt.rd_limit);
		WAKECODE_FIXUP(wakeup_gdt + 2, uint64_t,
		    susppcbs[0]->pcb_gdt.rd_base);
		WAKECODE_FIXUP(wakeup_cpu, int, 0);

		/* Call ACPICA to enter the desired sleep state */
		if (state == ACPI_STATE_S4 && sc->acpi_s4bios)
			status = AcpiEnterSleepStateS4bios();
		else
			status = AcpiEnterSleepState(state);

		if (status != AE_OK) {
			device_printf(sc->acpi_dev,
			    "AcpiEnterSleepState failed - %s\n",
			    AcpiFormatException(status));
			return (0);	/* couldn't sleep */
		}

		for (;;)
			ia32_pause();
	}

	return (1);	/* wakeup successfully */
}
Esempio n. 2
0
void
cpu_reset()
{
#ifdef SMP
	cpuset_t map;
	u_int cnt;

	if (smp_started) {
		map = all_cpus;
		CPU_CLR(PCPU_GET(cpuid), &map);
		CPU_NAND(&map, &stopped_cpus);
		if (!CPU_EMPTY(&map)) {
			printf("cpu_reset: Stopping other CPUs\n");
			stop_cpus(map);
		}

		if (PCPU_GET(cpuid) != 0) {
			cpu_reset_proxyid = PCPU_GET(cpuid);
			cpustop_restartfunc = cpu_reset_proxy;
			cpu_reset_proxy_active = 0;
			printf("cpu_reset: Restarting BSP\n");

			/* Restart CPU #0. */
			CPU_SETOF(0, &started_cpus);
			wmb();

			cnt = 0;
			while (cpu_reset_proxy_active == 0 && cnt < 10000000) {
				ia32_pause();
				cnt++;	/* Wait for BSP to announce restart */
			}
			if (cpu_reset_proxy_active == 0)
				printf("cpu_reset: Failed to restart BSP\n");
			enable_intr();
			cpu_reset_proxy_active = 2;

			while (1)
				ia32_pause();
			/* NOTREACHED */
		}

		DELAY(1000000);
	}
#endif
	cpu_reset_real();
	/* NOTREACHED */
}
Esempio n. 3
0
static void
cpu_reset_proxy()
{
	cpuset_t tcrp;

	cpu_reset_proxy_active = 1;
	while (cpu_reset_proxy_active == 1)
		ia32_pause(); /* Wait for other cpu to see that we've started */

	CPU_SETOF(cpu_reset_proxyid, &tcrp);
	stop_cpus(tcrp);
	printf("cpu_reset_proxy: Stopped CPU %d\n", cpu_reset_proxyid);
	DELAY(1000000);
	cpu_reset_real();
}
Esempio n. 4
0
static void
smp_targeted_tlb_shootdown(cpuset_t mask, u_int vector, vm_offset_t addr1, vm_offset_t addr2)
{
	int cpu, ncpu, othercpus;
	struct _call_data data;

	othercpus = mp_ncpus - 1;
	if (CPU_ISFULLSET(&mask)) {
		if (othercpus < 1)
			return;
	} else {
		CPU_CLR(PCPU_GET(cpuid), &mask);
		if (CPU_EMPTY(&mask))
			return;
	}
	if (!(read_eflags() & PSL_I))
		panic("%s: interrupts disabled", __func__);
	mtx_lock_spin(&smp_ipi_mtx);
	KASSERT(call_data == NULL, ("call_data isn't null?!"));
	call_data = &data;		
	call_data->func_id = vector;
	call_data->arg1 = addr1;
	call_data->arg2 = addr2;
	atomic_store_rel_int(&smp_tlb_wait, 0);
	if (CPU_ISFULLSET(&mask)) {
		ncpu = othercpus;
		ipi_all_but_self(vector);
	} else {
		ncpu = 0;
		while ((cpu = cpusetobj_ffs(&mask)) != 0) {
			cpu--;
			CPU_CLR(cpu, &mask);
			CTR3(KTR_SMP, "%s: cpu: %d ipi: %x", __func__, cpu,
			    vector);
			ipi_send_cpu(cpu, vector);
			ncpu++;
		}
	}
	while (smp_tlb_wait < ncpu)
		ia32_pause();
	call_data = NULL;
	mtx_unlock_spin(&smp_ipi_mtx);
}
Esempio n. 5
0
/*
 * Flush the TLB on all other CPU's
 */
static void
smp_tlb_shootdown(u_int vector, vm_offset_t addr1, vm_offset_t addr2)
{
	u_int ncpu;
	struct _call_data data;

	ncpu = mp_ncpus - 1;	/* does not shootdown self */
	if (ncpu < 1)
		return;		/* no other cpus */
	if (!(read_eflags() & PSL_I))
		panic("%s: interrupts disabled", __func__);
	mtx_lock_spin(&smp_ipi_mtx);
	KASSERT(call_data == NULL, ("call_data isn't null?!"));
	call_data = &data;
	call_data->func_id = vector;
	call_data->arg1 = addr1;
	call_data->arg2 = addr2;
	atomic_store_rel_int(&smp_tlb_wait, 0);
	ipi_all_but_self(vector);
	while (smp_tlb_wait < ncpu)
		ia32_pause();
	call_data = NULL;
	mtx_unlock_spin(&smp_ipi_mtx);
}
Esempio n. 6
0
/*
 * Handle an IPI_STOP by saving our current context and spinning until we
 * are resumed.
 */
void
cpustop_handler(void)
{
	int cpu;

	cpu = PCPU_GET(cpuid);

	savectx(&stoppcbs[cpu]);

	/* Indicate that we are stopped */
	CPU_SET_ATOMIC(cpu, &stopped_cpus);

	/* Wait for restart */
	while (!CPU_ISSET(cpu, &started_cpus))
	    ia32_pause();

	CPU_CLR_ATOMIC(cpu, &started_cpus);
	CPU_CLR_ATOMIC(cpu, &stopped_cpus);

	if (cpu == 0 && cpustop_restartfunc != NULL) {
		cpustop_restartfunc();
		cpustop_restartfunc = NULL;
	}
}
Esempio n. 7
0
/*
 * AP CPU's call this to initialize themselves.
 */
void
init_secondary(void)
{
	vm_offset_t addr;
	u_int	cpuid;
	int	gsel_tss;
	
	
	/* bootAP is set in start_ap() to our ID. */
	PCPU_SET(currentldt, _default_ldt);
	gsel_tss = GSEL(GPROC0_SEL, SEL_KPL);
#if 0
	gdt[bootAP * NGDT + GPROC0_SEL].sd.sd_type = SDT_SYS386TSS;
#endif
	PCPU_SET(common_tss.tss_esp0, 0); /* not used until after switch */
	PCPU_SET(common_tss.tss_ss0, GSEL(GDATA_SEL, SEL_KPL));
	PCPU_SET(common_tss.tss_ioopt, (sizeof (struct i386tss)) << 16);
#if 0
	PCPU_SET(tss_gdt, &gdt[bootAP * NGDT + GPROC0_SEL].sd);

	PCPU_SET(common_tssd, *PCPU_GET(tss_gdt));
#endif
	PCPU_SET(fsgs_gdt, &gdt[GUFS_SEL].sd);

	/*
	 * Set to a known state:
	 * Set by mpboot.s: CR0_PG, CR0_PE
	 * Set by cpu_setregs: CR0_NE, CR0_MP, CR0_TS, CR0_WP, CR0_AM
	 */
	/*
	 * signal our startup to the BSP.
	 */
	mp_naps++;

	/* Spin until the BSP releases the AP's. */
	while (!aps_ready)
		ia32_pause();

	/* BSP may have changed PTD while we were waiting */
	invltlb();
	for (addr = 0; addr < NKPT * NBPDR - 1; addr += PAGE_SIZE)
		invlpg(addr);

	/* set up FPU state on the AP */
	npxinit();
#if 0
	
	/* set up SSE registers */
	enable_sse();
#endif
#if 0 && defined(PAE)
	/* Enable the PTE no-execute bit. */
	if ((amd_feature & AMDID_NX) != 0) {
		uint64_t msr;

		msr = rdmsr(MSR_EFER) | EFER_NXE;
		wrmsr(MSR_EFER, msr);
	}
#endif
#if 0
	/* A quick check from sanity claus */
	if (PCPU_GET(apic_id) != lapic_id()) {
		printf("SMP: cpuid = %d\n", PCPU_GET(cpuid));
		printf("SMP: actual apic_id = %d\n", lapic_id());
		printf("SMP: correct apic_id = %d\n", PCPU_GET(apic_id));
		panic("cpuid mismatch! boom!!");
	}
#endif
	
	/* Initialize curthread. */
	KASSERT(PCPU_GET(idlethread) != NULL, ("no idle thread"));
	PCPU_SET(curthread, PCPU_GET(idlethread));

	mtx_lock_spin(&ap_boot_mtx);
#if 0
	
	/* Init local apic for irq's */
	lapic_setup(1);
#endif
	smp_cpus++;

	cpuid = PCPU_GET(cpuid);
	CTR1(KTR_SMP, "SMP: AP CPU #%d Launched", cpuid);
	printf("SMP: AP CPU #%d Launched!\n", cpuid);

	/* Determine if we are a logical CPU. */
	if (logical_cpus > 1 && PCPU_GET(apic_id) % logical_cpus != 0)
		CPU_SET(cpuid, &logical_cpus_mask);
	
	/* Determine if we are a hyperthread. */
	if (hyperthreading_cpus > 1 &&
	    PCPU_GET(apic_id) % hyperthreading_cpus != 0)
		CPU_SET(cpuid, &hyperthreading_cpus_mask);
#if 0
	if (bootverbose)
		lapic_dump("AP");
#endif
	if (smp_cpus == mp_ncpus) {
		/* enable IPI's, tlb shootdown, freezes etc */
		atomic_store_rel_int(&smp_started, 1);
		smp_active = 1;	 /* historic */
	}

	mtx_unlock_spin(&ap_boot_mtx);

	/* wait until all the AP's are up */
	while (smp_started == 0)
		ia32_pause();

	PCPU_SET(curthread, PCPU_GET(idlethread));

	/* Start per-CPU event timers. */
	cpu_initclocks_ap();

	/* enter the scheduler */
	sched_throw(NULL);

	panic("scheduler returned us to %s", __func__);
	/* NOTREACHED */
}
Esempio n. 8
0
int
acpi_sleep_machdep(struct acpi_softc *sc, int state)
{
	ACPI_STATUS	status;
	struct pcb	*pcb;

	if (sc->acpi_wakeaddr == 0ul)
		return (-1);	/* couldn't alloc wake memory */

#ifdef SMP
	suspcpus = all_cpus;
	CPU_CLR(PCPU_GET(cpuid), &suspcpus);
#endif

	if (acpi_resume_beep != 0)
		timer_spkr_acquire();

	AcpiSetFirmwareWakingVector(sc->acpi_wakephys, 0);

	intr_suspend();

	pcb = &susppcbs[0]->sp_pcb;
	if (savectx(pcb)) {
#ifdef __amd64__
		fpususpend(susppcbs[0]->sp_fpususpend);
#elif defined(DEV_NPX)
		npxsuspend(susppcbs[0]->sp_fpususpend);
#endif
#ifdef SMP
		if (!CPU_EMPTY(&suspcpus) && suspend_cpus(suspcpus) == 0) {
			device_printf(sc->acpi_dev, "Failed to suspend APs\n");
			return (0);	/* couldn't sleep */
		}
#endif

		WAKECODE_FIXUP(resume_beep, uint8_t, (acpi_resume_beep != 0));
		WAKECODE_FIXUP(reset_video, uint8_t, (acpi_reset_video != 0));

#ifndef __amd64__
		WAKECODE_FIXUP(wakeup_cr4, register_t, pcb->pcb_cr4);
#endif
		WAKECODE_FIXUP(wakeup_pcb, struct pcb *, pcb);
		WAKECODE_FIXUP(wakeup_gdt, uint16_t, pcb->pcb_gdt.rd_limit);
		WAKECODE_FIXUP(wakeup_gdt + 2, uint64_t, pcb->pcb_gdt.rd_base);

		/* Call ACPICA to enter the desired sleep state */
		if (state == ACPI_STATE_S4 && sc->acpi_s4bios)
			status = AcpiEnterSleepStateS4bios();
		else
			status = AcpiEnterSleepState(state);
		if (ACPI_FAILURE(status)) {
			device_printf(sc->acpi_dev,
			    "AcpiEnterSleepState failed - %s\n",
			    AcpiFormatException(status));
			return (0);	/* couldn't sleep */
		}

		for (;;)
			ia32_pause();
	} else {
#ifdef __amd64__
		fpuresume(susppcbs[0]->sp_fpususpend);
#elif defined(DEV_NPX)
		npxresume(susppcbs[0]->sp_fpususpend);
#endif
	}

	return (1);	/* wakeup successfully */
}
int
acpi_sleep_machdep(struct acpi_softc *sc, int state)
{
	struct savefpu	*stopfpu;
#ifdef SMP
	cpumask_t	wakeup_cpus;
#endif
	register_t	cr3, rf;
	ACPI_STATUS	status;
	int		ret;

	ret = -1;

	if (sc->acpi_wakeaddr == 0ul)
		return (ret);

#ifdef SMP
	wakeup_cpus = PCPU_GET(other_cpus);
#endif

	AcpiSetFirmwareWakingVector(WAKECODE_PADDR(sc));

	rf = intr_disable();
	intr_suspend();

	/*
	 * Temporarily switch to the kernel pmap because it provides
	 * an identity mapping (setup at boot) for the low physical
	 * memory region containing the wakeup code.
	 */
	cr3 = rcr3();
	load_cr3(KPML4phys);

	stopfpu = &stopxpcbs[0].xpcb_pcb.pcb_save;
	if (acpi_savecpu(&stopxpcbs[0])) {
		fpugetregs(curthread, stopfpu);

#ifdef SMP
		if (wakeup_cpus != 0 && suspend_cpus(wakeup_cpus) == 0) {
			device_printf(sc->acpi_dev,
			    "Failed to suspend APs: CPU mask = 0x%jx\n",
			    (uintmax_t)(wakeup_cpus & ~stopped_cpus));
			goto out;
		}
#endif

		WAKECODE_FIXUP(resume_beep, uint8_t, (acpi_resume_beep != 0));
		WAKECODE_FIXUP(reset_video, uint8_t, (acpi_reset_video != 0));

		WAKECODE_FIXUP(wakeup_xpcb, struct xpcb *, &stopxpcbs[0]);
		WAKECODE_FIXUP(wakeup_gdt, uint16_t,
		    stopxpcbs[0].xpcb_gdt.rd_limit);
		WAKECODE_FIXUP(wakeup_gdt + 2, uint64_t,
		    stopxpcbs[0].xpcb_gdt.rd_base);
		WAKECODE_FIXUP(wakeup_cpu, int, 0);

		/* Call ACPICA to enter the desired sleep state */
		if (state == ACPI_STATE_S4 && sc->acpi_s4bios)
			status = AcpiEnterSleepStateS4bios();
		else
			status = AcpiEnterSleepState(state);

		if (status != AE_OK) {
			device_printf(sc->acpi_dev,
			    "AcpiEnterSleepState failed - %s\n",
			    AcpiFormatException(status));
			goto out;
		}

		for (;;)
			ia32_pause();
	} else {
Esempio n. 10
0
int
acpi_sleep_machdep(struct acpi_softc *sc, int state)
{
	ACPI_STATUS		status;
	struct pmap		*pm;
	int			ret;
	uint32_t		cr3;
	u_long			ef;

	ret = -1;
	if (sc->acpi_wakeaddr == 0)
		return (ret);

	AcpiSetFirmwareWakingVector(sc->acpi_wakephys);

	ef = intr_disable();
	intr_suspend();

	/*
	 * Temporarily switch to the kernel pmap because it provides an
	 * identity mapping (setup at boot) for the low physical memory
	 * region containing the wakeup code.
	 */
	pm = kernel_pmap;
	cr3 = rcr3();
#ifdef PAE
	load_cr3(vtophys(pm->pm_pdpt));
#else
	load_cr3(vtophys(pm->pm_pdir));
#endif

	ret_addr = 0;
	if (acpi_savecpu()) {
		/* Execute Sleep */

		p_gdt = (struct region_descriptor *)
				(sc->acpi_wakeaddr + physical_gdt);
		p_gdt->rd_limit = saved_gdt.rd_limit;
		p_gdt->rd_base = vtophys(saved_gdt.rd_base);

		WAKECODE_FIXUP(physical_esp, uint32_t, vtophys(r_esp));
		WAKECODE_FIXUP(previous_cr0, uint32_t, r_cr0);
		WAKECODE_FIXUP(previous_cr2, uint32_t, r_cr2);
		WAKECODE_FIXUP(previous_cr3, uint32_t, r_cr3);
		WAKECODE_FIXUP(previous_cr4, uint32_t, r_cr4);

		WAKECODE_FIXUP(resume_beep, uint32_t, acpi_resume_beep);
		WAKECODE_FIXUP(reset_video, uint32_t, acpi_reset_video);

		WAKECODE_FIXUP(previous_tr,  uint16_t, r_tr);
		WAKECODE_BCOPY(previous_gdt, struct region_descriptor, saved_gdt);
		WAKECODE_FIXUP(previous_ldt, uint16_t, saved_ldt);
		WAKECODE_BCOPY(previous_idt, struct region_descriptor, saved_idt);

		WAKECODE_FIXUP(where_to_recover, void *, acpi_restorecpu);

		WAKECODE_FIXUP(previous_ds,  uint16_t, r_ds);
		WAKECODE_FIXUP(previous_es,  uint16_t, r_es);
		WAKECODE_FIXUP(previous_fs,  uint16_t, r_fs);
		WAKECODE_FIXUP(previous_gs,  uint16_t, r_gs);
		WAKECODE_FIXUP(previous_ss,  uint16_t, r_ss);

		if (bootverbose)
			acpi_printcpu();

		/* Call ACPICA to enter the desired sleep state */
		if (state == ACPI_STATE_S4 && sc->acpi_s4bios)
			status = AcpiEnterSleepStateS4bios();
		else
			status = AcpiEnterSleepState(state, acpi_sleep_flags);

		if (status != AE_OK) {
			device_printf(sc->acpi_dev,
				"AcpiEnterSleepState failed - %s\n",
				AcpiFormatException(status));
			goto out;
		}

		for (;;)
			ia32_pause();
	} else {
		pmap_init_pat();
		PCPU_SET(switchtime, 0);
		PCPU_SET(switchticks, ticks);
		if (bootverbose) {
			acpi_savecpu();
			acpi_printcpu();
		}
		ret = 0;
	}

out:
	load_cr3(cr3);
	mca_resume();
	intr_resume();
	intr_restore(ef);

	if (ret == 0 && mem_range_softc.mr_op != NULL &&
	    mem_range_softc.mr_op->reinit != NULL)
		mem_range_softc.mr_op->reinit(&mem_range_softc);

	/* If we beeped, turn it off after a delay. */
	if (acpi_resume_beep)
		timeout(acpi_stop_beep, NULL, 3 * hz);

	return (ret);
}
Esempio n. 11
0
int
acpi_sleep_machdep(struct acpi_softc *sc, int state)
{
	ACPI_STATUS	status;
	struct pcb	*pcb;
#ifdef __amd64__
	struct pcpu *pc;
	int i;
#endif

	if (sc->acpi_wakeaddr == 0ul)
		return (-1);	/* couldn't alloc wake memory */

#ifdef SMP
	suspcpus = all_cpus;
	CPU_CLR(PCPU_GET(cpuid), &suspcpus);
#endif

	if (acpi_resume_beep != 0)
		timer_spkr_acquire();

	AcpiSetFirmwareWakingVector(sc->acpi_wakephys, 0);

	intr_suspend();

	pcb = &susppcbs[0]->sp_pcb;
	if (savectx(pcb)) {
#ifdef __amd64__
		fpususpend(susppcbs[0]->sp_fpususpend);
#else
		npxsuspend(susppcbs[0]->sp_fpususpend);
#endif
#ifdef SMP
		if (!CPU_EMPTY(&suspcpus) && suspend_cpus(suspcpus) == 0) {
			device_printf(sc->acpi_dev, "Failed to suspend APs\n");
			return (0);	/* couldn't sleep */
		}
#endif
#ifdef __amd64__
		hw_ibrs_active = 0;
		hw_ssb_active = 0;
		cpu_stdext_feature3 = 0;
		CPU_FOREACH(i) {
			pc = pcpu_find(i);
			pc->pc_ibpb_set = 0;
		}
#endif

		WAKECODE_FIXUP(resume_beep, uint8_t, (acpi_resume_beep != 0));
		WAKECODE_FIXUP(reset_video, uint8_t, (acpi_reset_video != 0));

#ifdef __amd64__
		WAKECODE_FIXUP(wakeup_efer, uint64_t, rdmsr(MSR_EFER) &
		    ~(EFER_LMA));
#else
		if ((amd_feature & AMDID_NX) != 0)
			WAKECODE_FIXUP(wakeup_efer, uint64_t, rdmsr(MSR_EFER));
		WAKECODE_FIXUP(wakeup_cr4, register_t, pcb->pcb_cr4);
#endif
		WAKECODE_FIXUP(wakeup_pcb, struct pcb *, pcb);
		WAKECODE_FIXUP(wakeup_gdt, uint16_t, pcb->pcb_gdt.rd_limit);
		WAKECODE_FIXUP(wakeup_gdt + 2, uint64_t, pcb->pcb_gdt.rd_base);

#ifdef __i386__
		/*
		 * Map some low memory with virt == phys for ACPI wakecode
		 * to use to jump to high memory after enabling paging. This
		 * is the same as for similar jump in locore, except the
		 * jump is a single instruction, and we know its address
		 * more precisely so only need a single PTD, and we have to
		 * be careful to use the kernel map (PTD[0] is for curthread
		 * which may be a user thread in deprecated APIs).
		 */
		pmap_remap_lowptdi(true);
#endif

		/* Call ACPICA to enter the desired sleep state */
		if (state == ACPI_STATE_S4 && sc->acpi_s4bios)
			status = AcpiEnterSleepStateS4bios();
		else
			status = AcpiEnterSleepState(state);
		if (ACPI_FAILURE(status)) {
			device_printf(sc->acpi_dev,
			    "AcpiEnterSleepState failed - %s\n",
			    AcpiFormatException(status));
			return (0);	/* couldn't sleep */
		}

		if (acpi_susp_bounce)
			resumectx(pcb);

		for (;;)
			ia32_pause();
	} else {