Skip to content

Commit

Permalink
Merge pull request #551 from rodionov/mmu_rc
Browse files Browse the repository at this point in the history
LKL MMU support
  • Loading branch information
tavip authored Jan 5, 2025
2 parents 7682a9e + 1ee079e commit 2bc46f7
Show file tree
Hide file tree
Showing 25 changed files with 966 additions and 12 deletions.
5 changes: 5 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
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
Expand Down Expand Up @@ -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

Expand Down
1 change: 1 addition & 0 deletions arch/lkl/include/asm/Kbuild
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Up @@ -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
Expand Down
8 changes: 8 additions & 0 deletions arch/lkl/include/asm/io.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
12 changes: 12 additions & 0 deletions arch/lkl/include/asm/mmu_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
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

0 comments on commit 2bc46f7

Please sign in to comment.