1 /*-
2 * Copyright (c) 2001 Jake Burkholder.
3 * All rights reserved.
4 * Copyright 2001 by Thomas Moestl <tmm@FreeBSD.org>. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 * $FreeBSD: releng/6.0/sys/sparc64/sparc64/db_hwwatch.c 119291 2003-08-22 07:39:05Z imp $
28 */
29
30 #include <sys/param.h>
31
32 #include <vm/vm.h>
33
34 #include <machine/asi.h>
35 #include <machine/cpufunc.h>
36 #include <machine/lsu.h>
37 #include <machine/watch.h>
38
39 #include <ddb/ddb.h>
40 #include <ddb/db_access.h>
41 #include <ddb/db_sym.h>
42 #include <ddb/db_variables.h>
43 #include <ddb/db_watch.h>
44
45 int db_md_set_watchpoint(db_expr_t addr, db_expr_t size);
46 int db_md_clr_watchpoint(db_expr_t addr, db_expr_t size);
47 void db_md_list_watchpoints(void);
48
49 static void db_watch_print(vm_offset_t wp, int bm);
50
51 int
52 watch_phys_set_mask(vm_paddr_t pa, u_long mask)
53 {
54 u_long lsucr;
55
56 stxa_sync(AA_DMMU_PWPR, ASI_DMMU, pa & (((2UL << 38) - 1) << 3));
57 lsucr = ldxa(0, ASI_LSU_CTL_REG);
58 lsucr = ((lsucr | LSU_PW) & ~LSU_PM_MASK) |
59 (mask << LSU_PM_SHIFT);
60 stxa_sync(0, ASI_LSU_CTL_REG, lsucr);
61 return (0);
62 }
63
64 int
65 watch_phys_set(vm_paddr_t pa, int sz)
66 {
67 u_long off;
68
69 off = (u_long)pa & 7;
70 /* Test for misaligned watch points. */
71 if (off + sz > 8)
72 return (-1);
73 return (watch_phys_set_mask(pa, ((1 << sz) - 1) << off));
74 }
75
76 vm_paddr_t
77 watch_phys_get(int *bm)
78 {
79 vm_paddr_t pa;
80 u_long lsucr;
81
82 if (!watch_phys_active())
83 return (0);
84
85 pa = ldxa(AA_DMMU_PWPR, ASI_DMMU);
86 lsucr = ldxa(0, ASI_LSU_CTL_REG);
87 *bm = (lsucr & LSU_PM_MASK) >> LSU_PM_SHIFT;
88
89 return (pa);
90 }
91
92 void
93 watch_phys_clear()
94 {
95 stxa_sync(0, ASI_LSU_CTL_REG,
96 ldxa(0, ASI_LSU_CTL_REG) & ~LSU_PW);
97 }
98
99 int
100 watch_phys_active()
101 {
102
103 return (ldxa(0, ASI_LSU_CTL_REG) & LSU_PW);
104 }
105
106 int
107 watch_virt_set_mask(vm_offset_t va, u_long mask)
108 {
109 u_long lsucr;
110
111 stxa_sync(AA_DMMU_VWPR, ASI_DMMU, va & (((2UL << 41) - 1) << 3));
112 lsucr = ldxa(0, ASI_LSU_CTL_REG);
113 lsucr = ((lsucr | LSU_VW) & ~LSU_VM_MASK) |
114 (mask << LSU_VM_SHIFT);
115 stxa_sync(0, ASI_LSU_CTL_REG, lsucr);
116 return (0);
117 }
118
119 int
120 watch_virt_set(vm_offset_t va, int sz)
121 {
122 u_long off;
123
124 off = (u_long)va & 7;
125 /* Test for misaligned watch points. */
126 if (off + sz > 8)
127 return (-1);
128 return (watch_virt_set_mask(va, ((1 << sz) - 1) << off));
129 }
130
131 vm_offset_t
132 watch_virt_get(int *bm)
133 {
134 u_long va;
135 u_long lsucr;
136
137 if (!watch_virt_active())
138 return (0);
139
140 va = ldxa(AA_DMMU_VWPR, ASI_DMMU);
141 lsucr = ldxa(0, ASI_LSU_CTL_REG);
142 *bm = (lsucr & LSU_VM_MASK) >> LSU_VM_SHIFT;
143
144 return ((vm_offset_t)va);
145 }
146
147 void
148 watch_virt_clear()
149 {
150 stxa_sync(0, ASI_LSU_CTL_REG,
151 ldxa(0, ASI_LSU_CTL_REG) & ~LSU_VW);
152 }
153
154 int
155 watch_virt_active()
156 {
157
158 return (ldxa(0, ASI_LSU_CTL_REG) & LSU_VW);
159 }
160
161 int
162 db_md_set_watchpoint(db_expr_t addr, db_expr_t size)
163 {
164 int dummy;
165
166 if (watch_virt_active()) {
167 db_printf("Overwriting previously active watch point at "
168 "0x%lx\n", watch_virt_get(&dummy));
169 }
170 return (watch_virt_set(addr, size));
171 }
172
173 int
174 db_md_clr_watchpoint(db_expr_t addr, db_expr_t size)
175 {
176
177 watch_virt_clear();
178 return (0);
179 }
180
181 void
182 db_watch_print(vm_offset_t wp, int bm)
183 {
184 int i;
185
186 db_printf("\tat 0x%lx, active bytes: ", (u_long)wp);
187 for (i = 0; i < 8; i++) {
188 if ((bm & (1 << i)) != 0)
189 db_printf("%d ", i);
190 }
191 if (bm == 0)
192 db_printf("none");
193 db_printf("\n");
194 }
195
196 void
197 db_md_list_watchpoints(void)
198 {
199 vm_offset_t va;
200 vm_paddr_t pa;
201 int bm;
202
203 db_printf("Physical address watchpoint:\n");
204 if (watch_phys_active()) {
205 pa = watch_phys_get(&bm);
206 db_watch_print(pa, bm);
207 } else
208 db_printf("\tnot active.\n");
209 db_printf("Virtual address watchpoint:\n");
210 if (watch_virt_active()) {
211 va = watch_virt_get(&bm);
212 db_watch_print(va, bm);
213 } else
214 db_printf("\tnot active.\n");
215 }
Cache object: 2ebfff618dfba2eaab82432d9ec1930e
|