public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [edk2-devel] [PATCH] OvmfPkg: Don't make APIC MMIO accesses with encryption bit set
@ 2024-04-23 20:59 Roth, Michael via groups.io
  2024-04-24 11:54 ` Gerd Hoffmann
  0 siblings, 1 reply; 7+ messages in thread
From: Roth, Michael via groups.io @ 2024-04-23 20:59 UTC (permalink / raw)
  To: devel
  Cc: Tom Lendacky, Ard Biesheuvel, Gerd Hoffmann, Erdem Aktas,
	Jiewen Yao, Min Xu, Jianyong Wu, Anatol Belski

For the most part, OVMF will clear the encryption bit for MMIO regions,
but there is currently one known exception during SEC when the APIC
base address is accessed via MMIO with the encryption bit set for
SEV-ES/SEV-SNP guests. In the case of SEV-SNP, this requires special
handling on the hypervisor side which may not be available in the
future[1], so make the necessary changes in the SEC-configured page
table to clear the encryption bit for 4K region containing the APIC
base address.

While here, drop special handling for the APIC base address in the
SEV-ES/SNP #VC handler.

[1] https://lore.kernel.org/lkml/20240208002420.34mvemnzrwwsaesw@amd.com/#t

Suggested-by: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Ard Biesheuvel <ardb@kernel.org>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Cc: Erdem Aktas <erdemaktas@google.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Min Xu <min.m.xu@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Jianyong Wu <jianyong.wu@arm.com>
Cc: Anatol Belski <anbelski@linux.microsoft.com>
Signed-off-by: Michael Roth <michael.roth@amd.com>
---
 OvmfPkg/AmdSev/AmdSevX64.fdf                |  5 +-
 OvmfPkg/CloudHv/CloudHvX64.fdf              |  5 +-
 OvmfPkg/Library/CcExitLib/CcExitVcHandler.c | 12 +---
 OvmfPkg/Microvm/MicrovmX64.fdf              |  3 +
 OvmfPkg/OvmfPkg.dec                         |  5 ++
 OvmfPkg/OvmfPkgX64.fdf                      |  5 +-
 OvmfPkg/Sec/AmdSev.c                        | 71 +++++++++++++++++++++
 OvmfPkg/Sec/AmdSev.h                        | 14 ++++
 OvmfPkg/Sec/SecMain.c                       |  1 +
 OvmfPkg/Sec/SecMain.inf                     |  2 +
 10 files changed, 109 insertions(+), 14 deletions(-)

diff --git a/OvmfPkg/AmdSev/AmdSevX64.fdf b/OvmfPkg/AmdSev/AmdSevX64.fdf
index d49555c6c8..595945181c 100644
--- a/OvmfPkg/AmdSev/AmdSevX64.fdf
+++ b/OvmfPkg/AmdSev/AmdSevX64.fdf
@@ -77,7 +77,10 @@ gUefiOvmfPkgTokenSpaceGuid.PcdSevLaunchSecretBase|gUefiOvmfPkgTokenSpaceGuid.Pcd
 0x010C00|0x000400

 gUefiOvmfPkgTokenSpaceGuid.PcdQemuHashTableBase|gUefiOvmfPkgTokenSpaceGuid.PcdQemuHashTableSize

 

-0x011000|0x00F000

+0x011000|0x001000

+gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecApicPageTableBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecApicPageTableSize

+

+0x012000|0x00E000

 gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize

 

 0x020000|0x0E0000

diff --git a/OvmfPkg/CloudHv/CloudHvX64.fdf b/OvmfPkg/CloudHv/CloudHvX64.fdf
index eae3ada191..3e6688b103 100644
--- a/OvmfPkg/CloudHv/CloudHvX64.fdf
+++ b/OvmfPkg/CloudHv/CloudHvX64.fdf
@@ -76,7 +76,10 @@ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCpuidBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCp
 0x00F000|0x001000

 gUefiOvmfPkgTokenSpaceGuid.PcdXenPvhStartOfDayStructPtr|gUefiOvmfPkgTokenSpaceGuid.PcdXenPvhStartOfDayStructPtrSize

 

-0x010000|0x010000

+0x010000|0x001000

+gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecApicPageTableBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecApicPageTableSize

+

+0x011000|0x00F000

 gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize

 

 0x020000|0x0E0000

diff --git a/OvmfPkg/Library/CcExitLib/CcExitVcHandler.c b/OvmfPkg/Library/CcExitLib/CcExitVcHandler.c
index 549375dfed..da8f1e5db9 100644
--- a/OvmfPkg/Library/CcExitLib/CcExitVcHandler.c
+++ b/OvmfPkg/Library/CcExitLib/CcExitVcHandler.c
@@ -98,7 +98,7 @@ UnsupportedExit (
   Validate that the MMIO memory access is not to encrypted memory.

 

   Examine the pagetable entry for the memory specified. MMIO should not be

-  performed against encrypted memory. MMIO to the APIC page is always allowed.

+  performed against encrypted memory.

 

   @param[in] Ghcb           Pointer to the Guest-Hypervisor Communication Block

   @param[in] MemoryAddress  Memory address to validate

@@ -118,16 +118,6 @@ ValidateMmioMemory (
 {

   MEM_ENCRYPT_SEV_ADDRESS_RANGE_STATE  State;

   GHCB_EVENT_INJECTION                 GpEvent;

-  UINTN                                Address;

-

-  //

-  // Allow APIC accesses (which will have the encryption bit set during

-  // SEC and PEI phases).

-  //

-  Address = MemoryAddress & ~(SIZE_4KB - 1);

-  if (Address == GetLocalApicBaseAddress ()) {

-    return 0;

-  }

 

   State = MemEncryptSevGetAddressRangeState (

             0,

diff --git a/OvmfPkg/Microvm/MicrovmX64.fdf b/OvmfPkg/Microvm/MicrovmX64.fdf
index 825bf9f5e4..055e659a35 100644
--- a/OvmfPkg/Microvm/MicrovmX64.fdf
+++ b/OvmfPkg/Microvm/MicrovmX64.fdf
@@ -62,6 +62,9 @@ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfWorkAreaBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvm
 0x00C000|0x001000

 gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupSize

 

+0x00D000|0x001000

+gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecApicPageTableBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecApicPageTableSize

+

 0x010000|0x010000

 gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize

 

diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec
index 2f7bded926..b23219ebd4 100644
--- a/OvmfPkg/OvmfPkg.dec
+++ b/OvmfPkg/OvmfPkg.dec
@@ -277,6 +277,11 @@
   gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupBase|0|UINT32|0x44

   gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupSize|0|UINT32|0x45

 

+  ## Specify the extra page table needed to mark the APIC MMIO range as unencrypted.

+  #  The value should be a multiple of 4KB for each.

+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecApicPageTableBase|0x0|UINT32|0x72

+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecApicPageTableSize|0x0|UINT32|0x73

+

   ## The base address and size of the SEV Launch Secret Area provisioned

   #  after remote attestation.  If this is set in the .fdf, the platform

   #  is responsible for protecting the area from DXE phase overwrites.

diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf
index c2d3cc901e..b6e8f43566 100644
--- a/OvmfPkg/OvmfPkgX64.fdf
+++ b/OvmfPkg/OvmfPkgX64.fdf
@@ -97,7 +97,10 @@ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCpuidBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCp
 0x00F000|0x001000

 gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecSvsmCaaBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecSvsmCaaSize

 

-0x010000|0x010000

+0x010000|0x001000

+gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecApicPageTableBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecApicPageTableSize

+

+0x011000|0x00F000

 gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize

 

 0x020000|0x0E0000

diff --git a/OvmfPkg/Sec/AmdSev.c b/OvmfPkg/Sec/AmdSev.c
index 520b125132..cff2ecbb8c 100644
--- a/OvmfPkg/Sec/AmdSev.c
+++ b/OvmfPkg/Sec/AmdSev.c
@@ -8,11 +8,15 @@
 **/

 

 #include <Library/BaseLib.h>

+#include <Library/CpuLib.h>

 #include <Library/DebugLib.h>

+#include <Library/LocalApicLib.h>

 #include <Library/MemEncryptSevLib.h>

 #include <Library/BaseMemoryLib.h>

 #include <Register/Amd/Ghcb.h>

 #include <Register/Amd/Msr.h>

+#include <IndustryStandard/PageTable.h>

+#include <WorkArea.h>

 

 #include "AmdSev.h"

 

@@ -301,3 +305,70 @@ SecValidateSystemRam (
     MemEncryptSevSnpPreValidateSystemRam (Start, EFI_SIZE_TO_PAGES ((UINTN)(End - Start)));

   }

 }

+

+/**

+  Map known MMIO regions unencrypted if SEV-ES is active.

+

+  During early booting, page table entries default to having the encryption bit

+  set for SEV-ES/SEV-SNP guests. In cases where there is MMIO to an address, the

+  encryption bit should be cleared. Clear it here for any known MMIO accesses

+  during SEC, which is currently just the APIC base address.

+

+**/

+VOID

+SecMapApicBaseUnencrypted (

+  VOID

+  )

+{

+  PAGE_MAP_AND_DIRECTORY_POINTER  *Level4Entry;

+  PAGE_MAP_AND_DIRECTORY_POINTER  *Level3Entry;

+  PAGE_MAP_AND_DIRECTORY_POINTER  *Level2Entry;

+  PAGE_TABLE_4K_ENTRY             *Level1Entry;

+  SEC_SEV_ES_WORK_AREA            *SevEsWorkArea;

+  PHYSICAL_ADDRESS                Cr3;

+  UINT64                          ApicAddress;

+  UINT64                          PgTableMask;

+  UINT32                          Level1Page;

+  UINT64                          Level1Address;

+  UINT64                          Level1Flags;

+  UINTN                           PteIndex;

+

+  if (!SevEsIsEnabled ()) {

+    return;

+  }

+

+  SevEsWorkArea = (SEC_SEV_ES_WORK_AREA *)FixedPcdGet32 (PcdSevEsWorkAreaBase);

+  ApicAddress   = (UINT64)GetLocalApicBaseAddress ();

+  Level1Page    = FixedPcdGet32 (PcdOvmfSecApicPageTableBase);

+  PgTableMask   = PAGING_4K_ADDRESS_MASK_64;

+  PgTableMask  &= ~SevEsWorkArea->EncryptionMask;

+

+  Cr3          = AsmReadCr3 ();

+  Level4Entry  = (VOID *)(UINTN)(Cr3 & PgTableMask);

+  Level4Entry += (UINTN)BitFieldRead64 (ApicAddress, 39, 47);

+

+  Level3Entry  = (VOID *)(UINTN)(Level4Entry->Uint64 & PgTableMask);

+  Level3Entry += (UINTN)BitFieldRead64 (ApicAddress, 30, 38);

+

+  Level2Entry  = (VOID *)(UINTN)(Level3Entry->Uint64 & PgTableMask);

+  Level2Entry += (UINTN)BitFieldRead64 (ApicAddress, 21, 29);

+

+  //

+  // Get memory address including encryption bit

+  //

+  Level1Address = Level2Entry->Uint64 & PgTableMask;

+  Level1Entry   = (VOID *)(UINTN)Level1Page;

+  Level1Flags   = BitFieldRead64 (Level2Entry->Uint64, 0, 11);

+  Level1Flags  &= IA32_PG_P | IA32_PG_RW;

+  for (PteIndex = 0; PteIndex < 512; PteIndex++, Level1Entry++, Level1Address += SIZE_4KB) {

+    Level1Entry->Uint64 = Level1Address | Level1Flags;

+

+    if (Level1Address != ApicAddress) {

+      Level1Entry->Uint64 |= SevEsWorkArea->EncryptionMask;

+    }

+  }

+

+  Level2Entry->Uint64 = (UINT64)(UINTN)Level1Page | IA32_PG_P | IA32_PG_RW;

+

+  CpuFlushTlb ();

+}

diff --git a/OvmfPkg/Sec/AmdSev.h b/OvmfPkg/Sec/AmdSev.h
index f75877096e..c5ab0d5a0b 100644
--- a/OvmfPkg/Sec/AmdSev.h
+++ b/OvmfPkg/Sec/AmdSev.h
@@ -91,4 +91,18 @@ SevSnpIsEnabled (
   VOID

   );

 

+/**

+  Map MMIO regions unencrypted if SEV-ES is active.

+

+  During early booting, page table entries default to having the encryption bit

+  set for SEV-ES/SEV-SNP guests. In cases where there is MMIO to an address, the

+  encryption bit should be cleared. Clear it here for any known MMIO accesses

+  during SEC, which is currently just the APIC base address.

+

+**/

+VOID

+SecMapApicBaseUnencrypted (

+  VOID

+  );

+

 #endif

diff --git a/OvmfPkg/Sec/SecMain.c b/OvmfPkg/Sec/SecMain.c
index a30d4ce09e..60dfa61842 100644
--- a/OvmfPkg/Sec/SecMain.c
+++ b/OvmfPkg/Sec/SecMain.c
@@ -938,6 +938,7 @@ SecCoreStartupWithStack (
   // interrupts before initializing the Debug Agent and the debug timer is

   // enabled.

   //

+  SecMapApicBaseUnencrypted ();

   InitializeApicTimer (0, MAX_UINT32, TRUE, 5);

   DisableApicTimerInterrupt ();

 

diff --git a/OvmfPkg/Sec/SecMain.inf b/OvmfPkg/Sec/SecMain.inf
index dca932a474..7b93b4e7d0 100644
--- a/OvmfPkg/Sec/SecMain.inf
+++ b/OvmfPkg/Sec/SecMain.inf
@@ -83,6 +83,8 @@
   gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupBase

   gUefiOvmfPkgTokenSpaceGuid.PcdTdxAcceptPageSize

   gUefiOvmfPkgTokenSpaceGuid.PcdOvmfWorkAreaBase

+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecApicPageTableBase

+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecApicPageTableSize

 

 [FeaturePcd]

   gUefiOvmfPkgTokenSpaceGuid.PcdSmmSmramRequire

-- 
2.25.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#118176): https://edk2.groups.io/g/devel/message/118176
Mute This Topic: https://groups.io/mt/105698125/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [edk2-devel] [PATCH] OvmfPkg: Don't make APIC MMIO accesses with encryption bit set
  2024-04-23 20:59 [edk2-devel] [PATCH] OvmfPkg: Don't make APIC MMIO accesses with encryption bit set Roth, Michael via groups.io
@ 2024-04-24 11:54 ` Gerd Hoffmann
  2024-04-24 14:05   ` Lendacky, Thomas via groups.io
  2024-04-24 14:50   ` Roth, Michael via groups.io
  0 siblings, 2 replies; 7+ messages in thread
From: Gerd Hoffmann @ 2024-04-24 11:54 UTC (permalink / raw)
  To: Michael Roth
  Cc: devel, Tom Lendacky, Ard Biesheuvel, Erdem Aktas, Jiewen Yao,
	Min Xu, Jianyong Wu, Anatol Belski

On Tue, Apr 23, 2024 at 03:59:58PM -0500, Michael Roth wrote:
> For the most part, OVMF will clear the encryption bit for MMIO regions,
> but there is currently one known exception during SEC when the APIC
> base address is accessed via MMIO with the encryption bit set for
> SEV-ES/SEV-SNP guests.

what exactly accesses the lapic that early?

> +/**
> +  Map known MMIO regions unencrypted if SEV-ES is active.
> +
> +  During early booting, page table entries default to having the encryption bit
> +  set for SEV-ES/SEV-SNP guests. In cases where there is MMIO to an address, the
> +  encryption bit should be cleared. Clear it here for any known MMIO accesses
> +  during SEC, which is currently just the APIC base address.
> +
> +**/
> +VOID
> +SecMapApicBaseUnencrypted (
> +  VOID
> +  )
> +{
> +  PAGE_MAP_AND_DIRECTORY_POINTER  *Level4Entry;
> +  PAGE_MAP_AND_DIRECTORY_POINTER  *Level3Entry;
> +  PAGE_MAP_AND_DIRECTORY_POINTER  *Level2Entry;
> +  PAGE_TABLE_4K_ENTRY             *Level1Entry;
> +  SEC_SEV_ES_WORK_AREA            *SevEsWorkArea;
> +  PHYSICAL_ADDRESS                Cr3;
> +  UINT64                          ApicAddress;
> +  UINT64                          PgTableMask;
> +  UINT32                          Level1Page;
> +  UINT64                          Level1Address;
> +  UINT64                          Level1Flags;
> +  UINTN                           PteIndex;
> +
> +  if (!SevEsIsEnabled ()) {
> +    return;
> +  }

That is incompatible with 5-level paging.  The current reset vector will
never turn on 5-level paging in case SEV is active because we have more
incompatibilities elsewhere (BaseMemEncryptSevLib IIRC).  But still,
it's moving things into the wrong direction ...

Ideally CpuPageTableLib should be used for this.

take care,
  Gerd



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#118211): https://edk2.groups.io/g/devel/message/118211
Mute This Topic: https://groups.io/mt/105698125/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [edk2-devel] [PATCH] OvmfPkg: Don't make APIC MMIO accesses with encryption bit set
  2024-04-24 11:54 ` Gerd Hoffmann
@ 2024-04-24 14:05   ` Lendacky, Thomas via groups.io
  2024-04-24 14:45     ` Gerd Hoffmann
  2024-04-24 14:50   ` Roth, Michael via groups.io
  1 sibling, 1 reply; 7+ messages in thread
From: Lendacky, Thomas via groups.io @ 2024-04-24 14:05 UTC (permalink / raw)
  To: Gerd Hoffmann, Michael Roth
  Cc: devel, Ard Biesheuvel, Erdem Aktas, Jiewen Yao, Min Xu,
	Jianyong Wu, Anatol Belski

On 4/24/24 06:54, Gerd Hoffmann wrote:
> On Tue, Apr 23, 2024 at 03:59:58PM -0500, Michael Roth wrote:
>> For the most part, OVMF will clear the encryption bit for MMIO regions,
>> but there is currently one known exception during SEC when the APIC
>> base address is accessed via MMIO with the encryption bit set for
>> SEV-ES/SEV-SNP guests.
> 
> what exactly accesses the lapic that early?

InitializedApicTimer() in OvmfPkg/Sec/SecMain.c

> 
>> +/**
>> +  Map known MMIO regions unencrypted if SEV-ES is active.
>> +
>> +  During early booting, page table entries default to having the encryption bit
>> +  set for SEV-ES/SEV-SNP guests. In cases where there is MMIO to an address, the
>> +  encryption bit should be cleared. Clear it here for any known MMIO accesses
>> +  during SEC, which is currently just the APIC base address.
>> +
>> +**/
>> +VOID
>> +SecMapApicBaseUnencrypted (
>> +  VOID
>> +  )
>> +{
>> +  PAGE_MAP_AND_DIRECTORY_POINTER  *Level4Entry;
>> +  PAGE_MAP_AND_DIRECTORY_POINTER  *Level3Entry;
>> +  PAGE_MAP_AND_DIRECTORY_POINTER  *Level2Entry;
>> +  PAGE_TABLE_4K_ENTRY             *Level1Entry;
>> +  SEC_SEV_ES_WORK_AREA            *SevEsWorkArea;
>> +  PHYSICAL_ADDRESS                Cr3;
>> +  UINT64                          ApicAddress;
>> +  UINT64                          PgTableMask;
>> +  UINT32                          Level1Page;
>> +  UINT64                          Level1Address;
>> +  UINT64                          Level1Flags;
>> +  UINTN                           PteIndex;
>> +
>> +  if (!SevEsIsEnabled ()) {
>> +    return;
>> +  }
> 
> That is incompatible with 5-level paging.  The current reset vector will
> never turn on 5-level paging in case SEV is active because we have more
> incompatibilities elsewhere (BaseMemEncryptSevLib IIRC).  But still,
> it's moving things into the wrong direction ...

Agreed. SEV needs to clean up the pagetable manipulation in general in 
order to support 5-level paging and remove redundant code. That will be 
a patch series in itself.

But without this modification, the SNP support no longer works with the 
KVM/gmem support that will be upstream. This change gets OVMF SNP 
support working again.

> 
> Ideally CpuPageTableLib should be used for this.

CpuPageTableLib will need to be modified in order for it to be used at 
this (Sec) stage. In order to work in Sec - either the caller will have 
to supply a list of pages that can be used if pagetable entries need to 
be allocated for splits or new entries or by providing some kind of SEC 
pagetable allocation pool.

So it will take significant work to get SEV support updated to using 
CpuPageTableLib and that's why with this single patch we can get OVMF 
SNP support working again.

Thanks,
Tom

> 
> take care,
>    Gerd
> 


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#118215): https://edk2.groups.io/g/devel/message/118215
Mute This Topic: https://groups.io/mt/105698125/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [edk2-devel] [PATCH] OvmfPkg: Don't make APIC MMIO accesses with encryption bit set
  2024-04-24 14:05   ` Lendacky, Thomas via groups.io
@ 2024-04-24 14:45     ` Gerd Hoffmann
  2024-04-24 16:38       ` Lendacky, Thomas via groups.io
  0 siblings, 1 reply; 7+ messages in thread
From: Gerd Hoffmann @ 2024-04-24 14:45 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: Michael Roth, devel, Ard Biesheuvel, Erdem Aktas, Jiewen Yao,
	Min Xu, Jianyong Wu, Anatol Belski

  Hi,

> > Ideally CpuPageTableLib should be used for this.
> 
> CpuPageTableLib will need to be modified in order for it to be used at this
> (Sec) stage. In order to work in Sec - either the caller will have to supply
> a list of pages that can be used if pagetable entries need to be allocated
> for splits

I don't think so.  PageTableMap() has the 'Buffer' parameter for passing
in page table memory.  And the patch reserves a page in MEMFD.  Handing
that page over to PageTableMap() should work just fine, no?

take care,
  Gerd



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#118216): https://edk2.groups.io/g/devel/message/118216
Mute This Topic: https://groups.io/mt/105698125/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [edk2-devel] [PATCH] OvmfPkg: Don't make APIC MMIO accesses with encryption bit set
  2024-04-24 11:54 ` Gerd Hoffmann
  2024-04-24 14:05   ` Lendacky, Thomas via groups.io
@ 2024-04-24 14:50   ` Roth, Michael via groups.io
  2024-04-24 16:09     ` Gerd Hoffmann
  1 sibling, 1 reply; 7+ messages in thread
From: Roth, Michael via groups.io @ 2024-04-24 14:50 UTC (permalink / raw)
  To: Gerd Hoffmann
  Cc: devel, Tom Lendacky, Ard Biesheuvel, Erdem Aktas, Jiewen Yao,
	Min Xu, Jianyong Wu, Anatol Belski

On Wed, Apr 24, 2024 at 01:54:01PM +0200, Gerd Hoffmann wrote:
> On Tue, Apr 23, 2024 at 03:59:58PM -0500, Michael Roth wrote:
> > For the most part, OVMF will clear the encryption bit for MMIO regions,
> > but there is currently one known exception during SEC when the APIC
> > base address is accessed via MMIO with the encryption bit set for
> > SEV-ES/SEV-SNP guests.
> 
> what exactly accesses the lapic that early?

This looks to be for InitializeDebugAgent() to set up a timer to handle the
debug console.

> 
> > +/**
> > +  Map known MMIO regions unencrypted if SEV-ES is active.
> > +
> > +  During early booting, page table entries default to having the encryption bit
> > +  set for SEV-ES/SEV-SNP guests. In cases where there is MMIO to an address, the
> > +  encryption bit should be cleared. Clear it here for any known MMIO accesses
> > +  during SEC, which is currently just the APIC base address.
> > +
> > +**/
> > +VOID
> > +SecMapApicBaseUnencrypted (
> > +  VOID
> > +  )
> > +{
> > +  PAGE_MAP_AND_DIRECTORY_POINTER  *Level4Entry;
> > +  PAGE_MAP_AND_DIRECTORY_POINTER  *Level3Entry;
> > +  PAGE_MAP_AND_DIRECTORY_POINTER  *Level2Entry;
> > +  PAGE_TABLE_4K_ENTRY             *Level1Entry;
> > +  SEC_SEV_ES_WORK_AREA            *SevEsWorkArea;
> > +  PHYSICAL_ADDRESS                Cr3;
> > +  UINT64                          ApicAddress;
> > +  UINT64                          PgTableMask;
> > +  UINT32                          Level1Page;
> > +  UINT64                          Level1Address;
> > +  UINT64                          Level1Flags;
> > +  UINTN                           PteIndex;
> > +
> > +  if (!SevEsIsEnabled ()) {
> > +    return;
> > +  }
> 
> That is incompatible with 5-level paging.  The current reset vector will
> never turn on 5-level paging in case SEV is active because we have more
> incompatibilities elsewhere (BaseMemEncryptSevLib IIRC).  But still,
> it's moving things into the wrong direction ...

Tom had mentioned this eventuality and we discussed it to an extent. AIUI
once we make that switch then most of this function could be replaced with
a call into the library to handle the splitting, and similar re-work would
need to be done for handling splitting the area for the GHCB page which is
also currently done with direct page table manipulation. So while it
does sort of move in the wrong direction, I don't think it would
significantly complicate things as far as making that transition.

> 
> Ideally CpuPageTableLib should be used for this.

What's the outlook for moving CpuPageTableLib before the next OVMF release?
My concern is that once SNP KVM support goes upstream (which is currently
looking to be within kernel 6.10 timeframe), SNP guest support in OVMF will
be completely broken without a fix like this for APIC MMIO accesses.

One thing to maybe get ahead of is the fact that splitting pages with
5-level paging will require having 2 pages reserved for GHCB instead of
the 1 we have currently, and 2 pages reserved for APIC range instead of
the 1 proposed by this patch (since we'd need to not only split a 2MB PTE
to 4KB, but the upper 1GB PTE to 2MB).

Do we know enough about what that sort of allocation/reserve logic would
look to start modifying PcdOvmfSecPageTablesBase,
PcdOvmfSecGhcbPageTableBase, and PcdOvmfSecApicPageTableBase to start
preping for such a change?

If so we could maybe take steps toward that to ease the transition. But
either way if the move to CpuPageTableLib is a ways out then I think we
need a fix before then.

-Mike

> 
> take care,
>   Gerd
> 


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#118217): https://edk2.groups.io/g/devel/message/118217
Mute This Topic: https://groups.io/mt/105698125/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [edk2-devel] [PATCH] OvmfPkg: Don't make APIC MMIO accesses with encryption bit set
  2024-04-24 14:50   ` Roth, Michael via groups.io
@ 2024-04-24 16:09     ` Gerd Hoffmann
  0 siblings, 0 replies; 7+ messages in thread
From: Gerd Hoffmann @ 2024-04-24 16:09 UTC (permalink / raw)
  To: Michael Roth
  Cc: devel, Tom Lendacky, Ard Biesheuvel, Erdem Aktas, Jiewen Yao,
	Min Xu, Jianyong Wu, Anatol Belski

  Hi,

> > That is incompatible with 5-level paging.  The current reset vector will
> > never turn on 5-level paging in case SEV is active because we have more
> > incompatibilities elsewhere (BaseMemEncryptSevLib IIRC).  But still,
> > it's moving things into the wrong direction ...
> 
> Tom had mentioned this eventuality and we discussed it to an extent. AIUI
> once we make that switch then most of this function could be replaced with
> a call into the library to handle the splitting, and similar re-work would
> need to be done for handling splitting the area for the GHCB page which is
> also currently done with direct page table manipulation. So while it
> does sort of move in the wrong direction, I don't think it would
> significantly complicate things as far as making that transition.

GHCB page is handled with asm code in the reset vector and I'm not
sure it can be moved out there as the page will be needed quite early
in firmware boot.

> > Ideally CpuPageTableLib should be used for this.
> 
> What's the outlook for moving CpuPageTableLib before the next OVMF release?
> My concern is that once SNP KVM support goes upstream (which is currently
> looking to be within kernel 6.10 timeframe), SNP guest support in OVMF will
> be completely broken without a fix like this for APIC MMIO accesses.

Fixing this surely should be done before the may stable tag.  If
CpuPageTableLib changes are needed, then going the CpuPageTableLib
route is a bit risky indeed.

I don't think we need CpuPageTableLib changes though.  At least not for
the reason (page table memory allocation) mentioned by Tom.  The patch
reserves a page in MEMFD, and simply giving that page to CpuPageTableLib
should work just fine.

> One thing to maybe get ahead of is the fact that splitting pages with
> 5-level paging will require having 2 pages reserved for GHCB instead of
> the 1 we have currently, and 2 pages reserved for APIC range instead of
> the 1 proposed by this patch (since we'd need to not only split a 2MB PTE
> to 4KB, but the upper 1GB PTE to 2MB).

The first GB is covered by 2M pages even with 5-level paging, exactly to
simplify the GHCB setup.

For APIC + 5-level paging we'll indeed need a second page table page.

> Do we know enough about what that sort of allocation/reserve logic would
> look to start modifying PcdOvmfSecPageTablesBase,
> PcdOvmfSecGhcbPageTableBase, and PcdOvmfSecApicPageTableBase to start
> preping for such a change?

Well, CpuPageTableLib simply expects getting a buffer passed in with
page table memory.  So allocation is fully in the hands of the caller.
It's also possible to call the library without buffer and get back the
number of pages which will be needed to apply the changes, so the caller
can allocate exactly what will be needed.  That would not be needed here
given we need a big enough pool of pages in MEMFD anyway.

take care,
  Gerd



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#118218): https://edk2.groups.io/g/devel/message/118218
Mute This Topic: https://groups.io/mt/105698125/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [edk2-devel] [PATCH] OvmfPkg: Don't make APIC MMIO accesses with encryption bit set
  2024-04-24 14:45     ` Gerd Hoffmann
@ 2024-04-24 16:38       ` Lendacky, Thomas via groups.io
  0 siblings, 0 replies; 7+ messages in thread
From: Lendacky, Thomas via groups.io @ 2024-04-24 16:38 UTC (permalink / raw)
  To: Gerd Hoffmann
  Cc: Michael Roth, devel, Ard Biesheuvel, Erdem Aktas, Jiewen Yao,
	Min Xu, Jianyong Wu, Anatol Belski

On 4/24/24 09:45, Gerd Hoffmann wrote:
>    Hi,
> 
>>> Ideally CpuPageTableLib should be used for this.
>>
>> CpuPageTableLib will need to be modified in order for it to be used at this
>> (Sec) stage. In order to work in Sec - either the caller will have to supply
>> a list of pages that can be used if pagetable entries need to be allocated
>> for splits
> 
> I don't think so.  PageTableMap() has the 'Buffer' parameter for passing
> in page table memory.  And the patch reserves a page in MEMFD.  Handing
> that page over to PageTableMap() should work just fine, no?

Oh, I thought the library allocated the pages, my bad. Mike and I will 
take a look at that.

Thanks,
Tom

> 
> take care,
>    Gerd
> 


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#118223): https://edk2.groups.io/g/devel/message/118223
Mute This Topic: https://groups.io/mt/105698125/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2024-04-24 16:38 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-04-23 20:59 [edk2-devel] [PATCH] OvmfPkg: Don't make APIC MMIO accesses with encryption bit set Roth, Michael via groups.io
2024-04-24 11:54 ` Gerd Hoffmann
2024-04-24 14:05   ` Lendacky, Thomas via groups.io
2024-04-24 14:45     ` Gerd Hoffmann
2024-04-24 16:38       ` Lendacky, Thomas via groups.io
2024-04-24 14:50   ` Roth, Michael via groups.io
2024-04-24 16:09     ` Gerd Hoffmann

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox