Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(RHEL-56144) Backport confidential virt. improvements #41

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 45 additions & 1 deletion man/systemd-detect-virt.xml
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@
</thead>
<tbody>
<row>
<entry valign="top" morerows="16">VM</entry>
<entry valign="top" morerows="17">VM</entry>
<entry><varname>qemu</varname></entry>
<entry>QEMU software virtualization, without KVM</entry>
</row>
Expand Down Expand Up @@ -217,6 +217,50 @@
WSL is categorized as a container for practical purposes.
Multiple WSL environments share the same kernel and services
should generally behave like when being run in a container.</para>

<para>When executed with <option>--cvm</option>, instead of
printing the virtualization technology, it will display the
confidential virtual machine technology, if any. The
following technologies are currently identified:</para>

<table>
<title>Known confidential virtualization technologies</title>
<tgroup cols='2' align='left' colsep='1' rowsep='1'>
<colspec colname="id" />
<colspec colname="product" />
<thead>
<row>
<entry>Arch</entry>
<entry>ID</entry>
<entry>Technology</entry>
</row>
</thead>
<tbody>
<row>
<entry valign="top" morerows="3">x86_64</entry>
<entry><varname>sev</varname></entry>
<entry>AMD Secure Encrypted Virtualization</entry>
</row>
<row>
<entry><varname>sev-es</varname></entry>
<entry>AMD Secure Encrypted Virtualization - Encrypted State</entry>
</row>
<row>
<entry><varname>sev-snp</varname></entry>
<entry>AMD Secure Encrypted Virtualization - Secure Nested Paging</entry>
</row>
<row>
<entry><varname>tdx</varname></entry>
<entry>Intel Trust Domain Extensions</entry>
</row>
<row>
<entry>s390x</entry>
<entry><varname>protvirt</varname></entry>
<entry>IBM Protected Virtualization (Secure Execution)</entry>
</row>
</tbody>
</tgroup>
</table>
</refsect1>

<refsect1>
Expand Down
66 changes: 47 additions & 19 deletions src/basic/confidential-virt.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "confidential-virt-fundamental.h"
#include "confidential-virt.h"
#include "fd-util.h"
#include "fileio.h"
#include "missing_threads.h"
#include "string-table.h"
#include "utf8.h"
Expand Down Expand Up @@ -76,7 +77,7 @@ static uint64_t msr(uint64_t index) {
return ret;
}

static bool detect_hyperv_sev(void) {
static bool detect_hyperv_cvm(uint32_t isoltype) {
uint32_t eax, ebx, ecx, edx, feat;
char sig[13] = {};

Expand All @@ -100,7 +101,7 @@ static bool detect_hyperv_sev(void) {
ebx = ecx = edx = 0;
cpuid(&eax, &ebx, &ecx, &edx);

if ((ebx & CPUID_HYPERV_ISOLATION_TYPE_MASK) == CPUID_HYPERV_ISOLATION_TYPE_SNP)
if ((ebx & CPUID_HYPERV_ISOLATION_TYPE_MASK) == isoltype)
return true;
}

Expand Down Expand Up @@ -133,7 +134,7 @@ static ConfidentialVirtualization detect_sev(void) {
if (!(eax & EAX_SEV)) {
log_debug("No sev in CPUID, trying hyperv CPUID");

if (detect_hyperv_sev())
if (detect_hyperv_cvm(CPUID_HYPERV_ISOLATION_TYPE_SNP))
return CONFIDENTIAL_VIRTUALIZATION_SEV_SNP;

log_debug("No hyperv CPUID");
Expand Down Expand Up @@ -171,6 +172,11 @@ static ConfidentialVirtualization detect_tdx(void) {
if (memcmp(sig, CPUID_SIG_INTEL_TDX, sizeof(sig)) == 0)
return CONFIDENTIAL_VIRTUALIZATION_TDX;

log_debug("No tdx in CPUID, trying hyperv CPUID");

if (detect_hyperv_cvm(CPUID_HYPERV_ISOLATION_TYPE_TDX))
return CONFIDENTIAL_VIRTUALIZATION_TDX;

return CONFIDENTIAL_VIRTUALIZATION_NONE;
}

Expand All @@ -189,40 +195,62 @@ static bool detect_hypervisor(void) {
return is_hv;
}

ConfidentialVirtualization detect_confidential_virtualization(void) {
static thread_local ConfidentialVirtualization cached_found = _CONFIDENTIAL_VIRTUALIZATION_INVALID;
static ConfidentialVirtualization detect_confidential_virtualization_impl(void) {
char sig[13] = {};
ConfidentialVirtualization cv = CONFIDENTIAL_VIRTUALIZATION_NONE;

if (cached_found >= 0)
return cached_found;

/* Skip everything on bare metal */
if (detect_hypervisor()) {
cpuid_leaf(0, sig, true);

if (memcmp(sig, CPUID_SIG_AMD, sizeof(sig)) == 0)
cv = detect_sev();
return detect_sev();
else if (memcmp(sig, CPUID_SIG_INTEL, sizeof(sig)) == 0)
cv = detect_tdx();
return detect_tdx();
}

cached_found = cv;
return cv;
return CONFIDENTIAL_VIRTUALIZATION_NONE;
}
#elif defined(__s390x__)
static ConfidentialVirtualization detect_confidential_virtualization_impl(void) {
_cleanup_free_ char *s = NULL;
size_t readsize;
int r;

r = read_full_virtual_file("/sys/firmware/uv/prot_virt_guest", &s, &readsize);
if (r < 0) {
log_debug_errno(r, "Unable to read /sys/firmware/uv/prot_virt_guest: %m");
return CONFIDENTIAL_VIRTUALIZATION_NONE;
}

if (readsize >= 1 && s[0] == '1')
return CONFIDENTIAL_VIRTUALIZATION_PROTVIRT;

return CONFIDENTIAL_VIRTUALIZATION_NONE;
}

#else /* ! x86_64 */
ConfidentialVirtualization detect_confidential_virtualization(void) {
static ConfidentialVirtualization detect_confidential_virtualization_impl(void) {
log_debug("No confidential virtualization detection on this architecture");
return CONFIDENTIAL_VIRTUALIZATION_NONE;
}
#endif /* ! x86_64 */

ConfidentialVirtualization detect_confidential_virtualization(void) {
static thread_local ConfidentialVirtualization cached_found = _CONFIDENTIAL_VIRTUALIZATION_INVALID;

if (cached_found == _CONFIDENTIAL_VIRTUALIZATION_INVALID)
cached_found = detect_confidential_virtualization_impl();

return cached_found;
}

static const char *const confidential_virtualization_table[_CONFIDENTIAL_VIRTUALIZATION_MAX] = {
[CONFIDENTIAL_VIRTUALIZATION_NONE] = "none",
[CONFIDENTIAL_VIRTUALIZATION_SEV] = "sev",
[CONFIDENTIAL_VIRTUALIZATION_SEV_ES] = "sev-es",
[CONFIDENTIAL_VIRTUALIZATION_SEV_SNP] = "sev-snp",
[CONFIDENTIAL_VIRTUALIZATION_TDX] = "tdx",
[CONFIDENTIAL_VIRTUALIZATION_NONE] = "none",
[CONFIDENTIAL_VIRTUALIZATION_SEV] = "sev",
[CONFIDENTIAL_VIRTUALIZATION_SEV_ES] = "sev-es",
[CONFIDENTIAL_VIRTUALIZATION_SEV_SNP] = "sev-snp",
[CONFIDENTIAL_VIRTUALIZATION_TDX] = "tdx",
[CONFIDENTIAL_VIRTUALIZATION_PROTVIRT] = "protvirt",
};

DEFINE_STRING_TABLE_LOOKUP(confidential_virtualization, ConfidentialVirtualization);
1 change: 1 addition & 0 deletions src/basic/confidential-virt.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ typedef enum ConfidentialVirtualization {
CONFIDENTIAL_VIRTUALIZATION_SEV_ES,
CONFIDENTIAL_VIRTUALIZATION_SEV_SNP,
CONFIDENTIAL_VIRTUALIZATION_TDX,
CONFIDENTIAL_VIRTUALIZATION_PROTVIRT,

_CONFIDENTIAL_VIRTUALIZATION_MAX,
_CONFIDENTIAL_VIRTUALIZATION_INVALID = -EINVAL,
Expand Down
9 changes: 6 additions & 3 deletions src/boot/efi/vmm.c
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,7 @@ static uint64_t msr(uint32_t index) {
return val;
}

static bool detect_hyperv_sev(void) {
static bool detect_hyperv_cvm(uint32_t isoltype) {
uint32_t eax, ebx, ecx, edx, feat;
char sig[13] = {};

Expand All @@ -354,7 +354,7 @@ static bool detect_hyperv_sev(void) {
if (ebx & CPUID_HYPERV_ISOLATION && !(ebx & CPUID_HYPERV_CPU_MANAGEMENT)) {
__cpuid(CPUID_HYPERV_ISOLATION_CONFIG, eax, ebx, ecx, edx);

if ((ebx & CPUID_HYPERV_ISOLATION_TYPE_MASK) == CPUID_HYPERV_ISOLATION_TYPE_SNP)
if ((ebx & CPUID_HYPERV_ISOLATION_TYPE_MASK) == isoltype)
return true;
}

Expand All @@ -379,7 +379,7 @@ static bool detect_sev(void) {
* specific CPUID checks.
*/
if (!(eax & EAX_SEV))
return detect_hyperv_sev();
return detect_hyperv_cvm(CPUID_HYPERV_ISOLATION_TYPE_SNP);

msrval = msr(MSR_AMD64_SEV);

Expand All @@ -403,6 +403,9 @@ static bool detect_tdx(void) {
if (memcmp(sig, CPUID_SIG_INTEL_TDX, sizeof(sig)) == 0)
return true;

if (detect_hyperv_cvm(CPUID_HYPERV_ISOLATION_TYPE_TDX))
return true;

return false;
}
#endif /* ! __i386__ && ! __x86_64__ */
Expand Down
1 change: 1 addition & 0 deletions src/fundamental/confidential-virt-fundamental.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@

#define CPUID_HYPERV_ISOLATION_TYPE_MASK UINT32_C(0xf)
#define CPUID_HYPERV_ISOLATION_TYPE_SNP 2
#define CPUID_HYPERV_ISOLATION_TYPE_TDX 3

#define EAX_SEV (UINT32_C(1) << 1)
#define MSR_SEV (UINT64_C(1) << 0)
Expand Down