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
kdi_idtr_write(desctbr_t * idtr)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
kdi_idt_write(gate_desc_t * gate,uint_t vec)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
kdi_dreg_get(int reg)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
kdi_dreg_set(int reg,ulong_t value)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
kdi_flush_caches(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
kdi_stop_slaves(int cpu,int doxc)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
kdi_start_slaves(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
check_slave(void * arg)137*843e1988Sjohnlev check_slave(void *arg)
138*843e1988Sjohnlev {
139*843e1988Sjohnlev return (kdi_slaves_go == 1);
140*843e1988Sjohnlev }
141*843e1988Sjohnlev
142*843e1988Sjohnlev void
kdi_slave_wait(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 *
boot_kdi_tmpinit(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
boot_kdi_tmpfini(void * old)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 *
boot_kdi_tmpinit(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
boot_kdi_tmpfini(void * old)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