2891 lines
67 KiB
C
Executable File
2891 lines
67 KiB
C
Executable File
/* vmm.c: This is the virtual machine
|
|
* It will be loaded at virtual address 0x00400000 (vmma.asm that is which just jumps short to intialize paging)
|
|
* On initialisation 0 to 4MB is identity mapped, to the stored memory regions are available to mess with
|
|
*/
|
|
|
|
|
|
#include "common.h"
|
|
#include "main.h"
|
|
#include "mm.h"
|
|
#include "neward.h"
|
|
#include "apic.h"
|
|
|
|
#include "multicore.h"
|
|
#include "inthandlers.h"
|
|
#include "vmmhelper.h"
|
|
#include "vmeventhandler.h"
|
|
|
|
#include "distorm.h"
|
|
#include "keyboard.h"
|
|
|
|
#include "pci.h"
|
|
#include "offloados.h"
|
|
#include "msrnames.h"
|
|
#include "vmxcontrolstructures.h"
|
|
|
|
#include "test.h"
|
|
#include "vmcall.h"
|
|
#include "vmpaging.h"
|
|
#include "vmxsetup.h"
|
|
#include "vmcall.h"
|
|
#include "exports.h"
|
|
|
|
#include "luahandler.h"
|
|
|
|
//#include "psod.h" //for pink screen of death support
|
|
|
|
/*
|
|
//#include "logo.c"
|
|
*/
|
|
|
|
#define APIC_ID_OFFSET 0x020
|
|
#define APIC_SVR_OFFSET 0x0f0
|
|
|
|
|
|
|
|
void menu(void);
|
|
void menu2(void);
|
|
|
|
|
|
|
|
PINT_VECTOR intvector=NULL;
|
|
|
|
unsigned char *ffpage=NULL;
|
|
PPTE_PAE ffpagetable=NULL;
|
|
PPDE_PAE ffpagedir=NULL;
|
|
|
|
|
|
PTSS testTSS=NULL;
|
|
|
|
int cpu_stepping;
|
|
int cpu_model;
|
|
int cpu_familyID;
|
|
int cpu_type;
|
|
int cpu_ext_modelID;
|
|
int cpu_ext_familyID;
|
|
|
|
|
|
|
|
unsigned long long IA32_APIC_BASE=0xfee00000;
|
|
unsigned long long APIC_ID=0xfee00020;
|
|
unsigned long long APIC_SVR=0xfee000f0;
|
|
|
|
unsigned int BOOT_ID=0xffffffff;
|
|
|
|
extern unsigned int isAP;
|
|
volatile int AP_Terminate; //set to 1 to terminate the AP cpu's
|
|
volatile int AP_Launch; //set to 1 to launch the AP cpu's
|
|
|
|
#if (DISPLAYDEBUG==0)
|
|
int needtospawnApplicationProcessors=1;
|
|
#else
|
|
int needtospawnApplicationProcessors=0; //the display is cluttered as it is
|
|
#endif
|
|
|
|
|
|
#define SETINT(INTNR) intvector[INTNR].wLowOffset=(WORD)(UINT64)inthandler##INTNR; \
|
|
intvector[INTNR].wHighOffset=(WORD)((UINT64)inthandler##INTNR >> 16);
|
|
|
|
|
|
#ifdef DEBUG
|
|
int autostart=0; //since simnow amd emu doesn't support serial import...
|
|
#else
|
|
int autostart=1;
|
|
#endif //debug
|
|
|
|
//int isrunning=0;
|
|
|
|
pcpuinfo firstcpuinfo, lastaddedcpuinfo; //just for debugging, nothing important
|
|
|
|
|
|
#ifdef DEBUGINTHANDLER
|
|
criticalSection cinthandlerMenuCS;
|
|
#endif
|
|
|
|
int IntHandlerDebug=0;
|
|
|
|
char bootdisk;
|
|
|
|
|
|
|
|
int cinthandler(unsigned long long *stack, int intnr) //todo: move to it's own sourcefile
|
|
{
|
|
PRFLAGS rflags;
|
|
int errorcode=0;
|
|
UINT64 errorcodeValue;
|
|
int i;
|
|
DWORD thisAPICID;
|
|
int cpunr=0;
|
|
|
|
#ifdef DEBUG
|
|
sendstringCS.ignorelock=1;
|
|
sendstringfCS.ignorelock=1;
|
|
#endif
|
|
|
|
if (readMSRSafe(IA32_FS_BASE_MSR)==0)
|
|
{
|
|
sendstringf("Invalid FS base during exception\n");
|
|
while (1) ;
|
|
}
|
|
|
|
pcpuinfo cpuinfo=getcpuinfo();
|
|
cpunr=cpuinfo->cpunr;
|
|
|
|
//debug, remove:
|
|
//if PIC_StillEnabled
|
|
//outportb(0x20,0x20);
|
|
//outportb(0xa0,0x20);
|
|
|
|
|
|
//apic_eoi();
|
|
//^^^
|
|
|
|
|
|
UINT64 originalDR7=getDR7();
|
|
|
|
if (intnr==1)
|
|
{
|
|
//disable breakpoints
|
|
setDR7(0ULL);
|
|
}
|
|
|
|
thisAPICID=getAPICID();
|
|
|
|
#ifdef CHECKAPICID
|
|
if (thisAPICID!=cpuinfo->apicid)
|
|
{
|
|
sendstringCS.ignorelock=1;
|
|
sendstringfCS.ignorelock=1;
|
|
sendstringf("Interrupt %d. Invalid cpuinfo", intnr);
|
|
while(1);
|
|
}
|
|
#endif
|
|
|
|
|
|
|
|
sendstringCS.lockcount=0;
|
|
sendstringCS.locked=0;
|
|
sendstringfCS.lockcount=0;
|
|
sendstringfCS.locked=0;
|
|
|
|
|
|
// sendstringf("interrupt fired : %d (%x)\n\r", intnr,intnr);
|
|
|
|
sendstringf("cpunr=%d (apicid=%d)\n\r",cpunr, thisAPICID);
|
|
sendstringf("intnr=%d\n\r",intnr);
|
|
sendstringf("rsp=%x\n\r",getRSP());
|
|
sendstringf("cr2=%6\n\r",getCR2());
|
|
errorcode=0;
|
|
|
|
|
|
if ((stack[17]==80) && (stack[18]==80))
|
|
{
|
|
//not sure...
|
|
if ((stack[16]>=0x00400000) && (stack[16]<0x00800000))
|
|
{
|
|
//in the region of the code of the vmm, so I guess it's no errorcode (and cs and eflags=80)
|
|
errorcode=0;
|
|
}
|
|
else
|
|
errorcode=1;
|
|
}
|
|
else
|
|
if (stack[18]==80)
|
|
errorcode=1;
|
|
else
|
|
if (stack[17]==80)
|
|
errorcode=0;
|
|
|
|
if (errorcode)
|
|
{
|
|
|
|
errorcodeValue=stack[16];
|
|
sendstringf("Interrupt has errorcode : %x (",errorcodeValue);
|
|
if (errorcodeValue & 1)
|
|
{
|
|
sendstring("EXT ");
|
|
}
|
|
|
|
if (errorcodeValue & 2)
|
|
{
|
|
sendstring("IDT ");
|
|
}
|
|
|
|
if (errorcodeValue & 4)
|
|
{
|
|
sendstring("TI ");
|
|
}
|
|
|
|
sendstringf("%x ",errorcodeValue & 0xFFFFFFF8);
|
|
|
|
sendstringf(")\n\r");
|
|
}
|
|
else
|
|
{
|
|
//sendstringf("Interrupt has no errorcode\n\r");
|
|
}
|
|
|
|
sendstringf("rip=%x\n\r",stack[16+errorcode]);
|
|
sendstringf("rflags=%x\n\r",stack[16+2+errorcode]);
|
|
|
|
|
|
rflags=(PRFLAGS)&stack[16+2+errorcode];
|
|
|
|
|
|
if ((intnr==2) && (rflags->IF==0))
|
|
{
|
|
cpuinfo->NMIOccured=1;
|
|
NMIcount++;
|
|
|
|
cpuinfo->NMIOccured=2;
|
|
/*
|
|
|
|
//set up NMI window exiting
|
|
|
|
if (vmx_enableNMIWindowExiting()==0) //todo: test this code. I think it enters an invalid state
|
|
{
|
|
sendstringf("NMI handling: failed to set PBEF_NMI_WINDOW_EXITING. Raising NMI like a retard\n");
|
|
cpuinfo->NMIOccured=2;
|
|
}
|
|
*/
|
|
|
|
return 0;
|
|
}
|
|
|
|
sendstringf("Checking if it was an expected interrupt\n\r");
|
|
|
|
if (cpuinfo->OnException[0].RIP)
|
|
{
|
|
nosendchar[thisAPICID]=0;
|
|
|
|
sendstringf("OnException is set. Passing it to longjmp\n"); //no need to set rflags back, the original state contains that info
|
|
cpuinfo->LastExceptionRIP=stack[16+errorcode];
|
|
longjmp(cpuinfo->OnException, 0x100 | intnr);
|
|
|
|
sendstringf("longjmp just went through...\n");
|
|
while (1);
|
|
}
|
|
|
|
if (cpuinfo->OnInterrupt.RIP)
|
|
{
|
|
QWORD oldrip=stack[16+errorcode];
|
|
sendstringf("Yes, OnInterrupt is set to %x\n\r",cpuinfo->OnInterrupt);
|
|
|
|
stack[8+errorcode]=(QWORD)(cpuinfo->OnInterrupt.RBP);
|
|
stack[16+errorcode]=(QWORD)(cpuinfo->OnInterrupt.RIP);
|
|
stack[19+errorcode]=(QWORD)(cpuinfo->OnInterrupt.RSP);
|
|
|
|
rflags->IF=0; //disable the IF flag in the eflags register stored on the stack (when called during checks if an int was pending)
|
|
|
|
|
|
cpuinfo->LastInterrupt=(unsigned char)intnr;
|
|
if (errorcode)
|
|
{
|
|
cpuinfo->LastInterruptHasErrorcode=1;
|
|
cpuinfo->LastInterruptErrorcode=(WORD)stack[16];
|
|
}
|
|
cpuinfo->LastInterruptHasErrorcode=0;
|
|
|
|
cpuinfo->OnInterrupt.RIP=0; //clear exception handler
|
|
cpuinfo->OnInterrupt.RBP=0;
|
|
cpuinfo->OnInterrupt.RSP=0;
|
|
|
|
sendstringf("changed rip(was %6 is now %6)\n\r", oldrip, stack[16+errorcode]);
|
|
sendstringf("rflags upon return is %x\n\r", stack[16+2+errorcode]);
|
|
|
|
sendstring("returning now\n");
|
|
|
|
return errorcode;
|
|
}
|
|
sendstring("not expected\n\r");
|
|
|
|
|
|
|
|
sendstring("Status:\n\r");
|
|
sendstringf("r15=%6\n\r",stack[0]);
|
|
sendstringf("r14=%6\n\r",stack[1]);
|
|
sendstringf("r13=%6\n\r",stack[2]);
|
|
sendstringf("r12=%6\n\r",stack[3]);
|
|
sendstringf("r11=%6\n\r",stack[4]);
|
|
sendstringf("r10=%6\n\r",stack[5]);
|
|
sendstringf("r9=%6\n\r",stack[6]);
|
|
sendstringf("r8=%6\n\r",stack[7]);
|
|
sendstringf("rbp=%6\n\r",stack[8]);
|
|
sendstringf("rsi=%6\n\r",stack[9]);
|
|
sendstringf("rdi=%6\n\r",stack[10]);
|
|
sendstringf("rdx=%6\n\r",stack[11]);
|
|
sendstringf("rcx=%6\n\r",stack[12]);
|
|
sendstringf("rbx=%6\n\r",stack[13]);
|
|
sendstringf("rax=%6\n\r",stack[14]);
|
|
sendstringf("intnr=%6\n\r",stack[15]);
|
|
sendstringf("stack[16]=%6\n\r",stack[16]);
|
|
sendstringf("stack[17]=%6\n\r",stack[17]);
|
|
sendstringf("stack[18]=%6\n\r",stack[18]);
|
|
sendstringf("stack[19]=%6\n\r",stack[19]);
|
|
sendstringf("--------------\n\r");
|
|
|
|
sendstringf("DR6=%6\n\r",getDR6());
|
|
if (intnr==14)
|
|
{
|
|
sendstringf("DR2=%6\n\r",getDR2());
|
|
}
|
|
//16=errorcode/eip
|
|
//17=eip/cs
|
|
//18=cs/eflags
|
|
|
|
sendstringf("eip=%6\n\r",stack[16+errorcode]);
|
|
sendstringf("cs=%6\n\r",stack[17+errorcode]);
|
|
|
|
|
|
|
|
|
|
sendDissectedFlags(rflags);
|
|
|
|
sendstringf("Trying to disassemble caller instruction\n\r");
|
|
|
|
int found=0;
|
|
unsigned int used=0;
|
|
unsigned int start=0;
|
|
_DecodedInst disassembled[22];
|
|
|
|
while (start<30)
|
|
{
|
|
distorm_decode(stack[16+errorcode]-30+start, (unsigned char *)(stack[16+errorcode]-30+start), 120, Decode64Bits, disassembled, 22, &used);
|
|
|
|
for (i=0; (unsigned)i<used; i++)
|
|
if (disassembled[i].offset==stack[16+errorcode])
|
|
{
|
|
found=1;
|
|
break;
|
|
}
|
|
|
|
if (found)
|
|
break;
|
|
start++;
|
|
}
|
|
|
|
for (i=0; (unsigned)i<used; i++)
|
|
{
|
|
if (disassembled[i].offset==stack[16+errorcode])
|
|
{
|
|
sendstringf(">>");
|
|
}
|
|
|
|
sendstringf("%x : %s - %s %s\n\r",
|
|
disassembled[i].offset,
|
|
disassembled[i].instructionHex.p,
|
|
disassembled[i].mnemonic.p,
|
|
disassembled[i].operands.p);
|
|
}
|
|
|
|
|
|
|
|
autostart=0;
|
|
setDR7(originalDR7);
|
|
|
|
|
|
sendstring("End of interrupt\n\r");
|
|
|
|
|
|
#ifdef DEBUGINTHANDLER
|
|
|
|
csEnter(&cinthandlerMenuCS);
|
|
// inthandleroverride=1;
|
|
IntHandlerDebug=1;
|
|
|
|
|
|
unsigned char key;
|
|
while (1)
|
|
{
|
|
sendstring("----------------------------\n\r");
|
|
sendstring("Interrupt handler debug menu\n\r");
|
|
sendstring("----------------------------\n\r");
|
|
sendstring("1: Exit from interrupt\n\r");
|
|
sendstring("2: Check CRC values\n\r");
|
|
sendstring("3: Get vmstate\n\r");
|
|
sendstring("p: Previous vmstates\n\r");
|
|
|
|
|
|
|
|
key=waitforchar();
|
|
if (key==0xff) //serial port borked
|
|
key='1';
|
|
|
|
switch (key)
|
|
{
|
|
case '1':
|
|
sendstring("Exiting from interrupt\n\r");
|
|
IntHandlerDebug=0;
|
|
csLeave(&cinthandlerMenuCS);
|
|
return errorcode;
|
|
|
|
case '2':
|
|
CheckCRCValues();
|
|
break;
|
|
|
|
case '3':
|
|
sendvmstate(cpuinfo, NULL);
|
|
break;
|
|
|
|
case 'p':
|
|
displayPreviousStates();
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
#else
|
|
return errorcode;
|
|
#endif
|
|
}
|
|
|
|
void startNextCPU(void)
|
|
{
|
|
//setup a stack for the first AP cpu
|
|
nextstack=(QWORD)malloc2(4096*16);
|
|
markPageAsNotReadable((void *)nextstack); //when the thread tries to allocate more than it can it'll cause a pagefault instead of fucking with other memory
|
|
|
|
nextstack=(QWORD)nextstack+(4096*16)-16;
|
|
|
|
sendstringf("startNextCPU. nextstack=%6\n", nextstack);
|
|
|
|
asm volatile ("": : :"memory");
|
|
initcs=0; //let the next cpu pass
|
|
asm volatile ("": : :"memory");
|
|
}
|
|
|
|
|
|
void CheckCRCValues(void)
|
|
{
|
|
unsigned int newcrc;
|
|
|
|
sendstringf("Original VMM crc = %x\n\r",originalVMMcrc);
|
|
newcrc=generateCRC((void *)vmxloop,0x2a000);
|
|
sendstringf("Current VMM crc = %x\n\r",newcrc);
|
|
if (originalVMMcrc!=newcrc)
|
|
{
|
|
sendstring("!!!!!!!!!!MISMATCH!!!!!!!!!!\n\r");
|
|
}
|
|
|
|
|
|
return;
|
|
}
|
|
|
|
void setints(void)
|
|
{
|
|
IDT tidt;
|
|
int i;
|
|
|
|
tidt.wLimit=16*256;
|
|
tidt.vector=intvector;
|
|
|
|
if (intvector==NULL)
|
|
{
|
|
sendstring("setints was called too early");
|
|
while(1);
|
|
}
|
|
|
|
|
|
zeromemory(intvector, 256*sizeof(INT_VECTOR));
|
|
for (i=0; i<256; i++)
|
|
{
|
|
intvector[i].wSelector=80;
|
|
intvector[i].bUnused=0;
|
|
intvector[i].bAccess=0x8e; //10001110
|
|
}
|
|
|
|
intvector[8].bUnused=1; //double fault
|
|
intvector[11].bUnused=1; //segment fault
|
|
intvector[12].bUnused=1; //stack fault
|
|
|
|
SETINT(0);
|
|
SETINT(1);
|
|
SETINT(2);
|
|
SETINT(3);
|
|
SETINT(4);
|
|
SETINT(5);
|
|
SETINT(6);
|
|
SETINT(7);
|
|
SETINT(8);
|
|
SETINT(9);
|
|
SETINT(10);
|
|
SETINT(11);
|
|
SETINT(12);
|
|
SETINT(13);
|
|
SETINT(14);
|
|
SETINT(15);
|
|
SETINT(16);
|
|
SETINT(17);
|
|
SETINT(18);
|
|
SETINT(19);
|
|
SETINT(20);
|
|
SETINT(21);
|
|
SETINT(22);
|
|
SETINT(23);
|
|
SETINT(24);
|
|
SETINT(25);
|
|
SETINT(26);
|
|
SETINT(27);
|
|
SETINT(28);
|
|
SETINT(29);
|
|
SETINT(30);
|
|
SETINT(31);
|
|
SETINT(32);
|
|
SETINT(33);
|
|
SETINT(34);
|
|
SETINT(35);
|
|
SETINT(36);
|
|
SETINT(37);
|
|
SETINT(38);
|
|
SETINT(39);
|
|
SETINT(40);
|
|
SETINT(41);
|
|
SETINT(42);
|
|
SETINT(43);
|
|
SETINT(44);
|
|
SETINT(45);
|
|
SETINT(46);
|
|
SETINT(47);
|
|
SETINT(48);
|
|
SETINT(49);
|
|
SETINT(50);
|
|
SETINT(51);
|
|
SETINT(52);
|
|
SETINT(53);
|
|
SETINT(54);
|
|
SETINT(55);
|
|
SETINT(56);
|
|
SETINT(57);
|
|
SETINT(58);
|
|
SETINT(59);
|
|
SETINT(60);
|
|
SETINT(61);
|
|
SETINT(62);
|
|
SETINT(63);
|
|
SETINT(64);
|
|
SETINT(65);
|
|
SETINT(66);
|
|
SETINT(67);
|
|
SETINT(68);
|
|
SETINT(69);
|
|
SETINT(70);
|
|
SETINT(71);
|
|
SETINT(72);
|
|
SETINT(73);
|
|
SETINT(74);
|
|
SETINT(75);
|
|
SETINT(76);
|
|
SETINT(77);
|
|
SETINT(78);
|
|
SETINT(79);
|
|
SETINT(80);
|
|
SETINT(81);
|
|
SETINT(82);
|
|
SETINT(83);
|
|
SETINT(84);
|
|
SETINT(85);
|
|
SETINT(86);
|
|
SETINT(87);
|
|
SETINT(88);
|
|
SETINT(89);
|
|
SETINT(90);
|
|
SETINT(91);
|
|
SETINT(92);
|
|
SETINT(93);
|
|
SETINT(94);
|
|
SETINT(95);
|
|
SETINT(96);
|
|
SETINT(97);
|
|
SETINT(98);
|
|
SETINT(99);
|
|
SETINT(100);
|
|
SETINT(101);
|
|
SETINT(102);
|
|
SETINT(103);
|
|
SETINT(104);
|
|
SETINT(105);
|
|
SETINT(106);
|
|
SETINT(107);
|
|
SETINT(108);
|
|
SETINT(109);
|
|
SETINT(110);
|
|
SETINT(111);
|
|
SETINT(112);
|
|
SETINT(113);
|
|
SETINT(114);
|
|
SETINT(115);
|
|
SETINT(116);
|
|
SETINT(117);
|
|
SETINT(118);
|
|
SETINT(119);
|
|
SETINT(120);
|
|
SETINT(121);
|
|
SETINT(122);
|
|
SETINT(123);
|
|
SETINT(124);
|
|
SETINT(125);
|
|
SETINT(126);
|
|
SETINT(127);
|
|
SETINT(128);
|
|
SETINT(129);
|
|
SETINT(130);
|
|
SETINT(131);
|
|
SETINT(132);
|
|
SETINT(133);
|
|
SETINT(134);
|
|
SETINT(135);
|
|
SETINT(136);
|
|
SETINT(137);
|
|
SETINT(138);
|
|
SETINT(139);
|
|
SETINT(140);
|
|
SETINT(141);
|
|
SETINT(142);
|
|
SETINT(143);
|
|
SETINT(144);
|
|
SETINT(145);
|
|
SETINT(146);
|
|
SETINT(147);
|
|
SETINT(148);
|
|
SETINT(149);
|
|
SETINT(150);
|
|
SETINT(151);
|
|
SETINT(152);
|
|
SETINT(153);
|
|
SETINT(154);
|
|
SETINT(155);
|
|
SETINT(156);
|
|
SETINT(157);
|
|
SETINT(158);
|
|
SETINT(159);
|
|
SETINT(160);
|
|
SETINT(161);
|
|
SETINT(162);
|
|
SETINT(163);
|
|
SETINT(164);
|
|
SETINT(165);
|
|
SETINT(166);
|
|
SETINT(167);
|
|
SETINT(168);
|
|
SETINT(169);
|
|
SETINT(170);
|
|
SETINT(171);
|
|
SETINT(172);
|
|
SETINT(173);
|
|
SETINT(174);
|
|
SETINT(175);
|
|
SETINT(176);
|
|
SETINT(177);
|
|
SETINT(178);
|
|
SETINT(179);
|
|
SETINT(180);
|
|
SETINT(181);
|
|
SETINT(182);
|
|
SETINT(183);
|
|
SETINT(184);
|
|
SETINT(185);
|
|
SETINT(186);
|
|
SETINT(187);
|
|
SETINT(188);
|
|
SETINT(189);
|
|
SETINT(190);
|
|
SETINT(191);
|
|
SETINT(192);
|
|
SETINT(193);
|
|
SETINT(194);
|
|
SETINT(195);
|
|
SETINT(196);
|
|
SETINT(197);
|
|
SETINT(198);
|
|
SETINT(199);
|
|
SETINT(200);
|
|
SETINT(201);
|
|
SETINT(202);
|
|
SETINT(203);
|
|
SETINT(204);
|
|
SETINT(205);
|
|
SETINT(206);
|
|
SETINT(207);
|
|
SETINT(208);
|
|
SETINT(209);
|
|
SETINT(210);
|
|
SETINT(211);
|
|
SETINT(212);
|
|
SETINT(213);
|
|
SETINT(214);
|
|
SETINT(215);
|
|
SETINT(216);
|
|
SETINT(217);
|
|
SETINT(218);
|
|
SETINT(219);
|
|
SETINT(220);
|
|
SETINT(221);
|
|
SETINT(222);
|
|
SETINT(223);
|
|
SETINT(224);
|
|
SETINT(225);
|
|
SETINT(226);
|
|
SETINT(227);
|
|
SETINT(228);
|
|
SETINT(229);
|
|
SETINT(230);
|
|
SETINT(231);
|
|
SETINT(232);
|
|
SETINT(233);
|
|
SETINT(234);
|
|
SETINT(235);
|
|
SETINT(236);
|
|
SETINT(237);
|
|
SETINT(238);
|
|
SETINT(239);
|
|
SETINT(240);
|
|
SETINT(241);
|
|
SETINT(242);
|
|
SETINT(243);
|
|
SETINT(244);
|
|
SETINT(245);
|
|
SETINT(246);
|
|
SETINT(247);
|
|
SETINT(248);
|
|
SETINT(249);
|
|
SETINT(250);
|
|
SETINT(251);
|
|
SETINT(252);
|
|
SETINT(253);
|
|
SETINT(254);
|
|
SETINT(255);
|
|
|
|
cLIDT(&tidt);
|
|
}
|
|
|
|
|
|
void vmm_entry2_hlt(pcpuinfo currentcpuinfo)
|
|
{
|
|
UINT64 a,b,c,d;
|
|
if (currentcpuinfo)
|
|
sendstringf("CPU %d : Terminating...\n\r",currentcpuinfo->cpunr);
|
|
|
|
while (1)
|
|
{
|
|
if (currentcpuinfo)
|
|
currentcpuinfo->active=0;
|
|
a=1;
|
|
_cpuid(&a,&b,&c,&d); //always serialize after writing to a structure read by a different cpu
|
|
__asm("hlt\n\r");
|
|
}
|
|
}
|
|
|
|
|
|
void setupFSBase(void *fsbase)
|
|
{
|
|
writeMSR(IA32_FS_BASE_MSR, (UINT64)fsbase);
|
|
}
|
|
|
|
volatile int inflooponerror=1;
|
|
volatile int initializedCPUCount; //assume the first (main) cpu managed to start up
|
|
|
|
void vmm_entry2(void)
|
|
//Entry for application processors
|
|
//Memory manager has been initialized and GDT/IDT copies have been made
|
|
{
|
|
unsigned int cpunr;
|
|
if (AP_Terminate)
|
|
{
|
|
sendstringf("AP_Terminate!=0\n");
|
|
startNextCPU();
|
|
vmm_entry2_hlt(NULL);
|
|
}
|
|
|
|
if ((needtospawnApplicationProcessors>1) || (needtospawnApplicationProcessors<0))
|
|
{
|
|
sendstringf("memory corruption\n");
|
|
|
|
while (inflooponerror) ;
|
|
}
|
|
|
|
|
|
//debug code on my 8 core cpu:
|
|
//if (initializedCPUCount>=8)
|
|
//{
|
|
// sendstringf("More cpu's than expected\n");
|
|
// while (inflooponerror);
|
|
//}
|
|
|
|
|
|
//setup the GDT and IDT
|
|
setGDT((UINT64)GDT_BASE, GDT_SIZE);
|
|
setIDT((UINT64)intvector, 16*256);
|
|
|
|
//cLIDT(&intvector);
|
|
|
|
//sendstringf("Welcome to a extra cpu (cpunr=%d)\n",cpucount);
|
|
cpunr=initializedCPUCount;
|
|
sendstringf("Setting up cpunr=%d\n",cpunr);
|
|
|
|
|
|
initializedCPUCount++;
|
|
|
|
if (!loadedOS)
|
|
cpucount++; //cpucount is known, don't increase it
|
|
|
|
pcpuinfo cpuinfo=malloc2(sizeof(tcpuinfo)<4096?4096:sizeof(tcpuinfo)<4096);
|
|
|
|
zeromemory(cpuinfo, sizeof(tcpuinfo));
|
|
cpuinfo->active=1;
|
|
cpuinfo->cpunr=cpunr;
|
|
cpuinfo->apicid=getAPICID();
|
|
|
|
cpuinfo->TSbase=0;
|
|
cpuinfo->TSlimit=0xffff;
|
|
cpuinfo->TSsegment=0;
|
|
cpuinfo->TSaccessRights=0x8b;
|
|
cpuinfo->self=cpuinfo;
|
|
|
|
lastaddedcpuinfo->next=cpuinfo;
|
|
lastaddedcpuinfo=cpuinfo;
|
|
|
|
displayline("%d: New CPU CORE. CPUNR=%d APICID=%d (cpuinfo struct at : %p rsp=%x)\n",cpunr, cpuinfo->cpunr, cpuinfo->apicid, cpuinfo, getRSP());
|
|
|
|
|
|
setupFSBase((void *)cpuinfo);
|
|
|
|
sendstringf("%d: launching next CPU\n", cpunr);
|
|
startNextCPU(); //put at start for async
|
|
|
|
sendstringf("%d: Waiting till AP_Launch is not 0\n", cpunr);
|
|
|
|
while (AP_Launch==0)
|
|
{
|
|
resync();
|
|
if (AP_Terminate==1)
|
|
vmm_entry2_hlt(cpuinfo);
|
|
}
|
|
|
|
if (AP_Terminate==1)
|
|
{
|
|
startNextCPU();
|
|
vmm_entry2_hlt(cpuinfo);
|
|
}
|
|
|
|
|
|
startvmx(cpuinfo);
|
|
|
|
// while (1); //debug
|
|
|
|
displayline("CPU CORE %d: entering VMX mode\n",cpunr);
|
|
|
|
sendstringf("Application cpu returned from startvmx\n\r");
|
|
|
|
vmm_entry2_hlt(cpuinfo);
|
|
while (1);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void vmm_entry(void)
|
|
{
|
|
//make sure WP is on
|
|
setCR0(getCR0() | CR0_WP);
|
|
|
|
if (isAP)
|
|
{
|
|
vmm_entry2();
|
|
sendstringf("vmm_entry2 has PHAILED!!!!");
|
|
while (1);
|
|
}
|
|
isAP=1; //all other entries will be an AP
|
|
|
|
|
|
initializedCPUCount=1; //I managed to run this at least...
|
|
|
|
int i,k;
|
|
UINT64 a,b,c,d;
|
|
pcpuinfo cpuinfo;
|
|
|
|
|
|
//stack has been properly setup, so lets allow other cpu's to launch as well
|
|
InitCommon();
|
|
|
|
Password1=0x76543210; //later to be filled in by user, sector on disk, or at compile time
|
|
Password2=0xfedcba98;
|
|
|
|
/*version 1 was the 32-bit only version,
|
|
* 2 added 64-bit,
|
|
* 3 had a revised int1 redirect option,
|
|
* 4 has major bugfixes,
|
|
* 5=more fixes and some basic device recog,
|
|
* 6=Even more compatibility fixes,
|
|
* rm emu, and new vmcalls,
|
|
* 7=driver loading ,
|
|
* 8=amd support,
|
|
* 9 memory usage decrease and some fixes for newer systems,
|
|
* 10=xsaves (win10)
|
|
* 11=new memory manager , dynamic cpu initialization, UEFI boot support, EPT, unrestricted support, and other new features
|
|
* 12=vpid
|
|
* 13=basic TSC emulation
|
|
*/
|
|
dbvmversion=13;
|
|
int1redirection=1; //redirect to int vector 1 (might change this to the perfcounter interrupt in the future so I don't have to deal with interrupt prologue/epilogue)
|
|
int3redirection=3;
|
|
int14redirection=14;
|
|
|
|
//get max physical address
|
|
QWORD rax=0x80000008;
|
|
QWORD rbx=0;
|
|
QWORD rcx=0;
|
|
QWORD rdx=0;
|
|
_cpuid(&rax, &rbx, &rcx, &rdx);
|
|
MAXPHYADDR=rax & 0xff;
|
|
|
|
MAXPHYADDRMASK=0xFFFFFFFFFFFFFFFFULL;
|
|
MAXPHYADDRMASK=MAXPHYADDRMASK >> MAXPHYADDR; //if MAXPHYADDR==36 then MAXPHYADDRMASK=0x000000000fffffff
|
|
MAXPHYADDRMASK=~(MAXPHYADDRMASK << MAXPHYADDR); //<< 36 = 0xfffffff000000000 . after inverse : 0x0000000fffffffff
|
|
MAXPHYADDRMASKPB=MAXPHYADDRMASK & 0xfffffffffffff000ULL; //0x0000000ffffff000
|
|
|
|
sendstringf("MAXPHYADDR=%d", MAXPHYADDR);
|
|
sendstringf("MAXPHYADDRMASK=%6", MAXPHYADDRMASK);
|
|
sendstringf("MAXPHYADDRMASKPB=%6", MAXPHYADDRMASK);
|
|
|
|
|
|
|
|
|
|
|
|
//enableserial();
|
|
|
|
|
|
|
|
|
|
sendstringf("If you see this that means that the transition from unpaged to paged was a success\n\r");
|
|
sendstringf("loadedOS=%6\n",loadedOS);
|
|
|
|
currentdisplayline=7;
|
|
|
|
|
|
displayline("BOOT CPU CORE initializing\n");
|
|
|
|
displayline("CR3=%6\n", getCR3());
|
|
displayline("pagedirlvl4=%6\n",(UINT64)pagedirlvl4);
|
|
displayline("&pagedirlvl4=%6\n",(UINT64)&pagedirlvl4);
|
|
displayline("vmmstart=%6 (this is virtual address 00400000)\n",(UINT64)vmmstart);
|
|
|
|
//displayline("press any key to continue\n");
|
|
|
|
|
|
//initialize
|
|
|
|
sendstring("Welcome to Dark Byte\'s Virtual Machine Manager\n\r");
|
|
sendstringf("pagedirlvl4=%6\n\r",(unsigned long long)pagedirlvl4);
|
|
|
|
sendstring("Initializing MM\n\r");
|
|
InitializeMM((QWORD)pagedirlvl4+4096);
|
|
sendstring("Initialized MM\n\r");
|
|
/*
|
|
* POST INIT
|
|
*/
|
|
|
|
|
|
cpucount=1;
|
|
cpuinfo=malloc2(sizeof(tcpuinfo)<4096?4096:sizeof(tcpuinfo));
|
|
sendstringf("allocated cpuinfo at %6\n\r", cpuinfo);
|
|
zeromemory(cpuinfo,sizeof(tcpuinfo));
|
|
cpuinfo->active=1;
|
|
cpuinfo->cpunr=0;
|
|
cpuinfo->apicid=getAPICID();
|
|
cpuinfo->isboot=1;
|
|
cpuinfo->self=cpuinfo;
|
|
|
|
|
|
|
|
setupFSBase((void*)cpuinfo);
|
|
|
|
|
|
//debug info
|
|
firstcpuinfo=cpuinfo;
|
|
lastaddedcpuinfo=cpuinfo;
|
|
|
|
#if DISPLAYDEBUG==1
|
|
initialize_displaydebuglogs();
|
|
#endif
|
|
|
|
|
|
sendstringf("initialized cpuinfo at %6\n\r", cpuinfo);
|
|
|
|
|
|
//IA32_APIC_BASE=(unsigned long long)readMSR(0x1b);
|
|
|
|
IA32_APIC_BASE=(QWORD)mapPhysicalMemory((unsigned long long)readMSR(0x1b) & 0xfffffffffffff000ULL, 4096);
|
|
sendstringf("IA32_APIC_BASE=%6\n\r",IA32_APIC_BASE);
|
|
|
|
APIC_ID=IA32_APIC_BASE+APIC_ID_OFFSET;
|
|
APIC_SVR=IA32_APIC_BASE+APIC_SVR_OFFSET;
|
|
|
|
SetPageToWriteThrough((void*)IA32_APIC_BASE);
|
|
|
|
|
|
|
|
|
|
displayline("IA32_APIC_BASE=%6\n\r",IA32_APIC_BASE);
|
|
sendstringf("IA32_APIC_BASE=%6\n\r",IA32_APIC_BASE);
|
|
sendstringf("\tLocal APIC base=%6\n\r",IA32_APIC_BASE & 0xfffff000);
|
|
sendstringf("\tAPIC global enable/disable=%d\n\r",(IA32_APIC_BASE >> 11) & 1);
|
|
sendstringf("\tBSP=%d\n\r",(IA32_APIC_BASE >> 8) & 1);
|
|
|
|
a=1;
|
|
_cpuid(&a,&b,&c,&d);
|
|
displayline("CPUID.1: %8, %8, %8, %8\n",a,b,c,d);
|
|
|
|
cpu_stepping=a & 0xf;
|
|
cpu_model=(a >> 4) & 0xf;
|
|
cpu_familyID=(a >> 8) & 0xf;
|
|
cpu_type=(a >> 12) & 0x3;
|
|
cpu_ext_modelID=(a >> 16) & 0xf;
|
|
cpu_ext_familyID=(a >> 20) & 0xff;
|
|
|
|
|
|
cpu_model=cpu_model + (cpu_ext_modelID << 4);
|
|
cpu_familyID=cpu_familyID + (cpu_ext_familyID << 4);
|
|
|
|
|
|
if (1) //((d & (1<<28))>0) //this doesn't work in vmware, so find a different method
|
|
{
|
|
QWORD entrypage=0x30000;
|
|
unsigned long long initialcount;
|
|
unsigned int foundcpus;
|
|
sendstring("Multi processor supported\n\r");
|
|
sendstring("Launching application cpu's\n");
|
|
|
|
|
|
//displaystring("Multi processor supported\n");
|
|
displayline("Launching other cpu cores if present\n");
|
|
sendstring("Starting other cpu's\n\r");
|
|
|
|
|
|
APStartsInSIPI=1;
|
|
|
|
if ((needtospawnApplicationProcessors>1) || (needtospawnApplicationProcessors<0))
|
|
{
|
|
sendstringf("memory corruption\n");
|
|
volatile int debug=1;
|
|
while (debug) ;
|
|
}
|
|
|
|
if (loadedOS)
|
|
{
|
|
sendstringf("mapping loadedOS (%6)...\n", loadedOS);
|
|
|
|
POriginalState original=(POriginalState)mapPhysicalMemory(loadedOS, sizeof(OriginalState));
|
|
sendstringf("Success. It has been mapped at virtual address %6\n",original);
|
|
|
|
entrypage=original->APEntryPage;
|
|
|
|
sendstringf("original->cpucount=%d\n", original->cpucount);
|
|
if (original->cpucount>1000)
|
|
{
|
|
sendstringf("More than 1000 cpu\'s are currently not supported\n");
|
|
while (1);
|
|
}
|
|
|
|
if (original->cpucount)
|
|
{
|
|
needtospawnApplicationProcessors=0;
|
|
foundcpus=original->cpucount;
|
|
APStartsInSIPI=0; //AP should start according to the original state
|
|
}
|
|
unmapPhysicalMemory(original, sizeof(OriginalState));
|
|
}
|
|
|
|
if (needtospawnApplicationProcessors) //e.g UEFI boot with missing mpsupport
|
|
{
|
|
sendstringf("needtospawnApplicationProcessors!=0\n");
|
|
#ifndef NOMP
|
|
|
|
BOOT_ID=apic_getBootID();
|
|
|
|
//setup some info so that the AP cpu can find this
|
|
APBootVar_CR3=getCR3();
|
|
|
|
void *GDTbase=(void *)getGDTbase();
|
|
int GDTsize=getGDTsize();
|
|
APBootVar_Size=GDTsize;
|
|
|
|
if (GDTsize>192)
|
|
{
|
|
sendstringf("Update the AP boot GDT section to be bigger than 192 bytes");
|
|
}
|
|
memcpy(APBootVar_GDT, GDTbase, GDTsize);
|
|
|
|
APBootVar_GDT[2 ]=0x00cf9b000000ffffULL; //24: 32-bit code
|
|
APBootVar_GDT[2 ]|=(entrypage >> 8) << 24;
|
|
//with 0x5e000 or it with 0x05e0
|
|
|
|
sendstringf("vmmentrycount before launch=%d\n", vmmentrycount);
|
|
foundcpus=initAPcpus(entrypage);
|
|
|
|
sendstringf("foundcpus=%d cpucount=%d. Waiting till cpucount==foundcpus, or timeout\n",foundcpus, cpucount);
|
|
|
|
QWORD timeout=2000000000ULL;
|
|
|
|
for (i=0; i<3; i++)
|
|
{
|
|
initialcount=_rdtsc();
|
|
while ((_rdtsc()-initialcount) < timeout)
|
|
{
|
|
//sendstringf("cpucount=%d foundcpus=%d\n\r", cpucount, foundcpus);
|
|
|
|
if (vmmentrycount>=foundcpus)
|
|
break;
|
|
|
|
_pause();
|
|
}
|
|
displayline(".");
|
|
if (vmmentrycount>=foundcpus)
|
|
break;
|
|
}
|
|
|
|
if (i>=3)
|
|
displayline("Timeout\n");
|
|
else
|
|
displayline("\n");
|
|
|
|
}
|
|
else
|
|
AP_Launch=1; //no need to let the others wait. the launcher will decide when to load
|
|
|
|
displayline("Wait done. Cpu's found : %d (expected %d)\n",vmmentrycount, foundcpus);
|
|
sendstringf("vmmentrycount after launch=%d\n", vmmentrycount);
|
|
|
|
//the other CPU's should now be waiting in the spinlock at the start of dbvm
|
|
#endif
|
|
}
|
|
|
|
//copy GDT and IDT to VMM memory
|
|
GDT_BASE=malloc(4096);
|
|
GDT_SIZE=4096; //getGDTsize();
|
|
|
|
if (GDT_BASE==NULL)
|
|
{
|
|
sendstring("Memory allocation failed\n");
|
|
while (1) ;
|
|
}
|
|
|
|
sendstringf("Allocated GDT_BASE %6\n", GDT_BASE);
|
|
|
|
{
|
|
void *GDTbase=(void *)getGDTbase();
|
|
int GDTsize=getGDTsize();
|
|
|
|
sendstringf("getGDTbase=%p, getGDTsize=%d\n",GDTbase,GDTsize );
|
|
|
|
copymem(GDT_BASE,GDTbase,GDTsize);
|
|
}
|
|
sendstringf("Allocated and copied GDT to %x\n\r",(UINT64)GDT_BASE);
|
|
setGDT((UINT64)GDT_BASE, 4096);
|
|
|
|
{
|
|
//set the GDT to the way I like it (loaders could fuck this up)
|
|
QWORD *g=(QWORD *)GDT_BASE;
|
|
g[0 ]=0; //0 :
|
|
g[1 ]=0x00cf92000000ffffULL; //8 : 32-bit data
|
|
g[2 ]=0x00cf96000000ffffULL; //16: test, stack, failed, unused
|
|
g[3 ]=0x00cf9b000000ffffULL; //24: 32-bit code
|
|
g[4 ]=0x00009a000000ffffULL; //32: 16-bit code
|
|
g[5 ]=0x000092000000ffffULL; //40: 16-bit data
|
|
g[6 ]=0x00009a030000ffffULL; //48: 16-bit code, starting at 0x30000
|
|
g[7 ]=0; //56: 32-bit task
|
|
g[8 ]=0; //64: 64-bit task
|
|
g[9 ]=0; //72: ^ ^ ^
|
|
g[10]=0x00af9b000000ffffULL; //80: 64-bit code
|
|
g[11]=0x00cf9b000000ffffULL; //88: 32-bit code compat mode
|
|
g[12]=0; //96: 64-bit tss descriptor (2)
|
|
g[13]=0; //104: ^ ^ ^
|
|
}
|
|
|
|
//now replace the old IDT with a new one
|
|
intvector=malloc(sizeof(INT_VECTOR)*256);
|
|
zeromemory(intvector,sizeof(INT_VECTOR)*256);
|
|
sendstringf("Allocated intvector at %6\n\r",(unsigned long long)intvector);
|
|
|
|
setints();
|
|
sendstring("after setints()\n");
|
|
|
|
i=0;
|
|
setDR0((QWORD)((volatile void *)&&BPTest));
|
|
setDR6(0xffff0ff0);
|
|
setDR7(getDR7() | (1<<0));
|
|
displayline("Going to execute test breakpoint\n");
|
|
|
|
cpuinfo->OnInterrupt.RSP=getRSP();
|
|
cpuinfo->OnInterrupt.RBP=getRBP();
|
|
cpuinfo->OnInterrupt.RIP=(QWORD)((volatile void *)&&AfterBPTest);
|
|
asm volatile ("": : :"memory");
|
|
BPTest:
|
|
i=1;
|
|
sendstring("<<---------------WRONG!!! BPTest got executed...(ok if a jtag debugger is present)\n");
|
|
asm volatile ("": : :"memory");
|
|
AfterBPTest:
|
|
if (i==0)
|
|
sendstring("BPTest successfull\n");
|
|
else
|
|
sendstring(":(\n");
|
|
|
|
cpuinfo->OnInterrupt.RSP=0;
|
|
cpuinfo->OnInterrupt.RBP=0;
|
|
cpuinfo->OnInterrupt.RIP=0;
|
|
|
|
|
|
|
|
sendstringf("Letting the first AP cpu go through\n");
|
|
startNextCPU();
|
|
|
|
|
|
|
|
fakeARD=malloc(4096);
|
|
fakeARD[0].Type=255;
|
|
sendstringf("Allocated fakeARD at %6\n",(unsigned long long)fakeARD);
|
|
sendstringf("That is physical address %6\n", VirtualToPhysical(fakeARD));
|
|
|
|
|
|
if (!loadedOS)
|
|
{
|
|
sendstring("Copying ARD from 80000 to ARD location");
|
|
copymem((void *)fakeARD,(void *)0x80000,4096); //that should be enough
|
|
}
|
|
|
|
//ARD Setup
|
|
//The ARD is used for old boot mechanisms. This way DBVM can tell the guest which physical pages are 'reserved' by the system and should not be used/overwritten
|
|
//In loadedOS mode DBVM makes use of built-in memory allocation systems so not needed
|
|
|
|
sendstring("Calling initARDcount()\n");
|
|
initARDcount();
|
|
sendstring("Calling sendARD()\n");
|
|
sendARD();
|
|
|
|
sendstring("after sendARD()\n");
|
|
|
|
|
|
|
|
// alloc VirtualMachineTSS_V8086
|
|
VirtualMachineTSS_V8086=malloc(3*4096);
|
|
zeromemory(VirtualMachineTSS_V8086,3*4096);
|
|
|
|
RealmodeRing0Stack=malloc(4096); //(not even 1 KB used, but let's waste some mem)
|
|
|
|
|
|
//configure ffpage
|
|
|
|
//create a page filled with 0xff (for faking non present memory access)
|
|
ffpage=malloc(4096);
|
|
for (i=0; i<4096; i++)
|
|
ffpage[i]=0xce;
|
|
|
|
sendstringf("Physical address of ffpage=%6\n\r",(UINT64)VirtualToPhysical(ffpage));
|
|
|
|
|
|
//create a pagetable with only 0xff (2MB 0xff)
|
|
ffpagetable=malloc(4096);
|
|
zeromemory(ffpagetable,4096);
|
|
for (i=0; i<4096/8; i++)
|
|
{
|
|
*(QWORD*)(&ffpagetable[i])=VirtualToPhysical(ffpage);
|
|
ffpagetable[i].P=1;
|
|
ffpagetable[i].RW=0;
|
|
}
|
|
|
|
sendstringf("Physical address of ffpagetable=%6\n\r",(UINT64)VirtualToPhysical((void *)ffpagetable));
|
|
|
|
//create a pagedir where all entries point to the ffpagetable
|
|
ffpagedir=malloc(4096);
|
|
zeromemory(ffpagedir,4096);
|
|
for (i=0; i<4096/8; i++)
|
|
{
|
|
*(QWORD*)(&ffpagedir[i])=VirtualToPhysical((void *)ffpagetable);
|
|
ffpagedir[i].P=1;
|
|
ffpagedir[i].RW=0;
|
|
ffpagedir[i].PS=0;
|
|
}
|
|
|
|
sendstringf("Physical address of ffpagedir=%6\n\r",(UINT64)VirtualToPhysical((void *)ffpagedir));
|
|
|
|
__asm("mov %cr3,%rax\n mov %rax,%cr3\n");
|
|
|
|
displayline("emulated virtual memory has been configured\n");
|
|
|
|
displayline("Paging:\n");
|
|
displayline("0x00000000 is at %6\n", (UINT64)VirtualToPhysical((void *)0));
|
|
displayline("0x00200000 is at %6\n", (UINT64)VirtualToPhysical((void *)0x00200000));
|
|
displayline("0x00400000 is at %6\n", (UINT64)VirtualToPhysical((void *)0x00400000));
|
|
displayline("0x00600000 is at %6\n", (UINT64)VirtualToPhysical((void *)0x00600000));
|
|
|
|
|
|
|
|
//setup nonpagedEmulationPagedir
|
|
|
|
|
|
displayline("Calling hascpuid()\n");
|
|
if (hascpuid())
|
|
{
|
|
char *t;
|
|
a=0;
|
|
b=0;
|
|
c=0;
|
|
d=0;
|
|
_cpuid(&a,&b,&c,&d);
|
|
sendstringf("Your comp supports cpuid! (%d , %x %x %x )\n\r",a,b,d,c);
|
|
|
|
t=(char *)&b;
|
|
sendstringf("Max basicid=%x\n\r",a);
|
|
sendstringf("%c%c%c%c",t[0],t[1],t[2],t[3]);
|
|
|
|
|
|
t=(char *)&d;
|
|
sendstringf("%c%c%c%c",t[0],t[1],t[2],t[3]);
|
|
|
|
|
|
t=(char *)&c;
|
|
sendstringf("%c%c%c%c\n\r",t[0],t[1],t[2],t[3]);
|
|
|
|
|
|
|
|
if ((b==0x68747541) && (d==0x69746e65) && (c==0x444d4163))
|
|
{
|
|
isAMD=1;
|
|
AMD_hasDecodeAssists=0;
|
|
sendstring("This is an AMD system. going to use the AMD virtualization tech\n\r");
|
|
}
|
|
else
|
|
isAMD=0;
|
|
|
|
|
|
//a=0x80000000; _cpuid(&a,&b,&c,&d);
|
|
//if (!(a & 0x80000000))
|
|
{
|
|
unsigned int j;
|
|
|
|
// sendstring("\n\r\n\rBranch string=");
|
|
displayline("Branch string=");
|
|
|
|
for (j=0x80000002; j<=0x80000004; j++)
|
|
{
|
|
a=j;
|
|
_cpuid(&a,&b,&c,&d);
|
|
|
|
t=(char *)&a;
|
|
for (k=0; k<4; k++)
|
|
if (t[k]<32)
|
|
t[k]=' ';
|
|
//sendstringf("%c%c%c%c",t[0],t[1],t[2],t[3]);
|
|
displayline("%c%c%c%c",t[0],t[1],t[2],t[3]);
|
|
|
|
t=(char *)&b;
|
|
for (k=0; k<4; k++)
|
|
if (t[k]<32)
|
|
t[k]=' ';
|
|
//sendstringf("%c%c%c%c",t[0],t[1],t[2],t[3]);
|
|
displayline("%c%c%c%c",t[0],t[1],t[2],t[3]);
|
|
|
|
t=(char *)&c;
|
|
for (k=0; k<4; k++)
|
|
if (t[k]<32)
|
|
t[k]=' ';
|
|
// sendstringf("%c%c%c%c",t[0],t[1],t[2],t[3]);
|
|
displayline("%c%c%c%c",t[0],t[1],t[2],t[3]);
|
|
|
|
t=(char *)&d;
|
|
for (k=0; k<4; k++)
|
|
if (t[k]<32)
|
|
t[k]=' ';
|
|
// sendstringf("%c%c%c%c",t[0],t[1],t[2],t[3]);
|
|
displayline("%c%c%c%c",t[0],t[1],t[2],t[3]);
|
|
}
|
|
// sendstringf("\n\r");
|
|
displayline(" \n");
|
|
|
|
}
|
|
|
|
|
|
}
|
|
else
|
|
{
|
|
sendstring("Your crappy comp doesn\'t support cpuid\n\r");
|
|
displayline("Your system does not support CPUID\n");
|
|
}
|
|
|
|
cpuinfo->TSbase=0;
|
|
cpuinfo->TSlimit=0xffff;
|
|
cpuinfo->TSsegment=0;
|
|
cpuinfo->TSaccessRights=0x8b;
|
|
|
|
sendstringf("Setting up idttable and jumptable\n\r");
|
|
|
|
jumptable=malloc(4096);
|
|
idttable32=malloc(4096);
|
|
|
|
sendstringf("jumptable allocated at %x (%6)\n\r",(UINT64)jumptable, VirtualToPhysical(jumptable));
|
|
sendstringf("idttable32 allocated at %x (%6)\n\r",(UINT64)idttable32, VirtualToPhysical(idttable32));
|
|
|
|
//fill jumptable and IDT
|
|
PINT_VECTOR32 idt32=(PINT_VECTOR32)idttable32;
|
|
UINT64 pa=VirtualToPhysical(jumptable);
|
|
UINT64 inthandler32address=(UINT64)VirtualToPhysical(&inthandler_32);
|
|
|
|
unsigned char *jumptablepc;
|
|
jumptablepc=(unsigned char *)jumptable;
|
|
for (i=0; i<256; i++, pa+=10)
|
|
{
|
|
//push i
|
|
jumptablepc[i*10]=0x68; //push
|
|
*(DWORD *)&jumptablepc[i*10+1]=i;
|
|
|
|
//jmp inthandler_32
|
|
jumptablepc[i*10+5]=0xe9;
|
|
*(DWORD *)(&jumptablepc[i*10+6])=inthandler32address-(pa+10); //from (current offset+5(including push 7)) to inthandler_32
|
|
idt32[i].bAccess=0x8e;
|
|
idt32[i].bUnused=0;
|
|
idt32[i].wHighOffset=pa >> 16;
|
|
idt32[i].wLowOffset=pa & 0xffff;
|
|
idt32[i].wSelector=24;
|
|
|
|
//sendstringf("idt32[%x]=%x\n\r",i, *(UINT64*)&idt32[i]);
|
|
}
|
|
|
|
sendstring("setting up gdt entry at offset 0x64 as virtual8086 task\n\r");
|
|
PGDT_ENTRY currentgdt=(PGDT_ENTRY)getGDTbase();
|
|
|
|
|
|
sendstringf("currentgdt is %x (limit=%x)\n\r",(UINT64)currentgdt, getGDTsize());
|
|
ULONG length=(ULONG)sizeof(TSS)+32+8192+1;
|
|
|
|
|
|
currentgdt[8].Limit0_15=length;
|
|
currentgdt[8].Base0_23=(QWORD)VirtualMachineTSS_V8086;
|
|
currentgdt[8].Type=0x9;
|
|
currentgdt[8].NotSystem=0;
|
|
currentgdt[8].DPL=3;
|
|
currentgdt[8].P=1;
|
|
currentgdt[8].Limit16_19=length >> 16;
|
|
currentgdt[8].AVL=1;
|
|
currentgdt[8].L=0;
|
|
currentgdt[8].B_D=0;
|
|
currentgdt[8].G=0;
|
|
currentgdt[8].Base24_31=(QWORD)VirtualMachineTSS_V8086 >> 24;
|
|
*(QWORD*)¤tgdt[9]=((QWORD)VirtualMachineTSS_V8086) >> 32;
|
|
|
|
//setup GDT for realmode jump
|
|
currentgdt[4].Base0_23=0x20000;
|
|
|
|
|
|
//if (!loadedOS)
|
|
{
|
|
sendstringf("Setting up 64-bit TS and TSS\n\r");
|
|
|
|
TSS64 *temp=malloc(4096);
|
|
|
|
sendstringf("temp allocated at %x\n", temp);
|
|
ownTSS=temp;
|
|
zeromemory(temp,4096);
|
|
currentgdt=(PGDT_ENTRY)(getGDTbase()+96);
|
|
|
|
currentgdt[0].Limit0_15=4096;
|
|
currentgdt[0].Base0_23=(UINT64)temp;
|
|
currentgdt[0].Type=0x9;
|
|
currentgdt[0].NotSystem=0;
|
|
currentgdt[0].DPL=0;
|
|
currentgdt[0].P=1;
|
|
currentgdt[0].Limit16_19=4096 >> 16;
|
|
currentgdt[0].AVL=1;
|
|
currentgdt[0].L=0;
|
|
currentgdt[0].B_D=0;
|
|
currentgdt[0].G=0;
|
|
currentgdt[0].Base24_31=((UINT64)temp) >> 24;
|
|
*(QWORD*)¤tgdt[1]=((UINT64)temp) >> 32;
|
|
|
|
temp->IST1=(QWORD)malloc(8192)+8192-0x10; //panic stack
|
|
|
|
loadTaskRegister(96);
|
|
}
|
|
|
|
displayline("Generating debug information\n\r");
|
|
originalVMMcrc=generateCRC((void*)vmxloop,0x2a000);
|
|
|
|
|
|
displayline("Virtual machine manager loaded\n");
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
displayline("Entering menu system\n");
|
|
#else
|
|
displayline("Skipping menu system and autostarting VM\n");
|
|
#endif
|
|
|
|
{
|
|
//mark the region between 0 to 0x00400000 as readonly, if you need to write, map it
|
|
PPDPTE_PAE pml4entry;
|
|
PPDPTE_PAE pagedirpointerentry;
|
|
PPDE_PAE pagedirentry;
|
|
PPTE_PAE pagetableentry;
|
|
|
|
VirtualAddressToPageEntries(0, &pml4entry, &pagedirpointerentry, &pagedirentry, &pagetableentry);
|
|
pagedirentry[0].RW=0;
|
|
pagedirentry[1].RW=0;
|
|
}
|
|
|
|
#if DISPLAYDEBUG==0
|
|
if (needtospawnApplicationProcessors)
|
|
#endif
|
|
textmemory=(QWORD)mapPhysicalMemory(0xb8000, 4096); //at least enough for 80*25*2
|
|
|
|
|
|
InitExports();
|
|
|
|
|
|
menu2();
|
|
return;
|
|
}
|
|
|
|
//#pragma GCC push_options
|
|
//#pragma GCC optimize ("O0")
|
|
int testexception(void)
|
|
{
|
|
|
|
volatile int result=2;
|
|
|
|
|
|
bochsbp();
|
|
|
|
__asm("nop");
|
|
__asm("nop");
|
|
__asm("nop");
|
|
|
|
result=readMSRSafe(553);
|
|
|
|
//nothing happened
|
|
//result=0;
|
|
displayline("result=%d\n", result);
|
|
|
|
|
|
return result;
|
|
}
|
|
|
|
void vmcalltest(void)
|
|
{
|
|
int dbvmversion;
|
|
dbvmversion=0;
|
|
|
|
try
|
|
{
|
|
dbvmversion=vmcalltest_asm();
|
|
sendstringf("dbvm is loaded. Version %x\n", dbvmversion);
|
|
}
|
|
except
|
|
{
|
|
sendstringf("dbvm is not loaded\n");
|
|
}
|
|
tryend
|
|
}
|
|
|
|
|
|
//#pragma GCC pop_options
|
|
|
|
|
|
|
|
void reboot(int skipAPTerminationWait)
|
|
{
|
|
{
|
|
//remapping pagetable entry 0 to 0x00400000 so it's writabe (was marked unwritable after entry)
|
|
PPDPTE_PAE pml4entry;
|
|
PPDPTE_PAE pagedirpointerentry;
|
|
PPDE_PAE pagedirentry;
|
|
PPTE_PAE pagetableentry;
|
|
|
|
VirtualAddressToPageEntries(0, &pml4entry, &pagedirpointerentry, &pagedirentry, &pagetableentry);
|
|
pagedirentry[0].RW=1;
|
|
pagedirentry[1].RW=1;
|
|
asm volatile ("": : :"memory");
|
|
}
|
|
|
|
//Disable the AP cpu's as on a normal reboot, the memory they are looping in will first be zeroed out (it picks the same memory block)
|
|
AP_Terminate=1; //tells the AP cpu's to stop
|
|
|
|
if (skipAPTerminationWait==0) //can be skipped if ran by vmlaunch (the other cpu's will stay active as they are in wait-for-sipi mode)
|
|
{
|
|
startNextCPU(); //just make sure there is none waiting
|
|
|
|
int stillactive=1;
|
|
while (stillactive)
|
|
{
|
|
pcpuinfo c=firstcpuinfo->next;
|
|
stillactive=0;
|
|
while (c)
|
|
{
|
|
if ((c->vmxsetup==0) && (c->active)) //not configured to be a VMX, and still active
|
|
stillactive=1;
|
|
|
|
c=c->next;
|
|
}
|
|
}
|
|
}
|
|
|
|
UINT64 gdtaddress=getGDTbase(); //0x40002 contains the address of the GDT table
|
|
|
|
sendstring("Copying gdt to low memory\n\r");
|
|
copymem((void *)0x50000,(void *)(UINT64)gdtaddress,128); //copy gdt to 0x50000
|
|
|
|
sendstring("copying movetoreal to 0x2000\n\r");
|
|
copymem((void *)0x20000,(void *)(UINT64)&movetoreal,(UINT64)&vmxstartup_end-(UINT64)&movetoreal);
|
|
|
|
|
|
sendstring("Calling quickboot\n\r");
|
|
|
|
if (skipAPTerminationWait==0xcedead) //PSOD
|
|
*(unsigned char *)0x7c0e=0xff;
|
|
else
|
|
*(unsigned char *)0x7c0e=bootdisk;
|
|
|
|
|
|
|
|
quickboot();
|
|
sendstring("WTF?\n\r");
|
|
}
|
|
|
|
|
|
#ifdef DEBUG
|
|
#define SHOWFIRSTMENU 1
|
|
int showfirstmenu=1;
|
|
#else
|
|
#define SHOWFIRSTMENU 0
|
|
int showfirstmenu=0;
|
|
#endif
|
|
|
|
void menu2(void)
|
|
{
|
|
unsigned char key;
|
|
|
|
if (isAMD)
|
|
vmcall_instr=vmcall_amd;
|
|
else
|
|
vmcall_instr=vmcall_intel;
|
|
|
|
|
|
|
|
sendstringf("loadedOS=%6\n",loadedOS);
|
|
|
|
|
|
//*(BYTE *)0x7c0e=0x80;
|
|
bootdisk=0x80;
|
|
while (1)
|
|
{
|
|
clearScreen();
|
|
currentdisplayline=0;
|
|
|
|
{
|
|
vmcb x;
|
|
int offset;
|
|
|
|
offset=(QWORD)&x.DR6-(QWORD)&x;
|
|
|
|
|
|
displayline("DR6=%x\n", offset);
|
|
|
|
|
|
}
|
|
|
|
displayline("Welcome to the DBVM interactive menu\n\n");
|
|
displayline("These are your options:\n");
|
|
displayline("0: Start virtualization\n");
|
|
displayline("1: Keyboard test\n");
|
|
displayline("2: Set disk to startup from (currently %2)\n",bootdisk);
|
|
displayline("3: Disassembler test\n");
|
|
displayline("4: Interrupt test\n");
|
|
displayline("5: Breakpoint test\n");
|
|
displayline("6: Set Redirects with dbvm (only if dbvm is already loaded)\n");
|
|
displayline("7: cr3 fuck test\n");
|
|
displayline("8: PCI enum test (finds db's serial port)\n");
|
|
displayline("9: test input\n");
|
|
displayline("a: test branch profiling\n");
|
|
displayline("b: boot without vm (test state vm would set)\n");
|
|
displayline("c: PSOD test\n");
|
|
displayline("v: control register test\n");
|
|
displayline("e: efer test\n");
|
|
displayline("o: out of memory test\n");
|
|
|
|
key=0;
|
|
while (!key)
|
|
{
|
|
if ((!loadedOS) || (showfirstmenu))
|
|
{
|
|
if (loadedOS)
|
|
key=waitforchar();
|
|
else
|
|
key=kbd_getchar();
|
|
}
|
|
else
|
|
key='0';
|
|
|
|
while (IntHandlerDebug) ;
|
|
|
|
if (key)
|
|
{
|
|
char temps[16];
|
|
displayline("%c\n", key);
|
|
|
|
switch (key)
|
|
{
|
|
case '0':
|
|
clearScreen();
|
|
menu();
|
|
break;
|
|
|
|
case '1':
|
|
displayline("kdbstatus=%2\n",kbd_getstatus());
|
|
displayline("kdb_getoutputport=%2\n",kdb_getoutputport());
|
|
displayline("kdb_getinputport=%2\n",kdb_getinputport());
|
|
displayline("kdb_getcommandbyte=%2\n",kdb_getcommandbyte());
|
|
break;
|
|
|
|
case '2':
|
|
displayline("Set the new drive: ");
|
|
readstringc(temps,2,16);
|
|
temps[15]=0;
|
|
|
|
bootdisk=atoi2(temps,16,NULL);
|
|
displayline("\nNew drive=%2 \n",bootdisk);
|
|
break;
|
|
|
|
case '3': //disassemblerr
|
|
{
|
|
_DecodedInst disassembled[22];
|
|
unsigned int i;
|
|
unsigned int used=0;
|
|
distorm_decode((UINT64)&menu2,(unsigned char*)menu2, 256, Decode64Bits, disassembled, 22, &used);
|
|
|
|
if (used)
|
|
{
|
|
for (i=0; i<used; i++)
|
|
{
|
|
displayline("%x : %s - %s %s\n",
|
|
disassembled[i].offset,
|
|
disassembled[i].instructionHex.p,
|
|
disassembled[i].mnemonic.p,
|
|
disassembled[i].operands.p);
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
displayline("Failure...\n");
|
|
}
|
|
|
|
|
|
}
|
|
break;
|
|
|
|
case '4':
|
|
{
|
|
__asm("sti"); //enable interrupts
|
|
break;
|
|
}
|
|
|
|
case '5':
|
|
{
|
|
UINT64 rflags;
|
|
pcpuinfo i=getcpuinfo();
|
|
|
|
|
|
|
|
try
|
|
{
|
|
displayline("Doing an int3 bp\n");
|
|
int3bptest();
|
|
displayline("Failure to int3 break\n");
|
|
}
|
|
except
|
|
{
|
|
displayline("caught level 1 int3 :%d\n", lastexception);
|
|
}
|
|
tryend
|
|
|
|
try
|
|
{
|
|
displayline("Doing an int3 bp 2\n");
|
|
int3bptest();
|
|
displayline("Failure to int3 break 2\n");
|
|
}
|
|
except
|
|
{
|
|
displayline("caught level 1 int 3 2:%d\n", lastexception);
|
|
}
|
|
tryend
|
|
|
|
|
|
displayline("testing multilevel try/except\n");
|
|
try
|
|
{
|
|
displayline("inside try. Entering 2nd try\n");
|
|
try
|
|
{
|
|
displayline("inside 2nd try. calling int3bptest\n");
|
|
int3bptest();
|
|
displayline("int3bptest in level 2 failed to get caught\n");
|
|
}
|
|
except
|
|
{
|
|
displayline("caught level 2 int3:%d\n", lastexception);
|
|
}
|
|
tryend
|
|
|
|
int3bptest();
|
|
displayline("Failure to int3 break\n");
|
|
}
|
|
except
|
|
{
|
|
displayline("caught level 1 int3:%d\n", lastexception);
|
|
}
|
|
tryend
|
|
|
|
displayline("Setting the GD flag");
|
|
|
|
i->OnInterrupt.RSP=getRSP();
|
|
i->OnInterrupt.RBP=getRBP();
|
|
i->OnInterrupt.RIP=(QWORD)((volatile void *)&&afterGDtest);
|
|
asm volatile ("": : :"memory");
|
|
setDR6(0xfffffff0);
|
|
setDR7(getDR7() | (1<<13));
|
|
asm volatile ("": : :"memory");
|
|
setDR6(0xffff0ff0);
|
|
|
|
sendstringf("Failure to break on GD");
|
|
|
|
asm volatile ("": : :"memory");
|
|
afterGDtest:
|
|
|
|
//RF
|
|
|
|
|
|
displayline("Setting an execute breakpoint\n\r");
|
|
setDR0((QWORD)getCR0);
|
|
setDR6(0xffff0ff0);
|
|
setDR7(getDR7() | (1<<0));
|
|
displayline("Going to execute it\n");
|
|
|
|
i->OnInterrupt.RSP=getRSP();
|
|
i->OnInterrupt.RBP=getRBP();
|
|
i->OnInterrupt.RIP=(QWORD)((volatile void *)&&afterEXBPtest);
|
|
asm volatile ("": : :"memory");
|
|
getCR0();
|
|
|
|
sendstringf("Failure to break on execute\n");
|
|
asm volatile ("": : :"memory");
|
|
afterEXBPtest:
|
|
|
|
displayline("Setting a RW breakpoint\n\r");
|
|
setDR0((QWORD)&isAP);
|
|
setDR6(0xffff0ff0);
|
|
setDR7(getDR7() | (3<<18) | (3<<16) | (1<<0));
|
|
displayline("Going to write to that breakpoint\n");
|
|
|
|
i->OnInterrupt.RSP=getRSP();
|
|
i->OnInterrupt.RBP=getRBP();
|
|
i->OnInterrupt.RIP=(QWORD)((volatile void *)&&afterWRBPtest);
|
|
asm volatile ("": : :"memory");
|
|
|
|
isAP++;
|
|
asm volatile ("": : :"memory");
|
|
sendstringf("Failure to break on write. %d\n", isAP);
|
|
afterWRBPtest:
|
|
asm volatile ("": : :"memory");
|
|
displayline("done writing\n");
|
|
|
|
|
|
displayline("Setting the single step flag (this will give exceptions)\n\r");
|
|
rflags=getRFLAGS(); //NO RF
|
|
setRFLAGS(rflags | (1<<8));
|
|
|
|
setRFLAGS(rflags & (~(1<<8))); //unset
|
|
|
|
break;
|
|
}
|
|
|
|
case '6':
|
|
{
|
|
displayline("Setting the redirects. #UD Interrupt will fire if dbvm is not loaded (and crash)");
|
|
vmcall_setintredirects();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case '7':
|
|
{
|
|
QWORD cr3=getCR3();
|
|
displayline("CR3 was %6\n", cr3);
|
|
|
|
cr3=cr3&0xfffffffffffff000ULL;
|
|
setCR3(cr3);
|
|
setCR4(getCR4() | CR4_PCIDE);
|
|
|
|
cr3=cr3 | 2;
|
|
setCR3(cr3);
|
|
|
|
cr3=getCR3();
|
|
displayline("CR3 is %6\n", cr3);
|
|
|
|
cr3=cr3 | 0x8000000000000000ULL;
|
|
setCR3(cr3);
|
|
cr3=getCR3();
|
|
displayline("CR3 is %6\n", cr3);
|
|
|
|
break;
|
|
}
|
|
|
|
case '8':
|
|
{
|
|
//pci enum test
|
|
pciConfigEnumPci();
|
|
break;
|
|
}
|
|
|
|
case '9':
|
|
{
|
|
{
|
|
char temps[17];
|
|
UINT64 address;
|
|
int size;
|
|
int err2,err3;
|
|
|
|
sendstring("\nAddress:");
|
|
readstring(temps,16,16);
|
|
address=atoi2(temps,16,&err2);
|
|
|
|
sendstring("\nNumber of bytes:");
|
|
readstring(temps,16,16);
|
|
size=atoi2(temps,10,&err3);
|
|
|
|
{
|
|
_DecodedInst disassembled[22];
|
|
unsigned int i;
|
|
unsigned int used=0;
|
|
distorm_decode((UINT64)address,(unsigned char*)address, size, Decode64Bits, disassembled, 22, &used);
|
|
|
|
if (used)
|
|
{
|
|
for (i=0; i<used; i++)
|
|
{
|
|
displayline("%x : %s - %s %s\n",
|
|
disassembled[i].offset,
|
|
disassembled[i].instructionHex.p,
|
|
disassembled[i].mnemonic.p,
|
|
disassembled[i].operands.p);
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
displayline("Failure...\n");
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case 'a':
|
|
{
|
|
testBranchPrediction();
|
|
break;
|
|
}
|
|
|
|
case 'b':
|
|
{
|
|
reboot(0);
|
|
displayline("WTF?\n");
|
|
break;
|
|
}
|
|
|
|
case 'c':
|
|
{
|
|
psod();
|
|
displayline("WTF?\n");
|
|
break;
|
|
}
|
|
|
|
case 'e':
|
|
{
|
|
QWORD old=readMSR(EFER_MSR);
|
|
QWORD new;
|
|
|
|
sendstringf("old=%6\n", old);
|
|
|
|
new=old ^ (1<<11);
|
|
new=new & (~(1<<10));
|
|
sendstringf("new1=%6\n", new);
|
|
writeMSR(EFER_MSR, new);
|
|
|
|
new=readMSR(EFER_MSR);
|
|
sendstringf("new2=%6\n", new);
|
|
break;
|
|
}
|
|
|
|
case 'o':
|
|
{
|
|
int count;
|
|
void *mem;
|
|
|
|
while (1)
|
|
{
|
|
mem=malloc2(4096);
|
|
if (mem==NULL)
|
|
{
|
|
sendstringf("alloc fail\n");
|
|
while (1);
|
|
}
|
|
count++;
|
|
if (count%10==0)
|
|
{
|
|
sendstringf("count=%d\n", count);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
}
|
|
|
|
case 'v':
|
|
{
|
|
QWORD cr0=getCR0();
|
|
sendstringf("CR0=%x\n", cr0);
|
|
|
|
sendstring("Flipping WP\n");
|
|
|
|
cr0=cr0 ^ CR0_WP;
|
|
setCR0(cr0);
|
|
cr0=getCR0();
|
|
sendstringf("CR0=%x\n", cr0);
|
|
|
|
sendstring("Flipping NE\n");
|
|
cr0=cr0 ^ CR0_NE;
|
|
setCR0(cr0);
|
|
cr0=getCR0();
|
|
sendstringf("CR0=%x\n", cr0);
|
|
|
|
sendstring("Flipping NE again \n");
|
|
cr0=cr0 ^ CR0_NE;
|
|
setCR0(cr0);
|
|
cr0=getCR0();
|
|
sendstringf("CR0=%x\n", cr0);
|
|
|
|
QWORD cr4=getCR4();
|
|
sendstringf("CR4=%x\n", cr4);
|
|
|
|
sendstring("Flipping CR4_OSXSAVE\n");
|
|
|
|
cr4=cr4 ^ CR4_OSXSAVE;
|
|
setCR4(cr4);
|
|
cr4=getCR4();
|
|
sendstringf("CR4=%x\n", cr4);
|
|
|
|
sendstring("Flipping CR4_VMXE\n");
|
|
|
|
cr4=cr4 ^ CR4_VMXE;
|
|
setCR4(cr4);
|
|
cr4=getCR4();
|
|
sendstringf("CR4=%x\n", cr4);
|
|
|
|
sendstring("Flipping CR4_VMXE again\n");
|
|
|
|
cr4=cr4 ^ CR4_VMXE;
|
|
setCR4(cr4);
|
|
cr4=getCR4();
|
|
sendstringf("CR4=%x\n", cr4);
|
|
|
|
|
|
|
|
break;
|
|
}
|
|
|
|
default:
|
|
key=0;
|
|
break;
|
|
}
|
|
|
|
|
|
|
|
if (key)
|
|
{
|
|
displayline("Press any key to return to the menu\n");
|
|
if (loadedOS)
|
|
key=waitforchar();
|
|
else
|
|
key=kbd_getchar();
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
resync();
|
|
}
|
|
}
|
|
|
|
|
|
#if (defined SERIALPORT) && (SERIALPORT != 0)
|
|
//obsolete, part of lauxlib again
|
|
void *lalloc (void *ud, void *ptr, size_t osize, size_t nsize) {
|
|
(void)ud;
|
|
(void)osize;
|
|
if (nsize == 0) {
|
|
free(ptr);
|
|
return NULL;
|
|
}
|
|
else
|
|
return realloc(ptr, nsize);
|
|
}
|
|
#endif
|
|
|
|
|
|
void menu(void)
|
|
{
|
|
displayline("menu\n\r"); //debug to find out why the vm completely freezes when SERIALPORT==0
|
|
|
|
sendstring("menu\n\r");
|
|
|
|
displayline("After sendstring\n");
|
|
|
|
int i,j;
|
|
|
|
nosendchar[getAPICID()]=0; //force that it gets send
|
|
|
|
while (1)
|
|
{
|
|
char command;
|
|
QWORD mem;
|
|
QWORD pages;
|
|
mem=getTotalFreeMemory(&pages);
|
|
sendstring("\n\r\n\rWelcome to Dark Byte\'s virtual machine monitor\n\r");
|
|
|
|
|
|
sendstringf("Memory free: %d Bytes (Pages: %d) ", (int)mem, (int)pages);
|
|
sendstring("\n\r^^^^^^^^^^^^^^^^^^^^^^^Menu 1^^^^^^^^^^^^^^^^^^\n\r");
|
|
sendstring("Press 0 to run the VM\n\r");
|
|
sendstring("Press 1 to display the fake memory map\n\r");
|
|
sendstring("Press 2 to display the virtual memory of the VMM\n\r");
|
|
sendstring("Press 3 to display the physical memory of this system\n\r");
|
|
sendstring("Press 4 to display the virtual memory of the Virtual Machine\n\r");
|
|
sendstring("Press 5 to raise int 1 by software\n\r");
|
|
sendstring("Press 6 to run some testcode in the 2nd core (assuming there is one)\n\r");
|
|
sendstring("Press 7 to test some crap\n\r");
|
|
sendstring("Press 8 to execute testcode()\n\r");
|
|
sendstring("Press 9 to restart\n\r");
|
|
sendstring("Press M to test the memorymanager\n\r");
|
|
#if (defined SERIALPORT) && (SERIALPORT != 0)
|
|
sendstring("Press L for Lua\n\r");
|
|
#endif
|
|
sendstring("Your command:");
|
|
|
|
#ifndef DEBUG
|
|
if (autostart || loadedOS)
|
|
{
|
|
autostart=0;
|
|
command='0';
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
displayline("Waiting for serial port command:\n");
|
|
sendstring("waiting for command:");
|
|
|
|
if (loadedOS)
|
|
{
|
|
// command='0';
|
|
command=waitforchar();
|
|
|
|
}
|
|
else
|
|
{
|
|
#if (defined SERIALPORT) && (SERIALPORT != 0)
|
|
command=waitforchar();
|
|
#else
|
|
command='0';
|
|
#endif
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
displayline("Checking command %d ",command);
|
|
|
|
sendchar(command);
|
|
|
|
displayline("After sendchar\n");
|
|
sendstring("\n\r");
|
|
|
|
displayline("...");
|
|
|
|
switch (command)
|
|
{
|
|
|
|
case '0' : //run virtual machine
|
|
{
|
|
displayline("Starting the virtual machine\n");
|
|
|
|
if ((!loadedOS) || (needtospawnApplicationProcessors))
|
|
{
|
|
|
|
if (cpucount>0) //!isAMD for now during tests
|
|
{
|
|
displayline("Sending other CPU cores into VMX wait mode\n");
|
|
sendstring("BootCPU: Sending all AP's the command to start the VMX code\n\r");
|
|
|
|
AP_Launch=1;
|
|
int allsetup=0;
|
|
pcpuinfo c;
|
|
while (allsetup==0)
|
|
{
|
|
c=firstcpuinfo->next;
|
|
allsetup=1;
|
|
while (c)
|
|
{
|
|
if (c->vmxsetup==0)
|
|
{
|
|
allsetup=0;
|
|
resync();
|
|
break;
|
|
}
|
|
|
|
c=c->next;
|
|
}
|
|
}
|
|
//wait till the other cpu's are started
|
|
sendstring("BOOT CORE: Other cpu's finished setting up, now start the boot cpu\n\r");
|
|
}
|
|
|
|
|
|
displayline("Calling startvmx for main core\n");
|
|
}
|
|
|
|
//while (1) _pause(); //debug so I only see AP cpu's
|
|
|
|
|
|
startvmx(getcpuinfo());
|
|
sendstring("BootCPU: Back from startvmx\n\r");
|
|
break;
|
|
}
|
|
|
|
case '1' : //display fake mem map
|
|
sendARD();
|
|
break;
|
|
|
|
|
|
case '2' : //display vmm mem
|
|
{
|
|
char temps[17];
|
|
unsigned long long StartAddress;
|
|
unsigned int nrofbytes;
|
|
|
|
sendstring("Startaddress:");
|
|
readstring(temps,16,16);
|
|
sendstring("\n\r");
|
|
sendstringf("temps=%s \n\r",temps);
|
|
StartAddress=atoi2(temps,16,NULL);
|
|
|
|
|
|
sendstring("Number of bytes:");
|
|
readstring(temps,8,8);
|
|
sendstring("\n\r");
|
|
nrofbytes=atoi2(temps,10,NULL);
|
|
|
|
sendstringf("Going to show the memory region %6 to %6 (physical=%6)\n\r",StartAddress,StartAddress+nrofbytes,VirtualToPhysical((void *)StartAddress));
|
|
|
|
for (i=0; (unsigned int)i<nrofbytes; i+=16)
|
|
{
|
|
sendstringf("%8 : ",StartAddress+i);
|
|
for (j=i; (j<(i+16)) && ((unsigned)j<nrofbytes); j++)
|
|
sendstringf("%2 ",(unsigned char)*(unsigned char *)(StartAddress+j));
|
|
|
|
if ((unsigned)(i+16)>nrofbytes)
|
|
{
|
|
// Get the cursor to the right spot
|
|
int currentcol=11+3*(nrofbytes-i);
|
|
int wantedcol=11+3*16;
|
|
for (j=0; j<(wantedcol-currentcol); j++)
|
|
sendstring(" ");
|
|
}
|
|
|
|
for (j=i; j<(i+16) && ((unsigned)j<nrofbytes); j++)
|
|
{
|
|
unsigned char tempc=*(unsigned char *)(StartAddress+j);
|
|
if (tempc<32)
|
|
tempc='.';
|
|
|
|
sendstringf("%c",tempc);
|
|
}
|
|
|
|
sendstring("\n\r");
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
|
|
|
|
case '3' : //display physical memory
|
|
//use one page (mapped at 0x80000000, 4mb) to display the memory
|
|
{
|
|
displayPhysicalMemory();
|
|
}
|
|
break;
|
|
|
|
|
|
case '4' : //display vm memory (virtual)
|
|
{
|
|
sendstringf("obsolete\n");
|
|
|
|
}
|
|
break;
|
|
|
|
|
|
case '5' :
|
|
asm("int $5\n");
|
|
break;
|
|
|
|
|
|
case '6' : //run 2nd core testapp
|
|
{
|
|
/*
|
|
unsigned int a,b,c,d;
|
|
a=1;
|
|
_cpuid(&a,&b,&c,&d);
|
|
sendstringf("cpuid:1: eax=%8, ebx=%8, ecx=%8, edx=%8, \n\r",a,b,c,d);
|
|
if ((d & (1<<28))>0)
|
|
{
|
|
sendstring("Multi processor supported\n\r");
|
|
sendstringf("logical processor per package: %d \n\r",(d >> 16) & 0xff);
|
|
|
|
BOOT_ID=apic_getBootID();
|
|
sendstringf("BOOT_ID=%8\n\r",BOOT_ID);
|
|
|
|
sendstringf("APIC_SVR=%8\n\r",APIC_SVR);
|
|
|
|
|
|
cpucount=1;
|
|
apic_enableSVR();
|
|
while (cpucount==1)
|
|
{
|
|
a=1;
|
|
_cpuid(&a,&b,&c,&d); //serializing instruction
|
|
}
|
|
|
|
}
|
|
else
|
|
sendstring("No multi processor support\n");
|
|
|
|
|
|
*/
|
|
|
|
break;
|
|
}
|
|
|
|
case '7':
|
|
{
|
|
int error;
|
|
UINT64 pf;
|
|
|
|
void *address=mapVMmemory(getcpuinfo(), 0xc0000ULL, 16, &error, &pf);
|
|
sendstringf("address=%6\n", address);
|
|
|
|
if (error==0)
|
|
{
|
|
sendstringf("*address=%2\n", *(char *)address);
|
|
unmapPhysicalMemory(address,16);
|
|
}
|
|
else
|
|
sendstringf("error=%d (pf=%6)\n", error, pf);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
break;
|
|
//
|
|
|
|
|
|
|
|
}
|
|
|
|
case '8':
|
|
{
|
|
break;
|
|
}
|
|
|
|
case '9':
|
|
{
|
|
reboot(0);
|
|
|
|
break;
|
|
}
|
|
|
|
case 'm':
|
|
{
|
|
mmtest();
|
|
break;
|
|
}
|
|
|
|
|
|
#if (defined SERIALPORT) && (SERIALPORT != 0)
|
|
case 'l':
|
|
{
|
|
sendstring("Entering lua console:");
|
|
enterLuaConsole();
|
|
|
|
|
|
break;
|
|
}
|
|
#endif
|
|
|
|
|
|
|
|
case 'v':
|
|
{
|
|
sendstring("Trying vmcall\n");
|
|
vmcalltest();
|
|
break;
|
|
}
|
|
|
|
/*
|
|
case 'i':
|
|
showstate();
|
|
break;
|
|
|
|
case 't':
|
|
{
|
|
ULONG xxx=MapPhysicalMemory(0xfb000000, 0xfb000000);
|
|
sendstringf("xxx=%8\n\r",xxx);
|
|
testcode();
|
|
break;
|
|
}
|
|
|
|
case 'c' :
|
|
{
|
|
unsigned int crc=generateCRC((unsigned char *)(e), 0x007fffff-(e));
|
|
unsigned int idtcrc=generateCRC((unsigned char *)0, 0x400);
|
|
unsigned int vmmcrc=generateCRC((unsigned char *)0x00400000, getGDTbase() - 0x00400000);
|
|
sendstringf("stack crc=%8\n\r",crc);
|
|
sendstringf("idt crc=%8\n\r",idtcrc);
|
|
sendstringf("vmm crc=%8\n\r",vmmcrc);
|
|
break;
|
|
}
|
|
*/
|
|
|
|
default :
|
|
sendstring("That is not a valid option\n\r");
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
void startvmx(pcpuinfo currentcpuinfo)
|
|
{
|
|
#ifdef DEBUG
|
|
UINT64 entryrsp=getRSP();
|
|
#endif
|
|
|
|
UINT64 a,b,c,d;
|
|
|
|
|
|
|
|
displayline("cpu %d: startvmx:\n",currentcpuinfo->cpunr);
|
|
#ifdef DEBUG
|
|
sendstringf("currentcpuinfo=%6 (cpunr=%d)\n\r",(UINT64)currentcpuinfo, currentcpuinfo->cpunr);
|
|
sendstringf("ESP=%6\n\r",entryrsp);
|
|
sendstringf("APICID=%d\n\r",getAPICID());
|
|
#endif
|
|
|
|
|
|
|
|
|
|
// setup the vmx environment and run it
|
|
if (hascpuid())
|
|
{
|
|
|
|
unsigned char ext_fam_id;
|
|
unsigned char ext_model_id;
|
|
unsigned char proc_type;
|
|
unsigned char family_id;
|
|
unsigned char model;
|
|
unsigned char stepping_id;
|
|
|
|
a=1;
|
|
_cpuid(&a,&b,&d,&c);
|
|
|
|
|
|
stepping_id= a & 0xf; //4
|
|
model=(a >> 4) & 0xf; //4
|
|
family_id=(a >> 8) & 0xf; //4
|
|
proc_type=(a >> 12) & 0x3; //2
|
|
//2
|
|
ext_model_id=(a >> 16 ) & 0xf; //4
|
|
ext_fam_id=(a >> 20 ) & 0xff;
|
|
|
|
sendstringf("Version Information=%x : \n\r",a);
|
|
sendstringf("\tstepping_id=%d\n\r",stepping_id);
|
|
sendstringf("\tmodel=%d\n\r",model);
|
|
sendstringf("\tfamily_id=%d\n\r",family_id);
|
|
sendstringf("\tproc_type=%d\n\r",proc_type);
|
|
sendstringf("\text_model_id=%d\n\r",ext_model_id);
|
|
sendstringf("\text_fam_id=%d\n\r",ext_fam_id);
|
|
|
|
|
|
|
|
sendstringf("Brand Index/CLFLUSH/Maxnrcores/Init APIC=%x :\n",b);
|
|
{
|
|
unsigned char brand_index;
|
|
unsigned char CLFLUSH_line_size;
|
|
unsigned char max_logical_cpu;
|
|
unsigned char initial_APIC;
|
|
|
|
brand_index=b & 0xff; //4
|
|
CLFLUSH_line_size=(b >> 8) & 0xff;
|
|
max_logical_cpu=(b >> 16) & 0xff;
|
|
initial_APIC=(b >> 24) & 0xff;
|
|
|
|
sendstringf("\tBrand Index=%d\n\r",brand_index);
|
|
sendstringf("\tCLFLUSH line size=%d\n\r",CLFLUSH_line_size);
|
|
sendstringf("\tMaximum logical cpu\'s=%d\n\r",max_logical_cpu);
|
|
sendstringf("\tinitial APIC=%d\n\r",initial_APIC);
|
|
}
|
|
|
|
// PSOD("Line 2149: PSOD Test");
|
|
|
|
if (isAMD)
|
|
{
|
|
sendstring("AMD virtualization handling\n\r");
|
|
|
|
|
|
|
|
UINT64 a=0x80000001;
|
|
UINT64 b,c,d;
|
|
|
|
_cpuid(&a,&b,&c,&d);
|
|
|
|
if (c & (1<<2)) //SVM bit in cpuid
|
|
{
|
|
sendstring("SVM supported\n");
|
|
|
|
a=0x8000000a;
|
|
_cpuid(&a,&b,&c,&d);
|
|
|
|
displayline("cpuid: 0x8000000a:\n");
|
|
displayline("EAX=%8\n", a);
|
|
displayline("EBX=%8\n", b);
|
|
displayline("ECX=%8\n", c);
|
|
displayline("EDX=%8\n", d);
|
|
|
|
|
|
AMD_hasDecodeAssists=(d & (1<<7))>0;
|
|
AMD_hasNRIPS=(d & (1<<3))>0;
|
|
sendstringf("AMD_hasDecodeAssists=%d\n", AMD_hasDecodeAssists);
|
|
|
|
UINT64 VM_CR=readMSR(0xc0010114); //VM_CR MSR
|
|
sendstringf("VM_CR=%6\n", VM_CR);
|
|
|
|
if ((VM_CR & (1<<4))==0)
|
|
{
|
|
UINT64 efer;
|
|
sendstring("SVM is available\n");
|
|
|
|
|
|
|
|
currentcpuinfo->vmcb=malloc(4096);
|
|
//SetPageToWriteThrough((UINT64)currentcpuinfo->vmcb); //test. I doubt it's needed since no cpu touches another's vmcb
|
|
|
|
sendstringf("Have set vmcb at %x to WriteThrough caching protection\n", currentcpuinfo->vmcb);
|
|
|
|
zeromemory(currentcpuinfo->vmcb, 4096);
|
|
|
|
currentcpuinfo->vmcb_PA=(UINT64)VirtualToPhysical((void *)currentcpuinfo->vmcb);
|
|
|
|
sendstring("Setting SVME bit in EFER\n");
|
|
efer=readMSR(EFER_MSR);
|
|
|
|
sendstringf("EFER was %6\n", efer);
|
|
efer=efer | (1 << 12);
|
|
sendstringf("EFER will become %6\n", efer);
|
|
|
|
|
|
writeMSR(EFER_MSR, efer);
|
|
|
|
|
|
|
|
|
|
UINT64 VM_HSAVE_PA_MSR=readMSR(0xc0010117); //VM_HSAVE_PA MSR
|
|
sendstringf("VM_HSAVE_PA_MSR was %6\n", VM_HSAVE_PA_MSR);
|
|
|
|
currentcpuinfo->vmcb_host=malloc(4096);
|
|
// bochsbp();
|
|
writeMSR(0xc0010117, (UINT64)VirtualToPhysical(currentcpuinfo->vmcb_host));
|
|
|
|
|
|
|
|
setupVMX(currentcpuinfo);
|
|
|
|
|
|
/*if (!isAP)
|
|
clearScreen();*/
|
|
|
|
|
|
|
|
|
|
launchVMX(currentcpuinfo);
|
|
|
|
sendstring("launchVMX returned\n");
|
|
while (1)
|
|
{
|
|
|
|
}
|
|
|
|
|
|
}
|
|
else
|
|
{
|
|
sendstring("SVM has been disabled\n");
|
|
}
|
|
|
|
|
|
}
|
|
else
|
|
{
|
|
sendstring("This cpu does not support SVM\n");
|
|
sendstringf("cpuid: 0x80000001:\n");
|
|
sendstringf("EAX=%8\n", a);
|
|
sendstringf("EBX=%8\n", b);
|
|
sendstringf("ECX=%8\n", c);
|
|
sendstringf("EDX=%8\n", d);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
else
|
|
{
|
|
|
|
if ((d >> 5) & 1)
|
|
{
|
|
|
|
volatile UINT64 IA32_FEATURE_CONTROL;
|
|
|
|
|
|
displayline("%d:System check successful. INTEL-VT is supported\n", currentcpuinfo->cpunr);
|
|
sendstring("!!!!!!!!!!!!!!This system supports VMX!!!!!!!!!!!!!!\n\r");
|
|
|
|
displayline("Going to call IA32_FEATURE_CONTROL=readMSR(0x3a)\n");
|
|
IA32_FEATURE_CONTROL=readMSR(IA32_FEATURE_CONTROL_MSR);
|
|
displayline("IA32_FEATURE_CONTROL=%6\n\r",IA32_FEATURE_CONTROL);
|
|
|
|
|
|
if (IA32_FEATURE_CONTROL & FEATURE_CONTROL_LOCK)
|
|
{
|
|
displayline("IA32_FEATURE_CONTROL is locked (value=%6). (Disabled in bios?)\n\r",IA32_FEATURE_CONTROL);
|
|
if (!(IA32_FEATURE_CONTROL & FEATURE_CONTROL_VMXON ))
|
|
{
|
|
displayline("Bit 2 (VMX) is also disabled. VMX is not possible. Reboot!\n");
|
|
return;
|
|
}
|
|
else
|
|
sendstring("VMXON was already enabled in the feature control MSR\n");
|
|
}
|
|
else
|
|
{
|
|
sendstring("Not locked yet\n");
|
|
|
|
IA32_FEATURE_CONTROL=IA32_FEATURE_CONTROL | FEATURE_CONTROL_VMXON | FEATURE_CONTROL_LOCK;
|
|
|
|
displayline("setting IA32_FEATURE_CONTROL to %6\n\r",IA32_FEATURE_CONTROL);
|
|
|
|
writeMSR(IA32_FEATURE_CONTROL_MSR,IA32_FEATURE_CONTROL);
|
|
IA32_FEATURE_CONTROL=readMSR(IA32_FEATURE_CONTROL_MSR);
|
|
displayline("IA32_FEATURE_CONTROL is now %6\n\r",IA32_FEATURE_CONTROL);
|
|
}
|
|
|
|
|
|
sendstring("Gathering VMX info\n\r");
|
|
//gather info
|
|
IA32_VMX_BASIC.IA32_VMX_BASIC=readMSR(0x480);
|
|
|
|
IA32_VMX_CR0_FIXED0=readMSR(IA32_VMX_CR0_FIXED0_MSR);
|
|
IA32_VMX_CR0_FIXED1=readMSR(IA32_VMX_CR0_FIXED1_MSR);
|
|
IA32_VMX_CR4_FIXED0=readMSR(IA32_VMX_CR4_FIXED0_MSR);
|
|
IA32_VMX_CR4_FIXED1=readMSR(IA32_VMX_CR4_FIXED1_MSR);
|
|
|
|
|
|
sendstring("Setting CR4\n\r");
|
|
|
|
|
|
setCR4(getCR4() | CR4_VMXE);
|
|
|
|
if (currentcpuinfo->vmxon_region==NULL)
|
|
currentcpuinfo->vmxon_region=malloc(4096);
|
|
|
|
sendstringf("Allocated vmxon_region at %6 (%6)\n\r",(UINT64)currentcpuinfo->vmxon_region,(UINT64)VirtualToPhysical(currentcpuinfo->vmxon_region));
|
|
|
|
if (currentcpuinfo->vmxon_region==NULL)
|
|
{
|
|
sendstringf(">>>>>>>>>>>>>>>>>>>>vmxon allocation has failed<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
|
|
while (1);
|
|
}
|
|
|
|
zeromemory(currentcpuinfo->vmxon_region,4096);
|
|
*(ULONG *)currentcpuinfo->vmxon_region=IA32_VMX_BASIC.rev_id;
|
|
|
|
if (currentcpuinfo->vmcs_region==NULL)
|
|
currentcpuinfo->vmcs_region=malloc(4096);
|
|
|
|
sendstringf("Allocated vmcs_region at %6 (%6)\n\r",currentcpuinfo->vmcs_region,VirtualToPhysical(currentcpuinfo->vmcs_region));
|
|
|
|
if (currentcpuinfo->vmcs_region==NULL)
|
|
{
|
|
sendstringf(">>>>>>>>>>>>>>>>>>>>vmcs_region allocation has failed<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
|
|
while (1);
|
|
}
|
|
|
|
|
|
|
|
zeromemory(currentcpuinfo->vmcs_region,4096);
|
|
*(ULONG *)currentcpuinfo->vmcs_region=IA32_VMX_BASIC.rev_id;
|
|
|
|
currentcpuinfo->vmcs_regionPA=VirtualToPhysical(currentcpuinfo->vmcs_region);
|
|
|
|
displayline("revision id=%d\n\r",IA32_VMX_BASIC.rev_id);
|
|
|
|
displayline("IA32_FEATURE_CONTROL=%6\n\r",IA32_FEATURE_CONTROL);
|
|
displayline("IA32_VMX_CR0_FIXED0=%6 IA32_VMX_CR0_FIXED1=%6\n\r",IA32_VMX_CR0_FIXED0,IA32_VMX_CR0_FIXED1);
|
|
displayline("IA32_VMX_CR4_FIXED0=%6 IA32_VMX_CR4_FIXED1=%6\n\r",IA32_VMX_CR4_FIXED0,IA32_VMX_CR4_FIXED1);
|
|
|
|
|
|
displayline("CR0=%6 (Should be %6)\n\r",(UINT64)getCR0(),((UINT64)getCR0() | (UINT64)IA32_VMX_CR0_FIXED0) & (UINT64)IA32_VMX_CR0_FIXED1);
|
|
displayline("CR4=%6 (Should be %6)\n\r",(UINT64)getCR4(),((UINT64)getCR4() | (UINT64)IA32_VMX_CR4_FIXED0) & (UINT64)IA32_VMX_CR4_FIXED1);
|
|
|
|
setCR0(((UINT64)getCR0() | (UINT64)IA32_VMX_CR0_FIXED0) & (UINT64)IA32_VMX_CR0_FIXED1);
|
|
setCR4(((UINT64)getCR4() | (UINT64)IA32_VMX_CR4_FIXED0) & (UINT64)IA32_VMX_CR4_FIXED1);
|
|
|
|
|
|
displayline("vmxon_region=%6\n\r",VirtualToPhysical(currentcpuinfo->vmxon_region));
|
|
|
|
displayline("%d:Checks successfull. Going to call vmxon\n",currentcpuinfo->cpunr);
|
|
|
|
if (vmxon(VirtualToPhysical(currentcpuinfo->vmxon_region))==0)
|
|
{
|
|
sendstring("vmxon success\n\r");
|
|
displayline("%d: vmxon success\n",currentcpuinfo->cpunr);
|
|
|
|
displayline("%d: calling vmclear\n",currentcpuinfo->cpunr);
|
|
|
|
if (vmclear(VirtualToPhysical(currentcpuinfo->vmcs_region))==0)
|
|
{
|
|
displayline("%d: calling vmptrld\n",currentcpuinfo->cpunr);
|
|
|
|
if (vmptrld(VirtualToPhysical(currentcpuinfo->vmcs_region))==0)
|
|
{
|
|
|
|
displayline("%d: vmptrld successful. Calling setupVMX\n", currentcpuinfo->cpunr);
|
|
|
|
sendstringf("%d: Calling setupVMX with currentcpuinfo %6\n\r",currentcpuinfo->cpunr ,(UINT64)currentcpuinfo);
|
|
setupVMX(currentcpuinfo);
|
|
|
|
displayline("%d: Virtual Machine configuration successful. Launching...\n",currentcpuinfo->cpunr);
|
|
|
|
|
|
/*if (currentcpuinfo->cpunr==0)
|
|
while (1);*/
|
|
|
|
if (!isAP)
|
|
clearScreen();
|
|
|
|
//vmptrld(VirtualToPhysical(currentcpuinfo->vmcs_region));
|
|
// vmptrld(VirtualToPhysical(currentcpuinfo->vmcs_region));
|
|
//vmptrld(VirtualToPhysical(currentcpuinfo->vmcs_region));
|
|
|
|
launchVMX(currentcpuinfo);
|
|
|
|
displayline("Exit from launchVMX, if you see this, something horrible has happened\n");
|
|
sendstring("Exit from launchVMX\n\r");
|
|
|
|
}
|
|
else
|
|
{
|
|
sendstring("vmptrld failed\n\r");
|
|
|
|
displayline("vmptrld failure:");
|
|
displayline(getVMInstructionErrorString());
|
|
displayline(" \n");
|
|
|
|
|
|
}
|
|
}
|
|
else
|
|
{
|
|
sendstring("vmclear failed\n\r");
|
|
|
|
|
|
displayline("vmclear failure:");
|
|
displayline(getVMInstructionErrorString());
|
|
displayline(" \n");
|
|
|
|
}
|
|
sendstringf("Calling vmxoff() (rsp=%x)\n\r", getRSP());
|
|
|
|
vmxoff();
|
|
sendstring("still here so vmxoff succeeded\n\r");
|
|
|
|
}
|
|
else
|
|
{
|
|
displayline("vmxon failure\n");
|
|
sendstring("vmxon failed\n\r");
|
|
}
|
|
|
|
|
|
|
|
}
|
|
else
|
|
{
|
|
displayline("Fatal error: Your system does not support intel-VT!!!!\n");
|
|
displayline("Remove the disk, reboot, and go look for a better cpu\n");
|
|
sendstring("!!!!!!!!!!!!!!Your system is crap, it does NOT support VMX!!!!!!!!!!!!!!\n\r");
|
|
sendstringf("cpuid(1):\n");
|
|
sendstringf("EAX=%8\n", a);
|
|
sendstringf("EBX=%8\n", b);
|
|
sendstringf("ECX=%8\n", c);
|
|
sendstringf("EDX=%8\n", d);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
else
|
|
{
|
|
sendstring("This fucking retarded system doesn'\t even have cpuid. Should I fry it ?\n\r");
|
|
displayline("Your system doesn\'t even support CPUID, therefore it probably won\'t support Virtualization either\n");
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
sendstringf("End of startvmx (entryrsp=%6, returnrsp=%6)\n\r",entryrsp,getRSP());
|
|
#endif
|
|
|
|
if (currentcpuinfo->cpunr==0)
|
|
displayline("bye...\n");
|
|
}
|