Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/sh/mm/tlb-debugfs.c
10817 views
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
struct dentry *itlb, *utlb;
153
154
itlb = debugfs_create_file("itlb", S_IRUSR, arch_debugfs_dir,
155
(unsigned int *)TLB_TYPE_ITLB,
156
&tlb_debugfs_fops);
157
if (unlikely(!itlb))
158
return -ENOMEM;
159
160
utlb = debugfs_create_file("utlb", S_IRUSR, arch_debugfs_dir,
161
(unsigned int *)TLB_TYPE_UTLB,
162
&tlb_debugfs_fops);
163
if (unlikely(!utlb)) {
164
debugfs_remove(itlb);
165
return -ENOMEM;
166
}
167
168
return 0;
169
}
170
module_init(tlb_debugfs_init);
171
172
MODULE_LICENSE("GPL v2");
173
174