From: Max Filippov <jcmvbkbc@gmail.com>
To: linux-xtensa@linux-xtensa.org
Cc: Chris Zankel <chris@zankel.net>,
linux-kernel@vger.kernel.org, Max Filippov <jcmvbkbc@gmail.com>,
Thomas Gleixner <tglx@linutronix.de>
Subject: [PATCH] highmem: fix highmem for xtensa
Date: Fri, 13 Nov 2020 04:23:28 -0800 [thread overview]
Message-ID: <20201113122328.22942-1-jcmvbkbc@gmail.com> (raw)
Fixmap on xtensa grows upwards, i.e. bigger fixmap entry index
corresponds to a higher virtual address. This was lost in highmem
generalization resulting in the following runtime warnings:
WARNING: CPU: 0 PID: 18 at mm/highmem.c:494 kunmap_local_indexed+0x45/0x54
Modules linked in:
CPU: 0 PID: 18 Comm: kworker/u2:0 Not tainted 5.10.0-rc3-next-20201113 #1
Call Trace:
__warn+0x8f/0xc8
warn_slowpath_fmt+0x35/0x70
kunmap_local_indexed+0x45/0x54
handle_mm_fault+0x325/0xbe0
__get_user_pages.part.61+0x131/0x22c
__get_user_pages+0x44/0x60
__get_user_pages_remote+0xe8/0x290
get_user_pages_remote+0x24/0x40
get_arg_page+0x50/0x78
copy_string_kernel+0x5c/0x120
kernel_execve+0x76/0xc8
call_usermodehelper_exec_async+0xc8/0x10c
ret_from_kernel_thread+0xc/0x18
Fix it by adding __ARCH_HAS_POSITIVE_FIXMAP macro and implementing
vaddr_in_fixmap and fixmap_pte primitives differently depending on
whether it is defined or not.
Cc: Thomas Gleixner <tglx@linutronix.de>
Fixes: 629ed3f7dad2 ("xtensa/mm/highmem: Switch to generic kmap atomic")
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
arch/xtensa/include/asm/fixmap.h | 2 ++
mm/highmem.c | 29 ++++++++++++++++++++++++-----
2 files changed, 26 insertions(+), 5 deletions(-)
diff --git a/arch/xtensa/include/asm/fixmap.h b/arch/xtensa/include/asm/fixmap.h
index 92049b61c351..66787b5f13d6 100644
--- a/arch/xtensa/include/asm/fixmap.h
+++ b/arch/xtensa/include/asm/fixmap.h
@@ -51,6 +51,8 @@ enum fixed_addresses {
#define __fix_to_virt(x) (FIXADDR_START + ((x) << PAGE_SHIFT))
#define __virt_to_fix(x) (((x) - FIXADDR_START) >> PAGE_SHIFT)
+#define __ARCH_HAS_POSITIVE_FIXMAP
+
#ifndef __ASSEMBLY__
/*
* 'index to address' translation. If anyone tries to use the idx
diff --git a/mm/highmem.c b/mm/highmem.c
index 54bd233846c9..af27ed8d6a97 100644
--- a/mm/highmem.c
+++ b/mm/highmem.c
@@ -434,6 +434,26 @@ static inline void kmap_high_unmap_local(unsigned long vaddr)
#endif
}
+static inline bool vaddr_in_fixmap(unsigned long addr)
+{
+#ifdef __ARCH_HAS_POSITIVE_FIXMAP
+ return addr <= __fix_to_virt(FIX_KMAP_END) &&
+ addr >= __fix_to_virt(FIX_KMAP_BEGIN);
+#else
+ return addr >= __fix_to_virt(FIX_KMAP_END) &&
+ addr <= __fix_to_virt(FIX_KMAP_BEGIN);
+#endif
+}
+
+static pte_t *fixmap_pte(pte_t *kmap_pte, int idx)
+{
+#ifdef __ARCH_HAS_POSITIVE_FIXMAP
+ return kmap_pte + idx;
+#else
+ return kmap_pte - idx;
+#endif
+}
+
static inline int kmap_local_calc_idx(int idx)
{
return idx + KM_MAX_IDX * smp_processor_id();
@@ -457,9 +477,9 @@ void *__kmap_local_pfn_prot(unsigned long pfn, pgprot_t prot)
preempt_disable();
idx = arch_kmap_local_map_idx(kmap_local_idx_push(), pfn);
vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
- BUG_ON(!pte_none(*(kmap_pte - idx)));
+ BUG_ON(!pte_none(*(fixmap_pte(kmap_pte, idx))));
pteval = pfn_pte(pfn, prot);
- set_pte_at(&init_mm, vaddr, kmap_pte - idx, pteval);
+ set_pte_at(&init_mm, vaddr, fixmap_pte(kmap_pte, idx), pteval);
arch_kmap_local_post_map(vaddr, pteval);
preempt_enable();
@@ -489,8 +509,7 @@ void kunmap_local_indexed(void *vaddr)
pte_t *kmap_pte = kmap_get_pte();
int idx;
- if (addr < __fix_to_virt(FIX_KMAP_END) ||
- addr > __fix_to_virt(FIX_KMAP_BEGIN)) {
+ if (!vaddr_in_fixmap(addr)) {
WARN_ON_ONCE(addr < PAGE_OFFSET);
/* Handle mappings which were obtained by kmap_high_get() */
@@ -503,7 +522,7 @@ void kunmap_local_indexed(void *vaddr)
WARN_ON_ONCE(addr != __fix_to_virt(FIX_KMAP_BEGIN + idx));
arch_kmap_local_pre_unmap(addr);
- pte_clear(&init_mm, addr, kmap_pte - idx);
+ pte_clear(&init_mm, addr, fixmap_pte(kmap_pte, idx));
arch_kmap_local_post_unmap(addr);
kmap_local_idx_pop();
preempt_enable();
--
2.20.1
next reply other threads:[~2020-11-13 12:23 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-11-13 12:23 Max Filippov [this message]
2020-11-13 13:40 ` Thomas Gleixner
2020-11-13 13:50 ` Max Filippov
2020-11-13 14:36 ` Thomas Gleixner
2020-11-13 16:34 ` Max Filippov
2020-11-13 22:34 ` Thomas Gleixner
2020-11-16 14:47 ` Max Filippov
2020-11-16 17:37 ` Thomas Gleixner
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20201113122328.22942-1-jcmvbkbc@gmail.com \
--to=jcmvbkbc@gmail.com \
--cc=chris@zankel.net \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-xtensa@linux-xtensa.org \
--cc=tglx@linutronix.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Powered by JetHome