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 /* 23 * Copyright 2006 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 #include <kmdb/kmdb_auxv.h> 30 #include <kmdb/kctl/kctl.h> 31 32 #include <sys/bootconf.h> 33 #include <sys/kobj.h> 34 #include <sys/kobj_impl.h> 35 #include <sys/cpuvar.h> 36 #include <sys/kdi_impl.h> 37 #include <sys/x86_archext.h> 38 #include <sys/controlregs.h> 39 #include <sys/archsystm.h> 40 41 #if defined(__i386) 42 /* Copied from stand/i386/sys/bootdef.h */ 43 #define GS_GDT 0x38 /* dummy cpu_t pointer descriptor */ 44 #endif 45 46 static int 47 kctl_boot_prop_read(char *pname, char *prop_buf, int buf_len) 48 { 49 int len; 50 struct bootops *ops = kctl.kctl_boot_ops; 51 52 len = BOP_GETPROPLEN(ops, pname); 53 if (len > 0 && len <= buf_len) { 54 (void) BOP_GETPROP(ops, pname, (void *)prop_buf); 55 return (1); 56 } 57 58 return (0); 59 } 60 61 static int 62 kctl_ddi_prop_read(char *pname, char *prop_buf, int buf_len) 63 { 64 dev_info_t *dip = ddi_root_node(); 65 char *val; 66 int ret = 0; 67 68 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, 69 DDI_PROP_DONTPASS, pname, &val) != DDI_SUCCESS) 70 return (0); 71 72 if (strlen(val) < buf_len) { 73 (void) strcpy(prop_buf, val); 74 ret = 1; 75 } 76 77 ddi_prop_free(val); 78 return (ret); 79 } 80 81 /* 82 * We don't have any property-walking routines, so we have to specifically 83 * query and thus have guilty knowledge of the properties that the 84 * debugger wants to see. 85 * 86 * Here actually we only support four console properties: 87 * input-device, output-device, ttya-mode, ttyb-mode. 88 */ 89 #define KCTL_PROPNV_NENT 4 90 91 static kmdb_auxv_nv_t * 92 kctl_pcache_create(int *nprops) 93 { 94 int (*preader)(char *, char *, int); 95 kmdb_auxv_nv_t *pnv; 96 size_t psz = sizeof (kmdb_auxv_nv_t) * KCTL_PROPNV_NENT; 97 98 if (kctl.kctl_boot_loaded) { 99 preader = kctl_boot_prop_read; 100 } else { 101 preader = kctl_ddi_prop_read; 102 } 103 104 pnv = kobj_alloc(psz, KM_WAIT); 105 106 (void) strcpy((&pnv[0])->kanv_name, "input-device"); 107 (void) strcpy((&pnv[1])->kanv_name, "output-device"); 108 (void) strcpy((&pnv[2])->kanv_name, "ttya-mode"); 109 (void) strcpy((&pnv[3])->kanv_name, "ttyb-mode"); 110 111 /* 112 * console is defined by "console" property, with 113 * fallback on the old "input-device" property. 114 */ 115 (void) strcpy((&pnv[0])->kanv_val, "text"); /* default to screen */ 116 if (!preader("console", (&pnv[0])->kanv_val, 117 sizeof ((&pnv[0])->kanv_val))) 118 (void) preader("input-device", (&pnv[0])->kanv_val, 119 sizeof ((&pnv[0])->kanv_val)); 120 121 if (strcmp((&pnv[0])->kanv_val, "ttya") == 0 || 122 strcmp((&pnv[0])->kanv_val, "ttyb") == 0) { 123 (void) strcpy((&pnv[1])->kanv_val, (&pnv[0])->kanv_val); 124 } else { 125 (void) strcpy((&pnv[0])->kanv_val, "keyboard"); 126 (void) strcpy((&pnv[1])->kanv_val, "screen"); 127 } 128 129 if (!preader((&pnv[2])->kanv_name, (&pnv[2])->kanv_val, 130 sizeof ((&pnv[2])->kanv_val))) 131 (void) strcpy((&pnv[2])->kanv_val, "9600,8,n,1,-"); 132 133 if (!preader((&pnv[3])->kanv_name, (&pnv[3])->kanv_val, 134 sizeof ((&pnv[3])->kanv_val))) 135 (void) strcpy((&pnv[3])->kanv_val, "9600,8,n,1,-"); 136 137 *nprops = KCTL_PROPNV_NENT; 138 return (pnv); 139 } 140 141 static void 142 kctl_pcache_destroy(kmdb_auxv_nv_t *pnv) 143 { 144 kobj_free(pnv, sizeof (kmdb_auxv_nv_t) * KCTL_PROPNV_NENT); 145 } 146 147 /*ARGSUSED*/ 148 static void 149 kctl_cpu_init(void) 150 { 151 } 152 153 void 154 kctl_auxv_init_isadep(kmdb_auxv_t *kav, void *romp) 155 { 156 kav->kav_pcache = kctl_pcache_create(&kav->kav_nprops); 157 kav->kav_romp = romp; 158 } 159 160 void 161 kctl_auxv_fini_isadep(kmdb_auxv_t *kav) 162 { 163 if (kav->kav_pcache != NULL) 164 kctl_pcache_destroy(kav->kav_pcache); 165 } 166 167 int 168 kctl_preactivate_isadep(void) 169 { 170 return (0); 171 } 172 173 /*ARGSUSED*/ 174 int 175 kctl_activate_isadep(kdi_debugvec_t *dvec) 176 { 177 dvec->dv_kctl_cpu_init = kctl_cpu_init; 178 dvec->dv_kctl_vmready = hat_kdi_init; 179 180 if (!kctl.kctl_boot_loaded) 181 hat_kdi_init(); 182 183 return (0); 184 } 185 186 void 187 kctl_depreactivate_isadep(void) 188 { 189 } 190 191 void 192 kctl_deactivate_isadep(void) 193 { 194 hat_kdi_fini(); 195 } 196 197 #if defined(__amd64) 198 void * 199 kctl_boot_tmpinit(void) 200 { 201 /* 202 * Many common kernel functions assume that GSBASE has been initialized, 203 * and fail horribly if it hasn't. We'll install a pointer to a dummy 204 * cpu_t for use during our initialization. 205 */ 206 cpu_t *old = (cpu_t *)rdmsr(MSR_AMD_GSBASE); 207 208 wrmsr(MSR_AMD_GSBASE, (uint64_t)kobj_zalloc(sizeof (cpu_t), KM_TMP)); 209 return (old); 210 } 211 212 void 213 kctl_boot_tmpfini(void *old) 214 { 215 wrmsr(MSR_AMD_GSBASE, (uint64_t)old); 216 } 217 218 #else 219 220 void * 221 kctl_boot_tmpinit(void) 222 { 223 /* 224 * Many common kernel functions assume that %gs has been initialized, 225 * and fail horribly if it hasn't. Boot has reserved a descriptor for 226 * us (GS_GDT) in its GDT, a descriptor which we'll use to describe our 227 * dummy cpu_t. We then set %gs to refer to this descriptor. 228 */ 229 cpu_t *cpu = kobj_zalloc(sizeof (cpu_t), KM_TMP); 230 uintptr_t old; 231 desctbr_t bgdt; 232 user_desc_t *gsdesc; 233 234 rd_gdtr(&bgdt); 235 gsdesc = (user_desc_t *)(bgdt.dtr_base + GS_GDT); 236 237 USEGD_SETBASE(gsdesc, (uintptr_t)cpu); 238 USEGD_SETLIMIT(gsdesc, sizeof (cpu_t)); 239 240 old = getgs(); 241 setgs(GS_GDT); 242 243 return ((void *)old); 244 } 245 246 void 247 kctl_boot_tmpfini(void *old) 248 { 249 setgs((uintptr_t)old); 250 } 251 #endif 252