* [PATCH v4 10/26] mm: Introduce arch_calc_vm_flag_bits()
From: Catalin Marinas @ 2020-05-15 17:15 UTC (permalink / raw)
To: linux-arm-kernel
Cc: linux-arch, Szabolcs Nagy, Andrey Konovalov, Kevin Brodsky,
Peter Collingbourne, linux-mm, Andrew Morton, Vincenzo Frascino,
Will Deacon, Dave P Martin
In-Reply-To: <20200515171612.1020-1-catalin.marinas@arm.com>
From: Kevin Brodsky <Kevin.Brodsky@arm.com>
Similarly to arch_calc_vm_prot_bits(), introduce a dummy
arch_calc_vm_flag_bits() invoked from calc_vm_flag_bits(). This macro
can be overridden by architectures to insert specific VM_* flags derived
from the mmap() MAP_* flags.
Signed-off-by: Kevin Brodsky <Kevin.Brodsky@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
---
Notes:
v2:
- Updated the comment above arch_calc_vm_prot_bits().
- Changed author since this patch had already been posted (internally).
include/linux/mman.h | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/include/linux/mman.h b/include/linux/mman.h
index 4b08e9c9c538..15c1162b9d65 100644
--- a/include/linux/mman.h
+++ b/include/linux/mman.h
@@ -74,13 +74,17 @@ static inline void vm_unacct_memory(long pages)
}
/*
- * Allow architectures to handle additional protection bits
+ * Allow architectures to handle additional protection and flag bits
*/
#ifndef arch_calc_vm_prot_bits
#define arch_calc_vm_prot_bits(prot, pkey) 0
#endif
+#ifndef arch_calc_vm_flag_bits
+#define arch_calc_vm_flag_bits(flags) 0
+#endif
+
#ifndef arch_vm_get_page_prot
#define arch_vm_get_page_prot(vm_flags) __pgprot(0)
#endif
@@ -131,7 +135,8 @@ calc_vm_flag_bits(unsigned long flags)
return _calc_vm_trans(flags, MAP_GROWSDOWN, VM_GROWSDOWN ) |
_calc_vm_trans(flags, MAP_DENYWRITE, VM_DENYWRITE ) |
_calc_vm_trans(flags, MAP_LOCKED, VM_LOCKED ) |
- _calc_vm_trans(flags, MAP_SYNC, VM_SYNC );
+ _calc_vm_trans(flags, MAP_SYNC, VM_SYNC ) |
+ arch_calc_vm_flag_bits(flags);
}
unsigned long vm_commit_limit(void);
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v4 09/26] arm64: mte: Tags-aware aware memcmp_pages() implementation
From: Catalin Marinas @ 2020-05-15 17:15 UTC (permalink / raw)
To: linux-arm-kernel
Cc: linux-arch, Szabolcs Nagy, Andrey Konovalov, Kevin Brodsky,
Peter Collingbourne, linux-mm, Vincenzo Frascino, Will Deacon,
Dave P Martin
In-Reply-To: <20200515171612.1020-1-catalin.marinas@arm.com>
When the Memory Tagging Extension is enabled, two pages are identical
only if both their data and tags are identical.
Make the generic memcmp_pages() a __weak function and add an
arm64-specific implementation which returns non-zero if any of the two
pages contain valid MTE tags (PG_mte_tagged set). There isn't much
benefit in comparing the tags of two pages since these are normally used
for heap allocations and likely to differ anyway.
Co-developed-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
Signed-off-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will@kernel.org>
---
Notes:
v4:
- Remove page tag comparison. This is not very useful to detect
identical pages as long as set_pte_at() can zero the tags on a page
without copy-on-write if mapped with PROT_MTE. This can be improved
if a real case appears but it's unlikely for heap pages to be
identical across multiple processes.
- Move the memcmp_pages() function to mte.c.
arch/arm64/kernel/mte.c | 26 ++++++++++++++++++++++++++
mm/util.c | 2 +-
2 files changed, 27 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/kernel/mte.c b/arch/arm64/kernel/mte.c
index 65a2f8490d18..da2d70178a4b 100644
--- a/arch/arm64/kernel/mte.c
+++ b/arch/arm64/kernel/mte.c
@@ -5,6 +5,7 @@
#include <linux/bitops.h>
#include <linux/mm.h>
+#include <linux/string.h>
#include <linux/thread_info.h>
#include <asm/cpufeature.h>
@@ -23,6 +24,31 @@ void mte_sync_tags(pte_t *ptep, pte_t pte)
mte_clear_page_tags(page_address(page), page_size(page));
}
+int memcmp_pages(struct page *page1, struct page *page2)
+{
+ char *addr1, *addr2;
+ int ret;
+
+ addr1 = page_address(page1);
+ addr2 = page_address(page2);
+ ret = memcmp(addr1, addr2, PAGE_SIZE);
+
+ if (!system_supports_mte() || ret)
+ return ret;
+
+ /*
+ * If the page content is identical but at least one of the pages is
+ * tagged, return non-zero to avoid KSM merging. If only one of the
+ * pages is tagged, set_pte_at() may zero or change the tags of the
+ * other page via mte_sync_tags().
+ */
+ if (test_bit(PG_mte_tagged, &page1->flags) ||
+ test_bit(PG_mte_tagged, &page2->flags))
+ return addr1 != addr2;
+
+ return ret;
+}
+
void flush_mte_state(void)
{
if (!system_supports_mte())
diff --git a/mm/util.c b/mm/util.c
index 988d11e6c17c..662fb3da6d01 100644
--- a/mm/util.c
+++ b/mm/util.c
@@ -899,7 +899,7 @@ int get_cmdline(struct task_struct *task, char *buffer, int buflen)
return res;
}
-int memcmp_pages(struct page *page1, struct page *page2)
+int __weak memcmp_pages(struct page *page1, struct page *page2)
{
char *addr1, *addr2;
int ret;
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v4 08/26] arm64: mte: Tags-aware copy_page() implementation
From: Catalin Marinas @ 2020-05-15 17:15 UTC (permalink / raw)
To: linux-arm-kernel
Cc: linux-arch, Szabolcs Nagy, Andrey Konovalov, Kevin Brodsky,
Peter Collingbourne, linux-mm, Vincenzo Frascino, Will Deacon,
Dave P Martin
In-Reply-To: <20200515171612.1020-1-catalin.marinas@arm.com>
From: Vincenzo Frascino <vincenzo.frascino@arm.com>
When the Memory Tagging Extension is enabled, the tags need to be
preserved across page copy (e.g. for copy-on-write).
Introduce MTE-aware copy_page() which preserves the tags across page
copy.
Signed-off-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
Co-developed-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will@kernel.org>
---
Notes:
v4:
- Moved the tag copying to a separate function in mte.S and only called
if the source page has the PG_mte_tagged flag set.
arch/arm64/include/asm/mte.h | 4 ++++
arch/arm64/lib/mte.S | 19 +++++++++++++++++++
arch/arm64/mm/copypage.c | 14 ++++++++++++--
3 files changed, 35 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/include/asm/mte.h b/arch/arm64/include/asm/mte.h
index 4310a7ff10c0..c1a09499c678 100644
--- a/arch/arm64/include/asm/mte.h
+++ b/arch/arm64/include/asm/mte.h
@@ -19,6 +19,7 @@ void mte_clear_page_tags(void *addr, size_t size);
#define PG_mte_tagged PG_arch_2
void mte_sync_tags(pte_t *ptep, pte_t pte);
+void mte_copy_page_tags(void *kto, const void *kfrom);
void flush_mte_state(void);
#else
@@ -29,6 +30,9 @@ void flush_mte_state(void);
static inline void mte_sync_tags(pte_t *ptep, pte_t pte)
{
}
+static inline void mte_copy_page_tags(void *kto, const void *kfrom)
+{
+}
static inline void flush_mte_state(void)
{
}
diff --git a/arch/arm64/lib/mte.S b/arch/arm64/lib/mte.S
index 130fb7047e17..a531b52fa5ba 100644
--- a/arch/arm64/lib/mte.S
+++ b/arch/arm64/lib/mte.S
@@ -5,6 +5,7 @@
#include <linux/linkage.h>
#include <asm/assembler.h>
+#include <asm/page.h>
.arch armv8.5-a+memtag
@@ -21,3 +22,21 @@ SYM_FUNC_START(mte_clear_page_tags)
cbnz x1, 1b
ret
SYM_FUNC_END(mte_clear_page_tags)
+
+/*
+ * Copy the tags from the source page to the destination one
+ * x0 - address of the destination page
+ * x1 - address of the source page
+ */
+SYM_FUNC_START(mte_copy_page_tags)
+ mov x2, x0
+ mov x3, x1
+ multitag_transfer_size x5, x6
+1: ldgm x4, [x3]
+ stgm x4, [x2]
+ add x2, x2, x5
+ add x3, x3, x5
+ tst x2, #(PAGE_SIZE - 1)
+ b.ne 1b
+2:
+SYM_FUNC_END(mte_copy_page_tags)
diff --git a/arch/arm64/mm/copypage.c b/arch/arm64/mm/copypage.c
index 2ee7b73433a5..2560ddc479ac 100644
--- a/arch/arm64/mm/copypage.c
+++ b/arch/arm64/mm/copypage.c
@@ -6,16 +6,26 @@
* Copyright (C) 2012 ARM Ltd.
*/
+#include <linux/bitops.h>
#include <linux/mm.h>
#include <asm/page.h>
#include <asm/cacheflush.h>
+#include <asm/cpufeature.h>
+#include <asm/mte.h>
void __cpu_copy_user_page(void *kto, const void *kfrom, unsigned long vaddr)
{
- struct page *page = virt_to_page(kto);
+ struct page *to_page = virt_to_page(kto);
+ struct page *from_page = virt_to_page(kfrom);
+
copy_page(kto, kfrom);
- flush_dcache_page(page);
+ if (system_supports_mte() &&
+ test_bit(PG_mte_tagged, &from_page->flags)) {
+ mte_copy_page_tags(kto, kfrom);
+ set_bit(PG_mte_tagged, &to_page->flags);
+ }
+ flush_dcache_page(to_page);
}
EXPORT_SYMBOL_GPL(__cpu_copy_user_page);
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v4 07/26] arm64: mte: Clear the tags when a page is mapped in user-space with PROT_MTE
From: Catalin Marinas @ 2020-05-15 17:15 UTC (permalink / raw)
To: linux-arm-kernel
Cc: linux-arch, Szabolcs Nagy, Andrey Konovalov, Kevin Brodsky,
Steven Price, Peter Collingbourne, linux-mm, Vincenzo Frascino,
Will Deacon, Dave P Martin
In-Reply-To: <20200515171612.1020-1-catalin.marinas@arm.com>
Pages allocated by the kernel are not guaranteed to have the tags
zeroed, especially as the kernel does not yet use MTE itself. To ensure
the user can still access such pages when mapped into its address space,
clear the tags via set_pte_at(). A new page flag - PG_mte_tagged
(PG_arch_2) - is used to track pages with valid allocation tags.
Co-developed-by: Steven Price <steven.price@arm.com>
Signed-off-by: Steven Price <steven.price@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will@kernel.org>
---
Notes:
New in v4. Replacing a previous page zeroing the tags in clear_page().
arch/arm64/include/asm/assembler.h | 12 ++++++++++++
arch/arm64/include/asm/mte.h | 16 ++++++++++++++++
arch/arm64/include/asm/pgtable.h | 6 ++++++
arch/arm64/kernel/mte.c | 14 ++++++++++++++
arch/arm64/lib/Makefile | 2 ++
arch/arm64/lib/mte.S | 23 +++++++++++++++++++++++
6 files changed, 73 insertions(+)
create mode 100644 arch/arm64/lib/mte.S
diff --git a/arch/arm64/include/asm/assembler.h b/arch/arm64/include/asm/assembler.h
index 0bff325117b4..dacd66df6c05 100644
--- a/arch/arm64/include/asm/assembler.h
+++ b/arch/arm64/include/asm/assembler.h
@@ -21,6 +21,7 @@
#include <asm/page.h>
#include <asm/pgtable-hwdef.h>
#include <asm/ptrace.h>
+#include <asm/sysreg.h>
#include <asm/thread_info.h>
.macro save_and_disable_daif, flags
@@ -736,4 +737,15 @@ USER(\label, ic ivau, \tmp2) // invalidate I line PoU
.Lyield_out_\@ :
.endm
+/*
+ * multitag_transfer_size - set \reg to the block size that is accessed by the
+ * LDGM/STGM instructions.
+ */
+ .macro multitag_transfer_size, reg, tmp
+ mrs_s \reg, SYS_GMID_EL1
+ ubfx \reg, \reg, #SYS_GMID_EL1_BS_SHIFT, #SYS_GMID_EL1_BS_SIZE
+ mov \tmp, #4
+ lsl \reg, \tmp, \reg
+ .endm
+
#endif /* __ASM_ASSEMBLER_H */
diff --git a/arch/arm64/include/asm/mte.h b/arch/arm64/include/asm/mte.h
index a0bf310da74b..4310a7ff10c0 100644
--- a/arch/arm64/include/asm/mte.h
+++ b/arch/arm64/include/asm/mte.h
@@ -7,12 +7,28 @@
#ifndef __ASSEMBLY__
+#include <linux/page-flags.h>
+
+#include <asm/pgtable-types.h>
+
+void mte_clear_page_tags(void *addr, size_t size);
+
#ifdef CONFIG_ARM64_MTE
+/* track which pages have valid allocation tags */
+#define PG_mte_tagged PG_arch_2
+
+void mte_sync_tags(pte_t *ptep, pte_t pte);
void flush_mte_state(void);
#else
+/* unused if !CONFIG_ARM64_MTE, silence the compiler */
+#define PG_mte_tagged 0
+
+static inline void mte_sync_tags(pte_t *ptep, pte_t pte)
+{
+}
static inline void flush_mte_state(void)
{
}
diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
index 538c85e62f86..647a3f0c7874 100644
--- a/arch/arm64/include/asm/pgtable.h
+++ b/arch/arm64/include/asm/pgtable.h
@@ -9,6 +9,7 @@
#include <asm/proc-fns.h>
#include <asm/memory.h>
+#include <asm/mte.h>
#include <asm/pgtable-hwdef.h>
#include <asm/pgtable-prot.h>
#include <asm/tlbflush.h>
@@ -80,6 +81,8 @@ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
#define pte_user_exec(pte) (!(pte_val(pte) & PTE_UXN))
#define pte_cont(pte) (!!(pte_val(pte) & PTE_CONT))
#define pte_devmap(pte) (!!(pte_val(pte) & PTE_DEVMAP))
+#define pte_tagged(pte) ((pte_val(pte) & PTE_ATTRINDX_MASK) == \
+ PTE_ATTRINDX(MT_NORMAL_TAGGED))
#define pte_cont_addr_end(addr, end) \
({ unsigned long __boundary = ((addr) + CONT_PTE_SIZE) & CONT_PTE_MASK; \
@@ -274,6 +277,9 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
if (pte_present(pte) && pte_user_exec(pte) && !pte_special(pte))
__sync_icache_dcache(pte);
+ if (system_supports_mte() && pte_present(pte) && pte_tagged(pte))
+ mte_sync_tags(ptep, pte);
+
__check_racy_pte_update(mm, ptep, pte);
set_pte(ptep, pte);
diff --git a/arch/arm64/kernel/mte.c b/arch/arm64/kernel/mte.c
index 032016823957..65a2f8490d18 100644
--- a/arch/arm64/kernel/mte.c
+++ b/arch/arm64/kernel/mte.c
@@ -3,12 +3,26 @@
* Copyright (C) 2020 ARM Ltd.
*/
+#include <linux/bitops.h>
+#include <linux/mm.h>
#include <linux/thread_info.h>
#include <asm/cpufeature.h>
#include <asm/mte.h>
#include <asm/sysreg.h>
+void mte_sync_tags(pte_t *ptep, pte_t pte)
+{
+ struct page *page = pte_page(pte);
+
+ /* if PG_mte_tagged is set, tags have already been initialised */
+ if (test_and_set_bit(PG_mte_tagged, &page->flags))
+ return;
+
+ /* tags of the zero page will be cleared on first mapping */
+ mte_clear_page_tags(page_address(page), page_size(page));
+}
+
void flush_mte_state(void)
{
if (!system_supports_mte())
diff --git a/arch/arm64/lib/Makefile b/arch/arm64/lib/Makefile
index 2fc253466dbf..d31e1169d9b8 100644
--- a/arch/arm64/lib/Makefile
+++ b/arch/arm64/lib/Makefile
@@ -16,3 +16,5 @@ lib-$(CONFIG_ARCH_HAS_UACCESS_FLUSHCACHE) += uaccess_flushcache.o
obj-$(CONFIG_CRC32) += crc32.o
obj-$(CONFIG_FUNCTION_ERROR_INJECTION) += error-inject.o
+
+obj-$(CONFIG_ARM64_MTE) += mte.o
diff --git a/arch/arm64/lib/mte.S b/arch/arm64/lib/mte.S
new file mode 100644
index 000000000000..130fb7047e17
--- /dev/null
+++ b/arch/arm64/lib/mte.S
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2020 ARM Ltd.
+ */
+#include <linux/linkage.h>
+
+#include <asm/assembler.h>
+
+ .arch armv8.5-a+memtag
+
+/*
+ * Clear the tags in a (potentially huge) page
+ * x0 - page address
+ * x1 - page size
+ */
+SYM_FUNC_START(mte_clear_page_tags)
+ multitag_transfer_size x2, x3
+1: stgm xzr, [x0]
+ add x0, x0, x2
+ sub x1, x1, x2
+ cbnz x1, 1b
+ ret
+SYM_FUNC_END(mte_clear_page_tags)
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v4 06/26] mm: Add PG_ARCH_2 page flag
From: Catalin Marinas @ 2020-05-15 17:15 UTC (permalink / raw)
To: linux-arm-kernel
Cc: linux-arch, Szabolcs Nagy, Andrey Konovalov, Kevin Brodsky,
Steven Price, Peter Collingbourne, linux-mm, Andrew Morton,
Vincenzo Frascino, Will Deacon, Dave P Martin
In-Reply-To: <20200515171612.1020-1-catalin.marinas@arm.com>
From: Steven Price <steven.price@arm.com>
For arm64 MTE support it is necessary to be able to mark pages that
contain user space visible tags that will need to be saved/restored e.g.
when swapped out.
To support this add a new arch specific flag (PG_ARCH_2) that arch code
can opt into using ARCH_USES_PG_ARCH_2.
Signed-off-by: Steven Price <steven.price@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
---
Notes:
New in v4.
fs/proc/page.c | 3 +++
include/linux/kernel-page-flags.h | 1 +
include/linux/page-flags.h | 3 +++
include/trace/events/mmflags.h | 9 ++++++++-
mm/Kconfig | 3 +++
tools/vm/page-types.c | 2 ++
6 files changed, 20 insertions(+), 1 deletion(-)
diff --git a/fs/proc/page.c b/fs/proc/page.c
index f909243d4a66..1b6cbe0849a8 100644
--- a/fs/proc/page.c
+++ b/fs/proc/page.c
@@ -217,6 +217,9 @@ u64 stable_page_flags(struct page *page)
u |= kpf_copy_bit(k, KPF_PRIVATE_2, PG_private_2);
u |= kpf_copy_bit(k, KPF_OWNER_PRIVATE, PG_owner_priv_1);
u |= kpf_copy_bit(k, KPF_ARCH, PG_arch_1);
+#ifdef CONFIG_ARCH_USES_PG_ARCH_2
+ u |= kpf_copy_bit(k, KPF_ARCH_2, PG_arch_2);
+#endif
return u;
};
diff --git a/include/linux/kernel-page-flags.h b/include/linux/kernel-page-flags.h
index abd20ef93c98..eee1877a354e 100644
--- a/include/linux/kernel-page-flags.h
+++ b/include/linux/kernel-page-flags.h
@@ -17,5 +17,6 @@
#define KPF_ARCH 38
#define KPF_UNCACHED 39
#define KPF_SOFTDIRTY 40
+#define KPF_ARCH_2 41
#endif /* LINUX_KERNEL_PAGE_FLAGS_H */
diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
index 222f6f7b2bb3..1d4971fe4fee 100644
--- a/include/linux/page-flags.h
+++ b/include/linux/page-flags.h
@@ -135,6 +135,9 @@ enum pageflags {
#if defined(CONFIG_IDLE_PAGE_TRACKING) && defined(CONFIG_64BIT)
PG_young,
PG_idle,
+#endif
+#ifdef CONFIG_ARCH_USES_PG_ARCH_2
+ PG_arch_2,
#endif
__NR_PAGEFLAGS,
diff --git a/include/trace/events/mmflags.h b/include/trace/events/mmflags.h
index 5fb752034386..5d098029a2d8 100644
--- a/include/trace/events/mmflags.h
+++ b/include/trace/events/mmflags.h
@@ -79,6 +79,12 @@
#define IF_HAVE_PG_IDLE(flag,string)
#endif
+#ifdef CONFIG_ARCH_USES_PG_ARCH_2
+#define IF_HAVE_PG_ARCH_2(flag,string) ,{1UL << flag, string}
+#else
+#define IF_HAVE_PG_ARCH_2(flag,string)
+#endif
+
#define __def_pageflag_names \
{1UL << PG_locked, "locked" }, \
{1UL << PG_waiters, "waiters" }, \
@@ -105,7 +111,8 @@ IF_HAVE_PG_MLOCK(PG_mlocked, "mlocked" ) \
IF_HAVE_PG_UNCACHED(PG_uncached, "uncached" ) \
IF_HAVE_PG_HWPOISON(PG_hwpoison, "hwpoison" ) \
IF_HAVE_PG_IDLE(PG_young, "young" ) \
-IF_HAVE_PG_IDLE(PG_idle, "idle" )
+IF_HAVE_PG_IDLE(PG_idle, "idle" ) \
+IF_HAVE_PG_ARCH_2(PG_arch_2, "arch_2" )
#define show_page_flags(flags) \
(flags) ? __print_flags(flags, "|", \
diff --git a/mm/Kconfig b/mm/Kconfig
index c1acc34c1c35..60427ccc3cb8 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -867,4 +867,7 @@ config ARCH_HAS_HUGEPD
config MAPPING_DIRTY_HELPERS
bool
+config ARCH_USES_PG_ARCH_2
+ bool
+
endmenu
diff --git a/tools/vm/page-types.c b/tools/vm/page-types.c
index 58c0eab71bca..0517c744b04e 100644
--- a/tools/vm/page-types.c
+++ b/tools/vm/page-types.c
@@ -78,6 +78,7 @@
#define KPF_ARCH 38
#define KPF_UNCACHED 39
#define KPF_SOFTDIRTY 40
+#define KPF_ARCH_2 41
/* [48-] take some arbitrary free slots for expanding overloaded flags
* not part of kernel API
@@ -135,6 +136,7 @@ static const char * const page_flag_names[] = {
[KPF_ARCH] = "h:arch",
[KPF_UNCACHED] = "c:uncached",
[KPF_SOFTDIRTY] = "f:softdirty",
+ [KPF_ARCH_2] = "H:arch_2",
[KPF_READAHEAD] = "I:readahead",
[KPF_SLOB_FREE] = "P:slob_free",
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v4 05/26] arm64: mte: Handle synchronous and asynchronous tag check faults
From: Catalin Marinas @ 2020-05-15 17:15 UTC (permalink / raw)
To: linux-arm-kernel
Cc: linux-arch, Szabolcs Nagy, Andrey Konovalov, Kevin Brodsky,
Peter Collingbourne, linux-mm, Vincenzo Frascino, Will Deacon,
Dave P Martin
In-Reply-To: <20200515171612.1020-1-catalin.marinas@arm.com>
From: Vincenzo Frascino <vincenzo.frascino@arm.com>
The Memory Tagging Extension has two modes of notifying a tag check
fault at EL0, configurable through the SCTLR_EL1.TCF0 field:
1. Synchronous raising of a Data Abort exception with DFSC 17.
2. Asynchronous setting of a cumulative bit in TFSRE0_EL1.
Add the exception handler for the synchronous exception and handling of
the asynchronous TFSRE0_EL1.TF0 bit setting via a new TIF flag in
do_notify_resume().
On a tag check failure in user-space, whether synchronous or
asynchronous, a SIGSEGV will be raised on the faulting thread.
Signed-off-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
Co-developed-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will@kernel.org>
---
Notes:
v4:
- Use send_signal_fault() instead of fault_signal_inject() for
asynchronous tag check faults as execution can continue even if this
signal is masked.
- Add DSB ISH prior to writing TFSRE0_EL1 in the clear_mte_async_tcf
macro.
- Move clear_mte_async_tcf just after returning to user since
do_notify_resume() may still cause async tag faults via do_signal().
v3:
- Asynchronous tag check faults during the uaccess routines in the
kernel are ignored.
- Fix check_mte_async_tcf calling site as it expects the first argument
to be the thread flags.
- Move the mte_thread_switch() definition and call to a later patch as
this became empty with the removal of async uaccess checking.
- Add dsb() and clearing of TFSRE0_EL1 in flush_mte_state(), in case
execve() triggered a asynchronous tag check fault.
- Clear TIF_MTE_ASYNC_FAULT in arch_dup_task_struct() so that the child
does not inherit any pending tag fault in the parent.
v2:
- Clear PSTATE.TCO on exception entry (automatically set by the hardware).
- On syscall entry, for asynchronous tag check faults from user space,
generate the signal early via syscall restarting.
- Before context switch, save any potential async tag check fault
generated by the kernel to the TIF flag (this follows an architecture
update where the uaccess routines use the TCF0 mode).
- Moved the flush_mte_state() and mte_thread_switch() function to a new
mte.c file.
arch/arm64/include/asm/mte.h | 23 +++++++++++++++++
arch/arm64/include/asm/thread_info.h | 4 ++-
arch/arm64/kernel/Makefile | 1 +
arch/arm64/kernel/entry.S | 37 ++++++++++++++++++++++++++++
arch/arm64/kernel/mte.c | 21 ++++++++++++++++
arch/arm64/kernel/process.c | 5 ++++
arch/arm64/kernel/signal.c | 8 ++++++
arch/arm64/kernel/syscall.c | 10 ++++++++
arch/arm64/mm/fault.c | 9 ++++++-
9 files changed, 116 insertions(+), 2 deletions(-)
create mode 100644 arch/arm64/include/asm/mte.h
create mode 100644 arch/arm64/kernel/mte.c
diff --git a/arch/arm64/include/asm/mte.h b/arch/arm64/include/asm/mte.h
new file mode 100644
index 000000000000..a0bf310da74b
--- /dev/null
+++ b/arch/arm64/include/asm/mte.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2020 ARM Ltd.
+ */
+#ifndef __ASM_MTE_H
+#define __ASM_MTE_H
+
+#ifndef __ASSEMBLY__
+
+#ifdef CONFIG_ARM64_MTE
+
+void flush_mte_state(void);
+
+#else
+
+static inline void flush_mte_state(void)
+{
+}
+
+#endif
+
+#endif /* __ASSEMBLY__ */
+#endif /* __ASM_MTE_H */
diff --git a/arch/arm64/include/asm/thread_info.h b/arch/arm64/include/asm/thread_info.h
index 512174a8e789..0c6e5523b932 100644
--- a/arch/arm64/include/asm/thread_info.h
+++ b/arch/arm64/include/asm/thread_info.h
@@ -63,6 +63,7 @@ void arch_release_task_struct(struct task_struct *tsk);
#define TIF_FOREIGN_FPSTATE 3 /* CPU's FP state is not current's */
#define TIF_UPROBE 4 /* uprobe breakpoint or singlestep */
#define TIF_FSCHECK 5 /* Check FS is USER_DS on return */
+#define TIF_MTE_ASYNC_FAULT 6 /* MTE Asynchronous Tag Check Fault */
#define TIF_SYSCALL_TRACE 8 /* syscall trace active */
#define TIF_SYSCALL_AUDIT 9 /* syscall auditing */
#define TIF_SYSCALL_TRACEPOINT 10 /* syscall tracepoint for ftrace */
@@ -91,10 +92,11 @@ void arch_release_task_struct(struct task_struct *tsk);
#define _TIF_FSCHECK (1 << TIF_FSCHECK)
#define _TIF_32BIT (1 << TIF_32BIT)
#define _TIF_SVE (1 << TIF_SVE)
+#define _TIF_MTE_ASYNC_FAULT (1 << TIF_MTE_ASYNC_FAULT)
#define _TIF_WORK_MASK (_TIF_NEED_RESCHED | _TIF_SIGPENDING | \
_TIF_NOTIFY_RESUME | _TIF_FOREIGN_FPSTATE | \
- _TIF_UPROBE | _TIF_FSCHECK)
+ _TIF_UPROBE | _TIF_FSCHECK | _TIF_MTE_ASYNC_FAULT)
#define _TIF_SYSCALL_WORK (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \
_TIF_SYSCALL_TRACEPOINT | _TIF_SECCOMP | \
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 4e5b8ee31442..dbede7a4c5fb 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -63,6 +63,7 @@ obj-$(CONFIG_CRASH_CORE) += crash_core.o
obj-$(CONFIG_ARM_SDE_INTERFACE) += sdei.o
obj-$(CONFIG_ARM64_SSBD) += ssbd.o
obj-$(CONFIG_ARM64_PTR_AUTH) += pointer_auth.o
+obj-$(CONFIG_ARM64_MTE) += mte.o
obj-y += vdso/ probes/
obj-$(CONFIG_COMPAT_VDSO) += vdso32/
diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index ddcde093c433..cbb3cacdf79f 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -145,6 +145,32 @@ alternative_cb_end
#endif
.endm
+ /* Check for MTE asynchronous tag check faults */
+ .macro check_mte_async_tcf, flgs, tmp
+#ifdef CONFIG_ARM64_MTE
+alternative_if_not ARM64_MTE
+ b 1f
+alternative_else_nop_endif
+ mrs_s \tmp, SYS_TFSRE0_EL1
+ tbz \tmp, #SYS_TFSR_EL1_TF0_SHIFT, 1f
+ /* Asynchronous TCF occurred for TTBR0 access, set the TI flag */
+ orr \flgs, \flgs, #_TIF_MTE_ASYNC_FAULT
+ str \flgs, [tsk, #TSK_TI_FLAGS]
+ msr_s SYS_TFSRE0_EL1, xzr
+1:
+#endif
+ .endm
+
+ /* Clear the MTE asynchronous tag check faults */
+ .macro clear_mte_async_tcf
+#ifdef CONFIG_ARM64_MTE
+alternative_if ARM64_MTE
+ dsb ish
+ msr_s SYS_TFSRE0_EL1, xzr
+alternative_else_nop_endif
+#endif
+ .endm
+
.macro kernel_entry, el, regsize = 64
.if \regsize == 32
mov w0, w0 // zero upper 32 bits of x0
@@ -176,6 +202,8 @@ alternative_cb_end
ldr x19, [tsk, #TSK_TI_FLAGS]
disable_step_tsk x19, x20
+ /* Check for asynchronous tag check faults in user space */
+ check_mte_async_tcf x19, x22
apply_ssbd 1, x22, x23
ptrauth_keys_install_kernel tsk, 1, x20, x22, x23
@@ -244,6 +272,13 @@ alternative_if ARM64_HAS_IRQ_PRIO_MASKING
str x20, [sp, #S_PMR_SAVE]
alternative_else_nop_endif
+ /* Re-enable tag checking (TCO set on exception entry) */
+#ifdef CONFIG_ARM64_MTE
+alternative_if ARM64_MTE
+ SET_PSTATE_TCO(0)
+alternative_else_nop_endif
+#endif
+
/*
* Registers that may be useful after this macro is invoked:
*
@@ -748,6 +783,8 @@ ret_to_user:
and x2, x1, #_TIF_WORK_MASK
cbnz x2, work_pending
finish_ret_to_user:
+ /* Ignore asynchronous tag check faults in the uaccess routines */
+ clear_mte_async_tcf
enable_step_tsk x1, x2
#ifdef CONFIG_GCC_PLUGIN_STACKLEAK
bl stackleak_erase
diff --git a/arch/arm64/kernel/mte.c b/arch/arm64/kernel/mte.c
new file mode 100644
index 000000000000..032016823957
--- /dev/null
+++ b/arch/arm64/kernel/mte.c
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2020 ARM Ltd.
+ */
+
+#include <linux/thread_info.h>
+
+#include <asm/cpufeature.h>
+#include <asm/mte.h>
+#include <asm/sysreg.h>
+
+void flush_mte_state(void)
+{
+ if (!system_supports_mte())
+ return;
+
+ /* clear any pending asynchronous tag fault */
+ dsb(ish);
+ write_sysreg_s(0, SYS_TFSRE0_EL1);
+ clear_thread_flag(TIF_MTE_ASYNC_FAULT);
+}
diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
index 56be4cbf771f..740047c9cd13 100644
--- a/arch/arm64/kernel/process.c
+++ b/arch/arm64/kernel/process.c
@@ -50,6 +50,7 @@
#include <asm/exec.h>
#include <asm/fpsimd.h>
#include <asm/mmu_context.h>
+#include <asm/mte.h>
#include <asm/processor.h>
#include <asm/pointer_auth.h>
#include <asm/stacktrace.h>
@@ -323,6 +324,7 @@ void flush_thread(void)
tls_thread_flush();
flush_ptrace_hw_breakpoint(current);
flush_tagged_addr_state();
+ flush_mte_state();
}
void release_thread(struct task_struct *dead_task)
@@ -355,6 +357,9 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
dst->thread.sve_state = NULL;
clear_tsk_thread_flag(dst, TIF_SVE);
+ /* clear any pending asynchronous tag fault raised by the parent */
+ clear_tsk_thread_flag(dst, TIF_MTE_ASYNC_FAULT);
+
return 0;
}
diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c
index 339882db5a91..149334d5df02 100644
--- a/arch/arm64/kernel/signal.c
+++ b/arch/arm64/kernel/signal.c
@@ -732,6 +732,9 @@ static void setup_return(struct pt_regs *regs, struct k_sigaction *ka,
regs->regs[29] = (unsigned long)&user->next_frame->fp;
regs->pc = (unsigned long)ka->sa.sa_handler;
+ /* TCO (Tag Check Override) always cleared for signal handlers */
+ regs->pstate &= ~PSR_TCO_BIT;
+
if (ka->sa.sa_flags & SA_RESTORER)
sigtramp = ka->sa.sa_restorer;
else
@@ -923,6 +926,11 @@ asmlinkage void do_notify_resume(struct pt_regs *regs,
if (thread_flags & _TIF_UPROBE)
uprobe_notify_resume(regs);
+ if (thread_flags & _TIF_MTE_ASYNC_FAULT) {
+ clear_thread_flag(TIF_MTE_ASYNC_FAULT);
+ send_sig_fault(SIGSEGV, SEGV_MTEAERR, 0, current);
+ }
+
if (thread_flags & _TIF_SIGPENDING)
do_signal(regs);
diff --git a/arch/arm64/kernel/syscall.c b/arch/arm64/kernel/syscall.c
index a12c0c88d345..db25f5d6a07c 100644
--- a/arch/arm64/kernel/syscall.c
+++ b/arch/arm64/kernel/syscall.c
@@ -102,6 +102,16 @@ static void el0_svc_common(struct pt_regs *regs, int scno, int sc_nr,
local_daif_restore(DAIF_PROCCTX);
user_exit();
+ if (system_supports_mte() && (flags & _TIF_MTE_ASYNC_FAULT)) {
+ /*
+ * Process the asynchronous tag check fault before the actual
+ * syscall. do_notify_resume() will send a signal to userspace
+ * before the syscall is restarted.
+ */
+ regs->regs[0] = -ERESTARTNOINTR;
+ return;
+ }
+
if (has_syscall_work(flags)) {
/* set default errno for user-issued syscall(-1) */
if (scno == NO_SYSCALL)
diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
index c9cedc0432d2..38b59cace3e3 100644
--- a/arch/arm64/mm/fault.c
+++ b/arch/arm64/mm/fault.c
@@ -650,6 +650,13 @@ static int do_sea(unsigned long addr, unsigned int esr, struct pt_regs *regs)
return 0;
}
+static int do_tag_check_fault(unsigned long addr, unsigned int esr,
+ struct pt_regs *regs)
+{
+ do_bad_area(addr, esr, regs);
+ return 0;
+}
+
static const struct fault_info fault_info[] = {
{ do_bad, SIGKILL, SI_KERNEL, "ttbr address size fault" },
{ do_bad, SIGKILL, SI_KERNEL, "level 1 address size fault" },
@@ -668,7 +675,7 @@ static const struct fault_info fault_info[] = {
{ do_page_fault, SIGSEGV, SEGV_ACCERR, "level 2 permission fault" },
{ do_page_fault, SIGSEGV, SEGV_ACCERR, "level 3 permission fault" },
{ do_sea, SIGBUS, BUS_OBJERR, "synchronous external abort" },
- { do_bad, SIGKILL, SI_KERNEL, "unknown 17" },
+ { do_tag_check_fault, SIGSEGV, SEGV_MTESERR, "synchronous tag check fault" },
{ do_bad, SIGKILL, SI_KERNEL, "unknown 18" },
{ do_bad, SIGKILL, SI_KERNEL, "unknown 19" },
{ do_sea, SIGKILL, SI_KERNEL, "level 0 (translation table walk)" },
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v4 04/26] arm64: mte: Add specific SIGSEGV codes
From: Catalin Marinas @ 2020-05-15 17:15 UTC (permalink / raw)
To: linux-arm-kernel
Cc: linux-arch, Arnd Bergmann, Szabolcs Nagy, Andrey Konovalov,
Kevin Brodsky, Peter Collingbourne, linux-mm, Vincenzo Frascino,
Will Deacon, Dave P Martin
In-Reply-To: <20200515171612.1020-1-catalin.marinas@arm.com>
From: Vincenzo Frascino <vincenzo.frascino@arm.com>
Add MTE-specific SIGSEGV codes to siginfo.h and update the x86
BUILD_BUG_ON(NSIGSEGV != 7) compile check.
Signed-off-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
[catalin.marinas@arm.com: renamed precise/imprecise to sync/async]
[catalin.marinas@arm.com: dropped #ifdef __aarch64__, renumbered]
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Acked-by: "Eric W. Biederman" <ebiederm@xmission.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Will Deacon <will@kernel.org>
---
Notes:
v3:
- Fixed the BUILD_BUG_ON(NSIGSEGV != 7) on x86
- Updated the commit log
v2:
- Dropped the #ifdef __aarch64__.
- Renumbered the SEGV_MTE* values to avoid clash with ADI.
arch/x86/kernel/signal_compat.c | 2 +-
include/uapi/asm-generic/siginfo.h | 4 +++-
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/arch/x86/kernel/signal_compat.c b/arch/x86/kernel/signal_compat.c
index 9ccbf0576cd0..a7f3e12cfbdb 100644
--- a/arch/x86/kernel/signal_compat.c
+++ b/arch/x86/kernel/signal_compat.c
@@ -27,7 +27,7 @@ static inline void signal_compat_build_tests(void)
*/
BUILD_BUG_ON(NSIGILL != 11);
BUILD_BUG_ON(NSIGFPE != 15);
- BUILD_BUG_ON(NSIGSEGV != 7);
+ BUILD_BUG_ON(NSIGSEGV != 9);
BUILD_BUG_ON(NSIGBUS != 5);
BUILD_BUG_ON(NSIGTRAP != 5);
BUILD_BUG_ON(NSIGCHLD != 6);
diff --git a/include/uapi/asm-generic/siginfo.h b/include/uapi/asm-generic/siginfo.h
index cb3d6c267181..7aacf9389010 100644
--- a/include/uapi/asm-generic/siginfo.h
+++ b/include/uapi/asm-generic/siginfo.h
@@ -229,7 +229,9 @@ typedef struct siginfo {
#define SEGV_ACCADI 5 /* ADI not enabled for mapped object */
#define SEGV_ADIDERR 6 /* Disrupting MCD error */
#define SEGV_ADIPERR 7 /* Precise MCD exception */
-#define NSIGSEGV 7
+#define SEGV_MTEAERR 8 /* Asynchronous ARM MTE error */
+#define SEGV_MTESERR 9 /* Synchronous ARM MTE exception */
+#define NSIGSEGV 9
/*
* SIGBUS si_codes
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v4 03/26] arm64: mte: Use Normal Tagged attributes for the linear map
From: Catalin Marinas @ 2020-05-15 17:15 UTC (permalink / raw)
To: linux-arm-kernel
Cc: linux-arch, Suzuki K Poulose, Szabolcs Nagy, Andrey Konovalov,
Kevin Brodsky, Peter Collingbourne, linux-mm, Vincenzo Frascino,
Will Deacon, Dave P Martin
In-Reply-To: <20200515171612.1020-1-catalin.marinas@arm.com>
Once user space is given access to tagged memory, the kernel must be
able to clear/save/restore tags visible to the user. This is done via
the linear mapping, therefore map it as such. The new MT_NORMAL_TAGGED
index for MAIR_EL1 is initially mapped as Normal memory and later
changed to Normal Tagged via the cpufeature infrastructure. From a
mismatched attribute aliases perspective, the Tagged memory is
considered a permission and it won't lead to undefined behaviour.
The empty_zero_page is cleared to ensure that the tags it contains are
already zeroed. The actual tags-aware clear_page() implementation is
part of a subsequent patch.
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will@kernel.org>
Cc: Suzuki K Poulose <Suzuki.Poulose@arm.com>
---
Notes:
v3:
- Restrict the safe attribute change in pgattr_change_is_safe() only to
Normal to/from Normal-Tagged (old version allow any other type as long
as old or new was Normal(-Tagged)).
arch/arm64/include/asm/memory.h | 1 +
arch/arm64/include/asm/pgtable-prot.h | 2 ++
arch/arm64/kernel/cpufeature.c | 30 +++++++++++++++++++++++++++
arch/arm64/mm/dump.c | 4 ++++
arch/arm64/mm/mmu.c | 22 ++++++++++++++++++--
arch/arm64/mm/proc.S | 8 +++++--
6 files changed, 63 insertions(+), 4 deletions(-)
diff --git a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h
index a1871bb32bb1..472c77a68225 100644
--- a/arch/arm64/include/asm/memory.h
+++ b/arch/arm64/include/asm/memory.h
@@ -136,6 +136,7 @@
#define MT_NORMAL_NC 3
#define MT_NORMAL 4
#define MT_NORMAL_WT 5
+#define MT_NORMAL_TAGGED 6
/*
* Memory types for Stage-2 translation
diff --git a/arch/arm64/include/asm/pgtable-prot.h b/arch/arm64/include/asm/pgtable-prot.h
index 1305e28225fc..9c924b09d5c8 100644
--- a/arch/arm64/include/asm/pgtable-prot.h
+++ b/arch/arm64/include/asm/pgtable-prot.h
@@ -39,6 +39,7 @@ extern bool arm64_use_ng_mappings;
#define PROT_NORMAL_NC (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_WRITE | PTE_ATTRINDX(MT_NORMAL_NC))
#define PROT_NORMAL_WT (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_WRITE | PTE_ATTRINDX(MT_NORMAL_WT))
#define PROT_NORMAL (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_WRITE | PTE_ATTRINDX(MT_NORMAL))
+#define PROT_NORMAL_TAGGED (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_WRITE | PTE_ATTRINDX(MT_NORMAL_TAGGED))
#define PROT_SECT_DEVICE_nGnRE (PROT_SECT_DEFAULT | PMD_SECT_PXN | PMD_SECT_UXN | PMD_ATTRINDX(MT_DEVICE_nGnRE))
#define PROT_SECT_NORMAL (PROT_SECT_DEFAULT | PMD_SECT_PXN | PMD_SECT_UXN | PMD_ATTRINDX(MT_NORMAL))
@@ -48,6 +49,7 @@ extern bool arm64_use_ng_mappings;
#define _HYP_PAGE_DEFAULT _PAGE_DEFAULT
#define PAGE_KERNEL __pgprot(PROT_NORMAL)
+#define PAGE_KERNEL_TAGGED __pgprot(PROT_NORMAL_TAGGED)
#define PAGE_KERNEL_RO __pgprot((PROT_NORMAL & ~PTE_WRITE) | PTE_RDONLY)
#define PAGE_KERNEL_ROX __pgprot((PROT_NORMAL & ~(PTE_WRITE | PTE_PXN)) | PTE_RDONLY)
#define PAGE_KERNEL_EXEC __pgprot(PROT_NORMAL & ~PTE_PXN)
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 512a8b24c5df..d2fe8ff72324 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -1414,13 +1414,43 @@ static bool can_use_gic_priorities(const struct arm64_cpu_capabilities *entry,
#ifdef CONFIG_ARM64_MTE
static void cpu_enable_mte(struct arm64_cpu_capabilities const *cap)
{
+ u64 mair;
+
/* all non-zero tags excluded by default */
write_sysreg_s(SYS_GCR_EL1_RRND | SYS_GCR_EL1_EXCL_MASK, SYS_GCR_EL1);
write_sysreg_s(0, SYS_TFSR_EL1);
write_sysreg_s(0, SYS_TFSRE0_EL1);
+ /*
+ * Update the MT_NORMAL_TAGGED index in MAIR_EL1. Tag checking is
+ * disabled for the kernel, so there won't be any observable effect
+ * other than allowing the kernel to read and write tags.
+ */
+ mair = read_sysreg_s(SYS_MAIR_EL1);
+ mair &= ~MAIR_ATTRIDX(MAIR_ATTR_MASK, MT_NORMAL_TAGGED);
+ mair |= MAIR_ATTRIDX(MAIR_ATTR_NORMAL_TAGGED, MT_NORMAL_TAGGED);
+ write_sysreg_s(mair, SYS_MAIR_EL1);
+
isb();
}
+
+static int __init system_enable_mte(void)
+{
+ if (!system_supports_mte())
+ return 0;
+
+ /* Ensure the TLB does not have stale MAIR attributes */
+ flush_tlb_all();
+
+ /*
+ * Clear the zero page (again) so that tags are reset. This needs to
+ * be done via the linear map which has the Tagged attribute.
+ */
+ clear_page(lm_alias(empty_zero_page));
+
+ return 0;
+}
+core_initcall(system_enable_mte);
#endif /* CONFIG_ARM64_MTE */
/* Internal helper functions to match cpu capability type */
diff --git a/arch/arm64/mm/dump.c b/arch/arm64/mm/dump.c
index 860c00ec8bd3..416a2404ac83 100644
--- a/arch/arm64/mm/dump.c
+++ b/arch/arm64/mm/dump.c
@@ -165,6 +165,10 @@ static const struct prot_bits pte_bits[] = {
.mask = PTE_ATTRINDX_MASK,
.val = PTE_ATTRINDX(MT_NORMAL),
.set = "MEM/NORMAL",
+ }, {
+ .mask = PTE_ATTRINDX_MASK,
+ .val = PTE_ATTRINDX(MT_NORMAL_TAGGED),
+ .set = "MEM/NORMAL-TAGGED",
}
};
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index a374e4f51a62..37bb5b19bdf4 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -121,7 +121,7 @@ static bool pgattr_change_is_safe(u64 old, u64 new)
* The following mapping attributes may be updated in live
* kernel mappings without the need for break-before-make.
*/
- static const pteval_t mask = PTE_PXN | PTE_RDONLY | PTE_WRITE | PTE_NG;
+ pteval_t mask = PTE_PXN | PTE_RDONLY | PTE_WRITE | PTE_NG;
/* creating or taking down mappings is always safe */
if (old == 0 || new == 0)
@@ -135,6 +135,19 @@ static bool pgattr_change_is_safe(u64 old, u64 new)
if (old & ~new & PTE_NG)
return false;
+ if (system_supports_mte()) {
+ /*
+ * Changing the memory type between Normal and Normal-Tagged
+ * is safe since Tagged is considered a permission attribute
+ * from the mismatched attribute aliases perspective.
+ */
+ if (((old & PTE_ATTRINDX_MASK) == PTE_ATTRINDX(MT_NORMAL) ||
+ (old & PTE_ATTRINDX_MASK) == PTE_ATTRINDX(MT_NORMAL_TAGGED)) &&
+ ((new & PTE_ATTRINDX_MASK) == PTE_ATTRINDX(MT_NORMAL) ||
+ (new & PTE_ATTRINDX_MASK) == PTE_ATTRINDX(MT_NORMAL_TAGGED)))
+ mask |= PTE_ATTRINDX_MASK;
+ }
+
return ((old ^ new) & ~mask) == 0;
}
@@ -489,7 +502,12 @@ static void __init map_mem(pgd_t *pgdp)
if (memblock_is_nomap(reg))
continue;
- __map_memblock(pgdp, start, end, PAGE_KERNEL, flags);
+ /*
+ * The linear map must allow allocation tags reading/writing
+ * if MTE is present. Otherwise, it has the same attributes as
+ * PAGE_KERNEL.
+ */
+ __map_memblock(pgdp, start, end, PAGE_KERNEL_TAGGED, flags);
}
/*
diff --git a/arch/arm64/mm/proc.S b/arch/arm64/mm/proc.S
index 197a9ba2d5ea..48891095eaed 100644
--- a/arch/arm64/mm/proc.S
+++ b/arch/arm64/mm/proc.S
@@ -44,14 +44,18 @@
#define TCR_KASAN_FLAGS 0
#endif
-/* Default MAIR_EL1 */
+/*
+ * Default MAIR_EL1. MT_NORMAL_TAGGED is initially mapped as Normal memory and
+ * changed later to Normal Tagged if the system supports MTE.
+ */
#define MAIR_EL1_SET \
(MAIR_ATTRIDX(MAIR_ATTR_DEVICE_nGnRnE, MT_DEVICE_nGnRnE) | \
MAIR_ATTRIDX(MAIR_ATTR_DEVICE_nGnRE, MT_DEVICE_nGnRE) | \
MAIR_ATTRIDX(MAIR_ATTR_DEVICE_GRE, MT_DEVICE_GRE) | \
MAIR_ATTRIDX(MAIR_ATTR_NORMAL_NC, MT_NORMAL_NC) | \
MAIR_ATTRIDX(MAIR_ATTR_NORMAL, MT_NORMAL) | \
- MAIR_ATTRIDX(MAIR_ATTR_NORMAL_WT, MT_NORMAL_WT))
+ MAIR_ATTRIDX(MAIR_ATTR_NORMAL_WT, MT_NORMAL_WT) | \
+ MAIR_ATTRIDX(MAIR_ATTR_NORMAL, MT_NORMAL_TAGGED))
#ifdef CONFIG_CPU_PM
/**
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v4 02/26] arm64: mte: CPU feature detection and initial sysreg configuration
From: Catalin Marinas @ 2020-05-15 17:15 UTC (permalink / raw)
To: linux-arm-kernel
Cc: linux-arch, Suzuki K Poulose, Szabolcs Nagy, Andrey Konovalov,
Kevin Brodsky, Peter Collingbourne, linux-mm, Vincenzo Frascino,
Will Deacon, Dave P Martin
In-Reply-To: <20200515171612.1020-1-catalin.marinas@arm.com>
From: Vincenzo Frascino <vincenzo.frascino@arm.com>
Add the cpufeature and hwcap entries to detect the presence of MTE on
the boot CPUs (primary and secondary). Any late secondary CPU not
supporting the feature, if detected during boot, will be parked.
In addition, add the minimum SCTLR_EL1 and HCR_EL2 bits for enabling
MTE. Without subsequent setting of MAIR, these bits do not have an
effect on tag checking.
Signed-off-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
Co-developed-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will@kernel.org>
Cc: Suzuki K Poulose <Suzuki.Poulose@arm.com>
---
arch/arm64/include/asm/cpucaps.h | 4 +++-
arch/arm64/include/asm/cpufeature.h | 6 ++++++
arch/arm64/include/asm/hwcap.h | 1 +
arch/arm64/include/asm/kvm_arm.h | 2 +-
arch/arm64/include/asm/sysreg.h | 1 +
arch/arm64/include/uapi/asm/hwcap.h | 2 ++
arch/arm64/kernel/cpufeature.c | 30 +++++++++++++++++++++++++++++
arch/arm64/kernel/cpuinfo.c | 2 ++
8 files changed, 46 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h
index 8eb5a088ae65..4731ebacff54 100644
--- a/arch/arm64/include/asm/cpucaps.h
+++ b/arch/arm64/include/asm/cpucaps.h
@@ -61,7 +61,9 @@
#define ARM64_HAS_AMU_EXTN 51
#define ARM64_HAS_ADDRESS_AUTH 52
#define ARM64_HAS_GENERIC_AUTH 53
+/* 54 reserved for ARM64_BTI */
+#define ARM64_MTE 55
-#define ARM64_NCAPS 54
+#define ARM64_NCAPS 56
#endif /* __ASM_CPUCAPS_H */
diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index afe08251ff95..afc315814563 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -674,6 +674,12 @@ static inline bool system_uses_irq_prio_masking(void)
cpus_have_const_cap(ARM64_HAS_IRQ_PRIO_MASKING);
}
+static inline bool system_supports_mte(void)
+{
+ return IS_ENABLED(CONFIG_ARM64_MTE) &&
+ cpus_have_const_cap(ARM64_MTE);
+}
+
static inline bool system_has_prio_mask_debugging(void)
{
return IS_ENABLED(CONFIG_ARM64_DEBUG_PRIORITY_MASKING) &&
diff --git a/arch/arm64/include/asm/hwcap.h b/arch/arm64/include/asm/hwcap.h
index 0f00265248b5..8b302c88cfeb 100644
--- a/arch/arm64/include/asm/hwcap.h
+++ b/arch/arm64/include/asm/hwcap.h
@@ -94,6 +94,7 @@
#define KERNEL_HWCAP_BF16 __khwcap2_feature(BF16)
#define KERNEL_HWCAP_DGH __khwcap2_feature(DGH)
#define KERNEL_HWCAP_RNG __khwcap2_feature(RNG)
+#define KERNEL_HWCAP_MTE __khwcap2_feature(MTE)
/*
* This yields a mask that user programs can use to figure out what
diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h
index 8a1cbfd544d6..6c3b2fc922bb 100644
--- a/arch/arm64/include/asm/kvm_arm.h
+++ b/arch/arm64/include/asm/kvm_arm.h
@@ -78,7 +78,7 @@
HCR_AMO | HCR_SWIO | HCR_TIDCP | HCR_RW | HCR_TLOR | \
HCR_FMO | HCR_IMO)
#define HCR_VIRT_EXCP_MASK (HCR_VSE | HCR_VI | HCR_VF)
-#define HCR_HOST_NVHE_FLAGS (HCR_RW | HCR_API | HCR_APK)
+#define HCR_HOST_NVHE_FLAGS (HCR_RW | HCR_API | HCR_APK | HCR_ATA)
#define HCR_HOST_VHE_FLAGS (HCR_RW | HCR_TGE | HCR_E2H)
/* TCR_EL2 Registers bits */
diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
index e823e93b7429..86236ae6c4e7 100644
--- a/arch/arm64/include/asm/sysreg.h
+++ b/arch/arm64/include/asm/sysreg.h
@@ -604,6 +604,7 @@
SCTLR_EL1_SA0 | SCTLR_EL1_SED | SCTLR_ELx_I |\
SCTLR_EL1_DZE | SCTLR_EL1_UCT |\
SCTLR_EL1_NTWE | SCTLR_ELx_IESB | SCTLR_EL1_SPAN |\
+ SCTLR_ELx_ITFSB| SCTLR_ELx_ATA | SCTLR_EL1_ATA0 |\
ENDIAN_SET_EL1 | SCTLR_EL1_UCI | SCTLR_EL1_RES1)
/* MAIR_ELx memory attributes (used by Linux) */
diff --git a/arch/arm64/include/uapi/asm/hwcap.h b/arch/arm64/include/uapi/asm/hwcap.h
index 7752d93bb50f..73ac5aede18c 100644
--- a/arch/arm64/include/uapi/asm/hwcap.h
+++ b/arch/arm64/include/uapi/asm/hwcap.h
@@ -73,5 +73,7 @@
#define HWCAP2_BF16 (1 << 14)
#define HWCAP2_DGH (1 << 15)
#define HWCAP2_RNG (1 << 16)
+/* bit 17 reserved for HWCAP2_BTI */
+#define HWCAP2_MTE (1 << 18)
#endif /* _UAPI__ASM_HWCAP_H */
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 9fac745aa7bb..512a8b24c5df 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -182,6 +182,8 @@ static const struct arm64_ftr_bits ftr_id_aa64pfr0[] = {
static const struct arm64_ftr_bits ftr_id_aa64pfr1[] = {
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR1_SSBS_SHIFT, 4, ID_AA64PFR1_SSBS_PSTATE_NI),
+ ARM64_FTR_BITS(FTR_VISIBLE_IF_IS_ENABLED(CONFIG_ARM64_MTE),
+ FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR1_MTE_SHIFT, 4, ID_AA64PFR1_MTE_NI),
ARM64_FTR_END,
};
@@ -1409,6 +1411,18 @@ static bool can_use_gic_priorities(const struct arm64_cpu_capabilities *entry,
}
#endif
+#ifdef CONFIG_ARM64_MTE
+static void cpu_enable_mte(struct arm64_cpu_capabilities const *cap)
+{
+ /* all non-zero tags excluded by default */
+ write_sysreg_s(SYS_GCR_EL1_RRND | SYS_GCR_EL1_EXCL_MASK, SYS_GCR_EL1);
+ write_sysreg_s(0, SYS_TFSR_EL1);
+ write_sysreg_s(0, SYS_TFSRE0_EL1);
+
+ isb();
+}
+#endif /* CONFIG_ARM64_MTE */
+
/* Internal helper functions to match cpu capability type */
static bool
cpucap_late_cpu_optional(const struct arm64_cpu_capabilities *cap)
@@ -1779,6 +1793,19 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
.min_field_value = 1,
},
#endif
+#ifdef CONFIG_ARM64_MTE
+ {
+ .desc = "Memory Tagging Extension",
+ .capability = ARM64_MTE,
+ .type = ARM64_CPUCAP_SYSTEM_FEATURE,
+ .matches = has_cpuid_feature,
+ .sys_reg = SYS_ID_AA64PFR1_EL1,
+ .field_pos = ID_AA64PFR1_MTE_SHIFT,
+ .min_field_value = ID_AA64PFR1_MTE,
+ .sign = FTR_UNSIGNED,
+ .cpu_enable = cpu_enable_mte,
+ },
+#endif /* CONFIG_ARM64_MTE */
{},
};
@@ -1892,6 +1919,9 @@ static const struct arm64_cpu_capabilities arm64_elf_hwcaps[] = {
HWCAP_MULTI_CAP(ptr_auth_hwcap_addr_matches, CAP_HWCAP, KERNEL_HWCAP_PACA),
HWCAP_MULTI_CAP(ptr_auth_hwcap_gen_matches, CAP_HWCAP, KERNEL_HWCAP_PACG),
#endif
+#ifdef CONFIG_ARM64_MTE
+ HWCAP_CAP(SYS_ID_AA64PFR1_EL1, ID_AA64PFR1_MTE_SHIFT, FTR_UNSIGNED, ID_AA64PFR1_MTE, CAP_HWCAP, KERNEL_HWCAP_MTE),
+#endif /* CONFIG_ARM64_MTE */
{},
};
diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c
index 86136075ae41..d14b29de2c73 100644
--- a/arch/arm64/kernel/cpuinfo.c
+++ b/arch/arm64/kernel/cpuinfo.c
@@ -92,6 +92,8 @@ static const char *const hwcap_str[] = {
"bf16",
"dgh",
"rng",
+ "", /* reserved for BTI */
+ "mte",
NULL
};
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v4 00/26] arm64: Memory Tagging Extension user-space support
From: Catalin Marinas @ 2020-05-15 17:15 UTC (permalink / raw)
To: linux-arm-kernel
Cc: linux-arch, Szabolcs Nagy, Andrey Konovalov, Kevin Brodsky,
Peter Collingbourne, linux-mm, Vincenzo Frascino, Will Deacon,
Dave P Martin
This is the fourth version (third version here [1]) of the series adding
user-space support for the ARMv8.5 Memory Tagging Extension ([2], [3]).
The patches are also available on this branch:
git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux devel/mte-v4
Changes in this version:
- Swap and suspend to disk support for saving/restoring tags.
- Deferred the tag zeroing from clear_page() to set_pte_at() to cope
with RAM filesystems that do not start from a zeroed page. The
copy_page() function was also optimised to only copy tags if the page
has been previously mapped as tagged (PROT_MTE). This mechanism
requires a new PG_arch_2 flag.
- memcmp_pages() rewritten to always return a no-match if at least one
of the pages is tagged (tag comparison avoided).
- ptrace() updated to prevent accessing tags in a page that has not been
mapped with PROT_MTE (PG_arch_2 flag not set).
- copy_mount_options() fix re-implemented to avoid
arch_has_exact_copy_from_user().
- The CPUID handling has been reworked to ensure that, when the feature
is not backed by the DT, the HWCAP is also hidden from user. Note that
the DT description is still under internal discussion on whether we
need it or not.
- A new early param, arm64.mte_disable, was introduced to facilitate
testing with and without MTE on platforms that support it.
- Asynchronous TCF SIGSEGV is no longer forced, so it can be ignored but
the user thread.
- CONFIG_ARM64_MTE is now default y since swap is supported.
To do or discuss:
- prctl() accepting an include vs exclude mask for the GCR_EL1.Excl
field. There is an ongoing discussion on v3 which accepts an include
mask with 0 being a special case equivalent to 1. If this is not
desirable, we can change this to an exclude mask.
- mmap(tagged_addr, PROT_MTE) pre-tagging the memory with the tag given
in the tagged_addr hint.
- ptrace() to expose the prctl() configuration for the user thread (or
the TCF and GCR_EL1.Excl fields).
- coredump (user) to also dump the tags.
- Kselftest patches will be made available.
[1] https://lore.kernel.org/linux-arm-kernel/20200421142603.3894-1-catalin.marinas@arm.com/
[2] https://community.arm.com/developer/ip-products/processors/b/processors-ip-blog/posts/enhancing-memory-safety
[3] https://developer.arm.com/-/media/Arm%20Developer%20Community/PDF/Arm_Memory_Tagging_Extension_Whitepaper.pdf
Catalin Marinas (14):
arm64: mte: Use Normal Tagged attributes for the linear map
arm64: mte: Clear the tags when a page is mapped in user-space with
PROT_MTE
arm64: mte: Tags-aware aware memcmp_pages() implementation
arm64: mte: Add PROT_MTE support to mmap() and mprotect()
mm: Introduce arch_validate_flags()
arm64: mte: Validate the PROT_MTE request via arch_validate_flags()
mm: Allow arm64 mmap(PROT_MTE) on RAM-based files
arm64: mte: Allow user control of the tag check mode via prctl()
arm64: mte: Allow user control of the generated random tags via
prctl()
arm64: mte: Restore the GCR_EL1 register after a suspend
arm64: mte: Add PTRACE_{PEEK,POKE}MTETAGS support
fs: Handle intra-page faults in copy_mount_options()
arm64: mte: Check the DT memory nodes for MTE support
arm64: mte: Introduce early param to disable MTE support
Kevin Brodsky (1):
mm: Introduce arch_calc_vm_flag_bits()
Steven Price (4):
mm: Add PG_ARCH_2 page flag
mm: Add arch hooks for saving/restoring tags
arm64: mte: Enable swap of tagged pages
arm64: mte: Save tags when hibernating
Vincenzo Frascino (7):
arm64: mte: system register definitions
arm64: mte: CPU feature detection and initial sysreg configuration
arm64: mte: Add specific SIGSEGV codes
arm64: mte: Handle synchronous and asynchronous tag check faults
arm64: mte: Tags-aware copy_page() implementation
arm64: mte: Kconfig entry
arm64: mte: Add Memory Tagging Extension documentation
.../admin-guide/kernel-parameters.txt | 4 +
Documentation/arm64/cpu-feature-registers.rst | 2 +
Documentation/arm64/elf_hwcaps.rst | 5 +
Documentation/arm64/index.rst | 1 +
.../arm64/memory-tagging-extension.rst | 297 ++++++++++++++++
arch/arm64/Kconfig | 33 ++
arch/arm64/boot/dts/arm/fvp-base-revc.dts | 1 +
arch/arm64/include/asm/assembler.h | 12 +
arch/arm64/include/asm/cpucaps.h | 4 +-
arch/arm64/include/asm/cpufeature.h | 12 +-
arch/arm64/include/asm/hwcap.h | 1 +
arch/arm64/include/asm/kvm_arm.h | 3 +-
arch/arm64/include/asm/memory.h | 17 +-
arch/arm64/include/asm/mman.h | 78 +++++
arch/arm64/include/asm/mte.h | 86 +++++
arch/arm64/include/asm/page.h | 2 +-
arch/arm64/include/asm/pgtable-prot.h | 2 +
arch/arm64/include/asm/pgtable.h | 45 ++-
arch/arm64/include/asm/processor.h | 4 +
arch/arm64/include/asm/sysreg.h | 62 ++++
arch/arm64/include/asm/thread_info.h | 4 +-
arch/arm64/include/uapi/asm/hwcap.h | 2 +
arch/arm64/include/uapi/asm/mman.h | 14 +
arch/arm64/include/uapi/asm/ptrace.h | 4 +
arch/arm64/kernel/Makefile | 1 +
arch/arm64/kernel/cpufeature.c | 126 ++++++-
arch/arm64/kernel/cpuinfo.c | 2 +
arch/arm64/kernel/entry.S | 37 ++
arch/arm64/kernel/hibernate.c | 118 +++++++
arch/arm64/kernel/mte.c | 324 ++++++++++++++++++
arch/arm64/kernel/process.c | 31 +-
arch/arm64/kernel/ptrace.c | 9 +-
arch/arm64/kernel/signal.c | 8 +
arch/arm64/kernel/suspend.c | 4 +
arch/arm64/kernel/syscall.c | 10 +
arch/arm64/lib/Makefile | 2 +
arch/arm64/lib/mte.S | 140 ++++++++
arch/arm64/mm/Makefile | 1 +
arch/arm64/mm/copypage.c | 14 +-
arch/arm64/mm/dump.c | 4 +
arch/arm64/mm/fault.c | 9 +-
arch/arm64/mm/mmu.c | 22 +-
arch/arm64/mm/mteswap.c | 82 +++++
arch/arm64/mm/proc.S | 8 +-
arch/x86/kernel/signal_compat.c | 2 +-
fs/namespace.c | 24 +-
fs/proc/page.c | 3 +
fs/proc/task_mmu.c | 4 +
include/asm-generic/pgtable.h | 23 ++
include/linux/kernel-page-flags.h | 1 +
include/linux/mm.h | 8 +
include/linux/mman.h | 22 +-
include/linux/page-flags.h | 3 +
include/trace/events/mmflags.h | 9 +-
include/uapi/asm-generic/siginfo.h | 4 +-
include/uapi/linux/prctl.h | 9 +
mm/Kconfig | 3 +
mm/mmap.c | 9 +
mm/mprotect.c | 6 +
mm/page_io.c | 10 +
mm/shmem.c | 9 +
mm/swapfile.c | 2 +
mm/util.c | 2 +-
tools/vm/page-types.c | 2 +
64 files changed, 1765 insertions(+), 37 deletions(-)
create mode 100644 Documentation/arm64/memory-tagging-extension.rst
create mode 100644 arch/arm64/include/asm/mman.h
create mode 100644 arch/arm64/include/asm/mte.h
create mode 100644 arch/arm64/include/uapi/asm/mman.h
create mode 100644 arch/arm64/kernel/mte.c
create mode 100644 arch/arm64/lib/mte.S
create mode 100644 arch/arm64/mm/mteswap.c
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH v4 01/26] arm64: mte: system register definitions
From: Catalin Marinas @ 2020-05-15 17:15 UTC (permalink / raw)
To: linux-arm-kernel
Cc: linux-arch, Szabolcs Nagy, Andrey Konovalov, Kevin Brodsky,
Peter Collingbourne, linux-mm, Vincenzo Frascino, Will Deacon,
Dave P Martin
In-Reply-To: <20200515171612.1020-1-catalin.marinas@arm.com>
From: Vincenzo Frascino <vincenzo.frascino@arm.com>
Add Memory Tagging Extension system register definitions together with
the relevant bitfields.
Signed-off-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
Co-developed-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will@kernel.org>
---
Notes:
v2:
- Added SET_PSTATE_TCO() macro.
arch/arm64/include/asm/kvm_arm.h | 1 +
arch/arm64/include/asm/sysreg.h | 54 ++++++++++++++++++++++++++++
arch/arm64/include/uapi/asm/ptrace.h | 1 +
arch/arm64/kernel/ptrace.c | 2 +-
4 files changed, 57 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h
index 51c1d9918999..8a1cbfd544d6 100644
--- a/arch/arm64/include/asm/kvm_arm.h
+++ b/arch/arm64/include/asm/kvm_arm.h
@@ -12,6 +12,7 @@
#include <asm/types.h>
/* Hyp Configuration Register (HCR) bits */
+#define HCR_ATA (UL(1) << 56)
#define HCR_FWB (UL(1) << 46)
#define HCR_API (UL(1) << 41)
#define HCR_APK (UL(1) << 40)
diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
index c4ac0ac25a00..e823e93b7429 100644
--- a/arch/arm64/include/asm/sysreg.h
+++ b/arch/arm64/include/asm/sysreg.h
@@ -91,10 +91,12 @@
#define PSTATE_PAN pstate_field(0, 4)
#define PSTATE_UAO pstate_field(0, 3)
#define PSTATE_SSBS pstate_field(3, 1)
+#define PSTATE_TCO pstate_field(3, 4)
#define SET_PSTATE_PAN(x) __emit_inst(0xd500401f | PSTATE_PAN | ((!!x) << PSTATE_Imm_shift))
#define SET_PSTATE_UAO(x) __emit_inst(0xd500401f | PSTATE_UAO | ((!!x) << PSTATE_Imm_shift))
#define SET_PSTATE_SSBS(x) __emit_inst(0xd500401f | PSTATE_SSBS | ((!!x) << PSTATE_Imm_shift))
+#define SET_PSTATE_TCO(x) __emit_inst(0xd500401f | PSTATE_TCO | ((!!x) << PSTATE_Imm_shift))
#define __SYS_BARRIER_INSN(CRm, op2, Rt) \
__emit_inst(0xd5000000 | sys_insn(0, 3, 3, (CRm), (op2)) | ((Rt) & 0x1f))
@@ -174,6 +176,8 @@
#define SYS_SCTLR_EL1 sys_reg(3, 0, 1, 0, 0)
#define SYS_ACTLR_EL1 sys_reg(3, 0, 1, 0, 1)
#define SYS_CPACR_EL1 sys_reg(3, 0, 1, 0, 2)
+#define SYS_RGSR_EL1 sys_reg(3, 0, 1, 0, 5)
+#define SYS_GCR_EL1 sys_reg(3, 0, 1, 0, 6)
#define SYS_ZCR_EL1 sys_reg(3, 0, 1, 2, 0)
@@ -211,6 +215,8 @@
#define SYS_ERXADDR_EL1 sys_reg(3, 0, 5, 4, 3)
#define SYS_ERXMISC0_EL1 sys_reg(3, 0, 5, 5, 0)
#define SYS_ERXMISC1_EL1 sys_reg(3, 0, 5, 5, 1)
+#define SYS_TFSR_EL1 sys_reg(3, 0, 5, 6, 0)
+#define SYS_TFSRE0_EL1 sys_reg(3, 0, 5, 6, 1)
#define SYS_FAR_EL1 sys_reg(3, 0, 6, 0, 0)
#define SYS_PAR_EL1 sys_reg(3, 0, 7, 4, 0)
@@ -361,6 +367,7 @@
#define SYS_CCSIDR_EL1 sys_reg(3, 1, 0, 0, 0)
#define SYS_CLIDR_EL1 sys_reg(3, 1, 0, 0, 1)
+#define SYS_GMID_EL1 sys_reg(3, 1, 0, 0, 4)
#define SYS_AIDR_EL1 sys_reg(3, 1, 0, 0, 7)
#define SYS_CSSELR_EL1 sys_reg(3, 2, 0, 0, 0)
@@ -453,6 +460,7 @@
#define SYS_ESR_EL2 sys_reg(3, 4, 5, 2, 0)
#define SYS_VSESR_EL2 sys_reg(3, 4, 5, 2, 3)
#define SYS_FPEXC32_EL2 sys_reg(3, 4, 5, 3, 0)
+#define SYS_TFSR_EL2 sys_reg(3, 4, 5, 6, 0)
#define SYS_FAR_EL2 sys_reg(3, 4, 6, 0, 0)
#define SYS_VDISR_EL2 sys_reg(3, 4, 12, 1, 1)
@@ -509,6 +517,7 @@
#define SYS_AFSR0_EL12 sys_reg(3, 5, 5, 1, 0)
#define SYS_AFSR1_EL12 sys_reg(3, 5, 5, 1, 1)
#define SYS_ESR_EL12 sys_reg(3, 5, 5, 2, 0)
+#define SYS_TFSR_EL12 sys_reg(3, 5, 5, 6, 0)
#define SYS_FAR_EL12 sys_reg(3, 5, 6, 0, 0)
#define SYS_MAIR_EL12 sys_reg(3, 5, 10, 2, 0)
#define SYS_AMAIR_EL12 sys_reg(3, 5, 10, 3, 0)
@@ -524,6 +533,15 @@
/* Common SCTLR_ELx flags. */
#define SCTLR_ELx_DSSBS (BIT(44))
+#define SCTLR_ELx_ATA (BIT(43))
+
+#define SCTLR_ELx_TCF_SHIFT 40
+#define SCTLR_ELx_TCF_NONE (UL(0x0) << SCTLR_ELx_TCF_SHIFT)
+#define SCTLR_ELx_TCF_SYNC (UL(0x1) << SCTLR_ELx_TCF_SHIFT)
+#define SCTLR_ELx_TCF_ASYNC (UL(0x2) << SCTLR_ELx_TCF_SHIFT)
+#define SCTLR_ELx_TCF_MASK (UL(0x3) << SCTLR_ELx_TCF_SHIFT)
+
+#define SCTLR_ELx_ITFSB (BIT(37))
#define SCTLR_ELx_ENIA (BIT(31))
#define SCTLR_ELx_ENIB (BIT(30))
#define SCTLR_ELx_ENDA (BIT(27))
@@ -552,6 +570,14 @@
#endif
/* SCTLR_EL1 specific flags. */
+#define SCTLR_EL1_ATA0 (BIT(42))
+
+#define SCTLR_EL1_TCF0_SHIFT 38
+#define SCTLR_EL1_TCF0_NONE (UL(0x0) << SCTLR_EL1_TCF0_SHIFT)
+#define SCTLR_EL1_TCF0_SYNC (UL(0x1) << SCTLR_EL1_TCF0_SHIFT)
+#define SCTLR_EL1_TCF0_ASYNC (UL(0x2) << SCTLR_EL1_TCF0_SHIFT)
+#define SCTLR_EL1_TCF0_MASK (UL(0x3) << SCTLR_EL1_TCF0_SHIFT)
+
#define SCTLR_EL1_UCI (BIT(26))
#define SCTLR_EL1_E0E (BIT(24))
#define SCTLR_EL1_SPAN (BIT(23))
@@ -586,6 +612,7 @@
#define MAIR_ATTR_DEVICE_GRE UL(0x0c)
#define MAIR_ATTR_NORMAL_NC UL(0x44)
#define MAIR_ATTR_NORMAL_WT UL(0xbb)
+#define MAIR_ATTR_NORMAL_TAGGED UL(0xf0)
#define MAIR_ATTR_NORMAL UL(0xff)
#define MAIR_ATTR_MASK UL(0xff)
@@ -660,11 +687,16 @@
/* id_aa64pfr1 */
#define ID_AA64PFR1_SSBS_SHIFT 4
+#define ID_AA64PFR1_MTE_SHIFT 8
#define ID_AA64PFR1_SSBS_PSTATE_NI 0
#define ID_AA64PFR1_SSBS_PSTATE_ONLY 1
#define ID_AA64PFR1_SSBS_PSTATE_INSNS 2
+#define ID_AA64PFR1_MTE_NI 0x0
+#define ID_AA64PFR1_MTE_EL0 0x1
+#define ID_AA64PFR1_MTE 0x2
+
/* id_aa64zfr0 */
#define ID_AA64ZFR0_F64MM_SHIFT 56
#define ID_AA64ZFR0_F32MM_SHIFT 52
@@ -822,6 +854,28 @@
#define CPACR_EL1_ZEN_EL0EN (BIT(17)) /* enable EL0 access, if EL1EN set */
#define CPACR_EL1_ZEN (CPACR_EL1_ZEN_EL1EN | CPACR_EL1_ZEN_EL0EN)
+/* TCR EL1 Bit Definitions */
+#define SYS_TCR_EL1_TCMA1 (BIT(58))
+#define SYS_TCR_EL1_TCMA0 (BIT(57))
+
+/* GCR_EL1 Definitions */
+#define SYS_GCR_EL1_RRND (BIT(16))
+#define SYS_GCR_EL1_EXCL_MASK 0xffffUL
+
+/* RGSR_EL1 Definitions */
+#define SYS_RGSR_EL1_TAG_MASK 0xfUL
+#define SYS_RGSR_EL1_SEED_SHIFT 8
+#define SYS_RGSR_EL1_SEED_MASK 0xffffUL
+
+/* GMID_EL1 field definitions */
+#define SYS_GMID_EL1_BS_SHIFT 0
+#define SYS_GMID_EL1_BS_SIZE 4
+
+/* TFSR{,E0}_EL1 bit definitions */
+#define SYS_TFSR_EL1_TF0_SHIFT 0
+#define SYS_TFSR_EL1_TF1_SHIFT 1
+#define SYS_TFSR_EL1_TF0 (UL(1) << SYS_TFSR_EL1_TF0_SHIFT)
+#define SYS_TFSR_EL1_TF1 (UK(2) << SYS_TFSR_EL1_TF1_SHIFT)
/* Safe value for MPIDR_EL1: Bit31:RES1, Bit30:U:0, Bit24:MT:0 */
#define SYS_MPIDR_SAFE_VAL (BIT(31))
diff --git a/arch/arm64/include/uapi/asm/ptrace.h b/arch/arm64/include/uapi/asm/ptrace.h
index d1bb5b69f1ce..1daf6dda8af0 100644
--- a/arch/arm64/include/uapi/asm/ptrace.h
+++ b/arch/arm64/include/uapi/asm/ptrace.h
@@ -50,6 +50,7 @@
#define PSR_PAN_BIT 0x00400000
#define PSR_UAO_BIT 0x00800000
#define PSR_DIT_BIT 0x01000000
+#define PSR_TCO_BIT 0x02000000
#define PSR_V_BIT 0x10000000
#define PSR_C_BIT 0x20000000
#define PSR_Z_BIT 0x40000000
diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
index b3d3005d9515..077e352495eb 100644
--- a/arch/arm64/kernel/ptrace.c
+++ b/arch/arm64/kernel/ptrace.c
@@ -1873,7 +1873,7 @@ void syscall_trace_exit(struct pt_regs *regs)
* We also reserve IL for the kernel; SS is handled dynamically.
*/
#define SPSR_EL1_AARCH64_RES0_BITS \
- (GENMASK_ULL(63, 32) | GENMASK_ULL(27, 25) | GENMASK_ULL(23, 22) | \
+ (GENMASK_ULL(63, 32) | GENMASK_ULL(27, 26) | GENMASK_ULL(23, 22) | \
GENMASK_ULL(20, 13) | GENMASK_ULL(11, 10) | GENMASK_ULL(5, 5))
#define SPSR_EL1_AARCH32_RES0_BITS \
(GENMASK_ULL(63, 32) | GENMASK_ULL(22, 22) | GENMASK_ULL(20, 20))
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [GIT PULL] Allwinner Device Tree Changes for 5.8
From: Maxime Ripard @ 2020-05-15 17:12 UTC (permalink / raw)
To: arm, soc; +Cc: Chen-Yu Tsai, linux-arm-kernel, Maxime Ripard
[-- Attachment #1.1: Type: text/plain, Size: 4263 bytes --]
Hi,
Please pull the following changes for the next release.
Thanks!
Maxime
The following changes since commit 8f3d9f354286745c751374f5f1fcafee6b3f3136:
Linux 5.7-rc1 (2020-04-12 12:35:55 -0700)
are available in the Git repository at:
https://git.kernel.org/pub/scm/linux/kernel/git/sunxi/linux.git refs/tags/sunxi-dt-for-5.8-1
for you to fetch changes up to b3a0a2f910c7ae29074415e07f8d830935df19e2:
arm64: dts: allwinner: h6: Add IOMMU (2020-05-15 09:35:39 +0200)
----------------------------------------------------------------
Our usual number of patches to improve the Allwinner Device Tree
support, including:
- Support for the IOMMU on the H6
- Support for cpufreq / thermal throttling on the H6
- Support for the mailbox on the A64, A83t, H3, H5 and H6
- New boards: A20-OLinuXino-LIME-eMMC
-----BEGIN PGP SIGNATURE-----
iHUEABYIAB0WIQRcEzekXsqa64kGDp7j7w1vZxhRxQUCXr7NHgAKCRDj7w1vZxhR
xbhGAQCDavHkpjvq4Hwk/znoS0Y6NvW1JQUyKUWH8K6ah1ZkFwEA5gC0Ac9cbDAk
Q5fZeYl7mPbEL9DI0RphVqHmY2ezXw0=
=WR5/
-----END PGP SIGNATURE-----
----------------------------------------------------------------
Clément Péron (6):
arm64: dts: allwinner: h6: Enable CPU opp tables for Beelink GS1
arm64: dts: allwinner: h6: Enable CPU opp tables for Orange Pi 3
arm64: dts: allwinner: Sort Pine H64 device-tree nodes
arm64: dts: allwinner: h6: Enable CPU opp tables for Pine H64
arm64: dts: allwinner: h6: add voltage range to OPP table
arm64: dts: allwinner: h6: Enable CPU opp tables for Tanix TX6
Jernej Skrabec (2):
arm64: dts: allwinner: h6: orangepi: Add gpio power supply
arm64: dts: allwinner: h6: orangepi: Disable OTG mode
Maxime Ripard (1):
arm64: dts: allwinner: h6: Add IOMMU
Ondrej Jirman (3):
arm64: dts: allwinner: h6: Add thermal trip points/cooling map
arm64: dts: allwinner: h6: Add CPU Operating Performance Points table
arm64: dts: allwinner: sun50i-a64: Add missing address/size-cells
Petr Štetiar (1):
arm64: dts: allwinner: a64: olinuxino: add user red LED
Qiang Yu (1):
ARM: dts: sun8i-h3: add opp table for mali gpu
Samuel Holland (4):
ARM: dts: sunxi: a83t: Add msgbox node
ARM: dts: sunxi: h3/h5: Add msgbox node
arm64: dts: allwinner: a64: Add msgbox node
arm64: dts: allwinner: h6: Add msgbox node
Sebastian Meyer (1):
arm64: allwinner: h6: orangepi-lite2: Support BT+WIFI combo module
Stefan Mavrodiev (2):
dt-bindings: arm: sunxi: Add compatible for A20-OLinuXino-LIME-eMMC
ARM: dts: sun7i: Add A20-OLinuXino-LIME-eMMC
Vincent Stehlé (1):
ARM: dts: sun8i-h2-plus-bananapi-m2-zero: Fix led polarity
Yangtao Li (1):
arm64: dts: allwinner: h6: Add clock to CPU cores
Documentation/devicetree/bindings/arm/sunxi.yaml | 5 +-
arch/arm/boot/dts/Makefile | 1 +-
arch/arm/boot/dts/sun7i-a20-olinuxino-lime-emmc.dts | 32 ++++-
arch/arm/boot/dts/sun8i-a83t.dtsi | 10 +-
arch/arm/boot/dts/sun8i-h2-plus-bananapi-m2-zero.dts | 2 +-
arch/arm/boot/dts/sun8i-h3.dtsi | 24 ++-
arch/arm/boot/dts/sunxi-h3-h5.dtsi | 10 +-
arch/arm64/boot/dts/allwinner/sun50i-a64-olinuxino.dts | 9 +-
arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 12 +-
arch/arm64/boot/dts/allwinner/sun50i-h6-beelink-gs1.dts | 9 +-
arch/arm64/boot/dts/allwinner/sun50i-h6-cpu-opp.dtsi | 117 ++++++++++++++-
arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts | 3 +-
arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-lite2.dts | 65 ++++++++-
arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi.dtsi | 17 +-
arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts | 43 ++---
arch/arm64/boot/dts/allwinner/sun50i-h6-tanix-tx6.dts | 13 ++-
arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 60 +++++++-
17 files changed, 408 insertions(+), 24 deletions(-)
create mode 100644 arch/arm/boot/dts/sun7i-a20-olinuxino-lime-emmc.dts
create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-h6-cpu-opp.dtsi
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
[-- Attachment #2: Type: text/plain, Size: 176 bytes --]
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [GIT PULL] Allwinner Fixes for 5.7
From: Maxime Ripard @ 2020-05-15 17:10 UTC (permalink / raw)
To: arm, soc; +Cc: Chen-Yu Tsai, linux-arm-kernel, Maxime Ripard
[-- Attachment #1.1: Type: text/plain, Size: 1355 bytes --]
Hi,
Please pull the following changes for the current release.
Thanks!
Maxime
The following changes since commit 8f3d9f354286745c751374f5f1fcafee6b3f3136:
Linux 5.7-rc1 (2020-04-12 12:35:55 -0700)
are available in the Git repository at:
https://git.kernel.org/pub/scm/linux/kernel/git/sunxi/linux.git refs/tags/sunxi-fixes-for-5.7-1
for you to fetch changes up to 29ee412bb7090023a8dba15726d9be2f4f2644a4:
arm64: dts: allwinner: a64: Remove unused SPDIF sound card (2020-05-04 13:44:57 +0200)
----------------------------------------------------------------
Two fixes for the Allwinner SoCs, one to remove some inexistant sound card on
the A64, and one to fix the audio codec regulator on the pinetab.
-----BEGIN PGP SIGNATURE-----
iHUEABYIAB0WIQRcEzekXsqa64kGDp7j7w1vZxhRxQUCXr7M6gAKCRDj7w1vZxhR
xQxeAP4qE6EtWCAZoryxU3KMJGPRSDktuGFlzPkOL77svJvT9wEAkPvvgQtYk0UI
7nCsv4YVvAZGCRVocUx2XUS/uFLhbA4=
=BUW7
-----END PGP SIGNATURE-----
----------------------------------------------------------------
Samuel Holland (2):
arm64: dts: allwinner: a64: pinetab: Fix cpvdd supply name
arm64: dts: allwinner: a64: Remove unused SPDIF sound card
arch/arm64/boot/dts/allwinner/sun50i-a64-pinetab.dts | 2 +-
arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 18 ------------------
2 files changed, 1 insertion(+), 19 deletions(-)
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
[-- Attachment #2: Type: text/plain, Size: 176 bytes --]
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [GIT PULL] Allwinner arm Defconfig Changes for 5.8
From: Maxime Ripard @ 2020-05-15 17:09 UTC (permalink / raw)
To: arm, soc; +Cc: Chen-Yu Tsai, linux-arm-kernel, Maxime Ripard
[-- Attachment #1.1: Type: text/plain, Size: 1277 bytes --]
Hi,
Please pull the following changes for the next release.
Thanks!
Maxime
The following changes since commit 8f3d9f354286745c751374f5f1fcafee6b3f3136:
Linux 5.7-rc1 (2020-04-12 12:35:55 -0700)
are available in the Git repository at:
https://git.kernel.org/pub/scm/linux/kernel/git/sunxi/linux.git refs/tags/sunxi-config-for-5.8-1
for you to fetch changes up to cdaeaa2560a9511374986cf7ce6e164318caae53:
arm64: configs: Enable sun50i cpufreq nvmem (2020-04-20 10:25:20 +0200)
----------------------------------------------------------------
Two patches to enable the new cpufreq support on the H6 for the arm64
defconfig to enable the audio codec in sunxi_defconfig.
-----BEGIN PGP SIGNATURE-----
iHUEABYIAB0WIQRcEzekXsqa64kGDp7j7w1vZxhRxQUCXr7MmQAKCRDj7w1vZxhR
xYFJAQC7OE0ip7aQrJY24AXQgeA1abiQ1+P1oHbHW6E7qnXiGgD9Exd18pO1N1JH
URcmEMjg8plFQn9+gGcHy7VFhE5V8w8=
=ut84
-----END PGP SIGNATURE-----
----------------------------------------------------------------
Clément Péron (1):
arm64: configs: Enable sun50i cpufreq nvmem
Corentin Labbe (1):
ARM: configs: sunxi: Add sun8i analog codec
arch/arm/configs/sunxi_defconfig | 1 +
arch/arm64/configs/defconfig | 1 +
2 files changed, 2 insertions(+)
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
[-- Attachment #2: Type: text/plain, Size: 176 bytes --]
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH v4 2/2] irqchip/gic-v3-its: Balance initial LPI affinity across CPUs
From: Marc Zyngier @ 2020-05-15 16:57 UTC (permalink / raw)
To: linux-kernel, linux-arm-kernel
Cc: Jason Cooper, chenxiang, John Garry, Ming Lei, Zhou Wang,
Thomas Gleixner, kernel-team
In-Reply-To: <20200515165752.121296-1-maz@kernel.org>
When mapping a LPI, the ITS driver picks the first possible
affinity, which is in most cases CPU0, assuming that if
that's not suitable, someone will come and set the affinity
to something more interesting.
It apparently isn't the case, and people complain of poor
performance when many interrupts are glued to the same CPU.
So let's place the interrupts by finding the "least loaded"
CPU (that is, the one that has the fewer LPIs mapped to it).
So called 'managed' interrupts are an interesting case where
the affinity is actually dictated by the kernel itself, and
we should honor this.
Reported-by: John Garry <john.garry@huawei.com>
Link: https://lore.kernel.org/r/1575642904-58295-1-git-send-email-john.garry@huawei.com
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
drivers/irqchip/irq-gic-v3-its.c | 127 ++++++++++++++++++++++++-------
1 file changed, 100 insertions(+), 27 deletions(-)
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 4eb8441d0c2b..2aaf1e6bdc89 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -1541,15 +1541,104 @@ static void its_dec_lpi_count(struct irq_data *d, int cpu)
atomic_dec(&per_cpu_ptr(&cpu_lpi_count, cpu)->unmanaged);
}
+static unsigned int cpumask_pick_least_loaded(struct irq_data *d,
+ const struct cpumask *cpu_mask)
+{
+ unsigned int cpu = nr_cpu_ids, tmp;
+ int count = S32_MAX;
+
+ for_each_cpu(tmp, cpu_mask) {
+ int this_count = its_read_lpi_count(d, tmp);
+ if (this_count < count) {
+ cpu = tmp;
+ count = this_count;
+ }
+ }
+
+ return cpu;
+}
+
+/*
+ * As suggested by Thomas Gleixner in:
+ * https://lore.kernel.org/r/87h80q2aoc.fsf@nanos.tec.linutronix.de
+ */
+static int its_select_cpu(struct irq_data *d,
+ const struct cpumask *aff_mask)
+{
+ struct its_device *its_dev = irq_data_get_irq_chip_data(d);
+ cpumask_var_t tmpmask;
+ int cpu, node;
+
+ if (!alloc_cpumask_var(&tmpmask, GFP_KERNEL))
+ return -ENOMEM;
+
+ node = its_dev->its->numa_node;
+
+ if (!irqd_affinity_is_managed(d)) {
+ /* First try the NUMA node */
+ if (node != NUMA_NO_NODE) {
+ /*
+ * Try the intersection of the affinity mask and the
+ * node mask (and the online mask, just to be safe).
+ */
+ cpumask_and(tmpmask, cpumask_of_node(node), aff_mask);
+ cpumask_and(tmpmask, tmpmask, cpu_online_mask);
+
+ /*
+ * Ideally, we would check if the mask is empty, and
+ * try again on the full node here.
+ *
+ * But it turns out that the way API describes the
+ * affinity for ITSs only deals about memory, and
+ * not target CPUs, so it cannot describe a single
+ * ITS placed next to two NUMA nodes.
+ *
+ * Instead, just fallback on the online mask. This
+ * diverges from Thomas' suggestion above.
+ */
+ cpu = cpumask_pick_least_loaded(d, tmpmask);
+ if (cpu < nr_cpu_ids)
+ goto out;
+
+ /* If we can't cross sockets, give up */
+ if ((its_dev->its->flags & ITS_FLAGS_WORKAROUND_CAVIUM_23144))
+ goto out;
+
+ /* If the above failed, expand the search */
+ }
+
+ /* Try the intersection of the affinity and online masks */
+ cpumask_and(tmpmask, aff_mask, cpu_online_mask);
+
+ /* If that doesn't fly, the online mask is the last resort */
+ if (cpumask_empty(tmpmask))
+ cpumask_copy(tmpmask, cpu_online_mask);
+
+ cpu = cpumask_pick_least_loaded(d, tmpmask);
+ } else {
+ cpumask_and(tmpmask, irq_data_get_affinity_mask(d), cpu_online_mask);
+
+ /* If we cannot cross sockets, limit the search to that node */
+ if ((its_dev->its->flags & ITS_FLAGS_WORKAROUND_CAVIUM_23144) &&
+ node != NUMA_NO_NODE)
+ cpumask_and(tmpmask, tmpmask, cpumask_of_node(node));
+
+ cpu = cpumask_pick_least_loaded(d, tmpmask);
+ }
+out:
+ free_cpumask_var(tmpmask);
+
+ pr_debug("IRQ%d -> %*pbl CPU%d\n", d->irq, cpumask_pr_args(aff_mask), cpu);
+ return cpu;
+}
+
static int its_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
bool force)
{
- unsigned int cpu;
- const struct cpumask *cpu_mask = cpu_online_mask;
struct its_device *its_dev = irq_data_get_irq_chip_data(d);
struct its_collection *target_col;
u32 id = its_get_event_id(d);
- int prev_cpu;
+ int cpu, prev_cpu;
/* A forwarded interrupt should use irq_set_vcpu_affinity */
if (irqd_is_forwarded_to_vcpu(d))
@@ -1558,18 +1647,12 @@ static int its_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
prev_cpu = its_dev->event_map.col_map[id];
its_dec_lpi_count(d, prev_cpu);
- /* lpi cannot be routed to a redistributor that is on a foreign node */
- if (its_dev->its->flags & ITS_FLAGS_WORKAROUND_CAVIUM_23144) {
- if (its_dev->its->numa_node >= 0) {
- cpu_mask = cpumask_of_node(its_dev->its->numa_node);
- if (!cpumask_intersects(mask_val, cpu_mask))
- goto err;
- }
- }
-
- cpu = cpumask_any_and(mask_val, cpu_mask);
+ if (!force)
+ cpu = its_select_cpu(d, mask_val);
+ else
+ cpu = cpumask_pick_least_loaded(d, mask_val);
- if (cpu >= nr_cpu_ids)
+ if (cpu < 0 || cpu >= nr_cpu_ids)
goto err;
/* don't set the affinity when the target cpu is same as current one */
@@ -3473,21 +3556,11 @@ static int its_irq_domain_activate(struct irq_domain *domain,
{
struct its_device *its_dev = irq_data_get_irq_chip_data(d);
u32 event = its_get_event_id(d);
- const struct cpumask *cpu_mask = cpu_online_mask;
int cpu;
- /* get the cpu_mask of local node */
- if (its_dev->its->numa_node >= 0)
- cpu_mask = cpumask_of_node(its_dev->its->numa_node);
-
- /* Bind the LPI to the first possible CPU */
- cpu = cpumask_first_and(cpu_mask, cpu_online_mask);
- if (cpu >= nr_cpu_ids) {
- if (its_dev->its->flags & ITS_FLAGS_WORKAROUND_CAVIUM_23144)
- return -EINVAL;
-
- cpu = cpumask_first(cpu_online_mask);
- }
+ cpu = its_select_cpu(d, cpu_online_mask);
+ if (cpu < 0 || cpu >= nr_cpu_ids)
+ return -EINVAL;
its_inc_lpi_count(d, cpu);
its_dev->event_map.col_map[event] = cpu;
--
2.26.2
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v4 1/2] irqchip/gic-v3-its: Track LPI distribution on a per CPU basis
From: Marc Zyngier @ 2020-05-15 16:57 UTC (permalink / raw)
To: linux-kernel, linux-arm-kernel
Cc: Jason Cooper, chenxiang, John Garry, Ming Lei, Zhou Wang,
Thomas Gleixner, kernel-team
In-Reply-To: <20200515165752.121296-1-maz@kernel.org>
In order to improve the distribution of LPIs among CPUs, let start by
tracking the number of LPIs assigned to CPUs, both for managed and
non-managed interrupts (as separate counters).
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
drivers/irqchip/irq-gic-v3-its.c | 49 ++++++++++++++++++++++++++++++--
1 file changed, 46 insertions(+), 3 deletions(-)
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 124251b0ccba..4eb8441d0c2b 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -174,6 +174,13 @@ static struct {
int next_victim;
} vpe_proxy;
+struct cpu_lpi_count {
+ atomic_t managed;
+ atomic_t unmanaged;
+};
+
+static DEFINE_PER_CPU(struct cpu_lpi_count, cpu_lpi_count);
+
static LIST_HEAD(its_nodes);
static DEFINE_RAW_SPINLOCK(its_lock);
static struct rdists *gic_rdists;
@@ -1510,6 +1517,30 @@ static void its_unmask_irq(struct irq_data *d)
lpi_update_config(d, 0, LPI_PROP_ENABLED);
}
+static __maybe_unused u32 its_read_lpi_count(struct irq_data *d, int cpu)
+{
+ if (irqd_affinity_is_managed(d))
+ return atomic_read(&per_cpu_ptr(&cpu_lpi_count, cpu)->managed);
+
+ return atomic_read(&per_cpu_ptr(&cpu_lpi_count, cpu)->unmanaged);
+}
+
+static void its_inc_lpi_count(struct irq_data *d, int cpu)
+{
+ if (irqd_affinity_is_managed(d))
+ atomic_inc(&per_cpu_ptr(&cpu_lpi_count, cpu)->managed);
+ else
+ atomic_inc(&per_cpu_ptr(&cpu_lpi_count, cpu)->unmanaged);
+}
+
+static void its_dec_lpi_count(struct irq_data *d, int cpu)
+{
+ if (irqd_affinity_is_managed(d))
+ atomic_dec(&per_cpu_ptr(&cpu_lpi_count, cpu)->managed);
+ else
+ atomic_dec(&per_cpu_ptr(&cpu_lpi_count, cpu)->unmanaged);
+}
+
static int its_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
bool force)
{
@@ -1518,34 +1549,44 @@ static int its_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
struct its_device *its_dev = irq_data_get_irq_chip_data(d);
struct its_collection *target_col;
u32 id = its_get_event_id(d);
+ int prev_cpu;
/* A forwarded interrupt should use irq_set_vcpu_affinity */
if (irqd_is_forwarded_to_vcpu(d))
return -EINVAL;
+ prev_cpu = its_dev->event_map.col_map[id];
+ its_dec_lpi_count(d, prev_cpu);
+
/* lpi cannot be routed to a redistributor that is on a foreign node */
if (its_dev->its->flags & ITS_FLAGS_WORKAROUND_CAVIUM_23144) {
if (its_dev->its->numa_node >= 0) {
cpu_mask = cpumask_of_node(its_dev->its->numa_node);
if (!cpumask_intersects(mask_val, cpu_mask))
- return -EINVAL;
+ goto err;
}
}
cpu = cpumask_any_and(mask_val, cpu_mask);
if (cpu >= nr_cpu_ids)
- return -EINVAL;
+ goto err;
/* don't set the affinity when the target cpu is same as current one */
- if (cpu != its_dev->event_map.col_map[id]) {
+ if (cpu != prev_cpu) {
target_col = &its_dev->its->collections[cpu];
its_send_movi(its_dev, target_col, id);
its_dev->event_map.col_map[id] = cpu;
irq_data_update_effective_affinity(d, cpumask_of(cpu));
}
+ its_inc_lpi_count(d, cpu);
+
return IRQ_SET_MASK_OK_DONE;
+
+err:
+ its_inc_lpi_count(d, prev_cpu);
+ return -EINVAL;
}
static u64 its_irq_get_msi_base(struct its_device *its_dev)
@@ -3448,6 +3489,7 @@ static int its_irq_domain_activate(struct irq_domain *domain,
cpu = cpumask_first(cpu_online_mask);
}
+ its_inc_lpi_count(d, cpu);
its_dev->event_map.col_map[event] = cpu;
irq_data_update_effective_affinity(d, cpumask_of(cpu));
@@ -3462,6 +3504,7 @@ static void its_irq_domain_deactivate(struct irq_domain *domain,
struct its_device *its_dev = irq_data_get_irq_chip_data(d);
u32 event = its_get_event_id(d);
+ its_dec_lpi_count(d, its_dev->event_map.col_map[event]);
/* Stop the delivery of interrupts */
its_send_discard(its_dev, event);
}
--
2.26.2
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v4 0/2] irqchip/gic-v3-its: Balance LPI affinity across CPUs
From: Marc Zyngier @ 2020-05-15 16:57 UTC (permalink / raw)
To: linux-kernel, linux-arm-kernel
Cc: Jason Cooper, chenxiang, John Garry, Ming Lei, Zhou Wang,
Thomas Gleixner, kernel-team
When mapping a LPI, the ITS driver picks the first possible
affinity, which is in most cases CPU0, assuming that if
that's not suitable, someone will come and set the affinity
to something more interesting.
It apparently isn't the case, and people complain of poor
performance when many interrupts are glued to the same CPU.
So let's place the interrupts by finding the "least loaded"
CPU (that is, the one that has the fewer LPIs mapped to it).
So called 'managed' interrupts are an interesting case where
the affinity is actually dictated by the kernel itself, and
we should honor this.
* From v3:
- Always pre-decrement/post-increment affinity to avoid useless
changes of affinity (John)
- Don't use the node mask as a superset of the proposed affinity
as the ACPI tables can't really describe this (John)
- Rebased on v5.7-rc5
* From v2:
- Split accounting from CPU selection
- Track managed and unmanaged interrupts separately
Marc Zyngier (2):
irqchip/gic-v3-its: Track LPI distribution on a per CPU basis
irqchip/gic-v3-its: Balance initial LPI affinity across CPUs
drivers/irqchip/irq-gic-v3-its.c | 170 ++++++++++++++++++++++++++-----
1 file changed, 143 insertions(+), 27 deletions(-)
--
2.26.2
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH 1/4] dt-bindings: i2c: Document I2C controller binding for MT6797 SoC
From: Wolfram Sang @ 2020-05-15 16:56 UTC (permalink / raw)
To: Matthias Brugger
Cc: Rob Herring, devicetree, linux-kernel, robh+dt, linux-mediatek,
Manivannan Sadhasivam, adamboardman, linux-arm-kernel
In-Reply-To: <aa9ea456-dbee-229c-aea0-4860c6eb7adf@gmail.com>
[-- Attachment #1.1: Type: text/plain, Size: 811 bytes --]
On Fri, May 15, 2020 at 04:48:28PM +0200, Matthias Brugger wrote:
> Hi Wolfram,
>
> On 26/02/2020 23:23, Rob Herring wrote:
> > On Sat, 22 Feb 2020 21:54:41 +0530, Manivannan Sadhasivam wrote:
> >> I2C controller driver for MT6577 SoC is reused for MT6797 SoC. Hence,
> >> document that in DT binding.
> >>
> >> Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
> >> ---
> >> Documentation/devicetree/bindings/i2c/i2c-mt65xx.txt | 1 +
> >> 1 file changed, 1 insertion(+)
> >>
> >
> > Acked-by: Rob Herring <robh@kernel.org>
> >
>
> Do you want to take this thorough your tree or are you OK if I take it thorough
> mine?
The I2C list is neither in the CC field, nor is the patch in patchwork.
I suggest you take it.
Acked-by: Wolfram Sang <wsa@kernel.org>
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
[-- Attachment #2: Type: text/plain, Size: 176 bytes --]
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCHv2 6/7] Input: Add "inhibited" property
From: Andrzej Pietrasiewicz @ 2020-05-15 16:52 UTC (permalink / raw)
To: linux-input, linux-acpi, linux-iio, linux-arm-kernel,
linux-samsung-soc, linux-tegra, patches, ibm-acpi-devel,
platform-driver-x86
Cc: Nick Dyer, Laxman Dewangan, Peter Meerwald-Stadler, kernel,
Fabio Estevam, Lars-Peter Clausen, Krzysztof Kozlowski,
Jonathan Hunter, Kukjin Kim, NXP Linux Team, Sylvain Lemieux,
Len Brown, Michael Hennerich, Sascha Hauer,
Henrique de Moraes Holschuh, Vladimir Zapolskiy, Hans de Goede,
Barry Song, Ferruh Yigit, Patrik Fimml, Dmitry Torokhov,
Rafael J . Wysocki, Andrzej Pietrasiewicz, Thierry Reding,
Sangwon Jee, Pengutronix Kernel Team, Hartmut Knaack, Shawn Guo,
Jonathan Cameron
In-Reply-To: <20200515164943.28480-1-andrzej.p@collabora.com>
From: Patrik Fimml <patrikf@chromium.org>
Userspace might want to implement a policy to temporarily disregard input
from certain devices, including not treating them as wakeup sources.
An example use case is a laptop, whose keyboard can be folded under the
screen to create tablet-like experience. The user then must hold the laptop
in such a way that it is difficult to avoid pressing the keyboard keys. It
is therefore desirable to temporarily disregard input from the keyboard,
until it is folded back. This obviously is a policy which should be kept
out of the kernel, but the kernel must provide suitable means to implement
such a policy.
This patch adds a sysfs interface for exactly this purpose.
To implement the said interface it adds an "inhibited" property to struct
input_dev and two optional methods - inhibit() and uninhibit(), and
effectively creates four states a device can be in: closed uninhibited,
closed inhibited, open uninhibited, open inhibited. It also defers calling
driver's ->open() and ->close() to until they are actually needed, e.g. it
makes no sense to prepare the underlying device for generating events
(->open()) if the device is inhibited.
uninhibit
closed <------------ closed
uninhibited ------------> inhibited
| ^ inhibit | ^
1st | | 1st | |
open | | open | |
| | | |
| | last | | last
| | close | | close
v | uninhibit v |
open <------------ open
uninhibited ------------> inhibited
The top inhibit/uninhibit transition happens when users == 0.
The bottom inhibit/uninhibit transition happens when users > 0.
The left open/close transition happens when !inhibited.
The right open/close transition happens when inhibited.
Due to all transitions being serialized with dev->mutex, it is impossible
to have "diagonal" transitions between closed uninhibited and open
inhibited or between open uninhibited and closed inhibited.
open() and close() - if provided - are called in both inhibit and uninhibit
paths. Please note that close() does not return a value, so if your driver
might need failing inhibiting, you need to provide inhibit() so that it
returns a value to check.
It is drivers' responsibility to implement their inhibiting capability in
terms of whatever is suitable in their context, be it open/close,
inhibit/uninhibit or a combination of both. The drivers should also ensure
that they properly interact with suspend/resume and PM runtime, because
most likely a side effect of inhibiting a device should be its going into
low power mode. Properly inhibiting a device means to prevent it from being
a wakeup source, so drivers should also take care of that.
Signed-off-by: Patrik Fimml <patrikf@chromium.org>
Co-developed-by: Andrzej Pietrasiewicz <andrzej.p@collabora.com>
Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@collabora.com>
---
drivers/input/input.c | 136 ++++++++++++++++++++++++++++++++++++++----
include/linux/input.h | 8 +++
2 files changed, 134 insertions(+), 10 deletions(-)
diff --git a/drivers/input/input.c b/drivers/input/input.c
index 41377bfa142d..5b859a178c11 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -367,8 +367,13 @@ static int input_get_disposition(struct input_dev *dev,
static void input_handle_event(struct input_dev *dev,
unsigned int type, unsigned int code, int value)
{
- int disposition = input_get_disposition(dev, type, code, &value);
+ int disposition;
+ /* filter-out events from inhibited devices */
+ if (dev->inhibited)
+ return;
+
+ disposition = input_get_disposition(dev, type, code, &value);
if (disposition != INPUT_IGNORE_EVENT && type != EV_SYN)
add_input_randomness(type, code, value);
@@ -612,7 +617,7 @@ int input_open_device(struct input_handle *handle)
handle->open++;
- if (dev->users++) {
+ if (dev->users++ || dev->inhibited) {
/*
* Device is already opened, so we can exit immediately and
* report success.
@@ -660,6 +665,14 @@ int input_flush_device(struct input_handle *handle, struct file *file)
}
EXPORT_SYMBOL(input_flush_device);
+static inline void input_stop(struct input_dev *dev)
+{
+ if (dev->poller)
+ input_dev_poller_stop(dev->poller);
+ if (dev->close)
+ dev->close(dev);
+}
+
/**
* input_close_device - close input device
* @handle: handle through which device is being accessed
@@ -675,13 +688,8 @@ void input_close_device(struct input_handle *handle)
__input_release_device(handle);
- if (!--dev->users) {
- if (dev->poller)
- input_dev_poller_stop(dev->poller);
-
- if (dev->close)
- dev->close(dev);
- }
+ if (!dev->inhibited && !--dev->users)
+ input_stop(dev);
if (!--handle->open) {
/*
@@ -1416,12 +1424,49 @@ static ssize_t input_dev_show_properties(struct device *dev,
}
static DEVICE_ATTR(properties, S_IRUGO, input_dev_show_properties, NULL);
+static int input_inhibit(struct input_dev *dev);
+static int input_uninhibit(struct input_dev *dev);
+
+static ssize_t inhibited_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct input_dev *input_dev = to_input_dev(dev);
+
+ return scnprintf(buf, PAGE_SIZE, "%d\n", input_dev->inhibited);
+}
+
+static ssize_t inhibited_store(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t len)
+{
+ struct input_dev *input_dev = to_input_dev(dev);
+ ssize_t rv;
+ bool inhibited;
+
+ if (strtobool(buf, &inhibited))
+ return -EINVAL;
+
+ if (inhibited)
+ rv = input_inhibit(input_dev);
+ else
+ rv = input_uninhibit(input_dev);
+
+ if (rv != 0)
+ return rv;
+
+ return len;
+}
+
+static DEVICE_ATTR_RW(inhibited);
+
static struct attribute *input_dev_attrs[] = {
&dev_attr_name.attr,
&dev_attr_phys.attr,
&dev_attr_uniq.attr,
&dev_attr_modalias.attr,
&dev_attr_properties.attr,
+ &dev_attr_inhibited.attr,
NULL
};
@@ -1703,6 +1748,77 @@ void input_reset_device(struct input_dev *dev)
}
EXPORT_SYMBOL(input_reset_device);
+static int input_inhibit(struct input_dev *dev)
+{
+ int ret = 0;
+
+ mutex_lock(&dev->mutex);
+
+ if (dev->inhibited)
+ goto out;
+
+ if (dev->users) {
+ if (dev->inhibit) {
+ ret = dev->inhibit(dev);
+ if (ret)
+ goto out;
+ }
+ input_stop(dev);
+ }
+
+ spin_lock_irq(&dev->event_lock);
+ input_dev_release_keys(dev);
+ input_dev_toggle(dev, false);
+ spin_unlock_irq(&dev->event_lock);
+
+ dev->inhibited = true;
+
+out:
+ mutex_unlock(&dev->mutex);
+ return ret;
+}
+
+static int input_uninhibit(struct input_dev *dev)
+{
+ int ret = 0;
+
+ mutex_lock(&dev->mutex);
+
+ if (!dev->inhibited)
+ goto out;
+
+ if (dev->users) {
+ if (dev->open) {
+ ret = dev->open(dev);
+ if (ret)
+ goto toggle;
+ }
+ if (dev->uninhibit) {
+ ret = dev->uninhibit(dev);
+ if (ret) {
+ if (dev->close)
+ dev->close(dev);
+ goto toggle;
+ }
+ }
+ if (dev->poller)
+ input_dev_poller_start(dev->poller);
+ }
+
+ dev->inhibited = false;
+
+toggle:
+ if (!dev->inhibited) {
+ spin_lock_irq(&dev->event_lock);
+ input_dev_toggle(dev, true);
+ spin_unlock_irq(&dev->event_lock);
+ }
+
+out:
+ mutex_unlock(&dev->mutex);
+ return ret;
+}
+
#ifdef CONFIG_PM_SLEEP
static int input_dev_suspend(struct device *dev)
{
@@ -2131,7 +2247,7 @@ bool input_device_enabled(struct input_dev *dev)
{
lockdep_assert_held(&dev->mutex);
- return dev->users > 0;
+ return !dev->inhibited && dev->users > 0;
}
EXPORT_SYMBOL_GPL(input_device_enabled);
diff --git a/include/linux/input.h b/include/linux/input.h
index eda4587dba67..8d0dcfaeaf6f 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -127,6 +127,9 @@ enum input_clock_type {
* and needs not be explicitly unregistered or freed.
* @timestamp: storage for a timestamp set by input_set_timestamp called
* by a driver
+ * @inhibit: makes the device ignore all input
+ * @uninhibit: undoes the effect of inhibit
+ * @inhibited: indicates that the input device is inhibited
*/
struct input_dev {
const char *name;
@@ -201,6 +204,11 @@ struct input_dev {
bool devres_managed;
ktime_t timestamp[INPUT_CLK_MAX];
+
+ int (*inhibit)(struct input_dev *dev);
+ int (*uninhibit)(struct input_dev *dev);
+
+ bool inhibited;
};
#define to_input_dev(d) container_of(d, struct input_dev, dev)
--
2.17.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCHv2 4/7] iio: adc: exynos: Use input_device_enabled()
From: Andrzej Pietrasiewicz @ 2020-05-15 16:52 UTC (permalink / raw)
To: linux-input, linux-iio, linux-arm-kernel, linux-samsung-soc
Cc: Lars-Peter Clausen, Krzysztof Kozlowski, Andrzej Pietrasiewicz,
Kukjin Kim, Peter Meerwald-Stadler, Hartmut Knaack, kernel,
Jonathan Cameron
In-Reply-To: <20200515164943.28480-1-andrzej.p@collabora.com>
A new helper is available, so use it. Inspecting 'users' member of
input_dev requires taking device's mutex.
Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@collabora.com>
---
drivers/iio/adc/exynos_adc.c | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/drivers/iio/adc/exynos_adc.c b/drivers/iio/adc/exynos_adc.c
index 22131a677445..1253d94089a7 100644
--- a/drivers/iio/adc/exynos_adc.c
+++ b/drivers/iio/adc/exynos_adc.c
@@ -630,10 +630,13 @@ static irqreturn_t exynos_ts_isr(int irq, void *dev_id)
struct exynos_adc *info = dev_id;
struct iio_dev *dev = dev_get_drvdata(info->dev);
u32 x, y;
- bool pressed;
+ bool pressed, cont;
int ret;
- while (info->input->users) {
+ mutex_lock(&info->input);
+ cont = input_device_enabled(info->input);
+ mutex_unlock(&info->input);
+ while (cont) {
ret = exynos_read_s3c64xx_ts(dev, &x, &y);
if (ret == -ETIMEDOUT)
break;
@@ -651,6 +654,10 @@ static irqreturn_t exynos_ts_isr(int irq, void *dev_id)
input_sync(info->input);
usleep_range(1000, 1100);
+
+ mutex_lock(&info->input);
+ cont = input_device_enabled(info->input);
+ mutex_unlock(&info->input);
}
writel(0, ADC_V1_CLRINTPNDNUP(info->regs));
--
2.17.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCHv2 2/7] Input: use input_device_enabled()
From: Andrzej Pietrasiewicz @ 2020-05-15 16:51 UTC (permalink / raw)
To: linux-input, linux-arm-kernel, linux-tegra, patches
Cc: Barry Song, Sangwon Jee, Ferruh Yigit, Nick Dyer,
Michael Hennerich, Shawn Guo, Sascha Hauer, Dmitry Torokhov,
Vladimir Zapolskiy, Andrzej Pietrasiewicz, Hans de Goede,
Laxman Dewangan, Thierry Reding, NXP Linux Team,
Pengutronix Kernel Team, Sylvain Lemieux, kernel, Jonathan Hunter,
Fabio Estevam
In-Reply-To: <20200515164943.28480-1-andrzej.p@collabora.com>
Use the newly added helper in relevant input drivers.
Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@collabora.com>
---
drivers/input/joystick/xpad.c | 4 ++--
drivers/input/keyboard/ep93xx_keypad.c | 2 +-
drivers/input/keyboard/gpio_keys.c | 4 ++--
drivers/input/keyboard/imx_keypad.c | 4 ++--
drivers/input/keyboard/ipaq-micro-keys.c | 2 +-
drivers/input/keyboard/lpc32xx-keys.c | 4 ++--
drivers/input/keyboard/pmic8xxx-keypad.c | 4 ++--
drivers/input/keyboard/pxa27x_keypad.c | 2 +-
drivers/input/keyboard/samsung-keypad.c | 4 ++--
drivers/input/keyboard/spear-keyboard.c | 8 ++++----
drivers/input/keyboard/st-keyscan.c | 4 ++--
drivers/input/keyboard/tegra-kbc.c | 4 ++--
drivers/input/misc/drv260x.c | 4 ++--
drivers/input/misc/drv2665.c | 4 ++--
drivers/input/misc/drv2667.c | 4 ++--
drivers/input/misc/gp2ap002a00f.c | 4 ++--
drivers/input/misc/kxtj9.c | 4 ++--
drivers/input/misc/sirfsoc-onkey.c | 2 +-
drivers/input/mouse/navpoint.c | 4 ++--
drivers/input/touchscreen/ad7879.c | 6 +++---
drivers/input/touchscreen/atmel_mxt_ts.c | 4 ++--
drivers/input/touchscreen/auo-pixcir-ts.c | 8 ++++----
drivers/input/touchscreen/bu21029_ts.c | 4 ++--
drivers/input/touchscreen/chipone_icn8318.c | 4 ++--
drivers/input/touchscreen/cyttsp_core.c | 4 ++--
drivers/input/touchscreen/eeti_ts.c | 4 ++--
drivers/input/touchscreen/ektf2127.c | 4 ++--
drivers/input/touchscreen/imx6ul_tsc.c | 4 ++--
drivers/input/touchscreen/ipaq-micro-ts.c | 2 +-
drivers/input/touchscreen/iqs5xx.c | 4 ++--
drivers/input/touchscreen/lpc32xx_ts.c | 4 ++--
drivers/input/touchscreen/melfas_mip4.c | 4 ++--
drivers/input/touchscreen/mms114.c | 6 +++---
drivers/input/touchscreen/pixcir_i2c_ts.c | 8 ++++----
drivers/input/touchscreen/ucb1400_ts.c | 4 ++--
drivers/input/touchscreen/wm97xx-core.c | 14 +++++++++-----
drivers/input/touchscreen/zforce_ts.c | 8 ++++----
37 files changed, 86 insertions(+), 82 deletions(-)
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index 6b40a1c68f9f..5c61431e0440 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -1890,7 +1890,7 @@ static int xpad_suspend(struct usb_interface *intf, pm_message_t message)
xpad360w_poweroff_controller(xpad);
} else {
mutex_lock(&input->mutex);
- if (input->users)
+ if (input_device_enabled(input))
xpad_stop_input(xpad);
mutex_unlock(&input->mutex);
}
@@ -1910,7 +1910,7 @@ static int xpad_resume(struct usb_interface *intf)
retval = xpad360w_start_input(xpad);
} else {
mutex_lock(&input->mutex);
- if (input->users) {
+ if (input_device_enabled(input)) {
retval = xpad_start_input(xpad);
} else if (xpad->xtype == XTYPE_XBOXONE) {
/*
diff --git a/drivers/input/keyboard/ep93xx_keypad.c b/drivers/input/keyboard/ep93xx_keypad.c
index 7c70492d9d6b..8194e843d047 100644
--- a/drivers/input/keyboard/ep93xx_keypad.c
+++ b/drivers/input/keyboard/ep93xx_keypad.c
@@ -208,7 +208,7 @@ static int ep93xx_keypad_resume(struct device *dev)
mutex_lock(&input_dev->mutex);
- if (input_dev->users) {
+ if (input_device_enabled(input_dev)) {
if (!keypad->enabled) {
ep93xx_keypad_config(keypad);
clk_enable(keypad->clk);
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
index 53c9ff338dea..03ad27189553 100644
--- a/drivers/input/keyboard/gpio_keys.c
+++ b/drivers/input/keyboard/gpio_keys.c
@@ -966,7 +966,7 @@ static int __maybe_unused gpio_keys_suspend(struct device *dev)
return error;
} else {
mutex_lock(&input->mutex);
- if (input->users)
+ if (input_device_enabled(input))
gpio_keys_close(input);
mutex_unlock(&input->mutex);
}
@@ -984,7 +984,7 @@ static int __maybe_unused gpio_keys_resume(struct device *dev)
gpio_keys_disable_wakeup(ddata);
} else {
mutex_lock(&input->mutex);
- if (input->users)
+ if (input_device_enabled(input))
error = gpio_keys_open(input);
mutex_unlock(&input->mutex);
}
diff --git a/drivers/input/keyboard/imx_keypad.c b/drivers/input/keyboard/imx_keypad.c
index 5a46d113e909..1f5c9ea5e9e5 100644
--- a/drivers/input/keyboard/imx_keypad.c
+++ b/drivers/input/keyboard/imx_keypad.c
@@ -532,7 +532,7 @@ static int __maybe_unused imx_kbd_noirq_suspend(struct device *dev)
/* imx kbd can wake up system even clock is disabled */
mutex_lock(&input_dev->mutex);
- if (input_dev->users)
+ if (input_device_enabled(input_dev))
clk_disable_unprepare(kbd->clk);
mutex_unlock(&input_dev->mutex);
@@ -562,7 +562,7 @@ static int __maybe_unused imx_kbd_noirq_resume(struct device *dev)
mutex_lock(&input_dev->mutex);
- if (input_dev->users) {
+ if (input_device_enabled(input_dev)) {
ret = clk_prepare_enable(kbd->clk);
if (ret)
goto err_clk;
diff --git a/drivers/input/keyboard/ipaq-micro-keys.c b/drivers/input/keyboard/ipaq-micro-keys.c
index e3f9e445e880..13a66a8e3411 100644
--- a/drivers/input/keyboard/ipaq-micro-keys.c
+++ b/drivers/input/keyboard/ipaq-micro-keys.c
@@ -140,7 +140,7 @@ static int __maybe_unused micro_key_resume(struct device *dev)
mutex_lock(&input->mutex);
- if (input->users)
+ if (input_device_enabled(input))
micro_key_start(keys);
mutex_unlock(&input->mutex);
diff --git a/drivers/input/keyboard/lpc32xx-keys.c b/drivers/input/keyboard/lpc32xx-keys.c
index 348af2aeb5de..943aeeb0de79 100644
--- a/drivers/input/keyboard/lpc32xx-keys.c
+++ b/drivers/input/keyboard/lpc32xx-keys.c
@@ -273,7 +273,7 @@ static int lpc32xx_kscan_suspend(struct device *dev)
mutex_lock(&input->mutex);
- if (input->users) {
+ if (input_device_enabled(input)) {
/* Clear IRQ and disable clock */
writel(1, LPC32XX_KS_IRQ(kscandat->kscan_base));
clk_disable_unprepare(kscandat->clk);
@@ -292,7 +292,7 @@ static int lpc32xx_kscan_resume(struct device *dev)
mutex_lock(&input->mutex);
- if (input->users) {
+ if (input_device_enabled(input)) {
/* Enable clock and clear IRQ */
retval = clk_prepare_enable(kscandat->clk);
if (retval == 0)
diff --git a/drivers/input/keyboard/pmic8xxx-keypad.c b/drivers/input/keyboard/pmic8xxx-keypad.c
index 91d5811d6f0e..43b4533e7c41 100644
--- a/drivers/input/keyboard/pmic8xxx-keypad.c
+++ b/drivers/input/keyboard/pmic8xxx-keypad.c
@@ -633,7 +633,7 @@ static int pmic8xxx_kp_suspend(struct device *dev)
} else {
mutex_lock(&input_dev->mutex);
- if (input_dev->users)
+ if (input_device_enabled(input_dev))
pmic8xxx_kp_disable(kp);
mutex_unlock(&input_dev->mutex);
@@ -653,7 +653,7 @@ static int pmic8xxx_kp_resume(struct device *dev)
} else {
mutex_lock(&input_dev->mutex);
- if (input_dev->users)
+ if (input_device_enabled(input_dev))
pmic8xxx_kp_enable(kp);
mutex_unlock(&input_dev->mutex);
diff --git a/drivers/input/keyboard/pxa27x_keypad.c b/drivers/input/keyboard/pxa27x_keypad.c
index 7e65708b25a4..a7f8257c8a02 100644
--- a/drivers/input/keyboard/pxa27x_keypad.c
+++ b/drivers/input/keyboard/pxa27x_keypad.c
@@ -694,7 +694,7 @@ static int pxa27x_keypad_resume(struct device *dev)
} else {
mutex_lock(&input_dev->mutex);
- if (input_dev->users) {
+ if (input_device_enabled(input_dev)) {
/* Enable unit clock */
ret = clk_prepare_enable(keypad->clk);
if (!ret)
diff --git a/drivers/input/keyboard/samsung-keypad.c b/drivers/input/keyboard/samsung-keypad.c
index 70c1d086bdd2..74ec068fbf2f 100644
--- a/drivers/input/keyboard/samsung-keypad.c
+++ b/drivers/input/keyboard/samsung-keypad.c
@@ -537,7 +537,7 @@ static int samsung_keypad_suspend(struct device *dev)
mutex_lock(&input_dev->mutex);
- if (input_dev->users)
+ if (input_device_enabled(input_dev))
samsung_keypad_stop(keypad);
samsung_keypad_toggle_wakeup(keypad, true);
@@ -557,7 +557,7 @@ static int samsung_keypad_resume(struct device *dev)
samsung_keypad_toggle_wakeup(keypad, false);
- if (input_dev->users)
+ if (input_device_enabled(input_dev))
samsung_keypad_start(keypad);
mutex_unlock(&input_dev->mutex);
diff --git a/drivers/input/keyboard/spear-keyboard.c b/drivers/input/keyboard/spear-keyboard.c
index 9b8d78f87253..9838c79cb288 100644
--- a/drivers/input/keyboard/spear-keyboard.c
+++ b/drivers/input/keyboard/spear-keyboard.c
@@ -318,7 +318,7 @@ static int __maybe_unused spear_kbd_suspend(struct device *dev)
writel_relaxed(val, kbd->io_base + MODE_CTL_REG);
} else {
- if (input_dev->users) {
+ if (input_device_enabled(input_dev)) {
writel_relaxed(mode_ctl_reg & ~MODE_CTL_START_SCAN,
kbd->io_base + MODE_CTL_REG);
clk_disable(kbd->clk);
@@ -326,7 +326,7 @@ static int __maybe_unused spear_kbd_suspend(struct device *dev)
}
/* store current configuration */
- if (input_dev->users)
+ if (input_device_enabled(input_dev))
kbd->mode_ctl_reg = mode_ctl_reg;
/* restore previous clk state */
@@ -351,12 +351,12 @@ static int __maybe_unused spear_kbd_resume(struct device *dev)
disable_irq_wake(kbd->irq);
}
} else {
- if (input_dev->users)
+ if (input_device_enabled(input_dev))
clk_enable(kbd->clk);
}
/* restore current configuration */
- if (input_dev->users)
+ if (input_device_enabled(input_dev))
writel_relaxed(kbd->mode_ctl_reg, kbd->io_base + MODE_CTL_REG);
mutex_unlock(&input_dev->mutex);
diff --git a/drivers/input/keyboard/st-keyscan.c b/drivers/input/keyboard/st-keyscan.c
index 27562cd67fb6..a045d61165ac 100644
--- a/drivers/input/keyboard/st-keyscan.c
+++ b/drivers/input/keyboard/st-keyscan.c
@@ -221,7 +221,7 @@ static int keyscan_suspend(struct device *dev)
if (device_may_wakeup(dev))
enable_irq_wake(keypad->irq);
- else if (input->users)
+ else if (input_device_enabled(input))
keyscan_stop(keypad);
mutex_unlock(&input->mutex);
@@ -239,7 +239,7 @@ static int keyscan_resume(struct device *dev)
if (device_may_wakeup(dev))
disable_irq_wake(keypad->irq);
- else if (input->users)
+ else if (input_device_enabled(input))
retval = keyscan_start(keypad);
mutex_unlock(&input->mutex);
diff --git a/drivers/input/keyboard/tegra-kbc.c b/drivers/input/keyboard/tegra-kbc.c
index d34d6947960f..9671842a082a 100644
--- a/drivers/input/keyboard/tegra-kbc.c
+++ b/drivers/input/keyboard/tegra-kbc.c
@@ -756,7 +756,7 @@ static int tegra_kbc_suspend(struct device *dev)
enable_irq(kbc->irq);
enable_irq_wake(kbc->irq);
} else {
- if (kbc->idev->users)
+ if (input_device_enabled(kbc->idev))
tegra_kbc_stop(kbc);
}
mutex_unlock(&kbc->idev->mutex);
@@ -796,7 +796,7 @@ static int tegra_kbc_resume(struct device *dev)
input_sync(kbc->idev);
}
} else {
- if (kbc->idev->users)
+ if (input_device_enabled(kbc->idev))
err = tegra_kbc_start(kbc);
}
mutex_unlock(&kbc->idev->mutex);
diff --git a/drivers/input/misc/drv260x.c b/drivers/input/misc/drv260x.c
index 79d7fa710a71..11c1983e286a 100644
--- a/drivers/input/misc/drv260x.c
+++ b/drivers/input/misc/drv260x.c
@@ -580,7 +580,7 @@ static int __maybe_unused drv260x_suspend(struct device *dev)
mutex_lock(&haptics->input_dev->mutex);
- if (haptics->input_dev->users) {
+ if (input_device_enabled(haptics->input_dev)) {
ret = regmap_update_bits(haptics->regmap,
DRV260X_MODE,
DRV260X_STANDBY_MASK,
@@ -612,7 +612,7 @@ static int __maybe_unused drv260x_resume(struct device *dev)
mutex_lock(&haptics->input_dev->mutex);
- if (haptics->input_dev->users) {
+ if (input_device_enabled(haptics->input_dev)) {
ret = regulator_enable(haptics->regulator);
if (ret) {
dev_err(dev, "Failed to enable regulator\n");
diff --git a/drivers/input/misc/drv2665.c b/drivers/input/misc/drv2665.c
index 918ad9c3fa81..e4df1a3b8655 100644
--- a/drivers/input/misc/drv2665.c
+++ b/drivers/input/misc/drv2665.c
@@ -230,7 +230,7 @@ static int __maybe_unused drv2665_suspend(struct device *dev)
mutex_lock(&haptics->input_dev->mutex);
- if (haptics->input_dev->users) {
+ if (input_device_enabled(haptics->input_dev)) {
ret = regmap_update_bits(haptics->regmap, DRV2665_CTRL_2,
DRV2665_STANDBY, DRV2665_STANDBY);
if (ret) {
@@ -259,7 +259,7 @@ static int __maybe_unused drv2665_resume(struct device *dev)
mutex_lock(&haptics->input_dev->mutex);
- if (haptics->input_dev->users) {
+ if (input_device_enabled(haptics->input_dev)) {
ret = regulator_enable(haptics->regulator);
if (ret) {
dev_err(dev, "Failed to enable regulator\n");
diff --git a/drivers/input/misc/drv2667.c b/drivers/input/misc/drv2667.c
index bb9d5784df17..be4be2e0fd6f 100644
--- a/drivers/input/misc/drv2667.c
+++ b/drivers/input/misc/drv2667.c
@@ -405,7 +405,7 @@ static int __maybe_unused drv2667_suspend(struct device *dev)
mutex_lock(&haptics->input_dev->mutex);
- if (haptics->input_dev->users) {
+ if (input_device_enabled(haptics->input_dev)) {
ret = regmap_update_bits(haptics->regmap, DRV2667_CTRL_2,
DRV2667_STANDBY, DRV2667_STANDBY);
if (ret) {
@@ -434,7 +434,7 @@ static int __maybe_unused drv2667_resume(struct device *dev)
mutex_lock(&haptics->input_dev->mutex);
- if (haptics->input_dev->users) {
+ if (input_device_enabled(haptics->input_dev)) {
ret = regulator_enable(haptics->regulator);
if (ret) {
dev_err(dev, "Failed to enable regulator\n");
diff --git a/drivers/input/misc/gp2ap002a00f.c b/drivers/input/misc/gp2ap002a00f.c
index 90abda8eea67..5f61ef90b2f2 100644
--- a/drivers/input/misc/gp2ap002a00f.c
+++ b/drivers/input/misc/gp2ap002a00f.c
@@ -230,7 +230,7 @@ static int __maybe_unused gp2a_suspend(struct device *dev)
enable_irq_wake(client->irq);
} else {
mutex_lock(&dt->input->mutex);
- if (dt->input->users)
+ if (input_device_enabled(dt->input))
retval = gp2a_disable(dt);
mutex_unlock(&dt->input->mutex);
}
@@ -248,7 +248,7 @@ static int __maybe_unused gp2a_resume(struct device *dev)
disable_irq_wake(client->irq);
} else {
mutex_lock(&dt->input->mutex);
- if (dt->input->users)
+ if (input_device_enabled(dt->input))
retval = gp2a_enable(dt);
mutex_unlock(&dt->input->mutex);
}
diff --git a/drivers/input/misc/kxtj9.c b/drivers/input/misc/kxtj9.c
index 52313c6e3fb3..bbb81617c2b2 100644
--- a/drivers/input/misc/kxtj9.c
+++ b/drivers/input/misc/kxtj9.c
@@ -503,7 +503,7 @@ static int __maybe_unused kxtj9_suspend(struct device *dev)
mutex_lock(&input_dev->mutex);
- if (input_dev->users)
+ if (input_device_enabled(input_dev))
kxtj9_disable(tj9);
mutex_unlock(&input_dev->mutex);
@@ -518,7 +518,7 @@ static int __maybe_unused kxtj9_resume(struct device *dev)
mutex_lock(&input_dev->mutex);
- if (input_dev->users)
+ if (input_device_enabled(input_dev))
kxtj9_enable(tj9);
mutex_unlock(&input_dev->mutex);
diff --git a/drivers/input/misc/sirfsoc-onkey.c b/drivers/input/misc/sirfsoc-onkey.c
index 60e1f31ee60a..7982bf8fb839 100644
--- a/drivers/input/misc/sirfsoc-onkey.c
+++ b/drivers/input/misc/sirfsoc-onkey.c
@@ -181,7 +181,7 @@ static int __maybe_unused sirfsoc_pwrc_resume(struct device *dev)
* if users touch X_ONKEY_B, see arch/arm/mach-prima2/pm.c
*/
mutex_lock(&input->mutex);
- if (input->users)
+ if (input_device_enabled(input))
sirfsoc_pwrc_toggle_interrupts(pwrcdrv, true);
mutex_unlock(&input->mutex);
diff --git a/drivers/input/mouse/navpoint.c b/drivers/input/mouse/navpoint.c
index 0b75248c8380..643d4b805b64 100644
--- a/drivers/input/mouse/navpoint.c
+++ b/drivers/input/mouse/navpoint.c
@@ -322,7 +322,7 @@ static int __maybe_unused navpoint_suspend(struct device *dev)
struct input_dev *input = navpoint->input;
mutex_lock(&input->mutex);
- if (input->users)
+ if (input_device_enabled(input))
navpoint_down(navpoint);
mutex_unlock(&input->mutex);
@@ -336,7 +336,7 @@ static int __maybe_unused navpoint_resume(struct device *dev)
struct input_dev *input = navpoint->input;
mutex_lock(&input->mutex);
- if (input->users)
+ if (input_device_enabled(input))
navpoint_up(navpoint);
mutex_unlock(&input->mutex);
diff --git a/drivers/input/touchscreen/ad7879.c b/drivers/input/touchscreen/ad7879.c
index 556a2af46e18..e850853328f1 100644
--- a/drivers/input/touchscreen/ad7879.c
+++ b/drivers/input/touchscreen/ad7879.c
@@ -306,7 +306,7 @@ static int __maybe_unused ad7879_suspend(struct device *dev)
mutex_lock(&ts->input->mutex);
- if (!ts->suspended && !ts->disabled && ts->input->users)
+ if (!ts->suspended && !ts->disabled && input_device_enabled(ts->input))
__ad7879_disable(ts);
ts->suspended = true;
@@ -322,7 +322,7 @@ static int __maybe_unused ad7879_resume(struct device *dev)
mutex_lock(&ts->input->mutex);
- if (ts->suspended && !ts->disabled && ts->input->users)
+ if (ts->suspended && !ts->disabled && input_device_enabled(ts->input))
__ad7879_enable(ts);
ts->suspended = false;
@@ -339,7 +339,7 @@ static void ad7879_toggle(struct ad7879 *ts, bool disable)
{
mutex_lock(&ts->input->mutex);
- if (!ts->suspended && ts->input->users != 0) {
+ if (!ts->suspended && input_device_enabled(ts->input)) {
if (disable) {
if (ts->disabled)
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index ae60442efda0..47b7936bc3e3 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -3151,7 +3151,7 @@ static int __maybe_unused mxt_suspend(struct device *dev)
mutex_lock(&input_dev->mutex);
- if (input_dev->users)
+ if (input_device_enabled(input_dev))
mxt_stop(data);
mutex_unlock(&input_dev->mutex);
@@ -3174,7 +3174,7 @@ static int __maybe_unused mxt_resume(struct device *dev)
mutex_lock(&input_dev->mutex);
- if (input_dev->users)
+ if (input_device_enabled(input_dev))
mxt_start(data);
mutex_unlock(&input_dev->mutex);
diff --git a/drivers/input/touchscreen/auo-pixcir-ts.c b/drivers/input/touchscreen/auo-pixcir-ts.c
index 8e9f3b7b8180..c33e63ca6142 100644
--- a/drivers/input/touchscreen/auo-pixcir-ts.c
+++ b/drivers/input/touchscreen/auo-pixcir-ts.c
@@ -414,7 +414,7 @@ static int __maybe_unused auo_pixcir_suspend(struct device *dev)
*/
if (device_may_wakeup(&client->dev)) {
/* need to start device if not open, to be wakeup source */
- if (!input->users) {
+ if (!input_device_enabled(input)) {
ret = auo_pixcir_start(ts);
if (ret)
goto unlock;
@@ -422,7 +422,7 @@ static int __maybe_unused auo_pixcir_suspend(struct device *dev)
enable_irq_wake(client->irq);
ret = auo_pixcir_power_mode(ts, AUO_PIXCIR_POWER_SLEEP);
- } else if (input->users) {
+ } else if (input_device_enabled(input)) {
ret = auo_pixcir_stop(ts);
}
@@ -445,14 +445,14 @@ static int __maybe_unused auo_pixcir_resume(struct device *dev)
disable_irq_wake(client->irq);
/* need to stop device if it was not open on suspend */
- if (!input->users) {
+ if (!input_device_enabled(input)) {
ret = auo_pixcir_stop(ts);
if (ret)
goto unlock;
}
/* device wakes automatically from SLEEP */
- } else if (input->users) {
+ } else if (input_device_enabled(input)) {
ret = auo_pixcir_start(ts);
}
diff --git a/drivers/input/touchscreen/bu21029_ts.c b/drivers/input/touchscreen/bu21029_ts.c
index 49a8d4bbca3a..341925edb8e6 100644
--- a/drivers/input/touchscreen/bu21029_ts.c
+++ b/drivers/input/touchscreen/bu21029_ts.c
@@ -430,7 +430,7 @@ static int __maybe_unused bu21029_suspend(struct device *dev)
if (!device_may_wakeup(dev)) {
mutex_lock(&bu21029->in_dev->mutex);
- if (bu21029->in_dev->users)
+ if (input_device_enabled(bu21029->in_dev))
bu21029_stop_chip(bu21029->in_dev);
mutex_unlock(&bu21029->in_dev->mutex);
}
@@ -445,7 +445,7 @@ static int __maybe_unused bu21029_resume(struct device *dev)
if (!device_may_wakeup(dev)) {
mutex_lock(&bu21029->in_dev->mutex);
- if (bu21029->in_dev->users)
+ if (input_device_enabled(bu21029->in_dev))
bu21029_start_chip(bu21029->in_dev);
mutex_unlock(&bu21029->in_dev->mutex);
}
diff --git a/drivers/input/touchscreen/chipone_icn8318.c b/drivers/input/touchscreen/chipone_icn8318.c
index d91d2fd78649..f2fb41fb031e 100644
--- a/drivers/input/touchscreen/chipone_icn8318.c
+++ b/drivers/input/touchscreen/chipone_icn8318.c
@@ -154,7 +154,7 @@ static int icn8318_suspend(struct device *dev)
struct icn8318_data *data = i2c_get_clientdata(to_i2c_client(dev));
mutex_lock(&data->input->mutex);
- if (data->input->users)
+ if (input_device_enabled(data->input))
icn8318_stop(data->input);
mutex_unlock(&data->input->mutex);
@@ -166,7 +166,7 @@ static int icn8318_resume(struct device *dev)
struct icn8318_data *data = i2c_get_clientdata(to_i2c_client(dev));
mutex_lock(&data->input->mutex);
- if (data->input->users)
+ if (input_device_enabled(data->input))
icn8318_start(data->input);
mutex_unlock(&data->input->mutex);
diff --git a/drivers/input/touchscreen/cyttsp_core.c b/drivers/input/touchscreen/cyttsp_core.c
index 3f5d463dbeed..6e49cb80ec6d 100644
--- a/drivers/input/touchscreen/cyttsp_core.c
+++ b/drivers/input/touchscreen/cyttsp_core.c
@@ -479,7 +479,7 @@ static int __maybe_unused cyttsp_suspend(struct device *dev)
mutex_lock(&ts->input->mutex);
- if (ts->input->users) {
+ if (input_device_enabled(ts->input)) {
retval = cyttsp_disable(ts);
if (retval == 0)
ts->suspended = true;
@@ -496,7 +496,7 @@ static int __maybe_unused cyttsp_resume(struct device *dev)
mutex_lock(&ts->input->mutex);
- if (ts->input->users)
+ if (input_device_enabled(ts->input))
cyttsp_enable(ts);
ts->suspended = false;
diff --git a/drivers/input/touchscreen/eeti_ts.c b/drivers/input/touchscreen/eeti_ts.c
index 2e1404cd09ec..a639ba7e56ea 100644
--- a/drivers/input/touchscreen/eeti_ts.c
+++ b/drivers/input/touchscreen/eeti_ts.c
@@ -241,7 +241,7 @@ static int __maybe_unused eeti_ts_suspend(struct device *dev)
mutex_lock(&input_dev->mutex);
- if (input_dev->users)
+ if (input_device_enabled(input_dev))
eeti_ts_stop(eeti);
mutex_unlock(&input_dev->mutex);
@@ -263,7 +263,7 @@ static int __maybe_unused eeti_ts_resume(struct device *dev)
mutex_lock(&input_dev->mutex);
- if (input_dev->users)
+ if (input_device_enabled(input_dev))
eeti_ts_start(eeti);
mutex_unlock(&input_dev->mutex);
diff --git a/drivers/input/touchscreen/ektf2127.c b/drivers/input/touchscreen/ektf2127.c
index eadd389cf81f..263bbeb6cee9 100644
--- a/drivers/input/touchscreen/ektf2127.c
+++ b/drivers/input/touchscreen/ektf2127.c
@@ -154,7 +154,7 @@ static int __maybe_unused ektf2127_suspend(struct device *dev)
struct ektf2127_ts *ts = i2c_get_clientdata(to_i2c_client(dev));
mutex_lock(&ts->input->mutex);
- if (ts->input->users)
+ if (input_device_enabled(ts->input))
ektf2127_stop(ts->input);
mutex_unlock(&ts->input->mutex);
@@ -166,7 +166,7 @@ static int __maybe_unused ektf2127_resume(struct device *dev)
struct ektf2127_ts *ts = i2c_get_clientdata(to_i2c_client(dev));
mutex_lock(&ts->input->mutex);
- if (ts->input->users)
+ if (input_device_enabled(ts->input))
ektf2127_start(ts->input);
mutex_unlock(&ts->input->mutex);
diff --git a/drivers/input/touchscreen/imx6ul_tsc.c b/drivers/input/touchscreen/imx6ul_tsc.c
index 9ed258854349..59d4a4e9ecc2 100644
--- a/drivers/input/touchscreen/imx6ul_tsc.c
+++ b/drivers/input/touchscreen/imx6ul_tsc.c
@@ -509,7 +509,7 @@ static int __maybe_unused imx6ul_tsc_suspend(struct device *dev)
mutex_lock(&input_dev->mutex);
- if (input_dev->users) {
+ if (input_device_enabled(input_dev)) {
imx6ul_tsc_disable(tsc);
clk_disable_unprepare(tsc->tsc_clk);
@@ -530,7 +530,7 @@ static int __maybe_unused imx6ul_tsc_resume(struct device *dev)
mutex_lock(&input_dev->mutex);
- if (input_dev->users) {
+ if (input_device_enabled(input_dev)) {
retval = clk_prepare_enable(tsc->adc_clk);
if (retval)
goto out;
diff --git a/drivers/input/touchscreen/ipaq-micro-ts.c b/drivers/input/touchscreen/ipaq-micro-ts.c
index 5c3977e1af6f..0eb5689fe65f 100644
--- a/drivers/input/touchscreen/ipaq-micro-ts.c
+++ b/drivers/input/touchscreen/ipaq-micro-ts.c
@@ -135,7 +135,7 @@ static int __maybe_unused micro_ts_resume(struct device *dev)
mutex_lock(&input->mutex);
- if (input->users)
+ if (input_device_enabled(input))
micro_ts_toggle_receive(ts, true);
mutex_unlock(&input->mutex);
diff --git a/drivers/input/touchscreen/iqs5xx.c b/drivers/input/touchscreen/iqs5xx.c
index 5875bb1099a8..8b7b94ef7f39 100644
--- a/drivers/input/touchscreen/iqs5xx.c
+++ b/drivers/input/touchscreen/iqs5xx.c
@@ -1017,7 +1017,7 @@ static int __maybe_unused iqs5xx_suspend(struct device *dev)
mutex_lock(&input->mutex);
- if (input->users)
+ if (input_device_enabled(input))
error = iqs5xx_set_state(iqs5xx->client, IQS5XX_SUSPEND);
mutex_unlock(&input->mutex);
@@ -1036,7 +1036,7 @@ static int __maybe_unused iqs5xx_resume(struct device *dev)
mutex_lock(&input->mutex);
- if (input->users)
+ if (input_device_enabled(input))
error = iqs5xx_set_state(iqs5xx->client, IQS5XX_RESUME);
mutex_unlock(&input->mutex);
diff --git a/drivers/input/touchscreen/lpc32xx_ts.c b/drivers/input/touchscreen/lpc32xx_ts.c
index b2cd9472e2d1..b51450b3d943 100644
--- a/drivers/input/touchscreen/lpc32xx_ts.c
+++ b/drivers/input/touchscreen/lpc32xx_ts.c
@@ -334,7 +334,7 @@ static int lpc32xx_ts_suspend(struct device *dev)
*/
mutex_lock(&input->mutex);
- if (input->users) {
+ if (input_device_enabled(input)) {
if (device_may_wakeup(dev))
enable_irq_wake(tsc->irq);
else
@@ -353,7 +353,7 @@ static int lpc32xx_ts_resume(struct device *dev)
mutex_lock(&input->mutex);
- if (input->users) {
+ if (input_device_enabled(input)) {
if (device_may_wakeup(dev))
disable_irq_wake(tsc->irq);
else
diff --git a/drivers/input/touchscreen/melfas_mip4.c b/drivers/input/touchscreen/melfas_mip4.c
index 247c3aaba2d8..d33586919f58 100644
--- a/drivers/input/touchscreen/melfas_mip4.c
+++ b/drivers/input/touchscreen/melfas_mip4.c
@@ -1539,7 +1539,7 @@ static int __maybe_unused mip4_suspend(struct device *dev)
if (device_may_wakeup(dev))
ts->wake_irq_enabled = enable_irq_wake(client->irq) == 0;
- else if (input->users)
+ else if (input_device_enabled(input))
mip4_disable(ts);
mutex_unlock(&input->mutex);
@@ -1557,7 +1557,7 @@ static int __maybe_unused mip4_resume(struct device *dev)
if (ts->wake_irq_enabled)
disable_irq_wake(client->irq);
- else if (input->users)
+ else if (input_device_enabled(input))
mip4_enable(ts);
mutex_unlock(&input->mutex);
diff --git a/drivers/input/touchscreen/mms114.c b/drivers/input/touchscreen/mms114.c
index 69c6d559eeb0..21051795ce97 100644
--- a/drivers/input/touchscreen/mms114.c
+++ b/drivers/input/touchscreen/mms114.c
@@ -198,7 +198,7 @@ static irqreturn_t mms114_interrupt(int irq, void *dev_id)
int error;
mutex_lock(&input_dev->mutex);
- if (!input_dev->users) {
+ if (!input_device_enabled(input_dev)) {
mutex_unlock(&input_dev->mutex);
goto out;
}
@@ -556,7 +556,7 @@ static int __maybe_unused mms114_suspend(struct device *dev)
input_sync(input_dev);
mutex_lock(&input_dev->mutex);
- if (input_dev->users)
+ if (input_device_enabled(input_dev))
mms114_stop(data);
mutex_unlock(&input_dev->mutex);
@@ -571,7 +571,7 @@ static int __maybe_unused mms114_resume(struct device *dev)
int error;
mutex_lock(&input_dev->mutex);
- if (input_dev->users) {
+ if (input_device_enabled(input_dev)) {
error = mms114_start(data);
if (error < 0) {
mutex_unlock(&input_dev->mutex);
diff --git a/drivers/input/touchscreen/pixcir_i2c_ts.c b/drivers/input/touchscreen/pixcir_i2c_ts.c
index 9aa098577350..dc148b4bed74 100644
--- a/drivers/input/touchscreen/pixcir_i2c_ts.c
+++ b/drivers/input/touchscreen/pixcir_i2c_ts.c
@@ -415,14 +415,14 @@ static int __maybe_unused pixcir_i2c_ts_suspend(struct device *dev)
mutex_lock(&input->mutex);
if (device_may_wakeup(&client->dev)) {
- if (!input->users) {
+ if (!input_device_enabled(input)) {
ret = pixcir_start(ts);
if (ret) {
dev_err(dev, "Failed to start\n");
goto unlock;
}
}
- } else if (input->users) {
+ } else if (input_device_enabled(input)) {
ret = pixcir_stop(ts);
}
@@ -442,14 +442,14 @@ static int __maybe_unused pixcir_i2c_ts_resume(struct device *dev)
mutex_lock(&input->mutex);
if (device_may_wakeup(&client->dev)) {
- if (!input->users) {
+ if (!input_device_enabled(input)) {
ret = pixcir_stop(ts);
if (ret) {
dev_err(dev, "Failed to stop\n");
goto unlock;
}
}
- } else if (input->users) {
+ } else if (input_device_enabled(input)) {
ret = pixcir_start(ts);
}
diff --git a/drivers/input/touchscreen/ucb1400_ts.c b/drivers/input/touchscreen/ucb1400_ts.c
index 807d39e18091..e3f2c940ef3d 100644
--- a/drivers/input/touchscreen/ucb1400_ts.c
+++ b/drivers/input/touchscreen/ucb1400_ts.c
@@ -410,7 +410,7 @@ static int __maybe_unused ucb1400_ts_suspend(struct device *dev)
mutex_lock(&idev->mutex);
- if (idev->users)
+ if (input_device_enabled(idev))
ucb1400_ts_stop(ucb);
mutex_unlock(&idev->mutex);
@@ -424,7 +424,7 @@ static int __maybe_unused ucb1400_ts_resume(struct device *dev)
mutex_lock(&idev->mutex);
- if (idev->users)
+ if (input_device_enabled(idev))
ucb1400_ts_start(ucb);
mutex_unlock(&idev->mutex);
diff --git a/drivers/input/touchscreen/wm97xx-core.c b/drivers/input/touchscreen/wm97xx-core.c
index 0a174bd82915..2c2f1b6c5eff 100644
--- a/drivers/input/touchscreen/wm97xx-core.c
+++ b/drivers/input/touchscreen/wm97xx-core.c
@@ -806,23 +806,25 @@ static int __maybe_unused wm97xx_suspend(struct device *dev)
else
suspend_mode = 0;
- if (wm->input_dev->users)
+ mutex_lock(&wm->input_dev->mutex);
+ if (input_device_enabled(wm->input_dev))
cancel_delayed_work_sync(&wm->ts_reader);
/* Power down the digitiser (bypassing the cache for resume) */
reg = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER2);
reg &= ~WM97XX_PRP_DET_DIG;
- if (wm->input_dev->users)
+ if (input_device_enabled(wm->input_dev))
reg |= suspend_mode;
wm->ac97->bus->ops->write(wm->ac97, AC97_WM97XX_DIGITISER2, reg);
/* WM9713 has an additional power bit - turn it off if there
* are no users or if suspend mode is zero. */
if (wm->id == WM9713_ID2 &&
- (!wm->input_dev->users || !suspend_mode)) {
+ (!input_device_enabled(wm->input_dev) || !suspend_mode)) {
reg = wm97xx_reg_read(wm, AC97_EXTENDED_MID) | 0x8000;
wm97xx_reg_write(wm, AC97_EXTENDED_MID, reg);
}
+ mutex_unlock(&wm->input_dev->mutex);
return 0;
}
@@ -831,11 +833,12 @@ static int __maybe_unused wm97xx_resume(struct device *dev)
{
struct wm97xx *wm = dev_get_drvdata(dev);
+ mutex_lock(&wm->input_dev->mutex);
/* restore digitiser and gpios */
if (wm->id == WM9713_ID2) {
wm97xx_reg_write(wm, AC97_WM9713_DIG1, wm->dig[0]);
wm97xx_reg_write(wm, 0x5a, wm->misc);
- if (wm->input_dev->users) {
+ if (input_device_enabled(wm->input_dev)) {
u16 reg;
reg = wm97xx_reg_read(wm, AC97_EXTENDED_MID) & 0x7fff;
wm97xx_reg_write(wm, AC97_EXTENDED_MID, reg);
@@ -852,11 +855,12 @@ static int __maybe_unused wm97xx_resume(struct device *dev)
wm97xx_reg_write(wm, AC97_GPIO_STATUS, wm->gpio[4]);
wm97xx_reg_write(wm, AC97_MISC_AFE, wm->gpio[5]);
- if (wm->input_dev->users && !wm->pen_irq) {
+ if (input_device_enabled(wm->input_dev) && !wm->pen_irq) {
wm->ts_reader_interval = wm->ts_reader_min_interval;
queue_delayed_work(wm->ts_workq, &wm->ts_reader,
wm->ts_reader_interval);
}
+ mutex_unlock(&wm->input_dev->mutex);
return 0;
}
diff --git a/drivers/input/touchscreen/zforce_ts.c b/drivers/input/touchscreen/zforce_ts.c
index 5230519b0f74..495629628af6 100644
--- a/drivers/input/touchscreen/zforce_ts.c
+++ b/drivers/input/touchscreen/zforce_ts.c
@@ -626,14 +626,14 @@ static int __maybe_unused zforce_suspend(struct device *dev)
dev_dbg(&client->dev, "suspend while being a wakeup source\n");
/* Need to start device, if not open, to be a wakeup source. */
- if (!input->users) {
+ if (!input_device_enabled(input)) {
ret = zforce_start(ts);
if (ret)
goto unlock;
}
enable_irq_wake(client->irq);
- } else if (input->users) {
+ } else if (input_device_enabled(input)) {
dev_dbg(&client->dev,
"suspend without being a wakeup source\n");
@@ -670,12 +670,12 @@ static int __maybe_unused zforce_resume(struct device *dev)
disable_irq_wake(client->irq);
/* need to stop device if it was not open on suspend */
- if (!input->users) {
+ if (!input_device_enabled(input)) {
ret = zforce_stop(ts);
if (ret)
goto unlock;
}
- } else if (input->users) {
+ } else if (input_device_enabled(input)) {
dev_dbg(&client->dev, "resume without being a wakeup source\n");
enable_irq(client->irq);
--
2.17.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCHv2 1/7] Input: add input_device_enabled()
From: Andrzej Pietrasiewicz @ 2020-05-15 16:51 UTC (permalink / raw)
To: linux-input, linux-acpi, linux-iio, linux-arm-kernel,
linux-samsung-soc, linux-tegra, patches, ibm-acpi-devel,
platform-driver-x86
Cc: Nick Dyer, Laxman Dewangan, Peter Meerwald-Stadler, kernel,
Fabio Estevam, Lars-Peter Clausen, Krzysztof Kozlowski,
Jonathan Hunter, Kukjin Kim, NXP Linux Team, Sylvain Lemieux,
Len Brown, Michael Hennerich, Sascha Hauer,
Henrique de Moraes Holschuh, Vladimir Zapolskiy, Hans de Goede,
Barry Song, Ferruh Yigit, Dmitry Torokhov, Rafael J . Wysocki,
Andrzej Pietrasiewicz, Thierry Reding, Sangwon Jee,
Pengutronix Kernel Team, Hartmut Knaack, Shawn Guo,
Jonathan Cameron
In-Reply-To: <20200515164943.28480-1-andrzej.p@collabora.com>
A helper function for drivers to decide if the device is used or not.
A lockdep check is introduced as inspecting ->users should be done under
input device's mutex.
Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@collabora.com>
---
drivers/input/input.c | 8 ++++++++
include/linux/input.h | 2 ++
2 files changed, 10 insertions(+)
diff --git a/drivers/input/input.c b/drivers/input/input.c
index 3cfd2c18eebd..41377bfa142d 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -2127,6 +2127,14 @@ void input_enable_softrepeat(struct input_dev *dev, int delay, int period)
}
EXPORT_SYMBOL(input_enable_softrepeat);
+bool input_device_enabled(struct input_dev *dev)
+{
+ lockdep_assert_held(&dev->mutex);
+
+ return dev->users > 0;
+}
+EXPORT_SYMBOL_GPL(input_device_enabled);
+
/**
* input_register_device - register device with input core
* @dev: device to be registered
diff --git a/include/linux/input.h b/include/linux/input.h
index 56f2fd32e609..eda4587dba67 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -502,6 +502,8 @@ bool input_match_device_id(const struct input_dev *dev,
void input_enable_softrepeat(struct input_dev *dev, int delay, int period);
+bool input_device_enabled(struct input_dev *dev);
+
extern struct class input_class;
/**
--
2.17.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCHv2 0/7] Support inhibiting input devices
From: Andrzej Pietrasiewicz @ 2020-05-15 16:49 UTC (permalink / raw)
To: linux-input, linux-acpi, linux-iio, linux-arm-kernel,
linux-samsung-soc, linux-tegra, patches, ibm-acpi-devel,
platform-driver-x86
Cc: Nick Dyer, Laxman Dewangan, Peter Meerwald-Stadler, kernel,
Fabio Estevam, Lars-Peter Clausen, Krzysztof Kozlowski,
Jonathan Hunter, Kukjin Kim, NXP Linux Team, Sylvain Lemieux,
Len Brown, Michael Hennerich, Sascha Hauer,
Henrique de Moraes Holschuh, Vladimir Zapolskiy, Hans de Goede,
Barry Song, Ferruh Yigit, Dmitry Torokhov, Rafael J . Wysocki,
Andrzej Pietrasiewicz, Thierry Reding, Sangwon Jee,
Pengutronix Kernel Team, Hartmut Knaack, Shawn Guo,
Jonathan Cameron
In-Reply-To: <20200506002746.GB89269@dtor-ws>
Userspace might want to implement a policy to temporarily disregard input
from certain devices, including not treating them as wakeup sources.
An example use case is a laptop, whose keyboard can be folded under the
screen to create tablet-like experience. The user then must hold the laptop
in such a way that it is difficult to avoid pressing the keyboard keys. It
is therefore desirable to temporarily disregard input from the keyboard,
until it is folded back. This obviously is a policy which should be kept
out of the kernel, but the kernel must provide suitable means to implement
such a policy.
Due to interactions with suspend/resume, a helper has been added for drivers
to decide if the device is being used or not (PATCH 1/7) and it has been
applied to relevant drivers (PATCH 2-5/7). Patches 2-5 are only being sent
to relevant mailing lists and maintainers.
PATCH 6/7 adds support for inhibiting input devices, while PATCH 7/7
provides an example how to convert a driver to take advantage of this
new feature. Patch 7/7 is only being sent to input mailing list and
maintainer.
This work is inspired by:
https://chromium.googlesource.com/chromiumos/third_party/kernel/+/45c2d7bb398f74adfae0017e20b224152fde3822
and
https://chromium.googlesource.com/chromiumos/third_party/kernel/+/4ce0e8a3697edb8fd071110b3af65014512061c7
v1..v2:
- added input_device_enabled() helper and used it in drivers (Dmitry)
- the fact of open() and close() being called in inhibit/uninhibit paths has
been emphasized in the commit message of PATCH 6/7 (Dmitry)
Andrzej Pietrasiewicz (5):
Input: add input_device_enabled()
Input: use input_device_enabled()
ACPI: button: Use input_device_enabled() helper
iio: adc: exynos: Use input_device_enabled()
platform/x86: thinkpad_acpi: Use input_device_enabled()
Dmitry Torokhov (1):
Input: elan_i2c: Support inhibiting
Patrik Fimml (1):
Input: Add "inhibited" property
drivers/acpi/button.c | 8 +-
drivers/iio/adc/exynos_adc.c | 11 +-
drivers/input/input.c | 142 ++++++++++++++++++--
drivers/input/joystick/xpad.c | 4 +-
drivers/input/keyboard/ep93xx_keypad.c | 2 +-
drivers/input/keyboard/gpio_keys.c | 4 +-
drivers/input/keyboard/imx_keypad.c | 4 +-
drivers/input/keyboard/ipaq-micro-keys.c | 2 +-
drivers/input/keyboard/lpc32xx-keys.c | 4 +-
drivers/input/keyboard/pmic8xxx-keypad.c | 4 +-
drivers/input/keyboard/pxa27x_keypad.c | 2 +-
drivers/input/keyboard/samsung-keypad.c | 4 +-
drivers/input/keyboard/spear-keyboard.c | 8 +-
drivers/input/keyboard/st-keyscan.c | 4 +-
drivers/input/keyboard/tegra-kbc.c | 4 +-
drivers/input/misc/drv260x.c | 4 +-
drivers/input/misc/drv2665.c | 4 +-
drivers/input/misc/drv2667.c | 4 +-
drivers/input/misc/gp2ap002a00f.c | 4 +-
drivers/input/misc/kxtj9.c | 4 +-
drivers/input/misc/sirfsoc-onkey.c | 2 +-
drivers/input/mouse/elan_i2c_core.c | 112 +++++++++++----
drivers/input/mouse/navpoint.c | 4 +-
drivers/input/touchscreen/ad7879.c | 6 +-
drivers/input/touchscreen/atmel_mxt_ts.c | 4 +-
drivers/input/touchscreen/auo-pixcir-ts.c | 8 +-
drivers/input/touchscreen/bu21029_ts.c | 4 +-
drivers/input/touchscreen/chipone_icn8318.c | 4 +-
drivers/input/touchscreen/cyttsp_core.c | 4 +-
drivers/input/touchscreen/eeti_ts.c | 4 +-
drivers/input/touchscreen/ektf2127.c | 4 +-
drivers/input/touchscreen/imx6ul_tsc.c | 4 +-
drivers/input/touchscreen/ipaq-micro-ts.c | 2 +-
drivers/input/touchscreen/iqs5xx.c | 4 +-
drivers/input/touchscreen/lpc32xx_ts.c | 4 +-
drivers/input/touchscreen/melfas_mip4.c | 4 +-
drivers/input/touchscreen/mms114.c | 6 +-
drivers/input/touchscreen/pixcir_i2c_ts.c | 8 +-
drivers/input/touchscreen/ucb1400_ts.c | 4 +-
drivers/input/touchscreen/wm97xx-core.c | 14 +-
drivers/input/touchscreen/zforce_ts.c | 8 +-
drivers/platform/x86/thinkpad_acpi.c | 4 +-
include/linux/input.h | 10 ++
43 files changed, 336 insertions(+), 119 deletions(-)
base-commit: 2ef96a5bb12be62ef75b5828c0aab838ebb29cb8
--
2.17.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [RFC] dt-bindings: mailbox: add doorbell support to ARM MHU
From: Jassi Brar @ 2020-05-15 16:46 UTC (permalink / raw)
To: Viresh Kumar
Cc: Devicetree List, Arnd Bergmann, Linux Kernel Mailing List,
Bjorn Andersson, Rob Herring, Sudeep Holla, Frank Rowand,
linux-arm-kernel
In-Reply-To: <0a50f0cf5593baeb628dc8606c523665e5e2ae6c.1589519600.git.viresh.kumar@linaro.org>
On Fri, May 15, 2020 at 12:17 AM Viresh Kumar <viresh.kumar@linaro.org> wrote:
>
> - The hardware gives us the capability to write the register in
> parallel, i.e. we can write 0x800 and 0x400 together without any
> software locks, and so these 32 bits should be considered as separate
> channel even if only one interrupt is issued by the hardware finally.
> This shouldn't be called as virtualization of the channels, as the
> hardware supports this (as clearly mentioned in the TRM) and it takes
> care of handling the signal properly.
>
I'll leave this one open to bikeshed arguments.
> - With serialization, if we use only one channel as today at every
> priority, if there are 5 requests to send signal to the receiver and
> the dvfs request is the last one in queue (which may be called from
> scheduler's hot path with fast switching), it unnecessarily needs to
> wait for the first four transfers to finish due to the software
> locking imposed by the mailbox framework. This adds additional delay,
> maybe of few ms only, which isn't required by the hardware but just by
> the software and few ms can be important in scheduler's hotpath.
>
As I asked you yesterday over the call, it may help if you could share
some numbers to back up the doomsday scenario.
I don't believe mailbox will be a bottleneck, unless you send commands
in a while(1) ... but even then you have to compare against the
virtual-channel implementation. (Not to forget one usually doesn't
need/want the dvfs, power, clock, hotplug all happening at the _same_
time)
Please note, SCMI... lets not pretend it is not about making scmi work
with mhu :) ... itself uses shared-memory transfers and
wait_for_completion_timeout in scmi_do_xfer(). If some platform
_really-really_ faced speed bottlenecks, it would come to want to
exchange 32-bit encoded command/response over the mhu register,
asynchronously and totally bypassing shmem... which is possible only
now.
> - With the current approach it isn't possible to assign different bits
> (or doorbell numbers) to clients from DT and the only way of doing
> that without adding new bindings is by extending #mbox-cells to accept
> a value of 2 as done in this patch.
>
I am afraid you are confused. You can use bit/doorbell-6 by passing
0x40 to mhu as the data to send.
Cheers!
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH] cpuidle: psci: Fixup execution order when entering a domain idle state
From: Rafael J. Wysocki @ 2020-05-15 16:38 UTC (permalink / raw)
To: Ulf Hansson
Cc: Lorenzo Pieralisi, Benjamin Gaignard, Linux PM, Stephen Boyd,
Daniel Lezcano, Rafael J . Wysocki, Lina Iyer, Bjorn Andersson,
Sudeep Holla, Linux ARM
In-Reply-To: <CAPDyKFrsfLExZHvNrJgqsJj8TTzj9jg5v=jEowBTdi26uyjZXg@mail.gmail.com>
On Fri, May 15, 2020 at 1:30 PM Ulf Hansson <ulf.hansson@linaro.org> wrote:
>
> On Fri, 15 May 2020 at 12:23, Sudeep Holla <sudeep.holla@arm.com> wrote:
> >
> > On Thu, May 14, 2020 at 09:11:50PM +0200, Ulf Hansson wrote:
> > >
> > > No worries, thanks for reviewing.
> > >
> >
> > You are welcome.
> >
> > > That said, are you fine with Rafel queuing this then?
> > >
> >
> > I am fine with that. However I told if you need fixes tags as there are
> > no users of the notification yet in the kernel. Though this is trivial,
> > but do we need this backported to stable kernel. I don't have strong
> > opinion and leave it to you and Rafael.
>
> I wanted to add the fixes tag, to make it obvious that there is an
> error being fixed.
>
> On the other hand, no need to tag this for stable, nor to need to send
> it as fix for 5.7,
>
> >
> > Acked-by: Sudeep Holla <sudeep.holla@arm.com>
>
> Thanks!
So applied as 5.8 material, thanks!
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox