-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsyscall.cpp
118 lines (101 loc) · 2.87 KB
/
syscall.cpp
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
#include <syscall.h>
#include <kernel.h>
#include <irq.hpp>
#include <process.h>
#include <kernel-abi/syscall_nr.h>
#include <mm/mm.h>
void handle_syscall(Process *p, Context *c);
void Syscall::SetupSyscall(Kernel *kernel) {
kernel->irq_->Register(IRQ_SYSCALL, [](IrqHandlerInfo *info) {
auto p = processes[info->pid];
handle_syscall(p, info->context);
});
}
using SyscallFunc = int (Syscall::*)();
void _sys_exit() {
}
extern "C" {
// NOTE: keep these two tables in sync
SyscallFunc syscall_table[] = {
[SYSCALL_NR_NULL] = nullptr,
[SYSCALL_NR_READ] = &Syscall::sys_read,
[SYSCALL_NR_WRITE] = &Syscall::sys_write,
[SYSCALL_NR_OPEN] = &Syscall::sys_open,
[SYSCALL_NR_CLOSE] = &Syscall::sys_close,
[SYSCALL_NR_EXIT] = &Syscall::sys_exit,
[SYSCALL_NR_YIELD] = &Syscall::sys_yield,
[SYSCALL_NR_ANON_ALLOCATE] = &Syscall::sys_anon_allocate,
};
}
// * rax system call number
// * rdi arg0
// * rsi arg1
// * rdx arg2
// * r10 arg3
// * r8 arg4
// * r9 arg5
void handle_syscall(Process *p, Context *c) {
auto syscall_num = c->rax;
if (syscall_num == SYSCALL_NR_NULL) {
Kernel::k->panic("Invalid null syscall");
} else if (syscall_num >= SYSCALL_NR_MAX) {
Kernel::k->panic("Invalid syscall >= max");
}
auto syscall_object = p->syscall_.get();
auto syscall_func_ptr = syscall_table[syscall_num];
c->rax = (syscall_object->*syscall_func_ptr)();
}
int Syscall::sys_read() {
return -1;
}
int Syscall::sys_write() {
auto &c = process_->context;
int fd = (int)c.rdi;
auto data = (const char*)c.rsi;
size_t size = c.rdx;
if (fd == 0) {
return (ssize_t)size;
} else if (fd == 1 || fd == 2) {
Kernel::sp() << "process <" << process_->id << ">: ";
for (size_t i = 0; i < size; i++) {
Kernel::sp() << data[i];
}
Kernel::sp() << "\n";
return size;
} else {
return -1;
}
}
int Syscall::sys_open() {
return -1;
}
int Syscall::sys_close() {
return -1;
}
int Syscall::sys_exit() {
Kernel::sp() << "process " << SerialPort::IntRadix::Dec << current_pid << " successfully exit, not implemented so halt\n";
halt();
return -1;
}
int Syscall::sys_yield() {
return 0;
}
int Syscall::sys_anon_allocate() {
auto &c = process_->context;
auto size = (size_t)c.rdi;
auto ptr = (void**)c.rsi;
auto &ret = c.rax;
Kernel::sp() << "process " << SerialPort::IntRadix::Dec << current_pid << " anon_allocate(0x" << IntRadix::Hex << size << ", 0x" << (u64)ptr << ")\n";
auto aligned_size = (size + (PAGE_SIZE-1)) / PAGE_SIZE * PAGE_SIZE;
auto buf = kmalloc(aligned_size);
auto buf_phy = kernel2phy((u64)buf);
auto brk_start = process_->brk_start;
process_->brk_start += aligned_size;
if (process_->brk_start > process_->brk_end) {
Kernel::sp() << "user brk overflow\n";
return -1;
}
process_->map_user_addr(brk_start, buf_phy, aligned_size / PAGE_SIZE);
*ptr = (void*)brk_start;
return 0;
}