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 2005 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 <sys/types.h> 30 #include <sys/processor.h> 31 #include <fm/fmd_fmri.h> 32 33 #include <string.h> 34 #include <strings.h> 35 #include <errno.h> 36 #include <kstat.h> 37 #ifdef sparc 38 #include <sys/mdesc.h> 39 #include <cpu.h> 40 #endif /* sparc */ 41 42 /* 43 * The scheme plugin for cpu FMRIs. 44 */ 45 46 #ifdef sparc 47 cpu_t cpu; 48 #endif /* sparc */ 49 50 ssize_t 51 fmd_fmri_nvl2str(nvlist_t *nvl, char *buf, size_t buflen) 52 { 53 uint8_t version; 54 uint32_t cpuid; 55 uint64_t serialid; 56 57 if (nvlist_lookup_uint8(nvl, FM_VERSION, &version) != 0 || 58 version > FM_CPU_SCHEME_VERSION || 59 nvlist_lookup_uint32(nvl, FM_FMRI_CPU_ID, &cpuid) != 0 || 60 nvlist_lookup_uint64(nvl, FM_FMRI_CPU_SERIAL_ID, &serialid) != 0) 61 return (fmd_fmri_set_errno(EINVAL)); 62 63 return (snprintf(buf, buflen, "cpu:///%s=%u/%s=%llX", FM_FMRI_CPU_ID, 64 cpuid, FM_FMRI_CPU_SERIAL_ID, (u_longlong_t)serialid)); 65 } 66 67 static int 68 cpu_get_serialid_kstat(uint32_t cpuid, uint64_t *serialidp) 69 { 70 kstat_named_t *kn; 71 kstat_ctl_t *kc; 72 kstat_t *ksp; 73 int i; 74 75 if ((kc = kstat_open()) == NULL) /* XXX commonify */ 76 return (-1); /* errno is set for us */ 77 78 if ((ksp = kstat_lookup(kc, "cpu_info", cpuid, NULL)) == NULL) { 79 (void) kstat_close(kc); 80 return (fmd_fmri_set_errno(ENOENT)); 81 } 82 83 if (kstat_read(kc, ksp, NULL) == -1) { 84 int oserr = errno; 85 (void) kstat_close(kc); 86 return (fmd_fmri_set_errno(oserr)); 87 } 88 89 for (kn = ksp->ks_data, i = 0; i < ksp->ks_ndata; i++, kn++) { 90 if (strcmp(kn->name, "device_ID") == 0) { 91 *serialidp = kn->value.ui64; 92 (void) kstat_close(kc); 93 return (0); 94 } 95 } 96 97 (void) kstat_close(kc); 98 99 return (fmd_fmri_set_errno(ENOENT)); 100 } 101 102 static int 103 cpu_get_serialid(uint32_t cpuid, uint64_t *serialidp) 104 { 105 #ifdef sparc 106 if (cpu.cpu_mdesc_cpus != NULL) 107 return (cpu_get_serialid_mdesc(cpuid, serialidp)); 108 else 109 #endif /* sparc */ 110 return (cpu_get_serialid_kstat(cpuid, serialidp)); 111 } 112 113 int 114 fmd_fmri_expand(nvlist_t *nvl) 115 { 116 uint8_t version; 117 uint32_t cpuid; 118 uint64_t serialid; 119 int rc; 120 121 if (nvlist_lookup_uint8(nvl, FM_VERSION, &version) != 0 || 122 version > FM_CPU_SCHEME_VERSION || 123 nvlist_lookup_uint32(nvl, FM_FMRI_CPU_ID, &cpuid) != 0) 124 return (fmd_fmri_set_errno(EINVAL)); 125 126 if ((rc = nvlist_lookup_uint64(nvl, FM_FMRI_CPU_SERIAL_ID, 127 &serialid)) == 0) 128 return (0); /* fmri is already expanded */ 129 else if (rc != ENOENT) 130 return (fmd_fmri_set_errno(rc)); 131 132 if (cpu_get_serialid(cpuid, &serialid) != 0) 133 return (-1); /* errno is set for us */ 134 135 if ((rc = nvlist_add_uint64(nvl, FM_FMRI_CPU_SERIAL_ID, serialid)) != 0) 136 return (fmd_fmri_set_errno(rc)); 137 138 return (0); 139 } 140 141 int 142 fmd_fmri_present(nvlist_t *nvl) 143 { 144 uint8_t version; 145 uint32_t cpuid; 146 uint64_t nvlserid, curserid; 147 148 if (nvlist_lookup_uint8(nvl, FM_VERSION, &version) != 0 || 149 version > FM_CPU_SCHEME_VERSION || 150 nvlist_lookup_uint32(nvl, FM_FMRI_CPU_ID, &cpuid) != 0 || 151 nvlist_lookup_uint64(nvl, FM_FMRI_CPU_SERIAL_ID, &nvlserid) != 0) 152 return (fmd_fmri_set_errno(EINVAL)); 153 154 if (cpu_get_serialid(cpuid, &curserid) != 0) 155 return (errno == ENOENT ? 0 : -1); 156 157 return (curserid == nvlserid); 158 } 159 160 int 161 fmd_fmri_unusable(nvlist_t *nvl) 162 { 163 uint8_t version; 164 uint32_t cpuid; 165 166 if (nvlist_lookup_uint8(nvl, FM_VERSION, &version) != 0 || 167 version > FM_CPU_SCHEME_VERSION || 168 nvlist_lookup_uint32(nvl, FM_FMRI_CPU_ID, &cpuid) != 0) 169 return (fmd_fmri_set_errno(EINVAL)); 170 else 171 return (p_online(cpuid, P_STATUS) == P_FAULTED); 172 } 173 174 #ifdef sparc 175 int 176 fmd_fmri_init(void) 177 { 178 bzero(&cpu, sizeof (cpu_t)); 179 return (cpu_mdesc_init()); 180 } 181 182 void 183 fmd_fmri_fini(void) 184 { 185 cpu_mdesc_fini(); 186 } 187 #endif /* sparc */ 188