Interrupt Handling Issue
Posted: Wed Aug 09, 2023 9:10 am
Im having a problem when i try to handle interrupt request i tried it on virtualbox it gives me VINF_EM_TRIPLE_FAULT error and terminates the vbox. i tried it on my physical machine but it terminates when i try to start it. im using C++ and following a tutorial on youtube i double checked the code but i couldn't find the problem. Can someone help me please?
gdt.cpp
interrupts.cpp
kernel.cpp
gdt.cpp
Code: Select all
#include "gdt.h"
GlobalDescriptorTable::GlobalDescriptorTable():
nullSegmentSelector(0,0,0),
freeSegmentSelector(0,0,0),
codeSegmentSelector(0,64*1024*1024,0x9A),
dataSegmentSelector(0,64*1024*1024,0x92)
{
uint32_t i[2];
i[0] = (uint32_t)this;
i[1] = sizeof(GlobalDescriptorTable) << 16;
asm volatile("lgdt (%0)": : "p" (((uint8_t *) i)+2));
}
GlobalDescriptorTable::~GlobalDescriptorTable()
{
}
uint16_t GlobalDescriptorTable::DataSegmentSelector(){
return (uint8_t*)&dataSegmentSelector - (uint8_t*)this;
}
uint16_t GlobalDescriptorTable::CodeSegmentSelector(){
return (uint8_t*)&codeSegmentSelector - (uint8_t*)this;
}
GlobalDescriptorTable::SegmentDescriptor::SegmentDescriptor(uint32_t base, uint32_t limit, uint8_t flags){
uint8_t* target = (uint8_t *)this;
if(limit <= 65536){
target[6] = 0x40;
}
else{
if((limit&0xFFF) != 0xFFF){
limit = (limit>>12)-1;
}
else{
limit = limit>>12;
}
target[6] = 0xC0;
}
target[0] = limit & 0xFF;
target[1] = (limit>>8) & 0xFF;
target[6] |= (limit>>16) & 0xF;
target[2] = base & 0xFF;
target[3] = (base>>8) & 0xFF;
target[4] = (base>>16) & 0xFF;
target[7] = (base>>24) & 0xFF;
target[5] = flags;
}
uint32_t GlobalDescriptorTable::SegmentDescriptor::Base(){
uint8_t* target = (uint8_t*)this;
uint32_t result = target[7];
result = (result<<8) + target[4];
result = (result<<8) + target[3];
result = (result<<8) + target[2];
return result;
}
uint32_t GlobalDescriptorTable::SegmentDescriptor::Limit(){
uint8_t* target = (uint8_t *)this;
uint32_t result = target[6] & 0xF;
result = (result<<8) + target[1];
result = (result<<8) + target[0];
if((target[6] & 0xC0) == 0xC0){
result = (result<<12) | 0xFFF;
}
return result;
}
Code: Select all
#include "interrupts.h"
void printf(char* str);
InterruptManager::GateDescriptor InterruptManager::interruptDescriptorTable[256];
void InterruptManager::SetInterruptDescriptorTableEntry(uint8_t interruptNum, uint16_t codeSegmentSelectorOffset,void (*handler)(), uint8_t DescriptorAccessRights, uint8_t DescriptorType)
{
const uint8_t IDT_DESC_PRESENT = 0x80;
interruptDescriptorTable[interruptNum].handlerAddressLow = ((uint32_t) handler) & 0xFFFF;
interruptDescriptorTable[interruptNum].handlerAddressHigh = (((uint32_t) handler)>>16) & 0xFFFF;
interruptDescriptorTable[interruptNum].gdt_codeSegmentSelector = codeSegmentSelectorOffset;
interruptDescriptorTable[interruptNum].access = IDT_DESC_PRESENT | DescriptorType | ((DescriptorAccessRights&3) << 5);
interruptDescriptorTable[interruptNum].reserved = 0;
}
InterruptManager::InterruptManager(GlobalDescriptorTable* gdt) : picMasterCmd(0x20), picMasterData(0x21),picWorkerCmd(0xA0), picWorkerData(0xA1)
{
uint16_t codeSegment = gdt->CodeSegmentSelector();
const uint8_t IDT_INTERRUPT_GATE = 0xE;
for (uint16_t i = 0; i<256; i++)
{
SetInterruptDescriptorTableEntry(i, codeSegment, &IgnoreInterruptRequest, 0, IDT_INTERRUPT_GATE);
}
SetInterruptDescriptorTableEntry(0x20, codeSegment, &handleInterruptRequest0x00, 0, IDT_INTERRUPT_GATE);
SetInterruptDescriptorTableEntry(0x21, codeSegment, &handleInterruptRequest0x01, 0, IDT_INTERRUPT_GATE);
picMasterCmd.Write(0x11);
picWorkerCmd.Write(0x11);
picMasterData.Write(0x20);
picWorkerData.Write(0x28);
picMasterData.Write(0x04);
picWorkerData.Write(0x02);
picMasterData.Write(0x01);
picWorkerData.Write(0x01);
picMasterData.Write(0x00);
picWorkerData.Write(0x00);
interruptDescriptorTablePointer idt;
idt.size = 256 * sizeof(GateDescriptor) - 1;
idt.base = (uint32_t) interruptDescriptorTable;
asm volatile("lidt %0" : : "m" (idt));
}
InterruptManager::~InterruptManager(){}
void InterruptManager::Activate(){
asm("sti");
}
uint32_t InterruptManager::handleInterrupt(uint8_t interruptNum, uint32_t esp)
{
printf(" INTERRUPT");
return esp;
}
Code: Select all
#include "types.h"
#include "gdt.h"
#include "interrupts.h"
void printf(char* str){
static uint16_t* VideoMemory = (uint16_t*) 0xb8000;
static uint8_t x = 0 , y = 0;
for (int i = 0; str[i] != '\0'; i++){
switch(str[i]){
case '\n':
y++;
x = 0;
break;
default:
VideoMemory[80*y+x] = (VideoMemory[80*y+x] & 0xFF00) | str[i];
x++;
}
if(x>= 80){
y++;
x = 0;
}
if(y>= 25){
for (y = 0; y < 25; ++y)
{
for (x = 0; x < 80; ++x)
{
VideoMemory[80*y+x] = (VideoMemory[80*y+x] & 0xFF00) | ' ';
}
}
x = 0; y = 0;
}
}
}
typedef void (*constructor)();
extern "C" constructor start_ctors;
extern "C" constructor end_ctors;
extern "C" void callConstructors()
{
for(constructor* i = &start_ctors; i != &end_ctors; i++){
(*i)();
}
}
extern "C" void kernelMain(const void* multiboot_structure, uint32_t /*magicnum*/){
printf("cernOS ilk gosterim\n");
GlobalDescriptorTable gdt;
InterruptManager im(&gdt);
im.Activate();
while(1);
}