summaryrefslogtreecommitdiff
path: root/include/asm-arm
diff options
context:
space:
mode:
authorRussell King <rmk@flint.arm.linux.org.uk>2003-08-14 17:51:39 +0100
committerRussell King <rmk@flint.arm.linux.org.uk>2003-08-14 17:51:39 +0100
commitf1a3a362000963535d0be3d6fcac8f25c4569dcb (patch)
tree2a3fc4ad028dd3732011a2e6de00fdd3d35ca02d /include/asm-arm
parentaa5f1ea77b7d635db0345ee068b68f595c265193 (diff)
[ARM] Add ARMv6 MMU context handling.
Add MMU context ID handling.
Diffstat (limited to 'include/asm-arm')
-rw-r--r--include/asm-arm/mmu.h17
-rw-r--r--include/asm-arm/mmu_context.h40
2 files changed, 53 insertions, 4 deletions
diff --git a/include/asm-arm/mmu.h b/include/asm-arm/mmu.h
index 9b8d3d781a1e..c33797d6cc7b 100644
--- a/include/asm-arm/mmu.h
+++ b/include/asm-arm/mmu.h
@@ -1,9 +1,18 @@
#ifndef __ARM_MMU_H
#define __ARM_MMU_H
-/*
- * The ARM doesn't have a mmu context
- */
-typedef struct { } mm_context_t;
+#include <linux/config.h>
+
+typedef struct {
+#if __LINUX_ARM_ARCH__ >= 6
+ unsigned int id;
+#endif
+} mm_context_t;
+
+#if __LINUX_ARM_ARCH__ >= 6
+#define ASID(mm) ((mm)->context.id & 255)
+#else
+#define ASID(mm) (0)
+#endif
#endif
diff --git a/include/asm-arm/mmu_context.h b/include/asm-arm/mmu_context.h
index e0340f5fbf32..a4cb79241a73 100644
--- a/include/asm-arm/mmu_context.h
+++ b/include/asm-arm/mmu_context.h
@@ -15,7 +15,45 @@
#include <asm/proc-fns.h>
+#if __LINUX_ARM_ARCH__ >= 6
+
+/*
+ * On ARMv6, we have the following structure in the Context ID:
+ *
+ * 31 7 0
+ * +-------------------------+-----------+
+ * | process ID | ASID |
+ * +-------------------------+-----------+
+ * | context ID |
+ * +-------------------------------------+
+ *
+ * The ASID is used to tag entries in the CPU caches and TLBs.
+ * The context ID is used by debuggers and trace logic, and
+ * should be unique within all running processes.
+ */
+#define ASID_BITS 8
+#define ASID_MASK ((~0) << ASID_BITS)
+
+extern unsigned int cpu_last_asid;
+
+void __init_new_context(struct task_struct *tsk, struct mm_struct *mm);
+void __new_context(struct mm_struct *mm);
+
+static inline void check_context(struct mm_struct *mm)
+{
+ if (unlikely((mm->context.id ^ cpu_last_asid) >> ASID_BITS))
+ __new_context(mm);
+}
+
+#define init_new_context(tsk,mm) (__init_new_context(tsk,mm),0)
+
+#else
+
+#define check_context(mm) do { } while (0)
#define init_new_context(tsk,mm) 0
+
+#endif
+
#define destroy_context(mm) do { } while(0)
/*
@@ -43,6 +81,7 @@ switch_mm(struct mm_struct *prev, struct mm_struct *next,
struct task_struct *tsk)
{
if (prev != next) {
+ check_context(next);
cpu_switch_mm(next->pgd, next);
}
}
@@ -51,6 +90,7 @@ switch_mm(struct mm_struct *prev, struct mm_struct *next,
static inline void activate_mm(struct mm_struct *prev, struct mm_struct *next)
{
+ check_context(next);
cpu_switch_mm(next->pgd, next);
}