Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement API to find the frame for a given virtual address #313

Merged
merged 3 commits into from
Nov 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 100 additions & 0 deletions arch/x86/pagetables.c
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,106 @@ int vunmap_user(void *va, mfn_t *mfn, unsigned int *order) {
return err;
}

static int get_va_mfn_order(const cr3_t *cr3_ptr, const void *va, mfn_t *mfn,
unsigned int *order) {
unsigned int _order;
mfn_t _mfn;
pgentry_t *tab;

ASSERT(mfn || order);
if (mfn_invalid(cr3_ptr->mfn))
return -EINVAL;

tab = tmp_map_mfn(cr3_ptr->mfn);
#if defined(__x86_64__)
pml4_t *l4e = l4_table_entry((pml4_t *) tab, va);
if (mfn_invalid(l4e->mfn) || !l4e->P)
return -ENOENT;

tab = tmp_map_mfn(l4e->mfn);
#endif
pdpe_t *l3e = l3_table_entry((pdpe_t *) tab, va);
if (mfn_invalid(l3e->mfn) || !l3e->P)
return -ENOENT;

if (l3e->PS) {
_mfn = l3e->mfn;
_order = PAGE_ORDER_1G;
goto done;
}

tab = tmp_map_mfn(l3e->mfn);
pde_t *l2e = l2_table_entry((pde_t *) tab, va);
if (mfn_invalid(l2e->mfn) || !l2e->P)
return -ENOENT;

if (l2e->PS) {
_mfn = l2e->mfn;
_order = PAGE_ORDER_2M;
goto done;
}

tab = tmp_map_mfn(l2e->mfn);
pte_t *l1e = l1_table_entry((pte_t *) tab, va);
if (mfn_invalid(l1e->mfn) || !l1e->P)
return -ENOENT;

_mfn = l1e->mfn;
minipli-oss marked this conversation as resolved.
Show resolved Hide resolved
_order = PAGE_ORDER_4K;

done:
if (mfn)
*mfn = _mfn;
if (order)
*order = _order;
sktt marked this conversation as resolved.
Show resolved Hide resolved

return 0;
}

int get_kern_va_mfn_order(void *va, mfn_t *mfn, unsigned int *order) {
int err;

dprintk("%s: va: 0x%p (cr3: 0x%p)\n", __func__, va, &cr3);

spin_lock(&vmap_lock);
err = get_va_mfn_order(&cr3, va, mfn, order);
spin_unlock(&vmap_lock);

return err;
}

int get_user_va_mfn_order(void *va, mfn_t *mfn, unsigned int *order) {
int err;

dprintk("%s: va: 0x%p (cr3: 0x%p)\n", __func__, va, &user_cr3);

spin_lock(&vmap_lock);
err = get_va_mfn_order(&user_cr3, va, mfn, order);
spin_unlock(&vmap_lock);

return err;
}

static frame_t *find_va_frame(const cr3_t *cr3_ptr, const void *va) {
unsigned int order;
mfn_t mfn;
int err;

spin_lock(&vmap_lock);
err = get_va_mfn_order(cr3_ptr, va, &mfn, &order);
spin_unlock(&vmap_lock);

return err ? NULL : find_mfn_frame(mfn, order);
}

frame_t *find_kern_va_frame(const void *va) {
return find_va_frame(&cr3, va);
}

frame_t *find_user_va_frame(const void *va) {
return find_va_frame(&user_cr3, va);
}

static inline void init_cr3(cr3_t *cr3_ptr) {
memset(cr3_ptr, 0, sizeof(*cr3_ptr));
cr3_ptr->mfn = MFN_INVALID;
Expand Down
6 changes: 6 additions & 0 deletions include/arch/x86/pagetable.h
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,12 @@ extern void dump_pagetables(cr3_t *cr3_ptr);
extern void dump_kern_pagetable_va(void *va);
extern void dump_user_pagetable_va(void *va);

extern int get_kern_va_mfn_order(void *va, mfn_t *mfn, unsigned int *order);
extern int get_user_va_mfn_order(void *va, mfn_t *mfn, unsigned int *order);

extern frame_t *find_kern_va_frame(const void *va);
extern frame_t *find_user_va_frame(const void *va);

#endif /* __ASSEMBLY__ */

#endif /* KTF_PAGETABLE_H */
17 changes: 17 additions & 0 deletions include/mm/pmm.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,13 @@ extern frame_t *get_free_frames(unsigned int order);
extern void put_free_frames(mfn_t mfn, unsigned int order);
extern void reclaim_frame(mfn_t mfn, unsigned int order);

extern frame_t *find_free_mfn_frame(mfn_t mfn, unsigned int order);
extern frame_t *find_busy_mfn_frame(mfn_t mfn, unsigned int order);
extern frame_t *find_mfn_frame(mfn_t mfn, unsigned int order);
extern frame_t *find_free_paddr_frame(paddr_t paddr);
extern frame_t *find_busy_paddr_frame(paddr_t paddr);
extern frame_t *find_paddr_frame(paddr_t paddr);
sktt marked this conversation as resolved.
Show resolved Hide resolved

extern void map_used_memory(void);
extern void map_frames_array(void);

Expand All @@ -100,6 +107,16 @@ static inline frame_t *get_first_frame(list_head_t *frames, unsigned int order)
return list_first_entry(&frames[order], frame_t, list);
}

static inline bool frame_has_paddr(const frame_t *frame, paddr_t pa) {
if (!frame)
return false;

paddr_t start_pa = mfn_to_paddr(frame->mfn);
paddr_t end_pa = start_pa + ORDER_TO_SIZE(frame->order) - 1;

return pa >= start_pa && pa <= end_pa;
}

static inline frame_t *get_free_frame(void) {
return get_free_frames(PAGE_ORDER_4K);
}
Expand Down
85 changes: 81 additions & 4 deletions mm/pmm.c
Original file line number Diff line number Diff line change
Expand Up @@ -407,7 +407,7 @@ static inline bool return_frame(frame_t *frame) {
return false;
}

static frame_t *find_mfn_frame(list_head_t *list, mfn_t mfn, unsigned int order) {
static frame_t *_find_mfn_frame(list_head_t *list, mfn_t mfn, unsigned int order) {
frame_t *frame;

if (!has_frames(list, order))
Expand All @@ -421,6 +421,83 @@ static frame_t *find_mfn_frame(list_head_t *list, mfn_t mfn, unsigned int order)
return NULL;
}

frame_t *find_free_mfn_frame(mfn_t mfn, unsigned int order) {
frame_t *frame;

spin_lock(&lock);
frame = _find_mfn_frame(free_frames, mfn, order);
spin_unlock(&lock);

return frame;
}

frame_t *find_busy_mfn_frame(mfn_t mfn, unsigned int order) {
frame_t *frame;

spin_lock(&lock);
frame = _find_mfn_frame(busy_frames, mfn, order);
spin_unlock(&lock);

return frame;
}

frame_t *find_mfn_frame(mfn_t mfn, unsigned int order) {
frame_t *frame;

spin_lock(&lock);
frame = _find_mfn_frame(busy_frames, mfn, order);
if (!frame)
frame = _find_mfn_frame(free_frames, mfn, order);
spin_unlock(&lock);
sktt marked this conversation as resolved.
Show resolved Hide resolved

return frame;
}

static frame_t *_find_paddr_frame(list_head_t *list, paddr_t paddr) {
frame_t *frame;

for_each_order (order) {
list_for_each_entry (frame, &list[order], list) {
if (frame_has_paddr(frame, paddr))
return frame;
}
}

return NULL;
}

frame_t *find_free_paddr_frame(paddr_t paddr) {
frame_t *frame;

spin_lock(&lock);
frame = _find_paddr_frame(free_frames, paddr);
spin_unlock(&lock);

return frame;
}

frame_t *find_busy_paddr_frame(paddr_t paddr) {
frame_t *frame;

spin_lock(&lock);
frame = _find_paddr_frame(busy_frames, paddr);
spin_unlock(&lock);

return frame;
}

frame_t *find_paddr_frame(paddr_t paddr) {
frame_t *frame;

spin_lock(&lock);
frame = _find_paddr_frame(busy_frames, paddr);
if (!frame)
frame = _find_paddr_frame(free_frames, paddr);
spin_unlock(&lock);
sktt marked this conversation as resolved.
Show resolved Hide resolved

return frame;
}

static frame_t *find_larger_frame(list_head_t *list, unsigned int order) {
while (++order <= MAX_PAGE_ORDER) {
frame_t *frame = get_first_frame(list, order);
Expand Down Expand Up @@ -491,13 +568,13 @@ static void merge_frames(frame_t *first) {

wipawel marked this conversation as resolved.
Show resolved Hide resolved
if (FIRST_FRAME_SIBLING(first->mfn, first->order + 1)) {
mfn_t next_mfn = NEXT_MFN(first->mfn, first->order);
second = find_mfn_frame(free_frames, next_mfn, first->order);
second = _find_mfn_frame(free_frames, next_mfn, first->order);
wipawel marked this conversation as resolved.
Show resolved Hide resolved
}
else {
/* Second frame sibling */
mfn_t prev_mfn = PREV_MFN(first->mfn, first->order);
second = first;
first = find_mfn_frame(free_frames, prev_mfn, first->order);
first = _find_mfn_frame(free_frames, prev_mfn, first->order);
wipawel marked this conversation as resolved.
Show resolved Hide resolved
}

if (!first || !second)
Expand Down Expand Up @@ -547,7 +624,7 @@ void put_free_frames(mfn_t mfn, unsigned int order) {
ASSERT(order <= MAX_PAGE_ORDER);

spin_lock(&lock);
frame = find_mfn_frame(busy_frames, mfn, order);
frame = _find_mfn_frame(busy_frames, mfn, order);
wipawel marked this conversation as resolved.
Show resolved Hide resolved
if (!frame) {
warning("PMM: unable to find frame: %lx, order: %u among busy frames", mfn,
order);
Expand Down
8 changes: 6 additions & 2 deletions tests/unittests.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <console.h>
#include <cpuid.h>
#include <ktf.h>
#include <pagetable.h>
#include <real_mode.h>
#include <sched.h>
#include <string.h>
Expand Down Expand Up @@ -203,13 +204,16 @@ int unit_tests(void *_unused) {
task_user3 = new_user_task("test3 user", test_user_task_func3, NULL);
task_user4 = new_user_task("test4 user", test_user_task_func4, NULL);

vmap_4k(HIGH_USER_PTR + 0x1000, get_free_frame()->mfn, L1_PROT);
frame_t *frame = get_free_frame();
vmap_4k(HIGH_USER_PTR + 0x1000, frame->mfn, L1_PROT);
memset(HIGH_USER_PTR + 0x1000, 0, 0x1000);
vmap_user_4k(HIGH_USER_PTR, get_free_frame()->mfn, L1_PROT_USER);
vmap_user_4k(HIGH_USER_PTR, frame->mfn, L1_PROT_USER);

/* Be sure that we can still touch this vmap despite the user vmap. */
BUG_ON(*(unsigned long *) (HIGH_USER_PTR + 0x1000) != 0);

BUG_ON(frame != find_kern_va_frame(HIGH_USER_PTR + 0x1000));

set_task_repeat(task1, 10);
schedule_task(task1, get_bsp_cpu());
schedule_task(task2, get_cpu(1));
Expand Down
Loading