root/arch/sh/mm/tlb-debugfs.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. tlb_seq_show
  2. tlb_debugfs_open
  3. tlb_debugfs_init

   1 /*
   2  * arch/sh/mm/tlb-debugfs.c
   3  *
   4  * debugfs ops for SH-4 ITLB/UTLBs.
   5  *
   6  * Copyright (C) 2010  Matt Fleming
   7  *
   8  * This file is subject to the terms and conditions of the GNU General Public
   9  * License.  See the file "COPYING" in the main directory of this archive
  10  * for more details.
  11  */
  12 #include <linux/init.h>
  13 #include <linux/module.h>
  14 #include <linux/debugfs.h>
  15 #include <linux/seq_file.h>
  16 #include <asm/processor.h>
  17 #include <asm/mmu_context.h>
  18 #include <asm/tlbflush.h>
  19 
  20 enum tlb_type {
  21         TLB_TYPE_ITLB,
  22         TLB_TYPE_UTLB,
  23 };
  24 
  25 static struct {
  26         int bits;
  27         const char *size;
  28 } tlb_sizes[] = {
  29         { 0x0, "  1KB" },
  30         { 0x1, "  4KB" },
  31         { 0x2, "  8KB" },
  32         { 0x4, " 64KB" },
  33         { 0x5, "256KB" },
  34         { 0x7, "  1MB" },
  35         { 0x8, "  4MB" },
  36         { 0xc, " 64MB" },
  37 };
  38 
  39 static int tlb_seq_show(struct seq_file *file, void *iter)
  40 {
  41         unsigned int tlb_type = (unsigned int)file->private;
  42         unsigned long addr1, addr2, data1, data2;
  43         unsigned long flags;
  44         unsigned long mmucr;
  45         unsigned int nentries, entry;
  46         unsigned int urb;
  47 
  48         mmucr = __raw_readl(MMUCR);
  49         if ((mmucr & 0x1) == 0) {
  50                 seq_printf(file, "address translation disabled\n");
  51                 return 0;
  52         }
  53 
  54         if (tlb_type == TLB_TYPE_ITLB) {
  55                 addr1 = MMU_ITLB_ADDRESS_ARRAY;
  56                 addr2 = MMU_ITLB_ADDRESS_ARRAY2;
  57                 data1 = MMU_ITLB_DATA_ARRAY;
  58                 data2 = MMU_ITLB_DATA_ARRAY2;
  59                 nentries = 4;
  60         } else {
  61                 addr1 = MMU_UTLB_ADDRESS_ARRAY;
  62                 addr2 = MMU_UTLB_ADDRESS_ARRAY2;
  63                 data1 = MMU_UTLB_DATA_ARRAY;
  64                 data2 = MMU_UTLB_DATA_ARRAY2;
  65                 nentries = 64;
  66         }
  67 
  68         local_irq_save(flags);
  69         jump_to_uncached();
  70 
  71         urb = (mmucr & MMUCR_URB) >> MMUCR_URB_SHIFT;
  72 
  73         /* Make the "entry >= urb" test fail. */
  74         if (urb == 0)
  75                 urb = MMUCR_URB_NENTRIES + 1;
  76 
  77         if (tlb_type == TLB_TYPE_ITLB) {
  78                 addr1 = MMU_ITLB_ADDRESS_ARRAY;
  79                 addr2 = MMU_ITLB_ADDRESS_ARRAY2;
  80                 data1 = MMU_ITLB_DATA_ARRAY;
  81                 data2 = MMU_ITLB_DATA_ARRAY2;
  82                 nentries = 4;
  83         } else {
  84                 addr1 = MMU_UTLB_ADDRESS_ARRAY;
  85                 addr2 = MMU_UTLB_ADDRESS_ARRAY2;
  86                 data1 = MMU_UTLB_DATA_ARRAY;
  87                 data2 = MMU_UTLB_DATA_ARRAY2;
  88                 nentries = 64;
  89         }
  90 
  91         seq_printf(file, "entry:     vpn        ppn     asid  size valid wired\n");
  92 
  93         for (entry = 0; entry < nentries; entry++) {
  94                 unsigned long vpn, ppn, asid, size;
  95                 unsigned long valid;
  96                 unsigned long val;
  97                 const char *sz = "    ?";
  98                 int i;
  99 
 100                 val = __raw_readl(addr1 | (entry << MMU_TLB_ENTRY_SHIFT));
 101                 ctrl_barrier();
 102                 vpn = val & 0xfffffc00;
 103                 valid = val & 0x100;
 104 
 105                 val = __raw_readl(addr2 | (entry << MMU_TLB_ENTRY_SHIFT));
 106                 ctrl_barrier();
 107                 asid = val & MMU_CONTEXT_ASID_MASK;
 108 
 109                 val = __raw_readl(data1 | (entry << MMU_TLB_ENTRY_SHIFT));
 110                 ctrl_barrier();
 111                 ppn = (val & 0x0ffffc00) << 4;
 112 
 113                 val = __raw_readl(data2 | (entry << MMU_TLB_ENTRY_SHIFT));
 114                 ctrl_barrier();
 115                 size = (val & 0xf0) >> 4;
 116 
 117                 for (i = 0; i < ARRAY_SIZE(tlb_sizes); i++) {
 118                         if (tlb_sizes[i].bits == size)
 119                                 break;
 120                 }
 121 
 122                 if (i != ARRAY_SIZE(tlb_sizes))
 123                         sz = tlb_sizes[i].size;
 124 
 125                 seq_printf(file, "%2d:    0x%08lx 0x%08lx %5lu %s   %s     %s\n",
 126                            entry, vpn, ppn, asid,
 127                            sz, valid ? "V" : "-",
 128                            (urb <= entry) ? "W" : "-");
 129         }
 130 
 131         back_to_cached();
 132         local_irq_restore(flags);
 133 
 134         return 0;
 135 }
 136 
 137 static int tlb_debugfs_open(struct inode *inode, struct file *file)
 138 {
 139         return single_open(file, tlb_seq_show, inode->i_private);
 140 }
 141 
 142 static const struct file_operations tlb_debugfs_fops = {
 143         .owner          = THIS_MODULE,
 144         .open           = tlb_debugfs_open,
 145         .read           = seq_read,
 146         .llseek         = seq_lseek,
 147         .release        = single_release,
 148 };
 149 
 150 static int __init tlb_debugfs_init(void)
 151 {
 152         debugfs_create_file("itlb", S_IRUSR, arch_debugfs_dir,
 153                             (void *)TLB_TYPE_ITLB, &tlb_debugfs_fops);
 154         debugfs_create_file("utlb", S_IRUSR, arch_debugfs_dir,
 155                             (void *)TLB_TYPE_UTLB, &tlb_debugfs_fops);
 156         return 0;
 157 }
 158 module_init(tlb_debugfs_init);
 159 
 160 MODULE_LICENSE("GPL v2");

/* [<][>][^][v][top][bottom][index][help] */