1	.globl	entry, __switch_context, __exit_context, halt, init_exceptions
2
3	.text
4	.align	4
5
6/*
7 * Entry point
8 * We start execution from here.
9 * It is assumed that CPU is in 32-bit protected mode and
10 * all segments are 4GB and base zero (flat model).
11 */
12entry:
13	/* Save boot context and switch to our main context.
14	 * Main context is statically defined in C.
15	 */
16	pushl	%cs
17	call	__switch_context
18
19	/* We get here when the main context switches back to
20	 * the boot context.
21	 * Return to previous bootloader.
22	 */
23	ret
24
25/*
26 * Switch execution context
27 * This saves registers, segments, and GDT in the stack, then
28 * switches the stack, and restores everything from the new stack.
29 * This function takes no argument. New stack pointer is
30 * taken from global variable __context, and old stack pointer
31 * is also saved to __context. This way we can just jump to
32 * this routine to get back to the original context.
33 *
34 * Call this routine with lcall or pushl %cs; call.
35 */
36__switch_context:
37	/* Save everything in current stack */
38	pushfl		    /* 56 */
39	pushl	%ds	    /* 52 */
40	pushl	%es	    /* 48 */
41	pushl	%fs	    /* 44 */
42	pushl	%gs	    /* 40 */
43	pushal		    /* 8 */
44	subl	$8, %esp
45	movw	%ss, (%esp) /* 0 */
46	sgdt	2(%esp)	    /* 2 */
47
48#if 0
49	/* Swap %cs and %eip on the stack, so lret will work */
50	movl	60(%esp), %eax
51	xchgl	%eax, 64(%esp)
52	movl	%eax, 60(%esp)
53#endif
54
55	/* At this point we don't know if we are on flat segment
56	 * or relocated. So compute the address offset from %eip.
57	 * Assuming CS.base==DS.base==SS.base.
58	 */
59	call	1f
601:	popl	%ebx
61	subl	$1b, %ebx
62
63	/* Interrupts are not allowed... */
64	cli
65
66	/* Current context pointer is our stack pointer */
67	movl	%esp, %esi
68
69	/* Normalize the ctx pointer */
70	subl	%ebx, %esi
71
72	/* Swap it with new value */
73	xchgl	%esi, __context(%ebx)
74
75	/* Adjust new ctx pointer for current address offset */
76	addl	%ebx, %esi
77
78	/* Load new %ss and %esp to temporary */
79	movzwl	(%esi), %edx
80	movl	20(%esi), %eax
81
82	/* Load new GDT */
83	lgdt	2(%esi)
84
85	/* Load new stack segment with new GDT */
86	movl	%edx, %ss
87
88	/* Set new stack pointer, but we have to adjust it because
89	 * pushal saves %esp value before pushal, and we want the value
90	 * after pushal.
91	 */
92	leal	-32(%eax), %esp
93
94	/* Load the rest from new stack */
95	popal
96	popl	%gs
97	popl	%fs
98	popl	%es
99	popl	%ds
100	popfl
101
102	/* Finally, load new %cs and %eip */
103	lret
104
105__exit_context:
106	/* Get back to the original context */
107	pushl	%cs
108	call	__switch_context
109
110	/* We get here if the other context attempt to switch to this
111	 * dead context. This should not happen. */
112
113halt:
114	cli
115	hlt
116	jmp	halt
117
118/*
119 * initialize exception handler. All exceptions end up in the same
120 * C function.
121 */
122
123init_exceptions:
124	pushl	%ebx
125	pushl	%edi
126
127        /* Initialize the Interrupt Descriptor table */
128        leal    _idt, %edi
129        leal    vec0, %ebx
130        movl    $(0x08 << 16), %eax     /* cs selector */
131
1321:      movw    %bx, %ax
133        movl    %ebx, %edx
134        movw    $0x8E00, %dx            /* Interrupt gate - dpl=0, present */
135        movl    %eax, 0(%edi)
136        movl    %edx, 4(%edi)
137        addl    $6, %ebx
138        addl    $8, %edi
139        cmpl    $_idt_end, %edi
140        jne     1b
141
142        /* Load the Interrupt descriptor table */
143        lidt    idtarg
144
145	movl 	$0, %eax
146	popl	%edi
147	popl	%ebx
148	ret
149
150vec0:
151        pushl   $0 /* error code */
152        pushl   $0 /* vector */
153        jmp int_hand
154vec1:
155        pushl   $0 /* error code */
156        pushl   $1 /* vector */
157        jmp int_hand
158
159vec2:
160        pushl   $0 /* error code */
161        pushl   $2 /* vector */
162        jmp int_hand
163
164vec3:
165        pushl   $0 /* error code */
166        pushl   $3 /* vector */
167        jmp     int_hand
168
169vec4:
170        pushl   $0 /* error code */
171        pushl   $4 /* vector */
172        jmp     int_hand
173
174vec5:
175        pushl   $0 /* error code */
176        pushl   $5 /* vector */
177        jmp     int_hand
178
179vec6:
180        pushl   $0 /* error code */
181        pushl   $6 /* vector */
182        jmp     int_hand
183vec7:
184        pushl   $0 /* error code */
185        pushl   $7 /* vector */
186        jmp     int_hand
187
188vec8:
189        /* error code */
190        pushl   $8 /* vector */
191        jmp     int_hand
192        .word   0x9090
193
194vec9:
195        pushl   $0 /* error code */
196        pushl   $9 /* vector */
197        jmp int_hand
198
199vec10:
200        /* error code */
201        pushl   $10 /* vector */
202        jmp     int_hand
203        .word   0x9090
204
205vec11:
206        /* error code */
207        pushl   $11 /* vector */
208        jmp     int_hand
209        .word   0x9090
210
211vec12:
212        /* error code */
213        pushl   $12 /* vector */
214        jmp     int_hand
215        .word   0x9090
216
217vec13:
218        /* error code */
219        pushl   $13 /* vector */
220        jmp     int_hand
221        .word   0x9090
222
223vec14:
224        /* error code */
225        pushl   $14 /* vector */
226        jmp     int_hand
227        .word   0x9090
228
229vec15:
230        pushl   $0 /* error code */
231        pushl   $15 /* vector */
232        jmp     int_hand
233
234vec16:
235        pushl   $0 /* error code */
236        pushl   $16 /* vector */
237        jmp     int_hand
238
239vec17:
240        /* error code */
241        pushl   $17 /* vector */
242        jmp     int_hand
243        .word   0x9090
244
245vec18:
246        pushl   $0 /* error code */
247        pushl   $18 /* vector */
248        jmp     int_hand
249
250vec19:
251        pushl   $0 /* error code */
252        pushl   $19 /* vector */
253        jmp     int_hand
254
255__divide_error:
256        pushl   $0 /* error code */
257        pushl   $20 /* vector */
258        jmp     int_hand
259        .global __divide_error
260
261int_hand:
262        /* At this point on the stack there is:
263         *  0(%esp) vector
264         *  4(%esp) error code
265         *  8(%esp) eip
266         * 12(%esp) cs
267         * 16(%esp) eflags
268         */
269        pushl   %edi
270        pushl   %esi
271        pushl   %ebp
272        /* Original stack pointer */
273        leal    32(%esp), %ebp
274        pushl   %ebp
275        pushl   %ebx
276        pushl   %edx
277        pushl   %ecx
278        pushl   %eax
279
280        pushl   %esp    /* Pointer to structure on the stack */
281
282        call    x86_exception
283        pop     %eax    /* Drop the pointer */
284
285        popl    %eax
286        popl    %ecx
287        popl    %edx
288        popl    %ebx
289        popl    %ebp /* Ignore saved %esp value */
290        popl    %ebp
291        popl    %esi
292        popl    %edi
293
294        addl    $8, %esp /* pop of the vector and error code */
295
296        iret
297
298idtarg:
299        .word   _idt_end - _idt - 1     /* limit */
300        .long   _idt
301        .word   0
302_idt:
303        .fill   20, 8, 0        # idt is unitiailzed
304_idt_end:
305
306        .globl  arch_nvram_size, arch_nvram_get, arch_nvram_put
307arch_nvram_size:
308        xor     %eax, %eax
309        ret
310
311arch_nvram_get:
312        ret
313
314arch_nvram_put:
315        ret
316