From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
To: "Singh, Brijesh" <brijesh.singh@amd.com>
Cc: "pbonzini@redhat.com" <pbonzini@redhat.com>,
"Lendacky, Thomas" <Thomas.Lendacky@amd.com>,
"qemu-devel@nongnu.org" <qemu-devel@nongnu.org>,
"ehabkost@redhat.com" <ehabkost@redhat.com>
Subject: Re: [Qemu-devel] [PATCH v3 13/14] migration/ram: add support to send encrypted pages
Date: Wed, 14 Aug 2019 17:37:26 +0100 [thread overview]
Message-ID: <20190814163726.GO2920@work-vm> (raw)
In-Reply-To: <20190806165429.19327-14-brijesh.singh@amd.com>
* Singh, Brijesh (brijesh.singh@amd.com) wrote:
> When memory encryption is enabled, the guest memory will be encrypted with
> the guest specific key. The patch introduces RAM_SAVE_FLAG_ENCRYPTED_PAGE
> flag to distinguish the encrypted data from plaintext. Encrypted pages
> may need special handling. The kvm_memcrypt_save_outgoing_page() is used
> by the sender to write the encrypted pages onto the socket, similarly the
> kvm_memcrypt_load_incoming_page() is used by the target to read the
> encrypted pages from the socket and load into the guest memory.
>
> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
> ---
> migration/ram.c | 131 +++++++++++++++++++++++++++++++++++++++++++++++-
> 1 file changed, 130 insertions(+), 1 deletion(-)
>
> diff --git a/migration/ram.c b/migration/ram.c
> index 57c707525b..100a5a10cd 100644
> --- a/migration/ram.c
> +++ b/migration/ram.c
> @@ -59,6 +59,9 @@
> #include "qemu/iov.h"
> #include "hw/boards.h"
>
> +/* Defines RAM_SAVE_ENCRYPTED_PAGE and RAM_SAVE_ENCRYPTED_BITMAP */
> +#include "sysemu/sev.h"
> +
> /***********************************************************/
> /* ram save/restore */
>
> @@ -77,6 +80,7 @@
> #define RAM_SAVE_FLAG_XBZRLE 0x40
> /* 0x80 is reserved in migration.h start with 0x100 next */
> #define RAM_SAVE_FLAG_COMPRESS_PAGE 0x100
> +#define RAM_SAVE_FLAG_ENCRYPTED_DATA 0x200
>
> static inline bool is_zero_range(uint8_t *p, uint64_t size)
> {
> @@ -460,6 +464,9 @@ static QemuCond decomp_done_cond;
>
> static bool do_compress_ram_page(QEMUFile *f, z_stream *stream, RAMBlock *block,
> ram_addr_t offset, uint8_t *source_buf);
> +static int ram_save_encrypted_page(RAMState *rs, PageSearchStatus *pss,
> + bool last_stage);
> +
>
> static void *do_data_compress(void *opaque)
> {
> @@ -2039,6 +2046,73 @@ static int save_normal_page(RAMState *rs, RAMBlock *block, ram_addr_t offset,
> return 1;
> }
>
> +/**
> + * ram_save_encrypted_page - send the given encrypted page to the stream
> + */
> +static int ram_save_encrypted_page(RAMState *rs, PageSearchStatus *pss,
> + bool last_stage)
> +{
> + int ret;
> + uint8_t *p;
> + RAMBlock *block = pss->block;
> + ram_addr_t offset = pss->page << TARGET_PAGE_BITS;
> + uint64_t bytes_xmit;
> + MachineState *ms = MACHINE(qdev_get_machine());
> + MachineClass *mc = MACHINE_GET_CLASS(ms);
> + struct MachineMemoryEncryptionOps *ops = mc->memory_encryption_ops;
> +
> + p = block->host + offset;
> +
> + ram_counters.transferred +=
> + save_page_header(rs, rs->f, block,
> + offset | RAM_SAVE_FLAG_ENCRYPTED_DATA);
> +
> + qemu_put_be32(rs->f, RAM_SAVE_ENCRYPTED_PAGE);
> + ret = ops->save_outgoing_page(rs->f, p, TARGET_PAGE_SIZE, &bytes_xmit);
> + if (ret) {
> + return -1;
> + }
> +
> + ram_counters.transferred += bytes_xmit;
> + ram_counters.normal++;
> +
> + return 1;
> +}
> +
> +/**
> + * ram_save_encrypted_bitmap: send the encrypted page state bitmap
> + */
> +static int ram_save_encrypted_bitmap(RAMState *rs, QEMUFile *f)
> +{
> + MachineState *ms = MACHINE(qdev_get_machine());
> + MachineClass *mc = MACHINE_GET_CLASS(ms);
> + struct MachineMemoryEncryptionOps *ops = mc->memory_encryption_ops;
> +
> + save_page_header(rs, rs->f, rs->last_seen_block,
> + RAM_SAVE_FLAG_ENCRYPTED_DATA);
> + qemu_put_be32(rs->f, RAM_SAVE_ENCRYPTED_BITMAP);
> + return ops->save_outgoing_bitmap(rs->f);
> +}
> +
> +static int load_encrypted_data(QEMUFile *f, uint8_t *ptr)
> +{
> + MachineState *ms = MACHINE(qdev_get_machine());
> + MachineClass *mc = MACHINE_GET_CLASS(ms);
> + struct MachineMemoryEncryptionOps *ops = mc->memory_encryption_ops;
> + int flag;
> +
> + flag = qemu_get_be32(f);
> +
> + if (flag == RAM_SAVE_ENCRYPTED_PAGE) {
> + return ops->load_incoming_page(f, ptr);
> + } else if (flag == RAM_SAVE_ENCRYPTED_BITMAP) {
> + return ops->load_incoming_bitmap(f);
> + } else {
> + error_report("unknown encrypted flag %x", flag);
> + return 1;
> + }
> +}
> +
> /**
> * ram_save_page: send the given page to the stream
> *
> @@ -2528,6 +2602,22 @@ static bool save_compress_page(RAMState *rs, RAMBlock *block, ram_addr_t offset)
> return false;
> }
>
> +/**
> + * encrypted_test_bitmap: check if the page is encrypted
> + *
> + * Returns a bool indicating whether the page is encrypted.
> + */
> +static bool encrypted_test_bitmap(RAMState *rs, RAMBlock *block,
> + unsigned long page)
> +{
> + /* ROM devices contains the unencrypted data */
> + if (memory_region_is_rom(block->mr)) {
> + return false;
> + }
> +
> + return test_bit(page, block->encbmap);
> +}
> +
> /**
> * ram_save_target_page: save one target page
> *
> @@ -2548,6 +2638,17 @@ static int ram_save_target_page(RAMState *rs, PageSearchStatus *pss,
> return res;
> }
>
> + /*
> + * If memory encryption is enabled then use memory encryption APIs
> + * to write the outgoing buffer to the wire. The encryption APIs
> + * will take care of accessing the guest memory and re-encrypt it
> + * for the transport purposes.
> + */
> + if (memcrypt_enabled() &&
> + encrypted_test_bitmap(rs, pss->block, pss->page)) {
> + return ram_save_encrypted_page(rs, pss, last_stage);
> + }
> +
> if (save_compress_page(rs, block, offset)) {
> return 1;
> }
> @@ -3445,6 +3546,16 @@ void qemu_guest_free_page_hint(void *addr, size_t len)
> }
> }
>
> +static int ram_encrypted_save_setup(void)
> +{
> + MachineState *ms = MACHINE(qdev_get_machine());
> + MachineClass *mc = MACHINE_GET_CLASS(ms);
> + MigrationParameters *p = &migrate_get_current()->parameters;
> + struct MachineMemoryEncryptionOps *ops = mc->memory_encryption_ops;
> +
> + return ops->save_setup(p->sev_pdh, p->sev_plat_cert, p->sev_amd_cert);
> +}
> +
> /*
> * Each of ram_save_setup, ram_save_iterate and ram_save_complete has
> * long-running RCU critical section. When rcu-reclaims in the code
> @@ -3480,6 +3591,12 @@ static int ram_save_setup(QEMUFile *f, void *opaque)
>
> rcu_read_lock();
>
> + if (memcrypt_enabled()) {
> + if (ram_encrypted_save_setup()) {
> + return -1;
> + }
> + }
> +
> qemu_put_be64(f, ram_bytes_total_common(true) | RAM_SAVE_FLAG_MEM_SIZE);
>
> RAMBLOCK_FOREACH_MIGRATABLE(block) {
> @@ -3644,6 +3761,11 @@ static int ram_save_complete(QEMUFile *f, void *opaque)
> flush_compressed_data(rs);
> ram_control_after_iterate(f, RAM_CONTROL_FINISH);
>
> + /* send the page encryption state bitmap */
> + if (memcrypt_enabled()) {
> + ret = ram_save_encrypted_bitmap(rs, f);
> + }
> +
> rcu_read_unlock();
>
> multifd_send_sync_main();
> @@ -4391,7 +4513,8 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id)
> }
>
> if (flags & (RAM_SAVE_FLAG_ZERO | RAM_SAVE_FLAG_PAGE |
> - RAM_SAVE_FLAG_COMPRESS_PAGE | RAM_SAVE_FLAG_XBZRLE)) {
> + RAM_SAVE_FLAG_COMPRESS_PAGE | RAM_SAVE_FLAG_XBZRLE |
> + RAM_SAVE_FLAG_ENCRYPTED_DATA)) {
> RAMBlock *block = ram_block_from_stream(f, flags);
>
> /*
> @@ -4505,6 +4628,12 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id)
> break;
> }
> break;
> + case RAM_SAVE_FLAG_ENCRYPTED_DATA:
> + if (load_encrypted_data(f, host)) {
> + error_report("Failed to load encrypted data");
> + ret = -EINVAL;
> + }
> + break;
> case RAM_SAVE_FLAG_EOS:
> /* normal exit */
> multifd_recv_sync_main();
> --
> 2.17.1
>
--
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK
next prev parent reply other threads:[~2019-08-14 16:38 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-08-06 16:54 [Qemu-devel] [PATCH v3 00/14] Add SEV guest live migration support Singh, Brijesh
2019-08-06 16:54 ` [Qemu-devel] [PATCH v3 01/14] doc: update AMD SEV API spec web link Singh, Brijesh
2019-08-06 19:00 ` Dr. David Alan Gilbert
2019-08-06 16:54 ` [Qemu-devel] [PATCH v3 02/14] doc: update AMD SEV to include Live migration flow Singh, Brijesh
2019-08-07 11:01 ` Dr. David Alan Gilbert
2019-08-06 16:54 ` [Qemu-devel] [PATCH v3 03/14] migration.json: add AMD SEV specific migration parameters Singh, Brijesh
2019-08-07 11:06 ` Dr. David Alan Gilbert
2019-08-08 2:25 ` Singh, Brijesh
2019-08-08 10:48 ` Dr. David Alan Gilbert
2019-08-09 20:00 ` Singh, Brijesh
2019-08-06 16:54 ` [Qemu-devel] [PATCH v3 04/14] linux-headers: update kernel header to include SEV migration commands Singh, Brijesh
2019-08-06 16:54 ` [Qemu-devel] [PATCH v3 05/14] hw/machine: add helper to query the memory encryption state Singh, Brijesh
2019-08-07 16:14 ` Dr. David Alan Gilbert
2019-08-08 2:25 ` Singh, Brijesh
2019-08-06 16:54 ` [Qemu-devel] [PATCH v3 06/14] hw/machine: introduce MachineMemoryEncryptionOps for encrypted VMs Singh, Brijesh
2019-08-07 16:36 ` Dr. David Alan Gilbert
2019-08-06 16:54 ` [Qemu-devel] [PATCH v3 08/14] target/i386: sev: do not create launch context for an incoming guest Singh, Brijesh
2019-08-06 16:54 ` [Qemu-devel] [PATCH v3 07/14] target/i386: sev: provide callback to setup outgoing context Singh, Brijesh
2019-08-08 11:19 ` Dr. David Alan Gilbert
2019-08-06 16:54 ` [Qemu-devel] [PATCH v3 09/14] target/i386: sev: add support to encrypt the outgoing page Singh, Brijesh
2019-08-09 18:54 ` Dr. David Alan Gilbert
2019-08-06 16:54 ` [Qemu-devel] [PATCH v3 10/14] target/i386: sev: add support to load incoming encrypted page Singh, Brijesh
2019-08-13 17:38 ` Dr. David Alan Gilbert
2019-08-06 16:54 ` [Qemu-devel] [PATCH v3 11/14] migration: add support to migrate page encryption bitmap Singh, Brijesh
2019-08-13 18:57 ` Dr. David Alan Gilbert
2019-08-06 16:54 ` [Qemu-devel] [PATCH v3 13/14] migration/ram: add support to send encrypted pages Singh, Brijesh
2019-08-14 16:37 ` Dr. David Alan Gilbert [this message]
2019-08-06 16:54 ` [Qemu-devel] [PATCH v3 12/14] kvm: add support to sync the page encryption state bitmap Singh, Brijesh
2019-08-06 16:54 ` [Qemu-devel] [PATCH v3 14/14] target/i386: sev: remove migration blocker Singh, Brijesh
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20190814163726.GO2920@work-vm \
--to=dgilbert@redhat.com \
--cc=Thomas.Lendacky@amd.com \
--cc=brijesh.singh@amd.com \
--cc=ehabkost@redhat.com \
--cc=pbonzini@redhat.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.