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
|
/* SPDX-License-Identifier: GPL-3.0-or-later */
/* Copyright 2021 - 2022, Kim Kuparinen < kimi.h.kuparinen@gmail.com > */
/**
* @file mem.c
* Memory handling syscall implementations.
* \todo Should we return more error information?
*/
#include <apos/uapi.h>
#include <apos/utils.h>
#include <apos/vmem.h>
#include <apos/dmem.h>
/**
* Memory request syscall handler.
*
* @param t Current tcb.
* @param size Minimum size of allocation.
* @param flags Flags of allocation.
* @return \ref OK and start of allocation when succesful,
* \ref ERR_OOMEM and \c NULL otherwise.
*/
SYSCALL_DEFINE2(req_mem)(struct tcb *t, sys_arg_t size, sys_arg_t flags)
{
struct tcb *r = get_cproc(t);
vm_t start = 0;
/** @todo expose flags to users */
if (!(start = alloc_uvmem(r, size, flags)))
return_args(t, SYS_RET1(ERR_OOMEM));
return_args(t, SYS_RET2(OK, start));
}
/**
* Fixed memory request syscall handler.
*
* @param t Current tcb.
* @param fixed Address which should be included in allocation.
* @param size Minimum size of allocation after \c start.
* @param flags Flags of allocation.
* @return \ref OK and start of allocation when succesful,
* \ref ERR_OOMEM and \c NULL otherwise.
*/
SYSCALL_DEFINE3(req_fixmem)(struct tcb *t, sys_arg_t fixed, sys_arg_t size,
sys_arg_t flags)
{
struct tcb *r = get_cproc(t);
vm_t start = 0;
if (!(start = alloc_fixed_uvmem(r, fixed, size, flags)))
return_args(t, SYS_RET1(ERR_OOMEM));
return_args(t, SYS_RET2(OK, start));
}
/**
* Free memory syscall handler.
*
* @param t Current tcb.
* @param start Start of allocation to free.
* @return \ref OK and \c 0 when succesful, \ref ERR_NF and \c 0 otherwise.
*/
SYSCALL_DEFINE1(free_mem)(struct tcb *t, sys_arg_t start)
{
struct tcb *r = get_cproc(t);
vm_t vm_start = (vm_t)start;
stat_t status = OK;
/* try freeing normal user memory first, if that fails, try device
* memory, otherwise just assume the address is borked. */
if (!(status = free_uvmem(r, vm_start)))
return_args(t, SYS_RET1(OK));
if (!(status = free_devmem(r, vm_start)))
return_args(t, SYS_RET1(OK));
return_args(t, SYS_RET1(status));
}
/**
* Request physical memory syscall handler.
*
* @param t Current tcb.
* @param paddr Physical address to map.
* @param size Minimum size of allocation.
* @param flags Flags of allocation.
* @return \ref OK and start of allocation when succesful,
* \ref ERR_OOMEM and \c NULL otherwise.
*/
SYSCALL_DEFINE3(req_pmem)(struct tcb *t, sys_arg_t paddr, sys_arg_t size,
sys_arg_t flags)
{
/* this will require some pondering, but essentially this syscall should
* only be used for device access, so any addresses requested should be
* outside the RAM area, and I'll probably have to implement some method
* that keeps track of used regions outside of RAM. We'll see.
*/
struct tcb *r = get_cproc(t);
vm_t start = 0;
if (!(start = alloc_devmem(r, paddr, size, flags)))
return_args(t, SYS_RET1(ERR_OOMEM));
return_args(t, SYS_RET2(OK, start));
}
/**
* Request shared memory syscall handler.
*
* @param t Current tcb.
* @param size Minimum size of allocation.
* @param flags Flags of allocation.
* @return \ref OK and start of allocation when succesful,
* \ref ERR_OOMEM and \c NULL otherwise.
*
* @todo should we also take the thread who should get the other end of the
* memory?
*/
SYSCALL_DEFINE2(req_sharedmem)(struct tcb *t, sys_arg_t size, sys_arg_t flags)
{
/** \todo check that requester is server */
struct tcb *r = get_cproc(t);
vm_t start = 0;
if (!(start = alloc_shared_uvmem(r, size, flags)))
return_args(t, SYS_RET1(ERR_OOMEM));
return_args(t, SYS_RET2(OK, start));
}
/** \todo add some way to specify who gets to access the shared memory? */
|