* [PATCH 0/4] Switch GHES ioremap_page_range() to use fixmap
@ 2017-11-06 18:44 James Morse
2017-11-06 18:44 ` [PATCH 1/4] ACPI / APEI: Replace ioremap_page_range() with fixmap James Morse
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: James Morse @ 2017-11-06 18:44 UTC (permalink / raw)
To: linux-arm-kernel
GHES is doing ioremap_page_range() in both NMI and irq context, neither
are safe as it may sleep to allocate intermediate levels of page table.
Replace the NMI/irq GHES_IOREMAP_PAGES to use a fixmap entry each.
After this nothing uses ghes_ioremap_area or arch_apei_flush_tlb_one(),
rip them out.
This hasn't been tested on a system with x86's NOTIFY_NMI. Any more
more testing would be welcome. These patches are (still) based on rc7.
Changes since RFC:
* Added #ifdefs around the entries in fixmap.h
* Added a paragraph about HAVE_ACPI_APEI to the commit message
* Merged the first three patches for improved history
I've tried to be clear with who-acked-what when merging the patches.
For reference, the arch-acks are here:
https://lkml.org/lkml/2017/11/2/254
https://lkml.org/lkml/2017/10/31/780
Thanks,
James Morse (4):
ACPI / APEI: Replace ioremap_page_range() with fixmap
ACPI / APEI: Remove ghes_ioremap_area
arm64: mm: Remove arch_apei_flush_tlb_one()
ACPI / APEI: Remove arch_apei_flush_tlb_one()
arch/arm64/include/asm/acpi.h | 12 ------
arch/arm64/include/asm/fixmap.h | 7 ++++
arch/arm64/mm/mmu.c | 4 ++
arch/x86/include/asm/fixmap.h | 6 +++
arch/x86/kernel/acpi/apei.c | 5 ---
drivers/acpi/apei/ghes.c | 84 +++++++++--------------------------------
include/acpi/apei.h | 1 -
7 files changed, 34 insertions(+), 85 deletions(-)
--
2.15.0.rc2
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 1/4] ACPI / APEI: Replace ioremap_page_range() with fixmap
2017-11-06 18:44 [PATCH 0/4] Switch GHES ioremap_page_range() to use fixmap James Morse
@ 2017-11-06 18:44 ` James Morse
2017-11-06 18:44 ` [PATCH 2/4] ACPI / APEI: Remove ghes_ioremap_area James Morse
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: James Morse @ 2017-11-06 18:44 UTC (permalink / raw)
To: linux-arm-kernel
Replace ghes_io{re,un}map_pfn_{nmi,irq}()s use of ioremap_page_range()
with __set_fixmap() as ioremap_page_range() may sleep to allocate a new
level of page-table, even if its passed an existing final-address to
use in the mapping.
The GHES driver can only be enabled for architectures that select
HAVE_ACPI_APEI: Add fixmap entries to both x86 and arm64.
clear_fixmap() does the TLB invalidation in __set_fixmap() for arm64
and __set_pte_vaddr() for x86. In each case its the same as the
respective arch_apei_flush_tlb_one().
CC: Qiang Zheng <zhengqiang10@huawei.com>
Reported-by: Fengguang Wu <fengguang.wu@intel.com>
Suggested-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: James Morse <james.morse@arm.com>
Reviewed-by: Borislav Petkov <bp@suse.de>
Tested-by: Tyler Baicar <tbaicar@codeaurora.org>
Tested-by: Toshi Kani <toshi.kani@hpe.com>
[ For the arm64 bits: ]
Acked-by: Will Deacon <will.deacon@arm.com>
[ For the x86 bits: ]
Acked-by: Ingo Molnar <mingo@kernel.org>
---
Changes since RFC:
* Added #ifdefs around the entries in fixmap.h
* Added a paragraph about HAVE_ACPI_APEI to the commit message
* Merged the first three patches for improved history,
arch/arm64/include/asm/fixmap.h | 7 +++++++
arch/x86/include/asm/fixmap.h | 6 ++++++
drivers/acpi/apei/ghes.c | 45 ++++++++++++++---------------------------
3 files changed, 28 insertions(+), 30 deletions(-)
diff --git a/arch/arm64/include/asm/fixmap.h b/arch/arm64/include/asm/fixmap.h
index caf86be815ba..4052ec39e8db 100644
--- a/arch/arm64/include/asm/fixmap.h
+++ b/arch/arm64/include/asm/fixmap.h
@@ -51,6 +51,13 @@ enum fixed_addresses {
FIX_EARLYCON_MEM_BASE,
FIX_TEXT_POKE0,
+
+#ifdef CONFIG_ACPI_APEI_GHES
+ /* Used for GHES mapping from assorted contexts */
+ FIX_APEI_GHES_IRQ,
+ FIX_APEI_GHES_NMI,
+#endif /* CONFIG_ACPI_APEI_GHES */
+
__end_of_permanent_fixed_addresses,
/*
diff --git a/arch/x86/include/asm/fixmap.h b/arch/x86/include/asm/fixmap.h
index dcd9fb55e679..b0c505fe9a95 100644
--- a/arch/x86/include/asm/fixmap.h
+++ b/arch/x86/include/asm/fixmap.h
@@ -104,6 +104,12 @@ enum fixed_addresses {
FIX_GDT_REMAP_BEGIN,
FIX_GDT_REMAP_END = FIX_GDT_REMAP_BEGIN + NR_CPUS - 1,
+#ifdef CONFIG_ACPI_APEI_GHES
+ /* Used for GHES mapping from assorted contexts */
+ FIX_APEI_GHES_IRQ,
+ FIX_APEI_GHES_NMI,
+#endif
+
__end_of_permanent_fixed_addresses,
/*
diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
index 3c3a37b8503b..f3269816b997 100644
--- a/drivers/acpi/apei/ghes.c
+++ b/drivers/acpi/apei/ghes.c
@@ -51,6 +51,7 @@
#include <acpi/actbl1.h>
#include <acpi/ghes.h>
#include <acpi/apei.h>
+#include <asm/fixmap.h>
#include <asm/tlbflush.h>
#include <ras/ras_event.h>
@@ -112,7 +113,7 @@ static DEFINE_MUTEX(ghes_list_mutex);
* Because the memory area used to transfer hardware error information
* from BIOS to Linux can be determined only in NMI, IRQ or timer
* handler, but general ioremap can not be used in atomic context, so
- * a special version of atomic ioremap is implemented for that.
+ * the fixmap is used instead.
*/
/*
@@ -126,8 +127,8 @@ static DEFINE_MUTEX(ghes_list_mutex);
/* virtual memory area for atomic ioremap */
static struct vm_struct *ghes_ioremap_area;
/*
- * These 2 spinlock is used to prevent atomic ioremap virtual memory
- * area from being mapped simultaneously.
+ * These 2 spinlocks are used to prevent the fixmap entries from being used
+ * simultaneously.
*/
static DEFINE_RAW_SPINLOCK(ghes_ioremap_lock_nmi);
static DEFINE_SPINLOCK(ghes_ioremap_lock_irq);
@@ -159,52 +160,36 @@ static void ghes_ioremap_exit(void)
static void __iomem *ghes_ioremap_pfn_nmi(u64 pfn)
{
- unsigned long vaddr;
phys_addr_t paddr;
pgprot_t prot;
- vaddr = (unsigned long)GHES_IOREMAP_NMI_PAGE(ghes_ioremap_area->addr);
-
paddr = pfn << PAGE_SHIFT;
prot = arch_apei_get_mem_attribute(paddr);
- ioremap_page_range(vaddr, vaddr + PAGE_SIZE, paddr, prot);
+ __set_fixmap(FIX_APEI_GHES_NMI, paddr, prot);
- return (void __iomem *)vaddr;
+ return (void __iomem *) fix_to_virt(FIX_APEI_GHES_NMI);
}
static void __iomem *ghes_ioremap_pfn_irq(u64 pfn)
{
- unsigned long vaddr, paddr;
+ unsigned long paddr;
pgprot_t prot;
- vaddr = (unsigned long)GHES_IOREMAP_IRQ_PAGE(ghes_ioremap_area->addr);
-
paddr = pfn << PAGE_SHIFT;
prot = arch_apei_get_mem_attribute(paddr);
+ __set_fixmap(FIX_APEI_GHES_IRQ, paddr, prot);
- ioremap_page_range(vaddr, vaddr + PAGE_SIZE, paddr, prot);
-
- return (void __iomem *)vaddr;
+ return (void __iomem *) fix_to_virt(FIX_APEI_GHES_IRQ);
}
-static void ghes_iounmap_nmi(void __iomem *vaddr_ptr)
+static void ghes_iounmap_nmi(void)
{
- unsigned long vaddr = (unsigned long __force)vaddr_ptr;
- void *base = ghes_ioremap_area->addr;
-
- BUG_ON(vaddr != (unsigned long)GHES_IOREMAP_NMI_PAGE(base));
- unmap_kernel_range_noflush(vaddr, PAGE_SIZE);
- arch_apei_flush_tlb_one(vaddr);
+ clear_fixmap(FIX_APEI_GHES_NMI);
}
-static void ghes_iounmap_irq(void __iomem *vaddr_ptr)
+static void ghes_iounmap_irq(void)
{
- unsigned long vaddr = (unsigned long __force)vaddr_ptr;
- void *base = ghes_ioremap_area->addr;
-
- BUG_ON(vaddr != (unsigned long)GHES_IOREMAP_IRQ_PAGE(base));
- unmap_kernel_range_noflush(vaddr, PAGE_SIZE);
- arch_apei_flush_tlb_one(vaddr);
+ clear_fixmap(FIX_APEI_GHES_IRQ);
}
static int ghes_estatus_pool_init(void)
@@ -360,10 +345,10 @@ static void ghes_copy_tofrom_phys(void *buffer, u64 paddr, u32 len,
paddr += trunk;
buffer += trunk;
if (in_nmi) {
- ghes_iounmap_nmi(vaddr);
+ ghes_iounmap_nmi();
raw_spin_unlock(&ghes_ioremap_lock_nmi);
} else {
- ghes_iounmap_irq(vaddr);
+ ghes_iounmap_irq();
spin_unlock_irqrestore(&ghes_ioremap_lock_irq, flags);
}
}
--
2.15.0.rc2
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 2/4] ACPI / APEI: Remove ghes_ioremap_area
2017-11-06 18:44 [PATCH 0/4] Switch GHES ioremap_page_range() to use fixmap James Morse
2017-11-06 18:44 ` [PATCH 1/4] ACPI / APEI: Replace ioremap_page_range() with fixmap James Morse
@ 2017-11-06 18:44 ` James Morse
2017-11-06 18:44 ` [PATCH 3/4] arm64: mm: Remove arch_apei_flush_tlb_one() James Morse
2017-11-06 18:44 ` [PATCH 4/4] ACPI / APEI: " James Morse
3 siblings, 0 replies; 5+ messages in thread
From: James Morse @ 2017-11-06 18:44 UTC (permalink / raw)
To: linux-arm-kernel
Now that nothing is using the ghes_ioremap_area pages, rip them out.
Signed-off-by: James Morse <james.morse@arm.com>
Reviewed-by: Borislav Petkov <bp@suse.de>
Tested-by: Tyler Baicar <tbaicar@codeaurora.org>
---
drivers/acpi/apei/ghes.c | 39 ++-------------------------------------
1 file changed, 2 insertions(+), 37 deletions(-)
diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
index f3269816b997..1a4f16b10052 100644
--- a/drivers/acpi/apei/ghes.c
+++ b/drivers/acpi/apei/ghes.c
@@ -114,19 +114,7 @@ static DEFINE_MUTEX(ghes_list_mutex);
* from BIOS to Linux can be determined only in NMI, IRQ or timer
* handler, but general ioremap can not be used in atomic context, so
* the fixmap is used instead.
- */
-
-/*
- * Two virtual pages are used, one for IRQ/PROCESS context, the other for
- * NMI context (optionally).
- */
-#define GHES_IOREMAP_PAGES 2
-#define GHES_IOREMAP_IRQ_PAGE(base) (base)
-#define GHES_IOREMAP_NMI_PAGE(base) ((base) + PAGE_SIZE)
-
-/* virtual memory area for atomic ioremap */
-static struct vm_struct *ghes_ioremap_area;
-/*
+ *
* These 2 spinlocks are used to prevent the fixmap entries from being used
* simultaneously.
*/
@@ -141,23 +129,6 @@ static atomic_t ghes_estatus_cache_alloced;
static int ghes_panic_timeout __read_mostly = 30;
-static int ghes_ioremap_init(void)
-{
- ghes_ioremap_area = __get_vm_area(PAGE_SIZE * GHES_IOREMAP_PAGES,
- VM_IOREMAP, VMALLOC_START, VMALLOC_END);
- if (!ghes_ioremap_area) {
- pr_err(GHES_PFX "Failed to allocate virtual memory area for atomic ioremap.\n");
- return -ENOMEM;
- }
-
- return 0;
-}
-
-static void ghes_ioremap_exit(void)
-{
- free_vm_area(ghes_ioremap_area);
-}
-
static void __iomem *ghes_ioremap_pfn_nmi(u64 pfn)
{
phys_addr_t paddr;
@@ -1270,13 +1241,9 @@ static int __init ghes_init(void)
ghes_nmi_init_cxt();
- rc = ghes_ioremap_init();
- if (rc)
- goto err;
-
rc = ghes_estatus_pool_init();
if (rc)
- goto err_ioremap_exit;
+ goto err;
rc = ghes_estatus_pool_expand(GHES_ESTATUS_CACHE_AVG_SIZE *
GHES_ESTATUS_CACHE_ALLOCED_MAX);
@@ -1300,8 +1267,6 @@ static int __init ghes_init(void)
return 0;
err_pool_exit:
ghes_estatus_pool_exit();
-err_ioremap_exit:
- ghes_ioremap_exit();
err:
return rc;
}
--
2.15.0.rc2
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 3/4] arm64: mm: Remove arch_apei_flush_tlb_one()
2017-11-06 18:44 [PATCH 0/4] Switch GHES ioremap_page_range() to use fixmap James Morse
2017-11-06 18:44 ` [PATCH 1/4] ACPI / APEI: Replace ioremap_page_range() with fixmap James Morse
2017-11-06 18:44 ` [PATCH 2/4] ACPI / APEI: Remove ghes_ioremap_area James Morse
@ 2017-11-06 18:44 ` James Morse
2017-11-06 18:44 ` [PATCH 4/4] ACPI / APEI: " James Morse
3 siblings, 0 replies; 5+ messages in thread
From: James Morse @ 2017-11-06 18:44 UTC (permalink / raw)
To: linux-arm-kernel
Nothing calls arch_apei_flush_tlb_one() anymore, instead relying on
__set_fixmap() to do the invalidation. Remove it.
Move the IPI-considered-harmful comment to __set_fixmap().
Signed-off-by: James Morse <james.morse@arm.com>
Acked-by: Will Deacon <will.deacon@arm.com>
Tested-by: Tyler Baicar <tbaicar@codeaurora.org>
---
arch/arm64/include/asm/acpi.h | 12 ------------
arch/arm64/mm/mmu.c | 4 ++++
2 files changed, 4 insertions(+), 12 deletions(-)
diff --git a/arch/arm64/include/asm/acpi.h b/arch/arm64/include/asm/acpi.h
index 59cca1d6ec54..32f465a80e4e 100644
--- a/arch/arm64/include/asm/acpi.h
+++ b/arch/arm64/include/asm/acpi.h
@@ -126,18 +126,6 @@ static inline const char *acpi_get_enable_method(int cpu)
*/
#define acpi_disable_cmcff 1
pgprot_t arch_apei_get_mem_attribute(phys_addr_t addr);
-
-/*
- * Despite its name, this function must still broadcast the TLB
- * invalidation in order to ensure other CPUs don't end up with junk
- * entries as a result of speculation. Unusually, its also called in
- * IRQ context (ghes_iounmap_irq) so if we ever need to use IPIs for
- * TLB broadcasting, then we're in trouble here.
- */
-static inline void arch_apei_flush_tlb_one(unsigned long addr)
-{
- flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
-}
#endif /* CONFIG_ACPI_APEI */
#ifdef CONFIG_ACPI_NUMA
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index f1eb15e0e864..267d2b79d52d 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -778,6 +778,10 @@ void __init early_fixmap_init(void)
}
}
+/*
+ * Unusually, this is also called in IRQ context (ghes_iounmap_irq) so if we
+ * ever need to use IPIs for TLB broadcasting, then we're in trouble here.
+ */
void __set_fixmap(enum fixed_addresses idx,
phys_addr_t phys, pgprot_t flags)
{
--
2.15.0.rc2
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 4/4] ACPI / APEI: Remove arch_apei_flush_tlb_one()
2017-11-06 18:44 [PATCH 0/4] Switch GHES ioremap_page_range() to use fixmap James Morse
` (2 preceding siblings ...)
2017-11-06 18:44 ` [PATCH 3/4] arm64: mm: Remove arch_apei_flush_tlb_one() James Morse
@ 2017-11-06 18:44 ` James Morse
3 siblings, 0 replies; 5+ messages in thread
From: James Morse @ 2017-11-06 18:44 UTC (permalink / raw)
To: linux-arm-kernel
Nothing calls arch_apei_flush_tlb_one() anymore, instead relying on
__set_pte_vaddr() to do the invalidation when called from clear_fixmap()
Remove arch_apei_flush_tlb_one().
Signed-off-by: James Morse <james.morse@arm.com>
Reviewed-by: Borislav Petkov <bp@suse.de>
---
arch/x86/kernel/acpi/apei.c | 5 -----
include/acpi/apei.h | 1 -
2 files changed, 6 deletions(-)
diff --git a/arch/x86/kernel/acpi/apei.c b/arch/x86/kernel/acpi/apei.c
index ea3046e0b0cf..bb8d300fecbd 100644
--- a/arch/x86/kernel/acpi/apei.c
+++ b/arch/x86/kernel/acpi/apei.c
@@ -52,8 +52,3 @@ void arch_apei_report_mem_error(int sev, struct cper_sec_mem_err *mem_err)
apei_mce_report_mem_error(sev, mem_err);
#endif
}
-
-void arch_apei_flush_tlb_one(unsigned long addr)
-{
- __flush_tlb_one(addr);
-}
diff --git a/include/acpi/apei.h b/include/acpi/apei.h
index c46694abea28..82c451698c98 100644
--- a/include/acpi/apei.h
+++ b/include/acpi/apei.h
@@ -50,7 +50,6 @@ int erst_clear(u64 record_id);
int arch_apei_enable_cmcff(struct acpi_hest_header *hest_hdr, void *data);
void arch_apei_report_mem_error(int sev, struct cper_sec_mem_err *mem_err);
-void arch_apei_flush_tlb_one(unsigned long addr);
#endif
#endif
--
2.15.0.rc2
^ permalink raw reply related [flat|nested] 5+ messages in thread
end of thread, other threads:[~2017-11-06 18:44 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-11-06 18:44 [PATCH 0/4] Switch GHES ioremap_page_range() to use fixmap James Morse
2017-11-06 18:44 ` [PATCH 1/4] ACPI / APEI: Replace ioremap_page_range() with fixmap James Morse
2017-11-06 18:44 ` [PATCH 2/4] ACPI / APEI: Remove ghes_ioremap_area James Morse
2017-11-06 18:44 ` [PATCH 3/4] arm64: mm: Remove arch_apei_flush_tlb_one() James Morse
2017-11-06 18:44 ` [PATCH 4/4] ACPI / APEI: " James Morse
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).