]> pilppa.com Git - linux-2.6-omap-h63xx.git/commitdiff
sh: Support for extended ASIDs on PTEAEX-capable SH-X3 cores.
authorPaul Mundt <lethal@linux-sh.org>
Tue, 17 Mar 2009 08:49:49 +0000 (17:49 +0900)
committerPaul Mundt <lethal@linux-sh.org>
Tue, 17 Mar 2009 08:49:49 +0000 (17:49 +0900)
This adds support for extended ASIDs (up to 16-bits) on newer SH-X3 cores
that implement the PTAEX register and respective functionality. Presently
only the 65nm SH7786 (90nm only supports legacy 8-bit ASIDs).

The main change is in how the PTE is written out when loading the entry
in to the TLB, as well as in how the TLB entry is selectively flushed.

While SH-X2 extended mode splits out the memory-mapped U and I-TLB data
arrays for extra bits, extended ASID mode splits out the address arrays.
While we don't use the memory-mapped data array access, the address
array accesses are necessary for selective TLB flushes, so these are
implemented newly and replace the generic SH-4 implementation.

With this, TLB flushes in switch_mm() are almost non-existent on newer
parts.

Signed-off-by: Paul Mundt <lethal@linux-sh.org>
arch/sh/Kconfig
arch/sh/Kconfig.cpu
arch/sh/include/asm/cpu-features.h
arch/sh/include/asm/mmu_context.h
arch/sh/include/asm/mmu_context_32.h
arch/sh/include/cpu-sh4/cpu/mmu_context.h
arch/sh/kernel/cpu/sh4/probe.c
arch/sh/kernel/setup.c
arch/sh/mm/Makefile_32
arch/sh/mm/tlb-pteaex.c [new file with mode: 0644]

index a0c879d17fd62e72dc25e4d2c77caef618c4f886..6c56495fd15820ee4b9aaaf71097ddb35ca7421b 100644 (file)
@@ -365,6 +365,7 @@ config CPU_SUBTYPE_SH7786
        bool "Support SH7786 processor"
        select CPU_SH4A
        select CPU_SHX3
+       select CPU_HAS_PTEAEX
        select ARCH_SPARSEMEM_ENABLE
        select SYS_SUPPORTS_NUMA
 
index 0e27fe3b182b74e17e05a4b612a3a8f5081c4382..c7d704381a6d5425548751ed4874580a0e3c1ab9 100644 (file)
@@ -104,6 +104,9 @@ config CPU_HAS_SR_RB
 config CPU_HAS_PTEA
        bool
 
+config CPU_HAS_PTEAEX
+       bool
+
 config CPU_HAS_DSP
        bool
 
index 86308aa3973180867a7b30a2f95e43f6137e54c2..694abe490edb73edb280654b2ad8eec9a21d0ed6 100644 (file)
@@ -21,5 +21,6 @@
 #define CPU_HAS_LLSC           0x0040  /* movli.l/movco.l */
 #define CPU_HAS_L2_CACHE       0x0080  /* Secondary cache / URAM */
 #define CPU_HAS_OP32           0x0100  /* 32-bit instruction support */
+#define CPU_HAS_PTEAEX         0x0200  /* PTE ASID Extension support */
 
 #endif /* __ASM_SH_CPU_FEATURES_H */
index 5d9157bd474df7b6988f512e85389b1b31da0d5a..2a9c55f1a83f9f7429104b4c2671460d7caba373 100644 (file)
  *    (a) TLB cache version (or round, cycle whatever expression you like)
  *    (b) ASID (Address Space IDentifier)
  */
+#ifdef CONFIG_CPU_HAS_PTEAEX
+#define MMU_CONTEXT_ASID_MASK          0x0000ffff
+#else
 #define MMU_CONTEXT_ASID_MASK          0x000000ff
-#define MMU_CONTEXT_VERSION_MASK       0xffffff00
-#define MMU_CONTEXT_FIRST_VERSION      0x00000100
-#define NO_CONTEXT                     0UL
+#endif
 
-/* ASID is 8-bit value, so it can't be 0x100 */
-#define MMU_NO_ASID                    0x100
+#define MMU_CONTEXT_VERSION_MASK       (~0UL & ~MMU_CONTEXT_ASID_MASK)
+#define MMU_CONTEXT_FIRST_VERSION      (MMU_CONTEXT_ASID_MASK + 1)
+
+/* Impossible ASID value, to differentiate from NO_CONTEXT. */
+#define MMU_NO_ASID                    MMU_CONTEXT_FIRST_VERSION
+#define NO_CONTEXT                     0UL
 
 #define asid_cache(cpu)                (cpu_data[cpu].asid_cache)
 
index f4f9aebd68b797a7df2d9005af2e6e3ad0b4d58f..8ef800c549abcfd4be2ff3e8db9325ed88762442 100644 (file)
@@ -10,6 +10,17 @@ static inline void destroy_context(struct mm_struct *mm)
        /* Do nothing */
 }
 
+#ifdef CONFIG_CPU_HAS_PTEAEX
+static inline void set_asid(unsigned long asid)
+{
+       __raw_writel(asid, MMU_PTEAEX);
+}
+
+static inline unsigned long get_asid(void)
+{
+       return __raw_readl(MMU_PTEAEX) & MMU_CONTEXT_ASID_MASK;
+}
+#else
 static inline void set_asid(unsigned long asid)
 {
        unsigned long __dummy;
@@ -33,6 +44,7 @@ static inline unsigned long get_asid(void)
        asid &= MMU_CONTEXT_ASID_MASK;
        return asid;
 }
+#endif /* CONFIG_CPU_HAS_PTEAEX */
 
 /* MMU_TTB is used for optimizing the fault handling. */
 static inline void set_TTB(pgd_t *pgd)
index 9ea8eb27b18e20dd69d43ce9897a163a3851c9ed..3ce7ef6c29789ae0ff876703257f6f4b0d42d8d0 100644 (file)
 #define MMU_PTEL       0xFF000004      /* Page table entry register LOW */
 #define MMU_TTB                0xFF000008      /* Translation table base register */
 #define MMU_TEA                0xFF00000C      /* TLB Exception Address */
-#define MMU_PTEA       0xFF000034      /* Page table entry assistance register */
+#define MMU_PTEA       0xFF000034      /* PTE assistance register */
+#define MMU_PTEAEX     0xFF00007C      /* PTE ASID extension register */
 
 #define MMUCR          0xFF000010      /* MMU Control Register */
 
-#define MMU_ITLB_ADDRESS_ARRAY 0xF2000000
 #define MMU_UTLB_ADDRESS_ARRAY 0xF6000000
+#define MMU_UTLB_ADDRESS_ARRAY2        0xF6800000
 #define MMU_PAGE_ASSOC_BIT     0x80
 
 #define MMUCR_TI               (1<<2)
 
-#ifdef CONFIG_X2TLB
-#define MMUCR_ME               (1 << 7)
-#else
-#define MMUCR_ME               (0)
-#endif
-
 #if defined(CONFIG_32BIT) && defined(CONFIG_CPU_SUBTYPE_ST40)
 #define MMUCR_SE               (1 << 4)
 #else
 #define MMUCR_SE               (0)
 #endif
 
+#ifdef CONFIG_CPU_HAS_PTEAEX
+#define MMUCR_AEX              (1 << 6)
+#else
+#define MMUCR_AEX              (0)
+#endif
+
+#ifdef CONFIG_X2TLB
+#define MMUCR_ME               (1 << 7)
+#else
+#define MMUCR_ME               (0)
+#endif
+
 #ifdef CONFIG_SH_STORE_QUEUES
 #define MMUCR_SQMD             (1 << 9)
 #else
 #endif
 
 #define MMU_NTLB_ENTRIES       64
-#define MMU_CONTROL_INIT       (0x05|MMUCR_SQMD|MMUCR_ME|MMUCR_SE)
-
-#define MMU_ITLB_DATA_ARRAY    0xF3000000
-#define MMU_UTLB_DATA_ARRAY    0xF7000000
-
-#define MMU_UTLB_ENTRIES          64
-#define MMU_U_ENTRY_SHIFT          8
-#define MMU_UTLB_VALID         0x100
-#define MMU_ITLB_ENTRIES           4
-#define MMU_I_ENTRY_SHIFT          8
-#define MMU_ITLB_VALID         0x100
+#define MMU_CONTROL_INIT       (0x05|MMUCR_SQMD|MMUCR_ME|MMUCR_SE|MMUCR_AEX)
 
 #define TRA    0xff000020
 #define EXPEVT 0xff000024
index 2bd0ec962639b9d170bbe7e513d20089122d8fbe..3d3a3c4425a94a6edad883271ae771e617a13c1b 100644 (file)
@@ -134,7 +134,7 @@ int __init detect_cpu_and_cache_system(void)
                boot_cpu_data.icache.ways = 4;
                boot_cpu_data.dcache.ways = 4;
                boot_cpu_data.flags |= CPU_HAS_FPU | CPU_HAS_PERF_COUNTER |
-                       CPU_HAS_LLSC;
+                       CPU_HAS_LLSC | CPU_HAS_PTEAEX;
                break;
        case 0x3008:
                boot_cpu_data.icache.ways = 4;
index 61ab2a7f8647a600a2f1277ad0c93a8a67d1fab3..24c60251f68017d5c120b33b21a30dd46bb9c6e1 100644 (file)
@@ -449,7 +449,7 @@ EXPORT_SYMBOL(get_cpu_subtype);
 /* Symbolic CPU flags, keep in sync with asm/cpu-features.h */
 static const char *cpu_flags[] = {
        "none", "fpu", "p2flush", "mmuassoc", "dsp", "perfctr",
-       "ptea", "llsc", "l2", "op32", NULL
+       "ptea", "llsc", "l2", "op32", "pteaex", NULL
 };
 
 static void show_cpuflags(struct seq_file *m, struct sh_cpuinfo *c)
index 469ff1672451047e6c14c2821166b10b1503d636..986a1e0558348dfe2d8ef11873350918a28639ac 100644 (file)
@@ -25,8 +25,10 @@ obj-$(CONFIG_CPU_SH4)        += cache-debugfs.o
 endif
 
 ifdef CONFIG_MMU
-obj-$(CONFIG_CPU_SH3)  += tlb-sh3.o
-obj-$(CONFIG_CPU_SH4)  += tlb-sh4.o
+tlb-$(CONFIG_CPU_SH3)          := tlb-sh3.o
+tlb-$(CONFIG_CPU_SH4)          := tlb-sh4.o
+tlb-$(CONFIG_CPU_HAS_PTEAEX)   := tlb-pteaex.o
+obj-y                          += $(tlb-y)
 ifndef CONFIG_CACHE_OFF
 obj-$(CONFIG_CPU_SH4)          += pg-sh4.o
 obj-$(CONFIG_SH7705_CACHE_32KB)        += pg-sh7705.o
diff --git a/arch/sh/mm/tlb-pteaex.c b/arch/sh/mm/tlb-pteaex.c
new file mode 100644 (file)
index 0000000..5c9b2d7
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * arch/sh/mm/tlb-pteaex.c
+ *
+ * TLB operations for SH-X3 CPUs featuring PTE ASID Extensions.
+ *
+ * Copyright (C) 2009 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/io.h>
+#include <asm/system.h>
+#include <asm/mmu_context.h>
+#include <asm/cacheflush.h>
+
+void update_mmu_cache(struct vm_area_struct * vma,
+                     unsigned long address, pte_t pte)
+{
+       unsigned long flags;
+       unsigned long pteval;
+       unsigned long vpn;
+
+       /* Ptrace may call this routine. */
+       if (vma && current->active_mm != vma->vm_mm)
+               return;
+
+#ifndef CONFIG_CACHE_OFF
+       {
+               unsigned long pfn = pte_pfn(pte);
+
+               if (pfn_valid(pfn)) {
+                       struct page *page = pfn_to_page(pfn);
+
+                       if (!test_bit(PG_mapped, &page->flags)) {
+                               unsigned long phys = pte_val(pte) & PTE_PHYS_MASK;
+                               __flush_wback_region((void *)P1SEGADDR(phys),
+                                                    PAGE_SIZE);
+                               __set_bit(PG_mapped, &page->flags);
+                       }
+               }
+       }
+#endif
+
+       local_irq_save(flags);
+
+       /* Set PTEH register */
+       vpn = address & MMU_VPN_MASK;
+       __raw_writel(vpn, MMU_PTEH);
+
+       /* Set PTEAEX */
+       __raw_writel(get_asid(), MMU_PTEAEX);
+
+       pteval = pte.pte_low;
+
+       /* Set PTEA register */
+#ifdef CONFIG_X2TLB
+       /*
+        * For the extended mode TLB this is trivial, only the ESZ and
+        * EPR bits need to be written out to PTEA, with the remainder of
+        * the protection bits (with the exception of the compat-mode SZ
+        * and PR bits, which are cleared) being written out in PTEL.
+        */
+       __raw_writel(pte.pte_high, MMU_PTEA);
+#else
+       /* TODO: make this look less hacky */
+       __raw_writel(((pteval >> 28) & 0xe) | (pteval & 0x1), MMU_PTEA);
+#endif
+
+       /* Set PTEL register */
+       pteval &= _PAGE_FLAGS_HARDWARE_MASK; /* drop software flags */
+#ifdef CONFIG_CACHE_WRITETHROUGH
+       pteval |= _PAGE_WT;
+#endif
+       /* conveniently, we want all the software flags to be 0 anyway */
+       __raw_writel(pteval, MMU_PTEL);
+
+       /* Load the TLB */
+       asm volatile("ldtlb": /* no output */ : /* no input */ : "memory");
+       local_irq_restore(flags);
+}
+
+/*
+ * While SH-X2 extended TLB mode splits out the memory-mapped I/UTLB
+ * data arrays, SH-X3 cores with PTEAEX split out the memory-mapped
+ * address arrays. In compat mode the second array is inaccessible, while
+ * in extended mode, the legacy 8-bit ASID field in address array 1 has
+ * undefined behaviour.
+ */
+void __uses_jump_to_uncached local_flush_tlb_one(unsigned long asid,
+                                                unsigned long page)
+{
+       jump_to_uncached();
+       __raw_writel(page, MMU_UTLB_ADDRESS_ARRAY | MMU_PAGE_ASSOC_BIT);
+       __raw_writel(asid, MMU_UTLB_ADDRESS_ARRAY2 | MMU_PAGE_ASSOC_BIT);
+       back_to_cached();
+}