[PATCH v6 1/6] OvmfPkg/BaseMemEncryptLib: Detect SEV live migration feature.


Ashish Kalra
 

From: Ashish Kalra <ashish.kalra@amd.com>

Add support to check if we are running inside KVM HVM and
KVM HVM supports SEV Live Migration feature.

Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
Signed-off-by: Ashish Kalra <ashish.kalra@amd.com>
---
OvmfPkg/Include/Library/MemEncryptSevLib.h | 27 ++++++++++
OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLibInternal.c | 39 +++++++++++++++
OvmfPkg/Library/BaseMemEncryptSevLib/PeiDxeMemEncryptSevLibInternal.c | 52 ++++++++++++++++++++
OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLibInternal.c | 39 +++++++++++++++
OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLibInternal.c | 18 +++++++
5 files changed, 175 insertions(+)

diff --git a/OvmfPkg/Include/Library/MemEncryptSevLib.h b/OvmfPkg/Include/Library/MemEncryptSevLib.h
index 76d06c206c..59f694fb8a 100644
--- a/OvmfPkg/Include/Library/MemEncryptSevLib.h
+++ b/OvmfPkg/Include/Library/MemEncryptSevLib.h
@@ -90,6 +90,18 @@ MemEncryptSevIsEnabled (
VOID
);

+/**
+ Returns a boolean to indicate whether SEV live migration is enabled.
+
+ @retval TRUE SEV live migration is enabled
+ @retval FALSE SEV live migration is not enabled
+**/
+BOOLEAN
+EFIAPI
+MemEncryptSevLiveMigrationIsEnabled (
+ VOID
+ );
+
/**
This function clears memory encryption bit for the memory region specified by
BaseAddress and NumPages from the current page table context.
@@ -222,4 +234,19 @@ MemEncryptSevClearMmioPageEncMask (
IN UINTN NumPages
);

+#define KVM_FEATURE_MIGRATION_CONTROL BIT17
+
+/**
+ Figures out if we are running inside KVM HVM and
+ KVM HVM supports SEV Live Migration feature.
+
+ @retval TRUE SEV live migration is supported.
+ @retval FALSE SEV live migration is not supported.
+**/
+BOOLEAN
+EFIAPI
+KvmDetectSevLiveMigrationFeature(
+ VOID
+ );
+
#endif // _MEM_ENCRYPT_SEV_LIB_H_
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLibInternal.c b/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLibInternal.c
index 2816f859a0..ead754cd7b 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLibInternal.c
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLibInternal.c
@@ -20,6 +20,8 @@
STATIC BOOLEAN mSevStatus = FALSE;
STATIC BOOLEAN mSevEsStatus = FALSE;
STATIC BOOLEAN mSevStatusChecked = FALSE;
+STATIC BOOLEAN mSevLiveMigrationStatus = FALSE;
+STATIC BOOLEAN mSevLiveMigrationStatusChecked = FALSE;

STATIC UINT64 mSevEncryptionMask = 0;
STATIC BOOLEAN mSevEncryptionMaskSaved = FALSE;
@@ -87,6 +89,24 @@ InternalMemEncryptSevStatus (
mSevStatusChecked = TRUE;
}

+/**
+ Figures out if we are running inside KVM HVM and
+ KVM HVM supports SEV Live Migration feature.
+**/
+STATIC
+VOID
+EFIAPI
+InternalDetectSevLiveMigrationFeature(
+ VOID
+ )
+{
+ if (KvmDetectSevLiveMigrationFeature()) {
+ mSevLiveMigrationStatus = TRUE;
+ }
+
+ mSevLiveMigrationStatusChecked = TRUE;
+}
+
/**
Returns a boolean to indicate whether SEV-ES is enabled.

@@ -125,6 +145,25 @@ MemEncryptSevIsEnabled (
return mSevStatus;
}

+/**
+ Returns a boolean to indicate whether SEV live migration is enabled.
+
+ @retval TRUE SEV live migration is enabled
+ @retval FALSE SEV live migration is not enabled
+**/
+BOOLEAN
+EFIAPI
+MemEncryptSevLiveMigrationIsEnabled (
+ VOID
+ )
+{
+ if (!mSevLiveMigrationStatusChecked) {
+ InternalDetectSevLiveMigrationFeature ();
+ }
+
+ return mSevLiveMigrationStatus;
+}
+
/**
Returns the SEV encryption mask.

diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/PeiDxeMemEncryptSevLibInternal.c b/OvmfPkg/Library/BaseMemEncryptSevLib/PeiDxeMemEncryptSevLibInternal.c
index b4a9f464e2..d7fc973134 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/PeiDxeMemEncryptSevLibInternal.c
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/PeiDxeMemEncryptSevLibInternal.c
@@ -61,3 +61,55 @@ MemEncryptSevLocateInitialSmramSaveStateMapPages (

return RETURN_SUCCESS;
}
+
+/**
+ Figures out if we are running inside KVM HVM and
+ KVM HVM supports SEV Live Migration feature.
+
+ @retval TRUE SEV live migration is supported.
+ @retval FALSE SEV live migration is not supported.
+**/
+BOOLEAN
+EFIAPI
+KvmDetectSevLiveMigrationFeature(
+ VOID
+ )
+{
+ CHAR8 Signature[13];
+ UINT32 mKvmLeaf;
+ UINT32 RegEax, RegEbx, RegEcx, RegEdx;
+
+ Signature[12] = '\0';
+ for (mKvmLeaf = 0x40000000; mKvmLeaf < 0x40010000; mKvmLeaf += 0x100) {
+ AsmCpuid (
+ mKvmLeaf,
+ NULL,
+ (UINT32 *) &Signature[0],
+ (UINT32 *) &Signature[4],
+ (UINT32 *) &Signature[8]);
+
+ if (AsciiStrCmp (Signature, "KVMKVMKVM") == 0) {
+ DEBUG ((
+ DEBUG_INFO,
+ "%a: KVM Detected, signature = %a\n",
+ __FUNCTION__,
+ Signature
+ ));
+
+ RegEax = mKvmLeaf + 1;
+ RegEcx = 0;
+ AsmCpuid (mKvmLeaf + 1, &RegEax, &RegEbx, &RegEcx, &RegEdx);
+ if ((RegEax & KVM_FEATURE_MIGRATION_CONTROL) != 0) {
+ DEBUG ((
+ DEBUG_INFO,
+ "%a: SEV Live Migration feature supported\n",
+ __FUNCTION__
+ ));
+
+ return TRUE;
+ }
+ }
+ }
+
+ return FALSE;
+}
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLibInternal.c b/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLibInternal.c
index e2fd109d12..9db6c2ef71 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLibInternal.c
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLibInternal.c
@@ -20,6 +20,8 @@
STATIC BOOLEAN mSevStatus = FALSE;
STATIC BOOLEAN mSevEsStatus = FALSE;
STATIC BOOLEAN mSevStatusChecked = FALSE;
+STATIC BOOLEAN mSevLiveMigrationStatus = FALSE;
+STATIC BOOLEAN mSevLiveMigrationStatusChecked = FALSE;

STATIC UINT64 mSevEncryptionMask = 0;
STATIC BOOLEAN mSevEncryptionMaskSaved = FALSE;
@@ -87,6 +89,24 @@ InternalMemEncryptSevStatus (
mSevStatusChecked = TRUE;
}

+/**
+ Figures out if we are running inside KVM HVM and
+ KVM HVM supports SEV Live Migration feature.
+**/
+STATIC
+VOID
+EFIAPI
+InternalDetectSevLiveMigrationFeature(
+ VOID
+ )
+{
+ if (KvmDetectSevLiveMigrationFeature()) {
+ mSevLiveMigrationStatus = TRUE;
+ }
+
+ mSevLiveMigrationStatusChecked = TRUE;
+}
+
/**
Returns a boolean to indicate whether SEV-ES is enabled.

@@ -125,6 +145,25 @@ MemEncryptSevIsEnabled (
return mSevStatus;
}

+/**
+ Returns a boolean to indicate whether SEV live migration is enabled.
+
+ @retval TRUE SEV live migration is enabled
+ @retval FALSE SEV live migration is not enabled
+**/
+BOOLEAN
+EFIAPI
+MemEncryptSevLiveMigrationIsEnabled (
+ VOID
+ )
+{
+ if (!mSevLiveMigrationStatusChecked) {
+ InternalDetectSevLiveMigrationFeature ();
+ }
+
+ return mSevLiveMigrationStatus;
+}
+
/**
Returns the SEV encryption mask.

diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLibInternal.c b/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLibInternal.c
index 56d8f3f318..d9f7befcd2 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLibInternal.c
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLibInternal.c
@@ -100,6 +100,24 @@ MemEncryptSevIsEnabled (
return Msr.Bits.SevBit ? TRUE : FALSE;
}

+/**
+ Returns a boolean to indicate whether SEV live migration is enabled.
+
+ @retval TRUE SEV live migration is enabled
+ @retval FALSE SEV live migration is not enabled
+**/
+BOOLEAN
+EFIAPI
+MemEncryptSevLiveMigrationIsEnabled (
+ VOID
+ )
+{
+ //
+ // Not used in SEC phase.
+ //
+ return FALSE;
+}
+
/**
Returns the SEV encryption mask.

--
2.17.1


Lendacky, Thomas
 

On 8/2/21 7:31 AM, Ashish Kalra wrote:
From: Ashish Kalra <ashish.kalra@amd.com>

Add support to check if we are running inside KVM HVM and
KVM HVM supports SEV Live Migration feature.

Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
Signed-off-by: Ashish Kalra <ashish.kalra@amd.com>
---
OvmfPkg/Include/Library/MemEncryptSevLib.h | 27 ++++++++++
OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLibInternal.c | 39 +++++++++++++++
OvmfPkg/Library/BaseMemEncryptSevLib/PeiDxeMemEncryptSevLibInternal.c | 52 ++++++++++++++++++++
OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLibInternal.c | 39 +++++++++++++++
OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLibInternal.c | 18 +++++++
5 files changed, 175 insertions(+)

diff --git a/OvmfPkg/Include/Library/MemEncryptSevLib.h b/OvmfPkg/Include/Library/MemEncryptSevLib.h
index 76d06c206c..59f694fb8a 100644
--- a/OvmfPkg/Include/Library/MemEncryptSevLib.h
+++ b/OvmfPkg/Include/Library/MemEncryptSevLib.h
@@ -90,6 +90,18 @@ MemEncryptSevIsEnabled (
VOID
);

+/**
+ Returns a boolean to indicate whether SEV live migration is enabled.
+
+ @retval TRUE SEV live migration is enabled
+ @retval FALSE SEV live migration is not enabled
+**/
+BOOLEAN
+EFIAPI
+MemEncryptSevLiveMigrationIsEnabled (
+ VOID
+ );
+
/**
This function clears memory encryption bit for the memory region specified by
BaseAddress and NumPages from the current page table context.
@@ -222,4 +234,19 @@ MemEncryptSevClearMmioPageEncMask (
IN UINTN NumPages
);

+#define KVM_FEATURE_MIGRATION_CONTROL BIT17
+
+/**
+ Figures out if we are running inside KVM HVM and
+ KVM HVM supports SEV Live Migration feature.
+
+ @retval TRUE SEV live migration is supported.
+ @retval FALSE SEV live migration is not supported.
+**/
+BOOLEAN
+EFIAPI
+KvmDetectSevLiveMigrationFeature(
+ VOID
+ );
+
I don't think KvmDetectSevLiveMigrationFeature() should be in
OvmfPkg/Include/Library/MemEncryptSevLib.h since it isn't called except as
a helper by InternalDetectSevLiveMigrationFeature(). You should probably
create a new PeiDxeMemEncryptSevLibInternal.h header file for that
function that lives in OvmfPkg/Library/BaseMemEncryptSevLib.

#endif // _MEM_ENCRYPT_SEV_LIB_H_
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLibInternal.c b/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLibInternal.c
index 2816f859a0..ead754cd7b 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLibInternal.c
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLibInternal.c
@@ -20,6 +20,8 @@
STATIC BOOLEAN mSevStatus = FALSE;
STATIC BOOLEAN mSevEsStatus = FALSE;
STATIC BOOLEAN mSevStatusChecked = FALSE;
+STATIC BOOLEAN mSevLiveMigrationStatus = FALSE;
+STATIC BOOLEAN mSevLiveMigrationStatusChecked = FALSE;

STATIC UINT64 mSevEncryptionMask = 0;
STATIC BOOLEAN mSevEncryptionMaskSaved = FALSE;
@@ -87,6 +89,24 @@ InternalMemEncryptSevStatus (
mSevStatusChecked = TRUE;
}

+/**
+ Figures out if we are running inside KVM HVM and
+ KVM HVM supports SEV Live Migration feature.
+**/
+STATIC
+VOID
+EFIAPI
+InternalDetectSevLiveMigrationFeature(
+ VOID
+ )
+{
+ if (KvmDetectSevLiveMigrationFeature()) {
Add a space before the "()"

+ mSevLiveMigrationStatus = TRUE;
+ }
+
+ mSevLiveMigrationStatusChecked = TRUE;
+}
+
/**
Returns a boolean to indicate whether SEV-ES is enabled.

@@ -125,6 +145,25 @@ MemEncryptSevIsEnabled (
return mSevStatus;
}

+/**
+ Returns a boolean to indicate whether SEV live migration is enabled.
+
+ @retval TRUE SEV live migration is enabled
+ @retval FALSE SEV live migration is not enabled
+**/
+BOOLEAN
+EFIAPI
+MemEncryptSevLiveMigrationIsEnabled (
+ VOID
+ )
+{
+ if (!mSevLiveMigrationStatusChecked) {
+ InternalDetectSevLiveMigrationFeature ();
+ }
+
+ return mSevLiveMigrationStatus;
+}
+
/**
Returns the SEV encryption mask.

diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/PeiDxeMemEncryptSevLibInternal.c b/OvmfPkg/Library/BaseMemEncryptSevLib/PeiDxeMemEncryptSevLibInternal.c
index b4a9f464e2..d7fc973134 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/PeiDxeMemEncryptSevLibInternal.c
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/PeiDxeMemEncryptSevLibInternal.c
@@ -61,3 +61,55 @@ MemEncryptSevLocateInitialSmramSaveStateMapPages (

return RETURN_SUCCESS;
}
+
+/**
+ Figures out if we are running inside KVM HVM and
+ KVM HVM supports SEV Live Migration feature.
+
+ @retval TRUE SEV live migration is supported.
+ @retval FALSE SEV live migration is not supported.
+**/
+BOOLEAN
+EFIAPI
+KvmDetectSevLiveMigrationFeature(
Add a space before the "("

+ VOID
+ )
+{
+ CHAR8 Signature[13];
+ UINT32 mKvmLeaf;
+ UINT32 RegEax, RegEbx, RegEcx, RegEdx;
Coding style requires these to be four separate declarations.

+
+ Signature[12] = '\0';
+ for (mKvmLeaf = 0x40000000; mKvmLeaf < 0x40010000; mKvmLeaf += 0x100) {
I still really don't understand the need for the CPUID loop. KVM only ever
programs CPUID function 0x40000000, right?

+ AsmCpuid (
+ mKvmLeaf,
+ NULL,
+ (UINT32 *) &Signature[0],
+ (UINT32 *) &Signature[4],
+ (UINT32 *) &Signature[8]);
+
+ if (AsciiStrCmp (Signature, "KVMKVMKVM") == 0) {
+ DEBUG ((
+ DEBUG_INFO,
+ "%a: KVM Detected, signature = %a\n",
+ __FUNCTION__,
+ Signature
+ ));
+
+ RegEax = mKvmLeaf + 1;
+ RegEcx = 0;
+ AsmCpuid (mKvmLeaf + 1, &RegEax, &RegEbx, &RegEcx, &RegEdx);
+ if ((RegEax & KVM_FEATURE_MIGRATION_CONTROL) != 0) {
+ DEBUG ((
+ DEBUG_INFO,
+ "%a: SEV Live Migration feature supported\n",
+ __FUNCTION__
+ ));
+
+ return TRUE;
+ }
+ }
+ }
+
+ return FALSE;
+}
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLibInternal.c b/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLibInternal.c
index e2fd109d12..9db6c2ef71 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLibInternal.c
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLibInternal.c
@@ -20,6 +20,8 @@
STATIC BOOLEAN mSevStatus = FALSE;
STATIC BOOLEAN mSevEsStatus = FALSE;
STATIC BOOLEAN mSevStatusChecked = FALSE;
+STATIC BOOLEAN mSevLiveMigrationStatus = FALSE;
+STATIC BOOLEAN mSevLiveMigrationStatusChecked = FALSE;

STATIC UINT64 mSevEncryptionMask = 0;
STATIC BOOLEAN mSevEncryptionMaskSaved = FALSE;
@@ -87,6 +89,24 @@ InternalMemEncryptSevStatus (
mSevStatusChecked = TRUE;
}

+/**
+ Figures out if we are running inside KVM HVM and
+ KVM HVM supports SEV Live Migration feature.
+**/
+STATIC
+VOID
+EFIAPI
+InternalDetectSevLiveMigrationFeature(
Add a space before "("

+ VOID
+ )
+{
+ if (KvmDetectSevLiveMigrationFeature()) {
Add a space before "()"

Thanks,
Tom

+ mSevLiveMigrationStatus = TRUE;
+ }
+
+ mSevLiveMigrationStatusChecked = TRUE;
+}
+
/**
Returns a boolean to indicate whether SEV-ES is enabled.

@@ -125,6 +145,25 @@ MemEncryptSevIsEnabled (
return mSevStatus;
}

+/**
+ Returns a boolean to indicate whether SEV live migration is enabled.
+
+ @retval TRUE SEV live migration is enabled
+ @retval FALSE SEV live migration is not enabled
+**/
+BOOLEAN
+EFIAPI
+MemEncryptSevLiveMigrationIsEnabled (
+ VOID
+ )
+{
+ if (!mSevLiveMigrationStatusChecked) {
+ InternalDetectSevLiveMigrationFeature ();
+ }
+
+ return mSevLiveMigrationStatus;
+}
+
/**
Returns the SEV encryption mask.

diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLibInternal.c b/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLibInternal.c
index 56d8f3f318..d9f7befcd2 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLibInternal.c
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLibInternal.c
@@ -100,6 +100,24 @@ MemEncryptSevIsEnabled (
return Msr.Bits.SevBit ? TRUE : FALSE;
}

+/**
+ Returns a boolean to indicate whether SEV live migration is enabled.
+
+ @retval TRUE SEV live migration is enabled
+ @retval FALSE SEV live migration is not enabled
+**/
+BOOLEAN
+EFIAPI
+MemEncryptSevLiveMigrationIsEnabled (
+ VOID
+ )
+{
+ //
+ // Not used in SEC phase.
+ //
+ return FALSE;
+}
+
/**
Returns the SEV encryption mask.


Ashish Kalra
 

Hello Tom,

On Mon, Aug 09, 2021 at 08:41:27AM -0500, Tom Lendacky wrote:
On 8/2/21 7:31 AM, Ashish Kalra wrote:
+
+ Signature[12] = '\0';
+ for (mKvmLeaf = 0x40000000; mKvmLeaf < 0x40010000; mKvmLeaf += 0x100) {
I still really don't understand the need for the CPUID loop. KVM only ever
programs CPUID function 0x40000000, right?
Yes KVM only programs CPUID function 0x40000000, as do other hypervisors
like Hyper-V. Also mentioned that leaf 0x40000000 is the Hypervisor
CPUID leaf range and vendor ID signature in MSFT Hypervisor Interface
document.

But looking at linux kernel code for the same functionality :

static inline uint32_t hypervisor_cpuid_base(const char *sig, uint32_t leaves)
{
uint32_t base, eax, signature[3];

for (base = 0x40000000; base < 0x40010000; base += 0x100) {
cpuid(base, &eax, &signature[0], &signature[1], &signature[2]);

if (!memcmp(sig, signature, 12)
...
...


And the Xen detection code in OVMF:

for (mXenLeaf = 0x40000000; mXenLeaf < 0x40010000; mXenLeaf += 0x100) {
AsmCpuid (mXenLeaf,
NULL,
(UINT32 *) &Signature[0],
(UINT32 *) &Signature[4],
(UINT32 *) &Signature[8]);

if (!AsciiStrCmp ((CHAR8 *) Signature, "XenVMMXenVMM")) {
return TRUE;

The above functions are doing a loop-test.

The kernel patch also mentions about the loop-test :
https://lore.kernel.org/kvm/51FF1E26.6010707@redhat.com/t/

This patch introduce hypervisor_cpuid_base() which loop test the hypervisor
existence function until the signature match and check the number of leaves if
required. This could be used by Xen/KVM guest to detect the existence of
hypervisor.

The above patches/functions don't have any additonal documentation for
why are they doing the loop-test ?

I don't want to miss any functionality, hence i am reusing the same
loop-test code.

Thanks,
Ashish

+ AsmCpuid (
+ mKvmLeaf,
+ NULL,
+ (UINT32 *) &Signature[0],
+ (UINT32 *) &Signature[4],
+ (UINT32 *) &Signature[8]);
+
+ if (AsciiStrCmp (Signature, "KVMKVMKVM") == 0) {
+ DEBUG ((
+ DEBUG_INFO,
+ "%a: KVM Detected, signature = %a\n",
+ __FUNCTION__,
+ Signature
+ ));
+
+ RegEax = mKvmLeaf + 1;
+ RegEcx = 0;
+ AsmCpuid (mKvmLeaf + 1, &RegEax, &RegEbx, &RegEcx, &RegEdx);
+ if ((RegEax & KVM_FEATURE_MIGRATION_CONTROL) != 0) {
+ DEBUG ((
+ DEBUG_INFO,
+ "%a: SEV Live Migration feature supported\n",
+ __FUNCTION__
+ ));
+
+ return TRUE;
+ }
+ }
+ }
+
+ return FALSE;
+}


Gerd Hoffmann
 

Hi,

I still really don't understand the need for the CPUID loop. KVM only ever
programs CPUID function 0x40000000, right?
Nope. When you enable hyper-v emulation features you'll go find the kvm
cpuid @ 0x40000000 and the hyper-v cpuid @ 0x40000100 (or the other way
around, not sure).

take care,
Gerd


Lendacky, Thomas
 

On 8/10/21 1:05 AM, Gerd Hoffmann wrote:
Hi,

I still really don't understand the need for the CPUID loop. KVM only ever
programs CPUID function 0x40000000, right?
Nope. When you enable hyper-v emulation features you'll go find the kvm
cpuid @ 0x40000000 and the hyper-v cpuid @ 0x40000100 (or the other way
around, not sure).
Ah, thanks. I just saw the comment above get_out_of_range_cpuid_entry() in
arch/x86/kvm/cpuid.c where HyperV would get the 0x40000000-0x400000ff
range and KVM would then get the 0x40000100-0x400001ff range (basically
each hypervisor class gets their own 0x100 range).

Thanks,
Tom


take care,
Gerd