1 diff -ru usr/src/nv/Makefile.kbuild usr/src/nv.2305230/Makefile.kbuild
2 --- usr/src/nv/Makefile.kbuild 2008-01-21 11:48:11.000000000 -0800
3 +++ usr/src/nv.2305230/Makefile.kbuild 2008-03-18 12:55:25.461856977 -0700
11 sysctl_max_map_count \
12 diff -ru usr/src/nv/conftest.sh usr/src/nv.2305230/conftest.sh
13 --- usr/src/nv/conftest.sh 2008-01-21 11:48:11.000000000 -0800
14 +++ usr/src/nv.2305230/conftest.sh 2008-03-18 12:55:28.782046180 -0700
21 + # Determine if the set_pages_uc() function is present.
23 + echo "#include <linux/autoconf.h>
24 + #include <asm/cacheflush.h>
25 + void conftest_set_pages_uc(void) {
29 + $CC $CFLAGS -c conftest$$.c > /dev/null 2>&1
32 + if [ -f conftest$$.o ]; then
34 + echo "#undef NV_SET_PAGES_UC_PRESENT" >> conftest.h
37 + echo "#ifdef NV_CHANGE_PAGE_ATTR_PRESENT" >> conftest.h
38 + echo "#undef NV_CHANGE_PAGE_ATTR_PRESENT" >> conftest.h
39 + echo "#endif" >> conftest.h
40 + echo "#define NV_SET_PAGES_UC_PRESENT" >> conftest.h
47 # Determine if the change_page_attr() function is
52 + echo "#ifndef NV_SET_PAGES_UC_PRESENT" >> conftest.h
53 echo "#define NV_CHANGE_PAGE_ATTR_PRESENT" >> conftest.h
54 + echo "#endif" >> conftest.h
64 echo "#include <linux/autoconf.h>
65 #include <linux/interrupt.h>
66 irq_handler_t conftest_isr;
67 diff -ru usr/src/nv/nv-linux.h usr/src/nv.2305230/nv-linux.h
68 --- usr/src/nv/nv-linux.h 2008-01-21 11:48:11.000000000 -0800
69 +++ usr/src/nv.2305230/nv-linux.h 2008-03-18 12:57:26.340745475 -0700
71 #include <linux/utsname.h>
74 -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0)
75 -# error This driver does not support pre-2.4 kernels!
76 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 7)
77 +# error This driver does not support 2.4 kernels older than 2.4.7!
78 #elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
80 #elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
82 #include <linux/modversions.h>
85 +#if defined(KERNEL_2_4) && !defined(EXPORT_SYMTAB)
86 +#define EXPORT_SYMTAB
89 #include <linux/kernel.h>
90 #include <linux/module.h>
94 #include <linux/spinlock.h>
95 #include <asm/semaphore.h>
96 +#include <linux/completion.h>
97 #include <linux/highmem.h>
103 #if defined(CONFIG_KGDB)
104 +#if defined(NV_OLD_MM_KGDB_BREAKPOINT_PRESENT)
105 +#include <asm/kgdb.h>
107 #include <linux/kgdb.h>
111 #if defined (CONFIG_AGP) || defined (CONFIG_AGP_MODULE)
113 @@ -516,19 +525,16 @@
114 #define NV_KMEM_CACHE_ALLOC(ptr, kmem_cache, type) \
116 (ptr) = kmem_cache_alloc(kmem_cache, GFP_KERNEL); \
117 - KM_ALLOC_RECORD(ptr, sizeof(type), "km_cache_alloc"); \
120 #define NV_KMEM_CACHE_FREE(ptr, type, kmem_cache) \
122 - KM_FREE_RECORD(ptr, sizeof(type), "km_cache_free"); \
123 kmem_cache_free(kmem_cache, ptr); \
126 -#if defined(NV_SG_MAP_BUFFERS) /* Linux/x86-64, only */
127 #if defined(NV_VMAP_PRESENT)
128 #if (NV_VMAP_ARGUMENT_COUNT == 2)
129 -#define NV_VMAP(ptr, pages, count, cached) \
130 +#define NV_VMAP_KERNEL(ptr, pages, count, prot) \
132 (ptr) = (unsigned long)vmap(pages, count); \
133 VM_ALLOC_RECORD((void *)ptr, (count) * PAGE_SIZE, "vm_vmap"); \
134 @@ -537,26 +543,35 @@
138 -#define NV_VMAP(ptr, pages, count, cached) \
139 +#define NV_VMAP_KERNEL(ptr, pages, count, prot) \
141 - pgprot_t __prot = (cached) ? PAGE_KERNEL : PAGE_KERNEL_NOCACHE; \
142 - (ptr) = (unsigned long)vmap(pages, count, VM_MAP, __prot); \
143 + (ptr) = (unsigned long)vmap(pages, count, VM_MAP, prot); \
144 VM_ALLOC_RECORD((void *)ptr, (count) * PAGE_SIZE, "vm_vmap"); \
147 #error "NV_VMAP_ARGUMENT_COUNT value unrecognized!"
150 +#if defined(NV_SG_MAP_BUFFERS)
151 #error "NV_VMAP() undefined (vmap() unavailable)!"
153 #endif /* NV_VMAP_PRESENT */
155 -#define NV_VUNMAP(ptr, count) \
156 +#define NV_VUNMAP_KERNEL(ptr, count) \
158 - VM_FREE_RECORD((void *)ptr, (count) * PAGE_SIZE, "vm_vmap"); \
159 + VM_FREE_RECORD((void *)ptr, (count) * PAGE_SIZE, "vm_vunmap"); \
160 vunmap((void *)(ptr)); \
163 -#endif /* NV_SG_MAP_BUFFERS */
164 +#define NV_VMAP(addr, pages, count, cached) \
166 + pgprot_t __prot = (cached) ? PAGE_KERNEL : PAGE_KERNEL_NOCACHE; \
167 + void *__ptr = nv_vmap(pages, count, __prot); \
168 + (addr) = (unsigned long)__ptr; \
171 +#define NV_VUNMAP(addr, count) nv_vunmap((void *)addr, count)
174 #endif /* !defined NVWATCH */
178 #define NV_PGD_OFFSET(address, kernel, mm) \
180 + struct mm_struct *__mm = (mm); \
183 - __pgd = pgd_offset(mm, address); \
184 + __pgd = pgd_offset(__mm, address); \
186 __pgd = pgd_offset_k(address); \
189 #define NV_ALLOC_TYPE_PCI (1<<0)
190 #define NV_ALLOC_TYPE_AGP (1<<1)
191 #define NV_ALLOC_TYPE_CONTIG (1<<2)
192 -#define NV_ALLOC_TYPE_KERNEL (1<<3)
193 -#define NV_ALLOC_TYPE_VMALLOC (1<<4)
194 -#define NV_ALLOC_TYPE_VMAP (1<<5)
195 +#define NV_ALLOC_TYPE_VMAP (1<<3)
197 #define NV_ALLOC_MAPPING_SHIFT 16
198 #define NV_ALLOC_MAPPING(flags) (((flags)>>NV_ALLOC_MAPPING_SHIFT)&0xff)
201 #define NV_ALLOC_MAPPING_AGP(flags) ((flags) & NV_ALLOC_TYPE_AGP)
202 #define NV_ALLOC_MAPPING_CONTIG(flags) ((flags) & NV_ALLOC_TYPE_CONTIG)
203 -#define NV_ALLOC_MAPPING_VMALLOC(flags) ((flags) & NV_ALLOC_TYPE_VMALLOC)
204 #define NV_ALLOC_MAPPING_VMAP(flags) ((flags) & NV_ALLOC_TYPE_VMAP)
206 static inline U032 nv_alloc_init_flags(int cached, int agp, int contig, int kernel)
207 @@ -988,12 +1001,7 @@
208 U032 flags = NV_ALLOC_ENC_MAPPING(cached);
209 if (agp) flags |= NV_ALLOC_TYPE_AGP;
210 else flags |= NV_ALLOC_TYPE_PCI;
211 - if (kernel) flags |= NV_ALLOC_TYPE_KERNEL;
212 -#if defined(NV_SG_MAP_BUFFERS)
213 if (kernel && !contig) flags |= NV_ALLOC_TYPE_VMAP;
215 - if (kernel && !contig) flags |= NV_ALLOC_TYPE_VMALLOC;
217 if (contig && !agp) flags |= NV_ALLOC_TYPE_CONTIG;
220 @@ -1067,21 +1075,24 @@
221 #define NV_ATOMIC_DEC_AND_TEST(data) atomic_dec_and_test(&(data))
222 #define NV_ATOMIC_READ(data) atomic_read(&(data))
224 +extern int nv_update_memory_types;
227 - * a BUG() is triggered on early 2.6 x86_64 kernels. the underlying
228 - * problem actually exists on many architectures and kernels, but
229 - * these are the only kernels that check the condition and trigger
230 - * a BUG(). note that this is a problem of the core kernel, not an
231 - * nvidia bug (and can still be triggered by agpgart). let's avoid
232 - * change_page_attr on those kernels.
233 + * Using change_page_attr() on early Linux/x86-64 2.6 kernels may
234 + * result in a BUG() being triggered. The underlying problem
235 + * actually exists on multiple architectures and kernels, but only
236 + * the above check for the condition and trigger a BUG().
238 + * Note that this is a due to a bug in the Linux kernel, not an
239 + * NVIDIA driver bug (it can also be triggered by AGPGART).
241 + * We therefore need to determine at runtime if change_page_attr()
242 + * can be used safely on these kernels.
244 -#if defined(NV_CHANGE_PAGE_ATTR_PRESENT)
245 -extern int nv_use_cpa;
247 -#if defined(NVCPU_X86_64) && !defined(KERNEL_2_4) && \
248 - (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11))
249 -#define NV_CHANGE_PAGE_ATTR_BUG_PRESENT 1
251 +#if defined(NV_CHANGE_PAGE_ATTR_PRESENT) && defined(NVCPU_X86_64) && \
252 + !defined(KERNEL_2_4) && \
253 + (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11))
254 +#define NV_CHANGE_PAGE_ATTR_BUG_PRESENT
257 #if defined(NVCPU_X86) || defined(NVCPU_X86_64)
258 @@ -1093,7 +1104,7 @@
260 * We need to be careful to mask out _PAGE_NX when the host system
261 * doesn't support this feature or when it's disabled: the kernel
262 - * may not do this in its implementation of the change_page_attr()
263 + * may not do this in its implementation of the change_page_attr()
266 #ifndef X86_FEATURE_NX
267 diff -ru usr/src/nv/nv-vm.c usr/src/nv.2305230/nv-vm.c
268 --- usr/src/nv/nv-vm.c 2008-01-21 11:48:11.000000000 -0800
269 +++ usr/src/nv.2305230/nv-vm.c 2008-03-18 12:55:58.755754293 -0700
275 - * AMD Athlon processors expose a subtle bug in the Linux
276 - * kernel, that may lead to AGP memory corruption. Recent
277 - * kernel versions had a workaround for this problem, but
278 - * 2.4.20 is the first kernel to address it properly. The
279 - * page_attr API provides the means to solve the problem.
282 static inline void nv_set_page_attrib_uncached(nv_pte_t *page_ptr)
284 -#if defined(NV_CHANGE_PAGE_ATTR_PRESENT)
286 + if (nv_update_memory_types)
288 - struct page *page = virt_to_page(__va(page_ptr->phys_addr));
289 +#if defined(NV_SET_PAGES_UC_PRESENT)
290 + struct page *page = NV_GET_PAGE_STRUCT(page_ptr->phys_addr);
291 + set_pages_uc(page, 1);
292 +#elif defined(NV_CHANGE_PAGE_ATTR_PRESENT)
293 + struct page *page = NV_GET_PAGE_STRUCT(page_ptr->phys_addr);
294 pgprot_t prot = PAGE_KERNEL_NOCACHE;
295 #if defined(NVCPU_X86) || defined(NVCPU_X86_64)
296 pgprot_val(prot) &= __nv_supported_pte_mask;
298 change_page_attr(page, 1, prot);
304 static inline void nv_set_page_attrib_cached(nv_pte_t *page_ptr)
306 -#if defined(NV_CHANGE_PAGE_ATTR_PRESENT)
308 + if (nv_update_memory_types)
310 - struct page *page = virt_to_page(__va(page_ptr->phys_addr));
311 +#if defined(NV_SET_PAGES_UC_PRESENT)
312 + struct page *page = NV_GET_PAGE_STRUCT(page_ptr->phys_addr);
313 + set_pages_wb(page, 1);
314 +#elif defined(NV_CHANGE_PAGE_ATTR_PRESENT)
315 + struct page *page = NV_GET_PAGE_STRUCT(page_ptr->phys_addr);
316 pgprot_t prot = PAGE_KERNEL;
317 #if defined(NVCPU_X86) || defined(NVCPU_X86_64)
318 pgprot_val(prot) &= __nv_supported_pte_mask;
320 change_page_attr(page, 1, prot);
323 -#endif /* NV_CHANGE_PAGE_ATTR_PRESENT */
326 static inline void nv_lock_page(nv_pte_t *page_ptr)
328 #if defined(NV_CPA_NEEDS_FLUSHING)
329 nv_execute_on_all_cpus(cache_flush, NULL);
331 +#if (defined(NVCPU_X86) || defined(NVCPU_X86_64)) && \
332 + defined(NV_CHANGE_PAGE_ATTR_PRESENT)
339 @@ -409,11 +410,11 @@
340 nv_pte_t *page_ptr = *at->page_table;
341 unsigned int i, j, gfp_mask;
342 unsigned long virt_addr = 0, phys_addr;
343 + struct page **pages = 0;
344 #if defined(NV_SG_MAP_BUFFERS)
346 nv_linux_state_t *nvl = NV_GET_NVL_FROM_NV_STATE(nv);
347 struct pci_dev *dev = nvl->dev;
348 - struct page **pages = 0;
351 nv_printf(NV_DBG_MEMINFO, "NVRM: VM: nv_vm_malloc_pages: %d pages\n",
356 - else if (NV_ALLOC_MAPPING_VMALLOC(at->flags))
358 - void *virt_kptr = NULL;
359 - at->size = at->num_pages * PAGE_SIZE;
360 - nv_printf(NV_DBG_MEMINFO, "NVRM: VM: vmalloc, size 0x%x\n", at->size);
361 - NV_VMALLOC(virt_kptr, at->size, NV_ALLOC_MAPPING_CACHED(at->flags));
362 - virt_addr = (unsigned long) virt_kptr;
363 - if (virt_addr == 0)
365 - nv_printf(NV_DBG_ERRORS,
366 - "NVRM: nv_vm_malloc failed to allocate vmalloc memory\n");
371 -#if defined(NV_SG_MAP_BUFFERS)
372 if (NV_ALLOC_MAPPING_VMAP(at->flags))
374 NV_KMALLOC(pages, sizeof(struct page *) * at->num_pages);
375 @@ -488,11 +474,10 @@
381 for (i = 0; i < at->num_pages; i++)
383 - if (!NV_ALLOC_MAPPING_CONTIG(at->flags) && !NV_ALLOC_MAPPING_VMALLOC(at->flags))
384 + if (!NV_ALLOC_MAPPING_CONTIG(at->flags))
386 NV_GET_FREE_PAGES(virt_addr, 0, gfp_mask);
388 @@ -553,10 +538,10 @@
391 nv_sg_load(&page_ptr->sg_list, page_ptr);
394 if (NV_ALLOC_MAPPING_VMAP(at->flags))
395 pages[i] = NV_GET_PAGE_STRUCT(page_ptr->phys_addr);
398 if (!NV_ALLOC_MAPPING_CACHED(at->flags))
399 nv_set_page_attrib_uncached(page_ptr);
400 @@ -565,41 +550,21 @@
401 virt_addr += PAGE_SIZE;
404 -#if defined(NV_SG_MAP_BUFFERS)
405 if (NV_ALLOC_MAPPING_VMAP(at->flags))
407 NV_VMAP(virt_addr, pages, at->num_pages, NV_ALLOC_MAPPING_CACHED(at->flags));
408 -#if defined(KERNEL_2_4)
409 - if (virt_addr != 0)
413 - * XXX Linux 2.4's vmap() increments the pages' reference counts
414 - * in preparation for vfree(); the latter skips the calls to
415 - * __free_page() if the pages are marked reserved, however, so
416 - * that the underlying memory is effectively leaked when we free
417 - * it later. Decrement the count here to avoid this leak.
419 - for (i = 0; i < at->num_pages; i++)
421 - if (PageReserved(pages[i]))
422 - atomic_dec(&pages[i]->count);
426 - NV_KFREE((void *)pages, sizeof(struct page *) * at->num_pages);
429 nv_printf(NV_DBG_ERRORS,
430 "NVRM: VM: nv_vm_malloc_pages: failed to vmap pages\n");
433 + NV_KFREE((void *)pages, sizeof(struct page *) * at->num_pages);
434 for (i = 0; i < at->num_pages; i++)
436 at->page_table[i]->virt_addr = virt_addr + i * PAGE_SIZE;
439 -#endif /* NV_SG_MAP_BUFFERS */
441 nv_vm_list_page_count(at->page_table, at->num_pages);
444 nv_sg_unmap_buffer(dev, &page_ptr->sg_list, page_ptr);
446 nv_unlock_page(page_ptr);
447 - if (!NV_ALLOC_MAPPING_CONTIG(at->flags) && !NV_ALLOC_MAPPING_VMALLOC(at->flags))
448 + if (!NV_ALLOC_MAPPING_CONTIG(at->flags))
449 NV_FREE_PAGES(page_ptr->virt_addr, 0);
454 NV_FREE_PAGES(page_ptr->virt_addr, at->order);
456 - else if (NV_ALLOC_MAPPING_VMALLOC(at->flags))
458 - page_ptr = *at->page_table;
459 - NV_VFREE((void *) page_ptr->virt_addr, at->size);
462 -#if defined(NV_SG_MAP_BUFFERS)
463 if (NV_ALLOC_MAPPING_VMAP(at->flags) && pages != 0)
464 - NV_VFREE((void *)pages, sizeof(struct page *) * at->num_pages);
466 + NV_KFREE((void *)pages, sizeof(struct page *) * at->num_pages);
470 @@ -674,19 +632,17 @@
472 nv_vm_list_page_count(at->page_table, at->num_pages);
474 -#if defined(NV_SG_MAP_BUFFERS)
475 if (NV_ALLOC_MAPPING_VMAP(at->flags))
476 NV_VUNMAP((void *)at->page_table[0]->virt_addr, at->num_pages); // undo vmap()
479 for (i = 0; i < at->num_pages; i++)
481 page_ptr = at->page_table[i];
482 if (!NV_ALLOC_MAPPING_CACHED(at->flags))
483 nv_set_page_attrib_cached(page_ptr);
484 -#if defined(NV_SG_MAP_BUFFERS)
485 if (NV_ALLOC_MAPPING_VMAP(at->flags))
486 page_ptr->virt_addr = (unsigned long) __va(page_ptr->phys_addr);
487 +#if defined(NV_SG_MAP_BUFFERS)
488 if (!NV_ALLOC_MAPPING_CONTIG(at->flags))
489 nv_sg_unmap_buffer(dev, &page_ptr->sg_list, page_ptr);
494 nv_unlock_page(page_ptr);
495 - if (!NV_ALLOC_MAPPING_CONTIG(at->flags) && !NV_ALLOC_MAPPING_VMALLOC(at->flags))
496 + if (!NV_ALLOC_MAPPING_CONTIG(at->flags))
497 NV_FREE_PAGES(page_ptr->virt_addr, 0);
500 @@ -714,9 +670,136 @@
502 NV_FREE_PAGES(page_ptr->virt_addr, at->order);
504 - else if (NV_ALLOC_MAPPING_VMALLOC(at->flags))
507 +#if defined(NV_VMAP_PRESENT) && defined(KERNEL_2_4) && defined(NVCPU_X86)
508 +static unsigned long
511 + struct page **pages,
515 + void *virt_addr = NULL;
516 + unsigned int i, size = count * PAGE_SIZE;
518 + NV_VMALLOC(virt_addr, size, TRUE);
519 + if (virt_addr == NULL)
521 + nv_printf(NV_DBG_ERRORS,
522 + "NVRM: vmalloc() failed to allocate vmap() scratch pages!\n");
526 + for (i = 0; i < (unsigned int)count; i++)
528 - page_ptr = *at->page_table;
529 - NV_VFREE((void *) page_ptr->virt_addr, at->size);
533 + unsigned long address;
536 + address = (unsigned long)virt_addr + i * PAGE_SIZE;
538 + pgd = NV_PGD_OFFSET(address, 1, NULL);
539 + if (!NV_PGD_PRESENT(pgd))
542 + pmd = NV_PMD_OFFSET(address, pgd);
543 + if (!NV_PMD_PRESENT(pmd))
546 + pte = NV_PTE_OFFSET(address, pmd);
547 + if (!NV_PTE_PRESENT(pte))
550 + page = NV_GET_PAGE_STRUCT(pte_val(*pte) & PAGE_MASK);
551 + get_page(pages[i]);
552 + set_pte(pte, mk_pte(pages[i], prot));
558 + return (unsigned long)virt_addr;
561 + NV_VFREE(virt_addr, size);
572 + NV_VFREE(address, count * PAGE_SIZE);
574 +#endif /* NV_VMAP_PRESENT && KERNEL_2_4 && NVCPU_X86 */
577 + struct page **pages,
582 + unsigned long virt_addr = 0;
583 +#if defined(NV_VMAP_PRESENT)
584 +#if defined(KERNEL_2_4) && defined(NVCPU_X86)
586 + * XXX Linux 2.4's vmap() checks the requested mapping's size against
587 + * the value of (max_mapnr << PAGESHIFT); since 'map_nr' is a 32-bit
588 + * symbol, the checks fails given enough physical memory. We can't solve
589 + * this problem by adjusting the value of 'map_nr', but we can avoid
590 + * vmap() by going through vmalloc().
592 + if (max_mapnr >= 0x100000)
593 + virt_addr = nv_vmap_vmalloc(count, pages, prot);
596 + NV_VMAP_KERNEL(virt_addr, pages, count, prot);
597 +#if defined(KERNEL_2_4)
602 + * XXX Linux 2.4's vmap() increments the pages' reference counts
603 + * in preparation for vfree(); the latter skips the calls to
604 + * __free_page() if the pages are marked reserved, however, so
605 + * that the underlying memory is effectively leaked when we free
606 + * it later. Decrement the count here to avoid this leak.
608 + for (i = 0; i < count; i++)
610 + if (PageReserved(pages[i]))
611 + atomic_dec(&pages[i]->count);
615 +#endif /* NV_VMAP_PRESENT */
616 + return (void *)virt_addr;
624 +#if defined(NV_VMAP_PRESENT)
625 +#if defined(KERNEL_2_4) && defined(NVCPU_X86)
627 + * XXX Linux 2.4's vmap() checks the requested mapping's size against
628 + * the value of (max_mapnr << PAGESHIFT); since 'map_nr' is a 32-bit
629 + * symbol, the checks fails given enough physical memory. We can't solve
630 + * this problem by adjusting the value of 'map_nr', but we can avoid
631 + * vmap() by going through vmalloc().
633 + if (max_mapnr >= 0x100000)
634 + nv_vunmap_vmalloc(address, count);
637 + NV_VUNMAP_KERNEL(address, count);
638 +#endif /* NV_VMAP_PRESENT */
640 diff -ru usr/src/nv/nv-vm.h usr/src/nv.2305230/nv-vm.h
641 --- usr/src/nv/nv-vm.h 2008-01-21 11:48:11.000000000 -0800
642 +++ usr/src/nv.2305230/nv-vm.h 2008-03-18 12:55:54.643519951 -0700
647 +void * nv_vmap(struct page **, int, pgprot_t);
648 +void nv_vunmap(void *, int);
650 int nv_vm_malloc_pages(nv_state_t *, nv_alloc_t *);
651 void nv_vm_free_pages(nv_state_t *, nv_alloc_t *);
653 diff -ru usr/src/nv/nv.c usr/src/nv.2305230/nv.c
654 --- usr/src/nv/nv.c 2008-01-21 11:48:11.000000000 -0800
655 +++ usr/src/nv.2305230/nv.c 2008-03-18 12:56:01.123889244 -0700
657 unsigned int nv_remap_limit;
660 -#if defined(NV_CHANGE_PAGE_ATTR_PRESENT)
663 +int nv_update_memory_types = 1;
665 static void *nv_pte_t_cache = NULL;
667 @@ -850,16 +848,13 @@
669 for (i = 0; i < 4; i++)
671 - if (NV_PAT_ENTRY(pat1, i) == 1)
672 + if ((i != 1) && NV_PAT_ENTRY(pat1, i) == 1)
674 nv_printf(NV_DBG_ERRORS, "NVRM: PAT index %d already configured for Write-Combining!\n", i);
675 nv_printf(NV_DBG_ERRORS, "NVRM: Aborting, due to PAT already being configured\n");
680 - for (i = 0; i < 4; i++)
682 if (NV_PAT_ENTRY(pat2, i) == 1)
684 nv_printf(NV_DBG_ERRORS, "NVRM: PAT index %d already configured for Write-Combining!\n", i + 4);
685 @@ -969,30 +964,26 @@
686 #endif /* defined(NV_BUILD_NV_PAT_SUPPORT) */
690 #if defined(NV_CHANGE_PAGE_ATTR_BUG_PRESENT)
692 -/* nv_verify_cpa_interface - determine if the change_page_attr bug is fixed
695 + * nv_verify_cpa_interface() - determine if the change_page_attr() large page
696 + * management accounting bug known to exist in early Linux/x86-64 kernels
697 + * is present in this kernel.
699 - * there's really not a good way to determine if change_page_attr is fixed.
700 - * we can't really use cpa on 2.6 x86_64 kernels < 2.6.11, as if we run into
701 - * the accounting bug, the kernel will throw a BUG. this isn't 100% accurate,
702 - * as it doesn't throw a bug until we try to restore the caching attributes
703 - * of the page. so if we can track down a 4M allocation, we can mark it
704 - * uncached and see if the accounting was done correctly.
706 - * this is a little ugly, but the most accurate approach to determining if
707 - * this kernel is good.
708 + * There's really no good way to determine if change_page_attr() is working
709 + * correctly. We can't reliably use change_page_attr() on Linux/x86-64 2.6
710 + * kernels < 2.6.11: if we run into the accounting bug, the Linux kernel will
711 + * trigger a BUG() if we attempt to restore the WB memory type of a page
712 + * originally part of a large page.
714 - * why do we even bother? some distributions have back-ported the cpa fix to
715 - * kernels < 2.6.11. we want to use change_page_attr to avoid random corruption
716 - * and hangs, but need to make sure it's safe to do so.
717 + * So if we can successfully allocate such a page, change its memory type to
718 + * UC and check if the accounting was done correctly, we can determine if
719 + * the change_page_attr() interface can be used safely.
722 - * 0 - test passed, interface works
723 - * 1 - test failed, status unclear
724 - * -1 - test failed, interface broken
726 + * 0 - test passed, the change_page_attr() interface works
727 + * 1 - test failed, the status is unclear
728 + * -1 - test failed, the change_page_attr() interface is broken
731 static inline pte_t *check_large_page(unsigned long vaddr)
736 - pgd = NV_PGD_OFFSET(vaddr, 1, &init_mm);
737 + pgd = NV_PGD_OFFSET(vaddr, 1, NULL);
738 if (!NV_PGD_PRESENT(pgd))
741 @@ -1110,35 +1101,42 @@
746 #endif /* defined(NV_CHANGE_PAGE_ATTR_BUG_PRESENT) */
749 -// verify that the kernel's mapping matches the requested type
750 -// this is to protect against accidental cache aliasing problems
752 + * nv_verify_page_mappings() - verify that the kernel mapping of the specified
753 + * page matches the specified type. This is to help detect bugs in the Linux
754 + * kernel's change_page_attr() interface, early.
756 + * This function relies on the ability to perform kernel virtul address to PFN
757 + * translations and therefore on 'init_mm'. Unfortunately, the latter is no
758 + * longer exported in recent Linux/x86 2.6 kernels. The export was removed at
759 + * roughtly the same time as the set_pages_{uc,wb}() change_page_attr()
760 + * replacement interfaces were introduced; hopefully, it will be sufficient to
761 + * check for their presence.
763 int nv_verify_page_mappings(
765 unsigned int cachetype
768 - struct mm_struct *mm;
769 +#if defined(NV_CHANGE_PAGE_ATTR_PRESENT) || \
770 + (defined(NV_SET_PAGES_UC_PRESENT) && !defined(NVCPU_X86))
771 + unsigned long retval = -1;
772 +#if defined(NVCPU_X86) || defined(NVCPU_X86_64)
776 - unsigned long retval = -1;
777 unsigned int flags, expected;
778 unsigned long address;
779 static int count = 0;
781 -#if defined(NV_CHANGE_PAGE_ATTR_PRESENT)
783 + if (!nv_update_memory_types)
787 address = (unsigned long)__va(page_ptr->phys_addr);
788 - mm = &init_mm; // always a kernel page
790 - pgd = NV_PGD_OFFSET(address, 1, mm);
791 + pgd = NV_PGD_OFFSET(address, 1, NULL);
792 if (!NV_PGD_PRESENT(pgd))
794 nv_printf(NV_DBG_ERRORS, "NVRM: pgd not present for addr 0x%lx\n", address);
795 @@ -1204,7 +1202,11 @@
799 +#endif /* defined(NVCPU_X86) || defined(NVCPU_X86_64) */
806 #if defined(NV_BUILD_NV_PAT_SUPPORT) && defined(CONFIG_HOTPLUG_CPU)
807 @@ -1250,7 +1252,8 @@
808 static int __init nvidia_init_module(void)
812 + U032 i, count, data;
813 + nv_state_t *nv = NV_STATE_PTR(&nv_ctl_device);
815 #if defined(VM_CHECKER)
816 nv_init_lock(vm_lock);
817 @@ -1266,11 +1269,18 @@
823 + nv_printf(NV_DBG_ERRORS, "NVRM: rm_init_rm() failed!\n");
827 memset(nv_linux_devices, 0, sizeof(nv_linux_devices));
829 if (pci_register_driver(&nv_pci_driver) < 0)
831 pci_unregister_driver(&nv_pci_driver); // XXX ???
833 nv_printf(NV_DBG_ERRORS, "NVRM: No NVIDIA graphics adapter found!\n");
836 @@ -1293,6 +1303,7 @@
837 if (num_probed_nv_devices == 0)
839 pci_unregister_driver(&nv_pci_driver);
841 nv_printf(NV_DBG_ERRORS, "NVRM: No NVIDIA graphics adapter probed!\n");
844 @@ -1307,6 +1318,7 @@
845 if (num_nv_devices == 0)
847 pci_unregister_driver(&nv_pci_driver);
849 nv_printf(NV_DBG_ERRORS,
850 "NVRM: None of the NVIDIA graphics adapters were initialized!\n");
852 @@ -1317,8 +1329,9 @@
853 rc = register_chrdev(nv_major, "nvidia", &nv_fops);
856 - nv_printf(NV_DBG_ERRORS, "NVRM: register chrdev failed\n");
857 pci_unregister_driver(&nv_pci_driver);
859 + nv_printf(NV_DBG_ERRORS, "NVRM: register_chrdev() failed!\n");
863 @@ -1367,14 +1380,6 @@
867 - // Init the resource manager
870 - nv_printf(NV_DBG_ERRORS, "NVRM: rm_init_rm() failed\n");
875 #if defined(NV_SG_MAP_BUFFERS)
876 rm_read_registry_dword(NV_STATE_PTR(&nv_ctl_device), "NVreg", "RemapLimit", &nv_remap_limit);
878 @@ -1407,48 +1412,41 @@
879 /* create /proc/driver/nvidia */
882 -#if defined(NV_CHANGE_PAGE_ATTR_PRESENT)
884 + * Give users an opportunity to disable the driver's use of
885 + * the change_page_attr() and set_pages_{uc,wb}() kernel
888 + rc = rm_read_registry_dword(nv, "NVreg", "UpdateMemoryTypes", &data);
889 + if ((rc == 0) && ((int)data != ~0))
893 - // allow the user to override us with a registry key
894 - rc = rm_read_registry_dword(NV_STATE_PTR(&nv_ctl_device), "NVreg", "UseCPA", &data);
895 - if ((rc == 0) && (data != -1))
899 + nv_update_memory_types = data;
901 #if defined(NV_CHANGE_PAGE_ATTR_BUG_PRESENT)
904 + * Unless we explicitely detect that the change_page_attr()
905 + * inteface is fixed, disable usage of the interface on
906 + * this kernel. Notify the user of this problem using the
907 + * driver's /proc warnings interface (read by the installer
908 + * and the bug report script).
912 + rc = nv_verify_cpa_interface();
916 - * Unless we explicitely detect that the change_page_attr()
917 - * inteface is fixed, disable usage of the interface on
918 - * this kernel. Notify the user of this problem using the
919 - * driver's /proc warnings interface (read by the installer
920 - * and the bug report script).
922 - rc = nv_verify_cpa_interface();
925 - nv_prints(NV_DBG_ERRORS, __cpgattr_warning);
926 - nvos_proc_add_warning_file("change_page_attr", __cpgattr_warning);
931 - nv_prints(NV_DBG_ERRORS, __cpgattr_warning_2);
932 - nvos_proc_add_warning_file("change_page_attr", __cpgattr_warning_2);
935 + nv_prints(NV_DBG_ERRORS, __cpgattr_warning);
936 + nvos_proc_add_warning_file("change_page_attr", __cpgattr_warning);
937 + nv_update_memory_types = 0;
941 + nv_prints(NV_DBG_ERRORS, __cpgattr_warning_2);
942 + nvos_proc_add_warning_file("change_page_attr", __cpgattr_warning_2);
943 + nv_update_memory_types = 0;
951 - inter_module_register("nv_linux_devices", THIS_MODULE, nv_linux_devices);
953 +#endif /* defined(NV_CHANGE_PAGE_ATTR_BUG_PRESENT) */
955 #if defined(NVCPU_X86_64) && defined(CONFIG_IA32_EMULATION) && !defined(HAVE_COMPAT_IOCTL)
956 /* Register ioctl conversions for 32 bit clients */
957 @@ -1501,6 +1499,8 @@
960 pci_unregister_driver(&nv_pci_driver);
966 @@ -1532,10 +1532,6 @@
967 /* remove /proc/driver/nvidia */
971 - inter_module_unregister("nv_linux_devices");
974 #if defined(NV_PM_SUPPORT_OLD_STYLE_APM)
975 for (i = 0; i < num_nv_devices; i++)
977 @@ -2112,6 +2108,8 @@
978 if (rm_validate_pfn_range(file, NV_VMA_PGOFF(vma),
979 NV_VMA_SIZE(vma)) == RM_OK)
981 + if (vma->vm_flags & VM_WRITE)
983 vma->vm_flags |= (VM_IO | VM_LOCKED);
984 #if defined(NV_VM_INSERT_PAGE_PRESENT)
985 if (NV_VM_INSERT_PAGE(vma, vma->vm_start, pfn_to_page(NV_VMA_PGOFF(vma))))
986 @@ -2240,6 +2238,8 @@
987 if (rm_validate_pfn_range(file, NV_VMA_PGOFF(vma),
988 NV_VMA_SIZE(vma)) == RM_OK)
990 + if (vma->vm_flags & VM_WRITE)
992 vma->vm_flags |= (VM_IO | VM_LOCKED);
993 #if defined(NV_VM_INSERT_PAGE_PRESENT)
994 if (NV_VM_INSERT_PAGE(vma, vma->vm_start, pfn_to_page(NV_VMA_PGOFF(vma))))
995 @@ -3266,8 +3266,21 @@
997 unsigned long retval;
999 - mm = (kern) ? &init_mm : current->mm;
1000 - if (!kern) down_read(¤t->mm->mmap_sem);
1004 + down_read(&mm->mmap_sem);
1008 +#if defined(NV_SET_PAGES_UC_PRESENT) && defined(NVCPU_X86)
1009 + /* nv_printf(NV_DBG_ERRORS,
1010 + "NVRM: can't translate KVA in nv_get_phys_address()!\n"); */
1017 pgd = NV_PGD_OFFSET(address, kern, mm);
1018 if (!NV_PGD_PRESENT(pgd))
1019 @@ -3288,11 +3301,13 @@
1020 retval &= ~_PAGE_NX;
1023 - if (!kern) up_read(¤t->mm->mmap_sem);
1025 + up_read(&mm->mmap_sem);
1029 - if (!kern) up_read(¤t->mm->mmap_sem);
1031 + up_read(&mm->mmap_sem);
1035 @@ -3300,12 +3315,19 @@
1036 unsigned long address
1039 - // make sure this address is a kernel pointer
1040 +#if defined(NV_SET_PAGES_UC_PRESENT) && defined(NVCPU_X86)
1041 + nv_linux_state_t *nvl;
1043 + unsigned long virt_addr;
1047 + /* make sure this address is a kernel virtual address */
1048 #if defined(DEBUG) && !defined(CONFIG_X86_4G)
1049 if (address < PAGE_OFFSET)
1051 nv_printf(NV_DBG_WARNINGS,
1052 - "NVRM: user address passed to get_kern_phys_address: 0x%lx\n",
1053 + "NVRM: user address passed to get_kern_phys_address: 0x%llx!\n",
1057 @@ -3315,6 +3337,30 @@
1058 if ((address > PAGE_OFFSET) && (address < VMALLOC_START))
1059 return __pa(address);
1061 +#if defined(NV_SET_PAGES_UC_PRESENT) && defined(NVCPU_X86)
1062 + for (i = 0; i < num_nv_devices; i++)
1064 + nvl = &nv_linux_devices[i];
1066 + for (at = nvl->alloc_queue; (at != NULL); at = at->next)
1068 + if (!NV_ALLOC_MAPPING_VMAP(at->flags))
1071 + for (j = 0; j < at->num_pages; j++)
1073 + virt_addr = at->page_table[j]->virt_addr;
1074 + if ((address >= virt_addr) &&
1075 + (address < (virt_addr + PAGE_SIZE)))
1077 + return (at->page_table[j]->phys_addr +
1078 + (address & ~PAGE_MASK));
1085 return _get_phys_address(address, 1);
1088 @@ -3322,12 +3368,12 @@
1089 unsigned long address
1092 - // make sure this address is not a kernel pointer
1093 + /* make sure this address is not a kernel virtual address */
1094 #if defined(DEBUG) && !defined(CONFIG_X86_4G)
1095 if (address >= PAGE_OFFSET)
1097 nv_printf(NV_DBG_WARNINGS,
1098 - "NVRM: kernel address passed to get_user_phys_address: 0x%lx\n",
1099 + "NVRM: kernel address passed to get_user_phys_address: 0x%llx!\n",
1103 @@ -3396,8 +3442,6 @@
1104 if (nv_vm_malloc_pages(nv, at))
1107 - at->class = class;
1109 // set our 'key' to the page_table. rm_alloc_agp_pages will call
1110 // nv_translate_address below, which will look up pages using
1111 // the value of *pAddress as a key, then index into the page_table
1112 @@ -3952,7 +3996,8 @@
1114 if (num_nv_devices == NV_MAX_DEVICES)
1116 - nv_printf(NV_DBG_ERRORS, "NVRM: maximum device number (%d) reached!\n", num_nv_devices);
1117 + nv_printf(NV_DBG_ERRORS, "NVRM: maximum device number (%d) exceeded!\n",
1118 + (NV_MAX_DEVICES - 1));
1122 @@ -4085,13 +4130,10 @@
1126 -int NV_API_CALL nv_no_incoherent_mappings
1130 +int NV_API_CALL nv_no_incoherent_mappings(void)
1132 -#if defined(NV_CHANGE_PAGE_ATTR_PRESENT)
1134 +#if defined(NV_CHANGE_PAGE_ATTR_PRESENT) || defined(NV_SET_PAGES_UC_PRESENT)
1135 + return (nv_update_memory_types);
1139 diff -ru usr/src/nv/nv.h usr/src/nv.2305230/nv.h
1140 --- usr/src/nv/nv.h 2008-01-21 11:48:11.000000000 -0800
1141 +++ usr/src/nv.2305230/nv.h 2008-03-18 12:55:56.919649651 -0700
1142 @@ -335,15 +332,39 @@
1144 #define NV_DEVICE_NAME_LENGTH 40
1146 +#define NV_MAX_ISR_DELAY_US 20000
1147 +#define NV_MAX_ISR_DELAY_MS (NV_MAX_ISR_DELAY_US / 1000)
1149 +#define NV_TIMERCMP(a, b, CMP) \
1150 + (((a)->tv_sec == (b)->tv_sec) ? \
1151 + ((a)->tv_usec CMP (b)->tv_usec) : ((a)->tv_sec CMP (b)->tv_sec))
1153 +#define NV_TIMERADD(a, b, result) \
1155 + (result)->tv_sec = (a)->tv_sec + (b)->tv_sec; \
1156 + (result)->tv_usec = (a)->tv_usec + (b)->tv_usec; \
1157 + if ((result)->tv_usec >= 1000000) \
1159 + ++(result)->tv_sec; \
1160 + (result)->tv_usec -= 1000000; \
1164 +#define NV_TIMERSUB(a, b, result) \
1166 + (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
1167 + (result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
1168 + if ((result)->tv_usec < 0) \
1170 + --(result)->tv_sec; \
1171 + (result)->tv_usec += 1000000; \
1176 * driver internal interfaces
1179 -/* need a fake device number for control device; just to flag it for msgs */
1180 -#define NV_CONTROL_DEVICE_NUMBER 100
1186 diff -ru usr/src/nv/os-interface.c usr/src/nv.2305230/os-interface.c
1187 --- usr/src/nv/os-interface.c 2008-01-21 11:48:11.000000000 -0800
1188 +++ usr/src/nv.2305230/os-interface.c 2008-03-18 12:56:04.288069559 -0700
1190 #include "os-interface.h"
1191 #include "nv-linux.h"
1194 static volatile int os_block_on_smp_barrier;
1199 typedef struct os_sema_s
1201 - struct semaphore wait;
1202 + struct completion completion;
1209 os_sema = (os_sema_t *)*ppSema;
1210 - sema_init(&os_sema->wait, 0);
1211 + init_completion(&os_sema->completion);
1212 spin_lock_init(&os_sema->lock);
1218 spin_unlock_irqrestore(&os_sema->lock, old_irq);
1219 - down(&os_sema->wait);
1220 + wait_for_completion(&os_sema->completion);
1225 spin_unlock_irqrestore(&os_sema->lock, old_irq);
1228 - up(&os_sema->wait);
1229 + complete(&os_sema->completion);
1235 //---------------------------------------------------------------------------
1237 -#define NV_MAX_ISR_UDELAY 20000
1238 -#define NV_MAX_ISR_MDELAY (NV_MAX_ISR_UDELAY / 1000)
1239 #define NV_MSECS_PER_JIFFIE (1000 / HZ)
1240 #define NV_MSECS_TO_JIFFIES(msec) ((msec) * HZ / 1000)
1241 #define NV_USECS_PER_JIFFIE (1000000 / HZ)
1243 do_gettimeofday(&tm1);
1246 - if (in_irq() && MicroSeconds > NV_MAX_ISR_UDELAY)
1247 + if (in_irq() && (MicroSeconds > NV_MAX_ISR_DELAY_US))
1250 mdelay_safe_msec = MicroSeconds / 1000;
1251 @@ -494,36 +491,6 @@
1256 -# define timercmp(a, b, CMP) \
1257 - (((a)->tv_sec == (b)->tv_sec) ? \
1258 - ((a)->tv_usec CMP (b)->tv_usec) : \
1259 - ((a)->tv_sec CMP (b)->tv_sec))
1262 -# define timeradd(a, b, result) \
1264 - (result)->tv_sec = (a)->tv_sec + (b)->tv_sec; \
1265 - (result)->tv_usec = (a)->tv_usec + (b)->tv_usec; \
1266 - if ((result)->tv_usec >= 1000000) \
1268 - ++(result)->tv_sec; \
1269 - (result)->tv_usec -= 1000000; \
1274 -# define timersub(a, b, result) \
1276 - (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
1277 - (result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
1278 - if ((result)->tv_usec < 0) { \
1279 - --(result)->tv_sec; \
1280 - (result)->tv_usec += 1000000; \
1286 * On Linux, a jiffie represents the time passed in between two timer
1287 * interrupts. The number of jiffies per second (HZ) varies across the
1292 - if (in_irq() && MilliSeconds > NV_MAX_ISR_MDELAY)
1293 + if (in_irq() && (MilliSeconds > NV_MAX_ISR_DELAY_MS))
1296 if (!NV_MAY_SLEEP())
1298 MicroSeconds = MilliSeconds * 1000;
1299 tm_end.tv_usec = MicroSeconds;
1301 - timeradd(&tm_aux, &tm_end, &tm_end);
1302 + NV_TIMERADD(&tm_aux, &tm_end, &tm_end);
1304 /* do we have a full jiffie to wait? */
1305 jiffies = NV_USECS_TO_JIFFIES(MicroSeconds);
1307 schedule_timeout(jiffies);
1308 /* catch the remainder, if any */
1309 do_gettimeofday(&tm_aux);
1310 - if (timercmp(&tm_aux, &tm_end, <))
1311 + if (NV_TIMERCMP(&tm_aux, &tm_end, <))
1313 - timersub(&tm_end, &tm_aux, &tm_aux); // tm_aux = tm_end - tm_aux
1314 + NV_TIMERSUB(&tm_end, &tm_aux, &tm_aux); // tm_aux = tm_end - tm_aux
1315 MicroSeconds = tm_aux.tv_usec + tm_aux.tv_sec * 1000000;
1318 @@ -1109,6 +1076,18 @@
1324 + if (mode != NV_MEMORY_CACHED)
1326 + nv_printf(NV_DBG_ERRORS,
1327 + "NVRM: os_map_kernel_space: won't map address 0x%0llx UC!\n", start);
1331 + return (void *)PAGE_OFFSET;
1334 if (!NV_MAY_SLEEP())
1336 nv_printf(NV_DBG_ERRORS,
1337 @@ -1131,6 +1110,9 @@
1341 + if (addr == (void *)PAGE_OFFSET)
1344 NV_IOUNMAP(addr, size_bytes);
1347 @@ -1176,7 +1158,11 @@
1348 #if defined(CONFIG_X86_REMOTE_DEBUG)
1349 __asm__ __volatile__ ("int $3");
1350 #elif defined(CONFIG_KGDB)
1351 +#if defined(NV_OLD_MM_KGDB_BREAKPOINT_PRESENT)
1356 #elif defined(CONFIG_KDB)
1359 diff -ru usr/src/nv/os-registry.c usr/src/nv.2305230/os-registry.c
1360 --- usr/src/nv/os-registry.c 2008-01-21 11:48:11.000000000 -0800
1361 +++ usr/src/nv.2305230/os-registry.c 2008-03-18 12:56:07.492252151 -0700
1363 * This could be changed to work on a per-device basis.
1367 - * The 2nd argument to MODULE_PARM is used to verify parameters passed
1368 - * to the module at load time. It should be a string in the following
1371 - * [min[-max]]{b,h,i,l,s}
1373 - * The MIN and MAX specifiers delimit the length of the array. If MAX
1374 - * is omitted, it defaults to MIN; if both are omitted, the default is
1375 - * 1. The final character is a type specifier.
1385 * Option: VideoMemoryTypeOverride
1388 static int NVreg_DevicesConnected = 0;
1389 NV_MODULE_PARAMETER(NVreg_DevicesConnected);
1391 -static int NVreg_VideoEnhancement = 0;
1392 -NV_MODULE_PARAMETER(NVreg_VideoEnhancement);
1394 static int NVreg_RmLogonRC = 1;
1395 NV_MODULE_PARAMETER(NVreg_RmLogonRC);
1397 @@ -402,34 +381,36 @@
1398 NV_MODULE_PARAMETER(NVreg_RemapLimit);
1402 + * Option: UpdateMemoryTypes
1406 - * Many kernels have a broken implementation of change_page_attr that leads
1407 - * to cache aliasing problems. x86_64 kernels between 2.6.0 and 2.6.10 will
1408 - * force a kernel BUG_ON() when this condition is encountered. For this
1409 - * reason, the NVIDIA driver is very careful about not using the CPA kernel
1410 - * interface on these kernels.
1411 + * Many kernels have broken implementations of the change_page_attr()
1412 + * kernel interface that may cause cache aliasing problems. Linux/x86-64
1413 + * kernels between 2.6.0 and 2.6.10 may prompt kernel BUG()s due to
1414 + * improper accounting in the interface's large page management code, for
1415 + * example. For this reason, the NVIDIA Linux driver is very careful about
1416 + * not using the change_page_attr() kernel interface on these kernels.
1418 + * Due to the serious nature of the problems that can arise from bugs in
1419 + * the change_page_attr(), set_pages_{uc,wb}() and other kernel interfaces
1420 + * used to modify memory types, the NVIDIA driver implements a manual
1421 + * registry key override to allow forcibly enabling or disabling use of
1424 - * Some distributions have backported this fix to kernel versions that fall
1425 - * within this version range. The NVIDIA driver attempts to automatically
1426 - * detect these fixes and reenable usage of the change_page_attr interface.
1427 + * Possible values:
1429 - * Due to the serious nature of the problems that can arise from this, the
1430 - * NVIDIA driver implements a manual registry key to force usage of this API
1431 - * to be enabled or disabled. This registry key can be used to force usage
1432 - * of the API on a known fixed kernel if the NVIDIA driver fails to detect
1433 - * the kernel as fixed. This registry key can also be used to disable usage
1434 - * of the API on a bad kernel that is misdetected as a fixed kernel.
1435 + * ~0 = use the NVIDIA driver's default logic (default)
1436 + * 0 = enable use of change_page_attr(), etc.
1437 + * 1 = disable use of change_page_attr(), etc.
1439 - * The default value is '-1' (use NVIDIA driver default logic)
1440 - * A value of '0' will forcibly disable change_page_attr calls.
1441 - * A value of '1' will forcibly enable change_page_attr calls.
1442 + * By default, the NVIDIA driver will attempt to auto-detect if it can
1443 + * safely use the change_page_attr() and other kernel interfaces to modify
1444 + * the memory types of kernel mappings.
1447 -static int NVreg_UseCPA = -1;
1448 -NV_MODULE_PARAMETER(NVreg_UseCPA);
1449 +static int NVreg_UpdateMemoryTypes = ~0;
1450 +NV_MODULE_PARAMETER(NVreg_UpdateMemoryTypes);
1452 // 1 - Force sourcing vbios from ROM
1453 // 0 - business as usual
1454 @@ -477,15 +458,14 @@
1455 { "NVreg", "ResmanDebugLevel", &NVreg_ResmanDebugLevel, 1 },
1456 { "NVreg", "FlatPanelMode", &NVreg_FlatPanelMode, 1 },
1457 { "NVreg", "DevicesConnected", &NVreg_DevicesConnected, 1 },
1458 - { "NVreg", "VideoEnhancement", &NVreg_VideoEnhancement, 1 },
1459 { "NVreg", "RmLogonRC", &NVreg_RmLogonRC, 1 },
1460 + { "NVreg", "VbiosFromROM", &NVreg_VbiosFromROM, 1 },
1461 { "NVreg", "ModifyDeviceFiles", &NVreg_ModifyDeviceFiles, 1 },
1462 { "NVreg", "DeviceFileUID", &NVreg_DeviceFileUID, 1 },
1463 { "NVreg", "DeviceFileGID", &NVreg_DeviceFileGID, 1 },
1464 { "NVreg", "DeviceFileMode", &NVreg_DeviceFileMode, 1 },
1465 - { "NVreg", "VbiosFromROM", &NVreg_VbiosFromROM, 1 },
1466 { "NVreg", "RemapLimit", &NVreg_RemapLimit, 1 },
1467 - { "NVreg", "UseCPA", &NVreg_UseCPA, 1 },
1468 + { "NVreg", "UpdateMemoryTypes", &NVreg_UpdateMemoryTypes, 1 },
1469 { "NVreg", "RMEdgeIntrCheck", &NVreg_RMEdgeIntrCheck, 1 },
1470 { NULL, NULL, NULL, 0 }