diff --git a/Makefile.target b/Makefile.target
index a440bcb..74ad204 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -136,7 +136,7 @@ ifdef CONFIG_SOFTMMU
 obj-y += arch_init.o cpus.o monitor.o gdbstub.o balloon.o ioport.o numa.o
 obj-y += qtest.o bootdevice.o
 obj-y += hw/
-obj-$(CONFIG_KVM) += kvm-all.o
+obj-$(CONFIG_KVM) += kvm-all.o sev.o
 obj-y += memory.o cputlb.o
 obj-y += memory_mapping.o
 obj-y += dump.o
diff --git a/docs/amd-memory-encryption.txt b/docs/amd-memory-encryption.txt
new file mode 100644
index 0000000..ab2fdfb
--- /dev/null
+++ b/docs/amd-memory-encryption.txt
@@ -0,0 +1,260 @@
+Secure Encrypted Virtalization (SEV) is a feature found on AMD processors.
+
+SEV feature allows the memory contents of a virtual machine (VM) to be
+transparently encrypted with a key unique to the guest VM. The memory
+controller contains a high performance encryption engine which can be
+programmed with multiple keys for used by different VMs in the system.
+The programming and management of these keys is handled by the AMD Platform
+Secure Processor (PSP) firmware which exposes commands for these tasks. The
+SEV commands can be send via KVM_SEV_ISSUE_CMD ioctl.
+
+SEV is capable of supporting both light-weight virtual containers as well as
+conventional VM within an enterprise cloud environment. In either case,
+there are two parties concerned in the deloplyment of SEV guest: the guest
+owner and the platform owner. For example, in a cloud envrionment, the
+platform owner would be cloud vendor and the guest owner would be the user
+that wishes to run their workload in the cloud.
+
+Guest owners wish to protect the confidentiality of the data running within
+their guests. While they trust the platform owner to provide the infrastrcuture
+to run their guest, they benefit from reducing their risk exposure to
+vulnerablities within that infrastruture. The SEV feature encrypts the content
+of the memory of the guest and provides additional assurance that it was
+encrypted properly. The encryption of memory places an additional burden
+on attackers within the operational envrionment who may have already obtained
+some illicit access to the guest's memory through a vulnerability in the
+hypervisor or other supporting enterprise softwares.
+
+Platform owners wish to provide such protection to guest owners, but also must
+manage the computing resources efficiently and effectively. Resource allocation
+need to be fluid and their customers data must be safely backed up in case
+of failure. The SEV feature has been developed to be sensitive to this
+requirement; it integrates into the conventional guest life cycle surrounding
+guest launching, migration, and snapshotting.
+
+The following links provide additional detail:
+
+AMD Memory Encryption whitepaper:
+   http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2013/12/AMD_Memory_Encryptio \
+n_Whitepaper_v7-Public.pdf
+
+Secure Encrypted Virutualization Key Management:
+http://support.amd.com/TechDocs/55766_SEV-KM API_Spec.pdf
+
+KVM Forum slides:
+http://www.linux-kvm.org/images/7/74/02x08A-Thomas_Lendacky-AMDs_Virtualizatoin_Memory_Encryption_Technology.pdf
+
+AMD64 Architecture Programmer's Manual:
+   http://support.amd.com/TechDocs/24593.pdf
+   SME is section 7.10
+   SEV is section 15.34
+
+1. API description
+-----------------
+
+SEV provides the following command via KVM_SEV_ISSUE_CMD ioctl to launch,
+migrate and snapshot a SEV-enabled guest.
+
+1.0 LAUNCH_START (KVM_SEV_LAUNCH_START)
+
+The command is used to prepare a guest for the transition into SEV-enabled
+mode.
+
+Parameters: struct kvm_sev_launch_start
+Returns: 0 on success; -1 on error.
+
+/* for LAUNCH_START */
+struct kvm_sev_launch_start {
+    /* If KS is set; share key with guest reference by this handle */
+    u32 handle;
+
+    /* Bit 0 (KS) key sharing is enabled */
+    u32 flags;
+
+    /* Guest launch policy (see 1.5 for details)
+    u32 policy;
+
+    /* The Qx and Qy parameter of the owner's ECDH public key */
+    u8 dh_pub_qx[32], dh_pub_qy[32];
+
+    /* A nonce generated by the guest owner */
+    u8 nonce[16];
+}
+
+The firmware creates a new launch context and generate a new VM Encryption Key
+(VEK) - a 128-bit AES-128 key used to encrypt the memory of the guest. The key
+is loaded into memory controller by the firmware.
+
+1.1 LAUNCH_UPDATE (KVM_SEV_LAUNCH_UPDATE)
+
+The command is used to encrypt the guest memory region specified using the VEK
+loaded during LAUNCH_START.
+
+Parameters: struct kvm_sev_launch_update
+Returns: 0 on success; -1 on error
+
+/* for LAUNCH_UPDATE */
+struct kvm_sev_launch_update {
+    /* host virtual address to encrypt */
+    u64 address;
+
+    /* length of memory region to encrypt */
+    u32 len;
+}
+
+The firmware will perform the inline encryption of memory region and launch
+measurement will be updated with the contents of the memor region.
+
+1.2 LAUNCH_FINISH (KVM_SEV_LAUNCH_FINISH)
+
+The command is used to finalize the SEV guest launch process and get the
+measurement of encrypted contents.
+
+Parameters: struct kvm_sev_launch_update
+Returns: 0 on success; -1 on error
+
+/* for LAUNCH_FINISH */
+struct kvm_sev_launch_finish {
+    /* contains measurement of memory encrypted via LAUNCH_UPDATE */
+    u8 measurement[32];
+}
+
+After hypervisor has finished encrypting the guest's memory (via LAUNCH_UPDATE),
+the hypervisor concludes the launch operation. The measurement value returned
+from the LAUNCH_FINISH command can be handed to the guest owner to verify that
+guest is launched successfully.
+
+1.3 GUEST_STATUS (KVM_SEV_GUEST_STATUS)
+
+The command returns the current SEV guest status.
+
+Parameters: struct kvm_sev_guest_status
+Returns: 0 on success; -1 on error
+
+/* for GUEST_STATUS */
+struct kvm_sev_guest_status {
+    /* guest handle */
+    u32 handle;
+
+    /* guest policy */
+    u32 policy;
+
+    /* guest state (see state enum) */
+    u8 state;
+};
+
+/* for SEV guest state */
+GuestState {
+    STATE_INVALID = 0,
+    STATE_LAUNCHING,
+    STATE_RECEIVING,
+    STATE_SENDING,
+    STATE_RUNNING,
+};
+
+1.4 DBG_DECRYPT (KVM_SEV_DBG_DECRYPT)
+
+The command is used to decrypt a page of guest memory for debug.
+
+Parameters: struct kvm_sev_dbg_decrypt
+Returns: 0 on success; -1 on error
+
+/* DGB_DECRYPT */
+struct kvm_sev_dbg_decrypt {
+    /*  virtual address of memory region to debug from */
+    u64 src_address;
+
+    /*  virtual address of memory region to write decrypted contents into */
+    u64 dst_address;
+
+    /* length of memory region */
+    u32 length;
+}
+
+1.4 DBG_ENCRYPT (KVM_SEV_DBG_ENCRYPT)
+
+The command is used to encrypt a page of guest memory for debug.
+
+Parameters: struct kvm_sev_dbg_encrypt
+Returns: 0 on success; -1 on error
+
+/* DGB_ENCRYPT */
+struct kvm_sev_dbg_encrypt {
+    /*  virtual address of memory region to debug from */
+    u64 src_address;
+
+    /*  virtual address of memory region to write encrypted contents into */
+    u64 dst_address;
+
+    /* length of memory region */
+    u32 length;
+}
+
+1.5 SEV Policy
+
+Firmware maintain a guest policy provided by the guest owner. This policy is
+enforced by the firmware and restricts what configuration and operational
+command can be performed on the SEV guest by the hypervisor. For instance,
+if debug is off then hypervisor will not able to decrypt guest memory using
+DBG_DECRYPT commands.
+
+The policy is 4-byte structure with the following field
+
+Bit 0 (debug) - Debugging of the guest is disallowed when set
+Bit 1 (ks) - Sharing keys with other guests is disallowed when set
+Bit 2 (reserved) - must be set to 1
+Bit 3 (nosend) - Sending the guest to another platform is disallowed when set
+Bit 4 (domain) - The guest must not be transmitted to another platform that is not in the domain when set
+Bit 5 (sev) - The guest must not be transmitted to another platform that is not SEV capable when set.
+Bit 15:6 (reserved)
+Bit 16:24 (fw_major) - The guest must not be transmitted to another platform that is not SEV capable when set.
+Bit 25:31 (fw_minor) - The guest must not be transmitted to another platform that is not SEV capable when set.
+
+2. QEMU command line
+--------------------
+
+SEV support can be enabled through 'memory-encryption' parameters defined in
+security-policy object. 
+
+The following objects can be used to provide SEV guest parameters.
+
+2.0 sev-launch-info
+
+The object can be used to provide various parameters required to launch an
+unencrypted SEV guest. A unencrypted guest means that OS images (bios, kernel
+and initrd) received from guest owner are unencrypted and SEV guest should
+encrypt it using the LAUNCH command.
+
+e.g to launch an unencrypted SEV guest
+
+# $QEMU \
+    -object sev-launch-info,id=launch0,flags.ks=off,dh-pub-qx=zzzz \
+    -object sev-guest-info,id=sev0,launch=launch0 \
+    -object security-policy,id=secure0,memory-encryption=sev0 \
+    -machine ...,security-policy=secure0
+
+2.1 sev-policy-info
+
+The object can be used to provide the guest policy for sev-launch-info object
+
+e.g to launch a unencrypted SEV guest which does not allow the guest to be
+send to another platform (i.e disable migration)
+
+# $QEMU \
+    -object sev-policy-info,id=policy0,nosend=on \
+    -object sev-launch-info,id=launch0,policy=policy0 \
+    ....
+
+2.2 sev-guest-info
+
+The object provides the properties to set the SEV guest launch and send id to
+use during SEV guest creation and migration.
+
+e.g to use sev-launch-info object id during SEV guest creation
+
+# $QEMU \
+    -object sev-launch-info,id=launch0 \
+    -object sev-guest-info,id=sev0,launch=launch0 \
+    -object security-policy,id=secure0,memory-encryption=sev0 \
+    ....
+
diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
index c9c2436..16c14f4 100644
--- a/include/sysemu/kvm.h
+++ b/include/sysemu/kvm.h
@@ -56,6 +56,7 @@ extern bool kvm_ioeventfd_any_length_allowed;
 
 #if defined CONFIG_KVM || !defined NEED_CPU_H
 #define kvm_enabled()           (kvm_allowed)
+
 /**
  * kvm_irqchip_in_kernel:
  *
@@ -217,6 +218,11 @@ int kvm_has_intx_set_mask(void);
 int kvm_init_vcpu(CPUState *cpu);
 int kvm_cpu_exec(CPUState *cpu);
 int kvm_destroy_vcpu(CPUState *cpu);
+bool kvm_memory_encryption_enabled(void);
+int kvm_memory_encryption_start(void);
+int kvm_memory_encryption_finish(void);
+void *kvm_memory_encryption_get_handle(void);
+void kvm_memory_encryption_set_memory_region(MemoryRegion *mr);
 
 #ifdef NEED_CPU_H
 #include "cpu.h"
diff --git a/include/sysemu/sev.h b/include/sysemu/sev.h
new file mode 100644
index 0000000..534390b
--- /dev/null
+++ b/include/sysemu/sev.h
@@ -0,0 +1,208 @@
+/*
+ * QEMU Secure Encrypted Virutualization (SEV) support
+ *
+ * Copyright: Advanced Micro Devices, 2016
+ *
+ * Authors:
+ *  Brijesh Singh <brijesh.singh@amd.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef QEMU_SEV_H
+#define QEMU_SEV_H
+
+#include <linux/kvm.h>
+
+#include "qom/object.h"
+#include "qapi/error.h"
+#include "sysemu/kvm.h"
+
+#define TYPE_QSEV_GUEST_INFO "sev-guest-info"
+#define QSEV_GUEST_INFO(obj)                  \
+    OBJECT_CHECK(QSevGuestInfo, (obj), TYPE_QSEV_GUEST_INFO)
+
+typedef struct QSevGuestInfo QSevGuestInfo;
+typedef struct QSevGuestInfoClass QSevGuestInfoClass;
+
+/**
+ * QSevGuestInfo:
+ *
+ * The QSevGuestInfo object provides the guest launch and migration ID
+ * when memory encryption support is enabled in security-policy.
+ *
+ * The QSevGuestInfo object provides two properties:
+ * - launch: should be set to SEV guest launch object ID
+ * - send: should be set to SEV guest send object ID
+ *
+ * e.g to launch a unencrypted SEV guest
+ *
+ * # $QEMU -object sev-launch-info,id=launch0,flags.ks=off \
+ *         -object sev-migrate-send,id=send0 \
+ *         -object sev-guest-info,id=sev0,launch=launch0 send=send0 \
+ *         -object security-policy,id=secure0,memory-encryption=sev0 \
+ *         -machine ...security-policy=secure0
+ */
+struct QSevGuestInfo {
+    Object parent_obj;
+
+    char *launch;
+    char *send;
+};
+
+struct QSevGuestInfoClass {
+    ObjectClass parent_class;
+};
+
+#define TYPE_QSEV_POLICY_INFO "sev-policy-info"
+#define QSEV_POLICY_INFO(obj)                  \
+    OBJECT_CHECK(QSevPolicyInfo, (obj), TYPE_QSEV_POLICY_INFO)
+
+typedef struct QSevPolicyInfo QSevPolicyInfo;
+typedef struct QSevPolicyInfoClass QSevPolicyInfoClass;
+
+/**
+ * QSevPolicyInfo:
+ *
+ * The QSevPolicyInfo object provides the SEV guest policy parameters used
+ * in launch and send commands.
+ *
+ * # $QEMU -object sev-policy-info,id=policy0,debug=on,ks=on,nosend=off \
+ *         -object sev-launch-info,id=launch0,flag.ks=on,policy=policy0\
+ *         ....
+ */
+struct QSevPolicyInfo {
+    Object parent_obj;
+    bool debug;
+    bool ks;
+    bool nosend;
+    bool domain;
+    bool sev;
+    uint8_t fw_major;
+    uint8_t fw_minor;
+};
+
+struct QSevPolicyInfoClass {
+    ObjectClass parent_class;
+};
+
+#define TYPE_QSEV_LAUNCH_INFO "sev-launch-info"
+#define QSEV_LAUNCH_INFO(obj)                  \
+    OBJECT_CHECK(QSevLaunchInfo, (obj), TYPE_QSEV_LAUNCH_INFO)
+
+typedef struct QSevLaunchInfo QSevLaunchInfo;
+typedef struct QSevLaunchInfoClass QSevLaunchInfoClass;
+
+/**
+ * QSevLaunchInfo:
+ *
+ * The QSevLaunchInfo object provides parameters to launch an unencrypted
+ * sev guest. A unencrypted guest launch means that the guest owners
+ * provided OS images (kernel, initrd and bios) are unencrypted and SEV
+ * would encrypt the images using guest owner's key creating using the
+ * launch parameters.
+ *
+ * # $QEMU -object sev-policy,debug=on,ks=on,nosend=off,id=policy1 \
+ *         -object sev-launch-info,flag.ks=on,policy=policy1,id=sev \
+ *         -object sev-guest-info,launch=sev,id=secure-guest \
+ *         ....
+ */
+struct QSevLaunchInfo {
+    Object parent_obj;
+    uint32_t handle;
+    bool flags_ks;
+    char *policy_id;
+    uint8_t nonce[16];
+    uint8_t dh_pub_qx[32];
+    uint8_t dh_pub_qy[32];
+};
+
+struct QSevLaunchInfoClass {
+    ObjectClass parent_class;
+};
+
+#define TYPE_QSEV_RECEIVE_INFO "sev-receive-info"
+#define QSEV_RECEIVE_INFO(obj)                  \
+    OBJECT_CHECK(QSevReceiveInfo, (obj), TYPE_QSEV_RECEIVE_INFO)
+
+typedef struct QSevReceiveInfo QSevReceiveInfo;
+typedef struct QSevReceiveInfoClass QSevReceiveInfoClass;
+
+/**
+ * QSevReceiveInfo:
+ *
+ * The QSevReceiveInfo object provides parameters to launch a pre-encrypted
+ * sev guest or receive the guest during migration. In this mode the images
+ * received from the remote is encrypted using transport key, SEV guest would
+ * re-encrypt the data using the owner's key creating using the parameters
+ * specified in this object.
+ *
+ * # $QEMU \
+ *         -object sev-receive-info,id=launch0,wrapped-tek=xxxx,ten=xxxx \
+ *         -object sev-guest,sev=0,launch=launch0 \
+ *         .....
+ *
+ */
+
+struct QSevReceiveInfo {
+    Object parent_obj;
+    uint32_t handle;
+    bool flags_ks;
+    char *policy_id;
+    uint8_t nonce[16];
+    uint8_t dh_pub_qx[32];
+    uint8_t dh_pub_qy[32];
+    uint8_t policy_measure[32];
+    uint8_t wrapped_tek[24];
+    uint8_t wrapped_tik[24];
+    uint8_t ten[24];
+};
+
+struct QSevReceiveInfoClass {
+    ObjectClass parent_class;
+};
+
+enum SevLaunchMode {
+    SEV_LAUNCH_INVALID = 0,
+    SEV_LAUNCH_UNENCRYPTED,
+    SEV_LAUNCH_ENCRYPTED
+};
+
+enum SevState {
+    SEV_STATE_INVALID = 0,
+    SEV_STATE_LAUNCHING,
+    SEV_STATE_RECEIVING,
+    SEV_STATE_SENDING,
+    SEV_STATE_RUNNING
+};
+
+struct SEVState {
+    char *launch_id;
+    char *sev_info_id;
+
+    uint8_t mode;
+    uint8_t state;
+    struct kvm_sev_launch_start *launch_start;
+    struct kvm_sev_launch_update *launch_update;
+    struct kvm_sev_launch_finish *launch_finish;
+    struct kvm_sev_receive_start *recv_start;
+    struct kvm_sev_receive_update *recv_update;
+    struct kvm_sev_receive_finish *recv_finish;
+    struct kvm_sev_send_start *send_start;
+    struct kvm_sev_send_update *send_update;
+    struct kvm_sev_send_finish *send_finish;
+};
+
+typedef struct SEVState SEVState;
+
+bool sev_enabled(void);
+bool has_sev_guest_policy(const char *keyid);
+void *sev_guest_init(const char *keyid);
+int sev_guest_launch_start(void *handle);
+int sev_guest_launch_finish(void *handle);
+void sev_guest_set_ops(void *handle, MemoryRegion *mr);
+
+#endif
+
diff --git a/kvm-all.c b/kvm-all.c
index ebf35b0..bb5da88 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -36,6 +36,8 @@
 #include "qemu/event_notifier.h"
 #include "trace.h"
 #include "hw/irq.h"
+#include "sysemu/security-policy.h"
+#include "sysemu/sev.h"
 
 #include "hw/boards.h"
 
@@ -101,6 +103,12 @@ struct KVMState
 #endif
     KVMMemoryListener memory_listener;
     QLIST_HEAD(, KVMParkedVcpu) kvm_parked_vcpus;
+
+    /* memory encryption support */
+    void *mem_encrypt_handle;
+    int (*mem_encrypt_start)(void *handle);
+    int (*mem_encrypt_finish)(void *handle);
+    void (*mem_encrypt_ops)(void *handle, MemoryRegion *mr);
 };
 
 KVMState *kvm_state;
@@ -126,6 +134,42 @@ static const KVMCapabilityInfo kvm_required_capabilites[] = {
     KVM_CAP_LAST_INFO
 };
 
+bool kvm_memory_encryption_enabled(void)
+{
+    return kvm_state->mem_encrypt_handle ? true : false;
+}
+
+int kvm_memory_encryption_start(void)
+{
+    if (kvm_state->mem_encrypt_start) {
+        return kvm_state->mem_encrypt_start(kvm_state->mem_encrypt_handle);
+    }
+
+    return -1;
+}
+
+int kvm_memory_encryption_finish(void)
+{
+    if (kvm_state->mem_encrypt_finish) {
+        return kvm_state->mem_encrypt_finish(kvm_state->mem_encrypt_handle);
+    }
+
+    return -1;
+}
+
+void kvm_memory_encryption_set_memory_region(MemoryRegion *mr)
+{
+    if (kvm_state->mem_encrypt_ops) {
+        return kvm_state->mem_encrypt_ops(kvm_state->mem_encrypt_handle,
+                                          mr);
+    }
+}
+
+void *kvm_memory_encryption_get_handle(void)
+{
+    return kvm_state->mem_encrypt_handle;
+}
+
 int kvm_get_max_memslots(void)
 {
     KVMState *s = KVM_STATE(current_machine->accelerator);
@@ -1745,6 +1789,33 @@ static int kvm_init(MachineState *ms)
 
     kvm_state = s;
 
+    if (ms->security_policy) {
+        char *id;
+
+        /* if security-policy is enabled  then check whether memory encryption
+         * property is defined. If so, enable hardware memory encryption.
+         */
+        id = security_policy_get_memory_encryption_id(ms->security_policy);
+        if (id) {
+
+            /* check if its SEV guest policy */
+            if (has_sev_guest_policy(id)) {
+                kvm_state->mem_encrypt_handle = sev_guest_init(id);
+                if (!kvm_state->mem_encrypt_handle) {
+                    fprintf(stderr,
+                            "failed to initialize Secure Encrypted"
+                            " Virutalization (SEV) guest\n");
+                    goto err;
+                }
+                kvm_state->mem_encrypt_start = sev_guest_launch_start;
+                kvm_state->mem_encrypt_finish = sev_guest_launch_finish;
+                kvm_state->mem_encrypt_ops = sev_guest_set_ops;
+            }
+
+            g_free(id);
+        }
+    }
+
     if (kvm_eventfds_allowed) {
         s->memory_listener.listener.eventfd_add = kvm_mem_ioeventfd_add;
         s->memory_listener.listener.eventfd_del = kvm_mem_ioeventfd_del;
diff --git a/qemu-options.hx b/qemu-options.hx
index b90d6da..7362452 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -3985,7 +3985,111 @@ can be set to the unquie ID of memory encryption object.
 
 On AMD processor, memory encryption is supported via 'sev-guest-info' object.
 
-@end table
+@item -object sev-guest-info,id=@var{id},launch=@var{id}[,send=@var{id}]
+
+Create a Secure Encrypted Virtualization (SEV) guest object, which be used to
+provide the memory encryption support on AMD processors. The id paramerter is
+a unique ID that should be used in security-policy object when creating the
+SEV-enabled guest. 
+
+When creating a SEV guest, 'launch' parameter should be set to the unquire ID
+from SEV launch object.
+
+e.g to launch a SEV guest
+@example
+ # $QEMU \
+     -object sev-launch-info,id=launch0 \
+     -object sev-guest-info,id=sev0,launch=launch0 \
+     -object security-policy,id=secure0-guest,memory-encryption=sev0 \
+     -machine ...,security-policy=secure0
+@end example
+
+@item -object sev-launch-info,id=@var{id}[,flags.ks=@var{bool}][,policy=@var{id}][,nonce=@var{string}][,dh-pub-qx=@var{string}][,dh-pub-qy=@var{string}][,handle=@var{int}]
+
+Create a SEV launch info object, which can be used to pass various parameters
+required to transition an unencrypted guest into SEV-enabled mode.
+The id parameter is a unique ID that should be used in sev-guest-info object
+when creating a unencrypted SEV guest.
+
+The 'flags.ks' parameter should be set when guest owner has requested the key
+sharing with other guests.
+
+The 'nonce' parameter should be set with a nonce generated by guest owner.
+
+The 'dh-pub-qx' and 'dh-pub-qy' parameters should be set with guest owners
+ECDH public key.
+
+The 'policy' parameter should be set to unique ID created from 'sev-policy-info'.
+
+e.g to launch a unencrypted SEV guest
+@example
+ # $QEMU \
+     -object sev-launch-info,id=launch0,flags.ks=off,nonce=xxxx \
+     -object sev-guest-info,id=sev0,launch=launch0 \
+@end example
+
+@item -object sev-receive-info,id=@var{id},measurement=@var{string}[,flags.ks=@var{bool}][,policy=@var{id}][,nonce=@var{string}][,dh-pub-qx=@var{string}][,dh-pub-qy=@var{string}][,handle=@var{int}][,wrapped-tek=@var{string}][,wrapped-tik=@var{string}][,ten=@var{string}]
+
+Create a SEV guest receive info object, which can be used to pass various
+parameters required to receive a encrypted guest. The object can be used for
+both when launching a pre-encrypted guest or receiving a migration.
+The id parameter is a unique ID that should be used in sev-guest-info object
+when creating a encrypted SEV guest.
+
+The 'flags.ks' parameter should be set when guest owner has requested the key
+sharing with other guests.
+
+The 'nonce' parameter should be set with a nonce generated by guest owner.
+
+The 'dh-pub-qx' and 'dh-pub-qy' parameters should be set with guest owners
+ECDH public key.
+
+The 'policy' parameter should be set to unique ID created from 'sev-policy-info.
+
+The 'wrapped-tek' parameter should be set with transport encryption key.
+
+The 'wrapped-tik' parameter should be set with transport identity key.
+
+The 'ten' parameter should be set with transport encryption nonce.
+
+The 'measurement' should be set with measurement of transported guest.
+
+e.g to launch a encrypted SEV guest
+@example
+ # $QEMU \
+     -object sev-receive-info,id=launch0,flags.ks=off,nonce=xxxx \
+     -object sev-guest-info,id=sev0,launch=launch0 \
+@end example
+
+@item -object sev-policy-info,id=@var{id}[,debug=@var{bool}][,ks=@var{bool}][,nosend=@var{bool}][,domain=@var{bool}][,sev=@var{bool}][,fw-major=@var{int}][,fw-minor=@var{int}]
+
+Create SEV guest policy object, which can be used to pass the guest policy
+during SEV guest creation and migration. The id parameter is a unqiue ID that
+should be used in SEV launch and send objects.
+
+The SEV guest policy should be provided by the guest owner.
+
+debug: should be set if guest owner allows the debugging
+
+ks: should be set when guest owner allows sharing the key with other guest
+
+nosend: should be set when guest owner does not allow the platform to be
+        migrated to remote location.
+
+domain: should be set when guest owner does not allow platform to be transmitted
+        to another location that is not in the domain.
+
+sev: should be set when guest should not be transmitted to non SEV platform.
+
+fw_major/minor: guest should not be transmitted to another platform with a
+  lower firmware version.
+
+e.g to create a policy
+@example
+  # $QEMU \
+      -object sev-policy-info,id=policy0,debug=on,ks=off \
+      -object sev-launch-info,id=launch0,policy=policy0 \
+@end example
 
 ETEXI
 
diff --git a/sev.c b/sev.c
new file mode 100644
index 0000000..226ad76
--- /dev/null
+++ b/sev.c
@@ -0,0 +1,1074 @@
+/*
+ * QEMU SEV support
+ *
+ * Copyright Advanced Micro Devices 2016
+ *
+ * Author:
+ *      Brijesh Singh <brijesh.singh@amd.com>
+ *
+ * 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 "qemu/base64.h"
+#include "sysemu/kvm.h"
+#include "sysemu/sev.h"
+#include "trace.h"
+
+#define DEBUG_SEV
+#ifdef DEBUG_SEV
+#define DPRINTF(fmt, ...) \
+    do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0)
+#else
+#define DPRINTF(fmt, ...) \
+    do { } while (0)
+#endif
+
+static MemoryRegionRAMReadWriteOps sev_ops;
+static bool sev_allowed;
+
+static void
+DPRINTF_U8_PTR(const char *msg, uint8_t *ptr, int count)
+{
+    int i;
+
+    DPRINTF("%s = ", msg);
+    for (i = 0; i < count; i++) {
+        DPRINTF("%02hhx", ptr[i]);
+    }
+    DPRINTF("\n");
+}
+
+static void
+str_to_uint8_ptr(const char *str, uint8_t *ptr, int count)
+{
+    int i = 0;
+
+    while (*str && i != count) {
+        sscanf(str, "%2hhx", &ptr[i]);
+        str += 2;
+        i++;
+    }
+}
+
+static char *
+uint8_ptr_to_str(uint8_t *ptr, int count)
+{
+    char *str = g_malloc0(count);
+
+    return memcpy(str, ptr, count);
+}
+
+static Object *
+get_object_by_id(const char *id)
+{
+    Object *obj;
+
+    obj = object_resolve_path_component(
+        object_get_objects_root(), id);
+    if (!obj) {
+        return NULL;
+    }
+
+    return obj;
+
+}
+
+static bool
+qsev_policy_get_debug(Object *obj, Error **errp)
+{
+    QSevPolicyInfo *policy = QSEV_POLICY_INFO(obj);
+
+    return policy->debug;
+}
+
+static void
+qsev_policy_set_debug(Object *obj, bool value, Error **errp)
+{
+    QSevPolicyInfo *policy = QSEV_POLICY_INFO(obj);
+
+    policy->debug = value;
+}
+
+static bool
+qsev_policy_get_ks(Object *obj, Error **errp)
+{
+    QSevPolicyInfo *policy = QSEV_POLICY_INFO(obj);
+
+    return policy->ks;
+}
+
+static void
+qsev_policy_set_ks(Object *obj, bool value, Error **errp)
+{
+    QSevPolicyInfo *policy = QSEV_POLICY_INFO(obj);
+
+    policy->ks = value;
+}
+
+static bool
+qsev_policy_get_nosend(Object *obj, Error **errp)
+{
+    QSevPolicyInfo *policy = QSEV_POLICY_INFO(obj);
+
+    return policy->nosend;
+}
+
+static void
+qsev_policy_set_nosend(Object *obj, bool value, Error **errp)
+{
+    QSevPolicyInfo *policy = QSEV_POLICY_INFO(obj);
+
+    policy->nosend = value;
+}
+
+static bool
+qsev_policy_get_domain(Object *obj, Error **errp)
+{
+    QSevPolicyInfo *policy = QSEV_POLICY_INFO(obj);
+
+    return policy->domain;
+}
+
+static void
+qsev_policy_set_domain(Object *obj, bool value, Error **errp)
+{
+    QSevPolicyInfo *policy = QSEV_POLICY_INFO(obj);
+
+    policy->domain = value;
+}
+
+static bool
+qsev_policy_get_sev(Object *obj, Error **errp)
+{
+    QSevPolicyInfo *policy = QSEV_POLICY_INFO(obj);
+
+    return policy->sev;
+}
+
+static void
+qsev_policy_set_sev(Object *obj, bool value, Error **errp)
+{
+    QSevPolicyInfo *policy = QSEV_POLICY_INFO(obj);
+
+    policy->sev = value;
+}
+
+static void
+qsev_policy_get_fw_major(Object *obj, Visitor *v,
+                         const char *name, void *opaque,
+                         Error **errp)
+{
+    QSevPolicyInfo *policy = QSEV_POLICY_INFO(obj);
+    uint8_t value = policy->fw_major;
+
+    visit_type_uint8(v, name, &value, errp);
+}
+
+static void
+qsev_policy_set_fw_major(Object *obj, Visitor *v,
+                         const char *name, void *opaque,
+                         Error **errp)
+{
+    QSevPolicyInfo *policy = QSEV_POLICY_INFO(obj);
+    Error *error = NULL;
+    uint8_t value;
+
+    visit_type_uint8(v, name, &value, &error);
+    if (error) {
+        return;
+    }
+
+    policy->fw_major = value;
+}
+
+static void
+qsev_policy_get_fw_minor(Object *obj, Visitor *v,
+                         const char *name, void *opaque,
+                         Error **errp)
+{
+    QSevPolicyInfo *policy = QSEV_POLICY_INFO(obj);
+    uint8_t value = policy->fw_minor;
+
+    visit_type_uint8(v, name, &value, errp);
+}
+
+static void
+qsev_policy_set_fw_minor(Object *obj, Visitor *v,
+                         const char *name, void *opaque,
+                         Error **errp)
+{
+    QSevPolicyInfo *policy = QSEV_POLICY_INFO(obj);
+    Error *error = NULL;
+    uint8_t value;
+
+    visit_type_uint8(v, name, &value, &error);
+    if (error) {
+        return;
+    }
+
+    policy->fw_minor = value;
+}
+
+static void
+qsev_policy_class_init(ObjectClass *oc, void *data)
+{
+    object_class_property_add_bool(oc, "debug",
+                                   qsev_policy_get_debug,
+                                   qsev_policy_set_debug,
+                                   NULL);
+    object_class_property_set_description(oc, "debug",
+            "Set on/off if debugging is allowed on this guest",
+            NULL);
+
+    object_class_property_add_bool(oc, "ks",
+                                   qsev_policy_get_ks,
+                                   qsev_policy_set_ks,
+                                   NULL);
+    object_class_property_set_description(oc, "ks",
+            "Set on/off if guest is allowed to share key with others.",
+            NULL);
+
+    object_class_property_add_bool(oc, "nosend",
+                                   qsev_policy_get_nosend,
+                                   qsev_policy_set_nosend,
+                                   NULL);
+    object_class_property_set_description(oc, "nosend",
+            "Set on/off if sending guest to anoter platform is allowed",
+            NULL);
+
+    object_class_property_add_bool(oc, "domain",
+                                   qsev_policy_get_domain,
+                                   qsev_policy_set_domain,
+                                   NULL);
+    object_class_property_set_description(oc, "domain",
+            "Set on/off if guest should not be transmitted to another platform that is not in the same domain.",
+            NULL);
+
+    object_class_property_add_bool(oc, "sev",
+                                   qsev_policy_get_sev,
+                                   qsev_policy_set_sev,
+                                   NULL);
+    object_class_property_set_description(oc, "domain",
+            "Set on/off if guest should not be transmitted to another non SEV platform",
+            NULL);
+
+    object_class_property_add(oc, "fw_major", "uint8",
+                                   qsev_policy_get_fw_major,
+                                   qsev_policy_set_fw_major,
+                                   NULL, NULL, NULL);
+    object_class_property_set_description(oc, "fw_major",
+            "guest must not be transmitted to another platform with a lower firmware version",
+            NULL);
+    object_class_property_add(oc, "fw_minor", "uint8",
+                                   qsev_policy_get_fw_minor,
+                                   qsev_policy_set_fw_minor,
+                                   NULL, NULL, NULL);
+    object_class_property_set_description(oc, "fw_minor",
+            "guest must not be transmitted to another platform with a lower firmware version",
+            NULL);
+}
+
+static void
+qsev_policy_finalize(Object *obj)
+{
+}
+
+static QSevPolicyInfo *
+lookup_sev_policy_info(const char *id)
+{
+    QSevPolicyInfo *policy;
+    Object *obj = get_object_by_id(id);
+
+    if (!obj) {
+        return NULL;
+    }
+
+    policy = (QSevPolicyInfo *)
+        object_dynamic_cast(obj,
+                            TYPE_QSEV_POLICY_INFO);
+    if (!policy) {
+        return NULL;
+    }
+
+    return policy;
+}
+
+static uint32_t
+sev_policy_get_value(const char *id)
+{
+    uint32_t val = 0;
+    QSevPolicyInfo *policy = lookup_sev_policy_info(id);
+
+    if (!policy) {
+        return 0;
+    }
+
+    val = policy->debug;
+    val |= policy->ks << 1;
+    val |= (1 << 2);
+    val |= policy->nosend << 3;
+    val |= policy->domain << 4;
+    val |= policy->sev << 5;
+    val |= policy->fw_major << 16;
+    val |= policy->fw_minor << 24;
+
+    return val;
+}
+
+/* qsev policy */
+static const TypeInfo qsev_policy_info = {
+    .parent = TYPE_OBJECT,
+    .name = TYPE_QSEV_POLICY_INFO,
+    .instance_size = sizeof(QSevPolicyInfo),
+    .instance_finalize = qsev_policy_finalize,
+    .class_size = sizeof(QSevPolicyInfoClass),
+    .class_init = qsev_policy_class_init,
+    .interfaces = (InterfaceInfo[]) {
+        { TYPE_USER_CREATABLE },
+        { }
+    }
+};
+
+static char *
+qsev_guest_get_launch_id(Object *obj, Error **errp)
+{
+    QSevGuestInfo *sev_info = QSEV_GUEST_INFO(obj);
+
+    return g_strdup(sev_info->launch);
+}
+
+static void
+qsev_guest_set_launch_id(Object *obj, const char *value, Error **errp)
+{
+    QSevGuestInfo *sev_info = QSEV_GUEST_INFO(obj);
+
+    sev_info->launch = g_strdup(value);
+}
+
+static char *
+qsev_guest_get_send_id(Object *obj, Error **errp)
+{
+    QSevGuestInfo *sev_info = QSEV_GUEST_INFO(obj);
+
+    return g_strdup(sev_info->send);
+}
+
+static void
+qsev_guest_set_send_id(Object *obj, const char *value, Error **errp)
+{
+    QSevGuestInfo *sev_info = QSEV_GUEST_INFO(obj);
+
+    sev_info->send = g_strdup(value);
+}
+
+static void
+qsev_guest_finalize(Object *obj)
+{
+    QSevGuestInfo *sev_info = QSEV_GUEST_INFO(obj);
+
+    g_free(sev_info->launch);
+    g_free(sev_info->send);
+}
+
+static void
+qsev_guest_class_init(ObjectClass *oc, void *data)
+{
+    object_class_property_add_str(oc, "launch",
+                                  qsev_guest_get_launch_id,
+                                  qsev_guest_set_launch_id,
+                                  NULL);
+    object_class_property_set_description(oc, "launch",
+            "Set the launch object id to use", NULL);
+    object_class_property_add_str(oc, "send",
+                                  qsev_guest_get_send_id,
+                                  qsev_guest_set_send_id,
+                                  NULL);
+    object_class_property_set_description(oc, "send",
+            "Set the send object id to use when migrating the guest", NULL);
+}
+
+static QSevGuestInfo *
+lookup_sev_guest_info(const char *id)
+{
+    Object *obj;
+    QSevGuestInfo *info;
+
+    obj = object_resolve_path_component(
+        object_get_objects_root(), id);
+    if (!obj) {
+        return NULL;
+    }
+
+    info = (QSevGuestInfo *)
+            object_dynamic_cast(obj, TYPE_QSEV_GUEST_INFO);
+    if (!info) {
+        return NULL;
+    }
+
+    return info;
+}
+
+static uint8_t
+sev_guest_info_get_mode(const char *id)
+{
+    uint8_t ret = SEV_LAUNCH_INVALID;
+    Object *obj;
+
+    obj = get_object_by_id(id);
+    if (object_dynamic_cast(obj, TYPE_QSEV_LAUNCH_INFO)) {
+        ret = SEV_LAUNCH_UNENCRYPTED;
+    } else if (object_dynamic_cast(obj, TYPE_QSEV_RECEIVE_INFO)) {
+        ret = SEV_LAUNCH_ENCRYPTED;
+    }
+
+    return ret;
+}
+
+/* sev guest info */
+static const TypeInfo qsev_guest_info = {
+    .parent = TYPE_OBJECT,
+    .name = TYPE_QSEV_GUEST_INFO,
+    .instance_size = sizeof(QSevGuestInfo),
+    .instance_finalize = qsev_guest_finalize,
+    .class_size = sizeof(QSevGuestInfoClass),
+    .class_init = qsev_guest_class_init,
+    .interfaces = (InterfaceInfo[]) {
+        { TYPE_USER_CREATABLE },
+        { }
+    }
+};
+
+static void
+qsev_launch_finalize(Object *obj)
+{
+}
+
+static char *
+qsev_launch_get_policy_id(Object *obj, Error **errp)
+{
+    QSevLaunchInfo *sev_info = QSEV_LAUNCH_INFO(obj);
+
+    return g_strdup(sev_info->policy_id);
+}
+
+static void
+qsev_launch_set_policy_id(Object *obj, const char *value, Error **errp)
+{
+    QSevLaunchInfo *sev_info = QSEV_LAUNCH_INFO(obj);
+
+    sev_info->policy_id = g_strdup(value);
+}
+
+static bool
+qsev_launch_get_flags_ks(Object *obj, Error **errp)
+{
+    QSevLaunchInfo *launch = QSEV_LAUNCH_INFO(obj);
+
+    return launch->flags_ks;
+}
+
+static void
+qsev_launch_set_flags_ks(Object *obj, bool value, Error **errp)
+{
+    QSevLaunchInfo *launch = QSEV_LAUNCH_INFO(obj);
+
+    launch->flags_ks = value;
+}
+
+static char *
+qsev_launch_get_nonce(Object *obj, Error **errp)
+{
+    char *value, *str;
+    QSevLaunchInfo *launch = QSEV_LAUNCH_INFO(obj);
+
+    str = uint8_ptr_to_str(launch->nonce, sizeof(launch->nonce));
+    value = g_strdup(str);
+    g_free(str);
+
+    return value;
+}
+
+static void
+qsev_launch_set_nonce(Object *obj, const char *value, Error **errp)
+{
+    QSevLaunchInfo *launch = QSEV_LAUNCH_INFO(obj);
+
+    str_to_uint8_ptr(value, launch->nonce, sizeof(launch->nonce));
+}
+
+static char *
+qsev_launch_get_dh_pub_qx(Object *obj, Error **errp)
+{
+    char *value, *str;
+    QSevLaunchInfo *launch = QSEV_LAUNCH_INFO(obj);
+
+    str = uint8_ptr_to_str(launch->dh_pub_qx, sizeof(launch->dh_pub_qx));
+    value = g_strdup(str);
+    g_free(str);
+
+    return value;
+}
+
+static void
+qsev_launch_set_dh_pub_qx(Object *obj, const char *value, Error **errp)
+{
+    QSevLaunchInfo *launch = QSEV_LAUNCH_INFO(obj);
+
+    str_to_uint8_ptr(value, launch->dh_pub_qx,
+                     sizeof(launch->dh_pub_qx));
+}
+
+static char *
+qsev_launch_get_dh_pub_qy(Object *obj, Error **errp)
+{
+    char *value, *str;
+    QSevLaunchInfo *launch = QSEV_LAUNCH_INFO(obj);
+
+    str = uint8_ptr_to_str(launch->dh_pub_qy, sizeof(launch->dh_pub_qy));
+    value = g_strdup(str);
+    g_free(str);
+
+    return value;
+}
+
+static void
+qsev_launch_set_dh_pub_qy(Object *obj, const char *value, Error **errp)
+{
+    QSevLaunchInfo *launch = QSEV_LAUNCH_INFO(obj);
+
+    str_to_uint8_ptr(value, launch->dh_pub_qy,
+                     sizeof(launch->dh_pub_qy));
+}
+
+static void
+qsev_launch_class_init(ObjectClass *oc, void *data)
+{
+    object_class_property_add_bool(oc, "flags.ks",
+                                   qsev_launch_get_flags_ks,
+                                   qsev_launch_set_flags_ks,
+                                   NULL);
+    object_class_property_set_description(oc, "flags.ks",
+            "Set on/off if key sharing with other guests is allowed",
+            NULL);
+
+    object_class_property_add_str(oc, "policy",
+                                  qsev_launch_get_policy_id,
+                                  qsev_launch_set_policy_id,
+                                  NULL);
+    object_class_property_set_description(oc, "policy",
+            "Set the guest owner's sev-policy id", NULL);
+
+    object_class_property_add_str(oc, "nonce",
+                                  qsev_launch_get_nonce,
+                                  qsev_launch_set_nonce,
+                                  NULL);
+    object_class_property_set_description(oc, "nonce",
+            "a nonce provided by guest owner", NULL);
+
+    object_class_property_add_str(oc, "dh-pub-qx",
+                                  qsev_launch_get_dh_pub_qx,
+                                  qsev_launch_set_dh_pub_qx,
+                                  NULL);
+    object_class_property_set_description(oc, "dh-pub-qx",
+            "Qx parameter of owner's ECDH public key", NULL);
+
+    object_class_property_add_str(oc, "dh-pub-qy",
+                                  qsev_launch_get_dh_pub_qy,
+                                  qsev_launch_set_dh_pub_qy,
+                                  NULL);
+    object_class_property_set_description(oc, "dh-pub-qy",
+            "Qy parameter of owner's ECDH public key", NULL);
+}
+
+static uint8_t
+sev_launch_info_get_flags(QSevLaunchInfo *launch)
+{
+    uint8_t flags = launch->flags_ks;
+
+    return flags;
+}
+
+static QSevLaunchInfo *
+lookup_sev_launch_info(const char *id)
+{
+    Object *obj;
+    QSevLaunchInfo *info;
+
+    obj = object_resolve_path_component(
+        object_get_objects_root(), id);
+    if (!obj) {
+        return NULL;
+    }
+
+    info = (QSevLaunchInfo *)
+            object_dynamic_cast(obj, TYPE_QSEV_LAUNCH_INFO);
+    if (!info) {
+        return NULL;
+    }
+
+    return info;
+}
+
+static int
+sev_launch_info_get_params(const char *id,
+                           struct kvm_sev_launch_start **s,
+                           struct kvm_sev_launch_update **u,
+                           struct kvm_sev_launch_finish **f)
+{
+    QSevLaunchInfo *info;
+    struct kvm_sev_launch_start *start;
+    struct kvm_sev_launch_finish *finish;
+
+    info = lookup_sev_launch_info(id);
+    if (!info) {
+        return -1;
+    }
+
+    start = g_malloc0(sizeof(*start));
+    start->flags = sev_launch_info_get_flags(info);
+    start->policy = sev_policy_get_value(info->policy_id);
+    memcpy(start->nonce, info->nonce, sizeof(info->nonce));
+    memcpy(start->dh_pub_qx, info->dh_pub_qx, sizeof(info->dh_pub_qx));
+    memcpy(start->dh_pub_qy, info->dh_pub_qy, sizeof(info->dh_pub_qy));
+
+    finish = g_malloc0(sizeof(*finish));
+
+    DPRINTF("sev-launch\n");
+    DPRINTF(" flags: %#x\n", start->flags);
+    DPRINTF(" policy: %#x\n", start->policy);
+    DPRINTF_U8_PTR(" dh_pub_qx", start->dh_pub_qx, sizeof(start->dh_pub_qx));
+    DPRINTF_U8_PTR(" dh_pub_qy", start->dh_pub_qy, sizeof(start->dh_pub_qy));
+    DPRINTF_U8_PTR(" nonce", start->nonce, sizeof(start->nonce));
+
+    *s = start;
+    *u = g_malloc(sizeof(struct kvm_sev_launch_update));
+    *f = finish;
+
+    return 0;
+}
+
+/* unencrypted guest launch */
+static const TypeInfo qsev_launch_info = {
+    .parent = TYPE_OBJECT,
+    .name = TYPE_QSEV_LAUNCH_INFO,
+    .instance_size = sizeof(QSevLaunchInfo),
+    .instance_finalize = qsev_launch_finalize,
+    .class_size = sizeof(QSevLaunchInfoClass),
+    .class_init = qsev_launch_class_init,
+    .interfaces = (InterfaceInfo[]) {
+        { TYPE_USER_CREATABLE },
+        { }
+    }
+};
+
+static void
+qsev_receive_finalize(Object *obj)
+{
+}
+
+static char *
+qsev_receive_get_policy_id(Object *obj, Error **errp)
+{
+    QSevReceiveInfo *sev_info = QSEV_RECEIVE_INFO(obj);
+
+    return g_strdup(sev_info->policy_id);
+}
+
+static void
+qsev_receive_set_policy_id(Object *obj, const char *value, Error **errp)
+{
+    QSevReceiveInfo *sev_info = QSEV_RECEIVE_INFO(obj);
+
+    sev_info->policy_id = g_strdup(value);
+}
+
+static bool
+qsev_receive_get_flags_ks(Object *obj, Error **errp)
+{
+    QSevReceiveInfo *receive = QSEV_RECEIVE_INFO(obj);
+
+    return receive->flags_ks;
+}
+
+static void
+qsev_receive_set_flags_ks(Object *obj, bool value, Error **errp)
+{
+    QSevReceiveInfo *receive = QSEV_RECEIVE_INFO(obj);
+
+    receive->flags_ks = value;
+}
+
+static char *
+qsev_receive_get_nonce(Object *obj, Error **errp)
+{
+    char *value, *str;
+    QSevReceiveInfo *receive = QSEV_RECEIVE_INFO(obj);
+
+    str = uint8_ptr_to_str(receive->nonce, sizeof(receive->nonce));
+    value = g_strdup(str);
+    g_free(str);
+
+    return value;
+}
+
+static void
+qsev_receive_set_nonce(Object *obj, const char *value, Error **errp)
+{
+    QSevReceiveInfo *receive = QSEV_RECEIVE_INFO(obj);
+
+    str_to_uint8_ptr(value, receive->nonce, sizeof(receive->nonce));
+}
+
+static char *
+qsev_receive_get_dh_pub_qx(Object *obj, Error **errp)
+{
+    char *value, *str;
+    QSevReceiveInfo *receive = QSEV_RECEIVE_INFO(obj);
+
+    str = uint8_ptr_to_str(receive->dh_pub_qx, sizeof(receive->dh_pub_qx));
+    value = g_strdup(str);
+    g_free(str);
+
+    return value;
+}
+
+static void
+qsev_receive_set_dh_pub_qx(Object *obj, const char *value, Error **errp)
+{
+    QSevReceiveInfo *receive = QSEV_RECEIVE_INFO(obj);
+
+    str_to_uint8_ptr(value, receive->dh_pub_qx,
+                     sizeof(receive->dh_pub_qx));
+}
+
+static char *
+qsev_receive_get_dh_pub_qy(Object *obj, Error **errp)
+{
+    char *value, *str;
+    QSevReceiveInfo *receive = QSEV_RECEIVE_INFO(obj);
+
+    str = uint8_ptr_to_str(receive->dh_pub_qy, sizeof(receive->dh_pub_qy));
+    value = g_strdup(str);
+    g_free(str);
+
+    return value;
+}
+
+static void
+qsev_receive_set_dh_pub_qy(Object *obj, const char *value, Error **errp)
+{
+    QSevReceiveInfo *receive = QSEV_RECEIVE_INFO(obj);
+
+    str_to_uint8_ptr(value, receive->dh_pub_qy,
+                     sizeof(receive->dh_pub_qy));
+}
+
+static char *
+qsev_receive_get_ten(Object *obj, Error **errp)
+{
+    char *value, *str;
+    QSevReceiveInfo *receive = QSEV_RECEIVE_INFO(obj);
+
+    str = uint8_ptr_to_str(receive->ten, sizeof(receive->ten));
+    value = g_strdup(str);
+    g_free(str);
+
+    return value;
+}
+
+static void
+qsev_receive_set_ten(Object *obj, const char *value, Error **errp)
+{
+    QSevReceiveInfo *receive = QSEV_RECEIVE_INFO(obj);
+
+    str_to_uint8_ptr(value, receive->ten,
+                     sizeof(receive->ten));
+}
+
+static char *
+qsev_receive_get_wrapped_tik(Object *obj, Error **errp)
+{
+    char *value, *str;
+    QSevReceiveInfo *receive = QSEV_RECEIVE_INFO(obj);
+
+    str = uint8_ptr_to_str(receive->wrapped_tik, sizeof(receive->wrapped_tik));
+    value = g_strdup(str);
+    g_free(str);
+
+    return value;
+}
+
+static void
+qsev_receive_set_wrapped_tik(Object *obj, const char *value, Error **errp)
+{
+    QSevReceiveInfo *receive = QSEV_RECEIVE_INFO(obj);
+
+    str_to_uint8_ptr(value, receive->wrapped_tik,
+                     sizeof(receive->wrapped_tik));
+}
+
+static char *
+qsev_receive_get_wrapped_tek(Object *obj, Error **errp)
+{
+    char *value, *str;
+    QSevReceiveInfo *receive = QSEV_RECEIVE_INFO(obj);
+
+    str = uint8_ptr_to_str(receive->wrapped_tek, sizeof(receive->wrapped_tek));
+    value = g_strdup(str);
+    g_free(str);
+
+    return value;
+}
+
+static void
+qsev_receive_set_wrapped_tek(Object *obj, const char *value, Error **errp)
+{
+    QSevReceiveInfo *receive = QSEV_RECEIVE_INFO(obj);
+
+    str_to_uint8_ptr(value, receive->wrapped_tek,
+                     sizeof(receive->wrapped_tek));
+}
+
+static void
+qsev_receive_class_init(ObjectClass *oc, void *data)
+{
+    object_class_property_add_bool(oc, "flags.ks",
+                                   qsev_receive_get_flags_ks,
+                                   qsev_receive_set_flags_ks,
+                                   NULL);
+    object_class_property_set_description(oc, "flags.ks",
+            "Set on/off if key sharing with other guests is allowed",
+            NULL);
+
+    object_class_property_add_str(oc, "policy",
+                                  qsev_receive_get_policy_id,
+                                  qsev_receive_set_policy_id,
+                                  NULL);
+    object_class_property_set_description(oc, "policy",
+            "Set the guest origin sev-policy id", NULL);
+
+    object_class_property_add_str(oc, "nonce",
+                                  qsev_receive_get_nonce,
+                                  qsev_receive_set_nonce,
+                                  NULL);
+    object_class_property_set_description(oc, "nonce",
+            "a nonce provided by origin", NULL);
+
+    object_class_property_add_str(oc, "dh-pub-qx",
+                                  qsev_receive_get_dh_pub_qx,
+                                  qsev_receive_set_dh_pub_qx,
+                                  NULL);
+    object_class_property_set_description(oc, "dh-pub-qx",
+            "Qx parameter of origin ECDH public key", NULL);
+
+    object_class_property_add_str(oc, "dh-pub-qy",
+                                  qsev_receive_get_dh_pub_qy,
+                                  qsev_receive_set_dh_pub_qy,
+                                  NULL);
+    object_class_property_set_description(oc, "dh-pub-qy",
+            "Qy parameter of origin ECDH public key", NULL);
+
+    object_class_property_add_str(oc, "ten",
+                                  qsev_receive_get_ten,
+                                  qsev_receive_set_ten,
+                                  NULL);
+    object_class_property_set_description(oc, "ten",
+            "Set transport encryption nonce", NULL);
+
+    object_class_property_add_str(oc, "wrapped-tik",
+                                  qsev_receive_get_wrapped_tik,
+                                  qsev_receive_set_wrapped_tik,
+                                  NULL);
+    object_class_property_set_description(oc, "wrapped-tik",
+            "The wrapped transport identity key", NULL);
+
+    object_class_property_add_str(oc, "wrapped-tek",
+                                  qsev_receive_get_wrapped_tek,
+                                  qsev_receive_set_wrapped_tek,
+                                  NULL);
+    object_class_property_set_description(oc, "wrapped-tek",
+            "The wrapped transport encryption key", NULL);
+}
+
+/* pre-encrypted guest launch */
+static const TypeInfo qsev_receive_info = {
+    .parent = TYPE_OBJECT,
+    .name = TYPE_QSEV_RECEIVE_INFO,
+    .instance_size = sizeof(QSevReceiveInfo),
+    .instance_finalize = qsev_receive_finalize,
+    .class_size = sizeof(QSevReceiveInfoClass),
+    .class_init = qsev_receive_class_init,
+    .interfaces = (InterfaceInfo[]) {
+        { TYPE_USER_CREATABLE },
+        { }
+    }
+};
+
+static int
+sev_launch_start(SEVState *s)
+{
+    int ret;
+
+    ret = sev_launch_info_get_params(s->launch_id, &s->launch_start,
+                                     &s->launch_update, &s->launch_finish);
+    if (ret < 0) {
+        return -1;
+    }
+
+    // add the command to launch guest in next patches
+    return 0;
+}
+
+static int
+sev_launch_finish(SEVState *s)
+{
+    // add the command to finalize the launch in next patches
+    return 0;
+}
+
+/**
+ * Function returns 'true' if id is a valid QSevGuestInfo object.
+ */
+bool
+has_sev_guest_policy(const char *id)
+{
+    return lookup_sev_guest_info(id) ? true : false;
+}
+
+void *
+sev_guest_init(const char *id)
+{
+    int ret;
+    SEVState *s;
+    QSevGuestInfo *sev_info;
+
+    s = g_malloc0(sizeof(SEVState));
+    if (!s) {
+        return NULL;
+    }
+
+    sev_info = lookup_sev_guest_info(id);
+    if (!sev_info) {
+        fprintf(stderr, "'%s' not a valid '%s' object\n",
+                id, TYPE_QSEV_GUEST_INFO);
+        goto err;
+    }
+
+    s->mode = sev_guest_info_get_mode(sev_info->launch);
+    if (s->mode == SEV_LAUNCH_INVALID) {
+        fprintf(stderr, "'%s' invalid sev launch id\n", sev_info->launch);
+        goto err;
+    }
+
+    s->sev_info_id = g_strdup(id);
+    s->launch_id = g_strdup(sev_info->launch);
+
+    /* now launch the guest */
+    ret = sev_guest_launch_start(s);
+    if (ret < 0) {
+        goto err;
+    }
+
+    sev_allowed = true;
+    return s;
+err:
+    g_free(s);
+
+    return NULL;
+}
+
+int
+sev_guest_launch_start(void *handle)
+{
+    SEVState *s = (SEVState *)handle;
+
+    if (s->state == SEV_STATE_RUNNING) {
+        return 0;
+    }
+
+    if (s->mode == SEV_LAUNCH_UNENCRYPTED) {
+        return sev_launch_start(s);
+    } else if (s->mode == SEV_LAUNCH_ENCRYPTED) {
+        // use receive_info commands
+    }
+
+    return -1;
+}
+
+int
+sev_guest_launch_finish(void *handle)
+{
+    SEVState *s = (SEVState *)handle;
+
+    if (s->state == SEV_STATE_RUNNING) {
+        return 0;
+    }
+
+    if (s->state == SEV_STATE_LAUNCHING) {
+        return sev_launch_finish(s);
+        // use launch_finish commands
+    } else if (s->state == SEV_STATE_RECEIVING) {
+        // use receive_finish commands
+    } else {
+        return -1;
+    }
+
+    return -1;
+}
+
+static int
+sev_mem_write(uint8_t *dst, const uint8_t *src, uint32_t len, MemTxAttrs attrs)
+{
+    SEVState *s = kvm_memory_encryption_get_handle();
+
+    assert(s != NULL);
+
+    // fill in the code in next patches
+    return 0;
+}
+
+static int
+sev_mem_read(uint8_t *dst, const uint8_t *src, uint32_t len, MemTxAttrs attrs)
+{
+    SEVState *s = kvm_memory_encryption_get_handle();
+
+    assert(s != NULL);
+
+    // fill in the code in next patches
+    return 0;
+}
+
+void
+sev_guest_set_ops(void *handle, MemoryRegion *mr)
+{
+    SEVState *s = (SEVState *)handle;
+
+    assert(s != NULL);
+
+    sev_ops.read = sev_mem_read;
+    sev_ops.write = sev_mem_write;
+
+    memory_region_set_ram_ops(mr, &sev_ops);
+}
+
+bool
+sev_enabled(void)
+{
+    return sev_allowed;
+}
+
+static void
+sev_policy_register_types(void)
+{
+    type_register_static(&qsev_guest_info);
+    type_register_static(&qsev_policy_info);
+    type_register_static(&qsev_launch_info);
+    type_register_static(&qsev_receive_info);
+}
+
+type_init(sev_policy_register_types);
