Отладка Triple Fault - PullRequest
       46

Отладка Triple Fault

0 голосов
/ 30 апреля 2018

Я пробую учебник по разработке операционной системы (wyoos.org), и у меня возникают проблемы с работой прерываний. Когда я пытаюсь запустить свою ОС в Virtualbox, я получаю тройную ошибку, иногда после активации прерываний. Я узнал, что это, вероятно, потому, что моя глобальная таблица дескрипторов настроена неправильно. Вполне возможно, что я пытаюсь прыгнуть в блок данных.

Я почти уверен, что это происходит, когда прерывание запускается, и я не обрабатываю его, но мне трудно отлаживать его. Кто-нибудь может указать мне правильное направление, пожалуйста?

Моя обработка прерываний состоит из трех файлов: interruptstubs.s, interrupts.h и interrupts.cpp

#interruptstubs.s

.set IRQ_BASE, 0x20

.section .text
.extern _ZN16InterruptManager15HandleInterruptEhj
.global _ZN16IterruptManager26IgnoreInterruptRequestEv

.macro HandleException num
.global _ZN16InterruptManager16HandleException\num\()Ev
_ZN16InterruptManager16handleException\num\()Ev:
    movb $\num, (interruptnumber)
    jmp int_bottom
.endm

.macro HandleInterruptRequest num
.global _ZN16InterruptManager26HandleInterruptRequest\num\()Ev
_ZN16InterruptManager26handleInterruptRequest\num\()Ev:
    movb $\num + IRQ_BASE, (interruptnumber)
    jmp int_bottom
.endm

HandleInterruptRequest 0x00
HandleInterruptRequest 0x01

int_bottom:

  pusha
  pushl %ds
  pushl %es
  pushl %fs
  pushl %gs

  pushl %esp
  push (interruptnumber)
  call  _ZN16InterruptManager15HandleInterruptEhj
  # addl $5, %esp
  movl %eax, %esp

  popl %gs
  popl %fs
  popl %es
  popl %ds
  popa

_ZN16IterruptManager26IgnoreInterruptRequestEv:
  iret

  .data
interruptnumber:   .byte 0

interrupts.h

#ifndef __INTERRUPTS_H
#define __INTERRUPTS_H

#include "types.h"
#include "port.h"
#include "gdt.h"

class InterruptManager {
 public:
  InterruptManager(GlobalDescriptorTable* gdt);
  ~InterruptManager();

  static void Activate();

  static uint32_t HandleInterrupt(uint8_t interruptNumber, uint32_t esp );

  static void InterruptIgnore();
  static void HandleInterruptRequest();
  static void HandleInterruptRequest0x00();
  static void HandleInterruptRequest0x01();

 protected:
  struct GateDescriptor {
    uint16_t handlerAddressLowBits;
    uint16_t gdt_codeSegmentSelector;
    uint8_t reserved;
    uint8_t access_rights;
    uint16_t handlerAddressHighBits;
  } __attribute__((packed));

  static GateDescriptor interruptDescriptorTable[256];

  struct InterruptDescriptorTablePointer
  {
    uint16_t size;
    uint32_t base;
  } __attribute__((packed));

  static void SetInterruptDescriptorTableEntry(
                                               uint8_t interruptNumber,
                                               uint16_t codeSegmentSelectorOffset,
                                               void (*handler)(),
                                               uint8_t DescriptorPrivilegeLevel,
                                               uint8_t DescriptorType);

  Port8BitSlow picMasterCommand;
  Port8BitSlow picMasterData;
  Port8BitSlow picWorkerCommand;
  Port8BitSlow picWorkerData;

};

#endif

interrupts.cpp

#ifndef __INTERRUPTS_H
#define __INTERRUPTS_H

#include "types.h"
#include "port.h"
#include "gdt.h"

class InterruptManager {
 public:
  InterruptManager(GlobalDescriptorTable* gdt);
  ~InterruptManager();

  static void Activate();

  static uint32_t HandleInterrupt(uint8_t interruptNumber, uint32_t esp );

  static void InterruptIgnore();
  static void HandleInterruptRequest();
  static void HandleInterruptRequest0x00();
  static void HandleInterruptRequest0x01();

 protected:
  struct GateDescriptor {
    uint16_t handlerAddressLowBits;
    uint16_t gdt_codeSegmentSelector;
    uint8_t reserved;
    uint8_t access_rights;
    uint16_t handlerAddressHighBits;
  } __attribute__((packed));

  static GateDescriptor interruptDescriptorTable[256];

  struct InterruptDescriptorTablePointer
  {
    uint16_t size;
    uint32_t base;
  } __attribute__((packed));

  static void SetInterruptDescriptorTableEntry(
                                               uint8_t interruptNumber,
                                               uint16_t codeSegmentSelectorOffset,
                                               void (*handler)(),
                                               uint8_t DescriptorPrivilegeLevel,
                                               uint8_t DescriptorType);

  Port8BitSlow picMasterCommand;
  Port8BitSlow picMasterData;
  Port8BitSlow picWorkerCommand;
  Port8BitSlow picWorkerData;

};

#endif
(v2_ordergroove-py27) ~/s/wyoos ❯❯❯ cat interrupts.cpp
#include "interrupts.h"

void printf(const char* str);

InterruptManager::GateDescriptor InterruptManager::interruptDescriptorTable[256];

void InterruptManager::SetInterruptDescriptorTableEntry(
        uint8_t interruptNumber,
        uint16_t codeSegmentSelectorOffset,
        void (*handler)(),
        uint8_t DescriptorPrivilegeLevel,
        uint8_t descriptorType)
{
  printf("\nGDT Entry Start\n");
  interruptDescriptorTable[interruptNumber].handlerAddressLowBits = ((uint32_t)handler) & 0xFFFF;
  interruptDescriptorTable[interruptNumber].handlerAddressHighBits = (((uint32_t)handler) >> 16) & 0xFFFF;
  interruptDescriptorTable[interruptNumber].gdt_codeSegmentSelector = codeSegmentSelectorOffset;

  const uint8_t IDT_DESC_PRESENT = 0x00;
  interruptDescriptorTable[interruptNumber].access_rights = IDT_DESC_PRESENT | descriptorType | (DescriptorPrivilegeLevel << 5);
  interruptDescriptorTable[interruptNumber].reserved = 0;
  printf("\nGDT Entry End\n");
}

InterruptManager::InterruptManager(GlobalDescriptorTable* gdt)
  : picMasterCommand(0x20),
    picMasterData(0x21),
    picWorkerCommand(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, &InterruptIgnore, 0, IDT_INTERRUPT_GATE);
  }
  SetInterruptDescriptorTableEntry(0x20, CodeSegment, &HandleInterruptRequest0x00, 0, IDT_INTERRUPT_GATE);
  SetInterruptDescriptorTableEntry(0x21, CodeSegment, &HandleInterruptRequest0x01, 0, IDT_INTERRUPT_GATE);

  picMasterCommand.Write(0x11);
  picWorkerCommand.Write(0x11);

  picMasterData.Write(0x20);
  picWorkerData.Write(0x20);

  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));
}

void InterruptManager::InterruptIgnore() {

}

void InterruptManager::HandleInterruptRequest0x01() {
 printf("Handle 0x01"); 
}

void InterruptManager::HandleInterruptRequest0x00() {
 printf("Handle 0x00"); 
}

InterruptManager::~InterruptManager()
{
}


void InterruptManager::Activate()
{
  printf("\nStart activate\n");
  asm("sti");
  printf("Done activate\n");
}

uint32_t InterruptManager::HandleInterrupt(uint8_t interrupt, uint32_t esp)
{
  printf("start handle interrupt");
  //const char* debugString = " INTERRUPT";
  char* foo = "INTERRUPT 0x00";
  char* hex = "0123456789ABCDEF";

  foo[12] = hex[(interrupt >> 4) & 0xF];
  foo[13] = hex[interrupt & 0xF];
  printf(foo);

  return esp;
}

Мой полный исходный код доступен на https://github.com/munk/wyoos/tree/gdt-triple-fault

...