xref: /minix3/minix/kernel/arch/i386/klib.S (revision 433d6423c39e34ec4b79c950597bb2d236f886be)
1*433d6423SLionel Sambuc/* sections */
2*433d6423SLionel Sambuc
3*433d6423SLionel Sambuc
4*433d6423SLionel Sambuc#include <minix/config.h>
5*433d6423SLionel Sambuc#include <minix/const.h>
6*433d6423SLionel Sambuc#include <machine/asm.h>
7*433d6423SLionel Sambuc#include <machine/interrupt.h>
8*433d6423SLionel Sambuc#include <machine/vm.h>
9*433d6423SLionel Sambuc#include "archconst.h"
10*433d6423SLionel Sambuc#include "kernel/const.h"
11*433d6423SLionel Sambuc#include "sconst.h"
12*433d6423SLionel Sambuc#include <machine/multiboot.h>
13*433d6423SLionel Sambuc
14*433d6423SLionel Sambuc
15*433d6423SLionel Sambuc/* Easy way to make functions */
16*433d6423SLionel Sambuc
17*433d6423SLionel Sambuc/* Make a function of the form func(arg) */
18*433d6423SLionel Sambuc
19*433d6423SLionel Sambuc#define STACKARG 8(%ebp)
20*433d6423SLionel Sambuc
21*433d6423SLionel Sambuc#define ARG_EAX_ACTION(FUNCTION, ACTION)        ;\
22*433d6423SLionel SambucENTRY(FUNCTION)                         ;\
23*433d6423SLionel Sambuc        push    %ebp                    ;\
24*433d6423SLionel Sambuc        mov     %esp, %ebp              ;\
25*433d6423SLionel Sambuc        mov     STACKARG, %eax           ;\
26*433d6423SLionel Sambuc        ACTION                          ;\
27*433d6423SLionel Sambuc        pop     %ebp                    ;\
28*433d6423SLionel Sambuc        ret
29*433d6423SLionel Sambuc
30*433d6423SLionel Sambuc/* Make a function of the form ret = func() */
31*433d6423SLionel Sambuc#define ARG_EAX_RETURN(FUNCTION, EXPR)        ;\
32*433d6423SLionel SambucENTRY(FUNCTION)                         ;\
33*433d6423SLionel Sambuc        push    %ebp                    ;\
34*433d6423SLionel Sambuc        mov     %esp, %ebp              ;\
35*433d6423SLionel Sambuc        mov	EXPR, %eax              ;\
36*433d6423SLionel Sambuc        pop     %ebp                    ;\
37*433d6423SLionel Sambuc	ret
38*433d6423SLionel Sambuc
39*433d6423SLionel Sambuc/* Make a function of the form ret = func() */
40*433d6423SLionel Sambuc#define ARG_EAX_SET(FUNCTION, DEST)        ;\
41*433d6423SLionel SambucENTRY(FUNCTION)                         ;\
42*433d6423SLionel Sambuc        push    %ebp                    ;\
43*433d6423SLionel Sambuc        mov     %esp, %ebp              ;\
44*433d6423SLionel Sambuc	mov     STACKARG, %eax		;\
45*433d6423SLionel Sambuc        mov	%eax, DEST              ;\
46*433d6423SLionel Sambuc	jmp 0f /* a jump is required for some sets */ ;\
47*433d6423SLionel Sambuc0: 	pop     %ebp                    ;\
48*433d6423SLionel Sambuc        ret
49*433d6423SLionel Sambuc
50*433d6423SLionel Sambuc/* Make a function of the form ret = func() */
51*433d6423SLionel Sambuc#define ARG_AX_SET(FUNCTION, DEST)        ;\
52*433d6423SLionel SambucENTRY(FUNCTION)                         ;\
53*433d6423SLionel Sambuc        push    %ebp                    ;\
54*433d6423SLionel Sambuc        mov     %esp, %ebp              ;\
55*433d6423SLionel Sambuc	mov     STACKARG, %eax		;\
56*433d6423SLionel Sambuc        mov	%ax, DEST               ;\
57*433d6423SLionel Sambuc	jmp 0f /* a jump is required for some sets */ ;\
58*433d6423SLionel Sambuc0: 	pop     %ebp                    ;\
59*433d6423SLionel Sambuc        ret
60*433d6423SLionel Sambuc
61*433d6423SLionel Sambuc/*
62*433d6423SLionel Sambuc * This file contains a number of assembly code utility routines needed by the
63*433d6423SLionel Sambuc * kernel.
64*433d6423SLionel Sambuc */
65*433d6423SLionel Sambuc
66*433d6423SLionel SambucENTRY(__main)
67*433d6423SLionel Sambuc	ret
68*433d6423SLionel Sambuc
69*433d6423SLionel Sambuc
70*433d6423SLionel Sambuc/*===========================================================================*/
71*433d6423SLionel Sambuc/*				phys_insw				     */
72*433d6423SLionel Sambuc/*===========================================================================*/
73*433d6423SLionel Sambuc/*
74*433d6423SLionel Sambuc * PUBLIC void phys_insw(Port_t port, phys_bytes buf, size_t count);
75*433d6423SLionel Sambuc * Input an array from an I/O port.  Absolute address version of insw().
76*433d6423SLionel Sambuc */
77*433d6423SLionel Sambuc/* transfer data from (disk controller) port to memory */
78*433d6423SLionel SambucENTRY(phys_insw)
79*433d6423SLionel Sambuc	push	%ebp
80*433d6423SLionel Sambuc	mov	%esp, %ebp
81*433d6423SLionel Sambuc	cld
82*433d6423SLionel Sambuc	push	%edi
83*433d6423SLionel Sambuc
84*433d6423SLionel Sambuc	mov	8(%ebp), %edx	/* port to read from */
85*433d6423SLionel Sambuc	mov	12(%ebp), %edi	/* destination addr */
86*433d6423SLionel Sambuc	mov	16(%ebp), %ecx	/* byte count */
87*433d6423SLionel Sambuc	shr	$1, %ecx	/* word count */
88*433d6423SLionel Sambuc	rep insw	/* input many words */
89*433d6423SLionel Sambuc	pop	%edi
90*433d6423SLionel Sambuc	pop	%ebp
91*433d6423SLionel Sambuc	ret
92*433d6423SLionel Sambuc
93*433d6423SLionel Sambuc
94*433d6423SLionel Sambuc/*===========================================================================*/
95*433d6423SLionel Sambuc/*				phys_insb				     */
96*433d6423SLionel Sambuc/*===========================================================================*/
97*433d6423SLionel Sambuc/*
98*433d6423SLionel Sambuc * PUBLIC void phys_insb(Port_t port, phys_bytes buf, size_t count);
99*433d6423SLionel Sambuc * Input an array from an I/O port.  Absolute address version of insb().
100*433d6423SLionel Sambuc */
101*433d6423SLionel Sambuc/* transfer data from (disk controller) port to memory byte by byte */
102*433d6423SLionel SambucENTRY(phys_insb)
103*433d6423SLionel Sambuc	push	%ebp
104*433d6423SLionel Sambuc	mov	%esp, %ebp
105*433d6423SLionel Sambuc	cld
106*433d6423SLionel Sambuc	push	%edi
107*433d6423SLionel Sambuc
108*433d6423SLionel Sambuc	mov	8(%ebp), %edx	/* port to read from */
109*433d6423SLionel Sambuc	mov	12(%ebp), %edi	/* destination addr */
110*433d6423SLionel Sambuc	mov	16(%ebp), %ecx	/* byte count */
111*433d6423SLionel Sambuc	rep insb	/* input many bytes */
112*433d6423SLionel Sambuc	pop	%edi
113*433d6423SLionel Sambuc	pop	%ebp
114*433d6423SLionel Sambuc	ret
115*433d6423SLionel Sambuc
116*433d6423SLionel Sambuc
117*433d6423SLionel Sambuc/*===========================================================================*/
118*433d6423SLionel Sambuc/*				phys_outsw				     */
119*433d6423SLionel Sambuc/*===========================================================================*/
120*433d6423SLionel Sambuc/*
121*433d6423SLionel Sambuc * PUBLIC void phys_outsw(Port_t port, phys_bytes buf, size_t count);
122*433d6423SLionel Sambuc * Output an array to an I/O port.  Absolute address version of outsw().
123*433d6423SLionel Sambuc */
124*433d6423SLionel Sambuc/* transfer data from memory to (disk controller) port */
125*433d6423SLionel SambucENTRY(phys_outsw)
126*433d6423SLionel Sambuc	push	%ebp
127*433d6423SLionel Sambuc	mov	%esp, %ebp
128*433d6423SLionel Sambuc	cld
129*433d6423SLionel Sambuc	push	%esi
130*433d6423SLionel Sambuc
131*433d6423SLionel Sambuc	mov	8(%ebp), %edx	/* port to write to */
132*433d6423SLionel Sambuc	mov	12(%ebp), %esi	/* source addr */
133*433d6423SLionel Sambuc	mov	16(%ebp), %ecx	/* byte count */
134*433d6423SLionel Sambuc	shr	$1, %ecx	/* word count */
135*433d6423SLionel Sambuc	rep outsw	/* output many words */
136*433d6423SLionel Sambuc	pop	%esi
137*433d6423SLionel Sambuc	pop	%ebp
138*433d6423SLionel Sambuc	ret
139*433d6423SLionel Sambuc
140*433d6423SLionel Sambuc
141*433d6423SLionel Sambuc/*===========================================================================*/
142*433d6423SLionel Sambuc/*				phys_outsb				     */
143*433d6423SLionel Sambuc/*===========================================================================*/
144*433d6423SLionel Sambuc/*
145*433d6423SLionel Sambuc * PUBLIC void phys_outsb(Port_t port, phys_bytes buf, size_t count);
146*433d6423SLionel Sambuc * Output an array to an I/O port.  Absolute address version of outsb().
147*433d6423SLionel Sambuc */
148*433d6423SLionel Sambuc/* transfer data from memory to (disk controller) port byte by byte */
149*433d6423SLionel SambucENTRY(phys_outsb)
150*433d6423SLionel Sambuc	push	%ebp
151*433d6423SLionel Sambuc	mov	%esp, %ebp
152*433d6423SLionel Sambuc	cld
153*433d6423SLionel Sambuc	push	%esi
154*433d6423SLionel Sambuc
155*433d6423SLionel Sambuc	mov	8(%ebp), %edx	/* port to write to */
156*433d6423SLionel Sambuc	mov	12(%ebp), %esi	/* source addr */
157*433d6423SLionel Sambuc	mov	16(%ebp), %ecx	/* byte count */
158*433d6423SLionel Sambuc	rep outsb	/* output many bytes */
159*433d6423SLionel Sambuc	pop	%esi
160*433d6423SLionel Sambuc	pop	%ebp
161*433d6423SLionel Sambuc	ret
162*433d6423SLionel Sambuc
163*433d6423SLionel Sambuc
164*433d6423SLionel Sambuc/*===========================================================================*/
165*433d6423SLionel Sambuc/*				phys_copy				     */
166*433d6423SLionel Sambuc/*===========================================================================*/
167*433d6423SLionel Sambuc/*
168*433d6423SLionel Sambuc * PUBLIC phys_bytes phys_copy(phys_bytes source, phys_bytes destination,
169*433d6423SLionel Sambuc *			phys_bytes bytecount);
170*433d6423SLionel Sambuc * Copy a block of data from anywhere to anywhere in physical memory.
171*433d6423SLionel Sambuc */
172*433d6423SLionel Sambuc/*		es edi esi eip	 src dst len */
173*433d6423SLionel SambucENTRY(phys_copy)
174*433d6423SLionel Sambuc	push	%ebp
175*433d6423SLionel Sambuc	mov	%esp, %ebp
176*433d6423SLionel Sambuc
177*433d6423SLionel Sambuc	cld
178*433d6423SLionel Sambuc	push	%esi
179*433d6423SLionel Sambuc	push	%edi
180*433d6423SLionel Sambuc
181*433d6423SLionel Sambuc	mov	8(%ebp), %esi
182*433d6423SLionel Sambuc	mov	12(%ebp), %edi
183*433d6423SLionel Sambuc	mov	16(%ebp), %eax
184*433d6423SLionel Sambuc
185*433d6423SLionel Sambuc	cmp	$10, %eax	/* avoid align overhead for small counts */
186*433d6423SLionel Sambuc	jb	pc_small
187*433d6423SLionel Sambuc	mov	%esi, %ecx	/* align source, hope target is too */
188*433d6423SLionel Sambuc	neg	%ecx
189*433d6423SLionel Sambuc	and	$3, %ecx	/* count for alignment */
190*433d6423SLionel Sambuc	sub	%ecx, %eax
191*433d6423SLionel Sambuc
192*433d6423SLionel Sambuc	rep 	movsb (%esi), (%edi)
193*433d6423SLionel Sambuc	mov	%eax, %ecx
194*433d6423SLionel Sambuc	shr	$2, %ecx	/* count of dwords */
195*433d6423SLionel Sambuc
196*433d6423SLionel Sambuc	rep 	movsl (%esi), (%edi)
197*433d6423SLionel Sambuc	and	$3, %eax
198*433d6423SLionel Sambucpc_small:
199*433d6423SLionel Sambuc	xchg	%eax, %ecx	/* remainder */
200*433d6423SLionel Sambuc
201*433d6423SLionel Sambuc	rep 	movsb (%esi), (%edi)
202*433d6423SLionel Sambuc
203*433d6423SLionel Sambuc	mov	$0, %eax		/* 0 means: no fault */
204*433d6423SLionel SambucLABEL(phys_copy_fault)		/* kernel can send us here */
205*433d6423SLionel Sambuc	pop	%edi
206*433d6423SLionel Sambuc	pop	%esi
207*433d6423SLionel Sambuc	pop	%ebp
208*433d6423SLionel Sambuc	ret
209*433d6423SLionel Sambuc
210*433d6423SLionel SambucLABEL(phys_copy_fault_in_kernel)	/* kernel can send us here */
211*433d6423SLionel Sambuc	pop	%edi
212*433d6423SLionel Sambuc	pop	%esi
213*433d6423SLionel Sambuc	pop	%ebp
214*433d6423SLionel Sambuc	mov	%cr2, %eax
215*433d6423SLionel Sambuc	ret
216*433d6423SLionel Sambuc
217*433d6423SLionel Sambuc
218*433d6423SLionel Sambuc/*===========================================================================*/
219*433d6423SLionel Sambuc/*				copy_msg_from_user			     */
220*433d6423SLionel Sambuc/*===========================================================================*/
221*433d6423SLionel Sambuc/*
222*433d6423SLionel Sambuc * int copy_msg_from_user(message * user_mbuf, message * dst);
223*433d6423SLionel Sambuc *
224*433d6423SLionel Sambuc * Copies a message of 64 bytes from user process space to a kernel buffer. This
225*433d6423SLionel Sambuc * function assumes that the process address space is installed (cr3 loaded).
226*433d6423SLionel Sambuc *
227*433d6423SLionel Sambuc * This function from the callers point of view either succeeds or returns an
228*433d6423SLionel Sambuc * error which gives the caller a chance to respond accordingly. In fact it
229*433d6423SLionel Sambuc * either succeeds or if it generates a pagefault, general protection or other
230*433d6423SLionel Sambuc * exception, the trap handler has to redirect the execution to
231*433d6423SLionel Sambuc * __user_copy_msg_pointer_failure where the error is reported to the caller
232*433d6423SLionel Sambuc * without resolving the pagefault. It is not kernel's problem to deal with
233*433d6423SLionel Sambuc * wrong pointers from userspace and the caller should return an error to
234*433d6423SLionel Sambuc * userspace as if wrong values or request were passed to the kernel
235*433d6423SLionel Sambuc */
236*433d6423SLionel SambucENTRY(copy_msg_from_user)
237*433d6423SLionel Sambuc	/* load the source pointer */
238*433d6423SLionel Sambuc	mov	4(%esp), %ecx
239*433d6423SLionel Sambuc	/* load the destination pointer */
240*433d6423SLionel Sambuc	mov	8(%esp), %edx
241*433d6423SLionel Sambuc
242*433d6423SLionel Sambuc/*	mov	0*4(%ecx), %eax
243*433d6423SLionel Sambuc	mov	%eax, 0*4(%edx) */
244*433d6423SLionel Sambuc	mov	1*4(%ecx), %eax
245*433d6423SLionel Sambuc	mov	%eax, 1*4(%edx)
246*433d6423SLionel Sambuc	mov	2*4(%ecx), %eax
247*433d6423SLionel Sambuc	mov	%eax, 2*4(%edx)
248*433d6423SLionel Sambuc	mov	3*4(%ecx), %eax
249*433d6423SLionel Sambuc	mov	%eax, 3*4(%edx)
250*433d6423SLionel Sambuc	mov	4*4(%ecx), %eax
251*433d6423SLionel Sambuc	mov	%eax, 4*4(%edx)
252*433d6423SLionel Sambuc	mov	5*4(%ecx), %eax
253*433d6423SLionel Sambuc	mov	%eax, 5*4(%edx)
254*433d6423SLionel Sambuc	mov	6*4(%ecx), %eax
255*433d6423SLionel Sambuc	mov	%eax, 6*4(%edx)
256*433d6423SLionel Sambuc	mov	7*4(%ecx), %eax
257*433d6423SLionel Sambuc	mov	%eax, 7*4(%edx)
258*433d6423SLionel Sambuc	mov	8*4(%ecx), %eax
259*433d6423SLionel Sambuc	mov	%eax, 8*4(%edx)
260*433d6423SLionel Sambuc
261*433d6423SLionel Sambuc	mov	 9*4(%ecx), %eax
262*433d6423SLionel Sambuc	mov	%eax,  9*4(%edx)
263*433d6423SLionel Sambuc	mov	10*4(%ecx), %eax
264*433d6423SLionel Sambuc	mov	%eax, 10*4(%edx)
265*433d6423SLionel Sambuc	mov	11*4(%ecx), %eax
266*433d6423SLionel Sambuc	mov	%eax, 11*4(%edx)
267*433d6423SLionel Sambuc	mov	12*4(%ecx), %eax
268*433d6423SLionel Sambuc	mov	%eax, 12*4(%edx)
269*433d6423SLionel Sambuc	mov	13*4(%ecx), %eax
270*433d6423SLionel Sambuc	mov	%eax, 13*4(%edx)
271*433d6423SLionel Sambuc	mov	14*4(%ecx), %eax
272*433d6423SLionel Sambuc	mov	%eax, 14*4(%edx)
273*433d6423SLionel Sambuc	mov	15*4(%ecx), %eax
274*433d6423SLionel Sambuc	mov	%eax, 15*4(%edx)
275*433d6423SLionel Sambuc
276*433d6423SLionel SambucLABEL(__copy_msg_from_user_end)
277*433d6423SLionel Sambuc	movl	$0, %eax
278*433d6423SLionel Sambuc	ret
279*433d6423SLionel Sambuc
280*433d6423SLionel Sambuc/*===========================================================================*/
281*433d6423SLionel Sambuc/*				copy_msg_to_user			     */
282*433d6423SLionel Sambuc/*===========================================================================*/
283*433d6423SLionel Sambuc/*
284*433d6423SLionel Sambuc * void copy_msg_to_user(message * src, message * user_mbuf);
285*433d6423SLionel Sambuc *
286*433d6423SLionel Sambuc * Copies a message of 64 bytes to user process space from a kernel buffer.
287*433d6423SLionel Sambuc *
288*433d6423SLionel Sambuc * All the other copy_msg_from_user() comments apply here as well!
289*433d6423SLionel Sambuc */
290*433d6423SLionel SambucENTRY(copy_msg_to_user)
291*433d6423SLionel Sambuc	/* load the source pointer */
292*433d6423SLionel Sambuc	mov	4(%esp), %ecx
293*433d6423SLionel Sambuc	/* load the destination pointer */
294*433d6423SLionel Sambuc	mov	8(%esp), %edx
295*433d6423SLionel Sambuc
296*433d6423SLionel Sambuc	mov	0*4(%ecx), %eax
297*433d6423SLionel Sambuc	mov	%eax, 0*4(%edx)
298*433d6423SLionel Sambuc	mov	1*4(%ecx), %eax
299*433d6423SLionel Sambuc	mov	%eax, 1*4(%edx)
300*433d6423SLionel Sambuc	mov	2*4(%ecx), %eax
301*433d6423SLionel Sambuc	mov	%eax, 2*4(%edx)
302*433d6423SLionel Sambuc	mov	3*4(%ecx), %eax
303*433d6423SLionel Sambuc	mov	%eax, 3*4(%edx)
304*433d6423SLionel Sambuc	mov	4*4(%ecx), %eax
305*433d6423SLionel Sambuc	mov	%eax, 4*4(%edx)
306*433d6423SLionel Sambuc	mov	5*4(%ecx), %eax
307*433d6423SLionel Sambuc	mov	%eax, 5*4(%edx)
308*433d6423SLionel Sambuc	mov	6*4(%ecx), %eax
309*433d6423SLionel Sambuc	mov	%eax, 6*4(%edx)
310*433d6423SLionel Sambuc	mov	7*4(%ecx), %eax
311*433d6423SLionel Sambuc	mov	%eax, 7*4(%edx)
312*433d6423SLionel Sambuc	mov	8*4(%ecx), %eax
313*433d6423SLionel Sambuc	mov	%eax, 8*4(%edx)
314*433d6423SLionel Sambuc
315*433d6423SLionel Sambuc
316*433d6423SLionel Sambuc	mov	9*4(%ecx), %eax
317*433d6423SLionel Sambuc	mov	%eax, 9*4(%edx)
318*433d6423SLionel Sambuc	mov	10*4(%ecx), %eax
319*433d6423SLionel Sambuc	mov	%eax, 10*4(%edx)
320*433d6423SLionel Sambuc	mov	11*4(%ecx), %eax
321*433d6423SLionel Sambuc	mov	%eax, 11*4(%edx)
322*433d6423SLionel Sambuc	mov	12*4(%ecx), %eax
323*433d6423SLionel Sambuc	mov	%eax, 12*4(%edx)
324*433d6423SLionel Sambuc	mov	13*4(%ecx), %eax
325*433d6423SLionel Sambuc	mov	%eax, 13*4(%edx)
326*433d6423SLionel Sambuc	mov	14*4(%ecx), %eax
327*433d6423SLionel Sambuc	mov	%eax, 14*4(%edx)
328*433d6423SLionel Sambuc	mov	15*4(%ecx), %eax
329*433d6423SLionel Sambuc	mov	%eax, 15*4(%edx)
330*433d6423SLionel Sambuc
331*433d6423SLionel SambucLABEL(__copy_msg_to_user_end)
332*433d6423SLionel Sambuc	movl	$0, %eax
333*433d6423SLionel Sambuc	ret
334*433d6423SLionel Sambuc
335*433d6423SLionel Sambuc/*
336*433d6423SLionel Sambuc * if a function from a selected set of copies from or to userspace fails, it is
337*433d6423SLionel Sambuc * because of a wrong pointer supplied by the userspace. We have to clean up and
338*433d6423SLionel Sambuc * and return -1 to indicated that something wrong has happend. The place it was
339*433d6423SLionel Sambuc * called from has to handle this situation. The exception handler redirect us
340*433d6423SLionel Sambuc * here to continue, clean up and report the error
341*433d6423SLionel Sambuc */
342*433d6423SLionel SambucENTRY(__user_copy_msg_pointer_failure)
343*433d6423SLionel Sambuc	movl	$-1, %eax
344*433d6423SLionel Sambuc	ret
345*433d6423SLionel Sambuc
346*433d6423SLionel Sambuc/*===========================================================================*/
347*433d6423SLionel Sambuc/*				phys_memset				     */
348*433d6423SLionel Sambuc/*===========================================================================*/
349*433d6423SLionel Sambuc/*
350*433d6423SLionel Sambuc * PUBLIC void phys_memset(phys_bytes dst, unsigned long pattern,
351*433d6423SLionel Sambuc *	phys_bytes bytecount);
352*433d6423SLionel Sambuc * Fill a block of physical memory with pattern.
353*433d6423SLionel Sambuc */
354*433d6423SLionel SambucENTRY(phys_memset)
355*433d6423SLionel Sambuc	push	%ebp
356*433d6423SLionel Sambuc	mov	%esp, %ebp
357*433d6423SLionel Sambuc	push	%edi
358*433d6423SLionel Sambuc	cld
359*433d6423SLionel Sambuc
360*433d6423SLionel Sambuc	mov	8(%ebp), %edi
361*433d6423SLionel Sambuc	mov	16(%ebp), %ecx
362*433d6423SLionel Sambuc	mov	12(%ebp), %eax
363*433d6423SLionel Sambuc	shr	$2, %ecx
364*433d6423SLionel Sambuc	rep stosl
365*433d6423SLionel Sambuc
366*433d6423SLionel Sambuc/* Any remaining bytes? */
367*433d6423SLionel Sambuc	mov	16(%ebp), %ecx
368*433d6423SLionel Sambuc	and	$3, %ecx
369*433d6423SLionel Sambuc	rep stosb
370*433d6423SLionel Sambuc
371*433d6423SLionel SambucLABEL(memset_fault)		/* kernel can send us here */
372*433d6423SLionel Sambuc	mov	$0, %eax		/* 0 means: no fault */
373*433d6423SLionel Sambuc	pop	%edi
374*433d6423SLionel Sambuc	pop	%ebp
375*433d6423SLionel Sambuc	ret
376*433d6423SLionel Sambuc
377*433d6423SLionel SambucLABEL(memset_fault_in_kernel)		/* kernel can send us here */
378*433d6423SLionel Sambuc	pop	%edi
379*433d6423SLionel Sambuc	pop	%ebp
380*433d6423SLionel Sambuc	mov	%cr2, %eax
381*433d6423SLionel Sambuc	ret
382*433d6423SLionel Sambuc
383*433d6423SLionel Sambuc/*===========================================================================*/
384*433d6423SLionel Sambuc/*				x86_triplefault				     */
385*433d6423SLionel Sambuc/*===========================================================================*/
386*433d6423SLionel Sambuc/*
387*433d6423SLionel Sambuc * PUBLIC void x86_triplefault();
388*433d6423SLionel Sambuc * Reset the system by loading IDT with offset 0 and interrupting.
389*433d6423SLionel Sambuc */
390*433d6423SLionel SambucENTRY(x86_triplefault)
391*433d6423SLionel Sambuc	lidt	idt_zero
392*433d6423SLionel Sambuc	int	$3	/* anything goes, the 386 will not like it */
393*433d6423SLionel Sambuc.data
394*433d6423SLionel Sambucidt_zero:
395*433d6423SLionel Sambuc.long	0, 0
396*433d6423SLionel Sambuc.text
397*433d6423SLionel Sambuc
398*433d6423SLionel Sambuc
399*433d6423SLionel Sambuc/*===========================================================================*/
400*433d6423SLionel Sambuc/*			      	halt_cpu				     */
401*433d6423SLionel Sambuc/*===========================================================================*/
402*433d6423SLionel Sambuc/*
403*433d6423SLionel Sambuc * PUBLIC void halt_cpu(void);
404*433d6423SLionel Sambuc * reanables interrupts and puts the cpu in the halts state. Once an interrupt
405*433d6423SLionel Sambuc * is handled the execution resumes by disabling interrupts and continues
406*433d6423SLionel Sambuc */
407*433d6423SLionel SambucENTRY(halt_cpu)
408*433d6423SLionel Sambuc	sti
409*433d6423SLionel Sambuc	hlt /* interrupts enabled only after this instruction is executed! */
410*433d6423SLionel Sambuc	/*
411*433d6423SLionel Sambuc	 * interrupt handlers make sure that the interrupts are disabled when we
412*433d6423SLionel Sambuc	 * get here so we take only _one_ interrupt after halting the CPU
413*433d6423SLionel Sambuc	 */
414*433d6423SLionel Sambuc	ret
415*433d6423SLionel Sambuc
416*433d6423SLionel Sambuc/*===========================================================================*/
417*433d6423SLionel Sambuc/*			poweroff_vmware_clihlt				     */
418*433d6423SLionel Sambuc/*===========================================================================*/
419*433d6423SLionel Sambuc/*
420*433d6423SLionel Sambuc * PUBLIC void poweroff_vmware_clihlt(void);
421*433d6423SLionel Sambuc * VMware detects this peculiar sequence and forces the virtual machine off
422*433d6423SLionel Sambuc * when the parameter gui.exitOnCLIHLT is set to TRUE.
423*433d6423SLionel Sambuc * Otherwise this sequence just hangs the CPU, requiring a power down action.
424*433d6423SLionel Sambuc */
425*433d6423SLionel SambucENTRY(poweroff_vmware_clihlt)
426*433d6423SLionel Sambuc#ifndef NO_VMWARE_DETECTION
427*433d6423SLionel Sambuc	mov	$1, %eax
428*433d6423SLionel Sambuc	cpuid
429*433d6423SLionel Sambuc	test	$[1<<31], %ecx /* "virtualized" */
430*433d6423SLionel Sambuc	jz	1f	/* always 0 on real hardware */
431*433d6423SLionel Sambuc	mov	$0x40000000, %eax /* select hypervisor-use leaf */
432*433d6423SLionel Sambuc	cpuid
433*433d6423SLionel Sambuc	cmp	$0x61774D56, %ebx /* ASCII "VMwa" */
434*433d6423SLionel Sambuc	jne	1f
435*433d6423SLionel Sambuc	cmp	$0x4D566572, %ecx /* ASCII "reVM" */
436*433d6423SLionel Sambuc	jne	1f
437*433d6423SLionel Sambuc	cmp	$0x65726177, %edx /* ASCII "ware" */
438*433d6423SLionel Sambuc	jne	1f
439*433d6423SLionel Sambuc	/* we are virtualized by some VMware product! */
440*433d6423SLionel Sambuc#endif
441*433d6423SLionel Sambuc	cli
442*433d6423SLionel Sambuc	hlt
443*433d6423SLionel Sambuc1:	ret
444*433d6423SLionel Sambuc
445*433d6423SLionel Sambuc/*===========================================================================*/
446*433d6423SLionel Sambuc/*			      read_flags				     */
447*433d6423SLionel Sambuc/*===========================================================================*/
448*433d6423SLionel Sambuc/*
449*433d6423SLionel Sambuc * PUBLIC unsigned long read_cpu_flags(void);
450*433d6423SLionel Sambuc * Read CPU status flags from C.
451*433d6423SLionel Sambuc */
452*433d6423SLionel SambucENTRY(read_cpu_flags)
453*433d6423SLionel Sambuc	pushf
454*433d6423SLionel Sambuc	mov	(%esp), %eax
455*433d6423SLionel Sambuc	add	$4, %esp
456*433d6423SLionel Sambuc	ret
457*433d6423SLionel Sambuc
458*433d6423SLionel SambucENTRY(read_ds)
459*433d6423SLionel Sambuc	mov	$0, %eax
460*433d6423SLionel Sambuc	mov	%ds, %ax
461*433d6423SLionel Sambuc	ret
462*433d6423SLionel Sambuc
463*433d6423SLionel SambucENTRY(read_cs)
464*433d6423SLionel Sambuc	mov	$0, %eax
465*433d6423SLionel Sambuc	mov	%cs, %ax
466*433d6423SLionel Sambuc	ret
467*433d6423SLionel Sambuc
468*433d6423SLionel SambucENTRY(read_ss)
469*433d6423SLionel Sambuc	mov	$0, %eax
470*433d6423SLionel Sambuc	mov	%ss, %ax
471*433d6423SLionel Sambuc	ret
472*433d6423SLionel Sambuc
473*433d6423SLionel Sambuc/*===========================================================================*/
474*433d6423SLionel Sambuc/*                            fpu_routines                                   */
475*433d6423SLionel Sambuc/*===========================================================================*/
476*433d6423SLionel Sambuc
477*433d6423SLionel Sambuc/* non-waiting FPU initialization */
478*433d6423SLionel SambucENTRY(fninit)
479*433d6423SLionel Sambuc	fninit
480*433d6423SLionel Sambuc	ret
481*433d6423SLionel Sambuc
482*433d6423SLionel SambucENTRY(clts)
483*433d6423SLionel Sambuc	clts
484*433d6423SLionel Sambuc	ret
485*433d6423SLionel Sambuc
486*433d6423SLionel Sambuc/* store status word (non-waiting) */
487*433d6423SLionel SambucENTRY(fnstsw)
488*433d6423SLionel Sambuc	xor     %eax, %eax
489*433d6423SLionel Sambuc
490*433d6423SLionel Sambuc	/* DO NOT CHANGE THE OPERAND!!! gas2ack does not handle it yet */
491*433d6423SLionel Sambuc	fnstsw	%ax
492*433d6423SLionel Sambuc	ret
493*433d6423SLionel Sambuc
494*433d6423SLionel Sambuc/*===========================================================================*/
495*433d6423SLionel Sambuc/*				fxrstor					     */
496*433d6423SLionel Sambuc/*===========================================================================*/
497*433d6423SLionel SambucENTRY(fxrstor)
498*433d6423SLionel Sambuc	mov	4(%esp), %eax
499*433d6423SLionel Sambuc	fxrstor	(%eax)
500*433d6423SLionel SambucENTRY(__fxrstor_end)
501*433d6423SLionel Sambuc	xor     %eax, %eax
502*433d6423SLionel Sambuc	ret
503*433d6423SLionel Sambuc
504*433d6423SLionel Sambuc/*===========================================================================*/
505*433d6423SLionel Sambuc/*				frstor					     */
506*433d6423SLionel Sambuc/*===========================================================================*/
507*433d6423SLionel SambucENTRY(frstor)
508*433d6423SLionel Sambuc	mov	4(%esp), %eax
509*433d6423SLionel Sambuc	frstor	(%eax)
510*433d6423SLionel SambucENTRY(__frstor_end)
511*433d6423SLionel Sambuc	xor     %eax, %eax
512*433d6423SLionel Sambuc	ret
513*433d6423SLionel Sambuc
514*433d6423SLionel Sambuc/* Shared exception handler for both fxrstor and frstor. */
515*433d6423SLionel SambucENTRY(__frstor_failure)
516*433d6423SLionel Sambuc	mov	$1, %eax
517*433d6423SLionel Sambuc	ret
518*433d6423SLionel Sambuc
519*433d6423SLionel Sambuc/* Read/write control registers */
520*433d6423SLionel SambucARG_EAX_RETURN(read_cr0, %cr0);
521*433d6423SLionel SambucARG_EAX_RETURN(read_cr2, %cr2);
522*433d6423SLionel SambucARG_EAX_RETURN(read_cr3, %cr3);
523*433d6423SLionel SambucARG_EAX_RETURN(read_cr4, %cr4);
524*433d6423SLionel SambucARG_EAX_SET(write_cr4, %cr4);
525*433d6423SLionel SambucARG_EAX_SET(write_cr0, %cr0);
526*433d6423SLionel SambucARG_EAX_SET(write_cr3, %cr3);
527*433d6423SLionel Sambuc
528*433d6423SLionel Sambuc/* Read/write various descriptor tables */
529*433d6423SLionel SambucARG_EAX_ACTION(x86_ltr, ltr STACKARG );
530*433d6423SLionel SambucARG_EAX_ACTION(x86_lidt, lidtl (%eax));
531*433d6423SLionel SambucARG_EAX_ACTION(x86_lgdt, lgdt (%eax));
532*433d6423SLionel SambucARG_EAX_ACTION(x86_lldt, lldt STACKARG);
533*433d6423SLionel SambucARG_EAX_ACTION(x86_sgdt, sgdt (%eax));
534*433d6423SLionel SambucARG_EAX_ACTION(x86_sidt, sidt (%eax));
535*433d6423SLionel Sambuc
536*433d6423SLionel Sambuc/* Load segments */
537*433d6423SLionel SambucARG_AX_SET(x86_load_ds, %ds)
538*433d6423SLionel SambucARG_AX_SET(x86_load_es, %es)
539*433d6423SLionel SambucARG_AX_SET(x86_load_fs, %fs)
540*433d6423SLionel SambucARG_AX_SET(x86_load_gs, %gs)
541*433d6423SLionel SambucARG_AX_SET(x86_load_ss, %ss)
542*433d6423SLionel Sambuc
543*433d6423SLionel Sambuc/* FPU */
544*433d6423SLionel SambucARG_EAX_ACTION(fnsave, fnsave (%eax) ; fwait);
545*433d6423SLionel SambucARG_EAX_ACTION(fxsave, fxsave (%eax));
546*433d6423SLionel SambucARG_EAX_ACTION(fnstcw, fnstcw (%eax));
547*433d6423SLionel Sambuc
548*433d6423SLionel Sambuc/* invlpg */
549*433d6423SLionel SambucARG_EAX_ACTION(i386_invlpg, invlpg (%eax));
550*433d6423SLionel Sambuc
551*433d6423SLionel SambucENTRY(x86_load_kerncs)
552*433d6423SLionel Sambuc	push	%ebp
553*433d6423SLionel Sambuc	mov	%esp, %ebp
554*433d6423SLionel Sambuc	mov	8(%ebp), %eax
555*433d6423SLionel Sambuc	jmp	$KERN_CS_SELECTOR, $newcs
556*433d6423SLionel Sambucnewcs:
557*433d6423SLionel Sambuc	pop	%ebp
558*433d6423SLionel Sambuc	ret
559*433d6423SLionel Sambuc
560*433d6423SLionel Sambuc/*
561*433d6423SLionel Sambuc * Read the Model Specific Register (MSR) of IA32 architecture
562*433d6423SLionel Sambuc *
563*433d6423SLionel Sambuc * void ia32_msr_read(u32_t reg, u32_t * hi, u32_t * lo)
564*433d6423SLionel Sambuc */
565*433d6423SLionel SambucENTRY(ia32_msr_read)
566*433d6423SLionel Sambuc	push	%ebp
567*433d6423SLionel Sambuc	mov	%esp, %ebp
568*433d6423SLionel Sambuc
569*433d6423SLionel Sambuc	mov	8(%ebp), %ecx
570*433d6423SLionel Sambuc	rdmsr
571*433d6423SLionel Sambuc	mov	12(%ebp), %ecx
572*433d6423SLionel Sambuc	mov	%edx, (%ecx)
573*433d6423SLionel Sambuc	mov	16(%ebp), %ecx
574*433d6423SLionel Sambuc	mov	%eax, (%ecx)
575*433d6423SLionel Sambuc
576*433d6423SLionel Sambuc	pop	%ebp
577*433d6423SLionel Sambuc	ret
578*433d6423SLionel Sambuc
579*433d6423SLionel Sambuc/*
580*433d6423SLionel Sambuc * Write the Model Specific Register (MSR) of IA32 architecture
581*433d6423SLionel Sambuc *
582*433d6423SLionel Sambuc * void ia32_msr_write(u32_t reg, u32_t hi, u32_t lo)
583*433d6423SLionel Sambuc */
584*433d6423SLionel SambucENTRY(ia32_msr_write)
585*433d6423SLionel Sambuc	push	%ebp
586*433d6423SLionel Sambuc	mov	%esp, %ebp
587*433d6423SLionel Sambuc
588*433d6423SLionel Sambuc	mov	12(%ebp), %edx
589*433d6423SLionel Sambuc	mov	16(%ebp), %eax
590*433d6423SLionel Sambuc	mov	8(%ebp), %ecx
591*433d6423SLionel Sambuc	wrmsr
592*433d6423SLionel Sambuc
593*433d6423SLionel Sambuc	pop	%ebp
594*433d6423SLionel Sambuc	ret
595*433d6423SLionel Sambuc
596*433d6423SLionel Sambuc/*===========================================================================*/
597*433d6423SLionel Sambuc/*			      __switch_address_space			     */
598*433d6423SLionel Sambuc/*===========================================================================*/
599*433d6423SLionel Sambuc/* PUBLIC void __switch_address_space(struct proc *p, struct ** ptproc)
600*433d6423SLionel Sambuc *
601*433d6423SLionel Sambuc * sets the %cr3 register to the supplied value if it is not already set to the
602*433d6423SLionel Sambuc * same value in which case it would only result in an extra TLB flush which is
603*433d6423SLionel Sambuc * not desirable
604*433d6423SLionel Sambuc */
605*433d6423SLionel SambucENTRY(__switch_address_space)
606*433d6423SLionel Sambuc	/* read the process pointer */
607*433d6423SLionel Sambuc	mov	4(%esp), %edx
608*433d6423SLionel Sambuc	/* get the new cr3 value */
609*433d6423SLionel Sambuc	movl	P_CR3(%edx), %eax
610*433d6423SLionel Sambuc	/* test if the new cr3 != NULL */
611*433d6423SLionel Sambuc	cmpl	$0, %eax
612*433d6423SLionel Sambuc	je	0f
613*433d6423SLionel Sambuc
614*433d6423SLionel Sambuc	/*
615*433d6423SLionel Sambuc	 * test if the cr3 is loaded with the current value to avoid unnecessary
616*433d6423SLionel Sambuc	 * TLB flushes
617*433d6423SLionel Sambuc	 */
618*433d6423SLionel Sambuc	mov	%cr3, %ecx
619*433d6423SLionel Sambuc	cmp	%ecx, %eax
620*433d6423SLionel Sambuc	je	0f
621*433d6423SLionel Sambuc	mov	%eax, %cr3
622*433d6423SLionel Sambuc	/* get ptproc */
623*433d6423SLionel Sambuc	mov	8(%esp), %eax
624*433d6423SLionel Sambuc	mov	%edx, (%eax)
625*433d6423SLionel Sambuc0:
626*433d6423SLionel Sambuc	ret
627*433d6423SLionel Sambuc
628*433d6423SLionel Sambuc/* acknowledge just the master PIC */
629*433d6423SLionel SambucENTRY(eoi_8259_master)
630*433d6423SLionel Sambuc	movb	$END_OF_INT, %al
631*433d6423SLionel Sambuc	outb	$INT_CTL
632*433d6423SLionel Sambuc	ret
633*433d6423SLionel Sambuc
634*433d6423SLionel Sambuc/* we have to acknowledge both PICs */
635*433d6423SLionel SambucENTRY(eoi_8259_slave)
636*433d6423SLionel Sambuc	movb	$END_OF_INT, %al
637*433d6423SLionel Sambuc	outb	$INT_CTL
638*433d6423SLionel Sambuc	outb	$INT2_CTL
639*433d6423SLionel Sambuc	ret
640*433d6423SLionel Sambuc
641*433d6423SLionel Sambuc/* in some cases we need to force TLB update, reloading cr3 does the trick */
642*433d6423SLionel SambucENTRY(refresh_tlb)
643*433d6423SLionel Sambuc	mov	%cr3, %eax
644*433d6423SLionel Sambuc	mov	%eax, %cr3
645*433d6423SLionel Sambuc	ret
646*433d6423SLionel Sambuc
647*433d6423SLionel Sambuc#ifdef CONFIG_SMP
648*433d6423SLionel Sambuc
649*433d6423SLionel Sambuc/*===========================================================================*/
650*433d6423SLionel Sambuc/*			      smp_get_htt				     */
651*433d6423SLionel Sambuc/*===========================================================================*/
652*433d6423SLionel Sambuc/*  PUBLIC int smp_get_htt(void); */
653*433d6423SLionel Sambuc/*  return true if the processor is hyper-threaded. */
654*433d6423SLionel SambucENTRY(smp_get_htt)
655*433d6423SLionel Sambuc	push	%ebp
656*433d6423SLionel Sambuc	mov	%esp, %ebp
657*433d6423SLionel Sambuc	pushf
658*433d6423SLionel Sambuc	pop	%eax
659*433d6423SLionel Sambuc	mov	%eax, %ebx
660*433d6423SLionel Sambuc	and	$0x200000, %eax
661*433d6423SLionel Sambuc	je	0f
662*433d6423SLionel Sambuc	mov	$0x1, %eax
663*433d6423SLionel Sambuc/* FIXME don't use the byte code */
664*433d6423SLionel Sambuc.byte	0x0f, 0xa2	/*  opcode for cpuid  */
665*433d6423SLionel Sambuc	mov	%edx, %eax
666*433d6423SLionel Sambuc	pop	%ebp
667*433d6423SLionel Sambuc	ret
668*433d6423SLionel Sambuc0:
669*433d6423SLionel Sambuc	xor	%eax, %eax
670*433d6423SLionel Sambuc	pop	%ebp
671*433d6423SLionel Sambuc	ret
672*433d6423SLionel Sambuc
673*433d6423SLionel Sambuc/*===========================================================================*/
674*433d6423SLionel Sambuc/*			      smp_get_num_htt				     */
675*433d6423SLionel Sambuc/*===========================================================================*/
676*433d6423SLionel Sambuc/*  PUBLIC int smp_get_num_htt(void); */
677*433d6423SLionel Sambuc/*  Get the number of hyper-threaded processor cores */
678*433d6423SLionel SambucENTRY(smp_get_num_htt)
679*433d6423SLionel Sambuc	push	%ebp
680*433d6423SLionel Sambuc	mov	%esp, %ebp
681*433d6423SLionel Sambuc	pushf
682*433d6423SLionel Sambuc	pop	%eax
683*433d6423SLionel Sambuc	mov	%eax, %ebx
684*433d6423SLionel Sambuc	and	$0x200000, %eax
685*433d6423SLionel Sambuc	je	0f
686*433d6423SLionel Sambuc	mov	$0x1, %eax
687*433d6423SLionel Sambuc/* FIXME don't use the byte code */
688*433d6423SLionel Sambuc.byte	0x0f, 0xa2	/*  opcode for cpuid  */
689*433d6423SLionel Sambuc	mov	%ebx, %eax
690*433d6423SLionel Sambuc	pop	%ebp
691*433d6423SLionel Sambuc	ret
692*433d6423SLionel Sambuc0:
693*433d6423SLionel Sambuc	xor	%eax, %eax
694*433d6423SLionel Sambuc	pop	%ebp
695*433d6423SLionel Sambuc	ret
696*433d6423SLionel Sambuc
697*433d6423SLionel Sambuc/*===========================================================================*/
698*433d6423SLionel Sambuc/*			      smp_get_cores				    */
699*433d6423SLionel Sambuc/*===========================================================================*/
700*433d6423SLionel Sambuc/*  PUBLIC int smp_get_cores(void); */
701*433d6423SLionel Sambuc/*  Get the number of cores. */
702*433d6423SLionel SambucENTRY(smp_get_cores)
703*433d6423SLionel Sambuc	push	%ebp
704*433d6423SLionel Sambuc	mov	%esp, %ebp
705*433d6423SLionel Sambuc	pushf
706*433d6423SLionel Sambuc	pop	%eax
707*433d6423SLionel Sambuc	mov	%eax, %ebx
708*433d6423SLionel Sambuc	and	$0x200000, %eax
709*433d6423SLionel Sambuc	je	0f
710*433d6423SLionel Sambuc	push	%ecx
711*433d6423SLionel Sambuc	xor	%ecx, %ecx
712*433d6423SLionel Sambuc	mov	$0x4, %eax
713*433d6423SLionel Sambuc/* FIXME don't use the byte code */
714*433d6423SLionel Sambuc.byte	0x0f, 0xa2	/*  opcode for cpuid  */
715*433d6423SLionel Sambuc	pop	%ebp
716*433d6423SLionel Sambuc	ret
717*433d6423SLionel Sambuc0:
718*433d6423SLionel Sambuc	xor	%eax, %eax
719*433d6423SLionel Sambuc	pop	%ebp
720*433d6423SLionel Sambuc	ret
721*433d6423SLionel Sambuc
722*433d6423SLionel Sambuc/*===========================================================================*/
723*433d6423SLionel Sambuc/*				arch_spinlock_lock				    */
724*433d6423SLionel Sambuc/*===========================================================================*/
725*433d6423SLionel Sambuc/* void arch_spinlock_lock (u32_t  *lock_data)
726*433d6423SLionel Sambuc * {
727*433d6423SLionel Sambuc * 	while (test_and_set(lock_data) == 1)
728*433d6423SLionel Sambuc *		while (*lock_data == 1)
729*433d6423SLionel Sambuc *			;
730*433d6423SLionel Sambuc * }
731*433d6423SLionel Sambuc * eax register is clobbered.
732*433d6423SLionel Sambuc */
733*433d6423SLionel SambucENTRY(arch_spinlock_lock)
734*433d6423SLionel Sambuc	mov	4(%esp), %eax
735*433d6423SLionel Sambuc	mov	$1, %edx
736*433d6423SLionel Sambuc2:
737*433d6423SLionel Sambuc	mov	$1, %ecx
738*433d6423SLionel Sambuc	xchg	%ecx, (%eax)
739*433d6423SLionel Sambuc	test	%ecx, %ecx
740*433d6423SLionel Sambuc	je	0f
741*433d6423SLionel Sambuc
742*433d6423SLionel Sambuc	cmp	$(1<< 16), %edx
743*433d6423SLionel Sambuc	je	1f
744*433d6423SLionel Sambuc	shl	%edx
745*433d6423SLionel Sambuc1:
746*433d6423SLionel Sambuc	mov	%edx, %ecx
747*433d6423SLionel Sambuc3:
748*433d6423SLionel Sambuc	pause
749*433d6423SLionel Sambuc	sub	$1, %ecx
750*433d6423SLionel Sambuc	test	%ecx, %ecx
751*433d6423SLionel Sambuc	jz	2b
752*433d6423SLionel Sambuc	jmp	3b
753*433d6423SLionel Sambuc0:
754*433d6423SLionel Sambuc	mfence
755*433d6423SLionel Sambuc	ret
756*433d6423SLionel Sambuc
757*433d6423SLionel Sambuc/*===========================================================================*/
758*433d6423SLionel Sambuc/*				arch_spinlock_unlock	                             */
759*433d6423SLionel Sambuc/*===========================================================================*/
760*433d6423SLionel Sambuc/* * void arch_spinlock_unlock (unsigned int *lockp) */
761*433d6423SLionel Sambuc/*  spin lock release routine. */
762*433d6423SLionel SambucENTRY(arch_spinlock_unlock)
763*433d6423SLionel Sambuc	mov	4(%esp), %eax
764*433d6423SLionel Sambuc	mov	$0, %ecx
765*433d6423SLionel Sambuc	xchg	%ecx, (%eax)
766*433d6423SLionel Sambuc	mfence
767*433d6423SLionel Sambuc	ret
768*433d6423SLionel Sambuc
769*433d6423SLionel Sambuc#endif /* CONFIG_SMP */
770*433d6423SLionel Sambuc
771*433d6423SLionel Sambuc/*===========================================================================*/
772*433d6423SLionel Sambuc/*			      mfence					     */
773*433d6423SLionel Sambuc/*===========================================================================*/
774*433d6423SLionel Sambuc/*  PUBLIC void mfence (void); */
775*433d6423SLionel Sambuc/*  architecture specific memory barrier routine. */
776*433d6423SLionel SambucENTRY(mfence)
777*433d6423SLionel Sambuc	mfence
778*433d6423SLionel Sambuc	ret
779*433d6423SLionel Sambuc
780*433d6423SLionel Sambuc/*===========================================================================*/
781*433d6423SLionel Sambuc/*			      arch_pause				     */
782*433d6423SLionel Sambuc/*===========================================================================*/
783*433d6423SLionel Sambuc/*  PUBLIC void arch_pause (void); */
784*433d6423SLionel Sambuc/*  architecture specific pause routine. */
785*433d6423SLionel SambucENTRY(arch_pause)
786*433d6423SLionel Sambuc	pause
787*433d6423SLionel Sambuc	ret
788*433d6423SLionel Sambuc
789*433d6423SLionel Sambuc/*===========================================================================*/
790*433d6423SLionel Sambuc/*			      read_ebp				     	     */
791*433d6423SLionel Sambuc/*===========================================================================*/
792*433d6423SLionel Sambuc/*  PUBLIC u16_t cpuid(void) */
793*433d6423SLionel SambucENTRY(read_ebp)
794*433d6423SLionel Sambuc	mov	%ebp, %eax
795*433d6423SLionel Sambuc	ret
796*433d6423SLionel Sambuc
797*433d6423SLionel SambucENTRY(interrupts_enable)
798*433d6423SLionel Sambuc	sti
799*433d6423SLionel Sambuc	ret
800*433d6423SLionel Sambuc
801*433d6423SLionel SambucENTRY(interrupts_disable)
802*433d6423SLionel Sambuc	cli
803*433d6423SLionel Sambuc	ret
804*433d6423SLionel Sambuc
805*433d6423SLionel Sambuc
806*433d6423SLionel Sambuc/*
807*433d6423SLionel Sambuc * void switch_k_stack(void * esp, void (* continuation)(void));
808*433d6423SLionel Sambuc *
809*433d6423SLionel Sambuc * sets the current stack pointer to the given value and continues execution at
810*433d6423SLionel Sambuc * the given address
811*433d6423SLionel Sambuc */
812*433d6423SLionel SambucENTRY(switch_k_stack)
813*433d6423SLionel Sambuc	/* get the arguments from the stack */
814*433d6423SLionel Sambuc	mov	8(%esp), %eax
815*433d6423SLionel Sambuc	mov	4(%esp), %ecx
816*433d6423SLionel Sambuc	mov	$0, %ebp	/* reset %ebp for stack trace */
817*433d6423SLionel Sambuc	mov	%ecx, %esp	/* set the new stack */
818*433d6423SLionel Sambuc	jmp	*%eax		/* and jump to the continuation */
819*433d6423SLionel Sambuc
820*433d6423SLionel Sambuc	/* NOT_REACHABLE */
821*433d6423SLionel Sambuc0:	jmp	0b
822*433d6423SLionel Sambuc
823*433d6423SLionel Sambuc.data
824*433d6423SLionel Sambucidt_ptr:
825*433d6423SLionel Sambuc	.short 0x3ff
826*433d6423SLionel Sambuc	.long 0x0
827*433d6423SLionel Sambuc
828*433d6423SLionel Sambucldtsel:
829*433d6423SLionel Sambuc	.long LDT_SELECTOR
830