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