diff --git a/Makefile.target b/Makefile.target
index 7a5080e..004c3cd 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -137,7 +137,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..682f8e9
--- /dev/null
+++ b/docs/amd-memory-encryption.txt
@@ -0,0 +1,153 @@
+Secure Encrypted Virtualization (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  Secure
+Processor firmware which exposes commands for these tasks.
+
+At highest level the SEV key management APIs are divided into two sections:
+
+* Platform management commands
+* Guest management commands
+
+In this doc we will focus on Guest management commands. 
+
+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 deployment of SEV guest: the guest owner and
+the platform owner. For example, in a cloud environment, the platform owner
+would be cloud vendor and the guest owner would be the user that wishes to run
+their workload in the cloud.
+
+1. Guest Management Commands
+-----------------------------
+
+The guest management commands provide the support for common guest lifecycle
+events. These events include launching, running, snapshotting, migrating and
+decommission guest. The guest management commands are issued through
+KVM_SEV_ISSUE_CMD ioctl.
+
+1.1 Launch
+
+When a guest is launched, its memory must first be encrypted using guest owners
+key before SEV can be enabled in hardware. There are two types of launches:
+
+1.1.1 unencrypted
+
+Boot images (such as bios, kernel, initrd) provided by the guest owner to
+bootstrap the guest is unencrypted. The firmware provides interfaces to
+bootstrap the memory encryption for this purpose: LAUNCH_START, LAUNCH_UPDATE,
+and LAUNCH_FINISH. These three commands together generate a fresh memory
+encryption key for the guest, encrypt guest memory and provide an attestation
+of the successful launch.
+
+LAUNCH_START is called first to create a guest context within the firmware.
+To create this context, qemu user must provide guest's security policy, guest
+owners public Diffie-Hellman key (P-256 defined in section D.1.2.3 of
+[FIPS 186-4]) and nonce. The guest security policy is a 4-byte data structure
+containing several flags that restrict what the hypervisor can do on the running
+SEV guest. The guest security policy should be provided by the guest owner, any
+changes in policy by hypervisor would result in the wrong measurement. The policy
+is applied to the lifetime of the guest. Guest owners public diffie-hellman (pdh)
+key is used to establish a cryptographic session with the guest owner to
+negotiate keys used for attestation. If the hypervisor requests this guest to
+share key with another SEV guest then hypervisor must set 'key-sharing' and
+'handle' in LAUNCH_START command. The key sharing is permitted only if guest
+policy allows it.
+
+LAUNCH_UPDATE encrypts the memory region using the cryptographic context created
+via LAUNCH_START command. If required this command can be called multiple times
+to encrypt different memory regions. The command also calculates the measurement
+of the memory contents as it encrypts.
+
+LAUNCH_FINISH command finalizes the guest launch and generates measurement.
+This measurement is a signature of the memory contents that can be sent to the
+guest owner as an attestation that the memory was encrypted correctly by the
+firmware. The guest owner may wait to provide the guest confidential information
+until it can verify the attestation measurement. Since the guest owner knows the
+initial contents of the guest at boot, the attestation measurement can be
+verified by comparing it to what the guest owner expects.
+
+SEV support can be enabled via 'memory-encryption' parameters defined in
+security-policy object. If memory-encryption is enabled, then hypervisor
+uses MemoryRegionReadWriteOps callbacks to access guest memory.
+
+Before vm_start, rom_reset copies boot images from internal rom to guest memory
+as shown below.
+
+                       +----------------------+
+                       |   qemu_system_reset  |
+                       +----------------------+
+                                |
+                                |
+                                V
+                    +-----------------------------+
+                    |      rom_reset (loader.c)   |
+                    +-----------------------------+
+                           |    |      |
+       +-------------------+    |      +-----------------+
+       |                        |                        |
+       V                        V                        V
+  +--------------+      +------------------+       +----------------+
+  | LAUNCH_START |      | memory_rom_write |       | LAUNCH_FINISH  |
+  +--------------+      +------------------+       +----------------+
+                                |
+                                | 
+                                V
+                         +------------------+
+                         |  LAUNCH_UPDATE   |
+                         +------------------+
+
+Input to LAUNCH_START command can be provided through the properties defined in
+'sev-launch-info' object.
+
+e.g to launch SEV guest from unencrypted boot images
+
+# ${QEMU} \
+      -object sev-launch-info,id=launch0,dh-pub-qx=abcd,dh-pub-qy=1234,nonce=1234\
+      -object sev-guest,id=sev0\
+      -object security-policy,id=mypolicy,memory-encryption=sev0\
+      -machine ...,security-policy=mypolicy
+
+e.g launch this SEV guest using another SEV guest key (key sharing)
+
+# ${QEMU} \
+      -object sev-launch-info,id=launch0,key-sharing=on,handle=1234\
+      -object sev-guest,id=sev0\
+      -object security-policy,id=mypolicy,memory-encryption=sev0\
+      -machine ...,security-policy=mypolicy
+
+1.1.2 pre-encrypted
+
+1.2 Snapshot
+
+1.3 Restore
+
+1.4 Live Migration
+
+1.5 Debugging
+
+Since memory contents of SEV guest is encrypted hence hypervisor access to the
+guest memory will get a cipher text. If guest policy allows debugging, then
+hypervisor is allowed to access guest memory. Hypervisor can use DEBUG_DECRYPT
+command to decrypt guest memory region for debug purposes. Similarly hypervisor
+can use DEBUG_ENCRYPT command to write into guest memory.
+
+2. References
+-----------------
+
+AMD Memory Encryption whitepaper:
+http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2013/12/AMD_Memory_Encryption_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
diff --git a/include/sysemu/sev.h b/include/sysemu/sev.h
new file mode 100644
index 0000000..5ca39d1
--- /dev/null
+++ b/include/sysemu/sev.h
@@ -0,0 +1,112 @@
+/*
+ * 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_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 a SEV
+ * guest from unnencrypted boot images. SEV will encrypt the boot images using
+ * guest owner's key before launching the guest.
+ *
+ * # $QEMU -object sev-launch-info,id=launch0,dh-pub-qx=abcd \
+ *         ....
+ */
+struct QSevLaunchInfo {
+    Object parent_obj;
+    char *nonce;
+    char *dh_pub_qx;
+    char *dh_pub_qy;
+};
+
+struct QSevLaunchInfoClass {
+    ObjectClass parent_class;
+};
+
+#define TYPE_QSEV_GUEST_INFO "sev-guest"
+#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 is used for creating a SEV guest.
+ *
+ * e.g to launch a SEV guest from unencrypted boot images
+ *
+ * # $QEMU -object sev-launch-info,id=launch0 \
+ *         -object sev-guest,id=sev0 \
+ *         -object security-policy,id=secure0,memory-encryption=sev0 \
+ *         -machine ...security-policy=secure0
+ */
+struct QSevGuestInfo {
+    Object parent_obj;
+
+    QSevLaunchInfo *launch_info;
+};
+
+struct QSevGuestInfoClass {
+    ObjectClass parent_class;
+};
+
+struct SEVState {
+    uint8_t state;
+    QSevGuestInfo *sev_info;
+};
+
+typedef struct SEVState SEVState;
+
+enum {
+    INVALID_TYPE = 0,
+    USE_LAUNCH_INFO,
+    USE_RECEIVE_INFO
+};
+
+enum {
+    SEV_STATE_INVALID = 0,
+    SEV_STATE_LAUNCHING,
+    SEV_STATE_RECEIVING,
+    SEV_STATE_SENDING,
+    SEV_STATE_RUNNING
+};
+
+bool sev_enabled(void);
+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_debug_ops(void *handle, MemoryRegion *mr);
+int sev_guest_mem_dec(void *handle, uint8_t *dst,
+        const uint8_t *src, uint32_t len);
+int sev_guest_mem_enc(void *handle, uint8_t *dst,
+        const uint8_t *src, uint32_t len);
+
+#endif
+
diff --git a/kvm-all.c b/kvm-all.c
index 86c810e..e712b96 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -37,6 +37,7 @@
 #include "trace.h"
 #include "hw/irq.h"
 #include "sysemu/security-policy.h"
+#include "sysemu/sev.h"
 
 #include "hw/boards.h"
 
@@ -1818,6 +1819,31 @@ 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 */
+            kvm_state->ehandle = sev_guest_init(id);
+            if (!kvm_state->ehandle) {
+                fprintf(stderr,
+                        "failed to initialize 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_debug_ops = sev_guest_set_debug_ops;
+            kvm_state->mem_encrypt_dec = sev_guest_mem_dec;
+            kvm_state->mem_encrypt_enc = sev_guest_mem_enc;
+            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 7a65015..1c1f93d 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -4048,6 +4048,40 @@ can be set to the unquie ID of memory encryption object.
 
 On AMD processor, memory encryption is supported via 'sev-guest' object.
 
+@item -object sev-guest,id=@var{id}
+
+Create a Secure Encrypted Virtualization (SEV) guest object, which be used to
+provide the memory encryption support on AMD processors.
+
+e.g to launch a SEV guest
+@example
+ # $QEMU \
+     -object sev-launch-info,id=launch0 \
+     -object sev-guest-info,id=sev0 \
+     -object security-policy,id=secure0-guest,memory-encryption=sev0 \
+     -machine ...,security-policy=secure0
+@end example
+
+@item -object sev-launch-info,id=@var{id}[,nonce=@var{string}][,dh-pub-qx=@var{string}][,dh-pub-qy=@var{string}]
+
+Create a SEV launch info object, which can be used to pass various parameters
+required to boot SEV guest from  unencrypted boot images.
+The id parameter is a unique ID that should be used in sev-guest-info object
+when creating a unencrypted SEV guest.
+
+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.
+
+e.g to launch SEV guest from unencrypted boot images
+@example
+ # $QEMU \
+     -object sev-launch-info,id=launch0,nonce=abcd \
+     -object sev-guest,id=sev0 \
+@end example
+
+@end table
 ETEXI
 
 
diff --git a/sev.c b/sev.c
new file mode 100644
index 0000000..487dba6
--- /dev/null
+++ b/sev.c
@@ -0,0 +1,350 @@
+/*
+ * 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 "sysemu/sysemu.h"
+#include "trace.h"
+
+#define DEBUG_SEV
+#ifdef DEBUG_SEV
+#define DPRINTF(fmt, ...) \
+    do { fprintf(stdout, fmt, ## __VA_ARGS__); } while (0)
+#else
+#define DPRINTF(fmt, ...) \
+    do { } while (0)
+#endif
+
+static MemoryRegionRAMReadWriteOps sev_ops;
+static bool sev_allowed;
+
+static void
+qsev_guest_finalize(Object *obj)
+{
+}
+
+static void
+qsev_guest_class_init(ObjectClass *oc, void *data)
+{
+}
+
+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 void
+qsev_guest_init(Object *obj)
+{
+    QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
+
+    object_property_add_link(obj, "launch", TYPE_QSEV_LAUNCH_INFO,
+                             (Object **)&sev->launch_info,
+                             object_property_allow_set_link,
+                             OBJ_PROP_LINK_UNREF_ON_RELEASE, NULL);
+}
+
+/* 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,
+    .instance_init = qsev_guest_init,
+    .interfaces = (InterfaceInfo[]) {
+        { TYPE_USER_CREATABLE },
+        { }
+    }
+};
+
+static void
+qsev_launch_finalize(Object *obj)
+{
+}
+
+static char *
+qsev_launch_get_nonce(Object *obj, Error **errp)
+{
+    QSevLaunchInfo *launch = QSEV_LAUNCH_INFO(obj);
+
+    return g_strdup(launch->nonce);
+}
+
+static void
+qsev_launch_set_nonce(Object *obj, const char *value, Error **errp)
+{
+    QSevLaunchInfo *launch = QSEV_LAUNCH_INFO(obj);
+
+    launch->nonce = g_strdup(value);
+}
+
+static char *
+qsev_launch_get_dh_pub_qx(Object *obj, Error **errp)
+{
+    QSevLaunchInfo *launch = QSEV_LAUNCH_INFO(obj);
+
+    return g_strdup(launch->dh_pub_qx);
+}
+
+static void
+qsev_launch_set_dh_pub_qx(Object *obj, const char *value, Error **errp)
+{
+    QSevLaunchInfo *launch = QSEV_LAUNCH_INFO(obj);
+
+    launch->dh_pub_qx = g_strdup(value);
+}
+
+static char *
+qsev_launch_get_dh_pub_qy(Object *obj, Error **errp)
+{
+    QSevLaunchInfo *launch = QSEV_LAUNCH_INFO(obj);
+
+    return g_strdup(launch->dh_pub_qy);
+}
+
+static void
+qsev_launch_set_dh_pub_qy(Object *obj, const char *value, Error **errp)
+{
+    QSevLaunchInfo *launch = QSEV_LAUNCH_INFO(obj);
+
+    launch->dh_pub_qy = g_strdup(value);
+}
+
+static void
+qsev_launch_class_init(ObjectClass *oc, void *data)
+{
+    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 void
+qsev_launch_init(Object *obj)
+{
+}
+
+/* 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,
+    .instance_init = qsev_launch_init,
+    .interfaces = (InterfaceInfo[]) {
+        { TYPE_USER_CREATABLE },
+        { }
+    }
+};
+
+
+static int
+sev_launch_start(SEVState *s)
+{
+    return 0;
+}
+
+static int
+sev_launch_finish(SEVState *s)
+{
+    return 0;
+}
+
+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 && s->state != SEV_STATE_INVALID);
+
+    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 && s->state != SEV_STATE_INVALID);
+
+    return 0;
+}
+
+static int
+sev_get_launch_type(SEVState *s)
+{
+    QSevGuestInfo *sev_info = s->sev_info;
+
+    /* if <link>QSevLaunchInfo is set then we are configured to use
+     * launch_info object.
+     */
+    if (object_property_get_link(OBJECT(sev_info), "launch", &error_abort)) {
+        return USE_LAUNCH_INFO;
+    }
+
+    return INVALID_TYPE;
+}
+
+void *
+sev_guest_init(const char *id)
+{
+    Object *obj;
+    SEVState *s;
+
+    s = g_malloc0(sizeof(SEVState));
+    if (!s) {
+        return NULL;
+    }
+
+    s->sev_info = lookup_sev_guest_info(id);
+    if (!s->sev_info) {
+        fprintf(stderr, "'%s' not a valid '%s' object\n",
+                id, TYPE_QSEV_GUEST_INFO);
+        goto err;
+    }
+
+    obj = object_resolve_path_type("", TYPE_QSEV_LAUNCH_INFO, NULL);
+    if (obj) {
+        object_property_set_link(OBJECT(s->sev_info), obj, "launch",
+                &error_abort);
+    }
+
+    sev_allowed = true;
+    return s;
+err:
+    g_free(s);
+    return NULL;
+}
+
+int
+sev_guest_launch_start(void *handle)
+{
+    SEVState *s = (SEVState *)handle;
+
+    assert(s != NULL);
+
+    /* If we are in prelaunch state then create memory encryption context based
+     * on the sev launch object created by user.
+     */
+    if (runstate_check(RUN_STATE_PRELAUNCH)) {
+        if (sev_get_launch_type(s) == USE_LAUNCH_INFO) {
+            return sev_launch_start(s);
+        }
+    }
+
+    return 1;
+}
+
+int
+sev_guest_launch_finish(void *handle)
+{
+    SEVState *s = (SEVState *)handle;
+
+    assert(s != NULL);
+
+    if (s->state == SEV_STATE_LAUNCHING) {
+        return sev_launch_finish(s);
+    }
+
+    return 1;
+}
+
+void
+sev_guest_set_debug_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_debug_ops(mr, &sev_ops);
+}
+
+int
+sev_guest_mem_dec(void *handle, uint8_t *dst, const uint8_t *src, uint32_t len)
+{
+    SEVState *s = (SEVState *)handle;
+
+    assert(s != NULL && s->state != SEV_STATE_INVALID);
+
+    /* use SEV debug command to decrypt memory */
+    return 1;
+}
+
+int
+sev_guest_mem_enc(void *handle, uint8_t *dst, const uint8_t *src, uint32_t len)
+{
+    SEVState *s = (SEVState *)handle;
+
+    assert(s != NULL && s->state != SEV_STATE_INVALID);
+
+    /* use SEV debug command to decrypt memory */
+    return 1;
+}
+
+bool
+sev_enabled(void)
+{
+    return sev_allowed;
+}
+
+static void
+sev_policy_register_types(void)
+{
+    type_register_static(&qsev_guest_info);
+    type_register_static(&qsev_launch_info);
+}
+
+type_init(sev_policy_register_types);
