1ae115bc7Smrj /*
2ae115bc7Smrj * CDDL HEADER START
3ae115bc7Smrj *
4ae115bc7Smrj * The contents of this file are subject to the terms of the
5ae115bc7Smrj * Common Development and Distribution License (the "License").
6ae115bc7Smrj * You may not use this file except in compliance with the License.
7ae115bc7Smrj *
8ae115bc7Smrj * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9ae115bc7Smrj * or http://www.opensolaris.org/os/licensing.
10ae115bc7Smrj * See the License for the specific language governing permissions
11ae115bc7Smrj * and limitations under the License.
12ae115bc7Smrj *
13ae115bc7Smrj * When distributing Covered Code, include this CDDL HEADER in each
14ae115bc7Smrj * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15ae115bc7Smrj * If applicable, add the following below this CDDL HEADER, with the
16ae115bc7Smrj * fields enclosed by brackets "[]" replaced with your own identifying
17ae115bc7Smrj * information: Portions Copyright [yyyy] [name of copyright owner]
18ae115bc7Smrj *
19ae115bc7Smrj * CDDL HEADER END
20ae115bc7Smrj */
21ae115bc7Smrj /*
229844da31SSeth Goldberg * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23ae115bc7Smrj * Use is subject to license terms.
24399ca3a7SJohn Levon *
25399ca3a7SJohn Levon * Copyright 2018 Joyent, Inc.
26ae115bc7Smrj */
27ae115bc7Smrj
28ae115bc7Smrj /*
29ae115bc7Smrj * Management of KMDB's IDT, which is installed upon KMDB activation.
30ae115bc7Smrj *
31ae115bc7Smrj * Debugger activation has two flavors, which cover the cases where KMDB is
32ae115bc7Smrj * loaded at boot, and when it is loaded after boot. In brief, in both cases,
33ae115bc7Smrj * the KDI needs to interpose upon several handlers in the IDT. When
34ae115bc7Smrj * mod-loaded KMDB is deactivated, we undo the IDT interposition, restoring the
35ae115bc7Smrj * handlers to what they were before we started.
36ae115bc7Smrj *
37ae115bc7Smrj * We also take over the entirety of IDT (except the double-fault handler) on
38ae115bc7Smrj * the active CPU when we're in kmdb so we can handle things like page faults
39ae115bc7Smrj * sensibly.
40ae115bc7Smrj *
41ae115bc7Smrj * Boot-loaded KMDB
42ae115bc7Smrj *
43ae115bc7Smrj * When we're first activated, we're running on boot's IDT. We need to be able
44ae115bc7Smrj * to function in this world, so we'll install our handlers into boot's IDT.
45ae115bc7Smrj * This is a little complicated: we're using the fake cpu_t set up by
46ae115bc7Smrj * boot_kdi_tmpinit(), so we can't access cpu_idt directly. Instead,
47ae115bc7Smrj * kdi_idt_write() notices that cpu_idt is NULL, and works around this problem.
48ae115bc7Smrj *
49ae115bc7Smrj * Later, when we're about to switch to the kernel's IDT, it'll call us via
50ae115bc7Smrj * kdi_idt_sync(), allowing us to add our handlers to the new IDT. While
51ae115bc7Smrj * boot-loaded KMDB can't be unloaded, we still need to save the descriptors we
52ae115bc7Smrj * replace so we can pass traps back to the kernel as necessary.
53ae115bc7Smrj *
54ae115bc7Smrj * The last phase of boot-loaded KMDB activation occurs at non-boot CPU
55ae115bc7Smrj * startup. We will be called on each non-boot CPU, thus allowing us to set up
56ae115bc7Smrj * any watchpoints that may have been configured on the boot CPU and interpose
57ae115bc7Smrj * on the given CPU's IDT. We don't save the interposed descriptors in this
58ae115bc7Smrj * case -- see kdi_cpu_init() for details.
59ae115bc7Smrj *
60ae115bc7Smrj * Mod-loaded KMDB
61ae115bc7Smrj *
62ae115bc7Smrj * This style of activation is much simpler, as the CPUs are already running,
63ae115bc7Smrj * and are using their own copy of the kernel's IDT. We simply interpose upon
64ae115bc7Smrj * each CPU's IDT. We save the handlers we replace, both for deactivation and
65843e1988Sjohnlev * for passing traps back to the kernel. Note that for the hypervisors'
66843e1988Sjohnlev * benefit, we need to xcall to the other CPUs to do this, since we need to
67843e1988Sjohnlev * actively set the trap entries in its virtual IDT from that vcpu's context
68843e1988Sjohnlev * rather than just modifying the IDT table from the CPU running kdi_activate().
69ae115bc7Smrj */
70ae115bc7Smrj
71ae115bc7Smrj #include <sys/types.h>
72ae115bc7Smrj #include <sys/segments.h>
73ae115bc7Smrj #include <sys/trap.h>
74ae115bc7Smrj #include <sys/cpuvar.h>
75ae115bc7Smrj #include <sys/reboot.h>
76ae115bc7Smrj #include <sys/sunddi.h>
77ae115bc7Smrj #include <sys/archsystm.h>
78ae115bc7Smrj #include <sys/kdi_impl.h>
79ae115bc7Smrj #include <sys/x_call.h>
80*f0089e39SRichard Lowe #include <sys/psw.h>
8174ecdb51SJohn Levon #include <vm/hat_i86.h>
82ae115bc7Smrj
83ae115bc7Smrj #define KDI_GATE_NVECS 3
84ae115bc7Smrj
85ae115bc7Smrj #define KDI_IDT_NOSAVE 0
86ae115bc7Smrj #define KDI_IDT_SAVE 1
87ae115bc7Smrj
88ae115bc7Smrj #define KDI_IDT_DTYPE_KERNEL 0
89ae115bc7Smrj #define KDI_IDT_DTYPE_BOOT 1
90ae115bc7Smrj
9166a2141cSJohn Levon /* Solely to keep kdiregs_t in the CTF, otherwise unused. */
9266a2141cSJohn Levon kdiregs_t kdi_regs;
9366a2141cSJohn Levon
94ae115bc7Smrj kdi_cpusave_t *kdi_cpusave;
95ae115bc7Smrj int kdi_ncpusave;
96ae115bc7Smrj
97ae115bc7Smrj static kdi_main_t kdi_kmdb_main;
98ae115bc7Smrj
99ae115bc7Smrj kdi_drreg_t kdi_drreg;
100ae115bc7Smrj
101ae115bc7Smrj
102ae115bc7Smrj uintptr_t kdi_kernel_handler;
103ae115bc7Smrj
104ae115bc7Smrj int kdi_trap_switch;
105ae115bc7Smrj
106ae115bc7Smrj #define KDI_MEMRANGES_MAX 2
107ae115bc7Smrj
108ae115bc7Smrj kdi_memrange_t kdi_memranges[KDI_MEMRANGES_MAX];
109ae115bc7Smrj int kdi_nmemranges;
110ae115bc7Smrj
111ae115bc7Smrj typedef void idt_hdlr_f(void);
112ae115bc7Smrj
113ae115bc7Smrj extern idt_hdlr_f kdi_trap0, kdi_trap1, kdi_int2, kdi_trap3, kdi_trap4;
114ae115bc7Smrj extern idt_hdlr_f kdi_trap5, kdi_trap6, kdi_trap7, kdi_trap9;
115ae115bc7Smrj extern idt_hdlr_f kdi_traperr10, kdi_traperr11, kdi_traperr12;
11674ecdb51SJohn Levon extern idt_hdlr_f kdi_traperr13, kdi_traperr14, kdi_trap16, kdi_traperr17;
117ae115bc7Smrj extern idt_hdlr_f kdi_trap18, kdi_trap19, kdi_trap20, kdi_ivct32;
118ae115bc7Smrj extern idt_hdlr_f kdi_invaltrap;
119ae115bc7Smrj extern size_t kdi_ivct_size;
120ae115bc7Smrj
121ae115bc7Smrj typedef struct kdi_gate_spec {
122ae115bc7Smrj uint_t kgs_vec;
123ae115bc7Smrj uint_t kgs_dpl;
124ae115bc7Smrj } kdi_gate_spec_t;
125ae115bc7Smrj
126843e1988Sjohnlev /*
127843e1988Sjohnlev * Beware: kdi_pass_to_kernel() has unpleasant knowledge of this list.
128843e1988Sjohnlev */
129ae115bc7Smrj static const kdi_gate_spec_t kdi_gate_specs[KDI_GATE_NVECS] = {
130843e1988Sjohnlev { T_SGLSTP, TRP_KPL },
131843e1988Sjohnlev { T_BPTFLT, TRP_UPL },
132843e1988Sjohnlev { T_DBGENTR, TRP_KPL }
133ae115bc7Smrj };
134ae115bc7Smrj
135ae115bc7Smrj static gate_desc_t kdi_kgates[KDI_GATE_NVECS];
136ae115bc7Smrj
13774ecdb51SJohn Levon extern gate_desc_t kdi_idt[NIDT];
138ae115bc7Smrj
139ae115bc7Smrj struct idt_description {
140ae115bc7Smrj uint_t id_low;
141ae115bc7Smrj uint_t id_high;
142ae115bc7Smrj idt_hdlr_f *id_basehdlr;
143ae115bc7Smrj size_t *id_incrp;
144ae115bc7Smrj } idt_description[] = {
145ae115bc7Smrj { T_ZERODIV, 0, kdi_trap0, NULL },
146ae115bc7Smrj { T_SGLSTP, 0, kdi_trap1, NULL },
147ae115bc7Smrj { T_NMIFLT, 0, kdi_int2, NULL },
148ae115bc7Smrj { T_BPTFLT, 0, kdi_trap3, NULL },
149ae115bc7Smrj { T_OVFLW, 0, kdi_trap4, NULL },
150ae115bc7Smrj { T_BOUNDFLT, 0, kdi_trap5, NULL },
151ae115bc7Smrj { T_ILLINST, 0, kdi_trap6, NULL },
152ae115bc7Smrj { T_NOEXTFLT, 0, kdi_trap7, NULL },
153843e1988Sjohnlev #if !defined(__xpv)
154ae115bc7Smrj { T_DBLFLT, 0, syserrtrap, NULL },
155843e1988Sjohnlev #endif
156ae115bc7Smrj { T_EXTOVRFLT, 0, kdi_trap9, NULL },
157ae115bc7Smrj { T_TSSFLT, 0, kdi_traperr10, NULL },
158ae115bc7Smrj { T_SEGFLT, 0, kdi_traperr11, NULL },
159ae115bc7Smrj { T_STKFLT, 0, kdi_traperr12, NULL },
160ae115bc7Smrj { T_GPFLT, 0, kdi_traperr13, NULL },
161ae115bc7Smrj { T_PGFLT, 0, kdi_traperr14, NULL },
162ae115bc7Smrj { 15, 0, kdi_invaltrap, NULL },
163eea802b0SJohn Levon { T_EXTERRFLT, 0, kdi_trap16, NULL },
164eea802b0SJohn Levon { T_ALIGNMENT, 0, kdi_traperr17, NULL },
165ae115bc7Smrj { T_MCE, 0, kdi_trap18, NULL },
166ae115bc7Smrj { T_SIMDFPE, 0, kdi_trap19, NULL },
167ae115bc7Smrj { T_DBGENTR, 0, kdi_trap20, NULL },
168ae115bc7Smrj { 21, 31, kdi_invaltrap, NULL },
169ae115bc7Smrj { 32, 255, kdi_ivct32, &kdi_ivct_size },
170ae115bc7Smrj { 0, 0, NULL },
171ae115bc7Smrj };
172ae115bc7Smrj
173ae115bc7Smrj void
kdi_idt_init(selector_t sel)174ae115bc7Smrj kdi_idt_init(selector_t sel)
175ae115bc7Smrj {
176ae115bc7Smrj struct idt_description *id;
177ae115bc7Smrj int i;
178ae115bc7Smrj
179ae115bc7Smrj for (id = idt_description; id->id_basehdlr != NULL; id++) {
180ae115bc7Smrj uint_t high = id->id_high != 0 ? id->id_high : id->id_low;
181ae115bc7Smrj size_t incr = id->id_incrp != NULL ? *id->id_incrp : 0;
182ae115bc7Smrj
18374ecdb51SJohn Levon #if !defined(__xpv)
18474ecdb51SJohn Levon if (kpti_enable && sel == KCS_SEL && id->id_low == T_DBLFLT)
18574ecdb51SJohn Levon id->id_basehdlr = tr_syserrtrap;
18674ecdb51SJohn Levon #endif
18774ecdb51SJohn Levon
188ae115bc7Smrj for (i = id->id_low; i <= high; i++) {
189ae115bc7Smrj caddr_t hdlr = (caddr_t)id->id_basehdlr +
190ae115bc7Smrj incr * (i - id->id_low);
191ae115bc7Smrj set_gatesegd(&kdi_idt[i], (void (*)())hdlr, sel,
19274ecdb51SJohn Levon SDT_SYSIGT, TRP_KPL, IST_DBG);
193ae115bc7Smrj }
194ae115bc7Smrj }
195ae115bc7Smrj }
196ae115bc7Smrj
197ae115bc7Smrj static void
kdi_idt_gates_install(selector_t sel,int saveold)198ae115bc7Smrj kdi_idt_gates_install(selector_t sel, int saveold)
199ae115bc7Smrj {
200ae115bc7Smrj gate_desc_t gates[KDI_GATE_NVECS];
201ae115bc7Smrj int i;
202ae115bc7Smrj
203ae115bc7Smrj bzero(gates, sizeof (*gates));
204ae115bc7Smrj
205ae115bc7Smrj for (i = 0; i < KDI_GATE_NVECS; i++) {
206ae115bc7Smrj const kdi_gate_spec_t *gs = &kdi_gate_specs[i];
207ae115bc7Smrj uintptr_t func = GATESEG_GETOFFSET(&kdi_idt[gs->kgs_vec]);
208ae115bc7Smrj set_gatesegd(&gates[i], (void (*)())func, sel, SDT_SYSIGT,
20974ecdb51SJohn Levon gs->kgs_dpl, IST_DBG);
210ae115bc7Smrj }
211ae115bc7Smrj
212ae115bc7Smrj for (i = 0; i < KDI_GATE_NVECS; i++) {
213ae115bc7Smrj uint_t vec = kdi_gate_specs[i].kgs_vec;
214ae115bc7Smrj
215ae115bc7Smrj if (saveold)
216ae115bc7Smrj kdi_kgates[i] = CPU->cpu_m.mcpu_idt[vec];
217ae115bc7Smrj
218ae115bc7Smrj kdi_idt_write(&gates[i], vec);
219ae115bc7Smrj }
220ae115bc7Smrj }
221ae115bc7Smrj
222ae115bc7Smrj static void
kdi_idt_gates_restore(void)223ae115bc7Smrj kdi_idt_gates_restore(void)
224ae115bc7Smrj {
225ae115bc7Smrj int i;
226ae115bc7Smrj
227ae115bc7Smrj for (i = 0; i < KDI_GATE_NVECS; i++)
228ae115bc7Smrj kdi_idt_write(&kdi_kgates[i], kdi_gate_specs[i].kgs_vec);
229ae115bc7Smrj }
230ae115bc7Smrj
231ae115bc7Smrj /*
232ae115bc7Smrj * Called when we switch to the kernel's IDT. We need to interpose on the
233ae115bc7Smrj * kernel's IDT entries and stop using KMDBCODE_SEL.
234ae115bc7Smrj */
235ae115bc7Smrj void
kdi_idt_sync(void)236ae115bc7Smrj kdi_idt_sync(void)
237ae115bc7Smrj {
238ae115bc7Smrj kdi_idt_init(KCS_SEL);
239ae115bc7Smrj kdi_idt_gates_install(KCS_SEL, KDI_IDT_SAVE);
240ae115bc7Smrj }
241ae115bc7Smrj
242ae115bc7Smrj void
kdi_update_drreg(kdi_drreg_t * drreg)243ae115bc7Smrj kdi_update_drreg(kdi_drreg_t *drreg)
244ae115bc7Smrj {
245ae115bc7Smrj kdi_drreg = *drreg;
246ae115bc7Smrj }
247ae115bc7Smrj
248ae115bc7Smrj void
kdi_memrange_add(caddr_t base,size_t len)249ae115bc7Smrj kdi_memrange_add(caddr_t base, size_t len)
250ae115bc7Smrj {
251ae115bc7Smrj kdi_memrange_t *mr = &kdi_memranges[kdi_nmemranges];
252ae115bc7Smrj
253ae115bc7Smrj ASSERT(kdi_nmemranges != KDI_MEMRANGES_MAX);
254ae115bc7Smrj
255ae115bc7Smrj mr->mr_base = base;
256ae115bc7Smrj mr->mr_lim = base + len - 1;
257ae115bc7Smrj kdi_nmemranges++;
258ae115bc7Smrj }
259ae115bc7Smrj
260ae115bc7Smrj void
kdi_idt_switch(kdi_cpusave_t * cpusave)261ae115bc7Smrj kdi_idt_switch(kdi_cpusave_t *cpusave)
262ae115bc7Smrj {
263ae115bc7Smrj if (cpusave == NULL)
264ae115bc7Smrj kdi_idtr_set(kdi_idt, sizeof (kdi_idt) - 1);
265ae115bc7Smrj else
2660cfdb603Sjosephb kdi_idtr_set(cpusave->krs_idt, (sizeof (*idt0) * NIDT) - 1);
267ae115bc7Smrj }
268ae115bc7Smrj
269ae115bc7Smrj /*
270ae115bc7Smrj * Activation for CPUs other than the boot CPU, called from that CPU's
271ae115bc7Smrj * mp_startup(). We saved the kernel's descriptors when we initialized the
272ae115bc7Smrj * boot CPU, so we don't want to do it again. Saving the handlers from this
273ae115bc7Smrj * CPU's IDT would actually be dangerous with the CPU initialization method in
274ae115bc7Smrj * use at the time of this writing. With that method, the startup code creates
275ae115bc7Smrj * the IDTs for slave CPUs by copying the one used by the boot CPU, which has
276ae115bc7Smrj * already been interposed upon by KMDB. Were we to interpose again, we'd
277ae115bc7Smrj * replace the kernel's descriptors with our own in the save area. By not
278ae115bc7Smrj * saving, but still overwriting, we'll work in the current world, and in any
279ae115bc7Smrj * future world where the IDT is generated from scratch.
280ae115bc7Smrj */
281ae115bc7Smrj void
kdi_cpu_init(void)282ae115bc7Smrj kdi_cpu_init(void)
283ae115bc7Smrj {
284ae115bc7Smrj kdi_idt_gates_install(KCS_SEL, KDI_IDT_NOSAVE);
285399ca3a7SJohn Levon /* Load the debug registers. */
286ae115bc7Smrj kdi_cpu_debug_init(&kdi_cpusave[CPU->cpu_id]);
287ae115bc7Smrj }
288ae115bc7Smrj
289ae115bc7Smrj /*
290ae115bc7Smrj * Activation for all CPUs for mod-loaded kmdb, i.e. a kmdb that wasn't
291ae115bc7Smrj * loaded at boot.
292ae115bc7Smrj */
293ae115bc7Smrj static int
kdi_cpu_activate(xc_arg_t arg1 __unused,xc_arg_t arg2 __unused,xc_arg_t arg3 __unused)294027bcc9fSToomas Soome kdi_cpu_activate(xc_arg_t arg1 __unused, xc_arg_t arg2 __unused,
295027bcc9fSToomas Soome xc_arg_t arg3 __unused)
296ae115bc7Smrj {
297ae115bc7Smrj kdi_idt_gates_install(KCS_SEL, KDI_IDT_SAVE);
298ae115bc7Smrj return (0);
299ae115bc7Smrj }
300ae115bc7Smrj
301ae115bc7Smrj void
kdi_activate(kdi_main_t main,kdi_cpusave_t * cpusave,uint_t ncpusave)302ae115bc7Smrj kdi_activate(kdi_main_t main, kdi_cpusave_t *cpusave, uint_t ncpusave)
303ae115bc7Smrj {
304ae115bc7Smrj int i;
305ae115bc7Smrj cpuset_t cpuset;
306ae115bc7Smrj
307ae115bc7Smrj CPUSET_ALL(cpuset);
308ae115bc7Smrj
309ae115bc7Smrj kdi_cpusave = cpusave;
310ae115bc7Smrj kdi_ncpusave = ncpusave;
311ae115bc7Smrj
312ae115bc7Smrj kdi_kmdb_main = main;
313ae115bc7Smrj
314ae115bc7Smrj for (i = 0; i < kdi_ncpusave; i++) {
315ae115bc7Smrj kdi_cpusave[i].krs_cpu_id = i;
316ae115bc7Smrj
317ae115bc7Smrj kdi_cpusave[i].krs_curcrumb =
318ae115bc7Smrj &kdi_cpusave[i].krs_crumbs[KDI_NCRUMBS - 1];
319ae115bc7Smrj kdi_cpusave[i].krs_curcrumbidx = KDI_NCRUMBS - 1;
320ae115bc7Smrj }
321ae115bc7Smrj
322ae115bc7Smrj if (boothowto & RB_KMDB)
323ae115bc7Smrj kdi_idt_init(KMDBCODE_SEL);
324ae115bc7Smrj else
325ae115bc7Smrj kdi_idt_init(KCS_SEL);
326ae115bc7Smrj
327ae115bc7Smrj kdi_memranges[0].mr_base = kdi_segdebugbase;
328ae115bc7Smrj kdi_memranges[0].mr_lim = kdi_segdebugbase + kdi_segdebugsize - 1;
329ae115bc7Smrj kdi_nmemranges = 1;
330ae115bc7Smrj
331ae115bc7Smrj kdi_drreg.dr_ctl = KDIREG_DRCTL_RESERVED;
332ae115bc7Smrj kdi_drreg.dr_stat = KDIREG_DRSTAT_RESERVED;
333ae115bc7Smrj
334ae115bc7Smrj if (boothowto & RB_KMDB) {
335ae115bc7Smrj kdi_idt_gates_install(KMDBCODE_SEL, KDI_IDT_NOSAVE);
336ae115bc7Smrj } else {
337027bcc9fSToomas Soome xc_call(0, 0, 0, CPUSET2BV(cpuset), kdi_cpu_activate);
338ae115bc7Smrj }
339ae115bc7Smrj }
340ae115bc7Smrj
341ae115bc7Smrj static int
kdi_cpu_deactivate(xc_arg_t arg1 __unused,xc_arg_t arg2 __unused,xc_arg_t arg3 __unused)342027bcc9fSToomas Soome kdi_cpu_deactivate(xc_arg_t arg1 __unused, xc_arg_t arg2 __unused,
343027bcc9fSToomas Soome xc_arg_t arg3 __unused)
344ae115bc7Smrj {
345ae115bc7Smrj kdi_idt_gates_restore();
346ae115bc7Smrj return (0);
347ae115bc7Smrj }
348ae115bc7Smrj
349ae115bc7Smrj void
kdi_deactivate(void)350ae115bc7Smrj kdi_deactivate(void)
351ae115bc7Smrj {
352ae115bc7Smrj cpuset_t cpuset;
353ae115bc7Smrj CPUSET_ALL(cpuset);
354ae115bc7Smrj
355027bcc9fSToomas Soome xc_call(0, 0, 0, CPUSET2BV(cpuset), kdi_cpu_deactivate);
356ae115bc7Smrj kdi_nmemranges = 0;
357ae115bc7Smrj }
358ae115bc7Smrj
359ae115bc7Smrj /*
360eea802b0SJohn Levon * We receive all breakpoints and single step traps. Some of them, including
361eea802b0SJohn Levon * those from userland and those induced by DTrace providers, are intended for
362eea802b0SJohn Levon * the kernel, and must be processed there. We adopt this
363eea802b0SJohn Levon * ours-until-proven-otherwise position due to the painful consequences of
364eea802b0SJohn Levon * sending the kernel an unexpected breakpoint or single step. Unless someone
365eea802b0SJohn Levon * can prove to us that the kernel is prepared to handle the trap, we'll assume
366eea802b0SJohn Levon * there's a problem and will give the user a chance to debug it.
367eea802b0SJohn Levon *
368eea802b0SJohn Levon * If we return 2, then the calling code should restore the trap-time %cr3: that
369eea802b0SJohn Levon * is, it really is a kernel-originated trap.
370ae115bc7Smrj */
371843e1988Sjohnlev int
kdi_trap_pass(kdi_cpusave_t * cpusave)372ae115bc7Smrj kdi_trap_pass(kdi_cpusave_t *cpusave)
373ae115bc7Smrj {
374ae115bc7Smrj greg_t tt = cpusave->krs_gregs[KDIREG_TRAPNO];
375ae115bc7Smrj greg_t pc = cpusave->krs_gregs[KDIREG_PC];
376ae115bc7Smrj greg_t cs = cpusave->krs_gregs[KDIREG_CS];
377ae115bc7Smrj
378ae115bc7Smrj if (USERMODE(cs))
379ae115bc7Smrj return (1);
380ae115bc7Smrj
381ae115bc7Smrj if (tt != T_BPTFLT && tt != T_SGLSTP)
382ae115bc7Smrj return (0);
383ae115bc7Smrj
384ae115bc7Smrj if (tt == T_BPTFLT && kdi_dtrace_get_state() ==
385ae115bc7Smrj KDI_DTSTATE_DTRACE_ACTIVE)
386eea802b0SJohn Levon return (2);
387ae115bc7Smrj
388ae115bc7Smrj /*
389ae115bc7Smrj * See the comments in the kernel's T_SGLSTP handler for why we need to
390ae115bc7Smrj * do this.
391ae115bc7Smrj */
39274ecdb51SJohn Levon #if !defined(__xpv)
393ae115bc7Smrj if (tt == T_SGLSTP &&
39474ecdb51SJohn Levon (pc == (greg_t)sys_sysenter || pc == (greg_t)brand_sys_sysenter ||
39574ecdb51SJohn Levon pc == (greg_t)tr_sys_sysenter ||
39674ecdb51SJohn Levon pc == (greg_t)tr_brand_sys_sysenter)) {
39774ecdb51SJohn Levon #else
39874ecdb51SJohn Levon if (tt == T_SGLSTP &&
39974ecdb51SJohn Levon (pc == (greg_t)sys_sysenter || pc == (greg_t)brand_sys_sysenter)) {
40074ecdb51SJohn Levon #endif
401ae115bc7Smrj return (1);
40274ecdb51SJohn Levon }
403ae115bc7Smrj
404ae115bc7Smrj return (0);
405ae115bc7Smrj }
406ae115bc7Smrj
407ae115bc7Smrj /*
408ae115bc7Smrj * State has been saved, and all CPUs are on the CPU-specific stacks. All
409ae115bc7Smrj * CPUs enter here, and head off into the debugger proper.
410ae115bc7Smrj */
411843e1988Sjohnlev void
412ae115bc7Smrj kdi_debugger_entry(kdi_cpusave_t *cpusave)
413ae115bc7Smrj {
414ae115bc7Smrj /*
415ae115bc7Smrj * BPTFLT gives us control with %eip set to the instruction *after*
416ae115bc7Smrj * the int 3. Back it off, so we're looking at the instruction that
417ae115bc7Smrj * triggered the fault.
418ae115bc7Smrj */
419ae115bc7Smrj if (cpusave->krs_gregs[KDIREG_TRAPNO] == T_BPTFLT)
420ae115bc7Smrj cpusave->krs_gregs[KDIREG_PC]--;
421ae115bc7Smrj
422ae115bc7Smrj kdi_kmdb_main(cpusave);
423ae115bc7Smrj }
424