]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - arch/x86/mm/pageattr.c
Merge branch 'for-4.8/core' of git://git.kernel.dk/linux-block
[karo-tx-linux.git] / arch / x86 / mm / pageattr.c
index 7a1f7bbf4105b6ec570c9c15497a00237c5185e9..849dc09fa4f0b803b7139015de6b98f7778165bd 100644 (file)
@@ -101,7 +101,8 @@ static inline unsigned long highmap_start_pfn(void)
 
 static inline unsigned long highmap_end_pfn(void)
 {
-       return __pa_symbol(roundup(_brk_end, PMD_SIZE)) >> PAGE_SHIFT;
+       /* Do not reference physical address outside the kernel. */
+       return __pa_symbol(roundup(_brk_end, PMD_SIZE) - 1) >> PAGE_SHIFT;
 }
 
 #endif
@@ -112,6 +113,12 @@ within(unsigned long addr, unsigned long start, unsigned long end)
        return addr >= start && addr < end;
 }
 
+static inline int
+within_inclusive(unsigned long addr, unsigned long start, unsigned long end)
+{
+       return addr >= start && addr <= end;
+}
+
 /*
  * Flushing functions
  */
@@ -746,18 +753,6 @@ static bool try_to_free_pmd_page(pmd_t *pmd)
        return true;
 }
 
-static bool try_to_free_pud_page(pud_t *pud)
-{
-       int i;
-
-       for (i = 0; i < PTRS_PER_PUD; i++)
-               if (!pud_none(pud[i]))
-                       return false;
-
-       free_page((unsigned long)pud);
-       return true;
-}
-
 static bool unmap_pte_range(pmd_t *pmd, unsigned long start, unsigned long end)
 {
        pte_t *pte = pte_offset_kernel(pmd, start);
@@ -871,16 +866,6 @@ static void unmap_pud_range(pgd_t *pgd, unsigned long start, unsigned long end)
         */
 }
 
-static void unmap_pgd_range(pgd_t *root, unsigned long addr, unsigned long end)
-{
-       pgd_t *pgd_entry = root + pgd_index(addr);
-
-       unmap_pud_range(pgd_entry, addr, end);
-
-       if (try_to_free_pud_page((pud_t *)pgd_page_vaddr(*pgd_entry)))
-               pgd_clear(pgd_entry);
-}
-
 static int alloc_pte_page(pmd_t *pmd)
 {
        pte_t *pte = (pte_t *)get_zeroed_page(GFP_KERNEL | __GFP_NOTRACK);
@@ -1113,7 +1098,12 @@ static int populate_pgd(struct cpa_data *cpa, unsigned long addr)
 
        ret = populate_pud(cpa, addr, pgd_entry, pgprot);
        if (ret < 0) {
-               unmap_pgd_range(cpa->pgd, addr,
+               /*
+                * Leave the PUD page in place in case some other CPU or thread
+                * already found it, but remove any useless entries we just
+                * added to it.
+                */
+               unmap_pud_range(pgd_entry, addr,
                                addr + (cpa->numpages << PAGE_SHIFT));
                return ret;
        }
@@ -1185,7 +1175,7 @@ repeat:
                return __cpa_process_fault(cpa, address, primary);
 
        old_pte = *kpte;
-       if (!pte_val(old_pte))
+       if (pte_none(old_pte))
                return __cpa_process_fault(cpa, address, primary);
 
        if (level == PG_LEVEL_4K) {
@@ -1316,7 +1306,8 @@ static int cpa_process_alias(struct cpa_data *cpa)
         * to touch the high mapped kernel as well:
         */
        if (!within(vaddr, (unsigned long)_text, _brk_end) &&
-           within(cpa->pfn, highmap_start_pfn(), highmap_end_pfn())) {
+           within_inclusive(cpa->pfn, highmap_start_pfn(),
+                            highmap_end_pfn())) {
                unsigned long temp_cpa_vaddr = (cpa->pfn << PAGE_SHIFT) +
                                               __START_KERNEL_map - phys_base;
                alias_cpa = *cpa;
@@ -1991,12 +1982,6 @@ out:
        return retval;
 }
 
-void kernel_unmap_pages_in_pgd(pgd_t *root, unsigned long address,
-                              unsigned numpages)
-{
-       unmap_pgd_range(root, address, address + (numpages << PAGE_SHIFT));
-}
-
 /*
  * The testcases use internal knowledge of the implementation that shouldn't
  * be exposed to the rest of the kernel. Include these directly here.