xref: /illumos-gate/usr/src/uts/i86xpv/os/mach_kdi.c (revision 86ef0a63)
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