diff -ru usr/src/nv/nv-linux.h usr/src/nv.1189413/nv-linux.h --- usr/src/nv/nv-linux.h 2004-11-03 22:53:00.000000000 +0100 +++ usr/src/nv.1189413/nv-linux.h 2005-01-07 15:44:01.000000000 +0100 @@ -627,75 +627,109 @@ #define NV_REMAP_PAGE_RANGE(x...) remap_page_range(x) #endif + +#define NV_PGD_OFFSET(address, kernel, mm) \ + ({ \ + pgd_t *__pgd; \ + if (!kernel) \ + __pgd = pgd_offset(mm, address); \ + else \ + __pgd = pgd_offset_k(address); \ + __pgd; \ + }) + +#define NV_PGD_PRESENT(pgd) \ + ({ \ + if ((pgd != NULL) && \ + (pgd_bad(*pgd) || pgd_none(*pgd))) \ + /* static */ pgd = NULL; \ + pgd != NULL; \ + }) + #if defined(pmd_offset_map) -#define NV_PMD_OFFSET(addres, pg_dir, pg_mid_dir) \ - { \ - pg_mid_dir = pmd_offset_map(pg_dir, address); \ - } -#define NV_PMD_UNMAP(pg_mid_dir) \ - { \ - pmd_unmap(pg_mid_dir); \ - } +#define NV_PMD_OFFSET(address, pgd) \ + ({ \ + pmd_t *__pmd; \ + __pmd = pmd_offset_map(pgd, address); \ + }) +#define NV_PMD_UNMAP(pmd) pmd_unmap(pmd); #else -#define NV_PMD_OFFSET(addres, pg_dir, pg_mid_dir) \ - { \ - pg_mid_dir = pmd_offset(pg_dir, address); \ - } -#define NV_PMD_UNMAP(pg_mid_dir) +#if defined(PUD_SHIFT) /* 4-level pgtable */ +#define NV_PMD_OFFSET(address, pgd) \ + ({ \ + pmd_t *__pmd = NULL; \ + pud_t *__pud; \ + __pud = pud_offset(pgd, address); \ + if ((__pud != NULL) && \ + !(pud_bad(*__pud) || pud_none(*__pud))) \ + __pmd = pmd_offset(__pud, address); \ + __pmd; \ + }) +#else /* 3-level pgtable */ +#define NV_PMD_OFFSET(address, pgd) \ + ({ \ + pmd_t *__pmd; \ + __pmd = pmd_offset(pgd, address); \ + }) +#endif +#define NV_PMD_UNMAP(pmd) #endif -#define NV_PMD_PRESENT(pg_mid_dir) \ - ({ \ - if ( (pg_mid_dir) && (pmd_none(*pg_mid_dir))) { \ - NV_PMD_UNMAP(pg_mid_dir); pg_mid_dir = NULL; \ - } pg_mid_dir != NULL; \ +#define NV_PMD_PRESENT(pmd) \ + ({ \ + if ((pmd != NULL) && \ + (pmd_bad(*pmd) || pmd_none(*pmd))) \ + { \ + NV_PMD_UNMAP(pmd); \ + pmd = NULL; /* mark invalid */ \ + } \ + pmd != NULL; \ }) #if defined(pte_offset_atomic) -#define NV_PTE_OFFSET(addres, pg_mid_dir, pte) \ - { \ - pte = pte_offset_atomic(pg_mid_dir, address); \ - NV_PMD_UNMAP(pg_mid_dir); \ - } -#define NV_PTE_UNMAP(pte) \ - { \ - pte_kunmap(pte); \ - } +#define NV_PTE_OFFSET(address, pmd) \ + ({ \ + pte_t *__pte; \ + __pte = pte_offset_atomic(pmd, address); \ + NV_PMD_UNMAP(pmd); __pte; \ + }) +#define NV_PTE_UNMAP(pte) pte_kunmap(pte); #elif defined(pte_offset) -#define NV_PTE_OFFSET(addres, pg_mid_dir, pte) \ - { \ - pte = pte_offset(pg_mid_dir, address); \ - NV_PMD_UNMAP(pg_mid_dir); \ - } +#define NV_PTE_OFFSET(address, pmd) \ + ({ \ + pte_t *__pte; \ + __pte = pte_offset(pmd, address); \ + NV_PMD_UNMAP(pmd); __pte; \ + }) #define NV_PTE_UNMAP(pte) #else -#define NV_PTE_OFFSET(addres, pg_mid_dir, pte) \ - { \ - pte = pte_offset_map(pg_mid_dir, address); \ - NV_PMD_UNMAP(pg_mid_dir); \ - } -#define NV_PTE_UNMAP(pte) \ - { \ - pte_unmap(pte); \ - } +#define NV_PTE_OFFSET(address, pmd) \ + ({ \ + pte_t *__pte; \ + __pte = pte_offset_map(pmd, address); \ + NV_PMD_UNMAP(pmd); __pte; \ + }) +#define NV_PTE_UNMAP(pte) pte_unmap(pte); #endif -#define NV_PTE_PRESENT(pte) \ - ({ \ - if (pte) { \ - if (!pte_present(*pte)) { \ - NV_PTE_UNMAP(pte); pte = NULL; \ - } \ - } pte != NULL; \ +#define NV_PTE_PRESENT(pte) \ + ({ \ + if ((pte != NULL) && !pte_present(*pte)) \ + { \ + NV_PTE_UNMAP(pte); \ + pte = NULL; /* mark invalid */ \ + } \ + pte != NULL; \ }) -#define NV_PTE_VALUE(pte) \ - ({ \ - unsigned long __pte_value = pte_val(*pte); \ - NV_PTE_UNMAP(pte); \ - __pte_value; \ +#define NV_PTE_VALUE(pte) \ + ({ \ + unsigned long __pte_value = pte_val(*pte); \ + NV_PTE_UNMAP(pte); \ + __pte_value; \ }) + #define NV_PAGE_ALIGN(addr) ( ((addr) + PAGE_SIZE - 1) / PAGE_SIZE) #define NV_MASK_OFFSET(addr) ( (addr) & (PAGE_SIZE - 1) ) diff -ru usr/src/nv/nv-vm.c usr/src/nv.1189413/nv-vm.c --- usr/src/nv/nv-vm.c 2004-11-03 22:53:00.000000000 +0100 +++ usr/src/nv.1189413/nv-vm.c 2005-01-07 15:43:22.000000000 +0100 @@ -53,12 +53,13 @@ * 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 diff -ru usr/src/nv/nv.c usr/src/nv.1189413/nv.c --- usr/src/nv/nv.c 2004-11-03 22:53:00.000000000 +0100 +++ usr/src/nv.1189413/nv.c 2005-01-07 15:43:22.000000000 +0100 @@ -2492,26 +2492,23 @@ ) { struct mm_struct *mm; - pgd_t *pg_dir; - pmd_t *pg_mid_dir; - pte_t *pte; + pgd_t *pgd = NULL; + pmd_t *pmd = NULL; + pte_t *pte = NULL; unsigned long retval; mm = (kern) ? &init_mm : current->mm; spin_lock(&mm->page_table_lock); - if (kern) pg_dir = pgd_offset_k(address); - else pg_dir = pgd_offset(mm, address); - - if (!pg_dir || pgd_none(*pg_dir)) + pgd = NV_PGD_OFFSET(address, kern, mm); + if (!NV_PGD_PRESENT(pgd)) goto failed; - NV_PMD_OFFSET(address, pg_dir, pg_mid_dir); - if (!NV_PMD_PRESENT(pg_mid_dir)) + pmd = NV_PMD_OFFSET(address, pgd); + if (!NV_PMD_PRESENT(pmd)) goto failed; - NV_PTE_OFFSET(address, pg_mid_dir, pte); - + pte = NV_PTE_OFFSET(address, pmd); if (!NV_PTE_PRESENT(pte)) goto failed;