public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: Ard Biesheuvel <ard.biesheuvel@linaro.org>
To: Laszlo Ersek <lersek@redhat.com>
Cc: Leif Lindholm <leif.lindholm@linaro.org>,
	"afish@apple.com" <afish@apple.com>,
	 "Kinney, Michael D" <michael.d.kinney@intel.com>,
	edk2-devel-01 <edk2-devel@lists.01.org>,
	 Brijesh Singh <brijesh.singh@amd.com>,
	Eric Dong <eric.dong@intel.com>,
	 Jiewen Yao <jiewen.yao@intel.com>,
	Jordan Justen <jordan.l.justen@intel.com>,
	 Star Zeng <star.zeng@intel.com>
Subject: Re: [PATCH 00/10] MdeModulePkg, OvmfPkg: unmap DMA buffers at ExitBootServices
Date: Fri, 8 Sep 2017 12:25:42 +0100	[thread overview]
Message-ID: <CAKv+Gu_opApO_NYrRS-J+V70EfMdbcreTaETFw7kdfscBKgerA@mail.gmail.com> (raw)
In-Reply-To: <49a0e877-0500-b1f5-e4ba-753df311f868@redhat.com>

On 8 September 2017 at 10:48, Laszlo Ersek <lersek@redhat.com> wrote:
> On 09/08/17 10:53, Ard Biesheuvel wrote:
>> (cc'ing the trinity)
>>
>> On 7 September 2017 at 23:41, Laszlo Ersek <lersek@redhat.com> wrote:
>>> Repo:   https://github.com/lersek/edk2.git
>>> Branch: iommu_exit_boot
>>>
>>> This series is the result of the discussion under
>>>
>>>   [edk2] [PATCH 0/4] MdeModulePkg: some PCI HC drivers: unmap common
>>>                      buffers at ExitBootServices()
>>>   https://lists.01.org/pipermail/edk2-devel/2017-September/014099.html
>>>
>>> At ExitBootServices(), PCI and VirtIo drivers should only care about
>>> aborting pending DMA on the devices. Cleaning up PciIo mappings (which
>>> ultimately boil down to IOMMU mappings) for those aborted DMA operations
>>> should be the job of the IOMMU driver.
>>>
>>> Patches 01 through 03 clean up the AtaAtapiPassThru driver in
>>> MdeModulePkg a little bit, because at present, (a) it unmaps the buffers
>>> and disables BMDMA in the wrong order in its DriverBindingStop()
>>> function, (b) it doesn't abort pending DMA at ExitBootServices().
>>>
>>> This subset can be treated separately from the rest of the series, but I
>>> thought they belonged loosely together (given that AtaAtapiPassThru is
>>> used on QEMU's Q35 machine type).
>>>
>>> Patches 04 through 07 remove VIRTIO_DEVICE_PROTOCOL.UnmapSharedBuffer()
>>> calls from the VirtIo drivers' ExitBootServices() handlers.
>>>
>>> (The conversion of VirtioNetDxe to device addresses is still in progress
>>> -- Brijesh, when you submit v2 of that, under this approach, there is no
>>> need to change VirtioNetExitBoot() relative to current upstream, and you
>>> can use VirtioOperationBusMasterRead to map outgoing packets.)
>>>
>>> Patches 08 through 10 make OvmfPkg/IoMmuDxe track all mappings, and
>>> unmap all mappings (Read, Write, CommonBuffer) that are in effect when
>>> ExitBootServices() is called. It is ensured that PCI and VirtIo drivers
>>> abort pending DMA first, and IoMmuDxe clean up the mappings last.
>>>
>>
>> The patches look fine to me
>>
>> Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
>
> Thank you!
>
>> Given that we are now depending on events signalled in an event
>> handler to be queued after all currently pending events,
>
> marking this (*)
>
>> I think we
>> need to explicitly agree that this behavior that needs to be
>> preserved, and documented somewhere, given that the UEFI spec does not
>> offer this guarantee.
>
> The condition that you describe under (*) *is* guaranteed in the UEFI spec.
>
> The *only* bit that is edk2 specific in the last patch is that we invoke
> gBS->SignalEvent() from the notification function of an event that
> *specifically* has type EVT_SIGNAL_EXIT_BOOT_SERVICES.
>
> If the event, whose notification function we were calling
> gBS->SignalEvent() from, was a plain EVT_NOTIFY_SIGNAL type event, then
> *nothing* in the last patch would be edk2-specific.
>
> * It is guaranteed by the UEFI spec that signaling an event group queues
> the notification functions for all not-yet-signaled events in that
> group, before the first notification function is invoked (regardless of
> the signaled events' TPLs). From "CreateEventEx()": "All events are
> guaranteed to be signaled before the first notification action is taken."
>
> * The UEFI spec guarantees that, within the same TPL, if an event is
> signaled that is not pending yet, the notify function will be queued
> after notify functions already queued on the same TPL. See "CreateEvent()":
>
>     Events exist in one of two states, “waiting” or “signaled.” When an
>     event is created, firmware puts it in the “waiting” state. When the
>     event is signaled, firmware changes its state to “signaled” and, if
>     EVT_NOTIFY_SIGNAL is specified, places a call to its notification
>     function in a FIFO queue. There is a queue for each of the “basic”
>     task priority levels defined in Section 7.1 (TPL_CALLBACK, and
>     TPL_NOTIFY). The functions in these queues are invoked in FIFO
>     order, starting with the highest priority level queue and proceeding
>     to the lowest priority queue that is unmasked by the current TPL. If
>     the current TPL is equal to or greater than the queued notification,
>     it will wait until the TPL is lowered via
>     EFI_BOOT_SERVICES.RestoreTPL().
>
> * gBS->SignalEvent() is valid to call at TPL_CALLBACK and TPL_NOTIFY
> levels (see "Table 23. TPL Restrictions"); in fact it is one of the few
> services that can even be called at TPL_HIGH_LEVEL (which is reserved
> for the platform firmware).
>
> The upshot is:
>
> (1) assume you have Event1, Event2, Event3, Event4 in event group
> EventGroupFoobarGuid
>
> (2) assume all events are EVT_NOTIFY_SIGNAL type
>
> (3) assume Event1 and Event2 have TPL_NOTIFY, Event3 and Event4 are
> TPL_CALLBACK
>
> (4) Assume Event5 is also of type EVT_NOTIFY_SIGNAL, not part of any
> event group, and has TPL_CALLBACK task prio level
>
> (5) Assume an agent running at TPL_APPLICATION creates an event
> temporarily, with type 0 (see the code example in CreateEventEx), and
> signals EventGroupFoobarGuid through it.
>
> (6) All of Event1, Event2, Event3 and Event4 move into the signaled
> state at once. NotifyFunction1 and NotifyFunction2 are queued in
> unspecified order in the TPL_NOTIFY queue, and Event3 and Event4 are
> queued in unspecified order in the TPL_CALLBACK queue.
>
> (7) Because our current TPL is TPL_APPLICATION, and signaled events of
> type EVT_NOTIFY_SIGNAL with higher TPLs exist, the SignalEvent() service
> will start dispatching them immediately.
>
> (8) Either NotifyFunction1 or NotifyFunction2 is called first, running
> at TPL_NOTIFY.
>
> (9) Assume that NotifyFunction2 signals Event5. (it doesn't matter if
> NotifyFunction2 is called before or after NotifyFunction1).
>
> NotifyFunction5 is not dispatched immediately (on the stack of
> SignalEvent()) because the current TPL, TPL_NOTIFY, is higher than or
> equal to, the TPL of Event5, which is TPL_CALLBACK. So NotifyFunction5
> is queued instead.
>
> Because NotifyFunction3 and NotifyFunction4 are already in the
> TPL_CALLBACK queue (in unspecified relative order), from step (6),
> NotifyFunction5 will be queued after both of them, in FIFO order.
>
> (10) If NotifyFunction1 has not been invoked yet, it is invoked now. It
> runs at TPL_NOTIFY. The TPL_NOTIFY queue becomes empty.
>
> (11) NotifyFunction3 and NotifyFunction4 are invoked in unspecified
> order. They both run at TPL_CALLBACK.
>
> (12) NotifyFunction5 is invoked. It runs at TPL_CALLBACK. The
> TPL_CALLBACK queue becomes empty.
>
> (13) SignalEvent() returns to the agent mentioned in (5).
>
>
> The one thing to remember, from the client programmer's POV, is that
> *any* event of type EVT_NOTIFY_SIGNAL can only be dispatched from within
> two service calls:
>
> - SignalEvent(), if the caller is running at a TPL strictly below the
> TPL of the event being signaled (directly or via event group GUID), and
>
> - RestoreTPL(), if the restored TPL falls strictly below the TPL of the
> event, and the event has already been signaled.
>
> IOW, SignalEvent() "calls or queues", and RestoreTPL "de-queues and
> calls, or does nothing".
>
>
> So, again, the only question that the UEFI spec does not clarify is
> whether we can call gBS->SignalEvent() specifically from an EBS
> notification function.
>
> The intent is likely just that, because:
>
>   EVT_SIGNAL_EXIT_BOOT_SERVICES
>     [...] This event is of type EVT_NOTIFY_SIGNAL [...]
>
> and, again, if we call SignalEvent from the NotifyFunction of a plain
> EVT_NOTIFY_SIGNAL event, then it's all covered by the spec already.
>
> My apologies about the wall of text. I probably over-explained it five-fold.
>

OK


  reply	other threads:[~2017-09-08 11:22 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-09-07 22:41 [PATCH 00/10] MdeModulePkg, OvmfPkg: unmap DMA buffers at ExitBootServices Laszlo Ersek
2017-09-07 22:41 ` [PATCH 01/10] MdeModulePkg/AtaAtapiPassThru: cache EnabledPciAttributes Laszlo Ersek
2017-09-07 22:41 ` [PATCH 02/10] MdeModulePkg/AtaAtapiPassThru: unmap DMA buffers after disabling BM DMA Laszlo Ersek
2017-09-07 22:41 ` [PATCH 03/10] MdeModulePkg/AtaAtapiPassThru: disable the device at ExitBootServices() Laszlo Ersek
2017-10-25 15:26   ` Laszlo Ersek
2017-10-25 20:11     ` Ard Biesheuvel
2017-10-26  5:08       ` Zeng, Star
2017-10-26 14:09         ` Laszlo Ersek
2017-10-26 14:12           ` Ard Biesheuvel
2017-09-07 22:41 ` [PATCH 04/10] OvmfPkg/VirtioBlkDxe: don't unmap VRING " Laszlo Ersek
2017-09-07 22:41 ` [PATCH 05/10] OvmfPkg/VirtioGpuDxe: don't unmap VRING & BackingStore at ExitBootServices Laszlo Ersek
2017-09-07 22:41 ` [PATCH 06/10] OvmfPkg/VirtioRngDxe: don't unmap VRING at ExitBootServices() Laszlo Ersek
2017-09-07 22:41 ` [PATCH 07/10] OvmfPkg/VirtioScsiDxe: " Laszlo Ersek
2017-09-07 22:41 ` [PATCH 08/10] OvmfPkg/IoMmuDxe: track all mappings Laszlo Ersek
2017-09-07 22:41 ` [PATCH 09/10] OvmfPkg/IoMmuDxe: generalize IoMmuUnmap() to IoMmuUnmapWorker() Laszlo Ersek
2017-09-07 22:41 ` [PATCH 10/10] OvmfPkg/IoMmuDxe: unmap all IOMMU mappings at ExitBootServices() Laszlo Ersek
2017-09-08  7:28 ` [PATCH 00/10] MdeModulePkg, OvmfPkg: unmap DMA buffers at ExitBootServices Yao, Jiewen
2017-09-08  8:28   ` Yao, Jiewen
2017-09-08  7:29 ` Zeng, Star
2017-09-08  8:53 ` Ard Biesheuvel
2017-09-08  9:48   ` Laszlo Ersek
2017-09-08 11:25     ` Ard Biesheuvel [this message]
2017-09-08 15:50 ` Brijesh Singh
2017-09-08 16:00   ` Laszlo Ersek
2017-09-08 18:28 ` Laszlo Ersek

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-list 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=CAKv+Gu_opApO_NYrRS-J+V70EfMdbcreTaETFw7kdfscBKgerA@mail.gmail.com \
    --to=devel@edk2.groups.io \
    /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