[SOS] changement de privileges + interrupt manager

stephane duverger duvergers at chello.fr
Dim 6 Mar 18:55:59 CET 2005


Ok, merci david j'arriverais a dormir cette nuit :)

bonne fin de journée

On Sun, 2005-03-06 at 18:29 +0100, David Decotigny wrote:
> stephane duverger wrote:
> > J'ai cependant une derniere question. En regardant l'algo d'iret (intel
> > volume 2) je n'ai pas vu (bien que ce soit spécifié dans le volume 3 au
> > chapitre des interruptions) que l'instruction remettait les infos de la
> > pile user (ss et esp) dans les registres lors du depilement.
> 
> Je viens de jeter un coup d'oeil, et effectivement on dirait qu'ils ont 
> "oublié" ce detail. En tout cas c'est pas tres clair. Pour la recup de 
> SS, c'est presque sous-entendu au debut du pseudo code de 
> RETURN-TO-OUTER-PRIVILGE-LEVEL ("Read return segment selector ... "), 
> ils oublient juste de mettre a jour ss apres toutes les verifications. 
> Par contre, pour esp, la c'est carrement "oublié". Ceci dit, on devine 
> qu'il y a un "esp" dans le coup parce que le debut du pseudo-code dit 
> qu'on verifie que la pile doit posseder 8 octets supplementaires dans le 
> segment de pile actuel (ie SP [étendu a 32 bits] + ESP). Autre chose, a 
> aucun moment on ne fait Pop() de ss et esp. Bref, ce pseudo-code est faux.
> 
> La doc de reference correcte est celle du 5.12.1 dans la doc intel vol 3 
> (Exception- or Interrupt-Handler Procedures). En tous cas c'est le 
> comportement observe dans bochs, qemu, AMD k7 800, Cyrix 133, Intel PIV 
> 2.4 ;)
> 
> BTW, le code de qemu peut servir de reference plus "sure" que la doc 
> Intel : target-i386/{op,helper}.c
> Ou voit clairement la chose :
> 
>     if (rpl == cpl) {
>        ....
>      } else {
>          /* return to different priviledge level */
>          if (shift == 1) {
>              /* 32 bits */
>              POPL(ssp, sp, sp_mask, new_esp);
>              POPL(ssp, sp, sp_mask, new_ss);
>              new_ss &= 0xffff;
>          } else {
>            ...
>          }
>      ...
>      }
> 
> > J'ai vu dans ton code de la version "au debut sos devait fonctionner
> > comme ca" que tu preparais bien la pile avec ses infos en plus des
> > flags, cs et eip. Cela justifie bien que l'iret changera de pile au
> > retour. Je voulais juste avoir confirmation.
> 
> Voui, voir code bochs/qemu + Intel 5.12.1 (figure 5-4) dans le vol 3
> 
> > Tu places aussi un code d'erreur (push $0) et fait l'iret, hors n'est-il
> > pas a la charge du programmeur de supprimer ce fameux code d'erreur
> > avant un iret comme l'on fait durant le traitement d'une interruption
> > "normale" ?
> 
> C'etait en effet completement faux (iret n'a jamais eu a dependre d'un 
> code d'erreur empilé), c'etait pour voir si vous suiviez.
> 
> Je me suis plante de version dans le cvs, il fallait lire le code suivant :
> --------------------------------------------------------------------
> .globl sos_cpu_context_switch_to_user_mode
> .type sos_cpu_context_switch_to_user_mode, @function
> sos_cpu_context_switch_to_user_mode:
>          // arg2= user_initial_SP -- esp+8
>          // arg1= user_initial_PC -- esp+4
>          // caller ip             -- esp
> 
>    /*
>     * Store the kernel SP where the CPU will have to return to when
>     * returning from user to kernel mode. That SP is the value of
>     * the SP before the call to this function
>     */
>    movl  %esp, %eax
>    addl  $12,  %eax /* SP before function call is 12B above current SP */
>    pushl %eax
>    call  sos_cpu_context_update_kernel_tss_switch_to_user
>    addl  $4, %esp
> 
>    /*
>     * Setup the stack so as to suit the iret instruction for a "return"
>     * with privilege change. See figure 6-5 of Intel x86 vol 1 (error
>     * code is skipped). We could have used the "far ret" instruction,
>     * the only difference would have been that the IF flag of the
>     * EFLAGS register would not have been setup so that the IRQ inside
>     * the user thread are allowed
>     */
> 
>    /* Push SS register of the user context */
>    pushl $SOS_BUILD_SEGMENT_REG_VALUE(3, 0, SOS_SEG_UDATA) // ==> esp += 4
> 
>    /* Push the initial user SP */
>    pushl 12(%esp) // ==> esp += 4
> 
>    /* Push the initial user EFLAGS register */
>    pushl $(1 << 9) // IF flag set ==> esp += 4
> 
>    /* Push the CS register of the user context */
>    pushl $SOS_BUILD_SEGMENT_REG_VALUE(3, 0, SOS_SEG_UCODE) // ==> esp += 4
> 
>    /* Push the PC of the user context */
>    pushl 20(%esp)
> 
>    /*
>     * Reset the general purpose user segment registers
>     */
>    /* Build the contents of these registers */
>    movw $SOS_BUILD_SEGMENT_REG_VALUE(3, 0, SOS_SEG_UDATA), %ax
>    pushw %ax ; popw %ds
>    pushw %ax ; popw %es
>    pushw %ax ; popw %fs
>    pushw %ax ; popw %gs
> 
>    /*
>     * Reset the general purpose registers
>     */
>    movl $0, %eax
>    movl $0, %ebx
>    movl $0, %ecx
>    movl $0, %edx
>    movl $0, %ebp
>    movl $0, %esi
>    movl $0, %edi
> 
>    /* Now switch to user context ! */
>    iret
> --------------------------------------------------------------------
> Ce code-la a ete testé et approuvé.
> 
> Bonne journee,
> _______________________________________________
> Sos mailing list
> Sos at the-doors.enix.org
> http://the-doors.enix.org/cgi-bin/mailman/listinfo/sos
-- 
stephane duverger <duvergers at chello.fr>



Plus d'informations sur la liste de diffusion Sos