diff --git a/arch/x86/pagetables.c b/arch/x86/pagetables.c index 1d7b1a9e..6c99ac42 100644 --- a/arch/x86/pagetables.c +++ b/arch/x86/pagetables.c @@ -322,6 +322,7 @@ void *__vmap(cr3_t *cr3_ptr, void *va, mfn_t mfn, unsigned int order, invlpg(va); done: + refill_from_paging(); return va; } static void *_vmap(cr3_t *cr3_ptr, void *va, mfn_t mfn, unsigned int order, @@ -337,11 +338,13 @@ void *__vmap_paging(cr3_t *cr3_ptr, void *va, mfn_t mfn, unsigned int order, unsigned long l4_flags, #endif unsigned long l3_flags, unsigned long l2_flags, - unsigned long l1_flags, bool special_path) { - spin_lock(&vmap_lock); + unsigned long l1_flags, bool special_path, bool take_lock) { + if (take_lock) + spin_lock(&vmap_lock); void *res = __vmap(cr3_ptr, va, mfn, order, l4_flags, l3_flags, l2_flags, l1_flags, special_path); - spin_unlock(&vmap_lock); + if (take_lock) + spin_unlock(&vmap_lock); return res; } diff --git a/include/arch/x86/pagetable.h b/include/arch/x86/pagetable.h index 5b6399a6..fdf1688a 100644 --- a/include/arch/x86/pagetable.h +++ b/include/arch/x86/pagetable.h @@ -240,11 +240,11 @@ static inline pte_t *l1_table_entry(pte_t *tab, const void *va) { } static inline pgentry_t pgentry_from_paddr(paddr_t pa, unsigned long flags) { - return (pgentry_t) ((pa & ~(PADDR_MASK & PAGE_MASK)) | (flags & _PAGE_ALL_FLAGS)); + return (pgentry_t)((pa & ~(PADDR_MASK & PAGE_MASK)) | (flags & _PAGE_ALL_FLAGS)); } static inline paddr_t paddr_from_pgentry(pgentry_t pgentry) { - return (paddr_t) (pgentry & ~PADDR_MASK) & PAGE_MASK; + return (paddr_t)(pgentry & ~PADDR_MASK) & PAGE_MASK; } static inline pgentry_t pgentry_from_mfn(mfn_t mfn, unsigned long flags) { @@ -391,7 +391,7 @@ void *__vmap_paging(cr3_t *cr3_ptr, void *va, mfn_t mfn, unsigned int order, unsigned long l4_flags, #endif unsigned long l3_flags, unsigned long l2_flags, - unsigned long l1_flags, bool special_path); + unsigned long l1_flags, bool special_path, bool paging_lock); #endif /* __ASSEMBLY__ */ diff --git a/include/mm/pmm.h b/include/mm/pmm.h index 454dcdca..330f82d7 100644 --- a/include/mm/pmm.h +++ b/include/mm/pmm.h @@ -142,6 +142,7 @@ static inline bool is_frame_free(const frame_t *frame) { return frame->flags.free; } +void refill_from_paging(void); frame_t *get_backup_frame(void); frame_t *_get_backup_frame(void); diff --git a/mm/pmm.c b/mm/pmm.c index 33c1dabc..a839da6d 100644 --- a/mm/pmm.c +++ b/mm/pmm.c @@ -41,7 +41,9 @@ static frames_array_t early_frames; static list_head_t free_frames[MAX_PAGE_ORDER + 1]; static list_head_t busy_frames[MAX_PAGE_ORDER + 1]; -#define MIN_NUM_4K_FRAMES 2 + 4 + (MAX_PAGE_ORDER - PAGE_ORDER_4K) +/* 1 frame for array frame, 3 for mapping it and then one additional frame for each page + * order we might have to split */ +#define MIN_NUM_4K_FRAMES 1 + 3 + (MAX_PAGE_ORDER - PAGE_ORDER_4K) static size_t frames_count[MAX_PAGE_ORDER + 1]; static spinlock_t lock = SPINLOCK_INIT; @@ -97,7 +99,7 @@ static inline void init_frames_array(frames_array_t *array) { list_add(&array->list, &frames); } -static frames_array_t *new_frames_array(void) { +static frames_array_t *new_frames_array(bool paging_lock) { frames_array_t *array; frame_t *frame; @@ -111,7 +113,8 @@ static frames_array_t *new_frames_array(void) { array = __vmap_paging( &cr3, _ptr(_ul(mfn_to_virt_map(frame->mfn)) & PAGE_ORDER_TO_MASK(PAGE_ORDER_4K)), - frame->mfn, PAGE_ORDER_4K, L4_PROT, L3_PROT, L2_PROT, L1_PROT, true); + frame->mfn, PAGE_ORDER_4K, L4_PROT, L3_PROT, L2_PROT, L1_PROT, true, + paging_lock); if (!array) goto error; } @@ -160,7 +163,18 @@ static inline frames_array_t *get_frames_array(void) { return array; } - return new_frames_array(); + return new_frames_array(false); +} + +static inline size_t get_frames_array_space(void) { + size_t space = 0; + frames_array_t *array; + + list_for_each_entry (array, &frames, list) { + space += array->meta.free_count; + } + + return space; } static inline bool put_frames_array(frames_array_t *array) { @@ -195,7 +209,7 @@ static inline frame_t *take_frame(frame_t *frame, frames_array_t *array) { array->meta.free_count--; if (--total_free_frames <= MIN_FREE_FRAMES_THRESHOLD) - new_frames_array(); + new_frames_array(false); return frame; } @@ -693,3 +707,13 @@ void map_frames_array(void) { BUG_ON(!vmap_kern_4k(va, mfn, L1_PROT)); } } + +void refill_from_paging(void) { + // make sure we have enough space to refill the 4K frames + // so we need space for one frame per + if (get_frames_array_space() < MIN_NUM_4K_FRAMES) { + new_frames_array(false); + } + + try_create_4k_frames(); +} \ No newline at end of file