diff --git a/tools/testing/selftests/kvm/cr4_cpuid_sync_test.c b/tools/testing/selftests/kvm/cr4_cpuid_sync_test.c
index 8346b33c2073..d46b42274fd5 100644
--- a/tools/testing/selftests/kvm/cr4_cpuid_sync_test.c
+++ b/tools/testing/selftests/kvm/cr4_cpuid_sync_test.c
@@ -23,20 +23,6 @@
 #define X86_FEATURE_OSXSAVE	(1<<27)
 #define VCPU_ID			1
 
-enum {
-	GUEST_UPDATE_CR4 = 0x1000,
-	GUEST_FAILED,
-	GUEST_DONE,
-};
-
-static void exit_to_hv(uint16_t port)
-{
-	__asm__ __volatile__("in %[port], %%al"
-			     :
-			     : [port]"d"(port)
-			     : "rax");
-}
-
 static inline bool cr4_cpuid_is_sync(void)
 {
 	int func, subfunc;
@@ -64,17 +50,15 @@ static void guest_code(void)
 	set_cr4(cr4);
 
 	/* verify CR4.OSXSAVE == CPUID.OSXSAVE */
-	if (!cr4_cpuid_is_sync())
-		exit_to_hv(GUEST_FAILED);
+	GUEST_ASSERT(cr4_cpuid_is_sync());
 
 	/* notify hypervisor to change CR4 */
-	exit_to_hv(GUEST_UPDATE_CR4);
+	GUEST_SYNC(0);
 
 	/* check again */
-	if (!cr4_cpuid_is_sync())
-		exit_to_hv(GUEST_FAILED);
+	GUEST_ASSERT(cr4_cpuid_is_sync());
 
-	exit_to_hv(GUEST_DONE);
+	GUEST_DONE();
 }
 
 int main(int argc, char *argv[])
@@ -104,16 +88,16 @@ int main(int argc, char *argv[])
 
 		if (run->exit_reason == KVM_EXIT_IO) {
 			switch (run->io.port) {
-			case GUEST_UPDATE_CR4:
+			case GUEST_PORT_SYNC:
 				/* emulate hypervisor clearing CR4.OSXSAVE */
 				vcpu_sregs_get(vm, VCPU_ID, &sregs);
 				sregs.cr4 &= ~X86_CR4_OSXSAVE;
 				vcpu_sregs_set(vm, VCPU_ID, &sregs);
 				break;
-			case GUEST_FAILED:
+			case GUEST_PORT_ABORT:
 				TEST_ASSERT(false, "Guest CR4 bit (OSXSAVE) unsynchronized with CPUID bit.");
 				break;
-			case GUEST_DONE:
+			case GUEST_PORT_DONE:
 				goto done;
 			default:
 				TEST_ASSERT(false, "Unknown port 0x%x.",
diff --git a/tools/testing/selftests/kvm/include/kvm_util.h b/tools/testing/selftests/kvm/include/kvm_util.h
index d32632f71ab8..d8ca48687e35 100644
--- a/tools/testing/selftests/kvm/include/kvm_util.h
+++ b/tools/testing/selftests/kvm/include/kvm_util.h
@@ -144,4 +144,43 @@ allocate_kvm_dirty_log(struct kvm_userspace_memory_region *region);
 
 int vm_create_device(struct kvm_vm *vm, struct kvm_create_device *cd);
 
+#define GUEST_PORT_SYNC         0x1000
+#define GUEST_PORT_ABORT        0x1001
+#define GUEST_PORT_DONE         0x1002
+
+static inline void __exit_to_l0(uint16_t port, uint64_t arg0, uint64_t arg1)
+{
+	__asm__ __volatile__("in %[port], %%al"
+			     :
+			     : [port]"d"(port), "D"(arg0), "S"(arg1)
+			     : "rax");
+}
+
+/*
+ * Allows to pass three arguments to the host: port is 16bit wide,
+ * arg0 & arg1 are 64bit wide
+ */
+#define GUEST_SYNC_ARGS(_port, _arg0, _arg1) \
+	__exit_to_l0(_port, (uint64_t) (_arg0), (uint64_t) (_arg1))
+
+#define GUEST_ASSERT(_condition) do {				\
+		if (!(_condition))				\
+			GUEST_SYNC_ARGS(GUEST_PORT_ABORT,	\
+					"Failed guest assert: "	\
+					#_condition, __LINE__);	\
+	} while (0)
+
+#define GUEST_SYNC(stage)  GUEST_SYNC_ARGS(GUEST_PORT_SYNC, "hello", stage)
+
+#define GUEST_DONE()  GUEST_SYNC_ARGS(GUEST_PORT_DONE, 0, 0)
+
+struct guest_args {
+	uint64_t arg0;
+	uint64_t arg1;
+	uint16_t port;
+} __attribute__ ((packed));
+
+void guest_args_read(struct kvm_vm *vm, uint32_t vcpu_id,
+		     struct guest_args *args);
+
 #endif /* SELFTEST_KVM_UTIL_H */
diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/selftests/kvm/lib/kvm_util.c
index 643309d6de74..97d344303c92 100644
--- a/tools/testing/selftests/kvm/lib/kvm_util.c
+++ b/tools/testing/selftests/kvm/lib/kvm_util.c
@@ -1536,3 +1536,17 @@ void *addr_gva2hva(struct kvm_vm *vm, vm_vaddr_t gva)
 {
 	return addr_gpa2hva(vm, addr_gva2gpa(vm, gva));
 }
+
+void guest_args_read(struct kvm_vm *vm, uint32_t vcpu_id,
+		     struct guest_args *args)
+{
+	struct kvm_run *run = vcpu_state(vm, vcpu_id);
+	struct kvm_regs regs;
+
+	memset(&regs, 0, sizeof(regs));
+	vcpu_regs_get(vm, vcpu_id, &regs);
+
+	args->port = run->io.port;
+	args->arg0 = regs.rdi;
+	args->arg1 = regs.rsi;
+}
diff --git a/tools/testing/selftests/kvm/state_test.c b/tools/testing/selftests/kvm/state_test.c
index ecabf25b7077..438d7b828581 100644
--- a/tools/testing/selftests/kvm/state_test.c
+++ b/tools/testing/selftests/kvm/state_test.c
@@ -21,28 +21,6 @@
 #include "vmx.h"
 
 #define VCPU_ID		5
-#define PORT_SYNC	0x1000
-#define PORT_ABORT	0x1001
-#define PORT_DONE	0x1002
-
-static inline void __exit_to_l0(uint16_t port, uint64_t arg0, uint64_t arg1)
-{
-	__asm__ __volatile__("in %[port], %%al"
-			     :
-			     : [port]"d"(port), "D"(arg0), "S"(arg1)
-			     : "rax");
-}
-
-#define exit_to_l0(_port, _arg0, _arg1) \
-	__exit_to_l0(_port, (uint64_t) (_arg0), (uint64_t) (_arg1))
-
-#define GUEST_ASSERT(_condition) do { \
-	if (!(_condition)) \
-		exit_to_l0(PORT_ABORT, "Failed guest assert: " #_condition, __LINE__);\
-} while (0)
-
-#define GUEST_SYNC(stage) \
-	exit_to_l0(PORT_SYNC, "hello", stage);
 
 static bool have_nested_state;
 
@@ -137,7 +115,7 @@ void guest_code(struct vmx_pages *vmx_pages)
 	if (vmx_pages)
 		l1_guest_code(vmx_pages);
 
-	exit_to_l0(PORT_DONE, 0, 0);
+	GUEST_DONE();
 }
 
 int main(int argc, char *argv[])
@@ -178,13 +156,13 @@ int main(int argc, char *argv[])
 		memset(&regs1, 0, sizeof(regs1));
 		vcpu_regs_get(vm, VCPU_ID, &regs1);
 		switch (run->io.port) {
-		case PORT_ABORT:
+		case GUEST_PORT_ABORT:
 			TEST_ASSERT(false, "%s at %s:%d", (const char *) regs1.rdi,
 				    __FILE__, regs1.rsi);
 			/* NOT REACHED */
-		case PORT_SYNC:
+		case GUEST_PORT_SYNC:
 			break;
-		case PORT_DONE:
+		case GUEST_PORT_DONE:
 			goto done;
 		default:
 			TEST_ASSERT(false, "Unknown port 0x%x.", run->io.port);
diff --git a/tools/testing/selftests/kvm/sync_regs_test.c b/tools/testing/selftests/kvm/sync_regs_test.c
index eae1ece3c31b..2dbf2e1af6c6 100644
--- a/tools/testing/selftests/kvm/sync_regs_test.c
+++ b/tools/testing/selftests/kvm/sync_regs_test.c
@@ -22,28 +22,11 @@
 #include "x86.h"
 
 #define VCPU_ID 5
-#define PORT_HOST_SYNC 0x1000
-
-static void __exit_to_l0(uint16_t port, uint64_t arg0, uint64_t arg1)
-{
-	        __asm__ __volatile__("in %[port], %%al"
-				     :
-				     : [port]"d"(port), "D"(arg0), "S"(arg1)
-				     : "rax");
-}
-
-#define exit_to_l0(_port, _arg0, _arg1) \
-        __exit_to_l0(_port, (uint64_t) (_arg0), (uint64_t) (_arg1))
-
-#define GUEST_ASSERT(_condition) do { \
-	if (!(_condition)) \
-		exit_to_l0(PORT_ABORT, "Failed guest assert: " #_condition, 0);\
-} while (0)
 
 void guest_code(void)
 {
 	for (;;) {
-		exit_to_l0(PORT_HOST_SYNC, "hello", 0);
+		GUEST_SYNC(0);
 		asm volatile ("inc %r11");
 	}
 }
diff --git a/tools/testing/selftests/kvm/vmx_tsc_adjust_test.c b/tools/testing/selftests/kvm/vmx_tsc_adjust_test.c
index fc414c284368..4ddae120a9ea 100644
--- a/tools/testing/selftests/kvm/vmx_tsc_adjust_test.c
+++ b/tools/testing/selftests/kvm/vmx_tsc_adjust_test.c
@@ -62,27 +62,12 @@ struct kvm_single_msr {
 /* The virtual machine object. */
 static struct kvm_vm *vm;
 
-#define exit_to_l0(_port, _arg) do_exit_to_l0(_port, (unsigned long) (_arg))
-static void do_exit_to_l0(uint16_t port, unsigned long arg)
-{
-	__asm__ __volatile__("in %[port], %%al"
-		:
-		: [port]"d"(port), "D"(arg)
-		: "rax");
-}
-
-
-#define GUEST_ASSERT(_condition) do {					     \
-	if (!(_condition))						     \
-		exit_to_l0(PORT_ABORT, "Failed guest assert: " #_condition); \
-} while (0)
-
 static void check_ia32_tsc_adjust(int64_t max)
 {
 	int64_t adjust;
 
 	adjust = rdmsr(MSR_IA32_TSC_ADJUST);
-	exit_to_l0(PORT_REPORT, adjust);
+	GUEST_SYNC(adjust);
 	GUEST_ASSERT(adjust <= max);
 }
 
@@ -132,7 +117,7 @@ static void l1_guest_code(struct vmx_pages *vmx_pages)
 
 	check_ia32_tsc_adjust(-2 * TSC_ADJUST_VALUE);
 
-	exit_to_l0(PORT_DONE, 0);
+	GUEST_DONE();
 }
 
 void report(int64_t val)
@@ -161,26 +146,26 @@ int main(int argc, char *argv[])
 
 	for (;;) {
 		volatile struct kvm_run *run = vcpu_state(vm, VCPU_ID);
-		struct kvm_regs regs;
+		struct guest_args args;
 
 		vcpu_run(vm, VCPU_ID);
-		vcpu_regs_get(vm, VCPU_ID, &regs);
+		guest_args_read(vm, VCPU_ID, &args);
 		TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
-			    "Got exit_reason other than KVM_EXIT_IO: %u (%s), rip=%lx\n",
+			    "Got exit_reason other than KVM_EXIT_IO: %u (%s)\n",
 			    run->exit_reason,
-			    exit_reason_str(run->exit_reason), regs.rip);
+			    exit_reason_str(run->exit_reason));
 
-		switch (run->io.port) {
-		case PORT_ABORT:
-			TEST_ASSERT(false, "%s", (const char *) regs.rdi);
+		switch (args.port) {
+		case GUEST_PORT_ABORT:
+			TEST_ASSERT(false, "%s", (const char *) args.arg0);
 			/* NOT REACHED */
-		case PORT_REPORT:
-			report(regs.rdi);
+		case GUEST_PORT_SYNC:
+			report(args.arg1);
 			break;
-		case PORT_DONE:
+		case GUEST_PORT_DONE:
 			goto done;
 		default:
-			TEST_ASSERT(false, "Unknown port 0x%x.", run->io.port);
+			TEST_ASSERT(false, "Unknown port 0x%x.", args.port);
 		}
 	}