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