[PATCH RFC 08/18] x86/mm/pat: use cpa_split_data structure to pass split parameters
Mike Rapoport (Microsoft)
rppt at kernel.org
Tue Jul 21 09:23:31 PDT 2026
Keeping all split parameters in a struct between
should_split_large_page() and split_large_page() allows maintaining the
split state that is initially established in cpa_handle_large_page(),
then this state is updated in should_split_large_page() and finally
consumed by split_large_page().
Start passing parameters between should_split_large_page() and
split_large_page() in cpa_split_data structure.
As the first step only pass the existing parameters in the new
structure.
No functional change intended.
Assisted-by: Copilot:claude-opus-4.8
Signed-off-by: Mike Rapoport (Microsoft) <rppt at kernel.org>
---
arch/x86/mm/pat/set_memory.c | 49 ++++++++++++++++++++++++++++----------------
1 file changed, 31 insertions(+), 18 deletions(-)
diff --git a/arch/x86/mm/pat/set_memory.c b/arch/x86/mm/pat/set_memory.c
index a9d270e986ff..c2a72cd8b832 100644
--- a/arch/x86/mm/pat/set_memory.c
+++ b/arch/x86/mm/pat/set_memory.c
@@ -53,6 +53,15 @@ struct cpa_data {
struct page **pages;
};
+/*
+ * context for checking for a split a large page and splitting it if required.
+ */
+struct cpa_split_data {
+ unsigned long address;
+ pte_t *kpte;
+ struct ptdesc *ptdesc;
+};
+
enum cpa_warn {
CPA_CONFLICT,
CPA_PROTECT,
@@ -869,12 +878,14 @@ static pgprot_t pgprot_clear_protnone_bits(pgprot_t prot)
return prot;
}
-static int __should_split_large_page(pte_t *kpte, unsigned long address,
- struct cpa_data *cpa)
+static int __should_split_large_page(struct cpa_data *cpa,
+ struct cpa_split_data *sd)
{
unsigned long numpages, pmask, psize, lpaddr, pfn, old_pfn;
pgprot_t old_prot, new_prot, req_prot, chk_prot;
+ unsigned long address = sd->address;
enum pgtable_level level;
+ pte_t *kpte = sd->kpte;
pte_t new_pte, *tmp;
bool nx, rw;
@@ -1016,8 +1027,8 @@ static int __should_split_large_page(pte_t *kpte, unsigned long address,
return 0;
}
-static int should_split_large_page(pte_t *kpte, unsigned long address,
- struct cpa_data *cpa)
+static int should_split_large_page(struct cpa_data *cpa,
+ struct cpa_split_data *sd)
{
int do_split;
@@ -1025,7 +1036,7 @@ static int should_split_large_page(pte_t *kpte, unsigned long address,
return 1;
spin_lock(&pgd_lock);
- do_split = __should_split_large_page(kpte, address, cpa);
+ do_split = __should_split_large_page(cpa, sd);
spin_unlock(&pgd_lock);
return do_split;
@@ -1067,13 +1078,14 @@ static void split_set_pte(struct cpa_data *cpa, pte_t *pte, unsigned long pfn,
set_pte(pte, pfn_pte(pfn, ref_prot));
}
-static int
-__split_large_page(struct cpa_data *cpa, pte_t *kpte, unsigned long address,
- struct ptdesc *ptdesc)
+static int __split_large_page(struct cpa_data *cpa, struct cpa_split_data *sd)
{
unsigned long lpaddr, lpinc, ref_pfn, pfn, pfninc = 1;
+ struct ptdesc *ptdesc = sd->ptdesc;
struct page *base = ptdesc_page(ptdesc);
pte_t *pbase = (pte_t *)page_address(base);
+ unsigned long address = sd->address;
+ pte_t *kpte = sd->kpte;
unsigned int i, level;
pgprot_t ref_prot;
bool nx, rw;
@@ -1174,19 +1186,16 @@ __split_large_page(struct cpa_data *cpa, pte_t *kpte, unsigned long address,
return 0;
}
-static int split_large_page(struct cpa_data *cpa, pte_t *kpte,
- unsigned long address)
+static int split_large_page(struct cpa_data *cpa, struct cpa_split_data *sd)
{
- struct ptdesc *ptdesc;
-
spin_unlock(&cpa_lock);
- ptdesc = pagetable_alloc(GFP_KERNEL, 0);
+ sd->ptdesc = pagetable_alloc(GFP_KERNEL, 0);
spin_lock(&cpa_lock);
- if (!ptdesc)
+ if (!sd->ptdesc)
return -ENOMEM;
- if (__split_large_page(cpa, kpte, address, ptdesc))
- pagetable_free(ptdesc);
+ if (__split_large_page(cpa, sd))
+ pagetable_free(sd->ptdesc);
return 0;
}
@@ -1194,13 +1203,17 @@ static int split_large_page(struct cpa_data *cpa, pte_t *kpte,
static int cpa_handle_large_page(struct cpa_data *cpa, pte_t *kpte,
unsigned long address)
{
+ struct cpa_split_data sd = {
+ .address = address,
+ .kpte = kpte,
+ };
int do_split, err;
/*
* Check, whether we can keep the large page intact
* and just change the pte:
*/
- do_split = should_split_large_page(kpte, address, cpa);
+ do_split = should_split_large_page(cpa, &sd);
/*
* When the range fits into the existing large page, no split is
* required.
@@ -1213,7 +1226,7 @@ static int cpa_handle_large_page(struct cpa_data *cpa, pte_t *kpte,
/*
* We have to split the large page:
*/
- err = split_large_page(cpa, kpte, address);
+ err = split_large_page(cpa, &sd);
if (err)
return err;
--
2.53.0
More information about the linux-riscv
mailing list