Even the Alexei Frounze tutorials end with GPF whenever they use interrupts in that machine. And have tried fast A20, BIOS A20 and keyboard controller A20 in one of my boot sectors, and it doesn't work yet.
I made a small test kernel and have debugged it as far as I know, and have isolated the problem to the moment I enable interrupts with STI. But it only happens in 1 machine.
I don't think it's a stack alignment problem, but can be some other similar problem.
http://126.sytes.net/tmp/kern_int_err0000.zip
At the end I have put the most relevant "RealC" source (asm-C-like) in the most accurate order so you can evaluate it more easily.
It contains the full source code in Assembly. If you want to understand it clearly you can see the CSM files of the same names as those as the ASM files. These contain C-like source code which is easier to understand yet with assembly level.
What is that could be wrong here, judging from what it's doing, what details are lacking in the configuration process?
Code: Select all
The whole skeleton with PIT, keyboard and a
dummy inactive PS/2 mouse IRQs.
Files:
_____
bootf.zip -- The floppy boot sources by John Fine
floppy_image.img -- The whole floppy image
BOOTSECT.BIN -- Only th floppy bootsector
kernel.bin -- The kernel described below
The floppy boot sources have been modified. The
ONLY changes have been to both load the
kernel directly at 0x100000 and leave Paging
disabled in CR0. Everything else is intact and
unchanged.
It does the following, in order:
- Program resides at 0x100000
- Disables interrupts (CLI)
- Sets SS, DS, ES, FS, GS to data selector 16
- Sets ESP to 0x100000*3-1
- Sets PIC1 to INTs 28h-2Fh and PIC2 to 70h-77h
- Leaves keyboard and PS/2 mouse IRQs active at PIC1
- IDT resides at 0x100000*2
- Zeroes IDT up to INT 77h
- Builds keyboard, PS/2 mouse and PIT vectors
- Sets the first default onscreen text DWORD to "1234"
- Loads IDT with LIDT[IDTR]
- Enables Interrupts with STI (it Bombs in 1 PC)
- Loops forever incrementing onscreen text DWORD at [0xB8000+41]
Description of Bombing:
_____________________
When the program bombs, it has already been
loaded and configured. Just when interrupts are
enabled, it resets in a 2010 Asrock Intel E6500
Dual Core machine, model N73V-S. The A20 gate is enabled in the
boot code, because if the STI instruction to
enable interrupts is removed, it works fine
but without interrupts.
_________________________________________
_________________________________________
_________________________________________
_________________________________________
_________________________________________
Main:
Code: Select all
bits 32
org 1048576
asm cli
asm mov ax,16
asm mov ss,ax
asm mov ds,ax
asm mov es,ax
asm mov fs,ax
asm mov gs,ax
asm mov esp,1048576*3-1
#include "pmode_pic_reprogramming.asm"
#include "idt_builder.asm"
dword[0xB8000+160]="1234";
asm{
lidt[IDTR]
asm sti
are:
inc dword[0xB8000+41]
jmp are
}
#include "idtr.asm"
#include "ps2_keyb_isr.asm"
#include "ps2_mouse_isr.asm"
#include "pit_isr.asm"
_________________________________________
_________________________________________
_________________________________________
_________________________________________
_________________________________________
ISR sample:
Code: Select all
function pit_isr()
{
asm push eax
dword[0xB8002+60]++; //Print something
//Send EOI to PIC 1
///
$AL=20h;
asm out 20h,al
asm pop eax
asm iretd
}
PIC reprogramming:
Code: Select all
/*
Port 20h and A0h -- Write-only (supposedly)
After PIC initialization, used more commonly
for sending EOI (End Of Interrupt).
Port 21h and A1h -- Read/Write
After PIC initialization, used more commonly
to read/write/enable/disable specific IRQs
from 0 to 15 (0-7 in PIC_1_Master and 8-15
in PIC_2_Slave).
*/
;//Initialization Command Word 1
;//Initialization Command Word 1
;//Initialization Command Word 1
;//Send ICW1:
;;;
;//ICW1 bitset:
;// Bits:
;// bit 0 -- ICW4 needed (1) or ICW4 not needed (0)
;// bit 1 -- cascade mode (0) or single mode (1)
;// bit 2 -- IDT entry is 8 bytes (0) or 4 bytes (1)
;// bit 3 -- edge triggered mode (0) or level triggered mode (1)
;// bit 4 -- ICW1 is being issued (1) or ICW1 is not being issued (0)
;// bits 5-7 are only used if bit 2 is 0 (000)
;
$AL=00010001b;
asm out 0x20,al; ;//PIC1
$AL=00010001b;
asm out 0xA0,al; ;//PIC2
;//Initialization Command Word 2
;//Initialization Command Word 2
;//Initialization Command Word 2
;//Send ICW2:
;;;
;//ICW2 bitset:
;// Bits:
;// bit 0-2 -- reserved (00)
;// bits 3-7 -- first INT number to be handled by each PIC
;
$AL=0x28;
asm out 0x21,al; ;//PIC1: INT28h-2Fh (like in Real Mode but now it's INT (08h+20h))
$AL=0x70;
asm out 0xA1,al; ;//PIC2: INT70h-77h (like in Real Mode)
;//Initialization Command Word 3
;//Initialization Command Word 3
;//Initialization Command Word 3
;//Send ICW3:
;;;
;//ICW3 bitset:
;// Bits:
;// bit 0 -- PIC attached, "IRQ 0 to PIC2" for PIC1 and "IRQ 8" for PIC2 (1)
;// or cascaded disabled for "IRQ 0" for PIC1 and "IRQ 8" for PIC2 (0)
;//
;// bit 1 -- PIC attached, "IRQ 1 to PIC2" for PIC1 and "IRQ 9" for PIC2 (1)
;// or cascaded disabled for "IRQ 1" for PIC1 and "IRQ 9" for PIC2 (0)
;//
;// bit 2 -- PIC attached, "IRQ 2 to PIC2" for PIC1 and "IRQ 10" for PIC2 (1)
;// or cascaded disabled for "IRQ 2" for PIC1 and "IRQ 10" for PIC2 (0)
;//
;// bit 3 -- PIC attached, "IRQ 3 to PIC2" for PIC1 and "IRQ 11" for PIC2 (1)
;// or cascaded disabled for "IRQ 3" for PIC1 and "IRQ 11" for PIC2 (0)
;//
;// bit 4 -- PIC attached, "IRQ 4 to PIC2" for PIC1 and "IRQ 12" for PIC2 (1)
;// or cascaded disabled for "IRQ 4" for PIC1 and "IRQ 12" for PIC2 (0)
;//
;// bit 5 -- PIC attached, "IRQ 5 to PIC2" for PIC1 and "IRQ 13" for PIC2 (1)
;// or cascaded disabled for "IRQ 5" for PIC1 and "IRQ 13" for PIC2 (0)
;//
;// bit 6 -- PIC attached, "IRQ 6 to PIC2" for PIC1 and "IRQ 14" for PIC2 (1)
;// or cascaded disabled for "IRQ 6" for PIC1 and "IRQ 14" for PIC2 (0)
;//
;// bit 7 -- PIC attached, "IRQ 7 to PIC2" for PIC1 and "IRQ 15" for PIC2 (1)
;// or cascaded disabled for "IRQ 7" for PIC1 and "IRQ 15" for PIC2 (0)
;//
;
$AL=00000100b;
asm 0x21,al; ;//PIC1: connection to slave in IRQ2
$AL=00000010b;
asm out 0xA1,al; ;//PIC2: this is the hook from IRQ9 to the IRQ2 in PIC2
;//Initialization Command Word 4
;//Initialization Command Word 4
;//Initialization Command Word 4
;//Send ICW4:
;;;
;//ICW4 bitset:
;// Bits:
;// bit 0 -- 8086/8088 mode (1) or 8085 mode (0)
;// bit 1 -- manual EOI (0) or auto EOI (1) Interrupt Acknowledge
;// bits 2-3 -- [00] == nonbuffered mode == [00]
;// (01) == nonbuffered mode == (01)
;// (10) == buffered mode/slave == (10)
;// (11) == buffered mode/master == (11)
;// bit 4 -- normal mode (0) or special fully-nested mode (1)
;// bits 5-7 -- reserved (000)
;
$AL=00000001b;
asm out 0x21,al; ;//PIC1
$AL=00000001b;
asm out 0xA1,al; ;//PIC2
;//Output Control Word 1
;//Output Control Word 1
;//Output Control Word 1
;//Send OCW1:
;;;
;//OCW1 bitset:
;// Bits:
;// bit 0 -- disable IRQ0 in PIC1 or IRQ8 in PIC2 (1) or enable it (0)
;// bit 1 -- disable IRQ1 in PIC1 or IRQ9 in PIC2 (1) or enable it (0)
;// bit 2 -- disable IRQ2 in PIC1 or IRQ10 in PIC2 (1) or enable it (0)
;// bit 3 -- disable IRQ3 in PIC1 or IRQ11 in PIC2 (1) or enable it (0)
;// bit 4 -- disable IRQ4 in PIC1 or IRQ12 in PIC2 (1) or enable it (0)
;// bit 5 -- disable IRQ5 in PIC1 or IRQ13 in PIC2 (1) or enable it (0)
;// bit 6 -- disable IRQ6 in PIC1 or IRQ14 in PIC2 (1) or enable it (0)
;// bit 7 -- disable IRQ7 in PIC1 or IRQ15 in PIC2 (1) or enable it (0)
;
$AL=11111100b; //Enable keyboard and PIT IRQs
asm out 0x21,al; ;//PIC1, disables also the IRQ2 slave line response
$AL=11111111b;
asm out 0xA1,al; ;//PIC2
_________________________________________
_________________________________________
_________________________________________
_________________________________________
IDT building:
Code: Select all
IDT equ 1048576*2
///INIT: Zero-clear the IDT memory
///INIT: Zero-clear the IDT memory
///INIT: Zero-clear the IDT memory
// $ECX=(78h*8)/4; //Number of vectors times Size of INT vector
//divided by DWORD size
$ECX=240; //240 DWORDs!!!
$EDI=IDT; //Destination for the IDT
asm xor eax,eax ;Zero value
asm rep stosd ;Zero out!
///END: Zero-clear the IDT memory
///END: Zero-clear the IDT memory
///END: Zero-clear the IDT memory
///INIT: Setup the keyboard ISR
///INIT: Setup the keyboard ISR
///INIT: Setup the keyboard ISR
///INIT: Setup the keyboard ISR
$EDI=IDT; //Take IDT base address
$EDI+=328; //Go to 29h*8, or vector 29h
asm {
mov eax,ps2_keyb_isr ;take base address
;dw 00000h ; (Bytes 0-1) ISR Handler Low Word, bits 0-15
mov word[edi],ax
;dw 00008h ; (Bytes 2-3) Segment Selector
mov word[edi+2],8
;db 000h ; (Byte 4) bits 0-4 Reserved (00000b)
; bits 5-7 000b
mov byte[edi+4],0
;db 10001110b ; (Byte 5) bit 0 -- 0
; bit 1 -- 1
; bit 2 -- 1
; bit 3 -- Default Operand Size (D)
; 0b -- 16 bits
; 1b -- 32 bits
;
; bit 4 -- 0
; bit 5-6 -- Descriptor Privilege Level (DPL)
; 00b -- Ring 0
; 01b -- Ring 1
; 10b -- Ring 2
; 11b -- Ring 3
;
; bit 7 -- Present (P)
; 0b -- No
; 1b -- Yes
mov byte[edi+5],10001110b
;dw 00000h ; (Bytes 6-7) ISR Handler High Word, bits 16-31
ror eax,16
mov word[edi+6],ax
}
///END: Setup the keyboard ISR
///END: Setup the keyboard ISR
///END: Setup the keyboard ISR
///INIT: Setup the PS/2 mouse ISR
///INIT: Setup the PS/2 mouse ISR
///INIT: Setup the PS/2 mouse ISR
///INIT: Setup the PS/2 mouse ISR
$EDI=IDT; //Take IDT base address
$EDI+=928; //Go to 74h*8, or vector 74h
asm {
mov eax,ps2_mouse_isr ;take base address
;dw 00000h ; (Bytes 0-1) ISR Handler Low Word, bits 0-15
mov word[edi],ax
;dw 00008h ; (Bytes 2-3) Segment Selector
mov word[edi+2],8
;db 000h ; (Byte 4) bits 0-4 Reserved (00000b)
; bits 5-7 000b
mov byte[edi+4],0
;db 10001110b ; (Byte 5) bit 0 -- 0
; bit 1 -- 1
; bit 2 -- 1
; bit 3 -- Default Operand Size (D)
; 0b -- 16 bits
; 1b -- 32 bits
;
; bit 4 -- 0
; bit 5-6 -- Descriptor Privilege Level (DPL)
; 00b -- Ring 0
; 01b -- Ring 1
; 10b -- Ring 2
; 11b -- Ring 3
;
; bit 7 -- Present (P)
; 0b -- No
; 1b -- Yes
mov byte[edi+5],10001110b
;dw 00000h ; (Bytes 6-7) ISR Handler High Word, bits 16-31
ror eax,16
mov word[edi+6],ax
}
///END: Setup the PS/2 mouse ISR
///END: Setup the PS/2 mouse ISR
///END: Setup the PS/2 mouse ISR
///INIT: Setup the PIT ISR
///INIT: Setup the PIT ISR
///INIT: Setup the PIT ISR
///INIT: Setup the PIT ISR
$EDI=IDT; //Take IDT base address
$EDI+=320; //Go to 28h*8, or vector 28h
asm {
mov eax,pit_isr ;take base address
;dw 00000h ; (Bytes 0-1) ISR Handler Low Word, bits 0-15
mov word[edi],ax
;dw 00008h ; (Bytes 2-3) Segment Selector
mov word[edi+2],8
;db 000h ; (Byte 4) bits 0-4 Reserved (00000b)
; bits 5-7 000b
mov byte[edi+4],0
;db 10001110b ; (Byte 5) bit 0 -- 0
; bit 1 -- 1
; bit 2 -- 1
; bit 3 -- Default Operand Size (D)
; 0b -- 16 bits
; 1b -- 32 bits
;
; bit 4 -- 0
; bit 5-6 -- Descriptor Privilege Level (DPL)
; 00b -- Ring 0
; 01b -- Ring 1
; 10b -- Ring 2
; 11b -- Ring 3
;
; bit 7 -- Present (P)
; 0b -- No
; 1b -- Yes
mov byte[edi+5],10001110b
;dw 00000h ; (Bytes 6-7) ISR Handler High Word, bits 16-31
ror eax,16
mov word[edi+6],ax
}
///END: Setup the PIT ISR
///END: Setup the PIT ISR
///END: Setup the PIT ISR