PIT protected handles interrupts more correctly

This commit is contained in:
Ciro Santilli
2015-11-10 16:52:46 +01:00
parent 881300bd22
commit 1e87cda4c0
4 changed files with 90 additions and 48 deletions

View File

@@ -1,5 +1,8 @@
# TODO
-
http://stackoverflow.com/questions/1858640/how-can-i-create-a-sleep-function-in-16bit-masm-assembly-x86
- cache:
- http://stackoverflow.com/questions/1756825/how-can-i-do-a-cpu-cache-flush
@@ -101,10 +104,13 @@
- keyboard through interrupt (high level BIOS int 16 that waits for input done)
Almost there! pit_protected almost works, the problem is that it only fires once: <http://board.flatassembler.net/topic.php?t=17437>
Needs some resetting fixed it seems.
- happens on IRQ 1 as mentioned at: https://en.wikipedia.org/wiki/Interrupt_request_%28PC_architecture%29#Master_PIC
- keyboard protected mode: http://stackoverflow.com/questions/219120/x86-assembly-protected-mode-keyboard-access
- oszur does it with the i8042: http://stackoverflow.com/questions/22744624/keyboard-interrupt-handler-for-own-kernel-c
- https://github.com/arjun024/mkeykernel contains a small example that is easy to dissect
- happens on IRQ 1 as mentioned at: https://en.wikipedia.org/wiki/Interrupt_request_%28PC_architecture%29#Master_PIC
- mouse

View File

@@ -34,7 +34,7 @@ http://stackoverflow.com/questions/19776992/gas-altmacro-macro-with-a-percent-si
/* Helpers */
/* Push regiesters ax, bx, cx and dx. Lightweight `pusha`. */
/* Push registers ax, bx, cx and dx. Lightweight `pusha`. */
.macro PUSH_ADX
push %ax
push %bx
@@ -370,6 +370,61 @@ idt_descriptor:
pop %eax
.endm
/* Shamelessly copied from James Molloy's tutorial. */
.macro ISR_NOERRCODE i
isr\()\i:
cli
push $0
push $\i
jmp interrupt_handler
.endm
.macro ISR_ERRCODE i
isr\()\i:
cli
push $\i
jmp interrupt_handler
.endm
/*
Entries and handlers.
48 = 32 processor built-ins + 16 PIC interrupts.
*/
.macro IDT_48_ENTRIES
IDT_START
.rept 48
IDT_ENTRY
.endr
IDT_END
.irp i, 0, 1, 2, 3, 4, 5, 6, 7
ISR_NOERRCODE \i
.endr
ISR_ERRCODE 8
ISR_NOERRCODE 9
.irp i, 10, 11, 12, 13, 14
ISR_ERRCODE \i
.endr
.irp i, 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
ISR_NOERRCODE \i
.endr
.endm
.macro IDT_SETUP_48_ISRS
.irp i, 0, 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, \
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
IDT_SETUP_ENTRY $\i, $isr\()\i
.endr
lidt idt_descriptor
.endm
/* BIOS */
.macro CURSOR_POSITION x=$0, y=$0
@@ -654,6 +709,23 @@ end:
OUTB PIC_CMD_RESET, PORT_PIC_MASTER_CMD
.endm
.macro REMAP_PIC_32
/*
Remap the PIC interrupts to start at 32.
TODO understand.
*/
OUTB $0x11, PORT_PIC_MASTER_CMD
OUTB $0x11, PORT_PIC_SLAVE_CMD
OUTB $0x20, PORT_PIC_MASTER_DATA
OUTB $0x28, PORT_PIC_SLAVE_DATA
OUTB $0x04, PORT_PIC_MASTER_DATA
OUTB $0x02, PORT_PIC_SLAVE_DATA
OUTB $0x01, PORT_PIC_MASTER_DATA
OUTB $0x01, PORT_PIC_SLAVE_DATA
OUTB $0x00, PORT_PIC_MASTER_DATA
OUTB $0x00, PORT_PIC_SLAVE_DATA
.endm
/* PIT */
/*

View File

@@ -19,7 +19,7 @@ BEGIN
CLEAR
STAGE2
PROTECTED_MODE
IDT_SETUP_ENTRY $14, $handler
IDT_SETUP_ENTRY $14, $interrupt_handler
lidt idt_descriptor
SETUP_PAGING_4M
@@ -39,7 +39,7 @@ IDT_START
IDT_SKIP 14
IDT_ENTRY
IDT_END
handler:
interrupt_handler:
VGA_PRINT_STRING $message
/*
Mandatory because page faults push the error code to the stack.

View File

@@ -1,14 +1,5 @@
/*
# PIT protected mode
Unlike in real mode, for the protected mode to work well,
we have to setup the IDT properly.
TODO why? More maskable interrupts seem to be generated here by the PIC.
This handles all interrupts.
This is not very generic, because we don't know which interrupt number we are handling,
and cannot take the stack pushed error byte into account.
But it works for a very simple example.
*/
#include "common.h"
@@ -16,45 +7,18 @@ BEGIN
STAGE2
CLEAR
PROTECTED_MODE
mov $47, %ecx
setup_idt:
IDT_SETUP_ENTRY <%ecx>, $handler
loop setup_idt
lidt idt_descriptor
/*
Remap the PIC interrupts to start at 32.
TODO understand.
*/
OUTB $0x11, PORT_PIC_MASTER_CMD
OUTB $0x11, PORT_PIC_SLAVE_CMD
OUTB $0x20, PORT_PIC_MASTER_DATA
OUTB $0x28, PORT_PIC_SLAVE_DATA
OUTB $0x04, PORT_PIC_MASTER_DATA
OUTB $0x02, PORT_PIC_SLAVE_DATA
OUTB $0x01, PORT_PIC_MASTER_DATA
OUTB $0x01, PORT_PIC_SLAVE_DATA
OUTB $0x00, PORT_PIC_MASTER_DATA
OUTB $0x00, PORT_PIC_SLAVE_DATA
IDT_SETUP_48_ISRS
REMAP_PIC_32
OUTB $0b00110100, PORT_PIT_MODE
PIT_SET_MIN_FREQ
sti
jmp .
IDT_START
.rept 48
IDT_ENTRY
.endr
IDT_END
handler:
cli
VGA_PRINT_STRING $message
IDT_48_ENTRIES
interrupt_handler:
pop %eax
VGA_PRINT_HEX_4 <%eax>
OUTB $0x61, $0x20
PIC_EOI
add $4, %esp
sti
iret
message:
.asciz "interrupt"