diff --git a/hermit/arch/x86/include/asm/page.h b/hermit/arch/x86/include/asm/page.h index 8cb6adaa7..107476001 100644 --- a/hermit/arch/x86/include/asm/page.h +++ b/hermit/arch/x86/include/asm/page.h @@ -165,9 +165,23 @@ int page_init(void); * @param phyaddr Physical address to map from * @param npages The region's size in number of pages * @param bits Further page flags + * @param do_ipi if set, inform via IPI all other cores * @return */ -int page_map(size_t viraddr, size_t phyaddr, size_t npages, size_t bits); +int __page_map(size_t viraddr, size_t phyaddr, size_t npages, size_t bits, uint8_t do_ipi); + +/** @brief Map a continuous region of pages + * + * @param viraddr Desired virtual address + * @param phyaddr Physical address to map from + * @param npages The region's size in number of pages + * @param bits Further page flags + * @return + */ +static inline int page_map(size_t viraddr, size_t phyaddr, size_t npages, size_t bits) +{ + return __page_map(viraddr, phyaddr, npages, bits, 1); +} /** @brief Unmap a continuous region of pages * diff --git a/hermit/arch/x86/mm/page.c b/hermit/arch/x86/mm/page.c index bc6af9687..f034a0abb 100644 --- a/hermit/arch/x86/mm/page.c +++ b/hermit/arch/x86/mm/page.c @@ -112,7 +112,7 @@ int page_set_flags(size_t viraddr, uint32_t npages, int flags) return -EINVAL; } -int page_map(size_t viraddr, size_t phyaddr, size_t npages, size_t bits) +int __page_map(size_t viraddr, size_t phyaddr, size_t npages, size_t bits, uint8_t do_ipi) { int lvl, ret = -ENOMEM; long vpn = viraddr >> PAGE_BITS; @@ -169,7 +169,7 @@ int page_map(size_t viraddr, size_t phyaddr, size_t npages, size_t bits) } } - if (send_ipi) + if (do_ipi && send_ipi) ipi_tlb_flush(); ret = 0; @@ -246,8 +246,7 @@ void page_fault_handler(struct state *s) // on demand userspace heap mapping viraddr &= PAGE_MASK; - // TODO: a function to get zeroed pages is missing - size_t phyaddr = get_page(); + size_t phyaddr = get_zeroed_page(); if (BUILTIN_EXPECT(!phyaddr, 0)) { kprintf("out of memory: task = %u\n", task->id); goto default_handler; @@ -265,9 +264,6 @@ void page_fault_handler(struct state *s) goto default_handler; } - // reset page - memset(viraddr, 0x00, PAGE_SIZE); - spinlock_irqsave_unlock(&page_lock); return; diff --git a/hermit/include/hermit/memory.h b/hermit/include/hermit/memory.h index 4c77bc879..04ab0949e 100644 --- a/hermit/include/hermit/memory.h +++ b/hermit/include/hermit/memory.h @@ -48,6 +48,9 @@ size_t get_pages(size_t npages); */ static inline size_t get_page(void) { return get_pages(1); } +/** @brief Get a single zeroed page */ +size_t get_zeroed_page(void); + /** @brief release physical page frames */ int put_pages(size_t phyaddr, size_t npages); diff --git a/hermit/mm/memory.c b/hermit/mm/memory.c index 510e98728..eb6ad9366 100644 --- a/hermit/mm/memory.c +++ b/hermit/mm/memory.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -104,6 +105,40 @@ out: return ret; } +DEFINE_PER_CORE(size_t, ztmp_addr, 0); + +size_t get_zeroed_page(void) +{ + size_t phyaddr = get_page(); + size_t viraddr; + uint8_t flags; + + if (BUILTIN_EXPECT(!phyaddr, 0)) + return 0; + + flags = irq_nested_disable(); + + viraddr = per_core(ztmp_addr); + if (BUILTIN_EXPECT(!viraddr, 0)) + { + viraddr = vma_alloc(PAGE_SIZE, VMA_READ|VMA_WRITE|VMA_CACHEABLE); + if (BUILTIN_EXPECT(!viraddr, 0)) + goto novaddr; + + //kprintf("Core %d uses 0x%zx as temporary address\n", CORE_ID, viraddr); + set_per_core(ztmp_addr, viraddr); + } + + __page_map(viraddr, phyaddr, 1, PG_GLOBAL|PG_RW|PG_PRESENT, 0); + + memset((void*) viraddr, 0x00, PAGE_SIZE); + +novaddr: + irq_nested_enable(flags); + + return phyaddr; +} + /* TODO: reunion of elements is still missing */ int put_pages(size_t phyaddr, size_t npages) {