From: <gerg@snapgear.com>
To: linux-m68k@vger.kernel.org, uclinux-dev@uclinux.org
Cc: Greg Ungerer <gerg@uclinux.org>
Subject: [PATCH 20/35] m68k: ColdFire V4e MMU context support code
Date: Fri, 23 Dec 2011 13:15:33 +1000 [thread overview]
Message-ID: <1324610148-20666-21-git-send-email-gerg@snapgear.com> (raw)
In-Reply-To: <1324610148-20666-1-git-send-email-gerg@snapgear.com>
From: Greg Ungerer <gerg@uclinux.org>
Add code to manage the context's of the ColdFire V4e MMU. This code is
mostly taken from the Freescale 2.6.35 kernel BSP for MMU enabled ColdFire.
Signed-off-by: Greg Ungerer <gerg@uclinux.org>
Acked-by: Geert Uytterhoeven <geert@linux-m68k.org>
Acked-by: Matt Waddel <mwaddel@yahoo.com>
Acked-by: Kurt Mahan <kmahan@xmission.com>
---
arch/m68k/include/asm/atomic.h | 10 ++
arch/m68k/include/asm/mmu_context.h | 250 ++++++++++++++++++++++++++++-------
2 files changed, 211 insertions(+), 49 deletions(-)
diff --git a/arch/m68k/include/asm/atomic.h b/arch/m68k/include/asm/atomic.h
index 65c6be6..4eba796 100644
--- a/arch/m68k/include/asm/atomic.h
+++ b/arch/m68k/include/asm/atomic.h
@@ -55,6 +55,16 @@ static inline int atomic_dec_and_test(atomic_t *v)
return c != 0;
}
+static inline int atomic_dec_and_test_lt(atomic_t *v)
+{
+ char c;
+ __asm__ __volatile__(
+ "subql #1,%1; slt %0"
+ : "=d" (c), "=m" (*v)
+ : "m" (*v));
+ return c != 0;
+}
+
static inline int atomic_inc_and_test(atomic_t *v)
{
char c;
diff --git a/arch/m68k/include/asm/mmu_context.h b/arch/m68k/include/asm/mmu_context.h
index 7d4341e..dc3be99 100644
--- a/arch/m68k/include/asm/mmu_context.h
+++ b/arch/m68k/include/asm/mmu_context.h
@@ -8,7 +8,206 @@ static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
}
#ifdef CONFIG_MMU
-#ifndef CONFIG_SUN3
+
+#if defined(CONFIG_COLDFIRE)
+
+#include <asm/atomic.h>
+#include <asm/bitops.h>
+#include <asm/mcfmmu.h>
+#include <asm/mmu.h>
+
+#define NO_CONTEXT 256
+#define LAST_CONTEXT 255
+#define FIRST_CONTEXT 1
+
+extern unsigned long context_map[];
+extern mm_context_t next_mmu_context;
+
+extern atomic_t nr_free_contexts;
+extern struct mm_struct *context_mm[LAST_CONTEXT+1];
+extern void steal_context(void);
+
+static inline void get_mmu_context(struct mm_struct *mm)
+{
+ mm_context_t ctx;
+
+ if (mm->context != NO_CONTEXT)
+ return;
+ while (atomic_dec_and_test_lt(&nr_free_contexts)) {
+ atomic_inc(&nr_free_contexts);
+ steal_context();
+ }
+ ctx = next_mmu_context;
+ while (test_and_set_bit(ctx, context_map)) {
+ ctx = find_next_zero_bit(context_map, LAST_CONTEXT+1, ctx);
+ if (ctx > LAST_CONTEXT)
+ ctx = 0;
+ }
+ next_mmu_context = (ctx + 1) & LAST_CONTEXT;
+ mm->context = ctx;
+ context_mm[ctx] = mm;
+}
+
+/*
+ * Set up the context for a new address space.
+ */
+#define init_new_context(tsk, mm) (((mm)->context = NO_CONTEXT), 0)
+
+/*
+ * We're finished using the context for an address space.
+ */
+static inline void destroy_context(struct mm_struct *mm)
+{
+ if (mm->context != NO_CONTEXT) {
+ clear_bit(mm->context, context_map);
+ mm->context = NO_CONTEXT;
+ atomic_inc(&nr_free_contexts);
+ }
+}
+
+static inline void set_context(mm_context_t context, pgd_t *pgd)
+{
+ __asm__ __volatile__ ("movec %0,%%asid" : : "d" (context));
+}
+
+static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
+ struct task_struct *tsk)
+{
+ get_mmu_context(tsk->mm);
+ set_context(tsk->mm->context, next->pgd);
+}
+
+/*
+ * After we have set current->mm to a new value, this activates
+ * the context for the new mm so we see the new mappings.
+ */
+static inline void activate_mm(struct mm_struct *active_mm,
+ struct mm_struct *mm)
+{
+ get_mmu_context(mm);
+ set_context(mm->context, mm->pgd);
+}
+
+#define deactivate_mm(tsk, mm) do { } while (0)
+
+extern void mmu_context_init(void);
+#define prepare_arch_switch(next) load_ksp_mmu(next)
+
+static inline void load_ksp_mmu(struct task_struct *task)
+{
+ unsigned long flags;
+ struct mm_struct *mm;
+ int asid;
+ pgd_t *pgd;
+ pmd_t *pmd;
+ pte_t *pte;
+ unsigned long mmuar;
+
+ local_irq_save(flags);
+ mmuar = task->thread.ksp;
+
+ /* Search for a valid TLB entry, if one is found, don't remap */
+ mmu_write(MMUAR, mmuar);
+ mmu_write(MMUOR, MMUOR_STLB | MMUOR_ADR);
+ if (mmu_read(MMUSR) & MMUSR_HIT)
+ goto end;
+
+ if (mmuar >= PAGE_OFFSET) {
+ mm = &init_mm;
+ } else {
+ pr_info("load_ksp_mmu: non-kernel mm found: 0x%p\n", task->mm);
+ mm = task->mm;
+ }
+
+ if (!mm)
+ goto bug;
+
+ pgd = pgd_offset(mm, mmuar);
+ if (pgd_none(*pgd))
+ goto bug;
+
+ pmd = pmd_offset(pgd, mmuar);
+ if (pmd_none(*pmd))
+ goto bug;
+
+ pte = (mmuar >= PAGE_OFFSET) ? pte_offset_kernel(pmd, mmuar)
+ : pte_offset_map(pmd, mmuar);
+ if (pte_none(*pte) || !pte_present(*pte))
+ goto bug;
+
+ set_pte(pte, pte_mkyoung(*pte));
+ asid = mm->context & 0xff;
+ if (!pte_dirty(*pte) && mmuar <= PAGE_OFFSET)
+ set_pte(pte, pte_wrprotect(*pte));
+
+ mmu_write(MMUTR, (mmuar & PAGE_MASK) | (asid << MMUTR_IDN) |
+ (((int)(pte->pte) & (int)CF_PAGE_MMUTR_MASK)
+ >> CF_PAGE_MMUTR_SHIFT) | MMUTR_V);
+
+ mmu_write(MMUDR, (pte_val(*pte) & PAGE_MASK) |
+ ((pte->pte) & CF_PAGE_MMUDR_MASK) | MMUDR_SZ_8KB | MMUDR_X);
+
+ mmu_write(MMUOR, MMUOR_ACC | MMUOR_UAA);
+
+ goto end;
+
+bug:
+ pr_info("ksp load failed: mm=0x%p ksp=0x08%lx\n", mm, mmuar);
+end:
+ local_irq_restore(flags);
+}
+
+#elif defined(CONFIG_SUN3)
+#include <asm/sun3mmu.h>
+#include <linux/sched.h>
+
+extern unsigned long get_free_context(struct mm_struct *mm);
+extern void clear_context(unsigned long context);
+
+/* set the context for a new task to unmapped */
+static inline int init_new_context(struct task_struct *tsk,
+ struct mm_struct *mm)
+{
+ mm->context = SUN3_INVALID_CONTEXT;
+ return 0;
+}
+
+/* find the context given to this process, and if it hasn't already
+ got one, go get one for it. */
+static inline void get_mmu_context(struct mm_struct *mm)
+{
+ if (mm->context == SUN3_INVALID_CONTEXT)
+ mm->context = get_free_context(mm);
+}
+
+/* flush context if allocated... */
+static inline void destroy_context(struct mm_struct *mm)
+{
+ if (mm->context != SUN3_INVALID_CONTEXT)
+ clear_context(mm->context);
+}
+
+static inline void activate_context(struct mm_struct *mm)
+{
+ get_mmu_context(mm);
+ sun3_put_context(mm->context);
+}
+
+static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
+ struct task_struct *tsk)
+{
+ activate_context(tsk->mm);
+}
+
+#define deactivate_mm(tsk, mm) do { } while (0)
+
+static inline void activate_mm(struct mm_struct *prev_mm,
+ struct mm_struct *next_mm)
+{
+ activate_context(next_mm);
+}
+
+#else
#include <asm/setup.h>
#include <asm/page.h>
@@ -103,55 +302,8 @@ static inline void activate_mm(struct mm_struct *prev_mm,
switch_mm_0460(next_mm);
}
-#else /* CONFIG_SUN3 */
-#include <asm/sun3mmu.h>
-#include <linux/sched.h>
-
-extern unsigned long get_free_context(struct mm_struct *mm);
-extern void clear_context(unsigned long context);
-
-/* set the context for a new task to unmapped */
-static inline int init_new_context(struct task_struct *tsk, struct mm_struct *mm)
-{
- mm->context = SUN3_INVALID_CONTEXT;
- return 0;
-}
-
-/* find the context given to this process, and if it hasn't already
- got one, go get one for it. */
-static inline void get_mmu_context(struct mm_struct *mm)
-{
- if(mm->context == SUN3_INVALID_CONTEXT)
- mm->context = get_free_context(mm);
-}
-
-/* flush context if allocated... */
-static inline void destroy_context(struct mm_struct *mm)
-{
- if(mm->context != SUN3_INVALID_CONTEXT)
- clear_context(mm->context);
-}
-
-static inline void activate_context(struct mm_struct *mm)
-{
- get_mmu_context(mm);
- sun3_put_context(mm->context);
-}
-
-static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, struct task_struct *tsk)
-{
- activate_context(tsk->mm);
-}
-
-#define deactivate_mm(tsk,mm) do { } while (0)
-
-static inline void activate_mm(struct mm_struct *prev_mm,
- struct mm_struct *next_mm)
-{
- activate_context(next_mm);
-}
-
#endif
+
#else /* !CONFIG_MMU */
static inline int init_new_context(struct task_struct *tsk, struct mm_struct *mm)
--
1.7.0.4
next prev parent reply other threads:[~2011-12-23 3:14 UTC|newest]
Thread overview: 65+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-12-23 3:15 [PATCH 00/35 v4] m68k: ColdFire MMU support gerg
2011-12-23 3:15 ` [PATCH 01/35] m68k: add machine and CPU definitions for ColdFire cores gerg
2011-12-23 3:15 ` [PATCH 02/35] m68k: show ColdFire CPU/FPU/MMU type gerg
2011-12-23 3:15 ` [PATCH 03/35] m68k: definitions for the ColdFire V4e MMU hardware gerg
2011-12-23 3:15 ` [PATCH 04/35] m68k: make interrupt definitions conditional on correct CPU types gerg
2011-12-23 3:15 ` [PATCH 05/35] m68k: add TASK definitions for ColdFires running with MMU gerg
2011-12-23 3:15 ` [PATCH 06/35] m68k: modify user space access functions to support ColdFire CPUs gerg
2011-12-25 19:56 ` Geert Uytterhoeven
2011-12-23 3:15 ` [PATCH 07/35] m68k: use addr_limit checking for m68k CPUs that do no support address spaces gerg
2011-12-25 20:01 ` Geert Uytterhoeven
2011-12-27 12:30 ` Greg Ungerer
2011-12-23 3:15 ` [PATCH 08/35] m68k: init the MMU hardware for the 54xx ColdFire gerg
2011-12-23 3:15 ` [PATCH 09/35] m68k: add ColdFire 54xx CPU MMU memory init code gerg
2011-12-25 20:05 ` Geert Uytterhoeven
2011-12-23 3:15 ` [PATCH 10/35] m68k: set register a2 to current if MMU enabled on ColdFire gerg
2011-12-25 20:09 ` Geert Uytterhoeven
2011-12-23 3:15 ` [PATCH 11/35] m68k: page table support definitions and code for ColdFire MMU gerg
2011-12-23 3:15 ` [PATCH 12/35] m68k: add page table size definitions for ColdFire V4e MMU gerg
2011-12-23 3:15 ` [PATCH 13/35] m68k: add ColdFire paging exception handling code gerg
2011-12-23 3:15 ` [PATCH 14/35] m68k: add cache support for V4e ColdFire cores running with MMU enabled gerg
2011-12-23 3:15 ` [PATCH 15/35] m68k: modify ColdFire 54xx cache support for " gerg
2011-12-23 3:15 ` [PATCH 16/35] m68k: add TLB flush support for the ColdFire V4e MMU hardware gerg
2011-12-23 3:15 ` [PATCH 17/35] m68k: define PAGE_OFFSET_RAW for ColdFire CPU with MMU enabled gerg
2011-12-25 20:15 ` Geert Uytterhoeven
2011-12-27 12:08 ` Greg Ungerer
2011-12-23 3:15 ` [PATCH 18/35] m68k: set ColdFire MMU page size gerg
2011-12-23 3:15 ` [PATCH 19/35] m68k: MMU enabled ColdFire needs 8k ELF alignment gerg
2011-12-23 3:15 ` gerg [this message]
2011-12-23 3:15 ` [PATCH 21/35] m68k: use tracehook_report_syscall_entry/exit for ColdFire MMU ptrace path gerg
2011-12-23 3:15 ` [PATCH 22/35] m68k: modify cache push and clear code for ColdFire with MMU enable gerg
2011-12-23 3:15 ` [PATCH 23/35] m68k: use ColdFire MMU read/write bit flags when ioremapping gerg
2011-12-25 20:23 ` Geert Uytterhoeven
2011-12-23 3:15 ` [PATCH 24/35] m68k: ColdFire V4e MMU paging init code and miss handler gerg
2011-12-23 3:15 ` [PATCH 25/35] m68k: compile appropriate mm arch files for ColdFire MMU support gerg
2011-12-23 3:15 ` [PATCH 26/35] m68k: create ColdFire MMU pgalloc code gerg
2011-12-23 3:15 ` [PATCH 27/35] m68k: use non-MMU entry.S code when compiling for ColdFire CPU gerg
2011-12-23 3:15 ` [PATCH 28/35] m68k: add code to setup a ColdFire 54xx platform when MMU enabled gerg
2011-12-23 3:15 ` [PATCH 29/35] m68k: ColdFire with MMU enabled uses same clocking code as non-MMU gerg
2011-12-25 20:24 ` Geert Uytterhoeven
2011-12-23 3:15 ` [PATCH 30/35] m68k: use non-MMU linker script for ColdFire MMU builds gerg
2011-12-23 3:15 ` [PATCH 31/35] m68k: adjustments to stack frame for ColdFire with MMU enabled gerg
2011-12-23 3:15 ` [PATCH 32/35] m68k: add ColdFire FPU support for the V4e ColdFire CPU's gerg
2011-12-24 19:38 ` Geert Uytterhoeven
2011-12-27 12:36 ` Greg Ungerer
2011-12-28 5:53 ` Greg Ungerer
2011-12-28 10:06 ` Geert Uytterhoeven
2011-12-28 12:32 ` Greg Ungerer
2011-12-28 12:47 ` Andreas Schwab
2011-12-28 11:17 ` Joshua Juran
2011-12-28 12:57 ` Greg Ungerer
2011-12-23 3:15 ` [PATCH 33/35] m68k: do not use m68k startup or interrupt code for " gerg
2011-12-25 20:33 ` Geert Uytterhoeven
2011-12-27 12:24 ` Greg Ungerer
2011-12-27 18:30 ` Geert Uytterhoeven
2011-12-28 0:22 ` Greg Ungerer
2011-12-28 10:09 ` Geert Uytterhoeven
2011-12-29 2:01 ` Greg Ungerer
2011-12-23 3:15 ` [PATCH 34/35] m68k: add ColdFire with MMU enabled support to the m68k mem init code gerg
2011-12-23 3:15 ` [PATCH 35/35] m68k: allow ColdFire 547x and 548x CPUs to be built with MMU enabled gerg
2011-12-26 19:32 ` Geert Uytterhoeven
2011-12-26 19:33 ` Geert Uytterhoeven
2011-12-28 1:35 ` Greg Ungerer
2011-12-29 4:52 ` Greg Ungerer
-- strict thread matches above, loose matches on Subject: below --
2011-12-16 12:35 [PATCH 00/35 v3] m68k: ColdFire MMU support gerg
2011-12-16 12:36 ` [PATCH 20/35] m68k: ColdFire V4e MMU context support code gerg
2011-11-25 3:40 [PATCH 00/35 v2] m68k: ColdFire MMU support gerg
2011-11-25 3:41 ` [PATCH 20/35] m68k: ColdFire V4e MMU context support code gerg
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1324610148-20666-21-git-send-email-gerg@snapgear.com \
--to=gerg@snapgear.com \
--cc=gerg@uclinux.org \
--cc=linux-m68k@vger.kernel.org \
--cc=uclinux-dev@uclinux.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox