]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/i386/xen/exception.s
bypass call to trap when handling hypervisor_upcall
[FreeBSD/FreeBSD.git] / sys / i386 / xen / exception.s
1 /*-
2  * Copyright (c) 1989, 1990 William F. Jolitz.
3  * Copyright (c) 1990 The Regents of the University of California.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 4. Neither the name of the University nor the names of its contributors
15  *    may be used to endorse or promote products derived from this software
16  *    without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  *
30  * $FreeBSD$
31  */
32
33 #include "opt_apic.h"
34 #include "opt_npx.h"
35
36 #include <machine/asmacros.h>
37 #include <machine/psl.h>
38 #include <machine/trap.h>
39
40
41 #include "assym.s"
42
43 #define SEL_RPL_MASK    0x0002
44 #define __HYPERVISOR_iret       23
45         
46 /* Offsets into shared_info_t. */
47 #define evtchn_upcall_pending /* 0 */
48 #define evtchn_upcall_mask       1
49 #define XEN_BLOCK_EVENTS(reg)     movb $1,evtchn_upcall_mask(reg)
50 #define XEN_UNBLOCK_EVENTS(reg)   movb $0,evtchn_upcall_mask(reg)
51 #define XEN_TEST_PENDING(reg)     testb $0x1,evtchn_upcall_pending(reg)
52
53 #define POPA \
54         popl %edi; \
55         popl %esi; \
56         popl %ebp; \
57         popl %ebx; \
58         popl %ebx; \
59         popl %edx; \
60         popl %ecx; \
61         popl %eax;
62
63         .text
64
65 /*****************************************************************************/
66 /* Trap handling                                                             */
67 /*****************************************************************************/
68 /*
69  * Trap and fault vector routines.
70  *
71  * Most traps are 'trap gates', SDT_SYS386TGT.  A trap gate pushes state on
72  * the stack that mostly looks like an interrupt, but does not disable 
73  * interrupts.  A few of the traps we are use are interrupt gates, 
74  * SDT_SYS386IGT, which are nearly the same thing except interrupts are
75  * disabled on entry.
76  *
77  * The cpu will push a certain amount of state onto the kernel stack for
78  * the current process.  The amount of state depends on the type of trap 
79  * and whether the trap crossed rings or not.  See i386/include/frame.h.  
80  * At the very least the current EFLAGS (status register, which includes 
81  * the interrupt disable state prior to the trap), the code segment register,
82  * and the return instruction pointer are pushed by the cpu.  The cpu 
83  * will also push an 'error' code for certain traps.  We push a dummy 
84  * error code for those traps where the cpu doesn't in order to maintain 
85  * a consistent frame.  We also push a contrived 'trap number'.
86  *
87  * The cpu does not push the general registers, we must do that, and we 
88  * must restore them prior to calling 'iret'.  The cpu adjusts the %cs and
89  * %ss segment registers, but does not mess with %ds, %es, or %fs.  Thus we
90  * must load them with appropriate values for supervisor mode operation.
91  */
92
93 MCOUNT_LABEL(user)
94 MCOUNT_LABEL(btrap)
95
96 #define TRAP(a)         pushl $(a) ; jmp alltraps
97
98 IDTVEC(div)
99         pushl $0; TRAP(T_DIVIDE)
100 IDTVEC(dbg)
101         pushl $0; TRAP(T_TRCTRAP)
102 IDTVEC(nmi)
103         pushl $0; TRAP(T_NMI)
104 IDTVEC(bpt)
105         pushl $0; TRAP(T_BPTFLT)
106 IDTVEC(ofl)
107         pushl $0; TRAP(T_OFLOW)
108 IDTVEC(bnd)
109         pushl $0; TRAP(T_BOUND)
110 IDTVEC(ill)
111         pushl $0; TRAP(T_PRIVINFLT)
112 IDTVEC(dna)
113         pushl $0; TRAP(T_DNA)
114 IDTVEC(fpusegm)
115         pushl $0; TRAP(T_FPOPFLT)
116 IDTVEC(tss)
117         TRAP(T_TSSFLT)
118 IDTVEC(missing)
119         TRAP(T_SEGNPFLT)
120 IDTVEC(stk)
121         TRAP(T_STKFLT)
122 IDTVEC(prot)
123         TRAP(T_PROTFLT)
124 IDTVEC(page)
125         TRAP(T_PAGEFLT)
126 IDTVEC(mchk)
127         pushl $0; TRAP(T_MCHK)
128 IDTVEC(rsvd)
129         pushl $0; TRAP(T_RESERVED)
130 IDTVEC(fpu)
131         pushl $0; TRAP(T_ARITHTRAP)
132 IDTVEC(align)
133         TRAP(T_ALIGNFLT)
134 IDTVEC(xmm)
135         pushl $0; TRAP(T_XMMFLT)
136
137 IDTVEC(hypervisor_callback)
138         pushl $0; 
139         pushl $0; 
140         pushal
141         pushl   %ds
142         pushl   %es
143         pushl   %fs
144 upcall_with_regs_pushed:
145         SET_KERNEL_SREGS
146         FAKE_MCOUNT(TF_EIP(%esp))
147 call_evtchn_upcall:
148         movl    TF_EIP(%esp),%eax
149         cmpl    $scrit,%eax
150         jb      10f
151         cmpl    $ecrit,%eax
152         jb      critical_region_fixup
153         
154 10:     pushl   %esp
155         call    evtchn_do_upcall
156         addl    $4,%esp
157
158         /*
159          * Return via doreti to handle ASTs.
160          */
161         MEXITCOUNT
162         jmp     doreti
163
164         
165 hypervisor_callback_pending:
166         movl    HYPERVISOR_shared_info,%esi
167         XEN_BLOCK_EVENTS(%esi)                          /*      cli */  
168         jmp     10b
169
170         /*
171          * alltraps entry point.  Interrupts are enabled if this was a trap
172          * gate (TGT), else disabled if this was an interrupt gate (IGT).
173          * Note that int0x80_syscall is a trap gate.  Only page faults
174          * use an interrupt gate.
175          */
176
177         SUPERALIGN_TEXT
178         .globl  alltraps
179         .type   alltraps,@function
180 alltraps:
181         pushal
182         pushl   %ds
183         pushl   %es
184         pushl   %fs
185
186 alltraps_with_regs_pushed:
187         SET_KERNEL_SREGS
188         FAKE_MCOUNT(TF_EIP(%esp))
189
190 calltrap:
191         push    %esp
192         call    trap
193         add     $4, %esp
194
195         /*
196          * Return via doreti to handle ASTs.
197          */
198         MEXITCOUNT
199         jmp     doreti
200
201 /*
202  * SYSCALL CALL GATE (old entry point for a.out binaries)
203  *
204  * The intersegment call has been set up to specify one dummy parameter.
205  *
206  * This leaves a place to put eflags so that the call frame can be
207  * converted to a trap frame. Note that the eflags is (semi-)bogusly
208  * pushed into (what will be) tf_err and then copied later into the
209  * final spot. It has to be done this way because esp can't be just
210  * temporarily altered for the pushfl - an interrupt might come in
211  * and clobber the saved cs/eip.
212  */
213         SUPERALIGN_TEXT
214 IDTVEC(lcall_syscall)
215         pushfl                          /* save eflags */
216         popl    8(%esp)                 /* shuffle into tf_eflags */
217         pushl   $7                      /* sizeof "lcall 7,0" */
218         subl    $4,%esp                 /* skip over tf_trapno */
219         pushal
220         pushl   %ds
221         pushl   %es
222         pushl   %fs
223         SET_KERNEL_SREGS
224         FAKE_MCOUNT(TF_EIP(%esp))
225         pushl   %esp
226         call    syscall
227         add     $4, %esp
228         MEXITCOUNT
229         jmp     doreti
230
231 /*
232  * Call gate entry for FreeBSD ELF and Linux/NetBSD syscall (int 0x80)
233  *
234  * Even though the name says 'int0x80', this is actually a TGT (trap gate)
235  * rather then an IGT (interrupt gate).  Thus interrupts are enabled on
236  * entry just as they are for a normal syscall.
237  */
238         SUPERALIGN_TEXT
239 IDTVEC(int0x80_syscall)
240         pushl   $2                      /* sizeof "int 0x80" */
241         pushl   $0xBEEF                 /* for debug */
242         pushal
243         pushl   %ds
244         pushl   %es
245         pushl   %fs
246         SET_KERNEL_SREGS
247         FAKE_MCOUNT(TF_EIP(%esp))
248         pushl   %esp
249         call    syscall
250         add     $4, %esp
251         MEXITCOUNT
252         jmp     doreti
253
254 ENTRY(fork_trampoline)
255         pushl   %esp                    /* trapframe pointer */
256         pushl   %ebx                    /* arg1 */
257         pushl   %esi                    /* function */
258         call    fork_exit
259         addl    $12,%esp
260         /* cut from syscall */
261
262         /*
263          * Return via doreti to handle ASTs.
264          */
265         MEXITCOUNT
266         jmp     doreti
267
268
269 /*
270  * To efficiently implement classification of trap and interrupt handlers
271  * for profiling, there must be only trap handlers between the labels btrap
272  * and bintr, and only interrupt handlers between the labels bintr and
273  * eintr.  This is implemented (partly) by including files that contain
274  * some of the handlers.  Before including the files, set up a normal asm
275  * environment so that the included files doen't need to know that they are
276  * included.
277  */
278
279         .data
280         .p2align 4
281         .text
282         SUPERALIGN_TEXT
283 MCOUNT_LABEL(bintr)
284
285 #ifdef DEV_ATPIC        
286 #include <i386/isa/atpic_vector.s>
287 #endif
288         
289 #ifdef DEV_APIC
290         .data
291         .p2align 4
292         .text
293         SUPERALIGN_TEXT
294
295 #include <i386/i386/apic_vector.s>
296 #endif
297
298         .data
299         .p2align 4
300         .text
301         SUPERALIGN_TEXT
302 #include <i386/i386/vm86bios.s>
303
304         .text
305 MCOUNT_LABEL(eintr)
306
307 /*
308  * void doreti(struct trapframe)
309  *
310  * Handle return from interrupts, traps and syscalls.
311  */
312         .text
313         SUPERALIGN_TEXT
314         .type   doreti,@function
315 doreti:
316         FAKE_MCOUNT($bintr)             /* init "from" bintr -> doreti */
317 doreti_next:
318 #ifdef notyet
319         /*
320          * Check if ASTs can be handled now.  PSL_VM must be checked first
321          * since segment registers only have an RPL in non-VM86 mode.
322          */
323         testl   $PSL_VM,TF_EFLAGS(%esp) /* are we in vm86 mode? */
324         jz      doreti_notvm86
325         movl    PCPU(CURPCB),%ecx
326         testl   $PCB_VM86CALL,PCB_FLAGS(%ecx)   /* are we in a vm86 call? */
327         jz      doreti_ast              /* can handle ASTS now if not */
328         jmp     doreti_exit
329
330 doreti_notvm86:
331 #endif
332         testb   $SEL_RPL_MASK,TF_CS(%esp) /* are we returning to user mode? */
333         jz      doreti_exit             /* can't handle ASTs now if not */
334
335 doreti_ast:
336         /*
337          * Check for ASTs atomically with returning.  Disabling CPU
338          * interrupts provides sufficient locking even in the SMP case,
339          * since we will be informed of any new ASTs by an IPI.
340          */
341         movl    HYPERVISOR_shared_info,%esi
342         XEN_BLOCK_EVENTS(%esi)                          /*      cli */
343         movl    PCPU(CURTHREAD),%eax
344         testl   $TDF_ASTPENDING | TDF_NEEDRESCHED,TD_FLAGS(%eax)
345         je      doreti_exit
346         XEN_UNBLOCK_EVENTS(%esi)        /* sti */
347         pushl   %esp                    /* pass a pointer to the trapframe */
348         call    ast
349         add     $4,%esp
350         jmp     doreti_ast
351
352         /*
353          * doreti_exit: pop registers, iret.
354          *
355          *      The segment register pop is a special case, since it may
356          *      fault if (for example) a sigreturn specifies bad segment
357          *      registers.  The fault is handled in trap.c.
358          */
359 doreti_exit:
360         movl    HYPERVISOR_shared_info,%esi
361         XEN_UNBLOCK_EVENTS(%esi) # reenable event callbacks (sti)
362
363         .globl  scrit
364 scrit:
365         XEN_TEST_PENDING(%esi)
366         jnz     hypervisor_callback_pending     /* More to go  */
367
368         MEXITCOUNT
369
370         .globl  doreti_popl_fs
371 doreti_popl_fs:
372         popl    %fs
373         .globl  doreti_popl_es
374 doreti_popl_es:
375         popl    %es
376         .globl  doreti_popl_ds
377 doreti_popl_ds:
378         popl    %ds
379
380         /*
381          * This is important: as nothing is atomic over here (we can get
382          * interrupted any time), we use the critical_region_fixup() in
383          * order to figure out where out stack is. Therefore, do NOT use
384          * 'popal' here without fixing up the table!
385          */
386         POPA
387         addl    $8,%esp
388         .globl  doreti_iret
389 doreti_iret:
390         jmp     hypercall_page + (__HYPERVISOR_iret * 32)
391         .globl  ecrit
392 ecrit:
393         /*
394          * doreti_iret_fault and friends.  Alternative return code for
395          * the case where we get a fault in the doreti_exit code
396          * above.  trap() (i386/i386/trap.c) catches this specific
397          * case, sends the process a signal and continues in the
398          * corresponding place in the code below.
399          */
400         ALIGN_TEXT
401         .globl  doreti_iret_fault
402 doreti_iret_fault:
403         subl    $8,%esp
404         pushal
405         pushl   %ds
406         .globl  doreti_popl_ds_fault
407 doreti_popl_ds_fault:
408         pushl   %es
409         .globl  doreti_popl_es_fault
410 doreti_popl_es_fault:
411         pushl   %fs
412         .globl  doreti_popl_fs_fault
413 doreti_popl_fs_fault:
414         movl    $0,TF_ERR(%esp) /* XXX should be the error code */
415         movl    $T_PROTFLT,TF_TRAPNO(%esp)
416         jmp     alltraps_with_regs_pushed
417
418         /*
419 # [How we do the fixup]. We want to merge the current stack frame with the
420 # just-interrupted frame. How we do this depends on where in the critical
421 # region the interrupted handler was executing, and so how many saved
422 # registers are in each frame. We do this quickly using the lookup table
423 # 'critical_fixup_table'. For each byte offset in the critical region, it
424 # provides the number of bytes which have already been popped from the
425 # interrupted stack frame.
426 */
427
428 .globl critical_region_fixup
429 critical_region_fixup:
430         addl $critical_fixup_table-scrit,%eax
431         movzbl (%eax),%eax    # %eax contains num bytes popped
432         movl  %esp,%esi
433         add  %eax,%esi        # %esi points at end of src region
434         movl  %esp,%edi
435         add  $0x40,%edi       # %edi points at end of dst region
436         movl  %eax,%ecx
437         shr  $2,%ecx          # convert bytes to words
438         je   16f              # skip loop if nothing to copy
439 15:     subl $4,%esi          # pre-decrementing copy loop
440         subl $4,%edi
441         movl (%esi),%eax
442         movl %eax,(%edi)
443         loop 15b
444 16:     movl %edi,%esp        # final %edi is top of merged stack
445         jmp  hypervisor_callback_pending
446
447
448 critical_fixup_table:        
449 .byte   0x0,0x0,0x0                     #testb  $0x1,(%esi)
450 .byte   0x0,0x0,0x0,0x0,0x0,0x0         #jne    ea 
451 .byte   0x0,0x0                         #pop    %fs
452 .byte   0x04                            #pop    %es
453 .byte   0x08                            #pop    %ds
454 .byte   0x0c                            #pop    %edi
455 .byte   0x10                            #pop    %esi
456 .byte   0x14                            #pop    %ebp
457 .byte   0x18                            #pop    %ebx
458 .byte   0x1c                            #pop    %ebx
459 .byte   0x20                            #pop    %edx
460 .byte   0x24                            #pop    %ecx
461 .byte   0x28                            #pop    %eax
462 .byte   0x2c,0x2c,0x2c                  #add    $0x8,%esp
463 #if 0
464         .byte   0x34                            #iret   
465 #endif
466 .byte   0x34,0x34,0x34,0x34,0x34        #HYPERVISOR_iret 
467         
468         
469 /* # Hypervisor uses this for application faults while it executes.*/
470 ENTRY(failsafe_callback)
471         pushal
472         call xen_failsafe_handler
473 /*#     call install_safe_pf_handler */
474         movl 28(%esp),%ebx
475 1:      movl %ebx,%ds
476         movl 32(%esp),%ebx
477 2:      movl %ebx,%es
478         movl 36(%esp),%ebx
479 3:      movl %ebx,%fs
480         movl 40(%esp),%ebx
481 4:      movl %ebx,%gs
482 /*#        call install_normal_pf_handler */
483         popal
484         addl $12,%esp
485         iret
486
487