aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkaf24@freefall.cl.cam.ac.uk <kaf24@freefall.cl.cam.ac.uk>2004-11-16 13:26:33 +0000
committerkaf24@freefall.cl.cam.ac.uk <kaf24@freefall.cl.cam.ac.uk>2004-11-16 13:26:33 +0000
commit743287866ffc3fe907665c2d172ee5161a5f382e (patch)
treef6f8f853dcda088b4478c7cdedc647fdadbb93fd
parent896fb4d9cc5ccd42fe0255b1c383d2db45d42755 (diff)
downloadxen-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.
-rw-r--r--linux-2.6.9-xen-sparse/arch/xen/i386/kernel/traps.c2
-rw-r--r--linux-2.6.9-xen-sparse/arch/xen/i386/mm/pgtable.c78
-rw-r--r--linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/pgalloc.h2
-rw-r--r--linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/pgtable.h61
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)
{