On Sat, 26 Feb 2005 19:09:43 -0800
"David S. Miller" <[EMAIL PROTECTED]> wrote:
> I know of at least three such cases so far, vmalloc.c:unmap_area_pte(),
> vmalloc.c:map_area_pte(), and mprotect.c:change_pte_range()
>
> The latter could definitely explain the behavior you are seeing on
> ppc64.
Ok, here's a fix, let me know if it makes the PPC64 problems
go away Ben.
Thanks.
===== mm/memory.c 1.224 vs edited =====
--- 1.224/mm/memory.c 2005-02-23 15:40:53 -08:00
+++ edited/mm/memory.c 2005-02-26 20:12:21 -08:00
@@ -992,16 +992,17 @@
unsigned long address,
unsigned long size, pgprot_t prot)
{
- unsigned long end;
+ unsigned long base, end;
+ base = address & PMD_MASK;
address &= ~PMD_MASK;
end = address + size;
if (end > PMD_SIZE)
end = PMD_SIZE;
do {
- pte_t zero_pte = pte_wrprotect(mk_pte(ZERO_PAGE(address),
prot));
+ pte_t zero_pte = pte_wrprotect(mk_pte(ZERO_PAGE(base+address),
prot));
BUG_ON(!pte_none(*pte));
- set_pte_at(mm, address, pte, zero_pte);
+ set_pte_at(mm, base+address, pte, zero_pte);
address += PAGE_SIZE;
pte++;
} while (address && (address < end));
@@ -1106,8 +1107,9 @@
unsigned long address, unsigned long size,
unsigned long pfn, pgprot_t prot)
{
- unsigned long end;
+ unsigned long base, end;
+ base = address & PMD_MASK;
address &= ~PMD_MASK;
end = address + size;
if (end > PMD_SIZE)
@@ -1115,7 +1117,7 @@
do {
BUG_ON(!pte_none(*pte));
if (!pfn_valid(pfn) || PageReserved(pfn_to_page(pfn)))
- set_pte_at(mm, address, pte, pfn_pte(pfn, prot));
+ set_pte_at(mm, base+address, pte, pfn_pte(pfn, prot));
address += PAGE_SIZE;
pfn++;
pte++;
===== mm/mprotect.c 1.41 vs edited =====
--- 1.41/mm/mprotect.c 2005-02-23 15:40:53 -08:00
+++ edited/mm/mprotect.c 2005-02-26 20:40:27 -08:00
@@ -30,7 +30,7 @@
unsigned long size, pgprot_t newprot)
{
pte_t * pte;
- unsigned long end;
+ unsigned long base, end;
if (pmd_none(*pmd))
return;
@@ -40,6 +40,7 @@
return;
}
pte = pte_offset_map(pmd, address);
+ base = address & PMD_MASK;
address &= ~PMD_MASK;
end = address + size;
if (end > PMD_SIZE)
@@ -52,8 +53,8 @@
* bits by wiping the pte and then setting the new pte
* into place.
*/
- entry = ptep_get_and_clear(mm, address, pte);
- set_pte_at(mm, address, pte, pte_modify(entry,
newprot));
+ entry = ptep_get_and_clear(mm, base + address, pte);
+ set_pte_at(mm, base + address, pte, pte_modify(entry,
newprot));
}
address += PAGE_SIZE;
pte++;
@@ -66,7 +67,7 @@
unsigned long size, pgprot_t newprot)
{
pmd_t * pmd;
- unsigned long end;
+ unsigned long base, end;
if (pud_none(*pud))
return;
@@ -76,12 +77,13 @@
return;
}
pmd = pmd_offset(pud, address);
+ base = address & PUD_MASK;
address &= ~PUD_MASK;
end = address + size;
if (end > PUD_SIZE)
end = PUD_SIZE;
do {
- change_pte_range(mm, pmd, address, end - address, newprot);
+ change_pte_range(mm, pmd, base + address, end - address,
newprot);
address = (address + PMD_SIZE) & PMD_MASK;
pmd++;
} while (address && (address < end));
@@ -92,7 +94,7 @@
unsigned long size, pgprot_t newprot)
{
pud_t * pud;
- unsigned long end;
+ unsigned long base, end;
if (pgd_none(*pgd))
return;
@@ -102,12 +104,13 @@
return;
}
pud = pud_offset(pgd, address);
+ base = address & PGDIR_MASK;
address &= ~PGDIR_MASK;
end = address + size;
if (end > PGDIR_SIZE)
end = PGDIR_SIZE;
do {
- change_pmd_range(mm, pud, address, end - address, newprot);
+ change_pmd_range(mm, pud, base + address, end - address,
newprot);
address = (address + PUD_SIZE) & PUD_MASK;
pud++;
} while (address && (address < end));
===== mm/vmalloc.c 1.41 vs edited =====
--- 1.41/mm/vmalloc.c 2005-02-23 15:40:53 -08:00
+++ edited/mm/vmalloc.c 2005-02-26 20:18:44 -08:00
@@ -26,7 +26,7 @@
static void unmap_area_pte(pmd_t *pmd, unsigned long address,
unsigned long size)
{
- unsigned long end;
+ unsigned long base, end;
pte_t *pte;
if (pmd_none(*pmd))
@@ -38,6 +38,7 @@
}
pte = pte_offset_kernel(pmd, address);
+ base = address & PMD_MASK;
address &= ~PMD_MASK;
end = address + size;
if (end > PMD_SIZE)
@@ -45,7 +46,7 @@
do {
pte_t page;
- page = ptep_get_and_clear(&init_mm, address, pte);
+ page = ptep_get_and_clear(&init_mm, base + address, pte);
address += PAGE_SIZE;
pte++;
if (pte_none(page))
@@ -59,7 +60,7 @@
static void unmap_area_pmd(pud_t *pud, unsigned long address,
unsigned long size)
{
- unsigned long end;
+ unsigned long base, end;
pmd_t *pmd;
if (pud_none(*pud))
@@ -71,13 +72,14 @@
}
pmd = pmd_offset(pud, address);
+ base = address & PUD_MASK;
address &= ~PUD_MASK;
end = address + size;
if (end > PUD_SIZE)
end = PUD_SIZE;
do {
- unmap_area_pte(pmd, address, end - address);
+ unmap_area_pte(pmd, base + address, end - address);
address = (address + PMD_SIZE) & PMD_MASK;
pmd++;
} while (address < end);
@@ -87,7 +89,7 @@
unsigned long size)
{
pud_t *pud;
- unsigned long end;
+ unsigned long base, end;
if (pgd_none(*pgd))
return;
@@ -98,13 +100,14 @@
}
pud = pud_offset(pgd, address);
+ base = address & PGDIR_MASK;
address &= ~PGDIR_MASK;
end = address + size;
if (end > PGDIR_SIZE)
end = PGDIR_SIZE;
do {
- unmap_area_pmd(pud, address, end - address);
+ unmap_area_pmd(pud, base + address, end - address);
address = (address + PUD_SIZE) & PUD_MASK;
pud++;
} while (address && (address < end));
@@ -114,8 +117,9 @@
unsigned long size, pgprot_t prot,
struct page ***pages)
{
- unsigned long end;
+ unsigned long base, end;
+ base = address & PMD_MASK;
address &= ~PMD_MASK;
end = address + size;
if (end > PMD_SIZE)
@@ -127,7 +131,7 @@
if (!page)
return -ENOMEM;
- set_pte_at(&init_mm, address, pte, mk_pte(page, prot));
+ set_pte_at(&init_mm, base + address, pte, mk_pte(page, prot));
address += PAGE_SIZE;
pte++;
(*pages)++;
@@ -151,7 +155,7 @@
pte_t * pte = pte_alloc_kernel(&init_mm, pmd, base + address);
if (!pte)
return -ENOMEM;
- if (map_area_pte(pte, address, end - address, prot, pages))
+ if (map_area_pte(pte, base + address, end - address, prot,
pages))
return -ENOMEM;
address = (address + PMD_SIZE) & PMD_MASK;
pmd++;