Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Allow custom CPUID
[palacios.git] / palacios / src / palacios / vmm_cpuid.c
index bd0862b..fc89183 100644 (file)
@@ -34,11 +34,92 @@ struct masked_cpuid {
 };
 
 
+void init_custom(struct v3_vm_info *vm)
+{
+  /*
+    CPUID 0
+      EAX = maxid supported  (1)
+      EBX = first 4 bytes of string
+      EDX = second 4 bytes of string
+      ECX = third 4 bytes of string
+
+    GenuineIntel
+    AuthenticAMD
+    VirtualV3VEE
+    EBX EDX ECX
+  */
+  uint32_t ebx, ecx, edx;
+
+  memcpy(&ebx,"Virt",4);
+  memcpy(&edx,"ualV",4);
+  memcpy(&ecx,"3VEE",4);
+
+
+  // In the Intel Space, we are a VirtualV3VEE 
+  // and our maximum cpuid is 0x1
+  v3_cpuid_add_fields(vm,0x0,             // ID 0 (Vendor)
+                     0xffffffff, 1,      // Max CPUID is one
+                     0xffffffff, ebx,
+                     0xffffffff, ecx,
+                     0xffffffff, edx);
+
+  // In the AMD Space, we are a Virtual V3VEE
+  // and our maximum cpuid is 0x80000001
+  // other than the maximum cpuid, this is identical to Intel 0x0
+  //
+  v3_cpuid_add_fields(vm,0x80000000,          // ID 8...0 (Vendor - AMD variant)
+                     0xffffffff, 0x80000001, // Max CPUID is one
+                     0xffffffff, ebx,
+                     0xffffffff, ecx,
+                     0xffffffff, edx);
+
+  /* CPUID 1, EAX - Family, Model, Stepping 
+     We are Family 16, Model 1, Stepping 1 (family 16 puts us in x86-64)
+     31:28 = reserved
+     27:20 = extended family (extfam)
+     19:16 = extended model (extmod)
+     15:12 = reserved
+     11:8  = base family (basfam)
+     7:4   = base model  (basmod)
+     3:0   = stepping
+
+     family = extfam+basefam, model=extmod:basmod
+     but we need to "top out" basefam first (0xf)
+
+     So we want: 0x00100f11
+
+     EBX is probably bogus here, since we need the apic ids
+     of the vcores, not the pcores
+  */
+
+  // in Intel Space, we are family 16, model 1, stepping 1
+  // and our other features are passthrough
+  v3_cpuid_add_fields(vm,0x1,
+                     0xffffffff, 0x00100f11,
+                     0x0, 0,
+                     0x0, 0,
+                     0x0, 0);
+
+  // In the AMD space, we are family 16, model 1, stepping 1
+  // with other features passthrough
+  // These other fields are *different* from Intel's 0x1, however
+  // in particular, long mode is here, even if it's an Intel...
+  v3_cpuid_add_fields(vm,0x80000001, // AMD variant
+                     0xffffffff, 0x00100f11,
+                     0x0, 0,
+                     0x0, 0,
+                     0x0, 0);
+      
+} 
+
 void v3_init_cpuid_map(struct v3_vm_info * vm) {
     vm->cpuid_map.map.rb_node = NULL;
 
     // Setup default cpuid entries
 
+#ifdef V3_CONFIG_CUSTOM_CPUID
+    init_custom(vm);
+#endif
 
     // Disable XSAVE (cpuid 0x01, ECX bit 26)
     v3_cpuid_add_fields(vm, 0x01, 0, 0, 0, 0, (1 << 26), 0, 0, 0);
@@ -46,6 +127,30 @@ void v3_init_cpuid_map(struct v3_vm_info * vm) {
     // Disable MONITOR/MWAIT (cpuid 0x01, ECX bit 3)
     v3_cpuid_add_fields(vm, 0x01, 0, 0, 0, 0, (1 << 3), 0, 0, 0);
 
+
+    // disable MTRR
+    v3_cpuid_add_fields(vm, 0x00000001, 0, 0, 0, 0, 0, 0, (1 << 12), 0);
+    // disable PAT
+    v3_cpuid_add_fields(vm, 0x00000001, 0, 0, 0, 0, 0, 0, (1 << 16), 0);
+    // disable HTT
+    v3_cpuid_add_fields(vm, 0x00000001, 0, 0, 0, 0, 0, 0, (1 << 28), 0);
+
+    // disable X2APIC
+    v3_cpuid_add_fields(vm, 0x00000001, 0, 0, 0, 0, (1 << 21), 0, 0, 0);
+
+
+    // Demarcate machine as a VM
+    v3_cpuid_add_fields(vm, 0x00000001,
+                        0, 0,
+                        0, 0,
+                        0x80000000, 0x80000000,
+                        0, 0
+                        );
+
+
+    // disable ARAT
+    v3_cpuid_add_fields(vm, 0x00000006, (1 << 2), 0, 0, 0, 0, 0, 0, 0);
+
 }
 
 
@@ -169,7 +274,7 @@ int v3_cpuid_add_fields(struct v3_vm_info * vm, uint32_t cpuid,
 
     if ((~rax_mask & rax) || (~rbx_mask & rbx) ||
        (~rcx_mask & rcx) || (~rdx_mask & rdx)) {
-       PrintError("Invalid cpuid reg value (mask overrun)\n");
+       PrintError(vm, VCORE_NONE, "Invalid cpuid reg value (mask overrun)\n");
        return -1;
     }
 
@@ -178,7 +283,7 @@ int v3_cpuid_add_fields(struct v3_vm_info * vm, uint32_t cpuid,
        struct masked_cpuid * mask = V3_Malloc(sizeof(struct masked_cpuid));
 
        if (!mask) {
-           PrintError("Unable to alocate space for cpu id mask\n");
+           PrintError(vm, VCORE_NONE, "Unable to alocate space for cpu id mask\n");
            return -1;
        }
 
@@ -194,7 +299,7 @@ int v3_cpuid_add_fields(struct v3_vm_info * vm, uint32_t cpuid,
        mask->rdx = rdx;
 
        if (v3_hook_cpuid(vm, cpuid, mask_hook, mask) == -1) {
-           PrintError("Error hooking cpuid %d\n", cpuid);
+           PrintError(vm, VCORE_NONE, "Error hooking cpuid %d\n", cpuid);
            V3_Free(mask);
            return -1;
        }
@@ -203,7 +308,7 @@ int v3_cpuid_add_fields(struct v3_vm_info * vm, uint32_t cpuid,
        uint32_t tmp_val = 0;
 
        if (hook->hook_fn != mask_hook) {
-           PrintError("trying to add fields to a fully hooked cpuid (%d)\n", cpuid);
+           PrintError(vm, VCORE_NONE, "trying to add fields to a fully hooked cpuid (%d)\n", cpuid);
            return -1;
        }
        
@@ -213,7 +318,7 @@ int v3_cpuid_add_fields(struct v3_vm_info * vm, uint32_t cpuid,
            (mask->rbx_mask & rbx_mask) || 
            (mask->rcx_mask & rcx_mask) || 
            (mask->rdx_mask & rdx_mask)) {
-           PrintError("Trying to add fields that have already been masked\n");
+           PrintError(vm, VCORE_NONE, "Trying to add fields that have already been masked\n");
            return -1;
        }
 
@@ -247,7 +352,7 @@ int v3_unhook_cpuid(struct v3_vm_info * vm, uint32_t cpuid) {
     struct v3_cpuid_hook * hook = get_cpuid_hook(vm, cpuid);
 
     if (hook == NULL) {
-       PrintError("Could not find cpuid to unhook (0x%x)\n", cpuid);
+       PrintError(vm, VCORE_NONE, "Could not find cpuid to unhook (0x%x)\n", cpuid);
        return -1;
     }
 
@@ -267,14 +372,14 @@ int v3_hook_cpuid(struct v3_vm_info * vm, uint32_t cpuid,
     struct v3_cpuid_hook * hook = NULL;
 
     if (hook_fn == NULL) {
-       PrintError("CPUID hook requested with null handler\n");
+       PrintError(vm, VCORE_NONE, "CPUID hook requested with null handler\n");
        return -1;
     }
 
     hook = (struct v3_cpuid_hook *)V3_Malloc(sizeof(struct v3_cpuid_hook));
 
     if (!hook) {
-       PrintError("Cannot allocate memory to hook cpu id\n");
+       PrintError(vm, VCORE_NONE, "Cannot allocate memory to hook cpu id\n");
        return -1;
     }
 
@@ -283,7 +388,7 @@ int v3_hook_cpuid(struct v3_vm_info * vm, uint32_t cpuid,
     hook->hook_fn = hook_fn;
 
     if (insert_cpuid_hook(vm, hook)) {
-       PrintError("Could not hook cpuid 0x%x (already hooked)\n", cpuid);
+       PrintError(vm, VCORE_NONE, "Could not hook cpuid 0x%x (already hooked)\n", cpuid);
        V3_Free(hook);
        return -1;
     }
@@ -295,10 +400,10 @@ int v3_handle_cpuid(struct guest_info * info) {
     uint32_t cpuid = info->vm_regs.rax;
     struct v3_cpuid_hook * hook = get_cpuid_hook(info->vm_info, cpuid);
 
-    //PrintDebug("CPUID called for 0x%x\n", cpuid);
+    //PrintDebug(info->vm_info, info, "CPUID called for 0x%x\n", cpuid);
 
     if (hook == NULL) {
-       //PrintDebug("Calling passthrough handler\n");
+       //PrintDebug(info->vm_info, info, "Calling passthrough handler\n");
        // call the passthrough handler
        v3_cpuid(cpuid, 
                 (uint32_t *)&(info->vm_regs.rax), 
@@ -306,7 +411,7 @@ int v3_handle_cpuid(struct guest_info * info) {
                 (uint32_t *)&(info->vm_regs.rcx), 
                 (uint32_t *)&(info->vm_regs.rdx));
     } else {
-       //      PrintDebug("Calling hook function\n");
+       //      PrintDebug(info->vm_info, info, "Calling hook function\n");
 
        if (hook->hook_fn(info, cpuid, 
                          (uint32_t *)&(info->vm_regs.rax), 
@@ -314,12 +419,12 @@ int v3_handle_cpuid(struct guest_info * info) {
                          (uint32_t *)&(info->vm_regs.rcx), 
                          (uint32_t *)&(info->vm_regs.rdx), 
                          hook->private_data) == -1) {
-           PrintError("Error in cpuid handler for 0x%x\n", cpuid);
+           PrintError(info->vm_info, info, "Error in cpuid handler for 0x%x\n", cpuid);
            return -1;
        }
     }
 
-    //    PrintDebug("Cleaning up register contents\n");
+    //    PrintDebug(info->vm_info, info, "Cleaning up register contents\n");
 
     info->vm_regs.rax &= 0x00000000ffffffffLL;
     info->vm_regs.rbx &= 0x00000000ffffffffLL;