|
@@ -4417,19 +4417,53 @@ static void clear_gigantic_page(struct page *page,
|
|
|
}
|
|
|
}
|
|
|
void clear_huge_page(struct page *page,
|
|
|
- unsigned long addr, unsigned int pages_per_huge_page)
|
|
|
+ unsigned long addr_hint, unsigned int pages_per_huge_page)
|
|
|
{
|
|
|
- int i;
|
|
|
+ int i, n, base, l;
|
|
|
+ unsigned long addr = addr_hint &
|
|
|
+ ~(((unsigned long)pages_per_huge_page << PAGE_SHIFT) - 1);
|
|
|
|
|
|
if (unlikely(pages_per_huge_page > MAX_ORDER_NR_PAGES)) {
|
|
|
clear_gigantic_page(page, addr, pages_per_huge_page);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
+ /* Clear sub-page to access last to keep its cache lines hot */
|
|
|
might_sleep();
|
|
|
- for (i = 0; i < pages_per_huge_page; i++) {
|
|
|
+ n = (addr_hint - addr) / PAGE_SIZE;
|
|
|
+ if (2 * n <= pages_per_huge_page) {
|
|
|
+ /* If sub-page to access in first half of huge page */
|
|
|
+ base = 0;
|
|
|
+ l = n;
|
|
|
+ /* Clear sub-pages at the end of huge page */
|
|
|
+ for (i = pages_per_huge_page - 1; i >= 2 * n; i--) {
|
|
|
+ cond_resched();
|
|
|
+ clear_user_highpage(page + i, addr + i * PAGE_SIZE);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ /* If sub-page to access in second half of huge page */
|
|
|
+ base = pages_per_huge_page - 2 * (pages_per_huge_page - n);
|
|
|
+ l = pages_per_huge_page - n;
|
|
|
+ /* Clear sub-pages at the begin of huge page */
|
|
|
+ for (i = 0; i < base; i++) {
|
|
|
+ cond_resched();
|
|
|
+ clear_user_highpage(page + i, addr + i * PAGE_SIZE);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ /*
|
|
|
+ * Clear remaining sub-pages in left-right-left-right pattern
|
|
|
+ * towards the sub-page to access
|
|
|
+ */
|
|
|
+ for (i = 0; i < l; i++) {
|
|
|
+ int left_idx = base + i;
|
|
|
+ int right_idx = base + 2 * l - 1 - i;
|
|
|
+
|
|
|
+ cond_resched();
|
|
|
+ clear_user_highpage(page + left_idx,
|
|
|
+ addr + left_idx * PAGE_SIZE);
|
|
|
cond_resched();
|
|
|
- clear_user_highpage(page + i, addr + i * PAGE_SIZE);
|
|
|
+ clear_user_highpage(page + right_idx,
|
|
|
+ addr + right_idx * PAGE_SIZE);
|
|
|
}
|
|
|
}
|
|
|
|