Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Undervolting Through Hex Editor- SimpleMining

• Member Posts: 25
edited August 2017
I am a complete novice to this, so I am still figuring out what happened. I think I just had a bit of a breakthrough, which I am sharing for those who are learning like me.

The code @wolf0 added in the VOI to do the offset was: D2 00 00 00 E6 00 F4 00

I don't know that I yet understand what D2 00 00 00 does, but I think it has to do with selecting the right "loop" - though I have no idea what that is.

It appears E6 00 F4 00 is where the -75mv magic is happening.

Referencing the data sheet for the regulator (NCP81022) I discovered that the E6 register is "special purpose offset" (a.k.a the Wolf0 register). Apparently the format in hex is to address register, 0xE6, then follow with 0x00, then data you're putting in the register, 0xF4, followed by 0x00. The F4 confused me for a while but knowing Wolf0 set offset to -75mV and talked about two's compliment in the past I started messing with hex/bin/dec calculators. Here's what it means:

0xF4 -> binary = 11110100
binary -> two's complement: 00001100
binary -> two's complement decimal: -12

So, -12. What the heck is that!? Then I remembered offsets are multiples of 6.25mv. Sure enough -12 * 6.25 = -75.

So, @Wolf0, if "stock" voltage is 1000mV and I want card at ~810 I want my offset the E6 register to be -30 (-30 * 6.25 = -187.5, 1000mv - 187.5mv = 812.5mv). To set E6 to -30 I should send it 0x22? Is that right?

• Member Posts: 329 ✭✭✭
rhaegon said:

I remember when i modded my own BIOS (i had also NCP80122 VRM) and it worked for me only adding E6 00 XX 00 , D2 00 00 00 part wasn't necessary on my RX570 Nitro+, weird. I wish my uP9505 were so easy as NCP80122

Now that I think about it - the NCP81022's registers are NOT cleared on a warm boot. Naomi probably still had junk in 0xD2 - which meant I had to reset it before doing my undervolt. This could probably be omitted.
mike_do said:

I am a complete novice to this, so I am still figuring out what happened. I think I just had a bit of a breakthrough, which I am sharing for those who are learning like me.

The code @wolf0 added in the VOI to do the offset was: D2 00 00 00 E6 00 F4 00

I don't know that I yet understand what D2 00 00 00 does, but I think it has to do with selecting the right "loop" - though I have no idea what that is.

It appears E6 00 F4 00 is where the -75mv magic is happening.

Referencing the data sheet for the regulator (NCP81022) I discovered that the E6 register is "special purpose offset" (a.k.a the Wolf0 register). Apparently the format in hex is to address register, 0xE6, then follow with 0x00, then data you're putting in the register, 0xF4, followed by 0x00. The F4 confused me for a while but knowing Wolf0 set offset to -75mV and talked about two's compliment in the past I started messing with hex/bin/dec calculators. Here's what it means:

0xF4 -> binary = 11110100
binary -> two's complement: 00001100
binary -> two's complement decimal: -12

So, -12. What the heck is that!? Then I remembered offsets are multiples of 6.25mv. Sure enough -12 * 6.25 = -75.

So, @Wolf0, if "stock" voltage is 1000mV and I want card at ~810 I want my offset the E6 register to be -30 (-30 * 6.25 = -187.5, 1000mv - 187.5mv = 812.5mv). To set E6 to -30 I should send it 0x22? Is that right?

Nulling out 0xD2 sets it to a sane initial value, and likely could be omitted - see my comment above.

And... please, do NOT do that. -30 (-187.5mV) would be 226 decimal, or 0xE2. Setting 0x22 would not be -187.5mV, but rather +212.5mV. That ASIC would be dead before you could say "oops" after starting the miner xD
• Member Posts: 25
Well, glad I waited for your response. Thank you. Again.

One more question, is all the work you did further up in the VBIOS (related to better default values) necessary or just good practice that isn't mandatory? I am having a hard time understanding what you did there and don't know whether it's worth spending time trying to reverse engineer things. If it's superfluous to the larger discussion I am happy to drop the topic.

• Member Posts: 329 ✭✭✭
edited August 2017
mike_do said:

Well, glad I waited for your response. Thank you. Again.

One more question, is all the work you did further up in the VBIOS (related to better default values) necessary or just good practice that isn't mandatory? I am having a hard time understanding what you did there and don't know whether it's worth spending time trying to reverse engineer things. If it's superfluous to the larger discussion I am happy to drop the topic.

PROBABLY not mandatory. Just make sure you cold boot your rig. What I had done was - I had warm booted Naomi after one of my failed attempts... this probably clobbered 0xD2, which resulted in my successful attempt modifying the offset of the secondary rail - NOT the primary one. Since jack shit was on it - no effect. So I fixed it by setting 0xD2 to a sane default before doing the offset. Fun fact: On some of my XFX cards, their VDDCI won't change by modding PowerPlay... because it's on the aux rail of the NCP81022. You can offset their VDDCI by doing 0xD2 0x04 0xE6 0xXX - where the 0xXX is your desired offset.

EDIT: Changing the I2C address and the sizes were TOTALLY necessary, however.
Post edited by Wolf0 on
• Member Posts: 25
All is working well! Turns out -187.5mV was too much so I am stepping it down one-by-one to find the sweet spot.

@wolf0 does the work you did w/ offsets apply to memory voltage as well? My monitoring software doesn't seem to log that voltage, so I cannot tell.
• Member Posts: 329 ✭✭✭
mike_do said:

All is working well! Turns out -187.5mV was too much so I am stepping it down one-by-one to find the sweet spot.

@wolf0 does the work you did w/ offsets apply to memory voltage as well? My monitoring software doesn't seem to log that voltage, so I cannot tell.

Nope. Since you seem to be truly interested in the mechanics and such - I will show you why not. Dug up an older screenshot of mine that shows my tool's information on the VRM controller configuration of the GPUs, and the status of said VRM controllers (NSFW): http://i.imgur.com/2HfZoEI.jpg

You probably don't see any output of any VRM controller anywhere near the usual levels that would be needed to feed MVDDC on GDDR5. If you do, lemme know, cause I need my eyes checked, in that case! That pic was chosen to show that even on such a varied set of Polaris cards... not fucking ONE of them has MVDDC on a VRM controller that is on the I2C bus.

Fun fact: I own a DirectCU II 290X which DOES have MVDDC control capability (had to write the little "handler/driver" in for that one custom, but I can't bitch too much - the uP1801 has very few features to support, and is... dead simple compared to all the others I support) through quite the interesting config - IR3567B with the main rail feeding core, aux rail unused... but there's something else on the bus! It's a little uP1801! I honestly consider it as "half a VRM controller" in my head, due to its stunning simplicity - but it doesn't need to be complex, because it has just one job - feed MVDDC. As it's on the bus, I simply had to study it & pull the specs - I ended up needing to write only three functions for its (near full) support: uP1801Detect, uP1801GetVoltage, & uP1801SetVoltage. All controlllers I support require a "Detect" function, which basically goes to the GPU, accesses the I2C bus, and attempts to locate the given VRM controller at any address it is capable of residing at with a reasonable degree of accuracy... but I'm rambling now.
• Member Posts: 25
@Wolf0 That NSFW was spicy!

Given the Polaris MVDDC shortcoming how do you address memory undervolting? I've seen some hacks in Linux with custom kernels ... maybe that's how you get there?
• Member Posts: 329 ✭✭✭
mike_do said:

@Wolf0 That NSFW was spicy!

Given the Polaris MVDDC shortcoming how do you address memory undervolting? I've seen some hacks in Linux with custom kernels ... maybe that's how you get there?

Dropping MVDDC would be stupid - what *really* pulls the watts is the ASIC, and often, I find my Ethash hashrate on Polaris limited more by the memory than the core... in this case, you'd wanna RAISE the MVDDC.

But I don't think you understood my last post completely... no kernel mod will help you. My tool shown is damn near as low level as you can get (actually is lower-level than the Linux kernel driver, which I think uses either ATOM command tables, or the SMC firmware for this, which doesn't offer it much control over other, sometimes incredibly useful, abilities the VRM controller may have!) As such - you need to break out a soldering iron, or go home.
• Member Posts: 25
edited August 2017
In one of the Polaris Bios Editors you can set memory voltage and it does edit the BIOS as shown in the attached screen shot (E8 03 -> 34 04, 1000mv -> 820mv). It does this in the powerplay table (purple highlight). However it doesn't seem to stick. Must be overridden by something in software...

• Member Posts: 329 ✭✭✭
mike_do said:

In one of the Polaris Bios Editors you can set memory voltage and it does edit the BIOS as shown in the attached screen shot (E8 03 -> 34 04, 1000mv -> 820mv). It does this in the powerplay table (purple highlight). However it doesn't seem to stick. Must be overridden by something in software...

You can use OhGodATool to edit the exact same field.... and MANY others PBE won't let you touch. It simply is ignored. The field is there - but is simply not honored AT ALL, by anything. Like I said - soldering iron or you ain't changing shit.
• Member Posts: 25
edited August 2017
Wolf0 said:

The field is there - but is simply not honored AT ALL, by anything. Like I said - soldering iron or you ain't changing shit.

What I don't understand is why I can use something like WattTool (in windows) to undervolt memory. What process does WattTool use to accomplish what doesn't exist physically on the PCB and is generally ignored on VBIOS? I assume there's an AMD API it's calling, but then what can the API do that we couldn't do low-level or via VBIOS settings?
• Member Posts: 329 ✭✭✭
edited August 2017
mike_do said:

Wolf0 said:

The field is there - but is simply not honored AT ALL, by anything. Like I said - soldering iron or you ain't changing shit.

What I don't understand is why I can use something like WattTool (in windows) to undervolt memory. What process does WattTool use to accomplish what doesn't exist physically on the PCB and is generally ignored on VBIOS? I assume there's an AMD API it's calling, but then what can the API do that we couldn't do low-level or via VBIOS settings?
Simple - it doesn't. What you see as "memory" is actually the IMC, which is on the ASIC. Integrated Memory Controller. MVDDC & VDDCI are often mixed up.
• Member Posts: 25
edited August 2017
Wolf0 said:

mike_do said:

Wolf0 said:

The field is there - but is simply not honored AT ALL, by anything. Like I said - soldering iron or you ain't changing shit.

What I don't understand is why I can use something like WattTool (in windows) to undervolt memory. What process does WattTool use to accomplish what doesn't exist physically on the PCB and is generally ignored on VBIOS? I assume there's an AMD API it's calling, but then what can the API do that we couldn't do low-level or via VBIOS settings?
Simple - it doesn't. What you see as "memory" is actually the IMC, which is on the ASIC. Integrated Memory Controller. MVDDC & VDDCI are often mixed up.
Obviously an important distinction. Thanks for making it.

Here's where I landed:

Card: Sapphire RX470 (w/ NCP81022)
ROM: custom w/ @Wolf0 help, -24 offset = -150mv
Clock: 1100
Memory: 1940 (1500 straps)
Watts at wall: 137w. System watts: 43w. Implied GPU watts: 94w.
Ethash hashrate: 25.42MH/s (method: ethminer -G -M)

This is great because I can theoretically plop the card in Linux now and not have to worry about any software settings. I can also use the new blockchain drivers (as above) on Windows! Woohoo!

I also re-tested my old (not offset) ROM with the 16.9.2 drivers so that I could play with WattTool settings (which don't work with the blockchain drivers), specifically the Memory section mV. I was able to get watt-at-wall down to 131w implying GPU watts of 87w. I appears that undervolting the IMC via WattTool can save some power with negligible impact, so this is a topic for further exploration on Linux.

@Wolf0 - I also learned the hard versus soft restart lesson. To all those reading: when playing with ROMs it's better to hard reset (power down) so latent settings don't carry across sessions.

One more big thank you to Wolf0. You're awesome. And, as I learned, spicy too.
• Member Posts: 329 ✭✭✭
mike_do said:

Wolf0 said:

mike_do said:

Wolf0 said:

The field is there - but is simply not honored AT ALL, by anything. Like I said - soldering iron or you ain't changing shit.

What I don't understand is why I can use something like WattTool (in windows) to undervolt memory. What process does WattTool use to accomplish what doesn't exist physically on the PCB and is generally ignored on VBIOS? I assume there's an AMD API it's calling, but then what can the API do that we couldn't do low-level or via VBIOS settings?
Simple - it doesn't. What you see as "memory" is actually the IMC, which is on the ASIC. Integrated Memory Controller. MVDDC & VDDCI are often mixed up.
Obviously an important distinction. Thanks for making it.

Here's where I landed:

Card: Sapphire RX470 (w/ NCP81022)
ROM: custom w/ @Wolf0 help, -24 offset = -150mv
Clock: 1100
Memory: 1940 (1500 straps)
Watts at wall: 137w. System watts: 43w. Implied GPU watts: 94w.
Ethash hashrate: 25.42MH/s (method: ethminer -G -M)

This is great because I can theoretically plop the card in Linux now and not have to worry about any software settings. I can also use the new blockchain drivers (as above) on Windows! Woohoo!

I also re-tested my old (not offset) ROM with the 16.9.2 drivers so that I could play with WattTool settings (which don't work with the blockchain drivers), specifically the Memory section mV. I was able to get watt-at-wall down to 131w implying GPU watts of 87w. I appears that undervolting the IMC via WattTool can save some power with negligible impact, so this is a topic for further exploration on Linux.

@Wolf0 - I also learned the hard versus soft restart lesson. To all those reading: when playing with ROMs it's better to hard reset (power down) so latent settings don't carry across sessions.

One more big thank you to Wolf0. You're awesome. And, as I learned, spicy too.
Indeed - a lot of people are offended because I'm usually bluntly honest, but it's not like I won't help someone who really does want to learn & is capable of it. By the by - if you wanna change VDDCI on Linux, just use OhGodATool's -f switch (instead of -i) to write the changes to a VBIOS file. Then select a state to modify, and do so with the provided command line option (--help should show all of 'em.) Then fix the VBIOS checksum and flash. This has worked for me on every one of my Polaris cards except the odd XFX ones - the ones with VDDCI fed by the aux (NB) rail of the NCP81022... that one I had to do by paw at runtime.
• Member Posts: 3
Wolf0 said:

Indeed - a lot of people are offended because I'm usually bluntly honest, but it's not like I won't help someone who really does want to learn & is capable of it. By the by - if you wanna change VDDCI on Linux, just use OhGodATool's -f switch (instead of -i) to write the changes to a VBIOS file. Then select a state to modify, and do so with the provided command line option (--help should show all of 'em.) Then fix the VBIOS checksum and flash. This has worked for me on every one of my Polaris cards except the odd XFX ones - the ones with VDDCI fed by the aux (NB) rail of the NCP81022... that one I had to do by paw at runtime.

Hi wolf0,

Didn't know about yours OhGodATool, looks awesome, i've been testing and it seems like you can "undervolt" each DPM stage, does it work in linux? Normally i would prefer to add the offset to the VoI like i did with my NCP80122 but i want this for my other VGA with uP9505.

This is what i did:

Did you tried this on yours uP9505? Will it work? I would test by myself but since my MSI RX570 (the one with uP9505) and does not have dual bios i don't want to test without being sure.
• Member Posts: 329 ✭✭✭
rhaegon said:

Wolf0 said:

Indeed - a lot of people are offended because I'm usually bluntly honest, but it's not like I won't help someone who really does want to learn & is capable of it. By the by - if you wanna change VDDCI on Linux, just use OhGodATool's -f switch (instead of -i) to write the changes to a VBIOS file. Then select a state to modify, and do so with the provided command line option (--help should show all of 'em.) Then fix the VBIOS checksum and flash. This has worked for me on every one of my Polaris cards except the odd XFX ones - the ones with VDDCI fed by the aux (NB) rail of the NCP81022... that one I had to do by paw at runtime.

Hi wolf0,

Didn't know about yours OhGodATool, looks awesome, i've been testing and it seems like you can "undervolt" each DPM stage, does it work in linux? Normally i would prefer to add the offset to the VoI like i did with my NCP80122 but i want this for my other VGA with uP9505.

This is what i did:

Did you tried this on yours uP9505? Will it work? I would test by myself but since my MSI RX570 (the one with uP9505) and does not have dual bios i don't want to test without being sure.
Driver not gonna honor it, but give it a shot! Will prove AMDGPU kinda almost ignores the voltage portions of PowerPlayInfo.
• Member Posts: 4
hi, i have xfx 570 4g with NCP81022
`1C 00 03 01 01 07 0C 00 0E 00 00 00 00 00 00 00 04 07 0C 00 0E 00 00 00 00 00 00 00`
try add D2 00 02 00 E6 00 04 00 not work
`2A 00 03 01 01 03 0E 00 D2 00 04 00 E6 00 04 00 FF 00 01 07 0C 00 0E 00 00 00 00 00 00 00 04 07 0C 00 0E 00 00 00 00 00 00 00`
tell me my mistake, pls...
• Member Posts: 19
hi guys, can anyone help me with the Asus ASP1106 VRM (rebranded RT8894A) bios mod to set the voltage offset properly ?
there is a note in this thread, that the register 0x00 needs some value to put in:
http://www.overclock.net/t/1621800/would-appreciate-help-in-finding-editing-the-voltage-offset-in-the-rx480-bios/200
but that bitch is ignoring the 0x00 register settings from bios for any reason or i'm stupid to understand what is written in the DS
http://www.richtek.com/assets/product_file/RT8894A/DS8894A-05.pdf
thanks
• Member Posts: 35
mike_do said:

This is great because I can theoretically plop the card in Linux now and not have to worry about any software settings. I can also use the new blockchain drivers (as above) on Windows! Woohoo!

I also re-tested my old (not offset) ROM with the 16.9.2 drivers so that I could play with WattTool settings (which don't work with the blockchain drivers), specifically the Memory section mV. I was able to get watt-at-wall down to 131w implying GPU watts of 87w. I appears that undervolting the IMC via WattTool can save some power with negligible impact, so this is a topic for further exploration on Linux.

@Wolf0 - I also learned the hard versus soft restart lesson. To all those reading: when playing with ROMs it's better to hard reset (power down) so latent settings don't carry across sessions.

One more big thank you to Wolf0. You're awesome. And, as I learned, spicy too.

hi guys. Is this approach with current amdgpu-drivers on linux still needed? To me it looks like tuning core voltage via pp_table using ohgodatool --core-vddc-idx or --core-vddc-off will work as well.

Further conclusion is that memory voltages do not need to be tuned. Therefore ohgodatool options --mem-vddc-idx, --vddci, --mvdd or --vddc-gfx-off are useless to improve power consumption.

Is this all true or do I miss something. It seems that I still miss some optimisation potentail on my RX570 with ~130 W @ 28.5 MH/s...

Cheers, Xcoder
• Member Posts: 329 ✭✭✭
@Xcoder Memory voltages you can't change like this, so irrelevant. More can be done (a lot more) with the VRM than with the driver - even when it DOES honor your settings.
• Member Posts: 35
OK, thanks. As I realised yesterday it seems not to be a real undervolt. If the miner is booted without calling ohgodatool --core-vddc-idx, but just changing clock rates with --core-clock and --mem-clock, then the consumption is ~165 per GPU. If I call --core-vddc-idx for the active core state with any argument, irrelevant which one, then consumption drops to 130W. Obviously touching the pp_table just puts it to kind of another mode. But there seems to be no further tuning capability via pp_table.

The the VRM is my next target. Since my VBIOS does not have a VoltageObjectInfo it is a bit more serious:

42000301 01030E00 10962000 00000000 FF000107 0C000E00 00000000 00000400 24000004 00000280 10000000 00002003 00001000 52030200 00008403 02001000 B603

I would anyway prefer to talk to the VRM directly. Seems to be an NCP81022 as well in my case (regulator ID 0x10). Any hints how this is done?

Cheers, Xcoder
• Member Posts: 329 ✭✭✭
Xcoder said:

OK, thanks. As I realised yesterday it seems not to be a real undervolt. If the miner is booted without calling ohgodatool --core-vddc-idx, but just changing clock rates with --core-clock and --mem-clock, then the consumption is ~165 per GPU. If I call --core-vddc-idx for the active core state with any argument, irrelevant which one, then consumption drops to 130W. Obviously touching the pp_table just puts it to kind of another mode. But there seems to be no further tuning capability via pp_table.

The the VRM is my next target. Since my VBIOS does not have a VoltageObjectInfo it is a bit more serious:

42000301 01030E00 10962000 00000000 FF000107 0C000E00 00000000 00000400 24000004 00000280 10000000 00002003 00001000 52030200 00008403 02001000 B603

I would anyway prefer to talk to the VRM directly. Seems to be an NCP81022 as well in my case (regulator ID 0x10). Any hints how this is done?

Cheers, Xcoder

@Xcoder I prefer to do it at runtime... but you DO have a VoltageObjectInfo, and further, it's got an object of type VDDC, and mode of INIT_REGULATOR... what more do you want? xD
• Member Posts: 35
Right I have one. But is it is missing the bytes to write the NCP81022 registers, e.g. to the Special Purpose Offset 0xE6. If I got it right I have to enlarge this object to 01031600 10962000 00000000 D2000000 E600F400 FF00 for example. This means some stuff has to move within the image by 8 bytes.

Nevertheless, doing it at runtime would be much nicer. Can you give me a hint how the VRM registers are accessed. Can I find something in the amdgpu source, where would that be?

Cheers, Xcoder.
• Member Posts: 329 ✭✭✭
Xcoder said:

Right I have one. But is it is missing the bytes to write the NCP81022 registers, e.g. to the Special Purpose Offset 0xE6. If I got it right I have to enlarge this object to 01031600 10962000 00000000 D2000000 E600F400 FF00 for example. This means some stuff has to move within the image by 8 bytes.

Nevertheless, doing it at runtime would be much nicer. Can you give me a hint how the VRM registers are accessed. Can I find something in the amdgpu source, where would that be?

Cheers, Xcoder.

@Xcoder Nope, because I took a diff path, hating that damn thing. Mine works with amdgpu, fglrx, or no driver, actually. Opened /dev/mem as root, mmap()'d the area I needed into my process' address space.
• Member Posts: 35
But where can I find some description about this, i.e. which is the address space of interest, register descriptions etc.
• Member Posts: 329 ✭✭✭
Xcoder said:

But where can I find some description about this, i.e. which is the address space of interest, register descriptions etc.

The Linux Kernel has basically all you can expect. The rest is guess and check.
• Member Posts: 35
Then I assume amd/powerplay/smumgr/polaris10_smc.c is a good start. The memory ranges are shown with lcpci -v, e.g.:
`04:00.0 VGA compatible controller: Advanced Micro Devices, Inc. [AMD/ATI] Ellesmere [Radeon RX 470/480] (rev ef) (prog-if 00 [VGA controller])	Subsystem: Sapphire Technology Limited Ellesmere [Radeon RX 470/480/570/580] (Sapphire Radeon RX 580 Pulse 8GB)	Flags: bus master, fast devsel, latency 0, IRQ 30	Memory at c0000000 (64-bit, prefetchable) [size=256M]	Memory at d0000000 (64-bit, prefetchable) [size=2M]	I/O ports at d000 [size=256]	Memory at d0200000 (32-bit, non-prefetchable) [size=256K]	Expansion ROM at d0240000 [disabled] [size=128K]`
where to get from there?
• Member Posts: 35
@Wolf0 can you explain with slightly more details how VCM is accessed. Which part of the kernel, the amdgpu driver I assume, does the respective MMIO?
• Member Posts: 329 ✭✭✭
edited February 2
Xcoder said:

@Wolf0 can you explain with slightly more details how VCM is accessed. Which part of the kernel, the amdgpu driver I assume, does the respective MMIO?

@Xcoder No. My tool needs NO driver. Would even work on fglrx. I tried looking into amdgpu, and wanted to kill the devs - said fuck it and did it myself.
• Member Posts: 35
I perfecly ubderstand that your approach is not using any driver. But I assume the amdgpu driver source code provides some partial information on the hardware functionality, e.g. register addresses and descriptions. It would be great to hear from where the needed description can be found.
Greetings