/*
* Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
*
- * @APPLE_LICENSE_HEADER_START@
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
- * The contents of this file constitute Original Code as defined in and
- * are subject to the Apple Public Source License Version 1.1 (the
- * "License"). You may not use this file except in compliance with the
- * License. Please obtain a copy of the License at
- * http://www.apple.com/publicsource and read it before using this file.
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
*
- * This Original Code and all software distributed under the License are
- * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
- * License for the specific language governing rights and limitations
- * under the License.
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
*
- * @APPLE_LICENSE_HEADER_END@
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
*/
#include <i386/asm.h>
.text
.align 12 /* Page align for single bcopy_phys() */
-#define LJMP(segment, address) \
- .byte 0xea ;\
- .long address - EXT(acpi_wake_start) ;\
- .word segment
-
-#define PA(addr) ((addr)-KERNELBASE)
-
-/*
- * acpi_wake_start
- *
- * The code from acpi_wake_start to acpi_wake_end is copied to
- * memory below 1MB. The firmware waking vector is updated to
- * point at acpi_wake_start in low memory before sleeping.
- */
-
-ENTRY(acpi_wake_start)
- /*
- * CPU woke up from sleep, and is back in real mode.
- * Initialize it just enough to get back to protected mode.
- */
- cli
-
- POSTCODE(ACPI_WAKE_START_ENTRY)
-
- /* set up DS to match CS */
- movw %cs, %ax
- movw %ax, %ds
-
- /*
- * Must initialize GDTR before entering protected mode.
- * Use a temporary GDT that is 0 based, 4GB limit, code and data.
- * Restoring the actual GDT will come later.
- */
- addr16
- data16
- lgdt EXT(acpi_gdtr) - EXT(acpi_wake_start)
-
- /* set CR0.PE to enter protected mode */
- mov %cr0, %eax
- data16
- or $(CR0_PE), %eax
- mov %eax, %cr0
-
- /*
- * Make intra-segment jump to flush pipeline and reload CS register.
- * If GDT is bogus, it will blow up here.
- */
- data16
- LJMP(0x8, acpi_wake_prot + ACPI_WAKE_ADDR)
+#define PA(addr) (addr)
-acpi_wake_prot:
+#if CONFIG_SLEEP
+ENTRY(acpi_wake_prot)
/* protected mode, paging disabled */
movl PA(saved_eip), %eax
jmp *%eax
-/* Segment Descriptor
- *
- * 31 24 19 16 7 0
- * ------------------------------------------------------------
- * | | |B| |A| | | |1|0|E|W|A| |
- * | BASE 31..24 |G|/|0|V| LIMIT |P|DPL| TYPE | BASE 23:16 |
- * | | |D| |L| 19..16| | |1|1|C|R|A| |
- * ------------------------------------------------------------
- * | | |
- * | BASE 15..0 | LIMIT 15..0 |
- * | | |
- * ------------------------------------------------------------
- */
-ENTRY(acpi_gdt)
- .word 0, 0 /* 0x0 : null */
- .byte 0, 0, 0, 0
-
- .word 0xffff, 0x0000 /* 0x8 : code */
- .byte 0, 0x9e, 0xcf, 0
-
- .word 0xffff, 0x0000 /* 0x10 : data */
- .byte 0, 0x92, 0xcf, 0
-
-ENTRY(acpi_gdtr)
- .word 24 /* limit (8*3 segs) */
- .long EXT(acpi_gdt) - EXT(acpi_wake_start) + ACPI_WAKE_ADDR
-
-ENTRY(acpi_wake_end)
-
-
/*
* acpi_sleep_cpu(acpi_sleep_callback func, void * refcon)
*
pushal
movl %esp, saved_esp
+ /* make sure tlb is flushed */
+ movl %cr3,%eax
+ movl %eax,%cr3
+
/* save control registers */
movl %cr0, %eax
movl %eax, saved_cr0
jmp wake_restore
wake_prot:
-
/* protected mode, paging disabled */
POSTCODE(ACPI_WAKE_PROT_ENTRY)
+ movl PA(saved_cr3), %ebx
+ movl PA(saved_cr4), %ecx
+ /*
+ * restore cr3, PAE and NXE states in an orderly fashion
+ */
+ movl %ebx, %cr3
+ movl %ecx, %cr4
+
+ movl $(MSR_IA32_EFER), %ecx /* MSR number in ecx */
+ rdmsr /* MSR value return in edx: eax */
+ orl $(MSR_IA32_EFER_NXE), %eax /* Set NXE bit in low 32-bits */
+ wrmsr /* Update Extended Feature Enable reg */
+
/* restore kernel GDT */
lgdt PA(saved_gdt)
- /* restore control registers */
movl PA(saved_cr2), %eax
movl %eax, %cr2
-
-#ifdef PAE
- movl PA(EXT(IdlePDPT)), %eax
- movl (%eax), %esi /* save orig */
- movl 24(%eax), %ebx
- movl %ebx, (%eax) /* identity map low mem */
- movl %eax, %cr3
-
- movl PA(saved_cr4), %eax
- movl %eax, %cr4
-#else
- movl PA(saved_cr4), %eax
- movl %eax, %cr4
-
- /*
- * Temporarily use the page tables at IdlePTD
- * to enable paging. Copy the KPTDI entry to
- * entry 0 in the PTD to identity map the kernel.
- */
- movl PA(EXT(IdlePTD)), %eax
- movl %eax, %ebx
- addl $(KPTDI << PTEINDX), %ebx /* bytes per PDE */
- movl (%ebx), %ebx /* IdlePTD[KPTDI] */
- movl (%eax), %esi /* save original IdlePTD[0] */
- movl %ebx, (%eax) /* update IdlePTD[0] */
- movl %eax, %cr3 /* CR3 = IdlePTD */
-#endif
/* restore CR0, paging enabled */
movl PA(saved_cr0), %eax
movl %eax, %cr0
/* switch to kernel code segment */
- ljmpl $(KERNEL_CS), $wake_paged
+ ljmpl $(KERNEL32_CS), $wake_paged
wake_paged:
movw $(KERNEL_DS), %ax
movw %ax, %ds
- /* undo changes to IdlePTD */
-#ifdef PAE
- movl EXT(IdlePDPT), %eax
-#else
- movl EXT(IdlePTD), %eax
-#endif
- addl $(KERNELBASE), %eax /* make virtual */
- movl %esi, (%eax)
-
- /* restore real PDE base */
- movl saved_cr3, %eax
- movl %eax, %cr3
-
-
/* restore local and interrupt descriptor tables */
lldt saved_ldt
lidt saved_idt
.globl EXT(acpi_wake_prot_entry)
ENTRY(acpi_wake_prot_entry)
+ mov %cr0, %eax
+ and $(~CR0_PG), %eax
+ mov %eax, %cr0
+ mov $EXT(IdlePDPT), %eax
+ mov EXT(IdlePTD), %ecx
+ or $(INTEL_PTE_VALID), %ecx
+ mov $0x0, %edx
+ mov %ecx, (0*8+0)(%eax)
+ mov %edx, (0*8+4)(%eax)
+ add $(PAGE_SIZE), %ecx
+ mov %ecx, (1*8+0)(%eax)
+ mov %edx, (1*8+4)(%eax)
+ add $(PAGE_SIZE), %ecx
+ mov %ecx, (2*8+0)(%eax)
+ mov %edx, (2*8+4)(%eax)
+ add $(PAGE_SIZE), %ecx
+ mov %ecx, (3*8+0)(%eax)
+ mov %edx, (3*8+4)(%eax)
+ mov %eax, %cr3
+ mov %cr0, %eax
+ or $(CR0_PG), %eax
+ mov %eax, %cr0
+
/* protected mode, paging enabled */
+
POSTCODE(ACPI_WAKE_PAGED_ENTRY)
/* restore kernel GDT */
- lgdt PA(saved_gdt)
-
+ lgdt saved_gdt
+
POSTCODE(0x40)
+
/* restore control registers */
+
+ movl saved_cr0, %eax
+ movl %eax, %cr0
+
movl saved_cr2, %eax
movl %eax, %cr2
POSTCODE(0x3E)
- /* switch to kernel data segment */
- movw $(KERNEL_DS), %ax
- movw %ax, %ds
- POSTCODE(0x3D)
/* restore real PDE base */
movl saved_cr3, %eax
movl saved_cr4, %edx
movl %eax, %cr3
movl %edx, %cr4
+ movl %eax, %cr3
- POSTCODE(0x3C)
+ /* switch to kernel data segment */
+ movw $(KERNEL_DS), %ax
+ movw %ax, %ds
+
+ POSTCODE(0x3C)
/* restore local and interrupt descriptor tables */
lldt saved_ldt
lidt saved_idt
movl $2, %eax
leave
- ret
-
- .data
- .section __HIB, __data
- .align 2
+ ret
+#endif /* CONFIG_SLEEP */
+.data
+.section __SLEEP, __data
+.align 2
/*
* CPU registers saved across sleep/wake.
*/
+
saved_esp: .long 0
saved_es: .word 0
saved_fs: .word 0