Print this page
7127 remove -Wno-missing-braces from Makefile.uts
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/intel/io/ucode_drv.c
+++ new/usr/src/uts/intel/io/ucode_drv.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 25 */
26 26
27 27 #include <sys/types.h>
28 28 #include <sys/file.h>
29 29 #include <sys/errno.h>
30 30 #include <sys/open.h>
31 31 #include <sys/cred.h>
32 32 #include <sys/conf.h>
33 33 #include <sys/stat.h>
34 34 #include <sys/policy.h>
35 35 #include <sys/processor.h>
36 36 #include <sys/kmem.h>
37 37 #include <sys/modctl.h>
38 38 #include <sys/ddi.h>
39 39 #include <sys/sunddi.h>
40 40
41 41 #include <sys/auxv.h>
42 42 #include <sys/ucode.h>
43 43 #include <sys/systeminfo.h>
44 44 #include <sys/x86_archext.h>
45 45
46 46 static dev_info_t *ucode_devi;
47 47 static uint32_t ucode_max_combined_size;
48 48 static kmutex_t ucode_update_lock;
49 49
50 50 /*ARGSUSED*/
51 51 static int
52 52 ucode_getinfo(dev_info_t *devi, ddi_info_cmd_t cmd, void *arg, void **result)
53 53 {
54 54 switch (cmd) {
55 55 case DDI_INFO_DEVT2DEVINFO:
56 56 case DDI_INFO_DEVT2INSTANCE:
57 57 break;
58 58 default:
59 59 return (DDI_FAILURE);
60 60 }
61 61
62 62 switch (getminor((dev_t)arg)) {
63 63 case UCODE_MINOR:
64 64 break;
65 65 default:
66 66 return (DDI_FAILURE);
67 67 }
68 68
69 69 if (cmd == DDI_INFO_DEVT2INSTANCE)
70 70 *result = 0;
71 71 else
72 72 *result = ucode_devi;
73 73 return (DDI_SUCCESS);
74 74 }
75 75
76 76 static int
77 77 ucode_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
78 78 {
79 79 ASSERT(cmd != DDI_RESUME);
80 80
81 81 switch (cmd) {
82 82 case DDI_RESUME:
83 83 return (DDI_SUCCESS);
84 84
85 85 case DDI_ATTACH:
86 86 ucode_devi = devi;
87 87 ucode_max_combined_size = UCODE_MAX_COMBINED_SIZE;
88 88
89 89 if (ddi_create_minor_node(devi, UCODE_NODE_NAME, S_IFCHR,
90 90 UCODE_MINOR, DDI_PSEUDO, 0) != DDI_SUCCESS) {
91 91 cmn_err(CE_WARN, "%s: Unable to create minor node",
92 92 UCODE_NODE_NAME);
93 93 return (DDI_FAILURE);
94 94 }
95 95 ddi_report_dev(devi);
96 96 return (DDI_SUCCESS);
97 97
98 98 default:
99 99 return (DDI_FAILURE);
100 100 }
101 101 }
102 102
103 103 static int
104 104 ucode_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
105 105 {
106 106 /*
107 107 * The power management and DR framework should never invoke this
108 108 * driver with DDI_SUSPEND because the ucode pseudo device does not
109 109 * have a reg property or hardware binding. However, we will return
110 110 * DDI_SUCCESS so that in the unlikely event that it does get
111 111 * called, the system will still suspend and resume.
112 112 */
113 113 ASSERT(cmd != DDI_SUSPEND);
114 114
115 115 switch (cmd) {
116 116 case DDI_SUSPEND:
117 117 return (DDI_SUCCESS);
118 118
119 119 case DDI_DETACH:
120 120 ddi_remove_minor_node(devi, NULL);
121 121 ucode_devi = NULL;
122 122 return (DDI_SUCCESS);
123 123
124 124 default:
125 125 return (DDI_FAILURE);
126 126 }
127 127 }
128 128
129 129 /*ARGSUSED1*/
130 130 static int
131 131 ucode_open(dev_t *dev, int flag, int otyp, cred_t *cr)
132 132 {
133 133 return (getminor(*dev) == UCODE_MINOR ? 0 : ENXIO);
134 134 }
135 135
136 136
137 137 /*ARGSUSED*/
138 138 static int
139 139 ucode_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *cr, int *rval)
140 140 {
141 141 /*
142 142 * Make sure that the ucode ops pointer has been set up.
143 143 */
144 144 if (!ucode)
145 145 return (EIO);
146 146
147 147 switch (cmd) {
148 148 case UCODE_GET_VERSION: {
149 149 int size;
150 150 uint32_t *revp, *rev_array;
151 151 size_t bufsz = NCPU * sizeof (*revp);
152 152 ucode_errno_t rc = EM_OK;
153 153
154 154 STRUCT_DECL(ucode_get_rev_struct, h);
155 155 STRUCT_INIT(h, mode);
156 156 if (ddi_copyin((void *)arg,
157 157 STRUCT_BUF(h), STRUCT_SIZE(h), mode))
158 158 return (EFAULT);
159 159
160 160 if ((size = STRUCT_FGET(h, ugv_size)) > NCPU || size < 0)
161 161 return (EINVAL);
162 162
163 163 if (size == 0)
164 164 return (0);
165 165
166 166 if ((rev_array = STRUCT_FGETP(h, ugv_rev)) == NULL)
167 167 return (EINVAL);
168 168
169 169 size *= sizeof (uint32_t);
170 170
171 171 /* Can't rely on caller for kernel's buffer size. */
172 172 revp = kmem_zalloc(bufsz, KM_SLEEP);
173 173 if (ddi_copyin((void *)rev_array, revp, size, mode) != 0) {
174 174 kmem_free(revp, bufsz);
175 175 return (EINVAL);
176 176 }
177 177
178 178 rc = ucode_get_rev(revp);
179 179
180 180 STRUCT_FSET(h, ugv_errno, rc);
181 181
182 182 if (ddi_copyout(revp, (void *)rev_array, size, mode) != 0) {
183 183 kmem_free(revp, bufsz);
184 184 return (EFAULT);
185 185 }
186 186
187 187 kmem_free(revp, bufsz);
188 188
189 189 if (ddi_copyout(STRUCT_BUF(h), (void *)arg,
190 190 STRUCT_SIZE(h), mode))
191 191 return (EFAULT);
192 192
193 193 return (0);
194 194 }
195 195
196 196 case UCODE_UPDATE: {
197 197 int size;
198 198 uint8_t *ucodep, *uw_ucode;
199 199 ucode_errno_t rc = EM_OK;
200 200
201 201 /*
202 202 * Requires all privilege.
203 203 */
204 204 if (cr && secpolicy_ucode_update(cr))
205 205 return (EPERM);
206 206
207 207 STRUCT_DECL(ucode_write_struct, h);
208 208
209 209 STRUCT_INIT(h, mode);
210 210 if (ddi_copyin((void *)arg, STRUCT_BUF(h), STRUCT_SIZE(h),
211 211 mode))
212 212 return (EFAULT);
213 213
214 214 /*
215 215 * We allow the size of the combined microcode file to be up to
216 216 * ucode_max_combined_size. It is initialized to
217 217 * UCODE_MAX_COMBINED_SIZE, and can be patched if necessary.
218 218 */
219 219 size = STRUCT_FGET(h, uw_size);
220 220 if (size > ucode_max_combined_size || size == 0)
221 221 return (EINVAL);
222 222
223 223 if ((uw_ucode = STRUCT_FGETP(h, uw_ucode)) == NULL)
224 224 return (EINVAL);
225 225
226 226 ucodep = kmem_zalloc(size, KM_SLEEP);
227 227 if (ddi_copyin((void *)uw_ucode, ucodep, size, mode) != 0) {
228 228 kmem_free(ucodep, size);
229 229 return (EFAULT);
230 230 }
231 231
232 232 if ((rc = ucode->validate(ucodep, size)) != EM_OK) {
233 233 kmem_free(ucodep, size);
234 234 STRUCT_FSET(h, uw_errno, rc);
235 235 if (ddi_copyout(STRUCT_BUF(h), (void *)arg,
236 236 STRUCT_SIZE(h), mode))
237 237 return (EFAULT);
238 238 return (0);
239 239 }
240 240
241 241 mutex_enter(&ucode_update_lock);
242 242 rc = ucode_update(ucodep, size);
243 243 mutex_exit(&ucode_update_lock);
244 244
245 245 kmem_free(ucodep, size);
246 246
247 247 STRUCT_FSET(h, uw_errno, rc);
248 248 if (ddi_copyout(STRUCT_BUF(h), (void *)arg,
249 249 STRUCT_SIZE(h), mode))
250 250 return (EFAULT);
251 251
252 252 /*
253 253 * Even if rc is not EM_OK, it is a successful operation
254 254 * from ioctl()'s perspective. We return the detailed error
255 255 * code via the ucode_write_struct data structure.
256 256 */
257 257 return (0);
258 258 }
259 259
260 260
261 261 default:
262 262 return (ENOTTY);
263 263 }
264 264 }
265 265
266 266 static struct cb_ops ucode_cb_ops = {
267 267 ucode_open,
268 268 nulldev, /* close */
269 269 nodev, /* strategy */
270 270 nodev, /* print */
271 271 nodev, /* dump */
272 272 nodev, /* read */
273 273 nodev, /* write */
274 274 ucode_ioctl,
275 275 nodev, /* devmap */
276 276 nodev, /* mmap */
277 277 nodev, /* segmap */
278 278 nochpoll, /* poll */
279 279 ddi_prop_op,
280 280 NULL,
281 281 D_64BIT | D_NEW | D_MP
282 282 };
283 283
284 284 static struct dev_ops ucode_dv_ops = {
285 285 DEVO_REV,
286 286 0,
287 287 ucode_getinfo,
288 288 nulldev, /* identify */
289 289 nulldev, /* probe */
290 290 ucode_attach,
291 291 ucode_detach,
292 292 nodev, /* reset */
293 293 &ucode_cb_ops,
294 294 (struct bus_ops *)0,
295 295 NULL, /* power */
296 296 ddi_quiesce_not_needed, /* quiesce */
↓ open down ↓ |
296 lines elided |
↑ open up ↑ |
297 297 };
298 298
299 299 static struct modldrv modldrv = {
300 300 &mod_driverops,
301 301 "ucode driver",
302 302 &ucode_dv_ops
303 303 };
304 304
305 305 static struct modlinkage modl = {
306 306 MODREV_1,
307 - &modldrv
307 + { &modldrv, NULL }
308 308 };
309 309
310 310 int
311 311 _init(void)
312 312 {
313 313 int rc;
314 314
315 315 if ((rc = mod_install(&modl)) != 0)
316 316 return (rc);
317 317
318 318 mutex_init(&ucode_update_lock, NULL, MUTEX_DRIVER, NULL);
319 319
320 320 return (0);
321 321 }
322 322
323 323 int
324 324 _fini(void)
325 325 {
326 326 int rc;
327 327
328 328 if ((rc = mod_remove(&modl)) != 0)
329 329 return (rc);
330 330
331 331 mutex_destroy(&ucode_update_lock);
332 332
333 333 return (0);
334 334 }
335 335
336 336 int
337 337 _info(struct modinfo *modinfo)
338 338 {
339 339 return (mod_info(&modl, modinfo));
340 340 }
↓ open down ↓ |
23 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX