Print this page
5047 don't use atomic_*_nv if you discard the return value
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/i86pc/os/cmi_hw.c
+++ new/usr/src/uts/i86pc/os/cmi_hw.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 (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
24 24 */
25 25 /*
26 26 * Copyright (c) 2010, Intel Corporation.
27 27 * All rights reserved.
28 28 */
29 29
30 30 /*
31 31 * CPU Module Interface - hardware abstraction.
32 32 */
33 33
34 34 #ifdef __xpv
35 35 #include <sys/xpv_user.h>
36 36 #endif
37 37
38 38 #include <sys/types.h>
39 39 #include <sys/cpu_module.h>
40 40 #include <sys/kmem.h>
41 41 #include <sys/x86_archext.h>
42 42 #include <sys/cpuvar.h>
43 43 #include <sys/ksynch.h>
44 44 #include <sys/x_call.h>
45 45 #include <sys/pghw.h>
46 46 #include <sys/pci_cfgacc.h>
47 47 #include <sys/pci_cfgspace.h>
48 48 #include <sys/archsystm.h>
49 49 #include <sys/ontrap.h>
50 50 #include <sys/controlregs.h>
51 51 #include <sys/sunddi.h>
52 52 #include <sys/trap.h>
53 53 #include <sys/mca_x86.h>
54 54 #include <sys/processor.h>
55 55 #include <sys/cmn_err.h>
56 56 #include <sys/nvpair.h>
57 57 #include <sys/fm/util.h>
58 58 #include <sys/fm/protocol.h>
59 59 #include <sys/fm/smb/fmsmb.h>
60 60 #include <sys/cpu_module_impl.h>
61 61
62 62 /*
63 63 * Variable which determines if the SMBIOS supports x86 generic topology; or
64 64 * if legacy topolgy enumeration will occur.
65 65 */
66 66 extern int x86gentopo_legacy;
67 67
68 68 /*
69 69 * Outside of this file consumers use the opaque cmi_hdl_t. This
70 70 * definition is duplicated in the generic_cpu mdb module, so keep
71 71 * them in-sync when making changes.
72 72 */
73 73 typedef struct cmi_hdl_impl {
74 74 enum cmi_hdl_class cmih_class; /* Handle nature */
75 75 const struct cmi_hdl_ops *cmih_ops; /* Operations vector */
76 76 uint_t cmih_chipid; /* Chipid of cpu resource */
77 77 uint_t cmih_procnodeid; /* Nodeid of cpu resource */
78 78 uint_t cmih_coreid; /* Core within die */
79 79 uint_t cmih_strandid; /* Thread within core */
80 80 uint_t cmih_procnodes_per_pkg; /* Nodes in a processor */
81 81 boolean_t cmih_mstrand; /* cores are multithreaded */
82 82 volatile uint32_t *cmih_refcntp; /* Reference count pointer */
83 83 uint64_t cmih_msrsrc; /* MSR data source flags */
84 84 void *cmih_hdlpriv; /* cmi_hw.c private data */
85 85 void *cmih_spec; /* cmi_hdl_{set,get}_specific */
86 86 void *cmih_cmi; /* cpu mod control structure */
87 87 void *cmih_cmidata; /* cpu mod private data */
88 88 const struct cmi_mc_ops *cmih_mcops; /* Memory-controller ops */
89 89 void *cmih_mcdata; /* Memory-controller data */
90 90 uint64_t cmih_flags; /* See CMIH_F_* below */
91 91 uint16_t cmih_smbiosid; /* SMBIOS Type 4 struct ID */
92 92 uint_t cmih_smb_chipid; /* SMBIOS factored chipid */
93 93 nvlist_t *cmih_smb_bboard; /* SMBIOS bboard nvlist */
94 94 } cmi_hdl_impl_t;
95 95
96 96 #define IMPLHDL(ophdl) ((cmi_hdl_impl_t *)ophdl)
97 97 #define HDLOPS(hdl) ((hdl)->cmih_ops)
98 98
99 99 #define CMIH_F_INJACTV 0x1ULL
100 100 #define CMIH_F_DEAD 0x2ULL
101 101
102 102 /*
103 103 * Ops structure for handle operations.
104 104 */
105 105 struct cmi_hdl_ops {
106 106 /*
107 107 * These ops are required in an implementation.
108 108 */
109 109 uint_t (*cmio_vendor)(cmi_hdl_impl_t *);
110 110 const char *(*cmio_vendorstr)(cmi_hdl_impl_t *);
111 111 uint_t (*cmio_family)(cmi_hdl_impl_t *);
112 112 uint_t (*cmio_model)(cmi_hdl_impl_t *);
113 113 uint_t (*cmio_stepping)(cmi_hdl_impl_t *);
114 114 uint_t (*cmio_chipid)(cmi_hdl_impl_t *);
115 115 uint_t (*cmio_procnodeid)(cmi_hdl_impl_t *);
116 116 uint_t (*cmio_coreid)(cmi_hdl_impl_t *);
117 117 uint_t (*cmio_strandid)(cmi_hdl_impl_t *);
118 118 uint_t (*cmio_procnodes_per_pkg)(cmi_hdl_impl_t *);
119 119 uint_t (*cmio_strand_apicid)(cmi_hdl_impl_t *);
120 120 uint32_t (*cmio_chiprev)(cmi_hdl_impl_t *);
121 121 const char *(*cmio_chiprevstr)(cmi_hdl_impl_t *);
122 122 uint32_t (*cmio_getsockettype)(cmi_hdl_impl_t *);
123 123 const char *(*cmio_getsocketstr)(cmi_hdl_impl_t *);
124 124
125 125 id_t (*cmio_logical_id)(cmi_hdl_impl_t *);
126 126 /*
127 127 * These ops are optional in an implementation.
128 128 */
129 129 ulong_t (*cmio_getcr4)(cmi_hdl_impl_t *);
130 130 void (*cmio_setcr4)(cmi_hdl_impl_t *, ulong_t);
131 131 cmi_errno_t (*cmio_rdmsr)(cmi_hdl_impl_t *, uint_t, uint64_t *);
132 132 cmi_errno_t (*cmio_wrmsr)(cmi_hdl_impl_t *, uint_t, uint64_t);
133 133 cmi_errno_t (*cmio_msrinterpose)(cmi_hdl_impl_t *, uint_t, uint64_t);
134 134 void (*cmio_int)(cmi_hdl_impl_t *, int);
135 135 int (*cmio_online)(cmi_hdl_impl_t *, int, int *);
136 136 uint16_t (*cmio_smbiosid) (cmi_hdl_impl_t *);
137 137 uint_t (*cmio_smb_chipid)(cmi_hdl_impl_t *);
138 138 nvlist_t *(*cmio_smb_bboard)(cmi_hdl_impl_t *);
139 139 };
140 140
141 141 static const struct cmi_hdl_ops cmi_hdl_ops;
142 142
143 143 /*
144 144 * Handles are looked up from contexts such as polling, injection etc
145 145 * where the context is reasonably well defined (although a poller could
146 146 * interrupt any old thread holding any old lock). They are also looked
147 147 * up by machine check handlers, which may strike at inconvenient times
148 148 * such as during handle initialization or destruction or during handle
149 149 * lookup (which the #MC handler itself will also have to perform).
150 150 *
151 151 * So keeping handles in a linked list makes locking difficult when we
152 152 * consider #MC handlers. Our solution is to have a look-up table indexed
153 153 * by that which uniquely identifies a handle - chip/core/strand id -
154 154 * with each entry a structure including a pointer to a handle
155 155 * structure for the resource, and a reference count for the handle.
156 156 * Reference counts are modified atomically. The public cmi_hdl_hold
157 157 * always succeeds because this can only be used after handle creation
158 158 * and before the call to destruct, so the hold count is already at least one.
159 159 * In other functions that lookup a handle (cmi_hdl_lookup, cmi_hdl_any)
160 160 * we must be certain that the count has not already decrmented to zero
161 161 * before applying our hold.
162 162 *
163 163 * The table is an array of maximum number of chips defined in
164 164 * CMI_CHIPID_ARR_SZ indexed by the chip id. If the chip is not present, the
165 165 * entry is NULL. Each entry is a pointer to another array which contains a
166 166 * list of all strands of the chip. This first level table is allocated when
167 167 * first we want to populate an entry. The size of the latter (per chip) table
168 168 * is CMI_MAX_STRANDS_PER_CHIP and it is populated when one of its cpus starts.
169 169 *
170 170 * Ideally we should only allocate to the actual number of chips, cores per
171 171 * chip and strand per core. The number of chips is not available until all
172 172 * of them are passed. The number of cores and strands are partially available.
173 173 * For now we stick with the above approach.
174 174 */
175 175 #define CMI_MAX_CHIPID_NBITS 6 /* max chipid of 63 */
176 176 #define CMI_MAX_CORES_PER_CHIP_NBITS 4 /* 16 cores per chip max */
177 177 #define CMI_MAX_STRANDS_PER_CORE_NBITS 3 /* 8 strands per core max */
178 178
179 179 #define CMI_MAX_CHIPID ((1 << (CMI_MAX_CHIPID_NBITS)) - 1)
180 180 #define CMI_MAX_CORES_PER_CHIP(cbits) (1 << (cbits))
181 181 #define CMI_MAX_COREID(cbits) ((1 << (cbits)) - 1)
182 182 #define CMI_MAX_STRANDS_PER_CORE(sbits) (1 << (sbits))
183 183 #define CMI_MAX_STRANDID(sbits) ((1 << (sbits)) - 1)
184 184 #define CMI_MAX_STRANDS_PER_CHIP(cbits, sbits) \
185 185 (CMI_MAX_CORES_PER_CHIP(cbits) * CMI_MAX_STRANDS_PER_CORE(sbits))
186 186
187 187 #define CMI_CHIPID_ARR_SZ (1 << CMI_MAX_CHIPID_NBITS)
188 188
189 189 typedef struct cmi_hdl_ent {
190 190 volatile uint32_t cmae_refcnt;
191 191 cmi_hdl_impl_t *cmae_hdlp;
192 192 } cmi_hdl_ent_t;
193 193
194 194 static cmi_hdl_ent_t *cmi_chip_tab[CMI_CHIPID_ARR_SZ];
195 195
196 196 /*
197 197 * Default values for the number of core and strand bits.
198 198 */
199 199 uint_t cmi_core_nbits = CMI_MAX_CORES_PER_CHIP_NBITS;
200 200 uint_t cmi_strand_nbits = CMI_MAX_STRANDS_PER_CORE_NBITS;
201 201 static int cmi_ext_topo_check = 0;
202 202
203 203 /*
204 204 * Controls where we will source PCI config space data.
205 205 */
206 206 #define CMI_PCICFG_FLAG_RD_HWOK 0x0001
207 207 #define CMI_PCICFG_FLAG_RD_INTERPOSEOK 0X0002
208 208 #define CMI_PCICFG_FLAG_WR_HWOK 0x0004
209 209 #define CMI_PCICFG_FLAG_WR_INTERPOSEOK 0X0008
210 210
211 211 static uint64_t cmi_pcicfg_flags =
212 212 CMI_PCICFG_FLAG_RD_HWOK | CMI_PCICFG_FLAG_RD_INTERPOSEOK |
213 213 CMI_PCICFG_FLAG_WR_HWOK | CMI_PCICFG_FLAG_WR_INTERPOSEOK;
214 214
215 215 /*
216 216 * The flags for individual cpus are kept in their per-cpu handle cmih_msrsrc
217 217 */
218 218 #define CMI_MSR_FLAG_RD_HWOK 0x0001
219 219 #define CMI_MSR_FLAG_RD_INTERPOSEOK 0x0002
220 220 #define CMI_MSR_FLAG_WR_HWOK 0x0004
221 221 #define CMI_MSR_FLAG_WR_INTERPOSEOK 0x0008
222 222
223 223 int cmi_call_func_ntv_tries = 3;
224 224
225 225 static cmi_errno_t
226 226 call_func_ntv(int cpuid, xc_func_t func, xc_arg_t arg1, xc_arg_t arg2)
227 227 {
228 228 cmi_errno_t rc = -1;
229 229 int i;
230 230
231 231 kpreempt_disable();
232 232
233 233 if (CPU->cpu_id == cpuid) {
234 234 (*func)(arg1, arg2, (xc_arg_t)&rc);
235 235 } else {
236 236 /*
237 237 * This should not happen for a #MC trap or a poll, so
238 238 * this is likely an error injection or similar.
239 239 * We will try to cross call with xc_trycall - we
240 240 * can't guarantee success with xc_call because
241 241 * the interrupt code in the case of a #MC may
242 242 * already hold the xc mutex.
243 243 */
244 244 for (i = 0; i < cmi_call_func_ntv_tries; i++) {
245 245 cpuset_t cpus;
246 246
247 247 CPUSET_ONLY(cpus, cpuid);
248 248 xc_priority(arg1, arg2, (xc_arg_t)&rc,
249 249 CPUSET2BV(cpus), func);
250 250 if (rc != -1)
251 251 break;
252 252
253 253 DELAY(1);
254 254 }
255 255 }
256 256
257 257 kpreempt_enable();
258 258
259 259 return (rc != -1 ? rc : CMIERR_DEADLOCK);
260 260 }
261 261
262 262 static uint64_t injcnt;
263 263
264 264 void
265 265 cmi_hdl_inj_begin(cmi_hdl_t ophdl)
266 266 {
267 267 cmi_hdl_impl_t *hdl = IMPLHDL(ophdl);
268 268
269 269 if (hdl != NULL)
270 270 hdl->cmih_flags |= CMIH_F_INJACTV;
271 271 if (injcnt++ == 0) {
272 272 cmn_err(CE_NOTE, "Hardware error injection/simulation "
273 273 "activity noted");
274 274 }
275 275 }
276 276
277 277 void
278 278 cmi_hdl_inj_end(cmi_hdl_t ophdl)
279 279 {
280 280 cmi_hdl_impl_t *hdl = IMPLHDL(ophdl);
281 281
282 282 ASSERT(hdl == NULL || hdl->cmih_flags & CMIH_F_INJACTV);
283 283 if (hdl != NULL)
284 284 hdl->cmih_flags &= ~CMIH_F_INJACTV;
285 285 }
286 286
287 287 boolean_t
288 288 cmi_inj_tainted(void)
289 289 {
290 290 return (injcnt != 0 ? B_TRUE : B_FALSE);
291 291 }
292 292
293 293 /*
294 294 * =======================================================
295 295 * | MSR Interposition |
296 296 * | ----------------- |
297 297 * | |
298 298 * -------------------------------------------------------
299 299 */
300 300
301 301 #define CMI_MSRI_HASHSZ 16
302 302 #define CMI_MSRI_HASHIDX(hdl, msr) \
303 303 (((uintptr_t)(hdl) >> 3 + (msr)) % (CMI_MSRI_HASHSZ - 1))
304 304
305 305 struct cmi_msri_bkt {
306 306 kmutex_t msrib_lock;
307 307 struct cmi_msri_hashent *msrib_head;
308 308 };
309 309
310 310 struct cmi_msri_hashent {
311 311 struct cmi_msri_hashent *msrie_next;
312 312 struct cmi_msri_hashent *msrie_prev;
313 313 cmi_hdl_impl_t *msrie_hdl;
314 314 uint_t msrie_msrnum;
315 315 uint64_t msrie_msrval;
316 316 };
317 317
318 318 #define CMI_MSRI_MATCH(ent, hdl, req_msr) \
319 319 ((ent)->msrie_hdl == (hdl) && (ent)->msrie_msrnum == (req_msr))
320 320
321 321 static struct cmi_msri_bkt msrihash[CMI_MSRI_HASHSZ];
322 322
323 323 static void
324 324 msri_addent(cmi_hdl_impl_t *hdl, uint_t msr, uint64_t val)
325 325 {
326 326 int idx = CMI_MSRI_HASHIDX(hdl, msr);
327 327 struct cmi_msri_bkt *hbp = &msrihash[idx];
328 328 struct cmi_msri_hashent *hep;
329 329
330 330 mutex_enter(&hbp->msrib_lock);
331 331
332 332 for (hep = hbp->msrib_head; hep != NULL; hep = hep->msrie_next) {
333 333 if (CMI_MSRI_MATCH(hep, hdl, msr))
334 334 break;
335 335 }
336 336
337 337 if (hep != NULL) {
338 338 hep->msrie_msrval = val;
339 339 } else {
340 340 hep = kmem_alloc(sizeof (*hep), KM_SLEEP);
341 341 hep->msrie_hdl = hdl;
342 342 hep->msrie_msrnum = msr;
343 343 hep->msrie_msrval = val;
344 344
345 345 if (hbp->msrib_head != NULL)
346 346 hbp->msrib_head->msrie_prev = hep;
347 347 hep->msrie_next = hbp->msrib_head;
348 348 hep->msrie_prev = NULL;
349 349 hbp->msrib_head = hep;
350 350 }
351 351
352 352 mutex_exit(&hbp->msrib_lock);
353 353 }
354 354
355 355 /*
356 356 * Look for a match for the given hanlde and msr. Return 1 with valp
357 357 * filled if a match is found, otherwise return 0 with valp untouched.
358 358 */
359 359 static int
360 360 msri_lookup(cmi_hdl_impl_t *hdl, uint_t msr, uint64_t *valp)
361 361 {
362 362 int idx = CMI_MSRI_HASHIDX(hdl, msr);
363 363 struct cmi_msri_bkt *hbp = &msrihash[idx];
364 364 struct cmi_msri_hashent *hep;
365 365
366 366 /*
367 367 * This function is called during #MC trap handling, so we should
368 368 * consider the possibility that the hash mutex is held by the
369 369 * interrupted thread. This should not happen because interposition
370 370 * is an artificial injection mechanism and the #MC is requested
371 371 * after adding entries, but just in case of a real #MC at an
372 372 * unlucky moment we'll use mutex_tryenter here.
373 373 */
374 374 if (!mutex_tryenter(&hbp->msrib_lock))
375 375 return (0);
376 376
377 377 for (hep = hbp->msrib_head; hep != NULL; hep = hep->msrie_next) {
378 378 if (CMI_MSRI_MATCH(hep, hdl, msr)) {
379 379 *valp = hep->msrie_msrval;
380 380 break;
381 381 }
382 382 }
383 383
384 384 mutex_exit(&hbp->msrib_lock);
385 385
386 386 return (hep != NULL);
387 387 }
388 388
389 389 /*
390 390 * Remove any interposed value that matches.
391 391 */
392 392 static void
393 393 msri_rment(cmi_hdl_impl_t *hdl, uint_t msr)
394 394 {
395 395
396 396 int idx = CMI_MSRI_HASHIDX(hdl, msr);
397 397 struct cmi_msri_bkt *hbp = &msrihash[idx];
398 398 struct cmi_msri_hashent *hep;
399 399
400 400 if (!mutex_tryenter(&hbp->msrib_lock))
401 401 return;
402 402
403 403 for (hep = hbp->msrib_head; hep != NULL; hep = hep->msrie_next) {
404 404 if (CMI_MSRI_MATCH(hep, hdl, msr)) {
405 405 if (hep->msrie_prev != NULL)
406 406 hep->msrie_prev->msrie_next = hep->msrie_next;
407 407
408 408 if (hep->msrie_next != NULL)
409 409 hep->msrie_next->msrie_prev = hep->msrie_prev;
410 410
411 411 if (hbp->msrib_head == hep)
412 412 hbp->msrib_head = hep->msrie_next;
413 413
414 414 kmem_free(hep, sizeof (*hep));
415 415 break;
416 416 }
417 417 }
418 418
419 419 mutex_exit(&hbp->msrib_lock);
420 420 }
421 421
422 422 /*
423 423 * =======================================================
424 424 * | PCI Config Space Interposition |
425 425 * | ------------------------------ |
426 426 * | |
427 427 * -------------------------------------------------------
428 428 */
429 429
430 430 /*
431 431 * Hash for interposed PCI config space values. We lookup on bus/dev/fun/offset
432 432 * and then record whether the value stashed was made with a byte, word or
433 433 * doubleword access; we will only return a hit for an access of the
434 434 * same size. If you access say a 32-bit register using byte accesses
435 435 * and then attempt to read the full 32-bit value back you will not obtain
436 436 * any sort of merged result - you get a lookup miss.
437 437 */
438 438
439 439 #define CMI_PCII_HASHSZ 16
440 440 #define CMI_PCII_HASHIDX(b, d, f, o) \
441 441 (((b) + (d) + (f) + (o)) % (CMI_PCII_HASHSZ - 1))
442 442
443 443 struct cmi_pcii_bkt {
444 444 kmutex_t pciib_lock;
445 445 struct cmi_pcii_hashent *pciib_head;
446 446 };
447 447
448 448 struct cmi_pcii_hashent {
449 449 struct cmi_pcii_hashent *pcii_next;
450 450 struct cmi_pcii_hashent *pcii_prev;
451 451 int pcii_bus;
452 452 int pcii_dev;
453 453 int pcii_func;
454 454 int pcii_reg;
455 455 int pcii_asize;
456 456 uint32_t pcii_val;
457 457 };
458 458
459 459 #define CMI_PCII_MATCH(ent, b, d, f, r, asz) \
460 460 ((ent)->pcii_bus == (b) && (ent)->pcii_dev == (d) && \
461 461 (ent)->pcii_func == (f) && (ent)->pcii_reg == (r) && \
462 462 (ent)->pcii_asize == (asz))
463 463
464 464 static struct cmi_pcii_bkt pciihash[CMI_PCII_HASHSZ];
465 465
466 466
467 467 /*
468 468 * Add a new entry to the PCI interpose hash, overwriting any existing
469 469 * entry that is found.
470 470 */
471 471 static void
472 472 pcii_addent(int bus, int dev, int func, int reg, uint32_t val, int asz)
473 473 {
474 474 int idx = CMI_PCII_HASHIDX(bus, dev, func, reg);
475 475 struct cmi_pcii_bkt *hbp = &pciihash[idx];
476 476 struct cmi_pcii_hashent *hep;
477 477
478 478 cmi_hdl_inj_begin(NULL);
479 479
480 480 mutex_enter(&hbp->pciib_lock);
481 481
482 482 for (hep = hbp->pciib_head; hep != NULL; hep = hep->pcii_next) {
483 483 if (CMI_PCII_MATCH(hep, bus, dev, func, reg, asz))
484 484 break;
485 485 }
486 486
487 487 if (hep != NULL) {
488 488 hep->pcii_val = val;
489 489 } else {
490 490 hep = kmem_alloc(sizeof (*hep), KM_SLEEP);
491 491 hep->pcii_bus = bus;
492 492 hep->pcii_dev = dev;
493 493 hep->pcii_func = func;
494 494 hep->pcii_reg = reg;
495 495 hep->pcii_asize = asz;
496 496 hep->pcii_val = val;
497 497
498 498 if (hbp->pciib_head != NULL)
499 499 hbp->pciib_head->pcii_prev = hep;
500 500 hep->pcii_next = hbp->pciib_head;
501 501 hep->pcii_prev = NULL;
502 502 hbp->pciib_head = hep;
503 503 }
504 504
505 505 mutex_exit(&hbp->pciib_lock);
506 506
507 507 cmi_hdl_inj_end(NULL);
508 508 }
509 509
510 510 /*
511 511 * Look for a match for the given bus/dev/func/reg; return 1 with valp
512 512 * filled if a match is found, otherwise return 0 with valp untouched.
513 513 */
514 514 static int
515 515 pcii_lookup(int bus, int dev, int func, int reg, int asz, uint32_t *valp)
516 516 {
517 517 int idx = CMI_PCII_HASHIDX(bus, dev, func, reg);
518 518 struct cmi_pcii_bkt *hbp = &pciihash[idx];
519 519 struct cmi_pcii_hashent *hep;
520 520
521 521 if (!mutex_tryenter(&hbp->pciib_lock))
522 522 return (0);
523 523
524 524 for (hep = hbp->pciib_head; hep != NULL; hep = hep->pcii_next) {
525 525 if (CMI_PCII_MATCH(hep, bus, dev, func, reg, asz)) {
526 526 *valp = hep->pcii_val;
527 527 break;
528 528 }
529 529 }
530 530
531 531 mutex_exit(&hbp->pciib_lock);
532 532
533 533 return (hep != NULL);
534 534 }
535 535
536 536 static void
537 537 pcii_rment(int bus, int dev, int func, int reg, int asz)
538 538 {
539 539 int idx = CMI_PCII_HASHIDX(bus, dev, func, reg);
540 540 struct cmi_pcii_bkt *hbp = &pciihash[idx];
541 541 struct cmi_pcii_hashent *hep;
542 542
543 543 mutex_enter(&hbp->pciib_lock);
544 544
545 545 for (hep = hbp->pciib_head; hep != NULL; hep = hep->pcii_next) {
546 546 if (CMI_PCII_MATCH(hep, bus, dev, func, reg, asz)) {
547 547 if (hep->pcii_prev != NULL)
548 548 hep->pcii_prev->pcii_next = hep->pcii_next;
549 549
550 550 if (hep->pcii_next != NULL)
551 551 hep->pcii_next->pcii_prev = hep->pcii_prev;
552 552
553 553 if (hbp->pciib_head == hep)
554 554 hbp->pciib_head = hep->pcii_next;
555 555
556 556 kmem_free(hep, sizeof (*hep));
557 557 break;
558 558 }
559 559 }
560 560
561 561 mutex_exit(&hbp->pciib_lock);
562 562 }
563 563
564 564 #ifndef __xpv
565 565
566 566 /*
567 567 * =======================================================
568 568 * | Native methods |
569 569 * | -------------- |
570 570 * | |
571 571 * | These are used when we are running native on bare- |
572 572 * | metal, or simply don't know any better. |
573 573 * ---------------------------------------------------------
574 574 */
575 575
576 576 #define HDLPRIV(hdl) ((cpu_t *)(hdl)->cmih_hdlpriv)
577 577
578 578 static uint_t
579 579 ntv_vendor(cmi_hdl_impl_t *hdl)
580 580 {
581 581 return (cpuid_getvendor(HDLPRIV(hdl)));
582 582 }
583 583
584 584 static const char *
585 585 ntv_vendorstr(cmi_hdl_impl_t *hdl)
586 586 {
587 587 return (cpuid_getvendorstr(HDLPRIV(hdl)));
588 588 }
589 589
590 590 static uint_t
591 591 ntv_family(cmi_hdl_impl_t *hdl)
592 592 {
593 593 return (cpuid_getfamily(HDLPRIV(hdl)));
594 594 }
595 595
596 596 static uint_t
597 597 ntv_model(cmi_hdl_impl_t *hdl)
598 598 {
599 599 return (cpuid_getmodel(HDLPRIV(hdl)));
600 600 }
601 601
602 602 static uint_t
603 603 ntv_stepping(cmi_hdl_impl_t *hdl)
604 604 {
605 605 return (cpuid_getstep(HDLPRIV(hdl)));
606 606 }
607 607
608 608 static uint_t
609 609 ntv_chipid(cmi_hdl_impl_t *hdl)
610 610 {
611 611 return (hdl->cmih_chipid);
612 612
613 613 }
614 614
615 615 static uint_t
616 616 ntv_procnodeid(cmi_hdl_impl_t *hdl)
617 617 {
618 618 return (hdl->cmih_procnodeid);
619 619 }
620 620
621 621 static uint_t
622 622 ntv_procnodes_per_pkg(cmi_hdl_impl_t *hdl)
623 623 {
624 624 return (hdl->cmih_procnodes_per_pkg);
625 625 }
626 626
627 627 static uint_t
628 628 ntv_coreid(cmi_hdl_impl_t *hdl)
629 629 {
630 630 return (hdl->cmih_coreid);
631 631 }
632 632
633 633 static uint_t
634 634 ntv_strandid(cmi_hdl_impl_t *hdl)
635 635 {
636 636 return (hdl->cmih_strandid);
637 637 }
638 638
639 639 static uint_t
640 640 ntv_strand_apicid(cmi_hdl_impl_t *hdl)
641 641 {
642 642 return (cpuid_get_apicid(HDLPRIV(hdl)));
643 643 }
644 644
645 645 static uint16_t
646 646 ntv_smbiosid(cmi_hdl_impl_t *hdl)
647 647 {
648 648 return (hdl->cmih_smbiosid);
649 649 }
650 650
651 651 static uint_t
652 652 ntv_smb_chipid(cmi_hdl_impl_t *hdl)
653 653 {
654 654 return (hdl->cmih_smb_chipid);
655 655 }
656 656
657 657 static nvlist_t *
658 658 ntv_smb_bboard(cmi_hdl_impl_t *hdl)
659 659 {
660 660 return (hdl->cmih_smb_bboard);
661 661 }
662 662
663 663 static uint32_t
664 664 ntv_chiprev(cmi_hdl_impl_t *hdl)
665 665 {
666 666 return (cpuid_getchiprev(HDLPRIV(hdl)));
667 667 }
668 668
669 669 static const char *
670 670 ntv_chiprevstr(cmi_hdl_impl_t *hdl)
671 671 {
672 672 return (cpuid_getchiprevstr(HDLPRIV(hdl)));
673 673 }
674 674
675 675 static uint32_t
676 676 ntv_getsockettype(cmi_hdl_impl_t *hdl)
677 677 {
678 678 return (cpuid_getsockettype(HDLPRIV(hdl)));
679 679 }
680 680
681 681 static const char *
682 682 ntv_getsocketstr(cmi_hdl_impl_t *hdl)
683 683 {
684 684 return (cpuid_getsocketstr(HDLPRIV(hdl)));
685 685 }
686 686
687 687 static id_t
688 688 ntv_logical_id(cmi_hdl_impl_t *hdl)
689 689 {
690 690 return (HDLPRIV(hdl)->cpu_id);
691 691 }
692 692
693 693 /*ARGSUSED*/
694 694 static int
695 695 ntv_getcr4_xc(xc_arg_t arg1, xc_arg_t arg2, xc_arg_t arg3)
696 696 {
697 697 ulong_t *dest = (ulong_t *)arg1;
698 698 cmi_errno_t *rcp = (cmi_errno_t *)arg3;
699 699
700 700 *dest = getcr4();
701 701 *rcp = CMI_SUCCESS;
702 702
703 703 return (0);
704 704 }
705 705
706 706 static ulong_t
707 707 ntv_getcr4(cmi_hdl_impl_t *hdl)
708 708 {
709 709 cpu_t *cp = HDLPRIV(hdl);
710 710 ulong_t val;
711 711
712 712 (void) call_func_ntv(cp->cpu_id, ntv_getcr4_xc, (xc_arg_t)&val, NULL);
713 713
714 714 return (val);
715 715 }
716 716
717 717 /*ARGSUSED*/
718 718 static int
719 719 ntv_setcr4_xc(xc_arg_t arg1, xc_arg_t arg2, xc_arg_t arg3)
720 720 {
721 721 ulong_t val = (ulong_t)arg1;
722 722 cmi_errno_t *rcp = (cmi_errno_t *)arg3;
723 723
724 724 setcr4(val);
725 725 *rcp = CMI_SUCCESS;
726 726
727 727 return (0);
728 728 }
729 729
730 730 static void
731 731 ntv_setcr4(cmi_hdl_impl_t *hdl, ulong_t val)
732 732 {
733 733 cpu_t *cp = HDLPRIV(hdl);
734 734
735 735 (void) call_func_ntv(cp->cpu_id, ntv_setcr4_xc, (xc_arg_t)val, NULL);
736 736 }
737 737
738 738 volatile uint32_t cmi_trapped_rdmsr;
739 739
740 740 /*ARGSUSED*/
741 741 static int
742 742 ntv_rdmsr_xc(xc_arg_t arg1, xc_arg_t arg2, xc_arg_t arg3)
743 743 {
744 744 uint_t msr = (uint_t)arg1;
745 745 uint64_t *valp = (uint64_t *)arg2;
746 746 cmi_errno_t *rcp = (cmi_errno_t *)arg3;
747 747
748 748 on_trap_data_t otd;
749 749
750 750 if (on_trap(&otd, OT_DATA_ACCESS) == 0) {
751 751 if (checked_rdmsr(msr, valp) == 0)
752 752 *rcp = CMI_SUCCESS;
753 753 else
754 754 *rcp = CMIERR_NOTSUP;
755 755 } else {
756 756 *rcp = CMIERR_MSRGPF;
757 757 atomic_inc_32(&cmi_trapped_rdmsr);
758 758 }
759 759 no_trap();
760 760
761 761 return (0);
762 762 }
763 763
764 764 static cmi_errno_t
765 765 ntv_rdmsr(cmi_hdl_impl_t *hdl, uint_t msr, uint64_t *valp)
766 766 {
767 767 cpu_t *cp = HDLPRIV(hdl);
768 768
769 769 if (!(hdl->cmih_msrsrc & CMI_MSR_FLAG_RD_HWOK))
770 770 return (CMIERR_INTERPOSE);
771 771
772 772 return (call_func_ntv(cp->cpu_id, ntv_rdmsr_xc,
773 773 (xc_arg_t)msr, (xc_arg_t)valp));
774 774 }
775 775
776 776 volatile uint32_t cmi_trapped_wrmsr;
777 777
778 778 /*ARGSUSED*/
779 779 static int
780 780 ntv_wrmsr_xc(xc_arg_t arg1, xc_arg_t arg2, xc_arg_t arg3)
781 781 {
782 782 uint_t msr = (uint_t)arg1;
783 783 uint64_t val = *((uint64_t *)arg2);
784 784 cmi_errno_t *rcp = (cmi_errno_t *)arg3;
785 785 on_trap_data_t otd;
786 786
787 787 if (on_trap(&otd, OT_DATA_ACCESS) == 0) {
788 788 if (checked_wrmsr(msr, val) == 0)
789 789 *rcp = CMI_SUCCESS;
790 790 else
791 791 *rcp = CMIERR_NOTSUP;
792 792 } else {
793 793 *rcp = CMIERR_MSRGPF;
794 794 atomic_inc_32(&cmi_trapped_wrmsr);
795 795 }
796 796 no_trap();
797 797
798 798 return (0);
799 799
800 800 }
801 801
802 802 static cmi_errno_t
803 803 ntv_wrmsr(cmi_hdl_impl_t *hdl, uint_t msr, uint64_t val)
804 804 {
805 805 cpu_t *cp = HDLPRIV(hdl);
806 806
807 807 if (!(hdl->cmih_msrsrc & CMI_MSR_FLAG_WR_HWOK))
808 808 return (CMI_SUCCESS);
809 809
810 810 return (call_func_ntv(cp->cpu_id, ntv_wrmsr_xc,
811 811 (xc_arg_t)msr, (xc_arg_t)&val));
812 812 }
813 813
814 814 static cmi_errno_t
815 815 ntv_msrinterpose(cmi_hdl_impl_t *hdl, uint_t msr, uint64_t val)
816 816 {
817 817 msri_addent(hdl, msr, val);
818 818 return (CMI_SUCCESS);
819 819 }
820 820
821 821 /*ARGSUSED*/
822 822 static int
823 823 ntv_int_xc(xc_arg_t arg1, xc_arg_t arg2, xc_arg_t arg3)
824 824 {
825 825 cmi_errno_t *rcp = (cmi_errno_t *)arg3;
826 826 int int_no = (int)arg1;
827 827
828 828 if (int_no == T_MCE)
829 829 int18();
830 830 else
831 831 int_cmci();
832 832 *rcp = CMI_SUCCESS;
833 833
834 834 return (0);
835 835 }
836 836
837 837 static void
838 838 ntv_int(cmi_hdl_impl_t *hdl, int int_no)
839 839 {
840 840 cpu_t *cp = HDLPRIV(hdl);
841 841
842 842 (void) call_func_ntv(cp->cpu_id, ntv_int_xc, (xc_arg_t)int_no, NULL);
843 843 }
844 844
845 845 static int
846 846 ntv_online(cmi_hdl_impl_t *hdl, int new_status, int *old_status)
847 847 {
848 848 int rc;
849 849 processorid_t cpuid = HDLPRIV(hdl)->cpu_id;
850 850
851 851 while (mutex_tryenter(&cpu_lock) == 0) {
852 852 if (hdl->cmih_flags & CMIH_F_DEAD)
853 853 return (EBUSY);
854 854 delay(1);
855 855 }
856 856 rc = p_online_internal_locked(cpuid, new_status, old_status);
857 857 mutex_exit(&cpu_lock);
858 858
859 859 return (rc);
860 860 }
861 861
862 862 #else /* __xpv */
863 863
864 864 /*
865 865 * =======================================================
866 866 * | xVM dom0 methods |
867 867 * | ---------------- |
868 868 * | |
869 869 * | These are used when we are running as dom0 in |
870 870 * | a Solaris xVM context. |
871 871 * ---------------------------------------------------------
872 872 */
873 873
874 874 #define HDLPRIV(hdl) ((xen_mc_lcpu_cookie_t)(hdl)->cmih_hdlpriv)
875 875
876 876 extern uint_t _cpuid_vendorstr_to_vendorcode(char *);
877 877
878 878
879 879 static uint_t
880 880 xpv_vendor(cmi_hdl_impl_t *hdl)
881 881 {
882 882 return (_cpuid_vendorstr_to_vendorcode((char *)xen_physcpu_vendorstr(
883 883 HDLPRIV(hdl))));
884 884 }
885 885
886 886 static const char *
887 887 xpv_vendorstr(cmi_hdl_impl_t *hdl)
888 888 {
889 889 return (xen_physcpu_vendorstr(HDLPRIV(hdl)));
890 890 }
891 891
892 892 static uint_t
893 893 xpv_family(cmi_hdl_impl_t *hdl)
894 894 {
895 895 return (xen_physcpu_family(HDLPRIV(hdl)));
896 896 }
897 897
898 898 static uint_t
899 899 xpv_model(cmi_hdl_impl_t *hdl)
900 900 {
901 901 return (xen_physcpu_model(HDLPRIV(hdl)));
902 902 }
903 903
904 904 static uint_t
905 905 xpv_stepping(cmi_hdl_impl_t *hdl)
906 906 {
907 907 return (xen_physcpu_stepping(HDLPRIV(hdl)));
908 908 }
909 909
910 910 static uint_t
911 911 xpv_chipid(cmi_hdl_impl_t *hdl)
912 912 {
913 913 return (hdl->cmih_chipid);
914 914 }
915 915
916 916 static uint_t
917 917 xpv_procnodeid(cmi_hdl_impl_t *hdl)
918 918 {
919 919 return (hdl->cmih_procnodeid);
920 920 }
921 921
922 922 static uint_t
923 923 xpv_procnodes_per_pkg(cmi_hdl_impl_t *hdl)
924 924 {
925 925 return (hdl->cmih_procnodes_per_pkg);
926 926 }
927 927
928 928 static uint_t
929 929 xpv_coreid(cmi_hdl_impl_t *hdl)
930 930 {
931 931 return (hdl->cmih_coreid);
932 932 }
933 933
934 934 static uint_t
935 935 xpv_strandid(cmi_hdl_impl_t *hdl)
936 936 {
937 937 return (hdl->cmih_strandid);
938 938 }
939 939
940 940 static uint_t
941 941 xpv_strand_apicid(cmi_hdl_impl_t *hdl)
942 942 {
943 943 return (xen_physcpu_initial_apicid(HDLPRIV(hdl)));
944 944 }
945 945
946 946 static uint16_t
947 947 xpv_smbiosid(cmi_hdl_impl_t *hdl)
948 948 {
949 949 return (hdl->cmih_smbiosid);
950 950 }
951 951
952 952 static uint_t
953 953 xpv_smb_chipid(cmi_hdl_impl_t *hdl)
954 954 {
955 955 return (hdl->cmih_smb_chipid);
956 956 }
957 957
958 958 static nvlist_t *
959 959 xpv_smb_bboard(cmi_hdl_impl_t *hdl)
960 960 {
961 961 return (hdl->cmih_smb_bboard);
962 962 }
963 963
964 964 extern uint32_t _cpuid_chiprev(uint_t, uint_t, uint_t, uint_t);
965 965
966 966 static uint32_t
967 967 xpv_chiprev(cmi_hdl_impl_t *hdl)
968 968 {
969 969 return (_cpuid_chiprev(xpv_vendor(hdl), xpv_family(hdl),
970 970 xpv_model(hdl), xpv_stepping(hdl)));
971 971 }
972 972
973 973 extern const char *_cpuid_chiprevstr(uint_t, uint_t, uint_t, uint_t);
974 974
975 975 static const char *
976 976 xpv_chiprevstr(cmi_hdl_impl_t *hdl)
977 977 {
978 978 return (_cpuid_chiprevstr(xpv_vendor(hdl), xpv_family(hdl),
979 979 xpv_model(hdl), xpv_stepping(hdl)));
980 980 }
981 981
982 982 extern uint32_t _cpuid_skt(uint_t, uint_t, uint_t, uint_t);
983 983
984 984 static uint32_t
985 985 xpv_getsockettype(cmi_hdl_impl_t *hdl)
986 986 {
987 987 return (_cpuid_skt(xpv_vendor(hdl), xpv_family(hdl),
988 988 xpv_model(hdl), xpv_stepping(hdl)));
989 989 }
990 990
991 991 extern const char *_cpuid_sktstr(uint_t, uint_t, uint_t, uint_t);
992 992
993 993 static const char *
994 994 xpv_getsocketstr(cmi_hdl_impl_t *hdl)
995 995 {
996 996 return (_cpuid_sktstr(xpv_vendor(hdl), xpv_family(hdl),
997 997 xpv_model(hdl), xpv_stepping(hdl)));
998 998 }
999 999
1000 1000 static id_t
1001 1001 xpv_logical_id(cmi_hdl_impl_t *hdl)
1002 1002 {
1003 1003 return (xen_physcpu_logical_id(HDLPRIV(hdl)));
1004 1004 }
1005 1005
1006 1006 static cmi_errno_t
1007 1007 xpv_rdmsr(cmi_hdl_impl_t *hdl, uint_t msr, uint64_t *valp)
1008 1008 {
1009 1009 switch (msr) {
1010 1010 case IA32_MSR_MCG_CAP:
1011 1011 *valp = xen_physcpu_mcg_cap(HDLPRIV(hdl));
1012 1012 break;
1013 1013
1014 1014 default:
1015 1015 return (CMIERR_NOTSUP);
1016 1016 }
1017 1017
1018 1018 return (CMI_SUCCESS);
1019 1019 }
1020 1020
1021 1021 /*
1022 1022 * Request the hypervisor to write an MSR for us. The hypervisor
1023 1023 * will only accept MCA-related MSRs, as this is for MCA error
1024 1024 * simulation purposes alone. We will pre-screen MSRs for injection
1025 1025 * so we don't bother the HV with bogus requests. We will permit
1026 1026 * injection to any MCA bank register, and to MCG_STATUS.
1027 1027 */
1028 1028
1029 1029 #define IS_MCA_INJ_MSR(msr) \
1030 1030 (((msr) >= IA32_MSR_MC(0, CTL) && (msr) <= IA32_MSR_MC(10, MISC)) || \
1031 1031 (msr) == IA32_MSR_MCG_STATUS)
1032 1032
1033 1033 static cmi_errno_t
1034 1034 xpv_wrmsr_cmn(cmi_hdl_impl_t *hdl, uint_t msr, uint64_t val, boolean_t intpose)
1035 1035 {
1036 1036 xen_mc_t xmc;
1037 1037 struct xen_mc_msrinject *mci = &xmc.u.mc_msrinject;
1038 1038
1039 1039 if (!(hdl->cmih_flags & CMIH_F_INJACTV))
1040 1040 return (CMIERR_NOTSUP); /* for injection use only! */
1041 1041
1042 1042 if (!IS_MCA_INJ_MSR(msr))
1043 1043 return (CMIERR_API);
1044 1044
1045 1045 if (panicstr)
1046 1046 return (CMIERR_DEADLOCK);
1047 1047
1048 1048 mci->mcinj_cpunr = xen_physcpu_logical_id(HDLPRIV(hdl));
1049 1049 mci->mcinj_flags = intpose ? MC_MSRINJ_F_INTERPOSE : 0;
1050 1050 mci->mcinj_count = 1; /* learn to batch sometime */
1051 1051 mci->mcinj_msr[0].reg = msr;
1052 1052 mci->mcinj_msr[0].value = val;
1053 1053
1054 1054 return (HYPERVISOR_mca(XEN_MC_msrinject, &xmc) ==
1055 1055 0 ? CMI_SUCCESS : CMIERR_NOTSUP);
1056 1056 }
1057 1057
1058 1058 static cmi_errno_t
1059 1059 xpv_wrmsr(cmi_hdl_impl_t *hdl, uint_t msr, uint64_t val)
1060 1060 {
1061 1061 return (xpv_wrmsr_cmn(hdl, msr, val, B_FALSE));
1062 1062 }
1063 1063
1064 1064
1065 1065 static cmi_errno_t
1066 1066 xpv_msrinterpose(cmi_hdl_impl_t *hdl, uint_t msr, uint64_t val)
1067 1067 {
1068 1068 return (xpv_wrmsr_cmn(hdl, msr, val, B_TRUE));
1069 1069 }
1070 1070
1071 1071 static void
1072 1072 xpv_int(cmi_hdl_impl_t *hdl, int int_no)
1073 1073 {
1074 1074 xen_mc_t xmc;
1075 1075 struct xen_mc_mceinject *mce = &xmc.u.mc_mceinject;
1076 1076
1077 1077 if (!(hdl->cmih_flags & CMIH_F_INJACTV))
1078 1078 return;
1079 1079
1080 1080 if (int_no != T_MCE) {
1081 1081 cmn_err(CE_WARN, "xpv_int: int_no %d unimplemented\n",
1082 1082 int_no);
1083 1083 }
1084 1084
1085 1085 mce->mceinj_cpunr = xen_physcpu_logical_id(HDLPRIV(hdl));
1086 1086
1087 1087 (void) HYPERVISOR_mca(XEN_MC_mceinject, &xmc);
1088 1088 }
1089 1089
1090 1090 static int
1091 1091 xpv_online(cmi_hdl_impl_t *hdl, int new_status, int *old_status)
1092 1092 {
1093 1093 xen_sysctl_t xs;
1094 1094 int op, rc, status;
1095 1095
1096 1096 new_status &= ~P_FORCED;
1097 1097
1098 1098 switch (new_status) {
1099 1099 case P_STATUS:
1100 1100 op = XEN_SYSCTL_CPU_HOTPLUG_STATUS;
1101 1101 break;
1102 1102 case P_FAULTED:
1103 1103 case P_OFFLINE:
1104 1104 op = XEN_SYSCTL_CPU_HOTPLUG_OFFLINE;
1105 1105 break;
1106 1106 case P_ONLINE:
1107 1107 op = XEN_SYSCTL_CPU_HOTPLUG_ONLINE;
1108 1108 break;
1109 1109 default:
1110 1110 return (-1);
1111 1111 }
1112 1112
1113 1113 xs.cmd = XEN_SYSCTL_cpu_hotplug;
1114 1114 xs.interface_version = XEN_SYSCTL_INTERFACE_VERSION;
1115 1115 xs.u.cpu_hotplug.cpu = xen_physcpu_logical_id(HDLPRIV(hdl));
1116 1116 xs.u.cpu_hotplug.op = op;
1117 1117
1118 1118 if ((rc = HYPERVISOR_sysctl(&xs)) >= 0) {
1119 1119 status = rc;
1120 1120 rc = 0;
1121 1121 switch (status) {
1122 1122 case XEN_CPU_HOTPLUG_STATUS_NEW:
1123 1123 *old_status = P_OFFLINE;
1124 1124 break;
1125 1125 case XEN_CPU_HOTPLUG_STATUS_OFFLINE:
1126 1126 *old_status = P_FAULTED;
1127 1127 break;
1128 1128 case XEN_CPU_HOTPLUG_STATUS_ONLINE:
1129 1129 *old_status = P_ONLINE;
1130 1130 break;
1131 1131 default:
1132 1132 return (-1);
1133 1133 }
1134 1134 }
1135 1135
1136 1136 return (-rc);
1137 1137 }
1138 1138
1139 1139 #endif
1140 1140
1141 1141 /*ARGSUSED*/
1142 1142 static void *
1143 1143 cpu_search(enum cmi_hdl_class class, uint_t chipid, uint_t coreid,
1144 1144 uint_t strandid)
1145 1145 {
1146 1146 #ifdef __xpv
1147 1147 xen_mc_lcpu_cookie_t cpi;
1148 1148
1149 1149 for (cpi = xen_physcpu_next(NULL); cpi != NULL;
1150 1150 cpi = xen_physcpu_next(cpi)) {
1151 1151 if (xen_physcpu_chipid(cpi) == chipid &&
1152 1152 xen_physcpu_coreid(cpi) == coreid &&
1153 1153 xen_physcpu_strandid(cpi) == strandid)
1154 1154 return ((void *)cpi);
1155 1155 }
1156 1156 return (NULL);
1157 1157
1158 1158 #else /* __xpv */
1159 1159
1160 1160 cpu_t *cp, *startcp;
1161 1161
1162 1162 kpreempt_disable();
1163 1163 cp = startcp = CPU;
1164 1164 do {
1165 1165 if (cmi_ntv_hwchipid(cp) == chipid &&
1166 1166 cmi_ntv_hwcoreid(cp) == coreid &&
1167 1167 cmi_ntv_hwstrandid(cp) == strandid) {
1168 1168 kpreempt_enable();
1169 1169 return ((void *)cp);
1170 1170 }
1171 1171
1172 1172 cp = cp->cpu_next;
1173 1173 } while (cp != startcp);
1174 1174 kpreempt_enable();
1175 1175 return (NULL);
1176 1176 #endif /* __ xpv */
1177 1177 }
1178 1178
1179 1179 static boolean_t
1180 1180 cpu_is_cmt(void *priv)
1181 1181 {
1182 1182 #ifdef __xpv
1183 1183 return (xen_physcpu_is_cmt((xen_mc_lcpu_cookie_t)priv));
1184 1184 #else /* __xpv */
1185 1185 cpu_t *cp = (cpu_t *)priv;
1186 1186
1187 1187 int strands_per_core = cpuid_get_ncpu_per_chip(cp) /
1188 1188 cpuid_get_ncore_per_chip(cp);
1189 1189
1190 1190 return (strands_per_core > 1);
1191 1191 #endif /* __xpv */
1192 1192 }
1193 1193
1194 1194 /*
1195 1195 * Find the handle entry of a given cpu identified by a <chip,core,strand>
1196 1196 * tuple.
1197 1197 */
1198 1198 static cmi_hdl_ent_t *
1199 1199 cmi_hdl_ent_lookup(uint_t chipid, uint_t coreid, uint_t strandid)
1200 1200 {
1201 1201 int max_strands = CMI_MAX_STRANDS_PER_CHIP(cmi_core_nbits,
1202 1202 cmi_strand_nbits);
1203 1203
1204 1204 /*
1205 1205 * Allocate per-chip table which contains a list of handle of
1206 1206 * all strands of the chip.
1207 1207 */
1208 1208 if (cmi_chip_tab[chipid] == NULL) {
1209 1209 size_t sz;
1210 1210 cmi_hdl_ent_t *pg;
1211 1211
1212 1212 sz = max_strands * sizeof (cmi_hdl_ent_t);
1213 1213 pg = kmem_zalloc(sz, KM_SLEEP);
1214 1214
1215 1215 /* test and set the per-chip table if it is not allocated */
1216 1216 if (atomic_cas_ptr(&cmi_chip_tab[chipid], NULL, pg) != NULL)
1217 1217 kmem_free(pg, sz); /* someone beats us */
1218 1218 }
1219 1219
1220 1220 return (cmi_chip_tab[chipid] +
1221 1221 ((((coreid) & CMI_MAX_COREID(cmi_core_nbits)) << cmi_strand_nbits) |
1222 1222 ((strandid) & CMI_MAX_STRANDID(cmi_strand_nbits))));
1223 1223 }
1224 1224
1225 1225 extern void cpuid_get_ext_topo(uint_t, uint_t *, uint_t *);
1226 1226
1227 1227 cmi_hdl_t
1228 1228 cmi_hdl_create(enum cmi_hdl_class class, uint_t chipid, uint_t coreid,
1229 1229 uint_t strandid)
1230 1230 {
1231 1231 cmi_hdl_impl_t *hdl;
1232 1232 void *priv;
1233 1233 cmi_hdl_ent_t *ent;
1234 1234 uint_t vendor;
1235 1235
1236 1236 #ifdef __xpv
1237 1237 ASSERT(class == CMI_HDL_SOLARIS_xVM_MCA);
1238 1238 #else
1239 1239 ASSERT(class == CMI_HDL_NATIVE);
1240 1240 #endif
1241 1241
1242 1242 if ((priv = cpu_search(class, chipid, coreid, strandid)) == NULL)
1243 1243 return (NULL);
1244 1244
1245 1245 /*
1246 1246 * Assume all chips in the system are the same type.
1247 1247 * For Intel, attempt to check if extended topology is available
1248 1248 * CPUID.EAX=0xB. If so, get the number of core and strand bits.
1249 1249 */
1250 1250 #ifdef __xpv
1251 1251 vendor = _cpuid_vendorstr_to_vendorcode(
1252 1252 (char *)xen_physcpu_vendorstr((xen_mc_lcpu_cookie_t)priv));
1253 1253 #else
1254 1254 vendor = cpuid_getvendor((cpu_t *)priv);
1255 1255 #endif
1256 1256 if (vendor == X86_VENDOR_Intel && cmi_ext_topo_check == 0) {
1257 1257 cpuid_get_ext_topo(vendor, &cmi_core_nbits, &cmi_strand_nbits);
1258 1258 cmi_ext_topo_check = 1;
1259 1259 }
1260 1260
1261 1261 if (chipid > CMI_MAX_CHIPID ||
1262 1262 coreid > CMI_MAX_COREID(cmi_core_nbits) ||
1263 1263 strandid > CMI_MAX_STRANDID(cmi_strand_nbits))
1264 1264 return (NULL);
1265 1265
1266 1266 hdl = kmem_zalloc(sizeof (*hdl), KM_SLEEP);
1267 1267
1268 1268 hdl->cmih_class = class;
1269 1269 HDLOPS(hdl) = &cmi_hdl_ops;
1270 1270 hdl->cmih_chipid = chipid;
1271 1271 hdl->cmih_coreid = coreid;
1272 1272 hdl->cmih_strandid = strandid;
1273 1273 hdl->cmih_mstrand = cpu_is_cmt(priv);
1274 1274 hdl->cmih_hdlpriv = priv;
1275 1275 #ifdef __xpv
1276 1276 hdl->cmih_msrsrc = CMI_MSR_FLAG_RD_INTERPOSEOK |
1277 1277 CMI_MSR_FLAG_WR_INTERPOSEOK;
1278 1278
1279 1279 /*
1280 1280 * XXX: need hypervisor support for procnodeid, for now assume
1281 1281 * single-node processors (procnodeid = chipid)
1282 1282 */
1283 1283 hdl->cmih_procnodeid = xen_physcpu_chipid((xen_mc_lcpu_cookie_t)priv);
1284 1284 hdl->cmih_procnodes_per_pkg = 1;
1285 1285 #else /* __xpv */
1286 1286 hdl->cmih_msrsrc = CMI_MSR_FLAG_RD_HWOK | CMI_MSR_FLAG_RD_INTERPOSEOK |
1287 1287 CMI_MSR_FLAG_WR_HWOK | CMI_MSR_FLAG_WR_INTERPOSEOK;
1288 1288 hdl->cmih_procnodeid = cpuid_get_procnodeid((cpu_t *)priv);
1289 1289 hdl->cmih_procnodes_per_pkg =
1290 1290 cpuid_get_procnodes_per_pkg((cpu_t *)priv);
1291 1291 #endif /* __xpv */
1292 1292
1293 1293 ent = cmi_hdl_ent_lookup(chipid, coreid, strandid);
1294 1294 if (ent->cmae_refcnt != 0 || ent->cmae_hdlp != NULL) {
1295 1295 /*
1296 1296 * Somehow this (chipid, coreid, strandid) id tuple has
1297 1297 * already been assigned! This indicates that the
1298 1298 * callers logic in determining these values is busted,
1299 1299 * or perhaps undermined by bad BIOS setup. Complain,
1300 1300 * and refuse to initialize this tuple again as bad things
1301 1301 * will happen.
1302 1302 */
1303 1303 cmn_err(CE_NOTE, "cmi_hdl_create: chipid %d coreid %d "
1304 1304 "strandid %d handle already allocated!",
1305 1305 chipid, coreid, strandid);
1306 1306 kmem_free(hdl, sizeof (*hdl));
1307 1307 return (NULL);
1308 1308 }
1309 1309
1310 1310 /*
1311 1311 * Once we store a nonzero reference count others can find this
1312 1312 * handle via cmi_hdl_lookup etc. This initial hold on the handle
1313 1313 * is to be dropped only if some other part of cmi initialization
1314 1314 * fails or, if it succeeds, at later cpu deconfigure. Note the
1315 1315 * the module private data we hold in cmih_cmi and cmih_cmidata
1316 1316 * is still NULL at this point (the caller will fill it with
1317 1317 * cmi_hdl_setcmi if it initializes) so consumers of handles
1318 1318 * should always be ready for that possibility.
1319 1319 */
1320 1320 ent->cmae_hdlp = hdl;
1321 1321 hdl->cmih_refcntp = &ent->cmae_refcnt;
1322 1322 ent->cmae_refcnt = 1;
1323 1323
1324 1324 return ((cmi_hdl_t)hdl);
1325 1325 }
1326 1326
1327 1327 void
1328 1328 cmi_read_smbios(cmi_hdl_t ophdl)
1329 1329 {
1330 1330
1331 1331 uint_t strand_apicid = UINT_MAX;
1332 1332 uint_t chip_inst = UINT_MAX;
1333 1333 uint16_t smb_id = USHRT_MAX;
1334 1334 int rc = 0;
1335 1335
1336 1336 cmi_hdl_impl_t *hdl = IMPLHDL(ophdl);
1337 1337
1338 1338 /* set x86gentopo compatibility */
1339 1339 fm_smb_fmacompat();
1340 1340
1341 1341 #ifndef __xpv
1342 1342 strand_apicid = ntv_strand_apicid(hdl);
1343 1343 #else
1344 1344 strand_apicid = xpv_strand_apicid(hdl);
1345 1345 #endif
1346 1346
1347 1347 if (!x86gentopo_legacy) {
1348 1348 /*
1349 1349 * If fm_smb_chipinst() or fm_smb_bboard() fails,
1350 1350 * topo reverts to legacy mode
1351 1351 */
1352 1352 rc = fm_smb_chipinst(strand_apicid, &chip_inst, &smb_id);
1353 1353 if (rc == 0) {
1354 1354 hdl->cmih_smb_chipid = chip_inst;
1355 1355 hdl->cmih_smbiosid = smb_id;
1356 1356 } else {
1357 1357 #ifdef DEBUG
1358 1358 cmn_err(CE_NOTE, "!cmi reads smbios chip info failed");
1359 1359 #endif /* DEBUG */
1360 1360 return;
1361 1361 }
1362 1362
1363 1363 hdl->cmih_smb_bboard = fm_smb_bboard(strand_apicid);
1364 1364 #ifdef DEBUG
1365 1365 if (hdl->cmih_smb_bboard == NULL)
1366 1366 cmn_err(CE_NOTE,
1367 1367 "!cmi reads smbios base boards info failed");
1368 1368 #endif /* DEBUG */
1369 1369 }
1370 1370 }
1371 1371
1372 1372 void
1373 1373 cmi_hdl_hold(cmi_hdl_t ophdl)
1374 1374 {
1375 1375 cmi_hdl_impl_t *hdl = IMPLHDL(ophdl);
1376 1376
1377 1377 ASSERT(*hdl->cmih_refcntp != 0); /* must not be the initial hold */
1378 1378
1379 1379 atomic_inc_32(hdl->cmih_refcntp);
1380 1380 }
1381 1381
1382 1382 static int
1383 1383 cmi_hdl_canref(cmi_hdl_ent_t *ent)
1384 1384 {
1385 1385 volatile uint32_t *refcntp;
1386 1386 uint32_t refcnt;
1387 1387
1388 1388 refcntp = &ent->cmae_refcnt;
1389 1389 refcnt = *refcntp;
1390 1390
1391 1391 if (refcnt == 0) {
1392 1392 /*
1393 1393 * Associated object never existed, is being destroyed,
1394 1394 * or has been destroyed.
1395 1395 */
1396 1396 return (0);
1397 1397 }
1398 1398
1399 1399 /*
1400 1400 * We cannot use atomic increment here because once the reference
1401 1401 * count reaches zero it must never be bumped up again.
1402 1402 */
1403 1403 while (refcnt != 0) {
1404 1404 if (atomic_cas_32(refcntp, refcnt, refcnt + 1) == refcnt)
1405 1405 return (1);
1406 1406 refcnt = *refcntp;
1407 1407 }
1408 1408
1409 1409 /*
1410 1410 * Somebody dropped the reference count to 0 after our initial
1411 1411 * check.
1412 1412 */
↓ open down ↓ |
1412 lines elided |
↑ open up ↑ |
1413 1413 return (0);
1414 1414 }
1415 1415
1416 1416
1417 1417 void
1418 1418 cmi_hdl_rele(cmi_hdl_t ophdl)
1419 1419 {
1420 1420 cmi_hdl_impl_t *hdl = IMPLHDL(ophdl);
1421 1421
1422 1422 ASSERT(*hdl->cmih_refcntp > 0);
1423 - (void) atomic_dec_32_nv(hdl->cmih_refcntp);
1423 + atomic_dec_32(hdl->cmih_refcntp);
1424 1424 }
1425 1425
1426 1426 void
1427 1427 cmi_hdl_destroy(cmi_hdl_t ophdl)
1428 1428 {
1429 1429 cmi_hdl_impl_t *hdl = IMPLHDL(ophdl);
1430 1430 cmi_hdl_ent_t *ent;
1431 1431
1432 1432 /* Release the reference count held by cmi_hdl_create(). */
1433 1433 ASSERT(*hdl->cmih_refcntp > 0);
1434 - (void) atomic_dec_32_nv(hdl->cmih_refcntp);
1434 + atomic_dec_32(hdl->cmih_refcntp);
1435 1435 hdl->cmih_flags |= CMIH_F_DEAD;
1436 1436
1437 1437 ent = cmi_hdl_ent_lookup(hdl->cmih_chipid, hdl->cmih_coreid,
1438 1438 hdl->cmih_strandid);
1439 1439 /*
1440 1440 * Use busy polling instead of condition variable here because
1441 1441 * cmi_hdl_rele() may be called from #MC handler.
1442 1442 */
1443 1443 while (cmi_hdl_canref(ent)) {
1444 1444 cmi_hdl_rele(ophdl);
1445 1445 delay(1);
1446 1446 }
1447 1447 ent->cmae_hdlp = NULL;
1448 1448
1449 1449 kmem_free(hdl, sizeof (*hdl));
1450 1450 }
1451 1451
1452 1452 void
1453 1453 cmi_hdl_setspecific(cmi_hdl_t ophdl, void *arg)
1454 1454 {
1455 1455 IMPLHDL(ophdl)->cmih_spec = arg;
1456 1456 }
1457 1457
1458 1458 void *
1459 1459 cmi_hdl_getspecific(cmi_hdl_t ophdl)
1460 1460 {
1461 1461 return (IMPLHDL(ophdl)->cmih_spec);
1462 1462 }
1463 1463
1464 1464 void
1465 1465 cmi_hdl_setmc(cmi_hdl_t ophdl, const struct cmi_mc_ops *mcops, void *mcdata)
1466 1466 {
1467 1467 cmi_hdl_impl_t *hdl = IMPLHDL(ophdl);
1468 1468
1469 1469 ASSERT(hdl->cmih_mcops == NULL && hdl->cmih_mcdata == NULL);
1470 1470 hdl->cmih_mcops = mcops;
1471 1471 hdl->cmih_mcdata = mcdata;
1472 1472 }
1473 1473
1474 1474 const struct cmi_mc_ops *
1475 1475 cmi_hdl_getmcops(cmi_hdl_t ophdl)
1476 1476 {
1477 1477 return (IMPLHDL(ophdl)->cmih_mcops);
1478 1478 }
1479 1479
1480 1480 void *
1481 1481 cmi_hdl_getmcdata(cmi_hdl_t ophdl)
1482 1482 {
1483 1483 return (IMPLHDL(ophdl)->cmih_mcdata);
1484 1484 }
1485 1485
1486 1486 cmi_hdl_t
1487 1487 cmi_hdl_lookup(enum cmi_hdl_class class, uint_t chipid, uint_t coreid,
1488 1488 uint_t strandid)
1489 1489 {
1490 1490 cmi_hdl_ent_t *ent;
1491 1491
1492 1492 if (chipid > CMI_MAX_CHIPID ||
1493 1493 coreid > CMI_MAX_COREID(cmi_core_nbits) ||
1494 1494 strandid > CMI_MAX_STRANDID(cmi_strand_nbits))
1495 1495 return (NULL);
1496 1496
1497 1497 ent = cmi_hdl_ent_lookup(chipid, coreid, strandid);
1498 1498
1499 1499 if (class == CMI_HDL_NEUTRAL)
1500 1500 #ifdef __xpv
1501 1501 class = CMI_HDL_SOLARIS_xVM_MCA;
1502 1502 #else
1503 1503 class = CMI_HDL_NATIVE;
1504 1504 #endif
1505 1505
1506 1506 if (!cmi_hdl_canref(ent))
1507 1507 return (NULL);
1508 1508
1509 1509 if (ent->cmae_hdlp->cmih_class != class) {
1510 1510 cmi_hdl_rele((cmi_hdl_t)ent->cmae_hdlp);
1511 1511 return (NULL);
1512 1512 }
1513 1513
1514 1514 return ((cmi_hdl_t)ent->cmae_hdlp);
1515 1515 }
1516 1516
1517 1517 cmi_hdl_t
1518 1518 cmi_hdl_any(void)
1519 1519 {
1520 1520 int i, j;
1521 1521 cmi_hdl_ent_t *ent;
1522 1522 int max_strands = CMI_MAX_STRANDS_PER_CHIP(cmi_core_nbits,
1523 1523 cmi_strand_nbits);
1524 1524
1525 1525 for (i = 0; i < CMI_CHIPID_ARR_SZ; i++) {
1526 1526 if (cmi_chip_tab[i] == NULL)
1527 1527 continue;
1528 1528 for (j = 0, ent = cmi_chip_tab[i]; j < max_strands;
1529 1529 j++, ent++) {
1530 1530 if (cmi_hdl_canref(ent))
1531 1531 return ((cmi_hdl_t)ent->cmae_hdlp);
1532 1532 }
1533 1533 }
1534 1534
1535 1535 return (NULL);
1536 1536 }
1537 1537
1538 1538 void
1539 1539 cmi_hdl_walk(int (*cbfunc)(cmi_hdl_t, void *, void *, void *),
1540 1540 void *arg1, void *arg2, void *arg3)
1541 1541 {
1542 1542 int i, j;
1543 1543 cmi_hdl_ent_t *ent;
1544 1544 int max_strands = CMI_MAX_STRANDS_PER_CHIP(cmi_core_nbits,
1545 1545 cmi_strand_nbits);
1546 1546
1547 1547 for (i = 0; i < CMI_CHIPID_ARR_SZ; i++) {
1548 1548 if (cmi_chip_tab[i] == NULL)
1549 1549 continue;
1550 1550 for (j = 0, ent = cmi_chip_tab[i]; j < max_strands;
1551 1551 j++, ent++) {
1552 1552 if (cmi_hdl_canref(ent)) {
1553 1553 cmi_hdl_impl_t *hdl = ent->cmae_hdlp;
1554 1554 if ((*cbfunc)((cmi_hdl_t)hdl, arg1, arg2, arg3)
1555 1555 == CMI_HDL_WALK_DONE) {
1556 1556 cmi_hdl_rele((cmi_hdl_t)hdl);
1557 1557 return;
1558 1558 }
1559 1559 cmi_hdl_rele((cmi_hdl_t)hdl);
1560 1560 }
1561 1561 }
1562 1562 }
1563 1563 }
1564 1564
1565 1565 void
1566 1566 cmi_hdl_setcmi(cmi_hdl_t ophdl, void *cmi, void *cmidata)
1567 1567 {
1568 1568 IMPLHDL(ophdl)->cmih_cmidata = cmidata;
1569 1569 IMPLHDL(ophdl)->cmih_cmi = cmi;
1570 1570 }
1571 1571
1572 1572 void *
1573 1573 cmi_hdl_getcmi(cmi_hdl_t ophdl)
1574 1574 {
1575 1575 return (IMPLHDL(ophdl)->cmih_cmi);
1576 1576 }
1577 1577
1578 1578 void *
1579 1579 cmi_hdl_getcmidata(cmi_hdl_t ophdl)
1580 1580 {
1581 1581 return (IMPLHDL(ophdl)->cmih_cmidata);
1582 1582 }
1583 1583
1584 1584 enum cmi_hdl_class
1585 1585 cmi_hdl_class(cmi_hdl_t ophdl)
1586 1586 {
1587 1587 return (IMPLHDL(ophdl)->cmih_class);
1588 1588 }
1589 1589
1590 1590 #define CMI_HDL_OPFUNC(what, type) \
1591 1591 type \
1592 1592 cmi_hdl_##what(cmi_hdl_t ophdl) \
1593 1593 { \
1594 1594 return (HDLOPS(IMPLHDL(ophdl))-> \
1595 1595 cmio_##what(IMPLHDL(ophdl))); \
1596 1596 }
1597 1597
1598 1598 CMI_HDL_OPFUNC(vendor, uint_t)
1599 1599 CMI_HDL_OPFUNC(vendorstr, const char *)
1600 1600 CMI_HDL_OPFUNC(family, uint_t)
1601 1601 CMI_HDL_OPFUNC(model, uint_t)
1602 1602 CMI_HDL_OPFUNC(stepping, uint_t)
1603 1603 CMI_HDL_OPFUNC(chipid, uint_t)
1604 1604 CMI_HDL_OPFUNC(procnodeid, uint_t)
1605 1605 CMI_HDL_OPFUNC(coreid, uint_t)
1606 1606 CMI_HDL_OPFUNC(strandid, uint_t)
1607 1607 CMI_HDL_OPFUNC(procnodes_per_pkg, uint_t)
1608 1608 CMI_HDL_OPFUNC(strand_apicid, uint_t)
1609 1609 CMI_HDL_OPFUNC(chiprev, uint32_t)
1610 1610 CMI_HDL_OPFUNC(chiprevstr, const char *)
1611 1611 CMI_HDL_OPFUNC(getsockettype, uint32_t)
1612 1612 CMI_HDL_OPFUNC(getsocketstr, const char *)
1613 1613 CMI_HDL_OPFUNC(logical_id, id_t)
1614 1614 CMI_HDL_OPFUNC(smbiosid, uint16_t)
1615 1615 CMI_HDL_OPFUNC(smb_chipid, uint_t)
1616 1616 CMI_HDL_OPFUNC(smb_bboard, nvlist_t *)
1617 1617
1618 1618 boolean_t
1619 1619 cmi_hdl_is_cmt(cmi_hdl_t ophdl)
1620 1620 {
1621 1621 return (IMPLHDL(ophdl)->cmih_mstrand);
1622 1622 }
1623 1623
1624 1624 void
1625 1625 cmi_hdl_int(cmi_hdl_t ophdl, int num)
1626 1626 {
1627 1627 if (HDLOPS(IMPLHDL(ophdl))->cmio_int == NULL)
1628 1628 return;
1629 1629
1630 1630 cmi_hdl_inj_begin(ophdl);
1631 1631 HDLOPS(IMPLHDL(ophdl))->cmio_int(IMPLHDL(ophdl), num);
1632 1632 cmi_hdl_inj_end(NULL);
1633 1633 }
1634 1634
1635 1635 int
1636 1636 cmi_hdl_online(cmi_hdl_t ophdl, int new_status, int *old_status)
1637 1637 {
1638 1638 return (HDLOPS(IMPLHDL(ophdl))->cmio_online(IMPLHDL(ophdl),
1639 1639 new_status, old_status));
1640 1640 }
1641 1641
1642 1642 #ifndef __xpv
1643 1643 /*
1644 1644 * Return hardware chip instance; cpuid_get_chipid provides this directly.
1645 1645 */
1646 1646 uint_t
1647 1647 cmi_ntv_hwchipid(cpu_t *cp)
1648 1648 {
1649 1649 return (cpuid_get_chipid(cp));
1650 1650 }
1651 1651
1652 1652 /*
1653 1653 * Return hardware node instance; cpuid_get_procnodeid provides this directly.
1654 1654 */
1655 1655 uint_t
1656 1656 cmi_ntv_hwprocnodeid(cpu_t *cp)
1657 1657 {
1658 1658 return (cpuid_get_procnodeid(cp));
1659 1659 }
1660 1660
1661 1661 /*
1662 1662 * Return core instance within a single chip.
1663 1663 */
1664 1664 uint_t
1665 1665 cmi_ntv_hwcoreid(cpu_t *cp)
1666 1666 {
1667 1667 return (cpuid_get_pkgcoreid(cp));
1668 1668 }
1669 1669
1670 1670 /*
1671 1671 * Return strand number within a single core. cpuid_get_clogid numbers
1672 1672 * all execution units (strands, or cores in unstranded models) sequentially
1673 1673 * within a single chip.
1674 1674 */
1675 1675 uint_t
1676 1676 cmi_ntv_hwstrandid(cpu_t *cp)
1677 1677 {
1678 1678 int strands_per_core = cpuid_get_ncpu_per_chip(cp) /
1679 1679 cpuid_get_ncore_per_chip(cp);
1680 1680
1681 1681 return (cpuid_get_clogid(cp) % strands_per_core);
1682 1682 }
1683 1683
1684 1684 static void
1685 1685 cmi_ntv_hwdisable_mce_xc(void)
1686 1686 {
1687 1687 ulong_t cr4;
1688 1688
1689 1689 cr4 = getcr4();
1690 1690 cr4 = cr4 & (~CR4_MCE);
1691 1691 setcr4(cr4);
1692 1692 }
1693 1693
1694 1694 void
1695 1695 cmi_ntv_hwdisable_mce(cmi_hdl_t hdl)
1696 1696 {
1697 1697 cpuset_t set;
1698 1698 cmi_hdl_impl_t *thdl = IMPLHDL(hdl);
1699 1699 cpu_t *cp = HDLPRIV(thdl);
1700 1700
1701 1701 if (CPU->cpu_id == cp->cpu_id) {
1702 1702 cmi_ntv_hwdisable_mce_xc();
1703 1703 } else {
1704 1704 CPUSET_ONLY(set, cp->cpu_id);
1705 1705 xc_call(NULL, NULL, NULL, CPUSET2BV(set),
1706 1706 (xc_func_t)cmi_ntv_hwdisable_mce_xc);
1707 1707 }
1708 1708 }
1709 1709
1710 1710 #endif /* __xpv */
1711 1711
1712 1712 void
1713 1713 cmi_hdlconf_rdmsr_nohw(cmi_hdl_t ophdl)
1714 1714 {
1715 1715 cmi_hdl_impl_t *hdl = IMPLHDL(ophdl);
1716 1716
1717 1717 hdl->cmih_msrsrc &= ~CMI_MSR_FLAG_RD_HWOK;
1718 1718 }
1719 1719
1720 1720 void
1721 1721 cmi_hdlconf_wrmsr_nohw(cmi_hdl_t ophdl)
1722 1722 {
1723 1723 cmi_hdl_impl_t *hdl = IMPLHDL(ophdl);
1724 1724
1725 1725 hdl->cmih_msrsrc &= ~CMI_MSR_FLAG_WR_HWOK;
1726 1726 }
1727 1727
1728 1728 cmi_errno_t
1729 1729 cmi_hdl_rdmsr(cmi_hdl_t ophdl, uint_t msr, uint64_t *valp)
1730 1730 {
1731 1731 cmi_hdl_impl_t *hdl = IMPLHDL(ophdl);
1732 1732
1733 1733 /*
1734 1734 * Regardless of the handle class, we first check for am
1735 1735 * interposed value. In the xVM case you probably want to
1736 1736 * place interposed values within the hypervisor itself, but
1737 1737 * we still allow interposing them in dom0 for test and bringup
1738 1738 * purposes.
1739 1739 */
1740 1740 if ((hdl->cmih_msrsrc & CMI_MSR_FLAG_RD_INTERPOSEOK) &&
1741 1741 msri_lookup(hdl, msr, valp))
1742 1742 return (CMI_SUCCESS);
1743 1743
1744 1744 if (HDLOPS(hdl)->cmio_rdmsr == NULL)
1745 1745 return (CMIERR_NOTSUP);
1746 1746
1747 1747 return (HDLOPS(hdl)->cmio_rdmsr(hdl, msr, valp));
1748 1748 }
1749 1749
1750 1750 cmi_errno_t
1751 1751 cmi_hdl_wrmsr(cmi_hdl_t ophdl, uint_t msr, uint64_t val)
1752 1752 {
1753 1753 cmi_hdl_impl_t *hdl = IMPLHDL(ophdl);
1754 1754
1755 1755 /* Invalidate any interposed value */
1756 1756 msri_rment(hdl, msr);
1757 1757
1758 1758 if (HDLOPS(hdl)->cmio_wrmsr == NULL)
1759 1759 return (CMI_SUCCESS); /* pretend all is ok */
1760 1760
1761 1761 return (HDLOPS(hdl)->cmio_wrmsr(hdl, msr, val));
1762 1762 }
1763 1763
1764 1764 void
1765 1765 cmi_hdl_enable_mce(cmi_hdl_t ophdl)
1766 1766 {
1767 1767 cmi_hdl_impl_t *hdl = IMPLHDL(ophdl);
1768 1768 ulong_t cr4;
1769 1769
1770 1770 if (HDLOPS(hdl)->cmio_getcr4 == NULL ||
1771 1771 HDLOPS(hdl)->cmio_setcr4 == NULL)
1772 1772 return;
1773 1773
1774 1774 cr4 = HDLOPS(hdl)->cmio_getcr4(hdl);
1775 1775
1776 1776 HDLOPS(hdl)->cmio_setcr4(hdl, cr4 | CR4_MCE);
1777 1777 }
1778 1778
1779 1779 void
1780 1780 cmi_hdl_msrinterpose(cmi_hdl_t ophdl, cmi_mca_regs_t *regs, uint_t nregs)
1781 1781 {
1782 1782 cmi_hdl_impl_t *hdl = IMPLHDL(ophdl);
1783 1783 int i;
1784 1784
1785 1785 if (HDLOPS(hdl)->cmio_msrinterpose == NULL)
1786 1786 return;
1787 1787
1788 1788 cmi_hdl_inj_begin(ophdl);
1789 1789
1790 1790 for (i = 0; i < nregs; i++, regs++)
1791 1791 HDLOPS(hdl)->cmio_msrinterpose(hdl, regs->cmr_msrnum,
1792 1792 regs->cmr_msrval);
1793 1793
1794 1794 cmi_hdl_inj_end(ophdl);
1795 1795 }
1796 1796
1797 1797 /*ARGSUSED*/
1798 1798 void
1799 1799 cmi_hdl_msrforward(cmi_hdl_t ophdl, cmi_mca_regs_t *regs, uint_t nregs)
1800 1800 {
1801 1801 #ifdef __xpv
1802 1802 cmi_hdl_impl_t *hdl = IMPLHDL(ophdl);
1803 1803 int i;
1804 1804
1805 1805 for (i = 0; i < nregs; i++, regs++)
1806 1806 msri_addent(hdl, regs->cmr_msrnum, regs->cmr_msrval);
1807 1807 #endif
1808 1808 }
1809 1809
1810 1810
1811 1811 void
1812 1812 cmi_pcird_nohw(void)
1813 1813 {
1814 1814 cmi_pcicfg_flags &= ~CMI_PCICFG_FLAG_RD_HWOK;
1815 1815 }
1816 1816
1817 1817 void
1818 1818 cmi_pciwr_nohw(void)
1819 1819 {
1820 1820 cmi_pcicfg_flags &= ~CMI_PCICFG_FLAG_WR_HWOK;
1821 1821 }
1822 1822
1823 1823 static uint32_t
1824 1824 cmi_pci_get_cmn(int bus, int dev, int func, int reg, int asz,
1825 1825 int *interpose, ddi_acc_handle_t hdl)
1826 1826 {
1827 1827 uint32_t val;
1828 1828
1829 1829 if (cmi_pcicfg_flags & CMI_PCICFG_FLAG_RD_INTERPOSEOK &&
1830 1830 pcii_lookup(bus, dev, func, reg, asz, &val)) {
1831 1831 if (interpose)
1832 1832 *interpose = 1;
1833 1833 return (val);
1834 1834 }
1835 1835 if (interpose)
1836 1836 *interpose = 0;
1837 1837
1838 1838 if (!(cmi_pcicfg_flags & CMI_PCICFG_FLAG_RD_HWOK))
1839 1839 return (0);
1840 1840
1841 1841 switch (asz) {
1842 1842 case 1:
1843 1843 if (hdl)
1844 1844 val = pci_config_get8(hdl, (off_t)reg);
1845 1845 else
1846 1846 val = pci_cfgacc_get8(NULL, PCI_GETBDF(bus, dev, func),
1847 1847 reg);
1848 1848 break;
1849 1849 case 2:
1850 1850 if (hdl)
1851 1851 val = pci_config_get16(hdl, (off_t)reg);
1852 1852 else
1853 1853 val = pci_cfgacc_get16(NULL, PCI_GETBDF(bus, dev, func),
1854 1854 reg);
1855 1855 break;
1856 1856 case 4:
1857 1857 if (hdl)
1858 1858 val = pci_config_get32(hdl, (off_t)reg);
1859 1859 else
1860 1860 val = pci_cfgacc_get32(NULL, PCI_GETBDF(bus, dev, func),
1861 1861 reg);
1862 1862 break;
1863 1863 default:
1864 1864 val = 0;
1865 1865 }
1866 1866 return (val);
1867 1867 }
1868 1868
1869 1869 uint8_t
1870 1870 cmi_pci_getb(int bus, int dev, int func, int reg, int *interpose,
1871 1871 ddi_acc_handle_t hdl)
1872 1872 {
1873 1873 return ((uint8_t)cmi_pci_get_cmn(bus, dev, func, reg, 1, interpose,
1874 1874 hdl));
1875 1875 }
1876 1876
1877 1877 uint16_t
1878 1878 cmi_pci_getw(int bus, int dev, int func, int reg, int *interpose,
1879 1879 ddi_acc_handle_t hdl)
1880 1880 {
1881 1881 return ((uint16_t)cmi_pci_get_cmn(bus, dev, func, reg, 2, interpose,
1882 1882 hdl));
1883 1883 }
1884 1884
1885 1885 uint32_t
1886 1886 cmi_pci_getl(int bus, int dev, int func, int reg, int *interpose,
1887 1887 ddi_acc_handle_t hdl)
1888 1888 {
1889 1889 return (cmi_pci_get_cmn(bus, dev, func, reg, 4, interpose, hdl));
1890 1890 }
1891 1891
1892 1892 void
1893 1893 cmi_pci_interposeb(int bus, int dev, int func, int reg, uint8_t val)
1894 1894 {
1895 1895 pcii_addent(bus, dev, func, reg, val, 1);
1896 1896 }
1897 1897
1898 1898 void
1899 1899 cmi_pci_interposew(int bus, int dev, int func, int reg, uint16_t val)
1900 1900 {
1901 1901 pcii_addent(bus, dev, func, reg, val, 2);
1902 1902 }
1903 1903
1904 1904 void
1905 1905 cmi_pci_interposel(int bus, int dev, int func, int reg, uint32_t val)
1906 1906 {
1907 1907 pcii_addent(bus, dev, func, reg, val, 4);
1908 1908 }
1909 1909
1910 1910 static void
1911 1911 cmi_pci_put_cmn(int bus, int dev, int func, int reg, int asz,
1912 1912 ddi_acc_handle_t hdl, uint32_t val)
1913 1913 {
1914 1914 /*
1915 1915 * If there is an interposed value for this register invalidate it.
1916 1916 */
1917 1917 pcii_rment(bus, dev, func, reg, asz);
1918 1918
1919 1919 if (!(cmi_pcicfg_flags & CMI_PCICFG_FLAG_WR_HWOK))
1920 1920 return;
1921 1921
1922 1922 switch (asz) {
1923 1923 case 1:
1924 1924 if (hdl)
1925 1925 pci_config_put8(hdl, (off_t)reg, (uint8_t)val);
1926 1926 else
1927 1927 pci_cfgacc_put8(NULL, PCI_GETBDF(bus, dev, func), reg,
1928 1928 (uint8_t)val);
1929 1929 break;
1930 1930
1931 1931 case 2:
1932 1932 if (hdl)
1933 1933 pci_config_put16(hdl, (off_t)reg, (uint16_t)val);
1934 1934 else
1935 1935 pci_cfgacc_put16(NULL, PCI_GETBDF(bus, dev, func), reg,
1936 1936 (uint16_t)val);
1937 1937 break;
1938 1938
1939 1939 case 4:
1940 1940 if (hdl)
1941 1941 pci_config_put32(hdl, (off_t)reg, val);
1942 1942 else
1943 1943 pci_cfgacc_put32(NULL, PCI_GETBDF(bus, dev, func), reg,
1944 1944 val);
1945 1945 break;
1946 1946
1947 1947 default:
1948 1948 break;
1949 1949 }
1950 1950 }
1951 1951
1952 1952 void
1953 1953 cmi_pci_putb(int bus, int dev, int func, int reg, ddi_acc_handle_t hdl,
1954 1954 uint8_t val)
1955 1955 {
1956 1956 cmi_pci_put_cmn(bus, dev, func, reg, 1, hdl, val);
1957 1957 }
1958 1958
1959 1959 void
1960 1960 cmi_pci_putw(int bus, int dev, int func, int reg, ddi_acc_handle_t hdl,
1961 1961 uint16_t val)
1962 1962 {
1963 1963 cmi_pci_put_cmn(bus, dev, func, reg, 2, hdl, val);
1964 1964 }
1965 1965
1966 1966 void
1967 1967 cmi_pci_putl(int bus, int dev, int func, int reg, ddi_acc_handle_t hdl,
1968 1968 uint32_t val)
1969 1969 {
1970 1970 cmi_pci_put_cmn(bus, dev, func, reg, 4, hdl, val);
1971 1971 }
1972 1972
1973 1973 static const struct cmi_hdl_ops cmi_hdl_ops = {
1974 1974 #ifdef __xpv
1975 1975 /*
1976 1976 * CMI_HDL_SOLARIS_xVM_MCA - ops when we are an xVM dom0
1977 1977 */
1978 1978 xpv_vendor, /* cmio_vendor */
1979 1979 xpv_vendorstr, /* cmio_vendorstr */
1980 1980 xpv_family, /* cmio_family */
1981 1981 xpv_model, /* cmio_model */
1982 1982 xpv_stepping, /* cmio_stepping */
1983 1983 xpv_chipid, /* cmio_chipid */
1984 1984 xpv_procnodeid, /* cmio_procnodeid */
1985 1985 xpv_coreid, /* cmio_coreid */
1986 1986 xpv_strandid, /* cmio_strandid */
1987 1987 xpv_procnodes_per_pkg, /* cmio_procnodes_per_pkg */
1988 1988 xpv_strand_apicid, /* cmio_strand_apicid */
1989 1989 xpv_chiprev, /* cmio_chiprev */
1990 1990 xpv_chiprevstr, /* cmio_chiprevstr */
1991 1991 xpv_getsockettype, /* cmio_getsockettype */
1992 1992 xpv_getsocketstr, /* cmio_getsocketstr */
1993 1993 xpv_logical_id, /* cmio_logical_id */
1994 1994 NULL, /* cmio_getcr4 */
1995 1995 NULL, /* cmio_setcr4 */
1996 1996 xpv_rdmsr, /* cmio_rdmsr */
1997 1997 xpv_wrmsr, /* cmio_wrmsr */
1998 1998 xpv_msrinterpose, /* cmio_msrinterpose */
1999 1999 xpv_int, /* cmio_int */
2000 2000 xpv_online, /* cmio_online */
2001 2001 xpv_smbiosid, /* cmio_smbiosid */
2002 2002 xpv_smb_chipid, /* cmio_smb_chipid */
2003 2003 xpv_smb_bboard /* cmio_smb_bboard */
2004 2004
2005 2005 #else /* __xpv */
2006 2006
2007 2007 /*
2008 2008 * CMI_HDL_NATIVE - ops when apparently running on bare-metal
2009 2009 */
2010 2010 ntv_vendor, /* cmio_vendor */
2011 2011 ntv_vendorstr, /* cmio_vendorstr */
2012 2012 ntv_family, /* cmio_family */
2013 2013 ntv_model, /* cmio_model */
2014 2014 ntv_stepping, /* cmio_stepping */
2015 2015 ntv_chipid, /* cmio_chipid */
2016 2016 ntv_procnodeid, /* cmio_procnodeid */
2017 2017 ntv_coreid, /* cmio_coreid */
2018 2018 ntv_strandid, /* cmio_strandid */
2019 2019 ntv_procnodes_per_pkg, /* cmio_procnodes_per_pkg */
2020 2020 ntv_strand_apicid, /* cmio_strand_apicid */
2021 2021 ntv_chiprev, /* cmio_chiprev */
2022 2022 ntv_chiprevstr, /* cmio_chiprevstr */
2023 2023 ntv_getsockettype, /* cmio_getsockettype */
2024 2024 ntv_getsocketstr, /* cmio_getsocketstr */
2025 2025 ntv_logical_id, /* cmio_logical_id */
2026 2026 ntv_getcr4, /* cmio_getcr4 */
2027 2027 ntv_setcr4, /* cmio_setcr4 */
2028 2028 ntv_rdmsr, /* cmio_rdmsr */
2029 2029 ntv_wrmsr, /* cmio_wrmsr */
2030 2030 ntv_msrinterpose, /* cmio_msrinterpose */
2031 2031 ntv_int, /* cmio_int */
2032 2032 ntv_online, /* cmio_online */
2033 2033 ntv_smbiosid, /* cmio_smbiosid */
2034 2034 ntv_smb_chipid, /* cmio_smb_chipid */
2035 2035 ntv_smb_bboard /* cmio_smb_bboard */
2036 2036 #endif
2037 2037 };
↓ open down ↓ |
593 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX