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