status_t prepare_sleep_state(uint8 state, void (*wakeFunc)(void), size_t size) { ACPI_STATUS acpiStatus; TRACE("prepare_sleep_state %d, %p, %ld\n", state, wakeFunc, size); if (state != ACPI_POWER_STATE_OFF) { physical_entry wakeVector; status_t status; // Note: The supplied code must already be locked into memory. status = get_memory_map((const void*)wakeFunc, size, &wakeVector, 1); if (status != B_OK) return status; # if B_HAIKU_PHYSICAL_BITS > 32 if (wakeVector.address >= 0x100000000LL) { ERROR("prepare_sleep_state(): ACPI 2.0c says use 32 bit " "vector, but we have a physical address >= 4 GB\n"); } # endif acpiStatus = AcpiSetFirmwareWakingVector(wakeVector.address, wakeVector.address); if (acpiStatus != AE_OK) return B_ERROR; } acpiStatus = AcpiEnterSleepStatePrep(state); if (acpiStatus != AE_OK) return B_ERROR; return B_OK; }
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 */ }
/* * This is what we've all been waiting for! */ int acpi_enter_sleepstate(s3a_t *s3ap) { ACPI_PHYSICAL_ADDRESS wakephys = s3ap->s3a_wakephys; caddr_t wakevirt = rm_platter_va; /*LINTED*/ wakecode_t *wp = (wakecode_t *)wakevirt; uint_t Sx = s3ap->s3a_state; PT(PT_SWV); /* Set waking vector */ if (AcpiSetFirmwareWakingVector(wakephys) != AE_OK) { PT(PT_SWV_FAIL); PMD(PMD_SX, ("Can't SetFirmwareWakingVector(%lx)\n", (long)wakephys)) goto insomnia; }
int acpi_wakeup_machdep(struct acpi_softc *sc, int state, int sleep_result, int intr_enabled) { if (sleep_result == -1) return (sleep_result); if (!intr_enabled) { /* Wakeup MD procedures in interrupt disabled context */ if (sleep_result == 1) { pmap_init_pat(); initializecpu(); PCPU_SET(switchtime, 0); PCPU_SET(switchticks, ticks); #ifdef DEV_APIC lapic_xapic_mode(); #endif #ifdef SMP if (!CPU_EMPTY(&suspcpus)) acpi_wakeup_cpus(sc); #endif } #ifdef SMP if (!CPU_EMPTY(&suspcpus)) restart_cpus(suspcpus); #endif mca_resume(); #ifdef __amd64__ if (vmm_resume_p != NULL) vmm_resume_p(); #endif intr_resume(/*suspend_cancelled*/false); AcpiSetFirmwareWakingVector(0, 0); } else { /* Wakeup MD procedures in interrupt enabled context */ if (sleep_result == 1 && mem_range_softc.mr_op != NULL && mem_range_softc.mr_op->reinit != NULL) mem_range_softc.mr_op->reinit(&mem_range_softc); } return (sleep_result); }
int acpi_wakeup_machdep(struct acpi_softc *sc, int state, int sleep_result, int intr_enabled) { if (sleep_result == -1) return (sleep_result); if (intr_enabled == 0) { /* Wakeup MD procedures in interrupt disabled context */ if (sleep_result == 1) { pmap_init_pat(); load_cr3(susppcbs[0]->pcb_cr3); initializecpu(); PCPU_SET(switchtime, 0); PCPU_SET(switchticks, ticks); #ifdef SMP if (!CPU_EMPTY(&suspcpus)) acpi_wakeup_cpus(sc, &suspcpus); #endif } #ifdef SMP if (!CPU_EMPTY(&suspcpus)) restart_cpus(suspcpus); #endif mca_resume(); intr_resume(); } else { /* Wakeup MD procedures in interrupt enabled context */ AcpiSetFirmwareWakingVector(0); if (sleep_result == 1 && mem_range_softc.mr_op != NULL && mem_range_softc.mr_op->reinit != NULL) mem_range_softc.mr_op->reinit(&mem_range_softc); } return (sleep_result); }
int acpi_sleep_machdep(struct acpi_softc *sc, int state) { ACPI_STATUS status; vm_offset_t oldphys; struct pmap *pm; vm_page_t page; static vm_page_t opage = NULL; int ret = 0; int pteobj_allocated = 0; u_long ef; struct proc *p; if (sc->acpi_wakeaddr == 0) { return (0); } AcpiSetFirmwareWakingVector(sc->acpi_wakephys); ef = read_eflags(); disable_intr(); /* Create Identity Mapping */ if ((p = curproc) == NULL) p = &proc0; pm = vmspace_pmap(p->p_vmspace); if (pm->pm_pteobj == NULL) { pm->pm_pteobj = vm_object_allocate(OBJT_DEFAULT, PTDPTDI + 1); pteobj_allocated = 1; } oldphys = pmap_extract(pm, sc->acpi_wakephys); if (oldphys) { opage = PHYS_TO_VM_PAGE(oldphys); } page = PHYS_TO_VM_PAGE(sc->acpi_wakephys); pmap_enter(pm, sc->acpi_wakephys, page, VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE, 1); ret_addr = 0; if (acpi_savecpu()) { /* Execute Sleep */ p_gdt = (struct region_descriptor *)(sc->acpi_wakeaddr + physical_gdt); p_gdt->rd_limit = r_gdt.rd_limit; p_gdt->rd_base = vtophys(r_gdt.rd_base); WAKECODE_FIXUP(physical_esp, u_int32_t, vtophys(r_esp)); WAKECODE_FIXUP(previous_cr0, u_int32_t, r_cr0); WAKECODE_FIXUP(previous_cr2, u_int32_t, r_cr2); WAKECODE_FIXUP(previous_cr3, u_int32_t, r_cr3); WAKECODE_FIXUP(previous_cr4, u_int32_t, r_cr4); WAKECODE_FIXUP(previous_tr, u_int16_t, r_tr); WAKECODE_BCOPY(previous_gdt, struct region_descriptor, r_gdt); WAKECODE_FIXUP(previous_ldt, u_int16_t, r_ldt); WAKECODE_BCOPY(previous_idt, struct region_descriptor, r_idt); WAKECODE_FIXUP(where_to_recover, void, acpi_restorecpu); WAKECODE_FIXUP(previous_ds, u_int16_t, r_ds); WAKECODE_FIXUP(previous_es, u_int16_t, r_es); WAKECODE_FIXUP(previous_fs, u_int16_t, r_fs); WAKECODE_FIXUP(previous_gs, u_int16_t, r_gs); WAKECODE_FIXUP(previous_ss, u_int16_t, r_ss); if (acpi_get_verbose(sc)) { acpi_printcpu(); } wbinvd(); 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)); ret = -1; goto out; } for (;;) ; } else { /* Execute Wakeup */ #if 0 initializecpu(); #endif icu_reinit(); if (acpi_get_verbose(sc)) { acpi_savecpu(); acpi_printcpu(); } } out: vm_page_lock_queues(); pmap_remove(pm, sc->acpi_wakephys, sc->acpi_wakephys + PAGE_SIZE); vm_page_unlock_queues(); if (opage) { pmap_enter(pm, sc->acpi_wakephys, page, VM_PROT_READ | VM_PROT_WRITE, 0); } if (pteobj_allocated) { vm_object_deallocate(pm->pm_pteobj); pm->pm_pteobj = NULL; } write_eflags(ef); return (ret); }
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 {
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 = 0; if (sc->acpi_wakeaddr == 0) return (0); AcpiSetFirmwareWakingVector(sc->acpi_wakephys); ef = read_eflags(); /* * 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; ACPI_DISABLE_IRQS(); if (acpi_savecpu()) { /* Execute Sleep */ intr_suspend(); 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); if (status != AE_OK) { device_printf(sc->acpi_dev, "AcpiEnterSleepState failed - %s\n", AcpiFormatException(status)); ret = -1; goto out; } for (;;) ; } else { /* Execute Wakeup */ intr_resume(); if (bootverbose) { acpi_savecpu(); acpi_printcpu(); } } out: load_cr3(cr3); write_eflags(ef); /* If we beeped, turn it off after a delay. */ if (acpi_resume_beep) timeout(acpi_stop_beep, NULL, 3 * hz); return (ret); }
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 {