diff -ru usr/src/nv/nv-vm.c usr/src/nv.1386866/nv-vm.c --- usr/src/nv/nv-vm.c 2005-03-22 16:19:09.000000000 +0100 +++ usr/src/nv.1386866/nv-vm.c 2005-10-11 19:33:24.821108608 +0200 @@ -58,26 +58,57 @@ * conflicts. we try to rely on the kernel's provided interfaces when possible, * but need additional flushing on earlier kernels. */ -#if defined(KERNEL_2_4) -/* wrap CACHE_FLUSH so we can pass it to smp_call_function */ -static void cache_flush(void *p) -{ - CACHE_FLUSH(); -} -#endif - /* * 2.4 kernels handle flushing in the change_page_attr() call, but kernels * earlier than 2.4.27 don't flush on cpus that support Self Snoop, so we * manually flush on these kernels (actually, we go ahead and flush on all * 2.4 kernels, as it's possible some others may be missing this fix and * we'd prefer to be a little slower flushing caches than hanging the - * system. 2.6 kernels split the flushing out to a seperate call, - * global_flush_tlb(), so we rely on that. + * system. + * 2.6 kernels split the flushing out to a seperate call, + * global_flush_tlb(), so we rely on that. however, there are some 2.6 + * x86_64 kernels that do not properly flush. for now, we'll flush on all + * potential kernels, as it's slightly slower, but safer. */ +#if defined(KERNEL_2_4) || (defined(KERNEL_2_6) && defined(NVCPU_X86_64)) +#define NV_CPA_NEEDS_FLUSHING 1 +#endif + +#if defined(NV_CPA_NEEDS_FLUSHING) +static void cache_flush(void *p) +{ + unsigned long reg0, reg1; + + CACHE_FLUSH(); + + // flush global TLBs +#if defined (NVCPU_X86) + asm volatile("movl %%cr4, %0; \n" + "andl $~0x80, %0; \n" + "movl %0, %%cr4; \n" + "movl %%cr3, %1; \n" + "movl %1, %%cr3; \n" + "orl $0x80, %0; \n" + "movl %0, %%cr4; \n" + : "=&r" (reg0), "=&r" (reg1) + : : "memory"); +#else + asm volatile("movq %%cr4, %0; \n" + "andq $~0x80, %0; \n" + "movq %0, %%cr4; \n" + "movq %%cr3, %1; \n" + "movq %1, %%cr3; \n" + "orq $0x80, %0; \n" + "movq %0, %%cr4; \n" + : "=&r" (reg0), "=&r" (reg1) + : : "memory"); +#endif +} +#endif + static void nv_flush_caches(void) { -#if defined(KERNEL_2_4) +#if defined(NV_CPA_NEEDS_FLUSHING) #ifdef CONFIG_SMP smp_call_function(cache_flush, NULL, 1, 1); #endif