IDT is now really ready

This commit is contained in:
Adrien Bourmault 2019-04-27 00:04:27 +02:00
parent 74593f7f71
commit e7d56a8550
11 changed files with 196 additions and 269 deletions

View File

@ -148,24 +148,6 @@ $(KOBJDIR)/kernel/cpu/idt.o: $(KALEIDDIR)/kernel/cpu/idt.c \
@rm -f $@.1 $@.2
@echo ${CL2}[$@] ${CL}Compiled.${CL3}
$(KOBJDIR)/kernel/io/keyb.o: $(KALEIDDIR)/kernel/io/keyb.c \
$(KALEIDDIR)/kernel/io/keyb.asm $(INCLUDEDIR)/*/*.h | $(KOBJDIR)
@mkdir -p $(shell dirname $@)
@$(ASM) $(ASMFLAGS) $(KALEIDDIR)/kernel/io/keyb.asm -o $@.1
@$(KCC) $< -o $@.2
@$(LD) $(LDFLAGS) -r $@.1 $@.2 -o $@
@rm -f $@.1 $@.2
@echo ${CL2}[$@] ${CL}Compiled.${CL3}
$(KOBJDIR)/kernel/io/rtc.o: $(KALEIDDIR)/kernel/io/rtc.c \
$(KALEIDDIR)/kernel/io/rtc.asm $(INCLUDEDIR)/*/*.h | $(KOBJDIR)
@mkdir -p $(shell dirname $@)
@$(ASM) $(ASMFLAGS) $(KALEIDDIR)/kernel/io/rtc.asm -o $@.1
@$(KCC) $< -o $@.2
@$(LD) $(LDFLAGS) -r $@.1 $@.2 -o $@
@rm -f $@.1 $@.2
@echo ${CL2}[$@] ${CL}Compiled.${CL3}
## MAIN MAKEFILE ------------------------------------------------------------- #
$(KOBJDIR)/%.o: %.c $(INCLUDEDIR)/*/*.h | $(KOBJDIR)

View File

@ -43,8 +43,7 @@ typedef struct BootInfo_t BootInfo_t;
typedef struct ListHead_t ListHead_t;
typedef struct ListNode_t ListNode_t;
typedef struct Processor_t Processor_t;
typedef struct IRQList_t IRQList_t;
typedef struct ISRFrame_t ISRFrame_t;
typedef enum ProcState_t ProcState_t;
//------------------------------------------//
@ -89,6 +88,23 @@ struct Processor_t
ListHead_t *timeCritProcs;
};
struct ISRFrame_t {
/* the register file */
ulong regs[15];
/* the error code and interrupt id */
ulong intNo;
ulong ErrorCode;
/* these are pushed automatically by the CPU */
ulong rip;
ulong cs;
ulong rflags;
ulong rsp;
ulong ss;
} __attribute__((__packed__));
//------------------------------------------//
#ifndef NCPUS

View File

@ -13,7 +13,7 @@ typedef struct ISRFrame_t ISRFrame_t;
// -------------------------------------------------------------------------- //
#define interrupt(n) asm volatile ("int %0" : : "N" (n) : "cc", "memory") \
#define interrupt(n) asm volatile ("int %0" : : "N" (n) : "cc", "memory")
// -------------------------------------------------------------------------- //
@ -44,28 +44,12 @@ struct IRQList_t
uchar n; //number of entries in the list
struct entry {
void (*isr)(void);
void (*isr)(ISRFrame_t *regs);
uchar irq;
uchar flags;
} entry[224];
};
struct ISRFrame_t {
/* the register file */
uint64_t regs[15];
/* the error code and interrupt id */
uint64_t id;
uint64_t error;
/* these are pushed automatically by the CPU */
uint64_t rip;
uint64_t cs;
uint64_t rflags;
uint64_t rsp;
uint64_t ss;
} __attribute__((__packed__));
typedef struct
{
@ -108,10 +92,10 @@ static char *IsrExceptions[32] = {
// -------------------------------------------------------------------------- //
void IdtRegisterIrq(void (*isr)(void), uchar irq, uchar flags);
void IdtRegisterIrq(void (*isr)(ISRFrame_t *regs), uchar irq, uchar flags);
void IdtSetup(void);
void IdtSetGate(uchar rank, ulong base, ushort selector, uchar flags);
//void IdtHandler(ulong intNo);
void IdtExceptionHandler(ISRFrame_t *regs);
static void EnablePIC(void);
void SendEOItoPIC(uchar isr);
@ -148,5 +132,34 @@ extern void isr28();
extern void isr29();
extern void isr30();
extern void isr31();
extern void isr32();
extern void isr33();
extern void isr34();
extern void isr35();
extern void isr36();
extern void isr37();
extern void isr38();
extern void isr39();
extern void isr40();
extern void isr41();
extern void isr42();
extern void isr43();
extern void isr44();
extern void isr45();
extern void isr46();
extern void isr47();
extern void isr48();
extern void isr49();
extern void isr50();
extern void isr51();
extern void isr52();
extern void isr53();
extern void isr54();
extern void isr55();
extern void isr56();
extern void isr57();
extern void isr58();
extern void isr59();
extern void isr60();
#endif

View File

@ -64,7 +64,7 @@ static inline ulong KePauseIRQs(void) {
extern void IoSendEOItoPIC(uchar isr);
extern void IoEnableNMI(void);
extern void IoDisableNMI(void);
extern void IdtRegisterIrq(void (*isr)(void), uchar irq, uchar flags);
extern void IdtRegisterIrq(void (*isr)(ISRFrame_t *regs), uchar irq, uchar flags);
//
// Restore IRQ flag to its state before KePauseIRQs

View File

@ -37,11 +37,11 @@ IRQList_t irqList = { 0 };
//
// Registers an isr with his IRQ to handle driver interrupts
//
void IdtRegisterIrq(void (*isr)(void), uchar irq, uchar flags)
void IdtRegisterIrq(void (*isr)(ISRFrame_t *regs), uchar irq, uchar flags)
{
uchar n = irqList.n;
KalAssert(idt[0].flags==0); // IDT uninitialized
KalAssert(idt[0].flags!=0); // IDT initialized
if ((n == 224)) // IRQs not filled
KeStartPanic("[IdtRegisterIrq] Cannot register IRQ %c function %p !",
@ -103,15 +103,36 @@ void IdtSetup(void)
IdtSetGate(30, (ulong)isr30, codeSeg, 0x8E); // INTEL RESERVED
IdtSetGate(31, (ulong)isr31, codeSeg, 0x8E); // INTEL RESERVED
// Set the IRQ Driver Gates
for (int i = 0 ; i < irqList.n ; i++) {
IdtSetGate(
irqList.entry[i].irq,
(ulong)irqList.entry[i].isr,
codeSeg,
irqList.entry[i].flags
);
}
// Set IDT IRQs Gates
IdtSetGate(32, (ulong)isr32, codeSeg, 0x8E);
IdtSetGate(33, (ulong)isr33, codeSeg, 0x8E);
IdtSetGate(34, (ulong)isr34, codeSeg, 0x8E);
IdtSetGate(35, (ulong)isr35, codeSeg, 0x8E);
IdtSetGate(36, (ulong)isr36, codeSeg, 0x8E);
IdtSetGate(37, (ulong)isr37, codeSeg, 0x8E);
IdtSetGate(38, (ulong)isr38, codeSeg, 0x8E);
IdtSetGate(39, (ulong)isr39, codeSeg, 0x8E);
IdtSetGate(40, (ulong)isr40, codeSeg, 0x8E);
IdtSetGate(41, (ulong)isr41, codeSeg, 0x8E);
IdtSetGate(42, (ulong)isr42, codeSeg, 0x8E);
IdtSetGate(43, (ulong)isr43, codeSeg, 0x8E);
IdtSetGate(44, (ulong)isr44, codeSeg, 0x8E);
IdtSetGate(45, (ulong)isr45, codeSeg, 0x8E);
IdtSetGate(46, (ulong)isr46, codeSeg, 0x8E);
IdtSetGate(47, (ulong)isr47, codeSeg, 0x8E);
IdtSetGate(48, (ulong)isr48, codeSeg, 0x8E);
IdtSetGate(49, (ulong)isr49, codeSeg, 0x8E);
IdtSetGate(50, (ulong)isr50, codeSeg, 0x8E);
IdtSetGate(51, (ulong)isr51, codeSeg, 0x8E);
IdtSetGate(52, (ulong)isr52, codeSeg, 0x8E);
IdtSetGate(53, (ulong)isr53, codeSeg, 0x8E);
IdtSetGate(54, (ulong)isr54, codeSeg, 0x8E);
IdtSetGate(55, (ulong)isr55, codeSeg, 0x8E);
IdtSetGate(56, (ulong)isr56, codeSeg, 0x8E);
IdtSetGate(57, (ulong)isr57, codeSeg, 0x8E);
IdtSetGate(58, (ulong)isr58, codeSeg, 0x8E);
IdtSetGate(59, (ulong)isr59, codeSeg, 0x8E);
IdtSetGate(60, (ulong)isr60, codeSeg, 0x8E);
// Load IDT
IdtInit();
@ -185,21 +206,57 @@ void IoDisableNMI(void)
}
//
// The main exception handler
// The main ISR handler
//
void IdtHandler(ulong intNo)
void IsrHandler(ISRFrame_t *regs)
{
if ((!regs) || (!regs->rip))
KeStartPanic("[ISR ?] Unknown ISR Exception Abort\n");
if (regs->intNo < 32) {
IdtExceptionHandler(regs);
return;
}
for (int i = 0; i < irqList.n; i++) {
if (regs->intNo == irqList.entry[i].irq) {
irqList.entry[i].isr(regs);
return;
}
}
KeStartPanic("[ISR 0x%x] Unknown ISR Exception Abort\n", regs->intNo);
}
//
// CPU Exception handler
//
void IdtExceptionHandler(ISRFrame_t *regs)
{
int recoverable = 0;
char *exceptionMsg = "Unhandled ISR exception";
if (intNo >= 32) recoverable++;
if (intNo < 32) exceptionMsg = IsrExceptions[intNo];
exceptionMsg = IsrExceptions[regs->intNo];
if (!recoverable) {
KeStartPanic("[ISR 0x%x] Irrecoverable %s\n", intNo, exceptionMsg);
KeStartPanic("[ISR 0x%x] Irrecoverable Kernel %s\n"
" Error code : 0x%x\n"
" RIP:\t\t%p\n"
" CS:\t\t%p\n"
" RFLAGS:\t%022b\n"
" RSP:\t\t%p\n"
" SS:\t\t%p\n",
regs->intNo,
exceptionMsg,
regs->ErrorCode,
regs->rip,
regs->cs,
regs->rflags,
regs->rsp,
regs->ss
);
} else {
bprintf(BStdOut, "[ISR 0x%x] %s\n", intNo, exceptionMsg);
//IoSendEOItoPIC(intNo);
bprintf(BStdOut, "[ISR 0x%x] %s\n", regs->intNo, exceptionMsg);
}
}

View File

@ -27,7 +27,7 @@
global IdtInit
global divideByZero
extern idtPtr
extern IdtHandler
extern IsrHandler
extern label0
;;
@ -41,16 +41,14 @@ IdtInit:
;; Bug test
;;
divideByZero:
pushAll
mov eax, 17
mov ebx, 0
xor edx, edx
div ebx
popAll
ret
;;
;; ISR handler
;; ISR Exception pre-handler
;;
isrPreHandler:
pushAll
@ -71,7 +69,7 @@ isrPreHandler:
mov rdi, rsp ; First argument points to the processor state
mov rbp, 0 ; Terminate stack traces here
call IdtHandler
call IsrHandler
; decrement mask count
dec qword [gs:8]
@ -81,7 +79,7 @@ isrPreHandler:
and rax, 0x3000
jz .SExit
swapgs
swapgs ; XXX need TSS
.SExit:
popAll
@ -164,3 +162,11 @@ IsrWithoutErrCode 29
IsrWithoutErrCode 30
IsrWithoutErrCode 31
;; IRQs
%assign i 32
%rep 225
IsrWithoutErrCode i
%assign i i+1
%endrep

View File

@ -38,7 +38,6 @@ extern void BtInitBootInfo(multiboot_info_t *mbi, void *codeSeg);
extern error_t IoInitVGABuffer(void);
//io/keyb.c
extern void IoSetupKeyb(void);
extern void IoEnableKeyb(void);
// cpu/idt.c
@ -82,9 +81,6 @@ noreturn void BtStartKern(multiboot_info_t *mbInfo, uint mbMagic, void *codeSeg)
MmInitHeap();
PsInitSched();
// Drivers ISR inits
IoSetupRtc();
IoSetupKeyb();
// Interrupts launching
IdtSetup();
KeEnableIRQs();
@ -95,12 +91,14 @@ noreturn void BtStartKern(multiboot_info_t *mbInfo, uint mbMagic, void *codeSeg)
IoPrintRtcTime();
KernLog("There was %d ticks\n", IoGetRtcTicks());
for (uint i = 1; i < 20000 ; i++) {
for (uint i = 1; i < 2 ; i++) {
while (IoGetRtcTicks() < i * 10000) {
}
IoPrintRtcTime();
}
divideByZero();
KernLog("Goodbye after %d ticks\n", IoGetRtcTicks());
// End this machine's suffering
BFlushBuf(BStdOut);

View File

@ -1,68 +0,0 @@
;=----------------------------------------------------------------------------=;
; GNU GPL OS/K ;
; ;
; Desc: Basic Read Only Keyboard Driver ;
; (x86_64 architecture only) ;
; ;
; ;
; Copyright © 2018-2019 The OS/K Team ;
; ;
; This file is part of OS/K. ;
; ;
; OS/K is free software: you can redistribute it and/or modify ;
; it under the terms of the GNU General Public License as published by ;
; the Free Software Foundation, either version 3 of the License, or ;
; (at your option) any later version. ;
; ;
; OS/K is distributed in the hope that it will be useful, ;
; but WITHOUT ANY WARRANTY; without even the implied warranty of ;
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;
; GNU General Public License for more details. ;
; ;
; You should have received a copy of the GNU General Public License ;
; along with OS/K. If not, see <https://www.gnu.org/licenses/>. ;
;=----------------------------------------------------------------------------=;
[BITS 64]
global KeybIsr
extern KeybHandler
%macro pushAll 0
push rax
push rcx
push rdx
push rbx
push rbp
push rsi
push rdi
%endmacro
%macro popAll 0
pop rdi
pop rsi
pop rbp
pop rbx
pop rdx
pop rcx
pop rax
%endmacro
;;
;; Keyboard handler
;;
KeybIsr:
cli
pushAll
xor rax, rax
mov ax, ds
push rax
call KeybHandler
pop rax
mov ds, ax
popAll
iretq

View File

@ -26,14 +26,8 @@
#include <kernel/iomisc.h>
#include <extras/buf.h>
extern void KeybIsr(void);
char ScanCodes[100] = { 0 };
void IoSetupKeyb(void)
{
IdtRegisterIrq(KeybIsr, 0x21, 0x8E);
}
void KeybPrint(char code)
{
if (code) {
@ -88,17 +82,7 @@ void ScanCodesInit(void)
ScanCodes[0x39] = ' ';
}
void IoEnableKeyb(void)
{
ulong flags = KePauseIRQs();
char readedInterruptConfig = IoReadByteFromPort(0x21);
IoWriteByteOnPort(0x21, 0xFD & readedInterruptConfig);
KeRestoreIRQs(flags);
IoEnableNMI();
ScanCodesInit();
}
void KeybHandler(void)
void KeybHandler(ISRFrame_t *regs)
{
char status;
char code = 0;
@ -116,3 +100,14 @@ void KeybHandler(void)
KeybPrint((int)code);
IoSendEOItoPIC(0x21);
}
void IoEnableKeyb(void)
{
ulong flags = KePauseIRQs();
IdtRegisterIrq(KeybHandler, 0x21, 0x8E);
char readedInterruptConfig = IoReadByteFromPort(0x21);
IoWriteByteOnPort(0x21, 0xFD & readedInterruptConfig);
KeRestoreIRQs(flags);
IoEnableNMI();
ScanCodesInit();
}

View File

@ -1,68 +0,0 @@
;=----------------------------------------------------------------------------=;
; GNU GPL OS/K ;
; ;
; Desc: Basic Read Only Keyboard Driver ;
; (x86_64 architecture only) ;
; ;
; ;
; Copyright © 2018-2019 The OS/K Team ;
; ;
; This file is part of OS/K. ;
; ;
; OS/K is free software: you can redistribute it and/or modify ;
; it under the terms of the GNU General Public License as published by ;
; the Free Software Foundation, either version 3 of the License, or ;
; (at your option) any later version. ;
; ;
; OS/K is distributed in the hope that it will be useful, ;
; but WITHOUT ANY WARRANTY; without even the implied warranty of ;
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;
; GNU General Public License for more details. ;
; ;
; You should have received a copy of the GNU General Public License ;
; along with OS/K. If not, see <https://www.gnu.org/licenses/>. ;
;=----------------------------------------------------------------------------=;
[BITS 64]
global RtcIsr
extern RtcHandler
%macro pushAll 0
push rax
push rcx
push rdx
push rbx
push rbp
push rsi
push rdi
%endmacro
%macro popAll 0
pop rdi
pop rsi
pop rbp
pop rbx
pop rdx
pop rcx
pop rax
%endmacro
;;
;; Keyboard handler
;;
RtcIsr:
cli
pushAll
xor rax, rax
mov ax, ds
push rax
call RtcHandler
pop rax
mov ds, ax
popAll
iretq

View File

@ -27,17 +27,11 @@
#include <extras/buf.h>
#include <kernel/time.h>
extern void RtcIsr(void);
static ulong IoRtcTicks = 0;
static uchar RtcRate = 0x05; //2048Hz
static Time_t IoRtcOriginTime;
static Time_t IoRtcTime;
static char time24or12Mode;
void IoSetupRtc(void)
{
IdtRegisterIrq(RtcIsr, 0x28, 0x8E);
}
static void GetTimeFromRtc(void)
{
@ -143,45 +137,7 @@ static void GetTimeFromRtc(void)
IoRtcTime.century = IoRtcOriginTime.century;
}
void IoEnableRtc(void)
{
ulong flags = KePauseIRQs();
char readedInterruptConfig;
char readedRegister;
char readedIrqs;
// Setting up the register control and interrupt rates
DebugLog("[RTC Time] Interrupt frequency set to %d Hz\n",
32768 >> (RtcRate-1));
IoWriteByteOnPort(0x70, 0x8B);
readedRegister = IoReadByteFromPort(0x71);
IoWriteByteOnPort(0x70, 0x8B); // Because reading flushes
IoWriteByteOnPort(0x71, readedRegister | 0x40);
IoWriteByteOnPort(0x70, 0x8A);
readedInterruptConfig = IoReadByteFromPort(0x71);
IoWriteByteOnPort(0x70, 0x8A); // Because reading flushes
IoWriteByteOnPort(0x71, (readedInterruptConfig & 0xF0) | RtcRate);
IoWriteByteOnPort(0x70, 0x0C);
IoReadByteFromPort(0x71); // Flush
// Setting up the IRQs
readedIrqs = IoReadByteFromPort(0xA1);
IoWriteByteOnPort(0xA1, 0xFE & readedIrqs); // Enables IRQ on PIC 2
readedIrqs = IoReadByteFromPort(0x21);
IoWriteByteOnPort(0x21, 0xFB & readedIrqs); // Enables IRQ on PIC 1
// Clean-up
IoWriteByteOnPort(0x70, 0x0C); // Select status reg C
IoReadByteFromPort(0x71); // Flush
GetTimeFromRtc();
KeRestoreIRQs(flags);
IoEnableNMI();
}
void RtcHandler(void)
void RtcHandler(ISRFrame_t *regs)
{
//bprintf(BStdOut, " *RTC - ");
IoWriteByteOnPort(0x70, 0x0C); // Selects status reg C
@ -258,4 +214,44 @@ ulong IoGetRtcTicks(void)
return IoRtcTicks;
}
void IoEnableRtc(void)
{
ulong flags = KePauseIRQs();
char readedInterruptConfig;
char readedRegister;
char readedIrqs;
IdtRegisterIrq(RtcHandler, 0x28, 0x8E);
// Setting up the register control and interrupt rates
DebugLog("[RTC Time] Interrupt frequency set to %d Hz\n",
32768 >> (RtcRate-1));
IoWriteByteOnPort(0x70, 0x8B);
readedRegister = IoReadByteFromPort(0x71);
IoWriteByteOnPort(0x70, 0x8B); // Because reading flushes
IoWriteByteOnPort(0x71, readedRegister | 0x40);
IoWriteByteOnPort(0x70, 0x8A);
readedInterruptConfig = IoReadByteFromPort(0x71);
IoWriteByteOnPort(0x70, 0x8A); // Because reading flushes
IoWriteByteOnPort(0x71, (readedInterruptConfig & 0xF0) | RtcRate);
IoWriteByteOnPort(0x70, 0x0C);
IoReadByteFromPort(0x71); // Flush
// Setting up the IRQs
readedIrqs = IoReadByteFromPort(0xA1);
IoWriteByteOnPort(0xA1, 0xFE & readedIrqs); // Enables IRQ on PIC 2
readedIrqs = IoReadByteFromPort(0x21);
IoWriteByteOnPort(0x21, 0xFB & readedIrqs); // Enables IRQ on PIC 1
// Clean-up
IoWriteByteOnPort(0x70, 0x0C); // Select status reg C
IoReadByteFromPort(0x71); // Flush
GetTimeFromRtc();
KeRestoreIRQs(flags);
IoEnableNMI();
}