public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: Phil Dennis-Jordan <lists@philjordan.eu>
To: edk2-devel@lists.01.org
Cc: Phil Dennis-Jordan <phil@philjordan.eu>,
	Jordan Justen <jordan.l.justen@intel.com>,
	Laszlo Ersek <lersek@redhat.com>
Subject: [PATCH v5 2/3] OvmfPkg/QemuVideoDxe: Helper functions for unaligned port I/O.
Date: Fri,  7 Apr 2017 18:25:57 +1200	[thread overview]
Message-ID: <1491546358-58572-3-git-send-email-lists@philjordan.eu> (raw)
In-Reply-To: <1491546358-58572-1-git-send-email-lists@philjordan.eu>

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>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.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]
    
    v4, v5: (no changes)

 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)



  parent reply	other threads:[~2017-04-07  6:26 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-04-07  6:25 [PATCH v5 0/3] OvmfPkg/QemuVideoDxe: Add VMWare SVGA framebuffer support Phil Dennis-Jordan
2017-04-07  6:25 ` [PATCH v5 1/3] OvmfPkg: VMWare SVGA display device register definitions Phil Dennis-Jordan
2017-04-07  6:25 ` Phil Dennis-Jordan [this message]
2017-04-07  6:25 ` [PATCH v5 3/3] OvmfPkg/QemuVideoDxe: VMWare SVGA device support Phil Dennis-Jordan
2017-04-07 10:46   ` Laszlo Ersek
2017-04-12  2:47     ` Phil Dennis-Jordan

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=1491546358-58572-3-git-send-email-lists@philjordan.eu \
    --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