1 |
vapier 08/04/18 19:54:05 |
2 |
|
3 |
Added: NVIDIA_kernel-96.43.05-2290218.diff |
4 |
Log: |
5 |
Add fix from upstream for building with linux-2.6.25 #218178. |
6 |
(Portage version: 2.2_pre5) |
7 |
|
8 |
Revision Changes Path |
9 |
1.1 x11-drivers/nvidia-drivers/files/NVIDIA_kernel-96.43.05-2290218.diff |
10 |
|
11 |
file : http://sources.gentoo.org/viewcvs.py/gentoo-x86/x11-drivers/nvidia-drivers/files/NVIDIA_kernel-96.43.05-2290218.diff?rev=1.1&view=markup |
12 |
plain: http://sources.gentoo.org/viewcvs.py/gentoo-x86/x11-drivers/nvidia-drivers/files/NVIDIA_kernel-96.43.05-2290218.diff?rev=1.1&content-type=text/plain |
13 |
|
14 |
Index: NVIDIA_kernel-96.43.05-2290218.diff |
15 |
=================================================================== |
16 |
http://www.nvnews.net/vbulletin/showthread.php?t=110088 |
17 |
http://bugs.gentoo.org/218178 |
18 |
|
19 |
diff -ru usr/src/nv/Makefile.kbuild usr/src/nv.2290218/Makefile.kbuild |
20 |
--- usr/src/nv/Makefile.kbuild 2008-01-22 20:12:23.000000000 -0800 |
21 |
+++ usr/src/nv.2290218/Makefile.kbuild 2008-03-18 13:15:30.394522179 -0700 |
22 |
@@ -177,6 +177,7 @@ |
23 |
vmap \ |
24 |
signal_struct \ |
25 |
agp_backend_acquire \ |
26 |
+ set_pages_uc \ |
27 |
change_page_attr \ |
28 |
pci_get_class \ |
29 |
sysctl_max_map_count \ |
30 |
diff -ru usr/src/nv/conftest.sh usr/src/nv.2290218/conftest.sh |
31 |
--- usr/src/nv/conftest.sh 2008-01-22 20:12:23.000000000 -0800 |
32 |
+++ usr/src/nv.2290218/conftest.sh 2008-03-18 13:15:32.710654166 -0700 |
33 |
@@ -100,6 +100,32 @@ |
34 |
fi |
35 |
;; |
36 |
|
37 |
+ set_pages_uc) |
38 |
+ # |
39 |
+ # Determine if the set_pages_uc() function is present. |
40 |
+ # |
41 |
+ echo "#include <linux/autoconf.h> |
42 |
+ #include <asm/cacheflush.h> |
43 |
+ void conftest_set_pages_uc(void) { |
44 |
+ set_pages_uc(); |
45 |
+ }" > conftest$$.c |
46 |
+ |
47 |
+ $CC $CFLAGS -c conftest$$.c > /dev/null 2>&1 |
48 |
+ rm -f conftest$$.c |
49 |
+ |
50 |
+ if [ -f conftest$$.o ]; then |
51 |
+ rm -f conftest$$.o |
52 |
+ echo "#undef NV_SET_PAGES_UC_PRESENT" >> conftest.h |
53 |
+ return |
54 |
+ else |
55 |
+ echo "#ifdef NV_CHANGE_PAGE_ATTR_PRESENT" >> conftest.h |
56 |
+ echo "#undef NV_CHANGE_PAGE_ATTR_PRESENT" >> conftest.h |
57 |
+ echo "#endif" >> conftest.h |
58 |
+ echo "#define NV_SET_PAGES_UC_PRESENT" >> conftest.h |
59 |
+ return |
60 |
+ fi |
61 |
+ ;; |
62 |
+ |
63 |
change_page_attr) |
64 |
# |
65 |
# Determine if the change_page_attr() function is |
66 |
@@ -124,7 +150,9 @@ |
67 |
rm -f conftest$$.o |
68 |
return |
69 |
else |
70 |
+ echo "#ifndef NV_SET_PAGES_UC_PRESENT" >> conftest.h |
71 |
echo "#define NV_CHANGE_PAGE_ATTR_PRESENT" >> conftest.h |
72 |
+ echo "#endif" >> conftest.h |
73 |
return |
74 |
fi |
75 |
;; |
76 |
@@ -501,6 +529,8 @@ |
77 |
return |
78 |
fi |
79 |
|
80 |
+ rm -f conftest$$.o |
81 |
+ |
82 |
echo "#include <linux/autoconf.h> |
83 |
#include <linux/interrupt.h> |
84 |
irq_handler_t conftest_isr; |
85 |
diff -ru usr/src/nv/nv-linux.h usr/src/nv.2290218/nv-linux.h |
86 |
--- usr/src/nv/nv-linux.h 2008-01-22 20:12:23.000000000 -0800 |
87 |
+++ usr/src/nv.2290218/nv-linux.h 2008-03-18 13:15:26.674310174 -0700 |
88 |
@@ -808,9 +808,10 @@ |
89 |
|
90 |
#define NV_PGD_OFFSET(address, kernel, mm) \ |
91 |
({ \ |
92 |
+ struct mm_struct *__mm = (mm); \ |
93 |
pgd_t *__pgd; \ |
94 |
if (!kernel) \ |
95 |
- __pgd = pgd_offset(mm, address); \ |
96 |
+ __pgd = pgd_offset(__mm, address); \ |
97 |
else \ |
98 |
__pgd = pgd_offset_k(address); \ |
99 |
__pgd; \ |
100 |
@@ -1097,21 +1098,24 @@ |
101 |
#define NV_ATOMIC_DEC_AND_TEST(data) atomic_dec_and_test(&(data)) |
102 |
#define NV_ATOMIC_READ(data) atomic_read(&(data)) |
103 |
|
104 |
+extern int nv_update_memory_types; |
105 |
+ |
106 |
/* |
107 |
- * a BUG() is triggered on early 2.6 x86_64 kernels. the underlying |
108 |
- * problem actually exists on many architectures and kernels, but |
109 |
- * these are the only kernels that check the condition and trigger |
110 |
- * a BUG(). note that this is a problem of the core kernel, not an |
111 |
- * nvidia bug (and can still be triggered by agpgart). let's avoid |
112 |
- * change_page_attr on those kernels. |
113 |
+ * Using change_page_attr() on early Linux/x86-64 2.6 kernels may |
114 |
+ * result in a BUG() being triggered. The underlying problem |
115 |
+ * actually exists on multiple architectures and kernels, but only |
116 |
+ * the above check for the condition and trigger a BUG(). |
117 |
+ * |
118 |
+ * Note that this is a due to a bug in the Linux kernel, not an |
119 |
+ * NVIDIA driver bug (it can also be triggered by AGPGART). |
120 |
+ * |
121 |
+ * We therefore need to determine at runtime if change_page_attr() |
122 |
+ * can be used safely on these kernels. |
123 |
*/ |
124 |
-#if defined(NV_CHANGE_PAGE_ATTR_PRESENT) |
125 |
-extern int nv_use_cpa; |
126 |
- |
127 |
-#if defined(NVCPU_X86_64) && !defined(KERNEL_2_4) && \ |
128 |
- (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11)) |
129 |
-#define NV_CHANGE_PAGE_ATTR_BUG_PRESENT 1 |
130 |
-#endif |
131 |
+#if defined(NV_CHANGE_PAGE_ATTR_PRESENT) && defined(NVCPU_X86_64) && \ |
132 |
+ !defined(KERNEL_2_4) && \ |
133 |
+ (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11)) |
134 |
+#define NV_CHANGE_PAGE_ATTR_BUG_PRESENT |
135 |
#endif |
136 |
|
137 |
#if defined(NVCPU_X86) || defined(NVCPU_X86_64) |
138 |
@@ -1123,7 +1127,7 @@ |
139 |
* |
140 |
* We need to be careful to mask out _PAGE_NX when the host system |
141 |
* doesn't support this feature or when it's disabled: the kernel |
142 |
- * may not do this in its implementation of the change_page_attr() |
143 |
+ * may not do this in its implementation of the change_page_attr() |
144 |
* interface. |
145 |
*/ |
146 |
#ifndef X86_FEATURE_NX |
147 |
diff -ru usr/src/nv/nv-vm.c usr/src/nv.2290218/nv-vm.c |
148 |
--- usr/src/nv/nv-vm.c 2008-01-22 20:12:23.000000000 -0800 |
149 |
+++ usr/src/nv.2290218/nv-vm.c 2008-03-18 13:15:34.806773619 -0700 |
150 |
@@ -43,42 +43,40 @@ |
151 |
} |
152 |
#endif |
153 |
|
154 |
-/* |
155 |
- * AMD Athlon processors expose a subtle bug in the Linux |
156 |
- * kernel, that may lead to AGP memory corruption. Recent |
157 |
- * kernel versions had a workaround for this problem, but |
158 |
- * 2.4.20 is the first kernel to address it properly. The |
159 |
- * page_attr API provides the means to solve the problem. |
160 |
- */ |
161 |
- |
162 |
static inline void nv_set_page_attrib_uncached(nv_pte_t *page_ptr) |
163 |
{ |
164 |
-#if defined(NV_CHANGE_PAGE_ATTR_PRESENT) |
165 |
- if (nv_use_cpa) |
166 |
+ if (nv_update_memory_types) |
167 |
{ |
168 |
- struct page *page = virt_to_page(__va(page_ptr->phys_addr)); |
169 |
+#if defined(NV_SET_PAGES_UC_PRESENT) |
170 |
+ struct page *page = NV_GET_PAGE_STRUCT(page_ptr->phys_addr); |
171 |
+ set_pages_uc(page, 1); |
172 |
+#elif defined(NV_CHANGE_PAGE_ATTR_PRESENT) |
173 |
+ struct page *page = NV_GET_PAGE_STRUCT(page_ptr->phys_addr); |
174 |
pgprot_t prot = PAGE_KERNEL_NOCACHE; |
175 |
#if defined(NVCPU_X86) || defined(NVCPU_X86_64) |
176 |
pgprot_val(prot) &= __nv_supported_pte_mask; |
177 |
#endif |
178 |
change_page_attr(page, 1, prot); |
179 |
- } |
180 |
#endif |
181 |
+ } |
182 |
} |
183 |
|
184 |
static inline void nv_set_page_attrib_cached(nv_pte_t *page_ptr) |
185 |
{ |
186 |
-#if defined(NV_CHANGE_PAGE_ATTR_PRESENT) |
187 |
- if (nv_use_cpa) |
188 |
+ if (nv_update_memory_types) |
189 |
{ |
190 |
- struct page *page = virt_to_page(__va(page_ptr->phys_addr)); |
191 |
+#if defined(NV_SET_PAGES_UC_PRESENT) |
192 |
+ struct page *page = NV_GET_PAGE_STRUCT(page_ptr->phys_addr); |
193 |
+ set_pages_wb(page, 1); |
194 |
+#elif defined(NV_CHANGE_PAGE_ATTR_PRESENT) |
195 |
+ struct page *page = NV_GET_PAGE_STRUCT(page_ptr->phys_addr); |
196 |
pgprot_t prot = PAGE_KERNEL; |
197 |
#if defined(NVCPU_X86) || defined(NVCPU_X86_64) |
198 |
pgprot_val(prot) &= __nv_supported_pte_mask; |
199 |
#endif |
200 |
change_page_attr(page, 1, prot); |
201 |
+#endif |
202 |
} |
203 |
-#endif /* NV_CHANGE_PAGE_ATTR_PRESENT */ |
204 |
} |
205 |
|
206 |
static inline void nv_lock_page(nv_pte_t *page_ptr) |
207 |
@@ -360,8 +358,11 @@ |
208 |
#if defined(NV_CPA_NEEDS_FLUSHING) |
209 |
nv_execute_on_all_cpus(cache_flush, NULL); |
210 |
#endif |
211 |
+#if (defined(NVCPU_X86) || defined(NVCPU_X86_64)) && \ |
212 |
+ defined(NV_CHANGE_PAGE_ATTR_PRESENT) |
213 |
global_flush_tlb(); |
214 |
#endif |
215 |
+#endif |
216 |
} |
217 |
|
218 |
/* |
219 |
@@ -656,7 +657,7 @@ |
220 |
|
221 |
address = (unsigned long)virt_addr + i * PAGE_SIZE; |
222 |
|
223 |
- pgd = NV_PGD_OFFSET(address, 1, &init_mm); |
224 |
+ pgd = NV_PGD_OFFSET(address, 1, NULL); |
225 |
if (!NV_PGD_PRESENT(pgd)) |
226 |
goto failed; |
227 |
|
228 |
diff -ru usr/src/nv/nv.c usr/src/nv.2290218/nv.c |
229 |
--- usr/src/nv/nv.c 2008-01-22 20:12:23.000000000 -0800 |
230 |
+++ usr/src/nv.2290218/nv.c 2008-03-18 13:15:35.950838813 -0700 |
231 |
@@ -112,10 +112,7 @@ |
232 |
unsigned int nv_remap_limit; |
233 |
#endif |
234 |
|
235 |
-#if defined(NV_CHANGE_PAGE_ATTR_PRESENT) |
236 |
-int nv_use_cpa = 1; |
237 |
-#endif |
238 |
- |
239 |
+int nv_update_memory_types = 1; |
240 |
static int nv_mmconfig_failure_detected = 0; |
241 |
|
242 |
static void *nv_pte_t_cache = NULL; |
243 |
@@ -919,30 +916,26 @@ |
244 |
#endif /* defined(NV_BUILD_NV_PAT_SUPPORT) */ |
245 |
} |
246 |
|
247 |
- |
248 |
#if defined(NV_CHANGE_PAGE_ATTR_BUG_PRESENT) |
249 |
- |
250 |
-/* nv_verify_cpa_interface - determine if the change_page_attr bug is fixed |
251 |
- * in this kernel. |
252 |
+/* |
253 |
+ * nv_verify_cpa_interface() - determine if the change_page_attr() large page |
254 |
+ * management accounting bug known to exist in early Linux/x86-64 kernels |
255 |
+ * is present in this kernel. |
256 |
* |
257 |
- * there's really not a good way to determine if change_page_attr is fixed. |
258 |
- * we can't really use cpa on 2.6 x86_64 kernels < 2.6.11, as if we run into |
259 |
- * the accounting bug, the kernel will throw a BUG. this isn't 100% accurate, |
260 |
- * as it doesn't throw a bug until we try to restore the caching attributes |
261 |
- * of the page. so if we can track down a 4M allocation, we can mark it |
262 |
- * uncached and see if the accounting was done correctly. |
263 |
- * |
264 |
- * this is a little ugly, but the most accurate approach to determining if |
265 |
- * this kernel is good. |
266 |
+ * There's really no good way to determine if change_page_attr() is working |
267 |
+ * correctly. We can't reliably use change_page_attr() on Linux/x86-64 2.6 |
268 |
+ * kernels < 2.6.11: if we run into the accounting bug, the Linux kernel will |
269 |
+ * trigger a BUG() if we attempt to restore the WB memory type of a page |
270 |
+ * originally part of a large page. |
271 |
* |
272 |
- * why do we even bother? some distributions have back-ported the cpa fix to |
273 |
- * kernels < 2.6.11. we want to use change_page_attr to avoid random corruption |
274 |
- * and hangs, but need to make sure it's safe to do so. |
275 |
+ * So if we can successfully allocate such a page, change its memory type to |
276 |
+ * UC and check if the accounting was done correctly, we can determine if |
277 |
+ * the change_page_attr() interface can be used safely. |
278 |
* |
279 |
- * return values: |
280 |
- * 0 - test passed, interface works |
281 |
- * 1 - test failed, status unclear |
282 |
- * -1 - test failed, interface broken |
283 |
+ * Return values: |
284 |
+ * 0 - test passed, the change_page_attr() interface works |
285 |
+ * 1 - test failed, the status is unclear |
286 |
+ * -1 - test failed, the change_page_attr() interface is broken |
287 |
*/ |
288 |
|
289 |
static inline pte_t *check_large_page(unsigned long vaddr) |
290 |
@@ -950,7 +943,7 @@ |
291 |
pgd_t *pgd = NULL; |
292 |
pmd_t *pmd = NULL; |
293 |
|
294 |
- pgd = NV_PGD_OFFSET(vaddr, 1, &init_mm); |
295 |
+ pgd = NV_PGD_OFFSET(vaddr, 1, NULL); |
296 |
if (!NV_PGD_PRESENT(pgd)) |
297 |
return NULL; |
298 |
|
299 |
@@ -1060,35 +1053,42 @@ |
300 |
|
301 |
return 1; |
302 |
} |
303 |
- |
304 |
#endif /* defined(NV_CHANGE_PAGE_ATTR_BUG_PRESENT) */ |
305 |
|
306 |
- |
307 |
-// verify that the kernel's mapping matches the requested type |
308 |
-// this is to protect against accidental cache aliasing problems |
309 |
+/* |
310 |
+ * nv_verify_page_mappings() - verify that the kernel mapping of the specified |
311 |
+ * page matches the specified type. This is to help detect bugs in the Linux |
312 |
+ * kernel's change_page_attr() interface, early. |
313 |
+ * |
314 |
+ * This function relies on the ability to perform kernel virtul address to PFN |
315 |
+ * translations and therefore on 'init_mm'. Unfortunately, the latter is no |
316 |
+ * longer exported in recent Linux/x86 2.6 kernels. The export was removed at |
317 |
+ * roughtly the same time as the set_pages_{uc,wb}() change_page_attr() |
318 |
+ * replacement interfaces were introduced; hopefully, it will be sufficient to |
319 |
+ * check for their presence. |
320 |
+ */ |
321 |
int nv_verify_page_mappings( |
322 |
nv_pte_t *page_ptr, |
323 |
unsigned int cachetype |
324 |
) |
325 |
{ |
326 |
- struct mm_struct *mm; |
327 |
+#if defined(NV_CHANGE_PAGE_ATTR_PRESENT) || \ |
328 |
+ (defined(NV_SET_PAGES_UC_PRESENT) && !defined(NVCPU_X86)) |
329 |
+ unsigned long retval = -1; |
330 |
+#if defined(NVCPU_X86) || defined(NVCPU_X86_64) |
331 |
pgd_t *pgd = NULL; |
332 |
pmd_t *pmd = NULL; |
333 |
pte_t *pte = NULL; |
334 |
- unsigned long retval = -1; |
335 |
unsigned int flags, expected; |
336 |
unsigned long address; |
337 |
static int count = 0; |
338 |
|
339 |
-#if defined(NV_CHANGE_PAGE_ATTR_PRESENT) |
340 |
- if (!nv_use_cpa) |
341 |
+ if (!nv_update_memory_types) |
342 |
return 0; |
343 |
-#endif |
344 |
|
345 |
address = (unsigned long)__va(page_ptr->phys_addr); |
346 |
- mm = &init_mm; // always a kernel page |
347 |
|
348 |
- pgd = NV_PGD_OFFSET(address, 1, mm); |
349 |
+ pgd = NV_PGD_OFFSET(address, 1, NULL); |
350 |
if (!NV_PGD_PRESENT(pgd)) |
351 |
{ |
352 |
nv_printf(NV_DBG_ERRORS, "NVRM: pgd not present for addr 0x%lx\n", address); |
353 |
@@ -1154,7 +1154,11 @@ |
354 |
} |
355 |
|
356 |
failed: |
357 |
+#endif /* defined(NVCPU_X86) || defined(NVCPU_X86_64) */ |
358 |
return retval; |
359 |
+#else |
360 |
+ return 0; |
361 |
+#endif |
362 |
} |
363 |
|
364 |
#if defined(NV_BUILD_NV_PAT_SUPPORT) && defined(CONFIG_HOTPLUG_CPU) |
365 |
@@ -1200,7 +1204,8 @@ |
366 |
static int __init nvidia_init_module(void) |
367 |
{ |
368 |
int rc; |
369 |
- U032 i, count; |
370 |
+ U032 i, count, data; |
371 |
+ nv_state_t *nv = NV_STATE_PTR(&nv_ctl_device); |
372 |
|
373 |
#if defined(VM_CHECKER) |
374 |
nv_init_lock(vm_lock); |
375 |
@@ -1359,43 +1364,41 @@ |
376 |
/* create /proc/driver/nvidia */ |
377 |
nvos_proc_create(); |
378 |
|
379 |
-#if defined(NV_CHANGE_PAGE_ATTR_PRESENT) |
380 |
+ /* |
381 |
+ * Give users an opportunity to disable the driver's use of |
382 |
+ * the change_page_attr() and set_pages_{uc,wb}() kernel |
383 |
+ * interfaces. |
384 |
+ */ |
385 |
+ rc = rm_read_registry_dword(nv, "NVreg", "UpdateMemoryTypes", &data); |
386 |
+ if ((rc == 0) && ((int)data != ~0)) |
387 |
{ |
388 |
- int data; |
389 |
- |
390 |
- // allow the user to override us with a registry key |
391 |
- rc = rm_read_registry_dword(NV_STATE_PTR(&nv_ctl_device), "NVreg", "UseCPA", &data); |
392 |
- if ((rc == 0) && (data != -1)) |
393 |
- { |
394 |
- nv_use_cpa = data; |
395 |
- } |
396 |
+ nv_update_memory_types = data; |
397 |
+ } |
398 |
#if defined(NV_CHANGE_PAGE_ATTR_BUG_PRESENT) |
399 |
- else |
400 |
+ /* |
401 |
+ * Unless we explicitely detect that the change_page_attr() |
402 |
+ * inteface is fixed, disable usage of the interface on |
403 |
+ * this kernel. Notify the user of this problem using the |
404 |
+ * driver's /proc warnings interface (read by the installer |
405 |
+ * and the bug report script). |
406 |
+ */ |
407 |
+ else |
408 |
+ { |
409 |
+ rc = nv_verify_cpa_interface(); |
410 |
+ if (rc < 0) |
411 |
{ |
412 |
- /* |
413 |
- * Unless we explicitely detect that the change_page_attr() |
414 |
- * inteface is fixed, disable usage of the interface on |
415 |
- * this kernel. Notify the user of this problem using the |
416 |
- * driver's /proc warnings interface (read by the installer |
417 |
- * and the bug report script). |
418 |
- */ |
419 |
- rc = nv_verify_cpa_interface(); |
420 |
- if (rc < 0) |
421 |
- { |
422 |
- nv_prints(NV_DBG_ERRORS, __cpgattr_warning); |
423 |
- nvos_proc_add_warning_file("change_page_attr", __cpgattr_warning); |
424 |
- nv_use_cpa = 0; |
425 |
- } |
426 |
- else if (rc != 0) |
427 |
- { |
428 |
- nv_prints(NV_DBG_ERRORS, __cpgattr_warning_2); |
429 |
- nvos_proc_add_warning_file("change_page_attr", __cpgattr_warning_2); |
430 |
- nv_use_cpa = 0; |
431 |
- } |
432 |
+ nv_prints(NV_DBG_ERRORS, __cpgattr_warning); |
433 |
+ nvos_proc_add_warning_file("change_page_attr", __cpgattr_warning); |
434 |
+ nv_update_memory_types = 0; |
435 |
+ } |
436 |
+ else if (rc != 0) |
437 |
+ { |
438 |
+ nv_prints(NV_DBG_ERRORS, __cpgattr_warning_2); |
439 |
+ nvos_proc_add_warning_file("change_page_attr", __cpgattr_warning_2); |
440 |
+ nv_update_memory_types = 0; |
441 |
} |
442 |
-#endif |
443 |
} |
444 |
-#endif |
445 |
+#endif /* defined(NV_CHANGE_PAGE_ATTR_BUG_PRESENT) */ |
446 |
|
447 |
#if defined(NVCPU_X86_64) && defined(CONFIG_IA32_EMULATION) && !defined(HAVE_COMPAT_IOCTL) |
448 |
/* Register ioctl conversions for 32 bit clients */ |
449 |
@@ -3230,8 +3233,21 @@ |
450 |
pte_t *pte = NULL; |
451 |
NvU64 retval; |
452 |
|
453 |
- mm = (kern) ? &init_mm : current->mm; |
454 |
- if (!kern) down_read(¤t->mm->mmap_sem); |
455 |
+ if (!kern) |
456 |
+ { |
457 |
+ mm = current->mm; |
458 |
+ down_read(&mm->mmap_sem); |
459 |
+ } |
460 |
+ else |
461 |
+ { |
462 |
+#if defined(NV_SET_PAGES_UC_PRESENT) && defined(NVCPU_X86) |
463 |
+ /* nv_printf(NV_DBG_ERRORS, |
464 |
+ "NVRM: can't translate KVA in nv_get_phys_address()!\n"); */ |
465 |
+ return 0; |
466 |
+#else |
467 |
+ mm = NULL; |
468 |
+#endif |
469 |
+ } |
470 |
|
471 |
pgd = NV_PGD_OFFSET(address, kern, mm); |
472 |
if (!NV_PGD_PRESENT(pgd)) |
473 |
@@ -3252,22 +3268,24 @@ |
474 |
retval &= ~_PAGE_NX; |
475 |
#endif |
476 |
|
477 |
- if (!kern) up_read(¤t->mm->mmap_sem); |
478 |
+ if (!kern) |
479 |
+ up_read(&mm->mmap_sem); |
480 |
return retval; |
481 |
|
482 |
failed: |
483 |
- if (!kern) up_read(¤t->mm->mmap_sem); |
484 |
+ if (!kern) |
485 |
+ up_read(&mm->mmap_sem); |
486 |
return 0; |
487 |
} |
488 |
|
489 |
NvU64 NV_API_CALL nv_get_kern_phys_address(NvU64 address) |
490 |
{ |
491 |
- // make sure this address is a kernel pointer |
492 |
+ /* make sure this address is a kernel virtual address */ |
493 |
#if defined(DEBUG) && !defined(CONFIG_X86_4G) |
494 |
if (address < PAGE_OFFSET) |
495 |
{ |
496 |
nv_printf(NV_DBG_WARNINGS, |
497 |
- "NVRM: user address passed to get_kern_phys_address: 0x%lx\n", |
498 |
+ "NVRM: user address passed to get_kern_phys_address: 0x%llx!\n", |
499 |
address); |
500 |
return 0; |
501 |
} |
502 |
@@ -3282,12 +3300,12 @@ |
503 |
|
504 |
NvU64 NV_API_CALL nv_get_kern_user_address(NvU64 address) |
505 |
{ |
506 |
- // make sure this address is not a kernel pointer |
507 |
+ /* make sure this address is not a kernel virtual address */ |
508 |
#if defined(DEBUG) && !defined(CONFIG_X86_4G) |
509 |
if (address >= PAGE_OFFSET) |
510 |
{ |
511 |
nv_printf(NV_DBG_WARNINGS, |
512 |
- "NVRM: kernel address passed to get_user_phys_address: 0x%lx\n", |
513 |
+ "NVRM: kernel address passed to get_user_phys_address: 0x%llx!\n", |
514 |
address); |
515 |
return 0; |
516 |
} |
517 |
@@ -3989,13 +4007,10 @@ |
518 |
return -1; |
519 |
} |
520 |
|
521 |
-int NV_API_CALL nv_no_incoherent_mappings |
522 |
-( |
523 |
- void |
524 |
-) |
525 |
+int NV_API_CALL nv_no_incoherent_mappings(void) |
526 |
{ |
527 |
-#if defined(NV_CHANGE_PAGE_ATTR_PRESENT) |
528 |
- return 1; |
529 |
+#if defined(NV_CHANGE_PAGE_ATTR_PRESENT) || defined(NV_SET_PAGES_UC_PRESENT) |
530 |
+ return (nv_update_memory_types); |
531 |
#else |
532 |
return 0; |
533 |
#endif |
534 |
diff -ru usr/src/nv/os-interface.c usr/src/nv.2290218/os-interface.c |
535 |
--- usr/src/nv/os-interface.c 2008-01-22 20:12:23.000000000 -0800 |
536 |
+++ usr/src/nv.2290218/os-interface.c 2008-03-18 13:15:38.098961229 -0700 |
537 |
@@ -1130,6 +1130,18 @@ |
538 |
{ |
539 |
void *vaddr; |
540 |
|
541 |
+ if (start == 0) |
542 |
+ { |
543 |
+ if (mode != NV_MEMORY_CACHED) |
544 |
+ { |
545 |
+ nv_printf(NV_DBG_ERRORS, |
546 |
+ "NVRM: os_map_kernel_space: won't map address 0x%0llx UC!\n", start); |
547 |
+ return NULL; |
548 |
+ } |
549 |
+ else |
550 |
+ return (void *)PAGE_OFFSET; |
551 |
+ } |
552 |
+ |
553 |
if (!NV_MAY_SLEEP()) |
554 |
{ |
555 |
nv_printf(NV_DBG_ERRORS, |
556 |
@@ -1162,6 +1174,9 @@ |
557 |
NvU64 size_bytes |
558 |
) |
559 |
{ |
560 |
+ if (addr == (void *)PAGE_OFFSET) |
561 |
+ return; |
562 |
+ |
563 |
NV_IOUNMAP(addr, size_bytes); |
564 |
} |
565 |
|
566 |
diff -ru usr/src/nv/os-registry.c usr/src/nv.2290218/os-registry.c |
567 |
--- usr/src/nv/os-registry.c 2008-01-22 20:12:23.000000000 -0800 |
568 |
+++ usr/src/nv.2290218/os-registry.c 2008-03-18 13:15:40.631105529 -0700 |
569 |
@@ -381,34 +381,36 @@ |
570 |
NV_MODULE_PARAMETER(NVreg_RemapLimit); |
571 |
|
572 |
/* |
573 |
- * Option: UseCPA |
574 |
+ * Option: UpdateMemoryTypes |
575 |
* |
576 |
* Description: |
577 |
* |
578 |
- * Many kernels have a broken implementation of change_page_attr that leads |
579 |
- * to cache aliasing problems. x86_64 kernels between 2.6.0 and 2.6.10 will |
580 |
- * force a kernel BUG_ON() when this condition is encountered. For this |
581 |
- * reason, the NVIDIA driver is very careful about not using the CPA kernel |
582 |
- * interface on these kernels. |
583 |
- * |
584 |
- * Some distributions have backported this fix to kernel versions that fall |
585 |
- * within this version range. The NVIDIA driver attempts to automatically |
586 |
- * detect these fixes and reenable usage of the change_page_attr interface. |
587 |
- * |
588 |
- * Due to the serious nature of the problems that can arise from this, the |
589 |
- * NVIDIA driver implements a manual registry key to force usage of this API |
590 |
- * to be enabled or disabled. This registry key can be used to force usage |
591 |
- * of the API on a known fixed kernel if the NVIDIA driver fails to detect |
592 |
- * the kernel as fixed. This registry key can also be used to disable usage |
593 |
- * of the API on a bad kernel that is misdetected as a fixed kernel. |
594 |
- * |
595 |
- * The default value is '-1' (use NVIDIA driver default logic) |
596 |
- * A value of '0' will forcibly disable change_page_attr calls. |
597 |
- * A value of '1' will forcibly enable change_page_attr calls. |
598 |
+ * Many kernels have broken implementations of the change_page_attr() |
599 |
+ * kernel interface that may cause cache aliasing problems. Linux/x86-64 |
600 |
+ * kernels between 2.6.0 and 2.6.10 may prompt kernel BUG()s due to |
601 |
+ * improper accounting in the interface's large page management code, for |
602 |
+ * example. For this reason, the NVIDIA Linux driver is very careful about |
603 |
+ * not using the change_page_attr() kernel interface on these kernels. |
604 |
+ * |
605 |
+ * Due to the serious nature of the problems that can arise from bugs in |
606 |
+ * the change_page_attr(), set_pages_{uc,wb}() and other kernel interfaces |
607 |
+ * used to modify memory types, the NVIDIA driver implements a manual |
608 |
+ * registry key override to allow forcibly enabling or disabling use of |
609 |
+ * these APIs. |
610 |
+ * |
611 |
+ * Possible values: |
612 |
+ * |
613 |
+ * ~0 = use the NVIDIA driver's default logic (default) |
614 |
+ * 0 = enable use of change_page_attr(), etc. |
615 |
+ * 1 = disable use of change_page_attr(), etc. |
616 |
+ * |
617 |
+ * By default, the NVIDIA driver will attempt to auto-detect if it can |
618 |
+ * safely use the change_page_attr() and other kernel interfaces to modify |
619 |
+ * the memory types of kernel mappings. |
620 |
*/ |
621 |
|
622 |
-static int NVreg_UseCPA = -1; |
623 |
-NV_MODULE_PARAMETER(NVreg_UseCPA); |
624 |
+static int NVreg_UpdateMemoryTypes = ~0; |
625 |
+NV_MODULE_PARAMETER(NVreg_UpdateMemoryTypes); |
626 |
|
627 |
/* |
628 |
* Option: DetectPrimaryVga |
629 |
@@ -511,7 +513,7 @@ |
630 |
{ "NVreg", "DeviceFileGID", &NVreg_DeviceFileGID, 1 }, |
631 |
{ "NVreg", "DeviceFileMode", &NVreg_DeviceFileMode, 1 }, |
632 |
{ "NVreg", "RemapLimit", &NVreg_RemapLimit, 1 }, |
633 |
- { "NVreg", "UseCPA", &NVreg_UseCPA, 1 }, |
634 |
+ { "NVreg", "UpdateMemoryTypes", &NVreg_UpdateMemoryTypes, 1 }, |
635 |
{ "NVreg", "DetectPrimaryVga", &NVreg_DetectPrimaryVga, 1 }, |
636 |
{ "NVreg", "EnableBrightnessControl", &NVreg_EnableBrightnessControl, 1 }, |
637 |
{ "NVreg", "PanelPWMFrequency", &NVreg_PanelPWMFrequency, 1 }, |
638 |
|
639 |
|
640 |
|
641 |
-- |
642 |
gentoo-commits@l.g.o mailing list |