qemu-ppc
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] spapr: Add capability for Secure (PEF) VMs


From: David Gibson
Subject: [PATCH] spapr: Add capability for Secure (PEF) VMs
Date: Fri, 1 May 2020 16:02:49 +1000

Recent POWER9 machines have a system called PEF (Protected Execution
Framework) which uses a small ultravisor to allow guests to run in a
way that they can't be eavesdropped by the hypervisor.  The effect is
roughly similar to AMD SEV, although the mechanisms are quite
different.

Most of the work of this is done between the guest, KVM and the
ultravisor, with little need for involvement by qemu.  However qemu
does need to tell KVM to allow secure VMs.

Because the availability of secure mode is a guest visible difference
which depends on havint the right hardware and firmware, we don't
enable this by default.  In order to run a secure guest you need to
set the new 'cap-allow-secure-guest' flag on.  Note that this just
*allows* secure guests, the architecture of PEF is such that the guest
still needs to talk to the ultravisor to enter secure mode, so we
don't know if the guest actually is secure at machine creation time.

Signed-off-by: David Gibson <address@hidden>
---
 hw/ppc/spapr_caps.c    | 32 ++++++++++++++++++++++++++++++++
 include/hw/ppc/spapr.h |  4 +++-
 target/ppc/kvm.c       | 11 +++++++++++
 target/ppc/kvm_ppc.h   | 25 +++++++++++++++++++++++++
 4 files changed, 71 insertions(+), 1 deletion(-)

diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c
index eb54f94227..d37992b389 100644
--- a/hw/ppc/spapr_caps.c
+++ b/hw/ppc/spapr_caps.c
@@ -525,6 +525,29 @@ static void cap_fwnmi_apply(SpaprMachineState *spapr, 
uint8_t val,
     }
 }
 
+static void cap_allow_secure_guest_apply(SpaprMachineState *spapr,
+                                         uint8_t val, Error **errp)
+{
+    if (!val) {
+        /* capability disabled by default */
+        return;
+    }
+
+    if (tcg_enabled()) {
+        error_setg(errp,
+                   "No Secure VM support in tcg,"
+                   " try appending -machine cap-allow-secure-guest=off");
+    } else if (kvm_enabled()) {
+        if (!kvmppc_has_cap_secure_guest()) {
+            error_setg(errp,
+"KVM implementation does not support Secure VMs (is an ultravisor running?)");
+        } else if (kvmppc_set_cap_secure_guest(val) < 0) {
+                error_setg(errp,
+"Error enabling cap-allow-secure-guest with KVM, try 
cap-allow-secure-guest=off");
+        }
+    }
+}
+
 SpaprCapabilityInfo capability_table[SPAPR_CAP_NUM] = {
     [SPAPR_CAP_HTM] = {
         .name = "htm",
@@ -633,6 +656,15 @@ SpaprCapabilityInfo capability_table[SPAPR_CAP_NUM] = {
         .type = "bool",
         .apply = cap_fwnmi_apply,
     },
+    [SPAPR_CAP_ALLOW_SECURE_GUEST] = {
+        .name = "allow-secure-guest",
+        .description = "Allows guest to enter Ultravisor secure mode",
+        .index = SPAPR_CAP_ALLOW_SECURE_GUEST,
+        .get = spapr_cap_get_bool,
+        .set = spapr_cap_set_bool,
+        .type = "bool",
+        .apply = cap_allow_secure_guest_apply,
+    },
 };
 
 static SpaprCapabilities default_caps_with_cpu(SpaprMachineState *spapr,
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index e579eaf28c..eef773c0cc 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -81,8 +81,10 @@ typedef enum {
 #define SPAPR_CAP_CCF_ASSIST            0x09
 /* Implements PAPR FWNMI option */
 #define SPAPR_CAP_FWNMI                 0x0A
+/* Allows guest to enter secure mode with ultravisor */
+#define SPAPR_CAP_ALLOW_SECURE_GUEST    0x0B
 /* Num Caps */
-#define SPAPR_CAP_NUM                   (SPAPR_CAP_FWNMI + 1)
+#define SPAPR_CAP_NUM                   (SPAPR_CAP_ALLOW_SECURE_GUEST + 1)
 
 /*
  * Capability Values
diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c
index 2692f76130..1e68a11745 100644
--- a/target/ppc/kvm.c
+++ b/target/ppc/kvm.c
@@ -2539,6 +2539,17 @@ int kvmppc_enable_cap_large_decr(PowerPCCPU *cpu, int 
enable)
     return 0;
 }
 
+bool kvmppc_has_cap_secure_guest(void)
+{
+    return !!kvm_check_extension(kvm_state, KVM_CAP_PPC_SECURE_GUEST);
+}
+
+int kvmppc_set_cap_secure_guest(int enable)
+{
+    return kvm_vm_enable_cap(kvm_state, KVM_CAP_PPC_SECURE_GUEST, 0, enable);
+}
+
+
 PowerPCCPUClass *kvm_ppc_get_host_cpu_class(void)
 {
     uint32_t host_pvr = mfpvr();
diff --git a/target/ppc/kvm_ppc.h b/target/ppc/kvm_ppc.h
index fcaf745516..4bd2f7e255 100644
--- a/target/ppc/kvm_ppc.h
+++ b/target/ppc/kvm_ppc.h
@@ -72,6 +72,8 @@ bool kvmppc_has_cap_nested_kvm_hv(void);
 int kvmppc_set_cap_nested_kvm_hv(int enable);
 int kvmppc_get_cap_large_decr(void);
 int kvmppc_enable_cap_large_decr(PowerPCCPU *cpu, int enable);
+bool kvmppc_has_cap_secure_vm(void);
+int kvmppc_set_cap_secure_vm(int enable);
 int kvmppc_enable_hwrng(void);
 int kvmppc_put_books_sregs(PowerPCCPU *cpu);
 PowerPCCPUClass *kvm_ppc_get_host_cpu_class(void);
@@ -87,6 +89,9 @@ void kvmppc_set_reg_tb_offset(PowerPCCPU *cpu, int64_t 
tb_offset);
 
 int kvm_handle_nmi(PowerPCCPU *cpu, struct kvm_run *run);
 
+bool kvmppc_has_cap_secure_guest(void);
+int kvmppc_set_cap_secure_guest(int enable);
+
 #else
 
 static inline uint32_t kvmppc_get_tbfreq(void)
@@ -231,6 +236,16 @@ static inline void kvmppc_set_reg_tb_offset(PowerPCCPU 
*cpu, int64_t tb_offset)
 {
 }
 
+static inline bool kvmppc_has_cap_secure_guest(void)
+{
+    return false;
+}
+
+static inline int kvmppc_set_cap_secure_guest(int enable)
+{
+    g_assert_not_reached();
+}
+
 #ifndef CONFIG_USER_ONLY
 static inline bool kvmppc_spapr_use_multitce(void)
 {
@@ -386,6 +401,16 @@ static inline int kvmppc_enable_cap_large_decr(PowerPCCPU 
*cpu, int enable)
     return -1;
 }
 
+static inline bool kvmppc_has_cap_secure_vm(void)
+{
+    return false;
+}
+
+static inline int kvmppc_set_cap_secure_vm(int enable)
+{
+    return -1;
+}
+
 static inline int kvmppc_enable_hwrng(void)
 {
     return -1;
-- 
2.26.2




reply via email to

[Prev in Thread] Current Thread [Next in Thread]