for register 0xC0010064 the values will be something like: 80|00|..|..|..|00|28|10. You need to modify the '28' (increase the value to undervolt). Do note that these values are in hex, so you count 28, 29, 2a, ..., 2f, 30 (i.e. 28->30 is eight steps!)
Wait, wait! Don't increase that 28 one by one, otherwise you are changing the frequency as well! Increase two by two! 28, 2A, 2C, 2E, 30. Bits 15 to 9 on the MSR are the vid, 8-4 the core frequency divisor most significant digit ! So 29 means a 1 in bit 8 (i.e. the previous to last two digits in the register are bits 15 to 8, and cover just a little bit more than the vid).
Note that you need to change pstate before your changes 'take'. I think rw-everything is scriptable, so you can make it apply the undervolted values automatically (you can even add it as a scheduled task on startup to avoid the UAC prompt!)
And that, when you apply, if a single core is in another P-state, then the CPU will choose the highest voltage (lowest vid) of both.
@thierryg: I created a little bash script for undervolting, simpler than compiling a program. It's something like:
cpufreq-selector -f 1600000
wrmsr -p0 0xC0010064 0x80000100003810 # note: bogus values from memory!
wrmsr -p1 0xC0010064 0x80000100003810
wrmsr -p0 0xC0010065 0x800002c0003c12
wrmsr -p1 0xC0010066 0x800002c0003c12
cpufreq-selector -f 800000
wrmsr -p0 0xC0010066 0x800002c0007432
wrmsr -p1 0xC0010066 0x800002c0007432
cpufreq-selector -g ondemand
Still need to find out how to run it as root at startup but I think this should work.
Run it from /etc/rc.local, for example.
Nice touch the use of cpufreq-selector. I left it out; it changes P-states often enough to have the changes apply sooner than later.
What I've done is a simple C program with has the following interface:
./undervolt -p 0:0x1A -p 1:0x1A -p 2:0x35
I'm slowly adding to it a cpu type check, a MSR status check, and maybe the switch to P-states to make sure the changes are applied. It's more involved than your shell script, but not by much.
I don't know of any libraries that provide access to wrmsr/rdmsr on windows. These are ring-0 instructions and require a (signed) kernel driver - something should exist but I haven't been able to find it yet. (I've only found out about WinIO but I don't think this provides access to those instructions).
Yes, I had a colleague brief me at lunch how messy it would be for me to use the x86 assembler instructions (rdmsr and wrmsr) instead of the msr kernel module