diff --git a/x86/svm_tests.c b/x86/svm_tests.c
index 29a0b59..c14129a 100644
--- a/x86/svm_tests.c
+++ b/x86/svm_tests.c
@@ -1886,7 +1886,7 @@ static bool reg_corruption_finished(struct svm_test *test)
                "No RIP corruption detected after %d timer interrupts",
                isr_cnt);
         set_test_stage(test, 1);
-        return true;
+        goto finished;
     }
 
     if (vmcb->control.exit_code == SVM_EXIT_INTR) {
@@ -1901,11 +1901,14 @@ static bool reg_corruption_finished(struct svm_test *test)
             report(false,
                    "RIP corruption detected after %d timer interrupts",
                    isr_cnt);
-            return true;
+            goto finished;
         }
 
     }
     return false;
+finished:
+    apic_write(APIC_LVTT, APIC_LVT_TIMER_MASK);
+    return true;
 }
 
 static bool reg_corruption_check(struct svm_test *test)
@@ -2382,6 +2385,155 @@ static void svm_vmrun_errata_test(void)
     }
 }
 
+
+/*
+ * Test that nested exceptions are delivered correctly
+ * when parent exception is intercepted
+ */
+
+static void exception_merging_prepare(struct svm_test *test)
+{
+    default_prepare(test);
+    set_test_stage(test, 0);
+
+    vmcb->control.intercept_exceptions |= (1ULL << GP_VECTOR);
+
+    /* break UD vector idt entry to get #GP*/
+    boot_idt[UD_VECTOR].type = 1;
+}
+
+static void exception_merging_test(struct svm_test *test)
+{
+    asm volatile (
+        "ud2\n\t" :
+        /* no outputs*/ :
+        /* no inputs*/ :
+        /* no clobbers*/
+    );
+}
+
+static bool exception_merging_finished(struct svm_test *test)
+{
+    u32 vec = vmcb->control.exit_int_info & SVM_EXITINTINFO_VEC_MASK;
+    u32 type = vmcb->control.exit_int_info & SVM_EXITINTINFO_TYPE_MASK;
+
+    if (vmcb->control.exit_code != SVM_EXIT_EXCP_BASE + GP_VECTOR) {
+        report(false, "unexpected VM exit");
+        goto out;
+    }
+
+    if (! (vmcb->control.exit_int_info & SVM_EXITINTINFO_VALID)) {
+        report(false, "EXITINTINFO not valid");
+        goto out;
+    }
+
+    if (type != SVM_EXITINTINFO_TYPE_EXEPT) {
+        report(false, "Incorrect event type in EXITINTINFO");
+        goto out;
+    }
+
+    if (vec != UD_VECTOR) {
+        report(false, "Incorrect vector in EXITINTINFO");
+        goto out;
+    }
+
+    set_test_stage(test, 1);
+out:
+    boot_idt[UD_VECTOR].type = 14;
+    return true;
+}
+
+static bool exception_merging_check(struct svm_test *test)
+{
+    return get_test_stage(test) == 1;
+}
+
+
+/*
+ * Test that if exception is raised during interrupt delivery,
+ * and that exception is intercepted, the interrupt is preserved
+ * in EXITINTINFO of the exception
+ */
+
+static void interrupt_merging_prepare(struct svm_test *test)
+{
+    default_prepare(test);
+    set_test_stage(test, 0);
+
+    /* intercept #GP */
+    vmcb->control.intercept_exceptions |= (1ULL << GP_VECTOR);
+
+    /* set local APIC to inject external interrupts */
+    apic_write(APIC_TMICT, 0);
+    apic_write(APIC_TDCR, 0);
+    apic_write(APIC_LVTT, TIMER_VECTOR | APIC_LVT_TIMER_PERIODIC);
+    apic_write(APIC_TMICT, 1000);
+}
+
+static void interrupt_merging_test(struct svm_test *test)
+{
+    /* break timer vector IDT entry to get #GP on interrupt delivery */
+    boot_idt[TIMER_VECTOR].type = 1;
+
+    irq_enable();
+
+    /* just wait forever */
+    for(;;);
+}
+
+static bool interrupt_merging_finished(struct svm_test *test)
+{
+    u32 vec = vmcb->control.exit_int_info & SVM_EXITINTINFO_VEC_MASK;
+    u32 type = vmcb->control.exit_int_info & SVM_EXITINTINFO_TYPE_MASK;
+    u32 error_code = vmcb->control.exit_info_1;
+
+    /* exit on external interrupts is disabled, thus timer interrupt
+     * should be attempted to be delivered, but due to incorrect IDT entry
+     * an #GP should be raised
+     */
+    if (vmcb->control.exit_code != SVM_EXIT_EXCP_BASE + GP_VECTOR) {
+        report(false, "unexpected VM exit");
+        goto out;
+    }
+
+    /* GP error code should be about an IDT entry, and due to external event */
+    if (error_code != (TIMER_VECTOR << 3 | 3)) {
+        report(false, "Incorrect error code of the GP exception");
+        goto out;
+    }
+
+    /* Original interrupt should be preserved in EXITINTINFO */
+    if (! (vmcb->control.exit_int_info & SVM_EXITINTINFO_VALID)) {
+        report(false, "EXITINTINFO not valid");
+        goto out;
+    }
+
+    if (type != SVM_EXITINTINFO_TYPE_INTR) {
+        report(false, "Incorrect event type in EXITINTINFO");
+        goto out;
+    }
+
+    if (vec != TIMER_VECTOR) {
+        report(false, "Incorrect vector in EXITINTINFO");
+        goto out;
+    }
+
+    set_test_stage(test, 1);
+out:
+    boot_idt[TIMER_VECTOR].type = 14;
+    apic_write(APIC_LVTT, APIC_LVT_TIMER_MASK);
+    return true;
+
+}
+
+static bool interrupt_merging_check(struct svm_test *test)
+{
+    return get_test_stage(test) == 1;
+}
+
+////////////////////////////////////////////////
+
+
 struct svm_test svm_tests[] = {
     { "null", default_supported, default_prepare,
       default_prepare_gif_clear, null_test,
@@ -2492,6 +2644,12 @@ struct svm_test svm_tests[] = {
     { "svm_init_intercept_test", smp_supported, init_intercept_prepare,
       default_prepare_gif_clear, init_intercept_test,
       init_intercept_finished, init_intercept_check, .on_vcpu = 2 },
+    { "exception_merging", default_supported, exception_merging_prepare,
+      default_prepare_gif_clear, exception_merging_test,
+      exception_merging_finished, exception_merging_check },
+    { "interrupt_merging", default_supported, interrupt_merging_prepare,
+      default_prepare_gif_clear, interrupt_merging_test,
+      interrupt_merging_finished, interrupt_merging_check },
     TEST(svm_cr4_osxsave_test),
     TEST(svm_guest_state_test),
     TEST(svm_vmrun_errata_test),
