From: Matthias Kruk Date: Mon, 4 May 2020 08:26:15 +0000 (+0900) Subject: kernel/arch: Add pg_dir_memset() function, enhance pg_dir_mmap() function to support... X-Git-Url: https://git.corax.cc/?a=commitdiff_plain;h=1a2e9344c06ba4a8b2f84cb0e5109779b4fee2e6;p=corax kernel/arch: Add pg_dir_memset() function, enhance pg_dir_mmap() function to support mapping of virtual memory for text and data segments --- diff --git a/kernel/arch/paging.c b/kernel/arch/paging.c index 8e7d16e..99069e8 100644 --- a/kernel/arch/paging.c +++ b/kernel/arch/paging.c @@ -504,6 +504,68 @@ int pg_dir_memcpy(struct pagedir *ddir, void *dvaddr, return(ret_val); } +int _pg_dir_memset(struct pagedir *ddir, void *dvaddr, int c, u32_t n) +{ + int ret_val; + u32_t dpaddr; + u32_t wsize; + + ret_val = _pg_dir_vpxlate(ddir, (u32_t)dvaddr, (u32_t*)&dpaddr); + + if(ret_val < 0) { + goto gtfo; + } + + /* + * Calculate the number of bytes we can set without crossing + * page boundaries, writing into possibly unrelated pages. + */ + ret_val = _pg_dir_pagesize(ddir, (u32_t)dvaddr, &wsize); + + if(ret_val < 0) { + goto gtfo; + } + + wsize = ALIGN((u32_t)dvaddr, wsize) - (u32_t)dvaddr; + + memset((void*)dpaddr, c, wsize); + ret_val = (int)wsize; + +gtfo: + return(ret_val); +} + +int pg_dir_memset(struct pagedir *ddir, void *dvaddr, + int c, u32_t n) +{ + int ret_val; + + ret_val = 0; + + if(!ddir) { + /* kernel pagedir - just call memset() */ + memset(dvaddr, c, n); + return((int)n); + } + + while(n > 0) { + int set; + + set = _pg_dir_memset(ddir, dvaddr, c, n); + + if(set < 0) { + ret_val = set; + break; + } + + dvaddr += set; + n -= set; + ret_val += set; + } + + return(ret_val); +} + int _pg_dir_xfer(struct pagedir *ddir, void *dvaddr, struct pagedir *sdir, void *svaddr, u32_t bytes) { @@ -1440,7 +1502,7 @@ int pg_dir_foreach_region(pg_dir_t *pd, int (*func)(pg_dir_t*, region_t*, void*) } static int _pg_dir_add_region(pg_dir_t *pd, void *base, u32_t size, - u32_t type, u32_t attrs, u32_t flags) + u32_t type, u32_t attrs, u32_t flags) { struct region *reg; int ret_val; @@ -1622,48 +1684,65 @@ void pg_fault_debug(pg_dir_t *pdir, void *addr) return; } -int pg_dir_mmap(pg_dir_t *pgdir, void *addr, u32_t size, int prot, int flags, void **dst) +int pg_dir_mmap(pg_dir_t *pgdir, void *addr, u32_t size, + int prot, int flags, void **dst) { int ret_val; ret_val = -EINVAL; if(pgdir && dst) { + u32_t attrs; + u32_t rflags; + void* vaddr; + void* paddr; + ret_val = -EFAULT; /* FIXME: Lock the page directory */ - if(flags & MAP_PHYS) { - u32_t attrs; + attrs = PAGE_ATTR_PRESENT; - /* map the physical memory addr:size into the page directory */ - /* FIXME: Add another flag for identity mappings and otherwise map non-identically */ + if(!(prot & PROT_EXEC)) { + attrs |= PAGE_ATTR_NO_EXEC; + } - attrs = PAGE_ATTR_PRESENT; + if(prot & PROT_WRITE) { + attrs |= PAGE_ATTR_WRITABLE; + } - if(!(prot & PROT_EXEC)) { - attrs |= PAGE_ATTR_NO_EXEC; - } + if(prot & PROT_READ) { + attrs |= PAGE_ATTR_USER; + } - if(prot & PROT_WRITE) { - attrs |= PAGE_ATTR_WRITABLE; - } + rflags = REGION_PRIV; - if(prot & PROT_READ) { - attrs |= PAGE_ATTR_USER; - } + if(flags & MAP_PHYS) { + /* + * Map the physical memory addr:size into + * the page directory + */ - ret_val = pg_dir_map(pgdir, addr, addr, size, attrs); + vaddr = addr; + paddr = addr; + rflags = REGION_SHARED; + } - if(!ret_val) { - /* also account for the new region */ - ret_val = _pg_dir_add_region(pgdir, addr, size, - REGION_MMAP, 0, REGION_SHARED); + /* + * FIXME: Add another flag for identity mappings and + * otherwise map non-identically + */ + ret_val = pg_dir_map(pgdir, paddr, vaddr, size, attrs); - /* or unmap if it can't be accounted for */ - if(ret_val < 0) { - pg_dir_unmap(pgdir, addr, size); - } + if(!ret_val) { + /* also account for the new region */ + ret_val = _pg_dir_add_region(pgdir, addr, size, + REGION_MMAP, 0, + rflags); + + /* or unmap if it can't be accounted for */ + if(ret_val < 0) { + pg_dir_unmap(pgdir, addr, size); } } diff --git a/kernel/include/arch.h b/kernel/include/arch.h index 4741ab2..161fed5 100644 --- a/kernel/include/arch.h +++ b/kernel/include/arch.h @@ -237,6 +237,7 @@ void* pg_dir_get_ustack(pg_dir_t*); void* pg_dir_sbrk(pg_dir_t*, i32_t); int pg_dir_foreach_region(pg_dir_t*, int(*)(pg_dir_t*, struct region*, void*), void*); int pg_dir_memcpy(pg_dir_t*, void*, pg_dir_t*, void*, u32_t); +int pg_dir_memset(pg_dir_t*, void*, int, u32_t); int pg_dir_mmap(pg_dir_t*, void*, u32_t, int, int, void**); int pg_dir_munmap(pg_dir_t*, void*, u32_t);