From patchwork Fri Jun 19 02:05:55 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Gibson X-Patchwork-Id: 280041 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.5 required=3.0 tests=DKIM_INVALID,DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9D487C433E0 for ; Fri, 19 Jun 2020 02:07:44 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 67C4720888 for ; Fri, 19 Jun 2020 02:07:44 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=gibson.dropbear.id.au header.i=@gibson.dropbear.id.au header.b="Mm7MtGBT" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 67C4720888 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=gibson.dropbear.id.au Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:40152 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jm6RT-0005HJ-JA for qemu-devel@archiver.kernel.org; Thu, 18 Jun 2020 22:07:43 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:41872) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jm6Q7-0002zP-9F; Thu, 18 Jun 2020 22:06:19 -0400 Received: from bilbo.ozlabs.org ([2401:3900:2:1::2]:34221 helo=ozlabs.org) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jm6Q3-0000nO-81; Thu, 18 Jun 2020 22:06:18 -0400 Received: by ozlabs.org (Postfix, from userid 1007) id 49p2GS2q6qz9sRk; Fri, 19 Jun 2020 12:06:08 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gibson.dropbear.id.au; s=201602; t=1592532368; bh=XEsRFDuyA9etU74BIO7+DftC/mG9MemHlS+RfUcqgWk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Mm7MtGBTWXfvAn9KUWFu1PSbCvov+j8g3pczK4fahDCG5dPcWIQ1oFVn0sbM+L3vj MPaMFJSiWnV5XQhIhAaAtRldSguNquShBVzHTuPrM8BPyOyf5r7IPIE3cRfUgGqRDb DbZiCB7nl8UBg2P0E5OoVjo4T8jHjyW6d11Q+ta8= From: David Gibson To: qemu-devel@nongnu.org, brijesh.singh@amd.com, pair@us.ibm.com, pbonzini@redhat.com, dgilbert@redhat.com, frankja@linux.ibm.com Subject: [PATCH v3 2/9] host trust limitation: Handle memory encryption via interface Date: Fri, 19 Jun 2020 12:05:55 +1000 Message-Id: <20200619020602.118306-3-david@gibson.dropbear.id.au> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200619020602.118306-1-david@gibson.dropbear.id.au> References: <20200619020602.118306-1-david@gibson.dropbear.id.au> MIME-Version: 1.0 Received-SPF: pass client-ip=2401:3900:2:1::2; envelope-from=dgibson@ozlabs.org; helo=ozlabs.org X-detected-operating-system: by eggs.gnu.org: No matching host in p0f cache. That's all we know. X-Spam_score_int: -9 X-Spam_score: -1.0 X-Spam_bar: - X-Spam_report: (-1.0 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, HEADER_FROM_DIFFERENT_DOMAINS=1, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, URIBL_BLOCKED=0.001 autolearn=_AUTOLEARN X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Eduardo Habkost , kvm@vger.kernel.org, mst@redhat.com, Richard Henderson , cohuck@redhat.com, david@redhat.com, mdroth@linux.vnet.ibm.com, pasic@linux.ibm.com, qemu-s390x@nongnu.org, qemu-ppc@nongnu.org, David Gibson , Richard Henderson Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" At the moment AMD SEV sets a special function pointer, plus an opaque handle in KVMState to let things know how to encrypt guest memory. Now that we have a QOM interface for handling things related to host trust limitation, use a QOM method on that interface, rather than a bare function pointer for this. Signed-off-by: David Gibson Reviewed-by: Richard Henderson --- accel/kvm/kvm-all.c | 38 ++++++--- accel/kvm/sev-stub.c | 7 +- include/exec/host-trust-limitation.h | 3 + include/sysemu/sev.h | 4 +- target/i386/sev.c | 117 +++++++++++---------------- 5 files changed, 79 insertions(+), 90 deletions(-) diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c index f24d7da783..1e43e27f45 100644 --- a/accel/kvm/kvm-all.c +++ b/accel/kvm/kvm-all.c @@ -39,12 +39,12 @@ #include "qemu/main-loop.h" #include "trace.h" #include "hw/irq.h" -#include "sysemu/sev.h" #include "sysemu/balloon.h" #include "qapi/visitor.h" #include "qapi/qapi-types-common.h" #include "qapi/qapi-visit-common.h" #include "sysemu/reset.h" +#include "exec/host-trust-limitation.h" #include "hw/boards.h" @@ -118,9 +118,8 @@ struct KVMState KVMMemoryListener memory_listener; QLIST_HEAD(, KVMParkedVcpu) kvm_parked_vcpus; - /* memory encryption */ - void *memcrypt_handle; - int (*memcrypt_encrypt_data)(void *handle, uint8_t *ptr, uint64_t len); + /* host trust limitation (e.g. by guest memory encryption) */ + HostTrustLimitation *htl; /* For "info mtree -f" to tell if an MR is registered in KVM */ int nr_as; @@ -222,7 +221,7 @@ int kvm_get_max_memslots(void) bool kvm_memcrypt_enabled(void) { - if (kvm_state && kvm_state->memcrypt_handle) { + if (kvm_state && kvm_state->htl) { return true; } @@ -231,10 +230,12 @@ bool kvm_memcrypt_enabled(void) int kvm_memcrypt_encrypt_data(uint8_t *ptr, uint64_t len) { - if (kvm_state->memcrypt_handle && - kvm_state->memcrypt_encrypt_data) { - return kvm_state->memcrypt_encrypt_data(kvm_state->memcrypt_handle, - ptr, len); + HostTrustLimitation *htl = kvm_state->htl; + + if (htl) { + HostTrustLimitationClass *htlc = HOST_TRUST_LIMITATION_GET_CLASS(htl); + + return htlc->encrypt_data(htl, ptr, len); } return 1; @@ -2180,13 +2181,24 @@ static int kvm_init(MachineState *ms) * encryption context. */ if (ms->memory_encryption) { - kvm_state->memcrypt_handle = sev_guest_init(ms->memory_encryption); - if (!kvm_state->memcrypt_handle) { + Object *obj = object_resolve_path_component(object_get_objects_root(), + ms->memory_encryption); + + if (object_dynamic_cast(obj, TYPE_HOST_TRUST_LIMITATION)) { + HostTrustLimitation *htl = HOST_TRUST_LIMITATION(obj); + HostTrustLimitationClass *htlc + = HOST_TRUST_LIMITATION_GET_CLASS(htl); + + ret = htlc->kvm_init(htl); + if (ret < 0) { + goto err; + } + + kvm_state->htl = htl; + } else { ret = -1; goto err; } - - kvm_state->memcrypt_encrypt_data = sev_encrypt_data; } ret = kvm_arch_init(ms, s); diff --git a/accel/kvm/sev-stub.c b/accel/kvm/sev-stub.c index 4f97452585..9c7c897593 100644 --- a/accel/kvm/sev-stub.c +++ b/accel/kvm/sev-stub.c @@ -15,12 +15,7 @@ #include "qemu-common.h" #include "sysemu/sev.h" -int sev_encrypt_data(void *handle, uint8_t *ptr, uint64_t len) -{ - abort(); -} - -void *sev_guest_init(const char *id) +HostTrustLimitation *sev_guest_init(const char *id) { return NULL; } diff --git a/include/exec/host-trust-limitation.h b/include/exec/host-trust-limitation.h index 03887b1be1..a19f12ae14 100644 --- a/include/exec/host-trust-limitation.h +++ b/include/exec/host-trust-limitation.h @@ -28,6 +28,9 @@ typedef struct HostTrustLimitationClass { InterfaceClass parent; + + int (*kvm_init)(HostTrustLimitation *); + int (*encrypt_data)(HostTrustLimitation *, uint8_t *, uint64_t); } HostTrustLimitationClass; #endif /* QEMU_HOST_TRUST_LIMITATION_H */ diff --git a/include/sysemu/sev.h b/include/sysemu/sev.h index 98c1ec8d38..a4aee6a87d 100644 --- a/include/sysemu/sev.h +++ b/include/sysemu/sev.h @@ -16,6 +16,6 @@ #include "sysemu/kvm.h" -void *sev_guest_init(const char *id); -int sev_encrypt_data(void *handle, uint8_t *ptr, uint64_t len); +HostTrustLimitation *sev_guest_init(const char *id); + #endif diff --git a/target/i386/sev.c b/target/i386/sev.c index d273174ad3..052a05d15a 100644 --- a/target/i386/sev.c +++ b/target/i386/sev.c @@ -28,6 +28,7 @@ #include "sysemu/runstate.h" #include "trace.h" #include "migration/blocker.h" +#include "exec/host-trust-limitation.h" #define TYPE_SEV_GUEST "sev-guest" #define SEV_GUEST(obj) \ @@ -281,26 +282,6 @@ sev_guest_set_sev_device(Object *obj, const char *value, Error **errp) sev->sev_device = g_strdup(value); } -static void -sev_guest_class_init(ObjectClass *oc, void *data) -{ - object_class_property_add_str(oc, "sev-device", - sev_guest_get_sev_device, - sev_guest_set_sev_device); - object_class_property_set_description(oc, "sev-device", - "SEV device to use"); - object_class_property_add_str(oc, "dh-cert-file", - sev_guest_get_dh_cert_file, - sev_guest_set_dh_cert_file); - object_class_property_set_description(oc, "dh-cert-file", - "guest owners DH certificate (encoded with base64)"); - object_class_property_add_str(oc, "session-file", - sev_guest_get_session_file, - sev_guest_set_session_file); - object_class_property_set_description(oc, "session-file", - "guest owners session parameters (encoded with base64)"); -} - static void sev_guest_instance_init(Object *obj) { @@ -319,40 +300,6 @@ sev_guest_instance_init(Object *obj) OBJ_PROP_FLAG_READWRITE); } -/* sev guest info */ -static const TypeInfo sev_guest_info = { - .parent = TYPE_OBJECT, - .name = TYPE_SEV_GUEST, - .instance_size = sizeof(SevGuestState), - .instance_finalize = sev_guest_finalize, - .class_init = sev_guest_class_init, - .instance_init = sev_guest_instance_init, - .interfaces = (InterfaceInfo[]) { - { TYPE_USER_CREATABLE }, - { } - } -}; - -static SevGuestState * -lookup_sev_guest_info(const char *id) -{ - Object *obj; - SevGuestState *info; - - obj = object_resolve_path_component(object_get_objects_root(), id); - if (!obj) { - return NULL; - } - - info = (SevGuestState *) - object_dynamic_cast(obj, TYPE_SEV_GUEST); - if (!info) { - return NULL; - } - - return info; -} - bool sev_enabled(void) { @@ -670,23 +617,15 @@ sev_vm_state_change(void *opaque, int running, RunState state) } } -void * -sev_guest_init(const char *id) +static int sev_kvm_init(HostTrustLimitation *htl) { - SevGuestState *sev; + SevGuestState *sev = SEV_GUEST(htl); char *devname; int ret, fw_error; uint32_t ebx; uint32_t host_cbitpos; struct sev_user_data_status status = {}; - sev = lookup_sev_guest_info(id); - if (!sev) { - error_report("%s: '%s' is not a valid '%s' object", - __func__, id, TYPE_SEV_GUEST); - goto err; - } - sev_guest = sev; sev->state = SEV_STATE_UNINIT; @@ -748,16 +687,16 @@ sev_guest_init(const char *id) qemu_add_machine_init_done_notifier(&sev_machine_done_notify); qemu_add_vm_change_state_handler(sev_vm_state_change, sev); - return sev; + return 0; err: sev_guest = NULL; - return NULL; + return -1; } -int -sev_encrypt_data(void *handle, uint8_t *ptr, uint64_t len) +static int +sev_encrypt_data(HostTrustLimitation *opaque, uint8_t *ptr, uint64_t len) { - SevGuestState *sev = handle; + SevGuestState *sev = SEV_GUEST(opaque); assert(sev); @@ -769,6 +708,46 @@ sev_encrypt_data(void *handle, uint8_t *ptr, uint64_t len) return 0; } +static void +sev_guest_class_init(ObjectClass *oc, void *data) +{ + HostTrustLimitationClass *htlc = HOST_TRUST_LIMITATION_CLASS(oc); + + object_class_property_add_str(oc, "sev-device", + sev_guest_get_sev_device, + sev_guest_set_sev_device); + object_class_property_set_description(oc, "sev-device", + "SEV device to use"); + object_class_property_add_str(oc, "dh-cert-file", + sev_guest_get_dh_cert_file, + sev_guest_set_dh_cert_file); + object_class_property_set_description(oc, "dh-cert-file", + "guest owners DH certificate (encoded with base64)"); + object_class_property_add_str(oc, "session-file", + sev_guest_get_session_file, + sev_guest_set_session_file); + object_class_property_set_description(oc, "session-file", + "guest owners session parameters (encoded with base64)"); + + htlc->kvm_init = sev_kvm_init; + htlc->encrypt_data = sev_encrypt_data; +} + +/* sev guest info */ +static const TypeInfo sev_guest_info = { + .parent = TYPE_OBJECT, + .name = TYPE_SEV_GUEST, + .instance_size = sizeof(SevGuestState), + .instance_finalize = sev_guest_finalize, + .class_init = sev_guest_class_init, + .instance_init = sev_guest_instance_init, + .interfaces = (InterfaceInfo[]) { + { TYPE_HOST_TRUST_LIMITATION }, + { TYPE_USER_CREATABLE }, + { } + } +}; + static void sev_register_types(void) { From patchwork Fri Jun 19 02:05:59 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: David Gibson X-Patchwork-Id: 280038 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.5 required=3.0 tests=DKIM_INVALID,DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 90923C433E0 for ; Fri, 19 Jun 2020 02:11:01 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 4998320773 for ; Fri, 19 Jun 2020 02:11:01 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=gibson.dropbear.id.au header.i=@gibson.dropbear.id.au header.b="i+8S4y1n" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 4998320773 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=gibson.dropbear.id.au Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:55882 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jm6Ue-0003oc-HL for qemu-devel@archiver.kernel.org; Thu, 18 Jun 2020 22:11:00 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:41940) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jm6QC-0003BE-6o; Thu, 18 Jun 2020 22:06:24 -0400 Received: from bilbo.ozlabs.org ([203.11.71.1]:60065 helo=ozlabs.org) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jm6Q9-0000p4-DC; Thu, 18 Jun 2020 22:06:23 -0400 Received: by ozlabs.org (Postfix, from userid 1007) id 49p2GT35rgz9sT8; Fri, 19 Jun 2020 12:06:08 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gibson.dropbear.id.au; s=201602; t=1592532369; bh=rKuvzP3I0zndPbCxEWAF/KYSFkgJfgyIKqNEdtPx2Aw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=i+8S4y1njyzLLozEwk54jAInltcAB7xtL2/XwnGGBQFN7qOQAQ0LZY3Evxk2yTYJd 6bUkAK3fV2KpkTo/COE+7OTMowzQkzMykiAVXGhU7yVD8isuUojgXeq1Qi3x0BZowU tubDnZmwDpkophHRr3f8elKyeKGTHw6YoExLu9ag= From: David Gibson To: qemu-devel@nongnu.org, brijesh.singh@amd.com, pair@us.ibm.com, pbonzini@redhat.com, dgilbert@redhat.com, frankja@linux.ibm.com Subject: [PATCH v3 6/9] host trust limitation: Add Error ** to HostTrustLimitation::kvm_init Date: Fri, 19 Jun 2020 12:05:59 +1000 Message-Id: <20200619020602.118306-7-david@gibson.dropbear.id.au> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200619020602.118306-1-david@gibson.dropbear.id.au> References: <20200619020602.118306-1-david@gibson.dropbear.id.au> MIME-Version: 1.0 Received-SPF: pass client-ip=203.11.71.1; envelope-from=dgibson@ozlabs.org; helo=ozlabs.org X-detected-operating-system: by eggs.gnu.org: First seen = 2020/06/18 22:06:09 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] X-Spam_score_int: -9 X-Spam_score: -1.0 X-Spam_bar: - X-Spam_report: (-1.0 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, HEADER_FROM_DIFFERENT_DOMAINS=1, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, URIBL_BLOCKED=0.001 autolearn=_AUTOLEARN X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Eduardo Habkost , kvm@vger.kernel.org, mst@redhat.com, Richard Henderson , cohuck@redhat.com, david@redhat.com, mdroth@linux.vnet.ibm.com, pasic@linux.ibm.com, qemu-s390x@nongnu.org, qemu-ppc@nongnu.org, David Gibson , =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Richard Henderson Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" This allows failures to be reported richly and idiomatically. Signed-off-by: David Gibson Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson --- accel/kvm/kvm-all.c | 4 +++- include/exec/host-trust-limitation.h | 2 +- target/i386/sev.c | 31 ++++++++++++++-------------- 3 files changed, 19 insertions(+), 18 deletions(-) diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c index 9645271ca5..c236ebeae0 100644 --- a/accel/kvm/kvm-all.c +++ b/accel/kvm/kvm-all.c @@ -2158,9 +2158,11 @@ static int kvm_init(MachineState *ms) if (ms->htl) { HostTrustLimitationClass *htlc = HOST_TRUST_LIMITATION_GET_CLASS(ms->htl); + Error *local_err = NULL; - ret = htlc->kvm_init(ms->htl); + ret = htlc->kvm_init(ms->htl, &local_err); if (ret < 0) { + error_report_err(local_err); goto err; } } diff --git a/include/exec/host-trust-limitation.h b/include/exec/host-trust-limitation.h index fc30ea3f78..d93b537280 100644 --- a/include/exec/host-trust-limitation.h +++ b/include/exec/host-trust-limitation.h @@ -30,7 +30,7 @@ typedef struct HostTrustLimitationClass { InterfaceClass parent; - int (*kvm_init)(HostTrustLimitation *); + int (*kvm_init)(HostTrustLimitation *, Error **); int (*encrypt_data)(HostTrustLimitation *, uint8_t *, uint64_t); } HostTrustLimitationClass; diff --git a/target/i386/sev.c b/target/i386/sev.c index 052a05d15a..829f78436a 100644 --- a/target/i386/sev.c +++ b/target/i386/sev.c @@ -617,7 +617,7 @@ sev_vm_state_change(void *opaque, int running, RunState state) } } -static int sev_kvm_init(HostTrustLimitation *htl) +static int sev_kvm_init(HostTrustLimitation *htl, Error **errp) { SevGuestState *sev = SEV_GUEST(htl); char *devname; @@ -633,14 +633,14 @@ static int sev_kvm_init(HostTrustLimitation *htl) host_cbitpos = ebx & 0x3f; if (host_cbitpos != sev->cbitpos) { - error_report("%s: cbitpos check failed, host '%d' requested '%d'", - __func__, host_cbitpos, sev->cbitpos); + error_setg(errp, "%s: cbitpos check failed, host '%d' requested '%d'", + __func__, host_cbitpos, sev->cbitpos); goto err; } if (sev->reduced_phys_bits < 1) { - error_report("%s: reduced_phys_bits check failed, it should be >=1," - " requested '%d'", __func__, sev->reduced_phys_bits); + error_setg(errp, "%s: reduced_phys_bits check failed, it should be >=1," + " requested '%d'", __func__, sev->reduced_phys_bits); goto err; } @@ -649,20 +649,19 @@ static int sev_kvm_init(HostTrustLimitation *htl) devname = object_property_get_str(OBJECT(sev), "sev-device", NULL); sev->sev_fd = open(devname, O_RDWR); if (sev->sev_fd < 0) { - error_report("%s: Failed to open %s '%s'", __func__, - devname, strerror(errno)); - } - g_free(devname); - if (sev->sev_fd < 0) { + error_setg(errp, "%s: Failed to open %s '%s'", __func__, + devname, strerror(errno)); + g_free(devname); goto err; } + g_free(devname); ret = sev_platform_ioctl(sev->sev_fd, SEV_PLATFORM_STATUS, &status, &fw_error); if (ret) { - error_report("%s: failed to get platform status ret=%d " - "fw_error='%d: %s'", __func__, ret, fw_error, - fw_error_to_str(fw_error)); + error_setg(errp, "%s: failed to get platform status ret=%d " + "fw_error='%d: %s'", __func__, ret, fw_error, + fw_error_to_str(fw_error)); goto err; } sev->build_id = status.build; @@ -672,14 +671,14 @@ static int sev_kvm_init(HostTrustLimitation *htl) trace_kvm_sev_init(); ret = sev_ioctl(sev->sev_fd, KVM_SEV_INIT, NULL, &fw_error); if (ret) { - error_report("%s: failed to initialize ret=%d fw_error=%d '%s'", - __func__, ret, fw_error, fw_error_to_str(fw_error)); + error_setg(errp, "%s: failed to initialize ret=%d fw_error=%d '%s'", + __func__, ret, fw_error, fw_error_to_str(fw_error)); goto err; } ret = sev_launch_start(sev); if (ret) { - error_report("%s: failed to create encryption context", __func__); + error_setg(errp, "%s: failed to create encryption context", __func__); goto err; } From patchwork Fri Jun 19 02:06:00 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Gibson X-Patchwork-Id: 280039 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.6 required=3.0 tests=DKIM_INVALID,DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id B0519C433E0 for ; Fri, 19 Jun 2020 02:09:34 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 7715C20773 for ; Fri, 19 Jun 2020 02:09:34 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=gibson.dropbear.id.au header.i=@gibson.dropbear.id.au header.b="Dh6czTEK" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 7715C20773 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=gibson.dropbear.id.au Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:49934 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jm6TF-00013O-Ov for qemu-devel@archiver.kernel.org; Thu, 18 Jun 2020 22:09:33 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:41938) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jm6QC-0003BD-7B; Thu, 18 Jun 2020 22:06:24 -0400 Received: from bilbo.ozlabs.org ([203.11.71.1]:47045 helo=ozlabs.org) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jm6Q9-0000os-9Z; Thu, 18 Jun 2020 22:06:23 -0400 Received: by ozlabs.org (Postfix, from userid 1007) id 49p2GT2LD1z9sT2; Fri, 19 Jun 2020 12:06:08 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gibson.dropbear.id.au; s=201602; t=1592532369; bh=qMsc309NrDU+kjkrkNdXuQ5jS6081SEdRvf2Ra68+0k=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Dh6czTEKkpC3AwFZDUZjJ8VQHRUr7RcuJheAzLqBP5kPURdYs+0yGjCA/XT1zxs7D s1fb+ETwTqir/AVT8/Fg42F1EGeA4vLI/0GtfCdmqaPQ+UY6gkl6xNDVkQ5NE1MxKj c0LeubLAdqYb7kxaejnrpYAIiqHooNIW4j31udso= From: David Gibson To: qemu-devel@nongnu.org, brijesh.singh@amd.com, pair@us.ibm.com, pbonzini@redhat.com, dgilbert@redhat.com, frankja@linux.ibm.com Subject: [PATCH v3 7/9] spapr: Add PEF based host trust limitation Date: Fri, 19 Jun 2020 12:06:00 +1000 Message-Id: <20200619020602.118306-8-david@gibson.dropbear.id.au> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200619020602.118306-1-david@gibson.dropbear.id.au> References: <20200619020602.118306-1-david@gibson.dropbear.id.au> MIME-Version: 1.0 Received-SPF: pass client-ip=203.11.71.1; envelope-from=dgibson@ozlabs.org; helo=ozlabs.org X-detected-operating-system: by eggs.gnu.org: First seen = 2020/06/18 22:06:09 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] X-Spam_score_int: -9 X-Spam_score: -1.0 X-Spam_bar: - X-Spam_report: (-1.0 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, HEADER_FROM_DIFFERENT_DOMAINS=1, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, URIBL_BLOCKED=0.001 autolearn=_AUTOLEARN X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Eduardo Habkost , kvm@vger.kernel.org, mst@redhat.com, Ram Pai , cohuck@redhat.com, david@redhat.com, mdroth@linux.vnet.ibm.com, pasic@linux.ibm.com, qemu-s390x@nongnu.org, qemu-ppc@nongnu.org, David Gibson , Richard Henderson Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" Some upcoming POWER machines have a system called PEF (Protected Execution Facility) 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 having the right hardware and firmware, we don't enable this by default. In order to run a secure guest you need to create a "pef-guest" object and set the host-trust-limitation machine property to point to it. 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. Qemu has no directly way of knowing if the guest is in secure mode, and certainly can't know until well after machine creation time. Signed-off-by: David Gibson Acked-by: Ram Pai --- target/ppc/Makefile.objs | 2 +- target/ppc/pef.c | 83 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 target/ppc/pef.c diff --git a/target/ppc/Makefile.objs b/target/ppc/Makefile.objs index e8fa18ce13..ac93b9700e 100644 --- a/target/ppc/Makefile.objs +++ b/target/ppc/Makefile.objs @@ -6,7 +6,7 @@ obj-y += machine.o mmu_helper.o mmu-hash32.o monitor.o arch_dump.o obj-$(TARGET_PPC64) += mmu-hash64.o mmu-book3s-v3.o compat.o obj-$(TARGET_PPC64) += mmu-radix64.o endif -obj-$(CONFIG_KVM) += kvm.o +obj-$(CONFIG_KVM) += kvm.o pef.o obj-$(call lnot,$(CONFIG_KVM)) += kvm-stub.o obj-y += dfp_helper.o obj-y += excp_helper.o diff --git a/target/ppc/pef.c b/target/ppc/pef.c new file mode 100644 index 0000000000..53a6af0347 --- /dev/null +++ b/target/ppc/pef.c @@ -0,0 +1,83 @@ +/* + * PEF (Protected Execution Facility) for POWER support + * + * Copyright David Gibson, Redhat Inc. 2020 + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ + +#include "qemu/osdep.h" + +#include "qapi/error.h" +#include "qom/object_interfaces.h" +#include "sysemu/kvm.h" +#include "migration/blocker.h" +#include "exec/host-trust-limitation.h" + +#define TYPE_PEF_GUEST "pef-guest" +#define PEF_GUEST(obj) \ + OBJECT_CHECK(PefGuestState, (obj), TYPE_PEF_GUEST) + +typedef struct PefGuestState PefGuestState; + +/** + * PefGuestState: + * + * The PefGuestState object is used for creating and managing a PEF + * guest. + * + * # $QEMU \ + * -object pef-guest,id=pef0 \ + * -machine ...,host-trust-limitation=pef0 + */ +struct PefGuestState { + Object parent_obj; +}; + +static int pef_kvm_init(HostTrustLimitation *gmpo, Error **errp) +{ + if (!kvm_check_extension(kvm_state, KVM_CAP_PPC_SECURE_GUEST)) { + error_setg(errp, + "KVM implementation does not support Secure VMs (is an ultravisor running?)"); + return -1; + } else { + int ret = kvm_vm_enable_cap(kvm_state, KVM_CAP_PPC_SECURE_GUEST, 0, 1); + + if (ret < 0) { + error_setg(errp, + "Error enabling PEF with KVM"); + return -1; + } + } + + return 0; +} + +static void pef_guest_class_init(ObjectClass *oc, void *data) +{ + HostTrustLimitationClass *gmpc = HOST_TRUST_LIMITATION_CLASS(oc); + + gmpc->kvm_init = pef_kvm_init; +} + +static const TypeInfo pef_guest_info = { + .parent = TYPE_OBJECT, + .name = TYPE_PEF_GUEST, + .instance_size = sizeof(PefGuestState), + .class_init = pef_guest_class_init, + .interfaces = (InterfaceInfo[]) { + { TYPE_HOST_TRUST_LIMITATION }, + { TYPE_USER_CREATABLE }, + { } + } +}; + +static void +pef_register_types(void) +{ + type_register_static(&pef_guest_info); +} + +type_init(pef_register_types); From patchwork Fri Jun 19 02:06:01 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Gibson X-Patchwork-Id: 280040 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.5 required=3.0 tests=DKIM_INVALID,DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id E2143C433E0 for ; Fri, 19 Jun 2020 02:09:17 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id ACE4920773 for ; Fri, 19 Jun 2020 02:09:17 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=gibson.dropbear.id.au header.i=@gibson.dropbear.id.au header.b="IpLRJFPR" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org ACE4920773 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=gibson.dropbear.id.au Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:48114 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jm6Sy-0000HC-Ti for qemu-devel@archiver.kernel.org; Thu, 18 Jun 2020 22:09:16 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:41934) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jm6QB-0003AA-Ch; Thu, 18 Jun 2020 22:06:23 -0400 Received: from ozlabs.org ([2401:3900:2:1::2]:46513) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jm6Q8-0000p2-P8; Thu, 18 Jun 2020 22:06:22 -0400 Received: by ozlabs.org (Postfix, from userid 1007) id 49p2GT40bYz9sT6; Fri, 19 Jun 2020 12:06:09 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gibson.dropbear.id.au; s=201602; t=1592532369; bh=oUlu8u5TiukpYL5YY0i+HjSckV5d3NnHfXBN6cEFoNM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=IpLRJFPR1N23oZq2OQi5denxnJtl2OxBqOQnPDm3P9o+q4fZ5ysUcRMcPMD/rZTIM fgcPuCtC/xXL8TCuT3gP/WfwbsXGC9F3HeTX65JwHjfjT0DjaXNmyUmIY3q4H3J9uC BoMmZaz7l+Y+Dx4agziwde1pIyeDwdHvLvAaWS4k= From: David Gibson To: qemu-devel@nongnu.org, brijesh.singh@amd.com, pair@us.ibm.com, pbonzini@redhat.com, dgilbert@redhat.com, frankja@linux.ibm.com Subject: [PATCH v3 8/9] spapr: PEF: block migration Date: Fri, 19 Jun 2020 12:06:01 +1000 Message-Id: <20200619020602.118306-9-david@gibson.dropbear.id.au> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200619020602.118306-1-david@gibson.dropbear.id.au> References: <20200619020602.118306-1-david@gibson.dropbear.id.au> MIME-Version: 1.0 Received-SPF: pass client-ip=2401:3900:2:1::2; envelope-from=dgibson@ozlabs.org; helo=ozlabs.org X-detected-operating-system: by eggs.gnu.org: No matching host in p0f cache. That's all we know. X-Spam_score_int: -9 X-Spam_score: -1.0 X-Spam_bar: - X-Spam_report: (-1.0 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, HEADER_FROM_DIFFERENT_DOMAINS=1, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, URIBL_BLOCKED=0.001 autolearn=_AUTOLEARN X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Eduardo Habkost , kvm@vger.kernel.org, mst@redhat.com, cohuck@redhat.com, david@redhat.com, mdroth@linux.vnet.ibm.com, pasic@linux.ibm.com, qemu-s390x@nongnu.org, qemu-ppc@nongnu.org, David Gibson , Richard Henderson Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" We haven't yet implemented the fairly involved handshaking that will be needed to migrate PEF protected guests. For now, just use a migration blocker so we get a meaningful error if someone attempts this (this is the same approach used by AMD SEV). Signed-off-by: David Gibson --- target/ppc/pef.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/target/ppc/pef.c b/target/ppc/pef.c index 53a6af0347..6a50efd580 100644 --- a/target/ppc/pef.c +++ b/target/ppc/pef.c @@ -36,6 +36,8 @@ struct PefGuestState { Object parent_obj; }; +static Error *pef_mig_blocker; + static int pef_kvm_init(HostTrustLimitation *gmpo, Error **errp) { if (!kvm_check_extension(kvm_state, KVM_CAP_PPC_SECURE_GUEST)) { @@ -52,6 +54,10 @@ static int pef_kvm_init(HostTrustLimitation *gmpo, Error **errp) } } + /* add migration blocker */ + error_setg(&pef_mig_blocker, "PEF: Migration is not implemented"); + migrate_add_blocker(pef_mig_blocker, &error_abort); + return 0; }