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