You are not logged in.

#1 2018-03-05 12:26:05

loqs
Member
Registered: 2014-03-06
Posts: 18,032

linux 4.16 nvidia patches

Issue one
nvidia 390.25 does not build corretly against linux 4.16-rc4 due to https://git.kernel.org/pub/scm/linux/ke … 20b0213bec
Which removes the export of swiotlb_map_sg_attrs as the function call is still present just not exported this results in a build warning.

WARNING: "swiotlb_map_sg_attrs" [/tmp/nvidia-mainline/src/NVIDIA-Linux-x86_64-390.25-no-compat32/kernel/nvidia.ko] undefined!

Attempting to load the built module

# modprobe nvidia
modprobe: ERROR: could not insert 'nvidia': Unknown symbol in module, or unknown parameter (see dmesg)

dmesg output

[  313.646191] nvidia: Unknown symbol swiotlb_map_sg_attrs (err 0)

Solution one.  Revert 4bd89ed39b2ab8dc4ac4b6c59b07d420b0213bec this means going against upstreams wishes and carrying a custom patch.
Solution two.  Try using one of only two symbols left exported however both are EXPORT GPL so can not be used on none GPL modules so nasty work around claim module is GPL.
This does not appear to be distributable or clean but does appear to work.  Tracing swiotlb_map_sg_attrs it is only used in one call in
NVIDIA-Linux-x86_64-390.25-no-compat32/kernel/nvidia/nv-linux.h in the function nv_dma_maps_swiotlb if NV_DMA_MAP_OPS_PRESENT is defined and
not both NVCPU_AARCH64 are defined NV_NONCOHERENT_SWIOTLB_DMA_OPS_PRESENT so that would leave a different call but similar issue for ARM64.  The other
ifdef combinations in nv_dma_maps_swiotlb all seem to lead to the same result of calling no longer accesible members of swiotlb.

diff --git a/kernel/common/inc/nv-linux.h b/kernel/common/inc/nv-linux.h
index 10fc418..f64cfbc 100644
--- a/kernel/common/inc/nv-linux.h
+++ b/kernel/common/inc/nv-linux.h
@@ -1225,6 +1225,7 @@ static inline NvBool nv_dma_maps_swiotlb(struct pci_dev *dev)
     #else
     const struct dma_mapping_ops *ops = dma_ops;
     #endif
+#if 0
     #if defined(NV_DMA_MAP_OPS_PRESENT)
     /*
      * The switch from dma_mapping_ops -> dma_map_ops coincided with the
@@ -1241,6 +1242,9 @@ static inline NvBool nv_dma_maps_swiotlb(struct pci_dev *dev)
     #else
     swiotlb_in_use = (ops->map_sg == swiotlb_map_sg);
     #endif
+#endif
+    (void)ops;
+    swiotlb_in_use = (swiotlb_nr_tbl() > 0ul);
   #elif defined(NVCPU_X86_64)
     /*
      * Fallback for old 2.6 kernels - if the DMA operations infrastructure
diff --git a/kernel/nvidia/nv-frontend.c b/kernel/nvidia/nv-frontend.c
index 59c69a0..cc81ba4 100644
--- a/kernel/nvidia/nv-frontend.c
+++ b/kernel/nvidia/nv-frontend.c
@@ -15,7 +15,7 @@
 #include "nv-frontend.h"
 
 #if defined(MODULE_LICENSE)
-MODULE_LICENSE("NVIDIA");
+MODULE_LICENSE("GPL");
 #endif
 #if defined(MODULE_INFO)
 MODULE_INFO(supported, "external");

Solution three make nv_dma_maps_swiotlb always return NV_TRUE.  Tracing nv_dma_maps_swiotlb it is only used in one call in NVIDIA-Linux-x86_64-390.25-no-compat32/kernel/nvidia/nv.c
in the function nv_requires_dma_remap if NVCPU_ARM is not defined otherwise the function always returns true.  Tracing nv_requires_dma_remap it
is used in one call in NVIDIA-Linux-x86_64-390.25-no-compat32/kernel/nvidia/nv.c in nv_alloc_pages which initializes local variable will_remap
to the result of that function call.  There appears to also be a second call in  NVIDIA-Linux-x86_64-390.25-no-compat32/kernel/nvidia/nv-kernel.o_binary

diff --git a/kernel/common/inc/nv-linux.h b/kernel/common/inc/nv-linux.h
index 10fc418..628925e 100644
--- a/kernel/common/inc/nv-linux.h
+++ b/kernel/common/inc/nv-linux.h
@@ -1209,7 +1209,7 @@ static inline NvU32 nv_alloc_init_flags(int cached, int contiguous, int zeroed)
 static inline NvBool nv_dma_maps_swiotlb(struct pci_dev *dev)
 {
     NvBool swiotlb_in_use = NV_FALSE;
-#if defined(CONFIG_SWIOTLB)
+#if defined(CONFIG_SWIOTLB) && LINUX_VERSION_CODE < KERNEL_VERSION(4, 16, 0)
   #if defined(NV_DMA_OPS_PRESENT) || defined(NV_GET_DMA_OPS_PRESENT)
     /*
      * We only use the 'dma_ops' symbol on older x86_64 kernels; later kernels,
@@ -1249,6 +1249,8 @@ static inline NvBool nv_dma_maps_swiotlb(struct pci_dev *dev)
      * longer exported.
      */
     swiotlb_in_use = (swiotlb == 1);
+#else
+    swiotlb_in_use = NV_TRUE;
   #endif
 #endif
 

Solution  four make nv_dma_maps_swiotlb always return NV_FALSE.
Tracing will_remap it is used only once to determine if an address should be mapped through nv_phys_to_dma.
With solution three it will mapped through nv_phys_to_dma with solution four it will not.
Tracing nv_phys_to_dma it is defined in NVIDIA-Linux-x86_64-390.25-no-compat32/kernel/nvidia/nv-linux.h if NV_PHYS_TO_DMA_PRESENT is defined
it maps to the kernel call phys_to_dma else if NV_XEN_SUPPORT_FULLY_VIRTUALIZED_KERNEL is defined it maps to phys_to_machine otherwise it
returns the same address passed in.  NV_PHYS_TO_DMA_PRESENT will not be defined as in 4.16 was moved from linux/dma-mapping.h
to linux/dma-direct.h.   To prevent phys_to_machine being used the config test needs to be fixed for solution four.
phys_to_dma is defined in include/linux/dma-direct.h unless CONFIG_ARCH_HAS_PHYS_TO_DMA is defined.
The version when CONFIG_ARCH_HAS_PHYS_TO_DMA is not defined

static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
{
	dma_addr_t dev_addr = (dma_addr_t)paddr;

	return dev_addr - ((dma_addr_t)dev->dma_pfn_offset << PAGE_SHIFT);
}

So the input address would not be the same as the output unless dev->dma_pfn_offset is 0.
When CONFIG_ARCH_HAS_PHYS_TO_DMA is defined on x86 the version in is used arch/x86/include/asm/dma-direct.h

static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
{
	return __sme_set(paddr);
}

From include/linux/mem_encrypt.h

diff --git a/kernel/common/inc/nv-linux.h b/kernel/common/inc/nv-linux.h
index 10fc418..22ef968 100644
--- a/kernel/common/inc/nv-linux.h
+++ b/kernel/common/inc/nv-linux.h
@@ -175,7 +175,11 @@ static inline uid_t __kuid_val(kuid_t uid)
 
 #if defined(NV_VM_INSERT_PAGE_PRESENT)
 #include <linux/pagemap.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 16, 0)
 #include <linux/dma-mapping.h>
+#else
+#include <linux/dma-direct.h>
+#endif
 #endif
 
 #if defined(CONFIG_SWIOTLB) && defined(NVCPU_AARCH64)
@@ -1209,7 +1213,7 @@ static inline NvU32 nv_alloc_init_flags(int cached, int contiguous, int zeroed)
 static inline NvBool nv_dma_maps_swiotlb(struct pci_dev *dev)
 {
     NvBool swiotlb_in_use = NV_FALSE;
-#if defined(CONFIG_SWIOTLB)
+#if defined(CONFIG_SWIOTLB) && LINUX_VERSION_CODE < KERNEL_VERSION(4, 16, 0)
   #if defined(NV_DMA_OPS_PRESENT) || defined(NV_GET_DMA_OPS_PRESENT)
     /*
      * We only use the 'dma_ops' symbol on older x86_64 kernels; later kernels,
diff --git a/kernel/conftest.sh b/kernel/conftest.sh
index b23dbb4..42dc576 100755
--- a/kernel/conftest.sh
+++ b/kernel/conftest.sh
@@ -1906,7 +1906,12 @@ compile_test() {
             # Determine if the phys_to_dma function is present.
             #
             CODE="
+            #include <linux/version.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 16, 0)
             #include <linux/dma-mapping.h>
+#else
+            #include <linux/dma-direct.h>
+#endif
             void conftest_phys_to_dma(void) {
                 phys_to_dma();
             }"

Use of nv_phys_to_dma is decided at build time with solutions three and four nv_phys_to_dma is a no op under conditions outlined above otherwise the address generated will be different.

Issue two nvidia 390.25 triggers a WARN_ONCE in linux 4.16-rc4 due to https://git.kernel.org/pub/scm/linux/ke … f01afe778c
As the nvidia module does not define a usercopy region for the cache.

 ------------[ cut here ]------------
 Bad or missing usercopy whitelist? Kernel memory exposure attempt detected from SLUB object 'nvidia_stack_cache' (offset 11440, size 3)!
 WARNING: CPU: 3 PID: 555 at mm/usercopy.c:81 usercopy_warn+0x7e/0xa0
 Modules linked in: snd_hda_codec_hdmi nct6775 hwmon_vid snd_hda_codec_realtek snd_hda_codec_generic nvidia_drm(PO) nvidia_modeset(PO) nvidia(PO) wl(PO) iTCO_wdt iTCO_vendor_support eeepc_wmi asus_wmi sparse_keymap wmi_bmof mxm_wmi intel_rapl drm_kms_helper x86_pkg_temp_thermal btusb intel_powerclamp coretemp btrtl kvm_intel snd_hda_intel drm btbcm mousedev input_leds cfg80211 evdev led_class joydev snd_hda_codec btintel ipmi_devintf e1000e mac_hid ipmi_msghandler kvm snd_hda_core syscopyarea snd_hwdep bluetooth nls_iso8859_1 sysfillrect sysimgblt fb_sys_fops snd_pcm irqbypass nls_cp437 snd_timer vfat ecdh_generic intel_cstate snd ptp fat rfkill intel_rapl_perf i2c_i801 pcspkr soundcore shpchp pps_core lpc_ich mei_me ie31200_edac mei thermal fan wmi button video sch_fq_codel crypto_user
  ip_tables x_tables ext4 crc16 mbcache jbd2 fscrypto dm_crypt algif_skcipher af_alg hid_generic usbhid hid dm_mod dax sr_mod cdrom sd_mod crct10dif_pclmul crc32_pclmul crc32c_intel ghash_clmulni_intel pcbc ahci libahci aesni_intel aes_x86_64 crypto_simd xhci_pci glue_helper libata cryptd ehci_pci xhci_hcd ehci_hcd scsi_mod usbcore usb_common
 CPU: 3 PID: 555 Comm: Xorg Tainted: P           O     4.16.0-rc3-1-mainline #1
 Hardware name: System manufacturer System Product 
 RIP: 0010:usercopy_warn+0x7e/0xa0
 RSP: 0018:ffffa358c23f3b60 EFLAGS: 00010282
 RAX: 0000000000000000 RBX: ffff8c5c87f8acb0 RCX: 0000000000000006
 RDX: 0000000000000007 RSI: 0000000000000082 RDI: ffff8c5c9ecd6550
 RBP: 0000000000000003 R08: 000000000000037f R09: 0000000000000004
 R10: ffffffffbcd95dad R11: 0000000000000001 R12: 0000000000000001
 R13: ffff8c5c87f8acb3 R14: 0000000000000000 R15: ffff8c5c87f8acf8
 FS:  00007f9255821940(0000) GS:ffff8c5c9ecc0000(0000) knlGS:0000000000000000
 CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
 CR2: 00007f924d811e20 CR3: 000000040ad9a005 CR4: 00000000001606e0
 Call Trace:
  __check_object_size+0x130/0x1a0
  os_memcpy_to_user+0x21/0x40 [nvidia]
  _nv009373rm+0xbf/0xe0 [nvidia]
  ? _nv028042rm+0x79/0x90 [nvidia]
  ? _nv028042rm+0x55/0x90 [nvidia]
  ? _nv013687rm+0xee/0x100 [nvidia]
  ? _nv015333rm+0x154/0x270 [nvidia]
  ? _nv008306rm+0x134/0x1a0 [nvidia]
  ? _nv008285rm+0x29c/0x2b0 [nvidia]
  ? _nv001073rm+0xe/0x20 [nvidia]
  ? _nv007315rm+0xd8/0x100 [nvidia]
  ? _nv001172rm+0x627/0x830 [nvidia]
  ? rm_ioctl+0x73/0x100 [nvidia]
  ? nvidia_ioctl+0x573/0x720 [nvidia]
  ? nvidia_frontend_unlocked_ioctl+0x3e/0x50 [nvidia]
  ? do_vfs_ioctl+0xa4/0x630
  ? handle_mm_fault+0xe6/0x230
  ? SyS_ioctl+0x74/0x80
  ? do_syscall_64+0x67/0x120
  ? entry_SYSCALL_64_after_hwframe+0x3d/0xa2
 Code: 48 c7 c0 42 d6 d6 bc 48 0f 44 c2 41 50 51 41 51 48 89 f9 49 89 f1 4d 89 d8 4c 89 d2 48 89 c6 48 c7 c7 98 d6 d6 bc e8 22 11 e5 ff <0f> 0b 48 83 c4 18 c3 48 c7 c6 25 34 d6 bc 49 89 f1 49 89 f3 eb 
 ---[ end trace 41000305d58a23ba ]---

Solutuion one revert afcc90f8621e289cd082ba97900e76f01afe778c
Solution two declare the whole cache as a usercopy region.
Solution three as it is just a warning ignore it until nvidia fixes it.  Requires CONFIG_HARDENED_USERCOPY_FALLBACK=y or booting with slab_common.usercopy_fallback=Y
otherwise the copy will fail and that seems to cause X to fail usercopy_fallback is marked for removal "once it seems like all missing usercopy whitelists have been identified and fixed"

Any improvements or alternative solutions for either problem?
Edit:
fix git diff's being reversed.
Edit2:
The 4.15 modesetting patch is also still required for modesetting support.
Edit3:
Split issue one solution three into solutions three and four.

Last edited by loqs (2018-04-02 16:00:20)

Offline

Board footer

Powered by FluxBB