]> git.karo-electronics.de Git - linux-beck.git/blobdiff - arch/x86/mm/pageattr.c
x86/mm: Avoid premature success when changing page attributes
[linux-beck.git] / arch / x86 / mm / pageattr.c
index 6000ad7f560c399226f06612c406268ac6a68820..3dd6afd2c0e5769588a170c0317782f4b23611a8 100644 (file)
@@ -33,7 +33,7 @@ struct cpa_data {
        pgd_t           *pgd;
        pgprot_t        mask_set;
        pgprot_t        mask_clr;
-       int             numpages;
+       unsigned long   numpages;
        int             flags;
        unsigned long   pfn;
        unsigned        force_split : 1;
@@ -66,6 +66,9 @@ void update_page_count(int level, unsigned long pages)
 
 static void split_page_count(int level)
 {
+       if (direct_pages_count[level] == 0)
+               return;
+
        direct_pages_count[level]--;
        direct_pages_count[level - 1] += PTRS_PER_PTE;
 }
@@ -1119,8 +1122,10 @@ static int __cpa_process_fault(struct cpa_data *cpa, unsigned long vaddr,
        /*
         * Ignore all non primary paths.
         */
-       if (!primary)
+       if (!primary) {
+               cpa->numpages = 1;
                return 0;
+       }
 
        /*
         * Ignore the NULL PTE for kernel identity mapping, as it is expected
@@ -1347,7 +1352,7 @@ static int __change_page_attr_set_clr(struct cpa_data *cpa, int checkalias)
                 * CPA operation. Either a large page has been
                 * preserved or a single page update happened.
                 */
-               BUG_ON(cpa->numpages > numpages);
+               BUG_ON(cpa->numpages > numpages || !cpa->numpages);
                numpages -= cpa->numpages;
                if (cpa->flags & (CPA_PAGES_ARRAY | CPA_ARRAY))
                        cpa->curpage++;