Merge branch 'rbd-sysfs' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph...
[pandora-kernel.git] / arch / x86 / xen / mmu.c
index 21ed8d7..a1feff9 100644 (file)
@@ -2034,6 +2034,20 @@ static __init void xen_map_identity_early(pmd_t *pmd, unsigned long max_pfn)
        set_page_prot(pmd, PAGE_KERNEL_RO);
 }
 
+void __init xen_setup_machphys_mapping(void)
+{
+       struct xen_machphys_mapping mapping;
+       unsigned long machine_to_phys_nr_ents;
+
+       if (HYPERVISOR_memory_op(XENMEM_machphys_mapping, &mapping) == 0) {
+               machine_to_phys_mapping = (unsigned long *)mapping.v_start;
+               machine_to_phys_nr_ents = mapping.max_mfn + 1;
+       } else {
+               machine_to_phys_nr_ents = MACH2PHYS_NR_ENTRIES;
+       }
+       machine_to_phys_order = fls(machine_to_phys_nr_ents - 1);
+}
+
 #ifdef CONFIG_X86_64
 static void convert_pfn_mfn(void *v)
 {
@@ -2119,44 +2133,83 @@ __init pgd_t *xen_setup_kernel_pagetable(pgd_t *pgd,
        return pgd;
 }
 #else  /* !CONFIG_X86_64 */
-static RESERVE_BRK_ARRAY(pmd_t, level2_kernel_pgt, PTRS_PER_PMD);
+static RESERVE_BRK_ARRAY(pmd_t, initial_kernel_pmd, PTRS_PER_PMD);
+static RESERVE_BRK_ARRAY(pmd_t, swapper_kernel_pmd, PTRS_PER_PMD);
+
+static __init void xen_write_cr3_init(unsigned long cr3)
+{
+       unsigned long pfn = PFN_DOWN(__pa(swapper_pg_dir));
+
+       BUG_ON(read_cr3() != __pa(initial_page_table));
+       BUG_ON(cr3 != __pa(swapper_pg_dir));
+
+       /*
+        * We are switching to swapper_pg_dir for the first time (from
+        * initial_page_table) and therefore need to mark that page
+        * read-only and then pin it.
+        *
+        * Xen disallows sharing of kernel PMDs for PAE
+        * guests. Therefore we must copy the kernel PMD from
+        * initial_page_table into a new kernel PMD to be used in
+        * swapper_pg_dir.
+        */
+       swapper_kernel_pmd =
+               extend_brk(sizeof(pmd_t) * PTRS_PER_PMD, PAGE_SIZE);
+       memcpy(swapper_kernel_pmd, initial_kernel_pmd,
+              sizeof(pmd_t) * PTRS_PER_PMD);
+       swapper_pg_dir[KERNEL_PGD_BOUNDARY] =
+               __pgd(__pa(swapper_kernel_pmd) | _PAGE_PRESENT);
+       set_page_prot(swapper_kernel_pmd, PAGE_KERNEL_RO);
+
+       set_page_prot(swapper_pg_dir, PAGE_KERNEL_RO);
+       xen_write_cr3(cr3);
+       pin_pagetable_pfn(MMUEXT_PIN_L3_TABLE, pfn);
+
+       pin_pagetable_pfn(MMUEXT_UNPIN_TABLE,
+                         PFN_DOWN(__pa(initial_page_table)));
+       set_page_prot(initial_page_table, PAGE_KERNEL);
+       set_page_prot(initial_kernel_pmd, PAGE_KERNEL);
+
+       pv_mmu_ops.write_cr3 = &xen_write_cr3;
+}
 
 __init pgd_t *xen_setup_kernel_pagetable(pgd_t *pgd,
                                         unsigned long max_pfn)
 {
        pmd_t *kernel_pmd;
 
-       level2_kernel_pgt = extend_brk(sizeof(pmd_t) * PTRS_PER_PMD, PAGE_SIZE);
+       initial_kernel_pmd =
+               extend_brk(sizeof(pmd_t) * PTRS_PER_PMD, PAGE_SIZE);
 
        max_pfn_mapped = PFN_DOWN(__pa(xen_start_info->pt_base) +
                                  xen_start_info->nr_pt_frames * PAGE_SIZE +
                                  512*1024);
 
        kernel_pmd = m2v(pgd[KERNEL_PGD_BOUNDARY].pgd);
-       memcpy(level2_kernel_pgt, kernel_pmd, sizeof(pmd_t) * PTRS_PER_PMD);
+       memcpy(initial_kernel_pmd, kernel_pmd, sizeof(pmd_t) * PTRS_PER_PMD);
 
-       xen_map_identity_early(level2_kernel_pgt, max_pfn);
+       xen_map_identity_early(initial_kernel_pmd, max_pfn);
 
-       memcpy(swapper_pg_dir, pgd, sizeof(pgd_t) * PTRS_PER_PGD);
-       set_pgd(&swapper_pg_dir[KERNEL_PGD_BOUNDARY],
-                       __pgd(__pa(level2_kernel_pgt) | _PAGE_PRESENT));
+       memcpy(initial_page_table, pgd, sizeof(pgd_t) * PTRS_PER_PGD);
+       initial_page_table[KERNEL_PGD_BOUNDARY] =
+               __pgd(__pa(initial_kernel_pmd) | _PAGE_PRESENT);
 
-       set_page_prot(level2_kernel_pgt, PAGE_KERNEL_RO);
-       set_page_prot(swapper_pg_dir, PAGE_KERNEL_RO);
+       set_page_prot(initial_kernel_pmd, PAGE_KERNEL_RO);
+       set_page_prot(initial_page_table, PAGE_KERNEL_RO);
        set_page_prot(empty_zero_page, PAGE_KERNEL_RO);
 
        pin_pagetable_pfn(MMUEXT_UNPIN_TABLE, PFN_DOWN(__pa(pgd)));
 
-       xen_write_cr3(__pa(swapper_pg_dir));
-
-       pin_pagetable_pfn(MMUEXT_PIN_L3_TABLE, PFN_DOWN(__pa(swapper_pg_dir)));
+       pin_pagetable_pfn(MMUEXT_PIN_L3_TABLE,
+                         PFN_DOWN(__pa(initial_page_table)));
+       xen_write_cr3(__pa(initial_page_table));
 
        memblock_x86_reserve_range(__pa(xen_start_info->pt_base),
                      __pa(xen_start_info->pt_base +
                           xen_start_info->nr_pt_frames * PAGE_SIZE),
                      "XEN PAGETABLES");
 
-       return swapper_pg_dir;
+       return initial_page_table;
 }
 #endif /* CONFIG_X86_64 */
 
@@ -2290,7 +2343,11 @@ static const struct pv_mmu_ops xen_mmu_ops __initdata = {
        .write_cr2 = xen_write_cr2,
 
        .read_cr3 = xen_read_cr3,
+#ifdef CONFIG_X86_32
+       .write_cr3 = xen_write_cr3_init,
+#else
        .write_cr3 = xen_write_cr3,
+#endif
 
        .flush_tlb_user = xen_flush_tlb,
        .flush_tlb_kernel = xen_flush_tlb,
@@ -2627,7 +2684,8 @@ int xen_remap_domain_mfn_range(struct vm_area_struct *vma,
 
        prot = __pgprot(pgprot_val(prot) | _PAGE_IOMAP);
 
-       vma->vm_flags |= VM_IO | VM_RESERVED | VM_PFNMAP;
+       BUG_ON(!((vma->vm_flags & (VM_PFNMAP | VM_RESERVED | VM_IO)) ==
+                               (VM_PFNMAP | VM_RESERVED | VM_IO)));
 
        rmd.mfn = mfn;
        rmd.prot = prot;