All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jiri Slaby <jslaby@suse.cz>
To: stable@vger.kernel.org
Cc: Mikulas Patocka <mpatocka@redhat.com>,
	Helge Deller <deller@gmx.de>, Jiri Slaby <jslaby@suse.cz>
Subject: [patch added to 3.12-stable] parisc iommu: fix panic due to trying to allocate too large region
Date: Thu, 28 Jan 2016 11:52:20 +0100	[thread overview]
Message-ID: <1453978346-20237-29-git-send-email-jslaby@suse.cz> (raw)
In-Reply-To: <1453978346-20237-1-git-send-email-jslaby@suse.cz>

From: Mikulas Patocka <mpatocka@redhat.com>

This patch has been added to the 3.12 stable tree. If you have any
objections, please let us know.

===============

commit e46e31a3696ae2d66f32c207df3969613726e636 upstream.

When using the Promise TX2+ SATA controller on PA-RISC, the system often
crashes with kernel panic, for example just writing data with the dd
utility will make it crash.

Kernel panic - not syncing: drivers/parisc/sba_iommu.c: I/O MMU @ 000000000000a000 is out of mapping resources

CPU: 0 PID: 18442 Comm: mkspadfs Not tainted 4.4.0-rc2 #2
Backtrace:
 [<000000004021497c>] show_stack+0x14/0x20
 [<0000000040410bf0>] dump_stack+0x88/0x100
 [<000000004023978c>] panic+0x124/0x360
 [<0000000040452c18>] sba_alloc_range+0x698/0x6a0
 [<0000000040453150>] sba_map_sg+0x260/0x5b8
 [<000000000c18dbb4>] ata_qc_issue+0x264/0x4a8 [libata]
 [<000000000c19535c>] ata_scsi_translate+0xe4/0x220 [libata]
 [<000000000c19a93c>] ata_scsi_queuecmd+0xbc/0x320 [libata]
 [<0000000040499bbc>] scsi_dispatch_cmd+0xfc/0x130
 [<000000004049da34>] scsi_request_fn+0x6e4/0x970
 [<00000000403e95a8>] __blk_run_queue+0x40/0x60
 [<00000000403e9d8c>] blk_run_queue+0x3c/0x68
 [<000000004049a534>] scsi_run_queue+0x2a4/0x360
 [<000000004049be68>] scsi_end_request+0x1a8/0x238
 [<000000004049de84>] scsi_io_completion+0xfc/0x688
 [<0000000040493c74>] scsi_finish_command+0x17c/0x1d0

The cause of the crash is not exhaustion of the IOMMU space, there is
plenty of free pages. The function sba_alloc_range is called with size
0x11000, thus the pages_needed variable is 0x11. The function
sba_search_bitmap is called with bits_wanted 0x11 and boundary size is
0x10 (because dma_get_seg_boundary(dev) returns 0xffff).

The function sba_search_bitmap attempts to allocate 17 pages that must not
cross 16-page boundary - it can't satisfy this requirement
(iommu_is_span_boundary always returns true) and fails even if there are
many free entries in the IOMMU space.

How did it happen that we try to allocate 17 pages that don't cross
16-page boundary? The cause is in the function iommu_coalesce_chunks. This
function tries to coalesce adjacent entries in the scatterlist. The
function does several checks if it may coalesce one entry with the next,
one of those checks is this:

	if (startsg->length + dma_len > max_seg_size)
		break;

When it finishes coalescing adjacent entries, it allocates the mapping:

sg_dma_len(contig_sg) = dma_len;
dma_len = ALIGN(dma_len + dma_offset, IOVP_SIZE);
sg_dma_address(contig_sg) =
	PIDE_FLAG
	| (iommu_alloc_range(ioc, dev, dma_len) << IOVP_SHIFT)
	| dma_offset;

It is possible that (startsg->length + dma_len > max_seg_size) is false
(we are just near the 0x10000 max_seg_size boundary), so the funcion
decides to coalesce this entry with the next entry. When the coalescing
succeeds, the function performs
	dma_len = ALIGN(dma_len + dma_offset, IOVP_SIZE);
And now, because of non-zero dma_offset, dma_len is greater than 0x10000.
iommu_alloc_range (a pointer to sba_alloc_range) is called and it attempts
to allocate 17 pages for a device that must not cross 16-page boundary.

To fix the bug, we must make sure that dma_len after addition of
dma_offset and alignment doesn't cross the segment boundary. I.e. change
	if (startsg->length + dma_len > max_seg_size)
		break;
to
	if (ALIGN(dma_len + dma_offset + startsg->length, IOVP_SIZE) > max_seg_size)
		break;

This patch makes this change (it precalculates max_seg_boundary at the
beginning of the function iommu_coalesce_chunks). I also added a check
that the mapping length doesn't exceed dma_get_seg_boundary(dev) (it is
not needed for Promise TX2+ SATA, but it may be needed for other devices
that have dma_get_seg_boundary lower than dma_get_max_seg_size).

Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
Signed-off-by: Helge Deller <deller@gmx.de>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
---
 drivers/parisc/iommu-helpers.h | 15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/drivers/parisc/iommu-helpers.h b/drivers/parisc/iommu-helpers.h
index 8c33491b21fe..c6aa38883466 100644
--- a/drivers/parisc/iommu-helpers.h
+++ b/drivers/parisc/iommu-helpers.h
@@ -104,7 +104,11 @@ iommu_coalesce_chunks(struct ioc *ioc, struct device *dev,
 	struct scatterlist *contig_sg;	   /* contig chunk head */
 	unsigned long dma_offset, dma_len; /* start/len of DMA stream */
 	unsigned int n_mappings = 0;
-	unsigned int max_seg_size = dma_get_max_seg_size(dev);
+	unsigned int max_seg_size = min(dma_get_max_seg_size(dev),
+					(unsigned)DMA_CHUNK_SIZE);
+	unsigned int max_seg_boundary = dma_get_seg_boundary(dev) + 1;
+	if (max_seg_boundary)	/* check if the addition above didn't overflow */
+		max_seg_size = min(max_seg_size, max_seg_boundary);
 
 	while (nents > 0) {
 
@@ -139,14 +143,11 @@ iommu_coalesce_chunks(struct ioc *ioc, struct device *dev,
 
 			/*
 			** First make sure current dma stream won't
-			** exceed DMA_CHUNK_SIZE if we coalesce the
+			** exceed max_seg_size if we coalesce the
 			** next entry.
 			*/   
-			if(unlikely(ALIGN(dma_len + dma_offset + startsg->length,
-					    IOVP_SIZE) > DMA_CHUNK_SIZE))
-				break;
-
-			if (startsg->length + dma_len > max_seg_size)
+			if (unlikely(ALIGN(dma_len + dma_offset + startsg->length, IOVP_SIZE) >
+				     max_seg_size))
 				break;
 
 			/*
-- 
2.7.0


  parent reply	other threads:[~2016-01-28 10:52 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-01-28 10:51 [patch added to 3.12-stable] ARM: 8158/1: LLVMLinux: use static inline in ARM ftrace.h Jiri Slaby
2016-01-28 10:51 ` [patch added to 3.12-stable] ARM: 8160/1: drop warning about return_address not using unwind tables Jiri Slaby
2016-01-28 11:07   ` Uwe Kleine-König
2016-01-28 10:51 ` [patch added to 3.12-stable] drm/radeon: cypress_dpm: Fix unused variable warning when CONFIG_ACPI=n Jiri Slaby
2016-01-28 10:51 ` [patch added to 3.12-stable] drm: radeon: ni_dpm: " Jiri Slaby
2016-01-28 10:51 ` [patch added to 3.12-stable] lkdtm: adjust recursion size to avoid warnings Jiri Slaby
2016-01-28 10:51 ` [patch added to 3.12-stable] RDMA/cxgb4: Fix gcc warning on 32-bit arch Jiri Slaby
2016-01-28 10:51 ` [patch added to 3.12-stable] mISDN: avoid arch specific __builtin_return_address call Jiri Slaby
2016-01-28 10:51 ` [patch added to 3.12-stable] veth: don’t modify ip_summed; doing so treats packets with bad checksums as good Jiri Slaby
2016-01-28 10:52 ` [patch added to 3.12-stable] ipv6/addrlabel: fix ip6addrlbl_get() Jiri Slaby
2016-01-28 10:52 ` [patch added to 3.12-stable] sctp: sctp should release assoc when sctp_make_abort_user return NULL in sctp_close Jiri Slaby
2016-01-28 10:52 ` [patch added to 3.12-stable] connector: bump skb->users before callback invocation Jiri Slaby
2016-01-28 10:52 ` [patch added to 3.12-stable] unix: properly account for FDs passed over unix sockets Jiri Slaby
2016-01-28 10:52 ` [patch added to 3.12-stable] bridge: Only call /sbin/bridge-stp for the initial network namespace Jiri Slaby
2016-01-28 10:52 ` [patch added to 3.12-stable] net: sctp: prevent writes to cookie_hmac_alg from accessing invalid memory Jiri Slaby
2016-01-28 10:52 ` [patch added to 3.12-stable] ipv6: tcp: add rcu locking in tcp_v6_send_synack() Jiri Slaby
2016-01-28 10:52 ` [patch added to 3.12-stable] tcp_yeah: don't set ssthresh below 2 Jiri Slaby
2016-01-28 10:52 ` [patch added to 3.12-stable] phonet: properly unshare skbs in phonet_rcv() Jiri Slaby
2016-01-28 10:52 ` [patch added to 3.12-stable] ipv6: update skb->csum when CE mark is propagated Jiri Slaby
2016-01-28 10:52 ` [patch added to 3.12-stable] team: Replace rcu_read_lock with a mutex in team_vlan_rx_kill_vid Jiri Slaby
2016-01-28 10:52 ` [patch added to 3.12-stable] xfrm: dst_entries_init() per-net dst_ops Jiri Slaby
2016-01-28 10:52 ` [patch added to 3.12-stable] powerpc/tm: Block signal return setting invalid MSR state Jiri Slaby
2016-01-28 10:52 ` [patch added to 3.12-stable] powerpc: Make value-returning atomics fully ordered Jiri Slaby
2016-01-28 10:52 ` [patch added to 3.12-stable] powerpc: Make {cmp}xchg* and their atomic_ versions " Jiri Slaby
2016-01-28 10:52 ` [patch added to 3.12-stable] scripts/recordmcount.pl: support data in text section on powerpc Jiri Slaby
2016-01-28 10:52 ` [patch added to 3.12-stable] arm64: KVM: Fix AArch32 to AArch64 register mapping Jiri Slaby
2016-01-28 10:52 ` [patch added to 3.12-stable] arm64: fix building without CONFIG_UID16 Jiri Slaby
2016-01-28 10:52 ` [patch added to 3.12-stable] arm64: Clear out any singlestep state on a ptrace detach operation Jiri Slaby
2016-01-28 10:52 ` [patch added to 3.12-stable] arm64: mm: ensure that the zero page is visible to the page table walker Jiri Slaby
2016-01-28 10:52 ` Jiri Slaby [this message]
2016-01-28 10:52 ` [patch added to 3.12-stable] HID: core: Avoid uninitialized buffer access Jiri Slaby
2016-01-28 10:52 ` [patch added to 3.12-stable] mn10300: Select CONFIG_HAVE_UID16 to fix build failure Jiri Slaby

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=1453978346-20237-29-git-send-email-jslaby@suse.cz \
    --to=jslaby@suse.cz \
    --cc=deller@gmx.de \
    --cc=mpatocka@redhat.com \
    --cc=stable@vger.kernel.org \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.