]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - arch/x86/mm/pageattr.c
Merge branch 'efi-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[karo-tx-linux.git] / arch / x86 / mm / pageattr.c
index 4d0b26253042d525107106f8e230535c65f25ca8..01be9ec3bf792f65ac91cc57fe7d64e8e644998f 100644 (file)
@@ -909,16 +909,25 @@ static void populate_pte(struct cpa_data *cpa,
 
        pte = pte_offset_kernel(pmd, start);
 
-       while (num_pages-- && start < end) {
+       /*
+        * Set the GLOBAL flags only if the PRESENT flag is
+        * set otherwise pte_present will return true even on
+        * a non present pte. The canon_pgprot will clear
+        * _PAGE_GLOBAL for the ancient hardware that doesn't
+        * support it.
+        */
+       if (pgprot_val(pgprot) & _PAGE_PRESENT)
+               pgprot_val(pgprot) |= _PAGE_GLOBAL;
+       else
+               pgprot_val(pgprot) &= ~_PAGE_GLOBAL;
 
-               /* deal with the NX bit */
-               if (!(pgprot_val(pgprot) & _PAGE_NX))
-                       cpa->pfn &= ~_PAGE_NX;
+       pgprot = canon_pgprot(pgprot);
 
-               set_pte(pte, pfn_pte(cpa->pfn >> PAGE_SHIFT, pgprot));
+       while (num_pages-- && start < end) {
+               set_pte(pte, pfn_pte(cpa->pfn, pgprot));
 
                start    += PAGE_SIZE;
-               cpa->pfn += PAGE_SIZE;
+               cpa->pfn++;
                pte++;
        }
 }
@@ -974,11 +983,11 @@ static int populate_pmd(struct cpa_data *cpa,
 
                pmd = pmd_offset(pud, start);
 
-               set_pmd(pmd, __pmd(cpa->pfn | _PAGE_PSE |
+               set_pmd(pmd, __pmd(cpa->pfn << PAGE_SHIFT | _PAGE_PSE |
                                   massage_pgprot(pmd_pgprot)));
 
                start     += PMD_SIZE;
-               cpa->pfn  += PMD_SIZE;
+               cpa->pfn  += PMD_SIZE >> PAGE_SHIFT;
                cur_pages += PMD_SIZE >> PAGE_SHIFT;
        }
 
@@ -1046,12 +1055,12 @@ static int populate_pud(struct cpa_data *cpa, unsigned long start, pgd_t *pgd,
        /*
         * Map everything starting from the Gb boundary, possibly with 1G pages
         */
-       while (end - start >= PUD_SIZE) {
-               set_pud(pud, __pud(cpa->pfn | _PAGE_PSE |
+       while (cpu_has_gbpages && end - start >= PUD_SIZE) {
+               set_pud(pud, __pud(cpa->pfn << PAGE_SHIFT | _PAGE_PSE |
                                   massage_pgprot(pud_pgprot)));
 
                start     += PUD_SIZE;
-               cpa->pfn  += PUD_SIZE;
+               cpa->pfn  += PUD_SIZE >> PAGE_SHIFT;
                cur_pages += PUD_SIZE >> PAGE_SHIFT;
                pud++;
        }
@@ -1964,6 +1973,9 @@ int kernel_map_pages_in_pgd(pgd_t *pgd, u64 pfn, unsigned long address,
        if (!(page_flags & _PAGE_NX))
                cpa.mask_clr = __pgprot(_PAGE_NX);
 
+       if (!(page_flags & _PAGE_RW))
+               cpa.mask_clr = __pgprot(_PAGE_RW);
+
        cpa.mask_set = __pgprot(_PAGE_PRESENT | page_flags);
 
        retval = __change_page_attr_set_clr(&cpa, 0);