aboutsummaryrefslogtreecommitdiff
path: root/kernel/interrupts/idt.dats
blob: 0b912538951f97573f44310f444622dce69e94aa (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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#include "kernel/prelude/kernel_prelude.hats"

#define ATS_DYNLOADFLAG 0

staload "./idt.sats"

staload UN = "prelude/SATS/unsafe.sats"

extern typedef "int_frame" = int_frame

//----------------------------------No __attribute__ support in ats---------

%{
  __attribute__ ((interrupt))
  void default_exception_handler(int_frame *frame){
    default_exception_handler2(frame);
  }

  __attribute__ ((interrupt))
  void default_exception_handler_e(int_frame *frame, uint64_t error_code){
    default_exception_handler_e2(frame, error_code);
  }

  __attribute__ ((interrupt))
  void default_interrupt_handler(int_frame *frame, uint64_t error_code){
    default_interrupt_handler_e2(frame, error_code);
  }

  __attribute__ ((interrupt))
  void default_interrupt_handler_e(int_frame *frame, uint64_t error_code){
    default_interrupt_handler_e2(frame, error_code);
  }
%}

// DEFAULT HANDLERS,  --------------------------------------------------

extern fun default_exception_handler2(frame: &int_frame) : void = "mac#"
implement default_exception_handler2(frame) : void = let
in
  println!("DEFAULT EXCEPTION HANDLER - NO ERROR CODE");
end

extern fun default_exception_handler_e2(frame: &int_frame, error_code : uint64) : void = "mac#"
implement default_exception_handler_e2(frame,error_code) = let
in
  println!("DEFAULT EXCEPTION HANDLER - WIDTH ERROR CODE:", $UN.cast{int}(error_code));
end

extern fun default_interrupt_handler2(frame: &int_frame) : void = "mac#"
implement default_interrupt_handler2(frame) = let
in
  println!("DEFAULT INTERRUPT HANDLER - NO ERROR CODE");
end

extern fun default_interrupt_handler_e2 (frame: &int_frame, error_code : uint64) : void = "mac#"
implement default_interrupt_handler_e2(frame,error_code) = let
in
  println!("DEFAULT INTERRUPT HANDLER - WIDTH ERROR CODE:", $UN.cast{int}(error_code));
end

//-------------------------------------------------------

var idt : @[idt_entry_t][IDT_MAX_DESCRIPTORS] // The table
var idtr : idtr_t // interrupt descriptor table register instance

fun idt_set_descriptor  {n : nat | n < IDT_MAX_DESCRIPTORS} (vector: int n, isr: uint64, flags: uint8) : void = let
  extern praxi __assert{l:addr} (ptr: ptr (l)): vtakeout0 (@[idt_entry_t][IDT_MAX_DESCRIPTORS]@l) // takeout proof  UNSAFE:
  prval (pf, fpf) = __assert (addr@(idt))
  val x = $UN.cast{uint64}(0xFFFF)
  val y = $UN.cast{uint64}(0xFFFFFFF)
  val entry = @{
    isr_low = $UN.cast(isr land x), 
    kernel_cs = $UN.cast(0x08), 
    ist = $UN.cast(0), 
    attributes = flags, 
    isr_mid = $UN.cast((isr >> 16) land x), 
    isr_high = $UN.cast((isr >> 32) land y), 
    reserved = $UN.cast(0)
  }
in
  idt[vector] := entry;
  let prval () = fpf(pf) in end
end

extern typedef "idtr_t" = idtr_t
%{$
  void setup(idtr_t idtr) {
    __asm__ volatile ("lidt %0" : : "m"(idtr)); // load the new IDT
  }
%}

extern fun setup(idtr : idtr_t) : void = "ext#"

// Setup exception handlers (vector 0-31)
fun setup_exceptions() = let
  fun loop {n : nat | n <= 32} (i : int n) : void = if (i < 32) then (
    idt_set_descriptor(i,$UN.cast(
      case+ i of
        | _ when i = 8 || i = 10 || i = 11 || i = 12 
                || i = 13 || i = 14 || i = 17 || i = 22 => default_exception_handler_e
        | _ => default_exception_handler
      ),$UN.cast(TRAP_GATE_FLAGS));
    loop(i + 1)
  )
in
loop(0)
end

// Setup trap interrupts (vector 32-255)
fun setup_interrupts() = let
  fun loop {n : nat | n <= IDT_MAX_DESCRIPTORS && n >= 32} (i : int n) : void = if (i < IDT_MAX_DESCRIPTORS - 1) then (
    idt_set_descriptor(i,$UN.cast(default_interrupt_handler),$UN.cast(INT_GATE_FLAGS));
    loop(i + 1)
  )
in
loop(32)
end

implement idt_init() : void = let 
  extern praxi __assert{l:addr} (ptr: ptr (l)): vtakeout0 (idtr_t@l)
  prval (pf, fpf) = __assert (addr@(idtr)) // takeout proof  UNSAFE:
in 
  idtr.base := addr@(idt);
  idtr.limit := $UN.cast(8 * IDT_MAX_DESCRIPTORS);
  setup_exceptions();
  setup_interrupts();
  setup(idtr);
  let prval () = fpf(pf) in end
end