Ασυμβατότητα NVidia Drivers και 5.1 Kernel - οδηγός διόρθωσης

Ένα συχνό, πλέον, φαινόμενο, που όσοι από εμάς έχουν NVidia GPUs ξέρουν καλά, είναι να "σπάνε" οι NVidia Drivers μετά από αναβαθμίσεις της διανομής μας, όταν αυτή περιλαμβάνει αναβάθμιση του πυρήνα σε επόμενο version.
Η προσωπική μου, υποκειμενική άποψη, είναι ότι οι device drivers πρέπει να προσαρμόζονται στον πυρήνα του λειτουργικού συστήματος και όχι το ανάποδο. Δυστυχώς η NVidia αργεί πολύ να ακολουθήσει τις αλλαγές και να προσαρμοστεί, με αποτέλεσμα να μένουμε συχνά χωρίς γραφικό περιβάλλον.
Ειδικά μάλιστα σε rolling διανομές, που είναι σύνηθες η έκδοση του πυρήνα να είναι κοντά στην τελευταία ή, σε experimental διανομές, η τελευταία είναι σύνηθες να μπουτάρουμε σε TTY αντί για το γραφικό μας περιβάλλον, λόγω του παραπάνω.
Αρχικά, ας αναλύσουμε λίγο τα βασικά.
Οι NVidia Drivers, όπως και άλλοι, εκμεταλλεύονται το μηχανισμό DKMS.
Το DKMS - Dynamic Kernel Module Support - είναι, εν ολίγοις, ένας μηχανισμός που παρέχεται από όλες τις σύγχρονες διανομές και δίνει τη δυνατότητα να δημιουργούνται δυναμικά κάποια out-of-source-tree kernel modules. Συγκεκριμένα, όταν εγκαθίσταται ένας νέος πυρήνας, τα modules που είναι registered ως DKMS Modules, γίνονται αυτόματα compile, install και load.
Επίσης, συνήθως, τα ανωτέρω modules έχουν compile-time εξαρτήσεις. Για να γίνει δηλαδή επιτυχώς το αυτόματο αυτό compile/build χρειάζονται πολλές φορές βιβλιοθήκες του πυρήνα.
Στην περίπτωση της NVidia, οι εξαρτήσεις αυτές αφορούν κατά κύριο λόγο το κομμάτι του πυρήνα που έχει το interface και τα ανάλογα abstractions για το DRM (Direct Rendering Manager).

Η περιπέτειά μου ξεκίνησε αρχικά με την έκδοση 410 των driver και τον νέο τότε 4.20 kernel (πλέον 5.0+). Ύστερα από πολύ ψάξιμο στα install logs του driver, βρήκα την κατάλληλη, τότε, αλλαγή στα sources του driver και γεμάτος χαρά, απόλαυσα τον latest kernel με τους latest NVidia drivers (πλέον 418.56).
Δυστυχώς αυτό κράτησε λίγο..
Σαν φανατικός υποστηρικτής του kernel customization και recompile, το git pull μου έφερε τον 5.1.rc1. Κάνω το build μου γεμάτος χαρά και όπως μπορείτε να μαντέψετε, boot σε TTY…
Ευτυχώς, ύστερα από δύο συνεχόμενα ξενύχτια, κατάφερα να φέρω πάλι τα sources σε σημείο όπου κάνουν compile και, ως τώρα, δουλεύουν ρολόι σε όλα μου τα games και προγράμματα που χρησιμοποιούν την GPU. Είπα λοιπόν να μοιραστώ τη λύση μου, αν και δηλώνω από τώρα πως είναι σχετικά άκομψη, με τον υπόλοιπο κόσμο, ώστε όταν έρθει η μοιραία ώρα του update να ξέρει τι να κάνει.
Ουσιαστικά οι αλλαγές είναι πρόσθεση κάποιων function declarations που αφαιρέθηκαν από τα kernel sources, καθώς και αλλαγή κάποιων function signature ώστε να "ταιριάζουν" στα νέα kernel sources. Πλέον, για παράδειγμα, κάποιες function που επέστρεφαν int για να αντιπροσωπεύσουν faults, πρέπει να γυρνάνε τη δομή vm_fault_t.

Σημειώνεται πως ο οδηγός αφορά τους drivers για τις σχετικά σύγχρονες κάρτες γραφικών (σίγουρα όλη τη σειρά GTX 7/8/9/10). Θα βρείτε αν η κάρτα σας είναι supported στο https://www.nvidia.com/Download/driverResults.aspx/145182/en-us

Φύγαμε:

  1. Το πρώτο που πρέπει να κάνουμε είναι να κατεβάσουμε τους drivers και να τους κάνουμε extract
    > cd ~/Downloads && mkdir nvidia && cd nvidia
    > wget -O nvidia.run http://us.download.nvidia.com/XFree86/Linux-x86_64/418.56/NVIDIA-Linux-x86_64-418.56.run
    > chmod +x nvidia.run
    > ./nvidia.run --extract-only
    > cp -R NVIDIA-Linux-x86_64-418.56/ nvidia-patched
    > cd nvidia-patched
  2. Έχουμε πλέον το source tree των driver. Μπορούμε να ξεκινήσουμε το patching
    α. Το πρώτο που χτυπάει στο build είναι ότι το "list_is_first" function έχει οριστεί αλλού (symbol redefinition err). Πράγματι, ένα από τα commit στον 5.1 ορίζει το συγκεκριμένο helper function εντός πυρήνα. Ανοίγουμε το αρχείο nvidia-patched/kernel/common/inc/nv-list-helpers.h με τον αγαπημένο μας text editor (στην περίπτωσή μου το vim) και αλλάζουμε το
    static inline int list_is_first
    σε
    static inline int list_is_first_nvd
    β. Το επόμενο βήμα είναι αλλάξουμε τα function names που πλέον δεν υπάρχουν στον 5.1.
    • Στο αρχείο nvidia-patched/kernel/nvidia-drm/nvidia-drm-drv.c προσθέτουμε τα παρακάτω στη γραμμή 37
      bool drm_helper_hpd_irq_event(struct drm_device *dev);
      void drm_kms_helper_poll_init(struct drm_device *dev);
      void drm_kms_helper_poll_fini(struct drm_device *dev);
      void drm_kms_helper_poll_disable(struct drm_device *dev);
    • Στο αρχείο nvidia-patched/kernel/nvidia-drm/nvidia-drm-connector.c προσθέτουμε στη γραμμή 203 το παρακάτω function declaration:
      int drm_helper_probe_single_connector_modes(struct drm_connector* connector, uint32_t maxX, uint32_t maxY);
    • Στο αρχείο nvidia-patched/kernel/nvidia-drm/nvidia-drm-encoder.c προσθέτουμε τα παρακάτω στη γραμμή 38
      void drm_kms_helper_hotplug_event(struct drm_device *dev);
      και τα παρακάτω στη γραμμή 154
      int drm_helper_probe_single_connector_modes(struct drm_connector *connector, uint32_t maxX, uint32_t maxY);
    • Στο αρχείο nvidia-patched/kernel/nvidia-drm/nvidia-drm-gem-nvkms-memory.c αλλάζουμε το
      static int nv_drm_vma_fault(struct vm_fault *vmf)
      σε
      static vm_fault_t nv_drm_vma_fault(struct vm_fault *vmf)
    • Στο αρχείο nvidia-patched/kernel/nvidia-uvm/uvm8.c αλλάζουμε το
      static int uvm_vm_fault_sigbus_wrapper(struct vm_fault *vmf)
      σε
      static vm_fault_t uvm_vm_fault_sigbus_wrapper(struct vm_fault *vmf)
      και το
      static int uvm_vm_fault_wrapper(struct vm_fault *vmf)
      σε
      static vm_fault_t uvm_vm_fault_wrapper(struct vm_fault *vmf)
    • Τέλος, στο αρχείο nvidia-patched/kernel/nvidia-uvm/uvm8_range_tree.c αλλάζουμε το μόνο σημείο που βρήκα το "list_is_first" να χρησιμοποιείται από
      if (list_is_first(&node->list, &tree->head)
      σε
      if (list_is_first_nvd(&node->list, &tree->head)))
  3. Είμαστε έτοιμοι για το build:
  4. > cd ~/Downloads/nvidia-patched
    > ./nvidia-installer
  5. Αν όλα πήγαν καλά, ο driver έκανε compile και εγκαταστάθηκε σωστά στο σύστημα μας!
  6. Υ.Γ. Ξέρω πως δεν είναι η πιο κομψή δυνατή λύση, παρόλα αυτά φαίνεται πόσο εύκολο είναι να διορθωθεί ο κώδικας των NVidia drivers και να προσαρμοστεί στο νέο kernel.
    As always, Απολαύστε ανεύθυνα
8 «Μου αρέσει»

Άρα πολύ καλά έκανε ο Linus και χρησιμοποίησε το f word για την Nvidia!!!
Κι εγώ παθών είμαι, αν και ubuntάς!!!

2 «Μου αρέσει»

Μεγάλε με έσωσες!!! Σε ευχαριστώ @gmotux

1 «Μου αρέσει»

Και δοκίμασα χθες τον 5.1.2 και ξαναγύρισα στον 5.0.15 λόγω ασυμβατότητας :stuck_out_tongue:
Ευχαριστούμε!!!

Καλώς ήρθες στην παρέα μας @sv1sjp

1 «Μου αρέσει»