From 57f0f512b273f60d52568b8c6b77e17f5636edc0 Mon Sep 17 00:00:00 2001 From: André Fabian Silva Delgado Date: Wed, 5 Aug 2015 17:04:01 -0300 Subject: Initial import --- arch/metag/include/asm/mmu_context.h | 113 +++++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 arch/metag/include/asm/mmu_context.h (limited to 'arch/metag/include/asm/mmu_context.h') diff --git a/arch/metag/include/asm/mmu_context.h b/arch/metag/include/asm/mmu_context.h new file mode 100644 index 000000000..ae2a71b5e --- /dev/null +++ b/arch/metag/include/asm/mmu_context.h @@ -0,0 +1,113 @@ +#ifndef __METAG_MMU_CONTEXT_H +#define __METAG_MMU_CONTEXT_H + +#include + +#include +#include +#include +#include + +#include + +static inline void enter_lazy_tlb(struct mm_struct *mm, + struct task_struct *tsk) +{ +} + +static inline int init_new_context(struct task_struct *tsk, + struct mm_struct *mm) +{ +#ifndef CONFIG_METAG_META21_MMU + /* We use context to store a pointer to the page holding the + * pgd of a process while it is running. While a process is not + * running the pgd and context fields should be equal. + */ + mm->context.pgd_base = (unsigned long) mm->pgd; +#endif +#ifdef CONFIG_METAG_USER_TCM + INIT_LIST_HEAD(&mm->context.tcm); +#endif + return 0; +} + +#ifdef CONFIG_METAG_USER_TCM + +#include +#include + +static inline void destroy_context(struct mm_struct *mm) +{ + struct tcm_allocation *pos, *n; + + list_for_each_entry_safe(pos, n, &mm->context.tcm, list) { + tcm_free(pos->tag, pos->addr, pos->size); + list_del(&pos->list); + kfree(pos); + } +} +#else +#define destroy_context(mm) do { } while (0) +#endif + +#ifdef CONFIG_METAG_META21_MMU +static inline void load_pgd(pgd_t *pgd, int thread) +{ + unsigned long phys0 = mmu_phys0_addr(thread); + unsigned long phys1 = mmu_phys1_addr(thread); + + /* + * 0x900 2Gb address space + * The permission bits apply to MMU table region which gives a 2MB + * window into physical memory. We especially don't want userland to be + * able to access this. + */ + metag_out32(0x900 | _PAGE_CACHEABLE | _PAGE_PRIV | _PAGE_WRITE | + _PAGE_PRESENT, phys0); + /* Set new MMU base address */ + metag_out32(__pa(pgd) & MMCU_TBLPHYS1_ADDR_BITS, phys1); +} +#endif + +static inline void switch_mmu(struct mm_struct *prev, struct mm_struct *next) +{ +#ifdef CONFIG_METAG_META21_MMU + load_pgd(next->pgd, hard_processor_id()); +#else + unsigned int i; + + /* prev->context == prev->pgd in the case where we are initially + switching from the init task to the first process. */ + if (prev->context.pgd_base != (unsigned long) prev->pgd) { + for (i = FIRST_USER_PGD_NR; i < USER_PTRS_PER_PGD; i++) + ((pgd_t *) prev->context.pgd_base)[i] = prev->pgd[i]; + } else + prev->pgd = (pgd_t *)mmu_get_base(); + + next->pgd = prev->pgd; + prev->pgd = (pgd_t *) prev->context.pgd_base; + + for (i = FIRST_USER_PGD_NR; i < USER_PTRS_PER_PGD; i++) + next->pgd[i] = ((pgd_t *) next->context.pgd_base)[i]; + + flush_cache_all(); +#endif + flush_tlb_all(); +} + +static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, + struct task_struct *tsk) +{ + if (prev != next) + switch_mmu(prev, next); +} + +static inline void activate_mm(struct mm_struct *prev_mm, + struct mm_struct *next_mm) +{ + switch_mmu(prev_mm, next_mm); +} + +#define deactivate_mm(tsk, mm) do { } while (0) + +#endif -- cgit v1.2.3-54-g00ecf