[edk2] [PATCH v3 2/3] OvmfPkg/QemuVideoDxe: Helper functions for unaligned port I/O.

Phil Dennis-Jordan posted 3 patches 7 years, 7 months ago
There is a newer version of this series
[edk2] [PATCH v3 2/3] OvmfPkg/QemuVideoDxe: Helper functions for unaligned port I/O.
Posted by Phil Dennis-Jordan 7 years, 7 months ago
From: Phil Dennis-Jordan <phil@philjordan.eu>

The VMWare SVGA display device implemented by Qemu (-vga vmware) uses
an I/O-type BAR which is laid out such that some register offsets are
not aligned to the read/write width with which they are expected to be
accessed. (The register value port has an offset of 1 and requires
32 bit wide read/write access.)

The EFI_PCI_IO_PROTOCOL's Io.Read/Io.Write functions do not support
such unaligned I/O.

Before a driver for this device can be added to QemuVideoDxe, helper
functions for unaligned I/O are therefore required. This adds the
functions UnalignedIoWrite32 and UnalignedIoRead32, based on IoLib's
IoWrite32 and IoRead32, for the Ia32 and X64 architectures. Port I/O
requires inline assembly, so implementations are provided for the GCC,
ICC, and Microsoft compiler families. Such I/O is not possible on other
architectures, a dummy (ASSERT()ing) implementation is therefore
provided to satisfy the linker.

Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Suggested-by: Jordan Justen <jordan.l.justen@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Phil Dennis-Jordan <phil@philjordan.eu>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
---

Notes:
    v2:
    - Separate commit for the unaligned I/O helper functions. [Laszlo]
    - Dummy implementations return values despite ASSERT(). [Laszlo]
    - Build failure in ArmVirtPkg fixed. [Laszlo]
    - More consistent API docs and function ordering.
    
    v3:
    - Fixed typos in commit message [Laszlo]
    - Added Suggested-by: tag [Laszlo]
    - Rewrapped comment lines to 79 chars [Laszlo]
    - Corrected whitespace in function calls [Laszlo]
    - EFIAPI dropped. [Laszlo]
    - Fixed return value in dummy UnsignedIoWrite32 [Laszlo]
    - Dropped "N" imm8 constraint in GCC inline asm [Laszlo]

 OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf         |  6 ++
 OvmfPkg/QemuVideoDxe/UnalignedIoInternal.h    | 59 +++++++++++++++
 OvmfPkg/QemuVideoDxe/UnalignedIoGcc.c         | 70 +++++++++++++++++
 OvmfPkg/QemuVideoDxe/UnalignedIoIcc.c         | 80 ++++++++++++++++++++
 OvmfPkg/QemuVideoDxe/UnalignedIoMsc.c         | 78 +++++++++++++++++++
 OvmfPkg/QemuVideoDxe/UnalignedIoUnsupported.c | 66 ++++++++++++++++
 6 files changed, 359 insertions(+)

diff --git a/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf b/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
index affb6ffd88e0..346a5aed94fa 100644
--- a/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
+++ b/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
@@ -41,6 +41,12 @@ [Sources.common]
 
 [Sources.Ia32, Sources.X64]
   VbeShim.c
+  UnalignedIoGcc.c    | GCC
+  UnalignedIoMsc.c    | MSFT
+  UnalignedIoIcc.c    | INTEL
+
+[Sources.IPF, Sources.EBC, Sources.ARM, Sources.AARCH64]
+  UnalignedIoUnsupported.c
 
 [Packages]
   MdePkg/MdePkg.dec
diff --git a/OvmfPkg/QemuVideoDxe/UnalignedIoInternal.h b/OvmfPkg/QemuVideoDxe/UnalignedIoInternal.h
new file mode 100644
index 000000000000..234de6c21bd1
--- /dev/null
+++ b/OvmfPkg/QemuVideoDxe/UnalignedIoInternal.h
@@ -0,0 +1,59 @@
+/** @file
+  Unaligned port I/O, with implementations for various x86 compilers and a
+  dummy for platforms which do not support unaligned port I/O.
+
+  Copyright (c) 2017, Phil Dennis-Jordan.<BR>
+  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 _UNALIGNED_IO_INTERNAL_H_
+#define _UNALIGNED_IO_INTERNAL_H_
+
+/**
+  Performs a 32-bit write to the specified, possibly unaligned I/O-type address.
+
+  Writes the 32-bit I/O port specified by Port with the value specified by Value
+  and returns Value. This function must guarantee that all I/O read and write
+  operations are serialized.
+
+  If 32-bit unaligned I/O port operations are not supported, then ASSERT().
+
+  @param[in]  Port   I/O port address
+  @param[in]  Value  32-bit word to write
+
+  @return The value written to the I/O port.
+
+**/
+UINT32
+UnalignedIoWrite32 (
+  IN      UINTN                     Port,
+  IN      UINT32                    Value
+  );
+
+/**
+  Reads a 32-bit word from the specified, possibly unaligned I/O-type address.
+
+  Reads the 32-bit I/O port specified by Port. The 32-bit read value is
+  returned. This function must guarantee that all I/O read and write operations
+  are serialized.
+
+  If 32-bit unaligned I/O port operations are not supported, then ASSERT().
+
+  @param[in]  Port  The I/O port to read.
+
+  @return The value read.
+
+**/
+UINT32
+UnalignedIoRead32 (
+  IN      UINTN                     Port
+  );
+
+#endif
diff --git a/OvmfPkg/QemuVideoDxe/UnalignedIoGcc.c b/OvmfPkg/QemuVideoDxe/UnalignedIoGcc.c
new file mode 100644
index 000000000000..105d55d3b903
--- /dev/null
+++ b/OvmfPkg/QemuVideoDxe/UnalignedIoGcc.c
@@ -0,0 +1,70 @@
+/** @file
+  Unaligned Port I/O. This file has compiler specifics for GCC as there is no
+  ANSI C standard for doing IO.
+
+  Based on IoLibGcc.c.
+
+  Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+  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.
+
+**/
+
+
+#include "UnalignedIoInternal.h"
+
+/**
+  Performs a 32-bit write to the specified, possibly unaligned I/O-type
+  address.
+
+  Writes the 32-bit I/O port specified by Port with the value specified by
+  Value and returns Value. This function must guarantee that all I/O read and
+  write operations are serialized.
+
+  If 32-bit unaligned I/O port operations are not supported, then ASSERT().
+
+  @param[in]  Port   I/O port address
+  @param[in]  Value  32-bit word to write
+
+  @return The value written to the I/O port.
+
+**/
+UINT32
+UnalignedIoWrite32 (
+  IN      UINTN                     Port,
+  IN      UINT32                    Value
+  )
+{
+  __asm__ __volatile__ ( "outl %0, %1" : : "a" (Value), "d" ((UINT16)Port) );
+  return Value;
+}
+
+/**
+  Reads a 32-bit word from the specified, possibly unaligned I/O-type address.
+
+  Reads the 32-bit I/O port specified by Port. The 32-bit read value is
+  returned. This function must guarantee that all I/O read and write operations
+  are serialized.
+
+  If 32-bit unaligned I/O port operations are not supported, then ASSERT().
+
+  @param[in]  Port  The I/O port to read.
+
+  @return The value read.
+
+**/
+UINT32
+UnalignedIoRead32 (
+  IN      UINTN                     Port
+  )
+{
+  UINT32 Data;
+  __asm__ __volatile__ ( "inl %1, %0" : "=a" (Data) : "d" ((UINT16)Port) );
+  return Data;
+}
+
diff --git a/OvmfPkg/QemuVideoDxe/UnalignedIoIcc.c b/OvmfPkg/QemuVideoDxe/UnalignedIoIcc.c
new file mode 100644
index 000000000000..79f3e446ddba
--- /dev/null
+++ b/OvmfPkg/QemuVideoDxe/UnalignedIoIcc.c
@@ -0,0 +1,80 @@
+/** @file
+  Unaligned port I/O. This file has compiler specifics for ICC as there
+  is no ANSI C standard for doing IO.
+
+  Based on IoLibIcc.c.
+
+  Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.<BR>
+  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.
+
+**/
+
+
+#include "UnalignedIoInternal.h"
+
+/**
+  Performs a 32-bit write to the specified, possibly unaligned I/O-type
+  address.
+
+  Writes the 32-bit I/O port specified by Port with the value specified by
+  Value and returns Value. This function must guarantee that all I/O read and
+  write operations are serialized.
+
+  If 32-bit unaligned I/O port operations are not supported, then ASSERT().
+
+  @param[in]  Port   I/O port address
+  @param[in]  Value  32-bit word to write
+
+  @return The value written to the I/O port.
+
+**/
+UINT32
+UnalignedIoWrite32 (
+  IN      UINTN                     Port,
+  IN      UINT32                    Value
+  )
+{
+  __asm {
+    mov eax, dword ptr [Value]
+    mov dx, word ptr [Port]
+    out dx, eax
+  }
+
+  return Value;
+}
+
+/**
+  Reads a 32-bit word from the specified, possibly unaligned I/O-type address.
+
+  Reads the 32-bit I/O port specified by Port. The 32-bit read value is
+  returned. This function must guarantee that all I/O read and write operations
+  are serialized.
+
+  If 32-bit unaligned I/O port operations are not supported, then ASSERT().
+
+  @param[in]  Port  The I/O port to read.
+
+  @return The value read.
+
+**/
+UINT32
+UnalignedIoRead32 (
+  IN      UINTN                     Port
+  )
+{
+  UINT32 Data;
+
+  __asm {
+    mov dx, word ptr [Port]
+    in  eax, dx
+    mov dword ptr [Data], eax
+  }
+
+  return Data;
+}
diff --git a/OvmfPkg/QemuVideoDxe/UnalignedIoMsc.c b/OvmfPkg/QemuVideoDxe/UnalignedIoMsc.c
new file mode 100644
index 000000000000..a466baee8486
--- /dev/null
+++ b/OvmfPkg/QemuVideoDxe/UnalignedIoMsc.c
@@ -0,0 +1,78 @@
+/** @file
+  Unaligned port I/O. This file has compiler specifics for Microsoft C as there
+  is no ANSI C standard for doing IO.
+
+  Based on IoLibMsc.c
+
+  Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+  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.
+
+**/
+
+
+#include "UnalignedIoInternal.h"
+
+unsigned long  _inpd (unsigned short port);
+unsigned long  _outpd (unsigned short port, unsigned long dataword );
+void          _ReadWriteBarrier (void);
+
+/**
+  Performs a 32-bit write to the specified, possibly unaligned I/O-type
+  address.
+
+  Writes the 32-bit I/O port specified by Port with the value specified by
+  Value and returns Value. This function must guarantee that all I/O read and
+  write operations are serialized.
+
+  If 32-bit unaligned I/O port operations are not supported, then ASSERT().
+
+  @param[in]  Port   I/O port address
+  @param[in]  Value  32-bit word to write
+
+  @return The value written to the I/O port.
+
+**/
+UINT32
+UnalignedIoWrite32 (
+  IN      UINTN                     Port,
+  IN      UINT32                    Value
+  )
+{
+  _ReadWriteBarrier ();
+  _outpd ((UINT16)Port, Value);
+  _ReadWriteBarrier ();
+  return Value;
+}
+
+/**
+  Reads a 32-bit word from the specified, possibly unaligned I/O-type address.
+
+  Reads the 32-bit I/O port specified by Port. The 32-bit read value is
+  returned. This function must guarantee that all I/O read and write operations
+  are serialized.
+
+  If 32-bit unaligned I/O port operations are not supported, then ASSERT().
+
+  @param[in]  Port  The I/O port to read.
+
+  @return The value read.
+
+**/
+UINT32
+UnalignedIoRead32 (
+  IN      UINTN                     Port
+  )
+{
+  UINT32                            Value;
+
+  _ReadWriteBarrier ();
+  Value = _inpd ((UINT16)Port);
+  _ReadWriteBarrier ();
+  return Value;
+}
diff --git a/OvmfPkg/QemuVideoDxe/UnalignedIoUnsupported.c b/OvmfPkg/QemuVideoDxe/UnalignedIoUnsupported.c
new file mode 100644
index 000000000000..57560ab38fcf
--- /dev/null
+++ b/OvmfPkg/QemuVideoDxe/UnalignedIoUnsupported.c
@@ -0,0 +1,66 @@
+/** @file
+  Unaligned port I/O dummy implementation for platforms which do not support it.
+
+  Copyright (c) 2017, Phil Dennis-Jordan.<BR>
+  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.
+
+**/
+
+
+#include <Library/DebugLib.h>
+#include "UnalignedIoInternal.h"
+
+/**
+  Performs a 32-bit write to the specified, possibly unaligned I/O-type
+  address.
+
+  Writes the 32-bit I/O port specified by Port with the value specified by
+  Value and returns Value. This function must guarantee that all I/O read and
+  write operations are serialized.
+
+  If 32-bit unaligned I/O port operations are not supported, then ASSERT().
+
+  @param[in]  Port   I/O port address
+  @param[in]  Value  32-bit word to write
+
+  @return The value written to the I/O port.
+
+**/
+UINT32
+UnalignedIoWrite32 (
+  IN      UINTN                     Port,
+  IN      UINT32                    Value
+  )
+{
+  ASSERT (FALSE);
+  return Value;
+}
+
+/**
+  Reads a 32-bit word from the specified, possibly unaligned I/O-type address.
+
+  Reads the 32-bit I/O port specified by Port. The 32-bit read value is
+  returned. This function must guarantee that all I/O read and write operations
+  are serialized.
+
+  If 32-bit unaligned I/O port operations are not supported, then ASSERT().
+
+  @param[in]  Port  The I/O port to read.
+
+  @return The value read.
+
+**/
+UINT32
+UnalignedIoRead32 (
+  IN      UINTN                     Port
+  )
+{
+  ASSERT (FALSE);
+  return 0;
+}
-- 
2.3.2 (Apple Git-55)

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel
Re: [edk2] [PATCH v3 2/3] OvmfPkg/QemuVideoDxe: Helper functions for unaligned port I/O.
Posted by Laszlo Ersek 7 years, 7 months ago
On 04/05/17 11:57, Phil Dennis-Jordan wrote:
> From: Phil Dennis-Jordan <phil@philjordan.eu>
> 
> The VMWare SVGA display device implemented by Qemu (-vga vmware) uses
> an I/O-type BAR which is laid out such that some register offsets are
> not aligned to the read/write width with which they are expected to be
> accessed. (The register value port has an offset of 1 and requires
> 32 bit wide read/write access.)
> 
> The EFI_PCI_IO_PROTOCOL's Io.Read/Io.Write functions do not support
> such unaligned I/O.
> 
> Before a driver for this device can be added to QemuVideoDxe, helper
> functions for unaligned I/O are therefore required. This adds the
> functions UnalignedIoWrite32 and UnalignedIoRead32, based on IoLib's
> IoWrite32 and IoRead32, for the Ia32 and X64 architectures. Port I/O
> requires inline assembly, so implementations are provided for the GCC,
> ICC, and Microsoft compiler families. Such I/O is not possible on other
> architectures, a dummy (ASSERT()ing) implementation is therefore
> provided to satisfy the linker.
> 
> Cc: Jordan Justen <jordan.l.justen@intel.com>
> Cc: Laszlo Ersek <lersek@redhat.com>
> Suggested-by: Jordan Justen <jordan.l.justen@intel.com>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Phil Dennis-Jordan <phil@philjordan.eu>
> Reviewed-by: Laszlo Ersek <lersek@redhat.com>
> ---
> 
> Notes:
>     v2:
>     - Separate commit for the unaligned I/O helper functions. [Laszlo]
>     - Dummy implementations return values despite ASSERT(). [Laszlo]
>     - Build failure in ArmVirtPkg fixed. [Laszlo]
>     - More consistent API docs and function ordering.
>     
>     v3:
>     - Fixed typos in commit message [Laszlo]
>     - Added Suggested-by: tag [Laszlo]
>     - Rewrapped comment lines to 79 chars [Laszlo]
>     - Corrected whitespace in function calls [Laszlo]
>     - EFIAPI dropped. [Laszlo]
>     - Fixed return value in dummy UnsignedIoWrite32 [Laszlo]
>     - Dropped "N" imm8 constraint in GCC inline asm [Laszlo]
> 
>  OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf         |  6 ++
>  OvmfPkg/QemuVideoDxe/UnalignedIoInternal.h    | 59 +++++++++++++++
>  OvmfPkg/QemuVideoDxe/UnalignedIoGcc.c         | 70 +++++++++++++++++
>  OvmfPkg/QemuVideoDxe/UnalignedIoIcc.c         | 80 ++++++++++++++++++++
>  OvmfPkg/QemuVideoDxe/UnalignedIoMsc.c         | 78 +++++++++++++++++++
>  OvmfPkg/QemuVideoDxe/UnalignedIoUnsupported.c | 66 ++++++++++++++++
>  6 files changed, 359 insertions(+)

Looks good, thank you for the update.
Laszlo

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel