diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index d4c8faf4a4cddeb0dc700df40ac68575db38e91d..73c1f6ae7241528377acf127aa30eb2eaae7408f 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c @@ -111,7 +111,6 @@ static unsigned long cpa_1g_preserved; static unsigned long cpa_2m_checked; static unsigned long cpa_2m_sameprot; static unsigned long cpa_2m_preserved; -static unsigned long cpa_4k_checked; static unsigned long cpa_4k_install; static inline void cpa_inc_1g_checked(void) @@ -124,11 +123,6 @@ static inline void cpa_inc_2m_checked(void) cpa_2m_checked++; } -static inline void cpa_inc_4k_checked(void) -{ - cpa_4k_checked++; -} - static inline void cpa_inc_4k_install(void) { cpa_4k_install++; @@ -158,7 +152,6 @@ static int cpastats_show(struct seq_file *m, void *p) seq_printf(m, "2M pages checked: %16lu\n", cpa_2m_checked); seq_printf(m, "2M pages sameprot: %16lu\n", cpa_2m_sameprot); seq_printf(m, "2M pages preserved: %16lu\n", cpa_2m_preserved); - seq_printf(m, "4K pages checked: %16lu\n", cpa_4k_checked); seq_printf(m, "4K pages set-checked: %16lu\n", cpa_4k_install); return 0; } @@ -185,7 +178,6 @@ late_initcall(cpa_stats_init); #else static inline void cpa_inc_1g_checked(void) { } static inline void cpa_inc_2m_checked(void) { } -static inline void cpa_inc_4k_checked(void) { } static inline void cpa_inc_4k_install(void) { } static inline void cpa_inc_lp_sameprot(int level) { } static inline void cpa_inc_lp_preserved(int level) { } @@ -745,11 +737,10 @@ static pgprot_t pgprot_clear_protnone_bits(pgprot_t prot) static int __should_split_large_page(pte_t *kpte, unsigned long address, struct cpa_data *cpa) { - unsigned long numpages, pmask, psize, lpaddr, addr, pfn, old_pfn; + unsigned long numpages, pmask, psize, lpaddr, pfn, old_pfn; pgprot_t old_prot, new_prot, req_prot, chk_prot; pte_t new_pte, old_pte, *tmp; enum pg_level level; - int i; /* * Check for races, another CPU might have split this page @@ -854,53 +845,30 @@ static int __should_split_large_page(pte_t *kpte, unsigned long address, } /* - * Optimization: Check whether the requested pgprot is conflicting - * with a static protection requirement in the large page. If not, - * then checking whether the requested range is fully covering the - * large page can be done right here. + * If the requested range does not cover the full page, split it up */ - new_prot = static_protections(req_prot, lpaddr, old_pfn, numpages, - CPA_DETECT); - - if (pgprot_val(req_prot) == pgprot_val(new_prot)) { - if (address != lpaddr || cpa->numpages != numpages) - return 1; - goto setlp; - } + if (address != lpaddr || cpa->numpages != numpages) + return 1; /* - * Slow path. The full large page check above established that the - * requested pgprot cannot be applied to the full large page due to - * conflicting requirements of static protection regions. It might - * turn out that the whole requested range is covered by the - * modified protection of the first 4k segment at @address. This - * might result in the ability to preserve the large page - * nevertheless. + * Check whether the requested pgprot is conflicting with a static + * protection requirement in the large page. */ - new_prot = static_protections(req_prot, address, pfn, 1, CPA_DETECT); - pfn = old_pfn; - for (i = 0, addr = lpaddr; i < numpages; i++, addr += PAGE_SIZE, pfn++) { - chk_prot = static_protections(req_prot, addr, pfn, 1, - CPA_DETECT); - cpa_inc_4k_checked(); - if (pgprot_val(chk_prot) != pgprot_val(new_prot)) - return 1; - } - - /* If there are no changes, return. */ - if (pgprot_val(new_prot) == pgprot_val(old_prot)) { - cpa_inc_lp_sameprot(level); - return 0; - } + new_prot = static_protections(req_prot, lpaddr, old_pfn, numpages, + CPA_DETECT); /* - * Verify that the address is aligned and the number of pages - * covers the full page. + * If there is a conflict, split the large page. + * + * There used to be a 4k wise evaluation trying really hard to + * preserve the large pages, but experimentation has shown, that this + * does not help at all. There might be corner cases which would + * preserve one large page occasionally, but it's really not worth the + * extra code and cycles for the common case. */ - if (address != lpaddr || cpa->numpages != numpages) + if (pgprot_val(req_prot) != pgprot_val(new_prot)) return 1; -setlp: /* All checks passed. Update the large page mapping. */ new_pte = pfn_pte(old_pfn, new_prot); __set_pmd_pte(kpte, address, new_pte);