OSDev.org

The Place to Start for Operating System Developers
It is currently Thu Apr 25, 2024 6:55 pm

All times are UTC - 6 hours




Post new topic Reply to topic  [ 7 posts ] 
Author Message
 Post subject: IDT / interrrupts / Keyboard
PostPosted: Sat Apr 18, 2015 12:50 am 
Offline

Joined: Wed Dec 17, 2014 12:43 pm
Posts: 11
I cannot seem to wrap my head around this, the unhandled_int gets called but the keyboard handler causes a triple-fault.
Could anyone guide me to what goes wrong and why?

Code:
[bits 16]         
[org 0x7c00]

;- flush segments + set stack
   cli   
   xor ax, ax
   mov ds, ax
   mov es, ax
   mov fs, ax
   mov gs, ax
   mov ss, ax
   mov sp, 0x9c00

   jmp 0:start      

start:
;- init video
   mov ax, 0003h      ; subroutine 00, mode 03
   int 10h
   
;-  quick enable a20
enable_a20_fv:
   in al, 92h
   or al, 2
   out 92h, al
   
   cli
   lgdt [gdtr]
   lidt [idtr]

   mov eax, cr0
   or al, 1         ; enable paging / PE-bit
   mov cr0, eax

   jmp gdt.code:main

[bits 32]
main:
   mov eax, gdt.data
   mov ds, ax
   mov es, ax

   call pic_remap
   int 3h

   jmp $

;    FUNCTIONS

read_keyboard:
   pusha
   cli
   in al,64h        ; read status
   test al,01h      ;
    jz read_keyboard
    in al,60h        ; read scancode
    mov bx, ax
    mov al, [bx+keymap]
    ;mov [key], al
    mov [es:0xb8000], al
    mov al,0x20      ; clear irq-buffer
   out 0x20, al
   sti
   popa
    iret

unhandled_int:
   pusha
   
    mov byte [es:0xb8000], '*'

   popa
   iret

pic_remap:
    cli
   
    mov  al,0x11                           ; put both 8259s in init mode
   out  0x20,al
   out  0xA0,al

   mov  al,0x20                           ; remap pic irq0-irq7 -> int 0x20-27
   out  0x21,al

   mov  al,0x28
   out  0xA1,al                           ; remap pic irq8-irq15 -> int 0x28-30

   mov  al,4                                         ; icw3 pic1(master)
   out  0x21,al                                      ; bit 2=1: irq2 is the slave

   mov  al,2                                         ; icw3 pic2
   out  0xA1,al                                      ; bit 1=1: slave id is 2

   mov  al,1                                         ; icw4 to both controllers
   out  0x21,al                                      ; bit 0=1: 8086 mode
   out  0xA1,al
       
    cli
    mov  al,255                                       ; mask all irqs
    out  0xa1,al
    out  0x21,al
    ret


;    DATA SECTION

int_msg db 'unhandled interrrupt', 0

key    db 0
keymap:
        db    0, 0, '1','2','3','4','5','6','7','8','9','0','-','=',
        db    0, 0, 'q','w','e','r','t','y','u','i','o','p','[',']',
        db    0, 0, 'a','s','d','f','g','h','j','k','l',';',"'",'`',
        db    0,'/','z','x','c','v','b','n','m','7','8','9',',','.',
        db    0, '*'

; global descriptor tables
;--------------------------------------
gdt:
.null   equ $-gdt       ; 0x0       
      dq 0
.code    equ $-gdt       ; 0x8
      dw 0ffffh      ; limit 4 Gib
      dw 0000h         ; base 1-2
      db 0           ; base 3
      db 10011010b   ; type
      db 11001111b   ; flags
      db 0          ; base 4

.data    equ $-gdt        ; 0x10
      dw 0ffffh      ; limit 4 Gib
      dw 0000h      ; base 1-2   
      db 0           ; base 3
      db 10010010b   ; type
      db 11001111b   ; flags
      db 0          ; base 4
gdt_end:
gdtr:
      dw gdt_end - gdt    ; size
      dd gdt              ; base address

idt:
; int 0 - divide error
      dw unhandled_int
      dw gdt.code
      db 0
      db 10001110b
      dw 0

; int 1 - debug exception
      dw unhandled_int
      dw gdt.code
      db 0
      db 10001110b
      dw 0
; int 2 - intel reserved
      dw unhandled_int
      dw gdt.code
      db 0
      db 10001110b
      dw 0
; int 3 - breakpoint
      dw unhandled_int
      dw gdt.code
      db 0
      db 10001110b
      dw 0
; int 4 - overflow
      dw unhandled_int
      dw gdt.code
      db 0
      db 10001110b
      dw 0
; int 5 - bounds check
      dw unhandled_int
      dw gdt.code
      db 0
      db 10001110b
      dw 0
; int 6 - invalid opcode
      dw unhandled_int
      dw gdt.code
      db 0
      db 10001110b
      dw 0
; int 7 - coprocessor not available
      dw unhandled_int
      dw gdt.code
      db 0
      db 10001110b
      dw 0
; int 8 - double fault
      dw unhandled_int
      dw gdt.code
      db 0
      db 10001110b
      dw 0
; int 9 - coprocessor segment overrun
      dw unhandled_int
      dw gdt.code
      db 0
      db 10001110b
      dw 0
; int A - invalid tss
      dw unhandled_int
      dw gdt.code
      db 0
      db 10001110b
      dw 0
; int B - segment not present
      dw unhandled_int
      dw gdt.code
      db 0
      db 10001110b
      dw 0
; int C - stack exception
      dw unhandled_int
      dw gdt.code
      db 0
      db 10001110b
      dw 0
; int D - triple fault
      dw unhandled_int
      dw gdt.code
      db 0
      db 10001110b
      dw 0
; int E - page fault
      dw unhandled_int
      dw gdt.code
      db 0
      db 10001110b
      dw 0
; int F - intel reserved
      dw unhandled_int
      dw gdt.code
      db 0
      db 10001110b
      dw 0
; int 10 - stack exception
      dw unhandled_int
      dw gdt.code
      db 0
      db 10001110b
      dw 0
; int 11 - reserved
      dw unhandled_int
      dw gdt.code
      db 0
      db 10001110b
      dw 0
; int 12 - reserved
      dw unhandled_int
      dw gdt.code
      db 0
      db 10001110b
      dw 0
; int 13 - reserved
      dw unhandled_int
      dw gdt.code
      db 0
      db 10001110b
      dw 0
; int 14 - reserved
      dw unhandled_int
      dw gdt.code
      db 0
      db 10001110b
      dw 0
; int 15 - reserved
      dw unhandled_int
      dw gdt.code
      db 0
      db 10001110b
      dw 0
; int 16 - reserved
      dw unhandled_int
      dw gdt.code
      db 0
      db 10001110b
      dw 0
; int 17 - reserved
      dw unhandled_int
      dw gdt.code
      db 0
      db 10001110b
      dw 0
; int 18 - reserved
      dw unhandled_int
      dw gdt.code
      db 0
      db 10001110b
      dw 0
; int 19 - reserved
      dw unhandled_int
      dw gdt.code
      db 0
      db 10001110b
      dw 0
; int 20 - reserved
      dw unhandled_int
      dw gdt.code
      db 0
      db 10001110b
      dw 0
; int 21 - keyboard
      dw read_keyboard
      dw gdt.code
      db 0
      db 10001110b
      dw 0
idt_end:
idtr:
        dw idt_end - idt - 1
        dd idt

times  510 - ($-$$) db 0

bios_signature:
db 55h
db 0AAh   


Top
 Profile  
 
 Post subject: Re: IDT / interrrupts / Keyboard
PostPosted: Sat Apr 18, 2015 1:38 am 
Offline
Member
Member
User avatar

Joined: Sat Mar 31, 2012 3:07 am
Posts: 4597
Location: Chichester, UK
At a quick glance:

1. You mask all hardware interrupts.
2. You never do a "sti".
3. You don't set SS.

I'm sure there are many more points of interest. So I don't see how any interrupts fire in the first place.

Whatever, a triple fault almost always means multiple page faults or general protection faults. I'd suggest that you write rudimentary handlers for these two exceptions which stop the processor and display some indication of which fault it is and perhaps the value of the instruction pointer. That way you know where to look. Mind, with an invalid stack, which seems to be the case, you are still going to get a triple fault.


Top
 Profile  
 
 Post subject: Re: IDT / interrrupts / Keyboard
PostPosted: Sat Apr 18, 2015 4:01 am 
Offline
Member
Member

Joined: Thu Sep 20, 2012 5:11 am
Posts: 69
Location: germany hamburg
Hello.
Within a keyboard ISR the read status is not needed, because it only execute, if the keyboard have data in its output buffer and otherwise no interupt is generated:
Code:
in al,64h ; read status
test al,01h
jz read_keyboard

Dirk


Top
 Profile  
 
 Post subject: Re: IDT / interrrupts / Keyboard
PostPosted: Sat Apr 18, 2015 5:00 am 
Offline

Joined: Wed Dec 17, 2014 12:43 pm
Posts: 11
Tried to make some changes, if I understood you correct iansjack.
if I point any of int 0 - 19h to sys_talk (prints) or read_keyboard (doesnt seem to read or write, just blank) they fire, but 20h or above triggers the triple-fault. Is the problem in irq-remapping code? It's stolen so... As I said I can't really get my head around this.
How do you get debug-output to the console with qemu (linux)?

Code:
[bits 16]            ; real-mode
[org 0x7c00]

;- flush segments + set stack
   cli   
   xor ax, ax
   mov ds, ax
   mov es, ax
   mov fs, ax
   mov gs, ax
   ;mov ss, ax
   ;mov sp, 0x9c00

   jmp 0:start      

start:
;- init video
   mov ax, 0003h      ; subroutine 00, mode 03
   int 10h
   
;-  quick enable a20
enable_a20_fv:
   in al, 92h
   or al, 2
   out 92h, al
   
   cli
   lgdt [gdtr]
   lidt [idtr]

   mov eax, cr0
   or al, 1         ; enable paging / PE-bit
   mov cr0, eax

   jmp gdt.code:main

[bits 32]
main:
   mov eax, gdt.data
   mov ds, ax
   mov es, ax
   sti

        pic_remap
   int 21h

   jmp $

;    FUNCTIONS

read_keyboard:
   pusha
   cli
   ;in al,64h        ; read status
   ;test al,01h      ;
    ;jz read_keyboard
    in al,60h        ; read scancode
    mov bx, ax
    mov al, [bx+keymap]
    ;mov [key], al
    mov [es:0xb8000], al
    mov al,0x20      ; clear irq-buffer
   out 0x20, al
   sti
   popa
    iret

unhandled_int:
   pusha
   
    mov byte [es:0xb8000], '*'
    hlt
   popa
   iret

sys_talk:
   pusha
   
    mov byte [es:0xb8000], '!'
    hlt
   popa
   iret


triple_fault_handler:
   pusha
     
    mov byte [es:0xb8000], 'T'
    hlt
   popa
   iret

page_fault_handler:
   pusha
     
    mov byte [es:0xb8000], 'P'
    hlt
   popa
   iret

nmi_handler:
   pusha
     
    mov byte [es:0xb8000], 'N'
    hlt
   popa
   iret

pic_remap:
    cli
   
    mov  al,0x11                           ; put both 8259s in init mode
   out  0x20,al
   out  0xA0,al

   mov  al,0x20                           ; remap pic irq0-irq7 -> int 0x20-27
   out  0x21,al

   ;mov  al,0x28
   ;out  0xA1,al                           ; remap pic irq8-irq15 -> int 0x28-30

   mov  al,4                                         ; icw3 pic1(master)
   out  0x21,al                                      ; bit 2=1: irq2 is the slave

   mov  al,2                                         ; icw3 pic2
   out  0xA1,al                                      ; bit 1=1: slave id is 2

   mov  al,1                                         ; icw4 to both controllers
   out  0x21,al                                      ; bit 0=1: 8086 mode
   out  0xA1,al
       
    mov  al,21                             ; mask irqs
    out  0xa1,al
    out  0x21,al
    sti
    ret

;    DATA SECTION
keymap:
        db    0, 0, '1','2','3','4','5','6','7','8','9','0','-','=',
        db    0, 0, 'q','w','e','r','t','y','u','i','o','p','[',']',
        db    0, 0, 'a','s','d','f','g','h','j','k','l',';',"'",'`',
        db    0,'/','z','x','c','v','b','n','m','7','8','9',',','.',
        db    0, '*'

; global descriptor tables
;--------------------------------------
gdt:
.null   equ $-gdt       ; 0x0       
      dq 0
.code    equ $-gdt       ; 0x8
      dw 0ffffh      ; limit 4 Gib
      dw 0000h         ; base 1-2
      db 0           ; base 3
      db 10011010b   ; type
      db 11001111b   ; flags
      db 0          ; base 4

.data    equ $-gdt        ; 0x10
      dw 0ffffh      ; limit 4 Gib
      dw 0000h      ; base 1-2   
      db 0           ; base 3
      db 10010010b   ; type
      db 11001111b   ; flags
      db 0          ; base 4
gdt_end:
gdtr:
      dw gdt_end - gdt -1   ; size
      dd gdt              ; base address

idt:
; int 0 - divide error
      dw unhandled_int
      dw gdt.code
      db 0
      db 10001110b
      dw 0

; int 1 - debug exception
      dw unhandled_int
      dw gdt.code
      db 0
      db 10001110b
      dw 0
; int 2 - intel reserved
      dw nmi_handler
      dw gdt.code
      db 0
      db 10001110b
      dw 0
; int 3 - breakpoint
      dw unhandled_int
      dw gdt.code
      db 0
      db 10001110b
      dw 0
; int 4 - overflow
      dw unhandled_int
      dw gdt.code
      db 0
      db 10001110b
      dw 0
; int 5 - bounds check
      dw unhandled_int
      dw gdt.code
      db 0
      db 10001110b
      dw 0
; int 6 - invalid opcode
      dw unhandled_int
      dw gdt.code
      db 0
      db 10001110b
      dw 0
; int 7 - coprocessor not available
      dw unhandled_int
      dw gdt.code
      db 0
      db 10001110b
      dw 0
; int 8 - double fault
      dw unhandled_int
      dw gdt.code
      db 0
      db 10001110b
      dw 0
; int 9 - coprocessor segment overrun
      dw unhandled_int
      dw gdt.code
      db 0
      db 10001110b
      dw 0
; int A - invalid tss
      dw unhandled_int
      dw gdt.code
      db 0
      db 10001110b
      dw 0
; int B - segment not present
      dw unhandled_int
      dw gdt.code
      db 0
      db 10001110b
      dw 0
; int C - stack exception
      dw unhandled_int
      dw gdt.code
      db 0
      db 10001110b
      dw 0
; int D - triple fault
      dw triple_fault_handler
      dw gdt.code
      db 0
      db 10001110b
      dw 0
; int E - page fault
      dw page_fault_handler
      dw gdt.code
      db 0
      db 10001110b
      dw 0
; int F - intel reserved
      dw unhandled_int
      dw gdt.code
      db 0
      db 10001110b
      dw 0
; int 10 - stack exception
      dw unhandled_int
      dw gdt.code
      db 0
      db 10001110b
      dw 0
; int 11 - reserved
      dw unhandled_int
      dw gdt.code
      db 0
      db 10001110b
      dw 0
; int 12 - reserved
      dw unhandled_int
      dw gdt.code
      db 0
      db 10001110b
      dw 0
; int 13 - reserved
      dw unhandled_int
      dw gdt.code
      db 0
      db 10001110b
      dw 0
; int 14 - reserved
      dw unhandled_int
      dw gdt.code
      db 0
      db 10001110b
      dw 0
; int 15 - reserved
      dw unhandled_int
      dw gdt.code
      db 0
      db 10001110b
      dw 0
; int 16 - reserved
      dw unhandled_int
      dw gdt.code
      db 0
      db 10001110b
      dw 0
; int 17 - reserved
      dw unhandled_int
      dw gdt.code
      db 0
      db 10001110b
      dw 0
; int 18 - reserved
      dw unhandled_int
      dw gdt.code
      db 0
      db 10001110b
      dw 0
; int 19 - reserved
      dw sys_talk
      dw gdt.code
      db 0
      db 10001110b
      dw 0
; int 20 / irq 0 -reserved
      dw unhandled_int
      dw gdt.code
      db 0
      db 10001110b
      dw 0
; int 21 / irq 1 - keyboard
      dw read_keyboard
      dw gdt.code
      db 0
      db 10001110b
      dw 0
;int 22 /irq 2 - sys_talk
;      dw sys_talk
;      dw gdt.code
;      db 0
;      db 10001110b
;      dw 0

;int 23 /irq 2 - sys_talk
;      dw sys_talk
;      dw gdt.code
;      db 0
;      db 10001110b
;      dw 0
;int 24 /irq 2 - sys_talk
;      dw sys_talk
;      dw gdt.code
;      db 0
;      db 10001110b
;      dw 0
;int 25 /irq 2 - sys_talk
;      dw sys_talk
;      dw gdt.code
;      db 0
;      db 10001110b
;      dw 0
;int 26 /irq 2 - sys_talk
;      dw sys_talk
;      dw gdt.code
;      db 0
;      db 10001110b
;      dw 0
;int 28 /irq 2 - sys_talk
;      dw sys_talk
;      dw gdt.code
;      db 0
;      db 10001110b
;      dw 0
;int 29 /irq 2 - sys_talk
;      dw sys_talk
;      dw gdt.code
;      db 0
;      db 10001110b
;      dw 0
;int 30 /irq 2 - sys_talk
;      dw sys_talk
;      dw gdt.code
;      db 0
;      db 10001110b
;      dw 0

idt_end:
idtr:
        dw idt_end - idt -1
        dd idt

times  510 - ($-$$) db 0

bios_signature:
db 55h
db 0AAh   


Top
 Profile  
 
 Post subject: Re: IDT / interrrupts / Keyboard
PostPosted: Sat Apr 18, 2015 8:25 am 
Offline
Member
Member
User avatar

Joined: Sat Mar 31, 2012 3:07 am
Posts: 4597
Location: Chichester, UK
Printing to the screen is fairly easy. Converting a hex number in a register is fairly easy. So it's not difficult to write a routine to print the contents of a register to the screen; you can incorporate that in an exception handler. But it won't help if the problem is a faulty stack as the exception handler will never get called.

I would suggest that you take this chance to learn how to use gdb in conjunction with qemu; then you can single-step through your code and/or set breakpoints to see exactly what is happening. Pay particular attention to the stack.

(Disclaimer: other debugging environments are available. Many like Bochs; my favourite for this sort of thing is SimNow.)


Top
 Profile  
 
 Post subject: Re: IDT / interrrupts / Keyboard
PostPosted: Tue Apr 21, 2015 4:59 am 
Offline

Joined: Wed Dec 17, 2014 12:43 pm
Posts: 11
seems like the idtr doesn't get loaded properly (virtualbox logs ldtr={0000 base=00000000 limit=0000ffff flags=00000082}) and I don't a single clue why.

Code:
[bits 16]
[org 0x1000]
   mov ax, cs
   mov ds, ax

   mov ax, 0xb800
   mov gs, ax

    mov di, 6
   mov byte [gs:di], "4"
   
   cli

   lgdt [gdtr]
   lidt [idtr]

   mov eax, cr0
   or al, 1
   mov cr0, eax

   jmp gdt.code:entry

[bits 32]
entry:
   mov eax, gdt.data
   mov ds, ax
   mov es, ax

   sti

   call pic_remap
   call unmask_irq

   mov byte [es:0xb8008], "5"

   int 21h
   jmp $   

idtr:
        dw idt_end - idt -1 ; size
        dd idt             ; base address
gdtr:
      dw gdt_end - gdt -1   ; size
      dd gdt              ; base address

%include "idt.inc"
%include "gdt.inc"


Top
 Profile  
 
 Post subject: Re: IDT / interrrupts / Keyboard
PostPosted: Tue Apr 21, 2015 6:45 am 
Offline

Joined: Wed Dec 17, 2014 12:43 pm
Posts: 11
now irq7 fires instead of irq1 (keyboard), made a dummy handler for irq7 (read brendan's thread) but still
Code:
pic_remap:
    mov al, 0x11        ; put both 8259s in init mode
    out 0x20, al
    out 0xA0, al
    mov al, 0x20        ; IRQ0-IRQ7 -> int 0x20-27
    out 0x21, al
    mov al, 0x28
    out 0xA1, al        ; IRQ8-IRQ15 -> int 0x28-30
    mov al, 4
    out 0x21, al
    mov al, 2
    out 0xA1, al
    mov al, 1
    out 0x21, al
    out 0xA1, al

; testing
unmask_irq:
    mov al, 0xfd
    out 0x21, al
    mov al, 0xff
    out 0xa1, al
   
    sti
    ret   

...

wtf:
    iret

; int 21 / irq 1 - keyboard
      dw read_keyboard
      dw gdt.code
      db 0
      db 10001110b
      dw 0
;int 22 /irq 2
      dw sys_talk
      dw gdt.code
      db 0
      db 10001110b
      dw 0
;int 23 /irq 3
      dw sys_talk
      dw gdt.code
      db 0
      db 10001110b
      dw 0
;int 24 /irq 4
      dw sys_talk
      dw gdt.code
      db 0
      db 10001110b
      dw 0
;int 25 /irq 5
      dw sys_talk
      dw gdt.code
      db 0
      db 10001110b
      dw 0
;int 26 /irq 6
      dw sys_talk
      dw gdt.code
      db 0
      db 10001110b
      dw 0
;int 27 /irq 7
      dw wtf
      dw gdt.code
      db 0
      db 10001110b
      dw 0

....



Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 7 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: Google [Bot] and 97 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group