acpi_wakecode.S revision 121743
169626Sru/*-
269626Sru * Copyright (c) 2001 Takanori Watanabe <takawata@jp.freebsd.org>
369626Sru * Copyright (c) 2001 Mitsuru IWASAKI <iwasaki@jp.freebsd.org>
469626Sru * All rights reserved.
569626Sru *
669626Sru * Redistribution and use in source and binary forms, with or without
769626Sru * modification, are permitted provided that the following conditions
869626Sru * are met:
969626Sru * 1. Redistributions of source code must retain the above copyright
1069626Sru *    notice, this list of conditions and the following disclaimer.
1169626Sru * 2. Redistributions in binary form must reproduce the above copyright
1269626Sru *    notice, this list of conditions and the following disclaimer in the
1369626Sru *    documentation and/or other materials provided with the distribution.
1469626Sru *
1569626Sru * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1669626Sru * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1769626Sru * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1869626Sru * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1969626Sru * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2069626Sru * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2169626Sru * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2269626Sru * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2369626Sru * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2455839Sasmodai * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2555839Sasmodai * SUCH DAMAGE.
2655839Sasmodai */
2755839Sasmodai
2869626Sru#include <machine/asm.h>
2969626Sru__FBSDID("$FreeBSD: head/sys/i386/acpica/acpi_wakecode.S 121743 2003-10-30 16:14:55Z iwasaki $");
3055839Sasmodai
3169626Sru#define LOCORE
3255839Sasmodai
3355839Sasmodai#include <machine/specialreg.h>
3455839Sasmodai
3555839Sasmodai	.align 4
3655839Sasmodai	.code16
3755839Sasmodaiwakeup_16:
3855839Sasmodai	nop
3955839Sasmodai	cli
4055839Sasmodai
4155839Sasmodai	/* Set up segment registers for real mode */
4255839Sasmodai	movw	%cs,%ax
4355839Sasmodai	movw	%ax,%ds
4469626Sru	movw	%ax,%ss
4555839Sasmodai
4655839Sasmodai#ifndef ACPI_NO_RESET_VIDEO
4755839Sasmodai	/*
4855839Sasmodai	 * Re-initialize video BIOS.  Restore DS and SS from CS in
4955839Sasmodai	 * case the BIOS modified them.
5069626Sru	 */
5169626Sru	cmp	$1, no_reset_video
5269626Sru	je	wakeup_16_gdt
5369626Sru	lcall	$0xc000, $3
5469626Sru	movw	%cs, %ax
5569626Sru	movw	%ax, %ds
5669626Sru	movw	%ax, %ss
5755839Sasmodai#endif
5869626Sru
5969626Sruwakeup_16_gdt:
6069626Sru	/* Load GDT for real mode */
6169626Sru	lgdt	physical_gdt
6269626Sru
6369626Sru	/* Restore CR2, CR3 and CR4 */
6469626Sru	mov	previous_cr2,%eax
6569626Sru	mov	%eax,%cr2
6669626Sru	mov	previous_cr3,%eax
6769626Sru	mov	%eax,%cr3
6869626Sru	mov	previous_cr4,%eax
6969626Sru	mov	%eax,%cr4
7069626Sru
7169626Sru	/* Transfer some values to protected mode */
7269626Sru#define NVALUES	9
7369626Sru#define TRANSFER_STACK32(val, idx)	\
7469626Sru	mov	val,%eax;		\
7569626Sru	mov	%eax,wakeup_32stack+(idx+1)+(idx*4);
7669626Sru
7769626Sru	TRANSFER_STACK32(previous_ss,		(NVALUES - 9))
7869626Sru	TRANSFER_STACK32(previous_fs,		(NVALUES - 8))
7969626Sru	TRANSFER_STACK32(previous_ds,		(NVALUES - 7))
8069626Sru	TRANSFER_STACK32(physical_gdt+2,	(NVALUES - 6))
8169626Sru	TRANSFER_STACK32(where_to_recover,	(NVALUES - 5))
8269626Sru	TRANSFER_STACK32(previous_idt+2,	(NVALUES - 4))
8369626Sru	TRANSFER_STACK32(previous_ldt,		(NVALUES - 3))
8469626Sru	TRANSFER_STACK32(previous_gdt+2,	(NVALUES - 2))
8569626Sru	TRANSFER_STACK32(previous_tr,		(NVALUES - 1))
8669626Sru	TRANSFER_STACK32(previous_cr0,		(NVALUES - 0))
8769626Sru
8869626Sru	mov	physical_esp,%esi	/* to be used in 32bit code */
8969626Sru
9069626Sru	/* Enable protected mode */
9169626Sru	mov	%cr0,%eax
9269626Sru	orl	$(CR0_PE),%eax
9369626Sru	mov	%eax,%cr0
9469626Sru
9569626Sruwakeup_sw32:
9669626Sru	/* Switch to protected mode by intersegmental jump */
9769626Sru	ljmpl	$0x8,$0x12345678	/* Code location, to be replaced */
9855839Sasmodai
9955839Sasmodai	.code32
10055839Sasmodaiwakeup_32:
10155839Sasmodai	/*
10255839Sasmodai	 * Switched to protected mode w/o paging
10355839Sasmodai	 *	%esi:	KERNEL stack pointer (physical address)
10455839Sasmodai	 */
10555839Sasmodai
10655839Sasmodai	nop
10769626Sru
10869626Sru	/* Set up segment registers for protected mode */
10969626Sru	movw	$0x10,%ax		/* KDSEL to segment registers */
11069626Sru	movw	%ax,%ds
11169626Sru	movw	%ax,%es
11269626Sru	movw	%ax,%gs
11369626Sru	movw	%ax,%ss
11469626Sru	movw	$0x18,%ax		/* KPSEL to %fs */
11569626Sru	movw	%ax,%fs
11669626Sru	movl	%esi,%esp		/* physical address stack pointer */
11769626Sru
11869626Sruwakeup_32stack:
11969626Sru	/* Operands are overwritten in 16bit code */
12069626Sru	pushl	$0xabcdef09		/* ss + dummy */
12169626Sru	pushl	$0xabcdef08		/* fs + gs */
12269626Sru	pushl	$0xabcdef07		/* ds + es */
12369626Sru	pushl	$0xabcdef06		/* gdt:base (physical address) */
12469626Sru	pushl	$0xabcdef05		/* recover address */
12569626Sru	pushl	$0xabcdef04		/* idt:base */
12669626Sru	pushl	$0xabcdef03		/* ldt + idt:limit */
12769626Sru	pushl	$0xabcdef02		/* gdt:base */
12869626Sru	pushl	$0xabcdef01		/* TR + gdt:limit */
12969626Sru	pushl	$0xabcdef00		/* CR0 */
13069626Sru
13169626Sru	movl	%esp,%ebp
13255839Sasmodai#define CR0_REGISTER		0(%ebp)
13369626Sru#define TASK_REGISTER		4(%ebp)
13469626Sru#define PREVIOUS_GDT		6(%ebp)
13569626Sru#define PREVIOUS_LDT		12(%ebp)
13669626Sru#define PREVIOUS_IDT		14(%ebp)
13769626Sru#define RECOVER_ADDR		20(%ebp)
13869626Sru#define PHYSICAL_GDT_BASE	24(%ebp)
13969626Sru#define PREVIOUS_DS		28(%ebp)
14069626Sru#define PREVIOUS_ES		30(%ebp)
14169626Sru#define PREVIOUS_FS		32(%ebp)
14269626Sru#define PREVIOUS_GS		34(%ebp)
14355839Sasmodai#define PREVIOUS_SS		36(%ebp)
14469626Sru
14569626Sru	/* Fixup TSS type field */
14669626Sru#define TSS_TYPEFIX_MASK	0xf9
14769626Sru	xorl	%esi,%esi
14869626Sru	movl	PHYSICAL_GDT_BASE,%ebx
14969626Sru	movw	TASK_REGISTER,%si
15069626Sru	leal	(%ebx,%esi),%eax	/* get TSS segment descriptor */
15169626Sru	andb	$TSS_TYPEFIX_MASK,5(%eax)
15269626Sru
15369626Sru	/* Prepare to return to sleep/wakeup code point */
15455839Sasmodai	lgdt	PREVIOUS_GDT
15555839Sasmodai	lidt	PREVIOUS_IDT
15669626Sru
15755839Sasmodai	xorl	%eax,%eax
15855839Sasmodai	movl	%eax,%ebx
15969626Sru	movl	%eax,%ecx
16069626Sru	movl	%eax,%edx
16155839Sasmodai	movl	%eax,%esi
16255839Sasmodai	movl	%eax,%edi
16355839Sasmodai	movl	PREVIOUS_DS,%ebx
16455839Sasmodai	movl	PREVIOUS_FS,%ecx
16555839Sasmodai	movl	PREVIOUS_SS,%edx
16655839Sasmodai	movw	TASK_REGISTER,%si
16755839Sasmodai	shll	$16,%esi
16855839Sasmodai	movw	PREVIOUS_LDT,%si
16955839Sasmodai	movl	RECOVER_ADDR,%edi
17069626Sru
17169626Sru	/* Enable paging and etc. */
17269626Sru	movl	CR0_REGISTER,%eax
17369626Sru	movl	%eax,%cr0
17469626Sru
17569626Sru	/* Flush the prefetch queue */
17655839Sasmodai	jmp	1f
17769626Sru1:	jmp	1f
17869626Sru1:
17969626Sru	/*
18069626Sru	 * Now that we are in kernel virtual memory addressing
18169626Sru	 *	%ebx:	ds + es
18255839Sasmodai	 *	%ecx:	fs + gs
18355839Sasmodai	 *	%edx:	ss + dummy
18469626Sru	 *	%esi:	LDTR + TR
18569626Sru	 *	%edi:	recover address
18669626Sru	 */
18769626Sru
18869626Sru	nop
18955839Sasmodai
19055839Sasmodai	movl	%esi,%eax		/* LDTR + TR */
19155839Sasmodai	lldt	%ax			/* load LDT register */
19255839Sasmodai	shrl	$16,%eax
19355839Sasmodai	ltr	%ax			/* load task register */
19469626Sru
19555839Sasmodai	/* Restore segment registers */
19669626Sru	movl	%ebx,%eax		/* ds + es */
19769626Sru	movw	%ax,%ds
19869626Sru	shrl	$16,%eax
19969626Sru	movw	%ax,%es
20069626Sru	movl	%ecx,%eax		/* fs + gs */
20169626Sru	movw	%ax,%fs
20255839Sasmodai	shrl	$16,%eax
20355839Sasmodai	movw	%ax,%gs
20469626Sru	movl	%edx,%eax		/* ss */
20569626Sru	movw	%ax,%ss
20655839Sasmodai
20769626Sru	/* Jump to acpi_restorecpu() */
20869626Sru	jmp	*%edi
20969626Sru
21055839Sasmodai/* used in real mode */
21155839Sasmodaiphysical_gdt:		.word 0
21269626Sru			.long 0
21369626Sruphysical_esp:		.long 0
21455839Sasmodaiprevious_cr2:		.long 0
21555839Sasmodaiprevious_cr3:		.long 0
21669626Sruprevious_cr4:		.long 0
21769626Sruno_reset_video:		.long 0
21869626Sru
21969626Sru/* transfer from real mode to protected mode */
22055839Sasmodaiprevious_cr0:		.long 0
22155839Sasmodaiprevious_tr:		.word 0
22269626Sruprevious_gdt:		.word 0
22355839Sasmodai			.long 0
22455839Sasmodaiprevious_ldt:		.word 0
22569626Sruprevious_idt:		.word 0
22669626Sru			.long 0
22769626Sruwhere_to_recover:	.long 0
22869626Sruprevious_ds:		.word 0
22969626Sruprevious_es:		.word 0
23069626Sruprevious_fs:		.word 0
23169626Sruprevious_gs:		.word 0
23269626Sruprevious_ss:		.word 0
23369626Srudummy:			.word 0
23469626Sru