Lines Matching +full:cpu +full:- +full:core
1 // SPDX-License-Identifier: GPL-2.0-only
3 * coretemp.c - Linux kernel module for hardware monitoring
18 #include <linux/hwmon-sysfs.h>
23 #include <linux/cpu.h>
34 * force_tjmax only matters when TjMax can't be read from the CPU itself.
43 #define NUM_REAL_CORES 128 /* Number of Real cores per cpu */
49 #define TO_CORE_ID(cpu) (cpu_data(cpu).cpu_core_id) argument
50 #define TO_ATTR_NO(cpu) (TO_CORE_ID(cpu) + BASE_SYSFS_ATTR_NO) argument
53 #define for_each_sibling(i, cpu) \ argument
54 for_each_cpu(i, topology_sibling_cpumask(cpu))
56 #define for_each_sibling(i, cpu) for (i = 0; false; ) argument
60 * Per-Core Temperature Data
63 * @cpu_core_id: The CPU Core from which temperature values should be read
67 * @attr_size: Total number of pre-core attrs displayed in the sysfs.
77 unsigned int cpu; member
90 /* Platform Data per Physical CPU */
101 /* Array of zone pointers. Serialized by cpu hotplug lock */
109 struct temp_data *tdata = pdata->core_data[attr->index]; in show_label()
111 if (tdata->is_pkg_data) in show_label()
112 return sprintf(buf, "Package id %u\n", pdata->pkg_id); in show_label()
114 return sprintf(buf, "Core %u\n", tdata->cpu_core_id); in show_label()
123 struct temp_data *tdata = pdata->core_data[attr->index]; in show_crit_alarm()
125 mutex_lock(&tdata->update_lock); in show_crit_alarm()
126 rdmsr_on_cpu(tdata->cpu, tdata->status_reg, &eax, &edx); in show_crit_alarm()
127 mutex_unlock(&tdata->update_lock); in show_crit_alarm()
138 return sprintf(buf, "%d\n", pdata->core_data[attr->index]->tjmax); in show_tjmax()
147 return sprintf(buf, "%d\n", pdata->core_data[attr->index]->ttarget); in show_ttarget()
156 struct temp_data *tdata = pdata->core_data[attr->index]; in show_temp()
158 mutex_lock(&tdata->update_lock); in show_temp()
161 if (!tdata->valid || time_after(jiffies, tdata->last_updated + HZ)) { in show_temp()
162 rdmsr_on_cpu(tdata->cpu, tdata->status_reg, &eax, &edx); in show_temp()
169 tdata->temp = tdata->tjmax - ((eax >> 16) & 0x7f) * 1000; in show_temp()
170 tdata->valid = 1; in show_temp()
171 tdata->last_updated = jiffies; in show_temp()
174 mutex_unlock(&tdata->update_lock); in show_temp()
175 return sprintf(buf, "%d\n", tdata->temp); in show_temp()
196 { "CPU 230", 100000 }, /* Model 0x1c, stepping 2 */
197 { "CPU 330", 125000 }, /* Model 0x1c, stepping 2 */
215 * Note: TjMax for E6xxT is 110C, but CPU type
244 if (host_bridge && host_bridge->vendor == PCI_VENDOR_ID_INTEL) { in adjust_tjmax()
246 if (host_bridge->device == tjmax_pci_table[i].device) in adjust_tjmax()
252 if (strstr(c->x86_model_id, tjmax_table[i].id)) in adjust_tjmax()
258 if (c->x86_model == tm->model && in adjust_tjmax()
259 (tm->mask == ANY || c->x86_stepping == tm->mask)) in adjust_tjmax()
260 return tm->tjmax; in adjust_tjmax()
265 if (c->x86_model == 0xf && c->x86_stepping < 4) in adjust_tjmax()
268 if (c->x86_model > 0xe && usemsr_ee) { in adjust_tjmax()
272 * Now we can detect the mobile CPU using Intel provided table in adjust_tjmax()
274 * For Core2 cores, check MSR 0x17, bit 28 1 = Mobile CPU in adjust_tjmax()
280 " CPU\n"); in adjust_tjmax()
282 } else if (c->x86_model < 0x17 && !(eax & 0x10000000)) { in adjust_tjmax()
294 * Mobile Penryn CPU seems to be platform ID 7 or 5 in adjust_tjmax()
297 if (c->x86_model == 0x17 && in adjust_tjmax()
320 * If we don't use msr EE it means we are desktop CPU in adjust_tjmax()
331 u8 model = c->x86_model; in cpu_has_tjmax()
354 dev_warn(dev, "Unable to read TjMax from CPU %u\n", id); in get_tjmax()
392 for (i = 0; i < tdata->attr_size; i++) { in create_core_attrs()
393 snprintf(tdata->attr_name[i], CORETEMP_NAME_LENGTH, in create_core_attrs()
395 sysfs_attr_init(&tdata->sd_attrs[i].dev_attr.attr); in create_core_attrs()
396 tdata->sd_attrs[i].dev_attr.attr.name = tdata->attr_name[i]; in create_core_attrs()
397 tdata->sd_attrs[i].dev_attr.attr.mode = 0444; in create_core_attrs()
398 tdata->sd_attrs[i].dev_attr.show = rd_ptr[i]; in create_core_attrs()
399 tdata->sd_attrs[i].index = attr_no; in create_core_attrs()
400 tdata->attrs[i] = &tdata->sd_attrs[i].dev_attr.attr; in create_core_attrs()
402 tdata->attr_group.attrs = tdata->attrs; in create_core_attrs()
403 return sysfs_create_group(&dev->kobj, &tdata->attr_group); in create_core_attrs()
407 static int chk_ucode_version(unsigned int cpu) in chk_ucode_version() argument
409 struct cpuinfo_x86 *c = &cpu_data(cpu); in chk_ucode_version()
412 * Check if we have problem with errata AE18 of Core processors: in chk_ucode_version()
416 if (c->x86_model == 0xe && c->x86_stepping < 0xc && c->microcode < 0x39) { in chk_ucode_version()
417 pr_err("Errata AE18 not fixed, update BIOS or microcode of the CPU!\n"); in chk_ucode_version()
418 return -ENODEV; in chk_ucode_version()
423 static struct platform_device *coretemp_get_pdev(unsigned int cpu) in coretemp_get_pdev() argument
425 int id = topology_logical_die_id(cpu); in coretemp_get_pdev()
432 static struct temp_data *init_temp_data(unsigned int cpu, int pkg_flag) in init_temp_data() argument
440 tdata->status_reg = pkg_flag ? MSR_IA32_PACKAGE_THERM_STATUS : in init_temp_data()
442 tdata->is_pkg_data = pkg_flag; in init_temp_data()
443 tdata->cpu = cpu; in init_temp_data()
444 tdata->cpu_core_id = TO_CORE_ID(cpu); in init_temp_data()
445 tdata->attr_size = MAX_CORE_ATTRS; in init_temp_data()
446 mutex_init(&tdata->update_lock); in init_temp_data()
450 static int create_core_data(struct platform_device *pdev, unsigned int cpu, in create_core_data() argument
455 struct cpuinfo_x86 *c = &cpu_data(cpu); in create_core_data()
461 * We map the attr number to core id of the CPU in create_core_data()
462 * The attr number is always core id + 2 in create_core_data()
465 attr_no = pkg_flag ? PKG_SYSFS_ATTR_NO : TO_ATTR_NO(cpu); in create_core_data()
467 if (attr_no > MAX_CORE_DATA - 1) in create_core_data()
468 return -ERANGE; in create_core_data()
470 tdata = init_temp_data(cpu, pkg_flag); in create_core_data()
472 return -ENOMEM; in create_core_data()
475 err = rdmsr_safe_on_cpu(cpu, tdata->status_reg, &eax, &edx); in create_core_data()
480 tdata->tjmax = get_tjmax(c, cpu, &pdev->dev); in create_core_data()
487 if (c->x86_model > 0xe && c->x86_model != 0x1c) { in create_core_data()
488 err = rdmsr_safe_on_cpu(cpu, MSR_IA32_TEMPERATURE_TARGET, in create_core_data()
491 tdata->ttarget in create_core_data()
492 = tdata->tjmax - ((eax >> 8) & 0xff) * 1000; in create_core_data()
493 tdata->attr_size++; in create_core_data()
497 pdata->core_data[attr_no] = tdata; in create_core_data()
500 err = create_core_attrs(tdata, pdata->hwmon_dev, attr_no); in create_core_data()
506 pdata->core_data[attr_no] = NULL; in create_core_data()
512 coretemp_add_core(struct platform_device *pdev, unsigned int cpu, int pkg_flag) in coretemp_add_core() argument
514 if (create_core_data(pdev, cpu, pkg_flag)) in coretemp_add_core()
515 dev_err(&pdev->dev, "Adding Core %u failed\n", cpu); in coretemp_add_core()
520 struct temp_data *tdata = pdata->core_data[indx]; in coretemp_remove_core()
523 sysfs_remove_group(&pdata->hwmon_dev->kobj, &tdata->attr_group); in coretemp_remove_core()
525 kfree(pdata->core_data[indx]); in coretemp_remove_core()
526 pdata->core_data[indx] = NULL; in coretemp_remove_core()
531 struct device *dev = &pdev->dev; in coretemp_probe()
534 /* Initialize the per-zone data structures */ in coretemp_probe()
537 return -ENOMEM; in coretemp_probe()
539 pdata->pkg_id = pdev->id; in coretemp_probe()
542 pdata->hwmon_dev = devm_hwmon_device_register_with_groups(dev, DRVNAME, in coretemp_probe()
544 return PTR_ERR_OR_ZERO(pdata->hwmon_dev); in coretemp_probe()
552 for (i = MAX_CORE_DATA - 1; i >= 0; --i) in coretemp_remove()
553 if (pdata->core_data[i]) in coretemp_remove()
567 static struct platform_device *coretemp_device_add(unsigned int cpu) in coretemp_device_add() argument
569 int err, zoneid = topology_logical_die_id(cpu); in coretemp_device_add()
573 return ERR_PTR(-ENOMEM); in coretemp_device_add()
577 return ERR_PTR(-ENOMEM); in coretemp_device_add()
589 static int coretemp_cpu_online(unsigned int cpu) in coretemp_cpu_online() argument
591 struct platform_device *pdev = coretemp_get_pdev(cpu); in coretemp_cpu_online()
592 struct cpuinfo_x86 *c = &cpu_data(cpu); in coretemp_cpu_online()
603 * CPUID.06H.EAX[0] indicates whether the CPU has thermal in coretemp_cpu_online()
608 return -ENODEV; in coretemp_cpu_online()
611 /* Check the microcode version of the CPU */ in coretemp_cpu_online()
612 if (chk_ucode_version(cpu)) in coretemp_cpu_online()
613 return -EINVAL; in coretemp_cpu_online()
617 * We are bringing the _first_ core in this pkg in coretemp_cpu_online()
618 * online. So, initialize per-pkg data structures and in coretemp_cpu_online()
619 * then bring this core online. in coretemp_cpu_online()
621 pdev = coretemp_device_add(cpu); in coretemp_cpu_online()
630 coretemp_add_core(pdev, cpu, 1); in coretemp_cpu_online()
636 * interface for this CPU core. in coretemp_cpu_online()
638 if (!cpumask_intersects(&pdata->cpumask, topology_sibling_cpumask(cpu))) in coretemp_cpu_online()
639 coretemp_add_core(pdev, cpu, 0); in coretemp_cpu_online()
641 cpumask_set_cpu(cpu, &pdata->cpumask); in coretemp_cpu_online()
645 static int coretemp_cpu_offline(unsigned int cpu) in coretemp_cpu_offline() argument
647 struct platform_device *pdev = coretemp_get_pdev(cpu); in coretemp_cpu_offline()
659 /* If the physical CPU device does not exist, just return */ in coretemp_cpu_offline()
663 /* The core id is too big, just return */ in coretemp_cpu_offline()
664 indx = TO_ATTR_NO(cpu); in coretemp_cpu_offline()
665 if (indx > MAX_CORE_DATA - 1) in coretemp_cpu_offline()
669 tdata = pd->core_data[indx]; in coretemp_cpu_offline()
671 cpumask_clear_cpu(cpu, &pd->cpumask); in coretemp_cpu_offline()
674 * If this is the last thread sibling, remove the CPU core in coretemp_cpu_offline()
676 * target cpu of that core interface to it. in coretemp_cpu_offline()
678 target = cpumask_any_and(&pd->cpumask, topology_sibling_cpumask(cpu)); in coretemp_cpu_offline()
681 } else if (tdata && tdata->cpu == cpu) { in coretemp_cpu_offline()
682 mutex_lock(&tdata->update_lock); in coretemp_cpu_offline()
683 tdata->cpu = target; in coretemp_cpu_offline()
684 mutex_unlock(&tdata->update_lock); in coretemp_cpu_offline()
692 if (cpumask_empty(&pd->cpumask)) { in coretemp_cpu_offline()
693 zone_devices[topology_logical_die_id(cpu)] = NULL; in coretemp_cpu_offline()
699 * Check whether this core is the target for the package in coretemp_cpu_offline()
700 * interface. We need to assign it to some other cpu. in coretemp_cpu_offline()
702 tdata = pd->core_data[PKG_SYSFS_ATTR_NO]; in coretemp_cpu_offline()
703 if (tdata && tdata->cpu == cpu) { in coretemp_cpu_offline()
704 target = cpumask_first(&pd->cpumask); in coretemp_cpu_offline()
705 mutex_lock(&tdata->update_lock); in coretemp_cpu_offline()
706 tdata->cpu = target; in coretemp_cpu_offline()
707 mutex_unlock(&tdata->update_lock); in coretemp_cpu_offline()
724 * CPUID.06H.EAX[0] indicates whether the CPU has thermal in coretemp_init()
729 return -ENODEV; in coretemp_init()
735 return -ENOMEM; in coretemp_init()
765 MODULE_DESCRIPTION("Intel Core temperature monitor");