aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/lib-32
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/mips/lib-32
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'arch/mips/lib-32')
-rw-r--r--arch/mips/lib-32/Makefile25
-rw-r--r--arch/mips/lib-32/csum_partial.S240
-rw-r--r--arch/mips/lib-32/dump_tlb.c222
-rw-r--r--arch/mips/lib-32/memset.S145
-rw-r--r--arch/mips/lib-32/r3k_dump_tlb.c176
-rw-r--r--arch/mips/lib-32/watch.S60
6 files changed, 868 insertions, 0 deletions
diff --git a/arch/mips/lib-32/Makefile b/arch/mips/lib-32/Makefile
new file mode 100644
index 000000000000..fd6a2bafdfcf
--- /dev/null
+++ b/arch/mips/lib-32/Makefile
@@ -0,0 +1,25 @@
1#
2# Makefile for MIPS-specific library files..
3#
4
5lib-y += csum_partial.o memset.o watch.o
6
7obj-$(CONFIG_CPU_MIPS32) += dump_tlb.o
8obj-$(CONFIG_CPU_MIPS64) += dump_tlb.o
9obj-$(CONFIG_CPU_NEVADA) += dump_tlb.o
10obj-$(CONFIG_CPU_R10000) += dump_tlb.o
11obj-$(CONFIG_CPU_R3000) += r3k_dump_tlb.o
12obj-$(CONFIG_CPU_R4300) += dump_tlb.o
13obj-$(CONFIG_CPU_R4X00) += dump_tlb.o
14obj-$(CONFIG_CPU_R5000) += dump_tlb.o
15obj-$(CONFIG_CPU_R5432) += dump_tlb.o
16obj-$(CONFIG_CPU_R6000) +=
17obj-$(CONFIG_CPU_R8000) +=
18obj-$(CONFIG_CPU_RM7000) += dump_tlb.o
19obj-$(CONFIG_CPU_RM9000) += dump_tlb.o
20obj-$(CONFIG_CPU_SB1) += dump_tlb.o
21obj-$(CONFIG_CPU_TX39XX) += r3k_dump_tlb.o
22obj-$(CONFIG_CPU_TX49XX) += dump_tlb.o
23obj-$(CONFIG_CPU_VR41XX) += dump_tlb.o
24
25EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/lib-32/csum_partial.S b/arch/mips/lib-32/csum_partial.S
new file mode 100644
index 000000000000..ea257dbdcc40
--- /dev/null
+++ b/arch/mips/lib-32/csum_partial.S
@@ -0,0 +1,240 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 1998 Ralf Baechle
7 */
8#include <asm/asm.h>
9#include <asm/regdef.h>
10
11#define ADDC(sum,reg) \
12 addu sum, reg; \
13 sltu v1, sum, reg; \
14 addu sum, v1
15
16#define CSUM_BIGCHUNK(src, offset, sum, t0, t1, t2, t3) \
17 lw t0, (offset + 0x00)(src); \
18 lw t1, (offset + 0x04)(src); \
19 lw t2, (offset + 0x08)(src); \
20 lw t3, (offset + 0x0c)(src); \
21 ADDC(sum, t0); \
22 ADDC(sum, t1); \
23 ADDC(sum, t2); \
24 ADDC(sum, t3); \
25 lw t0, (offset + 0x10)(src); \
26 lw t1, (offset + 0x14)(src); \
27 lw t2, (offset + 0x18)(src); \
28 lw t3, (offset + 0x1c)(src); \
29 ADDC(sum, t0); \
30 ADDC(sum, t1); \
31 ADDC(sum, t2); \
32 ADDC(sum, t3); \
33
34/*
35 * a0: source address
36 * a1: length of the area to checksum
37 * a2: partial checksum
38 */
39
40#define src a0
41#define dest a1
42#define sum v0
43
44 .text
45 .set noreorder
46
47/* unknown src alignment and < 8 bytes to go */
48small_csumcpy:
49 move a1, t2
50
51 andi t0, a1, 4
52 beqz t0, 1f
53 andi t0, a1, 2
54
55 /* Still a full word to go */
56 ulw t1, (src)
57 addiu src, 4
58 ADDC(sum, t1)
59
601: move t1, zero
61 beqz t0, 1f
62 andi t0, a1, 1
63
64 /* Still a halfword to go */
65 ulhu t1, (src)
66 addiu src, 2
67
681: beqz t0, 1f
69 sll t1, t1, 16
70
71 lbu t2, (src)
72 nop
73
74#ifdef __MIPSEB__
75 sll t2, t2, 8
76#endif
77 or t1, t2
78
791: ADDC(sum, t1)
80
81 /* fold checksum */
82 sll v1, sum, 16
83 addu sum, v1
84 sltu v1, sum, v1
85 srl sum, sum, 16
86 addu sum, v1
87
88 /* odd buffer alignment? */
89 beqz t7, 1f
90 nop
91 sll v1, sum, 8
92 srl sum, sum, 8
93 or sum, v1
94 andi sum, 0xffff
951:
96 .set reorder
97 /* Add the passed partial csum. */
98 ADDC(sum, a2)
99 jr ra
100 .set noreorder
101
102/* ------------------------------------------------------------------------- */
103
104 .align 5
105LEAF(csum_partial)
106 move sum, zero
107 move t7, zero
108
109 sltiu t8, a1, 0x8
110 bnez t8, small_csumcpy /* < 8 bytes to copy */
111 move t2, a1
112
113 beqz a1, out
114 andi t7, src, 0x1 /* odd buffer? */
115
116hword_align:
117 beqz t7, word_align
118 andi t8, src, 0x2
119
120 lbu t0, (src)
121 subu a1, a1, 0x1
122#ifdef __MIPSEL__
123 sll t0, t0, 8
124#endif
125 ADDC(sum, t0)
126 addu src, src, 0x1
127 andi t8, src, 0x2
128
129word_align:
130 beqz t8, dword_align
131 sltiu t8, a1, 56
132
133 lhu t0, (src)
134 subu a1, a1, 0x2
135 ADDC(sum, t0)
136 sltiu t8, a1, 56
137 addu src, src, 0x2
138
139dword_align:
140 bnez t8, do_end_words
141 move t8, a1
142
143 andi t8, src, 0x4
144 beqz t8, qword_align
145 andi t8, src, 0x8
146
147 lw t0, 0x00(src)
148 subu a1, a1, 0x4
149 ADDC(sum, t0)
150 addu src, src, 0x4
151 andi t8, src, 0x8
152
153qword_align:
154 beqz t8, oword_align
155 andi t8, src, 0x10
156
157 lw t0, 0x00(src)
158 lw t1, 0x04(src)
159 subu a1, a1, 0x8
160 ADDC(sum, t0)
161 ADDC(sum, t1)
162 addu src, src, 0x8
163 andi t8, src, 0x10
164
165oword_align:
166 beqz t8, begin_movement
167 srl t8, a1, 0x7
168
169 lw t3, 0x08(src)
170 lw t4, 0x0c(src)
171 lw t0, 0x00(src)
172 lw t1, 0x04(src)
173 ADDC(sum, t3)
174 ADDC(sum, t4)
175 ADDC(sum, t0)
176 ADDC(sum, t1)
177 subu a1, a1, 0x10
178 addu src, src, 0x10
179 srl t8, a1, 0x7
180
181begin_movement:
182 beqz t8, 1f
183 andi t2, a1, 0x40
184
185move_128bytes:
186 CSUM_BIGCHUNK(src, 0x00, sum, t0, t1, t3, t4)
187 CSUM_BIGCHUNK(src, 0x20, sum, t0, t1, t3, t4)
188 CSUM_BIGCHUNK(src, 0x40, sum, t0, t1, t3, t4)
189 CSUM_BIGCHUNK(src, 0x60, sum, t0, t1, t3, t4)
190 subu t8, t8, 0x01
191 bnez t8, move_128bytes
192 addu src, src, 0x80
193
1941:
195 beqz t2, 1f
196 andi t2, a1, 0x20
197
198move_64bytes:
199 CSUM_BIGCHUNK(src, 0x00, sum, t0, t1, t3, t4)
200 CSUM_BIGCHUNK(src, 0x20, sum, t0, t1, t3, t4)
201 addu src, src, 0x40
202
2031:
204 beqz t2, do_end_words
205 andi t8, a1, 0x1c
206
207move_32bytes:
208 CSUM_BIGCHUNK(src, 0x00, sum, t0, t1, t3, t4)
209 andi t8, a1, 0x1c
210 addu src, src, 0x20
211
212do_end_words:
213 beqz t8, maybe_end_cruft
214 srl t8, t8, 0x2
215
216end_words:
217 lw t0, (src)
218 subu t8, t8, 0x1
219 ADDC(sum, t0)
220 bnez t8, end_words
221 addu src, src, 0x4
222
223maybe_end_cruft:
224 andi t2, a1, 0x3
225
226small_memcpy:
227 j small_csumcpy; move a1, t2
228 beqz t2, out
229 move a1, t2
230
231end_bytes:
232 lb t0, (src)
233 subu a1, a1, 0x1
234 bnez a2, end_bytes
235 addu src, src, 0x1
236
237out:
238 jr ra
239 move v0, sum
240 END(csum_partial)
diff --git a/arch/mips/lib-32/dump_tlb.c b/arch/mips/lib-32/dump_tlb.c
new file mode 100644
index 000000000000..019ac8f005d7
--- /dev/null
+++ b/arch/mips/lib-32/dump_tlb.c
@@ -0,0 +1,222 @@
1/*
2 * Dump R4x00 TLB for debugging purposes.
3 *
4 * Copyright (C) 1994, 1995 by Waldorf Electronics, written by Ralf Baechle.
5 * Copyright (C) 1999 by Silicon Graphics, Inc.
6 */
7#include <linux/config.h>
8#include <linux/kernel.h>
9#include <linux/mm.h>
10#include <linux/sched.h>
11#include <linux/string.h>
12
13#include <asm/bootinfo.h>
14#include <asm/cachectl.h>
15#include <asm/cpu.h>
16#include <asm/mipsregs.h>
17#include <asm/page.h>
18#include <asm/pgtable.h>
19
20static inline const char *msk2str(unsigned int mask)
21{
22 switch (mask) {
23 case PM_4K: return "4kb";
24 case PM_16K: return "16kb";
25 case PM_64K: return "64kb";
26 case PM_256K: return "256kb";
27#ifndef CONFIG_CPU_VR41XX
28 case PM_1M: return "1Mb";
29 case PM_4M: return "4Mb";
30 case PM_16M: return "16Mb";
31 case PM_64M: return "64Mb";
32 case PM_256M: return "256Mb";
33#endif
34 }
35
36 return "unknown";
37}
38
39#define BARRIER() \
40 __asm__ __volatile__( \
41 ".set\tnoreorder\n\t" \
42 "nop;nop;nop;nop;nop;nop;nop\n\t" \
43 ".set\treorder");
44
45void dump_tlb(int first, int last)
46{
47 unsigned int pagemask, c0, c1, asid;
48 unsigned long long entrylo0, entrylo1;
49 unsigned long entryhi;
50 int i;
51
52 asid = read_c0_entryhi() & 0xff;
53
54 printk("\n");
55 for (i = first; i <= last; i++) {
56 write_c0_index(i);
57 BARRIER();
58 tlb_read();
59 BARRIER();
60 pagemask = read_c0_pagemask();
61 entryhi = read_c0_entryhi();
62 entrylo0 = read_c0_entrylo0();
63 entrylo1 = read_c0_entrylo1();
64
65 /* Unused entries have a virtual address in KSEG0. */
66 if ((entryhi & 0xf0000000) != 0x80000000
67 && (entryhi & 0xff) == asid) {
68 /*
69 * Only print entries in use
70 */
71 printk("Index: %2d pgmask=%s ", i, msk2str(pagemask));
72
73 c0 = (entrylo0 >> 3) & 7;
74 c1 = (entrylo1 >> 3) & 7;
75
76 printk("va=%08lx asid=%02lx\n",
77 (entryhi & 0xffffe000), (entryhi & 0xff));
78 printk("\t\t\t[pa=%08Lx c=%d d=%d v=%d g=%Ld]\n",
79 (entrylo0 << 6) & PAGE_MASK, c0,
80 (entrylo0 & 4) ? 1 : 0,
81 (entrylo0 & 2) ? 1 : 0,
82 (entrylo0 & 1));
83 printk("\t\t\t[pa=%08Lx c=%d d=%d v=%d g=%Ld]\n",
84 (entrylo1 << 6) & PAGE_MASK, c1,
85 (entrylo1 & 4) ? 1 : 0,
86 (entrylo1 & 2) ? 1 : 0,
87 (entrylo1 & 1));
88 printk("\n");
89 }
90 }
91
92 write_c0_entryhi(asid);
93}
94
95void dump_tlb_all(void)
96{
97 dump_tlb(0, current_cpu_data.tlbsize - 1);
98}
99
100void dump_tlb_wired(void)
101{
102 int wired;
103
104 wired = read_c0_wired();
105 printk("Wired: %d", wired);
106 dump_tlb(0, read_c0_wired());
107}
108
109void dump_tlb_addr(unsigned long addr)
110{
111 unsigned int flags, oldpid;
112 int index;
113
114 local_irq_save(flags);
115 oldpid = read_c0_entryhi() & 0xff;
116 BARRIER();
117 write_c0_entryhi((addr & PAGE_MASK) | oldpid);
118 BARRIER();
119 tlb_probe();
120 BARRIER();
121 index = read_c0_index();
122 write_c0_entryhi(oldpid);
123 local_irq_restore(flags);
124
125 if (index < 0) {
126 printk("No entry for address 0x%08lx in TLB\n", addr);
127 return;
128 }
129
130 printk("Entry %d maps address 0x%08lx\n", index, addr);
131 dump_tlb(index, index);
132}
133
134void dump_tlb_nonwired(void)
135{
136 dump_tlb(read_c0_wired(), current_cpu_data.tlbsize - 1);
137}
138
139void dump_list_process(struct task_struct *t, void *address)
140{
141 pgd_t *page_dir, *pgd;
142 pmd_t *pmd;
143 pte_t *pte, page;
144 unsigned long addr, val;
145
146 addr = (unsigned long) address;
147
148 printk("Addr == %08lx\n", addr);
149 printk("task == %8p\n", t);
150 printk("task->mm == %8p\n", t->mm);
151 //printk("tasks->mm.pgd == %08x\n", (unsigned int) t->mm->pgd);
152
153 if (addr > KSEG0)
154 page_dir = pgd_offset_k(0);
155 else
156 page_dir = pgd_offset(t->mm, 0);
157 printk("page_dir == %08x\n", (unsigned int) page_dir);
158
159 if (addr > KSEG0)
160 pgd = pgd_offset_k(addr);
161 else
162 pgd = pgd_offset(t->mm, addr);
163 printk("pgd == %08x, ", (unsigned int) pgd);
164
165 pmd = pmd_offset(pgd, addr);
166 printk("pmd == %08x, ", (unsigned int) pmd);
167
168 pte = pte_offset(pmd, addr);
169 printk("pte == %08x, ", (unsigned int) pte);
170
171 page = *pte;
172#ifdef CONFIG_64BIT_PHYS_ADDR
173 printk("page == %08Lx\n", pte_val(page));
174#else
175 printk("page == %08lx\n", pte_val(page));
176#endif
177
178 val = pte_val(page);
179 if (val & _PAGE_PRESENT) printk("present ");
180 if (val & _PAGE_READ) printk("read ");
181 if (val & _PAGE_WRITE) printk("write ");
182 if (val & _PAGE_ACCESSED) printk("accessed ");
183 if (val & _PAGE_MODIFIED) printk("modified ");
184 if (val & _PAGE_R4KBUG) printk("r4kbug ");
185 if (val & _PAGE_GLOBAL) printk("global ");
186 if (val & _PAGE_VALID) printk("valid ");
187 printk("\n");
188}
189
190void dump_list_current(void *address)
191{
192 dump_list_process(current, address);
193}
194
195unsigned int vtop(void *address)
196{
197 pgd_t *pgd;
198 pmd_t *pmd;
199 pte_t *pte;
200 unsigned int addr, paddr;
201
202 addr = (unsigned long) address;
203 pgd = pgd_offset(current->mm, addr);
204 pmd = pmd_offset(pgd, addr);
205 pte = pte_offset(pmd, addr);
206 paddr = (KSEG1 | (unsigned int) pte_val(*pte)) & PAGE_MASK;
207 paddr |= (addr & ~PAGE_MASK);
208
209 return paddr;
210}
211
212void dump16(unsigned long *p)
213{
214 int i;
215
216 for (i = 0; i < 8; i++) {
217 printk("*%08lx == %08lx, ", (unsigned long)p, *p);
218 p++;
219 printk("*%08lx == %08lx\n", (unsigned long)p, *p);
220 p++;
221 }
222}
diff --git a/arch/mips/lib-32/memset.S b/arch/mips/lib-32/memset.S
new file mode 100644
index 000000000000..ad9ff4071ce9
--- /dev/null
+++ b/arch/mips/lib-32/memset.S
@@ -0,0 +1,145 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 1998, 1999, 2000 by Ralf Baechle
7 * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
8 */
9#include <asm/asm.h>
10#include <asm/offset.h>
11#include <asm/regdef.h>
12
13#define EX(insn,reg,addr,handler) \
149: insn reg, addr; \
15 .section __ex_table,"a"; \
16 PTR 9b, handler; \
17 .previous
18
19 .macro f_fill64 dst, offset, val, fixup
20 EX(LONG_S, \val, (\offset + 0 * LONGSIZE)(\dst), \fixup)
21 EX(LONG_S, \val, (\offset + 1 * LONGSIZE)(\dst), \fixup)
22 EX(LONG_S, \val, (\offset + 2 * LONGSIZE)(\dst), \fixup)
23 EX(LONG_S, \val, (\offset + 3 * LONGSIZE)(\dst), \fixup)
24 EX(LONG_S, \val, (\offset + 4 * LONGSIZE)(\dst), \fixup)
25 EX(LONG_S, \val, (\offset + 5 * LONGSIZE)(\dst), \fixup)
26 EX(LONG_S, \val, (\offset + 6 * LONGSIZE)(\dst), \fixup)
27 EX(LONG_S, \val, (\offset + 7 * LONGSIZE)(\dst), \fixup)
28 EX(LONG_S, \val, (\offset + 8 * LONGSIZE)(\dst), \fixup)
29 EX(LONG_S, \val, (\offset + 9 * LONGSIZE)(\dst), \fixup)
30 EX(LONG_S, \val, (\offset + 10 * LONGSIZE)(\dst), \fixup)
31 EX(LONG_S, \val, (\offset + 11 * LONGSIZE)(\dst), \fixup)
32 EX(LONG_S, \val, (\offset + 12 * LONGSIZE)(\dst), \fixup)
33 EX(LONG_S, \val, (\offset + 13 * LONGSIZE)(\dst), \fixup)
34 EX(LONG_S, \val, (\offset + 14 * LONGSIZE)(\dst), \fixup)
35 EX(LONG_S, \val, (\offset + 15 * LONGSIZE)(\dst), \fixup)
36 .endm
37
38/*
39 * memset(void *s, int c, size_t n)
40 *
41 * a0: start of area to clear
42 * a1: char to fill with
43 * a2: size of area to clear
44 */
45 .set noreorder
46 .align 5
47LEAF(memset)
48 beqz a1, 1f
49 move v0, a0 /* result */
50
51 andi a1, 0xff /* spread fillword */
52 sll t1, a1, 8
53 or a1, t1
54 sll t1, a1, 16
55 or a1, t1
561:
57
58FEXPORT(__bzero)
59 sltiu t0, a2, LONGSIZE /* very small region? */
60 bnez t0, small_memset
61 andi t0, a0, LONGMASK /* aligned? */
62
63 beqz t0, 1f
64 PTR_SUBU t0, LONGSIZE /* alignment in bytes */
65
66#ifdef __MIPSEB__
67 EX(swl, a1, (a0), first_fixup) /* make word aligned */
68#endif
69#ifdef __MIPSEL__
70 EX(swr, a1, (a0), first_fixup) /* make word aligned */
71#endif
72 PTR_SUBU a0, t0 /* long align ptr */
73 PTR_ADDU a2, t0 /* correct size */
74
751: ori t1, a2, 0x3f /* # of full blocks */
76 xori t1, 0x3f
77 beqz t1, memset_partial /* no block to fill */
78 andi t0, a2, 0x3c
79
80 PTR_ADDU t1, a0 /* end address */
81 .set reorder
821: PTR_ADDIU a0, 64
83 f_fill64 a0, -64, a1, fwd_fixup
84 bne t1, a0, 1b
85 .set noreorder
86
87memset_partial:
88 PTR_LA t1, 2f /* where to start */
89 PTR_SUBU t1, t0
90 jr t1
91 PTR_ADDU a0, t0 /* dest ptr */
92
93 .set push
94 .set noreorder
95 .set nomacro
96 f_fill64 a0, -64, a1, partial_fixup /* ... but first do longs ... */
972: .set pop
98 andi a2, LONGMASK /* At most one long to go */
99
100 beqz a2, 1f
101 PTR_ADDU a0, a2 /* What's left */
102#ifdef __MIPSEB__
103 EX(swr, a1, -1(a0), last_fixup)
104#endif
105#ifdef __MIPSEL__
106 EX(swl, a1, -1(a0), last_fixup)
107#endif
1081: jr ra
109 move a2, zero
110
111small_memset:
112 beqz a2, 2f
113 PTR_ADDU t1, a0, a2
114
1151: PTR_ADDIU a0, 1 /* fill bytewise */
116 bne t1, a0, 1b
117 sb a1, -1(a0)
118
1192: jr ra /* done */
120 move a2, zero
121 END(memset)
122
123first_fixup:
124 jr ra
125 nop
126
127fwd_fixup:
128 PTR_L t0, TI_TASK($28)
129 LONG_L t0, THREAD_BUADDR(t0)
130 andi a2, 0x3f
131 LONG_ADDU a2, t1
132 jr ra
133 LONG_SUBU a2, t0
134
135partial_fixup:
136 PTR_L t0, TI_TASK($28)
137 LONG_L t0, THREAD_BUADDR(t0)
138 andi a2, LONGMASK
139 LONG_ADDU a2, t1
140 jr ra
141 LONG_SUBU a2, t0
142
143last_fixup:
144 jr ra
145 andi v1, a2, LONGMASK
diff --git a/arch/mips/lib-32/r3k_dump_tlb.c b/arch/mips/lib-32/r3k_dump_tlb.c
new file mode 100644
index 000000000000..a878224004e5
--- /dev/null
+++ b/arch/mips/lib-32/r3k_dump_tlb.c
@@ -0,0 +1,176 @@
1/*
2 * Dump R3000 TLB for debugging purposes.
3 *
4 * Copyright (C) 1994, 1995 by Waldorf Electronics, written by Ralf Baechle.
5 * Copyright (C) 1999 by Silicon Graphics, Inc.
6 * Copyright (C) 1999 by Harald Koerfgen
7 */
8#include <linux/kernel.h>
9#include <linux/mm.h>
10#include <linux/sched.h>
11#include <linux/string.h>
12
13#include <asm/bootinfo.h>
14#include <asm/cachectl.h>
15#include <asm/cpu.h>
16#include <asm/mipsregs.h>
17#include <asm/page.h>
18#include <asm/pgtable.h>
19
20extern int r3k_have_wired_reg; /* defined in tlb-r3k.c */
21
22void dump_tlb(int first, int last)
23{
24 int i;
25 unsigned int asid;
26 unsigned long entryhi, entrylo0;
27
28 asid = read_c0_entryhi() & 0xfc0;
29
30 for (i = first; i <= last; i++) {
31 write_c0_index(i<<8);
32 __asm__ __volatile__(
33 ".set\tnoreorder\n\t"
34 "tlbr\n\t"
35 "nop\n\t"
36 ".set\treorder");
37 entryhi = read_c0_entryhi();
38 entrylo0 = read_c0_entrylo0();
39
40 /* Unused entries have a virtual address of KSEG0. */
41 if ((entryhi & 0xffffe000) != 0x80000000
42 && (entryhi & 0xfc0) == asid) {
43 /*
44 * Only print entries in use
45 */
46 printk("Index: %2d ", i);
47
48 printk("va=%08lx asid=%08lx"
49 " [pa=%06lx n=%d d=%d v=%d g=%d]",
50 (entryhi & 0xffffe000),
51 entryhi & 0xfc0,
52 entrylo0 & PAGE_MASK,
53 (entrylo0 & (1 << 11)) ? 1 : 0,
54 (entrylo0 & (1 << 10)) ? 1 : 0,
55 (entrylo0 & (1 << 9)) ? 1 : 0,
56 (entrylo0 & (1 << 8)) ? 1 : 0);
57 }
58 }
59 printk("\n");
60
61 write_c0_entryhi(asid);
62}
63
64void dump_tlb_all(void)
65{
66 dump_tlb(0, current_cpu_data.tlbsize - 1);
67}
68
69void dump_tlb_wired(void)
70{
71 int wired = r3k_have_wired_reg ? read_c0_wired() : 8;
72
73 printk("Wired: %d", wired);
74 dump_tlb(0, wired - 1);
75}
76
77void dump_tlb_addr(unsigned long addr)
78{
79 unsigned long flags, oldpid;
80 int index;
81
82 local_irq_save(flags);
83 oldpid = read_c0_entryhi() & 0xff;
84 write_c0_entryhi((addr & PAGE_MASK) | oldpid);
85 tlb_probe();
86 index = read_c0_index();
87 write_c0_entryhi(oldpid);
88 local_irq_restore(flags);
89
90 if (index < 0) {
91 printk("No entry for address 0x%08lx in TLB\n", addr);
92 return;
93 }
94
95 printk("Entry %d maps address 0x%08lx\n", index, addr);
96 dump_tlb(index, index);
97}
98
99void dump_tlb_nonwired(void)
100{
101 int wired = r3k_have_wired_reg ? read_c0_wired() : 8;
102 dump_tlb(wired, current_cpu_data.tlbsize - 1);
103}
104
105void dump_list_process(struct task_struct *t, void *address)
106{
107 pgd_t *page_dir, *pgd;
108 pmd_t *pmd;
109 pte_t *pte, page;
110 unsigned int addr;
111 unsigned long val;
112
113 addr = (unsigned int) address;
114
115 printk("Addr == %08x\n", addr);
116 printk("tasks->mm.pgd == %08x\n", (unsigned int) t->mm->pgd);
117
118 page_dir = pgd_offset(t->mm, 0);
119 printk("page_dir == %08x\n", (unsigned int) page_dir);
120
121 pgd = pgd_offset(t->mm, addr);
122 printk("pgd == %08x, ", (unsigned int) pgd);
123
124 pmd = pmd_offset(pgd, addr);
125 printk("pmd == %08x, ", (unsigned int) pmd);
126
127 pte = pte_offset(pmd, addr);
128 printk("pte == %08x, ", (unsigned int) pte);
129
130 page = *pte;
131 printk("page == %08x\n", (unsigned int) pte_val(page));
132
133 val = pte_val(page);
134 if (val & _PAGE_PRESENT) printk("present ");
135 if (val & _PAGE_READ) printk("read ");
136 if (val & _PAGE_WRITE) printk("write ");
137 if (val & _PAGE_ACCESSED) printk("accessed ");
138 if (val & _PAGE_MODIFIED) printk("modified ");
139 if (val & _PAGE_GLOBAL) printk("global ");
140 if (val & _PAGE_VALID) printk("valid ");
141 printk("\n");
142}
143
144void dump_list_current(void *address)
145{
146 dump_list_process(current, address);
147}
148
149unsigned int vtop(void *address)
150{
151 pgd_t *pgd;
152 pmd_t *pmd;
153 pte_t *pte;
154 unsigned int addr, paddr;
155
156 addr = (unsigned long) address;
157 pgd = pgd_offset(current->mm, addr);
158 pmd = pmd_offset(pgd, addr);
159 pte = pte_offset(pmd, addr);
160 paddr = (KSEG1 | (unsigned int) pte_val(*pte)) & PAGE_MASK;
161 paddr |= (addr & ~PAGE_MASK);
162
163 return paddr;
164}
165
166void dump16(unsigned long *p)
167{
168 int i;
169
170 for (i = 0; i < 8; i++) {
171 printk("*%08lx == %08lx, ", (unsigned long)p, *p);
172 p++;
173 printk("*%08lx == %08lx\n", (unsigned long)p, *p);
174 p++;
175 }
176}
diff --git a/arch/mips/lib-32/watch.S b/arch/mips/lib-32/watch.S
new file mode 100644
index 000000000000..808b3af1a605
--- /dev/null
+++ b/arch/mips/lib-32/watch.S
@@ -0,0 +1,60 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Kernel debug stuff to use the Watch registers.
7 * Useful to find stack overflows, dangling pointers etc.
8 *
9 * Copyright (C) 1995, 1996, 1999 by Ralf Baechle
10 */
11#include <asm/asm.h>
12#include <asm/mipsregs.h>
13#include <asm/regdef.h>
14
15 .set noreorder
16/*
17 * Parameter: a0 - logic address to watch
18 * Currently only KSEG0 addresses are allowed!
19 * a1 - set bit #1 to trap on load references
20 * bit #0 to trap on store references
21 * Results : none
22 */
23 LEAF(__watch_set)
24 li t0, 0x80000000
25 subu a0, t0
26 ori a0, 7
27 xori a0, 7
28 or a0, a1
29 mtc0 a0, CP0_WATCHLO
30 sw a0, watch_savelo
31
32 jr ra
33 mtc0 zero, CP0_WATCHHI
34 END(__watch_set)
35
36/*
37 * Parameter: none
38 * Results : none
39 */
40 LEAF(__watch_clear)
41 jr ra
42 mtc0 zero, CP0_WATCHLO
43 END(__watch_clear)
44
45/*
46 * Parameter: none
47 * Results : none
48 */
49 LEAF(__watch_reenable)
50 lw t0, watch_savelo
51 jr ra
52 mtc0 t0, CP0_WATCHLO
53 END(__watch_reenable)
54
55/*
56 * Saved value of the c0_watchlo register for watch_reenable()
57 */
58 .data
59watch_savelo: .word 0
60 .text