diff options
author | Marco Peereboom <marco@cvs.openbsd.org> | 2009-02-19 21:02:06 +0000 |
---|---|---|
committer | Marco Peereboom <marco@cvs.openbsd.org> | 2009-02-19 21:02:06 +0000 |
commit | 748c385494ee5d641b7e648df28568538e41467c (patch) | |
tree | 9b3648d5d080c29915d0f71b7a8d9c490046223d /sys/arch | |
parent | 6fb68817a3957ab44390ea949e41e4b949d653a7 (diff) |
suspend/resume bits so that we can develop this in tree. This is disabled.
code from mlarkin and me
help from art,toby,jordan and several others
ok jordan, go for it deraadt
Diffstat (limited to 'sys/arch')
-rw-r--r-- | sys/arch/amd64/amd64/acpi_machdep.c | 71 | ||||
-rw-r--r-- | sys/arch/amd64/amd64/acpi_wakecode.S | 26 | ||||
-rw-r--r-- | sys/arch/i386/i386/acpi_machdep.c | 78 | ||||
-rw-r--r-- | sys/arch/i386/i386/acpi_wakecode.S | 19 |
4 files changed, 158 insertions, 36 deletions
diff --git a/sys/arch/amd64/amd64/acpi_machdep.c b/sys/arch/amd64/amd64/acpi_machdep.c index 24cdfc7b58b..f6a5f98e30f 100644 --- a/sys/arch/amd64/amd64/acpi_machdep.c +++ b/sys/arch/amd64/amd64/acpi_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: acpi_machdep.c,v 1.15 2009/02/15 02:03:40 marco Exp $ */ +/* $OpenBSD: acpi_machdep.c,v 1.16 2009/02/19 21:02:05 marco Exp $ */ /* * Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com> * @@ -30,6 +30,7 @@ #include <dev/isa/isareg.h> #include <dev/acpi/acpireg.h> #include <dev/acpi/acpivar.h> +#include <dev/acpi/acpidev.h> #include "ioapic.h" @@ -171,4 +172,72 @@ acpi_attach_machdep(struct acpi_softc *sc) #endif /* ACPI_SLEEP_ENABLED */ } + +void +acpi_cpu_flush(struct acpi_softc *sc, int state) +{ + /* + * Flush write back caches since we'll lose them. + */ + if (state > ACPI_STATE_S1) + wbinvd(); +} +int +acpi_sleep_machdep(struct acpi_softc *sc, int state) +{ +#ifdef ACPI_SLEEP_ENABLED + + if (sc->sc_facs == NULL) { + printf("%s: acpi_sleep_machdep: no FACS\n", DEVNAME(sc)); + return (ENXIO); + } + + if (rcr3() != pmap_kernel()->pm_pdirpa) { + printf("%s: acpi_sleep_machdep: only kernel may sleep\n", + DEVNAME(sc)); + return (ENXIO); + } + + /* + * + * ACPI defines two wakeup vectors. One is used for ACPI 1.0 + * implementations - it's in the FACS table as wakeup_vector and + * indicates a 32-bit physical address containing real-mode wakeup + * code. + * + * The second wakeup vector is in the FACS table as + * x_wakeup_vector and indicates a 64-bit physical address + * containing protected-mode wakeup code. + * + */ + + sc->sc_facs->wakeup_vector = (u_int32_t)ACPI_TRAMPOLINE; + if (sc->sc_facs->version == 1) + sc->sc_facs->x_wakeup_vector = 0; + + disable_intr(); + + /* Copy the current cpu registers into a safe place for resume. */ + if (acpi_savecpu()) { + wbinvd(); + acpi_enter_sleep_state(sc, state); + panic("%s: acpi_enter_sleep_state failed", DEVNAME(sc)); + } + + /* + * On resume, the execution path will actually occur here. + * This is because we previously saved the stack location + * in acpi_savecpu, and issued a far jmp to the restore + * routine in the wakeup code. This means we are + * returning to the location immediately following the + * last call instruction - after the call to acpi_savecpu. + */ + + initrtclock(); + enable_intr(); +#endif /* ACPI_SLEEP_ENABLED */ + return 0; + } + + #endif /* ! SMALL_KERNEL */ diff --git a/sys/arch/amd64/amd64/acpi_wakecode.S b/sys/arch/amd64/amd64/acpi_wakecode.S index 777a9a13809..7da9a0a4b8a 100644 --- a/sys/arch/amd64/amd64/acpi_wakecode.S +++ b/sys/arch/amd64/amd64/acpi_wakecode.S @@ -1,4 +1,4 @@ -/* $OpenBSD: acpi_wakecode.S,v 1.2 2009/02/15 02:06:09 marco Exp $ */ +/* $OpenBSD: acpi_wakecode.S,v 1.3 2009/02/19 21:02:05 marco Exp $ */ /* * Copyright (c) 2001 Takanori Watanabe <takawata@jp.freebsd.org> * Copyright (c) 2001 Mitsuru IWASAKI <iwasaki@jp.freebsd.org> @@ -128,6 +128,7 @@ _C_LABEL(acpi_real_mode_resume): * laptops), we might not restore the proper VGA mode * on resume. Caveat emptor. */ + jmp nobiosreset /* XXX make this a tunable */ lcall $0xc000,$3 /* @@ -137,6 +138,7 @@ _C_LABEL(acpi_real_mode_resume): movw %cs,%ax movw %ax,%ds movw %ax,%ss +nobiosreset: /* * Set up esi to point to start of current routine's CS. @@ -152,7 +154,6 @@ _C_LABEL(acpi_real_mode_resume): 1: jmp 1f 1: - /* * We're about to enter protected mode, so we need a GDT for that. * Set up a temporary GDT describing 2 segments, one for code @@ -180,11 +181,10 @@ _C_LABEL(acpi_real_mode_resume): */ ljmpl $0x8, $acpi_protected_mode_trampoline -_ACPI_TRMP_LABEL(acpi_protected_mode_trampoline) -_C_LABEL(acpi_protected_mode_resume): .code32 .align 16 - +_ACPI_TRMP_LABEL(acpi_protected_mode_trampoline) +_C_LABEL(acpi_protected_mode_resume): nop /* @@ -257,13 +257,10 @@ _C_LABEL(acpi_protected_mode_resume): /* Enter long mode by making another intersegment jump */ ljmp $0x8, $acpi_long_mode_trampoline -_ACPI_TRMP_LABEL(acpi_long_mode_trampoline) -_C_LABEL(acpi_long_mode_resume): .code64 .align 16 - - - +_ACPI_TRMP_LABEL(acpi_long_mode_trampoline) +_C_LABEL(acpi_long_mode_resume): /* Restore the stashed copy of EFER we set aside earlier */ movl %ebx, %eax movl $MSR_EFER, %ecx @@ -353,8 +350,6 @@ _C_LABEL(acpi_long_mode_resume): xorq %rax, %rax jmp *acpi_saved_ret - - .align 8 _ACPI_TRMP_OFFSET(tmp_gdt) .word tmp_gdt_end - tmp_gdtable @@ -398,7 +393,6 @@ _ACPI_TRMP_LABEL(tmp_gdtable) */ .word 0xffff, 0 .byte 0, 0x93, 0xcf, 0 - _ACPI_TRMP_LABEL(tmp_gdt_end) .align 8 @@ -411,7 +405,6 @@ _ACPI_TRMP_LABEL(tmp_gdtable64) .quad 0x0000000000000000 .quad 0x00af9a000000ffff .quad 0x00cf92000000ffff - _ACPI_TRMP_LABEL(tmp_gdt64_end) .align 8 @@ -447,7 +440,6 @@ _ACPI_TRMP_LABEL(acpi_saved_r14) .quad 0 _ACPI_TRMP_LABEL(acpi_saved_r15) .quad 0 - _ACPI_TRMP_LABEL(acpi_saved_fl) .quad 0 _ACPI_TRMP_LABEL(acpi_saved_cr0) @@ -460,7 +452,6 @@ _ACPI_TRMP_LABEL(acpi_saved_cr4) .quad 0 _ACPI_TRMP_LABEL(acpi_saved_cr8) .quad 0 - _ACPI_TRMP_LABEL(acpi_saved_ret) .quad 0 @@ -563,7 +554,6 @@ NENTRY(acpi_savecpu) popq %rdx popq %rcx - sgdt acpi_saved_gdt sidt acpi_saved_idt sldt acpi_saved_ldt @@ -571,7 +561,5 @@ NENTRY(acpi_savecpu) movl $1, %eax ret - - #endif /* SMALL_KERNEL */ #endif /* NACPI > 0 */ diff --git a/sys/arch/i386/i386/acpi_machdep.c b/sys/arch/i386/i386/acpi_machdep.c index 8f5f7b36b87..bac6d1f8757 100644 --- a/sys/arch/i386/i386/acpi_machdep.c +++ b/sys/arch/i386/i386/acpi_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: acpi_machdep.c,v 1.16 2009/01/20 20:21:03 mlarkin Exp $ */ +/* $OpenBSD: acpi_machdep.c,v 1.17 2009/02/19 21:02:05 marco Exp $ */ /* * Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com> * @@ -34,6 +34,7 @@ #include <dev/isa/isareg.h> #include <dev/acpi/acpireg.h> #include <dev/acpi/acpivar.h> +#include <dev/acpi/acpidev.h> #include "apm.h" @@ -44,6 +45,8 @@ int haveacpibutusingapm; extern u_char acpi_real_mode_resume[], acpi_resume_end[]; int acpi_savecpu(void); +void intr_calculatemasks(void); +void acpi_cpu_flush(struct acpi_softc *, int); #define ACPI_BIOS_RSDP_WINDOW_BASE 0xe0000 #define ACPI_BIOS_RSDP_WINDOW_SIZE 0x20000 @@ -174,15 +177,84 @@ acpi_attach_machdep(struct acpi_softc *sc) cpuresetfn = acpi_reset; #ifdef ACPI_SLEEP_ENABLED - /* * Sanity check before setting up trampoline. * Ensure the trampoline size is < PAGE_SIZE */ KASSERT(acpi_resume_end - acpi_real_mode_resume < PAGE_SIZE); - bcopy(acpi_real_mode_resume, (caddr_t)ACPI_TRAMPOLINE, acpi_resume_end - acpi_real_mode_resume); #endif /* ACPI_SLEEP_ENABLED */ +} + +void +acpi_cpu_flush(struct acpi_softc *sc, int state) +{ + /* flush write back caches since we'll lose them */ + if (state > ACPI_STATE_S1) + wbinvd(); +} + +int +acpi_sleep_machdep(struct acpi_softc *sc, int state) +{ +#ifdef ACPI_SLEEP_ENABLED + u_long ef; + + if (sc->sc_facs == NULL) { + printf("%s: acpi_sleep_machdep: no FACS\n", DEVNAME(sc)); + return (ENXIO); + } + + if (rcr3() != pmap_kernel()->pm_pdirpa) { + printf("%s: acpi_sleep_machdep: only kernel may sleep\n", + DEVNAME(sc)); + return (ENXIO); + } + + /* + * + * ACPI defines two wakeup vectors. One is used for ACPI 1.0 + * implementations - it's in the FACS table as wakeup_vector and + * indicates a 32-bit physical address containing real-mode wakeup + * code. + * + * The second wakeup vector is in the FACS table as + * x_wakeup_vector and indicates a 64-bit physical address + * containing protected-mode wakeup code. + * + */ + sc->sc_facs->wakeup_vector = (u_int32_t)ACPI_TRAMPOLINE; + if (sc->sc_facs->version == 1) + sc->sc_facs->x_wakeup_vector = 0; + + ef = read_eflags(); + + /* Copy the current cpu registers into a safe place for resume. */ + if (acpi_savecpu()) { + wbinvd(); + acpi_enter_sleep_state(sc, state); + panic("%s: acpi_enter_sleep_state failed", DEVNAME(sc)); + } + /* + * On resume, the execution path will actually occur here. + * This is because we previously saved the stack location + * in acpi_savecpu, and issued a far jmp to the restore + * routine in the wakeup code. This means we are + * returning to the location immediately following the + * last call instruction - after the call to acpi_savecpu. + */ + + npxinit(&cpu_info_primary); + isa_defaultirq(); + intr_calculatemasks(); +#if NIOAPIC > 0 + ioapic_enable(); +#endif + initrtclock(); + enable_intr(); + write_eflags(ef); +#endif /* ACPI_SLEEP_ENABLED */ + return (0); } #endif /* ! SMALL_KERNEL */ diff --git a/sys/arch/i386/i386/acpi_wakecode.S b/sys/arch/i386/i386/acpi_wakecode.S index daedfdf7a07..5ec361465b7 100644 --- a/sys/arch/i386/i386/acpi_wakecode.S +++ b/sys/arch/i386/i386/acpi_wakecode.S @@ -90,7 +90,7 @@ _C_LABEL(acpi_real_mode_resume): /* * Set up segment registers for real mode. * We'll only be in real mode for a moment, and we don't have - * ant real dependencies on data or stack, so we'll just use + * want real dependencies on data or stack, so we'll just use * the code segment for data and stack (eg, a 64k memory space). */ movw %cs,%ax @@ -124,6 +124,7 @@ _C_LABEL(acpi_real_mode_resume): * laptops), we might not restore the proper VGA mode * on resume. Caveat emptor. */ + jmp nobiosreset /* XXX make this a tunable */ lcall $0xc000,$3 /* @@ -133,6 +134,7 @@ _C_LABEL(acpi_real_mode_resume): movw %cs,%ax movw %ax,%ds movw %ax,%ss +nobiosreset: /* * Set up esi to point to start of current routine's CS. @@ -148,7 +150,6 @@ _C_LABEL(acpi_real_mode_resume): 1: jmp 1f 1: - /* * We're about to enter protected mode, so we need a GDT for that. * Set up a temporary GDT describing 2 segments, one for code @@ -176,11 +177,10 @@ _C_LABEL(acpi_real_mode_resume): */ ljmpl $0x8, $acpi_protected_mode_trampoline -_ACPI_TRMP_LABEL(acpi_protected_mode_trampoline) -_C_LABEL(acpi_protected_mode_resume): .code32 .align 16 - +_ACPI_TRMP_LABEL(acpi_protected_mode_trampoline) +_C_LABEL(acpi_protected_mode_resume): nop /* @@ -322,9 +322,7 @@ _C_LABEL(acpi_protected_mode_resume): * before we went to sleep. */ xorl %eax, %eax - jmp *acpi_saved_ret - - + jmp *acpi_saved_ret .align 8 _ACPI_TRMP_OFFSET(tmp_gdt) @@ -369,7 +367,6 @@ _ACPI_TRMP_LABEL(tmp_gdtable) */ .word 0xffff, 0 .byte 0, 0x93, 0xcf, 0 - _ACPI_TRMP_LABEL(tmp_gdt_end) .align 4 @@ -387,7 +384,6 @@ _ACPI_TRMP_LABEL(acpi_saved_edi) .long 0 _ACPI_TRMP_LABEL(acpi_saved_esp) .long 0 - _ACPI_TRMP_LABEL(acpi_saved_fl) .long 0 _ACPI_TRMP_LABEL(acpi_saved_cr0) @@ -398,7 +394,6 @@ _ACPI_TRMP_LABEL(acpi_saved_cr3) .long 0 _ACPI_TRMP_LABEL(acpi_saved_cr4) .long 0 - _ACPI_TRMP_LABEL(acpi_saved_ret) .long 0 @@ -476,7 +471,5 @@ NENTRY(acpi_savecpu) movl $1, %eax ret - - #endif /* SMALL_KERNEL */ #endif /* NACPI > 0 */ |