Commit Graph

1142 Commits

Author SHA1 Message Date
Laszlo Ersek d83defe0df OvmfPkg/VirtioNetDxe: log debug message in VirtioNetExitBoot()
The other four virtio device drivers (VirtioBlkDxe, VirtioGpuDxe,
VirtioRngDxe, VirtioScsiDxe) log such messages at this point; follow suit.

Cc: Brijesh Singh <brijesh.singh@amd.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Brijesh Singh <brijesh.singh@amd.com>
2017-09-22 15:01:51 +02:00
Laszlo Ersek 53b55831e0 OvmfPkg/VirtioNetDxe: document Rx/Tx allocs and mappings on Init/Shutdown
Document the following actions on the

  EfiSimpleNetworkStarted <-> EfiSimpleNetworkInitialized

state transitions:

* from commit 46b11f00ac ("OvmfPkg/VirtioNetDxe: alloc RxBuf using
  AllocateSharedPages()", 2017-09-14):

  VirtioNetInitRx ->
  { VirtIo->AllocateSharedPages, VirtioMapAllBytesInSharedBuffer }

  VirtioNetShutdownRx ->
  { VirtIo->UnmapSharedBuffer, VirtIo->FreeSharedPages }

* from commit 891f016c1b ("OvmfPkg/VirtioNetDxe: dynamically alloc
  transmit header", 2017-09-14):

  VirtioNetInitTx ->
  { VirtIo->AllocateSharedPages, VirtioMapAllBytesInSharedBuffer }

  VirtioNetShutdownTx ->
  { VirtIo->UnmapSharedBuffer, VirtIo->FreeSharedPages }

Cc: Brijesh Singh <brijesh.singh@amd.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Brijesh Singh <brijesh.singh@amd.com>
2017-09-22 15:01:29 +02:00
Laszlo Ersek f9c59fa44a OvmfPkg/QemuBootOrderLib: recognize "usb-storage" devices in XHCI ports
The feature is primarily useful for modern AARCH64 guests that have no
built-in virtio block / SCSI drivers; as on "qemu-system-aarch64 -M virt",
there are no IDE or AHCI controllers that could be used as fallback. XHCI
is available in "-M virt" however, and because XHCI predates AARCH64 by
several years, said guests are expected to have built-in drivers for it.

Other device models ("usb-uas", "usb-bot") are out of scope for now,
similarly to USB1.x (UHCI) and USB2 (EHCI) host controllers, and similarly
to USB hubs (which are USB1.1 only). In particular, port mapping between
EHCI and companion UHCI controllers is very complex; it even leads to PCI
slot/function differences between the OpenFirmware device paths exported
by QEMU and the the UEFI device paths generated by edk2.

The number of ports on the XHCI controller defaults to 4, but it can be
raised via the "p3" property to 15. In addition, several XHCI controllers
can be grouped into a single-slot, multi-function PCI device. These allow
for a good number of usb-storage devices, while their desired boot order
remains recognizable to this patch.

In the example below, we create two XHCI controllers, grouped into PCI
slot 00:02 as functions 0 and 1. Both controllers are given 15 ports. We
attach a "usb-storage" device to controller 1 at port 3 (ports are 1-based
in QEMU, 0-based in edk2), and attach another "usb-storage" device to
controller 2 at port 9.

QEMU command line options (NB. they apply equally to aarch64/virt and
x86_64/{i440fx,q35}):

  -device qemu-xhci,id=xhci1,p3=15,addr=02.0,multifunction=on \
  -device qemu-xhci,id=xhci2,p3=15,addr=02.1 \
  \
  -drive id=disk1,if=none,format=qcow2,$DISK1_OPTIONS \
  -drive id=disk2,if=none,format=qcow2,$DISK2_OPTIONS \
  \
  -device usb-storage,drive=disk1,bus=xhci1.0,port=3,bootindex=1 \
  -device usb-storage,drive=disk2,bus=xhci2.0,port=9,bootindex=2 \

Libvirt domain XML fragment:

  <controller type='usb' index='1' model='qemu-xhci' ports='15'>
    <address type='pci'
     domain='0x0000' bus='0x00' slot='0x02' function='0x0'
     multifunction='on'/>
  </controller>
  <controller type='usb' index='2' model='qemu-xhci' ports='15'>
    <address type='pci'
     domain='0x0000' bus='0x00' slot='0x02' function='0x1'/>
  </controller>

  <disk type='file' device='disk'>
    <driver name='qemu' type='qcow2'/>
    <source file='...'/>
    <target dev='sda' bus='usb'/>
    <boot order='1'/>
    <address type='usb' bus='1' port='3'/>
  </disk>
  <disk type='file' device='disk'>
    <driver name='qemu' type='qcow2'/>
    <source file='...'/>
    <target dev='sdb' bus='usb'/>
    <boot order='2'/>
    <address type='usb' bus='2' port='9'/>
  </disk>

Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Acked-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
2017-09-22 14:54:35 +02:00
Laszlo Ersek 947f3737ab OvmfPkg/QemuVideoDxe/VbeShim: handle PAM1 register on Q35 correctly
In commit db27e9f3d8 ("OvmfPkg/LegacyRegion: Support legacy region
manipulation of Q35", 2016-03-15), Ray extended the
OvmfPkg/Csm/CsmSupportLib PAM register manipulation to Q35. However, we
missed that the same should be done to the QemuVideoDxe VBE Shim as well.

The omission has caused no problems in practice on Q35, because QEMU has
let us write to the ROM area, regardless of the PAM1 setting, all this
time. This has now changed with recent QEMU commit 208fa0e43645 ("pc: make
'pc.rom' readonly when machine has PCI enabled", 2017-07-28). The QEMU
commit exposes the OVMF bug when Windows 7 is started on Q35, using QEMU
2.10 -- the VBE Shim is no longer put in place and Windows 7 cannot find
it.

To remedy this, assign the "Pam1Address" local variable a PciLib address
that matches the board type (i440fx vs. q35).

Regarding the PcdLib dependency: QemuVideoDxe already uses PcdLib, both
directly (see "PcdDriverSupportedEfiVersion") and indirectly (e.g. via the
DxePciLibI440FxQ35 PciLib instance). Add PcdLib to [LibraryClasses] for
completeness.

Cc: Aleksei Kovura <alex3kov@zoho.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Cc: Igor Mammedov <imammedo@redhat.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ruiyu Ni <ruiyu.ni@intel.com>
Ref: https://bugs.launchpad.net/qemu/+bug/1715700
Reported-by: Aleksei Kovura <alex3kov@zoho.com>
Special-thanks-to: Gerd Hoffmann <kraxel@redhat.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Tested-by: Aleksei Kovura <alex3kov@zoho.com>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
2017-09-20 20:25:19 +02:00
Laszlo Ersek ce461ae240 OvmfPkg/QemuVideoDxe/VbeShim: rename Status to Segment0AllocationStatus
This clarifies the purpose of the local variable in InstallVbeShim().

Cc: Aleksei Kovura <alex3kov@zoho.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Cc: Igor Mammedov <imammedo@redhat.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ruiyu Ni <ruiyu.ni@intel.com>
Ref: https://bugs.launchpad.net/qemu/+bug/1715700
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Tested-by: Aleksei Kovura <alex3kov@zoho.com>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
2017-09-20 20:25:15 +02:00
Laszlo Ersek ba1d245f1d OvmfPkg/CsmSupportLib: move PAM register addresses to IndustryStandard
* Introduce the PIIX4_PAM* and MCH_PAM* macros under
  "OvmfPkg/Include/IndustryStandard". These macros capture the PAM
  register offsets (in PCI config space) on the respective Memory
  Controller B/D/F, from the respective data sheets.

* Under IndustryStandard, introduce the PMC_REGISTER_PIIX4() macro for
  PIIX4. (For Q35, we already have DRAMC_REGISTER_Q35().) In both cases,
  the B/D/F is 0/0/0.

* Under CsmSupportLib, replace the "PAMRegOffset" field (UINT8) in the
  PAM_REGISTER_VALUE structure with "PAMRegPciLibAddress" (UINTN). The new
  field contains the return value of the PCI_LIB_ADDRESS() macro.

* Under CsmSupportLib, replace the "mRegisterValues440" elements as
  follows:

    REG_PAMx_OFFSET_440, ReadEnableData, WriteEnableData
    -->
    PMC_REGISTER_PIIX4 (PIIX4_PAMx), ReadEnableData, WriteEnableData

* Under CsmSupportLib, replace the "mRegisterValuesQ35" elements as
  follows:

    REG_PAMx_OFFSET_Q35, ReadEnableData, WriteEnableData
    -->
    DRAMC_REGISTER_Q35 (MCH_PAMx), ReadEnableData, WriteEnableData

* Under CsmSupportLib, update the register address calculations as follows
  (for all of PciOr8(), PciAnd8() and PciRead8()):

    PCI_LIB_ADDRESS (
      PAM_PCI_BUS,
      PAM_PCI_DEV,
      PAM_PCI_FUNC,
      mRegisterValues[Index].PAMRegOffset
      )
    -->
    mRegisterValues[Index].PAMRegPciLibAddress

* Under CsmSupportLib, remove the PAM_PCI_* and REG_PAM*_OFFSET_* macros.

Technically speaking, these changes could be split into three patches
(IndustryStandard macro additions, CsmSupportLib code updates,
CsmSupportLib macro removals). However, the patch is not big, and in this
case it is actually helpful to present the code movement / refactoring in
one step, for easier verification.

Cc: Aleksei Kovura <alex3kov@zoho.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Cc: Igor Mammedov <imammedo@redhat.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ruiyu Ni <ruiyu.ni@intel.com>
Ref: https://bugs.launchpad.net/qemu/+bug/1715700
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Tested-by: Aleksei Kovura <alex3kov@zoho.com>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
2017-09-20 20:24:26 +02:00
Brijesh Singh f60ed5ab7f OvmfPkg/VirtioNetDxe: negotiate VIRTIO_F_IOMMU_PLATFORM
VirtioNetDxe driver has been updated to use IOMMU-like member functions
from VIRTIO_DEVICE_PROTOCOL to translate the system physical address to
device address. We do not need to do anything special when
VIRTIO_F_IOMMU_PLATFORM bit is present hence treat it in parallel with
VIRTIO_F_VERSION_1.

Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Regression-tested-by: Laszlo Ersek <lersek@redhat.com>
Tested-by: Laszlo Ersek <lersek@redhat.com>
2017-09-14 23:54:20 +02:00
Brijesh Singh 8fa54a8a94 OvmfPkg/VirtioNetDxe: map caller-supplied Tx packet to device-address
When device is behind the IOMMU, driver is require to pass the device
address of caller-supplied transmit buffer for the bus master operations.

The patch uses VirtioNetMapTxBuf() to map caller-supplied Tx packet to a
device-address and enqueue the device address in VRING for transfer and
perform the reverse mapping when transfer is completed so that we can
return the caller-supplied buffer.

Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Regression-tested-by: Laszlo Ersek <lersek@redhat.com>
Tested-by: Laszlo Ersek <lersek@redhat.com>
2017-09-14 23:54:18 +02:00
Brijesh Singh bd114d9f77 OvmfPkg/VirtioNetDxe: add Tx packet map/unmap helper functions
When device is behind IOMMU, driver is require to pass the device address
of TxBuf in the Tx VRING. The patch adds helper functions and data
structure to map and unmap the TxBuf system physical address to a device
address.

Since the TxBuf is returned back to caller from VirtioNetGetStatus() hence
we use OrderedCollection interface to save the TxBuf system physical to
device address mapping. After the TxBuf is succesfully transmitted
VirtioNetUnmapTxBuf() does the reverse lookup in OrderedCollection data
structure to get the system physical address of TxBuf for a given device
address.

Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Regression-tested-by: Laszlo Ersek <lersek@redhat.com>
Tested-by: Laszlo Ersek <lersek@redhat.com>
2017-09-14 23:54:15 +02:00
Brijesh Singh 76ad23ca82 OvmfPkg/VirtioNetDxe: update TechNotes
In next patches we will update Virtio transmit to use the device-mapped
address of the caller-supplied packet. The patch documents the new model.

Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Regression-tested-by: Laszlo Ersek <lersek@redhat.com>
Tested-by: Laszlo Ersek <lersek@redhat.com>
2017-09-14 23:54:12 +02:00
Brijesh Singh 891f016c1b OvmfPkg/VirtioNetDxe: dynamically alloc transmit header
Each network packet is submitted for transmission by pushing the head
descriptor of a two-part descriptor chain to the Available Ring of the
TX queue. VirtioNetInitTx() sets up the the descriptor chains for all
queueable packets in advance, and points all the head descriptors to the
same shared, never modified, VIRTIO_1_0_NET_REQ header object (or its
initial VIRTIO_NET_REQ sub-object, dependent on virtio version).
VirtioNetInitTx() currently uses the header object's system physical
address for populating the head descriptors.

When device is behind the IOMMU, VirtioNet driver is required to provide
the device address of VIRTIO_1_0_NET_REQ header. In this patch we
dynamically allocate the header using AllocateSharedPages() and map with
BusMasterCommonBuffer so that header can be accessed by both processor
and the device.

We map the header object for CommonBuffer operation because, in order to
stick with the current code order, we populate the head descriptors with
the header's device address first, and fill in the header itself second.

Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Regression-tested-by: Laszlo Ersek <lersek@redhat.com>
Tested-by: Laszlo Ersek <lersek@redhat.com>
2017-09-14 23:54:10 +02:00
Brijesh Singh 46b11f00ac OvmfPkg/VirtioNetDxe: alloc RxBuf using AllocateSharedPages()
When device is behind the IOMMU, VirtioNetDxe is required to use the
device address in bus master operations. RxBuf is allocated using
AllocatePool() which returns the system physical address.

The patch uses VIRTIO_DEVICE_PROTOCOL.AllocateSharedPages() to allocate
the RxBuf and map with VirtioMapAllBytesInSharedBuffer() so that we can
obtain the device address for RxBuf.

Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Regression-tested-by: Laszlo Ersek <lersek@redhat.com>
Tested-by: Laszlo Ersek <lersek@redhat.com>
2017-09-14 23:54:07 +02:00
Brijesh Singh 940baec09c OvmfPkg/VirtioNetDxe: map VRINGs using VirtioRingMap()
When device is behind the IOMMU then driver need to pass the device
address when programing the bus master. The patch uses VirtioRingMap() to
map the VRING system physical address[es] to device address[es].

Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Regression-tested-by: Laszlo Ersek <lersek@redhat.com>
Tested-by: Laszlo Ersek <lersek@redhat.com>
2017-09-14 23:54:05 +02:00
Brijesh Singh 55dd5a673b OvmfPkg/VirtioNetDxe: add helper VirtioNetUninitRing()
Consolidate the virtio VRING resource cleanup into VirtioNetUninitRing().

Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Regression-tested-by: Laszlo Ersek <lersek@redhat.com>
Tested-by: Laszlo Ersek <lersek@redhat.com>
2017-09-14 23:53:46 +02:00
Laszlo Ersek 5dfba97c4d OvmfPkg/SataControllerDxe: log informative message at DEBUG_INFO level
When a UEFI_DRIVER attempts to open a protocol interface with BY_DRIVER
attribute that it already has open with BY_DRIVER attribute,
OpenProtocol() returns EFI_ALREADY_STARTED. This is not an error. The
UEFI-2.7 spec currently says,

> EFI_ALREADY_STARTED -- Attributes is BY_DRIVER and there is an item on
>                        the open list with an attribute of BY_DRIVER
>                        whose agent handle is the same as AgentHandle.

(In fact it is so much an expected condition that recent USWG Mantis
ticket <https://mantis.uefi.org/mantis/view.php?id=1815> will codify its
additional edk2-specific behavior, namely to output the protocol interface
at once.)

Downgrade the log mask for this one condition to DEBUG_INFO, in
SataControllerStart(). This will match the log mask of the other two
informative messages in this function, "SataControllerStart START", and
"SataControllerStart END status = %r" (at which point Status can only be
EFI_SUCCESS).

Cc: Jordan Justen <jordan.l.justen@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
2017-09-11 22:39:32 +02:00
Laszlo Ersek 837d9eea7d OvmfPkg/PlatformBootManagerLib: log informative message at DEBUG_INFO lvl
"Boot Mode:%x" is an informative message, not an error report. Set its
debug mask to DEBUG_INFO.

Cc: Jordan Justen <jordan.l.justen@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
2017-09-11 22:39:32 +02:00
Laszlo Ersek 7707c9fd69 OvmfPkg/PlatformPei: log informative message at DEBUG_INFO level
"Platform PEIM Loaded" is an informative message, not an error report. Set
its debug mask to DEBUG_INFO.

Cc: Jordan Justen <jordan.l.justen@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
2017-09-11 22:39:31 +02:00
Laszlo Ersek 80886a6953 OvmfPkg/PlatformDebugLibIoPort: write messages with IoWriteFifo8()
Since commit 19c6d9feaa ("MdePkg: Expand BaseIoLibIntrinsic (IoLib
class) library", 2017-01-14), IoWriteFifo8() has been widely available to
modules. Use it to print debug messages and assertion failures to the QEMU
debug port, rather than open-coded loops.

In the general case this speeds up logging, because debug messages will
now trap to QEMU once per message (as opposed to once per character), due
to "REP OUTSB" in "MdePkg/Library/BaseIoLibIntrinsic/*/IoFifoSev.nasm".

In SEV guests, there is no speedup (SEV doesn't support the REP prefix).
SEV is detected internally to BaseIoLibIntrinsic.

Cc: Brijesh Singh <brijesh.singh@amd.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Acked-by: Brijesh Singh <brijesh.singh@amd.com>
2017-09-11 22:28:25 +02:00
Paulo Alcantara f5566d1530 OvmfPkg: Enable UDF file system support
This patch enables UDF file system support by default.

Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Paulo Alcantara <pcacjr@zytor.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Ruiyu Ni <ruiyu.ni@intel.com>
2017-09-08 20:42:51 +02:00
Laszlo Ersek 7aee391fa3 OvmfPkg/IoMmuDxe: unmap all IOMMU mappings at ExitBootServices()
Register an ExitBootServices() callback that tears down all IOMMU
mappings, without modifying the UEFI memory map.

The trick is that in the ExitBootServices() callback, we don't immediately
do the work; instead we signal another (private) event.

Normally the dispatch order of ExitBootServices() callbacks is unspecified
(within the same task priority level anyway). By queueing another
function, we delay the unmapping until after all PciIo and Virtio drivers
abort -- in their own ExitBootServices() callbacks -- the pending DMA
operations of their respective controllers.

Furthermore, the fact that IoMmuUnmapWorker() rewrites client-owned memory
when it unmaps a Write or CommonBuffer bus master operation, is safe even
in this context. The existence of any given "MapInfo" in "mMapInfos"
implies that the client buffer pointed-to by "MapInfo->CryptedAddress" was
live when ExitBootServices() was entered. And, after entering
ExitBootServices(), nothing must have changed the UEFI memory map, hence
the client buffer at "MapInfo->CryptedAddress" still exists.

Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Brijesh Singh <brijesh.singh@amd.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Reviewed-by: Brijesh Singh <brijesh.singh@amd.com>
Tested-by: Brijesh Singh <brijesh.singh@amd.com>
2017-09-08 20:24:06 +02:00
Laszlo Ersek 550acd08e5 OvmfPkg/IoMmuDxe: generalize IoMmuUnmap() to IoMmuUnmapWorker()
IoMmuUnmapWorker() is identical to IoMmuUnmap(), it just takes an
additional BOOLEAN parameter called "MemoryMapLocked".  If the memory map
is locked, IoMmuUnmapWorker() does its usual job, but it purposely leaks
memory rather than freeing it. This makes it callable from
ExitBootServices() context.

Turn IoMmuUnmap() into a thin wrapper around IoMmuUnmapWorker() that
passes constant FALSE for "MemoryMapLocked".

Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Brijesh Singh <brijesh.singh@amd.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Reviewed-by: Brijesh Singh <brijesh.singh@amd.com>
Tested-by: Brijesh Singh <brijesh.singh@amd.com>
2017-09-08 20:24:04 +02:00
Laszlo Ersek 9ed745b967 OvmfPkg/IoMmuDxe: track all mappings
The "mRecycledMapInfos" list implements an internal pool of unused
MAP_INFO structures between the IoMmuUnmap() and IoMmuMap() functions. The
original goal was to allow IoMmuUnmap() to tear down CommonBuffer mappings
without releasing any memory: IoMmuUnmap() would recycle the MAP_INFO
structure to the list, and IoMmuMap() would always check the list first,
before allocating a brand new MAP_INFO structure.

In one of the following patches, we'll change OvmfPkg/IoMmuDxe so that it
unmaps all existent bus master operations (CommonBuffer, Read, Write) at
ExitBootServices(), strictly after the individual device drivers abort
pending DMA on the devices they manage, in their own ExitBootServices()
notification functions.

For this, rename and repurpose the list to track all live mappings.

This means that IoMmuUnmap() will always release a MAP_INFO structure
(even when cleaning up a CommonBuffer operation). That's fine (for now),
because device drivers are no longer expected to call Unmap() in their
ExitBootServices() notification functions.

In theory, we could also move the allocation and freeing of the stash
buffer from IoMmuAllocateBuffer() and IoMmuFreeBuffer(), respectively, to
IoMmuMap() and IoMmuUnmap(). However, this would require allocating and
freeing a stash buffer in *both* IoMmuMap() and IoMmuUnmap(), as
IoMmuMap() performs in-place decryption for CommonBuffer operations, and
IoMmuUnmap() performs in-place encryption for the same.

By keeping the stash buffer allocation as-is, not only do we keep the code
almost fully undisturbed, but

- we also continue to guarantee that IoMmuUnmap() succeeds: allocating a
  stash buffer in IoMmuUnmap(), for in-place encryption after a
  CommonBuffer operation, could fail;

- we also keep IoMmuUnmap() largely reusable for ExitBootServices()
  callback context: allocating a stash buffer in IoMmuUnmap() would simply
  be forbidden in that context.

Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Brijesh Singh <brijesh.singh@amd.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Reviewed-by: Brijesh Singh <brijesh.singh@amd.com>
Tested-by: Brijesh Singh <brijesh.singh@amd.com>
2017-09-08 20:24:01 +02:00
Laszlo Ersek bf99bdd1f7 OvmfPkg/VirtioScsiDxe: don't unmap VRING at ExitBootServices()
In one of the following patches, we'll change OvmfPkg/IoMmuDxe so that it
unmaps all existent bus master operations (CommonBuffer, Read, Write) at
ExitBootServices(), strictly after the individual device drivers abort
pending DMA on the devices they manage, in their own ExitBootServices()
notification functions.

In preparation, remove the explicit
VIRTIO_DEVICE_PROTOCOL.UnmapSharedBuffer() call from VirtioScsiExitBoot(),
originally added in commit fc2168feb2 ("OvmfPkg/VirtioScsiDxe: map VRING
using VirtioRingMap()", 2017-08-31).

Add a DEBUG message so we can observe the ordering between
VirtioScsiExitBoot() and the upcoming cleanup of mappings in
OvmfPkg/IoMmuDxe.

Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Brijesh Singh <brijesh.singh@amd.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Reviewed-by: Brijesh Singh <brijesh.singh@amd.com>
Tested-by: Brijesh Singh <brijesh.singh@amd.com>
2017-09-08 20:23:58 +02:00
Laszlo Ersek 21e57370fc OvmfPkg/VirtioRngDxe: don't unmap VRING at ExitBootServices()
In one of the following patches, we'll change OvmfPkg/IoMmuDxe so that it
unmaps all existent bus master operations (CommonBuffer, Read, Write) at
ExitBootServices(), strictly after the individual device drivers abort
pending DMA on the devices they manage, in their own ExitBootServices()
notification functions.

In preparation, remove the explicit
VIRTIO_DEVICE_PROTOCOL.UnmapSharedBuffer() call from VirtioRngExitBoot(),
originally added in commit 0a568ccbcb ("OvmfPkg/VirtioRngDxe: map host
address to device address", 2017-08-23).

Add a DEBUG message so we can observe the ordering between
VirtioRngExitBoot() and the upcoming cleanup of mappings in
OvmfPkg/IoMmuDxe.

Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Brijesh Singh <brijesh.singh@amd.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Reviewed-by: Brijesh Singh <brijesh.singh@amd.com>
Tested-by: Brijesh Singh <brijesh.singh@amd.com>
2017-09-08 20:23:56 +02:00
Laszlo Ersek 8ddd12e53f OvmfPkg/VirtioGpuDxe: don't unmap VRING & BackingStore at ExitBootServices
In one of the following patches, we'll change OvmfPkg/IoMmuDxe so that it
unmaps all existent bus master operations (CommonBuffer, Read, Write) at
ExitBootServices(), strictly after the individual device drivers abort
pending DMA on the devices they manage, in their own ExitBootServices()
notification functions.

In preparation, remove the explicit
VIRTIO_DEVICE_PROTOCOL.UnmapSharedBuffer() calls from VirtioGpuExitBoot(),
originally added in commit 9bc5026c19 ("OvmfPkg/VirtioGpuDxe: map VRING
for bus master common buffer operation", 2017-08-26) and commit
f10ae92366 ("OvmfPkg/VirtioGpuDxe: map backing store to bus master
device address", 2017-08-26).

Add a DEBUG message so we can observe the ordering between
VirtioGpuExitBoot() and the upcoming cleanup of mappings in
OvmfPkg/IoMmuDxe.

Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Brijesh Singh <brijesh.singh@amd.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Reviewed-by: Brijesh Singh <brijesh.singh@amd.com>
Tested-by: Brijesh Singh <brijesh.singh@amd.com>
2017-09-08 20:23:53 +02:00
Laszlo Ersek 5659ec3fa9 OvmfPkg/VirtioBlkDxe: don't unmap VRING at ExitBootServices()
In one of the following patches, we'll change OvmfPkg/IoMmuDxe so that it
unmaps all existent bus master operations (CommonBuffer, Read, Write) at
ExitBootServices(), strictly after the individual device drivers abort
pending DMA on the devices they manage, in their own ExitBootServices()
notification functions.

In preparation, remove the explicit
VIRTIO_DEVICE_PROTOCOL.UnmapSharedBuffer() call from VirtioBlkExitBoot(),
originally added in commit 1916513047 ("OvmfPkg/VirtioBlkDxe: map VRING
using VirtioRingMap()", 2017-08-27).

Add a DEBUG message so we can observe the ordering between
VirtioBlkExitBoot() and the upcoming cleanup of mappings in
OvmfPkg/IoMmuDxe.

Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Brijesh Singh <brijesh.singh@amd.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Reviewed-by: Brijesh Singh <brijesh.singh@amd.com>
Tested-by: Brijesh Singh <brijesh.singh@amd.com>
2017-09-08 20:23:47 +02:00
Ge Song 89796c69d9 OvmfPkg/SecMain: Fix stack switching to permanent memory
In earlier PEI stage, temporary memory at PcdOvmfSecPeiTempRamBase is
employed as stack and heap. We move them to the new room and do some
relocation fixup when permanent memory becomes available.
TemporaryRamMigration() is responsible for switching the stack.

Before entering TemporaryRamMigration(), Ebp/Rbp is populated with the
content of Esp/Rsp and used as frame pointer.

After the execution of SetJump/LongJump, stack migrates to new position
while the context keeps unchanged.

But when TemporaryRamMigration() exits, Esp/Rsp is filled with
the content of Ebp/Rbp to destroy this stack frame.

The result is, stack switches back to previous temporary memory.

When permanent memory becomes available, modules that have registered
themselves for shadowing will be scheduled to execute. Some of them
need to consume more memory(heap/stack). Contrast to temporary stack,
permanent stack possesses larger space.

The potential risk is overflowing the stack if stack staying in
temporary memory. When it happens, system may crash during S3 resume.

More detailed information:
> (gdb) disassemble /r
> Dump of assembler code for function TemporaryRamMigration:
>   0x00000000fffcd29c <+0>:	55	push   %rbp
>   0x00000000fffcd29d <+1>:	48 89 e5	mov    %rsp,%rbp
>   0x00000000fffcd2a0 <+4>:	48 81 ec 70 01 00 00	sub
> $0x170,%rsp
>    ...
>    ...
>    0x00000000fffcd425 <+393>:	e8 80 10 00 00	callq  0xfffce4aa
> <SaveAndSetDebugTimerInterrupt>
> => 0x00000000fffcd42a <+398>:	b8 00 00 00 00	mov    $0x0,%eax
>    0x00000000fffcd42f <+403>:	c9	leaveq
>    0x00000000fffcd430 <+404>:	c3	retq
> End of assembler dump.

See the description of leave(opcode: c9), from
Intel 64 and IA-32 Architectures Software Developer's Manual, Volume 2A

"Releases the stack frame set up by an earlier ENTER instruction. The
LEAVE instruction copies the frame pointer (in the EBP register) into
the stack pointer register (ESP), which releases the stack space
allocated to the stack frame. The old frame pointer (the frame pointer
for the calling procedure that was saved by the ENTER instruction) is
then popped from the stack into the EBP register, restoring the calling
procedure’s stack frame."

To solve this, update Ebp/Rbp too when Esp/Rsp is updated

Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Ge Song <ge.song@hxt-semitech.com>
Tested-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
2017-09-06 10:07:16 -07:00
Laszlo Ersek db52890926 OvmfPkg/VirtioGpuDxe: negotiate VIRTIO_F_IOMMU_PLATFORM
VirtioGpuDxe is now IOMMU-clean; it translates system memory addresses to
bus master device addresses. Negotiate VIRTIO_F_IOMMU_PLATFORM in parallel
with VIRTIO_F_VERSION_1. (Note: the VirtIo GPU device, and this driver,
are virtio-1.0 only (a.k.a. "modern-only").)

Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Brijesh Singh <brijesh.singh@amd.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Tested-by: Brijesh Singh <brijesh.singh@amd.com>
2017-09-01 14:28:28 +02:00
Laszlo Ersek f10ae92366 OvmfPkg/VirtioGpuDxe: map backing store to bus master device address
VirtioGpuDxe is a UEFI Bus driver (not a Device driver). This is because a
UEFI graphics driver is expected to produce its GraphicsOutput protocol
instance(s) on new child handle(s) of the video controller handle, one
child handle (plus GOP) per video output (or, one child handle plus GOP
per combination of multiple video outputs).

In VirtioGpuDxe, we support a single VirtIo GPU head (scanout), namely
head#0. This means that, with regard to a specific VirtIo GPU device, the
driver may be in one of three states, at any time:

[1] VirtioGpuDxe has not bound the device at all,

[2] VirtioGpuDxe has bound the device, but not produced the sole child
    handle for head#0,

[3] VirtioGpuDxe has bound the device, and produced the sole child handle
    for head#0, with a GOP instance on the child handle.

(Which state the driver is in wrt. a given VirtIo GPU device depends on
the VirtioGpuDriverBindingStart() / VirtioGpuDriverBindingStop()
invocations issued by the ConnectController() / DisconnectController()
boot services. In turn those come from BDS or e.g. the UEFI shell.)

The concept of "current video mode" is technically tied to the GOP (i.e.,
the child handle, state [3] only), not the VirtIo GPU controller handle.
This is why we manage the storage that backs the current video mode in our
EFI_GRAPHICS_OUTPUT_PROTOCOL.SetMode() member implementation.

GopSetMode() is first called *internally*, when we enter state [3] (that
is, when we produce the child handle + GOP on it):

  VirtioGpuDriverBindingStart() [DriverBinding.c]
    InitVgpuGop()               [DriverBinding.c]
      VgpuGop->Gop.SetMode()    [Gop.c]

When this happens, we allocate the backing store *without* having a
preexistent backing store (due to no preexistent video mode and GOP).
Skipping VirtIo GPU details not relevant for this patch, we just note that
the backing store is exposed *permanently* to the VirtIo GPU device, with
the RESOURCE_ATTACH_BACKING command.

When external clients call the EFI_GRAPHICS_OUTPUT_PROTOCOL.Blt() member
function -- called GopBlt() in this driver --, in state [3], the function
operates on the backing store, and sends only small messages to the VirtIo
GPU device.

When external clients call GopSetMode() for switching between video modes
-- in state [3] --, then

- a new backing store is allocated and exposed to the device (attached to
  a new host-side VirtIo GPU resource),

- head#0 is flipped to the new backing store,

- on success, the ReleaseGopResources() function both detaches the
  previous backing store from the VirtIo GPU device, an releases it. The
  new backing store address and size are saved in our GOP object. (In
  other words, we "commit" to the new video mode.)

When the DisconnectController() boot service asks us to leave state [3] --
we can leave it directly only for state [2] --, then the
ReleaseGopResources() function is called on a different path:

  VirtioGpuDriverBindingStop() [DriverBinding.c]
    UninitVgpuGop()            [DriverBinding.c]
      ReleaseGopResources()    [Gop.c]

In this case, the backing store being released is still in use (we're not
leaving it for a new mode -- head#0 has not been flipped "away" from it),
so in ReleaseGopResources() we disable head#0 first.

(The ReleaseGopResources() function is called the same way on the error
path in InitVgpuGop(), if the first -- internal -- VgpuGop->Gop.SetMode()
call succeeds, but the rest of InitVgpuGop() fails.)

Based on the above, for IOMMU-compatibility,

- in GopSetMode(), don't just allocate, but also map the backing store of
  the nascent video mode to a device address, for bus master common buffer
  operation,

- (the VirtioGpuAllocateZeroAndMapBackingStore() helper function
  introduced in the last patch takes care of zeroing internally,)

- pass the device address to the VirtIo GPU device in the
  RESOURCE_ATTACH_BACKING command,

- if GopSetMode() succeeds, save the mapping token,

- if GopSetMode() fails, don't just free but also unmap the still-born
  backing store,

- in ReleaseGopResources(), don't just free but also unmap the backing
  store -- which is the previous backing store if we're mode-switching,
  and the current backing store if we're leaving state [3].

Finally, ExitBootServices() may be called when the driver is in either
state [1], [2] or [3], wrt. a given VirtIo GPU device. (Of course we are
only notified in states [2] and [3].) If we get the notification in state
[3], then the current video mode's backing store has to be unmapped, but
not released. (We must not change the UEFI memory map.)

Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Brijesh Singh <brijesh.singh@amd.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Tested-by: Brijesh Singh <brijesh.singh@amd.com>
2017-09-01 14:28:22 +02:00
Laszlo Ersek 5c8f091bd8 OvmfPkg/VirtioGpuDxe: helpers for backing store (de)allocation+(un)mapping
Introduce the VirtioGpuAllocateZeroAndMapBackingStore() and
VirtioGpuUnmapAndFreeBackingStore() helper functions. These functions tie
together the allocation, zeroing and mapping, and unmapping and
deallocation, respectively, of memory that the virtio GPU will permanently
reference after receiving the RESOURCE_ATTACH_BACKING command.

With these functions we can keep the next patch simpler -- the GOP
implementation in "Gop.c" retains its error handling structure, and
remains oblivious to VIRTIO_DEVICE_PROTOCOL and VirtioLib.

Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Brijesh Singh <brijesh.singh@amd.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Tested-by: Brijesh Singh <brijesh.singh@amd.com>
2017-09-01 14:28:20 +02:00
Laszlo Ersek 5409c6abc8 OvmfPkg/VirtioGpuDxe: take EFI_PHYSICAL_ADDRESS in ResourceAttachBacking()
The RESOURCE_ATTACH_BACKING virtio GPU command assigns guest-side backing
pages to a host-side resource that was created earlier with the
RESOURCE_CREATE_2D command.

We compose the RESOURCE_ATTACH_BACKING command in the
VirtioGpuResourceAttachBacking() function. Currently this function takes
the parameter

  IN VOID *FirstBackingPage

This is only appropriate as long as we pass a (guest-phys) system memory
address to the device. In preparation for a mapped bus master device
address, change the above parameter to

  IN EFI_PHYSICAL_ADDRESS BackingStoreDeviceAddress

In order to keep the current call site functional, move the (VOID*) to
(UINTN) conversion out of the function, to the call site.

The "Request.Entry.Addr" field already has type UINT64.

This patch is similar to commit 4b725858de ("OvmfPkg/VirtioLib: change
the parameter of VirtioAppendDesc() to UINT64", 2017-08-23).

Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Brijesh Singh <brijesh.singh@amd.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Tested-by: Brijesh Singh <brijesh.singh@amd.com>
2017-09-01 14:28:17 +02:00
Laszlo Ersek 067b648332 OvmfPkg/VirtioGpuDxe: map virtio GPU command objects to device addresses
Every virtio GPU command used by VirtioGpuDxe is synchronous and formatted
as a two-descriptor chain: request, response. The internal workhorse
function that all the command-specific functions call for such messaging
is VirtioGpuSendCommand().

In VirtioGpuSendCommand(), map the request from system memory to bus
master device address for BusMasterRead operation, and map the response
from system memory to bus master device address for BusMasterWrite
operation.

Pass the bus master device addresses to VirtioAppendDesc(). (See also
commit 4b725858de, "OvmfPkg/VirtioLib: change the parameter of
VirtioAppendDesc() to UINT64", 2017-08-23.)

Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Brijesh Singh <brijesh.singh@amd.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Tested-by: Brijesh Singh <brijesh.singh@amd.com>
2017-09-01 14:28:15 +02:00
Laszlo Ersek 9bc5026c19 OvmfPkg/VirtioGpuDxe: map VRING for bus master common buffer operation
VirtioGpuDxe uses one virtio ring, for VIRTIO_GPU_CONTROL_QUEUE.

Map it for bus master common buffer operation with VirtioRingMap(), so
that it can be accessed equally by both guest and hypervisor even if an
IOMMU is used. (VirtioRingInit() already allocates the ring suitably for
this, see commit b0338c5329, "OvmfPkg/VirtioLib: alloc VRING buffer with
AllocateSharedPages()", 2017-08-23).

Pass the resultant translation offset ("RingBaseShift"), from system
memory address to bus master device address, to VIRTIO_SET_QUEUE_ADDRESS.

Unmap the ring in all contexts where the ring becomes unused (these
contexts are mutually exclusive):

- in VirtioGpuInit(): the ring has been mapped, but we cannot complete the
  virtio initialization for another reason,

- in VirtioGpuUninit(): the virtio initialization has succeeded, but
  VirtioGpuDriverBindingStart() fails for another reason, or
  VirtioGpuDriverBindingStop() unbinds the device after use,

- in VirtioGpuExitBoot(): ExitBootServices() is called after
  VirtioGpuDriverBindingStart() has successfully bound the device.
  (Unmapping the ring does not change the UEFI memory map.)

Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Brijesh Singh <brijesh.singh@amd.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Tested-by: Brijesh Singh <brijesh.singh@amd.com>
2017-09-01 14:27:28 +02:00
Laszlo Ersek 1afbb85f87 OvmfPkg/IoMmuDxe: IoMmuFreeBuffer(): clean up DEBUG message
Log all relevant IN parameters on entry. (There are only IN parameters.)
Beautify the format string.

Cc: Brijesh Singh <brijesh.singh@amd.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Brijesh Singh <brijesh.singh@amd.com>
Tested-by: Brijesh Singh <brijesh.singh@amd.com>
2017-09-01 14:20:47 +02:00
Laszlo Ersek 80ddd336da OvmfPkg/IoMmuDxe: IoMmuAllocateBuffer(): nicer and more informative DEBUGs
Log all relevant IN and IN OUT parameters on entry.

(Note that the HostAddress parameter is IN OUT rather than OUT due to
historical reasons. The "IN EFI_ALLOCATE_TYPE Type" parameter is now to be
ignored, but historically it could be set to AllocateMaxAddress for
example, and for that HostAddress had to be IN OUT.)

When exiting with success, log all relevant OUT parameters (i.e.,
HostAddress). Also log the new (internal) StashBuffer address, on which
IoMmuMap() and IoMmuUnmap() rely on, for BusMasterCommonBuffer operations
(in-place decryption and encryption, respectively).

Cc: Brijesh Singh <brijesh.singh@amd.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Brijesh Singh <brijesh.singh@amd.com>
Tested-by: Brijesh Singh <brijesh.singh@amd.com>
2017-09-01 14:20:45 +02:00
Laszlo Ersek a1d6a9dcda OvmfPkg/IoMmuDxe: IoMmuUnmap(): clean up DEBUG message
The only important external information for this function, and for the
human looking at the log, is the Mapping input parameter. Log it on entry.

Stop logging the contents of the MAP_INFO structure pointed-to by Mapping.
Thanks to the previous patch, we can now associate IoMmuUnmap() messages
with IoMmuMap() messages -- and thereby with MAP_INFO contents -- purely
via Mapping.

Cc: Brijesh Singh <brijesh.singh@amd.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Brijesh Singh <brijesh.singh@amd.com>
Tested-by: Brijesh Singh <brijesh.singh@amd.com>
2017-09-01 14:20:42 +02:00
Laszlo Ersek 2ad6ba80a1 OvmfPkg/IoMmuDxe: IoMmuMap(): log nicer and more informative DEBUG msgs
Log all relevant IN and IN OUT parameters on entry.

When exiting with success, log all relevant OUT and IN OUT parameters.
Don't log OUT and IN OUT parameters that are never set or changed after
entering the function (i.e., *NumberOfBytes).

Cc: Brijesh Singh <brijesh.singh@amd.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Brijesh Singh <brijesh.singh@amd.com>
Tested-by: Brijesh Singh <brijesh.singh@amd.com>
2017-09-01 14:20:40 +02:00
Laszlo Ersek d8d33741e8 OvmfPkg/BaseMemEncryptSevLib: fix typos in DEBUG messages
Replace "spliting" with "splitting".

Cc: Brijesh Singh <brijesh.singh@amd.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Brijesh Singh <brijesh.singh@amd.com>
Tested-by: Brijesh Singh <brijesh.singh@amd.com>
2017-09-01 14:20:37 +02:00
Laszlo Ersek 5597edfa8b OvmfPkg/BaseMemEncryptSevLib: clean up upper-case / lower-case in DEBUGs
Debug messages that start as natural (English) language phrases (after the
debug prefix) should uniformly begin with lower-case or upper-case. In
SetMemoryEncDec() we have a mixture now. Stick with lower-case.
(Upper-case is better for full sentences that also end with punctuation.)

Cc: Brijesh Singh <brijesh.singh@amd.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Brijesh Singh <brijesh.singh@amd.com>
Tested-by: Brijesh Singh <brijesh.singh@amd.com>
2017-09-01 14:20:35 +02:00
Laszlo Ersek 3728ea5a95 OvmfPkg/BaseMemEncryptSevLib: promote DEBUG_WARN levels to DEBUG_ERROR
In SetMemoryEncDec(), we have four locations where we (a) log a message on
the DEBUG_WARN level that says "ERROR", (b) return the status code
RETURN_NO_MAPPING right after.

These messages clearly describe actual errors (bad PML4, PDPE, PDE, PTE).
Promote their debug levels to DEBUG_ERROR, and remove the word "ERROR"
from the messages.

Cc: Brijesh Singh <brijesh.singh@amd.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Brijesh Singh <brijesh.singh@amd.com>
Tested-by: Brijesh Singh <brijesh.singh@amd.com>
2017-09-01 14:20:33 +02:00
Laszlo Ersek 631bd7e084 OvmfPkg/BaseMemEncryptSevLib: clean up debug logging of PhysicalAddress
In the SetMemoryEncDec() function, the way we currently report
PhysicalAddress is not uniform:

- mostly we say "for %lx",

- in one spot we say "at %lx" (even though the 2MB page being split does
  not live *at* PhysicalAddress, instead it maps PhysicalAddress),

- in another spot we don't log PhysicalAddress at all (when splitting a
  1GB page).

Unify this, using the format string "for Physical=0x%Lx".

Cc: Brijesh Singh <brijesh.singh@amd.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Brijesh Singh <brijesh.singh@amd.com>
Tested-by: Brijesh Singh <brijesh.singh@amd.com>
2017-09-01 14:20:30 +02:00
Laszlo Ersek 6c72134dff OvmfPkg/BaseMemEncryptSevLib: clean up DEBUG prefixes
The prefix for the SetMemoryEncDec() DEBUG messages should be

  "ModuleName:FunctionName: "

not

  "ModuleName:FunctionName "

Cc: Brijesh Singh <brijesh.singh@amd.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Brijesh Singh <brijesh.singh@amd.com>
Tested-by: Brijesh Singh <brijesh.singh@amd.com>
2017-09-01 14:20:27 +02:00
Laszlo Ersek 6692af92b1 OvmfPkg/BaseMemEncryptSevLib: break DEBUG calls to multiple lines
None of the DEBUG macro invocations in SetMemoryEncDec() fit on a single
line. Break them to multiple lines, for (a) conforming to the coding style
spec, (b) easier modification in later patches.

Cc: Brijesh Singh <brijesh.singh@amd.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Brijesh Singh <brijesh.singh@amd.com>
Tested-by: Brijesh Singh <brijesh.singh@amd.com>
2017-09-01 14:20:24 +02:00
Laszlo Ersek 70063aecde OvmfPkg/BaseMemEncryptSevLib: unify encrypt/decrypt DEBUG messages
Unify the debug messages between InternalMemEncryptSevSetMemoryEncrypted()
and InternalMemEncryptSevSetMemoryDecrypted().

Cc: Brijesh Singh <brijesh.singh@amd.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Brijesh Singh <brijesh.singh@amd.com>
Tested-by: Brijesh Singh <brijesh.singh@amd.com>
2017-09-01 14:19:43 +02:00
Brijesh Singh 17cbf7359f OvmfPkg/VirtioScsiDxe: negotiate VIRTIO_F_IOMMU_PLATFORM
VirtioScsiDxe driver has been updated to use IOMMU-like member functions
from VIRTIO_DEVICE_PROTOCOL to translate the system physical address to
device address. We do not need to do anything special when
VIRTIO_F_IOMMU_PLATFORM bit is present hence treat it in parallel with
VIRTIO_F_VERSION_1.

Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Regression-tested-by: Laszlo Ersek <lersek@redhat.com>
Tested-by: Laszlo Ersek <lersek@redhat.com>
2017-08-31 21:29:53 +02:00
Brijesh Singh 9d0d5050c7 OvmfPkg/VirtioScsiDxe: map virtio-scsi request and response buffers
When device is behind the IOMMU, driver is require to pass the device
address of virtio request, response and any memory referenced by those
request/response to the bus master.

The patch uses IOMMU-like member functions from VIRTIO_DEVICE_PROTOCOL to
map request and response buffers system physical address to the device
address.

- If the buffer need to be accessed by both the processor and a bus
  master then map with BusMasterCommonBuffer.

- If the buffer need to be accessed for a write operation by a bus master
  then map with BusMasterWrite.

  However, after a BusMasterWrite Unmap() failure, error reporting via
  EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET would be very complex,
  therefore we map such buffers too with BusMasterCommonBuffer.

- If the buffer need to be accessed for a read  operation by a bus master
  then map with BusMasterRead.

Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
[lersek@redhat.com: restore lost sentence/paragraph in commit message]
[lersek@redhat.com: reindent/reflow "InDataBuffer" comment block]
[lersek@redhat.com: cast arg, not result, of EFI_SIZE_TO_PAGES() to UINTN]
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Regression-tested-by: Laszlo Ersek <lersek@redhat.com>
Tested-by: Laszlo Ersek <lersek@redhat.com>
2017-08-31 21:28:26 +02:00
Brijesh Singh 1b15eb06c7 OvmfPkg/VirtioScsiDxe: add helper to create a fake host adapter error
When virtio request fails we return EFI_DEVICE_ERROR, as per the spec
EFI_EXT_SCSI_PASS_THRU_PROTOCOL.PassThru() member function is required
to implement elaborated error reporting.

The patch refactors out entire block of the code that creates the host
adapter error into a separate helper function (ReportHostAdapterError).

Suggested-by: Laszlo Ersek <lersek@redhat.com>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
[lersek@redhat.com: fix style & typo in ReportHostAdapterError() comment]
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Regression-tested-by: Laszlo Ersek <lersek@redhat.com>
Tested-by: Laszlo Ersek <lersek@redhat.com>
2017-08-31 21:01:31 +02:00
Brijesh Singh fc2168feb2 OvmfPkg/VirtioScsiDxe: map VRING using VirtioRingMap()
When device is behind the IOMMU then driver need to pass the device
address when programing the bus master. The patch uses VirtioRingMap() to
map the VRING system physical address to device address.

Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Regression-tested-by: Laszlo Ersek <lersek@redhat.com>
Tested-by: Laszlo Ersek <lersek@redhat.com>
2017-08-31 20:57:04 +02:00
Brijesh Singh ea8314e440 OvmfPkg/VirtioBlkDxe: Check the return status of unmap data buffer
when "RequestIsWrite" is FALSE -- i.e., the CPU wants data from
the device, we map "Buffer" for VirtioOperationBusMasterWrite. In
this case, checking the return status of

Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, BufferMapping);

is must. If the unmapping fails, then "Buffer" will not contain the
actual data from the device, and we must fail the request with
EFI_DEVICE_ERROR.

Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
[lersek@redhat.com: fix typos in subject]
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Tested-by: Laszlo Ersek <lersek@redhat.com>
2017-08-30 18:53:54 +02:00
Laszlo Ersek d431d8339e OvmfPkg/QemuFwCfgDxeLib: SEV: zero FW_CFG_DMA_ACCESS before decrypting it
There's a small window between

- AllocFwCfgDmaAccessBuffer() mapping the new FW_CFG_DMA_ACCESS object for
  common buffer operation (i.e., decrypting it), and

- InternalQemuFwCfgDmaBytes() setting the fields of the object.

In this window, earlier garbage in the object is "leaked" to the
hypervisor. So zero the object before we decrypt it.

(This commit message references AMD SEV directly, because QemuFwCfgDxeLib
is not *generally* enabled for IOMMU operation just yet, unlike our goal
for the virtio infrastructure. Instead, QemuFwCfgDxeLib uses
MemEncryptSevLib explicitly to detect SEV, and then relies on IOMMU
protocol behavior that is specific to SEV. At this point, this is by
design.)

Cc: Brijesh Singh <brijesh.singh@amd.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
Reviewed-by: Brijesh Singh <brijesh.singh@amd.com>
2017-08-29 22:44:33 +02:00