render / rpms / edk2

Forked from rpms/edk2 3 months ago
Clone

Blame 0024-OvmfPkg-save-on-I-O-port-accesses-when-the-debug-por.patch

Paolo Bonzini 2e34e0
From b23853af6eb71e4c9b2e2d235b1db80541d33116 Mon Sep 17 00:00:00 2001
Paolo Bonzini 2e34e0
From: Paolo Bonzini <pbonzini@redhat.com>
Paolo Bonzini 2e34e0
Date: Wed, 15 Nov 2017 18:01:00 +0100
Paolo Bonzini 2e34e0
Subject: [PATCH 3/3] OvmfPkg: save on I/O port accesses when the debug port is
Paolo Bonzini 2e34e0
 not in use
Paolo Bonzini 2e34e0
Paolo Bonzini 2e34e0
When SEV is enabled, every debug message printed by OVMF to the
Paolo Bonzini 2e34e0
QEMU debug port traps from the guest to QEMU character by character
Paolo Bonzini 2e34e0
because "REP OUTSB" cannot be used by IoWriteFifo8.  Furthermore,
Paolo Bonzini 2e34e0
when OVMF is built with the DEBUG_VERBOSE bit (value 0x00400000)
Paolo Bonzini 2e34e0
enabled in "gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel", then the
Paolo Bonzini 2e34e0
OvmfPkg/IoMmuDxe driver, and the OvmfPkg/Library/BaseMemEncryptSevLib
Paolo Bonzini 2e34e0
library instance that is built into it, produce a huge amount of
Paolo Bonzini 2e34e0
log messages.  Therefore, in SEV guests, the boot time impact is huge
Paolo Bonzini 2e34e0
(about 45 seconds _additional_ time spent writing to the debug port).
Paolo Bonzini 2e34e0
Paolo Bonzini 2e34e0
While these messages are very useful for analyzing guest behavior,
Paolo Bonzini 2e34e0
most of the time the user won't be capturing the OVMF debug log.
Paolo Bonzini 2e34e0
In fact libvirt does not provide a method for configuring log capture;
Paolo Bonzini 2e34e0
users that wish to do this (or are instructed to do this) have to resort
Paolo Bonzini 2e34e0
to <qemu:arg>.
Paolo Bonzini 2e34e0
Paolo Bonzini 2e34e0
The debug console device provides a handy detection mechanism; when read,
Paolo Bonzini 2e34e0
it returns 0xE9 (which is very much unlike the 0xFF that is returned by
Paolo Bonzini 2e34e0
an unused port).  Use it to skip the possibly expensive OUT instructions
Paolo Bonzini 2e34e0
when the debug I/O port isn't plugged anywhere.
Paolo Bonzini 2e34e0
Paolo Bonzini 2e34e0
For SEC, the debug port has to be read before each full message.
Paolo Bonzini 2e34e0
However:
Paolo Bonzini 2e34e0
Paolo Bonzini 2e34e0
- if the debug port is available, then reading one byte before writing
Paolo Bonzini 2e34e0
a full message isn't tragic, especially because SEC doesn't print many
Paolo Bonzini 2e34e0
messages
Paolo Bonzini 2e34e0
Paolo Bonzini 2e34e0
- if the debug port is not available, then reading one byte instead of
Paolo Bonzini 2e34e0
writing a full message is still a win.
Paolo Bonzini 2e34e0
Paolo Bonzini 2e34e0
Contributed-under: TianoCore Contribution Agreement 1.0
Paolo Bonzini 2e34e0
Cc: Laszlo Ersek <lersek@redhat.com>
Paolo Bonzini 2e34e0
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Paolo Bonzini 2e34e0
Cc: Jordan Justen (Intel address) <jordan.l.justen@intel.com>
Paolo Bonzini 2e34e0
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Paolo Bonzini 2e34e0
---
Paolo Bonzini 2e34e0
 .../PlatformDebugLibIoPort/DebugLibDetect.h        | 57 ++++++++++++++++++++++
Paolo Bonzini 2e34e0
 OvmfPkg/Library/PlatformDebugLibIoPort/DebugLib.c  | 28 +++++++++--
Paolo Bonzini 2e34e0
 .../PlatformDebugLibIoPort/DebugLibDetect.c        | 30 ++++++++++--
Paolo Bonzini 2e34e0
 .../PlatformDebugLibIoPort/DebugLibDetectRom.c     | 21 +++++++-
Paolo Bonzini 2e34e0
 4 files changed, 127 insertions(+), 9 deletions(-)
Paolo Bonzini 2e34e0
 create mode 100644 OvmfPkg/Library/PlatformDebugLibIoPort/DebugLibDetect.h
Paolo Bonzini 2e34e0
Paolo Bonzini 2e34e0
diff --git a/OvmfPkg/Library/PlatformDebugLibIoPort/DebugLibDetect.h b/OvmfPkg/Library/PlatformDebugLibIoPort/DebugLibDetect.h
Paolo Bonzini 2e34e0
new file mode 100644
Paolo Bonzini 2e34e0
index 0000000000..1f739b55d8
Paolo Bonzini 2e34e0
--- /dev/null
Paolo Bonzini 2e34e0
+++ b/OvmfPkg/Library/PlatformDebugLibIoPort/DebugLibDetect.h
Paolo Bonzini 2e34e0
@@ -0,0 +1,57 @@
Paolo Bonzini 2e34e0
+/** @file
Paolo Bonzini 2e34e0
+  Base Debug library instance for QEMU debug port.
Paolo Bonzini 2e34e0
+  It uses PrintLib to send debug messages to a fixed I/O port.
Paolo Bonzini 2e34e0
+
Paolo Bonzini 2e34e0
+  Copyright (c) 2017, Red Hat, Inc.
Paolo Bonzini 2e34e0
+  This program and the accompanying materials
Paolo Bonzini 2e34e0
+  are licensed and made available under the terms and conditions of the BSD License
Paolo Bonzini 2e34e0
+  which accompanies this distribution.  The full text of the license may be found at
Paolo Bonzini 2e34e0
+  http://opensource.org/licenses/bsd-license.php.
Paolo Bonzini 2e34e0
+
Paolo Bonzini 2e34e0
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
Paolo Bonzini 2e34e0
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Paolo Bonzini 2e34e0
+
Paolo Bonzini 2e34e0
+**/
Paolo Bonzini 2e34e0
+
Paolo Bonzini 2e34e0
+#ifndef __DEBUG_IO_PORT_DETECT_H__
Paolo Bonzini 2e34e0
+#define __DEBUG_IO_PORT_DETECT_H__
Paolo Bonzini 2e34e0
+
Paolo Bonzini 2e34e0
+#include <Base.h>
Paolo Bonzini 2e34e0
+
Paolo Bonzini 2e34e0
+//
Paolo Bonzini 2e34e0
+// The constant value that is read from the debug I/O port
Paolo Bonzini 2e34e0
+//
Paolo Bonzini 2e34e0
+#define BOCHS_DEBUG_PORT_MAGIC    0xE9
Paolo Bonzini 2e34e0
+
Paolo Bonzini 2e34e0
+
Paolo Bonzini 2e34e0
+/**
Paolo Bonzini 2e34e0
+  Helper function to return whether the virtual machine has a debug I/O port.
Paolo Bonzini 2e34e0
+  PlatformDebugLibIoPortFound can call this function directly or cache the
Paolo Bonzini 2e34e0
+  result.
Paolo Bonzini 2e34e0
+
Paolo Bonzini 2e34e0
+  @retval TRUE   if the debug I/O port device was detected.
Paolo Bonzini 2e34e0
+  @retval FALSE  otherwise
Paolo Bonzini 2e34e0
+
Paolo Bonzini 2e34e0
+**/
Paolo Bonzini 2e34e0
+BOOLEAN
Paolo Bonzini 2e34e0
+EFIAPI
Paolo Bonzini 2e34e0
+PlatformDebugLibIoPortDetect (
Paolo Bonzini 2e34e0
+  VOID
Paolo Bonzini 2e34e0
+  );
Paolo Bonzini 2e34e0
+
Paolo Bonzini 2e34e0
+/**
Paolo Bonzini 2e34e0
+  Return whether the virtual machine has a debug I/O port.  DebugLib.c
Paolo Bonzini 2e34e0
+  calls this function instead of PlatformDebugLibIoPortDetect, to allow
Paolo Bonzini 2e34e0
+  caching if possible.
Paolo Bonzini 2e34e0
+
Paolo Bonzini 2e34e0
+  @retval TRUE   if the debug I/O port device was detected.
Paolo Bonzini 2e34e0
+  @retval FALSE  otherwise
Paolo Bonzini 2e34e0
+
Paolo Bonzini 2e34e0
+**/
Paolo Bonzini 2e34e0
+BOOLEAN
Paolo Bonzini 2e34e0
+EFIAPI
Paolo Bonzini 2e34e0
+PlatformDebugLibIoPortFound (
Paolo Bonzini 2e34e0
+  VOID
Paolo Bonzini 2e34e0
+  );
Paolo Bonzini 2e34e0
+
Paolo Bonzini 2e34e0
+#endif
Paolo Bonzini 2e34e0
diff --git a/OvmfPkg/Library/PlatformDebugLibIoPort/DebugLib.c b/OvmfPkg/Library/PlatformDebugLibIoPort/DebugLib.c
Paolo Bonzini 2e34e0
index 5a1c86f2c3..36cde54976 100644
Paolo Bonzini 2e34e0
--- a/OvmfPkg/Library/PlatformDebugLibIoPort/DebugLib.c
Paolo Bonzini 2e34e0
+++ b/OvmfPkg/Library/PlatformDebugLibIoPort/DebugLib.c
Paolo Bonzini 2e34e0
@@ -22,6 +22,7 @@
Paolo Bonzini 2e34e0
 #include <Library/PcdLib.h>
Paolo Bonzini 2e34e0
 #include <Library/BaseMemoryLib.h>
Paolo Bonzini 2e34e0
 #include <Library/DebugPrintErrorLevelLib.h>
Paolo Bonzini 2e34e0
+#include "DebugLibDetect.h"
Paolo Bonzini 2e34e0
 
Paolo Bonzini 2e34e0
 //
Paolo Bonzini 2e34e0
 // Define the maximum debug and assert message length that this library supports
Paolo Bonzini 2e34e0
@@ -61,9 +62,10 @@ DebugPrint (
Paolo Bonzini 2e34e0
   ASSERT (Format != NULL);
Paolo Bonzini 2e34e0
 
Paolo Bonzini 2e34e0
   //
Paolo Bonzini 2e34e0
-  // Check driver debug mask value and global mask
Paolo Bonzini 2e34e0
+  // Check if the global mask disables this message or the device is inactive
Paolo Bonzini 2e34e0
   //
Paolo Bonzini 2e34e0
-  if ((ErrorLevel & GetDebugPrintErrorLevel ()) == 0) {
Paolo Bonzini 2e34e0
+  if ((ErrorLevel & GetDebugPrintErrorLevel ()) == 0 ||
Paolo Bonzini 2e34e0
+      !PlatformDebugLibIoPortFound ()) {
Paolo Bonzini 2e34e0
     return;
Paolo Bonzini 2e34e0
   }
Paolo Bonzini 2e34e0
 
Paolo Bonzini 2e34e0
@@ -120,9 +122,11 @@ DebugAssert (
Paolo Bonzini 2e34e0
              FileName, (UINT64)LineNumber, Description);
Paolo Bonzini 2e34e0
 
Paolo Bonzini 2e34e0
   //
Paolo Bonzini 2e34e0
-  // Send the print string to the debug I/O port
Paolo Bonzini 2e34e0
+  // Send the print string to the debug I/O port, if present
Paolo Bonzini 2e34e0
   //
Paolo Bonzini 2e34e0
-  IoWriteFifo8 (PcdGet16 (PcdDebugIoPort), Length, Buffer);
Paolo Bonzini 2e34e0
+  if (PlatformDebugLibIoPortFound ()) {
Paolo Bonzini 2e34e0
+    IoWriteFifo8 (PcdGet16 (PcdDebugIoPort), Length, Buffer);
Paolo Bonzini 2e34e0
+  }
Paolo Bonzini 2e34e0
 
Paolo Bonzini 2e34e0
   //
Paolo Bonzini 2e34e0
   // Generate a Breakpoint, DeadLoop, or NOP based on PCD settings
Paolo Bonzini 2e34e0
@@ -265,3 +269,19 @@ DebugPrintLevelEnabled (
Paolo Bonzini 2e34e0
 {
Paolo Bonzini 2e34e0
   return (BOOLEAN) ((ErrorLevel & PcdGet32(PcdFixedDebugPrintErrorLevel)) != 0);
Paolo Bonzini 2e34e0
 }
Paolo Bonzini 2e34e0
+
Paolo Bonzini 2e34e0
+/**
Paolo Bonzini 2e34e0
+  Return the result of detecting the debug I/O port device.
Paolo Bonzini 2e34e0
+
Paolo Bonzini 2e34e0
+  @retval TRUE   if the debug I/O port device was detected.
Paolo Bonzini 2e34e0
+  @retval FALSE  otherwise
Paolo Bonzini 2e34e0
+
Paolo Bonzini 2e34e0
+**/
Paolo Bonzini 2e34e0
+BOOLEAN
Paolo Bonzini 2e34e0
+EFIAPI
Paolo Bonzini 2e34e0
+PlatformDebugLibIoPortDetect (
Paolo Bonzini 2e34e0
+  VOID
Paolo Bonzini 2e34e0
+  )
Paolo Bonzini 2e34e0
+{
Paolo Bonzini 2e34e0
+  return IoRead8 (PcdGet16 (PcdDebugIoPort)) == BOCHS_DEBUG_PORT_MAGIC;
Paolo Bonzini 2e34e0
+}
Paolo Bonzini 2e34e0
diff --git a/OvmfPkg/Library/PlatformDebugLibIoPort/DebugLibDetect.c b/OvmfPkg/Library/PlatformDebugLibIoPort/DebugLibDetect.c
Paolo Bonzini 2e34e0
index bad054f286..81c44eece9 100644
Paolo Bonzini 2e34e0
--- a/OvmfPkg/Library/PlatformDebugLibIoPort/DebugLibDetect.c
Paolo Bonzini 2e34e0
+++ b/OvmfPkg/Library/PlatformDebugLibIoPort/DebugLibDetect.c
Paolo Bonzini 2e34e0
@@ -1,6 +1,6 @@
Paolo Bonzini 2e34e0
 /** @file
Paolo Bonzini 2e34e0
-  Constructor code for QEMU debug port library.
Paolo Bonzini 2e34e0
-  Non-SEC instance.
Paolo Bonzini 2e34e0
+  Detection code for QEMU debug port.
Paolo Bonzini 2e34e0
+  Non-SEC instance, caches the result of detection.
Paolo Bonzini 2e34e0
 
Paolo Bonzini 2e34e0
   Copyright (c) 2017, Red Hat, Inc.
Paolo Bonzini 2e34e0
   This program and the accompanying materials
Paolo Bonzini 2e34e0
@@ -14,9 +14,16 @@
Paolo Bonzini 2e34e0
 **/
Paolo Bonzini 2e34e0
 
Paolo Bonzini 2e34e0
 #include <Base.h>
Paolo Bonzini 2e34e0
+#include "DebugLibDetect.h"
Paolo Bonzini 2e34e0
+
Paolo Bonzini 2e34e0
+//
Paolo Bonzini 2e34e0
+// Set to TRUE if the debug I/O port is enabled
Paolo Bonzini 2e34e0
+//
Paolo Bonzini 2e34e0
+STATIC BOOLEAN mDebugIoPortFound = FALSE;
Paolo Bonzini 2e34e0
 
Paolo Bonzini 2e34e0
 /**
Paolo Bonzini 2e34e0
-  This constructor function does not have anything to do.
Paolo Bonzini 2e34e0
+  This constructor function checks if the debug I/O port device is present,
Paolo Bonzini 2e34e0
+  caching the result for later use.
Paolo Bonzini 2e34e0
 
Paolo Bonzini 2e34e0
   @retval RETURN_SUCCESS   The constructor always returns RETURN_SUCCESS.
Paolo Bonzini 2e34e0
 
Paolo Bonzini 2e34e0
@@ -27,5 +34,22 @@ PlatformDebugLibIoPortConstructor (
Paolo Bonzini 2e34e0
   VOID
Paolo Bonzini 2e34e0
   )
Paolo Bonzini 2e34e0
 {
Paolo Bonzini 2e34e0
+  mDebugIoPortFound = PlatformDebugLibIoPortDetect();
Paolo Bonzini 2e34e0
   return RETURN_SUCCESS;
Paolo Bonzini 2e34e0
 }
Paolo Bonzini 2e34e0
+
Paolo Bonzini 2e34e0
+/**
Paolo Bonzini 2e34e0
+  Return the cached result of detecting the debug I/O port device.
Paolo Bonzini 2e34e0
+
Paolo Bonzini 2e34e0
+  @retval TRUE   if the debug I/O port device was detected.
Paolo Bonzini 2e34e0
+  @retval FALSE  otherwise
Paolo Bonzini 2e34e0
+
Paolo Bonzini 2e34e0
+**/
Paolo Bonzini 2e34e0
+BOOLEAN
Paolo Bonzini 2e34e0
+EFIAPI
Paolo Bonzini 2e34e0
+PlatformDebugLibIoPortFound (
Paolo Bonzini 2e34e0
+  VOID
Paolo Bonzini 2e34e0
+  )
Paolo Bonzini 2e34e0
+{
Paolo Bonzini 2e34e0
+  return mDebugIoPortFound;
Paolo Bonzini 2e34e0
+}
Paolo Bonzini 2e34e0
diff --git a/OvmfPkg/Library/PlatformDebugLibIoPort/DebugLibDetectRom.c b/OvmfPkg/Library/PlatformDebugLibIoPort/DebugLibDetectRom.c
Paolo Bonzini 2e34e0
index 83a118a0f7..b950919675 100644
Paolo Bonzini 2e34e0
--- a/OvmfPkg/Library/PlatformDebugLibIoPort/DebugLibDetectRom.c
Paolo Bonzini 2e34e0
+++ b/OvmfPkg/Library/PlatformDebugLibIoPort/DebugLibDetectRom.c
Paolo Bonzini 2e34e0
@@ -1,6 +1,6 @@
Paolo Bonzini 2e34e0
 /** @file
Paolo Bonzini 2e34e0
-  Constructor code for QEMU debug port library.
Paolo Bonzini 2e34e0
-  SEC instance.
Paolo Bonzini 2e34e0
+  Detection code for QEMU debug port.
Paolo Bonzini 2e34e0
+  SEC instance, cannot cache the result of detection.
Paolo Bonzini 2e34e0
 
Paolo Bonzini 2e34e0
   Copyright (c) 2017, Red Hat, Inc.
Paolo Bonzini 2e34e0
   This program and the accompanying materials
Paolo Bonzini 2e34e0
@@ -14,6 +14,7 @@
Paolo Bonzini 2e34e0
 **/
Paolo Bonzini 2e34e0
 
Paolo Bonzini 2e34e0
 #include <Base.h>
Paolo Bonzini 2e34e0
+#include "DebugLibDetect.h"
Paolo Bonzini 2e34e0
 
Paolo Bonzini 2e34e0
 /**
Paolo Bonzini 2e34e0
   This constructor function does not have anything to do.
Paolo Bonzini 2e34e0
@@ -29,3 +30,19 @@ PlatformRomDebugLibIoPortConstructor (
Paolo Bonzini 2e34e0
 {
Paolo Bonzini 2e34e0
   return RETURN_SUCCESS;
Paolo Bonzini 2e34e0
 }
Paolo Bonzini 2e34e0
+
Paolo Bonzini 2e34e0
+/**
Paolo Bonzini 2e34e0
+  Return the result of detecting the debug I/O port device.
Paolo Bonzini 2e34e0
+
Paolo Bonzini 2e34e0
+  @retval TRUE   if the debug I/O port device was detected.
Paolo Bonzini 2e34e0
+  @retval FALSE  otherwise
Paolo Bonzini 2e34e0
+
Paolo Bonzini 2e34e0
+**/
Paolo Bonzini 2e34e0
+BOOLEAN
Paolo Bonzini 2e34e0
+EFIAPI
Paolo Bonzini 2e34e0
+PlatformDebugLibIoPortFound (
Paolo Bonzini 2e34e0
+  VOID
Paolo Bonzini 2e34e0
+  )
Paolo Bonzini 2e34e0
+{
Paolo Bonzini 2e34e0
+  return PlatformDebugLibIoPortDetect ();
Paolo Bonzini 2e34e0
+}
Paolo Bonzini 2e34e0
-- 
Paolo Bonzini 2e34e0
2.14.3
Paolo Bonzini 2e34e0