acpi_wakecode.S revision 121743
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 121743 2003-10-30 16:14:55Z iwasaki $");
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
45121603Snjl
46121641Siwasaki#ifndef ACPI_NO_RESET_VIDEO
47121603Snjl	/*
48121603Snjl	 * Re-initialize video BIOS.  Restore DS and SS from CS in
49121603Snjl	 * case the BIOS modified them.
50121603Snjl	 */
51121743Siwasaki	cmp	$1, no_reset_video
52121743Siwasaki	je	wakeup_16_gdt
53121603Snjl	lcall	$0xc000, $3
54121603Snjl	movw	%cs, %ax
55121603Snjl	movw	%ax, %ds
56121603Snjl	movw	%ax, %ss
57121641Siwasaki#endif
5880028Stakawata
59121743Siwasakiwakeup_16_gdt:
6080028Stakawata	/* Load GDT for real mode */
6180028Stakawata	lgdt	physical_gdt
6280028Stakawata
6380028Stakawata	/* Restore CR2, CR3 and CR4 */
6480028Stakawata	mov	previous_cr2,%eax
6580028Stakawata	mov	%eax,%cr2
6680028Stakawata	mov	previous_cr3,%eax
6780028Stakawata	mov	%eax,%cr3
6880028Stakawata	mov	previous_cr4,%eax
6980028Stakawata	mov	%eax,%cr4
7080028Stakawata
7180028Stakawata	/* Transfer some values to protected mode */
7280028Stakawata#define NVALUES	9
7380028Stakawata#define TRANSFER_STACK32(val, idx)	\
7480028Stakawata	mov	val,%eax;		\
7580028Stakawata	mov	%eax,wakeup_32stack+(idx+1)+(idx*4);
7680028Stakawata
7780028Stakawata	TRANSFER_STACK32(previous_ss,		(NVALUES - 9))
7880028Stakawata	TRANSFER_STACK32(previous_fs,		(NVALUES - 8))
7980028Stakawata	TRANSFER_STACK32(previous_ds,		(NVALUES - 7))
8080028Stakawata	TRANSFER_STACK32(physical_gdt+2,	(NVALUES - 6))
8180028Stakawata	TRANSFER_STACK32(where_to_recover,	(NVALUES - 5))
8280028Stakawata	TRANSFER_STACK32(previous_idt+2,	(NVALUES - 4))
8380028Stakawata	TRANSFER_STACK32(previous_ldt,		(NVALUES - 3))
8480028Stakawata	TRANSFER_STACK32(previous_gdt+2,	(NVALUES - 2))
8580028Stakawata	TRANSFER_STACK32(previous_tr,		(NVALUES - 1))
8680028Stakawata	TRANSFER_STACK32(previous_cr0,		(NVALUES - 0))
8780028Stakawata
8880028Stakawata	mov	physical_esp,%esi	/* to be used in 32bit code */
8980028Stakawata
9080028Stakawata	/* Enable protected mode */
9180028Stakawata	mov	%cr0,%eax
9280028Stakawata	orl	$(CR0_PE),%eax
9380028Stakawata	mov	%eax,%cr0
9480028Stakawata
9580028Stakawatawakeup_sw32:
9680028Stakawata	/* Switch to protected mode by intersegmental jump */
9780028Stakawata	ljmpl	$0x8,$0x12345678	/* Code location, to be replaced */
9880028Stakawata
9980028Stakawata	.code32
10080028Stakawatawakeup_32:
10180028Stakawata	/*
10280028Stakawata	 * Switched to protected mode w/o paging
10380028Stakawata	 *	%esi:	KERNEL stack pointer (physical address)
10480028Stakawata	 */
10580028Stakawata
10680028Stakawata	nop
10780028Stakawata
10880028Stakawata	/* Set up segment registers for protected mode */
10980028Stakawata	movw	$0x10,%ax		/* KDSEL to segment registers */
11080028Stakawata	movw	%ax,%ds
11180028Stakawata	movw	%ax,%es
11280028Stakawata	movw	%ax,%gs
11380028Stakawata	movw	%ax,%ss
11480028Stakawata	movw	$0x18,%ax		/* KPSEL to %fs */
11580028Stakawata	movw	%ax,%fs
11680028Stakawata	movl	%esi,%esp		/* physical address stack pointer */
11780028Stakawata
11880028Stakawatawakeup_32stack:
11980028Stakawata	/* Operands are overwritten in 16bit code */
12080028Stakawata	pushl	$0xabcdef09		/* ss + dummy */
12180028Stakawata	pushl	$0xabcdef08		/* fs + gs */
12280028Stakawata	pushl	$0xabcdef07		/* ds + es */
12380028Stakawata	pushl	$0xabcdef06		/* gdt:base (physical address) */
12480028Stakawata	pushl	$0xabcdef05		/* recover address */
12580028Stakawata	pushl	$0xabcdef04		/* idt:base */
12680028Stakawata	pushl	$0xabcdef03		/* ldt + idt:limit */
12780028Stakawata	pushl	$0xabcdef02		/* gdt:base */
12880028Stakawata	pushl	$0xabcdef01		/* TR + gdt:limit */
12980028Stakawata	pushl	$0xabcdef00		/* CR0 */
13080028Stakawata
13180028Stakawata	movl	%esp,%ebp
13280028Stakawata#define CR0_REGISTER		0(%ebp)
13380028Stakawata#define TASK_REGISTER		4(%ebp)
13480028Stakawata#define PREVIOUS_GDT		6(%ebp)
13580028Stakawata#define PREVIOUS_LDT		12(%ebp)
13680028Stakawata#define PREVIOUS_IDT		14(%ebp)
13780028Stakawata#define RECOVER_ADDR		20(%ebp)
13880028Stakawata#define PHYSICAL_GDT_BASE	24(%ebp)
13980028Stakawata#define PREVIOUS_DS		28(%ebp)
14080028Stakawata#define PREVIOUS_ES		30(%ebp)
14180028Stakawata#define PREVIOUS_FS		32(%ebp)
14280028Stakawata#define PREVIOUS_GS		34(%ebp)
14380028Stakawata#define PREVIOUS_SS		36(%ebp)
14480028Stakawata
14580028Stakawata	/* Fixup TSS type field */
14680028Stakawata#define TSS_TYPEFIX_MASK	0xf9
14780028Stakawata	xorl	%esi,%esi
14880028Stakawata	movl	PHYSICAL_GDT_BASE,%ebx
14980028Stakawata	movw	TASK_REGISTER,%si
15080028Stakawata	leal	(%ebx,%esi),%eax	/* get TSS segment descriptor */
15180028Stakawata	andb	$TSS_TYPEFIX_MASK,5(%eax)
15280028Stakawata
15380028Stakawata	/* Prepare to return to sleep/wakeup code point */
15480028Stakawata	lgdt	PREVIOUS_GDT
15580028Stakawata	lidt	PREVIOUS_IDT
15680028Stakawata
15780028Stakawata	xorl	%eax,%eax
15880028Stakawata	movl	%eax,%ebx
15980028Stakawata	movl	%eax,%ecx
16080028Stakawata	movl	%eax,%edx
16180028Stakawata	movl	%eax,%esi
16280028Stakawata	movl	%eax,%edi
16380028Stakawata	movl	PREVIOUS_DS,%ebx
16480028Stakawata	movl	PREVIOUS_FS,%ecx
16580028Stakawata	movl	PREVIOUS_SS,%edx
16680028Stakawata	movw	TASK_REGISTER,%si
16780028Stakawata	shll	$16,%esi
16880028Stakawata	movw	PREVIOUS_LDT,%si
16980028Stakawata	movl	RECOVER_ADDR,%edi
17080028Stakawata
17180028Stakawata	/* Enable paging and etc. */
17280028Stakawata	movl	CR0_REGISTER,%eax
17380028Stakawata	movl	%eax,%cr0
17480028Stakawata
17580028Stakawata	/* Flush the prefetch queue */
17680028Stakawata	jmp	1f
17780028Stakawata1:	jmp	1f
17880028Stakawata1:
17980028Stakawata	/*
18080028Stakawata	 * Now that we are in kernel virtual memory addressing
18180028Stakawata	 *	%ebx:	ds + es
18280028Stakawata	 *	%ecx:	fs + gs
18380028Stakawata	 *	%edx:	ss + dummy
18480028Stakawata	 *	%esi:	LDTR + TR
18580028Stakawata	 *	%edi:	recover address
18680028Stakawata	 */
18780028Stakawata
18880028Stakawata	nop
18980028Stakawata
19080028Stakawata	movl	%esi,%eax		/* LDTR + TR */
19180028Stakawata	lldt	%ax			/* load LDT register */
19280028Stakawata	shrl	$16,%eax
19380028Stakawata	ltr	%ax			/* load task register */
19480028Stakawata
19580028Stakawata	/* Restore segment registers */
19680028Stakawata	movl	%ebx,%eax		/* ds + es */
19780028Stakawata	movw	%ax,%ds
19880028Stakawata	shrl	$16,%eax
19980028Stakawata	movw	%ax,%es
20080028Stakawata	movl	%ecx,%eax		/* fs + gs */
20180028Stakawata	movw	%ax,%fs
20280028Stakawata	shrl	$16,%eax
20380028Stakawata	movw	%ax,%gs
20480028Stakawata	movl	%edx,%eax		/* ss */
20580028Stakawata	movw	%ax,%ss
20680028Stakawata
20780028Stakawata	/* Jump to acpi_restorecpu() */
20880028Stakawata	jmp	*%edi
20980028Stakawata
21080028Stakawata/* used in real mode */
21180028Stakawataphysical_gdt:		.word 0
21280028Stakawata			.long 0
21380028Stakawataphysical_esp:		.long 0
21480028Stakawataprevious_cr2:		.long 0
21580028Stakawataprevious_cr3:		.long 0
21680028Stakawataprevious_cr4:		.long 0
217121743Siwasakino_reset_video:		.long 0
21880028Stakawata
21980028Stakawata/* transfer from real mode to protected mode */
22080028Stakawataprevious_cr0:		.long 0
22180028Stakawataprevious_tr:		.word 0
22280028Stakawataprevious_gdt:		.word 0
22380028Stakawata			.long 0
22480028Stakawataprevious_ldt:		.word 0
22580028Stakawataprevious_idt:		.word 0
22680028Stakawata			.long 0
22780028Stakawatawhere_to_recover:	.long 0
22880028Stakawataprevious_ds:		.word 0
22980028Stakawataprevious_es:		.word 0
23080028Stakawataprevious_fs:		.word 0
23180028Stakawataprevious_gs:		.word 0
23280028Stakawataprevious_ss:		.word 0
23380028Stakawatadummy:			.word 0
234