# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxx
# Date 1190215609 -3600
# Node ID 08e2785d344f66abe3e84b875c3cb7b26497459f
# Parent 4d713626f5b5eecfbd71ebd9f8c85c20b822fed7
linux/i386-PAE: avoid temporarily inconsistent pte's.
One more of these issues (which were considered fixed): Other than on
x86-64, i386 allows set_fixmap() to replace already present mappings.
Consequently, on PAE, care must be taken to not update the high half
of a pte while the low half is still holding the old value.
Signed-off-by: Jan Beulich <jbeulich@xxxxxxxxxx>
---
arch/i386/mm/pgtable-xen.c | 92 ++-------------------------------------------
1 files changed, 6 insertions(+), 86 deletions(-)
diff -r 4d713626f5b5 -r 08e2785d344f arch/i386/mm/pgtable-xen.c
--- a/arch/i386/mm/pgtable-xen.c Wed Sep 19 12:06:01 2007 +0100
+++ b/arch/i386/mm/pgtable-xen.c Wed Sep 19 16:26:49 2007 +0100
@@ -74,87 +74,6 @@ void show_mem(void)
}
/*
- * Associate a virtual page frame with a given physical page frame
- * and protection flags for that frame.
- */
-static void set_pte_pfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags)
-{
- pgd_t *pgd;
- pud_t *pud;
- pmd_t *pmd;
- pte_t *pte;
-
- pgd = swapper_pg_dir + pgd_index(vaddr);
- if (pgd_none(*pgd)) {
- BUG();
- return;
- }
- pud = pud_offset(pgd, vaddr);
- if (pud_none(*pud)) {
- BUG();
- return;
- }
- pmd = pmd_offset(pud, vaddr);
- if (pmd_none(*pmd)) {
- BUG();
- return;
- }
- pte = pte_offset_kernel(pmd, vaddr);
- if (pgprot_val(flags))
- /* <pfn,flags> stored as-is, to permit clearing entries */
- set_pte(pte, pfn_pte(pfn, flags));
- else
- pte_clear(&init_mm, vaddr, pte);
-
- /*
- * It's enough to flush this one mapping.
- * (PGE mappings get flushed as well)
- */
- __flush_tlb_one(vaddr);
-}
-
-/*
- * Associate a virtual page frame with a given physical page frame
- * and protection flags for that frame.
- */
-static void set_pte_pfn_ma(unsigned long vaddr, unsigned long pfn,
- pgprot_t flags)
-{
- pgd_t *pgd;
- pud_t *pud;
- pmd_t *pmd;
- pte_t *pte;
-
- pgd = swapper_pg_dir + pgd_index(vaddr);
- if (pgd_none(*pgd)) {
- BUG();
- return;
- }
- pud = pud_offset(pgd, vaddr);
- if (pud_none(*pud)) {
- BUG();
- return;
- }
- pmd = pmd_offset(pud, vaddr);
- if (pmd_none(*pmd)) {
- BUG();
- return;
- }
- pte = pte_offset_kernel(pmd, vaddr);
- if (pgprot_val(flags))
- /* <pfn,flags> stored as-is, to permit clearing entries */
- set_pte(pte, pfn_pte_ma(pfn, flags));
- else
- pte_clear(&init_mm, vaddr, pte);
-
- /*
- * It's enough to flush this one mapping.
- * (PGE mappings get flushed as well)
- */
- __flush_tlb_one(vaddr);
-}
-
-/*
* Associate a large virtual page frame with a given physical page frame
* and protection flags for that frame. pfn is for the base of the page,
* vaddr is what the page gets mapped to - both must be properly aligned.
@@ -204,6 +123,7 @@ void __set_fixmap (enum fixed_addresses
void __set_fixmap (enum fixed_addresses idx, maddr_t phys, pgprot_t flags)
{
unsigned long address = __fix_to_virt(idx);
+ pte_t pte;
if (idx >= __end_of_fixed_addresses) {
BUG();
@@ -211,16 +131,16 @@ void __set_fixmap (enum fixed_addresses
}
switch (idx) {
case FIX_WP_TEST:
-#ifdef CONFIG_X86_F00F_BUG
- case FIX_F00F_IDT:
-#endif
case FIX_VDSO:
- set_pte_pfn(address, phys >> PAGE_SHIFT, flags);
+ pte = pfn_pte(phys >> PAGE_SHIFT, flags);
break;
default:
- set_pte_pfn_ma(address, phys >> PAGE_SHIFT, flags);
+ pte = pfn_pte_ma(phys >> PAGE_SHIFT, flags);
break;
}
+ if (HYPERVISOR_update_va_mapping(address, pte,
+ UVMF_INVLPG|UVMF_ALL))
+ BUG();
nr_fixmaps++;
}
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|