From 838b142b7374150df63ec02b02377c114a14b314 Mon Sep 17 00:00:00 2001 From: dzwdz Date: Sun, 5 Sep 2021 18:32:08 +0200 Subject: move most of the memory stuff to kernel/mem/ --- src/kernel/arch/i386/pagedir.c | 2 +- src/kernel/main.c | 2 +- src/kernel/mem.c | 115 ----------------------------------------- src/kernel/mem.h | 41 --------------- src/kernel/mem/alloc.c | 38 ++++++++++++++ src/kernel/mem/alloc.h | 15 ++++++ src/kernel/mem/virt.c | 78 ++++++++++++++++++++++++++++ src/kernel/mem/virt.h | 28 ++++++++++ src/kernel/proc.c | 2 +- src/kernel/syscalls.c | 3 +- src/kernel/tests/vfs.c | 2 +- src/kernel/vfs/mount.c | 2 +- src/kernel/vfs/root.c | 2 +- 13 files changed, 167 insertions(+), 163 deletions(-) delete mode 100644 src/kernel/mem.c delete mode 100644 src/kernel/mem.h create mode 100644 src/kernel/mem/alloc.c create mode 100644 src/kernel/mem/alloc.h create mode 100644 src/kernel/mem/virt.c create mode 100644 src/kernel/mem/virt.h (limited to 'src/kernel') diff --git a/src/kernel/arch/i386/pagedir.c b/src/kernel/arch/i386/pagedir.c index 8f62a45..2fc96f4 100644 --- a/src/kernel/arch/i386/pagedir.c +++ b/src/kernel/arch/i386/pagedir.c @@ -1,5 +1,5 @@ #include -#include +#include #include #include diff --git a/src/kernel/main.c b/src/kernel/main.c index cc8e10d..97fd6f1 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -1,6 +1,6 @@ #include #include -#include +#include #include #include #include diff --git a/src/kernel/mem.c b/src/kernel/mem.c deleted file mode 100644 index 55b0361..0000000 --- a/src/kernel/mem.c +++ /dev/null @@ -1,115 +0,0 @@ -#include -#include -#include -#include - -static void *highest_page; - -void mem_init(struct kmain_info *info) { - // finds the highest used page, and starts allocating pages above it - void *highest = &_bss_end; - - if (highest < info->init.at + info->init.size) - highest = info->init.at + info->init.size; - - // align up to PAGE_SIZE - highest_page = (void*)(((uintptr_t)highest + PAGE_MASK) & ~PAGE_MASK); -} - -void *page_alloc(size_t pages) { - void *bottom = highest_page; - highest_page += pages * PAGE_SIZE; - return bottom; -} - -// frees `pages` consecutive pages starting from *first -void page_free(void *first, size_t pages) { - // not implemented -} - - -void *kmalloc(size_t len) { - // extremely inefficient, but this is only temporary anyways - return page_alloc(len / PAGE_SIZE + 1); -} - -void kfree(void *ptr) { - // unimplemented -} - - -// TODO move to some shared file in kernel/arch/ -void virt_iter_new( - struct virt_iter *iter, user_ptr virt, size_t length, - struct pagedir *pages, bool user, bool writeable) -{ - iter->frag = 0; - iter->frag_len = 0; - iter->prior = 0; - iter->error = false; - iter->_virt = virt; - iter->_remaining = length; - iter->_pages = pages; - iter->_user = user; - iter->_writeable = writeable; -} - -bool virt_iter_next(struct virt_iter *iter) { - /* note: While i'm pretty sure that this should always work, this - * was only tested in cases where the pages were consecutive both in - * virtual and physical memory, which might not always be the case. - * TODO test this */ - - user_ptr virt = iter->_virt; - size_t partial = iter->_remaining; - iter->prior += iter->frag_len; - if (partial <= 0) return false; - - // don't read past the page - if ((virt & PAGE_MASK) + partial > PAGE_SIZE) - partial = PAGE_SIZE - (virt & PAGE_MASK); - - iter->frag = pagedir_virt2phys(iter->_pages, - iter->_virt, iter->_user, iter->_writeable); - - if (iter->frag == 0) { - iter->error = true; - return false; - } - - iter->frag_len = partial; - iter->_remaining -= partial; - iter->_virt += partial; - return true; -} - -bool virt_user_cpy( - struct pagedir *dest_pages, user_ptr dest, - struct pagedir *src_pages, const user_ptr src, size_t length) -{ - struct virt_iter dest_iter, src_iter; - size_t min; - - virt_iter_new(&dest_iter, dest, length, dest_pages, true, true); - virt_iter_new( &src_iter, src, length, src_pages, true, false); - dest_iter.frag_len = 0; - src_iter.frag_len = 0; - - for (;;) { - if (dest_iter.frag_len <= 0) - if (!virt_iter_next(&dest_iter)) break; - if ( src_iter.frag_len <= 0) - if (!virt_iter_next( &src_iter)) break; - - min = src_iter.frag_len < dest_iter.frag_len - ? src_iter.frag_len : dest_iter.frag_len; - memcpy(dest_iter.frag, src_iter.frag, min); - - dest_iter.frag_len -= min; - dest_iter.frag += min; - src_iter.frag_len -= min; - src_iter.frag += min; - } - - return !(dest_iter.error || src_iter.error); -} diff --git a/src/kernel/mem.h b/src/kernel/mem.h deleted file mode 100644 index 5184ec5..0000000 --- a/src/kernel/mem.h +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once -#include -#include -#include -#include - -void mem_init(struct kmain_info *); - -// allocates `pages` consecutive pages -void *page_alloc(size_t pages); - -// frees `pages` consecutive pages starting from *first -void page_free(void *first, size_t pages); - -void *kmalloc(size_t len); -void kfree(void *ptr); - - -// used for iterating through some part of a process' memory -struct virt_iter { - void *frag; - size_t frag_len; - size_t prior; // sum of all prior frag_lens - bool error; - - user_ptr _virt; - size_t _remaining; - struct pagedir *_pages; - bool _user; - bool _writeable; -}; - -void virt_iter_new( - struct virt_iter *iter, user_ptr virt, size_t length, - struct pagedir *pages, bool user, bool writeable); - -bool virt_iter_next(struct virt_iter *); - -bool virt_user_cpy( - struct pagedir *dest_pages, user_ptr dest, - struct pagedir *src_pages, const user_ptr src, size_t length); diff --git a/src/kernel/mem/alloc.c b/src/kernel/mem/alloc.c new file mode 100644 index 0000000..42a2f3b --- /dev/null +++ b/src/kernel/mem/alloc.c @@ -0,0 +1,38 @@ +#include +#include +#include +#include + +static void *highest_page; + +void mem_init(struct kmain_info *info) { + // finds the highest used page, and starts allocating pages above it + void *highest = &_bss_end; + + if (highest < info->init.at + info->init.size) + highest = info->init.at + info->init.size; + + // align up to PAGE_SIZE + highest_page = (void*)(((uintptr_t)highest + PAGE_MASK) & ~PAGE_MASK); +} + +void *page_alloc(size_t pages) { + void *bottom = highest_page; + highest_page += pages * PAGE_SIZE; + return bottom; +} + +// frees `pages` consecutive pages starting from *first +void page_free(void *first, size_t pages) { + // not implemented +} + + +void *kmalloc(size_t len) { + // extremely inefficient, but this is only temporary anyways + return page_alloc(len / PAGE_SIZE + 1); +} + +void kfree(void *ptr) { + // unimplemented +} diff --git a/src/kernel/mem/alloc.h b/src/kernel/mem/alloc.h new file mode 100644 index 0000000..571b289 --- /dev/null +++ b/src/kernel/mem/alloc.h @@ -0,0 +1,15 @@ +#pragma once +#include +#include +#include + +void mem_init(struct kmain_info *); + +// allocates `pages` consecutive pages +void *page_alloc(size_t pages); + +// frees `pages` consecutive pages starting from *first +void page_free(void *first, size_t pages); + +void *kmalloc(size_t len); +void kfree(void *ptr); diff --git a/src/kernel/mem/virt.c b/src/kernel/mem/virt.c new file mode 100644 index 0000000..2990668 --- /dev/null +++ b/src/kernel/mem/virt.c @@ -0,0 +1,78 @@ +#include +#include +#include + +void virt_iter_new( + struct virt_iter *iter, user_ptr virt, size_t length, + struct pagedir *pages, bool user, bool writeable) +{ + iter->frag = 0; + iter->frag_len = 0; + iter->prior = 0; + iter->error = false; + iter->_virt = virt; + iter->_remaining = length; + iter->_pages = pages; + iter->_user = user; + iter->_writeable = writeable; +} + +bool virt_iter_next(struct virt_iter *iter) { + /* note: While i'm pretty sure that this should always work, this + * was only tested in cases where the pages were consecutive both in + * virtual and physical memory, which might not always be the case. + * TODO test this */ + + user_ptr virt = iter->_virt; + size_t partial = iter->_remaining; + iter->prior += iter->frag_len; + if (partial <= 0) return false; + + // don't read past the page + if ((virt & PAGE_MASK) + partial > PAGE_SIZE) + partial = PAGE_SIZE - (virt & PAGE_MASK); + + iter->frag = pagedir_virt2phys(iter->_pages, + iter->_virt, iter->_user, iter->_writeable); + + if (iter->frag == 0) { + iter->error = true; + return false; + } + + iter->frag_len = partial; + iter->_remaining -= partial; + iter->_virt += partial; + return true; +} + +bool virt_user_cpy( + struct pagedir *dest_pages, user_ptr dest, + struct pagedir *src_pages, const user_ptr src, size_t length) +{ + struct virt_iter dest_iter, src_iter; + size_t min; + + virt_iter_new(&dest_iter, dest, length, dest_pages, true, true); + virt_iter_new( &src_iter, src, length, src_pages, true, false); + dest_iter.frag_len = 0; + src_iter.frag_len = 0; + + for (;;) { + if (dest_iter.frag_len <= 0) + if (!virt_iter_next(&dest_iter)) break; + if ( src_iter.frag_len <= 0) + if (!virt_iter_next( &src_iter)) break; + + min = src_iter.frag_len < dest_iter.frag_len + ? src_iter.frag_len : dest_iter.frag_len; + memcpy(dest_iter.frag, src_iter.frag, min); + + dest_iter.frag_len -= min; + dest_iter.frag += min; + src_iter.frag_len -= min; + src_iter.frag += min; + } + + return !(dest_iter.error || src_iter.error); +} diff --git a/src/kernel/mem/virt.h b/src/kernel/mem/virt.h new file mode 100644 index 0000000..98a7a16 --- /dev/null +++ b/src/kernel/mem/virt.h @@ -0,0 +1,28 @@ +/* contains utilities for interacting with virtual memory */ +#pragma once +#include +#include +#include + +struct virt_iter { + void *frag; + size_t frag_len; + size_t prior; // sum of all prior frag_lens + bool error; + + user_ptr _virt; + size_t _remaining; + struct pagedir *_pages; + bool _user; + bool _writeable; +}; + +void virt_iter_new( + struct virt_iter *iter, user_ptr virt, size_t length, + struct pagedir *pages, bool user, bool writeable); + +bool virt_iter_next(struct virt_iter *); + +bool virt_user_cpy( + struct pagedir *dest_pages, user_ptr dest, + struct pagedir *src_pages, const user_ptr src, size_t length); diff --git a/src/kernel/proc.c b/src/kernel/proc.c index e504a5d..445536a 100644 --- a/src/kernel/proc.c +++ b/src/kernel/proc.c @@ -1,5 +1,5 @@ #include -#include +#include #include #include #include diff --git a/src/kernel/syscalls.c b/src/kernel/syscalls.c index 0a53a00..416c815 100644 --- a/src/kernel/syscalls.c +++ b/src/kernel/syscalls.c @@ -1,5 +1,6 @@ #include -#include +#include +#include #include #include #include diff --git a/src/kernel/tests/vfs.c b/src/kernel/tests/vfs.c index 0871f92..69e40af 100644 --- a/src/kernel/tests/vfs.c +++ b/src/kernel/tests/vfs.c @@ -1,4 +1,4 @@ -#include +#include #include #include #include diff --git a/src/kernel/vfs/mount.c b/src/kernel/vfs/mount.c index 07eed0d..37bfe63 100644 --- a/src/kernel/vfs/mount.c +++ b/src/kernel/vfs/mount.c @@ -1,4 +1,4 @@ -#include +#include #include #include diff --git a/src/kernel/vfs/root.c b/src/kernel/vfs/root.c index 0f11a5b..5b23555 100644 --- a/src/kernel/vfs/root.c +++ b/src/kernel/vfs/root.c @@ -1,4 +1,4 @@ -#include +#include #include #include #include -- cgit v1.2.3