diff options
author | kaf24@freefall.cl.cam.ac.uk <kaf24@freefall.cl.cam.ac.uk> | 2004-11-16 13:26:33 +0000 |
---|---|---|
committer | kaf24@freefall.cl.cam.ac.uk <kaf24@freefall.cl.cam.ac.uk> | 2004-11-16 13:26:33 +0000 |
commit | 743287866ffc3fe907665c2d172ee5161a5f382e (patch) | |
tree | f6f8f853dcda088b4478c7cdedc647fdadbb93fd | |
parent | 896fb4d9cc5ccd42fe0255b1c383d2db45d42755 (diff) | |
download | xen-743287866ffc3fe907665c2d172ee5161a5f382e.tar.gz xen-743287866ffc3fe907665c2d172ee5161a5f382e.tar.bz2 xen-743287866ffc3fe907665c2d172ee5161a5f382e.zip |
bitkeeper revision 1.1159.170.29 (419a0009K2EoexbNZXY_leDTaivx2w)
Fix make_page_{readonly,writable} to deal properly with highmem.
4 files changed, 81 insertions, 62 deletions
diff --git a/linux-2.6.9-xen-sparse/arch/xen/i386/kernel/traps.c b/linux-2.6.9-xen-sparse/arch/xen/i386/kernel/traps.c index dd1c42b840..dd14a5bc58 100644 --- a/linux-2.6.9-xen-sparse/arch/xen/i386/kernel/traps.c +++ b/linux-2.6.9-xen-sparse/arch/xen/i386/kernel/traps.c @@ -1064,7 +1064,7 @@ void __init trap_init(void) clear_page(&default_ldt[0]); set_call_gate(&default_ldt[0],lcall7); set_call_gate(&default_ldt[4],lcall27); - __make_page_readonly(&default_ldt[0]); + make_lowmem_page_readonly(&default_ldt[0]); xen_flush_page_update_queue(); /* diff --git a/linux-2.6.9-xen-sparse/arch/xen/i386/mm/pgtable.c b/linux-2.6.9-xen-sparse/arch/xen/i386/mm/pgtable.c index 4516df1643..791c6ce3f8 100644 --- a/linux-2.6.9-xen-sparse/arch/xen/i386/mm/pgtable.c +++ b/linux-2.6.9-xen-sparse/arch/xen/i386/mm/pgtable.c @@ -179,7 +179,7 @@ pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address) pte_t *pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT); if (pte) { clear_page(pte); - __make_page_readonly(pte); + make_page_readonly(pte); xen_flush_page_update_queue(); } return pte; @@ -192,7 +192,7 @@ void pte_ctor(void *pte, kmem_cache_t *cache, unsigned long unused) set_page_count(page, 1); clear_page(pte); - __make_page_readonly(pte); + make_page_readonly(pte); queue_pte_pin(virt_to_phys(pte)); flush_page_update_queue(); } @@ -203,7 +203,7 @@ void pte_dtor(void *pte, kmem_cache_t *cache, unsigned long unused) ClearPageForeign(page); queue_pte_unpin(virt_to_phys(pte)); - __make_page_writable(pte); + make_page_writable(pte); flush_page_update_queue(); } @@ -304,7 +304,7 @@ void pgd_ctor(void *pgd, kmem_cache_t *cache, unsigned long unused) spin_unlock_irqrestore(&pgd_lock, flags); memset(pgd, 0, USER_PTRS_PER_PGD*sizeof(pgd_t)); out: - __make_page_readonly(pgd); + make_page_readonly(pgd); queue_pgd_pin(__pa(pgd)); flush_page_update_queue(); } @@ -315,7 +315,7 @@ void pgd_dtor(void *pgd, kmem_cache_t *cache, unsigned long unused) unsigned long flags; /* can be called from interrupt context */ queue_pgd_unpin(__pa(pgd)); - __make_page_writable(pgd); + make_page_writable(pgd); flush_page_update_queue(); if (PTRS_PER_PMD > 1) @@ -360,3 +360,71 @@ void pgd_free(pgd_t *pgd) /* in the non-PAE case, clear_page_tables() clears user pgd entries */ kmem_cache_free(pgd_cache, pgd); } + +void make_lowmem_page_readonly(void *va) +{ + pgd_t *pgd = pgd_offset_k((unsigned long)va); + pmd_t *pmd = pmd_offset(pgd, (unsigned long)va); + pte_t *pte = pte_offset_kernel(pmd, (unsigned long)va); + queue_l1_entry_update(pte, (*(unsigned long *)pte)&~_PAGE_RW); +} + +void make_lowmem_page_writable(void *va) +{ + pgd_t *pgd = pgd_offset_k((unsigned long)va); + pmd_t *pmd = pmd_offset(pgd, (unsigned long)va); + pte_t *pte = pte_offset_kernel(pmd, (unsigned long)va); + queue_l1_entry_update(pte, (*(unsigned long *)pte)|_PAGE_RW); +} + +void make_page_readonly(void *va) +{ + pgd_t *pgd = pgd_offset_k((unsigned long)va); + pmd_t *pmd = pmd_offset(pgd, (unsigned long)va); + pte_t *pte = pte_offset_kernel(pmd, (unsigned long)va); + queue_l1_entry_update(pte, (*(unsigned long *)pte)&~_PAGE_RW); + if ( (unsigned long)va >= (unsigned long)high_memory ) + { + unsigned long phys; + phys = machine_to_phys(*(unsigned long *)pte & PAGE_MASK); +#ifdef CONFIG_HIGHMEM + if ( (phys >> PAGE_SHIFT) < highstart_pfn ) +#endif + make_lowmem_page_readonly(phys_to_virt(phys)); + } +} + +void make_page_writable(void *va) +{ + pgd_t *pgd = pgd_offset_k((unsigned long)va); + pmd_t *pmd = pmd_offset(pgd, (unsigned long)va); + pte_t *pte = pte_offset_kernel(pmd, (unsigned long)va); + queue_l1_entry_update(pte, (*(unsigned long *)pte)|_PAGE_RW); + if ( (unsigned long)va >= (unsigned long)high_memory ) + { + unsigned long phys; + phys = machine_to_phys(*(unsigned long *)pte & PAGE_MASK); +#ifdef CONFIG_HIGHMEM + if ( (phys >> PAGE_SHIFT) < highstart_pfn ) +#endif + make_lowmem_page_writable(phys_to_virt(phys)); + } +} + +void make_pages_readonly(void *va, unsigned int nr) +{ + while ( nr-- != 0 ) + { + make_page_readonly(va); + va = (void *)((unsigned long)va + PAGE_SIZE); + } +} + +void make_pages_writable(void *va, unsigned int nr) +{ + while ( nr-- != 0 ) + { + make_page_writable(va); + va = (void *)((unsigned long)va + PAGE_SIZE); + } +} diff --git a/linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/pgalloc.h b/linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/pgalloc.h index 77d16e3e72..c98a6d2933 100644 --- a/linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/pgalloc.h +++ b/linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/pgalloc.h @@ -32,7 +32,7 @@ extern struct page *pte_alloc_one(struct mm_struct *, unsigned long); static inline void pte_free_kernel(pte_t *pte) { free_page((unsigned long)pte); - __make_page_writable(pte); + make_page_writable(pte); flush_page_update_queue(); } diff --git a/linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/pgtable.h b/linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/pgtable.h index 67325a0262..cb5c4bb372 100644 --- a/linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/pgtable.h +++ b/linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/pgtable.h @@ -465,61 +465,12 @@ do { \ } while (0) /* NOTE: make_page* callers must call flush_page_update_queue() */ -static inline void __make_page_readonly(void *va) -{ - pgd_t *pgd = pgd_offset_k((unsigned long)va); - pmd_t *pmd = pmd_offset(pgd, (unsigned long)va); - pte_t *pte = pte_offset_kernel(pmd, (unsigned long)va); - queue_l1_entry_update(pte, (*(unsigned long *)pte)&~_PAGE_RW); -} - -static inline void __make_page_writable(void *va) -{ - pgd_t *pgd = pgd_offset_k((unsigned long)va); - pmd_t *pmd = pmd_offset(pgd, (unsigned long)va); - pte_t *pte = pte_offset_kernel(pmd, (unsigned long)va); - queue_l1_entry_update(pte, (*(unsigned long *)pte)|_PAGE_RW); -} - -static inline void make_page_readonly(void *va) -{ - pgd_t *pgd = pgd_offset_k((unsigned long)va); - pmd_t *pmd = pmd_offset(pgd, (unsigned long)va); - pte_t *pte = pte_offset_kernel(pmd, (unsigned long)va); - queue_l1_entry_update(pte, (*(unsigned long *)pte)&~_PAGE_RW); - if ( (unsigned long)va >= VMALLOC_START ) - __make_page_readonly(machine_to_virt( - *(unsigned long *)pte&PAGE_MASK)); -} - -static inline void make_page_writable(void *va) -{ - pgd_t *pgd = pgd_offset_k((unsigned long)va); - pmd_t *pmd = pmd_offset(pgd, (unsigned long)va); - pte_t *pte = pte_offset_kernel(pmd, (unsigned long)va); - queue_l1_entry_update(pte, (*(unsigned long *)pte)|_PAGE_RW); - if ( (unsigned long)va >= VMALLOC_START ) - __make_page_writable(machine_to_virt( - *(unsigned long *)pte&PAGE_MASK)); -} - -static inline void make_pages_readonly(void *va, unsigned int nr) -{ - while ( nr-- != 0 ) - { - make_page_readonly(va); - va = (void *)((unsigned long)va + PAGE_SIZE); - } -} - -static inline void make_pages_writable(void *va, unsigned int nr) -{ - while ( nr-- != 0 ) - { - make_page_writable(va); - va = (void *)((unsigned long)va + PAGE_SIZE); - } -} +void make_lowmem_page_readonly(void *va); +void make_lowmem_page_writable(void *va); +void make_page_readonly(void *va); +void make_page_writable(void *va); +void make_pages_readonly(void *va, unsigned int nr); +void make_pages_writable(void *va, unsigned int nr); static inline unsigned long arbitrary_virt_to_phys(void *va) { |