1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 #pragma ident "%Z%%M% %I% %E% SMI"
27
28 #include <sys/types.h>
29 #include <sys/systm.h>
30 #include <sys/bootconf.h>
31 #include <sys/cpu_module.h>
32 #include <sys/x_call.h>
33 #include <sys/kdi_impl.h>
34 #include <sys/mmu.h>
35 #include <sys/cpuvar.h>
36 #include <sys/kobj.h>
37 #include <sys/kobj_impl.h>
38 #ifdef sun4v
39 #include <sys/ldoms.h>
40 #include <sys/promif_impl.h>
41 #include <kmdb/kmdb_kctl.h>
42 #endif
43
44 #include <kmdb/kctl/kctl.h>
45
46 #define KCTL_TTABLE_SIZE 0x6000 /* trap table size */
47
48 static uint32_t kctl_trap_brsav; /* saved ba,a from kmdb_trap */
49 static uint32_t kctl_trap_tl1_brsav; /* saved ba,a from kmdb_trap_tl1 */
50
51 extern struct scb trap_table;
52
53 static void
kctl_patch_text(caddr_t addr,uint32_t data)54 kctl_patch_text(caddr_t addr, uint32_t data)
55 {
56 if (kctl.kctl_boot_loaded) {
57 /* LINTED - pointer alignment */
58 *((uint32_t *)addr) = data;
59 } else {
60 hot_patch_kernel_text(addr, data, sizeof (data));
61 }
62 }
63
64 /*
65 * The traps that transfer control to kmdb (breakpoint, programmed entry, etc)
66 * use kmdb_trap and kmdb_trap_tl1, which normally begin with a ba,a to
67 * trap_table0 - a bad trap entry. When kmdb starts, it will use
68 * kctl_ktrap_install to replace the ba with a jmp to the appropriate kmdb
69 * entry points. Deactivation uses kctl_ktrap_restore to restore the ba
70 * instructions.
71 */
72 static void
kctl_ktrap_install(int tl,void (* handler)(void))73 kctl_ktrap_install(int tl, void (*handler)(void))
74 {
75 extern uint32_t kmdb_trap, kmdb_trap_tl1;
76 uint32_t *entryp = tl ? &kmdb_trap_tl1 : &kmdb_trap;
77 uint32_t *savp = tl ? &kctl_trap_brsav : &kctl_trap_tl1_brsav;
78 uint32_t hi = (uint32_t)(uintptr_t)handler >> 10;
79 uint32_t lo = (uint32_t)(uintptr_t)handler & 0x3ff;
80 uint32_t inst;
81
82 *savp = *entryp;
83
84 inst = 0x81c06000 | lo; /* jmp %g1 + %lo(handler) */
85 kctl_patch_text((caddr_t)(entryp + 1), inst);
86
87 inst = 0x03000000 | hi; /* sethi %hi(handler), %g1 */
88 kctl_patch_text((caddr_t)entryp, inst);
89 }
90
91 static void
kctl_ktrap_restore(void)92 kctl_ktrap_restore(void)
93 {
94 extern uint32_t kmdb_trap, kmdb_trap_tl1;
95
96 hot_patch_kernel_text((caddr_t)&kmdb_trap, kctl_trap_brsav, 4);
97 hot_patch_kernel_text((caddr_t)&kmdb_trap_tl1, kctl_trap_tl1_brsav, 4);
98 }
99
100 static void
kctl_ttable_tlb_modify(caddr_t tba,size_t sz,void (* func)(caddr_t,int))101 kctl_ttable_tlb_modify(caddr_t tba, size_t sz, void (*func)(caddr_t, int))
102 {
103 #if defined(KMDB_TRAPCOUNT)
104 int do_dtlb = 1;
105 #else
106 int do_dtlb = 0;
107 #endif
108
109 caddr_t va;
110
111 ASSERT((sz & MMU_PAGEOFFSET) == 0);
112
113 for (va = tba; sz > 0; sz -= MMU_PAGESIZE, va += MMU_PAGESIZE)
114 func(va, do_dtlb);
115 }
116
117 static void
kctl_ttable_tlb_lock(caddr_t tba,size_t sz)118 kctl_ttable_tlb_lock(caddr_t tba, size_t sz)
119 {
120 kctl_ttable_tlb_modify(tba, sz, kdi_tlb_page_lock);
121 }
122
123 static void
kctl_ttable_tlb_unlock(caddr_t tba,size_t sz)124 kctl_ttable_tlb_unlock(caddr_t tba, size_t sz)
125 {
126 kctl_ttable_tlb_modify(tba, sz, kdi_tlb_page_unlock);
127 }
128
129 /*
130 * kmdb has its own trap table. Life is made considerably easier if
131 * we allocate and configure it here, passing it to the debugger for
132 * final tweaking.
133 *
134 * The debugger code, and data accessed by the handlers are either
135 * a) locked into the TLB or b) accessible by our tte-lookup code. As
136 * such, we need only lock the trap table itself into the TLBs. We'll
137 * get the memory for the table from the beginning of the debugger
138 * segment, which has already been allocated.
139 */
140 static void
kctl_ttable_init(void)141 kctl_ttable_init(void)
142 {
143 xc_all((xcfunc_t *)kctl_ttable_tlb_lock, (uint64_t)kctl.kctl_tba,
144 KCTL_TTABLE_SIZE);
145 }
146
147 static void
kctl_ttable_fini(void)148 kctl_ttable_fini(void)
149 {
150 xc_all((xcfunc_t *)kctl_ttable_tlb_unlock, (uint64_t)kctl.kctl_dseg,
151 KCTL_TTABLE_SIZE);
152 }
153
154 static caddr_t
kctl_ttable_reserve(kmdb_auxv_t * kav,size_t * szp)155 kctl_ttable_reserve(kmdb_auxv_t *kav, size_t *szp)
156 {
157 caddr_t tba = kav->kav_dseg;
158
159 ASSERT(kav->kav_dseg_size > KCTL_TTABLE_SIZE);
160 ASSERT(((uintptr_t)kav->kav_dseg & ((1 << 16) - 1)) == 0);
161
162 kav->kav_dseg += KCTL_TTABLE_SIZE;
163 kav->kav_dseg_size -= KCTL_TTABLE_SIZE;
164
165 *szp = KCTL_TTABLE_SIZE;
166 return (tba);
167 }
168
169 static void
kctl_cpu_init(void)170 kctl_cpu_init(void)
171 {
172 kctl_ttable_tlb_lock(kctl.kctl_tba, KCTL_TTABLE_SIZE);
173 }
174
175 int
kctl_preactivate_isadep(void)176 kctl_preactivate_isadep(void)
177 {
178 if (!kctl.kctl_boot_loaded) {
179 if (kdi_watchdog_disable() != 0) {
180 cmn_err(CE_WARN, "hardware watchdog disabled while "
181 "debugger is activated");
182 }
183
184 kctl_ttable_init();
185 }
186
187 return (0);
188 }
189
190 void
kctl_depreactivate_isadep(void)191 kctl_depreactivate_isadep(void)
192 {
193 kctl_ttable_fini();
194
195 kdi_watchdog_restore();
196 }
197
198 void
kctl_activate_isadep(kdi_debugvec_t * dvec)199 kctl_activate_isadep(kdi_debugvec_t *dvec)
200 {
201 dvec->dv_kctl_cpu_init = kctl_cpu_init;
202 dvec->dv_kctl_vmready = kctl_ttable_init;
203 }
204
205 void
kctl_auxv_init_isadep(kmdb_auxv_t * kav,void * romp)206 kctl_auxv_init_isadep(kmdb_auxv_t *kav, void *romp)
207 {
208 extern caddr_t boot_tba;
209 extern void *get_tba(void);
210 extern int (*cif_handler)(void *);
211 extern int prom_exit_enter_debugger;
212
213 kctl.kctl_tba = kav->kav_tba_native = kctl_ttable_reserve(kav,
214 &kav->kav_tba_native_sz);
215
216 kav->kav_tba_obp = (boot_tba == NULL ? get_tba() : boot_tba);
217 #ifdef sun4v
218 kav->kav_tba_kernel = (caddr_t)&trap_table;
219 #endif
220 kav->kav_tba_active = (kctl.kctl_boot_loaded ? kav->kav_tba_obp :
221 kav->kav_tba_native);
222
223 kav->kav_promexitarmp = &prom_exit_enter_debugger;
224
225 kav->kav_romp = (kctl.kctl_boot_loaded ? romp : (void *)cif_handler);
226
227 kav->kav_ktrap_install = kctl_ktrap_install;
228 kav->kav_ktrap_restore = kctl_ktrap_restore;
229 #ifdef sun4v
230 if (kctl.kctl_boot_loaded) {
231 /*
232 * When booting kmdb, kmdb starts before domaining is
233 * enabled and before the cif handler is changed to the
234 * kernel cif handler. So we start kmdb with using the
235 * OBP and we will change this when the cif handler is
236 * installed.
237 */
238 kav->kav_domaining = 0;
239 } else {
240 kctl_auxv_set_promif(kav);
241 }
242 #endif
243 }
244
245 #ifdef sun4v
246
247 void
kctl_auxv_set_promif(kmdb_auxv_t * kav)248 kctl_auxv_set_promif(kmdb_auxv_t *kav)
249 {
250 kav->kav_domaining = domaining_enabled();
251 kav->kav_promif_root = promif_stree_getroot();
252 kav->kav_promif_in = prom_stdin_ihandle();
253 kav->kav_promif_out = prom_stdout_ihandle();
254 kav->kav_promif_pin = prom_stdin_node();
255 kav->kav_promif_pout = prom_stdout_node();
256 kav->kav_promif_chosennode = prom_chosennode();
257 kav->kav_promif_optionsnode = prom_finddevice("/options");
258 }
259
260 void
kctl_switch_promif(void)261 kctl_switch_promif(void)
262 {
263 kmdb_auxv_t kav;
264
265 kctl_auxv_set_promif(&kav);
266 kmdb_init_promif(NULL, &kav);
267 }
268
269 #endif
270
271 /*ARGSUSED*/
272 void
kctl_auxv_fini_isadep(kmdb_auxv_t * auxv)273 kctl_auxv_fini_isadep(kmdb_auxv_t *auxv)
274 {
275 }
276
277 void *
kctl_boot_tmpinit(void)278 kctl_boot_tmpinit(void)
279 {
280 kthread_t *kt0 = kobj_zalloc(sizeof (kthread_t), KM_TMP);
281 cpu_t *cpu = kobj_zalloc(sizeof (cpu_t), KM_TMP);
282 kt0->t_cpu = cpu;
283
284 return (kctl_curthread_set(kt0));
285 }
286
287 void
kctl_boot_tmpfini(void * old)288 kctl_boot_tmpfini(void *old)
289 {
290 (void) kctl_curthread_set(old);
291 }
292