Skip to content

Commit

Permalink
mm,pagetables: add VIRT_KERNEL_HIGH memory area
Browse files Browse the repository at this point in the history
The VIRT_KERNEL_HIGH is currently located at the address 0xffff900000000000.
The memory area should be used for high-address or large memory allocations.
The VIRT_KERNEL_BASE area, while reachable from within the VIRT_IDENT_BASE
area, does not have enough addressing space for high address allocations
(base address overflow). All such allocations should go to the new area.

Add mmap() helper (or its order size variants) to automatically use the
VIRT_KERNEL_HIGH area.

The get_free_pages() gets a new flag GPF_KERNEL_HIGH to use the area.

Signed-off-by: Pawel Wieczorkiewicz <[email protected]>
  • Loading branch information
wipawel committed Jan 19, 2022
1 parent 0a91b08 commit 23ae53a
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 0 deletions.
41 changes: 41 additions & 0 deletions include/arch/x86/page.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@
#define PADDR_MASK (~(PADDR_SIZE - 1))

#define VIRT_KERNEL_BASE _U64(0xffffffff80000000)
#define VIRT_KERNEL_HIGH _U64(0xffff900000000000)
#define VIRT_USER_BASE _U64(0x0000000000400000)
#define VIRT_IDENT_BASE _U64(0x0000000000000000)

Expand Down Expand Up @@ -150,29 +151,44 @@ static inline paddr_t mfn_to_paddr(mfn_t mfn) { return (paddr_t)(mfn << PAGE_SHI
static inline void *_paddr_to_virt(paddr_t pa, unsigned long addr_space) {
return _ptr(pa + addr_space);
}

static inline void *paddr_to_virt_kern(paddr_t pa) {
return _paddr_to_virt(pa, VIRT_KERNEL_BASE);
}

static inline void *paddr_to_virt_high(paddr_t pa) {
return _paddr_to_virt(pa, VIRT_KERNEL_HIGH);
}

static inline void *paddr_to_virt_user(paddr_t pa) {
return _paddr_to_virt(pa, VIRT_USER_BASE);
}

static inline void *paddr_to_virt(paddr_t pa) {
return _paddr_to_virt(pa, VIRT_IDENT_BASE);
}

static inline void *mfn_to_virt_kern(mfn_t mfn) {
return paddr_to_virt_kern(mfn << PAGE_SHIFT);
}

static inline void *mfn_to_virt_high(mfn_t mfn) {
return paddr_to_virt_high(mfn << PAGE_SHIFT);
}

static inline void *mfn_to_virt_user(mfn_t mfn) {
return paddr_to_virt_user(mfn << PAGE_SHIFT);
}

static inline void *mfn_to_virt(mfn_t mfn) { return paddr_to_virt(mfn << PAGE_SHIFT); }

static inline paddr_t virt_to_paddr(const void *va) {
paddr_t pa = (paddr_t) va;

if (IS_ADDR_SPACE_VA(va, VIRT_KERNEL_BASE))
return pa - VIRT_KERNEL_BASE;
if (IS_ADDR_SPACE_VA(va, VIRT_KERNEL_HIGH))
return pa - VIRT_KERNEL_HIGH;
if (IS_ADDR_SPACE_VA(va, VIRT_USER_BASE))
return pa - VIRT_USER_BASE;

Expand All @@ -196,6 +212,19 @@ static inline void *kmap(mfn_t mfn, unsigned int order,
l3_flags, l2_flags, l1_flags);
}

static inline void *mmap(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) {
return vmap(mfn_to_virt_high(mfn), mfn, order,
#if defined(__x86_64__)
l4_flags,
#endif
l3_flags, l2_flags, l1_flags);
}

static inline void *vmap_1g(void *va, mfn_t mfn, unsigned long l3_flags) {
return vmap(va, mfn, PAGE_ORDER_1G, L4_PROT_USER, l3_flags, PT_NO_FLAGS, PT_NO_FLAGS);
}
Expand All @@ -222,6 +251,18 @@ static inline void *kmap_4k(mfn_t mfn, unsigned long l1_flags) {
return kmap(mfn, PAGE_ORDER_4K, L4_PROT_USER, L3_PROT_USER, L2_PROT_USER, l1_flags);
}

static inline void *mmap_1g(mfn_t mfn, unsigned long l3_flags) {
return mmap(mfn, PAGE_ORDER_1G, L4_PROT_USER, l3_flags, PT_NO_FLAGS, PT_NO_FLAGS);
}

static inline void *mmap_2m(mfn_t mfn, unsigned long l2_flags) {
return mmap(mfn, PAGE_ORDER_2M, L4_PROT_USER, L3_PROT_USER, l2_flags, PT_NO_FLAGS);
}

static inline void *mmap_4k(mfn_t mfn, unsigned long l1_flags) {
return mmap(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/mm/vmm.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ enum gfp_flags {
GFP_KERNEL = 0x00000001,
GFP_USER = 0x00000002,
GFP_IDENT = 0x00000004,
GFP_KERNEL_HIGH = 0x00000008,
};

/* External definitions */
Expand Down
2 changes: 2 additions & 0 deletions mm/vmm.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ void *get_free_pages(unsigned int order, uint32_t flags) {
L2_PROT_USER, L1_PROT_USER);
if (flags & GFP_KERNEL)
va = kmap(mfn, order, L4_PROT, L3_PROT, L2_PROT, L1_PROT);
if (flags & GFP_KERNEL_HIGH)
va = mmap(mfn, order, L4_PROT, L3_PROT, L2_PROT, L1_PROT);

return va;
}
Expand Down

0 comments on commit 23ae53a

Please sign in to comment.