static int cpufreq_p4_setdc(unsigned int cpu, unsigned int newstate) { u32 l, h; if ((newstate > DC_DISABLE) || (newstate == DC_RESV)) return -EINVAL; rdmsr_on_cpu(cpu, MSR_IA32_THERM_STATUS, &l, &h); if (l & 0x01) pr_debug("CPU#%d currently thermal throttled\n", cpu); if (has_N44_O17_errata[cpu] && (newstate == DC_25PT || newstate == DC_DFLT)) newstate = DC_38PT; rdmsr_on_cpu(cpu, MSR_IA32_THERM_CONTROL, &l, &h); if (newstate == DC_DISABLE) { pr_debug("CPU#%d disabling modulation\n", cpu); wrmsr_on_cpu(cpu, MSR_IA32_THERM_CONTROL, l & ~(1<<4), h); } else { pr_debug("CPU#%d setting duty cycle to %d%%\n", cpu, ((125 * newstate) / 10)); /* bits 63 - 5 : reserved * bit 4 : enable/disable * bits 3-1 : duty cycle * bit 0 : reserved */ l = (l & ~14); l = l | (1<<4) | ((newstate & 0x7)<<1); wrmsr_on_cpu(cpu, MSR_IA32_THERM_CONTROL, l, h); } return 0; }
static ssize_t store_tmin(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) { struct platform_data *pdata = dev_get_drvdata(dev); struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct temp_data *tdata = pdata->core_data[attr->index]; u32 eax, edx; unsigned long val; int diff; if (strict_strtoul(buf, 10, &val)) return -EINVAL; /* * THERM_MASK_THRESHOLD0 is 7 bits wide. Values are entered in terms * of milli degree celsius. Hence don't accept val > (127 * 1000) */ if (val > tdata->tjmax || val > 127000) return -EINVAL; diff = (tdata->tjmax - val) / 1000; mutex_lock(&tdata->update_lock); rdmsr_on_cpu(tdata->cpu, tdata->intrpt_reg, &eax, &edx); eax = (eax & ~THERM_MASK_THRESHOLD0) | (diff << THERM_SHIFT_THRESHOLD0); wrmsr_on_cpu(tdata->cpu, tdata->intrpt_reg, eax, edx); tdata->tmin = val; mutex_unlock(&tdata->update_lock); return count; }
static void enable_soc_dts(void) { int i; u32 val, eax, edx; rdmsr_on_cpu(0, MSR_THERM_CFG1, &eax, &edx); /* B[11:13] C2H Hyst */ eax = (eax & ~(0x7 << 11)) | (DEFAULT_C2H_HYST << 11); /* B[8:10] H2C Hyst */ eax = (eax & ~(0x7 << 8)) | (DEFAULT_H2C_HYST << 8); /* Set the Hysteresis value */ wrmsr_on_cpu(0, MSR_THERM_CFG1, eax, edx); /* Enable the DTS */ write_soc_reg(DTS_ENABLE_REG, DTS_ENABLE); val = read_soc_reg(SOC_DTS_CONTROL); write_soc_reg(SOC_DTS_CONTROL, val | ENABLE_AUX_INTRPT | ENABLE_CPU0); /* Enable Interrupts for all the AUX trips for the DTS */ for (i = 0; i < SOC_THERMAL_TRIPS; i++) { val = read_soc_reg(TE_AUX0 + i); write_soc_reg(TE_AUX0 + i, (val | RTE_ENABLE)); } }
static void one_msr_rd(RegRec * r) { uint32_t hi, lo; switch(r->box & 0xf) { case GMSR: rdmsr(r->ofs, lo, hi); break; #if RAS_SAVE_CPU_MSR case LMSR: rdmsr_on_cpu(r->num, r->ofs, &lo, &hi); break; #endif default: r->box &= ~VLD; return; } r->reg = ((uint64_t) hi) << 32 | (uint64_t) lo; r->box |= VLD; #if PM_VERBOSE printk("msr_rd: box %d, idx %3d, ofs %04x -> %llx\n", r->box & 0xf, r->num, r->ofs, r->reg); #endif }
static bool boost_state(unsigned int cpu) { u32 lo, hi; u64 msr; switch (boot_cpu_data.x86_vendor) { case X86_VENDOR_INTEL: rdmsr_on_cpu(cpu, MSR_IA32_MISC_ENABLE, &lo, &hi); msr = lo | ((u64)hi << 32); return !(msr & MSR_IA32_MISC_ENABLE_TURBO_DISABLE); case X86_VENDOR_AMD: rdmsr_on_cpu(cpu, MSR_K7_HWCR, &lo, &hi); msr = lo | ((u64)hi << 32); return !(msr & MSR_K7_HWCR_CPB_DIS); } return false; }
static unsigned int cpufreq_p4_get(unsigned int cpu) { u32 l, h; rdmsr_on_cpu(cpu, MSR_IA32_THERM_CONTROL, &l, &h); if (l & 0x10) { l = l >> 1; l &= 0x7; } else
static ssize_t show_crit_alarm(struct device *dev, struct device_attribute *devattr, char *buf) { u32 eax, edx; struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct platform_data *pdata = dev_get_drvdata(dev); struct temp_data *tdata = pdata->core_data[attr->index]; rdmsr_on_cpu(tdata->cpu, tdata->status_reg, &eax, &edx); return sprintf(buf, "%d\n", (eax >> 5) & 1); }
void rdmsr_on_all_cpus(uint32_t reg) { struct dirent **namelist; int dir_entries; dir_entries = scandir("/dev/cpu", &namelist, dir_filter, 0); while (dir_entries--) { rdmsr_on_cpu(reg, atoi(namelist[dir_entries]->d_name)); free(namelist[dir_entries]); } free(namelist); }
static int sfi_cpufreq_target(struct cpufreq_policy *policy, unsigned int index) { unsigned int next_perf_state = 0; /* Index into perf table */ u32 lo, hi; next_perf_state = policy->freq_table[index].driver_data; rdmsr_on_cpu(policy->cpu, MSR_IA32_PERF_CTL, &lo, &hi); lo = (lo & ~INTEL_PERF_CTL_MASK) | ((u32) sfi_cpufreq_array[next_perf_state].ctrl_val & INTEL_PERF_CTL_MASK); wrmsr_on_cpu(policy->cpu, MSR_IA32_PERF_CTL, lo, hi); return 0; }
static struct coretemp_data *coretemp_update_device(struct device *dev) { struct coretemp_data *data = dev_get_drvdata(dev); mutex_lock(&data->update_lock); if (!data->valid || time_after(jiffies, data->last_updated + HZ)) { u32 eax, edx; data->valid = 0; rdmsr_on_cpu(data->id, MSR_IA32_THERM_STATUS, &eax, &edx); data->alarm = (eax >> 5) & 1; /* update only if data has been valid */ if (eax & 0x80000000) { data->temp = data->tjmax - (((eax >> 16) & 0x7f) * 1000); data->valid = 1; } else {
// Thie function use fork to create a child process. The child process tries to read MSR_KVM_API_MAGIC. // If the register exists, it is readable. Otherwise, it is not readable. // Return: 1 if bug exist, 0 if not sure. int test_msr_ia32_perf_status() { uint64_t data; data=rdmsr_on_cpu(MSR_IA32_PERF_STATUS,0); if(data==0) { DPRINTF("DEBUG: Bug Exists: MSR_IA32_PERF_STATUS returns 0 upon read!\n"); return 1; } else { DPRINTF("DEBUG: Bug Fixed: MSR_IA32_PERF_STATUS returns non-zero upon read!\n"); DPRINTF("DEBUG: Bug Fixed: MSR_IA32_PERF_STATUS returns %" PRIu64 "\n",data); return 0; } return 0; }
// Thie function use fork to create a child process. The child process tries to read MSR_KVM_API_MAGIC. // If the register exists, it is readable. Otherwise, it is not readable. // Return: 1 if bug exist, 0 if not sure. int test_msr_vm_hsave_pa() { pid_t pid; int status; if( (pid=fork()) < 0 ) { perror("fail to fork\n"); } if(pid==0) //child process { DPRINTF("DEBUG: Child: %s %d \n",__FUNCTION__,__LINE__); rdmsr_on_cpu(MSR_VM_HSAVE_PA,0); DPRINTF("DEBUG: Child: Bug Fixed: MSR_VM_HSAVE_PA is readable!\n"); exit(0); }else //parent process { wait(&status); if(WIFEXITED(status)) { if(WEXITSTATUS(status)) { DPRINTF("DEBUG: Parent: The return code of child process is non zero.\n"); DPRINTF("DEBUG: Parent: Bug Exists: MSR_VM_HSAVE_PA is not readable!\n"); return 1; } else { DPRINTF("DEBUG: Parent: The return code of child process is zero.\n"); DPRINTF("DEBUG: Parent: Bug Fixed: MSR_VM_HSAVE_PA is readable!\n"); return 0; //child process exit normally with exit code 0, which means the register is readable, so the bug is not existing. } }else { DPRINTF("DEBUG: Parent: Bug Exists: MSR_VM_HSAVE_PA is not readable!\n"); return 1; //child process exit abnormally, the register is not writable, so the bug is existing. } DPRINTF("DEBUG: Parent: %s %d \n",__FUNCTION__,__LINE__); } return 0; }
// Thie function use fork to create a child process. The child process tries to read MSR_CORE_PERF_GLOBAL_CTRL. // If the register exists, it is readable. Otherwise, it is not readable. // Return: 1 if feature exist, 0 if not sure. int test_pmu_v2() { pid_t pid; int status; if( (pid=fork()) < 0 ) { perror("fail to fork\n"); } if(pid==0) //child process { DPRINTF("DEBUG: Child: %s %d \n",__FUNCTION__,__LINE__); rdmsr_on_cpu(MSR_CORE_PERF_GLOBAL_CTRL,0); DPRINTF("DEBUG: Child: Feature Exists: MSR_CORE_PERF_GLOBAL_CTRL is readable!\n"); exit(0); }else //parent process { wait(&status); if(WIFEXITED(status)) // WIFEXITED(status) returns true if the child terminated normally { if(WEXITSTATUS(status)) // WEXITSTATUS(status) returns the exit status of the child. { DPRINTF("DEBUG: Parent: The return code of child process is non zero.\n"); DPRINTF("DEBUG: Parent: Feature not Exists: MSR_CORE_PERF_GLOBAL_CTRL is not readable!\n"); return 0; } else { DPRINTF("DEBUG: Parent: The return code of child process is zero.\n"); DPRINTF("DEBUG: Parent: Feature Exists: MSR_CORE_PERF_GLOBAL_CTRL is readable!\n"); return 1; //child process exit normally with exit code 0, which means the register is readable, so the bug is not existing. } }else { DPRINTF("DEBUG: Parent: Feature not Exists: MSR_CORE_PERF_GLOBAL_CTRL is not readable!\n"); return 0; //child process exit abnormally, the register is not readable, so the bug is existing. } DPRINTF("DEBUG: Parent: %s %d \n",__FUNCTION__,__LINE__); } return 0; }
static ssize_t show_temp(struct device *dev, struct device_attribute *devattr, char *buf) { u32 eax, edx; struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct platform_data *pdata = dev_get_drvdata(dev); struct temp_data *tdata = pdata->core_data[attr->index]; mutex_lock(&tdata->update_lock); /* Check whether the time interval has elapsed */ if (!tdata->valid || time_after(jiffies, tdata->last_updated + HZ)) { rdmsr_on_cpu(tdata->cpu, tdata->status_reg, &eax, &edx); tdata->valid = 0; /* Check whether the data is valid */ if (eax & 0x80000000) { tdata->temp = tdata->tjmax - ((eax >> 16) & 0x7f) * 1000; tdata->valid = 1; }
static struct pkgtemp_data *pkgtemp_update_device(struct device *dev) { struct pkgtemp_data *data = dev_get_drvdata(dev); unsigned int cpu; int err; mutex_lock(&data->update_lock); if (!data->valid || time_after(jiffies, data->last_updated + HZ)) { u32 eax, edx; data->valid = 0; cpu = data->id; err = rdmsr_on_cpu(cpu, MSR_IA32_PACKAGE_THERM_STATUS, &eax, &edx); if (!err) { data->alarm = (eax >> 5) & 1; data->temp = data->tjmax - (((eax >> 16) & 0x7f) * 1000); data->valid = 1; } else
static ssize_t show_trip_hyst(struct thermal_zone_device *tzd, int trip, long *hyst) { u32 eax, edx; struct thermal_device_info *td_info = tzd->devdata; /* Hysteresis is only supported for trip point 0 and 1. */ if (trip != 0 && trip != 1) return -EINVAL; mutex_lock(&td_info->lock_aux); rdmsr_on_cpu(0, MSR_THERM_CFG1, &eax, &edx); /* * B[11:13] C2H Hyst, for trip 0 * B[8:10] H2C Hyst, for trip 1 * Report hysteresis in mC */ if (trip == 0) *hyst = ((eax >> 11) & 0x7) * 1000; else
static ssize_t show_temp(struct device *dev, struct device_attribute *devattr, char *buf) { u32 eax, edx; struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct platform_data *pdata = dev_get_drvdata(dev); struct temp_data *tdata = pdata->core_data[attr->index]; mutex_lock(&tdata->update_lock); /* Check whether the time interval has elapsed */ if (!tdata->valid || time_after(jiffies, tdata->last_updated + HZ)) { rdmsr_on_cpu(tdata->cpu, tdata->status_reg, &eax, &edx); /* * Ignore the valid bit. In all observed cases the register * value is either low or zero if the valid bit is 0. * Return it instead of reporting an error which doesn't * really help at all. */ tdata->temp = tdata->tjmax - ((eax >> 16) & 0x7f) * 1000; tdata->valid = 1; tdata->last_updated = jiffies; }
int main(int argc, char *argv[]) { uint32_t reg; int c; int cpu = 0; unsigned long arg; char *endarg; program = argv[0]; while ((c = getopt_long(argc, argv, short_options, long_options, NULL)) != -1) { switch (c) { case 'h': usage(); exit(0); case 'V': fprintf(stderr, "%s: version %s\n", program, VERSION_STRING); exit(0); case 'x': mode = (mode & ~mo_mask) | mo_hex; break; case 'X': mode = (mode & ~mo_mask) | mo_chx; break; case 'o': mode = (mode & ~mo_mask) | mo_oct; break; case 'd': mode = (mode & ~mo_mask) | mo_dec; break; case 'r': mode = (mode & ~mo_mask) | mo_raw; break; case 'u': mode = (mode & ~mo_mask) | mo_uns; break; case 'c': mode |= mo_c; break; case '0': mode |= mo_fill; break; case 'a': cpu = -1; break; case 'p': arg = strtoul(optarg, &endarg, 0); if (*endarg || arg > 5119) { usage(); exit(127); } cpu = (int)arg; break; case 'f': if (sscanf(optarg, "%u:%u", &highbit, &lowbit) != 2 || highbit > 63 || lowbit > highbit) { usage(); exit(127); } break; default: usage(); exit(127); } } if (optind != argc - 1) { /* Should have exactly one argument */ usage(); exit(127); } reg = strtoul(argv[optind], NULL, 0); if (cpu == -1) { doing_for_all = 1; rdmsr_on_all_cpus(reg); } else rdmsr_on_cpu(reg, cpu); exit(0); }