powerpc: Randomise lower bits of stack address
[safe/jmp/linux-2.6] / arch / sh / mm / pmb.c
index b60ad83..8424167 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Privileged Space Mapping Buffer (PMB) Support.
  *
- * Copyright (C) 2005, 2006 Paul Mundt
+ * Copyright (C) 2005, 2006, 2007 Paul Mundt
  *
  * P1/P2 Section mapping definitions from map32.h, which was:
  *
@@ -27,6 +27,7 @@
 #include <asm/pgtable.h>
 #include <asm/mmu.h>
 #include <asm/io.h>
+#include <asm/mmu_context.h>
 
 #define NR_PMB_ENTRIES 16
 
@@ -68,6 +69,32 @@ static inline unsigned long mk_pmb_data(unsigned int entry)
        return mk_pmb_entry(entry) | PMB_DATA;
 }
 
+static DEFINE_SPINLOCK(pmb_list_lock);
+static struct pmb_entry *pmb_list;
+
+static inline void pmb_list_add(struct pmb_entry *pmbe)
+{
+       struct pmb_entry **p, *tmp;
+
+       p = &pmb_list;
+       while ((tmp = *p) != NULL)
+               p = &tmp->next;
+
+       pmbe->next = tmp;
+       *p = pmbe;
+}
+
+static inline void pmb_list_del(struct pmb_entry *pmbe)
+{
+       struct pmb_entry **p, *tmp;
+
+       for (p = &pmb_list; (tmp = *p); p = &tmp->next)
+               if (tmp == pmbe) {
+                       *p = tmp->next;
+                       return;
+               }
+}
+
 struct pmb_entry *pmb_alloc(unsigned long vpn, unsigned long ppn,
                            unsigned long flags)
 {
@@ -81,11 +108,19 @@ struct pmb_entry *pmb_alloc(unsigned long vpn, unsigned long ppn,
        pmbe->ppn       = ppn;
        pmbe->flags     = flags;
 
+       spin_lock_irq(&pmb_list_lock);
+       pmb_list_add(pmbe);
+       spin_unlock_irq(&pmb_list_lock);
+
        return pmbe;
 }
 
 void pmb_free(struct pmb_entry *pmbe)
 {
+       spin_lock_irq(&pmb_list_lock);
+       pmb_list_del(pmbe);
+       spin_unlock_irq(&pmb_list_lock);
+
        kmem_cache_free(pmb_cache, pmbe);
 }
 
@@ -111,7 +146,7 @@ repeat:
 
        ctrl_outl(vpn | PMB_V, mk_pmb_addr(pos));
 
-#ifdef CONFIG_SH_WRITETHROUGH
+#ifdef CONFIG_CACHE_WRITETHROUGH
        /*
         * When we are in 32-bit address extended mode, CCR.CB becomes
         * invalid, so care must be taken to manually adjust cacheable
@@ -128,18 +163,18 @@ repeat:
        return 0;
 }
 
-int set_pmb_entry(struct pmb_entry *pmbe)
+int __uses_jump_to_uncached set_pmb_entry(struct pmb_entry *pmbe)
 {
        int ret;
 
-       jump_to_P2();
+       jump_to_uncached();
        ret = __set_pmb_entry(pmbe->vpn, pmbe->ppn, pmbe->flags, &pmbe->entry);
-       back_to_P1();
+       back_to_cached();
 
        return ret;
 }
 
-void clear_pmb_entry(struct pmb_entry *pmbe)
+void __uses_jump_to_uncached clear_pmb_entry(struct pmb_entry *pmbe)
 {
        unsigned int entry = pmbe->entry;
        unsigned long addr;
@@ -153,7 +188,7 @@ void clear_pmb_entry(struct pmb_entry *pmbe)
                     entry >= NR_PMB_ENTRIES))
                return;
 
-       jump_to_P2();
+       jump_to_uncached();
 
        /* Clear V-bit */
        addr = mk_pmb_addr(entry);
@@ -162,36 +197,11 @@ void clear_pmb_entry(struct pmb_entry *pmbe)
        addr = mk_pmb_data(entry);
        ctrl_outl(ctrl_inl(addr) & ~PMB_V, addr);
 
-       back_to_P1();
+       back_to_cached();
 
        clear_bit(entry, &pmb_map);
 }
 
-static DEFINE_SPINLOCK(pmb_list_lock);
-static struct pmb_entry *pmb_list;
-
-static inline void pmb_list_add(struct pmb_entry *pmbe)
-{
-       struct pmb_entry **p, *tmp;
-
-       p = &pmb_list;
-       while ((tmp = *p) != NULL)
-               p = &tmp->next;
-
-       pmbe->next = tmp;
-       *p = pmbe;
-}
-
-static inline void pmb_list_del(struct pmb_entry *pmbe)
-{
-       struct pmb_entry **p, *tmp;
-
-       for (p = &pmb_list; (tmp = *p); p = &tmp->next)
-               if (tmp == pmbe) {
-                       *p = tmp->next;
-                       return;
-               }
-}
 
 static struct {
        unsigned long size;
@@ -283,39 +293,26 @@ void pmb_unmap(unsigned long addr)
        } while (pmbe);
 }
 
-static void pmb_cache_ctor(void *pmb, struct kmem_cache *cachep, unsigned long flags)
+static void pmb_cache_ctor(void *pmb)
 {
        struct pmb_entry *pmbe = pmb;
 
        memset(pmb, 0, sizeof(struct pmb_entry));
 
-       spin_lock_irq(&pmb_list_lock);
-
        pmbe->entry = PMB_NO_ENTRY;
-       pmb_list_add(pmbe);
-
-       spin_unlock_irq(&pmb_list_lock);
-}
-
-static void pmb_cache_dtor(void *pmb, struct kmem_cache *cachep, unsigned long flags)
-{
-       spin_lock_irq(&pmb_list_lock);
-       pmb_list_del(pmb);
-       spin_unlock_irq(&pmb_list_lock);
 }
 
-static int __init pmb_init(void)
+static int __uses_jump_to_uncached pmb_init(void)
 {
        unsigned int nr_entries = ARRAY_SIZE(pmb_init_map);
-       unsigned int entry;
+       unsigned int entry, i;
 
        BUG_ON(unlikely(nr_entries >= NR_PMB_ENTRIES));
 
-       pmb_cache = kmem_cache_create("pmb", sizeof(struct pmb_entry),
-                                     0, 0, pmb_cache_ctor, pmb_cache_dtor);
-       BUG_ON(!pmb_cache);
+       pmb_cache = kmem_cache_create("pmb", sizeof(struct pmb_entry), 0,
+                                     SLAB_PANIC, pmb_cache_ctor);
 
-       jump_to_P2();
+       jump_to_uncached();
 
        /*
         * Ordering is important, P2 must be mapped in the PMB before we
@@ -333,7 +330,12 @@ static int __init pmb_init(void)
        /* PMB.SE and UB[7] */
        ctrl_outl((1 << 31) | (1 << 7), PMB_PASCR);
 
-       back_to_P1();
+       /* Flush out the TLB */
+       i =  ctrl_inl(MMUCR);
+       i |= MMUCR_TI;
+       ctrl_outl(i, MMUCR);
+
+       back_to_cached();
 
        return 0;
 }
@@ -378,12 +380,12 @@ static int pmb_debugfs_open(struct inode *inode, struct file *file)
        return single_open(file, pmb_seq_show, NULL);
 }
 
-static struct file_operations pmb_debugfs_fops = {
+static const struct file_operations pmb_debugfs_fops = {
        .owner          = THIS_MODULE,
        .open           = pmb_debugfs_open,
        .read           = seq_read,
        .llseek         = seq_lseek,
-       .release        = seq_release,
+       .release        = single_release,
 };
 
 static int __init pmb_debugfs_init(void)
@@ -391,7 +393,9 @@ static int __init pmb_debugfs_init(void)
        struct dentry *dentry;
 
        dentry = debugfs_create_file("pmb", S_IFREG | S_IRUGO,
-                                    NULL, NULL, &pmb_debugfs_fops);
+                                    sh_debugfs_root, NULL, &pmb_debugfs_fops);
+       if (!dentry)
+               return -ENOMEM;
        if (IS_ERR(dentry))
                return PTR_ERR(dentry);