My Project
Chargement...
Recherche...
Aucune correspondance
interruptions.c
Aller à la documentation de ce fichier.
1
7#include "manux/printk.h"
8#include <manux/config.h>
9#include <manux/debug.h> // assert
10#include <manux/interruptions.h>
11#if (MANUX_PIC == INTEL_8259A)
12# include "manux/intel-8259a.h"
13#endif
14#include <manux/memoire.h> // NULL
16#include <manux/io.h> // inb
17#include <manux/i386.h> // str
18#include <manux/segment.h> // gdtSysteme
19#include <manux/scheduler.h> // basculerTache
20#include <manux/appelsysteme.h> // MANUX_AS_INT
21#include <manux/atomique.h>
22#include <manux/ecran.h> // Caractéristiques de l'écran
23#ifdef MANUX_CONSOLES_VIRTUELLES
24# include <manux/console.h> // basculerVersConsoleSuivante
25#endif
26#include <manux/tache.h> // IntelTSS
27#include <manux/string.h> // memcpy
28#define MANUX_SELECTEUR_SEGMENT_CODE 0x08 /* WARNING a mettre ailleurs */
29
30#ifdef MANUX_APPELS_SYSTEME
31extern void handlerAppelSysteme(void); /* WARNING à définir dans un .h */
32#endif
33
40#define MANUX_NB_SOFT_INT \
41 (MANUX_NB_INTERRUPTIONS - (MANUX_NB_EXCEPTIONS + MANUX_NB_IRQ))
42
49
54
58#ifdef MANUX_INT_AUDIT
59uint32_t nbItRecues[MANUX_NB_INTERRUPTIONS] = {0};
60#endif // MANUX_INT_AUDIT
61
62void gestionExceptionPanique(TousRegistres registres,
63 uint32_t numEx, uint32_t errCode,
64 uint32_t eip, uint32_t cs, uint32_t eFlags);
65
70static
71void gestionExceptionDiv0(TousRegistres registres,
72 uint32_t numEx, uint32_t errCode,
73 uint32_t eip, uint32_t cs, uint32_t eFlags)
74{
75 printk("Caca %d, 0x%x\n", numEx, eip);
76 gestionExceptionPanique(registres, numEx, errCode, eip, cs, eFlags);
77}
78
83void gestionException(TousRegistres registres,
84 uint32_t numEx, uint32_t errCode,
85 uint32_t eip, uint32_t cs, uint32_t eFlags)
86{
87#ifdef MANUX_INT_AUDIT
88 nbItRecues[numEx] ++;
89#endif
90 fonctionDeGestionException[numEx](registres, numEx, errCode, eip, cs, eFlags);
91}
92
97
101static
102void neRienFaire(TousRegistres registres,
103 uint32_t eip, uint32_t cs, uint32_t eFlags,
104 uint32_t numIt)
105{
106 (void) registres;
107 (void) eip;
108 (void) cs;
109 (void) eFlags;
110 (void) numIt;
111
112 printk("neRienFaire %d\n", numIt);
113}
114
119void gestionInterruption(TousRegistres registres,
120 uint32_t numIt,
121 uint32_t eip, uint32_t cs, uint32_t eFlags)
122{
123 int idx = numIt-(MANUX_NB_EXCEPTIONS + MANUX_NB_IRQ);
124
125#ifdef MANUX_INT_AUDIT
126 nbItRecues[numIt] ++;
127#endif
128
129 fonctionDeGestionInterruption[idx](registres, eip, cs, eFlags, numIt);
130}
131
135static
136void positionnerHandlerInterruption(IDT idt, int i, Handler handler)
137{
138 idt[i].itg.offsetFaible = ((uint32_t)handler & 0xFFFF);
139 idt[i].itg.offsetFort = ((uint32_t)handler >> 16);
140 idt[i].itg.parametres = 0x8E00;
142}
143
150static
151void chargerIDT(IDT idt)
152{
153 volatile uint8_t argument[6];
154
155 argument[0] = 0xFF;
156 argument[1] = 0x07;
157 argument[2] = ( (uint32_t)idt & 0xFF);
158 argument[3] = (((uint32_t)idt>>8) & 0xFF);
159 argument[4] = (((uint32_t)idt>>16) & 0xFF);
160 argument[5] = (((uint32_t)idt>>24) & 0xFF);
161
162 __asm__ __volatile__ ("lidt (%0)"
163 : /* Pas de sortie */
164 :"a" ((char *)argument)
165 );
166 //return argument[0] + argument[1]+argument[2]+argument[3]+ argument[4]+argument[5];
167
168}
169
176{
178
179 return 0;
180}
181
186{
187 int i;
188 IDT idt = (IDT) MANUX_ADRESSE_IDT;
189
190 // On commence par positionner les handlers "stub" des exceptions
191 positionnerHandlerInterruption(idt, 0x00, stubHandlerExDiv0);
192 positionnerHandlerInterruption(idt, 0x01, stubHandlerExDebug);
193 positionnerHandlerInterruption(idt, 0x02, stubHandlerExNMI);
194 positionnerHandlerInterruption(idt, 0x03, stubHandlerExBreakpoint);
195 positionnerHandlerInterruption(idt, 0x04, stubHandlerExOverflow);
196 positionnerHandlerInterruption(idt, 0x05, stubHandlerExBoundExceeded);
197 positionnerHandlerInterruption(idt, 0x06, stubHandlerExDeviceInvalidOpcode);
198 positionnerHandlerInterruption(idt, 0x07, stubHandlerExDeviceUnavailable);
199 positionnerHandlerInterruption(idt, 0x08, stubHandlerExDoubleFault);
200 positionnerHandlerInterruption(idt, 0x09, stubHandlerExCoproOverrun);
201 positionnerHandlerInterruption(idt, 0x0a, stubHandlerExInvalidTSS);
202 positionnerHandlerInterruption(idt, 0x0b, stubHandlerExSegmentNotPresent);
203 positionnerHandlerInterruption(idt, 0x0c, stubHandlerExStackSegmentFault);
204 positionnerHandlerInterruption(idt, 0x0d, stubHandlerExGeneralProtectionFault);
205 positionnerHandlerInterruption(idt, 0x0e, stubHandlerExPageFault);
206 positionnerHandlerInterruption(idt, 0x0f, stubHandlerExReserved);
207 positionnerHandlerInterruption(idt, 0x10, stubHandlerExFloatingPoint);
208 positionnerHandlerInterruption(idt, 0x11, stubHandlerExAlignmentCheck);
209 positionnerHandlerInterruption(idt, 0x12, stubHandlerExFloatingMachineCheck);
210 positionnerHandlerInterruption(idt, 0x13, stubHandlerExFloatingSIMDFPE);
211 positionnerHandlerInterruption(idt, 0x14, stubHandlerExFloatingVirtualization);
212 positionnerHandlerInterruption(idt, 0x15, stubHandlerExControlProtection);
213 positionnerHandlerInterruption(idt, 0x16, stubHandlerExReserved2);
214 positionnerHandlerInterruption(idt, 0x17, stubHandlerExReserved3);
215 positionnerHandlerInterruption(idt, 0x18, stubHandlerExReserved4);
216 positionnerHandlerInterruption(idt, 0x19, stubHandlerExReserved5);
217 positionnerHandlerInterruption(idt, 0x1a, stubHandlerExReserved6);
218 positionnerHandlerInterruption(idt, 0x1b, stubHandlerExReserved7);
219 positionnerHandlerInterruption(idt, 0x1c, stubHandlerExHypervisionInjection);
220 positionnerHandlerInterruption(idt, 0x1d, stubHandlerExVMMCommunication);
221 positionnerHandlerInterruption(idt, 0x1e, stubHandlerExSecurity);
222 positionnerHandlerInterruption(idt, 0x1f, stubHandlerExReserved8);
223
224 // On configure l'aiguillage des exceptions. Par défaut, on panique !
225 for (i = 0; i < MANUX_NB_EXCEPTIONS; i++) {
227 }
228
229 // Maintenant, les exceptions que l'on veut gérer
230 fonctionDeGestionException[0] = gestionExceptionDiv0;
231
232 // Les IRQs sont gérées au travers du PIC. On positionne les
233 // handlers bas niveau
234 positionnerHandlerInterruption(idt, MANUX_INT_BASE_IRQ + 0, stubHandlerIRQ0);
235 positionnerHandlerInterruption(idt, MANUX_INT_BASE_IRQ + 1, stubHandlerIRQ1);
236 positionnerHandlerInterruption(idt, MANUX_INT_BASE_IRQ + 2, stubHandlerIRQ2);
237 positionnerHandlerInterruption(idt, MANUX_INT_BASE_IRQ + 3, stubHandlerIRQ3);
238 positionnerHandlerInterruption(idt, MANUX_INT_BASE_IRQ + 4, stubHandlerIRQ4);
239 positionnerHandlerInterruption(idt, MANUX_INT_BASE_IRQ + 5, stubHandlerIRQ5);
240 positionnerHandlerInterruption(idt, MANUX_INT_BASE_IRQ + 6, stubHandlerIRQ6);
241 positionnerHandlerInterruption(idt, MANUX_INT_BASE_IRQ + 7, stubHandlerIRQ7);
242 positionnerHandlerInterruption(idt, MANUX_INT_BASE_IRQ + 8, stubHandlerIRQ8);
243 positionnerHandlerInterruption(idt, MANUX_INT_BASE_IRQ + 9, stubHandlerIRQ9);
244 positionnerHandlerInterruption(idt, MANUX_INT_BASE_IRQ + 10, stubHandlerIRQ10);
245 positionnerHandlerInterruption(idt, MANUX_INT_BASE_IRQ + 11, stubHandlerIRQ11);
246 positionnerHandlerInterruption(idt, MANUX_INT_BASE_IRQ + 12, stubHandlerIRQ12);
247 positionnerHandlerInterruption(idt, MANUX_INT_BASE_IRQ + 13, stubHandlerIRQ13);
248 positionnerHandlerInterruption(idt, MANUX_INT_BASE_IRQ + 14, stubHandlerIRQ14);
249 positionnerHandlerInterruption(idt, MANUX_INT_BASE_IRQ + 15, stubHandlerIRQ15);
250
251 // On vérifie qu'on est en cohérence avec le nombre d'IRQ défini
252 // par le PIC
253 assert(MANUX_NB_IRQ == 16);
254
255 // L'aiguillage des IRQ est réalisé par le pilote du PIC que l'on
256 // initialise maintenant
258
259 // On va chercher les adresses des fonctions d'interruption
261
262 // On peuple l'IDT avec ces pointeurs
263 for (i = 0; i < MANUX_NB_SOFT_INT; i++) {
264 positionnerHandlerInterruption(idt,
267 }
268
269 // On configure l'aiguillage des interruptions logicielles. Par
270 // défaut, on ne fait rien
271 for (i = 0; i < MANUX_NB_SOFT_INT; i++) {
272 fonctionDeGestionInterruption[i] = neRienFaire;
273 }
274
275#ifdef MANUX_APPELS_SYSTEME
276 /* Le handler de l'interruption utilisée pour les appels système */
277 positionnerHandlerInterruption(idt, MANUX_AS_INT, handlerAppelSysteme);
278#endif
279
280 // On charge finalement l'IDT !
281 chargerIDT(idt);
282
283 asm( "sti" );
284}
285
286
287/*
288 * Affichage de la valeur v en hexa sur n chiffres à la position l, c
289 */
290#define afficherHexa(v, n, l, c) \
291{ \
292 uint32_t __val = (uint32_t) v; \
293 for (int __i = MANUX_CON_COLONNES*l+c+n-1; __i>=MANUX_CON_COLONNES*l+c; __i--) { \
294 ecran[2*__i] = chiffre[__val&15] ; \
295 __val /=16 ; \
296 } \
297}
298#define afficherBin(v, n, l, c) \
299{ \
300 uint32_t __val = (uint32_t) v; \
301 for (int __i = MANUX_CON_COLONNES*l+c+n-1; __i>=MANUX_CON_COLONNES*l+c; __i--) { \
302 ecran[2*__i] = chiffre[__val&1] ; \
303 __val /=2 ; \
304 } \
305}
306
307/*
308 * Pour sauver l'ecran caché par l'écran bleu de la mort
309 */
310static char bufferEcran[4000];
311
312static
313void ecranDeLaMort(uint32_t errCode, uint32_t itNum, TousRegistres registres,
314 uint32_t eip, uint32_t cs, uint32_t eFlags)
315{
316 (void) registres;
317
318 /* A définir ailleurs lorsque ce sera au point */
319 char *ecranPanique ="\
320+-------------+-------------------+--------32--28--24--20--16--12---8---4---0--+\
321| it : 0x-- | tss = 0x-------- | eflags= -------------------------------- |\
322+-------------+-------------------+-------------+---+---+---+---+---+---+---+--+\
323| cs : 0x---- | eip = 0x-------- | cr3 = 0x |\
324+-------------+-------------------+--------------------------------------------+\
325| ss : 0x---- | esp = 0x-------- | |\
326+-------------+-------------------+--------------------------------------------+\
327| ds : 0x---- | esi = 0x-------- | |\
328+-------------+-------------------+--------------------------------------------+\
329| | edi = 0x-------- | err = 0x |\
330+-------------+-----------------(Esp pour cacher)------------------------------+";
331
332 char chiffre[16] = "0123456789ABCDEF";
333 char * ecran = MANUX_CON_SCREEN;
334 int i;
335 uint32_t indice;
336
337 // Sauvegardons l'écran dans un buffer avant de le pourrir
338 memcpy(bufferEcran, ecran, 4000);
339
340 // On fait un peu de place en haut de l'écran
341 for (i=0; i<11*2*MANUX_CON_COLONNES; i+=2) {
342 ecran[i] = ecranPanique[i/2];
343 ecran[i+1] = COUL_FOND_BLEU | COUL_TXT_JAUNE;
344 }
345
346 __asm__ __volatile__("str %%eax" : "=a" (indice)); // WARNING WTF !?
347
348 // Première ligne
349 afficherHexa(itNum, 2, 1, 9);
350 afficherBin(eFlags, 32, 1, 45);
351 afficherHexa(cs, 4, 3, 9);
352 afficherHexa(eip, 8, 3, 25);
353 afficherHexa(errCode, 8, 9, 45);
354
355#ifdef MANUX_GESTION_MEMOIRE
356 Descripteur desc = gdtSysteme->descripteur[indice>>3];
357 IntelTSS * tssDuFautif = (IntelTSS *)(
358 (((uint32_t)desc.dt.baseFort) << 24)
359 + (((uint32_t)desc.dt.baseInter) << 16)
360 + desc.dt.baseFaible
361 );
362
363 afficherHexa(tssDuFautif, 8, 1, 25);
364 //afficherBin(tssDuFautif->EFLAGS, 32, 1, 45);
365 afficherHexa(tssDuFautif->CR3, 8, 3, 45);
366
367 // Les descripteurs de segment
368 afficherHexa(tssDuFautif->SS, 4, 5, 9);
369 afficherHexa(tssDuFautif->DS, 4, 7, 9);
370
371 // Les pointeurs
372 //afficherHexa(tssDuFautif->EIP, 8, 3, 25);
373 afficherHexa(tssDuFautif->ESP, 8, 5, 25);
374 afficherHexa(tssDuFautif->ESI, 8, 7, 25);
375 afficherHexa(tssDuFautif->EDI, 8, 9, 25);
376#endif
377}
378
384void gestionExceptionPanique(TousRegistres registres,
385 uint32_t numIt,uint32_t errCode,
386 uint32_t eip, uint32_t cs, uint32_t eFlags)
387{
388 char * ecran = MANUX_CON_SCREEN;
389 int d = 1;
390 unsigned char c;
391
392 ecranDeLaMort(errCode, numIt, registres, eip, cs, eFlags);
393
394 while (1) {
395 inb(0x60, c);
396 switch (c) {
397 case 0x01: // ESC
398#ifdef MANUX_CONSOLES_VIRTUELLES
399 basculerVersConsoleSuivante();
400#endif
401 while (c == 0x81){
402 inb(0x60, c);
403 };
404 break;
405 case 0x39: // SPACE On alterne entre l'écran bleu et l'écran au moment du drame
406 d = 1-d;
407 if (d) {
408 ecranDeLaMort(errCode, numIt, registres, eip, cs, eFlags);
409 }else{
410 // On restaure l'écran
411 memcpy(ecran, bufferEcran, 4000);
412 };
413 while (c == 0x39){
414 inb(0x60, c);
415 };
416 break;
417 }
418 }
419 halt();
420}
421
Définition des opérations de synchronisation de ManuX.
#define MANUX_NB_IRQ
Definition intel-8259a.h:19
#define MANUX_PIC_INIT
Definition intel-8259a.h:26
Définition des caractéristiques de base de l'écran.
#define MANUX_CON_COLONNES
Definition ecran.h:28
@ COUL_FOND_BLEU
Definition ecran.h:54
@ COUL_TXT_JAUNE
Definition ecran.h:51
#define MANUX_CON_SCREEN
Definition ecran.h:27
#define MANUX_AS_INT
Définition des fonctions de base d'accés à la console.
void halt(void)
void(* FonctionGestionException)(TousRegistres registres, uint32_t eip, uint32_t cs, uint32_t eFlags, uint32_t numEx, uint32_t errCode)
typedef void(Handler(void))
IDTGate * IDT
void(* FonctionGestionInterruption)(TousRegistres registres, uint32_t eip, uint32_t cs, uint32_t eFlags, uint32_t numIt)
Définition des fonctions de base d'entrée-sortie du noyau.
void printk(char *format,...)
Fonction principale d'affichage dans le noyau.
Definition printk.c:166
void * memcpy(void *dest, const void *src, size_t n)
Definition string.c:12
unsigned long uint32_t
Definition types.h:20
unsigned char uint8_t
Definition types.h:12
void stubHandlerExFloatingVirtualization(void)
void stubHandlerIRQ15(void)
void stubHandlerExReserved6(void)
void stubHandlerExNMI(void)
void stubHandlerIRQ9(void)
void stubHandlerIRQ6(void)
void stubHandlerIRQ4(void)
void stubHandlerExReserved(void)
void stubHandlerIRQ5(void)
void stubHandlerExFloatingSIMDFPE(void)
void stubHandlerExDebug(void)
void stubHandlerIRQ1(void)
void stubHandlerExReserved4(void)
void stubHandlerExDeviceInvalidOpcode(void)
void stubHandlerIRQ7(void)
void stubHandlerIRQ0(void)
void stubHandlerIRQ13(void)
void stubHandlerIRQ12(void)
void stubHandlerExOverflow(void)
void stubHandlerIRQ3(void)
void stubHandlerExStackSegmentFault(void)
void stubHandlerExDoubleFault(void)
void stubHandlerExAlignmentCheck(void)
void stubHandlerExVMMCommunication(void)
void stubHandlerExInvalidTSS(void)
void stubHandlerExDeviceUnavailable(void)
void stubHandlerExReserved2(void)
void stubHandlerExGeneralProtectionFault(void)
void stubHandlerIRQ11(void)
void stubHandlerIRQ8(void)
void stubHandlerIRQ2(void)
void stubHandlerIRQ14(void)
void stubHandlerExCoproOverrun(void)
void stubHandlerExReserved5(void)
void initialiserHandlersInterruption(void *table, uint32_t taille)
void stubHandlerExHypervisionInjection(void)
void stubHandlerExReserved8(void)
void stubHandlerExBreakpoint(void)
void stubHandlerIRQ10(void)
void stubHandlerExPageFault(void)
void stubHandlerExFloatingPoint(void)
void stubHandlerExReserved3(void)
void stubHandlerExBoundExceeded(void)
void stubHandlerExControlProtection(void)
void stubHandlerExReserved7(void)
void stubHandlerExSegmentNotPresent(void)
void stubHandlerExDiv0(void)
void stubHandlerExFloatingMachineCheck(void)
void stubHandlerExSecurity(void)
void gestionExceptionPanique(TousRegistres registres, uint32_t numEx, uint32_t errCode, uint32_t eip, uint32_t cs, uint32_t eFlags)
Décompte des interruptions reçues.
void gestionInterruption(TousRegistres registres, uint32_t numIt, uint32_t eip, uint32_t cs, uint32_t eFlags)
: Fonction de base de gestion d'une exception
FonctionGestionException fonctionDeGestionException[MANUX_NB_EXCEPTIONS]
: la table de gestion des exceptions
#define afficherHexa(v, n, l, c)
int definirFonctionGestionInterruption(int num, FonctionGestionInterruption fg)
#define afficherBin(v, n, l, c)
void * handlerBasNiveauInterruption[MANUX_NB_SOFT_INT]
Une table (initialisée par la fonction initialiserHandlersInterruption de interBasNiveau....
void initialiserIDT(void)
! Initialiser l'IDT (Interrupt Description Table)
#define MANUX_NB_SOFT_INT
Combien y a-t-il d'interruptions logicielles ?
void gestionException(TousRegistres registres, uint32_t numEx, uint32_t errCode, uint32_t eip, uint32_t cs, uint32_t eFlags)
: Fonction de base de gestion d'une exception
#define MANUX_SELECTEUR_SEGMENT_CODE
FonctionGestionInterruption fonctionDeGestionInterruption[MANUX_NB_SOFT_INT]
#define inb(port, adresseOctet)
Lecture d'un octet depuis un port.
Definition io.h:19
uint16_t c
uint16_t d
#define assert(cond)
Definition debug.h:126
#define MANUX_INT_BASE_IRQ
Definition pc-i386.h:33
#define MANUX_NB_INTERRUPTIONS
Definition pc-i386.h:25
#define MANUX_NB_EXCEPTIONS
Definition pc-i386.h:18
#define MANUX_ADRESSE_IDT
#define chiffre
Definition printk.c:24
DescriptorTable * gdtSysteme
Definition segment.c:12
uint16_t selSegment
uint16_t offsetFort
uint16_t offsetFaible
uint16_t parametres
uint16_t baseFaible
Definition segment.h:28
uint8_t baseInter
Definition segment.h:29
uint8_t baseFort
Definition segment.h:32
Descripteur descripteur[0]
Definition segment.h:47
uint32_t EDI
Definition tache.h:61
uint32_t CR3
Definition tache.h:56
uint32_t ESP
Definition tache.h:60
uint16_t SS
Definition tache.h:66
uint32_t ESI
Definition tache.h:61
uint16_t DS
Definition tache.h:68
InterruptGate itg
DescTSS dt
Definition segment.h:37