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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * Kernel/Debugger Interface (KDI) routines. Called during debugger under 31 * various system states (boot, while running, while the debugger has control). 32 * Functions intended for use while the debugger has control may not grab any 33 * locks or perform any functions that assume the availability of other system 34 * services. 35 */ 36 37 #include <sys/systm.h> 38 #include <sys/x86_archext.h> 39 #include <sys/kdi_impl.h> 40 #include <sys/smp_impldefs.h> 41 #include <sys/psm_types.h> 42 #include <sys/segments.h> 43 44 static void 45 kdi_system_claim(void) 46 { 47 psm_notifyf(PSM_DEBUG_ENTER); 48 } 49 50 static void 51 kdi_system_release(void) 52 { 53 psm_notifyf(PSM_DEBUG_EXIT); 54 } 55 56 static cpu_t * 57 kdi_gdt2cpu(uintptr_t gdtbase) 58 { 59 cpu_t *cp = cpu_list; 60 61 if (cp == NULL) 62 return (NULL); 63 64 do { 65 if (gdtbase == (uintptr_t)cp->cpu_gdt) 66 return (cp); 67 } while ((cp = cp->cpu_next) != cpu_list); 68 69 return (NULL); 70 } 71 72 #if defined(__amd64) 73 static uintptr_t 74 kdi_gdt2gsbase(uintptr_t gdtbase) 75 { 76 return ((uintptr_t)kdi_gdt2cpu(gdtbase)); 77 } 78 #endif 79 80 static void 81 kdi_cpu_iter(void (*iter)(cpu_t *, uint_t), uint_t arg) 82 { 83 cpu_t *cp; 84 85 mutex_enter(&cpu_lock); 86 87 cp = cpu_list; 88 do { 89 iter(cp, arg); 90 } while ((cp = cp->cpu_next) != cpu_list); 91 92 mutex_exit(&cpu_lock); 93 } 94 95 static gate_desc_t * 96 curidt(void) 97 { 98 desctbr_t idtdesc; 99 rd_idtr(&idtdesc); 100 return ((gate_desc_t *)idtdesc.dtr_base); 101 } 102 103 static void 104 kdi_idt_init_gate(gate_desc_t *gate, void (*hdlr)(void), uint_t dpl, 105 int useboot) 106 { 107 bzero(gate, sizeof (gate_desc_t)); 108 109 #if defined(__amd64) 110 set_gatesegd(gate, hdlr, (useboot ? B64CODE_SEL : KCS_SEL), 0, 111 SDT_SYSIGT, dpl); 112 #else 113 set_gatesegd(gate, hdlr, (useboot ? BOOTCODE_SEL : KCS_SEL), 0, 114 SDT_SYSIGT, dpl); 115 #endif 116 } 117 118 static void 119 kdi_idt_read(gate_desc_t *idt, gate_desc_t *gatep, uint_t vec) 120 { 121 if (idt == NULL) 122 idt = curidt(); 123 *gatep = idt[vec]; 124 } 125 126 static void 127 kdi_idt_write(gate_desc_t *idt, gate_desc_t *gate, uint_t vec) 128 { 129 if (idt == NULL) 130 idt = curidt(); 131 idt[vec] = *gate; 132 } 133 134 static gate_desc_t * 135 kdi_cpu2idt(cpu_t *cp) 136 { 137 if (cp == NULL) 138 cp = CPU; 139 return (cp->cpu_idt); 140 } 141 142 void 143 kdi_flush_caches(void) 144 { 145 reload_cr3(); 146 } 147 148 static int 149 kdi_get_cpuinfo(uint_t *vendorp, uint_t *familyp, uint_t *modelp) 150 { 151 desctbr_t gdtr; 152 cpu_t *cpu; 153 154 /* 155 * CPU doesn't work until the GDT and gs/GSBASE have been set up. 156 * Boot-loaded kmdb will call us well before then, so we have to 157 * find the current cpu_t the hard way. 158 */ 159 rd_gdtr(&gdtr); 160 if ((cpu = kdi_gdt2cpu(gdtr.dtr_base)) == NULL || 161 !cpuid_checkpass(cpu, 1)) 162 return (EAGAIN); /* cpuid isn't done yet */ 163 164 *vendorp = cpuid_getvendor(cpu); 165 *familyp = cpuid_getfamily(cpu); 166 *modelp = cpuid_getmodel(cpu); 167 168 return (0); 169 } 170 171 static void 172 kdi_plat_call(void (*platfn)(void)) 173 { 174 if (platfn != NULL) 175 platfn(); 176 } 177 178 void 179 mach_kdi_init(kdi_t *kdi) 180 { 181 kdi->kdi_plat_call = kdi_plat_call; 182 kdi->mkdi_get_cpuinfo = kdi_get_cpuinfo; 183 kdi->mkdi_xc_initialized = kdi_xc_initialized; 184 kdi->mkdi_xc_others = kdi_xc_others; 185 kdi->mkdi_get_userlimit = kdi_get_userlimit; 186 187 kdi->mkdi_idt_init_gate = kdi_idt_init_gate; 188 kdi->mkdi_idt_read = kdi_idt_read; 189 kdi->mkdi_idt_write = kdi_idt_write; 190 kdi->mkdi_cpu2idt = kdi_cpu2idt; 191 192 kdi->mkdi_shutdownp = &psm_shutdownf; 193 #if defined(__amd64) 194 kdi->mkdi_gdt2gsbase = &kdi_gdt2gsbase; 195 #endif 196 197 kdi->mkdi_cpu_iter = kdi_cpu_iter; 198 } 199 200 /*ARGSUSED*/ 201 void 202 mach_kdi_fini(kdi_t *kdi) 203 { 204 hat_kdi_fini(); 205 } 206 207 void 208 plat_kdi_init(kdi_t *kdi) 209 { 210 kdi->pkdi_system_claim = kdi_system_claim; 211 kdi->pkdi_system_release = kdi_system_release; 212 } 213