From: Laszlo Ersek <lersek@redhat.com>
To: edk2-devel-01 <edk2-devel@lists.01.org>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>,
Jordan Justen <jordan.l.justen@intel.com>,
Liming Gao <liming.gao@intel.com>,
Michael D Kinney <michael.d.kinney@intel.com>
Subject: [PATCH 0/7] MdePkg, OvmfPkg, ArmVirtPkg: add and use PCI(E) Capabilities Library
Date: Fri, 4 May 2018 23:36:30 +0200 [thread overview]
Message-ID: <20180504213637.11266-1-lersek@redhat.com> (raw)
Repo: https://github.com/lersek/edk2.git
Branch: pci_cap
In message [1], Jordan suggested a general "capabilities helper lib that
could iterate & read the PCI capability structs". Patch #1 introduces
that library (class and central BASE instance) to MdePkg; the library
class is called PciCapLib.
[1] http://mid.mail-archive.com/150696619010.2454.9266470245604846575@jljusten-skl
PciCapLib offers APIs to parse capabilities lists, and to locate,
describe, read and write capabilities.
The library class targets a wide range of client module types; for
example, platform PEIMs, platform DXE drivers, and UEFI drivers that
follow the UEFI Driver Model. For this reason, the library class is
designed with PCI config access abstracted away, even beyond the PPI /
Protocol level, since those cannot cross the PEI / DXE boundary.
This (minimal) config space access method abstraction is called
PCI_CAP_DEV. It is *conceptually* a protocol. Client modules plug
PCI_CAP_DEV instances into PciCapLib for config space access, similarly
to how DiskIo and BlockIo instances are plugged into filesystem drivers.
Similarly to the filesystem driver example, PciCapLib is an example for
the "strategy pattern".
Patches #2 and #3 introduce small "factory" libraries that help client
modules produce PCI_CAP_DEV instances:
- PciCapPciSegmentLib -- incl. class and central BASE instance -- from
patch #2 produces PCI_CAP_DEV instances on top of PciSegmentLib, using
the "Segment:Bus:Device.Function" notation. This is meant for platform
modules (PEIMs and DXE drivers), which generally have a working
PciSegmentLib instance available.
- PciCapPciIoLib -- incl. class and central UEFI instance -- from patch
#3 lets client modules produce PCI_CAP_DEV instances on top of
EFI_PCI_IO_PROTOCOL instances. This is meant for UEFI drivers.
Patches #4 and #5 resolve the three new lib classes to their respective
central instances in the OvmfPkg and ArmVirtPkg DSC files.
Patch #6 converts OvmfPkg/PciHotPlugInitDxe to the new APIs, from manual
capability list parsing. Because PciHotPlugInitDxe is a platform DXE
driver, this conversion uses PciCapPciSegmentLib and PciCapLib.
Patch #7 converts OvmfPkg/Virtio10Dxe to the new APIs, from manual
capability list parsing. Because Virtio10Dxe is a UEFI driver, this
conversion uses PciCapPciIoLib and PciCapLib.
----[ jump to the patches now, and return if you have questions: I
have answers, but you might find them too verbose in advance ]----
Q1: If PCI config access needs to be abstracted from PciCapLib, then why
don't we provide multiple instances of PciCapLib? In other words,
why the PCI_CAP_DEV "protocol" rather than multiple instances of
PciCapLib?
A1: The point of lib classes and instances is that the class provides a
common interface, and the instances provide different
implementations. We have the opposite use case here (hence the
"strategy pattern"): the implementation of the higher level
algorithm is common, and the objects that plug into it differ at the
*interface* level ("Segment:Bus:Device.Function" notation versus
PciIo protocol).
None of those notations are suitable for inclusion in the PciCapLib
*class*; a more abstract interface is needed for identifying the PCI
device to the library, for parsing of capabilities lists.
Q2: OK, let's say we can't (and shouldn't) include both notations in the
PciCapLib class; can we settle on one of them, rather than
PCI_CAP_DEV?
A2: No, we can't. PciIo is obviously unusable in PEIMs (and in quite a
few platform DXE drivers too).
It takes a bit longer to explain why the other choice, i.e. adopting
the "Segment:Bus:Device.Function" notation for the PciCapLib
interface, is not good either. It has to do with the portability of
UEFI drivers that bind PciIo protocol instances:
It is indeed easy enough to call PciIo->GetLocation() and plug the
output values into a theoretical "Segment:Bus:Device.Function"
interface. However, about the only two things that could consume
such location identifiers and actually *implement* config space
access would be:
(a) the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.Pci.Read/Write member
functions, where the member functions themselves take the
"Bus:Device.Function" part, and the "Segment" part must be used
for selecting the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance
itself, through the SegmentNumber member;
(b) the PciSegmentLib interfaces.
Building a PciCapLib instance that uses (a) into a UEFI driver is a
bad idea, because there are platforms that provide PciIo instances
-- hence the driver can generally run on them -- but don't provide
PciRootBridgeIo instances.
Building a PciCapLib instance that uses (b) into a UEFI driver is
worse. The PciSegmentLib interfaces are not capable of returning
errors. For example, if a device appears as PCI Express (implying
its extended config space exists, potentially containing extended
capabilities), but the underlying platform does not support extended
config space access (for example because it only supports
0xCF8/0xCFC, and not ECAM), then peeking at the extended config
space of the device may invoke undefined behavior within
PciSegmentLib, and the PciCapLib instance will be none the wiser.
(In fact, for the same reason, even PciCapPciSegmentLib has to
extend the "Segment:Bus:Device.Function" notation slightly; so that
such issues are caught *before* the call is made to PciSegmentLib.)
Q3: Wait, I thought it wasn't possible for a PCI Express device to
appear on a platform that lacked ECAM.
A3: Is that a question? :) Yes, it is plenty possible [2]. Same way as
garbage / looped config spaces are [3].
[2] https://github.com/tianocore/edk2/commit/014b472053ae3
[3] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=02d578e5edd9
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Thanks,
Laszlo
Laszlo Ersek (7):
MdePkg: introduce PciCapLib
MdePkg: introduce PciCapPciSegmentLib
MdePkg: introduce PciCapPciIoLib
OvmfPkg: resolve PciCapLib, PciCapPciSegmentLib, PciCapPciIoLib
ArmVirtPkg: resolve PciCapLib, PciCapPciSegmentLib, PciCapPciIoLib
OvmfPkg/PciHotPlugInitDxe: convert to PciCapLib
OvmfPkg/Virtio10Dxe: convert to PciCapLib
ArmVirtPkg/ArmVirt.dsc.inc | 3 +
MdePkg/Include/Library/PciCapLib.h | 429 +++++++++
MdePkg/Include/Library/PciCapPciIoLib.h | 58 ++
MdePkg/Include/Library/PciCapPciSegmentLib.h | 82 ++
MdePkg/Library/BasePciCapLib/BasePciCapLib.c | 1007 ++++++++++++++++++++
MdePkg/Library/BasePciCapLib/BasePciCapLib.h | 60 ++
MdePkg/Library/BasePciCapLib/BasePciCapLib.inf | 37 +
MdePkg/Library/BasePciCapPciSegmentLib/BasePciCapPciSegmentLib.c | 226 +++++
MdePkg/Library/BasePciCapPciSegmentLib/BasePciCapPciSegmentLib.h | 47 +
MdePkg/Library/BasePciCapPciSegmentLib/BasePciCapPciSegmentLib.inf | 34 +
MdePkg/Library/UefiPciCapPciIoLib/UefiPciCapPciIoLib.c | 243 +++++
MdePkg/Library/UefiPciCapPciIoLib/UefiPciCapPciIoLib.h | 44 +
MdePkg/Library/UefiPciCapPciIoLib/UefiPciCapPciIoLib.inf | 35 +
MdePkg/MdePkg.dec | 14 +
MdePkg/MdePkg.dsc | 3 +
OvmfPkg/Include/IndustryStandard/Virtio10.h | 7 +-
OvmfPkg/OvmfPkgIa32.dsc | 3 +
OvmfPkg/OvmfPkgIa32X64.dsc | 3 +
OvmfPkg/OvmfPkgX64.dsc | 3 +
OvmfPkg/PciHotPlugInitDxe/PciHotPlugInit.c | 267 ++----
OvmfPkg/PciHotPlugInitDxe/PciHotPlugInit.inf | 5 +
OvmfPkg/Virtio10Dxe/Virtio10.c | 135 +--
OvmfPkg/Virtio10Dxe/Virtio10.inf | 2 +
23 files changed, 2485 insertions(+), 262 deletions(-)
create mode 100644 MdePkg/Include/Library/PciCapLib.h
create mode 100644 MdePkg/Include/Library/PciCapPciIoLib.h
create mode 100644 MdePkg/Include/Library/PciCapPciSegmentLib.h
create mode 100644 MdePkg/Library/BasePciCapLib/BasePciCapLib.c
create mode 100644 MdePkg/Library/BasePciCapLib/BasePciCapLib.h
create mode 100644 MdePkg/Library/BasePciCapLib/BasePciCapLib.inf
create mode 100644 MdePkg/Library/BasePciCapPciSegmentLib/BasePciCapPciSegmentLib.c
create mode 100644 MdePkg/Library/BasePciCapPciSegmentLib/BasePciCapPciSegmentLib.h
create mode 100644 MdePkg/Library/BasePciCapPciSegmentLib/BasePciCapPciSegmentLib.inf
create mode 100644 MdePkg/Library/UefiPciCapPciIoLib/UefiPciCapPciIoLib.c
create mode 100644 MdePkg/Library/UefiPciCapPciIoLib/UefiPciCapPciIoLib.h
create mode 100644 MdePkg/Library/UefiPciCapPciIoLib/UefiPciCapPciIoLib.inf
--
2.14.1.3.gb7cf6e02401b
next reply other threads:[~2018-05-04 21:36 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-05-04 21:36 Laszlo Ersek [this message]
2018-05-04 21:36 ` [PATCH 1/7] MdePkg: introduce PciCapLib Laszlo Ersek
2018-05-04 21:36 ` [PATCH 2/7] MdePkg: introduce PciCapPciSegmentLib Laszlo Ersek
2018-05-04 21:36 ` [PATCH 3/7] MdePkg: introduce PciCapPciIoLib Laszlo Ersek
2018-05-04 21:36 ` [PATCH 4/7] OvmfPkg: resolve PciCapLib, PciCapPciSegmentLib, PciCapPciIoLib Laszlo Ersek
2018-05-04 21:36 ` [PATCH 5/7] ArmVirtPkg: " Laszlo Ersek
2018-05-04 21:36 ` [PATCH 6/7] OvmfPkg/PciHotPlugInitDxe: convert to PciCapLib Laszlo Ersek
2018-05-04 21:36 ` [PATCH 7/7] OvmfPkg/Virtio10Dxe: " Laszlo Ersek
2018-05-14 13:15 ` [PATCH 0/7] MdePkg, OvmfPkg, ArmVirtPkg: add and use PCI(E) Capabilities Library Laszlo Ersek
2018-05-14 15:06 ` Gao, Liming
2018-05-14 17:19 ` 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=20180504213637.11266-1-lersek@redhat.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