On 2016-04-05 01:31:27, Laszlo Ersek wrote: > On 04/05/16 09:03, Jordan Justen wrote: > > On 2016-03-14 05:53:23, Laszlo Ersek wrote: > >> These header files are intentionally minimal, and intentionally kept apart > >> from the VirtIo 0.9.5 headers. > >> > >> Cc: Ard Biesheuvel <[email protected]> > >> Cc: Jordan Justen <[email protected]> > >> Contributed-under: TianoCore Contribution Agreement 1.0 > >> Signed-off-by: Laszlo Ersek <[email protected]> > >> --- > >> OvmfPkg/Include/IndustryStandard/Virtio10.h | 81 ++++++++++++++++++++ > >> OvmfPkg/Include/IndustryStandard/Virtio10Net.h | 31 ++++++++ > >> 2 files changed, 112 insertions(+) > >> > >> diff --git a/OvmfPkg/Include/IndustryStandard/Virtio10.h > >> b/OvmfPkg/Include/IndustryStandard/Virtio10.h > >> new file mode 100644 > >> index 000000000000..722475c4ea55 > >> --- /dev/null > >> +++ b/OvmfPkg/Include/IndustryStandard/Virtio10.h
How about including Virtio10.h from Virtio.h? > >> @@ -0,0 +1,81 @@ > >> +/** @file > >> + Definitions from the VirtIo 1.0 specification (csprd05). > >> + > >> + Copyright (C) 2016, Red Hat, Inc. > >> + > >> + This program and the accompanying materials are licensed and made > >> available > >> + under the terms and conditions of the BSD License which accompanies this > >> + distribution. The full text of the license may be found at > >> + http://opensource.org/licenses/bsd-license.php > >> + > >> + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > >> WITHOUT > >> + WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. > >> +**/ > >> + > >> +#ifndef _VIRTIO_1_0_H_ > >> +#define _VIRTIO_1_0_H_ > >> + > >> +#include <Base.h> > >> + > >> +// > >> +// Structures for parsing the VirtIo 1.0 specific PCI capabilities from > >> the > >> +// config space > >> +// > >> +#pragma pack (1) > >> +typedef struct { > >> + UINT8 CapId; // Capability identifier (generic) > >> + UINT8 CapNext; // Link to next capability (generic) > >> +} VIRTIO_PCI_CAP_LINK; > >> + > >> +typedef struct { > >> + UINT8 ConfigType; // Identifies the specific VirtIo 1.0 config > >> structure > >> + UINT8 Bar; // The BAR that contains the structure > >> + UINT8 Padding[3]; > >> + UINT32 Offset; // Offset within Bar until the start of the structure > >> + UINT32 Length; // Length of the structure > >> +} VIRTIO_PCI_CAP; > >> +#pragma pack () > >> + > >> +// > >> +// Values for the VIRTIO_PCI_CAP.ConfigType field > >> +// > >> +#define VIRTIO_PCI_CAP_COMMON_CFG 1 // Common configuration > >> +#define VIRTIO_PCI_CAP_NOTIFY_CFG 2 // Notifications > >> +#define VIRTIO_PCI_CAP_DEVICE_CFG 4 // Device specific configuration > >> + > >> +// > >> +// Structure pointed-to by Bar and Offset in VIRTIO_PCI_CAP when > >> ConfigType is > >> +// VIRTIO_PCI_CAP_COMMON_CFG > >> +// > >> +#pragma pack (1) > >> +typedef struct { > >> + UINT32 DeviceFeatureSelect; > >> + UINT32 DeviceFeature; > >> + UINT32 DriverFeatureSelect; > >> + UINT32 DriverFeature; > >> + UINT16 MsixConfig; > >> + UINT16 NumQueues; > >> + UINT8 DeviceStatus; > >> + UINT8 ConfigGeneration; > >> + UINT16 QueueSelect; > >> + UINT16 QueueSize; > >> + UINT16 QueueMsixVector; > >> + UINT16 QueueEnable; > >> + UINT16 QueueNotifyOff; > >> + UINT64 QueueDesc; > >> + UINT64 QueueAvail; > >> + UINT64 QueueUsed; > >> +} VIRTIO_PCI_COMMON_CFG; > >> +#pragma pack () > >> + > >> +// > >> +// VirtIo 1.0 device status bits > >> +// > >> +#define VSTAT_FEATURES_OK BIT3 > >> + > >> +// > >> +// VirtIo 1.0 reserved (device-independent) feature bits > >> +// > >> +#define VIRTIO_F_VERSION_1 BIT32 > >> + > >> +#endif // _VIRTIO_1_0_H_ > >> diff --git a/OvmfPkg/Include/IndustryStandard/Virtio10Net.h > >> b/OvmfPkg/Include/IndustryStandard/Virtio10Net.h > >> new file mode 100644 > >> index 000000000000..2befc661dc62 > >> --- /dev/null > >> +++ b/OvmfPkg/Include/IndustryStandard/Virtio10Net.h > >> @@ -0,0 +1,31 @@ > >> +/** @file > >> + Definitions from the VirtIo 1.0 specification (csprd05), specifically > >> for the > >> + network device. > >> + > >> + Copyright (C) 2016, Red Hat, Inc. > >> + > >> + This program and the accompanying materials are licensed and made > >> available > >> + under the terms and conditions of the BSD License which accompanies this > >> + distribution. The full text of the license may be found at > >> + http://opensource.org/licenses/bsd-license.php > >> + > >> + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > >> WITHOUT > >> + WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. > >> +**/ > >> + > >> +#ifndef _VIRTIO_1_0_NET_H_ > >> +#define _VIRTIO_1_0_NET_H_ > >> + > >> +#include <IndustryStandard/VirtioNet.h> How about instead we have VirtioNet.h include Virtio10Net.h? What about naming this VirtioNet10.h instead? > >> + > >> +// > >> +// VirtIo 1.0 packet header > >> +// > >> +#pragma pack (1) > >> +typedef struct { > >> + VIRTIO_NET_REQ Legacy; > > > > This naming seems a bit unfortunate. > > I can change the field name, sure. > > > I thought the nested version structures seemed a bit strange for edk2. > > Why? > For some reason, it just seems out of place in EDK II. I don't personally have a problem with nesting structures, but I'm just trying to think about what this would look like if it lived in MdePkg instead. > > Then I took a look at EFI_ACPI_4_0_FIXED_ACPI_DESCRIPTION_TABLE vs > > EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE. > > PCI_3_0_DATA_STRUCTURE and PCI_DATA_STRUCTURE seem to be another example, but in that case the structure is not just being extended, so it seems more natural to not embed v2.2 of the structure. > > What are your thoughts? > > I'm not sure about the exact justification for defining those structures > the way they are defined. I can imagine that nesting would have made no > sense for them. Personally, I would have defined the 5.0 FADT on top of > the 4.0 FADT, if only to save some space (in the source code). > > However, the main bonus of nesting is not just saving source code. It is > about convertibility between pointers to the container structure and the > contained (first member) structure. In C99, "6.7.2.1 Structure and union > specifiers" paragraph 13 says, > > [...] A pointer to a structure object, suitably converted, points > to its initial member [...] and vice versa. There may be > unnamed padding within a structure object, but not at its beginning. > > Without nesting, you can't access the initial portion of the 5.0 struct > through a pointer to 4.0; the compiler might even decide to insert > different padding between the same fields in 4.0 vs. 5.0. > > (This holds for C89 too.) > > Additionally, if you look at the strict aliasing (effective type) rules, > in C99 "6.5 Expressions", paragraph 7: > > An object shall have its stored value accessed only by an lvalue > expression that has one of the following types: > > — a type compatible with the effective type of the object, > — a qualified version of a type compatible with the effective type > of the object, > — a type that is the signed or unsigned type corresponding to the > effective type of the object, > — a type that is the signed or unsigned type corresponding to a > qualified version of the effective type of the object, > — an aggregate or union type that includes one of the > aforementioned types among its members (including, recursively, a > member of a subaggregate or contained union), or > — a character type. > > This means that, without nesting the 4.0 FADT into the 5.0 FADT, a > compiler that is allowed to enforce strict aliasing will assume that > pointers to 4.0 FADT and 5.0 FADT never alias; in other words, that > their pointed-to objects never overlap. However, if you embed the 4.0 > FADT into the 5.0 FADT, then the compiler will "keep in mind" (due to > the penultimate bullet) that the target of the pointer-to-4.0 could > actually be part of the target of the pointer-to-5.0. > > (The effective type rules were not spelled out this clearly in C89.) > > So, nesting is generally superior. > > There is one alternative (that keeps the above benefits): placing both > structures into a union. See "6.5.2.3 Structure and union members", > paragraph 5: > > One special guarantee is made in order to simplify the use of > unions: if a union contains several structures that share a common > initial sequence (see below), and if the union object currently > contains one of these structures, it is permitted to inspect the > common initial part of any of them anywhere that a declaration of > the complete type of the union is visible. Two structures share a > common initial sequence if corresponding members have compatible > types (and, for bit-fields, the same widths) for a sequence of one > or more initial members. > > (This is also guaranteed by C89.) > > > In patch 12/15 ("OvmfPkg: VirtioNetDxe: adapt virtio-net packet header > size to virtio-1.0") you can see how I'm using the Legacy field. > Embedding VIRTIO_NET_REQ into VIRTIO_1_0_NET_REQ is the natural choice. > > I guess I could define VIRTIO_1_0_NET_REQ independently, without > embedding VIRTIO_NET_REQ. In that case however I'd have to introduce > another type (a union type) for patch 12/15. > > But that would be strictly worse: not only would I have to call the > union member representing the old header "Legacy", I would also have to > call the union member representing the new header *something*. > > So, I think: > - Nesting is natural, frugal, and standard C; we should use it. > - If you dislike the field name "Legacy", I can certainly rename the > field to, say, Virtio095NetReq, or something else you'd recommend. > Virtio095NetReq, Virtio095, V0_95, _0_95, or Base all seem better to me. I guess Base or V0_95 would be my preference. -Jordan > > > > > -Jordan > > > >> + UINT16 NumBuffers; > >> +} VIRTIO_1_0_NET_REQ; > >> +#pragma pack () > >> + > >> +#endif // _VIRTIO_1_0_NET_H_ > >> -- > >> 1.8.3.1 > >> > >> > > _______________________________________________ > edk2-devel mailing list > [email protected] > https://lists.01.org/mailman/listinfo/edk2-devel _______________________________________________ edk2-devel mailing list [email protected] https://lists.01.org/mailman/listinfo/edk2-devel

