sh: Acquire some more page flags for SH-5.
authorMatt Fleming <matt@console-pimps.org>
Thu, 19 Nov 2009 21:11:05 +0000 (21:11 +0000)
committerMatt Fleming <matt@console-pimps.org>
Sat, 16 Jan 2010 14:29:06 +0000 (14:29 +0000)
We need some more page flags to hook up _PAGE_WIRED (and eventually
other things). So use the unused PTE bits above the PPN field as no
implementations use these for anything currently.

Now that we have _PAGE_WIRED let's provide the SH-5 functions for wiring
up TLB entries.

Signed-off-by: Matt Fleming <matt@console-pimps.org>
arch/sh/include/asm/page.h
arch/sh/include/asm/pgtable_64.h
arch/sh/include/asm/tlb.h
arch/sh/mm/tlbflush_64.c

index a86c0f1..61e5810 100644 (file)
@@ -88,7 +88,7 @@ typedef struct { unsigned long pgd; } pgd_t;
 #define __pte(x)       ((pte_t) { (x) } )
 #else
 typedef struct { unsigned long long pte_low; } pte_t;
-typedef struct { unsigned long pgprot; } pgprot_t;
+typedef struct { unsigned long long pgprot; } pgprot_t;
 typedef struct { unsigned long pgd; } pgd_t;
 #define pte_val(x)     ((x).pte_low)
 #define __pte(x)       ((pte_t) { (x) } )
index dd38158..0ee4677 100644 (file)
@@ -123,8 +123,21 @@ static __inline__ void set_pte(pte_t *pteptr, pte_t pteval)
 #define _PAGE_DIRTY    0x400  /* software: page accessed in write */
 #define _PAGE_ACCESSED 0x800  /* software: page referenced */
 
+/* Wrapper for extended mode pgprot twiddling */
+#define _PAGE_EXT(x)           ((unsigned long long)(x) << 32)
+
+/*
+ * We can use the sign-extended bits in the PTEL to get 32 bits of
+ * software flags. This works for now because no implementations uses
+ * anything above the PPN field.
+ */
+#define _PAGE_WIRED    _PAGE_EXT(0x001) /* software: wire the tlb entry */
+
+#define _PAGE_CLEAR_FLAGS      (_PAGE_PRESENT | _PAGE_FILE | _PAGE_SHARED | \
+                                _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_WIRED)
+
 /* Mask which drops software flags */
-#define _PAGE_FLAGS_HARDWARE_MASK      0xfffffffffffff3dbLL
+#define _PAGE_FLAGS_HARDWARE_MASK      (NEFF_MASK & ~(_PAGE_CLEAR_FLAGS))
 
 /*
  * HugeTLB support
index 3ed2f7a..dfc8fcd 100644 (file)
@@ -11,6 +11,7 @@
 #ifdef CONFIG_MMU
 #include <asm/pgalloc.h>
 #include <asm/tlbflush.h>
+#include <asm/mmu_context.h>
 
 /*
  * TLB handling.  This allows us to remove pages from the page
@@ -100,6 +101,46 @@ tlb_end_vma(struct mmu_gather *tlb, struct vm_area_struct *vma)
 #ifdef CONFIG_CPU_SH4
 extern void tlb_wire_entry(struct vm_area_struct *, unsigned long, pte_t);
 extern void tlb_unwire_entry(void);
+#elif defined(CONFIG_SUPERH64)
+static int dtlb_entry;
+static unsigned long long dtlb_entries[64];
+
+static inline void tlb_wire_entry(struct vm_area_struct *vma,
+                                 unsigned long addr, pte_t pte)
+{
+       unsigned long long entry;
+       unsigned long paddr, flags;
+
+       BUG_ON(dtlb_entry == 64);
+
+       local_irq_save(flags);
+
+       entry = sh64_get_wired_dtlb_entry();
+       dtlb_entries[dtlb_entry++] = entry;
+
+       paddr = pte_val(pte) & _PAGE_FLAGS_HARDWARE_MASK;
+       paddr &= ~PAGE_MASK;
+
+       sh64_setup_tlb_slot(entry, addr, get_asid(), paddr);
+
+       local_irq_restore(flags);
+}
+
+static inline void tlb_unwire_entry(void)
+{
+       unsigned long long entry;
+       unsigned long flags;
+
+       BUG_ON(!dtlb_entry);
+
+       local_irq_save(flags);
+       entry = dtlb_entries[dtlb_entry--];
+
+       sh64_teardown_tlb_slot(entry);
+       sh64_put_wired_dtlb_entry(entry);
+
+       local_irq_restore(flags);
+}
 #else
 static inline void tlb_wire_entry(struct vm_area_struct *vma ,
                                  unsigned long addr, pte_t pte)
index de0b0e8..706da1d 100644 (file)
@@ -36,7 +36,7 @@ extern void die(const char *,struct pt_regs *,long);
 
 static inline void print_prots(pgprot_t prot)
 {
-       printk("prot is 0x%08lx\n",pgprot_val(prot));
+       printk("prot is 0x%016llx\n",pgprot_val(prot));
 
        printk("%s %s %s %s %s\n",PPROT(_PAGE_SHARED),PPROT(_PAGE_READ),
               PPROT(_PAGE_EXECUTE),PPROT(_PAGE_WRITE),PPROT(_PAGE_USER));