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.
As always, tested on 2.6.22 and made apply on 2.6.18.
Signed-off-by: Jan Beulich <jbeulich@xxxxxxxxxx>
Index: head-2007-09-03/arch/i386/mm/pgtable-xen.c
===================================================================
--- head-2007-09-03.orig/arch/i386/mm/pgtable-xen.c 2007-06-01
16:57:12.000000000 +0200
+++ head-2007-09-03/arch/i386/mm/pgtable-xen.c 2007-09-19 11:04:16.000000000
+0200
@@ -77,87 +77,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.
@@ -200,6 +119,7 @@ EXPORT_SYMBOL(__FIXADDR_TOP);
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();
@@ -207,16 +127,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-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|