aboutsummaryrefslogtreecommitdiff
path: root/src/idt.h
blob: 628eb23716c659b3f2cfbbebcf4627912baf855a (plain)
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#pragma once

#include <types.h>

class IDT {
public:
  struct Pointer {
    uint16_t limit;
    uint32_t base;
  } __attribute__((packed));

  enum InterruptType : uint8_t {
    Null = 0,
    InterruptGate = 0b110,  // hardware interrupts are disabled while the handler runs
    TrapGate = 0b111,       // hardware interrupts remain active while the handler runs
    TaskGate = 0b101,       // selector points to TSS rather than a code segment
  };

  class Entry {
  public:
    constexpr Entry(uint32_t offset = 0, uint16_t select = 0, InterruptType t = Null) {
      offset_0_15 = offset & 0xffff;
      offset_16_31 = (offset & 0xffff0000) >> 16;
      selector = select;
      type = t;
      if (offset != 0) {
        e = true;
      }
    }

  private:
    uint16_t offset_0_15;                //  0-15 offset in the segment
    uint16_t selector;                   // 16-31 selector of the code segment
    [[maybe_unused]] uint8_t null = 0;   // 32-39 unused in protected mode
    InterruptType type : 3;              // 40-42 type
    [[maybe_unused]] bool d : 1 = true;  //    43 true: 32-bit, false: 16-bit segment
    [[maybe_unused]] uint8_t u : 1 = 0;  //    44 unused
    [[maybe_unused]] uint8_t dpl : 2 = 0;  // 45-46 descriptor privilege level
    [[maybe_unused]] bool e : 1 = false;   //    47 enable
    uint16_t offset_16_31;               // 48-63 offset high
  } __attribute__((packed));

  IDT();

private:
  Entry table[256];
};

struct interrupt_frame {
  uword_t ip;
  uword_t cs;
  uword_t flags;
  uword_t sp;
  uword_t ss;
};

/* https://wiki.osdev.org/Interrupt_Service_Routines */
template <uint8_t irq>
__attribute__((interrupt)) void kirq(interrupt_frame* frame);

template <>
void kirq<0x0>(interrupt_frame* frame);
template <>
void kirq<0x1>(interrupt_frame* frame);