All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] x86: Fix overlap of i386 CPU_ENTRY_AREA with FIX_BTMAP
@ 2018-01-30 11:22 William Grant
  2018-01-30 13:10 ` Thomas Gleixner
  2018-01-30 14:48 ` [tip:x86/pti] x86/mm: " tip-bot for William Grant
  0 siblings, 2 replies; 3+ messages in thread
From: William Grant @ 2018-01-30 11:22 UTC (permalink / raw)
  To: Thomas Gleixner, Ingo Molnar, H. Peter Anvin, x86
  Cc: linux-kernel, William Grant

Since commit 92a0f81d8957 ("x86/cpu_entry_area: Move it out of the
fixmap"), i386's CPU_ENTRY_AREA has been mapped to the memory area just
below FIXADDR_START. But already immediately before FIXADDR_START is the
FIX_BTMAP area, which means that early_ioremap can collide with the
entry area.

It's especially bad on PAE where FIX_BTMAP_BEGIN gets aligned to exactly
match CPU_ENTRY_AREA_BASE, so the first early_ioremap slot clobbers the
IDT and causes interrupts during early boot to reset the system.

The overlap wasn't a problem before the CPU entry area was introduced,
as the fixmap has classically been preceded by the pkmap or vmalloc
areas, neither of which is used until early_ioremap is out of the
picture.

Relocate CPU_ENTRY_AREA to below FIX_BTMAP, not just below the permanent
fixmap area.

Signed-off-by: William Grant <william.grant@canonical.com>
---
This fixes a triple fault during early boot of 4.15 with PAE on x86 when
an Intel IOMMU is present. The ACPI table retrieval inside pci_iommu_alloc()
called early_ioremap and unmapped the IDT, and so the exception inside
test_wp_bit triple faulted.

2MiB of i386 kernel address space is wasted in the FIX_BTMAP area that
isn't used after boot, but I couldn't see a better place to put
CPU_ENTRY_AREA. We can't stick it just before the pkmap, since pkmap
doesn't exist when highmem is disabled. We could potentially shift fixmap
down from the top of the address space, but that's already variable due to
reserve_top_address. The only other option would be to shuffle it in
between lowmem and vmalloc, which looks messy due to their variable sizes.

 arch/x86/include/asm/fixmap.h           | 6 ++++--
 arch/x86/include/asm/pgtable_32_types.h | 5 +++--
 2 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/arch/x86/include/asm/fixmap.h b/arch/x86/include/asm/fixmap.h
index 64c4a30e0d39..987020a28534 100644
--- a/arch/x86/include/asm/fixmap.h
+++ b/arch/x86/include/asm/fixmap.h
@@ -137,8 +137,10 @@ enum fixed_addresses {
 
 extern void reserve_top_address(unsigned long reserve);
 
-#define FIXADDR_SIZE	(__end_of_permanent_fixed_addresses << PAGE_SHIFT)
-#define FIXADDR_START	(FIXADDR_TOP - FIXADDR_SIZE)
+#define FIXADDR_SIZE        (__end_of_permanent_fixed_addresses << PAGE_SHIFT)
+#define FIXADDR_START       (FIXADDR_TOP - FIXADDR_SIZE)
+#define FIXADDR_ALL_SIZE    (__end_of_fixed_addresses << PAGE_SHIFT)
+#define FIXADDR_ALL_START   (FIXADDR_TOP - FIXADDR_ALL_SIZE)
 
 extern int fixmaps_set;
 
diff --git a/arch/x86/include/asm/pgtable_32_types.h b/arch/x86/include/asm/pgtable_32_types.h
index ce245b0cdfca..01973e9fd269 100644
--- a/arch/x86/include/asm/pgtable_32_types.h
+++ b/arch/x86/include/asm/pgtable_32_types.h
@@ -44,8 +44,9 @@ extern bool __vmalloc_start_set; /* set once high_memory is set */
  */
 #define CPU_ENTRY_AREA_PAGES	(NR_CPUS * 40)
 
-#define CPU_ENTRY_AREA_BASE				\
-	((FIXADDR_START - PAGE_SIZE * (CPU_ENTRY_AREA_PAGES + 1)) & PMD_MASK)
+#define CPU_ENTRY_AREA_BASE						\
+	((FIXADDR_ALL_START - PAGE_SIZE * (CPU_ENTRY_AREA_PAGES + 1))   \
+	 & PMD_MASK)
 
 #define PKMAP_BASE		\
 	((CPU_ENTRY_AREA_BASE - PAGE_SIZE) & PMD_MASK)
-- 
2.15.1

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH] x86: Fix overlap of i386 CPU_ENTRY_AREA with FIX_BTMAP
  2018-01-30 11:22 [PATCH] x86: Fix overlap of i386 CPU_ENTRY_AREA with FIX_BTMAP William Grant
@ 2018-01-30 13:10 ` Thomas Gleixner
  2018-01-30 14:48 ` [tip:x86/pti] x86/mm: " tip-bot for William Grant
  1 sibling, 0 replies; 3+ messages in thread
From: Thomas Gleixner @ 2018-01-30 13:10 UTC (permalink / raw)
  To: William Grant; +Cc: Ingo Molnar, H. Peter Anvin, x86, linux-kernel

On Tue, 30 Jan 2018, William Grant wrote:

> Since commit 92a0f81d8957 ("x86/cpu_entry_area: Move it out of the
> fixmap"), i386's CPU_ENTRY_AREA has been mapped to the memory area just
> below FIXADDR_START. But already immediately before FIXADDR_START is the
> FIX_BTMAP area, which means that early_ioremap can collide with the
> entry area.
> 
> It's especially bad on PAE where FIX_BTMAP_BEGIN gets aligned to exactly
> match CPU_ENTRY_AREA_BASE, so the first early_ioremap slot clobbers the
> IDT and causes interrupts during early boot to reset the system.
> 
> The overlap wasn't a problem before the CPU entry area was introduced,
> as the fixmap has classically been preceded by the pkmap or vmalloc
> areas, neither of which is used until early_ioremap is out of the
> picture.
> 
> Relocate CPU_ENTRY_AREA to below FIX_BTMAP, not just below the permanent
> fixmap area.

Nice catch. I'm sure I stared at that more than once....

Thanks,

	tglx

^ permalink raw reply	[flat|nested] 3+ messages in thread

* [tip:x86/pti] x86/mm: Fix overlap of i386 CPU_ENTRY_AREA with FIX_BTMAP
  2018-01-30 11:22 [PATCH] x86: Fix overlap of i386 CPU_ENTRY_AREA with FIX_BTMAP William Grant
  2018-01-30 13:10 ` Thomas Gleixner
@ 2018-01-30 14:48 ` tip-bot for William Grant
  1 sibling, 0 replies; 3+ messages in thread
From: tip-bot for William Grant @ 2018-01-30 14:48 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: hpa, mingo, tglx, william.grant, linux-kernel

Commit-ID:  55f49fcb879fbeebf2a8c1ac7c9e6d90df55f798
Gitweb:     https://git.kernel.org/tip/55f49fcb879fbeebf2a8c1ac7c9e6d90df55f798
Author:     William Grant <william.grant@canonical.com>
AuthorDate: Tue, 30 Jan 2018 22:22:55 +1100
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Tue, 30 Jan 2018 15:30:35 +0100

x86/mm: Fix overlap of i386 CPU_ENTRY_AREA with FIX_BTMAP

Since commit 92a0f81d8957 ("x86/cpu_entry_area: Move it out of the
fixmap"), i386's CPU_ENTRY_AREA has been mapped to the memory area just
below FIXADDR_START. But already immediately before FIXADDR_START is the
FIX_BTMAP area, which means that early_ioremap can collide with the entry
area.

It's especially bad on PAE where FIX_BTMAP_BEGIN gets aligned to exactly
match CPU_ENTRY_AREA_BASE, so the first early_ioremap slot clobbers the
IDT and causes interrupts during early boot to reset the system.

The overlap wasn't a problem before the CPU entry area was introduced,
as the fixmap has classically been preceded by the pkmap or vmalloc
areas, neither of which is used until early_ioremap is out of the
picture.

Relocate CPU_ENTRY_AREA to below FIX_BTMAP, not just below the permanent
fixmap area.

Fixes: commit 92a0f81d8957 ("x86/cpu_entry_area: Move it out of the fixmap")
Signed-off-by: William Grant <william.grant@canonical.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: stable@vger.kernel.org
Link: https://lkml.kernel.org/r/7041d181-a019-e8b9-4e4e-48215f841e2c@canonical.com

---
 arch/x86/include/asm/fixmap.h           | 6 ++++--
 arch/x86/include/asm/pgtable_32_types.h | 5 +++--
 2 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/arch/x86/include/asm/fixmap.h b/arch/x86/include/asm/fixmap.h
index 64c4a30..e203169 100644
--- a/arch/x86/include/asm/fixmap.h
+++ b/arch/x86/include/asm/fixmap.h
@@ -137,8 +137,10 @@ enum fixed_addresses {
 
 extern void reserve_top_address(unsigned long reserve);
 
-#define FIXADDR_SIZE	(__end_of_permanent_fixed_addresses << PAGE_SHIFT)
-#define FIXADDR_START	(FIXADDR_TOP - FIXADDR_SIZE)
+#define FIXADDR_SIZE		(__end_of_permanent_fixed_addresses << PAGE_SHIFT)
+#define FIXADDR_START		(FIXADDR_TOP - FIXADDR_SIZE)
+#define FIXADDR_TOT_SIZE	(__end_of_fixed_addresses << PAGE_SHIFT)
+#define FIXADDR_TOT_START	(FIXADDR_TOP - FIXADDR_TOT_SIZE)
 
 extern int fixmaps_set;
 
diff --git a/arch/x86/include/asm/pgtable_32_types.h b/arch/x86/include/asm/pgtable_32_types.h
index ce245b0..0777e18 100644
--- a/arch/x86/include/asm/pgtable_32_types.h
+++ b/arch/x86/include/asm/pgtable_32_types.h
@@ -44,8 +44,9 @@ extern bool __vmalloc_start_set; /* set once high_memory is set */
  */
 #define CPU_ENTRY_AREA_PAGES	(NR_CPUS * 40)
 
-#define CPU_ENTRY_AREA_BASE				\
-	((FIXADDR_START - PAGE_SIZE * (CPU_ENTRY_AREA_PAGES + 1)) & PMD_MASK)
+#define CPU_ENTRY_AREA_BASE						\
+	((FIXADDR_TOT_START - PAGE_SIZE * (CPU_ENTRY_AREA_PAGES + 1))   \
+	 & PMD_MASK)
 
 #define PKMAP_BASE		\
 	((CPU_ENTRY_AREA_BASE - PAGE_SIZE) & PMD_MASK)

^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2018-01-30 14:50 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-01-30 11:22 [PATCH] x86: Fix overlap of i386 CPU_ENTRY_AREA with FIX_BTMAP William Grant
2018-01-30 13:10 ` Thomas Gleixner
2018-01-30 14:48 ` [tip:x86/pti] x86/mm: " tip-bot for William Grant

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.