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