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 /*
29 * Kernel/Debugger Interface (KDI) routines. Called during debugger under
30 * various system states (boot, while running, while the debugger has control).
31 * Functions intended for use while the debugger has control may not grab any
32 * locks or perform any functions that assume the availability of other system
33 * services.
34 */
35
36 #include <sys/systm.h>
37 #include <sys/x86_archext.h>
38 #include <sys/kdi_impl.h>
39 #include <sys/smp_impldefs.h>
40 #include <sys/psm_types.h>
41 #include <sys/segments.h>
42 #include <sys/archsystm.h>
43 #include <sys/controlregs.h>
44 #include <sys/trap.h>
45 #include <sys/kobj.h>
46 #include <sys/kobj_impl.h>
47 #include <sys/hypervisor.h>
48 #include <sys/bootconf.h>
49 #include <sys/bootinfo.h>
50 #include <sys/promif.h>
51 #include <sys/evtchn_impl.h>
52 #include <sys/cpu.h>
53 #include <vm/kboot_mmu.h>
54 #include <vm/hat_pte.h>
55
56 static volatile int kdi_slaves_go;
57
58 /*
59 * These are not safe against dropping into kmdb when fbt::: is active. This is
60 * also broken on i86pc...
61 */
62
63 void
kdi_idtr_write(desctbr_t * idtr)64 kdi_idtr_write(desctbr_t *idtr)
65 {
66 gate_desc_t *idt = (gate_desc_t *)idtr->dtr_base;
67 uint_t nidt = (idtr->dtr_limit + 1) / sizeof (*idt);
68 uint_t vec;
69
70 for (vec = 0; vec < nidt; vec++, idt++)
71 xen_idt_write(idt, vec);
72 }
73
74 void
kdi_idt_write(gate_desc_t * gate,uint_t vec)75 kdi_idt_write(gate_desc_t *gate, uint_t vec)
76 {
77 gate_desc_t *idt = CPU->cpu_m.mcpu_idt;
78
79 /*
80 * See kdi_idtr_set().
81 */
82 if (idt != NULL)
83 idt[vec] = *gate;
84
85 xen_idt_write(gate, vec);
86 }
87
88 ulong_t
kdi_dreg_get(int reg)89 kdi_dreg_get(int reg)
90 {
91 return (__hypercall1(__HYPERVISOR_get_debugreg, (long)reg));
92 }
93
94 void
kdi_dreg_set(int reg,ulong_t value)95 kdi_dreg_set(int reg, ulong_t value)
96 {
97 (void) __hypercall2(__HYPERVISOR_set_debugreg, (long)reg, value);
98 }
99
100 void
kdi_flush_caches(void)101 kdi_flush_caches(void)
102 {
103 }
104
105 /*
106 * To avoid domains sucking up CPU while sitting in kmdb, we make all the slave
107 * CPUs wait for a wake-up evtchn. The master CPU, meanwhile, sleeps for
108 * console activity.
109 */
110
111 extern void kdi_slave_entry(void);
112
113 void
kdi_stop_slaves(int cpu,int doxc)114 kdi_stop_slaves(int cpu, int doxc)
115 {
116 if (doxc)
117 kdi_xc_others(cpu, kdi_slave_entry);
118 kdi_slaves_go = 0;
119 }
120
121 void
kdi_start_slaves(void)122 kdi_start_slaves(void)
123 {
124 int c;
125
126 kdi_slaves_go = 1;
127
128 for (c = 0; c < NCPU; c++) {
129 if (cpu[c] == NULL || !(cpu[c]->cpu_flags & CPU_READY))
130 continue;
131 ec_try_ipi(XC_CPUPOKE_PIL, c);
132 }
133 }
134
135 /*ARGSUSED*/
136 static int
check_slave(void * arg)137 check_slave(void *arg)
138 {
139 return (kdi_slaves_go == 1);
140 }
141
142 void
kdi_slave_wait(void)143 kdi_slave_wait(void)
144 {
145 if (!(cpu[CPU->cpu_id]->cpu_flags & CPU_READY))
146 return;
147
148 ec_wait_on_ipi(XC_CPUPOKE_PIL, check_slave, NULL);
149 }
150
151 /*
152 * Caution.
153 * These routines are called -extremely- early, during kmdb initialization.
154 *
155 * Many common kernel functions assume that %gs has been initialized,
156 * and fail horribly if it hasn't. At this point, the boot code has
157 * reserved a descriptor for us (KMDBGS_SEL) in it's GDT; arrange for it
158 * to point at a dummy cpu_t, temporarily at least.
159 *
160 * Note that kmdb entry relies on the fake cpu_t having zero cpu_idt/cpu_id.
161 */
162
163 #if defined(__amd64)
164
165 void *
boot_kdi_tmpinit(void)166 boot_kdi_tmpinit(void)
167 {
168 cpu_t *cpu = kobj_zalloc(sizeof (*cpu), KM_TMP);
169 user_desc_t *bgdt;
170 uint64_t gdtpa;
171 ulong_t ma[1];
172
173 cpu->cpu_self = cpu;
174
175 /*
176 * (Note that we had better switch to a -new- GDT before
177 * we discard the KM_TMP mappings, or disaster will ensue.)
178 */
179 bgdt = kobj_zalloc(PAGESIZE, KM_TMP);
180 ASSERT(((uintptr_t)bgdt & PAGEOFFSET) == 0);
181
182 init_boot_gdt(bgdt);
183
184 gdtpa = pfn_to_pa(va_to_pfn(bgdt));
185 ma[0] = (ulong_t)(pa_to_ma(gdtpa) >> PAGESHIFT);
186 kbm_read_only((uintptr_t)bgdt, gdtpa);
187 if (HYPERVISOR_set_gdt(ma, PAGESIZE / sizeof (user_desc_t)))
188 panic("boot_kdi_tmpinit:HYPERVISOR_set_gdt() failed");
189
190 load_segment_registers(B64CODE_SEL, 0, 0, B32DATA_SEL);
191
192 /*
193 * Now point %gsbase to our temp cpu structure.
194 */
195 xen_set_segment_base(SEGBASE_GS_KERNEL, (ulong_t)cpu);
196 return (0);
197 }
198
199 /*ARGSUSED*/
200 void
boot_kdi_tmpfini(void * old)201 boot_kdi_tmpfini(void *old)
202 {
203 /*
204 * This breaks, why do we need it anyway?
205 */
206 #if 0 /* XXPV */
207 load_segment_registers(B64CODE_SEL, 0, KMDBGS_SEL, B32DATA_SEL);
208 #endif
209 }
210
211 #elif defined(__i386)
212
213 /*
214 * Sigh. We're called before we've initialized the kernels GDT, living
215 * off the hypervisor's default GDT. For kmdb's sake, we switch now to
216 * a GDT that looks like dboot's GDT; very shortly we'll initialize and
217 * switch to the kernel's GDT.
218 */
219
220 void *
boot_kdi_tmpinit(void)221 boot_kdi_tmpinit(void)
222 {
223 cpu_t *cpu = kobj_zalloc(sizeof (*cpu), KM_TMP);
224 user_desc_t *bgdt;
225 uint64_t gdtpa;
226 ulong_t ma[1];
227
228 cpu->cpu_self = cpu;
229
230 /*
231 * (Note that we had better switch to a -new- GDT before
232 * we discard the KM_TMP mappings, or disaster will ensue.)
233 */
234 bgdt = kobj_zalloc(PAGESIZE, KM_TMP);
235
236 ASSERT(((uintptr_t)bgdt & PAGEOFFSET) == 0);
237 gdtpa = pfn_to_pa(va_to_pfn(bgdt));
238
239 init_boot_gdt(bgdt);
240
241 set_usegd(&bgdt[GDT_BGSTMP],
242 cpu, sizeof (*cpu), SDT_MEMRWA, SEL_KPL, SDP_BYTES, SDP_OP32);
243
244 ma[0] = (ulong_t)(pa_to_ma(gdtpa) >> PAGESHIFT);
245 kbm_read_only((uintptr_t)bgdt, gdtpa);
246 if (HYPERVISOR_set_gdt(ma, PAGESIZE / sizeof (user_desc_t)))
247 panic("boot_kdi_tmpinit:HYPERVISOR_set_gdt() failed");
248
249 load_segment_registers(B32CODE_SEL, B32DATA_SEL, B32DATA_SEL, 0,
250 KMDBGS_SEL, B32DATA_SEL);
251 return (0);
252 }
253
254 /*ARGSUSED*/
255 void
boot_kdi_tmpfini(void * old)256 boot_kdi_tmpfini(void *old)
257 {
258 load_segment_registers(B32CODE_SEL, B32DATA_SEL, B32DATA_SEL, 0,
259 0, B32DATA_SEL);
260 }
261
262 #endif /* __i386 */
263