Skip to content

Commit

Permalink
Adds APERF options, example fix, cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
rountree committed Sep 21, 2024
1 parent ae69acd commit 51890be
Show file tree
Hide file tree
Showing 3 changed files with 165 additions and 102 deletions.
66 changes: 63 additions & 3 deletions examples/example.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
#include <stdio.h> // printf(3)
#include <assert.h> // assert(3)
#include <fcntl.h> // open(2)
#include <unistd.h> // write(2), pwrite(2), pread(2)
#include <unistd.h> // write(2)
#include <string.h> // strlen(3), memset(3)
#include <stdint.h> // uint8_t
#include <inttypes.h> // PRIu8
Expand Down Expand Up @@ -49,7 +49,20 @@ void batch( void ){
b.version = MSR_SAFE_VERSION_u32;

struct msr_batch_op o[] = {
{ .cpu = 2, .op = OP_READ | OP_POLL | OP_INITIAL_MPERF | OP_FINAL_MPERF | OP_POLL_MPERF, .err = 0, .poll_max = 10000, .msr = 0x611, .msrdata = 0, .wmask = 0, .mperf_initial = 0, .mperf_poll = 0, .mperf_final = 0, .msrdata2 = 0 }
{ .cpu = 2,
.op = OP_READ | OP_POLL | OP_INITIAL_MPERF | OP_FINAL_MPERF | OP_POLL_MPERF | OP_INITIAL_APERF | OP_FINAL_APERF | OP_POLL_APERF,
.err = 0,
.poll_max = 10000,
.msr = 0x611,
.msrdata = 0,
.wmask = 0,
.mperf_initial = 0,
.mperf_poll = 0,
.mperf_final = 0,
.aperf_initial = 0,
.aperf_poll = 0,
.aperf_final = 0,
.msrdata2 = 0 }
};
b.numops = sizeof(o) / sizeof( struct msr_batch_op );
b.ops = o;
Expand All @@ -59,12 +72,19 @@ void batch( void ){
fd = open( "/dev/cpu/msr_batch", O_RDONLY );
assert(-1 != fd);

printf("cpu op err poll_max msr msrdata wmask mi mp mf ai ap af msrdata2\n");
for( size_t i=0; i<100000; i++ ){
o[0].poll_max = 10000;
rc = ioctl( fd, X86_IOC_MSR_BATCH, &b );
assert(-1 != rc);

printf("%llu %llu %llu %llu %u\n", o[0].mperf_poll, o[0].mperf_final, o[0].msrdata, o[0].msrdata2, o[0].poll_max);
// cpu op err p m md w mi mp mf ai ap af md2
printf("%hu %hu %d %u %u %llu %llu %llu %llu %llu %llu %llu %llu %llu\n",
o[0].cpu, o[0].op, o[0].err, o[0].poll_max, o[0].msr, o[0].msrdata, o[0].wmask,
o[0].mperf_initial, o[0].mperf_poll, o[0].mperf_final,
o[0].aperf_initial, o[0].aperf_poll, o[0].aperf_final,
o[0].msrdata2);

}
close( fd );
}
Expand All @@ -75,3 +95,43 @@ int main()
batch();
return 0;
}
/*
struct msr_batch_op
{
__u16 cpu; // In: CPU to execute {rd/wr}msr instruction
__u16 op; // In: OR at least one of the following:
// OP_WRITE, OP_READ, OP_POLL, OP_INITIAL_MPERF,
// OP_FINAL_MPERF, OP_POLL_MPERF
// OP_INITIAL_APERF, OP_FINAL_APERF, OP_POLL_APERF
__s32 err; // Out: set if error occurred with this operation
__u32 poll_max; // In/Out: Max/remaining poll attempts
__u32 msr; // In: MSR Address to perform operation
__u64 msrdata; // In/Out: Input/Result to/from operation
__u64 wmask; // Out: Write mask applied to wrmsr
__u64 mperf_initial; // Out: reference clock reading at the start of the op
__u64 mperf_poll; // Out: reference clock reading at start of final poll
__u64 mperf_final; // Out: reference clock reading at the end of r/w/p
__u64 aperf_initial; // Out: cycle count reading at the start of the op
__u64 aperf_poll; // Out: cycle count reading at start of final poll
__u64 aperf_final; // Out: cycle count reading at the end of r/w/p
__u64 msrdata2; // Out: last polled reading
};
typedef __signed__ char __s8;
typedef unsigned char __u8;
typedef __signed__ short __s16;
typedef unsigned short __u16;
typedef __signed__ int __s32;
typedef unsigned int __u32;
#ifdef __GNUC__
__extension__ typedef __signed__ long long __s64;
__extension__ typedef unsigned long long __u64;
#else
typedef __signed__ long long __s64;
typedef unsigned long long __u64;
#endif
*/

154 changes: 75 additions & 79 deletions msr-smp.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,8 @@ static void __msr_safe_batch(void *info)
struct msr_batch_array *oa = info;
struct msr_batch_op *op;
int this_cpu = smp_processor_id();
u64 rdval, wrval, mperfval, pollval;
u32 *rdptr=(u32 *)&rdval, *wrptr=(u32 *)&wrval, *mperfptr=(u32 *)&mperfval, *pollptr=(u32 *)&pollval;
/*
u64 oldmsr;
u64 newmsr;
*/
u64 rdval, wrval, mperfval, aperfval, pollval;
u32 *rdptr=(u32 *)&rdval, *wrptr=(u32 *)&wrval, *mperfptr=(u32 *)&mperfval, *aperfptr=(u32 *)&aperfval, *pollptr=(u32 *)&pollval;

for (op = oa->ops; op < oa->ops + oa->numops; ++op)
{
Expand All @@ -41,82 +37,82 @@ static void __msr_safe_batch(void *info)
}

op->err = 0;
/*
dp = (u32 *)&oldmsr;
if (rdmsr_safe(op->msr, &dp[0], &dp[1]))
{
op->err = -EIO;
continue;

if ( op->op & OP_INITIAL_MPERF ){
if ( rdmsr_safe( MSR_IA32_MPERF, &mperfptr[0], &mperfptr[1] )){
op->err = -EIO;
continue;
}
op->mperf_initial = mperfval;
}
if (op->isrdmsr)
{
op->msrdata = oldmsr;
continue;
if ( op->op & OP_INITIAL_APERF ){
if ( rdmsr_safe( MSR_IA32_APERF, &aperfptr[0], &aperfptr[1] )){
op->err = -EIO;
continue;
}
op->aperf_initial = aperfval;
}
newmsr = op->msrdata & op->wmask;
newmsr |= (oldmsr & ~op->wmask);
dp = (u32 *)&newmsr;
if (wrmsr_safe(op->msr, dp[0], dp[1]))
{
op->err = -EIO;
if ( op->op & OP_WRITE || op->op & OP_READ || op->op & OP_POLL ){
if ( rdmsr_safe( op->msr, &rdptr[0], &rdptr[1] )){
op->err = -EIO;
continue;
}
if ( op->op & OP_READ || op->op & OP_POLL ){
op->msrdata = rdval;
}
}
if ( op->op & OP_WRITE ){
wrval = op->msrdata & op->wmask;
wrval |= rdval & ~op->wmask;
if ( wrmsr_safe( op->msr, wrptr[0], wrptr[1] ) ){
op->err = -EIO;
continue;
}
}
if ( op->op & OP_POLL ){
while(1){
if( 0 == op->poll_max ){
break;
}
op->poll_max--;
if ( op->op & OP_POLL_MPERF ){
if ( rdmsr_safe( MSR_IA32_MPERF, &mperfptr[0], &mperfptr[1] )){
op->err = -EIO;
continue;
}
op->mperf_poll = mperfval;
}
if ( op->op & OP_POLL_APERF ){
if ( rdmsr_safe( MSR_IA32_APERF, &aperfptr[0], &aperfptr[1] )){
op->err = -EIO;
continue;
}
op->aperf_poll = mperfval;
}
if ( rdmsr_safe( op->msr, &pollptr[0], &pollptr[1] )){
op->err = -EIO;
continue;
}
if ( pollval != rdval ){
op->msrdata2 = pollval;
break;
}
}
}
if ( op->op & OP_FINAL_APERF ){
if ( rdmsr_safe( MSR_IA32_APERF, &aperfptr[0], &aperfptr[1] )){
op->err = -EIO;
continue;
}
op->mperf_final = aperfval;
}
if ( op->op & OP_FINAL_MPERF ){
if ( rdmsr_safe( MSR_IA32_MPERF, &mperfptr[0], &mperfptr[1] )){
op->err = -EIO;
continue;
}
op->mperf_final = mperfval;
}
*/

if ( op->op & OP_INITIAL_MPERF ){
if ( rdmsr_safe( MSR_IA32_MPERF, &mperfptr[0], &mperfptr[1] )){
op->err = -EIO;
continue;
}
op->mperf_initial = mperfval;
}
if ( op->op & OP_WRITE || op->op & OP_READ || op->op & OP_POLL ){
if ( rdmsr_safe( op->msr, &rdptr[0], &rdptr[1] )){
op->err = -EIO;
continue;
}
if ( op->op & OP_READ || op->op & OP_POLL ){
op->msrdata = rdval;
}
}
if ( op->op & OP_WRITE ){
wrval = op->msrdata & op->wmask;
wrval |= rdval & ~op->wmask;
if ( wrmsr_safe( op->msr, wrptr[0], wrptr[1] ) ){
op->err = -EIO;
continue;
}
}
if ( op->op & OP_POLL ){
while(1){
if( 0 == op->poll_max ){
break;
}
op->poll_max--;
if ( op->op & OP_POLL_MPERF ){
if ( rdmsr_safe( MSR_IA32_MPERF, &mperfptr[0], &mperfptr[1] )){
op->err = -EIO;
continue;
}
op->mperf_poll = mperfval;
}
if ( rdmsr_safe( op->msr, &pollptr[0], &pollptr[1] )){
op->err = -EIO;
continue;
}
if ( pollval != rdval ){
op->msrdata2 = pollval;
break;
}
}
}
if ( op->op & OP_FINAL_MPERF ){
if ( rdmsr_safe( MSR_IA32_MPERF, &mperfptr[0], &mperfptr[1] )){
op->err = -EIO;
continue;
}
op->mperf_final = mperfval;
}
}
}

Expand Down
47 changes: 27 additions & 20 deletions msr_safe.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,34 +18,41 @@
#include <linux/ioctl.h>
#include <linux/types.h>

#define OP_WRITE 0x01
#define OP_READ 0x02
#define OP_POLL 0x04
#define OP_INITIAL_MPERF 0x10
#define OP_FINAL_MPERF 0x20
#define OP_POLL_MPERF 0x40
#define OP_WRITE 0x0001
#define OP_READ 0x0002
#define OP_POLL 0x0004
#define OP_INITIAL_MPERF 0x0010
#define OP_FINAL_MPERF 0x0020
#define OP_POLL_MPERF 0x0040
#define OP_INITIAL_APERF 0x0100
#define OP_FINAL_APERF 0x0200
#define OP_POLL_APERF 0x0400

struct msr_batch_op
{
__u16 cpu; // In: CPU to execute {rd/wr}msr instruction
__u16 op; // In: OR at least one of the following:
// OP_WRITE, OP_READ, OP_POLL, OP_INITIAL_MPERF,
// OP_FINAL_MPERF, OP_POLL_MPERF
__s32 err; // Out: set if error occurred with this operation
__u32 poll_max; // In/Out: Max/remaining poll attempts
__u32 msr; // In: MSR Address to perform operation
__u64 msrdata; // In/Out: Input/Result to/from operation
__u64 wmask; // Out: Write mask applied to wrmsr
__u64 mperf_initial;// Out: reference clock reading at the start of the op
__u64 mperf_poll; // Out: reference clock reading at start of final poll
__u64 mperf_final; // Out: reference clock reading at the end of r/w/p
__u64 msrdata2; // Out: last polled reading
__u16 cpu; // In: CPU to execute {rd/wr}msr instruction
__u16 op; // In: OR at least one of the following:
// OP_WRITE, OP_READ, OP_POLL, OP_INITIAL_MPERF,
// OP_FINAL_MPERF, OP_POLL_MPERF
// OP_INITIAL_APERF, OP_FINAL_APERF, OP_POLL_APERF
__s32 err; // Out: set if error occurred with this operation
__u32 poll_max; // In/Out: Max/remaining poll attempts
__u32 msr; // In: MSR Address to perform operation
__u64 msrdata; // In/Out: Input/Result to/from operation
__u64 wmask; // Out: Write mask applied to wrmsr
__u64 mperf_initial; // Out: reference clock reading at the start of the op
__u64 mperf_poll; // Out: reference clock reading at start of final poll
__u64 mperf_final; // Out: reference clock reading at the end of r/w/p
__u64 aperf_initial; // Out: cycle count reading at the start of the op
__u64 aperf_poll; // Out: cycle count reading at start of final poll
__u64 aperf_final; // Out: cycle count reading at the end of r/w/p
__u64 msrdata2; // Out: last polled reading
};

struct msr_batch_array
{
__u32 numops; // In: # of operations in operations array
__u32 version; // In: MSR_SAFE_VERSION_u32 (see msr_version.h)
__u32 version; // In: MSR_SAFE_VERSION_u32 (see msr_version.h)
struct msr_batch_op *ops; // In: Array[numops] of operations
};

Expand Down

0 comments on commit 51890be

Please sign in to comment.