diff --git a/vmm/handler.c b/vmm/handler.c
index 65c476afad22c1a9a0bf29a4f97be0022792276b..31ef2c42c3efe3a81f9cc6caf12f6658f331a345 100644
--- a/vmm/handler.c
+++ b/vmm/handler.c
@@ -3,6 +3,7 @@
 #include <err.h>
 #include <stdio.h>
 #include <stdint.h>
+#include <stdarg.h>
 #include <unistd.h>
 #include <stdbool.h>
 
@@ -165,12 +166,26 @@ static void wrapper_op_gfx_init(uint8_t *shared_buf) {
 
 // - VMM EXIT REASON HANDLER -
 
-void handle_halt(struct kvm_run *run, uint8_t *shared_buf, uint8_t *mem) {
+void handle_halt(struct kvm_run *run, ...) {
 
-    // printf("KVM_EXIT_HLT\n");
+    va_list args; va_start(args, run);
+
+    va_arg(args, uint8_t *); va_arg(args, uint8_t *); // skip two first args
+    bool *done = va_arg(args, bool *);
+
+    printf("guest halted\n");
+    *done = true;
+
+    va_end(args);
 }
 
-void handle_pmio(struct kvm_run *run, uint8_t *shared_buf, uint8_t *mem) {
+// waiting for : uint8_t *shared_buf, uint8_t *mem
+void handle_pmio(struct kvm_run *run, ...) {
+
+    va_list args; va_start(args, run);
+
+    uint8_t *shared_buf = va_arg(args, uint8_t *);
+    uint8_t *mem = va_arg(args, uint8_t *);
 
     if (run->io.direction == KVM_EXIT_IO_OUT) {
 
@@ -189,9 +204,12 @@ void handle_pmio(struct kvm_run *run, uint8_t *shared_buf, uint8_t *mem) {
                 state_compute(current_state, value);
         }
     }
+
+    va_end(args);
 }
 
-void handle_mmio(struct kvm_run *run, uint8_t *shared_buf, uint8_t *mem) {
+// waiting for : uint8_t *shared_buf, uint8_t *mem
+void handle_mmio(struct kvm_run *run, ...) {
 
     if (run->mmio.is_write) {
 
@@ -219,7 +237,7 @@ void handle_hypercall(uint32_t code, uint8_t *shared_buf, uint8_t *mem) {
             wrapper_op_timer(shared_buf);
         break;
 
-        case HYPERCALL_CODE_GFX_INIT: 
+        case HYPERCALL_CODE_GFX_INIT:
             wrapper_op_gfx_init(shared_buf);
         break;
 
diff --git a/vmm/handler.h b/vmm/handler.h
index ee1d2176d7049036136e9fd4559ccaf88efe85f9..d604a76884170fbbe2f0fc7228cbc6031e53393d 100644
--- a/vmm/handler.h
+++ b/vmm/handler.h
@@ -2,11 +2,12 @@
 #define _STATES_H_
 
 #include <stdint.h>
+#include <stdbool.h>
 #include <linux/kvm.h>
 
 // --- DEFINE ---
 
-typedef void (*state_handler_t)(struct kvm_run *run, uint8_t *shared_buf, uint8_t *mem);
+typedef void (*state_handler_t)(struct kvm_run *run, ...);
 
 extern state_handler_t const STATE_HANDLERS[];
 
@@ -19,7 +20,7 @@ extern state_handler_t const STATE_HANDLERS[];
  * @param shared_buf Buffer shared between the host and guest.
  * @param mem        Pointer to the VM's memory.
  */
-void handle_halt(struct kvm_run *run, uint8_t *shared_buf, uint8_t *mem);
+void handle_halt(struct kvm_run *run, ...);
 
 /**
  * @brief Handles the I/O port access (PMIO) exit from the virtual machine.
@@ -30,7 +31,7 @@ void handle_halt(struct kvm_run *run, uint8_t *shared_buf, uint8_t *mem);
  * @param shared_buf Buffer shared between the host and guest.
  * @param mem        Pointer to the VM's memory.
  */
-void handle_pmio(struct kvm_run *run, uint8_t *shared_buf, uint8_t *mem);
+void handle_pmio(struct kvm_run *run, ...);
 
 /**
  * @brief Handles the memory-mapped I/O (MMIO) exit from the virtual machine.
@@ -41,7 +42,7 @@ void handle_pmio(struct kvm_run *run, uint8_t *shared_buf, uint8_t *mem);
  * @param shared_buf Buffer shared between the host and guest.
  * @param mem        Pointer to the VM's memory.
  */
-void handle_mmio(struct kvm_run *run, uint8_t *shared_buf, uint8_t *mem);
+void handle_mmio(struct kvm_run *run, ...);
 
 /**
  * @brief Handles hypercalls issued by the virtual machine.
diff --git a/vmm/operation.c b/vmm/operation.c
index 471256fd52eca87574b9e7aa731aefccb81d20d3..54035b2fe3cffc2ae74f593a30fb700b8dd0ee14 100644
--- a/vmm/operation.c
+++ b/vmm/operation.c
@@ -3,6 +3,7 @@
 #include <stdio.h>
 #include <stdint.h>
 #include <unistd.h>
+#include <semaphore.h>
 
 #include "shared/hypercall_params.h"
 
@@ -57,7 +58,7 @@ void op_callback_timer_conclude(void *addr) {
     hyper_timer_sleep_params_t *p_timer = (addr == NULL) ? &param_timer : (hyper_timer_sleep_params_t *)addr;
 
     printf("hypercall : setting up a %dus timer...\n", p_timer->us);
-    sleep(p_timer->us / 1e6);
+    usleep(p_timer->us);
 }
 
 void op_callback_gfx_init_store_w(void *addr) {
@@ -75,5 +76,7 @@ void op_callback_gfx_init_conclude(void *addr) {
     hyper_init_gfx_params_t *p_gfx_init = (addr == NULL) ? &param_gfx_init : (hyper_init_gfx_params_t *)addr;
 
     printf("hypercall : initializing gfx %dx%d...\n", p_gfx_init->width, p_gfx_init->height);
-    // TODO:
+    width_gfx = p_gfx_init->width;
+    height_gfx = p_gfx_init->height;
+    sem_post(&sem_gfx);
 }
diff --git a/vmm/operation.h b/vmm/operation.h
index b57c453d9a8a77878cc7d7a0e4834e47b1178ac0..05f95d806affcfd172a0a81ef3f42adb544aecf8 100644
--- a/vmm/operation.h
+++ b/vmm/operation.h
@@ -3,6 +3,8 @@
 
 #include <stdint.h>
 #include <unistd.h>
+#include <pthread.h>
+#include <semaphore.h>
 
 
 // --- DEFINE ---
@@ -26,6 +28,10 @@ typedef struct {
     void (*callback)(void *addr);   // custom function that would be executed at the end of the state
 } state_t;
 
+extern sem_t sem_gfx;
+extern uint32_t width_gfx;
+extern uint32_t height_gfx;
+
 extern state_t *STATE_ALL_STARTERS[];
 
 extern state_t STATE_TIMER[];
diff --git a/vmm/vmm_main.c b/vmm/vmm_main.c
index 2660c38121f3eb73bb61b6551286fbd4bc9fc845..91771d21bf2628e458287ea9f16f8527b120d4f8 100644
--- a/vmm/vmm_main.c
+++ b/vmm/vmm_main.c
@@ -11,8 +11,12 @@
 #include <sys/mman.h>
 #include <sys/stat.h>
 #include <sys/types.h>
+#include <pthread.h>
+#include <semaphore.h>
 
+#include "gfx.h"
 #include "handler.h"
+#include "operation.h"
 #include "shared/hypercall_params.h"
 
 // -- DEFINE --
@@ -20,15 +24,47 @@
 #define KVM_API_VERSION   12
 #define RAM_SIZE          (512 * 1024)
 
+#define SEM_THREAD  0
+
+sem_t sem_gfx;
+uint32_t width_gfx;
+uint32_t height_gfx;
+
+static uint8_t *mem, *shared_buf;
+static struct kvm_run *run;
+static int vcpufd;
+
+// -- THREAD --
+
+static void *thread_hypercall() {
+
+    bool done = false;
+    while (!done) {
+
+        if (ioctl(vcpufd, KVM_RUN, NULL) == -1) err(1, "KVM_RUN");
+
+        state_handler_t handler = STATE_HANDLERS[run->exit_reason];
+
+        if (handler) {
+
+            handler(run, shared_buf, mem, &done);
+        }
+        else {
+
+            errx(1, "exit_reason = 0x%x", run->exit_reason);
+        }
+    }
+
+    return NULL;
+}
+
 // -- MAIN --
 
 int main(int argc, char* argv[])
 {
-    int kvmfd, vmfd, vcpufd;
+    int kvmfd, vmfd;
     struct kvm_sregs sregs;
-    struct kvm_run *run;
     int32_t mmap_size;
-    uint8_t *mem, *shared_buf;
 
     // -- 0. Handle Args --
     if (argc != 2) err(1, "Number of args invalide");
@@ -139,20 +175,23 @@ int main(int argc, char* argv[])
 
     // -- 7. Run the vCPU --
 
-    bool done = false;
-    while (!done) {
+    sem_init(&sem_gfx, SEM_THREAD, 0);
 
-        if (ioctl(vcpufd, KVM_RUN, NULL) == -1) err(1, "KVM_RUN");
+    pthread_t t_hypercall;
+    pthread_create(&t_hypercall, NULL, thread_hypercall, NULL);
 
-        state_handler_t handler = STATE_HANDLERS[run->exit_reason];
+    sem_wait(&sem_gfx);
 
-        if (handler) {
+    // -- 8. Manage gfx --
 
-            handler(run, shared_buf, mem);
-        }
-        else {
+    gfx_context_t *ctxt = gfx_create("Basic Example", width_gfx, height_gfx);
+    if (!ctxt) err(1, "KVM_SET_REGS");
 
-            errx(1, "exit_reason = 0x%x", run->exit_reason);
-        }
-    }
+    // -- X. Finalize --
+    pthread_join(t_hypercall, NULL);
+
+    gfx_destroy(ctxt);
+    sem_destroy(&sem_gfx);
+
+    return 0;
 }