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/cpuvar.h>
27#include <sys/kdi_impl.h>
28#include <sys/reboot.h>
29#include <sys/errno.h>
30#include <sys/atomic.h>
31#include <sys/kmem.h>
32
33kdi_debugvec_t	*kdi_dvec;
34struct modctl	*kdi_dmods;
35
36static kdi_dtrace_state_t kdi_dtrace_state = KDI_DTSTATE_IDLE;
37
38void
39kdi_dvec_vmready(void)
40{
41	kdi_dvec->dv_kctl_vmready();
42	kdi_dvec->dv_vmready();
43}
44
45void
46kdi_dvec_memavail(void)
47{
48	/*
49	 * The driver will allocate more memory (if requested), and will call
50	 * dv_memavail itself.
51	 */
52	kdi_dvec->dv_kctl_memavail();
53}
54
55#if defined(__x86)
56void
57kdi_dvec_handle_fault(greg_t trapno, greg_t pc, greg_t sp, int cpuid)
58{
59	kdi_dvec->dv_handle_fault(trapno, pc, sp, cpuid);
60}
61#endif
62
63#if defined(__sparc)
64/*
65 * Called on the CPU being initialized
66 */
67void
68kdi_dvec_cpu_init(struct cpu *cp)
69{
70	kdi_dvec->dv_kctl_cpu_init();
71	kdi_dvec->dv_cpu_init(cp);
72}
73
74void
75kdi_dvec_cpr_restart(void)
76{
77	kdi_dvec->dv_kctl_cpu_init();
78	kdi_dvec->dv_cpr_restart();
79}
80#endif	/* __sparc */
81
82void
83kdi_dvec_modavail(void)
84{
85	kdi_dvec->dv_kctl_modavail();
86}
87
88void
89kdi_dvec_thravail(void)
90{
91	kdi_dvec->dv_kctl_thravail();
92}
93
94void
95kdi_dvec_mod_loaded(struct modctl *modp)
96{
97	kdi_dvec->dv_mod_loaded(modp);
98}
99
100void
101kdi_dvec_mod_unloading(struct modctl *modp)
102{
103	kdi_dvec->dv_mod_unloading(modp);
104}
105
106kdi_dtrace_state_t
107kdi_dtrace_get_state(void)
108{
109	return (kdi_dtrace_state);
110}
111
112int
113kdi_dtrace_set(kdi_dtrace_set_t transition)
114{
115	kdi_dtrace_state_t new, cur;
116
117	do {
118		cur = kdi_dtrace_state;
119
120		switch (transition) {
121		case KDI_DTSET_DTRACE_ACTIVATE:
122			if (cur == KDI_DTSTATE_KMDB_BPT_ACTIVE)
123				return (EBUSY);
124			if (cur == KDI_DTSTATE_DTRACE_ACTIVE)
125				return (0);
126			new = KDI_DTSTATE_DTRACE_ACTIVE;
127			break;
128		case KDI_DTSET_DTRACE_DEACTIVATE:
129			if (cur == KDI_DTSTATE_KMDB_BPT_ACTIVE)
130				return (EBUSY);
131			if (cur == KDI_DTSTATE_IDLE)
132				return (0);
133			new = KDI_DTSTATE_IDLE;
134			break;
135		case KDI_DTSET_KMDB_BPT_ACTIVATE:
136			if (cur == KDI_DTSTATE_DTRACE_ACTIVE)
137				return (EBUSY);
138			if (cur == KDI_DTSTATE_KMDB_BPT_ACTIVE)
139				return (0);
140			new = KDI_DTSTATE_KMDB_BPT_ACTIVE;
141			break;
142		case KDI_DTSET_KMDB_BPT_DEACTIVATE:
143			if (cur == KDI_DTSTATE_DTRACE_ACTIVE)
144				return (EBUSY);
145			if (cur == KDI_DTSTATE_IDLE)
146				return (0);
147			new = KDI_DTSTATE_IDLE;
148			break;
149		default:
150			return (EINVAL);
151		}
152	} while (atomic_cas_32((uint_t *)&kdi_dtrace_state, cur, new) != cur);
153
154	return (0);
155}
156