]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - arch/x86/xen/mmu.c
Merge branch 'linus' into x86/delay
[linux-2.6-omap-h63xx.git] / arch / x86 / xen / mmu.c
index 2a054ef2a3dab3ac6fc3cebd380a21b8b84dd54a..df40bf74ea751da4a0556a5b6603af1f3989a39b 100644 (file)
@@ -60,7 +60,7 @@ xmaddr_t arbitrary_virt_to_machine(unsigned long address)
 {
        unsigned int level;
        pte_t *pte = lookup_address(address, &level);
-       unsigned offset = address & PAGE_MASK;
+       unsigned offset = address & ~PAGE_MASK;
 
        BUG_ON(pte == NULL);
 
@@ -156,6 +156,10 @@ void set_pte_mfn(unsigned long vaddr, unsigned long mfn, pgprot_t flags)
 void xen_set_pte_at(struct mm_struct *mm, unsigned long addr,
                    pte_t *ptep, pte_t pteval)
 {
+       /* updates to init_mm may be done without lock */
+       if (mm == &init_mm)
+               preempt_disable();
+
        if (mm == current->mm || mm == &init_mm) {
                if (paravirt_get_lazy_mode() == PARAVIRT_LAZY_MMU) {
                        struct multicall_space mcs;
@@ -163,152 +167,115 @@ void xen_set_pte_at(struct mm_struct *mm, unsigned long addr,
 
                        MULTI_update_va_mapping(mcs.mc, addr, pteval, 0);
                        xen_mc_issue(PARAVIRT_LAZY_MMU);
-                       return;
+                       goto out;
                } else
                        if (HYPERVISOR_update_va_mapping(addr, pteval, 0) == 0)
-                               return;
+                               goto out;
        }
        xen_set_pte(ptep, pteval);
+
+out:
+       if (mm == &init_mm)
+               preempt_enable();
 }
 
-#ifdef CONFIG_X86_PAE
-void xen_set_pud(pud_t *ptr, pud_t val)
+/* Assume pteval_t is equivalent to all the other *val_t types. */
+static pteval_t pte_mfn_to_pfn(pteval_t val)
 {
-       struct multicall_space mcs;
-       struct mmu_update *u;
-
-       preempt_disable();
-
-       mcs = xen_mc_entry(sizeof(*u));
-       u = mcs.args;
-       u->ptr = virt_to_machine(ptr).maddr;
-       u->val = pud_val_ma(val);
-       MULTI_mmu_update(mcs.mc, u, 1, NULL, DOMID_SELF);
-
-       xen_mc_issue(PARAVIRT_LAZY_MMU);
+       if (val & _PAGE_PRESENT) {
+               unsigned long mfn = (val & PTE_MASK) >> PAGE_SHIFT;
+               pteval_t flags = val & ~PTE_MASK;
+               val = (mfn_to_pfn(mfn) << PAGE_SHIFT) | flags;
+       }
 
-       preempt_enable();
+       return val;
 }
 
-void xen_set_pte(pte_t *ptep, pte_t pte)
+static pteval_t pte_pfn_to_mfn(pteval_t val)
 {
-       ptep->pte_high = pte.pte_high;
-       smp_wmb();
-       ptep->pte_low = pte.pte_low;
-}
+       if (val & _PAGE_PRESENT) {
+               unsigned long pfn = (val & PTE_MASK) >> PAGE_SHIFT;
+               pteval_t flags = val & ~PTE_MASK;
+               val = (pfn_to_mfn(pfn) << PAGE_SHIFT) | flags;
+       }
 
-void xen_set_pte_atomic(pte_t *ptep, pte_t pte)
-{
-       set_64bit((u64 *)ptep, pte_val_ma(pte));
+       return val;
 }
 
-void xen_pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
+pteval_t xen_pte_val(pte_t pte)
 {
-       ptep->pte_low = 0;
-       smp_wmb();              /* make sure low gets written first */
-       ptep->pte_high = 0;
+       return pte_mfn_to_pfn(pte.pte);
 }
 
-void xen_pmd_clear(pmd_t *pmdp)
+pgdval_t xen_pgd_val(pgd_t pgd)
 {
-       xen_set_pmd(pmdp, __pmd(0));
+       return pte_mfn_to_pfn(pgd.pgd);
 }
 
-unsigned long long xen_pte_val(pte_t pte)
+pte_t xen_make_pte(pteval_t pte)
 {
-       unsigned long long ret = 0;
-
-       if (pte.pte_low) {
-               ret = ((unsigned long long)pte.pte_high << 32) | pte.pte_low;
-               ret = machine_to_phys(XMADDR(ret)).paddr | 1;
-       }
-
-       return ret;
+       pte = pte_pfn_to_mfn(pte);
+       return native_make_pte(pte);
 }
 
-unsigned long long xen_pmd_val(pmd_t pmd)
+pgd_t xen_make_pgd(pgdval_t pgd)
 {
-       unsigned long long ret = pmd.pmd;
-       if (ret)
-               ret = machine_to_phys(XMADDR(ret)).paddr | 1;
-       return ret;
+       pgd = pte_pfn_to_mfn(pgd);
+       return native_make_pgd(pgd);
 }
 
-unsigned long long xen_pgd_val(pgd_t pgd)
+pmdval_t xen_pmd_val(pmd_t pmd)
 {
-       unsigned long long ret = pgd.pgd;
-       if (ret)
-               ret = machine_to_phys(XMADDR(ret)).paddr | 1;
-       return ret;
+       return pte_mfn_to_pfn(pmd.pmd);
 }
 
-pte_t xen_make_pte(unsigned long long pte)
+void xen_set_pud(pud_t *ptr, pud_t val)
 {
-       if (pte & _PAGE_PRESENT) {
-               pte = phys_to_machine(XPADDR(pte)).maddr;
-               pte &= ~(_PAGE_PCD | _PAGE_PWT);
-       }
-
-       return (pte_t){ .pte = pte };
-}
+       struct multicall_space mcs;
+       struct mmu_update *u;
 
-pmd_t xen_make_pmd(unsigned long long pmd)
-{
-       if (pmd & 1)
-               pmd = phys_to_machine(XPADDR(pmd)).maddr;
+       preempt_disable();
 
-       return (pmd_t){ pmd };
-}
+       mcs = xen_mc_entry(sizeof(*u));
+       u = mcs.args;
+       u->ptr = virt_to_machine(ptr).maddr;
+       u->val = pud_val_ma(val);
+       MULTI_mmu_update(mcs.mc, u, 1, NULL, DOMID_SELF);
 
-pgd_t xen_make_pgd(unsigned long long pgd)
-{
-       if (pgd & _PAGE_PRESENT)
-               pgd = phys_to_machine(XPADDR(pgd)).maddr;
+       xen_mc_issue(PARAVIRT_LAZY_MMU);
 
-       return (pgd_t){ pgd };
+       preempt_enable();
 }
-#else  /* !PAE */
+
 void xen_set_pte(pte_t *ptep, pte_t pte)
 {
-       *ptep = pte;
+       ptep->pte_high = pte.pte_high;
+       smp_wmb();
+       ptep->pte_low = pte.pte_low;
 }
 
-unsigned long xen_pte_val(pte_t pte)
+void xen_set_pte_atomic(pte_t *ptep, pte_t pte)
 {
-       unsigned long ret = pte.pte_low;
-
-       if (ret & _PAGE_PRESENT)
-               ret = machine_to_phys(XMADDR(ret)).paddr;
-
-       return ret;
+       set_64bit((u64 *)ptep, pte_val_ma(pte));
 }
 
-unsigned long xen_pgd_val(pgd_t pgd)
+void xen_pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
 {
-       unsigned long ret = pgd.pgd;
-       if (ret)
-               ret = machine_to_phys(XMADDR(ret)).paddr | 1;
-       return ret;
+       ptep->pte_low = 0;
+       smp_wmb();              /* make sure low gets written first */
+       ptep->pte_high = 0;
 }
 
-pte_t xen_make_pte(unsigned long pte)
+void xen_pmd_clear(pmd_t *pmdp)
 {
-       if (pte & _PAGE_PRESENT) {
-               pte = phys_to_machine(XPADDR(pte)).maddr;
-               pte &= ~(_PAGE_PCD | _PAGE_PWT);
-       }
-
-       return (pte_t){ pte };
+       xen_set_pmd(pmdp, __pmd(0));
 }
 
-pgd_t xen_make_pgd(unsigned long pgd)
+pmd_t xen_make_pmd(pmdval_t pmd)
 {
-       if (pgd & _PAGE_PRESENT)
-               pgd = phys_to_machine(XPADDR(pgd)).maddr;
-
-       return (pgd_t){ pgd };
+       pmd = pte_pfn_to_mfn(pmd);
+       return native_make_pmd(pmd);
 }
-#endif /* CONFIG_X86_PAE */
 
 /*
   (Yet another) pagetable walker.  This one is intended for pinning a
@@ -418,7 +385,7 @@ static void xen_do_pin(unsigned level, unsigned long pfn)
 
 static int pin_page(struct page *page, enum pt_level level)
 {
-       unsigned pgfl = test_and_set_bit(PG_pinned, &page->flags);
+       unsigned pgfl = TestSetPagePinned(page);
        int flush;
 
        if (pgfl)
@@ -461,8 +428,6 @@ static int pin_page(struct page *page, enum pt_level level)
    read-only, and can be pinned. */
 void xen_pgd_pin(pgd_t *pgd)
 {
-       unsigned level;
-
        xen_mc_batch();
 
        if (pgd_walk(pgd, pin_page, TASK_SIZE)) {
@@ -472,14 +437,7 @@ void xen_pgd_pin(pgd_t *pgd)
                xen_mc_batch();
        }
 
-#ifdef CONFIG_X86_PAE
-       level = MMUEXT_PIN_L3_TABLE;
-#else
-       level = MMUEXT_PIN_L2_TABLE;
-#endif
-
-       xen_do_pin(level, PFN_DOWN(__pa(pgd)));
-
+       xen_do_pin(MMUEXT_PIN_L3_TABLE, PFN_DOWN(__pa(pgd)));
        xen_mc_issue(0);
 }
 
@@ -499,7 +457,7 @@ void __init xen_mark_init_mm_pinned(void)
 
 static int unpin_page(struct page *page, enum pt_level level)
 {
-       unsigned pgfl = test_and_clear_bit(PG_pinned, &page->flags);
+       unsigned pgfl = TestClearPagePinned(page);
 
        if (pgfl && !PageHighMem(page)) {
                void *pt = lowmem_page_address(page);