1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12 /* 13 * Copyright 2019 Robert Mustacchi 14 */ 15 16 /* 17 * AMD Northbridge CPU Temperature Driver 18 * 19 * The AMD northbridge CPU temperature driver supports the temperature sensor 20 * that was found on the AMD northbridge on AMD CPUs from approximately AMD 21 * Family 10h to Family 16h. For Zen and newer processors (Family 17h+) see the 22 * 'amdf17nbdf' driver. 23 * 24 * The temperature is stored on the 'miscellaneous' device on the northbridge. 25 * This is always found at PCI Device 18h, Function 3h. When there is more than 26 * one 'node' (see cpuid.c for the AMD parlance), then the node id is added to 27 * the device to create a unique device. This allows us to map the given PCI 28 * device we find back to the corresponding CPU. 29 * 30 * While all family 10h, 11h, 12h, 14h, and 16h CPUs are supported, not all 31 * family 15h CPUs are. Models 60h+ require the SMN interface, which this does 32 * not know how to consume. 33 */ 34 35 #include <sys/modctl.h> 36 #include <sys/conf.h> 37 #include <sys/devops.h> 38 #include <sys/types.h> 39 #include <sys/file.h> 40 #include <sys/open.h> 41 #include <sys/cred.h> 42 #include <sys/stat.h> 43 #include <sys/ddi.h> 44 #include <sys/sunddi.h> 45 #include <sys/cmn_err.h> 46 #include <sys/pci.h> 47 #include <sys/stddef.h> 48 #include <sys/cpuvar.h> 49 #include <sys/x86_archext.h> 50 #include <sys/list.h> 51 #include <sys/bitset.h> 52 #include <sys/sensors.h> 53 54 /* 55 * This register offset, in PCI config space, has the current temperature of the 56 * device. 57 */ 58 #define AMDNBTEMP_TEMPREG 0xa4 59 #define AMDNBTEMP_TEMPREG_CURTMP(x) BITX(x, 31, 21) 60 #define AMDNBTEMP_TEMPREG_TJSEL(x) BITX(x, 17, 16) 61 62 /* 63 * Each bit in the temperature range represents 1/8th of a degree C. 64 */ 65 #define AMDNBTEMP_GRANULARITY 8 66 #define AMDNBTEMP_GSHIFT 3 67 68 /* 69 * If the value of the current CurTmpTjSel is set to three, then the range that 70 * the data is in is shifted by -49 degrees. In this mode, the bottom two bits 71 * always read as zero. 72 */ 73 #define AMDNBTEMP_TJSEL_ADJUST 0x3 74 #define AMDNBTEMP_TEMP_ADJUST (49 << AMDNBTEMP_GSHIFT) 75 76 /* 77 * There are a variable number of northbridges that exist in the system. The AMD 78 * BIOS and Kernel Developer's Guide (BKDG) says that for these families, the 79 * first node has a device of 0x18. This means that node 7, the maximum, has a 80 * device of 0x1f. 81 */ 82 #define AMDNBTEMP_FIRST_DEV 0x18 83 84 typedef enum andnbtemp_state { 85 AMDNBTEMP_S_CFGSPACE = 1 << 0, 86 AMDNBTEMP_S_MUTEX = 1 << 1, 87 AMDNBTEMP_S_MINOR = 1 << 2, 88 AMDNBTEMP_S_LIST = 1 << 3 89 } amdnbtemp_state_t; 90 91 typedef struct amdnbtemp { 92 amdnbtemp_state_t at_state; 93 list_node_t at_link; 94 dev_info_t *at_dip; 95 ddi_acc_handle_t at_cfgspace; 96 uint_t at_bus; 97 uint_t at_dev; 98 uint_t at_func; 99 minor_t at_minor; 100 boolean_t at_tjsel; 101 kmutex_t at_mutex; 102 uint32_t at_raw; 103 int64_t at_temp; 104 } amdnbtemp_t; 105 106 static void *amdnbtemp_state; 107 static list_t amdnbtemp_list; 108 static kmutex_t amdnbtemp_mutex; 109 110 static amdnbtemp_t * 111 amdnbtemp_find_by_dev(dev_t dev) 112 { 113 minor_t m = getminor(dev); 114 amdnbtemp_t *at; 115 116 mutex_enter(&amdnbtemp_mutex); 117 for (at = list_head(&amdnbtemp_list); at != NULL; 118 at = list_next(&amdnbtemp_list, at)) { 119 if (at->at_minor == m) { 120 break; 121 } 122 } 123 mutex_exit(&amdnbtemp_mutex); 124 125 return (at); 126 } 127 128 static int 129 amdnbtemp_read(amdnbtemp_t *at) 130 { 131 ASSERT(MUTEX_HELD(&at->at_mutex)); 132 133 at->at_raw = pci_config_get32(at->at_cfgspace, AMDNBTEMP_TEMPREG); 134 if (at->at_raw == PCI_EINVAL32) { 135 return (EIO); 136 } 137 138 at->at_temp = AMDNBTEMP_TEMPREG_CURTMP(at->at_raw); 139 if (at->at_tjsel && 140 AMDNBTEMP_TEMPREG_TJSEL(at->at_raw) == AMDNBTEMP_TJSEL_ADJUST) { 141 at->at_temp -= AMDNBTEMP_TEMP_ADJUST; 142 } 143 144 return (0); 145 } 146 147 static int 148 amdnbtemp_open(dev_t *devp, int flags, int otype, cred_t *credp) 149 { 150 amdnbtemp_t *at; 151 152 if (crgetzoneid(credp) != GLOBAL_ZONEID || drv_priv(credp) != 0) { 153 return (EPERM); 154 } 155 156 if ((flags & (FEXCL | FNDELAY | FWRITE)) != 0) { 157 return (EINVAL); 158 } 159 160 if (otype != OTYP_CHR) { 161 return (EINVAL); 162 } 163 164 at = amdnbtemp_find_by_dev(*devp); 165 if (at == NULL) { 166 return (ENXIO); 167 } 168 169 return (0); 170 } 171 172 static int 173 amdnbtemp_ioctl_kind(intptr_t arg, int mode) 174 { 175 sensor_ioctl_kind_t kind; 176 177 bzero(&kind, sizeof (kind)); 178 kind.sik_kind = SENSOR_KIND_TEMPERATURE; 179 180 if (ddi_copyout(&kind, (void *)arg, sizeof (kind), mode & FKIOCTL) != 181 0) { 182 return (EFAULT); 183 } 184 185 return (0); 186 } 187 188 static int 189 amdnbtemp_ioctl_temp(amdnbtemp_t *at, intptr_t arg, int mode) 190 { 191 int ret; 192 sensor_ioctl_temperature_t temp; 193 194 bzero(&temp, sizeof (temp)); 195 196 mutex_enter(&at->at_mutex); 197 if ((ret = amdnbtemp_read(at)) != 0) { 198 mutex_exit(&at->at_mutex); 199 return (ret); 200 } 201 202 temp.sit_unit = SENSOR_UNIT_CELSIUS; 203 temp.sit_gran = AMDNBTEMP_GRANULARITY; 204 temp.sit_temp = at->at_temp; 205 mutex_exit(&at->at_mutex); 206 207 if (ddi_copyout(&temp, (void *)arg, sizeof (temp), mode & FKIOCTL) != 208 0) { 209 return (EFAULT); 210 } 211 212 return (0); 213 } 214 215 static int 216 amdnbtemp_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, 217 int *rvalp) 218 { 219 amdnbtemp_t *at; 220 221 at = amdnbtemp_find_by_dev(dev); 222 if (at == NULL) { 223 return (ENXIO); 224 } 225 226 if ((mode & FREAD) == 0) { 227 return (EINVAL); 228 } 229 230 switch (cmd) { 231 case SENSOR_IOCTL_TYPE: 232 return (amdnbtemp_ioctl_kind(arg, mode)); 233 case SENSOR_IOCTL_TEMPERATURE: 234 return (amdnbtemp_ioctl_temp(at, arg, mode)); 235 default: 236 return (ENOTTY); 237 } 238 } 239 240 static int 241 amdnbtemp_close(dev_t dev, int flags, int otype, cred_t *credp) 242 { 243 return (0); 244 } 245 246 static void 247 amdnbtemp_cleanup(amdnbtemp_t *at) 248 { 249 int inst; 250 inst = ddi_get_instance(at->at_dip); 251 252 if ((at->at_state & AMDNBTEMP_S_LIST) != 0) { 253 mutex_enter(&amdnbtemp_mutex); 254 list_remove(&amdnbtemp_list, at); 255 mutex_exit(&amdnbtemp_mutex); 256 at->at_state &= ~AMDNBTEMP_S_LIST; 257 } 258 259 if ((at->at_state & AMDNBTEMP_S_MINOR) != 0) { 260 ddi_remove_minor_node(at->at_dip, NULL); 261 at->at_state &= ~AMDNBTEMP_S_MINOR; 262 } 263 264 if ((at->at_state & AMDNBTEMP_S_MUTEX) != 0) { 265 mutex_destroy(&at->at_mutex); 266 at->at_state &= ~AMDNBTEMP_S_MUTEX; 267 } 268 269 if ((at->at_state & AMDNBTEMP_S_CFGSPACE) != 0) { 270 pci_config_teardown(&at->at_cfgspace); 271 at->at_state &= ~AMDNBTEMP_S_CFGSPACE; 272 } 273 274 ASSERT0(at->at_state); 275 ddi_soft_state_free(amdnbtemp_state, inst); 276 } 277 278 /* 279 * For several family 10h processors, certain models have an erratum which says 280 * that temperature information is unreliable. If we're on a platform that is 281 * subject to this erratum, do not attach to the device. 282 */ 283 static boolean_t 284 amdnbtemp_erratum_319(void) 285 { 286 uint32_t socket; 287 288 if (cpuid_getfamily(CPU) != 0x10) { 289 return (B_FALSE); 290 } 291 292 /* 293 * All Family 10h socket F parts are impacted. Socket AM2 parts are all 294 * impacted. The family 10h socket bits in cpuid share the same bit for 295 * socket AM2 and AM3. If you look at the erratum description, they use 296 * information about the memory controller to do DDR2/DDR3 297 * disambiguation to determine whether it's socket AM2 or AM3. Our cpuid 298 * subroutines already do the DDR2/DDR3 disambiguation so we can just 299 * check the socket type as the disambiguation has already been done. 300 */ 301 socket = cpuid_getsockettype(CPU); 302 if (socket == X86_SOCKET_F1207 || socket == X86_SOCKET_AM2R2) { 303 return (B_TRUE); 304 } 305 306 return (B_FALSE); 307 } 308 309 static int 310 amdnbtemp_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 311 { 312 int inst, *regs; 313 amdnbtemp_t *at; 314 uint_t nregs; 315 char buf[128]; 316 317 switch (cmd) { 318 case DDI_RESUME: 319 return (DDI_SUCCESS); 320 case DDI_ATTACH: 321 break; 322 default: 323 return (DDI_FAILURE); 324 } 325 326 inst = ddi_get_instance(dip); 327 if (ddi_soft_state_zalloc(amdnbtemp_state, inst) != DDI_SUCCESS) { 328 dev_err(dip, CE_WARN, "failed to allocate soft state entry %d", 329 inst); 330 return (DDI_FAILURE); 331 } 332 333 at = ddi_get_soft_state(amdnbtemp_state, inst); 334 if (at == NULL) { 335 dev_err(dip, CE_WARN, "failed to retrieve soft state entry %d", 336 inst); 337 return (DDI_FAILURE); 338 } 339 340 at->at_dip = dip; 341 342 if (pci_config_setup(dip, &at->at_cfgspace) != DDI_SUCCESS) { 343 dev_err(dip, CE_WARN, "failed to set up PCI config space"); 344 goto err; 345 } 346 at->at_state |= AMDNBTEMP_S_CFGSPACE; 347 348 if (amdnbtemp_erratum_319()) { 349 dev_err(dip, CE_WARN, "!device subject to AMD Erratum 319, " 350 "not attaching to unreliable sensor"); 351 goto err; 352 } 353 354 mutex_init(&at->at_mutex, NULL, MUTEX_DRIVER, NULL); 355 at->at_state |= AMDNBTEMP_S_MUTEX; 356 357 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 0, "reg", 358 ®s, &nregs) != DDI_PROP_SUCCESS) { 359 dev_err(dip, CE_WARN, "failed to get pci 'reg' property"); 360 goto err; 361 } 362 363 if (nregs < 1) { 364 dev_err(dip, CE_WARN, "'reg' property missing PCI b/d/f"); 365 ddi_prop_free(regs); 366 goto err; 367 } 368 369 at->at_bus = PCI_REG_BUS_G(regs[0]); 370 at->at_dev = PCI_REG_DEV_G(regs[0]); 371 at->at_func = PCI_REG_DEV_G(regs[0]); 372 ddi_prop_free(regs); 373 374 if (at->at_dev < AMDNBTEMP_FIRST_DEV) { 375 dev_err(dip, CE_WARN, "Invalid pci b/d/f device, found 0x%x", 376 at->at_dev); 377 goto err; 378 } 379 380 at->at_minor = at->at_dev - AMDNBTEMP_FIRST_DEV; 381 if (snprintf(buf, sizeof (buf), "procnode.%u", at->at_minor) >= 382 sizeof (buf)) { 383 dev_err(dip, CE_WARN, "unexpected buffer name overrun " 384 "constructing minor %u", at->at_minor); 385 goto err; 386 } 387 388 if (ddi_create_minor_node(dip, buf, S_IFCHR, at->at_minor, 389 DDI_NT_SENSOR_TEMP_CPU, 0) != DDI_SUCCESS) { 390 dev_err(dip, CE_WARN, "failed to create minor node %s", 391 buf); 392 goto err; 393 } 394 at->at_state |= AMDNBTEMP_S_MINOR; 395 396 mutex_enter(&amdnbtemp_mutex); 397 list_insert_tail(&amdnbtemp_list, at); 398 mutex_exit(&amdnbtemp_mutex); 399 at->at_state |= AMDNBTEMP_S_LIST; 400 401 /* 402 * On families 15h and 16h the BKDG documents that the CurTmpTjSel bits 403 * of the temperature register dictate how the temperature reading 404 * should be interpreted. Capture that now. 405 */ 406 if (cpuid_getfamily(CPU) >= 0x15) { 407 at->at_tjsel = B_TRUE; 408 } 409 410 mutex_enter(&at->at_mutex); 411 (void) amdnbtemp_read(at); 412 mutex_exit(&at->at_mutex); 413 414 return (DDI_SUCCESS); 415 416 err: 417 amdnbtemp_cleanup(at); 418 return (DDI_FAILURE); 419 } 420 421 static int 422 amdnbtemp_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, 423 void **resultp) 424 { 425 amdnbtemp_t *at; 426 427 if (cmd != DDI_INFO_DEVT2DEVINFO && cmd != DDI_INFO_DEVT2INSTANCE) { 428 return (DDI_FAILURE); 429 } 430 431 at = amdnbtemp_find_by_dev((dev_t)arg); 432 if (at == NULL) { 433 return (DDI_FAILURE); 434 } 435 436 if (cmd == DDI_INFO_DEVT2DEVINFO) { 437 *resultp = at->at_dip; 438 } else { 439 *resultp = (void *)(uintptr_t)ddi_get_instance(at->at_dip); 440 } 441 442 return (DDI_SUCCESS); 443 } 444 445 static int 446 amdnbtemp_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 447 { 448 int inst; 449 amdnbtemp_t *at; 450 451 switch (cmd) { 452 case DDI_DETACH: 453 break; 454 case DDI_SUSPEND: 455 return (DDI_SUCCESS); 456 default: 457 return (DDI_FAILURE); 458 } 459 460 inst = ddi_get_instance(dip); 461 at = ddi_get_soft_state(amdnbtemp_state, inst); 462 if (at == NULL) { 463 dev_err(dip, CE_WARN, "asked to detach instance %d, but it is " 464 "missing from the soft state", inst); 465 return (DDI_FAILURE); 466 } 467 468 amdnbtemp_cleanup(at); 469 return (DDI_SUCCESS); 470 } 471 472 static struct cb_ops amdnbtemp_cb_ops = { 473 .cb_open = amdnbtemp_open, 474 .cb_close = amdnbtemp_close, 475 .cb_strategy = nodev, 476 .cb_print = nodev, 477 .cb_dump = nodev, 478 .cb_read = nodev, 479 .cb_write = nodev, 480 .cb_ioctl = amdnbtemp_ioctl, 481 .cb_devmap = nodev, 482 .cb_mmap = nodev, 483 .cb_segmap = nodev, 484 .cb_chpoll = nochpoll, 485 .cb_prop_op = ddi_prop_op, 486 .cb_flag = D_MP, 487 .cb_rev = CB_REV, 488 .cb_aread = nodev, 489 .cb_awrite = nodev 490 }; 491 492 static struct dev_ops amdnbtemp_dev_ops = { 493 .devo_rev = DEVO_REV, 494 .devo_refcnt = 0, 495 .devo_getinfo = amdnbtemp_getinfo, 496 .devo_identify = nulldev, 497 .devo_probe = nulldev, 498 .devo_attach = amdnbtemp_attach, 499 .devo_detach = amdnbtemp_detach, 500 .devo_reset = nodev, 501 .devo_power = ddi_power, 502 .devo_quiesce = ddi_quiesce_not_needed, 503 .devo_cb_ops = &amdnbtemp_cb_ops 504 }; 505 506 static struct modldrv amdnbtemp_modldrv = { 507 .drv_modops = &mod_driverops, 508 .drv_linkinfo = "AMD NB Temp Driver", 509 .drv_dev_ops = &amdnbtemp_dev_ops 510 }; 511 512 static struct modlinkage amdnbtemp_modlinkage = { 513 .ml_rev = MODREV_1, 514 .ml_linkage = { &amdnbtemp_modldrv, NULL } 515 }; 516 517 int 518 _init(void) 519 { 520 int ret; 521 522 if (ddi_soft_state_init(&amdnbtemp_state, sizeof (amdnbtemp_t), 2) != 523 DDI_SUCCESS) { 524 return (ENOMEM); 525 } 526 527 if ((ret = mod_install(&amdnbtemp_modlinkage)) != 0) { 528 ddi_soft_state_fini(&amdnbtemp_state); 529 return (ret); 530 } 531 532 list_create(&amdnbtemp_list, sizeof (amdnbtemp_t), 533 offsetof(amdnbtemp_t, at_link)); 534 mutex_init(&amdnbtemp_mutex, NULL, MUTEX_DRIVER, NULL); 535 536 return (ret); 537 } 538 539 int 540 _info(struct modinfo *modinfop) 541 { 542 return (mod_info(&amdnbtemp_modlinkage, modinfop)); 543 } 544 545 int 546 _fini(void) 547 { 548 int ret; 549 550 if ((ret = mod_remove(&amdnbtemp_modlinkage)) != 0) { 551 return (ret); 552 } 553 554 mutex_destroy(&amdnbtemp_mutex); 555 list_destroy(&amdnbtemp_list); 556 ddi_soft_state_fini(&amdnbtemp_state); 557 return (ret); 558 } 559