diff options
author | Marvin Borner | 2021-03-21 00:13:13 +0100 |
---|---|---|
committer | Marvin Borner | 2021-03-21 00:13:13 +0100 |
commit | 68a0ad7f21ba07b93cd63613996e27afd8780f9c (patch) | |
tree | 1fb7ff055743737ab5903d81507ea4732e45e095 /kernel | |
parent | 535018ae7247ede06606e4d8aced2d12c761f28f (diff) |
Added basic shared memory support
This will be improved soon. It's very insecure right now.
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/features/mm.c | 89 | ||||
-rw-r--r-- | kernel/features/syscall.c | 50 | ||||
-rw-r--r-- | kernel/inc/mm.h | 4 |
3 files changed, 101 insertions, 42 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; diff --git a/kernel/inc/mm.h b/kernel/inc/mm.h index e506331..5e30be6 100644 --- a/kernel/inc/mm.h +++ b/kernel/inc/mm.h @@ -104,8 +104,10 @@ struct memory_range memory_range_around(u32 base, u32 size); void *memory_alloc(struct page_dir *dir, u32 size, u32 flags); void *memory_alloc_identity(struct page_dir *dir, u32 flags); -void memory_map_identity(struct page_dir *dir, struct memory_range prange, u32 flags); +u32 memory_shalloc(struct page_dir *dir, u32 size, u32 flags); +void *memory_shaccess(struct page_dir *dir, u32 shid); void memory_free(struct page_dir *dir, struct memory_range vrange); +void memory_map_identity(struct page_dir *dir, struct memory_range prange, u32 flags); void memory_switch_dir(struct page_dir *dir); void memory_backup_dir(struct page_dir **backup); |