From f5c52c59c14135d16aa51cfa4882416e52662ef1 Mon Sep 17 00:00:00 2001
From: "iliya.saroukha" <iliya.saroukhanian@etu.hesge.ch>
Date: Tue, 10 Dec 2024 13:45:53 +0100
Subject: [PATCH] "fix": vmxon carry flag = 1

seems like i was loading the module, the process associated with it was
"almost always" scheduled to be ran on the same logical processor,
therefore when i was executing `vmxon` on a processor alreading running
vmx, it was failing (again, not sure...). gonna have grey hair soon
---
 proto/hypervisor.c | 31 ++++++++++++++++++++++++-------
 1 file changed, 24 insertions(+), 7 deletions(-)

diff --git a/proto/hypervisor.c b/proto/hypervisor.c
index 4eb4bcf..2f262fa 100644
--- a/proto/hypervisor.c
+++ b/proto/hypervisor.c
@@ -11,6 +11,7 @@
 #include <linux/slab.h>
 
 /*============== my includes ==============*/
+#include "asm/special_insns.h"
 #include "debug/debug.h"
 #include "msr/msr.h"
 #include "region/vxmon_reg.h"
@@ -31,24 +32,39 @@ static void cr4_enable_vmx(void) {
     __asm__ volatile("mov %%cr4, %0" : "=r"(cr4));
     cr4 |= (1UL << 13);
     __asm__ volatile("mov %0, %%cr4" ::"r"(cr4));
+
+    DEBUG_FMT("CR4[13].VMXE set? %s\n",
+              (__read_cr4() >> 13) & 1 ? "true" : "false");
 }
 
 static bool vmx_support_cpuid(void) {
-    unsigned int ecx = cpuid_ecx(1);
+    unsigned int eax, ebx, ecx, edx;
+    cpuid(0, &eax, &ebx, &ecx, &edx);
+
+    unsigned int ret_str[3] = {ebx, edx, ecx};
+
+    DEBUG_FMT("Vendor ID = %s\n", (char *)ret_str);
+
+    unsigned int ecx_vmx = cpuid_ecx(1);
 
     /*__asm__ volatile("mov $1, %rax");*/
     /*__asm__ volatile("cpuid");*/
     /*__asm__ volatile("mov %%ecx , %0\n\t" : "=r"(ecx));*/
 
-    return (ecx >> 5) & 1;
+    unsigned int addr_width = cpuid_eax(0x80000008);
+
+    DEBUG_FMT("Physical address width = %d\n", addr_width & 0xff);
+
+    return (ecx_vmx >> 5) & 1;
 }
 
 /*
  * https://elixir.bootlin.com/linux/v6.12.4/source/tools/testing/selftests/kvm/include/x86_64/vmx.h#L297
  */
-static unsigned char vmxon(void *pa) {
+static unsigned char vmxon(unsigned long long pa) {
     unsigned char ret;
 
+    // setna: "Set byte if not above" (CF=1 or ZF=1)
     __asm__ volatile("vmxon %[pa]; setna %[ret]"
                      : [ret] "=rm"(ret)
                      : [pa] "m"(pa)
@@ -78,10 +94,10 @@ static int my_init(void) {
     }
 
     pr_info("VA of the allocated region = 0x%px\n", vmxon_region.va);
-    pr_info("PA of the allocated region = 0x%px\n", vmxon_region.pa);
+    pr_info("PA of the allocated region = 0x%llx\n", vmxon_region.pa);
 
-    pr_info("Reading VMXON region for VMCS ID: 0x%x\n",
-            (*(uint32_t *)vmxon_region.va));
+    pr_info("Reading VMXON region for VMCS ID: 0x%lx\n",
+            (*(unsigned long *)vmxon_region.va));
 
     pr_info("Patching CR0 and CR4 depending on the value of their respective "
             "MSRs\n");
@@ -97,13 +113,14 @@ static int my_init(void) {
         return -1;
     }
 
-    pr_info("Executing VMXON with address = 0x%px as its operand\n",
+    pr_info("Executing VMXON with address = 0x%llx as its operand\n",
             vmxon_region.pa);
 
     unsigned char vmxon_ret = 0;
 
     if ((vmxon_ret = vmxon(vmxon_region.pa) != 0)) {
         kfree(vmxon_region.va);
+        __asm__ volatile("vmxoff");
         pr_err("`vmxon` failed with return code %d\n", vmxon_ret);
         return -1;
     }
-- 
GitLab