-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathtrap.c
139 lines (126 loc) · 3.61 KB
/
trap.c
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
134
135
136
137
138
139
#include <stddef.h>
#include "csr.h"
#include "csr_func.h"
#include "exception.h"
#include "interrupt.h"
#include "io_interface.h"
#include "memory_manager.h"
#include "plic.h"
#include "register.h"
#include "string.h"
#include "system_call.h"
#include "timer.h"
#include "trap.h"
#include "utils.h"
extern void trap_handler(void);
static thread_info_t bsp_ti;
bool init_trap(uint64_t cpu_id)
{
uint64_t kernel_stack_base = (uint64_t)kalloc_4k();
if (kernel_stack_base == (uint64_t)NULL)
{
return false;
}
bsp_ti.kernel_stack = kernel_stack_base + 0x1000 - 8;
bsp_ti.user_stack = (uint64_t)NULL;
bsp_ti.cpu_id = cpu_id;
csr_write_sscratch((uint64_t)&bsp_ti);
write_tp(0); // clear the thread pointer.
csr_write_stvec((uint64_t)trap_handler);
// TODO create and setup thread_info for each processors.
return true;
}
void enable_interrupt(void)
{
__asm__ volatile("csrs sstatus, 0x00000002");
csr_write_sie(-1);
}
void disable_interrupt(void)
{
__asm__ volatile("csrc sstatus, 0x00000002");
csr_write_sie(0);
}
void c_trap_handler(trap_frame_t *trap_frame)
{
uint64_t code = trap_frame->scause.code;
if (trap_frame->scause.interrupt)
{
switch (code)
{
case user_software_interrupt:
case supervisor_software_interrupt:
case user_timer_interrupt:
case user_external_interrupt:
// TODO
// printf("the trap [%s] is not implemented\n",
// convert_interrupt_code_to_string(code));
break;
case supervisor_timer_interrupt:
{
count_up_tick();
break;
}
case supervisor_external_interrupt:
{
uint64_t irq = plic_claim();
bool result = handle_external_interrupt(irq);
if (!result)
{
// TODO
}
// TODO
plic_complete(irq);
// TODO
break;
}
default:
panic(convert_interrupt_code_to_string(code));
break;
}
}
else
{
// exception
char sepc_str[65];
char stval_str[65];
char hstatus_str[65];
int_to_str(trap_frame->sepc, sepc_str);
int_to_str(trap_frame->stval, stval_str);
int_to_str(trap_frame->hstatus, hstatus_str);
switch (code)
{
case environment_call_from_u:
{
uint64_t result = do_system_call(trap_frame);
trap_frame->a0 = result;
// sepc indicates the ecall instruction address, not the
// following instruction.
trap_frame->sepc += 0x4;
break;
}
case environment_call_from_vs:
{
break;
}
default:
{
char error_code_str[10];
int_to_str(code, error_code_str);
put_string(error_code_str);
put_string(convert_exception_code_to_string(code));
put_string("\n");
put_string("sepc:\t0x");
put_string(sepc_str);
put_string("\n");
put_string("stval:\t0x");
put_string(stval_str);
put_string("\n");
put_string("hstatus:\t0x");
put_string(hstatus_str);
put_string("\n");
panic("panic");
break;
}
}
}
}