There are cases that the operands of an expression are all with rank less
than UINT64/INT64 and the result of the expression is explicitly cast to
UINT64/INT64 to fit the target size.
An example will be:
UINT32 a,b;
// a and b can be any unsigned int type with rank less than UINT64, like
// UINT8, UINT16, etc.
UINT64 c;
c = (UINT64) (a + b);
Some static code checkers may warn that the expression result might
overflow within the rank of "int" (integer promotions) and the result is
then cast to a bigger size.
The commit refines codes by the following rules:
1). When the expression is possible to overflow the range of unsigned int/
int:
c = (UINT64)a + b;
2). When the expression will not overflow within the rank of "int", remove
the explicit type casts:
c = a + b;
3). When the expression will be cast to pointer of possible greater size:
UINT32 a,b;
VOID *c;
c = (VOID *)(UINTN)(a + b); --> c = (VOID *)((UINTN)a + b);
4). When one side of a comparison expression contains only operands with
rank less than UINT32:
UINT8 a;
UINT16 b;
UINTN c;
if ((UINTN)(a + b) > c) {...} --> if (((UINT32)a + b) > c) {...}
For rule 4), if we remove the 'UINTN' type cast like:
if (a + b > c) {...}
The VS compiler will complain with warning C4018 (signed/unsigned
mismatch, level 3 warning) due to promoting 'a + b' to type 'int'.
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Hao Wu <hao.a.wu@intel.com>
Reviewed-by: Jeff Fan <jeff.fan@intel.com>
The Fifo routines from the UefiCpuPkg/CpuIo2Dxe driver have been
moved to the new BaseIoLibIntrinsic (IoLib class) library.
Cc: Jeff Fan <jeff.fan@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
Signed-off-by: Leo Duran <leo.duran@amd.com>
Reviewed-by: Liming Gao <liming.gao@intel.com>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
Reviewed-by: Jeff Fan <jeff.fan@intel.com>
* Short description:
The CpuIoServiceRead() and CpuIoServiceWrite() functions transfer data
between memory and IO ports with individual Io(Read|Write)(8|16|32)
function calls, each in an appropriately set up loop.
On the Ia32 and X64 platforms however, FIFO reads and writes can be
optimized, by coding them in assembly, and delegating the loop to the
CPU, with the REP prefix.
On KVM virtualization hosts, this difference has a huge performance
impact: if the loop is open-coded, then the virtual machine traps to the
hypervisor on every single UINT8 / UINT16 / UINT32 transfer, whereas
with the REP prefix, KVM can transfer up to a page of data per VM trap.
This is especially noticeable with IDE PIO transfers, where all the data
are squeezed through IO ports.
* Long description:
The RootBridgeIoIoRW() function in
PcAtChipsetPkg/PciHostBridgeDxe/PciRootBridgeIo.c
used to have the exact same IO port acces optimization, dating back
verbatim to commit 1fd376d9792:
PcAtChipsetPkg/PciHostBridgeDxe: Improve KVM FIFO I/O read/write
performance
OvmfPkg cloned the "PcAtChipsetPkg/PciHostBridgeDxe" driver (for
unrelated reasons), and inherited the optimization from PcAtChipsetPkg.
The "PcAtChipsetPkg/PciHostBridgeDxe" driver was ultimately removed in
commit 111d79db47:
PcAtChipsetPkg/PciHostBridge: Remove PciHostBridge driver
and OvmfPkg too was rebased to the new core Pci Host Bridge Driver, in
commit 4014885ffd:
OvmfPkg: switch to MdeModulePkg/Bus/Pci/PciHostBridgeDxe
This caused the optimization to go lost. Namely, the
RootBridgeIoIoRead() and RootBridgeIoIoWrite() functions in the new core
Pci Host Bridge Driver delegate IO port accesses to
EFI_CPU_IO2_PROTOCOL. And, in OvmfPkg (and likely most other Ia32 / X64
edk2 platforms), this protocol is provided by "UefiCpuPkg/CpuIo2Dxe",
which lacks the optimization.
Therefore, this patch ports the C source code logic from commit
1fd376d979 (see above) to "UefiCpuPkg/CpuIo2Dxe", plus it ports the
NASM-converted assembly helper functions from OvmfPkg commits
6026bf4600 and ace1d0517b65:
OvmfPkg PciHostBridgeDxe: Convert Ia32/IoFifo.asm to NASM
OvmfPkg PciHostBridgeDxe: Convert X64/IoFifo.asm to NASM
In order to support the MSFT and INTEL toolchains as well, the *.asm
files are ported from OvmfPkg as well, immediately from before the above
conversion (that is, at 6026bf460037^).
* Notes about the port:
- The write and read branches from commit 1fd376d979 are split to the
separate functions CpuIoServiceWrite() and CpuIoServiceRead().
- The EfiPciWidthUintXX constants are replaced with EfiCpuIoWidthUintXX.
- The cast expression "(UINTN) Address" is replaced with
"(UINTN)Address" (i.e., no space), because that's how the receiving
functions spell it as well.
- The labels in the switch statements are unindented by one level, to
match the edk2 coding style (and the rest of UefiCpuPkg) better.
* The first signoff belongs to Jordan, because he authored all of
1fd376d979, 6026bf4600 and ace1d0517b.
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jordan Justen <jordan.l.justen@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Ref: https://www.redhat.com/archives/vfio-users/2016-April/msg00029.html
Reported-by: Mark <kram321@gmail.com>
Ref: http://thread.gmane.org/gmane.comp.bios.edk2.devel/10424/focus=10432
Reported-by: Jordan Justen <jordan.l.justen@intel.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ruiyu Ni <ruiyu.ni@intel.com>
Cc: Jeff Fan <jeff.fan@intel.com>
Cc: Mark <kram321@gmail.com>
Tested-by: Mark <kram321@gmail.com>
Reviewed-by: Jeff Fan <jeff.fan@intel.com>