summaryrefslogtreecommitdiffstats
path: root/arch/x86/secondary.S
blob: 4fa6f4e170273f1cb19b0edae90d4a086f3947bc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/*
 * This file is part of the coreboot project.
 *
 * Copyright (C) 2002 Linux Networx
 * (Written by Eric Biederman <ebiederman@lnxi.com> for Linux Networx)
 * Copyright (C) 2004 Ollie Lo
 * Copyright (C) 2005 YingHai Lu
 * Copyright (C) Copyright (C) 2005-2007 Stefan Reinauer <stepan@openbios.org>
 * Copyright (C) 2009 Ronald G. Minnich <rminnich@gmail.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 2 of the License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
 */
	.text
	.globl _secondary_start, _secondary_start_end
_secondary_start:
1:
	.code16
	.balign 4096
	cli
	movw	$0xdead, 0
	movw	$0xbeef, 2
	xorl	%eax, %eax
	movl	%eax, %cr3    /* Invalidate TLB*/
	/* On hyper threaded cpus, invalidating the cache here is
	 * very very bad.  Don't.
	 */
	movw	$0, 0
	movl	$1b, %ebx
	movw	$1, 0
	movw	$2, 0

	/* setup the data segment */
	movw	%cs, %ax
	movw	%ax, 2
	movw	$3, 0
	movw	%ax, %ds
	movw	$4, 0
	/* past this point, "0" means ds:0, i.e. cs:0, or the 
	 * segment part of the address. 
	 */

	data32	lgdt	gdtaddr  - _secondary_start
//	data32 lgdt %cs:gdtptr
	movw	$5, 0

	movl	%cr0, %eax
	movw	$6, 0
	andl	$0x7FFAFFD1, %eax /* PG,AM,WP,NE,TS,EM,MP = 0 */
	movw	$7, 0
	orl	$0x60000001, %eax /* CD, NW, PE = 1 */
	movw	$8, 0
	movl	%eax, %cr0
	movw	$9, 0
	hlt
	/* tested to this point but not past it */

	/* I am pretty sure this just jumps back into 
	 * ROM; it's an abs jump
	 */
	data32 ljmp	$0x10, $secondary32
	movw	$0xa, 0
1:	
	.code32
secondary32:
	hlt
	movw	$0x18, %ax
	movw	%ax, %ds
	movw	%ax, %es
	movw	%ax, %ss
	movw	%ax, %fs
	movw	%ax, %gs

	/* Load the Interrupt descriptor table */
	lidt	idtarg

	/* Set the stack pointer */
	movl	-4(%ebx),%esp
	movl	$0, -4(%ebx)

	call	secondary_cpu_init
1:	hlt
	jmp	1b
	.align 4

gdt_limit = gdt_end - gdt - 1		/* Compute the table limit. */

gdt:
gdtptr:
	.word	gdt_end - gdt -1	/* Compute the table limit. */
	.long	gdt			/* We know the offset. */
	.word	0

	/* selgdt 0x08, flat code segment */
	.word	0xffff, 0x0000
	.byte	0x00, 0x9b, 0xcf, 0x00

	/* selgdt 0x10, flat data segment */
	.word	0xffff, 0x0000
	.byte	0x00, 0x93, 0xcf, 0x00

	/* selgdt 0x18, flat code segment for CAR */
	.word	0xffff, 0x0000
	.byte	0x00, 0x9b, 0xcf, 0x00

	/* selgdt 0x20, flat data segment for CAR */
	.word	0xffff, 0x0000
	.byte	0x00, 0x93, 0xcf, 0x00
gdt_end:


	gdtaddr:
	.word   gdt_limit	/* the table limit */
	.long   gdt             /* we know the offset */
idtarg:
        .word   _idt_end - _idt - 1     /* limit */
        .long   _idt
        .word   0       
_idt:
        .fill   20, 8, 0        # idt is unitiailzed
_idt_end:


_secondary_start_end:
.code32