summaryrefslogtreecommitdiffhomepage
path: root/Private/HALKit/AMD64/HalDescriptorLoader.cpp
blob: 64f7ca655698bb06a116da879c6faad44a9a5dd1 (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
65
66
67
68
69
70
/*
 *	========================================================
 *
 *	HCore
 * 	Copyright Mahrouss Logic, all rights reserved.
 *
 * 	========================================================
 */

#include <ArchKit/ArchKit.hpp>

namespace HCore::HAL {
void GDTLoader::Load(Register64 &gdt) {
  Register64 gdtReg;

  gdtReg.Base = gdt.Base;
  gdtReg.Limit = gdt.Limit;

  rt_load_gdt(gdtReg);
}

namespace Detail::AMD64 {
struct InterruptDescriptorAMD64 final {
  UInt16 OffsetLow;  // offset bits 0..15
  UInt16 Selector;   // a code segment selector in GDT or LDT
  UInt8
      Ist;  // bits 0..2 holds Interrupt Stack Table offset, rest of bits zero.
  UInt8 TypeAttributes;  // gate type, dpl, and p fields
  UInt16 OffsetMid;      // offset bits 16..31
  UInt32 OffsetHigh;     // offset bits 32..63
  UInt32 Zero;           // reserved
};
}  // namespace Detail::AMD64

#define kInterruptGate 0x8E
#define kTrapGate 0x8F
#define kTaskGate 0x85
#define kGdtSelector 0xa0

extern "C" HCore::UIntPtr rt_handle_interrupts(HCore::UIntPtr &rsp);

static ALIGN(0x10)
    Detail::AMD64::InterruptDescriptorAMD64 kIdtRegs[kKernelMaxSystemCalls];

static HAL::Register64 kRegIdt;

void IDTLoader::Load(Register64 &idt) {
  VoidPtr *baseIdt = (VoidPtr *)idt.Base;

  for (auto i = 0; i < 32; i++) {
    kIdtRegs[i].Selector = kGdtSelector;
    kIdtRegs[i].Ist = 001;
    kIdtRegs[i].TypeAttributes = kTrapGate;
    kIdtRegs[i].OffsetLow = (UIntPtr)baseIdt & 0xFFFF;
    kIdtRegs[i].OffsetMid = (UIntPtr)baseIdt >> 16 & 0xFFFF;
    kIdtRegs[i].OffsetHigh = (UIntPtr)baseIdt >> 32 & 0xFFFFFFFF;
    kIdtRegs[i].Zero = 0;
  }

  kRegIdt.Base = (UIntPtr)&kIdtRegs[0];
  kRegIdt.Limit =
      sizeof(Detail::AMD64::InterruptDescriptorAMD64) * idt.Limit - 1;

  rt_load_idt(kRegIdt);
}

void GDTLoader::Load(Ref<Register64> &gdt) { GDTLoader::Load(gdt.Leak()); }

void IDTLoader::Load(Ref<Register64> &idt) { IDTLoader::Load(idt.Leak()); }
}  // namespace HCore::HAL