The example codes list here.
/*
* msrsup.c
*
* Created on: 25/lug/2013
* Author: MSangalli
*
* NOTES ABOUT CPU TEMPERATURES:
* Intel defines a certain Tjunction temperature for the processor.
* This value is usually in the range between 85癈 and 105癈.
* In the later generation of processors, starting with Nehalem, the exact
* Tjunction Max value is available for software to read in an MSR.
* A different MSR contains the temperature data.
* The data is represented as a Delta in 癈 between current temperature and Tjunction.
* So the actual temperature is calculated like this 'Core Temp = Tjunction - Delta'
* The size of the data field is 7 bits.
* This means a Delta of 0 - 127癈 can be reported in theory.
* In fact the reported temperature can rarely go below 0癈 and in some cases
* (Core 2 - 45nm series) temperatures below 30?or even 40癈 are not reported.
*
* AMD processors report the temperature via a special register in the CPU's northbridge.
* Core Temp reads the value from the register and uses a formula provided by AMD
* to calculate the current temperature.
* The formula for the Athlon 64 series, early Opterons and Semprons (K8 architecture) is:
* 'Core Temp = Value - 49'.
* For the newer generation of AMD processors like Phenom, Phenom II, newer Athlons,
* Semprons and Opterons (K10 architecture and up), and their derivatives, there is a
* different formula:
* 'CPU Temp* = Value / 8'.
* CPU Temp is because the Phenom\Opteron (K10) have only one sensor per package,
* meaning there is only one reading per processor.
*
* VIA processors are capable of reporting the temperature of each core.
* The thermal sensor provides an absolute temperature value in Celsius, there is
* no need for any conversion or manipulation.
* The Tjunction or TjMax temperature on VIA chips is usually between 70 and 90C.
* 90C for the mobile and low power versions and 70C is for the desktop variants.
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <err.h>
#include <x86/priv.h>
#include <sys/neutrino.h>
/*
* LOw WORD temperature into
*/
typedef struct x86_term_info
{
uint32_t th_sts: 1;
uint32_t th_sts_log: 1;
uint32_t prochot_forcepr: 1;
uint32_t prochot_forcepr_log: 1;
uint32_t out_of_spec_sts: 1;
uint32_t out_of_spec_sts_log: 1;
uint32_t th_threshold_status1: 1;
uint32_t th_threshold_status1_log: 1;
uint32_t th_threshold_status2: 1;
uint32_t th_threshold_status2_log: 1;
uint32_t reserved0: 6;
uint32_t dig_readout: 7;
uint32_t rsv1: 4;
uint32_t res_in_degrees_celsius: 4;
uint32_t rd_valid: 1;
uint32_t rsv2;
}X86_TERM_T;
typedef struct msr{
struct sigevent IntrEvent;
intrspin_t sLock;
int IntrId; // Int id
int msrOp; // Operation to do
volatile uint32_t reg_sel; // msr Register index
volatile uint64_t val64; // value to read/write
}MSR_T;
static MSR_T lv_msr;
static
const struct sigevent* msr_irq(void* area, int size)
{
/*
* rdmsr/wrmsr are privileged instruction that can be executed
* only in the kernel space, so use the interrupt to do the work.
*/
InterruptLock(&lv_msr.sLock );
{
switch(lv_msr.msrOp)
{
default:{;}break;
case 1:{
// Read MSR register
if ( lv_msr.reg_sel )
{
lv_msr.val64 = rdmsr( lv_msr.reg_sel );
lv_msr.reg_sel = 0;
}
}break;
case 2:{
// Write MSR register
if ( lv_msr.reg_sel )
{
wrmsr( lv_msr.reg_sel, lv_msr.val64 );
}
}break;
}
lv_msr.msrOp =0; //NOP
lv_msr.reg_sel=0;
}InterruptUnlock( &lv_msr.sLock );
return(&lv_msr.IntrEvent);
}
uint64_t x86_msr_read( uint32_t idx )
{
uint64_t res;
if(0 >= lv_msr.IntrId) return(-1);
// Set command
InterruptMask( 0, lv_msr.IntrId );
{
InterruptLock( &lv_msr.sLock );
{
lv_msr.reg_sel= idx;
lv_msr.msrOp =1;
}InterruptUnlock( &lv_msr.sLock );
}InterruptUnmask( 0, lv_msr.IntrId );
// Eventually, use a TimerTimeot here...
/*********************************************/
InterruptWait( 0, NULL );
/*********************************************/
// Read result
InterruptMask( 0, lv_msr.IntrId );
{
InterruptLock( &lv_msr.sLock );{
res = lv_msr.val64;
}InterruptUnlock( &lv_msr.sLock );
}InterruptUnmask( 0, lv_msr.IntrId );
return( res );
}
void x86_msr_write( uint32_t idx, uint64_t val )
{
if(0 >= lv_msr.IntrId) return;
// Set command
InterruptMask( 0, lv_msr.IntrId );{
InterruptLock( &lv_msr.sLock );{
lv_msr.val64= val;
lv_msr.reg_sel= idx;
lv_msr.msrOp = 2;
}InterruptUnlock( &lv_msr.sLock );
}InterruptUnmask( 0, lv_msr.IntrId );
// Eventually, use a TimerTimeot here...
/*********************************************/
InterruptWait( 0, NULL );
/*********************************************/
}
int x86_msr_init(void)
{
int res;
SIGEV_INTR_INIT( &lv_msr.IntrEvent );
if( 0 < (res= (InterruptAttach( 0, msr_irq, NULL, 0, 0 ))))
{
lv_msr.IntrId=res;
}
return(res);
}
void x86_msr_close(void)
{
int intid;
intid=lv_msr.IntrId;
lv_msr.IntrId=0;
if(0 >= intid) return;
(void)InterruptDetach(intid);
}
void x86_print_cpu_temp(void)
{
union {
X86_TERM_T info;
uint64_t temp;
}x;
int32_t th;
int j;
// Intel CPU temp: Core Temp = Tjunction - Delta
// This value is usually in the range between 85癈 and 105癈.
// Check if Tjunsction is available in MSR register
//
for(j=0; j < 100; j++){
x.temp=x86_msr_read(0x19c);
if( x.info.rd_valid) break; // temp is valid
}
printf("\nMSR[19C]: %08llx", x.temp);
th = (x.info.dig_readout);
printf(" C= %d@85/%d@105 +/-%d \n",85-th,105-th, x.info.res_in_degrees_celsius );
}
int main(void)
{
ThreadCtl(_NTO_TCTL_IO, NULL);
x86_msr_init();
x86_print_cpu_temp();
x86_msr_close();
}