Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1593378

[PATCHv4 16/33] x86/mm/pat: handle additional page table

From "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>
Newsgroups linux.kernel
Subject [PATCHv4 16/33] x86/mm/pat: handle additional page table
Date 2017-03-06 15:10 +0100
Message-ID <ti1uP-Rx-65@gated-at.bofh.it> (permalink)
References <ti1l7-yB-3@gated-at.bofh.it>
Organization linux.* mail to news gateway

Show all headers | View raw


Straight-forward extension of existing code to support additional page
table level.

Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
---
 arch/x86/mm/pageattr.c | 56 ++++++++++++++++++++++++++++++++++++--------------
 1 file changed, 41 insertions(+), 15 deletions(-)

diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
index 28d42130243c..eb0ad12cdfde 100644
--- a/arch/x86/mm/pageattr.c
+++ b/arch/x86/mm/pageattr.c
@@ -346,6 +346,7 @@ static inline pgprot_t static_protections(pgprot_t prot, unsigned long address,
 pte_t *lookup_address_in_pgd(pgd_t *pgd, unsigned long address,
 			     unsigned int *level)
 {
+	p4d_t *p4d;
 	pud_t *pud;
 	pmd_t *pmd;
 
@@ -354,7 +355,15 @@ pte_t *lookup_address_in_pgd(pgd_t *pgd, unsigned long address,
 	if (pgd_none(*pgd))
 		return NULL;
 
-	pud = pud_offset(pgd, address);
+	p4d = p4d_offset(pgd, address);
+	if (p4d_none(*p4d))
+		return NULL;
+
+	*level = PG_LEVEL_512G;
+	if (p4d_large(*p4d) || !p4d_present(*p4d))
+		return (pte_t *)p4d;
+
+	pud = pud_offset(p4d, address);
 	if (pud_none(*pud))
 		return NULL;
 
@@ -406,13 +415,18 @@ static pte_t *_lookup_address_cpa(struct cpa_data *cpa, unsigned long address,
 pmd_t *lookup_pmd_address(unsigned long address)
 {
 	pgd_t *pgd;
+	p4d_t *p4d;
 	pud_t *pud;
 
 	pgd = pgd_offset_k(address);
 	if (pgd_none(*pgd))
 		return NULL;
 
-	pud = pud_offset(pgd, address);
+	p4d = p4d_offset(pgd, address);
+	if (p4d_none(*p4d) || p4d_large(*p4d) || !p4d_present(*p4d))
+		return NULL;
+
+	pud = pud_offset(p4d, address);
 	if (pud_none(*pud) || pud_large(*pud) || !pud_present(*pud))
 		return NULL;
 
@@ -477,11 +491,13 @@ static void __set_pmd_pte(pte_t *kpte, unsigned long address, pte_t pte)
 
 		list_for_each_entry(page, &pgd_list, lru) {
 			pgd_t *pgd;
+			p4d_t *p4d;
 			pud_t *pud;
 			pmd_t *pmd;
 
 			pgd = (pgd_t *)page_address(page) + pgd_index(address);
-			pud = pud_offset(pgd, address);
+			p4d = p4d_offset(pgd, address);
+			pud = pud_offset(p4d, address);
 			pmd = pmd_offset(pud, address);
 			set_pte_atomic((pte_t *)pmd, pte);
 		}
@@ -836,9 +852,9 @@ static void unmap_pmd_range(pud_t *pud, unsigned long start, unsigned long end)
 			pud_clear(pud);
 }
 
-static void unmap_pud_range(pgd_t *pgd, unsigned long start, unsigned long end)
+static void unmap_pud_range(p4d_t *p4d, unsigned long start, unsigned long end)
 {
-	pud_t *pud = pud_offset(pgd, start);
+	pud_t *pud = pud_offset(p4d, start);
 
 	/*
 	 * Not on a GB page boundary?
@@ -1004,8 +1020,8 @@ static long populate_pmd(struct cpa_data *cpa,
 	return num_pages;
 }
 
-static long populate_pud(struct cpa_data *cpa, unsigned long start, pgd_t *pgd,
-			 pgprot_t pgprot)
+static int populate_pud(struct cpa_data *cpa, unsigned long start, p4d_t *p4d,
+			pgprot_t pgprot)
 {
 	pud_t *pud;
 	unsigned long end;
@@ -1026,7 +1042,7 @@ static long populate_pud(struct cpa_data *cpa, unsigned long start, pgd_t *pgd,
 		cur_pages = (pre_end - start) >> PAGE_SHIFT;
 		cur_pages = min_t(int, (int)cpa->numpages, cur_pages);
 
-		pud = pud_offset(pgd, start);
+		pud = pud_offset(p4d, start);
 
 		/*
 		 * Need a PMD page?
@@ -1047,7 +1063,7 @@ static long populate_pud(struct cpa_data *cpa, unsigned long start, pgd_t *pgd,
 	if (cpa->numpages == cur_pages)
 		return cur_pages;
 
-	pud = pud_offset(pgd, start);
+	pud = pud_offset(p4d, start);
 	pud_pgprot = pgprot_4k_2_large(pgprot);
 
 	/*
@@ -1067,7 +1083,7 @@ static long populate_pud(struct cpa_data *cpa, unsigned long start, pgd_t *pgd,
 	if (start < end) {
 		long tmp;
 
-		pud = pud_offset(pgd, start);
+		pud = pud_offset(p4d, start);
 		if (pud_none(*pud))
 			if (alloc_pmd_page(pud))
 				return -1;
@@ -1090,33 +1106,43 @@ static int populate_pgd(struct cpa_data *cpa, unsigned long addr)
 {
 	pgprot_t pgprot = __pgprot(_KERNPG_TABLE);
 	pud_t *pud = NULL;	/* shut up gcc */
+	p4d_t *p4d;
 	pgd_t *pgd_entry;
 	long ret;
 
 	pgd_entry = cpa->pgd + pgd_index(addr);
 
+	if (pgd_none(*pgd_entry)) {
+		p4d = (p4d_t *)get_zeroed_page(GFP_KERNEL | __GFP_NOTRACK);
+		if (!p4d)
+			return -1;
+
+		set_pgd(pgd_entry, __pgd(__pa(p4d) | _KERNPG_TABLE));
+	}
+
 	/*
-	 * Allocate a PUD page and hand it down for mapping.
+	 * Allocate a P4D page and hand it down for mapping.
 	 */
-	if (pgd_none(*pgd_entry)) {
+	p4d = p4d_offset(pgd_entry, addr);
+	if (p4d_none(*p4d)) {
 		pud = (pud_t *)get_zeroed_page(GFP_KERNEL | __GFP_NOTRACK);
 		if (!pud)
 			return -1;
 
-		set_pgd(pgd_entry, __pgd(__pa(pud) | _KERNPG_TABLE));
+		set_p4d(p4d, __p4d(__pa(pud) | _KERNPG_TABLE));
 	}
 
 	pgprot_val(pgprot) &= ~pgprot_val(cpa->mask_clr);
 	pgprot_val(pgprot) |=  pgprot_val(cpa->mask_set);
 
-	ret = populate_pud(cpa, addr, pgd_entry, pgprot);
+	ret = populate_pud(cpa, addr, p4d, pgprot);
 	if (ret < 0) {
 		/*
 		 * 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,
+		unmap_pud_range(p4d, addr,
 				addr + (cpa->numpages << PAGE_SHIFT));
 		return ret;
 	}
-- 
2.11.0

Back to linux.kernel | Previous | NextPrevious in thread | Next in thread | Find similar | Unroll thread


Thread

[PATCHv4 00/33] 5-level paging "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com> - 2017-03-06 15:10 +0100
  [PATCHv4 01/33] x86/cpufeature: Add 5-level paging detection "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com> - 2017-03-06 15:10 +0100
  [PATCHv4 14/33] x86/kexec: support p4d_t "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com> - 2017-03-06 15:10 +0100
  [PATCHv4 18/33] x86/xen: convert __xen_pgd_walk() and xen_cleanmfnmap() to support p4d "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com> - 2017-03-06 15:10 +0100
    Re: [PATCHv4 18/33] x86/xen: convert __xen_pgd_walk() and  xen_cleanmfnmap() to support p4d Boris Ostrovsky <boris.ostrovsky@oracle.com> - 2017-03-06 21:50 +0100
      Re: [PATCHv4 18/33] x86/xen: convert __xen_pgd_walk() and  xen_cleanmfnmap() to support p4d "Kirill A. Shutemov" <kirill@shutemov.name> - 2017-03-07 14:10 +0100
        Re: [PATCHv4 18/33] x86/xen: convert __xen_pgd_walk() and  xen_cleanmfnmap() to support p4d Boris Ostrovsky <boris.ostrovsky@oracle.com> - 2017-03-07 19:20 +0100
          Re: [Xen-devel] [PATCHv4 18/33] x86/xen: convert __xen_pgd_walk() and  xen_cleanmfnmap() to support p4d Andrew Cooper <andrew.cooper3@citrix.com> - 2017-03-07 19:30 +0100
            Re: [Xen-devel] [PATCHv4 18/33] x86/xen: convert __xen_pgd_walk() and  xen_cleanmfnmap() to support p4d Boris Ostrovsky <boris.ostrovsky@oracle.com> - 2017-03-07 20:30 +0100
  [PATCHv4 30/33] x86/mm: make kernel_physical_mapping_init() support 5-level paging "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com> - 2017-03-06 15:10 +0100
  [PATCHv4 21/33] x86/asm: remove __VIRTUAL_MASK_SHIFT==47 assert "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com> - 2017-03-06 15:10 +0100
  [PATCHv4 08/33] x86: basic changes into headers for 5-level paging "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com> - 2017-03-06 15:10 +0100
  [PATCHv4 16/33] x86/mm/pat: handle additional page table "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com> - 2017-03-06 15:10 +0100
  [PATCHv4 05/33] asm-generic: introduce <asm-generic/pgtable-nop4d.h> "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com> - 2017-03-06 15:10 +0100
  [PATCHv4 15/33] x86/efi: handle p4d in EFI pagetables "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com> - 2017-03-06 15:10 +0100
  [PATCHv4 19/33] x86: convert the rest of the code to support p4d_t "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com> - 2017-03-06 15:10 +0100
  [PATCHv4 20/33] x86: detect 5-level paging support "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com> - 2017-03-06 15:10 +0100
  [PATCHv4 07/33] mm: introduce __p4d_alloc() "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com> - 2017-03-06 15:10 +0100
  [PATCHv4 27/33] x86/espfix: support 5-level paging "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com> - 2017-03-06 15:10 +0100
  [PATCHv4 13/33] x86/power: support p4d_t in hibernate code "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com> - 2017-03-06 15:10 +0100
  [PATCHv4 02/33] asm-generic: introduce 5level-fixup.h "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com> - 2017-03-06 15:20 +0100
  Re: [PATCHv4 00/33] 5-level paging Linus Torvalds <torvalds@linux-foundation.org> - 2017-03-06 19:40 +0100
    Re: [PATCHv4 00/33] 5-level paging Thomas Gleixner <tglx@linutronix.de> - 2017-03-06 19:50 +0100
      Re: [PATCHv4 00/33] 5-level paging Linus Torvalds <torvalds@linux-foundation.org> - 2017-03-06 20:10 +0100
        Re: [PATCHv4 00/33] 5-level paging "Kirill A. Shutemov" <kirill@shutemov.name> - 2017-03-06 20:10 +0100
          Re: [PATCHv4 00/33] 5-level paging Linus Torvalds <torvalds@linux-foundation.org> - 2017-03-06 20:50 +0100
      Re: [PATCHv4 00/33] 5-level paging Stephen Rothwell <sfr@canb.auug.org.au> - 2017-03-07 02:30 +0100
        Re: [PATCHv4 00/33] 5-level paging Thomas Gleixner <tglx@linutronix.de> - 2017-03-07 11:20 +0100

csiph-web