Enable VT-X on Mac Pro (Early 2008)

From KVM

Why?

The Mac Pro is a great home server machine - twin quad core Xeons, plenty of memory capability, and very quiet. The problem is that by default, Apple doesnt enable the intel VT-X extensions, which are needed to get KVM working.

The problem

It would seem that there is a special set of registers on Intel processors called the MSR (manufacturs specific register). One of these registers is used to turn on VT-X (Intels HVM tech). The way is works is that it has 2 flags, one of which enables/disables VTX, and a lock bit, which once set prevents the VTX enable from being changed.

Normally, the PC BIOS will set and lock VTX on / off according to a setting in the CMOS setup screen.

There are 4 situations you can be in regarding this -

1. BIOS support for VT-X, in which case VTX will be locked on / off according to a bios setting 2. BIOS locks VT-X off (ie, unsets VTX enable, sets lock bit). Nothing can be done about this :( 3. BIOS locks VT-X on - you are already OK 4. BIOS does nothing...

The Mac Pro ('s EFI BIOS) does number 4 - it neither turns VTX on, nor locks it. This means we can enable it later :)

Linux has a driver called msr, which allows userland programs to write / read the MSR. It is loaded (in Ubuntu 8.10 at least) by

modprobe msr

The following is some source I ([GeorgeStyles]) wrote that when compiled (gcc -o msrmagic) will create a program that will tell you the status of your MSR (on all cores), and if its unlocked and off, will attempt to turn on VTX and lock it on. It will then stay on until the machine is power-cycled. It seems to be OK to run this, and them immediately run KVM without a reboot. This is prefereable to the other method of getting VTX turned on, which is to boot into MacOs and run a VM such as VMWare which flips MSR on.

This will probably work on other Intel based machines that have VTX capability in the CPU / Chipset, but no BIOS support.

It wont help you if the BIOS locks VTX off however

Code:

#include <sys/types.h>
#include <sys/stat.h> 
#include <fcntl.h>    
                      
#include <unistd.h>   
#include <stdio.h>    
                      
/* Returns 1 if processor found, 0 otherwise */
                                               
int setupCpu(int cpuid)                        
{                                              
 int addr = 0x3a; // VTX enable                
                                               
 char devfile[255];                            
 sprintf(devfile, "/dev/cpu/%d/msr", cpuid);   
                                               
 int fd = open(devfile, O_RDONLY);             
 if (fd==-1)                                   
 {                                             
   printf("Device %s does not exist. Either we have run out of processors, or the msr kernel module is not loaded\n", devfile);                                                                                  
   return 0;
}
                                                                                                        
 char buf[8];
                                                                                                        
//  printf("Setting up cpu %d - %s\n",cpuid, devfile);
                                                                                                        
 lseek(fd, addr, SEEK_SET);
 read(fd, buf, 8);                                                             
                                                                                                        
 char bLo = buf[0]; // Low byte
 if (bLo & 1) // locked
 { 
   if (bLo & 4)
     printf("cpud %d is locked ON :)\n", cpuid);
   else
     printf("cpud %d is locked OFF :(\n", cpuid);
 }
 else                                                                                                   
 {  // Unlocked - we can try and turn vtx on
   fd = open(devfile, O_WRONLY);
   if (fd == -1)
   {
     printf("Failed to open device %s for writing\n", devfile);
   }
   else
   {
     buf[0] = buf[0] | 5; // On + lock
     lseek(fd, addr, SEEK_SET);
     if (write(fd, buf, 8) < 0)
     {
       printf("Failed to write to device %s\n", devfile);
     }
     else
     {
       printf("cpu %d - Switched VT-X on :)\n", cpuid);
     }
   }
 }

 return 1;
}

int main(int argc, char *argv[])
{
 printf("MSR Magic 1.0 (C) 2009 George Styles www.georgestyles.co.uk\n\n");
 int iCpu = 0;
 while (setupCpu(iCpu) != 0)
 {
   iCpu++;
 }
 return 0;
}