Patch "x86/mm/kmmio: Fix mmiotrace for page unaligned addresses" has been added to the 4.14-stable tree
Subsystems (4)
This is a note to let you know that I've just added the patch titled
x86/mm/kmmio: Fix mmiotrace for page unaligned addresses
to the 4.14-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
x86-mm-kmmio-fix-mmiotrace-for-page-unaligned-addresses.patch
and it can be found in the queue-4.14 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From foo@baz Fri Feb 23 11:45:09 CET 2018
From: Karol Herbst <[email protected]>
Date: Mon, 27 Nov 2017 08:51:39 +0100
Subject: x86/mm/kmmio: Fix mmiotrace for page unaligned addresses
From: Karol Herbst <[email protected]>
[ Upstream commit 6d60ce384d1d5ca32b595244db4077a419acc687 ]
If something calls ioremap() with an address not aligned to PAGE_SIZE, the returned address might be not aligned as well. This led to a probe registered on exactly the returned address, but the entire page was armed for mmiotracing.
On calling iounmap() the address passed to unregister_kmmio_probe() was PAGE_SIZE aligned by the caller leading to a complete freeze of the machine.
We should always page align addresses while (un)registerung mappings, because the mmiotracer works on top of pages, not mappings. We still keep track of the probes based on their real addresses and lengths though, because the mmiotrace still needs to know what are mapped memory regions.
Also move the call to mmiotrace_iounmap() prior page aligning the address, so that all probes are unregistered properly, otherwise the kernel ends up failing memory allocations randomly after disabling the mmiotracer.
--- arch/x86/mm/ioremap.c | 4 ++-- arch/x86/mm/kmmio.c | 12 +++++++----- 2 files changed, 9 insertions(+), 7 deletions(-)
arch/x86/mm/ioremap.c +2 -2
@@ -349,11 +349,11 @@ void iounmap(volatile void __iomem *addrreturn ; } +mmiotrace_iounmap (addr); + addr = (volatile void __iomem *) (PAGE_MASK & (unsigned long __force )addr); -mmiotrace_iounmap (addr); -/* Use the vm area unlocked, assuming the caller ensures there isn't another iounmap for the same address in parallel. Reuse of the virtual address is prevented by
arch/x86/mm/kmmio.c +7 -5
@@ -435,17 +435,18 @@ int register_kmmio_probe(struct kmmio_prunsigned long flags;int ret =0 ;unsigned long size =0 ; +unsigned long addr = p->addr &PAGE_MASK ;const unsigned long size_lim = p->len + (p->addr & ~PAGE_MASK );unsigned int l;pte_t *pte;spin_lock_irqsave (&kmmio_lock, flags); -if (get_kmmio_probe (p->addr)) { +if (get_kmmio_probe (addr)) { ret = -EEXIST ; goto out; } - pte =lookup_address (p->addr, &l); + pte =lookup_address (addr, &l);if (!pte) { ret = -EINVAL ; goto out;
@@ -454,7 +455,7 @@ int register_kmmio_probe(struct kmmio_pr kmmio_count++;list_add_rcu (&p->list, &kmmio_probes);while (size < size_lim) { -if (add_kmmio_fault_page (p->addr + size)) +if (add_kmmio_fault_page (addr + size))pr_err ("Unable to set page fault.\n" ); size +=page_level_size (l); }
@@ -528,19 +529,20 @@ void unregister_kmmio_probe(struct kmmio {unsigned long flags;unsigned long size =0 ; +unsigned long addr = p->addr &PAGE_MASK ;const unsigned long size_lim = p->len + (p->addr & ~PAGE_MASK );struct kmmio_fault_page *release_list =NULL ;struct kmmio_delayed_release *drelease;unsigned int l;pte_t *pte; - pte =lookup_address (p->addr, &l); + pte =lookup_address (addr, &l);if (!pte)return ;spin_lock_irqsave (&kmmio_lock, flags);while (size < size_lim) { -release_kmmio_fault_page (p->addr + size, &release_list); +release_kmmio_fault_page (addr + size, &release_list); size +=page_level_size (l); }list_del_rcu (&p->list);
Patches currently in stable-queue which might be from [email protected] are
queue-4.14/x86-mm-kmmio-fix-mmiotrace-for-page-unaligned-addresses.patch