From 51890be7484752cf8f120cc32322803e233a95cc Mon Sep 17 00:00:00 2001 From: Barry Date: Sat, 21 Sep 2024 16:41:20 -0700 Subject: [PATCH] Adds APERF options, example fix, cleanup --- examples/example.c | 66 ++++++++++++++++++- msr-smp.c | 154 ++++++++++++++++++++++----------------------- msr_safe.h | 47 ++++++++------ 3 files changed, 165 insertions(+), 102 deletions(-) diff --git a/examples/example.c b/examples/example.c index 6a16af1..a950455 100644 --- a/examples/example.c +++ b/examples/example.c @@ -19,7 +19,7 @@ #include // printf(3) #include // assert(3) #include // open(2) -#include // write(2), pwrite(2), pread(2) +#include // write(2) #include // strlen(3), memset(3) #include // uint8_t #include // PRIu8 @@ -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; @@ -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 ); } @@ -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 +*/ + diff --git a/msr-smp.c b/msr-smp.c index 3656c14..3767fbd 100644 --- a/msr-smp.c +++ b/msr-smp.c @@ -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) { @@ -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; - } } } diff --git a/msr_safe.h b/msr_safe.h index 5c540cc..59e0041 100644 --- a/msr_safe.h +++ b/msr_safe.h @@ -18,34 +18,41 @@ #include #include -#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 };