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 2007 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 * PROM interface 31 */ 32 33 #include <sys/types.h> 34 #include <unistd.h> 35 #include <string.h> 36 #include <stdlib.h> 37 38 #define _KERNEL 39 #define _BOOT 40 #include <sys/promif.h> 41 #undef _BOOT 42 #undef _KERNEL 43 44 #include <mdb/mdb_debug.h> 45 #include <mdb/mdb_err.h> 46 #include <kmdb/kmdb_promif_impl.h> 47 #include <kmdb/kmdb_kdi.h> 48 #include <mdb/mdb_string.h> 49 #include <mdb/mdb.h> 50 51 #ifndef sun4v 52 int kmdb_prom_preserve_kctx = 0; 53 #endif /* sun4v */ 54 55 ssize_t 56 kmdb_prom_obp_writer(caddr_t buf, size_t len) 57 { 58 return (prom_write(prom_stdout_ihandle(), buf, len, 0, 0)); 59 } 60 61 ihandle_t 62 kmdb_prom_get_handle(char *name) 63 { 64 if (strcmp(name, "stdin") == 0) 65 return (prom_stdin_ihandle()); 66 else if (strcmp(name, "stdout") == 0 || strcmp(name, "stderr") == 0) 67 return (prom_stdout_ihandle()); 68 else 69 return (-1); 70 } 71 72 /*ARGSUSED*/ 73 char * 74 kmdb_prom_get_ddi_prop(kmdb_auxv_t *kav, char *propname) 75 { 76 pnode_t node; 77 ssize_t len; 78 char *val; 79 80 if ((node = prom_finddevice("/options")) == NULL) 81 return (NULL); 82 83 if ((len = prom_getproplen(node, propname)) < 0) 84 return (NULL); 85 86 val = mdb_alloc(len + 1, UM_SLEEP); 87 88 if (prom_bounded_getprop(node, propname, val, len) != len) { 89 mdb_free(val, len); 90 return (NULL); 91 } 92 val[len] = '\0'; 93 94 return (val); 95 } 96 97 void 98 kmdb_prom_free_ddi_prop(char *val) 99 { 100 strfree(val); 101 } 102 103 int 104 kmdb_prom_getprop(pnode_t node, char *name, caddr_t value) 105 { 106 return (prom_getprop(node, name, value)); 107 } 108 109 typedef struct walk_cpu_data { 110 int (*wcd_cb)(pnode_t, void *, void *); 111 void *wcd_arg; 112 } walk_cpu_data_t; 113 114 static int 115 walk_cpus_cb(pnode_t node, void *arg, void *result) 116 { 117 walk_cpu_data_t *wcd = arg; 118 119 /* 120 * Sun4v doesn't support port_id on guest. 121 */ 122 #ifndef sun4v 123 int port_id; 124 #endif /* sun4v */ 125 126 if (!prom_devicetype(node, OBP_CPU)) 127 return (PROM_WALK_CONTINUE); 128 129 #ifndef sun4v 130 if ((prom_getprop(node, "portid", (caddr_t)&port_id) == -1) && 131 (prom_getprop(node, "upa-portid", (caddr_t)&port_id) == -1) && 132 (prom_getprop(node, "cpuid", (caddr_t)&port_id) == -1)) { 133 warn("cpu node %x has no identifying properties\n", 134 node); 135 return (PROM_WALK_CONTINUE); 136 } 137 #endif /* sun4v */ 138 139 if (wcd->wcd_cb(node, wcd->wcd_arg, result) != 0) 140 return (PROM_WALK_TERMINATE); 141 142 return (PROM_WALK_CONTINUE); 143 } 144 145 void 146 kmdb_prom_walk_cpus(int (*cb)(pnode_t, void *, void *), void *arg, void *result) 147 { 148 walk_cpu_data_t wcd; 149 150 wcd.wcd_cb = cb; 151 wcd.wcd_arg = arg; 152 153 prom_walk_devs(prom_rootnode(), walk_cpus_cb, &wcd, result); 154 } 155 156 void 157 kmdb_prom_enter_mon(void) 158 { 159 prom_enter_mon(); 160 } 161 162 #ifndef sun4v 163 pnode_t 164 kmdb_prom_getcpu_propnode(pnode_t node) 165 { 166 int val; 167 pnode_t pnode; 168 char name[OBP_MAXPROPNAME]; 169 170 171 /* 172 * Check for the CMT case where cpu nodes are "strand" nodes 173 * In this case, the "cpu node" properties are contained in 174 * its parent "core" node. 175 */ 176 if (prom_getprop(node, "portid", (caddr_t)&val) == -1 && 177 prom_getprop(node, "upa-portid", (caddr_t)&val) == -1 && 178 prom_getprop((pnode = prom_parentnode(node)), "name", name) != -1 && 179 strcmp(name, "core") == 0) 180 return (pnode); 181 182 return (node); 183 } 184 #endif /* sun4v */ 185 186 void 187 kmdb_prom_exit_to_mon(void) 188 { 189 prom_exit_to_mon(); 190 } 191 192 void 193 kmdb_prom_interpret(const char *str) 194 { 195 prom_interpret((char *)str, 0, 0, 0, 0, 0); 196 } 197 198 /*ARGSUSED*/ 199 int 200 kmdb_prom_translate_virt(uintptr_t virt, physaddr_t *pap) 201 { 202 extern int prom_translate_virt(caddr_t, int *, u_longlong_t *, int *); 203 204 int valid, mode; 205 uintptr_t vabase = virt & ~(mdb.m_pagesize - 1); 206 uintptr_t off = virt - vabase; 207 u_longlong_t pa; 208 209 mdb_dprintf(MDB_DBG_DPI, "using OBP for vtop of %p\n", (void *)virt); 210 211 if (prom_translate_virt((caddr_t)vabase, &valid, &pa, &mode) != 0) 212 return (set_errno(EMDB_NOMAP)); 213 214 *pap = pa + off; 215 return (0); 216 } 217 218 /*ARGSUSED*/ 219 int 220 kmdb_prom_stdout_is_framebuffer(kmdb_auxv_t *kav) 221 { 222 return (prom_stdout_is_framebuffer()); 223 } 224 225 #ifndef sun4v 226 #define PROM_KCTX_PRESERVED_PROPNAME "context0-page-size-preserved" 227 void 228 kmdb_prom_preserve_kctx_init(void) 229 { 230 pnode_t pnode; 231 int val; 232 233 pnode = (pnode_t)prom_getphandle(prom_mmu_ihandle()); 234 if (prom_getprop(pnode, PROM_KCTX_PRESERVED_PROPNAME, 235 (caddr_t)&val) == 0) { 236 kmdb_prom_preserve_kctx = 1; 237 } 238 } 239 #endif /* sun4v */ 240