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