Changes between Version 4 and Version 5 of AS6-TME-B1


Ignore:
Timestamp:
Feb 8, 2022, 12:32:04 PM (2 years ago)
Author:
franck
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • AS6-TME-B1

    v4 v5  
    651651 - placer cette adresse dans un registre, par exemple `$2`;
    652652 - exécuter l'instruction `jal` (ici, `jal $2`) pour appeler la fonction.
    653 
    654653 Que doivent contenir les registres `$4` à `$7` et comment doit-être la pile?
    655654{{{#!protected ------------------------------------------------------------------------------------
     
    721720'''''''''''''''
    722721}}}
    723 1. Dans la question **A2.5**, nous avons vu comment la fonction `kinit()` appelle la fonction `__start()` grâce à un bout de code en assembleur placé au début de la section `.text`. Nous allons voir maintenant quelles sont les conditions de cet appel. Dans le code de la question **A2.5**, `$26` est un registre de travail pour le kernel. Quels sont les autres registres modifiés? Expliquez pour chacun la valeur affectée.
     7221. Dans la question **A6.5**, nous avons vu comment la fonction `kinit()` appelle la fonction `__start()` grâce à un bout de code en assembleur placé au début de la section `.text`. Nous allons voir maintenant quelles sont les conditions de cet appel. Dans le code de la question **A6.5**, `$26` est un registre de travail pour le kernel. Quels sont les autres registres modifiés? Expliquez pour chacun la valeur affectée.
    724723{{{#!protected ------------------------------------------------------------------------------------
    725724'''''''''''''''
     
    771770'''''''''''''''
    772771}}}
    773 1. Le gestionnaire de `syscall` est la partie du code qui gère le comportement du noyau lors de l'exécution de l'instruction `syscall`. C'est un code en assembleur présent dans le fichier `kernel/hcpu.S` que nous allons observer. Pour vous aider dans la compréhension de ce code, vous devez imaginer que l'instruction `syscall` est un peu comme un appel de fonction. Ce code utilise un tableau de pointeurs de fonctions nommé `syscall_vector` définit dans le fichier `kernel/ksyscalls.c`. Les lignes `36` à `43` sont chargées d'allouer de la place dans la pile.\\Dessinez l'état de la pile après l'exécution de ces instructions. Que fait l'instruction ligne `44` et quelle conséquence cela a-t-il? Que font les lignes `46` à `51`? Et enfin que font les lignes `53` à `59` sans détailler ligne à ligne.\\ \\**`common/syscalls.h`**
    774 {{{#!c
    775   1 #define SYSCALL_EXIT        0
    776   2 #define SYSCALL_TTY_WRITE   1
    777   3 #define SYSCALL_TTY_READ    2
    778   4 #define SYSCALL_CLOCK       3
    779   5 #define SYSCALL_NR          32
     7721. Le gestionnaire de `syscall` est la partie du code qui gère le comportement du noyau lors de l'exécution de l'instruction `syscall`. C'est un code en assembleur présent dans le fichier `kernel/hcpu.S` que nous allons observer. Pour vous aider dans la compréhension de ce code, vous devez imaginer que l'instruction `syscall` est un peu comme un appel de fonction. Ce code utilise un tableau de pointeurs de fonctions nommé `syscall_vector` définit dans le fichier `kernel/ksyscalls.c`. Les lignes `47` à `54` sont chargées d'allouer de la place dans la pile.\\- Dessinez l'état de la pile après l'exécution de ces instructions.\\- Que fait l'instruction ligne `55` et quelle conséquence cela a-t-il?\\- Que font les lignes `57` à `62`?\\- Et enfin que font les lignes `64` à `70` ?\\Les commentaires ont été laissés, vous devez juste mettre à quoi ça sert, sans détailler ligne à ligne.\\ \\**`common/syscalls.h`**
     773{{{#!c
     774#define SYSCALL_EXIT        0       /* see exit()   in ulib/libc.c */
     775#define SYSCALL_READ        1       /* see read()   in ulib/libc.c */
     776#define SYSCALL_WRITE       2       /* see write()  in ulib/libc.c */
     777#define SYSCALL_CLOCK       3       /* see clock()  in ulib/libc.c */
     778#define SYSCALL_NR          32
    780779}}}
    781780  **`kernel/ksyscalls.c`**
    782781{{{#!c
    783782void *syscall_vector[] = {
    784     [0 ... SYSCALL_NR - 1] = unknown_syscall,
    785     [SYSCALL_EXIT]      = exit,
    786     [SYSCALL_TTY_READ] = tty_read,
    787     [SYSCALL_TTY_WRITE] = tty_write,
    788     [SYSCALL_CLOCK]    = clock,
     783    [0 ... SYSCALL_NR - 1] = unknown_syscall,   /* default function */
     784    [SYSCALL_EXIT        ] = exit,
     785    [SYSCALL_READ        ] = tty_read,
     786    [SYSCALL_WRITE       ] = tty_write,
     787    [SYSCALL_CLOCK       ] = clock,
    789788};
    790789}}}
    791790  **`kernel/hcpu.S`**
    792 {{{#!xml
    793  34 ksyscall:
    794  35
    795  36     addiu   $29,    $29,    -8*4           
    796  37     mfc0    $27,    $14                     
    797  38     mfc0    $26,    $12                     
    798  39     addiu   $27,    $27,    4               
    799  40     sw      $31,    7*4($29)               
    800  41     sw      $27,    6*4($29)               
    801  42     sw      $26,    5*4($29)               
    802  43     sw      $2,     4*4($29)               
    803  44     mtc0    $0,     $12                     
    804  45
    805  46     la      $26,    syscall_vector         
    806  47     andi    $2,     $2,     SYSCALL_NR-1   
    807  48     sll     $2,     $2,     2               
    808  49     addu    $2,     $26,    $2             
    809  50     lw      $2,     0($2)                   
    810  51     jalr    $2                             
    811  52
    812  53     lw      $26,    5*4($29)               
    813  54     lw      $27,    6*4($29)               
    814  55     lw      $31,    7*4($29)               
    815  56     mtc0    $26,    $12                     
    816  57     mtc0    $27,    $14                     
    817  58     addiu   $29,    $29,    8*4             
    818  59     eret                       
     791{{{#!asm
     792 45 syscall_handler:
     793 46
     794 47     addiu   $29,    $29,    -8*4        // context for $31 + EPC + SR + syscall_code + 4 args
     795 48     mfc0    $27,    $14                 // $27 <- EPC (addr of syscall instruction)
     796 49     mfc0    $26,    $12                 // $26 <- SR (status register)
     797 50     addiu   $27,    $27,    4           // $27 <- EPC+4 (return address)
     798 51     sw      $31,    7*4($29)            // save $31 because it will be erased
     799 52     sw      $27,    6*4($29)            // save EPC+4 (return address of syscall)
     800 53     sw      $26,    5*4($29)            // save SR (status register)
     801 54     sw      $2,     4*4($29)            // save syscall code (useful for debug message)
     802 55     mtc0    $0,     $12                 // SR <- kernel-mode without INT (UM=0 ERL=0 EXL=0 IE=0)
     803 56
     804 57     la      $26,    syscall_vector      // $26 <- table of syscall functions
     805 58     andi    $2,     $2,     SYSCALL_NR-1// apply syscall mask
     806 59     sll     $2,     $2,     2           // compute syscall index (mutiply by 4)
     807 60     addu    $2,     $26,    $2          // $2 <- & syscall_vector[$2]
     808 61     lw      $2,     ($2)                // at the end: $2 <- syscall_vector[$2]
     809 62     jalr    $2                          // call service function
     810 63
     811 64     lw      $26,    5*4($29)            // get old SR
     812 65     lw      $27,    6*4($29)            // get return address of syscall
     813 66     lw      $31,    7*4($29)            // restore $31 (return address of syscall function)
     814 67     mtc0    $26,    $12                 // restore SR
     815 68     mtc0    $27,    $14                 // restore EPC
     816 69     addiu   $29,    $29,    8*4         // restore stack pointer
     817 70     eret                                // return : jr EPC with EXL <- 0
    819818}}}
    820819{{{#!protected ------------------------------------------------------------------------------------