xref: /illumos-gate/usr/src/cmd/fm/schemes/cpu/cpu.c (revision cc6c5292fa8a241fe50604cf6a918edfbf7cd7d2)
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