Skip to content

Commit

Permalink
arch, pagetables: add user address space
Browse files Browse the repository at this point in the history
Add separate CR3 variable holding top of the user space page tables.
Add vmap_user*() helper functions, capable of mapping both kernel
mappings (kernel privilege, for necessary kernel mappings in user
address space) and user mappings (userland data and code).

Map userland data and code to both kernel and user address spaces.

Map IDT and TSS's RSP0 stack to user address space as kernel mappings.

Signed-off-by: Pawel Wieczorkiewicz <[email protected]>
  • Loading branch information
wipawel committed Jul 11, 2022
1 parent aa28159 commit f53bfa1
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 4 deletions.
20 changes: 18 additions & 2 deletions arch/x86/pagetables.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include <string.h>

cr3_t cr3;
cr3_t user_cr3;

static inline const char *dump_pte_flags(char *buf, size_t size, pte_t pte) {
/* clang-format off */
Expand Down Expand Up @@ -211,6 +212,17 @@ void *vmap_kern(void *va, mfn_t mfn, unsigned int order,
return _vmap(&cr3, _ptr(_va), mfn, order, l4_flags, l3_flags, l2_flags, l1_flags);
}

void *vmap_user(void *va, mfn_t mfn, unsigned int order,
#if defined(__x86_64__)
unsigned long l4_flags,
#endif
unsigned long l3_flags, unsigned long l2_flags, unsigned long l1_flags) {
unsigned long _va = _ul(va) & PAGE_ORDER_TO_MASK(order);

return _vmap(&user_cr3, _ptr(_va), mfn, order, l4_flags, l3_flags, l2_flags,
l1_flags);
}

void init_pagetables(void) {
for_each_memory_range (r) {
switch (r->base) {
Expand All @@ -223,8 +235,12 @@ void init_pagetables(void) {
kmap_4k(mfn, r->flags);
break;
case VIRT_USER_BASE:
for (mfn_t mfn = virt_to_mfn(r->start); mfn < virt_to_mfn(r->end); mfn++)
vmap_4k(mfn_to_virt_user(mfn), mfn, r->flags);
for (mfn_t mfn = virt_to_mfn(r->start); mfn < virt_to_mfn(r->end); mfn++) {
void *va = mfn_to_virt_user(mfn);

vmap_4k(va, mfn, r->flags);
vmap_user_4k(va, mfn, r->flags);
}
break;
default:
break;
Expand Down
4 changes: 2 additions & 2 deletions arch/x86/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ static void init_tss(percpu_t *percpu) {
percpu->tss.ss0 = __KERN_DS;
percpu->tss.cr3 = _ul(cr3.reg);
#elif defined(__x86_64__)
percpu->tss.rsp0 = _ul(get_free_page_top(GFP_KERNEL));
percpu->tss.rsp0 = _ul(get_free_page_top(GFP_KERNEL | GFP_USER));
percpu->tss.ist[0] = _ul(get_free_page_top(GFP_KERNEL));
#endif
percpu->tss.iopb = sizeof(percpu->tss);
Expand Down Expand Up @@ -124,7 +124,7 @@ void init_traps(unsigned int cpu) {

BUG_ON(!percpu);

percpu->idt = get_free_page(GFP_KERNEL);
percpu->idt = get_free_page(GFP_KERNEL | GFP_USER);
BUG_ON(!percpu->idt);

percpu->idt_ptr.size = (sizeof(percpu->idt) * MAX_INT) - 1;
Expand Down
31 changes: 31 additions & 0 deletions include/arch/x86/page.h
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,12 @@ extern void *vmap_kern(void *va, mfn_t mfn, unsigned int order,
unsigned long l3_flags, unsigned long l2_flags,
unsigned long l1_flags);

extern void *vmap_user(void *va, mfn_t mfn, unsigned int order,
#if defined(__x86_64__)
unsigned long l4_flags,
#endif
unsigned long l3_flags, unsigned long l2_flags,
unsigned long l1_flags);

extern void pat_set_type(pat_field_t field, pat_memory_type_t type);
extern pat_memory_type_t pat_get_type(pat_field_t field);
Expand Down Expand Up @@ -231,6 +237,10 @@ static inline void vunmap_kern(void *va, unsigned int order) {
vmap_kern(va, MFN_INVALID, order, PT_NO_FLAGS, PT_NO_FLAGS, PT_NO_FLAGS, PT_NO_FLAGS);
}

static inline void vunmap_user(void *va, unsigned int order) {
vmap_user(va, MFN_INVALID, order, PT_NO_FLAGS, PT_NO_FLAGS, PT_NO_FLAGS, PT_NO_FLAGS);
}

static inline void *kmap(mfn_t mfn, unsigned int order,
#if defined(__x86_64__)
unsigned long l4_flags,
Expand Down Expand Up @@ -268,6 +278,27 @@ static inline void *kmap_4k(mfn_t mfn, unsigned long l1_flags) {
return kmap(mfn, PAGE_ORDER_4K, L4_PROT, L3_PROT, L2_PROT, l1_flags);
}

static inline void *vmap_user_1g(void *va, mfn_t mfn, unsigned long l3_flags) {
unsigned long user = l3_flags & _PAGE_USER;

return vmap_user(va, mfn, PAGE_ORDER_1G, L4_PROT | user, l3_flags | user, PT_NO_FLAGS,
PT_NO_FLAGS);
}

static inline void *vmap_user_2m(void *va, mfn_t mfn, unsigned long l2_flags) {
unsigned long user = l2_flags & _PAGE_USER;

return vmap_user(va, mfn, PAGE_ORDER_2M, L4_PROT | user, L3_PROT | user,
l2_flags | user, PT_NO_FLAGS);
}

static inline void *vmap_user_4k(void *va, mfn_t mfn, unsigned long l1_flags) {
unsigned long user = l1_flags & _PAGE_USER;

return vmap_user(va, mfn, PAGE_ORDER_4K, L4_PROT | user, L3_PROT | user,
L2_PROT | user, l1_flags);
}

#endif /* __ASSEMBLY__ */

#endif /* KTF_PAGE_H */
1 change: 1 addition & 0 deletions include/arch/x86/pagetable.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ union cr3 {
typedef union cr3 cr3_t;

extern cr3_t cr3;
extern cr3_t user_cr3;

typedef unsigned int pt_index_t;

Expand Down
10 changes: 10 additions & 0 deletions mm/vmm.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,19 +45,29 @@ void *get_free_pages(unsigned int order, uint32_t flags) {
if (flags == GFP_USER) {
va = vmap_kern(mfn_to_virt_user(mfn), mfn, order, L4_PROT, L3_PROT, L2_PROT,
L1_PROT);
vmap_user(mfn_to_virt_user(mfn), mfn, order, L4_PROT_USER, L3_PROT_USER,
L2_PROT_USER, L1_PROT_USER);
}

if (flags & GFP_IDENT) {
va = vmap_kern(mfn_to_virt(mfn), mfn, order, L4_PROT, L3_PROT, L2_PROT, L1_PROT);
if (flags & GFP_USER)
vmap_user(mfn_to_virt(mfn), mfn, order, L4_PROT, L3_PROT, L2_PROT, L1_PROT);
}

if (flags & GFP_KERNEL) {
va = kmap(mfn, order, L4_PROT, L3_PROT, L2_PROT, L1_PROT);
if (flags & GFP_USER)
vmap_user(mfn_to_virt_kern(mfn), mfn, order, L4_PROT, L3_PROT, L2_PROT,
L1_PROT);
}

if (flags & GFP_KERNEL_MAP) {
va = vmap_kern(mfn_to_virt_map(mfn), mfn, order, L4_PROT, L3_PROT, L2_PROT,
L1_PROT);
if (flags & GFP_USER)
vmap_user(mfn_to_virt_map(mfn), mfn, order, L4_PROT, L3_PROT, L2_PROT,
L1_PROT);
}

return va;
Expand Down

0 comments on commit f53bfa1

Please sign in to comment.