]> rtime.felk.cvut.cz Git - l4.git/blobdiff - l4/pkg/examples/sys/vmtest/main.c
update
[l4.git] / l4 / pkg / examples / sys / vmtest / main.c
index 8418c8bcbd33fdb7695b1ac70518e6420c497c17..88197007092e713495b27650adee1e42447a3aa9 100644 (file)
@@ -14,6 +14,8 @@
 #include <l4/sys/thread.h>
 #include <l4/sys/vcpu.h>
 
+#include <l4/sys/irq.h>
+
 #include <l4/util/util.h>
 #include <l4/util/cpu.h>
 #include <l4/re/env.h>
 #include <stdio.h>
 #include <string.h>
 
+#include <pthread.h>
+
 #define STACKSIZE (8<<10)
 
 static char stack[STACKSIZE];
+static char hdl_stack[STACKSIZE];
 static unsigned long idt[32 * 2] __attribute__((aligned(4096)));
 static unsigned long gdt[32 * 2] __attribute__((aligned(4096)));
 
-static void init_vmcb(l4_vm_svm_vmcb_t *vmcb_s)
-{
-
-  vmcb_s->control_area.np_enable = 1;
-  vmcb_s->control_area.guest_asid_tlb_ctl = 1;
-
-  vmcb_s->state_save_area.es.selector = 0;
-  vmcb_s->state_save_area.es.attrib = 0;
-  vmcb_s->state_save_area.es.limit  = 0;
-  vmcb_s->state_save_area.es.base = 0ULL;
+void vm_resume(void);
+void handle_vmexit(void);
+l4_vcpu_state_t *vcpu;
+l4_vm_svm_vmcb_t *vmcb_s;
+
+static void init_vmcb(l4_vm_svm_vmcb_t *vmcb_s) {
+
+    vmcb_s->control_area.np_enable = 1;
+    vmcb_s->control_area.guest_asid_tlb_ctl = 1;
+
+    vmcb_s->state_save_area.es.selector = 0;
+    vmcb_s->state_save_area.es.attrib = 0;
+    vmcb_s->state_save_area.es.limit = 0;
+    vmcb_s->state_save_area.es.base = 0ULL;
+
+    //  vmcb[256 +  0] = 0;        // es; attrib sel
+
+    vmcb_s->state_save_area.cs.selector = 0x8;
+    vmcb_s->state_save_area.cs.attrib = 0xc9b;
+    vmcb_s->state_save_area.cs.limit = 0xffffffff;
+    vmcb_s->state_save_area.cs.base = 0ULL;
+
+    vmcb_s->state_save_area.ss.selector = 0x10;
+    vmcb_s->state_save_area.ss.attrib = 0xc93;
+    vmcb_s->state_save_area.ss.limit = 0xffffffff;
+    vmcb_s->state_save_area.ss.base = 0ULL;
+
+    vmcb_s->state_save_area.ds.selector = 0x23;
+    vmcb_s->state_save_area.ds.attrib = 0xcf3;
+    vmcb_s->state_save_area.ds.limit = 0xffffffff;
+    vmcb_s->state_save_area.ds.base = 0ULL;
+
+    vmcb_s->state_save_area.fs.selector = 0;
+    vmcb_s->state_save_area.fs.attrib = 0xcf3;
+    vmcb_s->state_save_area.fs.limit = 0xffffffff;
+    vmcb_s->state_save_area.fs.base = 0ULL;
+
+    vmcb_s->state_save_area.gs.selector = 0;
+    vmcb_s->state_save_area.gs.attrib = 0xcf3;
+    vmcb_s->state_save_area.gs.limit = 0xffffffff;
+    vmcb_s->state_save_area.gs.base = 0ULL;
+
+    vmcb_s->state_save_area.gdtr.selector = 0;
+    vmcb_s->state_save_area.gdtr.attrib = 0;
+    vmcb_s->state_save_area.gdtr.limit = 0x3f;
+    vmcb_s->state_save_area.gdtr.base = (unsigned long) gdt;
+
+    vmcb_s->state_save_area.ldtr.selector = 0;
+    vmcb_s->state_save_area.ldtr.attrib = 0;
+    vmcb_s->state_save_area.ldtr.limit = 0;
+    vmcb_s->state_save_area.ldtr.base = 0;
+
+    vmcb_s->state_save_area.idtr.selector = 0;
+    vmcb_s->state_save_area.idtr.attrib = 0;
+    vmcb_s->state_save_area.idtr.limit = 0xff;
+    vmcb_s->state_save_area.idtr.base = (unsigned long) idt;
+
+    vmcb_s->state_save_area.tr.selector = 0x28;
+    vmcb_s->state_save_area.tr.attrib = 0x8b;
+    vmcb_s->state_save_area.tr.limit = 0x67;
+    vmcb_s->state_save_area.tr.base = 0;
+
+    vmcb_s->state_save_area.g_pat = 0x7040600010406ULL;
+}
 
+static int check_svm(void) {
+    l4_umword_t ax, bx, cx, dx;
 
-//  vmcb[256 +  0] = 0;        // es; attrib sel
+    if (!l4util_cpu_has_cpuid())
+        return 1;
 
-  vmcb_s->state_save_area.cs.selector = 0x8;
-  vmcb_s->state_save_area.cs.attrib = 0xc9b;
-  vmcb_s->state_save_area.cs.limit  = 0xffffffff;
-  vmcb_s->state_save_area.cs.base = 0ULL;
+    l4util_cpu_cpuid(0x80000001, &ax, &bx, &cx, &dx);
 
-  vmcb_s->state_save_area.ss.selector = 0x10;
-  vmcb_s->state_save_area.ss.attrib = 0xc93;
-  vmcb_s->state_save_area.ss.limit  = 0xffffffff;
-  vmcb_s->state_save_area.ss.base = 0ULL;
+    if (!(cx & 4)) {
+        printf("CPU does not support SVM.\n");
+        return 1;
+    }
 
+    l4util_cpu_cpuid(0x8000000a, &ax, &bx, &cx, &dx);
 
-  vmcb_s->state_save_area.ds.selector = 0x23;
-  vmcb_s->state_save_area.ds.attrib = 0xcf3;
-  vmcb_s->state_save_area.ds.limit  = 0xffffffff;
-  vmcb_s->state_save_area.ds.base = 0ULL;
+    printf("SVM revision: %lx\n", ax & 0xf);
+    printf("Number of ASIDs: %lx\n", bx);
 
-  vmcb_s->state_save_area.fs.selector = 0;
-  vmcb_s->state_save_area.fs.attrib = 0xcf3;
-  vmcb_s->state_save_area.fs.limit  = 0xffffffff;
-  vmcb_s->state_save_area.fs.base = 0ULL;
+    return 0;
+}
 
-  vmcb_s->state_save_area.gs.selector = 0;
-  vmcb_s->state_save_area.gs.attrib = 0xcf3;
-  vmcb_s->state_save_area.gs.limit  = 0xffffffff;
-  vmcb_s->state_save_area.gs.base = 0ULL;
+static int check_svm_npt(void) {
+    l4_umword_t ax, bx, cx, dx;
 
-  vmcb_s->state_save_area.gdtr.selector = 0;
-  vmcb_s->state_save_area.gdtr.attrib = 0;
-  vmcb_s->state_save_area.gdtr.limit  = 0x3f;
-  vmcb_s->state_save_area.gdtr.base = (unsigned long) gdt;
+    l4util_cpu_cpuid(0x8000000a, &ax, &bx, &cx, &dx);
 
-  vmcb_s->state_save_area.ldtr.selector = 0;
-  vmcb_s->state_save_area.ldtr.attrib = 0;
-  vmcb_s->state_save_area.ldtr.limit  = 0;
-  vmcb_s->state_save_area.ldtr.base = 0;
+    printf("NPT available: %s\n", dx & 1 ? "yes" : "no");
 
-  vmcb_s->state_save_area.idtr.selector = 0;
-  vmcb_s->state_save_area.idtr.attrib = 0;
-  vmcb_s->state_save_area.idtr.limit  = 0xff;
-  vmcb_s->state_save_area.idtr.base = (unsigned long) idt;
+    return (!(dx & 1));
+}
 
-  vmcb_s->state_save_area.tr.selector = 0x28;
-  vmcb_s->state_save_area.tr.attrib = 0x8b;
-  vmcb_s->state_save_area.tr.limit  = 0x67;
-  vmcb_s->state_save_area.tr.base = 0;
+int vmexit = 0;
+
+static int cnt_triggered, cnt_received;
+
+static void handler(void) {
+    //if(vmexit){
+        //vmexit = 0;
+        //handle_vmexit();
+    //} else {
+        // exception and ipc handling here
+    cnt_received++;
+    printf("received interrupt %d | %d %d\n", (int)vcpu->i.label,
+           cnt_triggered, cnt_received);
+    //}
+    vm_resume();
+}
 
-  vmcb_s->state_save_area.g_pat = 0x7040600010406ULL;
+void vm_resume(void) {
+    unsigned long long old_rip;
+    l4_msgtag_t tag;
+
+//    if ((vmcb_s->state_save_area.rip >= marker)) {
+//        //printf("set tf for rip=%llx\n", vmcb_s->state_save_area.rip);
+//        vmcb_s->state_save_area.rflags |= 0x100; // set tf
+//    }
+
+    vmcb_s->control_area.intercept_exceptions |= 0xa; // intercept #1 & #3
+    vmcb_s->control_area.intercept_exceptions |= 0xffffffff;
+    vmcb_s->control_area.intercept_instruction1 |= 0x20; // intercept int1
+
+    //vmcb_s->control_area.exitcode = 0x100 << i;
+    vmcb_s->control_area.exitcode = 0;
+
+    old_rip = vmcb_s->state_save_area.rip;
+
+    tag = l4_thread_vcpu_resume_commit(L4_INVALID_CAP,
+            l4_thread_vcpu_resume_start());
+    if (l4_error(tag))
+        printf("vm-resume failed: %s (%ld)\n", l4sys_errtostr(l4_error(tag)),
+                l4_error(tag));
+
+    // if l4_thread_vcpu_resume_commit returns without error
+    // tell the handler that a vmexit occurred
+    vmexit = 1;
+    // and rewind the stack before we return into the handler
+    // simulating an upcall
+    handle_vmexit();
+    vm_resume();
+#if 0
+    asm volatile (
+            "movl %0, %%esp\n"
+            "pushl %1\n"
+            "ret\n"
+            : : "r"(vcpu->entry_sp), "r"(handler) );
+#endif
 }
 
-static int check_svm(void)
-{
-  l4_umword_t ax, bx, cx, dx;
+void handle_vmexit(void) {
+    static unsigned int i = 0;
+    ++i;
+    printf("iteration=%d, exit code=%llx", i,
+            vmcb_s->control_area.exitcode);
 
-  if (!l4util_cpu_has_cpuid())
-    return 1;
+    if (vmcb_s->control_area.exitcode == 0x43)
+        // int3 is treated as fault, not trap
+        vmcb_s->state_save_area.rip += 1;
 
-  l4util_cpu_cpuid(0x80000001, &ax, &bx, &cx, &dx);
+    if (vmcb_s->control_area.exitcode == 0x46) {
+//        if (vmcb_s->state_save_area.rip >= test_end)
+//            break;
+        vmcb_s->state_save_area.rip += 2;
+    }
 
-  if (!(cx & 4))
-    {
-      printf("CPU does not support SVM.\n");
-      return 1;
+    if (vmcb_s->control_area.exitcode == 0x400) {
+        printf("host-level page fault; error code=%llx, gpa=%llx\n",
+                vmcb_s->control_area.exitinfo1, vmcb_s->control_area.exitinfo2);
     }
 
-  l4util_cpu_cpuid(0x8000000a, &ax, &bx, &cx, &dx);
+    if (vmcb_s->control_area.exitcode == 0x4e) {
+        printf("page fault; error code=%llx, pfa=%llx\n",
+                vmcb_s->control_area.exitinfo1, vmcb_s->control_area.exitinfo2);
+    }
 
-  printf("SVM revision: %lx\n", ax & 0xf);
-  printf("Number of ASIDs: %lx\n", bx);
+    if (vmcb_s->control_area.exitcode == 0x81) {
+        printf("VMMCALL\n");
+        vmcb_s->state_save_area.rip += 3;
+    }
 
-  return 0;
+    if (vmcb_s->control_area.exitcode == 0x4d) {
+        printf("cs=%08x attrib=%x, limit=%x, base=%llx\n",
+                vmcb_s->state_save_area.cs.selector,
+                vmcb_s->state_save_area.cs.attrib,
+                vmcb_s->state_save_area.cs.limit,
+                vmcb_s->state_save_area.cs.base);
+        printf("ss=%08x attrib=%x, limit=%x, base=%llx\n",
+                vmcb_s->state_save_area.ss.selector,
+                vmcb_s->state_save_area.ss.attrib,
+                vmcb_s->state_save_area.ss.limit,
+                vmcb_s->state_save_area.ss.base);
+        printf("np_enabled=%lld\n", vmcb_s->control_area.np_enable);
+        printf("cr0=%llx cr4=%llx\n", vmcb_s->state_save_area.cr0,
+                vmcb_s->state_save_area.cr4);
+        printf("interrupt_ctl=%llx\n", vmcb_s->control_area.interrupt_ctl);
+        printf("rip=%llx, rsp=%llx, cpl=%d\n", vmcb_s->state_save_area.rip,
+                vmcb_s->state_save_area.rsp, vmcb_s->state_save_area.cpl);
+        printf("exitinfo1=%llx\n", vmcb_s->control_area.exitinfo1);
+    }
 }
 
-static int check_svm_npt(void)
-{
-  l4_umword_t ax, bx, cx, dx;
-
-  l4util_cpu_cpuid(0x8000000a, &ax, &bx, &cx, &dx);
-
-  printf("NPT available: %s\n", dx & 1 ? "yes" : "no");
-
-  return (!(dx & 1));
-}
+static l4_vcpu_state_t *get_state_mem(l4_addr_t *extstate) {
+    static int done;
+    long r;
+    l4_msgtag_t tag;
+    static l4_addr_t ext_state;
 
-static l4_vcpu_state_t *get_state_mem(l4_addr_t *extstate)
-{
-  static int done;
-  long r;
-  l4_msgtag_t tag;
-  static l4_vcpu_state_t *vcpu;
-  static l4_addr_t ext_state;
-
-  if (done)
-    {
-      *extstate = ext_state;
-      return vcpu;
+    if (done) {
+        *extstate = ext_state;
+        return vcpu;
     }
 
-  if ((r = l4vcpu_ext_alloc(&vcpu, &ext_state,
-                            L4_BASE_TASK_CAP, l4re_env()->rm)))
-    {
-      printf("Adding state mem failed: %ld\n", r);
-      exit(1);
+    if ((r = l4vcpu_ext_alloc(&vcpu, &ext_state, L4_BASE_TASK_CAP,
+            l4re_env()->rm))) {
+        printf("Adding state mem failed: %ld\n", r);
+        exit(1);
     }
 
-  vcpu->state       = L4_VCPU_F_FPU_ENABLED;
-  vcpu->saved_state = L4_VCPU_F_USER_MODE | L4_VCPU_F_FPU_ENABLED;
+    vcpu->state = L4_VCPU_F_FPU_ENABLED;
+    vcpu->saved_state = L4_VCPU_F_USER_MODE | L4_VCPU_F_FPU_ENABLED | L4_VCPU_F_IRQ;
+
+    vcpu->entry_ip = (l4_umword_t)handler;
+    l4_umword_t * stack = (l4_umword_t*)(hdl_stack + STACKSIZE);
+    --stack;
+    *stack = 0;
+    vcpu->entry_sp = (l4_umword_t)stack;
+
 
-  tag = l4_thread_vcpu_control_ext(L4_INVALID_CAP, (l4_addr_t)vcpu);
-  if (l4_error(tag))
-    {
-      printf("Could not enable ext vCPU\n");
-      exit(1);
+    tag = l4_thread_vcpu_control_ext(L4_INVALID_CAP, (l4_addr_t) vcpu);
+    if (l4_error(tag)) {
+        printf("Could not enable ext vCPU\n");
+        exit(1);
     }
 
-  done = 1;
-  *extstate = ext_state;
+    done = 1;
+    *extstate = ext_state;
 
-  return vcpu;
+    return vcpu;
 }
 
-static void run_test(int np_available)
-{
-  l4_umword_t eflags;
-  l4_msgtag_t tag;
-  l4_cap_idx_t vm_task = l4re_util_cap_alloc();
-  int i;
-  l4_umword_t ip, marker, test_end;
-  l4_addr_t vmcx;
-  l4_vcpu_state_t *vcpu = get_state_mem(&vmcx);
-
-  printf("run test, np_available=%d\n", np_available);
-
-  if (l4_is_invalid_cap(vm_task))
-    {
-      printf("No more caps.\n");
-      return;
+
+static void run_test(int np_available) {
+    l4_umword_t eflags;
+    l4_msgtag_t tag;
+    l4_cap_idx_t vm_task = l4re_util_cap_alloc();
+//    int i;
+    l4_umword_t ip; //, marker, test_end;
+    l4_addr_t vmcx;
+    get_state_mem(&vmcx);
+
+    printf("run test, np_available=%d\n", np_available);
+
+    if (l4_is_invalid_cap(vm_task)) {
+        printf("No more caps.\n");
+        return;
     }
 
-  tag = l4_factory_create_vm(l4re_env()->factory, vm_task);
-  if (l4_error(tag))
-    {
-      printf("Failed to create new task\n");
-      exit(1);
+    tag = l4_factory_create_vm(l4re_env()->factory, vm_task);
+    if (l4_error(tag)) {
+        printf("Failed to create new task\n");
+        exit(1);
     }
 
-  l4_vm_svm_vmcb_t *vmcb_s = (l4_vm_svm_vmcb_t *)vmcx;
-
-  vcpu->user_task = vm_task;
-
-  vcpu->r.dx = 1;
-  vcpu->r.cx = 2;
-  vcpu->r.bx = 3;
-  vcpu->r.bp = 4;
-  vcpu->r.si = 5;
-  vcpu->r.di = 6;
-
-  printf("clearing exit codes\n");
-
-  asm volatile("    jmp 1f;           \n"
-               "2:  nop               \n"
-               "    nop               \n"
-               "    ud2               \n"
-               "    int3              \n"
-               "3:  nop               \n"
-               "    nop               \n"
-               "    int3              \n"
-               //"3:  nop               \n"
-               //"    int3              \n"
-               "    nop               \n"
-               "    nop               \n"
-               "    movl %%eax, %%ecx \n"
-               "    addl %%edx, %%ecx \n"
-               "    vmmcall           \n"
-               "4:                    \n"
-               "    ud2               \n"
-               "1:  movl $2b, %0      \n"
-               "    movl $3b, %1      \n"
-               "    movl $4b, %2      \n"
-               : "=r" (ip), "=r" (marker), "=r" (test_end));
-
-
-  init_vmcb(vmcb_s);
-
-  vmcb_s->state_save_area.cpl = 0;
-  vmcb_s->state_save_area.efer = 0x1000; // svme set
-
-  vmcb_s->state_save_area.cr4 = 0x690;
-  vmcb_s->state_save_area.cr3 = 0;
-  // PG[31] = 0, WP[16] = 1, NE[5]  = 1, ET[4]  = 1
-  // TS[3]  = 1, MP[1]  = 1, PE[0]  = 1
-  vmcb_s->state_save_area.cr0 = 0x1003b; 
-
-  if (!np_available)
-    {
-      vmcb_s->state_save_area.cr0    |= 0x80000000;  // PG = 1
-      vmcb_s->control_area.np_enable &= ~1;
+    vmcb_s = (l4_vm_svm_vmcb_t *) vmcx;
+
+    vcpu->user_task = vm_task;
+
+    vcpu->r.dx = 1;
+    vcpu->r.cx = 2;
+    vcpu->r.bx = 3;
+    vcpu->r.bp = 4;
+    vcpu->r.si = 5;
+    vcpu->r.di = 6;
+
+    printf("clearing exit codes\n");
+
+    //  asm volatile("    jmp 1f;           \n"
+    //               "2:  nop               \n"
+    //               "    nop               \n"
+    //               "    ud2               \n"
+    //               "    int3              \n"
+    //               "3:  nop               \n"
+    //               "    nop               \n"
+    //               "    int3              \n"
+    //               //"3:  nop               \n"
+    //               //"    int3              \n"
+    //               "    nop               \n"
+    //               "    nop               \n"
+    //               "    movl %%eax, %%ecx \n"
+    //               "    addl %%edx, %%ecx \n"
+    //               "    vmmcall           \n"
+    //               "4:                    \n"
+    //               "    ud2               \n"
+    //               "1:  movl $2b, %0      \n"
+    //               "    movl $3b, %1      \n"
+    //               "    movl $4b, %2      \n"
+    //               : "=r" (ip), "=r" (marker), "=r" (test_end));
+
+    asm volatile("    jmp 1f;           \n"
+            "2:  nop               \n"
+            "    nop               \n"
+            "    nop               \n"
+            "    jmp 2b            \n"
+            "1:  movl $2b, %0      \n"
+            : "=r" (ip));
+
+    init_vmcb(vmcb_s);
+
+    vmcb_s->state_save_area.cpl = 0;
+    vmcb_s->state_save_area.efer = 0x1000; // svme set
+
+    vmcb_s->state_save_area.cr4 = 0x690;
+    vmcb_s->state_save_area.cr3 = 0;
+    // PG[31] = 0, WP[16] = 1, NE[5]  = 1, ET[4]  = 1
+    // TS[3]  = 1, MP[1]  = 1, PE[0]  = 1
+    vmcb_s->state_save_area.cr0 = 0x1003b;
+
+    if (!np_available) {
+        vmcb_s->state_save_area.cr0 |= 0x80000000; // PG = 1
+        vmcb_s->control_area.np_enable &= ~1;
     }
 
-  vmcb_s->state_save_area.dr7 = 0x300;
-  vmcb_s->state_save_area.dr6 = 0;
+    vmcb_s->state_save_area.dr7 = 0x300;
+    vmcb_s->state_save_area.dr6 = 0;
 
-  asm volatile("pushf     \n"
-               "popl %0   \n"
-               : "=r" (eflags));
+    asm volatile("pushf     \n"
+            "popl %0   \n"
+            : "=r" (eflags));
 
-  vmcb_s->state_save_area.rflags = eflags;
-  vmcb_s->state_save_area.rip = ip;
-  vmcb_s->state_save_area.rsp = (l4_umword_t)stack + STACKSIZE;
+    vmcb_s->state_save_area.rflags = eflags;
+    vmcb_s->state_save_area.rip = ip;
+    vmcb_s->state_save_area.rsp = (l4_umword_t) stack + STACKSIZE;
 
-  unsigned ofs;
-  for (ofs = 0; ofs < STACKSIZE; ofs += L4_PAGESIZE)
-    {
-      stack[ofs] = 0;
-      unsigned char c = stack[ofs];
-      unsigned dummy;
+    unsigned ofs;
+    for (ofs = 0; ofs < STACKSIZE; ofs += L4_PAGESIZE) {
+        stack[ofs] = 0;
+        unsigned char c = stack[ofs];
+        unsigned dummy;
 
-      asm volatile("nop" : "=a"(dummy) : "0" (c));
+        asm volatile("nop" : "=a"(dummy) : "0" (c));
 
-      tag = l4_task_map(vm_task, L4RE_THIS_TASK_CAP,
-                        l4_fpage((((l4_umword_t)(stack)) + ofs) & L4_PAGEMASK,
-                                 L4_PAGESHIFT, L4_FPAGE_RW),
-                        l4_map_control(((l4_umword_t)stack) +  ofs, 0,
-                                       L4_MAP_ITEM_MAP));
-      printf("msgtag raw=%08x, ofs=%08x\n", (unsigned) tag.raw, ofs);
+        tag = l4_task_map(vm_task, L4RE_THIS_TASK_CAP, l4_fpage(
+                (((l4_umword_t)(stack)) + ofs) & L4_PAGEMASK, L4_PAGESHIFT,
+                L4_FPAGE_RW), l4_map_control(((l4_umword_t) stack) + ofs, 0,
+                L4_MAP_ITEM_MAP));
+        printf("msgtag raw=%08x, ofs=%08x\n", (unsigned) tag.raw, ofs);
     }
 
-  tag = l4_task_map(vm_task, L4RE_THIS_TASK_CAP,
-                    l4_fpage(ip & L4_PAGEMASK, L4_PAGESHIFT, L4_FPAGE_RW),
-                    l4_map_control(ip, 0, L4_MAP_ITEM_MAP));
-
-  printf("msgtag raw=%08lx, ip=%08lx\n", tag.raw, ip);
-
-  idt[26] = 0x80000; // #13 general protection fault
-  idt[27] = 0x8e00;
+    tag = l4_task_map(vm_task, L4RE_THIS_TASK_CAP, l4_fpage(ip & L4_PAGEMASK,
+            L4_PAGESHIFT, L4_FPAGE_RW), l4_map_control(ip, 0, L4_MAP_ITEM_MAP));
 
-  idt[28] = 0x80000; // #14 page fault
-  idt[29] = 0x8e00;
+    printf("msgtag raw=%08lx, ip=%08lx\n", tag.raw, ip);
 
-  // code segment 0x08
-  gdt[2] = 0xffff;
-  gdt[3] = 0xcf9b00;
+    idt[26] = 0x80000; // #13 general protection fault
+    idt[27] = 0x8e00;
 
-  // stack segment 0x10
-  gdt[4] = 0xffff;
-  gdt[5] = 0xcf9300;
+    idt[28] = 0x80000; // #14 page fault
+    idt[29] = 0x8e00;
 
-  // data segment 0x20
-  gdt[8] = 0xffff;
-  gdt[9] = 0xcff300;
+    // code segment 0x08
+    gdt[2] = 0xffff;
+    gdt[3] = 0xcf9b00;
 
-  // tss 0x28
-  gdt[10] = 0x67;
-  gdt[11] = 0x8b00;
+    // stack segment 0x10
+    gdt[4] = 0xffff;
+    gdt[5] = 0xcf9300;
 
-  unsigned idt0 = (unsigned) idt;
-  tag = l4_task_map(vm_task, L4RE_THIS_TASK_CAP,
-                    l4_fpage(idt0 & L4_PAGEMASK, L4_PAGESHIFT, L4_FPAGE_RW),
-                    l4_map_control(idt0, 0, L4_MAP_ITEM_MAP));
-  printf("msgtag raw=%08x, idt=%08x\n", (unsigned) tag.raw, idt0);
+    // data segment 0x20
+    gdt[8] = 0xffff;
+    gdt[9] = 0xcff300;
 
-  unsigned gdt0 = (unsigned) gdt;
-  tag = l4_task_map(vm_task, L4RE_THIS_TASK_CAP,
-                    l4_fpage(gdt0 & L4_PAGEMASK, L4_PAGESHIFT, L4_FPAGE_RW),
-                    l4_map_control(gdt0, 0, L4_MAP_ITEM_MAP));
-  printf("msgtag raw=%08x, gdt=%08x\n", (unsigned) tag.raw, gdt0);
+    // tss 0x28
+    gdt[10] = 0x67;
+    gdt[11] = 0x8b00;
 
+    unsigned idt0 = (unsigned) idt;
+    tag = l4_task_map(vm_task, L4RE_THIS_TASK_CAP, l4_fpage(idt0 & L4_PAGEMASK,
+            L4_PAGESHIFT, L4_FPAGE_RW),
+            l4_map_control(idt0, 0, L4_MAP_ITEM_MAP));
+    printf("msgtag raw=%08x, idt=%08x\n", (unsigned) tag.raw, idt0);
 
-//  printf("sizes vmcb=%x, control=%x,  state=%x\n",
-//         sizeof(*vmcb_s),
-//         sizeof(vmcb_s->control_area), sizeof(vmcb_s->sitate_save_area));
+    unsigned gdt0 = (unsigned) gdt;
+    tag = l4_task_map(vm_task, L4RE_THIS_TASK_CAP, l4_fpage(gdt0 & L4_PAGEMASK,
+            L4_PAGESHIFT, L4_FPAGE_RW),
+            l4_map_control(gdt0, 0, L4_MAP_ITEM_MAP));
+    printf("msgtag raw=%08x, gdt=%08x\n", (unsigned) tag.raw, gdt0);
 
-  printf("start rip=%llx\n", vmcb_s->state_save_area.rip);
+    //  printf("sizes vmcb=%x, control=%x,  state=%x\n",
+    //         sizeof(*vmcb_s),
+    //         sizeof(vmcb_s->control_area), sizeof(vmcb_s->sitate_save_area));
 
-  vmcb_s->state_save_area.rax = 8;
+    printf("start rip=%llx\n", vmcb_s->state_save_area.rip);
 
-  for (i = 0; i < 16; i++)
-    {
-      unsigned long long old_rip;
+    vmcb_s->state_save_area.rax = 8;
 
-      if ((vmcb_s->state_save_area.rip >= marker))
-        {
-          //printf("set tf for rip=%llx\n", vmcb_s->state_save_area.rip);
-          vmcb_s->state_save_area.rflags |= 0x100; // set tf
-        }
+    vm_resume();
 
-      vmcb_s->control_area.intercept_exceptions |= 0xa; // intercept #1 & #3
-      vmcb_s->control_area.intercept_exceptions |= 0xffffffff;
-      vmcb_s->control_area.intercept_instruction1 |= 0x20; // intercept int1
-
-      //vmcb_s->control_area.exitcode = 0x100 << i;
-      vmcb_s->control_area.exitcode = 0;
+}
 
-      old_rip = vmcb_s->state_save_area.rip;
 
+//  printf("rip=%08llx, rax=%llx, edx=%lx, ecx=%lx\n",
+//         vmcb_s->state_save_area.rip,
+//         vmcb_s->state_save_area.rax,
+//         vcpu->r.dx, vcpu->r.cx);
+//
+//  printf("run vm stop, status=%s\n", vcpu->r.cx == 9 ? "success" : "failure");
+//
+//  l4_task_unmap(L4RE_THIS_TASK_CAP,
+//                l4_obj_fpage(vm_task, 0, L4_FPAGE_RWX),
+//                L4_FP_ALL_SPACES);
+//}
+
+#include <l4/sys/ktrace.h>
+l4_cap_idx_t timer_irq;
+void * timer_thread(void * );
+void * timer_thread(void * data) {
+    (void)data;
+    l4_sleep(1000);
+    fiasco_tbuf_log("FIRST");
+    while(1){
+        l4_sleep(200);
+        fiasco_tbuf_log("Trig");
+        printf("trigger\n");
+        cnt_triggered++;
+        l4_irq_trigger(timer_irq);
+    }
+}
 
-      tag = l4_thread_vcpu_resume_commit(L4_INVALID_CAP,
-                                         l4_thread_vcpu_resume_start());
-      if (l4_error(tag))
-       printf("vm-resume failed: %s (%ld)\n",
-               l4sys_errtostr(l4_error(tag)), l4_error(tag));
+#include <unistd.h>
 
-      printf("iteration=%d, exit code=%llx, rip=%llx -> %llx\n",
-             i, vmcb_s->control_area.exitcode,
-             old_rip, vmcb_s->state_save_area.rip);
+int main(void)
+{
+    timer_irq = l4re_util_cap_alloc();
+    if (l4_error(l4_factory_create_irq(l4re_env()->factory, timer_irq)))
+      printf("irq creation failed\n");
 
+    if (l4_error(l4_irq_attach(timer_irq, 0x120, L4_INVALID_CAP)))
+        printf("irq attach failed\n");
 
-      if (vmcb_s->control_area.exitcode == 0x43)
-        // int3 is treated as fault, not trap
-        vmcb_s->state_save_area.rip += 1;
+    printf("VM testing\n");
 
-      if (vmcb_s->control_area.exitcode == 0x46)
-        {
-          if (vmcb_s->state_save_area.rip >= test_end)
-            break;
-          vmcb_s->state_save_area.rip += 2;
-        }
-
-      if (vmcb_s->control_area.exitcode == 0x400)
-        {
-          printf("host-level page fault; error code=%llx, gpa=%llx\n",
-                 vmcb_s->control_area.exitinfo1,
-                 vmcb_s->control_area.exitinfo2);
-        }
-
-      if (vmcb_s->control_area.exitcode == 0x4e)
-        {
-          printf("page fault; error code=%llx, pfa=%llx\n",
-                 vmcb_s->control_area.exitinfo1,
-                 vmcb_s->control_area.exitinfo2);
-        }
-
-      if (vmcb_s->control_area.exitcode == 0x81)
-        {
-          printf("VMMCALL\n");
-          vmcb_s->state_save_area.rip += 3;
-        }
-
-      if (vmcb_s->control_area.exitcode == 0x4d)
-        {
-          printf("cs=%08x attrib=%x, limit=%x, base=%llx\n",
-                 vmcb_s->state_save_area.cs.selector,
-                 vmcb_s->state_save_area.cs.attrib,
-                 vmcb_s->state_save_area.cs.limit,
-                 vmcb_s->state_save_area.cs.base);
-          printf("ss=%08x attrib=%x, limit=%x, base=%llx\n",
-                 vmcb_s->state_save_area.ss.selector,
-                 vmcb_s->state_save_area.ss.attrib,
-                 vmcb_s->state_save_area.ss.limit,
-                 vmcb_s->state_save_area.ss.base);
-          printf("np_enabled=%lld\n",
-                 vmcb_s->control_area.np_enable);
-          printf("cr0=%llx cr4=%llx\n",
-                 vmcb_s->state_save_area.cr0,
-                 vmcb_s->state_save_area.cr4);
-          printf("interrupt_ctl=%llx\n",
-                 vmcb_s->control_area.interrupt_ctl);
-          printf("rip=%llx, rsp=%llx, cpl=%d\n",
-                 vmcb_s->state_save_area.rip,
-                 vmcb_s->state_save_area.rsp,
-                 vmcb_s->state_save_area.cpl);
-                 printf("exitinfo1=%llx\n", vmcb_s->control_area.exitinfo1);
-          break;
-        }
-  }
-
-  printf("rip=%08llx, rax=%llx, edx=%lx, ecx=%lx\n",
-         vmcb_s->state_save_area.rip,
-         vmcb_s->state_save_area.rax,
-         vcpu->r.dx, vcpu->r.cx);
-
-  printf("run vm stop, status=%s\n", vcpu->r.cx == 9 ? "success" : "failure");
-
-  l4_task_unmap(L4RE_THIS_TASK_CAP,
-                l4_obj_fpage(vm_task, 0, L4_FPAGE_RWX),
-                L4_FP_ALL_SPACES);
-}
+    if (check_svm())
+      {
+        printf("No SVM CPU. Bye.\n");
+        return 1;
+      }
 
-int main(void)
-{
-  printf("VM testing\n");
+    l4_touch_rw(stack, sizeof(stack));
+    l4_touch_rw(hdl_stack, sizeof(hdl_stack));
 
-  if (check_svm())
-    {
-      printf("No SVM CPU. Bye.\n");
-      return 1;
-    }
+    pthread_t pthread_timer_thread;
 
-  l4_touch_rw(stack, sizeof(stack));
+    pthread_create(&pthread_timer_thread, NULL, timer_thread, NULL);
 
-  run_test(0);
+    run_test(0);
 
-  if (!check_svm_npt())
-    run_test(1);
+    if (!check_svm_npt())
+        run_test(1);
 
-  return 0;
+    return 0;
 }