diff options
author | Peter Zijlstra <peterz@infradead.org> | 2018-12-03 12:03:50 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2018-12-17 12:54:27 -0500 |
commit | 83b4e39146aa70913580966e0f2b78b7c3492760 (patch) | |
tree | 9e05cc0576a9bfb239380d40c48abfb281bd1e59 | |
parent | 935f5839827ef54b53406e80906f7c355eb73c1b (diff) |
x86/mm/cpa: Make cpa_data::numpages invariant
Make sure __change_page_attr_set_clr() doesn't modify cpa->numpages.
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Rik van Riel <riel@surriel.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Tom.StDenis@amd.com
Cc: dave.hansen@intel.com
Link: http://lkml.kernel.org/r/20181203171043.493000228@infradead.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r-- | arch/x86/mm/pageattr.c | 21 |
1 files changed, 13 insertions, 8 deletions
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index 351874259a71..12b69263e501 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c | |||
@@ -1625,14 +1625,15 @@ static int cpa_process_alias(struct cpa_data *cpa) | |||
1625 | static int __change_page_attr_set_clr(struct cpa_data *cpa, int checkalias) | 1625 | static int __change_page_attr_set_clr(struct cpa_data *cpa, int checkalias) |
1626 | { | 1626 | { |
1627 | unsigned long numpages = cpa->numpages; | 1627 | unsigned long numpages = cpa->numpages; |
1628 | int ret; | 1628 | unsigned long rempages = numpages; |
1629 | int ret = 0; | ||
1629 | 1630 | ||
1630 | while (numpages) { | 1631 | while (rempages) { |
1631 | /* | 1632 | /* |
1632 | * Store the remaining nr of pages for the large page | 1633 | * Store the remaining nr of pages for the large page |
1633 | * preservation check. | 1634 | * preservation check. |
1634 | */ | 1635 | */ |
1635 | cpa->numpages = numpages; | 1636 | cpa->numpages = rempages; |
1636 | /* for array changes, we can't use large page */ | 1637 | /* for array changes, we can't use large page */ |
1637 | if (cpa->flags & (CPA_ARRAY | CPA_PAGES_ARRAY)) | 1638 | if (cpa->flags & (CPA_ARRAY | CPA_PAGES_ARRAY)) |
1638 | cpa->numpages = 1; | 1639 | cpa->numpages = 1; |
@@ -1643,12 +1644,12 @@ static int __change_page_attr_set_clr(struct cpa_data *cpa, int checkalias) | |||
1643 | if (!debug_pagealloc_enabled()) | 1644 | if (!debug_pagealloc_enabled()) |
1644 | spin_unlock(&cpa_lock); | 1645 | spin_unlock(&cpa_lock); |
1645 | if (ret) | 1646 | if (ret) |
1646 | return ret; | 1647 | goto out; |
1647 | 1648 | ||
1648 | if (checkalias) { | 1649 | if (checkalias) { |
1649 | ret = cpa_process_alias(cpa); | 1650 | ret = cpa_process_alias(cpa); |
1650 | if (ret) | 1651 | if (ret) |
1651 | return ret; | 1652 | goto out; |
1652 | } | 1653 | } |
1653 | 1654 | ||
1654 | /* | 1655 | /* |
@@ -1656,11 +1657,15 @@ static int __change_page_attr_set_clr(struct cpa_data *cpa, int checkalias) | |||
1656 | * CPA operation. Either a large page has been | 1657 | * CPA operation. Either a large page has been |
1657 | * preserved or a single page update happened. | 1658 | * preserved or a single page update happened. |
1658 | */ | 1659 | */ |
1659 | BUG_ON(cpa->numpages > numpages || !cpa->numpages); | 1660 | BUG_ON(cpa->numpages > rempages || !cpa->numpages); |
1660 | numpages -= cpa->numpages; | 1661 | rempages -= cpa->numpages; |
1661 | cpa->curpage += cpa->numpages; | 1662 | cpa->curpage += cpa->numpages; |
1662 | } | 1663 | } |
1663 | return 0; | 1664 | |
1665 | out: | ||
1666 | /* Restore the original numpages */ | ||
1667 | cpa->numpages = numpages; | ||
1668 | return ret; | ||
1664 | } | 1669 | } |
1665 | 1670 | ||
1666 | /* | 1671 | /* |