The MASM Forum

General => The Laboratory => Topic started by: guga on December 31, 2015, 04:08:08 PM

Title: How to enable rdpmc from user mode ?
Post by: guga on December 31, 2015, 04:08:08 PM
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 ?

Title: Re: How to enable rdpmc from user mode ?
Post by: TouEnMasm on December 31, 2015, 08:11:51 PM
Try to compile the c or c++ code ,/Fa wil give the answer.
What did you call a user mode ?
Title: Re: How to enable rdpmc from user mode ?
Post by: sinsi on December 31, 2015, 10:59:57 PM
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.
Title: Re: How to enable rdpmc from user mode ?
Post by: guga on December 31, 2015, 11:01:52 PM
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.
Title: Re: How to enable rdpmc from user mode ?
Post by: guga on December 31, 2015, 11:05:56 PM
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);
}
Title: Re: How to enable rdpmc from user mode ?
Post by: sinsi on December 31, 2015, 11:53:25 PM
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.
*/
Title: Re: How to enable rdpmc from user mode ?
Post by: guga on January 02, 2016, 12:25:18 AM
Yep, it is for linux but i was wondering if it could be ported to windows