Quantcast
Channel: Intel Communities: Message List
Viewing all articles
Browse latest Browse all 22051

Re: How to get the values of on die digital thermal sensors for Atom D510?

$
0
0

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();
}


Viewing all articles
Browse latest Browse all 22051

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>