Dunno if its going to work on Geode but on desktop intel i use this.
You can do RDMSR only in interrupt handler, so just register the -1 timer interrupt and read the "ThermStatus" MSR now
and then.
You are interested in the "digital_readout" which SHOULD be core temperature in degree celsius.
Hope this helps..
#include <stdlib.h>
#include <sys/types.h>
#include <sys/kernel.h>
#include <sys/psinfo.h>
#include <sys/proxy.h>
#include <sys/irqinfo.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <time.h>
#include <stdio.h>
#include <errno.h>
typedef unsigned uint32_t;
typedef struct UINT64_T
{
uint32_t lo;
uint32_t hi;
} uint64_t;
typedef struct THERM_STATUS_T
{
union
{
struct
{
uint32_t thermal_status: 1;
uint32_t thermal_status_log: 1;
uint32_t prochot_forcepr: 1;
uint32_t prochot_forcepr_log: 1;
uint32_t out_of_spec_status: 1;
uint32_t out_of_spec_status_log: 1;
uint32_t thermal_threshold_status1: 1;
uint32_t thermal_threshold_status1_log: 1;
uint32_t thermal_threshold_status2: 1;
uint32_t thermal_threshold_status2_log: 1;
uint32_t reserved0: 6;
uint32_t digital_readout: 7;
uint32_t reserved1: 4;
uint32_t resolution_in_degrees_celsius: 4;
uint32_t reading_valid: 1;
uint32_t reserved2;
};
struct
{
uint32_t lo;
uint32_t hi;
};
};
} therm_status_t;
/* operation: EDX:EAX <- MSR[ECX] (ECX = t; out->lo = EAX, out->hi = EDX) */
void RDMSR (uint32_t t, uint64_t *out);
#pragma aux RDMSR = \
".586 " \
"rdmsr " \
"mov [ebx],eax " \
"mov [ebx+4],edx " \
parm [ecx] [ebx] \
modify exact [eax edx];
volatile pid_t timer_intr_proxy;
volatile int timer_intr_counter = 0;
volatile therm_status_t therm_status;
#pragma off(check_stack)
pid_t far intr_handler ()
{
if (++timer_intr_counter == 20)
{
timer_intr_counter = 0;
// 0x19c is ThermStatus register
RDMSR(0x19c, (uint64_t *)&therm_status);
return timer_intr_proxy;
}
return 0;
}
#pragma on(check_stack)
int main (int argc, char *argv [])
{
int timer_intr_id, rpid;
pid_t program_pid;
const char *program;
therm_status_t therm_status0, therm_status1;
program = (const char *)basename(argv[0]);
program_pid = getpid();
if ((timer_intr_proxy = qnx_proxy_attach(0, NULL, 0, -1)) == -1)
{
// error
return 1;
}
if (timer_intr_id = qnx_hint_attach(-1, &intr_handler, FP_SEG(&timer_intr_proxy)) == -1)
{
// error
return 1;
}
for (;;)
{
rpid = Receive(0, NULL, 0);
if (rpid == timer_intr_proxy)
{
// double read
therm_status0.lo = therm_status.lo;
therm_status0.hi = therm_status.hi;
therm_status1.lo = therm_status.lo;
therm_status1.hi = therm_status.hi;
// check double read
if ((therm_status0.lo == therm_status1.lo) && (therm_status0.hi == therm_status1.hi))
{
printf("%05d: %s: %s: %s=%d\n", program_pid, program, "therm_status", "thermal_status", therm_status0.
thermal_status);
printf("%05d: %s: %s: %s=%d\n", program_pid, program, "therm_status", "thermal_status_log", therm_status0.
thermal_status_log);
printf("%05d: %s: %s: %s=%d\n", program_pid, program, "therm_status", "prochot_forcepr", therm_status0.
prochot_forcepr);
printf("%05d: %s: %s: %s=%d\n", program_pid, program, "therm_status", "prochot_forcepr_log", therm_status0.
prochot_forcepr_log);
printf("%05d: %s: %s: %s=%d\n", program_pid, program, "therm_status", "out_of_spec_status", therm_status0.
out_of_spec_status);
printf("%05d: %s: %s: %s=%d\n", program_pid, program, "therm_status", "out_of_spec_status_log", therm_status0.
out_of_spec_status_log);
printf("%05d: %s: %s: %s=%d\n", program_pid, program, "therm_status", "thermal_threshold_status1", therm_status0.
thermal_threshold_status1);
printf("%05d: %s: %s: %s=%d\n",...
View Full Message