|
@@ -299,6 +299,27 @@ pti_clone_pmds(unsigned long start, unsigned long end, pmdval_t clear)
|
|
if (WARN_ON(!target_pmd))
|
|
if (WARN_ON(!target_pmd))
|
|
return;
|
|
return;
|
|
|
|
|
|
|
|
+ /*
|
|
|
|
+ * Only clone present PMDs. This ensures only setting
|
|
|
|
+ * _PAGE_GLOBAL on present PMDs. This should only be
|
|
|
|
+ * called on well-known addresses anyway, so a non-
|
|
|
|
+ * present PMD would be a surprise.
|
|
|
|
+ */
|
|
|
|
+ if (WARN_ON(!(pmd_flags(*pmd) & _PAGE_PRESENT)))
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * Setting 'target_pmd' below creates a mapping in both
|
|
|
|
+ * the user and kernel page tables. It is effectively
|
|
|
|
+ * global, so set it as global in both copies. Note:
|
|
|
|
+ * the X86_FEATURE_PGE check is not _required_ because
|
|
|
|
+ * the CPU ignores _PAGE_GLOBAL when PGE is not
|
|
|
|
+ * supported. The check keeps consistentency with
|
|
|
|
+ * code that only set this bit when supported.
|
|
|
|
+ */
|
|
|
|
+ if (boot_cpu_has(X86_FEATURE_PGE))
|
|
|
|
+ *pmd = pmd_set_flags(*pmd, _PAGE_GLOBAL);
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* Copy the PMD. That is, the kernelmode and usermode
|
|
* Copy the PMD. That is, the kernelmode and usermode
|
|
* tables will share the last-level page tables of this
|
|
* tables will share the last-level page tables of this
|
|
@@ -348,7 +369,7 @@ static void __init pti_clone_entry_text(void)
|
|
{
|
|
{
|
|
pti_clone_pmds((unsigned long) __entry_text_start,
|
|
pti_clone_pmds((unsigned long) __entry_text_start,
|
|
(unsigned long) __irqentry_text_end,
|
|
(unsigned long) __irqentry_text_end,
|
|
- _PAGE_RW | _PAGE_GLOBAL);
|
|
|
|
|
|
+ _PAGE_RW);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|