AMD GPU uykudan uyandırma sorununu tespit etme

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.

Kullandığım Materyaller​


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;
  1. iGPU’yu birincil GPU olarak seçin.
  2. CSM'yi etkinleştirin ve AMD GPU'nun Legacy VBIOS'unu kullanın.
UEFI VBIOS ile neyin farklı olduğunu merak ettim ve öğrenmek için CSM etkin, Legacy VBIOS kullanırken ve CSM devre dışı, UEFI VBIOS kullanırken GPU’nun kontrol kayıt alanı dökümlerini oluşturmaya karar verdim. Kayıt alanı içeriklerini karşılaştırdığımızda sorunun kökünün nerede olduğunu ve bir DSDT yamasıyla nasıl düzeltilebileceği ortaya çıktı.

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:

Geri
Yukarı