Whatevergreen.kext ile ilk olarak El Capitan'ın piyasaya sürülmesiyle ortaya çıkan AMD GPU uyandırma sorunu için hâlihazırda bir geçici çözümümüz var, ancak geçici bir çözüm yerine sorunun ana nedenini araştırmaya karar verdim ve bu gönderi araştırmamın sonucudur. Araştırmamı yaparken kullandığım tek AMD GPU olan R9 270X kullandığım için bu yamanın yalnızca bu çip ile düzgün çalıştığını söyleyebilirim ancak kullandığım diğer bilgi kaynaklarına göre diğer AMD GPU’larda da çalışmayacağına dair bir bilgi edinmedim. Bazı noktalarda hala bir belirsizlik varsa, bunu açıkça belirteceğim.
AMD GPU'larla uyanmanın hala El Capitan ile çalıştığı ve Sierra'nın size sağladığı bilinen bir gerçek olduğu için;
Legacy VBIOS kullanıldığında yalnızca birincil GPU, VBIOS tarafından başlatılır, yani AMD GPU dokunulmadan bırakılırken yalnızca iGPU başlatılır. OS X başlatıldığında, framebuffer denetleyicisi kext, AMD GPU'yu saf durumda bulacak, düzgün şekilde başlatacak ve uyandırma beklendiği gibi çalışacaktır. Bu konfigürasyonda blind boot yapmanızın nedeni de budur.
UEFI VBIOS'u kullanarak AMD GPU, bağlantı noktalarından birine bağlı bir ekrana sahip olması koşuluyla başlatılacaktır. BIOS açılış ekranını göreceksiniz ve BIOS ayarlarına erişebileceksiniz ancak ne yazık ki macOS'un framebuffer denetleyici kexti, GPU'nun zaten başlatıldığını fark edecek ve temel kurulumu atlayacaktır. Böylece VBIOS tarafından yapılan konfigürasyon kullanılacak ve bu, işlerin ters gitmeye başladığı noktadır çünkü bu konfigürasyon, uyanmanın başarısız olmasına neden olacak şekilde bozulmuş gibi görünüyor.
Öncelikle yapacağınız ilk şey DSDT’nizde AMD GPU’yu bulmak olacak. Benim durumumda _SB.PCI0.PEG0.PEGP adresinde bulunabilir, ancak AppleGraphicsDevicePolicy.kext (AGDP)'nin düzgün çalışması için GFX0 olarak yeniden adlandırılması gerek. Bu manuel olarak veya bir Clover yaması kullanılarak yapılabilir (ben Clover yaması kullanarak yaptım) ve bu sorunun daha önce çözüldüğünü varsayıyorum. Bunu burada açıklamamın nedeni, AMD GPU’nuzun DSDT’de IORegistry’den farklı bir adı olduğunda bunun farkında olmanız ve bundan dolayı kafanızın karışmamasını önlemek.
Daha sonra, GPU’nun kontrol kayıt alanına erişmemiz gerekiyor. Linux kaynaklarına göre, PCI Base Address Register 2 (BAR2), Radeon HD5000, HD6000 ve HD7000 GPU'larda kontrol kayıt alanını adreslemek için kullanılır. Bu 64 bitlik bir temel adres kayıtı, fakat daha yeni GPU’lar (BONAIRE ve üstü, yani Radeon HD8000 ve HD9xxx) BAR2 yerine BAR5 kullanımından farklıdır. BAR2’den farklı olarak BAR5, 32 bitlik bir temel adres kaydıdır. R9 270X'imde (PITCAIRN) BAR5 sıfırdır, bu yüzden bunu BAR2'yi kullanmak için bir gösterge olarak kullanmaya karar verdim, ancak desteklenen tüm GPU'lar için de çalışıp çalışmadığını kontrol etmediğimi itiraf etmeliyim. Yamam sizin için işe yaramazsa, bunun bir tuzak olabileceğini unutmayın!
Radeon sürücüsünün kaynak kodu bize, ilk ekran denetleyici motorunun kayıtlarının 0x6800 ofsetinden başlayarak bulunabileceğini söyler. Ayrıca bize kayıt içeriklerinin anlamı hakkında da birçok şey anlatır. Legacy VBIOS'u kullandığımda R9 270X'imin ekran denetleyici motorunun kayıtları, macOS önyükleme yaptığında hala varsayılan değerlerinde kaldı:
UEFI VBIOS ile ekran denetleyici motorunun kayıtları oldukça farklı görünüyor. Linux sürücü kaynaklarını kullanarak bu değerleri kolayca anlayabilirsiniz ve piksel başına 32 bit kullanarak yerel çözünürlüğüne yapılandırılmış olan R9 270X'ime bağlı bir 4K ekranım olduğunu göreceksiniz.
Gerisi biraz zahmetli çalışma, deneme yanılma, kayıt içeriklerini karşılaştırma, anlamlarını anlama ve bu kayıtları varsayılan değerlerine sıfırladığınızda ne olacağını görmekti. GPU'nuzun kontrol kayıtlarıyla biraz daha oynamaya çalışırsanız, birkaç saniyeliğine bozuk bir ekran alabilirsiniz. Sonuç olarak, önyükleme sırasında ekran çıktısını korurken yanlış kayıtları düzelten ve en önemlisi uyandırma sorununu çözen bir DSDT yaması oluşturmayı başardım.
Bir şeyleri bir araya getirerek, yanlış başlatılmış kayıtları düzeltmek için bir DSDT yaması oluşturdum. Bu yama uygulanıldığında, artık UEFI kurulumunda CSM devre dışı bırakılmış UEFI VBIOS kullanarak Sierra (10.12.6) altında R9 270X ile sorunsuz bir şekilde uykudan uyandırıyorum. Artık uyku / uyanmanın R9 270X’im ile düzgün çalışması için kext yamalarına veya ek kextlere'e gerek yok. Ekranımda BIOS açılış ekranını görebiliyorum ve UEFI kurulumuna erişebiliyorum, fakat en iyisi, bu yamayı uyguladığımdan beri tek bir uyandırma sorunu ile karşılaşmamış olmam.
Ayrıntılı sorularınız varsa veya hata ayıklama için AML koduna ihtiyacınız varsa (BAR'ları boşaltmak veya GPU'ların kontrol kayıt alanını boşaltmak için kod) lütfen bana bildirin. Daha fazla araştırmayı desteklemek için tüm bilgilerimi paylaşmaya hazırım. Aşağıda oluşturduğum kayıt dökümlerini bu gönderiye ek olarak bulabilirsiniz.
SSS
Kaynak: Tracing back the AMD GPU wakeup issue to its origin
Kullandığım Materyaller
- GPU'nun dâhili bileşenlerini daha iyi anlamak için Radeon sürücüsünün Linux çekirdek kaynakları: https://git.kernel.org/pub/scm/linu...t/tree/drivers/gpu/drm/radeon?h=next-20171013
- Çipin kontrol kayıt alanını nasıl boşaltacağınızı bulmak için ACPI 6.0 özelliklerinin bir kopyası.
- Bir ayırıcı, ör. Terminal'deki objdump veya Hopper Disassembler'ın deneme sürümü.
Yaptıklarım
AMD GPU'larla uyanmanın hala El Capitan ile çalıştığı ve Sierra'nın size sağladığı bilinen bir gerçek olduğu için;
- iGPU’yu birincil GPU olarak seçin.
- CSM'yi etkinleştirin ve AMD GPU'nun Legacy VBIOS'unu kullanın.
Teknik arka plan
Legacy VBIOS kullanıldığında yalnızca birincil GPU, VBIOS tarafından başlatılır, yani AMD GPU dokunulmadan bırakılırken yalnızca iGPU başlatılır. OS X başlatıldığında, framebuffer denetleyicisi kext, AMD GPU'yu saf durumda bulacak, düzgün şekilde başlatacak ve uyandırma beklendiği gibi çalışacaktır. Bu konfigürasyonda blind boot yapmanızın nedeni de budur.
UEFI VBIOS'u kullanarak AMD GPU, bağlantı noktalarından birine bağlı bir ekrana sahip olması koşuluyla başlatılacaktır. BIOS açılış ekranını göreceksiniz ve BIOS ayarlarına erişebileceksiniz ancak ne yazık ki macOS'un framebuffer denetleyici kexti, GPU'nun zaten başlatıldığını fark edecek ve temel kurulumu atlayacaktır. Böylece VBIOS tarafından yapılan konfigürasyon kullanılacak ve bu, işlerin ters gitmeye başladığı noktadır çünkü bu konfigürasyon, uyanmanın başarısız olmasına neden olacak şekilde bozulmuş gibi görünüyor.
Öncelikle yapacağınız ilk şey DSDT’nizde AMD GPU’yu bulmak olacak. Benim durumumda _SB.PCI0.PEG0.PEGP adresinde bulunabilir, ancak AppleGraphicsDevicePolicy.kext (AGDP)'nin düzgün çalışması için GFX0 olarak yeniden adlandırılması gerek. Bu manuel olarak veya bir Clover yaması kullanılarak yapılabilir (ben Clover yaması kullanarak yaptım) ve bu sorunun daha önce çözüldüğünü varsayıyorum. Bunu burada açıklamamın nedeni, AMD GPU’nuzun DSDT’de IORegistry’den farklı bir adı olduğunda bunun farkında olmanız ve bundan dolayı kafanızın karışmamasını önlemek.
Daha sonra, GPU’nun kontrol kayıt alanına erişmemiz gerekiyor. Linux kaynaklarına göre, PCI Base Address Register 2 (BAR2), Radeon HD5000, HD6000 ve HD7000 GPU'larda kontrol kayıt alanını adreslemek için kullanılır. Bu 64 bitlik bir temel adres kayıtı, fakat daha yeni GPU’lar (BONAIRE ve üstü, yani Radeon HD8000 ve HD9xxx) BAR2 yerine BAR5 kullanımından farklıdır. BAR2’den farklı olarak BAR5, 32 bitlik bir temel adres kaydıdır. R9 270X'imde (PITCAIRN) BAR5 sıfırdır, bu yüzden bunu BAR2'yi kullanmak için bir gösterge olarak kullanmaya karar verdim, ancak desteklenen tüm GPU'lar için de çalışıp çalışmadığını kontrol etmediğimi itiraf etmeliyim. Yamam sizin için işe yaramazsa, bunun bir tuzak olabileceğini unutmayın!
Radeon sürücüsünün kaynak kodu bize, ilk ekran denetleyici motorunun kayıtlarının 0x6800 ofsetinden başlayarak bulunabileceğini söyler. Ayrıca bize kayıt içeriklerinin anlamı hakkında da birçok şey anlatır. Legacy VBIOS'u kullandığımda R9 270X'imin ekran denetleyici motorunun kayıtları, macOS önyükleme yaptığında hala varsayılan değerlerinde kaldı:
Kod:
00006800 01 00 00 00 08 80 00 0a 00 00 00 00 00 00 00 00 |................|
00006810 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00006820 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00006830 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00006840 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00006850 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00006860 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00006870 00 00 00 00 08 80 00 14 00 00 00 00 00 00 00 00 |................|
00006880 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00006890 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000068a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000068b0 00 00 00 00 10 00 00 00 00 00 00 20 00 00 00 20 |........... ... |
000068c0 00 00 00 20 10 00 00 00 00 00 00 20 00 00 00 20 |... ....... ... |
000068d0 00 00 00 20 00 00 00 00 00 20 00 00 00 00 00 00 |... ..... ......|
000068e0 00 00 00 20 00 00 00 00 00 00 00 00 00 20 00 00 |... ......... ..|
000068f0 00 00 00 00 00 20 00 00 00 00 00 00 00 00 00 20 |..... ......... |
UEFI VBIOS ile ekran denetleyici motorunun kayıtları oldukça farklı görünüyor. Linux sürücü kaynaklarını kullanarak bu değerleri kolayca anlayabilirsiniz ve piksel başına 32 bit kullanarak yerel çözünürlüğüne yapılandırılmış olan R9 270X'ime bağlı bir 4K ekranım olduğunu göreceksiniz.
Kod:
00006800 01 00 00 00 0a 80 00 0a 00 00 00 00 00 00 00 00 |................|
00006810 00 00 00 00 00 00 00 00 00 0f 00 00 f4 00 00 00 |................|
00006820 f4 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00006830 00 00 00 00 00 0f 00 00 70 08 00 00 00 00 00 00 |........p.......|
00006840 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00006850 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 |................|
00006860 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00006870 00 00 00 00 08 80 00 14 00 00 00 00 00 00 00 00 |................|
00006880 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00006890 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000068a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000068b0 00 00 00 00 10 00 00 00 00 00 00 20 00 00 00 20 |........... ... |
000068c0 00 00 00 20 10 00 00 00 00 00 00 20 00 00 00 20 |... ....... ... |
000068d0 00 00 00 20 00 00 00 00 00 20 00 00 00 00 00 00 |... ..... ......|
000068e0 00 00 00 20 00 00 00 00 00 00 00 00 00 20 00 00 |... ......... ..|
000068f0 00 00 00 00 00 20 00 00 00 00 00 00 00 00 00 20 |..... ......... |
Gerisi biraz zahmetli çalışma, deneme yanılma, kayıt içeriklerini karşılaştırma, anlamlarını anlama ve bu kayıtları varsayılan değerlerine sıfırladığınızda ne olacağını görmekti. GPU'nuzun kontrol kayıtlarıyla biraz daha oynamaya çalışırsanız, birkaç saniyeliğine bozuk bir ekran alabilirsiniz. Sonuç olarak, önyükleme sırasında ekran çıktısını korurken yanlış kayıtları düzelten ve en önemlisi uyandırma sorununu çözen bir DSDT yaması oluşturmayı başardım.
Yama
Bir şeyleri bir araya getirerek, yanlış başlatılmış kayıtları düzeltmek için bir DSDT yaması oluşturdum. Bu yama uygulanıldığında, artık UEFI kurulumunda CSM devre dışı bırakılmış UEFI VBIOS kullanarak Sierra (10.12.6) altında R9 270X ile sorunsuz bir şekilde uykudan uyandırıyorum. Artık uyku / uyanmanın R9 270X’im ile düzgün çalışması için kext yamalarına veya ek kextlere'e gerek yok. Ekranımda BIOS açılış ekranını görebiliyorum ve UEFI kurulumuna erişebiliyorum, fakat en iyisi, bu yamayı uyguladığımdan beri tek bir uyandırma sorunu ile karşılaşmamış olmam.
Kod:
Device (PEGP)
{
Name (_ADR, Zero) // _ADR: Address
OperationRegion (PCIB, PCI_Config, Zero, 0x0100)
Field (PCIB, AnyAcc, NoLock, Preserve)
{
Offset (0x10),
BAR0, 32,
BAR1, 32,
BAR2, 64,
BAR4, 32,
BAR5, 32
}
Method (_INI, 0, NotSerialized) // _INI: Initialize
{
If (LEqual (BAR5, Zero))
{
Store (BAR2, Local0)
}
Else
{
Store (BAR5, Local0)
}
OperationRegion (GREG, SystemMemory, And (Local0, 0xFFFFFFFFFFFFFFF0), 0x8000)
Field (GREG, AnyAcc, NoLock, Preserve)
{
Offset (0x6800),
GENA, 32,
GCTL, 32,
LTBC, 32,
Offset (0x6810),
PSBL, 32,
SSBL, 32,
PTCH, 32,
PSBH, 32,
SSBH, 32,
Offset (0x6848),
FCTL, 32,
Offset (0x6EF8),
MUMD, 32
}
Store (Zero, FCTL)
Store (Zero, PSBH)
Store (Zero, SSBH)
Store (Zero, LTBC)
Store (One, GENA)
Store (Zero, MUMD)
}
}
Ayrıntılı sorularınız varsa veya hata ayıklama için AML koduna ihtiyacınız varsa (BAR'ları boşaltmak veya GPU'ların kontrol kayıt alanını boşaltmak için kod) lütfen bana bildirin. Daha fazla araştırmayı desteklemek için tüm bilgilerimi paylaşmaya hazırım. Aşağıda oluşturduğum kayıt dökümlerini bu gönderiye ek olarak bulabilirsiniz.
SSS
- iGPU’yu yine de birincil ekran olarak seçmem gerekiyor mu?
Hayır. Bunu kendi başıma denememiş olmama rağmen, chh1 kullanıcısı yamayı kullanırken bunun artık gerekli olmadığını doğruladı (linke bakınTracing back the AMD GPU wakeup issue to its origin). Yine de, IGPU'yu birincil olarak seçmenizi tavsiye ediyorum. Özellikle IGPU, birincil olmadığı zaman Haswell tabanlı sistemlerde multimedya hızlandırma için kullanılamayacağından (IGPU'nun dev kimliği, birincil olmadığı zaman farklıdır) bunu yapmamak için bir nedeniniz yok.
- MacOS'ta başlattığımda her zaman siyah bir ekranla karşılaşıyorum. Yamanız da bu sorunu çözüyor mu?
Hayır çözmüyor. Bu yama sadece uyanma sorununu çözer. Önyüklemeden sonra çıkan siyah ekran, bir konektör sorununun sonucudur (lütfen iyi bilinen yöntemleri kullanarak grafik kartınız için bir konektör yaması oluşturun) veya belirli sistem tanımları (özellikle yeni iMac'ler) grafik güç yönetimi için özel yapılandırmalar seçerken AGPM ile ilgili bir sorunun sonucu olabilir. AGPM'nin düzgün çalışmasını sağlamak için, GPU'larınızın DSDT'de sistem tanımı için AGPM yapılandırmasında listelenenlerle eşleşen doğru adlara sahip olması çok önemlidir (Intel GPU için IGPU ve iMac15,1, iMac17'de AMD GPU için GFX0, 1 ve iMac18, x). DSDT'nize manuel olarak yama uygulayabilir veya cihaz adlarını düzeltmek için bir Clover DSDT yaması kullanabilirsiniz.
Katkılar
- Whatevergreen.kext'i geliştirdiği ve beni doğru yöne yönlendirdiği için vit9696.
- ACPIDebug.kext’i geliştirdiği için RehabMan
- Bana ihtiyacım olan arka plan bilgilerini sağladıkları için de Linux Radeon sürücü çekirdeği geliştiricileri.
Kaynak: Tracing back the AMD GPU wakeup issue to its origin
Son düzenleyen: Moderatör: