STI doesn't work [SOLVED]
Re: STI doesn't work
This is what I would do in the following order:
1. Check the IDT and ISR handlers, check for any unwanted PUSH or POP (may affect the return address)
2. Setup a bigger stack, 12kB should be enough -> set it somewhere where BIOS/your kernel or its parts do not reside to avoid mem overwriting
3. Didn't you forget to send EOI to every PIC using ISR? e.g. IRQ0, mouse irq, floppy etc
4. Check your timer settings
5. If all else fails, open bochs debugger and execute DIV AX with AX=0 and see what happens, if it jumps to your ISR, or gives some error, or just skips the instruction.
I agree with JamesM, PEBKAC...
1. Check the IDT and ISR handlers, check for any unwanted PUSH or POP (may affect the return address)
2. Setup a bigger stack, 12kB should be enough -> set it somewhere where BIOS/your kernel or its parts do not reside to avoid mem overwriting
3. Didn't you forget to send EOI to every PIC using ISR? e.g. IRQ0, mouse irq, floppy etc
4. Check your timer settings
5. If all else fails, open bochs debugger and execute DIV AX with AX=0 and see what happens, if it jumps to your ISR, or gives some error, or just skips the instruction.
I agree with JamesM, PEBKAC...
My web site: http://inflater.wz.cz (Slovak)
Derrick operating system: http://derrick.xf.cz (Slovak and English )
Derrick operating system: http://derrick.xf.cz (Slovak and English )
Re: STI doesn't work
A typical problem of non-working ISRs. Could be many things, from non-existant IRQ-handllers, errors in interrupt descriptors, errors in ISR code, error in the iret (wrong type), and so on.
I would build a simple panic that lists segment registers and general purpose registers, and link it to GPF, TSS fault, stack fault, page fault.
I would build a simple panic that lists segment registers and general purpose registers, and link it to GPF, TSS fault, stack fault, page fault.
Re: STI doesn't work
Bochs jumps to the correct ISR exception code but it gets stuck in an infinite loop there. One question: fro my IRQ_common_stub I noticed that there iis no sti before iret, I put one there but it didn't solve the problem. I was just wondering if this sti must be there
Gizmic OS
Currently - Busy with FAT12 driver and VFS
Currently - Busy with FAT12 driver and VFS
Re: STI doesn't work
STI affects EFLAGS. IRET pops the new value of EFLAGS off the stack. Therefore your STI must be before you PUSHFD (race condition ahoy!) or you must pushfd, pop, OR in the IF flag, then PUSH again, in order to affect the post-IRET state.
Re: STI doesn't work
A possible problem might be the use of an incorrect gate in the IDT. It must be an interrupt gate, otherwise interrupts will not be disabled in the ISR code, and reentry will occur, and an infinite loop.
Re: STI doesn't work
An sti before the iret in an ISR will not have any other affect than the possibility for accepting another interrupt. The original EFLAGS will overwrite the state of the interrupt enable bit. To modify the state one needs to modify the state on the stack since EFLAGS is not at the top (EIP is).JamesM wrote:STI affects EFLAGS. IRET pops the new value of EFLAGS off the stack. Therefore your STI must be before you PUSHFD (race condition ahoy!) or you must pushfd, pop, OR in the IF flag, then PUSH again, in order to affect the post-IRET state.
Re: STI doesn't work
I send an EOI at the end of my irq_handler. So every function will get one after it has been handled
Gizmic OS
Currently - Busy with FAT12 driver and VFS
Currently - Busy with FAT12 driver and VFS
Re: STI doesn't work
You've just repeated what I said...rdos wrote:An sti before the iret in an ISR will not have any other affect than the possibility for accepting another interrupt. The original EFLAGS will overwrite the state of the interrupt enable bit. To modify the state one needs to modify the state on the stack since EFLAGS is not at the top (EIP is).JamesM wrote:STI affects EFLAGS. IRET pops the new value of EFLAGS off the stack. Therefore your STI must be before you PUSHFD (race condition ahoy!) or you must pushfd, pop, OR in the IF flag, then PUSH again, in order to affect the post-IRET state.
Re: STI doesn't work
I didn't look your code but if you don't have any code after an instruction that doesn't transfer control (jump) anywhere then your PC suppose to hang and even reboot if exception handlers are absent. Description of your problem is incomplete.System123 wrote:Yes I know I said that before hand it was working but that is because I didn't have any code after sti.
Re: STI doesn't work
Read all the posts!!
And it has other code to set up gdt and idt and isr... Etc
sti only executes after all those are set up else the cpu would triple fault.
By other code i meant like writting to the screen thats y my kernel appeared to work. Until i added a floppy driver which never gets initialised because nothin after sti is run. This is because the interrupts are not returning properly!
And it has other code to set up gdt and idt and isr... Etc
sti only executes after all those are set up else the cpu would triple fault.
By other code i meant like writting to the screen thats y my kernel appeared to work. Until i added a floppy driver which never gets initialised because nothin after sti is run. This is because the interrupts are not returning properly!
Gizmic OS
Currently - Busy with FAT12 driver and VFS
Currently - Busy with FAT12 driver and VFS
Re: STI doesn't work
Do you remove the cause of the floppy interrupt before you return from ISR? If not, the handler will simply reenter in an infinite loop. Have you isolated the problem to the floppy ISR (disable all other ISRs in the PIC/APIC)?
Re: STI doesn't work
No it has nothing to do with the floppy the keyboard or the timer. I only noticed the problem because I added a floppy driver which initialises after sti. Even if I put a printstring command there it never executes. If I do not install and IRQ's it still doesn't get passed sti even though the PIC and ISR's are set up correctly. Look at the code in kernel.pas and you will see what I mean. Any code after sti never executes, thats why I say the interupts aren't returning.
Gizmic OS
Currently - Busy with FAT12 driver and VFS
Currently - Busy with FAT12 driver and VFS
Re: STI doesn't work
We're going in circles. Post your code.
Re: STI doesn't work
Ok here is my IRQ, ISR, IDT, and KERNEL code as well as the Assembler stubs
ISR and IRQ asm stub
IRQ code
ISR code:
IDT code
Kernel Code
I hope this can help.
ISR and IRQ asm stub
Code: Select all
[BITS 32]
%macro ISR_NOERRCODE 2 ; define a macro, taking one parameter
GLOBAL %1 ; %1 accesses the first parameter.
%1:
cli
push byte 0
push byte %2
jmp isr_common_stub
%endmacro
%macro ISR_ERRCODE 2
GLOBAL %1
%1:
cli
push byte %2
jmp isr_common_stub
%endmacro
ISR_NOERRCODE isr0,0
ISR_NOERRCODE isr1,1
ISR_NOERRCODE isr2,2
ISR_NOERRCODE isr3,3
ISR_NOERRCODE isr4,4
ISR_NOERRCODE isr5,5
ISR_NOERRCODE isr6,6
ISR_NOERRCODE isr7,7
ISR_ERRCODE isr8,8
ISR_NOERRCODE isr9,9
ISR_ERRCODE isr10,10
ISR_ERRCODE isr11,11
ISR_ERRCODE isr12,12
ISR_ERRCODE isr13,13
ISR_ERRCODE isr14,14
ISR_NOERRCODE isr15,15
ISR_NOERRCODE isr16,16
ISR_NOERRCODE isr17,17
ISR_NOERRCODE isr18,18
ISR_NOERRCODE isr19,19
ISR_NOERRCODE isr20,20
ISR_NOERRCODE isr21,21
ISR_NOERRCODE isr22,22
ISR_NOERRCODE isr23,23
ISR_NOERRCODE isr24,24
ISR_NOERRCODE isr25,25
ISR_NOERRCODE isr26,26
ISR_NOERRCODE isr27,27
ISR_NOERRCODE isr28,28
ISR_NOERRCODE isr29,29
ISR_NOERRCODE isr30,30
ISR_NOERRCODE isr31,31
ISR_NOERRCODE isr32,32
[EXTERN isr_handler]
; This is our common ISR stub. It saves the processor state, sets
; up for kernel mode segments, calls the C-level fault handler,
; and finally restores the stack frame.
isr_common_stub:
pusha ; Pushes edi,esi,ebp,esp,ebx,edx,ecx,eax
mov ax, ds ; Lower 16-bits of eax = ds.
push eax ; save the data segment descriptor
mov ax, 0x10 ; load the kernel data segment descriptor
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
call isr_handler
pop eax ; reload the original data segment descriptor
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
popa ; Pops edi,esi,ebp...
add esp, 8 ; Cleans up the pushed error code and pushed ISR number
sti
iret ; pops 5 things at once: CS, EIP, EFLAGS, SS, and ESP
%macro irqmacro 2
global %1
%1:
cli
push byte 0
push byte %2
jmp irq_common_stub
%endmacro
irqmacro irq0,32 ; 32: Timer
irqmacro irq1,33 ; 33: Keyboard
irqmacro irq2,34 ; 34: ???
irqmacro irq3,35 ; 35: ???
irqmacro irq4,36 ; 36: ???
irqmacro irq5,37 ; 37: ???
irqmacro irq6,38 ; 38: ???
irqmacro irq7,39 ; 39: ???
irqmacro irq8,40 ; 40: ???
irqmacro irq9,41 ; 41: ???
irqmacro irq10,42 ; 42: ???
irqmacro irq11,43 ; 43: ???
irqmacro irq12,44 ; 44: ???
irqmacro irq13,45 ; 45: ???
irqmacro irq14,46 ; 46: ???
irqmacro irq15,47 ; 47: ???
extern irq_handler
irq_common_stub:
pusha
push ds
push es
push fs
push gs
mov ax,0x10
mov ds,ax
mov es,ax
mov fs,ax
mov gs,ax
mov eax,esp
push eax
mov eax,irq_handler
call eax
pop eax
pop gs
pop fs
pop es
pop ds
popa
add esp,8
iret
Code: Select all
unit irq;
interface
type
TIRQHandler = procedure (var r : TRegisters);
const
IRQRoutines : array[0..15] of TIRQHandler = (
nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil
);
procedure InitIRQ;stdcall;
procedure InstallIRQHandler(const IRQNo : byte; Handler : TIRQHandler);
procedure UninstallIRQHandler(const IRQNo : byte);
procedure IRQWait(IRQNo : byte);
var
IRQWaiting : boolean = false;
IRQWaiter : byte;
implementation
uses IDT, console;
procedure irq0; external name 'irq0';
procedure irq1; external name 'irq1';
procedure irq2; external name 'irq2';
procedure irq3; external name 'irq3';
procedure irq4; external name 'irq4';
procedure irq5; external name 'irq5';
procedure irq6; external name 'irq6';
procedure irq7; external name 'irq7';
procedure irq8; external name 'irq8';
procedure irq9; external name 'irq9';
procedure irq10; external name 'irq10';
procedure irq11; external name 'irq11';
procedure irq12; external name 'irq12';
procedure irq13; external name 'irq13';
procedure irq14; external name 'irq14';
procedure irq15; external name 'irq15';
procedure InstallIRQHandler(const IRQNo : byte; Handler : TIRQHandler);
begin
IRQRoutines[IRQNo] := Handler;
end;
procedure UninstallIRQHandler(const IRQNo : byte);
begin
IRQRoutines[IRQNo] := nil;
end;
procedure RemapIRQ;
begin
WritePort($20,$11);
WritePort($A0,$11);
WritePort($21,$20);
WritePort($A1,$28);
WritePort($21,$04);
WritePort($A1,$02);
WritePort($21,$01);
WritePort($A1,$01);
WritePort($21,$0);
WritePort($A1,$0);
end;
procedure InitIRQ;stdcall;[public, alias : 'initIRQ'];
begin
PrintString(#10'Remapping the Interupt Requests (IRQ)');
RemapIRQ;
PrintString(#10'Done'#10'Initialising IRQs 0 - 15');
SetIDTGate(32,PtrUInt(@irq0),$08,$8E,false); //timer
SetIDTGate(33,PtrUInt(@irq1),$08,$8E,false); //keyboard
SetIDTGate(34,PtrUInt(@irq2),$08,$8E,false);
SetIDTGate(35,PtrUInt(@irq3),$08,$8E,false);
SetIDTGate(36,PtrUInt(@irq4),$08,$8E,false);
SetIDTGate(37,PtrUInt(@irq5),$08,$8E,false);
SetIDTGate(38,PtrUInt(@irq6),$08,$8E,false);
SetIDTGate(39,PtrUInt(@irq7),$08,$8E,false);
SetIDTGate(40,PtrUInt(@irq8),$08,$8E,false);
SetIDTGate(41,PtrUInt(@irq9),$08,$8E,false);
SetIDTGate(42,PtrUInt(@irq10),$08,$8E,false);
SetIDTGate(43,PtrUInt(@irq11),$08,$8E,false);
SetIDTGate(44,PtrUInt(@irq12),$08,$8E,false);
SetIDTGate(45,PtrUInt(@irq13),$08,$8E,false);
SetIDTGate(46,PtrUInt(@irq14),$08,$8E,false);
SetIDTGate(47,PtrUInt(@irq15),$08,$8E,false);
PrintString(#10'Done');
end;
procedure IRQWait(IRQNo : byte);
begin
IRQWaiter := IRQNo;
IRQWaiting := true;
while IRQWaiting = true do;
end;
procedure IrqHandler(var r : TRegisters); cdecl; [public, alias: 'irq_handler'];
var
Handler : TIrqHandler = nil;
begin
Handler := IrqRoutines[r.InterruptNumber-32];
if (IRQWaiting = true) and (IRQWaiter = (r.InterruptNumber-32)) then
IRQWaiting := false;
if Assigned(Handler) then
Handler(r);
if r.InterruptNumber >= 40 then
WritePort($A0,$20);
WritePort($20,$20);
end;
end.
Code: Select all
unit isr;
interface
procedure InitISR;stdcall;
implementation
uses idt, console;
const
ExceptionMessages: array [0..31] of String = (
'Division By Zero',
'Debug',
'Non Maskable Interrupt',
'Breakpoint',
'Into Detected Overflow',
'Out of Bounds',
'Invalid Opcode',
'No Coprocessor',
'Double Fault',
'Coprocessor Segment Overrun',
'Bad TSS',
'Segment Not Present',
'Stack Fault',
'General Protection Fault',
'Page Fault',
'Unknown Interrupt',
'Coprocessor Fault',
'Alignment Check',
'Machine Check',
'Reserved',
'Reserved',
'Reserved',
'Reserved',
'Reserved',
'Reserved',
'Reserved',
'Reserved',
'Reserved',
'Reserved',
'Reserved',
'Reserved',
'Reserved'
);
procedure isr0; external name 'isr0';
procedure isr1; external name 'isr1';
procedure isr2; external name 'isr2';
procedure isr3; external name 'isr3';
procedure isr4; external name 'isr4';
procedure isr5; external name 'isr5';
procedure isr6; external name 'isr6';
procedure isr7; external name 'isr7';
procedure isr8; external name 'isr8';
procedure isr9; external name 'isr9';
procedure isr10; external name 'isr10';
procedure isr11; external name 'isr11';
procedure isr12; external name 'isr12';
procedure isr13; external name 'isr13';
procedure isr14; external name 'isr14';
procedure isr15; external name 'isr15';
procedure isr16; external name 'isr16';
procedure isr17; external name 'isr17';
procedure isr18; external name 'isr18';
procedure isr19; external name 'isr19';
procedure isr20; external name 'isr20';
procedure isr21; external name 'isr21';
procedure isr22; external name 'isr22';
procedure isr23; external name 'isr23';
procedure isr24; external name 'isr24';
procedure isr25; external name 'isr25';
procedure isr26; external name 'isr26';
procedure isr27; external name 'isr27';
procedure isr28; external name 'isr28';
procedure isr29; external name 'isr29';
procedure isr30; external name 'isr30';
procedure isr31; external name 'isr31';
procedure InitISR; stdcall;[public, alias: 'initISR'];
begin
// PrintString(#10'Initalising Interupt Service Requests (ISR)');
SetIDTGate(0,PtrUInt(@isr0),$08,$8E,false);
SetIDTGate(1,PtrUInt(@isr1),$08,$8E,false);
SetIDTGate(2,PtrUInt(@isr2),$08,$8E,false);
SetIDTGate(3,PtrUInt(@isr3),$08,$8E,false);
SetIDTGate(4,PtrUInt(@isr4),$08,$8E,false);
SetIDTGate(5,PtrUInt(@isr5),$08,$8E,false);
SetIDTGate(6,PtrUInt(@isr6),$08,$8E,false);
SetIDTGate(7,PtrUInt(@isr7),$08,$8E,false);
SetIDTGate(8,PtrUInt(@isr8),$08,$8E,false);
SetIDTGate(9,PtrUInt(@isr9),$08,$8E,false);
SetIDTGate(10,PtrUInt(@isr10),$08,$8E,false);
SetIDTGate(11,PtrUInt(@isr11),$08,$8E,false);
SetIDTGate(12,PtrUInt(@isr12),$08,$8E,false);
SetIDTGate(13,PtrUInt(@isr13),$08,$8E,false);
SetIDTGate(14,PtrUInt(@isr14),$08,$8E,false);
SetIDTGate(15,PtrUInt(@isr15),$08,$8E,false);
SetIDTGate(16,PtrUInt(@isr16),$08,$8E,false);
SetIDTGate(17,PtrUInt(@isr17),$08,$8E,false);
SetIDTGate(18,PtrUInt(@isr18),$08,$8E,false);
SetIDTGate(19,PtrUInt(@isr19),$08,$8E,false);
SetIDTGate(20,PtrUInt(@isr20),$08,$8E,false);
SetIDTGate(21,PtrUInt(@isr21),$08,$8E,false);
SetIDTGate(22,PtrUInt(@isr22),$08,$8E,false);
SetIDTGate(23,PtrUInt(@isr23),$08,$8E,false);
SetIDTGate(24,PtrUInt(@isr24),$08,$8E,false);
SetIDTGate(25,PtrUInt(@isr25),$08,$8E,false);
SetIDTGate(26,PtrUInt(@isr26),$08,$8E,false);
SetIDTGate(27,PtrUInt(@isr27),$08,$8E,false);
SetIDTGate(28,PtrUInt(@isr28),$08,$8E,false);
SetIDTGate(29,PtrUInt(@isr29),$08,$8E,false);
SetIDTGate(30,PtrUInt(@isr30),$08,$8E,false);
SetIDTGate(31,PtrUInt(@isr31),$08,$8E,false);
// PrintString(#10'Done');
end;
procedure ISR_Handler(var r: TRegisters); cdecl; [public, alias: 'isr_handler'];
var
s : string;
begin
if r.InterruptNumber < 32 then begin
SetTextColor(clBlack,clRed);
PrintChar(#10);
PrintString(ExceptionMessages[r.InterruptNumber]);
PrintString(' Exception');
with r do begin
Str(ErrorCode, s);
PrintString(#10'Error code = ');PrintString(s);
PrintString(#10'EAX'#9'= $');PrintString(HexStr(eax,8));
PrintString(#10'EBX'#9'= $');PrintString(HexStr(ebx,8));
PrintString(#10'ECX'#9'= $');PrintString(HexStr(ecx,8));
PrintString(#10'EDX'#9'= $');PrintString(HexStr(edx,8));
PrintString(#10'ESI'#9'= $');PrintString(HexStr(esi,8));
PrintString(#10'EDI'#9'= $');PrintString(HexStr(edi,8));
PrintString(#10'ESP'#9'= $');PrintString(HexStr(esp,8));
PrintString(#10'EBP'#9'= $');PrintString(HexStr(ebp,8));
PrintString(#10'CS'#9'= $');PrintString(HexStr(cs,8));
PrintString(#10'DS'#9'= $');PrintString(HexStr(ds,8));
PrintString(#10'ES'#9'= $');PrintString(HexStr(es,8));
PrintString(#10'FS'#9'= $');PrintString(HexStr(fs,8));
PrintString(#10'GS'#9'= $');PrintString(HexStr(gs,8));
PrintString(#10'SS'#9'= $');PrintString(HexStr(ss,8));
PrintString(#10'EIP'#9'= $');PrintString(HexStr(eip,8));
PrintString(#10'EFLAGS'#9'= $');PrintString(HexStr(eflags,8));
PrintString(#10'User ESP'#9'= $');PrintString(HexStr(UserESP,8));
end;
SetTextColor(clBlack,clWhite);
PrintChar(#10);
while true do ;
end;
end;
end.
Code: Select all
unit idt;
interface
type
TIDTEntry = packed record
BaseLow : word;
SegSel : word;
Always0 : byte;
Flags : byte;
BaseHigh : word;
end;
TIDTPtr = packed record
limit : word;
base : LongWord;
end;
var
IDTPtr : TIDTPtr;
IDTTables : array[0..255] of TIDTEntry;
procedure SetIDTGate(idx: Byte; base: LongWord; SSelect: Word; flg: Byte; UserMode : boolean);
procedure initIDT;stdcall;
implementation
uses console;
procedure FlushIDT; assembler; nostackframe;
asm
lidt IDTPtr
end;
procedure SetIDTGate(idx: Byte; base: LongWord; SSelect: Word; flg: Byte; UserMode : boolean);
begin
with IDTTables[idx] do
begin
BaseLow := base and $FFFF;
BaseHigh := (base shr 16) and $FFFF;
SegSel := SSelect;
Always0 := 0;
if UserMode = true then
Flags := flg or $60
else
Flags := flg;
end;
end;
procedure initIDT;stdcall;[public, alias: 'initIDT'];
begin
//PrintString(#10'Initialising the Interupt Descriptor Table (IDT)');
IDTPtr.limit := SizeOf(IDTTables)-1;
IDTPtr.base := PtrUInt(@IDTTables);
FillByte(IDTTables,SizeOf(IDTTables),0);
FlushIDT;
//PrintString(#10'Done');
end;
end.
Code: Select all
unit kernel;
interface
procedure kmain; stdcall;
implementation
uses console, idt, gdt, isr, irq, pit, keyboard, paging{, heap, DMA, Sound}, Floppy {,ConsoleEXP};
Const
kHeader = 'GIZMIC OS v0.01';
kHeaderBg = clBlue;
kHeaderFg = clWhite;
procedure kmain; stdcall;[public, alias: 'kmain'];
var
sTemp : string;
i, x : byte;
begin
initScreen;
SetTextColor(clBlack,clLightGreen);
initGDT;
initIDT;
initISR;
initIRQ;
initTimer(100);
initKeyboard;
initPaging(1000000);
PrintString('STI - Start');
asm
sti
end;
PrintString(#10'STI - done');
//dmainit;
//initFloppy;
SetTextColor(clBlack,clWhite);
ClearScreen;
GoToXY(0,0);
SetTextColor(clBlue,clWhite);
PrintString(kHeader + #10);
SetTextColor(clBlack,clWhite);
SetHeader(true);
{i := 0;
x := 122323 div i; }
while true do ;
end;
end.
Gizmic OS
Currently - Busy with FAT12 driver and VFS
Currently - Busy with FAT12 driver and VFS
Re: STI doesn't work
Code: Select all
%macro ISR_NOERRCODE 2 ; define a macro, taking one parameter
GLOBAL %1 ; %1 accesses the first parameter.
%1:
cli
push byte 0
push byte %2
jmp isr_common_stub
%endmacro
Code: Select all
; This is our common ISR stub. It saves the processor state, sets
; up for kernel mode segments, calls the C-level fault handler,
; and finally restores the stack frame.
isr_common_stub:
pusha ; Pushes edi,esi,ebp,esp,ebx,edx,ecx,eax
Code: Select all
popa ; Pops edi,esi,ebp...
add esp, 8 ; Cleans up the pushed error code and pushed ISR number
sti
iret ; pops 5 things at once: CS, EIP, EFLAGS, SS, and ESP