diff --git a/.gitignore b/.gitignore
index ab765a5cdd..017856c93e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -308,6 +308,7 @@ xen/include/xen/acm_policy.h
 xen/include/xen/compile.h
 xen/include/xen/lib/x86/cpuid-autogen.h
 xen/test/livepatch/config.h
+xen/test/livepatch/expect_config.h
 xen/test/livepatch/*.livepatch
 xen/tools/kconfig/.tmp_gtkcheck
 xen/tools/kconfig/.tmp_qtcheck
diff --git a/docs/misc/livepatch.pandoc b/docs/misc/livepatch.pandoc
index 02348dd49e..4f9238d235 100644
--- a/docs/misc/livepatch.pandoc
+++ b/docs/misc/livepatch.pandoc
@@ -300,10 +300,11 @@ which describe the functions to be patched:
         /* Added to livepatch payload version 2: */
         uint8_t applied;
         uint8_t _pad[7];
+        livepatch_expectation_t expect;
     };
 
-The size of the structure is 64 bytes on 64-bit hypervisors. It will be
-52 on 32-bit hypervisors.
+The size of the structure is 104 bytes on 64-bit hypervisors. It will be
+92 on 32-bit hypervisors.
 The version 2 of the payload adds additional 8 bytes to the structure size.
 
  * `name` is the symbol name of the old function. Only used if `old_addr` is
@@ -336,6 +337,28 @@ The version 2 of the payload adds the following fields to the structure:
   * `applied` tracks function's applied/reverted state. It has a boolean type
     either LIVEPATCH_FUNC_NOT_APPLIED or LIVEPATCH_FUNC_APPLIED.
   * `_pad[7]` adds padding to align to 8 bytes.
+  * `expect` is an optional structure containing expected to-be-replaced data
+    (mostly for inline asm patching). The `expect` structure format is:
+
+    struct livepatch_expectation {
+        uint8_t enabled : 1;
+        uint8_t len : 5;
+        uint8_t rsv: 2;
+        uint8_t data[LIVEPATCH_OPAQUE_SIZE]; /* Same size as opaque[] buffer of
+                                            struct livepatch_func. This is the
+                                            max number of bytes to be patched */
+    };
+    typedef struct livepatch_expectation livepatch_expectation_t;
+
+    * `enabled` allows to enable the expectation check for given function.
+      Default state is disabled.
+    * `len` specifies the number of valid bytes in `data` array. 5 bits is
+      enough to specify values up to 32 (of bytes), which is above the array
+      size.
+    * `rsv` reserved bitfields. **MUST** be zero.
+    * `data` contains expected bytes of content to be replaced. Same size as
+      `opaque` buffer of `struct livepatch_func` (max number of bytes to be
+      patched).
 
 The size of the `livepatch_func` array is determined from the ELF section
 size.
@@ -391,6 +414,7 @@ A simple example of what a payload file can be:
         /* Added to livepatch payload version 2: */
         uint8_t applied;
         uint8_t _pad[7];
+        livepatch_expectation_t expect;
     };
 
     /* Our replacement function for xen_extra_version. */
@@ -408,6 +432,13 @@ A simple example of what a payload file can be:
         .old_addr = (void *)0xffff82d08013963c, /* Extracted from xen-syms. */
         .new_size = 13, /* To be be computed by scripts. */
         .old_size = 13, /* -----------""---------------  */
+        /* Added to livepatch payload version 2: */
+        .expect = { /* All fields to be filled manually */
+            .enabled = 1,
+            .len = 5,
+            .rsv = 0,
+            .data = { 0x48, 0x8d, 0x05, 0x33, 0x1C }
+        },
     } __attribute__((__section__(".livepatch.funcs")));
 
 Code must be compiled with `-fPIC`.
diff --git a/xen/common/livepatch.c b/xen/common/livepatch.c
index 62827f96a8..1c3c446220 100644
--- a/xen/common/livepatch.c
+++ b/xen/common/livepatch.c
@@ -560,6 +560,61 @@ static int check_patching_sections(const struct livepatch_elf *elf)
     return 0;
 }
 
+static inline int livepatch_verify_expectation_fn(const struct livepatch_func *func)
+{
+    const livepatch_expectation_t *exp = &func->expect;
+
+    /* Ignore disabled expectations. */
+    if ( !exp->enabled )
+        return 0;
+
+    /* There is nothing to expect */
+    if ( !func->old_addr )
+        return -EFAULT;
+
+    if ( exp->len > sizeof(exp->data))
+        return -EOVERFLOW;
+
+    if ( exp->rsv )
+        return -EINVAL;
+
+    /* Incorrect expectation */
+    if ( func->old_size < exp->len )
+        return -ERANGE;
+
+    if ( memcmp(func->old_addr, exp->data, exp->len) )
+    {
+        printk(XENLOG_ERR LIVEPATCH "%s: expectation failed: expected:%*phN, actual:%*phN\n",
+               func->name, exp->len, exp->data, exp->len, func->old_addr);
+        return -EINVAL;
+    }
+
+    return 0;
+}
+
+static inline int livepatch_check_expectations(const struct payload *payload)
+{
+    int i, rc;
+
+    printk(XENLOG_INFO LIVEPATCH "%s: Verifying enabled expectations for all functions\n",
+           payload->name);
+
+    for ( i = 0; i < payload->nfuncs; i++ )
+    {
+        const struct livepatch_func *func = &(payload->funcs[i]);
+
+        rc = livepatch_verify_expectation_fn(func);
+        if ( rc )
+        {
+            printk(XENLOG_ERR LIVEPATCH "%s: expectations of %s failed (rc=%d), aborting!\n",
+                   payload->name, func->name ?: "unknown", rc);
+            return rc;
+        }
+    }
+
+    return 0;
+}
+
 /*
  * Lookup specified section and when exists assign its address to a specified hook.
  * Perform section pointer and size validation: single hook sections must contain a
@@ -1344,6 +1399,20 @@ static void livepatch_do_action(void)
 
         if ( rc == 0 )
         {
+            /*
+             * Make sure all expectation requirements are met.
+             * Beware all the payloads are reverted at this point.
+             * If expectations are not met the system is left in a
+             * completely UNPATCHED state!
+             */
+            rc = livepatch_check_expectations(data);
+            if ( rc )
+            {
+                printk(XENLOG_ERR LIVEPATCH "%s: SYSTEM MIGHT BE INSECURE: "
+                       "Replace action has been aborted after reverting ALL payloads!\n", data->name);
+                break;
+            }
+
             if ( is_hook_enabled(data->hooks.apply.action) )
             {
                 printk(XENLOG_INFO LIVEPATCH "%s: Calling apply action hook function\n", data->name);
@@ -1800,6 +1869,11 @@ static int livepatch_action(struct xen_sysctl_livepatch_action *action)
                     break;
             }
 
+            /* Make sure all expectation requirements are met. */
+            rc = livepatch_check_expectations(data);
+            if ( rc )
+                break;
+
             if ( is_hook_enabled(data->hooks.apply.pre) )
             {
                 printk(XENLOG_INFO LIVEPATCH "%s: Calling pre-apply hook function\n", data->name);
diff --git a/xen/include/public/sysctl.h b/xen/include/public/sysctl.h
index 4f52ad581f..ec6f16f0e6 100644
--- a/xen/include/public/sysctl.h
+++ b/xen/include/public/sysctl.h
@@ -840,6 +840,19 @@ struct xen_sysctl_cpu_featureset {
  * We guard this with __XEN__ as toolstacks SHOULD not use it.
  */
 #ifdef __XEN__
+#define LIVEPATCH_OPAQUE_SIZE 31
+
+struct livepatch_expectation {
+    uint8_t enabled : 1;
+    uint8_t len : 5;        /* Length of data up to LIVEPATCH_OPAQUE_SIZE
+                               (5 bits is enough for now) */
+    uint8_t rsv : 2;        /* Reserved. Zero value */
+    uint8_t data[LIVEPATCH_OPAQUE_SIZE]; /* Same size as opaque[] buffer of
+                                            struct livepatch_func. This is the
+                                            max number of bytes to be patched */
+};
+typedef struct livepatch_expectation livepatch_expectation_t;
+
 typedef enum livepatch_func_state {
     LIVEPATCH_FUNC_NOT_APPLIED,
     LIVEPATCH_FUNC_APPLIED
@@ -852,9 +865,10 @@ struct livepatch_func {
     uint32_t new_size;
     uint32_t old_size;
     uint8_t version;        /* MUST be LIVEPATCH_PAYLOAD_VERSION. */
-    uint8_t opaque[31];
+    uint8_t opaque[LIVEPATCH_OPAQUE_SIZE];
     uint8_t applied;
     uint8_t _pad[7];
+    livepatch_expectation_t expect;
 };
 typedef struct livepatch_func livepatch_func_t;
 #endif
diff --git a/xen/test/livepatch/Makefile b/xen/test/livepatch/Makefile
index 23113d3418..cebd3eb49c 100644
--- a/xen/test/livepatch/Makefile
+++ b/xen/test/livepatch/Makefile
@@ -27,6 +27,8 @@ LIVEPATCH_ACTION_HOOKS_NOFUNC := xen_action_hooks_nofunc.livepatch
 LIVEPATCH_ACTION_HOOKS_MARKER:= xen_action_hooks_marker.livepatch
 LIVEPATCH_ACTION_HOOKS_NOAPPLY:= xen_action_hooks_noapply.livepatch
 LIVEPATCH_ACTION_HOOKS_NOREVERT:= xen_action_hooks_norevert.livepatch
+LIVEPATCH_EXPECTATIONS:= xen_expectations.livepatch
+LIVEPATCH_EXPECTATIONS_FAIL:= xen_expectations_fail.livepatch
 
 LIVEPATCHES += $(LIVEPATCH)
 LIVEPATCHES += $(LIVEPATCH_BYE)
@@ -40,6 +42,8 @@ LIVEPATCHES += $(LIVEPATCH_ACTION_HOOKS_NOFUNC)
 LIVEPATCHES += $(LIVEPATCH_ACTION_HOOKS_MARKER)
 LIVEPATCHES += $(LIVEPATCH_ACTION_HOOKS_NOAPPLY)
 LIVEPATCHES += $(LIVEPATCH_ACTION_HOOKS_NOREVERT)
+LIVEPATCHES += $(LIVEPATCH_EXPECTATIONS)
+LIVEPATCHES += $(LIVEPATCH_EXPECTATIONS_FAIL)
 
 LIVEPATCH_DEBUG_DIR ?= $(DEBUG_DIR)/xen-livepatch
 
@@ -54,7 +58,7 @@ uninstall:
 
 .PHONY: clean
 clean::
-	rm -f *.o .*.o.d *.livepatch config.h
+	rm -f *.o .*.o.d *.livepatch config.h expect_config.h
 
 #
 # To compute these values we need the binary files: xen-syms
@@ -182,8 +186,27 @@ xen_actions_hooks_norevert.o: config.h
 $(LIVEPATCH_ACTION_HOOKS_NOREVERT): xen_action_hooks_marker.o xen_hello_world_func.o note.o xen_note.o
 	$(LD) $(LDFLAGS) $(build_id_linker) -r -o $(LIVEPATCH_ACTION_HOOKS_NOREVERT) $^
 
+EXPECT_BYTES_COUNT := 8
+CODE_GET_EXPECT=$(shell $(OBJDUMP) -d --insn-width=1 $(1) | sed -n -e '/<'$(2)'>:$$/,/^$$/ p' | tail -n +2 | head -n $(EXPECT_BYTES_COUNT) | awk '{$$0=$$2; printf "%s", substr($$0,length-1)}' | sed 's/.\{2\}/0x&,/g' | sed 's/^/{/;s/,$$/}/g')
+.PHONY: expect_config.h
+expect_config.h: EXPECT_BYTES=$(call CODE_GET_EXPECT,$(BASEDIR)/xen-syms,xen_extra_version)
+expect_config.h: xen_expectations.o
+	(set -e; \
+	 echo "#define EXPECT_BYTES $(EXPECT_BYTES)"; \
+         echo "#define EXPECT_BYTES_COUNT $(EXPECT_BYTES_COUNT)") > $@
+
+xen_expectations.o: expect_config.h
+
+.PHONY: $(LIVEPATCH_EXPECTATIONS)
+$(LIVEPATCH_EXPECTATIONS): xen_expectations.o xen_hello_world_func.o note.o xen_note.o
+	$(LD) $(LDFLAGS) $(build_id_linker) -r -o $(LIVEPATCH_EXPECTATIONS) $^
+
+.PHONY: $(LIVEPATCH_EXPECTATIONS_FAIL)
+$(LIVEPATCH_EXPECTATIONS_FAIL): xen_expectations_fail.o xen_hello_world_func.o note.o xen_note.o
+	$(LD) $(LDFLAGS) $(build_id_linker) -r -o $(LIVEPATCH_EXPECTATIONS_FAIL) $^
+
 .PHONY: livepatch
 livepatch: $(LIVEPATCH) $(LIVEPATCH_BYE) $(LIVEPATCH_REPLACE) $(LIVEPATCH_NOP) $(LIVEPATCH_NO_XEN_BUILDID) \
            $(LIVEPATCH_PREPOST_HOOKS) $(LIVEPATCH_PREPOST_HOOKS_FAIL) $(LIVEPATCH_ACTION_HOOKS) \
            $(LIVEPATCH_ACTION_HOOKS_NOFUNC) $(LIVEPATCH_ACTION_HOOKS_MARKER) $(LIVEPATCH_ACTION_HOOKS_NOAPPLY) \
-           $(LIVEPATCH_ACTION_HOOKS_NOREVERT)
+           $(LIVEPATCH_ACTION_HOOKS_NOREVERT) $(LIVEPATCH_EXPECTATIONS) $(LIVEPATCH_EXPECTATIONS_FAIL)
diff --git a/xen/test/livepatch/xen_expectations.c b/xen/test/livepatch/xen_expectations.c
new file mode 100644
index 0000000000..c8175a458b
--- /dev/null
+++ b/xen/test/livepatch/xen_expectations.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2019 Amazon.com, Inc. or its affiliates. All rights reserved.
+ *
+ */
+
+#include "expect_config.h"
+#include <xen/lib.h>
+#include <xen/types.h>
+#include <xen/version.h>
+#include <xen/livepatch.h>
+#include <xen/livepatch_payload.h>
+
+#include <public/sysctl.h>
+
+static const char livepatch_exceptions_str[] = "xen_extra_version";
+extern const char *xen_hello_world(void);
+
+struct livepatch_func __section(".livepatch.funcs") livepatch_exceptions = {
+    .version = LIVEPATCH_PAYLOAD_VERSION,
+    .name = livepatch_exceptions_str,
+    .new_addr = xen_hello_world,
+    .old_addr = xen_extra_version,
+    .new_size = EXPECT_BYTES_COUNT,
+    .old_size = EXPECT_BYTES_COUNT,
+    .expect = {
+        .enabled = 1,
+        .len = EXPECT_BYTES_COUNT,
+        .data = EXPECT_BYTES
+    },
+
+};
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/test/livepatch/xen_expectations_fail.c b/xen/test/livepatch/xen_expectations_fail.c
new file mode 100644
index 0000000000..36a110286f
--- /dev/null
+++ b/xen/test/livepatch/xen_expectations_fail.c
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2019 Amazon.com, Inc. or its affiliates. All rights reserved.
+ *
+ */
+
+#include <xen/lib.h>
+#include <xen/types.h>
+#include <xen/version.h>
+#include <xen/livepatch.h>
+#include <xen/livepatch_payload.h>
+
+#include <public/sysctl.h>
+
+static const char livepatch_exceptions_str[] = "xen_extra_version";
+extern const char *xen_hello_world(void);
+
+#define EXPECT_BYTES_COUNT 6
+
+struct livepatch_func __section(".livepatch.funcs") livepatch_exceptions = {
+    .version = LIVEPATCH_PAYLOAD_VERSION,
+    .name = livepatch_exceptions_str,
+    .new_addr = xen_hello_world,
+    .old_addr = xen_extra_version,
+    .new_size = EXPECT_BYTES_COUNT,
+    .old_size = EXPECT_BYTES_COUNT,
+    .expect = {
+        .enabled = 1,
+        .len = EXPECT_BYTES_COUNT,
+        .data = { 0xDE, 0xAD, 0xC0, 0xDE, 0xBA, 0xBE }
+    },
+
+};
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
