Что делать, если таблица прерываний (IDT) не функционирует должным образом?

Здравствуйте! Я разрабатываю собственную операционную систему и столкнулся с проблемой при реализации таблицы прерываний (IDT). Когда я сознательно вызываю прерывание, оно, к сожалению, не обрабатывается должным образом. Вот содержимое моего файла IDT.h: 
<pre><code class="cpp">#pragma once

#ifndef _IDT_

#include "stdint.h"

#define IDT_SIZE 256

namespace SimpleOS {

    class IDT {

        struct IDTSlot;
        struct IDTPtr;

        static IDTSlot idt[IDT_SIZE];
        static IDTPtr idt_ptr;

    public:

        static void init_idt();

    private:
        
        static void dividing_by_zero();

    private:

        static void set_in_idt_slot(int pos, uint32_t base, uint16_t sel, uint8_t flags);

        static void load_idt();

        struct IDTSlot {
            uint16_t offset_first;
            uint16_t selector;
            uint8_t zero;
            uint8_t type_attr;
            uint16_t offset_second;
        };

        struct IDTPtr {
            uint16_t limit;
            uint32_t base;
        };
    };
}

#endif // _IDT_</code></pre> 
Вот также содержимое моего файла IDT.cpp: 
<pre><code class="cpp">#include "IDT/IDT.h"
#include "terminal/terminal.h"

using namespace SimpleOS;

void IDT::init_idt() {

    set_in_idt_slot(0, (uint32_t)dividing_by_zero, 0x08, 0x8E); // 0x08, 0x8E

    load_idt();

    __asm__ __volatile__("sti");
}

void IDT::set_in_idt_slot(int pos, uint32_t base, uint16_t sel, uint8_t flags) {
    idt[pos].offset_first = base &amp; 0xFFFF;
    idt[pos].selector = sel;
    idt[pos].zero = 0;
    idt[pos].type_attr = flags;
    idt[pos].offset_second = (base &gt;&gt; 16) &amp; 0xFFFF;
}

void IDT::load_idt() {
    idt_ptr.limit = (sizeof(IDTSlot) * IDT_SIZE) - 1;
    idt_ptr.base = (uint32_t)&am
  • 22 сентября 2024 г. 9:23
Ответы на вопрос 2
Согласно вашему описанию, вы создаете таблицу прерываний (IDT) в своей операционной системе, но у вас возникают проблемы с ее работой, особенно при вызове прерывания. Давайте рассмотрим несколько потенциальных причин проблем и возможные решения.

### 1. Проверьте структуру IDT

Убедитесь, что структура `IDTSlot` правильно определена. Возможно, вам не хватает необходимых битов или атрибутов. Также убедитесь, что вы правильно используете старший и младший адреса для указания на обработчик прерываний.

Пример правильной инициализации:
```cpp
void IDT::set_in_idt_slot(int pos, uint32_t base, uint16_t sel, uint8_t flags) {
    idt[pos].offset_first = base & 0xFFFF;
    idt[pos].selector = sel;
    idt[pos].zero = 0;
    idt[pos].type_attr = flags;
    idt[pos].offset_second = (base >> 16) & 0xFFFF;
}
```

### 2. Проверка функции загрузки IDT

Убедитесь, что вы правильно загружаете IDT. Например, использование инструкции `lidt` для загрузки таблицы прерываний:

```cpp
void IDT::load_idt() {
    idt_ptr.limit = (sizeof(IDTSlot) * IDT_SIZE) - 1;
    idt_ptr.base = (uint32_t)&idt;
    __asm__ __volatile__("lidt %0" : : "m"(idt_ptr));
}
```

### 3. Настройки флагов

Убедитесь, что выставлены правильные флаги в `type_attr`. Например, для 32-битного прерывания:
- `0x8E` — это тип для прерывания, где прерывание является привилегированным (ring 0) и разрешено (present).

### 4. Проверка обработчиков прерываний

Убедитесь, что функция `dividing_by_zero()` правильно определена и объявлена. Также проверьте, что она объявлена как `extern "C"` (предотвратить изменения имени) и вызывается без изменения стека:

```cpp
extern "C" void dividing_by_zero() {
    // Обработка прерывания деления на ноль
    // Например, вывести сообщение на терминал
}
```

### 5. Системные вызовы и глобальная блокировка прерываний

Убедитесь, что вы находитесь в защищенном контексте при вызове прерывания и что глобальные прерывания (interrupts) были включены с использованием `sti`.

### 6. Проверка инициализации

Убедитесь, что ваша функция `init_idt()` действительно вызывается перед попыткой использования прерываний. Перепроверьте, что после вызова `init_idt()` у вас нет других операций, которые могут сбросить IDT.

### 7. Используйте отладку

Если у вас есть доступ к отладчику, используйте его для проверки состояния регистров, а также адресов возврата во время обработки. Это может помочь выявить проблемы связанного с контекстом прерывания.

### 8. Проверка на других прерываниях

Проведите тестирование инициализации и обработки других прерываний, чтобы понять, функциональность IDT выполняется корректно для всех прерываний или только для конкретного.

Если вы проведете вышеуказанные проверки и исправления, это может помочь решить проблемы с вашей таблицей прерываний.
В чем может быть проблема?

Проблема может быть в чём угодно, чтобы сказать точнее нужен полный собирающийся код.
Похожие вопросы