| From pasha.tatashin@oracle.com Mon Jan 15 18:48:49 2018 |
| From: Pavel Tatashin <pasha.tatashin@oracle.com> |
| Date: Mon, 15 Jan 2018 11:44:14 -0500 |
| Subject: x86/pti/efi: broken conversion from efi to kernel page table |
| To: steven.sistare@oracle.com, linux-kernel@vger.kernel.org, tglx@linutronix.de, mingo@redhat.com, hpa@zytor.com, x86@kernel.org, gregkh@linuxfoundation.org, jkosina@suse.cz, hughd@google.com, dave.hansen@linux.intel.com, luto@kernel.org, stable@vger.kernel.org |
| Message-ID: <20180115164414.19778-1-pasha.tatashin@oracle.com> |
| |
| From: Pavel Tatashin <pasha.tatashin@oracle.com> |
| |
| The page table order must be increased for EFI table in order to avoid a |
| bug where NMI tries to change the page table to kernel page table, while |
| efi page table is active. |
| |
| For more disccussion about this bug, see this thread: |
| http://lkml.iu.edu/hypermail/linux/kernel/1801.1/00951.html |
| |
| Signed-off-by: Pavel Tatashin <pasha.tatashin@oracle.com> |
| Reviewed-by: Steven Sistare <steven.sistare@oracle.com> |
| Acked-by: Jiri Kosina <jkosina@suse.cz> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| arch/x86/include/asm/pgalloc.h | 11 +++++++++++ |
| arch/x86/mm/pgtable.c | 7 ------- |
| arch/x86/platform/efi/efi_64.c | 2 +- |
| 3 files changed, 12 insertions(+), 8 deletions(-) |
| |
| Changelog: |
| v1 - v2: Fixed compiling warning |
| |
| --- a/arch/x86/include/asm/pgalloc.h |
| +++ b/arch/x86/include/asm/pgalloc.h |
| @@ -27,6 +27,17 @@ static inline void paravirt_release_pud( |
| */ |
| extern gfp_t __userpte_alloc_gfp; |
| |
| +#ifdef CONFIG_PAGE_TABLE_ISOLATION |
| +/* |
| + * Instead of one PGD, we acquire two PGDs. Being order-1, it is |
| + * both 8k in size and 8k-aligned. That lets us just flip bit 12 |
| + * in a pointer to swap between the two 4k halves. |
| + */ |
| +#define PGD_ALLOCATION_ORDER 1 |
| +#else |
| +#define PGD_ALLOCATION_ORDER 0 |
| +#endif |
| + |
| /* |
| * Allocate and free page tables. |
| */ |
| --- a/arch/x86/mm/pgtable.c |
| +++ b/arch/x86/mm/pgtable.c |
| @@ -345,13 +345,6 @@ static inline void _pgd_free(pgd_t *pgd) |
| } |
| #else |
| |
| -/* |
| - * Instead of one pgd, Kaiser acquires two pgds. Being order-1, it is |
| - * both 8k in size and 8k-aligned. That lets us just flip bit 12 |
| - * in a pointer to swap between the two 4k halves. |
| - */ |
| -#define PGD_ALLOCATION_ORDER kaiser_enabled |
| - |
| static inline pgd_t *_pgd_alloc(void) |
| { |
| return (pgd_t *)__get_free_pages(PGALLOC_GFP, PGD_ALLOCATION_ORDER); |
| --- a/arch/x86/platform/efi/efi_64.c |
| +++ b/arch/x86/platform/efi/efi_64.c |
| @@ -142,7 +142,7 @@ int __init efi_alloc_page_tables(void) |
| return 0; |
| |
| gfp_mask = GFP_KERNEL | __GFP_NOTRACK | __GFP_ZERO; |
| - efi_pgd = (pgd_t *)__get_free_page(gfp_mask); |
| + efi_pgd = (pgd_t *)__get_free_pages(gfp_mask, PGD_ALLOCATION_ORDER); |
| if (!efi_pgd) |
| return -ENOMEM; |
| |