Skip to content

LKL MMU support #551

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

Merged
merged 6 commits into from
Jan 5, 2025
Merged
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
5 changes: 5 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -22,6 +22,11 @@ jobs:
runs_on: ubuntu-22.04
shell: bash
build_options: "kasan=yes kasan_test=yes"
- displayTargetName: mmu_kasan
os: unix
runs_on: ubuntu-22.04
shell: bash
build_options: "MMU=1 MMU_KUNIT=1 kasan=yes"
- displayTargetName: windows-2019
os: windows
runs_on: windows-2019
39 changes: 38 additions & 1 deletion arch/lkl/Kconfig
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
config LKL
def_bool y
depends on !SMP && !MMU && !COREDUMP && !SECCOMP && !UPROBES && !COMPAT && !USER_RETURN_NOTIFIER
depends on !SMP && !COREDUMP && !SECCOMP && !UPROBES && !COMPAT && !USER_RETURN_NOTIFIER
select ARCH_THREAD_STACK_ALLOCATOR
select RWSEM_GENERIC_SPINLOCK
select GENERIC_ATOMIC64
@@ -77,6 +77,43 @@ config 64BIT
bool "64bit kernel"
default n

config MMU
bool "LKL MMU implementation"
depends on 64BIT
default n

if MMU
config PGTABLE_LEVELS
int
default 3

config LKL_MEMORY_START
hex
default 0x50000000
help
Base address of kernel virtual address space for LKL. No particular
reason for picking this specific value. It is assumed that the host
mmap is able to map requested amount of memory at this address.
STACK_TOP and VMALLOC_START values depend on it.


config LKL_TASK_UNMAPPED_BASE
hex
default 0x100000
help
Starting virtual address for LKL user-space mmap. It is assumed that
the host mmap is able to map requested amount of memory starting from
this address.

config LKL_MMU_KUNIT_TEST
bool "Kunit tests for LKL MMU"
default n
depends on KUNIT
help
Kunit tests to test correctness of MMU-related kernel interfaces (such
as vmalloc, for example) which are difficult to test in user-space.
endif

config COREDUMP
def_bool n

1 change: 1 addition & 0 deletions arch/lkl/include/asm/Kbuild
Original file line number Diff line number Diff line change
@@ -75,3 +75,4 @@ generic-y += vga.h
generic-y += word-at-a-time.h
generic-y += kprobes.h
generic-y += uaccess.h
generic-y += mman.h
7 changes: 7 additions & 0 deletions arch/lkl/include/asm/elf.h
Original file line number Diff line number Diff line change
@@ -9,6 +9,13 @@
#define ELF_CLASS ELFCLASS32
#endif

#ifdef CONFIG_MMU
#define ELF_EXEC_PAGESIZE 4096
#define ELF_PLATFORM "i586"
#define ELF_HWCAP 0L
#define ELF_ET_DYN_BASE (TASK_SIZE)
#endif // CONFIG_MMU

#define elf_gregset_t long
#define elf_fpregset_t double
#endif
8 changes: 8 additions & 0 deletions arch/lkl/include/asm/io.h
Original file line number Diff line number Diff line change
@@ -98,6 +98,14 @@ static inline void __iomem *ioremap(phys_addr_t offset, size_t size)
return (void __iomem *)lkl_ops->ioremap(offset, size);
}

#ifdef CONFIG_MMU
static inline void __iounmap(void __iomem *addr)
{
// No-op according to ioremap implementation.
}
#define iounmap __iounmap
#endif

#include <asm-generic/io.h>

#endif /* _ASM_LKL_IO_H */
12 changes: 12 additions & 0 deletions arch/lkl/include/asm/mmu_context.h
Original file line number Diff line number Diff line change
@@ -2,6 +2,18 @@
#ifndef _ASM_LKL_MMU_CONTEXT_H
#define _ASM_LKL_MMU_CONTEXT_H

#ifdef CONFIG_MMU
static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
struct task_struct *tsk) {
// No-op for LKL as it doesn't support multiple user-mode address spaces.
}

/* Generic hooks for arch_dup_mmap and arch_exit_mmap */
#include <asm-generic/mm_hooks.h>
#include <asm-generic/mmu_context.h>

#else
#include <asm-generic/nommu_context.h>
#endif

#endif /* _ASM_LKL_MMU_CONTEXT_H */
68 changes: 68 additions & 0 deletions arch/lkl/include/asm/page-mmu.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_LKL_PAGE_MMU_H
#define _ASM_LKL_PAGE_MMU_H

#include <linux/const.h>

/* PAGE_SHIFT determines the page size */
#define PAGE_SHIFT 12
#define PAGE_SIZE (_AC(1, UL) << PAGE_SHIFT)
#define PAGE_MASK (~(PAGE_SIZE-1))
#define PFN_PTE_SHIFT PAGE_SHIFT

#ifndef __ASSEMBLY__

struct page;
#define clear_page(page) memset((void *)(page), 0, PAGE_SIZE)
#define copy_page(to, from) memcpy((void *)(to), (void *)(from), PAGE_SIZE)
#define clear_user_page(page, vaddr, pg) clear_page(page)
#define copy_user_page(to, from, vaddr, pg) copy_page(to, from)

typedef struct {unsigned long pte; } pte_t;
typedef struct {unsigned long pmd; } pmd_t;
typedef struct {unsigned long pgd; } pgd_t;
typedef struct {unsigned long pgprot; } pgprot_t;
typedef struct page *pgtable_t;

#define pte_val(p) ((p).pte)
#define pgd_val(x) ((x).pgd)
#define pgprot_val(x) ((x).pgprot)

#define pmd_val(x) ((x).pmd)
#define __pmd(x) ((pmd_t) { (x) })

#define __pte(x) ((pte_t) { (x) })
#define __pgd(x) ((pgd_t) { (x) })
#define __pgprot(x) ((pgprot_t) { (x) })

#define pte_get_bits(p, bits) ((p).pte & (bits))
#define pte_set_bits(p, bits) ((p).pte |= (bits))
#define pte_clear_bits(p, bits) ((p).pte &= ~(bits))
#define pte_copy(to, from) ({ (to).pte = (from).pte; })
#define pte_is_zero(p) (!((p).pte & ~_PAGE_NEWPAGE))
#define pte_set_val(p, phys, prot) ({ (p).pte = (phys) | pgprot_val(prot); })

extern unsigned long memory_start;
extern unsigned long memory_end;

#define PAGE_OFFSET (memory_start)
// Define ARCH_PFN_OFFSET so that kernel virtual addresses are the same as
// the corresponding physical addresses (i.e. 1-to-1 mapping).
#define ARCH_PFN_OFFSET (memory_start >> PAGE_SHIFT)

#define __pa(virt) ((unsigned long) (virt))
#define __va(phys) ((void *)(phys))

#define virt_to_pfn(kaddr) (__pa(kaddr) >> PAGE_SHIFT)

#define phys_to_pfn(p) PHYS_PFN(p)
#define pfn_to_phys(pfn) PFN_PHYS(pfn)

#define virt_addr_valid(v) pfn_valid(phys_to_pfn(__pa(v)))

#endif // __ASSEMBLY__

#include <asm-generic/memory_model.h>
#include <asm-generic/getorder.h>

#endif // _ASM_LKL_PAGE_MMU_H
8 changes: 6 additions & 2 deletions arch/lkl/include/asm/page.h
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_LKL_PAGE_H
#define _ASM_LKL_PAGE_H

#ifndef CONFIG_MMU
#define ARCH_PFN_OFFSET (memory_start >> PAGE_SHIFT)
#include <asm-generic/page.h>
#else // CONFIG_MMU
#include <asm/page-mmu.h>
#endif // CONFIG_MMU

#ifndef __ASSEMBLY__
void free_mem(void);
void bootmem_init(unsigned long mem_size);
#endif

#include <asm-generic/page.h>

#undef PAGE_OFFSET
#define PAGE_OFFSET memory_start

38 changes: 38 additions & 0 deletions arch/lkl/include/asm/pgalloc.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _LKL_PGALLOC_H
#define _LKL_PGALLOC_H

#include <linux/mm.h>
#include <linux/mmzone.h>

#include <asm-generic/pgalloc.h>

#ifdef CONFIG_MMU

static inline void pmd_populate_kernel(struct mm_struct *mm,
pmd_t *pmd, pte_t *pte)
{
set_pmd(pmd, __pmd(_PAGE_TABLE + (unsigned long) __pa(pte)));
}

static inline void pmd_populate(struct mm_struct *mm,
pmd_t *pmd, pgtable_t pte)
{
set_pmd(pmd, __pmd(_PAGE_TABLE + (page_to_pfn(pte) << PAGE_SHIFT)));
}

#define pmd_pgtable(pmd) pmd_page(pmd)

extern pgd_t *pgd_alloc(struct mm_struct *mm);

#define __pte_free_tlb(tlb, pte, address) tlb_remove_page((tlb), (pte))

#define __pmd_free_tlb(tlb, pmd, address) \
do { \
pagetable_pmd_dtor(virt_to_ptdesc(pmd)); \
tlb_remove_page_ptdesc((tlb), virt_to_ptdesc(pmd)); \
} while (0)

#endif // CONFIG_MMU

#endif /* _LKL_PGALLOC_H */
Loading