powerpc/mm: Ensure change_page_attr() doesn't invalidate pinned TLBs
__change_page_attr() uses flush_tlb_page(). flush_tlb_page() uses tlbie instruction, which also invalidates pinned TLBs, which is not what we expect. This patch modifies the implementation to use flush_tlb_kernel_range() instead. This will make use of tlbia which will preserve pinned TLBs. Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
This commit is contained in:
parent
2ef973a9af
commit
e611939fc8
@ -325,7 +325,7 @@ get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep, pmd_t **pmdp)
|
|||||||
|
|
||||||
#ifdef CONFIG_DEBUG_PAGEALLOC
|
#ifdef CONFIG_DEBUG_PAGEALLOC
|
||||||
|
|
||||||
static int __change_page_attr(struct page *page, pgprot_t prot)
|
static int __change_page_attr_noflush(struct page *page, pgprot_t prot)
|
||||||
{
|
{
|
||||||
pte_t *kpte;
|
pte_t *kpte;
|
||||||
pmd_t *kpmd;
|
pmd_t *kpmd;
|
||||||
@ -339,8 +339,6 @@ static int __change_page_attr(struct page *page, pgprot_t prot)
|
|||||||
if (!get_pteptr(&init_mm, address, &kpte, &kpmd))
|
if (!get_pteptr(&init_mm, address, &kpte, &kpmd))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
__set_pte_at(&init_mm, address, kpte, mk_pte(page, prot), 0);
|
__set_pte_at(&init_mm, address, kpte, mk_pte(page, prot), 0);
|
||||||
wmb();
|
|
||||||
flush_tlb_page(NULL, address);
|
|
||||||
pte_unmap(kpte);
|
pte_unmap(kpte);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -355,13 +353,17 @@ static int change_page_attr(struct page *page, int numpages, pgprot_t prot)
|
|||||||
{
|
{
|
||||||
int i, err = 0;
|
int i, err = 0;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
struct page *start = page;
|
||||||
|
|
||||||
local_irq_save(flags);
|
local_irq_save(flags);
|
||||||
for (i = 0; i < numpages; i++, page++) {
|
for (i = 0; i < numpages; i++, page++) {
|
||||||
err = __change_page_attr(page, prot);
|
err = __change_page_attr_noflush(page, prot);
|
||||||
if (err)
|
if (err)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
wmb();
|
||||||
|
flush_tlb_kernel_range((unsigned long)page_address(start),
|
||||||
|
(unsigned long)page_address(page));
|
||||||
local_irq_restore(flags);
|
local_irq_restore(flags);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user