/[rtmk]/rtmk/i386/i386-locore.S
ViewVC logotype

Diff of /rtmk/i386/i386-locore.S

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.4 by jrydberg, Tue Dec 11 02:15:17 2001 UTC revision 1.5 by jrydberg, Wed Dec 12 02:31:09 2001 UTC
# Line 18  Foundation, Inc., 59 Temple Place - Suit Line 18  Foundation, Inc., 59 Temple Place - Suit
18  #ifndef INTERRUPT_BASE_OFFSET  #ifndef INTERRUPT_BASE_OFFSET
19  # define INTERRUPT_BASE_OFFSET  0x60  # define INTERRUPT_BASE_OFFSET  0x60
20  #endif  #endif
           
 #define INTERRUPT_BASE_OFFSET   0x60  
21    
22  #include "cpus.h"  #include "cpus.h"
23  #include "i386-asm.h"  #include "i386-asm.h"
24  #include "i386-segment.h"  #include "i386-segment.h"
25  #include "i386-trap.h"  #include "i386-trap.h"
26  #include "i386-syms.h"  #include "i386-syms.h"
           
 #define R_CS 60  
 #define R_EFLAGS 64  
 #define R_EAX 44  
 #define R_EBX 32  
 #define R_ECX 40  
 #define R_TRAPNO 48  
 #define R_ERR 52  
 #define R_EIP 56  
 #define R_CR2 28  
 #define R_UESP 68  
           
 #define KSS_EBX 0  
 #define KSS_ESP 4  
 #define KSS_EBP 8  
 #define KSS_ESI 16  
 #define KSS_EDI 12  
 #define KSS_EIP 20  
27    
28  /* All interrupts enter here.          .bss
29     old %eax on stack; interrupt number in %eax.  */  LEXT(kernel_stacks)
30            .fill   4, NCPUS
31    
32    
33    /* Interrupt exception point.
34    
35       Interrupt number and null error code on stack.
36    
37       ?? interrupts run on kernel stack if we interrupted a
38          user mode thread.  */
39    
40          .text          .text
         .globl  allintrs  
41  allintrs:        allintrs:      
42          pusha          pusha
43    
44  int_push_segs:  int_push_segs:
45          pushl   %ds          pushl   %ds
46          pushl   %es          pushl   %es
47          pushl   %fs          pushl   %fs
48          pushl   %gs          pushl   %gs
49            cld
50    
51  int_set_segs:  int_set_segs:
52          cld          /* Set segment registers.  */
53          jmp     int_from_intstack  
54            mov     %ss,%dx
55            mov     %dx,%ds
56            mov     %dx,%es
57            mov     %dx,%gs
58            mov     %dx,%fs
59    
60            /* Check if we interrupted a user mode thread.  */
61    
62            testb   $3,R_CS(%esp)
63            jz      int_from_intstack
64    
65    int_from_usermode:
66    
67            /* Switch to kernel stack.  */
68    
69            CPU_NUMBER(%edx)
70            movl    CX(kernel_stacks,%edx),%ebx
71            xchgl   %ebx,%esp
72    
73            /* Call machine specific interrupt handler.  */
74    
75            movl    R_TRAPNO(%ebx), %eax
76            pushl   %ebx
77            call    machine_interrupt
78            popl    %esp
79    
80    return_from_int:
81            popl    %gs
82            popl    %fs
83            popl    %es
84            popl    %ds
85            popa
86            addl    $8,%esp
87            iret
88    
89  int_from_intstack:  int_from_intstack:
90            /* Interrupt came from kernel mode.  */
91    
92          movl    R_TRAPNO(%esp), %eax          movl    R_TRAPNO(%esp), %eax
93          movl    %esp, %ebx          pushl   $return_from_int
           
         pushl   $_return_from_kernel  
94          jmp     machine_interrupt          jmp     machine_interrupt
95                    
96    
97  /* Machine specific part of interrupt handler.  This will ack the  /* Machine specific part of interrupt handler.  This will ack the
98     interrupt.  ??? is this correct?  */     interrupt.  ??? is this correct?  */
99                    
100          .align  4          .align  4
101  machine_interrupt:        machine_interrupt:
102    
103            /* Save interrupt number on stack.  */
104          pushl   %eax                              pushl   %eax                    
105          cmpl    $8, %eax                  cmpl    $8, %eax        
106          jae     _second_pic          jae     .Lsecondary_pic
107    
108          movl    $0x20, %edx                      movl    $0x20, %edx            
109          movb    $0x20, %al          movb    $0x20, %al
110          outb    %al, %dx          outb    %al, %dx
111          jmp     _take_interrupt          jmp     .Ltake_intr
112  _second_pic:              
113    .Lsecondary_pic:
114            /* Send EOI to both primary and secondary PIC.  */
115    
116          movl    $0x20, %edx              movl    $0x20, %edx    
117          movb    $0x20, %al          movb    $0x20, %al
118          outb    %al, %dx          outb    %al, %dx
# Line 91  _second_pic: Line 121  _second_pic:
121          movb    $0x20, %al                movb    $0x20, %al      
122          outb    %al, %dx          outb    %al, %dx
123    
124  _take_interrupt:  
125    /* Take interrupt.  
126       We optimize for the case with timer interrupt.  */
127    
128    .Ltake_intr:    
129          popl    %eax                              popl    %eax                    
130          cmpl    $0, %eax          cmpl    $0, %eax
131          jne     _take_generic_interrupt          jne     _take_generic_interrupt
132    
133    #if 0
134            movl    R_CS(%esp), %eax
135            andl    $3, %eax
136            pushl   %eax
137            call    timer_interrupt
138            addl    $4, %esp
139            ret
140    #else
141          testb   $3,R_CS(%esp)          testb   $3,R_CS(%esp)
142          jnz     _clock_from_kernel          jnz     _clock_from_kernel
143          jmp     _clock_from_user          jmp     _clock_from_user
144    #endif
145                    
146  _clock_from_kernel:  _clock_from_kernel:
147          pushl   $0          pushl   $0
# Line 122  _take_generic_interrupt: Line 165  _take_generic_interrupt:
165          call    *%ebx          call    *%ebx
166          addl    $8, %esp          addl    $8, %esp
167  0:      ret  0:      ret
168    
169            
170                            
171            .text
172            .globl  machine_syscall
173    machine_syscall:
174            pushl   $0
175            pushl   $0
176            jmp     alltraps
177            
178    
179    /* System call entry point.
180    
181       Since we never should get system calls from kernel mode we can
182       try to optimize for user mode.  */
183    
184            .text
185            .align  4
186    ENTRY(syscall)
187    
188            pushl   $0
189            pushl   %eax
190            
191            /* Push generic and segment registers on stack.  */
192            
193            pusha
194            pushl   %ds
195            pushl   %es
196            pushl   %fs
197            pushl   %gs
198            cld
199    
200            /* Set segment registers.  */
201    
202            mov     %ss,%ax
203            mov     %ax,%ds
204            mov     %ax,%es
205            mov     %ax,%gs
206            mov     %ax,%fs
207    
208            /* Switch to kernel stack.  */
209    
210            CPU_NUMBER(%edx)
211            movl    CX(kernel_stacks,%edx),%ebx
212            xchgl   %ebx,%esp
213    
214    
215            /* Check so that its a valid system call.  */
216    
217            movl    R_TRAPNO(%ebx), %eax    /* trapno in eax */
218            movl    EXT(syscalls_count), %edx
219            cmp     %edx, %eax
220            jae     .Linvalidsc
221    
222    
223            /* Get system call information (arg cnt).  */
224                                    
225            lea     EXT(syscalls_table)(, %eax, 8), %esi
226            movl    4(%esi), %edx
227            testl   %edx, %edx
228            jz      .Lcall_with_no_args
229                            
230            /* Reserve space for arguments on stack.  */
231    
232            shll    $2, %edx                /* *= 4 */
233            subl    %edx, %esp
234            movl    %esp, %edi
235    
236            movl    R_UESP(%ebx), %esi      /* user stack ptr */
237            addl    $4, %esi                /* ??? return address */
238    
239            /* Copy arguments from user stack to our stack.  */
240            
241            pushl   %ebx                    /* save frame pointer */
242            pushl   %edx
243            pushl   %esi
244            pushl   %edi
245            call    EXT(copyin)            
246            addl    $12, %esp
247            popl    %ebx    
248    
249            /* Get syscall function address.  */
250            
251            movl    R_TRAPNO(%ebx), %eax
252            movl    EXT(syscalls_table)(, %eax, 8), %ecx
253    
254            /* Call function.  */
255            
256            pushl   %ebx
257            pushl   %edi
258            call    *%ecx
259            .globl  __syscall_frame_address_0
260    __syscall_frame_address_0:
261            movl    4(%esp), %esp
262            jmp     _return_from_syscall
263    
264    /* Fast path for system calls without arguments.  */
265    
266    .Lcall_with_no_args:
267            pushl   %ebx
268            call    *%ecx
269            .globl  __syscall_frame_address_1
270    __syscall_frame_address_1:
271            movl    0(%esp),%esp
272            jmp     _return_from_syscall    /* ??? fall through ?  */
273            
274    _return_from_syscall:
275            popl    %gs
276            popl    %fs
277            popl    %es
278            popl    %ds
279            popa
280            addl    $8,%esp
281            iret
282    
283    .Linvalidsc:
284            cli
285    0:      jmp     0b
286            
287    
288  /* All exceptions enter here with this state:  /* Trap enter function.
289      
290          %esp->  trap number     On stack we have exception number, error code, old %eip, cold %cs,
291                  error code     old %eflags and old %esp, old %ss if we trapped from user mode.
292                  old eip  
293                  old cs     We save all registers and switch to kernel stack if we trapped from
294                  old eflags     user mode.  We call the exception handling function.  */
295                  old esp         if trapped from user  
                 old ss          if trapped from user  
  *//  
296          .text          .text
297          .align  2          .align  2
298  alltraps:  alltraps:
# Line 147  _trap_push_segs: Line 306  _trap_push_segs:
306  _trap_set_segs:  _trap_set_segs:
307          cld          cld
308    
309  /* Trap from kernel mode.            /* Check if we trapped from user mode.  */
310     No need to switch stacks or load segment registers. */  
311            testb   $3,R_CS(%esp)
312            jz      _trap_from_kernel
313    
314    _trap_from_user:
315    
316            /* Set segment registers.  */
317            mov     %ss,%ax
318            mov     %ax,%ds
319            mov     %ax,%es
320            mov     %ax,%gs
321            mov     %ax,%fs
322    
323            /* Save CR2 register.  
324               ??? should we do this for all traps?  */
325    
326            movl    %cr2, %eax
327            movl    %eax, R_CR2(%esp)
328    
329            /* Switch to kernel stack.  */
330    
331            CPU_NUMBER(%edx)
332            movl    CX(kernel_stacks,%edx),%ebx
333            xchgl   %ebx,%esp
334    
335            /* Call generic exception handler.  */
336    
337            pushl   %ebx
338            call    cpu_exception_kernel
339            movl    0(%esp),%esp
340    
341            jmp     _return_from_kernel
342            
343            /* Trap from kernel mode.  
344               No need to switch stacks or load segment registers. */
345    
346  _trap_from_kernel:  _trap_from_kernel:
 #if 1  
347          movl    %cr2, %eax          movl    %cr2, %eax
348          movl    %eax, R_CR2(%esp)          movl    %eax, R_CR2(%esp)
 #endif  
           
         mov     %ss,%ax  
         mov     %ax,%ds  
         mov     %ax,%es  
         mov     %ax,%gs  
         mov     %ax,%fs  
349    
350          sti          /* Set segment registers.  */
351                    mov     %ss,%ax
352            mov     %ax,%ds
353            mov     %ax,%es
354            mov     %ax,%gs
355            mov     %ax,%fs
356    
357            /* Call generic exception handler.  */
358    
359          pushl   %esp          pushl   %esp
360          call    cpu_exception_kernel          call    cpu_exception_kernel
361          addl    $4,%esp          addl    $4,%esp
362    
363            /* Fall through */
364    
365    /* Return from exception.  Stack points to exceptin frame.
366       ??? should this be global ?  */
367                    
368          .globl  _return_from_kernel              .globl  _return_from_kernel    
369  _return_from_kernel:  _return_from_kernel:
# Line 183  _kret_popl_ds: Line 380  _kret_popl_ds:
380  _kret_iret:  _kret_iret:
381          iret          iret
382    
383    /* cpu_load_context (THREAD)
384    
385       Load kernel context from THREAD.  Store kernel stack in
386  /* Context switch routines for i386.  */     active_stacks and stack pointer in kernel_stacks.  */  
   
         .text  
         .align  4  
         .globl  cpu_load_kstate  
 cpu_load_kstate:  
         movl    4(%esp), %edx  
   
         movl    KSS_ESP(%edx),%esp  
         movl    KSS_ESI(%edx),%esi  
         movl    KSS_EDI(%edx),%edi  
         movl    KSS_EBP(%edx),%ebp  
         movl    KSS_EBX(%edx),%ebx  
         xorl    %eax,%eax        
         jmp     *KSS_EIP(%edx)  
   
         .align  4  
         .globl  cpu_switch_kstate  
 cpu_switch_kstate:  
         movl    4(%esp), %edx  
         movl    %esp, KSS_ESP(%edx)  
         movl    %esi, KSS_ESI(%edx)  
         movl    %edi, KSS_EDI(%edx)  
         movl    %ebp, KSS_EBP(%edx)  
         movl    %ebx, KSS_EBX(%edx)  
         popl    KSS_EIP(%edx)  
         jmp     cpu_load_kstate  
   
         .bss  
 LEXT(kernel_stacks)  
         .fill   4, NCPUS  
           
 /* Context switch routines for i386.  */  
387    
388          .text          .text
389  ENTRY(cpu_load_context)  ENTRY(cpu_load_context)
# Line 227  ENTRY(cpu_load_context) Line 393  ENTRY(cpu_load_context)
393                                                    
394          CPU_NUMBER(%eax)          CPU_NUMBER(%eax)
395          movl    %ecx, CX(active_stacks,%eax)          movl    %ecx, CX(active_stacks,%eax)
396          movl    %edx, CX(kernel_stack,%eax)          movl    %edx, CX(kernel_stacks,%eax)
397                    
398          movl    KSS_ESP(%edx),%esp          movl    KSS_ESP(%edx),%esp
399          movl    KSS_ESI(%edx),%esi          movl    KSS_ESI(%edx),%esi
# Line 237  ENTRY(cpu_load_context) Line 403  ENTRY(cpu_load_context)
403          xorl    %eax,%eax                xorl    %eax,%eax      
404          jmp     *KSS_EIP(%edx)          jmp     *KSS_EIP(%edx)
405    
406    
407  /* This really only has to save registers  /* This really only has to save registers
408     when there is no explicit continuation.  */     when there is no explicit continuation.  */
409    
# Line 273  ENTRY(cpu_switch_context) Line 440  ENTRY(cpu_switch_context)
440          movl    KSS_EBX(%edx),%ebx          movl    KSS_EBX(%edx),%ebx
441          jmp     *KSS_EIP(%edx)          jmp     *KSS_EIP(%edx)
442    
443    
444    /* Machine continutation point.  We clear the frame pointer
445       and call function in %ebx.  */
446    
447  ENTRY(cpu_thread_continue)  ENTRY(cpu_thread_continue)
448          pushl   %eax          pushl   %eax
449          xorl    %ebp,%ebp          xorl    %ebp,%ebp
450          call    *%ebx          call    *%ebx
451    
452    /* cpu_call_continuation (CONTINUATION)
453    
454       Reset kernel stack and call CONTINUATION.  */
455    
456  ENTRY(cpu_call_continuation)  ENTRY(cpu_call_continuation)
457          movl    4(%esp),%eax          movl    4(%esp),%eax
458          movl    %esp,%ecx          movl    %esp,%ecx
# Line 287  ENTRY(cpu_call_continuation) Line 462  ENTRY(cpu_call_continuation)
462          xorl    %ebp,%ebp          xorl    %ebp,%ebp
463          jmp     *%eax            jmp     *%eax  
464    
465  /* Copy from user address space.  ??? copyin (DST_KA, SRC_UA, COUNTER) */  /* Exception return function.  Reset kernel stack and return
466       to user mode.  ??? takes no arguments.  */
467    
468            .globl  EXT(thread_exception_return)
469            .globl  EXT(thread_bootstrap_return)
470    LEXT(thread_exception_return)
471    LEXT(thread_bootstrap_return)
472            movl    %esp,%ecx
473            or      $(KERNEL_STACK_SIZE-1),%ecx
474            movl    -3-IKS_SIZE(%ecx),%esp
475            jmp     _return_from_kernel
476    
477    
478    /* copyin (DST, SRC, COUNT)
479    
480       Copy COUNT bytes from user address SRC to kernel address DST.
481       This do not recover from page faults.  Returns zero.  */
482    
483  ENTRY(copyin)  ENTRY(copyin)
484          pushl   %esi          pushl   %esi
# Line 321  ENTRY(copyin) Line 512  ENTRY(copyin)
512          movw    %ax, %fs          movw    %ax, %fs
513    
514          xorl    %eax,%eax               /* return 0 for success */          xorl    %eax,%eax               /* return 0 for success */
 copy_ret_1:  
515          popl    %edi                    /* restore registers */          popl    %edi                    /* restore registers */
516          popl    %esi          popl    %esi
517          ret                             /* and return */          ret                             /* and return */
518    
 copy_fail_1:  
         movl    $KERNEL_DS, %eax  
         movw    %ax, %es  
         movw    %ax, %fs  
519    
520          movl    $1,%eax                 /* return 1 for failure */  /* copyout (DST, SRC, COUNT)
521          jmp     copy_ret_1              /* pop frame and return */  
522       Copy COUNT bytes from kernel address SRC to user address DST.
523       This do not recover from page faults.  Returns zero.  */
524    
 /* Copy to user address space. ??? copyout (DST_VA, SRC_KA, COUNT) */  
525  ENTRY(copyout)  ENTRY(copyout)
526          pushl   %esi          pushl   %esi
527          pushl   %edi                    /* save registers */          pushl   %edi                    /* save registers */
# Line 366  ENTRY(copyout) Line 553  ENTRY(copyout)
553          movw    %ax, %fs          movw    %ax, %fs
554    
555          xorl    %eax,%eax               /* return 0 for success */          xorl    %eax,%eax               /* return 0 for success */
 copy_ret_2:  
556          popl    %edi                    /* restore registers */          popl    %edi                    /* restore registers */
557          popl    %esi          popl    %esi
558          ret                             /* and return */          ret                             /* and return */
559    
 copy_fail_2:  
         movl    $KERNEL_DS, %eax  
         movw    %ax, %es  
         movw    %ax, %fs  
560    
561    /* SMP locore functions.
562    
563          movl    $1,%eax                 /* return 1 for failure */     ??? these should be moved to its own file.  */
         jmp     copy_ret_2              /* pop frame and return */  
564    
                   
         /* SMP STUFF! */  
565  #if NCPUS > 1  #if NCPUS > 1
566    
567          .text          .text
# Line 453  apicint_fn_table: Line 633  apicint_fn_table:
633                    
634  #endif /* NCPUS > 1 */  #endif /* NCPUS > 1 */
635                                                                    
636    
637  /* There are three diffrent types of exceptions:  /* There are three diffrent types of exceptions:
638    
639      . traps   The CS and EIP values stored when the trap is reported      . traps   The CS and EIP values stored when the trap is reported
# Line 520  r##n:  jmp     f Line 701  r##n:  jmp     f
701  idttable:  idttable:
702    
703  /* type                          exception id */  /* type                          exception id */
 #if 1  
704  exception                       (TRAP_DIVIDE_ERROR);  exception                       (TRAP_DIVIDE_ERROR);
705  exception                       (TRAP_DEBUG_EXCEPTION);  exception                       (TRAP_DEBUG_EXCEPTION);
706  exception_user                  (TRAP_BREAKPOINT);  exception_user                  (TRAP_BREAKPOINT);
# Line 538  exception_error                        (TRAP_PAGE_FAULT); Line 718  exception_error                        (TRAP_PAGE_FAULT);
718  exception                       (TRAP_FPU_ERROR);  exception                       (TRAP_FPU_ERROR);
719  exception                       (TRAP_ALIGNMENT_CHECK);  exception                       (TRAP_ALIGNMENT_CHECK);
720  exception                       (TRAP_MACHINE_CHECK);  exception                       (TRAP_MACHINE_CHECK);
 #endif  
721                    
722  interrupt_master                (0);  interrupt_master                (0);
723  interrupt_master                (1);  interrupt_master                (1);
# Line 558  interrupt_slave                        (5); Line 737  interrupt_slave                        (5);
737  interrupt_slave                 (6);  interrupt_slave                 (6);
738  interrupt_slave                 (7);  interrupt_slave                 (7);
739    
740    routine_stub                    (99, ACC_PL_U|ACC_TRAP_GATE, syscall)
741            
742  #if NCPUS > 1  #if NCPUS > 1
743  apic_interrupt                  (0xfb);  apic_interrupt                  (0xfb);
744  apic_interrupt                  (0xfc);  apic_interrupt                  (0xfc);

Legend:
Removed from v.1.4  
changed lines
  Added in v.1.5

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26