Index: qemu.tscdeadline/qapi-schema.json
===================================================================
--- qemu.tscdeadline.orig/qapi-schema.json
+++ qemu.tscdeadline/qapi-schema.json
@@ -3515,3 +3515,32 @@
 # Since: 2.1
 ##
 { 'command': 'rtc-reset-reinjection' }
+
+##
+# @set-lapic-tscdeadline-advance
+#
+# This command sets the TSC deadline timer advancement.
+# This value will be subtracted from the expiration time
+# of the high resolution timer which emulates
+# TSC deadline timer.
+#
+# Useful to achieve low timer latencies.
+#
+# Only supported by KVM acceleration.
+#
+# Since: 2.3
+##
+{ 'command': 'set-lapic-tscdeadline-advance',
+  'data': { 'advance':'int' }
+}
+
+##
+# @get-lapic-tscdeadline-advance
+#
+# This command gets the TSC deadline timer advancement.
+#
+# Only supported by KVM acceleration.
+#
+# Since: 2.3
+##
+{ 'command': 'get-lapic-tscdeadline-advance', 'returns': 'int' }
Index: qemu.tscdeadline/qmp-commands.hx
===================================================================
--- qemu.tscdeadline.orig/qmp-commands.hx
+++ qemu.tscdeadline/qmp-commands.hx
@@ -3854,3 +3854,51 @@ Move mouse pointer to absolute coordinat
 <- { "return": {} }
 
 EQMP
+
+    {
+        .name       = "set-lapic-tscdeadline-advance",
+        .args_type  = "advance:i",
+        .mhandler.cmd_new = qmp_marshal_input_set_lapic_tscdeadline_advance,
+    },
+
+SQMP
+set-lapic-tscdeadline-advance
+-----------------------------
+
+Set LAPIC tscdeadline timer advancement, in nanoseconds.
+
+Arguments:
+
+- "advance": LAPIC tscdeadline timer advancement (json-int)
+
+Example:
+
+-> { "execute": "set-lapic-tscdeadline-advance 1000" }
+<- { "return": {} }
+
+EQMP
+
+    {
+        .name       = "get-lapic-tscdeadline-advance",
+        .args_type  = "",
+        .mhandler.cmd_new = qmp_marshal_input_get_lapic_tscdeadline_advance,
+    },
+
+SQMP
+get-lapic-tscdeadline-advance
+-----------------------------
+
+Get LAPIC tscdeadline timer advancement, in nanoseconds.
+
+Arguments: None.
+
+returns a json-object with the following information:
+- "value" : json-int
+
+Example:
+
+-> { "execute": "get-lapic-tscdeadline-advance" }
+<- { "return": {1000} }
+
+EQMP
+
Index: qemu.tscdeadline/vl.c
===================================================================
--- qemu.tscdeadline.orig/vl.c
+++ qemu.tscdeadline/vl.c
@@ -387,6 +387,10 @@ static QemuOptsList qemu_machine_opts =
             .name = "iommu",
             .type = QEMU_OPT_BOOL,
             .help = "Set on/off to enable/disable Intel IOMMU (VT-d)",
+        },{
+            .name = "lapic-tscdeadline-advance",
+            .type = QEMU_OPT_NUMBER,
+            .help = "Set lapic tscdeadline timer advance",
         },
         { /* End of list */ }
     },
Index: qemu.tscdeadline/target-i386/kvm.c
===================================================================
--- qemu.tscdeadline.orig/target-i386/kvm.c
+++ qemu.tscdeadline/target-i386/kvm.c
@@ -37,6 +37,7 @@
 #include "hw/pci/pci.h"
 #include "migration/migration.h"
 #include "qapi/qmp/qerror.h"
+#include "qmp-commands.h"
 
 //#define DEBUG_KVM
 
@@ -84,6 +85,10 @@ static bool has_msr_mtrr;
 static bool has_msr_architectural_pmu;
 static uint32_t num_architectural_pmu_counters;
 
+static struct lapic_tscdeadline_advance {
+    unsigned int advance_ns;
+} lapic_tscdeadline_advance;
+
 bool kvm_allows_irq0_override(void)
 {
     return !kvm_irqchip_in_kernel() || kvm_has_gsi_routing();
@@ -835,12 +840,32 @@ static int kvm_get_supported_msrs(KVMSta
     return ret;
 }
 
+static int kvm_set_lapic_tscdeadline(KVMState *s, uint32_t advance)
+{
+    struct kvm_tscdeadline_advance adv;
+    int ret = 0;
+
+    memset(&adv, 0, sizeof(adv));
+
+    adv.timer_advance = advance;
+
+    ret = kvm_vm_ioctl(s, KVM_SET_TSCDEADLINE_ADVANCE, &adv);
+    if (ret < 0) {
+        return ret;
+    }
+
+    lapic_tscdeadline_advance.advance_ns = advance;
+
+    return ret;
+}
+
 int kvm_arch_init(KVMState *s)
 {
     uint64_t identity_base = 0xfffbc000;
     uint64_t shadow_mem;
     int ret;
     struct utsname utsname;
+    uint32_t lapic_advance_ns;
 
     ret = kvm_get_supported_msrs(s);
     if (ret < 0) {
@@ -894,9 +919,40 @@ int kvm_arch_init(KVMState *s)
             return ret;
         }
     }
+
+    lapic_advance_ns = qemu_opt_get_number(qemu_get_machine_opts(),
+                                           "lapic-tscdeadline-advance",
+                                           0);
+    if (lapic_advance_ns) {
+        ret = kvm_set_lapic_tscdeadline(s, lapic_advance_ns);
+        if (ret) {
+            fprintf(stderr, "Set tscdeadline advance failed: %s\n",
+                    strerror(-ret));
+            return ret;
+        }
+    }
+
+
     return 0;
 }
 
+int64_t qmp_get_lapic_tscdeadline_advance(Error **errp)
+{
+    return lapic_tscdeadline_advance.advance_ns;
+}
+
+void qmp_set_lapic_tscdeadline_advance(int64_t advance, Error **errp)
+{
+    KVMState *s = kvm_state;
+    int ret;
+
+    ret = kvm_set_lapic_tscdeadline(s, advance);
+    if (ret) {
+        error_setg_errno(errp, ret, "set lapic tscdeadline failed");
+        return;
+    }
+}
+
 static void set_v8086_seg(struct kvm_segment *lhs, const SegmentCache *rhs)
 {
     lhs->selector = rhs->selector;
Index: qemu.tscdeadline/monitor.c
===================================================================
--- qemu.tscdeadline.orig/monitor.c
+++ qemu.tscdeadline/monitor.c
@@ -5447,3 +5447,18 @@ void qmp_rtc_reset_reinjection(Error **e
     error_set(errp, QERR_FEATURE_DISABLED, "rtc-reset-reinjection");
 }
 #endif
+
+#if !defined (TARGET_I386) || !defined (CONFIG_KVM)
+int64_t qmp_get_lapic_tscdeadline_advance(Error **errp)
+{
+    error_set(errp, QERR_FEATURE_DISABLED, "get-lapic-tscdeadline-advance");
+
+    return 0;
+}
+
+void qmp_set_lapic_tscdeadline_advance(int64_t advance, Error **errp)
+{
+    error_set(errp, QERR_FEATURE_DISABLED, "set-lapic-tscdeadline-advance");
+}
+#endif
+
Index: qemu.tscdeadline/include/hw/boards.h
===================================================================
--- qemu.tscdeadline.orig/include/hw/boards.h
+++ qemu.tscdeadline/include/hw/boards.h
@@ -133,6 +133,7 @@ struct MachineState {
     bool usb;
     char *firmware;
     bool iommu;
+    int lapi_tscdeadline_advance;
 
     ram_addr_t ram_size;
     ram_addr_t maxram_size;
Index: qemu.tscdeadline/qemu-options.hx
===================================================================
--- qemu.tscdeadline.orig/qemu-options.hx
+++ qemu.tscdeadline/qemu-options.hx
@@ -37,7 +37,8 @@ DEF("machine", HAS_ARG, QEMU_OPTION_mach
     "                kvm_shadow_mem=size of KVM shadow MMU\n"
     "                dump-guest-core=on|off include guest memory in a core dump (default=on)\n"
     "                mem-merge=on|off controls memory merge support (default: on)\n"
-    "                iommu=on|off controls emulated Intel IOMMU (VT-d) support (default=off)\n",
+    "                iommu=on|off controls emulated Intel IOMMU (VT-d) support (default=off)\n"
+    "                lapic-tscdeadline-advance=value controls LAPIC tscdeadline timer advancement (default=0)\n",
     QEMU_ARCH_ALL)
 STEXI
 @item -machine [type=]@var{name}[,prop=@var{value}[,...]]
@@ -66,6 +67,8 @@ the host, de-duplicates identical memory
 (enabled by default).
 @item iommu=on|off
 Enables or disables emulated Intel IOMMU (VT-d) support. The default is off.
+@item lapic-tscdeadline-advance=value
+Defines the advancement of LAPIC TSC deadline timer, in nanoseconds.
 @end table
 ETEXI
 
Index: qemu.tscdeadline/hw/core/machine.c
===================================================================
--- qemu.tscdeadline.orig/hw/core/machine.c
+++ qemu.tscdeadline/hw/core/machine.c
@@ -72,6 +72,35 @@ static void machine_set_kvm_shadow_mem(O
     ms->kvm_shadow_mem = value;
 }
 
+static void machine_get_lapic_tscdeadline_advance(Object *obj, Visitor *v,
+                                                  void *opaque,
+                                                  const char *name,
+                                                  Error **errp)
+{
+    MachineState *ms = MACHINE(obj);
+    int64_t value = ms->kvm_shadow_mem;
+
+    visit_type_int(v, &value, name, errp);
+}
+
+static void machine_set_lapic_tscdeadline_advance(Object *obj, Visitor *v,
+                                                  void *opaque,
+                                                  const char *name,
+                                                  Error **errp)
+{
+    MachineState *ms = MACHINE(obj);
+    Error *error = NULL;
+    int64_t value;
+
+    visit_type_int(v, &value, name, &error);
+    if (error) {
+        error_propagate(errp, error);
+        return;
+    }
+
+    ms->lapi_tscdeadline_advance = value;
+}
+
 static char *machine_get_kernel(Object *obj, Error **errp)
 {
     MachineState *ms = MACHINE(obj);
@@ -299,6 +328,10 @@ static void machine_initfn(Object *obj)
                         machine_get_kvm_shadow_mem,
                         machine_set_kvm_shadow_mem,
                         NULL, NULL, NULL);
+    object_property_add(obj, "lapic-tscdeadline-advance", "int",
+                        machine_get_lapic_tscdeadline_advance,
+                        machine_set_lapic_tscdeadline_advance,
+                        NULL, NULL, NULL);
     object_property_add_str(obj, "kernel",
                             machine_get_kernel, machine_set_kernel, NULL);
     object_property_add_str(obj, "initrd",
