Jump to content

[GUIDE] Edit AppleGraphicsPowerManagement.kext to unleash nvidia's GTX 570/580 full power and save energy at the same time.


Jordan2Delta
 Share

77 posts in this topic

Recommended Posts

I did some more research on the thresholds inside AppleGraphicsPowerManagement.kext for NVIDIA GTX 570 after reading "AGPM on Fermi laptop":

 

Many thanks to oldnapalm and especially camoguy! This wouldn't be possible without you. :)

 

 

I think my results can be transferred to the GTX 580 as well. I don't know about other GTX 5xx series cards. They might have 4 or more power modes. GTX 570 only has three. I noticed that when looking on total PC power consumption and G-state switches.

 

So if you are not a GTX 570 or GTX 580 user, be careful, the following values ignores the G-state 0 and won't get invoked. This is usually the highest mode possible for most other graphics card. Um, speaking of the ancient nvidia 9500 (GT120?) and GTX 260.... Here lies the real problem, aren't all those values that someone took from this or that card outdated for the GTX 4xx or 5xx series? They might work nonetheless, but I wanted a more optimized power management, especially when I saw my "Mac" sucking more than 200W just for surfing the web or video watching. At idle my machine uses ~130W.

 

Let's get started, I wrote a long explanation why and how to edit these thresholds. You may want to read all of this or just copy and paste these values to your AppleGraphicsPowerManagement.kext and change to your vendor device.

I might add, these values are not written into stone. I have used the power efficiency thresholds for a week and I am very happy with them. You however, might find thresholds that works better for your everyday usage. I encourage to edit these values and run tests on them. I added a high performance mode as well, to show the difference.

 

Power efficiency thresholds:

(focused to stay in G-state 2 during everyday usage and therefore saves up to 55W~110W)

Threshold_High

0

45

75

100

Threshold_Low

0

0

87

98

<key>MacPro5,1</key>
			 <dict>
				 <key>Vendor10deDevice1081</key>
				 <dict>
					 <key>Heuristic</key>
					 <dict>
						 <key>ID</key>
						 <integer>0</integer>
						 <key>IdleInterval</key>
						 <integer>250</integer>
						 <key>SensorOption</key>
						 <integer>1</integer>
						 <key>SensorSampleRate</key>
						 <integer>4</integer>
						 <key>TargetCount</key>
						 <integer>5</integer>
						 <key>Threshold_High</key>
						 <array>
							 <integer>0</integer>
							 <integer>45</integer>
							 <integer>75</integer>
							 <integer>100</integer>
						 </array>
						 <key>Threshold_Low</key>
						 <array>
							 <integer>0</integer>
							 <integer>0</integer>
							 <integer>87</integer>
							 <integer>98</integer>
						 </array>
					 </dict>
					 <key>LogControl</key>
					 <integer>1</integer>
					 <key>control-id</key>
					 <integer>18</integer>
				 </dict>
				 <key>default-control-id</key>
				 <integer>18</integer>
			 </dict>

 

 

High performance thresholds:

(focused on G-state 1 (caution) this mode still switches quickly between 2 and 1

Threshold_High

0

85

75

100

Threshold_Low

0

0

95

98

<key>MacPro5,1</key>
			 <dict>
				 <key>Vendor10deDevice1081</key>
				 <dict>
					 <key>Heuristic</key>
					 <dict>
						 <key>ID</key>
						 <integer>0</integer>
						 <key>IdleInterval</key>
						 <integer>250</integer>
						 <key>SensorOption</key>
						 <integer>1</integer>
						 <key>SensorSampleRate</key>
						 <integer>4</integer>
						 <key>TargetCount</key>
						 <integer>5</integer>
						 <key>Threshold_High</key>
						 <array>
							 <integer>0</integer>
							 <integer>85</integer>
							 <integer>75</integer>
							 <integer>100</integer>
						 </array>
						 <key>Threshold_Low</key>
						 <array>
							 <integer>0</integer>
							 <integer>0</integer>
							 <integer>95</integer>
							 <integer>98</integer>
						 </array>
					 </dict>
					 <key>LogControl</key>
					 <integer>1</integer>
					 <key>control-id</key>
					 <integer>18</integer>
				 </dict>
				 <key>default-control-id</key>
				 <integer>18</integer>
			 </dict>

 

 

How and why to edit thresholds for AppleGraphicsPowerManagement.kext (AGPM)

 

I based my research on the GTX 570 but the basics should be valid to any other nvidia card, e.g. Fermi based: 460/470/480/550/560 too.

 

First of all the bad news. I couldn't get Lion as smooth as I had hoped for. I still think my previous Ati 5770 was better in that regards. Although in Novabench it only reaches ~800fps whereas the GTX 570 easily hits more than 2500fps!! Oh, don't get me started on cinebench. I get about 37fps with the Ati 5770 and only 30fps with the GTX 570 with both modes above.

 

G-state 1 (maximum speed) (Total power consumption at Idle: ~190W)

Core: 732 MHz

Memory: 950 MHz

Shader: 1464 MHz

High performance mode doesn't make much of a difference. Lagging occasionally still happens.

To test lagging I did one of the following tests:

 

1. Scrolling down/up in a Numbers document or long Firefox web page.

2. Open up more than 15 Finder windows and while in Finder switch to a desktop without any open windows and switch back. There should be quite a heavy lag at the 'ease out' movement animation, no matter what G-state the card has switched to.

 

Conclusion:

For everyday usage there are no real benefits using the threshold values from high performance mode. Test 1 generates above 20% GPU load if you are at G-state 2. Then it jumps to G-state 1 because of 85 (Threshold_High value of G-state 1). Still under load the card has switched to its highest clocks possible and so the GPU load goes down to ~7%. It stays at G-state 1 because of 95 (Threshold_Low value of G-state 2).

 

 

G-state 3 (lowest speed) (Idle: ~130W)

Core: 50 MHz

Memory: 76 MHz

Shader: 100 MHz

 

Mac OS X lags most of the time at this G-state. So I made the range for this G-state very small.

Because of 98 (Threshold_Low value of G-state 3) the GPU Idle % must be greater than 98 to get into G-state 3. During every use, a GPU load smaller than 2% is very unlikely, so in reality the G-state won't get invoked at all.

 

 

G-state 2 (medium speed) (Idle: ~135W)

Core: 405 MHz

Memory: 162 MHz

Shader: 810 MHz

 

This is the best mode for Lion. The user interface is pretty much smooth. During idle GPU it costs only 5 Watts more than G-state 3. So I adjusted the threshold values to get easy in and stay at this G-state for the power efficiency thresholds.

 

Let's see how G-state changes occur

 

how to get into G-state 2 from G-state 3:

GPU Idle % must be less than 75 says the Threshold_High value or in other words: GPU load greater than 25%

 

how to get from G-state 1 to G-state 2

GPU idle % must be greater than 87 or let's say: less than 13% GPU load.

 

Let's see how G-state 2 sticks to its own

It likes to stay there, because the Threshold_High value of G-state 1 actually defines the "get out of G-state 2" value.

It's 45. So a GPU Idle % lower than 45% is needed to invoke a change to G-state 1.

Basically you can say about the two different thresholds:

The Threshold_Low says: "To all G-states above me, you may enter my G-state only, if you decrease your GPU Load below my limit value."

 

The Threshold_High says: "To all G-states below me, you may come up here only, if you raise GPU Load and exceed my limit value."

  • Like 7
Link to comment
Share on other sites

Awesome post. Thanks for explaining your understanding.

I have a GTX 470, I am curious to test both of your edits. How many power states does my card have?

 

I will try the everyday edit first.

 

For some reason the High Power settings I don't understand. It switches into G1 if it goes above 15%GPU, but drops to g2 if less than 5% gpu? Is the thresholdLow for g2 set at 75 so that it would never hit g2 on the way up? ie computer starts. How to tell that it will invoke G1 from threshold High of 85? Will it always exceed that?

 

BTW, what is a good bench for GPU usage of an application? Or to determine the current GSTate?

 

Thanks for your post

 

TY

  • Like 1
Link to comment
Share on other sites

@myrorym

 

Sorry, for my late reply.

 

I don't know about other cards' power states. I have tried once to get some for the 560GTX, but couldn't find and took to much time for me.

You can find about your power states when booting into windows and using a tool like GPU-Z ? to check for GPU load, Core clock speed changes and alike. Just do some tests during idle medium and heavy GPU load.

 

You can check GPU Load by using OpenGL Driver Monitor. This application is bundled with Apple's Xcode.

 

I think then you will understand why it drops from G1 to G2 if GPU Idle is lower than 95%.

Hint: When being in G1 mode OpenGL Driver Monitor will tell you that GPU Idle increases because it got "stronger" to do certain tasks. That's why Apple and me chose to set the "back to lower modes enter threshold" high like 95, to not let the card switch between high performance mode and lower performance mode every 5 seconds or so. Otherwise I think this could lead to fps drops, stutter and lagging.

Link to comment
Share on other sites

Nice post,

I've got a GTX 560 TI

i'll try your two settings to see how the card handle the load.

 

what about the idelInterval value ?

- the higher it is the higher the latency to go in a better power mode ? or

- the higher it is the higher the latency to go in a better economy mode ? or

or perhaps it goes the same in the two way ?

Link to comment
Share on other sites

I've read through this thread several times and I've read the one that oldnapalm started (AGPM on Fermi laptop), but I'm doubting my understanding of the subject. If someone can help me out, that would be great.

 

In the plist in AppleGraphicsPowerManagement.kext, there are the values in Heuristic for Threshold_High and Threshold_Low. Presumably those values refer to remaining GPU capacity -- i.e. 100 - (GPU utilization in percent). In the stock AGPM plists from Apple that I've looked at, the high value is larger than the low value for each power state of the GPU. However, some examples shown above in this thread, don't stick to that pattern.

 

And in the stock Apple AGPM plists, there are examples where the power state ranges don't overlap.

 

What seems logical to me is the the high and low thresholds are the limits for each corresponding power state. If the GPU nonactivity value falls outside of the limits of the power state that the GPU is in, the power state is adjusted to the next (or previous) one in the list whose range should include that value.

 

Shouldn't the Threshold_High be greater than the Threshold_Low for each power state? And should there be no gaps in the ranges, e.g. Threshold_Low for power state 1 should be less than or equal to Threshold_High for power state 0 (I wonder what happens when the GPU utilization, which is determined by the graphics activity of the programs being run, is in a gap between threshold ranges. What GPU power state does the system choose in that case?)?

 

dgktkr

Link to comment
Share on other sites

I think that each values are percent of the actual power stage

let's say

stage 3 gives you a processing power of 200 @ 100%

stage 2 gives you a processing power of 1000 @ 100%

stage 1 gives you a processing power of 3000 @ 100%

 

each threshold value refers to the a specific stage and so you have 3 ranges in each stages and no gap.

under the low - between low and high - above high.

 

I don't think that every threshold values refers to stage 1.

 

I've read through this thread several times and I've read the one that oldnapalm started (AGPM on Fermi laptop), but I'm doubting my understanding of the subject. If someone can help me out, that would be great.

 

In the plist in AppleGraphicsPowerManagement.kext, there are the values in Heuristic for Threshold_High and Threshold_Low. Presumably those values refer to remaining GPU capacity -- i.e. 100 - (GPU utilization in percent). In the stock AGPM plists from Apple that I've looked at, the high value is larger than the low value for each power state of the GPU. However, some examples shown above in this thread, don't stick to that pattern.

 

And in the stock Apple AGPM plists, there are examples where the power state ranges don't overlap.

 

What seems logical to me is the the high and low thresholds are the limits for each corresponding power state. If the GPU nonactivity value falls outside of the limits of the power state that the GPU is in, the power state is adjusted to the next (or previous) one in the list whose range should include that value.

 

Shouldn't the Threshold_High be greater than the Threshold_Low for each power state? And should there be no gaps in the ranges, e.g. Threshold_Low for power state 1 should be less than or equal to Threshold_High for power state 0 (I wonder what happens when the GPU utilization, which is determined by the graphics activity of the programs being run, is in a gap between threshold ranges. What GPU power state does the system choose in that case?)?

 

dgktkr

Link to comment
Share on other sites

atshoom,

 

Thanks for the insight.

 

In the examples you give, what are the units for processing power?

 

Do you have any suggestions where I might look to find values specific to my Nvidia GPU?

 

dgktkr

 

I think that each values are percent of the actual power stage

let's say

stage 3 gives you a processing power of 200 @ 100%

stage 2 gives you a processing power of 1000 @ 100%

stage 1 gives you a processing power of 3000 @ 100%

 

each threshold value refers to the a specific stage and so you have 3 ranges in each stages and no gap.

under the low - between low and high - above high.

 

I don't think that every threshold values refers to stage 1.

Link to comment
Share on other sites

I can't tell you a unit, I think you should use a GPU benchmark software to fix one.

then edit the info.plist file to block your GPU in each state and see the ratio of each state compared to the higher one.

for example if I start Starcraft 2, during the login sequence that have a login animation, I can get 3fps, 30 fps or 60 fps depending of the state of my GTX 560 TI.

 

 

atshoom,

 

Thanks for the insight.

 

In the examples you give, what are the units for processing power?

 

Do you have any suggestions where I might look to find values specific to my Nvidia GPU?

 

dgktkr

Link to comment
Share on other sites

  • 2 weeks later...

I've had time and interest to do more experimenting with this agpm thing. So far I've found that I can replace Vendor10deDevice1200 with GFX then a number. GFX3 in my case because the motherboard enumerates it that way. To see yours, type

 ioreg -l | grep attached

It's the one right after IOPCI2PCIBridge

 

Since all I have is this GTX560Ti, that's my primary focus.

 

I was messing around with changing the mac model identifier to something else, even though I was now a MacPro3,1 because of the change I did above I was still enjoying power savings, which was contrary to my thinking the Model identifier entry is somehow necessary. I guess it was, when I was using the Vendor id for it.

 

Couple more things, if I removed the SensorOption 1, I would lose agpm and would be stuck in power state zero, getting great smooth transitions and such and great performance at a price of 65 more watts.

 

If I set control id to 18, I would also lose power management. 17 seems to be the ticket these days. Idle 100, target count 5. Also decided to add iMac12,1 's BoostPstate and BoostTime array's to the equation and it didn't crash the system, so whatever doesn't kernel panic only makes you stronger... we'll see

 

I'm currently using these threshold settings

 

High

0=55 1=40 2=60 3=100

Low

0=0 1=75 2=90 3=98

mcxit2.jpg

These settings makes for smoother web page scrolling, they don't invoke state 3 very much, and therefore eliminates the screen drag and stutter that plagues the otherwise beautiful desktop experience.

 

One interesting new thing I've found, is that, inverted values for state 2 and 1 seem to play nicer meaning, less jumping from power state to state. I think I'm seeing a pattern. If you take a look at this example you will see what I'm trying to say.

 

I wish they would overhaul civ 5 for mac. It's terrible on the 560. I bought it on steam when it was on sale and, it's a laggy mess I can't stand. I've tried monitoring it with driver monitor and it's terribly unoptimized for the 560, but I understand why... :) It's not utilizing the GPU or Vram at all, unlike starcraft 2 which runs perfectly on the 560, and obviously the driver monitor reflects near 100% utilization of hardware.

 

Also I think this message in console "copyPrimaryAirPortInterface::ACInterfaceDeviceNameCopy returned NULL" & "_CSIsWirelessP2PEnabled::copyPrimaryAirPortInterface failed" prints because you mac doesn't have an airport card capable of airdrop. So each time you open finder and go clicking around it prints, because I guess it's still running some function that wasn't disabled once it realized you didn't have airdrop compatiblity.

  • Like 1
Link to comment
Share on other sites

  • 2 weeks later...

i edited the AGPM kext according to this guide. everything works like a charm, except a few lags (i suppose it's because of the gpu power state switching)... but one other thing came up, which i dont understand - when i restart or shutdown my system, the machine won't restart or turn off... everything turns off, the usb mous, disks spin down, but the machine won't power off.... whe i use the original AGPM kext, everything works... any clues?

 

i have a gf gtx 560 (AGPM set exactly as in this guide), p8p67 deluxe mobo with DSDT

 

any help appreciated, thx :D

 

EDIT: i think i found the reason, my AGPM kext isnt loaded :/ ...i dont see it in System information / Software / Extensions ... when i use the original kext, it is there... i think that's the reason for the reset/shutdown problem.... hopefully i'll find out what i did wrong

 

EDIT 2: finally i fixed it, there was a typo in my AGPM kext...

Link to comment
Share on other sites

i edited the AGPM kext according to this guide. everything works like a charm, except a few lags (i suppose it's because of the gpu power state switching)... but one other thing came up, which i dont understand - when i restart or shutdown my system, the machine won't restart or turn off... everything turns off, the usb mous, disks spin down, but the machine won't power off.... whe i use the original AGPM kext, everything works... any clues?

 

i have a gf gtx 560 (AGPM set exactly as in this guide), p8p67 deluxe mobo with DSDT

 

any help appreciated, thx ;)

 

-Hi

Post your kext, we'll take a look

Link to comment
Share on other sites

  • 2 weeks later...

I don't know where to start but maybe we can collect data on different cards eventually. I have a Asus Laptop G74SX wit a GeForce GTX 560M 3GB graphics.

 

Vendor: NVIDIA (0x10de)

Device ID: 0x1251

 

I have no idea where to start unless I can find an Vendor and Device similar to mine in the Info.plist

Link to comment
Share on other sites

I don't know where to start but maybe we can collect data on different cards eventually. I have a Asus Laptop G74SX wit a GeForce GTX 560M 3GB graphics.

 

Vendor: NVIDIA (0x10de)

Device ID: 0x1251

 

I have no idea where to start unless I can find an Vendor and Device similar to mine in the Info.plist

My VGA is just like yours. I'm gonna test it and will post back after results.

 

EDIT: Well one thing tested, a Flash game I play (www.glitch.com) is much better now. Was a lot laggy before, now runs like Im in Windows. The modded kexts is attached for Geforce GTX 560M (mobile vga, Vendor10deDevice1251) just to be more pratical in the future.

 

Thanks to the OP :)

 

EDIT 2: The thing now is test more to know why these numbers are so low here:

post-237333-1318950824_thumb.png

AppleGraphicsPowerManagement.kext.zip

Link to comment
Share on other sites

  • 2 weeks later...
My VGA is just like yours. I'm gonna test it and will post back after results.

 

EDIT: Well one thing tested, a Flash game I play (www.glitch.com) is much better now. Was a lot laggy before, now runs like Im in Windows. The modded kexts is attached for Geforce GTX 560M (mobile vga, Vendor10deDevice1251) just to be more pratical in the future.

 

Thanks to the OP ;)

 

EDIT 2: The thing now is test more to know why these numbers are so low here:

 

I have a 560M also, and was working on this as well. Did you just replace a vendor ID, or did you create new threshold values? What macmodel did you put it under? I'll try it out if you used 8,2, or I'll edit then try if not

 

 

Edit: I took your 8,1 entry for it in put it in 8,2. This double my performance in cinebench over removing the AGPM. Went from 12fps to 27. Still not as fast as it should be, but it's a good start

post-903829-1319737217_thumb.png

Link to comment
Share on other sites

@eksployted and @bsides

 

I disabled my AGPM and I seem to have higher scores now around 638-700FPS in Open GLviewer and around 31.39 in cinebench Open Gl scores.

 

Novabench scores are double the newest MacBook Pros October 2011. Ran them in the store the other day.

 

I have the same graphics card as you but mine has the 3GB Vram.

 

SInce my scores seem to be ok unless I am missing something here do I need re-enable my AGPM and modify it?

 

Do you have a profile for the 8,3 model which is what I have in my smbios.plist. Better for AICPUPM patched with speedstepper.

 

See this link for my scores compared to MacBook Pro:

 

http://www.insanelymac.com/forum/index.php...t&p=1767023

 

 

EDITED:

 

I replaced the section under 8,3 with yours and holy cow My Open GLviewer scores went from 700 to 2600 how can that be? All the other Benchmark Software Scores I linked above remained the same.

 

I noticed the Apple Spin wheel a bit more when I open anything but its rather short. I do not see this when I disable AGPM. I still wonder if its worth running the edited AGPM just for better scored on Open GL Viewer?

 

EDITED AGAIN:

 

I have no idea how my scores jumped so high but they are back to what they were before placing the edited AGPM back into the extensions.

 

Conclusion, I see no differences in benchmarks with or without the Edit but with the AGPM enabled I do see the Apple Spin Wheel.

 

 

EDITED ONCE AGAIN:

 

@eksployted and @bsides

 

Since this is suppose to be better overall for the graphics card power management I am running it daily with the edited version you provided and seems to be fine so far. Again I have the same Benchmarks with or without the patch.

 

 

 

One disturbing thing. Have either of you noticed any random desktop freezing at all. Nothing to do with APGM because it happens with or without it. I have done all the edits to the GeForceGLDriver.bundle. The current Chameleon and Chimera has the entry for our card so I never put the card ID into the NvDanV100HAL.

 

The panic points back to the NvDanV100HAL. I have the 3GB Vram version. I cannot figure out when or why but I noticed if I am clicking around in different safari tabs is when it happens to me. It may happen in other scenarios but I have not seen any pattern as of yet.

 

 

OMG EDITED AGAIN:

 

I am getting in the 2200 to 2400 FPS now in Open Gl Viewer, so my result from before was not a glitch, it was true results before. As soon as the tests start I move the window over then it reads the higher rate, which I did not pick on until now. If I leave the window in the default location bottom left of the desktop my scores are around 650-700FPS

 

The Random Panics may actually have been caused by VoodooHDA. Was using Jeffs2009 Kext, his guide for the G73SX/G74SX thread install for Lion. Someone from that thread found a better one in kexts.com. No more panics and volume is louder now.

 

@bsides,

 

I have not tried your VoodooHDA that you link in your signature yet. Did you mod it yourself or grab it from another source, and if so just curious which source?

 

Everything seems to be working nicely with the Modded AGPM. Moved your section over from 8,1 and replaced section 8,3 with yours since, I dunno if I can use 8,1, since my SMBIOS.plist uses 8,3 and speedstepper works better with the 8,3 mac profile. Can I use the 8,1 section in AGPM if I am using 8,3 in smbios.plist?

 

Thanks

Link to comment
Share on other sites

  • 2 months later...

Thank you very much for all your valuable info. I just got a Asus GTX 560 and am eager to put this info to use. I hava dualboot partition. Would theese values also work on snow leopard? Either way its a great help as this card is a "power hog".

Thanks again!!!

Link to comment
Share on other sites

  • 2 weeks later...

I think I am very close with my GTX580 to work well since I have 45.5 FPS in Cinebench but... I cant even start iMovie 11. It says it cant use core image during to a incompatible graphics card. Thats a shame!

Shall I have the AppleGraphicsPowerManagement in S/L/E only? I think I put it in the root Extra folder.

Would be happy to get this right before I try... I just hate KPs!! I panic myself!!

Link to comment
Share on other sites

I'm not sure if it's any help, but when I ran CPU-Z in Windows it shows 4 performance levels for my GTX460. Assuming these correspond to the states in the AGPM kext, maybe it's a way to find the "official" values for our cards?

 

Display adapter 0
Name   NVIDIA GeForce GTX 460
Revision  A1
Codename  GF104
Technology  40 nm
Memory size  768 MB
PCI device  bus 1 (0x1), device 0 (0x0), function 0 (0x0)
Vendor ID  0x10DE (0x1043)
Model ID  0x0E22 (0x835C)
Performance Level Default
 Core clock 50.5 MHz
 Shader clock 101.0 MHz
 Memory clock 135.0 MHz
Performance Level 2D Desktop
 Core clock 405.0 MHz
 Shader clock 810.0 MHz
 Memory clock 324.0 MHz
Performance Level 3D Applications
 Core clock 405.0 MHz
 Shader clock 810.0 MHz
 Memory clock 1840.0 MHz
Performance Level 3D Applications
 Core clock 700.0 MHz
 Shader clock 1400.0 MHz
 Memory clock 1840.0 MHz

Link to comment
Share on other sites

hello

 

anyone tried these edits with dual screen setup? seems my card always run in some higher mode, as power consumption in idle is 70wats higher than it is in windows 7. when i unplug the second monitor the consumption goes down.

 

do you have any settings for such a setup please?

 

tx

Link to comment
Share on other sites

  • 2 weeks later...

For reference, here are my results for GTX 560Ti-448 (448 Shaders) on 10.7.3 without modification of AppleGraphicsPowerManagement.kext.

 

OpenGL enabler patches applied.

 

 

Report:

 

Renderer: NVIDIA GeForce Pre-Release Unknown OpenGL Engine

Vendor: NVIDIA Corporation

Memory: 1280 MB

Version: 2.1 NVIDIA-7.18.11

Device: MacPro4,1

Shading language version: 1.20

post-186599-0-54741100-1329402407_thumb.jpg

  • Like 1
Link to comment
Share on other sites

 Share

×
×
  • Create New...