Hi guys
Reading Agner´s fog paper i saw the instruction rdpmc can be used as a benchmark counter as well. The problem is...how to use it under user mode ? I don´t want to make a driver only to read this.
I saw these paper that supposedly allos the instruction to operate in user mode, but i didn´t understood the proper syntax
http://www.btday.com/rdpmc-in-user-mode-does-not-work-even-with-pce-set/
On this one, it don´t know how to port to windows
http://sourceforge.net/p/perfmon2/libpfm4/ci/d77777d58644a1f49721fbd8498ad14d63aa7fc1/tree/perf_examples/self_count.c#l38
and also
http://www.cse.psu.edu/~deh25/rabbit/pmc_able.c
Someone ever tried to use this rdpmc on user mode for benchmark testings ?
Try to compile the c or c++ code ,/Fa wil give the answer.
What did you call a user mode ?
Access to RDPMC is controlled via CR4 but user land can't even MOV EAX,CR4 to test the bit since CR4 is only accessible in ring 0.
Looks like Linux has a function to enable it but Windows doesn't.
I mean the Not protected one. So i can try to use the instructin without having to create a driver for it. I mean, creating a executable or a dll and using it in a normal app.
I tried to compile but it is not working :( said /fI requires an argument. And when i tried again without it, but it can´t compile under windows.
Hi Sinsi, yep, it seems to be only in ring0, but it seems that CR4 can be enabled somehow.
I´m trying to port some function i´m finding to windows but,....unsuccessfully
I found another one:
http://www.btday.com/rdpmc-in-user-mode-does-not-work-even-with-pce-set/
/*
* Read PMC in kernel mode.
*/
#include <linux/module.h> /* Needed by all modules */
#include <linux/kernel.h> /* Needed for KERN_INFO */
static void printc4(void) {
typedef long unsigned int uint64_t;
uint64_t output;
// Read back CR4 to check the bit.
__asm__("\t mov %%cr4,%0" : "=r"(output));
printk(KERN_INFO "%lu", output);
}
static void setc4b8(void * info) {
// Set CR4, Bit 8 (9th bit from the right) to enable
__asm__("push %rax\n\t"
"mov %cr4,%rax;\n\t"
"or $(1 << 8),%rax;\n\t"
"mov %rax,%cr4;\n\t"
"wbinvd\n\t"
"pop %rax"
);
// Check which CPU we are on:
printk(KERN_INFO "Ran on Processor %d", smp_processor_id());
printc4();
}
static void clearc4b8(void * info) {
printc4();
__asm__("push %rax\n\t"
"push %rbx\n\t"
"mov %cr4,%rax;\n\t"
"mov $(1 << 8), %rbx\n\t"
"not %rbx\n\t"
"and %rbx, %rax;\n\t"
"mov %rax,%cr4;\n\t"
"wbinvd\n\t"
"pop %rbx\n\t"
"pop %rax\n\t"
);
printk(KERN_INFO "Ran on Processor %d", smp_processor_id());
}
int init_module(void)
{
on_each_cpu(setc4b8, NULL, 0);
return 0;
}
void cleanup_module(void)
{
on_each_cpu(clearc4b8, NULL, 0);
}
To enable RDPMC from ring 3 you need access to CR4, but only ring 0 can access CR4.
That last bit of code you posted is for Linux, also the comment
Quote from: guga on December 31, 2015, 11:05:56 PM
/*
* Read PMC in kernel mode.
*/
Yep, it is for linux but i was wondering if it could be ported to windows