aboutsummaryrefslogtreecommitdiff
path: root/pk/handlers.c
blob: 474aa34841b996a3b0aabd1150a1748c4d4df4df (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
132
133
#include "pcr.h"
#include "pk.h"

int have_fp = 1; // initialized to 1 because it can't be in the .bss section!
int have_vector = 1;

static void handle_fp_disabled(trapframe_t* tf)
{
  if(have_fp)
    init_fp();
  else
  {
#ifdef PK_ENABLE_FP_EMULATION
    if(emulate_fp(tf) != 0)
    {
      dump_tf(tf);
      panic("FPU emulation failed!");
    }
#else
    panic("FPU emulation disabled! pc %lx, insn %x",tf->epc,(uint32_t)tf->insn);
#endif
  }
}

static void handle_vector_disabled(trapframe_t* tf)
{
  if (have_vector)
    tf->sr |= SR_EV;
  else
    panic("No vector hardware! pc %lx, insn %x",tf->epc,(uint32_t)tf->insn);
}

static void handle_privileged_instruction(trapframe_t* tf)
{
  dump_tf(tf);
  panic("A privileged instruction was executed!");
}

static void handle_illegal_instruction(trapframe_t* tf)
{
#ifdef PK_ENABLE_FP_EMULATION
  if(emulate_fp(tf) == 0)
    return;
#endif

  dump_tf(tf);
  panic("An illegal instruction was executed!");
}

static void handle_breakpoint(trapframe_t* tf)
{
  dump_tf(tf);
  printk("Breakpoint!\n");
}

static void handle_misaligned_fetch(trapframe_t* tf)
{
  dump_tf(tf);
  panic("Misaligned instruction access!");
}

void handle_misaligned_ldst(trapframe_t* tf)
{
  dump_tf(tf);
  panic("Misaligned data access!");
}

static void handle_fault_fetch(trapframe_t* tf)
{
  dump_tf(tf);
  panic("Faulting instruction access!");
}

void handle_fault_load(trapframe_t* tf)
{
  dump_tf(tf);
  panic("Faulting load!");
}

void handle_fault_store(trapframe_t* tf)
{
  dump_tf(tf);
  panic("Faulting store!");
}

static void handle_bad_interrupt(trapframe_t* tf, int interrupt)
{
  panic("Bad interrupt %d!",interrupt);
}

static void handle_timer_interrupt(trapframe_t* tf)
{
  mtpcr(mfpcr(PCR_COMPARE)+TIMER_PERIOD,PCR_COMPARE);
}

static void handle_interrupt(trapframe_t* tf)
{
  int interrupts = (tf->cause & CAUSE_IP) >> CAUSE_IP_SHIFT;

  for(int i = 0; interrupts; interrupts >>= 1, i++)
  {
    if(i == TIMER_IRQ)
      handle_timer_interrupt(tf);
    else
      handle_bad_interrupt(tf,i);
  }
}

void handle_trap(trapframe_t* tf)
{
  typedef void (*trap_handler)(trapframe_t*);
  const static trap_handler trap_handlers[] = {
    handle_misaligned_fetch,
    handle_fault_fetch,
    handle_illegal_instruction,
    handle_privileged_instruction,
    handle_fp_disabled,
    handle_interrupt,
    handle_syscall,
    handle_breakpoint,
    handle_misaligned_ldst,
    handle_fault_load,
    handle_fault_store,
    handle_vector_disabled,
  };

  int exccode = (tf->cause & CAUSE_EXCCODE) >> CAUSE_EXCCODE_SHIFT;
  kassert(exccode < sizeof(trap_handlers)/sizeof(trap_handlers[0]));

  trap_handlers[exccode](tf);

  pop_tf(tf);
}