Linux-USB Archive on lore.kernel.org
 help / color / Atom feed
From: Ross Zwisler <zwisler@google.com>
To: Mathias Nyman <mathias.nyman@linux.intel.com>
Cc: Andrzej Pietrasiewicz <andrzej.p@collabora.com>,
	"linux-usb@vger.kernel.org" <linux-usb@vger.kernel.org>,
	"kernel@collabora.com" <kernel@collabora.com>
Subject: Re: xhci problem -> general protection fault
Date: Fri, 25 Sep 2020 15:05:17 -0600
Message-ID: <20200925210517.GA4487@google.com> (raw)
In-Reply-To: <133c123e-e857-7f83-d146-f39c00afe39f@linux.intel.com>

On Fri, Sep 25, 2020 at 04:40:29PM +0300, Mathias Nyman wrote:
> On 18.9.2020 17.20, Andrzej Pietrasiewicz wrote:
> > Hi Mathias,
> > 
> > W dniu 18.09.2020 o 12:50, Mathias Nyman pisze:
> >> On 17.9.2020 18.30, Andrzej Pietrasiewicz wrote:
> >>> Dear All,
> >>>
> >>> I have encountered a problem in xhci which leads to general protection fault.
> >>>
> >>> The problem is triggered by running this program:
> >>>
> >>> https://gitlab.collabora.com/andrzej.p/bulk-cancel.git
> >>>
> >>> $ sudo ./bulk-cancel -D /dev/bus/usb/002/006 -i 1 -b 1
> >>>
> >>> where /dev/bus/usb/002/006 is a Gadget Zero:
> >>>
> >>> It takes less than a minute until the crash happens.
> >>> The DMAR (iommu) errors don't happen always, i.e. there are crashes
> >>> when they are not reported in the system log. In either case the
> >>>
> >>> "WARN Cannot submit Set TR Deq Ptr"
> >>> "A Set TR Deq Ptr command is pending."
> >>> "WARN Set TR Deq Ptr cmd failed due to incorrect slot or ep state."
> >>>
> >>> messages do appear.
> >>>
> >>
> >> Nice testcase and report, thanks.
> >>
> >> I started looking at issues in this area some time ago, and wrote a couple patches but
> >> it was left hanging. The two patches (now rebased on 5.9-rc3) can be found in my tree in the
> >> fix_invalid_context_at_stop_endpoint branch
> >>
> >> git://git.kernel.org/pub/scm/linux/kernel/git/mnyman/xhci.git fix_invalid_context_at_stop_endpoint
> >>
> >> https://git.kernel.org/pub/scm/linux/kernel/git/mnyman/xhci.git/log/?h=fix_invalid_context_at_stop_endpoint
> >>
> >> If you could give those a try and see if they help I'd be grateful.
> > 
> > No, it doesn't help, albeit the errors are slightly different:
> > 
> > xhci_hcd 0000:00:14.0: WARN Cannot submit Set TR Deq Ptr
> > xhci_hcd 0000:00:14.0: A Set TR Deq Ptr command is pending.
> > dmar_fault: 44 callbacks suppressed
> > DRHD: handling fault status reg 3> DMAR: [DMA Write] Request device [00:14.0] PASID ffffffff fault addr ffcda000 [fault reason 05] PTE Write access is not set
> > DMAR: DRHD: handling fault status reg 3
> 
> Ok, thanks, the DMA problems make sense to me now.
> 
> If a transfer ring stops on a transfer request (TRB) that should be canceled (manual cancel,
> or error) it's not enough to just turn the  TRB to a no-op.
> HW has most likely cached the TRB, and we need to move the transfer ring dequeue pointer past this TRB.
> Moving deq also clears controller cache.
> 
> We do all this, but if we fail to queue the Set TR Deq command the TRB (with DMA  pointers) will stay on the ring,
> and controller will access the TRB DMA  address once it continues running. At this point xhci driver has already
> given back the canceled/erroneous TRB, and is probably unmapped already.
> Hence the DMAR entries.  
> 
> Looks like this part of the code needs a more extensive rewrite, on top of this we are not handling
> races between endpoints halted due errors, and endpoints stopped by driver to cancel URBs. 
> 
> -Mathias

I'm chasing a similar problem which is also most easily reproduced using
Andrzej's bulk-cancel program, though we have seen it in the field many times
as well with normal usage.

The symptom is that we get the following errors in dmesg:

 xhci_hcd 0000:00:14.0: Mismatch between completed Set TR Deq Ptr command & xHCI internal state.
 xhci_hcd 0000:00:14.0: ep deq seg = 000000001141d6a0, deq ptr = 00000000ebd28dcf
 xhci_hcd 0000:00:14.0: WARNING: Host System Error
 DMAR: DRHD: handling fault status reg 2
 DMAR: [DMA Read] Request device [00:14.0] PASID ffffffff fault addr 0 [fault reason 06] PTE Read access is not set
 xhci_hcd 0000:00:14.0: xHCI host not responding to stop endpoint command.
 xhci_hcd 0000:00:14.0: USBSTS: HCHalted HSE EINT
 xhci_hcd 0000:00:14.0: xHCI host controller not responding, assume dead
 xhci_hcd 0000:00:14.0: HC died; cleaning up

The xhci USB stack loses all attached devices, and on my system at least has
only been recoverable by rebooting.

Full dmesg and trace after 'echo 1 > /sys/kernel/debug/tracing/events/xhci-hcd/enable'
can be found here:

https://gist.github.com/rzwisler/531b926e3d160609ead371c23fc15b55
https://gist.github.com/rzwisler/4621f805737993fec30b5ae23bfd8289

One interesting bit from the trace is that we observe the ep_ctx->deq pointer
being 0 in xhci_handle_cmd_set_deq():

 xhci_inc_enq: CMD 000000000b6352e0: enq 0x00000000ffffe0c0(0x00000000ffffe000) deq 0x00000000ffffe090(0x00000000ffffe000) segs 1 stream 0 free_trbs 251 bounce 0 cycle 0
 xhci_ring_host_doorbell: Ring doorbell for Command Ring 0
 xhci_urb_giveback: ep7in-bulk: urb 000000003c80b7a8 pipe 3221455744 slot 2 length 0/256 sgs 0/0 stream 0 flags 00010200
 xhci_inc_deq: CMD 000000000b6352e0: enq 0x00000000ffffe0c0(0x00000000ffffe000) deq 0x00000000ffffe0a0(0x00000000ffffe000) segs 1 stream 0 free_trbs 252 bounce 0 cycle 0
 xhci_inc_deq: EVENT 00000000b5c6e6a2: enq 0x00000000ffffc000(0x00000000ffffc000) deq 0x00000000ffffc1b0(0x00000000ffffc000) segs 1 stream 0 free_trbs 254 bounce 0 cycle 1
 xhci_handle_event: EVENT: TRB 00000000ffffe0a0 status 'Success' len 0 slot 4 ep 0 type 'Command Completion Event' flags e:C
 xhci_handle_command: CMD: Set TR Dequeue Pointer Command: deq 00000000fff296a1 stream 0 slot 4 ep 3 flags c
 xhci_handle_cmd_set_deq: RS 00000 full-speed Ctx Entries 15 MEL 0 us Port# 13/0 [TT Slot 0 Port# 0 TTT 0 Intr 0] Addr 4 State configured
 xhci_handle_cmd_set_deq_ep: State stopped mult 1 max P. Streams 0 interval 125 us max ESIT payload 0 CErr 3 Type Bulk IN burst 0 maxp 64 deq 0000000000000000 avg trb len 0
																	  ^^^^^^^^^^^^^^^^^^^^
 xhci_dbg_cancel_urb: Successful Set TR Deq Ptr cmd, deq = @00000000
						     ^^^^^^^^^^^^^^^

In successful completions they are real values:

 xhci_ring_ep_doorbell: Ring doorbell for Slot 4 ep1in
 xhci_inc_deq: CMD 000000000b6352e0: enq 0x00000000ffffe0c0(0x00000000ffffe000) deq 0x00000000ffffe0b0(0x00000000ffffe000) segs 1 stream 0 free_trbs 253 bounce 0 cycle 0
 xhci_inc_deq: EVENT 00000000b5c6e6a2: enq 0x00000000ffffc000(0x00000000ffffc000) deq 0x00000000ffffc1c0(0x00000000ffffc000) segs 1 stream 0 free_trbs 254 bounce 0 cycle 1
 xhci_handle_event: EVENT: TRB 00000000ffffe0b0 status 'Success' len 0 slot 2 ep 0 type 'Command Completion Event' flags e:C
 xhci_handle_command: CMD: Set TR Dequeue Pointer Command: deq 00000000fff86551 stream 0 slot 2 ep 15 flags c
 xhci_handle_cmd_set_deq: RS 00000 full-speed Ctx Entries 15 MEL 0 us Port# 11/0 [TT Slot 0 Port# 0 TTT 0 Intr 0] Addr 2 State configured
 xhci_handle_cmd_set_deq_ep: State stopped mult 1 max P. Streams 0 interval 125 us max ESIT payload 0 CErr 3 Type Bulk IN burst 0 maxp 16 deq 00000000fff86551 avg trb len 0
																	  ^^^^^^^^^^^^^^^^^^^^
 xhci_dbg_cancel_urb: Successful Set TR Deq Ptr cmd, deq = @fff86550
						     ^^^^^^^^^^^^^^^

I've noticed that I have to have CONFIG_INTEL_IOMMU_DEFAULT_ON=y for this
clean repro case, else the system still fails but I don't always (ever?) see
the failure to read at address 0.  

Mathias, do you think that your above explanation also covers my failure case?  
Are we just failing to enqueue a Set TR Deq command, and the HC is processing
a stale TRB?  Or does the fact that ep_ctx->deq == 0 not fit with that
explanation?

Other tidbits that I've disovered along the way:

1) We first started noticing this in the field with v4.19 based kernels, but
   I've been able to reproduce it using bulk-cancel with a v4.18 kernel
   without much trouble, so I'm pretty sure it's an old issue.

2) This definitely looks like a race which is very sensitive to timing.  If I
   put a single trace_printk() line in xhci_handle_cmd_set_deq() function, the
   issue is 10x harder to repro (on average 3 seconds to on average 30
   seconds).  Similarly, when we turned on tracing in the field to try and get
   logs the issue reproduces much less frequently.  I also tried to bisect,
   and it turns out that whether or not it reproduced on my system with older
   kernels was dependent on how tracing functions were inlined (!!).

   I think that we started seeing this in the field with v4.19 based kernels
   purely because of a timing change.

3) I did run with your patches from
   https://git.kernel.org/pub/scm/linux/kernel/git/mnyman/xhci.git/log/?h=fix_invalid_context_at_stop_endpoint
   and it didn't change anything for me.

I'm reading up more on xhci and trying to understand this race, but would
appreciate any help or direction that you're able to provide.

Thanks,
- Ross

  reply index

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-09-17 15:30 Andrzej Pietrasiewicz
2020-09-18 10:50 ` Mathias Nyman
2020-09-18 14:20   ` Andrzej Pietrasiewicz
2020-09-25 13:40     ` Mathias Nyman
2020-09-25 21:05       ` Ross Zwisler [this message]
2020-09-28 13:32         ` Andrzej Pietrasiewicz
2020-09-29  7:13           ` Mathias Nyman
2020-10-01 14:13             ` Andrzej Pietrasiewicz
2020-09-28 22:35         ` Mathias Nyman
2020-10-01 16:43           ` zwisler
2020-10-12 19:20             ` Mathias Nyman
2020-10-12 21:53               ` zwisler
2020-10-13  7:49                 ` Mathias Nyman
2020-10-13  8:29                   ` Andrzej Pietrasiewicz
2020-10-13 16:44                     ` zwisler
2020-11-19 16:52                   ` Ross Zwisler
2020-11-23 15:06                     ` Mathias Nyman
2020-12-02 22:59                       ` Ross Zwisler
2020-12-04 18:07                         ` Mathias Nyman
2020-12-08 17:24                           ` Ross Zwisler
2020-12-09 13:11                             ` Mathias Nyman
2020-12-09 18:54                               ` Ross Zwisler
2020-12-30 12:33                                 ` Mathias Nyman
2021-01-06 18:52                                   ` Ross Zwisler
2021-01-07  8:57                                     ` Mathias Nyman
2021-01-07 16:07                                       ` Ross Zwisler

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=20200925210517.GA4487@google.com \
    --to=zwisler@google.com \
    --cc=andrzej.p@collabora.com \
    --cc=kernel@collabora.com \
    --cc=linux-usb@vger.kernel.org \
    --cc=mathias.nyman@linux.intel.com \
    /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

Linux-USB Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/linux-usb/0 linux-usb/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 linux-usb linux-usb/ https://lore.kernel.org/linux-usb \
		linux-usb@vger.kernel.org
	public-inbox-index linux-usb

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.linux-usb


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git