Exemplo n.º 1
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(WAKECODE_PADDR(sc));

	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 */
}
Exemplo n.º 2
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 {