acpi_wakecode.S revision 115681
180028Stakawata/*-
280028Stakawata * Copyright (c) 2001 Takanori Watanabe <takawata@jp.freebsd.org>
380028Stakawata * Copyright (c) 2001 Mitsuru IWASAKI <iwasaki@jp.freebsd.org>
480028Stakawata * All rights reserved.
580028Stakawata *
680028Stakawata * Redistribution and use in source and binary forms, with or without
780028Stakawata * modification, are permitted provided that the following conditions
880028Stakawata * are met:
980028Stakawata * 1. Redistributions of source code must retain the above copyright
1080028Stakawata *    notice, this list of conditions and the following disclaimer.
1180028Stakawata * 2. Redistributions in binary form must reproduce the above copyright
1280028Stakawata *    notice, this list of conditions and the following disclaimer in the
1380028Stakawata *    documentation and/or other materials provided with the distribution.
1480028Stakawata *
1580028Stakawata * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1680028Stakawata * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1780028Stakawata * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1880028Stakawata * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1980028Stakawata * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2080028Stakawata * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2180028Stakawata * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2280028Stakawata * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2380028Stakawata * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2480028Stakawata * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2580028Stakawata * SUCH DAMAGE.
2680028Stakawata */
2780028Stakawata
28115681Sobrien#include <machine/asm.h>
29115681Sobrien__FBSDID("$FreeBSD: head/sys/i386/acpica/acpi_wakecode.S 115681 2003-06-02 06:16:45Z obrien $");
30115681Sobrien
3180028Stakawata#define LOCORE
3280028Stakawata
3380028Stakawata#include <machine/specialreg.h>
3480028Stakawata
3580028Stakawata	.align 4
3680028Stakawata	.code16
3780028Stakawatawakeup_16:
3880028Stakawata	nop
3980028Stakawata	cli
4080028Stakawata
4180028Stakawata	/* Set up segment registers for real mode */
4280028Stakawata	movw	%cs,%ax
4380028Stakawata	movw	%ax,%ds
4480028Stakawata	movw	%ax,%ss
4580028Stakawata
4680028Stakawata	/* Load GDT for real mode */
4780028Stakawata	lgdt	physical_gdt
4880028Stakawata
4980028Stakawata	/* Restore CR2, CR3 and CR4 */
5080028Stakawata	mov	previous_cr2,%eax
5180028Stakawata	mov	%eax,%cr2
5280028Stakawata	mov	previous_cr3,%eax
5380028Stakawata	mov	%eax,%cr3
5480028Stakawata	mov	previous_cr4,%eax
5580028Stakawata	mov	%eax,%cr4
5680028Stakawata
5780028Stakawata	/* Transfer some values to protected mode */
5880028Stakawata#define NVALUES	9
5980028Stakawata#define TRANSFER_STACK32(val, idx)	\
6080028Stakawata	mov	val,%eax;		\
6180028Stakawata	mov	%eax,wakeup_32stack+(idx+1)+(idx*4);
6280028Stakawata
6380028Stakawata	TRANSFER_STACK32(previous_ss,		(NVALUES - 9))
6480028Stakawata	TRANSFER_STACK32(previous_fs,		(NVALUES - 8))
6580028Stakawata	TRANSFER_STACK32(previous_ds,		(NVALUES - 7))
6680028Stakawata	TRANSFER_STACK32(physical_gdt+2,	(NVALUES - 6))
6780028Stakawata	TRANSFER_STACK32(where_to_recover,	(NVALUES - 5))
6880028Stakawata	TRANSFER_STACK32(previous_idt+2,	(NVALUES - 4))
6980028Stakawata	TRANSFER_STACK32(previous_ldt,		(NVALUES - 3))
7080028Stakawata	TRANSFER_STACK32(previous_gdt+2,	(NVALUES - 2))
7180028Stakawata	TRANSFER_STACK32(previous_tr,		(NVALUES - 1))
7280028Stakawata	TRANSFER_STACK32(previous_cr0,		(NVALUES - 0))
7380028Stakawata
7480028Stakawata	mov	physical_esp,%esi	/* to be used in 32bit code */
7580028Stakawata
7680028Stakawata	/* Enable protected mode */
7780028Stakawata	mov	%cr0,%eax
7880028Stakawata	orl	$(CR0_PE),%eax
7980028Stakawata	mov	%eax,%cr0
8080028Stakawata
8180028Stakawatawakeup_sw32:
8280028Stakawata	/* Switch to protected mode by intersegmental jump */
8380028Stakawata	ljmpl	$0x8,$0x12345678	/* Code location, to be replaced */
8480028Stakawata
8580028Stakawata	.code32
8680028Stakawatawakeup_32:
8780028Stakawata	/*
8880028Stakawata	 * Switched to protected mode w/o paging
8980028Stakawata	 *	%esi:	KERNEL stack pointer (physical address)
9080028Stakawata	 */
9180028Stakawata
9280028Stakawata	nop
9380028Stakawata
9480028Stakawata	/* Set up segment registers for protected mode */
9580028Stakawata	movw	$0x10,%ax		/* KDSEL to segment registers */
9680028Stakawata	movw	%ax,%ds
9780028Stakawata	movw	%ax,%es
9880028Stakawata	movw	%ax,%gs
9980028Stakawata	movw	%ax,%ss
10080028Stakawata	movw	$0x18,%ax		/* KPSEL to %fs */
10180028Stakawata	movw	%ax,%fs
10280028Stakawata	movl	%esi,%esp		/* physical address stack pointer */
10380028Stakawata
10480028Stakawatawakeup_32stack:
10580028Stakawata	/* Operands are overwritten in 16bit code */
10680028Stakawata	pushl	$0xabcdef09		/* ss + dummy */
10780028Stakawata	pushl	$0xabcdef08		/* fs + gs */
10880028Stakawata	pushl	$0xabcdef07		/* ds + es */
10980028Stakawata	pushl	$0xabcdef06		/* gdt:base (physical address) */
11080028Stakawata	pushl	$0xabcdef05		/* recover address */
11180028Stakawata	pushl	$0xabcdef04		/* idt:base */
11280028Stakawata	pushl	$0xabcdef03		/* ldt + idt:limit */
11380028Stakawata	pushl	$0xabcdef02		/* gdt:base */
11480028Stakawata	pushl	$0xabcdef01		/* TR + gdt:limit */
11580028Stakawata	pushl	$0xabcdef00		/* CR0 */
11680028Stakawata
11780028Stakawata	movl	%esp,%ebp
11880028Stakawata#define CR0_REGISTER		0(%ebp)
11980028Stakawata#define TASK_REGISTER		4(%ebp)
12080028Stakawata#define PREVIOUS_GDT		6(%ebp)
12180028Stakawata#define PREVIOUS_LDT		12(%ebp)
12280028Stakawata#define PREVIOUS_IDT		14(%ebp)
12380028Stakawata#define RECOVER_ADDR		20(%ebp)
12480028Stakawata#define PHYSICAL_GDT_BASE	24(%ebp)
12580028Stakawata#define PREVIOUS_DS		28(%ebp)
12680028Stakawata#define PREVIOUS_ES		30(%ebp)
12780028Stakawata#define PREVIOUS_FS		32(%ebp)
12880028Stakawata#define PREVIOUS_GS		34(%ebp)
12980028Stakawata#define PREVIOUS_SS		36(%ebp)
13080028Stakawata
13180028Stakawata	/* Fixup TSS type field */
13280028Stakawata#define TSS_TYPEFIX_MASK	0xf9
13380028Stakawata	xorl	%esi,%esi
13480028Stakawata	movl	PHYSICAL_GDT_BASE,%ebx
13580028Stakawata	movw	TASK_REGISTER,%si
13680028Stakawata	leal	(%ebx,%esi),%eax	/* get TSS segment descriptor */
13780028Stakawata	andb	$TSS_TYPEFIX_MASK,5(%eax)
13880028Stakawata
13980028Stakawata	/* Prepare to return to sleep/wakeup code point */
14080028Stakawata	lgdt	PREVIOUS_GDT
14180028Stakawata	lidt	PREVIOUS_IDT
14280028Stakawata
14380028Stakawata	xorl	%eax,%eax
14480028Stakawata	movl	%eax,%ebx
14580028Stakawata	movl	%eax,%ecx
14680028Stakawata	movl	%eax,%edx
14780028Stakawata	movl	%eax,%esi
14880028Stakawata	movl	%eax,%edi
14980028Stakawata	movl	PREVIOUS_DS,%ebx
15080028Stakawata	movl	PREVIOUS_FS,%ecx
15180028Stakawata	movl	PREVIOUS_SS,%edx
15280028Stakawata	movw	TASK_REGISTER,%si
15380028Stakawata	shll	$16,%esi
15480028Stakawata	movw	PREVIOUS_LDT,%si
15580028Stakawata	movl	RECOVER_ADDR,%edi
15680028Stakawata
15780028Stakawata	/* Enable paging and etc. */
15880028Stakawata	movl	CR0_REGISTER,%eax
15980028Stakawata	movl	%eax,%cr0
16080028Stakawata
16180028Stakawata	/* Flush the prefetch queue */
16280028Stakawata	jmp	1f
16380028Stakawata1:	jmp	1f
16480028Stakawata1:
16580028Stakawata	/*
16680028Stakawata	 * Now that we are in kernel virtual memory addressing
16780028Stakawata	 *	%ebx:	ds + es
16880028Stakawata	 *	%ecx:	fs + gs
16980028Stakawata	 *	%edx:	ss + dummy
17080028Stakawata	 *	%esi:	LDTR + TR
17180028Stakawata	 *	%edi:	recover address
17280028Stakawata	 */
17380028Stakawata
17480028Stakawata	nop
17580028Stakawata
17680028Stakawata	movl	%esi,%eax		/* LDTR + TR */
17780028Stakawata	lldt	%ax			/* load LDT register */
17880028Stakawata	shrl	$16,%eax
17980028Stakawata	ltr	%ax			/* load task register */
18080028Stakawata
18180028Stakawata	/* Restore segment registers */
18280028Stakawata	movl	%ebx,%eax		/* ds + es */
18380028Stakawata	movw	%ax,%ds
18480028Stakawata	shrl	$16,%eax
18580028Stakawata	movw	%ax,%es
18680028Stakawata	movl	%ecx,%eax		/* fs + gs */
18780028Stakawata	movw	%ax,%fs
18880028Stakawata	shrl	$16,%eax
18980028Stakawata	movw	%ax,%gs
19080028Stakawata	movl	%edx,%eax		/* ss */
19180028Stakawata	movw	%ax,%ss
19280028Stakawata
19380028Stakawata	/* Jump to acpi_restorecpu() */
19480028Stakawata	jmp	*%edi
19580028Stakawata
19680028Stakawata/* used in real mode */
19780028Stakawataphysical_gdt:		.word 0
19880028Stakawata			.long 0
19980028Stakawataphysical_esp:		.long 0
20080028Stakawataprevious_cr2:		.long 0
20180028Stakawataprevious_cr3:		.long 0
20280028Stakawataprevious_cr4:		.long 0
20380028Stakawata
20480028Stakawata/* transfer from real mode to protected mode */
20580028Stakawataprevious_cr0:		.long 0
20680028Stakawataprevious_tr:		.word 0
20780028Stakawataprevious_gdt:		.word 0
20880028Stakawata			.long 0
20980028Stakawataprevious_ldt:		.word 0
21080028Stakawataprevious_idt:		.word 0
21180028Stakawata			.long 0
21280028Stakawatawhere_to_recover:	.long 0
21380028Stakawataprevious_ds:		.word 0
21480028Stakawataprevious_es:		.word 0
21580028Stakawataprevious_fs:		.word 0
21680028Stakawataprevious_gs:		.word 0
21780028Stakawataprevious_ss:		.word 0
21880028Stakawatadummy:			.word 0
21980028Stakawata
220