aboutsummaryrefslogtreecommitdiff
path: root/kernel/features
diff options
context:
space:
mode:
authorMarvin Borner2021-03-21 00:13:13 +0100
committerMarvin Borner2021-03-21 00:13:13 +0100
commit68a0ad7f21ba07b93cd63613996e27afd8780f9c (patch)
tree1fb7ff055743737ab5903d81507ea4732e45e095 /kernel/features
parent535018ae7247ede06606e4d8aced2d12c761f28f (diff)
Added basic shared memory support
This will be improved soon. It's very insecure right now.
Diffstat (limited to 'kernel/features')
-rw-r--r--kernel/features/mm.c89
-rw-r--r--kernel/features/syscall.c50
2 files changed, 98 insertions, 41 deletions
diff --git a/kernel/features/mm.c b/kernel/features/mm.c
index d14bd81..a8e7e22 100644
--- a/kernel/features/mm.c
+++ b/kernel/features/mm.c
@@ -8,6 +8,7 @@
#include <mem.h>
#include <mm.h>
#include <print.h>
+#include <random.h>
static struct page_dir kernel_dir ALIGNED(PAGE_SIZE) = { 0 };
static struct page_table kernel_tables[PAGE_KERNEL_COUNT] ALIGNED(PAGE_SIZE) = { 0 };
@@ -353,7 +354,7 @@ void *memory_alloc(struct page_dir *dir, u32 size, u32 flags)
return (void *)vaddr;
err:
- printf("Memory allocation error!\n");
+ print("Memory allocation error!\n");
return NULL;
}
@@ -374,10 +375,96 @@ void *memory_alloc_identity(struct page_dir *dir, u32 flags)
return 0;
}
+#define SHARED_MEMORY_MAX 128
+struct shared_memory {
+ u32 id;
+ u32 refs;
+ u8 used;
+ struct memory_range prange;
+};
+static struct shared_memory shmem[SHARED_MEMORY_MAX] = { 0 };
+u32 memory_shalloc(struct page_dir *dir, u32 size, u32 flags)
+{
+ u32 slot = SHARED_MEMORY_MAX + 1;
+
+ for (u32 i = 0; i < SHARED_MEMORY_MAX; i++) {
+ if (!shmem[i].used) {
+ slot = i;
+ break;
+ }
+ }
+
+ if (slot >= SHARED_MEMORY_MAX)
+ return 0;
+
+ void *addr = memory_alloc(dir, size, flags);
+ if (!addr)
+ return 0;
+
+ // TODO: Verify that shid isn't used already
+ // TODO: Check for colliding prange
+ u32 shid = rand() + 1;
+ shmem[slot].id = shid;
+ shmem[slot].used = 1;
+ shmem[slot].prange = memory_range(virtual_to_physical(dir, (u32)addr), size);
+
+ return shid;
+}
+
+static struct shared_memory memory_shresolve_range(struct memory_range prange)
+{
+ for (u32 i = 0; i < SHARED_MEMORY_MAX; i++) {
+ if (!shmem[i].used)
+ continue;
+
+ struct memory_range shrange = shmem[i].prange;
+ if (prange.base < shrange.base + shrange.size &&
+ prange.base + prange.size > shrange.base)
+ return shmem[i];
+ }
+
+ return (struct shared_memory){ 0, 0, 0, memory_range(0, 0) };
+}
+
+static struct shared_memory memory_shresolve_id(u32 shid)
+{
+ for (u32 i = 0; i < SHARED_MEMORY_MAX; i++) {
+ if (!shmem[i].used)
+ continue;
+
+ if (shmem[i].id == shid)
+ return shmem[i];
+ }
+
+ return shmem[0];
+}
+
+void *memory_shaccess(struct page_dir *dir, u32 shid)
+{
+ struct shared_memory sh = memory_shresolve_id(shid);
+ struct memory_range prange = sh.prange;
+ if (sh.used == 0 || prange.base == 0 || prange.size == 0)
+ return NULL;
+
+ sh.refs++;
+
+ return (void *)virtual_alloc(dir, prange, MEMORY_CLEAR | MEMORY_USER).base;
+}
+
+// TODO: Free by address instead of vrange (combine with shmem map?)
void memory_free(struct page_dir *dir, struct memory_range vrange)
{
assert(PAGE_ALIGNED(vrange.base) && PAGE_ALIGNED(vrange.size));
+ struct memory_range prange =
+ memory_range(virtual_to_physical(dir, vrange.base), vrange.size);
+ struct shared_memory sh = memory_shresolve_range(prange);
+ if (sh.used != 0 && sh.refs > 1) {
+ panic("Freeing busy memory!\n");
+ return;
+ }
+ /* sh.used = 0; */
+
for (u32 i = 0; i < vrange.size / PAGE_SIZE; i++) {
u32 vaddr = vrange.base + i * PAGE_SIZE;
if (virtual_present(dir, vaddr)) {
diff --git a/kernel/features/syscall.c b/kernel/features/syscall.c
index 7d68d93..c59c423 100644
--- a/kernel/features/syscall.c
+++ b/kernel/features/syscall.c
@@ -29,10 +29,19 @@ static void syscall_handler(struct regs *r)
break;
}
case SYS_ALLOC: {
- r->eax = (u32)memory_alloc(proc_current()->page_dir, r->ebx,
+ r->eax = (u32)memory_alloc(proc_current()->page_dir, PAGE_ALIGN_UP(r->ebx),
MEMORY_CLEAR | MEMORY_USER);
break;
}
+ case SYS_SHALLOC: {
+ r->eax = (u32)memory_shalloc(proc_current()->page_dir, PAGE_ALIGN_UP(r->ebx),
+ MEMORY_CLEAR | MEMORY_USER);
+ break;
+ }
+ case SYS_SHACCESS: {
+ r->eax = (u32)memory_shaccess(proc_current()->page_dir, r->ebx);
+ break;
+ }
case SYS_FREE: {
memory_free(proc_current()->page_dir, memory_range(r->ebx, r->ecx));
break;
@@ -123,45 +132,6 @@ static void syscall_handler(struct regs *r)
break;
}
// TODO: Reimplement network functions using VFS
- case SYS_NET_OPEN:
- case SYS_NET_CLOSE:
- case SYS_NET_CONNECT:
- case SYS_NET_SEND:
- case SYS_NET_RECEIVE:
-#if 0
- case SYS_NET_OPEN: {
- r->eax = (int)net_open(r->ebx);
- break;
- }
- case SYS_NET_CLOSE: {
- struct socket *s = (void *)r->ebx;
- int status = net_close(s);
- if (!status) {
- proc_yield(r);
- return;
- }
- r->eax = net_close(s);
- break;
- }
- case SYS_NET_CONNECT: {
- struct socket *s = (void *)r->ebx;
- if (s->state == S_CONNECTED)
- r->eax = 1;
- else if (s->state == S_FAILED || s->state == S_CLOSED)
- r->eax = 0;
- else if (s->state == S_OPEN)
- r->eax = net_connect(s, r->ecx, r->edx);
- break;
- }
- case SYS_NET_SEND: {
- net_send((void *)r->ebx, (void *)r->ecx, r->edx);
- break;
- }
- case SYS_NET_RECEIVE: {
- r->eax = net_receive((void *)r->ebx, (void *)r->ecx, r->edx);
- break;
- }
-#endif
default: {
printf("Unknown syscall %d!\n", num);
break;