[RFC, PATCHv1 24/28] x86/mm: add sync_global_pgds() for configuration with 5-level paging

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This basically restores slightly modified version of original
sync_global_pgds() which we had before foldedl p4d was introduced.

The only modification is protection against 'address' overflow.

Signed-off-by: Kirill A. Shutemov <kirill.shutemov@xxxxxxxxxxxxxxx>
---
 arch/x86/mm/init_64.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 47 insertions(+)

diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
index a991f5c4c2c4..d637893ac8c2 100644
--- a/arch/x86/mm/init_64.c
+++ b/arch/x86/mm/init_64.c
@@ -92,6 +92,52 @@ __setup("noexec32=", nonx32_setup);
  * When memory was added/removed make sure all the processes MM have
  * suitable PGD entries in the local PGD level page.
  */
+#ifdef CONFIG_X86_5LEVEL
+void sync_global_pgds(unsigned long start, unsigned long end, int removed)
+{
+        unsigned long address;
+
+	for (address = start; address <= end && address >= start;
+			address += PGDIR_SIZE) {
+                const pgd_t *pgd_ref = pgd_offset_k(address);
+                struct page *page;
+
+                /*
+                 * When it is called after memory hot remove, pgd_none()
+                 * returns true. In this case (removed == 1), we must clear
+                 * the PGD entries in the local PGD level page.
+                 */
+                if (pgd_none(*pgd_ref) && !removed)
+                        continue;
+
+                spin_lock(&pgd_lock);
+                list_for_each_entry(page, &pgd_list, lru) {
+                        pgd_t *pgd;
+                        spinlock_t *pgt_lock;
+
+                        pgd = (pgd_t *)page_address(page) + pgd_index(address);
+                        /* the pgt_lock only for Xen */
+                        pgt_lock = &pgd_page_get_mm(page)->page_table_lock;
+                        spin_lock(pgt_lock);
+
+                        if (!pgd_none(*pgd_ref) && !pgd_none(*pgd))
+                                BUG_ON(pgd_page_vaddr(*pgd)
+                                       != pgd_page_vaddr(*pgd_ref));
+
+                        if (removed) {
+                                if (pgd_none(*pgd_ref) && !pgd_none(*pgd))
+                                        pgd_clear(pgd);
+                        } else {
+                                if (pgd_none(*pgd))
+                                        set_pgd(pgd, *pgd_ref);
+                        }
+
+                        spin_unlock(pgt_lock);
+                }
+                spin_unlock(&pgd_lock);
+        }
+}
+#else
 void sync_global_pgds(unsigned long start, unsigned long end, int removed)
 {
 	unsigned long address;
@@ -145,6 +191,7 @@ void sync_global_pgds(unsigned long start, unsigned long end, int removed)
 		spin_unlock(&pgd_lock);
 	}
 }
+#endif
 
 /*
  * NOTE: This function is marked __ref because it calls __init function
-- 
2.10.2

--
To unsubscribe from this list: send the line "unsubscribe linux-arch" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Kernel]     [Kernel Newbies]     [x86 Platform Driver]     [Netdev]     [Linux Wireless]     [Netfilter]     [Bugtraq]     [Linux Filesystems]     [Yosemite Discussion]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Device Mapper]

  Powered by Linux