qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH 2/2] ide/atapi: partially avoid deadlock if the


From: Stefan Hajnoczi
Subject: Re: [Qemu-devel] [PATCH 2/2] ide/atapi: partially avoid deadlock if the storage backend is dead
Date: Mon, 7 Sep 2015 14:43:26 +0100
User-agent: Mutt/1.5.23 (2014-03-12)

On Sun, Sep 06, 2015 at 11:24:10AM +0200, Peter Lieven wrote:
> > Taking a step back, what are the semantics of writing !(val &
> > BM_CMD_START)?  Is the device guaranteed to cancel/complete requests
> > during the register write?
> 
> I have to check that. John, do you have an idea?
> 
> Stefan, or do you have a better approach for getting rid of the bdrv_drain_all
> in this piece of code?

What's needed is an asynchronous approach that honors the semantics of
the Start/Stop bit.

>From "Programming Interface for Bus Master IDE Controller", Revision 1.0:

"Start/Stop Bus Master: Writing a '1' to this bit enables bus master
operation of the controller.  Bus master operation begins when this bit
is detected changing from a zero to a one. The controller will transfer
data between the IDE device and memory only when this bit is set.
Master operation can be halted by writing a '0' to this bit. All state
information is lost when a '0' is written; Master mode operation cannot
be stopped and then resumed. If this bit is reset while bus master
operation is still active (i.e., the Bus Master IDE Active bit of the
Bus Master IDE Status register for that IDE channel is set) and the
drive has not yet finished its data transfer (The Interupt bit in the
Bus Master IDE Status register for that IDE channel is not set), the bus
master command is said to be aborted and data transfered from the drive
may be discarded before being written to system memory. This bit is
intended to be reset after the data transfer is completed, as indicated
by either the Bus Master IDE Active bit or the Interrupt bit of the Bus
Master IDE Status register for that IDE channel being set, or both."

bdrv_aio_cancel() can be used to nudge the request to cancel.  The
completion function is still called at some later point - and it could
take an arbitrary amount of time before the request finishes.

>From the IDE emulation perspective, there are two requirements:

1. After the Start bit has been cleared, no IDE state changes should
   occur due to the pending request.  No interrupts should be raised and
   no registers should change when the request completes
   (success/error/cancelled).  Also, the guest should be able to set the
   bit again and submit a new request.

2. No guest memory should be touched by a running request after the bit
   is cleared.  QEMU needs to go through bounce buffers in all cases
   instead of doing zero copy (mapping the PRDT).

   Using bounce buffers should be doable but you need to check the IDE
   code paths (PIO, DMA, and ATAPI) reachable from hw/ide/pci.c.
   There's also a denial-of-service scenario where the guest repeatedly
   submits an I/O requests and then clears the Start/Stop bit.  That
   would cause QEMU to build up many pending I/O requests and bounce
   buffers.  That needs to be handled, for example by punishing the
   guest by failing news I/O if there are more than 16 cancelled
   requests pending.

I'm interested in other ideas, but I think the solution space for
synchronous approaches that implement the semantics correctly is small.
I can think of a few other approaches that are easier to implement,
perform better, etc but they aren't correct.

Stefan



reply via email to

[Prev in Thread] Current Thread [Next in Thread]