Bonjour,
Je suis en train de programmer un embryon de kernel pour apprendre un peu mieux comment tout cela fonctionne.
J'utilise pour ca les tutoriels suivants :
http://a.michelizza.free.fr/pmwiki.php?n=TutoOS.TutoOS
http://www.osdever.net/bkerndev/Docs/idt.htm
http://www.jamesmolloy.co.uk/tutorial_html/index.html
Mais je bloque sur la gestion des interruptions.
Je reussis a charger la GDT et a l'utiliser sans problème, mais quand je charge l'IDT et reprogramme les 8259A, bochs me dit que j'ai des erreurs de segments.
Je pense que je comprends le problème, c'est a dire que quand il y a une interruption et que le processeur va chercher le descripteur systeme dans l'IDT grace au vecteur que lui transmet le 8259A, il le trouve bien. Apres, quand il va chercher l'ISR dans le segment de code que lui indique le descripteur systeme de l'IDT avec l'offset qui est aussi présent dans ce même descripteur système, il le trouve aussi ( la preuve mon ISR par defaut est bien apellee, et elle a pour effet d'ecrire 'Default' a l'ecran ).
Le problème est que je lance le programme, je charge l'IDT et reprogramme les 8259A, ca m'ecrit Default beaucoup de fois a l'ecran et bochs lance un >>panic<< et s'arrete en me disant qu'il y a un depassement de limite de segment.
Je ne sais pas trop d'ou ca vient donc je demande de l'aide !
Voila le code :
idt.h :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38 #ifndef IDT_HEADER #define IDT_HEADER #define IDT_BASE 0x0800 #define IDT_SIZE 0xFF /* note : la limit est la taille et NON l'adresse de fin */ /* le type des descripteurs systeme que l'on va mettre dans l'IDT */ struct idt_descriptor_t { unsigned short offset0_15; unsigned short segment_selector16_31; unsigned char always0; unsigned char flags; /* P sur 1 bit, DPL ( contient le ring sur 2 bit ), et toujours 01110 */ unsigned short offset48_63; }__attribute__ ((packed)); /* the structure that will be loaded into the IDTR register */ struct idt_ptr_t { unsigned short limit; unsigned int base; }__attribute__ ((packed)); void init_idt_desc(struct idt_descriptor_t* idt_desc, unsigned int offset, unsigned short ss, unsigned char flags); void init_idt(); extern void idt_load(); extern void isr_default(); extern void isr_clock(); extern void isr_kbd(); #endif
idt.c
asm_idt.asm
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67 #include <idt.h> #include <lib.h> #include <screen.h> /* l'IDT elle meme. c'est un tableau de 256 descripteurs systeme */ struct idt_descriptor_t idt[IDT_SIZE]; /* l'offset designe ou se trouve l'ISR a partir du debut du segment de code. Comme il est separe en deux parties dans un descripteur systeme ( pour la retro compatibilite 80286 ), la partie basse et la partie haute, il faut faire des operations bitwise pour le diviser. */ void init_idt_desc(struct idt_descriptor_t* idt_desc, unsigned int offset, unsigned short ss, unsigned char flags) { idt_desc->offset0_15 = ( offset & 0xFFFF ); /* on recupere les 16 bits de poids faible de l'offset */ idt_desc->segment_selector16_31 = ss; idt_desc->always0 = 0x00; idt_desc->flags = flags; idt_desc->offset48_63 = ( offset & 0xFFFF0000 ) >> 16; /* on recupere les 16 bits de poids fort */ } /* Fonction qui initialise TOUTES les entrees de L'IDT grace a la fonction init_idt_desc() */ void init_idt() { short i=0; /* on initialise tous les descripteurs de l'IDT pour qu'ils pointent vers l'ISR par defaut */ for(i=0; i<IDT_SIZE; i++) { /* 0x8E signifie : descripteur systeme de type interrupt gate */ init_idt_desc(&idt[i], (unsigned int)isr_default, 0x0008, 0x8E); } screen_write(TEXT_FORMAT_GREEN, "2\n"); /* les interruptions 32 et 33 apelleront les isr horloge et clavier */ init_idt_desc(&idt[32], (unsigned int)isr_clock, 0x0008, 0x8E); /* clock */ init_idt_desc(&idt[33], (unsigned int)isr_kbd, 0x0008, 0x8E); /* clavier */ screen_write(TEXT_FORMAT_GREEN, "3\n"); struct idt_ptr_t idt_ptr; idt_ptr.base = IDT_BASE; idt_ptr.limit = IDT_SIZE*8; /* car un descripteur fait 8 Bytes */ screen_write(TEXT_FORMAT_GREEN, "4\n"); /* et on recopie effectivement l'IDT a l'adresse prevue */ memcpy( (char*) idt_ptr.base, (char*) &idt, idt_ptr.limit ); screen_write(TEXT_FORMAT_GREEN, "5\n"); /* fonction assembleur qui va charger notre IDT */ idt_load(&idt_ptr); }
asm_isrs.asm :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 [GLOBAL idt_load] idt_load: mov eax, [esp+4] ; on recupere l'adresse de la structure idt_ptr_t, passee sur la pile lidt [eax] ; et on charge la structure idt_ptr_t dans le registre IDTR ret
isrs.c
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 [GLOBAL isr_default] [GLOBAL isr_clock] [GLOBAL isr_kbd] [extern isr_default_c] [extern isr_clock_c] [extern isr_kbd_c] isr_default: call isr_default_c ; on apelle la fonction C qui contient le code de l'ISR mov al, 0x20 ; on met dans al la valeur qui correspond a EOI pour le PIC out 0x20, al ; on envoie le signal au PIC que l'interruption a ete traitee iret ; retour d'interruption isr_clock: call isr_clock_c mov al, 0x20 out 0x20, al iret isr_kbd: call isr_kbd_c mov al, 0x20 out 0x20, al iret
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 #include <screen.h> void isr_default_c() { screen_write(TEXT_FORMAT_RED, "default.\n"); } void isr_clock_c() { screen_write(TEXT_FORMAT_RED, "clock.\n"); } void isr_kbd_c() { screen_write(TEXT_FORMAT_RED, "keyboard.\n"); }
le code pour reprogrammer les 8259A :
et les erreurs que me renvoie bochs :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67 [GLOBAL init_pics] ; pour que le code C puisse apeller init_pics(). ; note : les jmp servent a faire une temporisation pour etre sur ; que le PIC a le temps de lire les registres avant de reecrire. init_pics: ; on envoie la valeur de al sur les ports des PICS, ; pour initialiser leur ICW1 mov al, 0x11 ; sequence d'initialisation out 0x20, al ; maitre jmp .1 .1: out 0xA0, al ; esclave jmp .init_icw2 .init_icw2: ; initialisation de ICW2 ; c'est la qu'on va dire en gros au pic : ; "quand tu recois l'IRQ x, tu vas envoyer au processeur le vecteur de valeur y" ; ce vecteur correspondra a un index dans l'IDT bien sur ; on va faire comme ca : ; les IRQ0-7 (PIC 1) sont programmees pour renvoyer les vecteurs correspondant aux interruptions 0x20-0x27 ( 32 a 39 ) ; les IRQ8-15 (PIC 2) sont programmees pour renvoyer les vecteurs correspondant aux interruptions 0x28-0x2f ( 40 a 47 ) mov al, 0x20 out 0x21, al ; maitre, vecteur de depart = 32 jmp .2 .2: mov al, 0x28 out 0xA1, al ; esclave, vecteur de depart = 40 jmp .init_icw3 .init_icw3: ; initialisation du registre ICW3 ; celui ci informe les PICS sur la maniere donc ils sont cascades. ; le controleur esclave est rattache a la broche 2 du maitre par sa broche 4 mov al, 0x04 out 0x21, al ; le maitre est relie sur la broche 4 de l'esclave ( 8259-1 is master ) jmp .3 .3: mov al, 0x02 out 0xA1, al ; l'esclave est relie sur la broche 2 du maitre ( 8259-2 is slave ) jmp .init_icw4 .init_icw4: ; initialisation du registre ICW4 ; celui ci specifie aux 8259A dans quel mode ils doivent fonctionner ; ici on utilise le mode par defaut, AEOI: automatic end of interrupt ; aussi connu sous le nom de mode 8086 mov al, 0x01 out 0x21, al jmp .4 .4: out 0xA1, al jmp .set_ocw1 .set_ocw1: ; le mot d'operation de controle OCW1 permet masquer/demasquer les interruptions ; en ecrivant dans le registre IMR du 8259A mov al,0xff ; on masque tout pour l'instant ( 1=masked, 0=unmasked ) out 0x21,al jmp .5 .5: out 0xA1,al
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55 05163214e[CPU0 ] fetch_raw_descriptor: GDT: index (151f) 2a3 > limit (7f8) 00005163241e[CPU0 ] fetch_raw_descriptor: GDT: index (151f) 2a3 > limit (7f8) 00005163268e[CPU0 ] fetch_raw_descriptor: GDT: index (151f) 2a3 > limit (7f8) 00005163295e[CPU0 ] fetch_raw_descriptor: GDT: index (151f) 2a3 > limit (7f8) 00005163322e[CPU0 ] fetch_raw_descriptor: GDT: index (151f) 2a3 > limit (7f8) 00005163349e[CPU0 ] fetch_raw_descriptor: GDT: index (151f) 2a3 > limit (7f8) 00005163376e[CPU0 ] fetch_raw_descriptor: GDT: index (151f) 2a3 > limit (7f8) 00005163403e[CPU0 ] fetch_raw_descriptor: GDT: index (151f) 2a3 > limit (7f8) 00005163430e[CPU0 ] fetch_raw_descriptor: GDT: index (151f) 2a3 > limit (7f8) 00005163457e[CPU0 ] fetch_raw_descriptor: GDT: index (151f) 2a3 > limit (7f8) 00005163485e[CPU0 ] read_RMW_virtual_byte_32(): segment limit violation 00005163486e[CPU0 ] branch_near32: offset outside of CS limits 00005163487e[CPU0 ] branch_near32: offset outside of CS limits 00005163678e[CPU0 ] read_RMW_virtual_byte_32(): segment limit violation 00005163679e[CPU0 ] read_RMW_virtual_byte_32(): segment limit violation 00005163680e[CPU0 ] read_RMW_virtual_byte_32(): segment limit violation 00005163681e[CPU0 ] read_RMW_virtual_byte_32(): segment limit violation 00005163682e[CPU0 ] read_RMW_virtual_byte_32(): segment limit violation 00005163683e[CPU0 ] read_RMW_virtual_byte_32(): segment limit violation 00005163684e[CPU0 ] read_RMW_virtual_byte_32(): segment limit violation 00005163685e[CPU0 ] read_RMW_virtual_byte_32(): segment limit violation 00005163686e[CPU0 ] read_RMW_virtual_byte_32(): segment limit violation 00005163687e[CPU0 ] read_RMW_virtual_byte_32(): segment limit violation 00005163688e[CPU0 ] read_RMW_virtual_byte_32(): segment limit violation 00005163689e[CPU0 ] read_RMW_virtual_byte_32(): segment limit violation 00005163690e[CPU0 ] read_RMW_virtual_byte_32(): segment limit violation 00005163691e[CPU0 ] read_RMW_virtual_byte_32(): segment limit violation 00005163691e[CPU0 ] interrupt(): gate.type(1) != {5,6,7,14,15} 00005163692e[CPU0 ] read_RMW_virtual_byte_32(): segment limit violation 00005163692e[CPU0 ] interrupt(): gate.type(1) != {5,6,7,14,15} 00005163693e[CPU0 ] read_RMW_virtual_byte_32(): segment limit violation 00005163693e[CPU0 ] interrupt(): gate.type(1) != {5,6,7,14,15} 00005163693e[CPU0 ] interrupt(): gate descriptor is not valid sys seg (vector=0x08) 00005163693i[CPU0 ] CPU is in protected mode (active) 00005163693i[CPU0 ] CS.d_b = 32 bit 00005163693i[CPU0 ] SS.d_b = 32 bit 00005163693i[CPU0 ] | EAX=14ba0000 EBX=4000007c ECX=88fff69f EDX=000b5131 00005163693i[CPU0 ] | ESP=0000083f EBP=000015e6 ESI=00000004 EDI=000010a6 00005163693i[CPU0 ] | IOPL=0 id vip vif ac vm RF nt of df if tf sf zf af PF cf 00005163693i[CPU0 ] | SEG selector base limit G D 00005163693i[CPU0 ] | SEG sltr(index|ti|rpl) base limit G D 00005163693i[CPU0 ] | CS:0008( 0001| 0| 0) 00000000 0fffffff 1 1 00005163693i[CPU0 ] | DS:0010( 0002| 0| 0) 00000000 0fffffff 1 1 00005163693i[CPU0 ] | SS:0018( 0003| 0| 0) 00000000 0fffffff 1 1 00005163693i[CPU0 ] | ES:0010( 0002| 0| 0) 00000000 0fffffff 1 1 00005163693i[CPU0 ] | FS:0010( 0002| 0| 0) 00000000 0fffffff 1 1 00005163693i[CPU0 ] | GS:0010( 0002| 0| 0) 00000000 0fffffff 1 1 00005163693i[CPU0 ] | EIP=00001510 (00001510) 00005163693i[CPU0 ] | CR0=0x60000011 CR2=0x00000000 00005163693i[CPU0 ] | CR3=0x00000000 CR4=0x00000000 00005163693i[CPU0 ] 0x00001510>> add byte ptr ds:[eax], al : 0000 00005163693e[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting 00005163693i[SYS ] bx_pc_system_c::Reset(HARDWARE) called 00005163693i[CPU0 ] cpu hardware reset
Voila donc si une ame charitable pouvait m'aider un peu, parce que la je coince un peu...
Merci
EDIT ! : Je viens de regler mon probleme d'IDT et de GDT en recompilant Bochs en mode debug et en verifiant chaque octet en memoire, elles sont tout a fait valides maintenant. Il me reste juste un souci lors de la reprogrammation des 8259-A, c'est a dire que quand je les reprogramme ils foutent totalement en l'air la GDT et l'IDT.... c'est assez bizarre...
Enfin bon voila je vais continuer a debugger le programme lentement mais surement
Partager