mirror of
https://github.com/daeken/Zookeeper.git
synced 2024-05-14 19:09:33 -04:00
Abstracted away hypervisor interface.
This commit is contained in:
parent
2872766a5b
commit
a9cc9c018d
469
Cpu.cpp
469
Cpu.cpp
|
@ -24,31 +24,10 @@ Cpu::Cpu(uint8_t *ram, uint8_t *kram) {
|
|||
mem = ram;
|
||||
kmem = kram;
|
||||
|
||||
bailout(hv_vm_create(HV_VM_DEFAULT));
|
||||
hv = new HVImpl();
|
||||
memset(mem, 0, RAM_SIZE);
|
||||
bailout(hv_vm_map(mem, 0, RAM_SIZE, HV_MEMORY_READ | HV_MEMORY_WRITE | HV_MEMORY_EXEC));
|
||||
bailout(hv_vm_map(kmem, 0xc0000000, KRAM_SIZE, HV_MEMORY_READ | HV_MEMORY_WRITE | HV_MEMORY_EXEC));
|
||||
bailout(hv_vcpu_create(&vcpu, HV_VCPU_DEFAULT));
|
||||
|
||||
uint64_t vmx_cap_pinbased, vmx_cap_procbased, vmx_cap_procbased2, vmx_cap_entry;
|
||||
bailout(hv_vmx_read_capability(HV_VMX_CAP_PINBASED, &vmx_cap_pinbased));
|
||||
bailout(hv_vmx_read_capability(HV_VMX_CAP_PROCBASED, &vmx_cap_procbased));
|
||||
bailout(hv_vmx_read_capability(HV_VMX_CAP_PROCBASED2, &vmx_cap_procbased2));
|
||||
bailout(hv_vmx_read_capability(HV_VMX_CAP_ENTRY, &vmx_cap_entry));
|
||||
|
||||
wvmcs(VMCS_CTRL_PIN_BASED, cap2ctrl(vmx_cap_pinbased, 0));
|
||||
wvmcs(VMCS_CTRL_CPU_BASED, cap2ctrl(
|
||||
vmx_cap_procbased,
|
||||
VMCS_PRI_PROC_BASED_CTLS_HLT |
|
||||
VMCS_PRI_PROC_BASED_CTLS_CR8_LOAD |
|
||||
VMCS_PRI_PROC_BASED_CTLS_CR8_STORE));
|
||||
wvmcs(VMCS_CTRL_CPU_BASED2, cap2ctrl(vmx_cap_procbased2, 0));
|
||||
wvmcs(VMCS_CTRL_VMENTRY_CONTROLS, cap2ctrl(vmx_cap_entry, 0));
|
||||
wvmcs(VMCS_CTRL_EXC_BITMAP, 0xffffffff);
|
||||
wvmcs(VMCS_CTRL_CR0_MASK, 0xffffffff);
|
||||
wvmcs(VMCS_CTRL_CR0_SHADOW, 0xffffffff);
|
||||
wvmcs(VMCS_CTRL_CR4_MASK, 0xffffffff);
|
||||
wvmcs(VMCS_CTRL_CR4_SHADOW, 0xffffffff);
|
||||
hv->map_phys(mem, 0x00000000, RAM_SIZE);
|
||||
hv->map_phys(kmem, 0xc0000000, KRAM_SIZE);
|
||||
|
||||
auto directory = 64*1024*1024; // Page directory base
|
||||
auto dir = (uint32_t *) (mem + directory);
|
||||
|
@ -59,59 +38,19 @@ Cpu::Cpu(uint8_t *ram, uint8_t *kram) {
|
|||
table[j] = 0x0;
|
||||
}
|
||||
}
|
||||
wvmcs(VMCS_GUEST_CR3, directory);
|
||||
wvmcs(VMCS_GUEST_CR0, 0x80000000 | 0x20 | 0x01); // Paging | NE | PE
|
||||
hv->reg(CR3, directory);
|
||||
hv->reg(CR0, 0x80000000 | 0x20 | 0x01); // Paging | NE | PE
|
||||
|
||||
auto gdt = ram + 96*1024*1024;
|
||||
memset(gdt, 0, 0x10000);
|
||||
gdt_encode(gdt, 0, 0, 0, 0); // Null entry
|
||||
gdt_encode(gdt, 1, 0, 0xffffffff, 0x9A); // Code
|
||||
gdt_encode(gdt, 2, 0, 0xffffffff, 0x92); // Data
|
||||
wvmcs(VMCS_GUEST_GDTR_LIMIT, 0xFFFF);
|
||||
wvmcs(VMCS_GUEST_GDTR_BASE, 96*1024*1024);
|
||||
hv->reg(GDT_LIMIT, 0xFFFF);
|
||||
hv->reg(GDT_BASE, 96*1024*1024);
|
||||
map_pages(96 * 1024 * 1024, 96 * 1024 * 1024, 16);
|
||||
|
||||
wvmcs(VMCS_GUEST_CS, 1 << 3);
|
||||
wvmcs(VMCS_GUEST_CS_AR, 0xc093);
|
||||
wvmcs(VMCS_GUEST_CS_LIMIT, 0xffffffff);
|
||||
wvmcs(VMCS_GUEST_CS_BASE, 0x0);
|
||||
|
||||
wvmcs(VMCS_GUEST_DS, 2 << 3);
|
||||
wvmcs(VMCS_GUEST_DS_AR, 0xc093);
|
||||
wvmcs(VMCS_GUEST_DS_LIMIT, 0xffffffff);
|
||||
wvmcs(VMCS_GUEST_DS_BASE, 0);
|
||||
|
||||
wvmcs(VMCS_GUEST_ES, 2 << 3);
|
||||
wvmcs(VMCS_GUEST_ES_AR, 0xc093);
|
||||
wvmcs(VMCS_GUEST_ES_LIMIT, 0xffffffff);
|
||||
wvmcs(VMCS_GUEST_ES_BASE, 0);
|
||||
|
||||
wvmcs(VMCS_GUEST_FS, 2 << 3);
|
||||
wvmcs(VMCS_GUEST_FS_AR, 0xc093);
|
||||
wvmcs(VMCS_GUEST_FS_LIMIT, 0xffffffff);
|
||||
wvmcs(VMCS_GUEST_FS_BASE, 0);
|
||||
|
||||
wvmcs(VMCS_GUEST_GS, 2 << 3);
|
||||
wvmcs(VMCS_GUEST_GS_AR, 0xc093);
|
||||
wvmcs(VMCS_GUEST_GS_LIMIT, 0xffffffff);
|
||||
wvmcs(VMCS_GUEST_GS_BASE, 0);
|
||||
|
||||
wvmcs(VMCS_GUEST_SS, 2 << 3);
|
||||
wvmcs(VMCS_GUEST_SS_AR, 0xc093);
|
||||
wvmcs(VMCS_GUEST_SS_LIMIT, 0xffffffff);
|
||||
wvmcs(VMCS_GUEST_SS_BASE, 0);
|
||||
|
||||
wvmcs(VMCS_GUEST_LDTR, 0);
|
||||
wvmcs(VMCS_GUEST_LDTR_LIMIT, 0);
|
||||
wvmcs(VMCS_GUEST_LDTR_AR, 0x10000);
|
||||
wvmcs(VMCS_GUEST_LDTR_BASE, 0);
|
||||
|
||||
wvmcs(VMCS_GUEST_TR, 0);
|
||||
wvmcs(VMCS_GUEST_TR_LIMIT, 0);
|
||||
wvmcs(VMCS_GUEST_TR_AR, 0x83);
|
||||
wvmcs(VMCS_GUEST_TR_BASE, 0);
|
||||
|
||||
wvmcs(VMCS_GUEST_CR4, 0x2000);
|
||||
hv->reg(CR4, 0x2000);
|
||||
}
|
||||
|
||||
void Cpu::map_pages(uint32_t virt, uint32_t phys, uint32_t count) {
|
||||
|
@ -122,15 +61,11 @@ void Cpu::map_pages(uint32_t virt, uint32_t phys, uint32_t count) {
|
|||
virt += 4096;
|
||||
phys += 4096;
|
||||
}
|
||||
invalidate_tlb();
|
||||
}
|
||||
|
||||
void Cpu::invalidate_tlb() {
|
||||
hv_vcpu_invalidate_tlb(vcpu);
|
||||
hv->invalidate_tlb(); // Do we really need to do this all the time?
|
||||
}
|
||||
|
||||
uint32_t Cpu::virt2phys(uint32_t addr) {
|
||||
auto cr3 = rreg(HV_X86_CR3);
|
||||
auto cr3 = hv->reg(CR3);
|
||||
if(cr3 == 0)
|
||||
return addr;
|
||||
|
||||
|
@ -140,7 +75,7 @@ uint32_t Cpu::virt2phys(uint32_t addr) {
|
|||
}
|
||||
|
||||
bool Cpu::is_mapped(uint32_t addr) {
|
||||
auto cr3 = rreg(HV_X86_CR3);
|
||||
auto cr3 = hv->reg(CR3);
|
||||
if(cr3 == 0)
|
||||
return true;
|
||||
|
||||
|
@ -150,7 +85,7 @@ bool Cpu::is_mapped(uint32_t addr) {
|
|||
}
|
||||
|
||||
void Cpu::read_memory(uint32_t addr, uint32_t size, void *buffer) {
|
||||
auto cr3 = rreg(HV_X86_CR3);
|
||||
auto cr3 = hv->reg(CR3);
|
||||
if(cr3 == 0) {
|
||||
if(addr >= 0xc0000000)
|
||||
memcpy(buffer, &kmem[addr - 0xc0000000], size);
|
||||
|
@ -172,7 +107,7 @@ void Cpu::read_memory(uint32_t addr, uint32_t size, void *buffer) {
|
|||
}
|
||||
|
||||
void Cpu::write_memory(uint32_t addr, uint32_t size, void *buffer) {
|
||||
auto cr3 = rreg(HV_X86_CR3);
|
||||
auto cr3 = hv->reg(CR3);
|
||||
if(cr3 == 0) {
|
||||
if(addr >= 0xc0000000)
|
||||
memcpy(&kmem[addr - 0xc0000000], buffer, size);
|
||||
|
@ -193,26 +128,8 @@ void Cpu::write_memory(uint32_t addr, uint32_t size, void *buffer) {
|
|||
}
|
||||
}
|
||||
|
||||
uint64_t Cpu::rdmsr(uint32_t msr) {
|
||||
switch(msr) {
|
||||
default:
|
||||
cout << "Unknown MSR being read: " << hex << msr << endl;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Cpu::wrmsr(uint32_t msr, uint64_t val) {
|
||||
switch(msr) {
|
||||
default:
|
||||
cout << "Unknown MSR being written: " << hex << msr << " == 0x" << hex << val << endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Cpu::~Cpu() {
|
||||
bailout(hv_vcpu_destroy(vcpu));
|
||||
bailout(hv_vm_unmap(0, RAM_SIZE));
|
||||
bailout(hv_vm_destroy());
|
||||
delete hv;
|
||||
}
|
||||
|
||||
#define TASK_TIMER 20 // Milliseconds
|
||||
|
@ -224,202 +141,9 @@ uint64_t systime() {
|
|||
return (time.tv_sec * 1000) + (time.tv_usec / 1000);
|
||||
}
|
||||
|
||||
void log_exit_reason(uint32_t reason, uint32_t eip) {
|
||||
if(reason & 0x80000000) {
|
||||
reason &= 0x7FFFFFFF;
|
||||
cout << "Entry failed: ";
|
||||
} else
|
||||
cout << "Exit ";
|
||||
switch(reason) {
|
||||
case VMX_REASON_EXC_NMI:
|
||||
cout << "VMX_REASON_EXC_NMI";
|
||||
break;
|
||||
case VMX_REASON_IRQ:
|
||||
cout << "VMX_REASON_IRQ";
|
||||
break;
|
||||
case VMX_REASON_TRIPLE_FAULT:
|
||||
cout << "VMX_REASON_TRIPLE_FAULT";
|
||||
break;
|
||||
case VMX_REASON_INIT:
|
||||
cout << "VMX_REASON_INIT";
|
||||
break;
|
||||
case VMX_REASON_SIPI:
|
||||
cout << "VMX_REASON_SIPI";
|
||||
break;
|
||||
case VMX_REASON_IO_SMI:
|
||||
cout << "VMX_REASON_IO_SMI";
|
||||
break;
|
||||
case VMX_REASON_OTHER_SMI:
|
||||
cout << "VMX_REASON_OTHER_SMI";
|
||||
break;
|
||||
case VMX_REASON_IRQ_WND:
|
||||
cout << "VMX_REASON_IRQ_WND";
|
||||
break;
|
||||
case VMX_REASON_VIRTUAL_NMI_WND:
|
||||
cout << "VMX_REASON_VIRTUAL_NMI_WND";
|
||||
break;
|
||||
case VMX_REASON_TASK:
|
||||
cout << "VMX_REASON_TASK";
|
||||
break;
|
||||
case VMX_REASON_CPUID:
|
||||
cout << "VMX_REASON_CPUID";
|
||||
break;
|
||||
case VMX_REASON_GETSEC:
|
||||
cout << "VMX_REASON_GETSEC";
|
||||
break;
|
||||
case VMX_REASON_HLT:
|
||||
cout << "VMX_REASON_HLT";
|
||||
break;
|
||||
case VMX_REASON_INVD:
|
||||
cout << "VMX_REASON_INVD";
|
||||
break;
|
||||
case VMX_REASON_INVLPG:
|
||||
cout << "VMX_REASON_INVLPG";
|
||||
break;
|
||||
case VMX_REASON_RDPMC:
|
||||
cout << "VMX_REASON_RDPMC";
|
||||
break;
|
||||
case VMX_REASON_RDTSC:
|
||||
cout << "VMX_REASON_RDTSC";
|
||||
break;
|
||||
case VMX_REASON_RSM:
|
||||
cout << "VMX_REASON_RSM";
|
||||
break;
|
||||
case VMX_REASON_VMCALL:
|
||||
cout << "VMX_REASON_VMCALL";
|
||||
break;
|
||||
case VMX_REASON_VMCLEAR:
|
||||
cout << "VMX_REASON_VMCLEAR";
|
||||
break;
|
||||
case VMX_REASON_VMLAUNCH:
|
||||
cout << "VMX_REASON_VMLAUNCH";
|
||||
break;
|
||||
case VMX_REASON_VMPTRLD:
|
||||
cout << "VMX_REASON_VMPTRLD";
|
||||
break;
|
||||
case VMX_REASON_VMPTRST:
|
||||
cout << "VMX_REASON_VMPTRST";
|
||||
break;
|
||||
case VMX_REASON_VMREAD:
|
||||
cout << "VMX_REASON_VMREAD";
|
||||
break;
|
||||
case VMX_REASON_VMRESUME:
|
||||
cout << "VMX_REASON_VMRESUME";
|
||||
break;
|
||||
case VMX_REASON_VMWRITE:
|
||||
cout << "VMX_REASON_VMWRITE";
|
||||
break;
|
||||
case VMX_REASON_VMOFF:
|
||||
cout << "VMX_REASON_VMOFF";
|
||||
break;
|
||||
case VMX_REASON_VMON:
|
||||
cout << "VMX_REASON_VMON";
|
||||
break;
|
||||
case VMX_REASON_MOV_CR:
|
||||
cout << "VMX_REASON_MOV_CR";
|
||||
break;
|
||||
case VMX_REASON_MOV_DR:
|
||||
cout << "VMX_REASON_MOV_DR";
|
||||
break;
|
||||
case VMX_REASON_IO:
|
||||
cout << "VMX_REASON_IO";
|
||||
break;
|
||||
case VMX_REASON_RDMSR:
|
||||
cout << "VMX_REASON_RDMSR";
|
||||
break;
|
||||
case VMX_REASON_WRMSR:
|
||||
cout << "VMX_REASON_WRMSR";
|
||||
break;
|
||||
case VMX_REASON_VMENTRY_GUEST:
|
||||
cout << "VMX_REASON_VMENTRY_GUEST";
|
||||
break;
|
||||
case VMX_REASON_VMENTRY_MSR:
|
||||
cout << "VMX_REASON_VMENTRY_MSR";
|
||||
break;
|
||||
case VMX_REASON_MWAIT:
|
||||
cout << "VMX_REASON_MWAIT";
|
||||
break;
|
||||
case VMX_REASON_MTF:
|
||||
cout << "VMX_REASON_MTF";
|
||||
break;
|
||||
case VMX_REASON_MONITOR:
|
||||
cout << "VMX_REASON_MONITOR";
|
||||
break;
|
||||
case VMX_REASON_PAUSE:
|
||||
cout << "VMX_REASON_PAUSE";
|
||||
break;
|
||||
case VMX_REASON_VMENTRY_MC:
|
||||
cout << "VMX_REASON_VMENTRY_MC";
|
||||
break;
|
||||
case VMX_REASON_TPR_THRESHOLD:
|
||||
cout << "VMX_REASON_TPR_THRESHOLD";
|
||||
break;
|
||||
case VMX_REASON_APIC_ACCESS:
|
||||
cout << "VMX_REASON_APIC_ACCESS";
|
||||
break;
|
||||
case VMX_REASON_VIRTUALIZED_EOI:
|
||||
cout << "VMX_REASON_VIRTUALIZED_EOI";
|
||||
break;
|
||||
case VMX_REASON_GDTR_IDTR:
|
||||
cout << "VMX_REASON_GDTR_IDTR";
|
||||
break;
|
||||
case VMX_REASON_LDTR_TR:
|
||||
cout << "VMX_REASON_LDTR_TR";
|
||||
break;
|
||||
case VMX_REASON_EPT_VIOLATION:
|
||||
cout << "VMX_REASON_EPT_VIOLATION";
|
||||
break;
|
||||
case VMX_REASON_EPT_MISCONFIG:
|
||||
cout << "VMX_REASON_EPT_MISCONFIG";
|
||||
break;
|
||||
case VMX_REASON_EPT_INVEPT:
|
||||
cout << "VMX_REASON_EPT_INVEPT";
|
||||
break;
|
||||
case VMX_REASON_RDTSCP:
|
||||
cout << "VMX_REASON_RDTSCP";
|
||||
break;
|
||||
case VMX_REASON_VMX_TIMER_EXPIRED:
|
||||
cout << "VMX_REASON_VMX_TIMER_EXPIRED";
|
||||
break;
|
||||
case VMX_REASON_INVVPID:
|
||||
cout << "VMX_REASON_INVVPID";
|
||||
break;
|
||||
case VMX_REASON_WBINVD:
|
||||
cout << "VMX_REASON_WBINVD";
|
||||
break;
|
||||
case VMX_REASON_XSETBV:
|
||||
cout << "VMX_REASON_XSETBV";
|
||||
break;
|
||||
case VMX_REASON_APIC_WRITE:
|
||||
cout << "VMX_REASON_APIC_WRITE";
|
||||
break;
|
||||
case VMX_REASON_RDRAND:
|
||||
cout << "VMX_REASON_RDRAND";
|
||||
break;
|
||||
case VMX_REASON_INVPCID:
|
||||
cout << "VMX_REASON_INVPCID";
|
||||
break;
|
||||
case VMX_REASON_VMFUNC:
|
||||
cout << "VMX_REASON_VMFUNC";
|
||||
break;
|
||||
case VMX_REASON_RDSEED:
|
||||
cout << "VMX_REASON_RDSEED";
|
||||
break;
|
||||
case VMX_REASON_XSAVES:
|
||||
cout << "VMX_REASON_XSAVES";
|
||||
break;
|
||||
case VMX_REASON_XRSTORS:
|
||||
cout << "VMX_REASON_XRSTORS";
|
||||
break;
|
||||
default:
|
||||
cout << "Unknown reason: " << dec << reason;
|
||||
}
|
||||
cout << " @ " << hex << eip << endl;
|
||||
}
|
||||
|
||||
void Cpu::run(uint32_t eip) {
|
||||
wreg(HV_X86_RIP, eip);
|
||||
wreg(HV_X86_RFLAGS, 0x2);
|
||||
hv->reg(EIP, eip);
|
||||
hv->reg(EFLAGS, 0x2);
|
||||
|
||||
box->debugger->enter(0);
|
||||
|
||||
|
@ -427,113 +151,74 @@ void Cpu::run(uint32_t eip) {
|
|||
|
||||
auto swap = true;
|
||||
do {
|
||||
bailout(hv_vcpu_run(vcpu));
|
||||
auto exit = hv->enter();
|
||||
|
||||
auto exit_reason = rvmcs(VMCS_RO_EXIT_REASON);
|
||||
|
||||
if(exit_reason & 0x80000000) {
|
||||
cout << "Entry failed? " << dec << (exit_reason & 0x7FFFFFFF) << endl;
|
||||
stop = true;
|
||||
} else
|
||||
switch (exit_reason) {
|
||||
case VMX_REASON_EXC_NMI: {
|
||||
auto vec_val = rvmcs(VMCS_RO_VMEXIT_IRQ_INFO) & 0xFFFF;
|
||||
switch((vec_val >> 8) & 7) {
|
||||
case 6: { // Interrupt
|
||||
if((vec_val & 0xFF) == 3) {
|
||||
box->debugger->enter();
|
||||
} else {
|
||||
cout << "Unknown interrupt. " << dec << (vec_val & 0xFF) << endl;
|
||||
box->debugger->enter();
|
||||
exit(0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 3: { // Exception
|
||||
switch(vec_val & 0xFF) {
|
||||
case 1: { // Single step
|
||||
auto flags = rreg(HV_X86_RFLAGS);
|
||||
wreg(HV_X86_RFLAGS, flags & ~(1 << 8));
|
||||
if(single_step == 2) { // Requested
|
||||
single_step = 0;
|
||||
box->debugger->enter();
|
||||
}
|
||||
else
|
||||
box->debugger->reenable();
|
||||
swap = true;
|
||||
break;
|
||||
}
|
||||
case 6: {
|
||||
cout << "Invalid opcode" << endl;
|
||||
box->debugger->enter();
|
||||
break;
|
||||
}
|
||||
case 14: {
|
||||
cout << format("Page fault reading %08x") % rvmcs(VMCS_RO_EXIT_QUALIFIC) << endl;
|
||||
box->debugger->enter();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
cout << "Unknown exception. " << dec << (vec_val & 0xFF) << endl;
|
||||
box->debugger->enter();
|
||||
exit(0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
cout << "Unknown NMI class. " << hex << vec_val << endl;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case VMX_REASON_VMCALL: {
|
||||
wreg(HV_X86_RIP, rreg(HV_X86_RIP) + 3);
|
||||
hypercall_dispatch(rreg(HV_X86_RAX), rreg(HV_X86_RDX));
|
||||
break;
|
||||
}
|
||||
case VMX_REASON_IRQ:
|
||||
break;
|
||||
case VMX_REASON_TRIPLE_FAULT:
|
||||
cout << "Triple fault!" << endl;
|
||||
cout << "IDTR Base " << hex << rreg(HV_X86_IDT_BASE) << " " << hex << rvmcs(VMCS_GUEST_IDTR_BASE) << endl;
|
||||
cout << "IDTR Limit " << hex << rreg(HV_X86_IDT_LIMIT) << endl;
|
||||
cout << "ISR 0 == " << hex << read_memory<uint64_t>(rvmcs(VMCS_GUEST_IDTR_BASE)) << endl;
|
||||
cout << "ISR 7 == " << hex << read_memory<uint64_t>(rvmcs(VMCS_GUEST_IDTR_BASE) + 8 * 7) << endl;
|
||||
stop = 1;
|
||||
break;
|
||||
case VMX_REASON_RDMSR: {
|
||||
auto msr = 0L;
|
||||
cout << "RDMSR " << hex << rreg(HV_X86_RCX);
|
||||
msr = rdmsr(rreg(HV_X86_RCX));
|
||||
cout << " == 0x" << hex << msr << endl;
|
||||
wreg(HV_X86_RIP, rreg(HV_X86_RIP) + 2);
|
||||
wreg(HV_X86_RAX, msr & 0xFFFFFFFF);
|
||||
wreg(HV_X86_RDX, msr >> 32);
|
||||
break;
|
||||
}
|
||||
case VMX_REASON_WRMSR: {
|
||||
auto msr = ((uint64_t) rreg(HV_X86_RDX) << 32) | (uint64_t) rreg(HV_X86_RAX);
|
||||
cout << "WRMSR " << hex << rreg(HV_X86_RCX) << " == 0x" << hex << msr << endl;
|
||||
wrmsr(rreg(HV_X86_RCX), msr);
|
||||
wreg(HV_X86_RIP, rreg(HV_X86_RIP) + 2);
|
||||
break;
|
||||
}
|
||||
case VMX_REASON_HLT:
|
||||
cout << "HLT" << endl;
|
||||
stop = true;
|
||||
break;
|
||||
case VMX_REASON_EPT_VIOLATION:
|
||||
// cout << "EPT_VIOLATION" << endl;
|
||||
break;
|
||||
default:
|
||||
cout << "Unhandled VM exit: " << dec << exit_reason << endl;
|
||||
switch (exit.reason) {
|
||||
case Interrupt: {
|
||||
if(exit.interrupt_no == 3) {
|
||||
box->debugger->enter();
|
||||
} else {
|
||||
cout << "Unknown interrupt. " << dec << exit.interrupt_no << endl;
|
||||
box->debugger->enter();
|
||||
stop = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Exception: {
|
||||
switch(exit.interrupt_no) {
|
||||
case 1: { // Single step
|
||||
auto flags = hv->reg(EFLAGS);
|
||||
hv->reg(EFLAGS, flags & ~(1 << 8));
|
||||
if(single_step == 2) { // Requested
|
||||
single_step = 0;
|
||||
box->debugger->enter();
|
||||
}
|
||||
else
|
||||
box->debugger->reenable();
|
||||
swap = true;
|
||||
break;
|
||||
}
|
||||
case 6: {
|
||||
cout << "Invalid opcode" << endl;
|
||||
stop = true;
|
||||
break;
|
||||
}
|
||||
case 14: {
|
||||
cout << format("Page fault reading %08x") % exit.address << endl;
|
||||
stop = true;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
cout << "Unknown exception. " << dec << exit.interrupt_no << endl;
|
||||
stop = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case VmCall: {
|
||||
hv->reg(EIP, hv->reg(EIP) + 3);
|
||||
hypercall_dispatch(hv->reg(EAX), hv->reg(EDX));
|
||||
break;
|
||||
}
|
||||
case TripleFault:
|
||||
cout << "Triple fault!" << endl;
|
||||
stop = true;
|
||||
break;
|
||||
case Hlt:
|
||||
cout << "HLT" << endl;
|
||||
stop = true;
|
||||
break;
|
||||
case Ignore:
|
||||
break;
|
||||
default:
|
||||
stop = true;
|
||||
}
|
||||
|
||||
if(single_step) {
|
||||
if(single_step == 1)
|
||||
single_step = 0;
|
||||
auto flags = rreg(HV_X86_RFLAGS);
|
||||
wreg(HV_X86_RFLAGS, flags | (1 << 8));
|
||||
auto flags = hv->reg(EFLAGS);
|
||||
hv->reg(EFLAGS, flags | (1 << 8));
|
||||
swap = false;
|
||||
}
|
||||
|
||||
|
|
33
Cpu.hpp
33
Cpu.hpp
|
@ -2,11 +2,6 @@
|
|||
|
||||
#include "Zookeeper.hpp"
|
||||
|
||||
#define cap2ctrl(cap, ctrl) ((ctrl) | ((cap) & 0xffffffff)) & ((cap) >> 32)
|
||||
#define VMCS_PRI_PROC_BASED_CTLS_HLT (1 << 7)
|
||||
#define VMCS_PRI_PROC_BASED_CTLS_CR8_LOAD (1 << 19)
|
||||
#define VMCS_PRI_PROC_BASED_CTLS_CR8_STORE (1 << 20)
|
||||
|
||||
class Cpu {
|
||||
public:
|
||||
Cpu(uint8_t *ram, uint8_t *kram);
|
||||
|
@ -28,33 +23,11 @@ public:
|
|||
write_memory(addr, sizeof(T), &value);
|
||||
}
|
||||
|
||||
void invalidate_tlb();
|
||||
|
||||
uint64_t rdmsr(uint32_t msr);
|
||||
void wrmsr(uint32_t msr, uint64_t val);
|
||||
|
||||
/* read GPR */
|
||||
uint32_t rreg(hv_x86_reg_t reg) {
|
||||
uint64_t v;
|
||||
bailout(hv_vcpu_read_register(vcpu, reg, &v));
|
||||
return (uint32_t) v;
|
||||
}
|
||||
/* write GPR */
|
||||
void wreg(hv_x86_reg_t reg, uint32_t v) {
|
||||
bailout(hv_vcpu_write_register(vcpu, reg, (uint32_t) v));
|
||||
}
|
||||
/* read VMCS field */
|
||||
uint64_t rvmcs(uint32_t field) {
|
||||
uint64_t v;
|
||||
bailout(hv_vmx_vcpu_read_vmcs(vcpu, field, &v));
|
||||
return v;
|
||||
}
|
||||
/* write VMCS field */
|
||||
void wvmcs(uint32_t field, uint64_t v) {
|
||||
bailout(hv_vmx_vcpu_write_vmcs(vcpu, field, v));
|
||||
void invalidate_tlb() {
|
||||
hv->invalidate_tlb();
|
||||
}
|
||||
|
||||
hv_vcpuid_t vcpu;
|
||||
HV *hv;
|
||||
uint8_t *mem, *kmem;
|
||||
int single_step = 0;
|
||||
bool stop = false;
|
||||
|
|
16
Debugger.cpp
16
Debugger.cpp
|
@ -28,7 +28,7 @@ Debugger::Debugger() {
|
|||
void Debugger::stack_trace() {
|
||||
cout << "Stack trace:" << endl;
|
||||
|
||||
auto ebp = box->cpu->rreg(HV_X86_RBP);
|
||||
auto ebp = box->cpu->hv->reg(EBP);
|
||||
for(auto i = 0; i < MAX_FRAMES; ++i) {
|
||||
if(ebp == 0)
|
||||
break;
|
||||
|
@ -42,13 +42,13 @@ void Debugger::stack_trace() {
|
|||
|
||||
#define MAX_LENGTH 20
|
||||
void Debugger::dump_stack() {
|
||||
auto esp = box->cpu->rreg(HV_X86_RSP);
|
||||
auto esp = box->cpu->hv->reg(ESP);
|
||||
for(auto i = 0; i < MAX_LENGTH; ++i)
|
||||
cout << format("%08x") % box->cpu->read_memory<uint32_t>(esp + i * 4) << endl;
|
||||
}
|
||||
|
||||
void Debugger::enter(uint32_t reason) {
|
||||
auto eip = box->cpu->rreg(HV_X86_RIP);
|
||||
auto eip = box->cpu->hv->reg(EIP);
|
||||
|
||||
if(breakpoints.find(eip) != breakpoints.end()) {
|
||||
cout << format("Hit breakpoint at 0x%08x") % eip << endl;
|
||||
|
@ -91,11 +91,11 @@ void Debugger::enter(uint32_t reason) {
|
|||
} else if(cmd == "stack") {
|
||||
dump_stack();
|
||||
} else if(cmd == "r" || cmd == "regs") {
|
||||
cout << format("eax %08x ebx %08x") % box->cpu->rreg(HV_X86_RAX) % box->cpu->rreg(HV_X86_RBX) << endl;
|
||||
cout << format("ecx %08x edx %08x") % box->cpu->rreg(HV_X86_RCX) % box->cpu->rreg(HV_X86_RDX) << endl;
|
||||
cout << format("edi %08x esi %08x") % box->cpu->rreg(HV_X86_RDI) % box->cpu->rreg(HV_X86_RSI) << endl;
|
||||
cout << format("ebp %08x esp %08x") % box->cpu->rreg(HV_X86_RBP) % box->cpu->rreg(HV_X86_RSP) << endl;
|
||||
cout << format("eflags %08x") % box->cpu->rreg(HV_X86_RFLAGS) << endl;
|
||||
cout << format("eax %08x ebx %08x") % box->cpu->hv->reg(EAX) % box->cpu->hv->reg(EBX) << endl;
|
||||
cout << format("ecx %08x edx %08x") % box->cpu->hv->reg(ECX) % box->cpu->hv->reg(EDX) << endl;
|
||||
cout << format("edi %08x esi %08x") % box->cpu->hv->reg(EDI) % box->cpu->hv->reg(ESI) << endl;
|
||||
cout << format("ebp %08x esp %08x") % box->cpu->hv->reg(EBP) % box->cpu->hv->reg(ESP) << endl;
|
||||
cout << format("eflags %08x") % box->cpu->hv->reg(EFLAGS) << endl;
|
||||
} else if(cmd == "rm" || cmd == "read") {
|
||||
string type = "u32";
|
||||
auto offset = 1;
|
||||
|
|
45
HV.hpp
Normal file
45
HV.hpp
Normal file
|
@ -0,0 +1,45 @@
|
|||
#pragma once
|
||||
#include "Zookeeper.hpp"
|
||||
|
||||
enum HVReg {
|
||||
EIP,
|
||||
EFLAGS,
|
||||
EAX, ECX, EDX, EBX,
|
||||
ESI, EDI, ESP, EBP,
|
||||
CS, SS, DS, ES, FS, GS,
|
||||
IDT_BASE, IDT_LIMIT,
|
||||
GDT_BASE, GDT_LIMIT,
|
||||
LDTR, LDT_BASE, LDT_LIMIT, LDT_AR,
|
||||
TR, TSS_BASE, TSS_LIMIT, TSS_AR,
|
||||
CR0, CR1, CR2, CR3, CR4,
|
||||
DR0, DR1, DR2, DR3, DR4, DR5, DR6, DR7,
|
||||
TPR, XCR0
|
||||
};
|
||||
|
||||
enum HVExitReason {
|
||||
Ignore,
|
||||
Unknown,
|
||||
EntryFailed,
|
||||
Interrupt,
|
||||
Exception,
|
||||
VmCall,
|
||||
TripleFault,
|
||||
Hlt
|
||||
};
|
||||
|
||||
typedef struct exit {
|
||||
HVExitReason reason;
|
||||
uint32_t instruction_length;
|
||||
uint32_t interrupt_no;
|
||||
uint32_t address; // Used for page faults
|
||||
} exit_t;
|
||||
|
||||
class HV {
|
||||
public:
|
||||
virtual ~HV() = 0;
|
||||
virtual void map_phys(void *memory, uint32_t base, uint32_t size) = 0;
|
||||
virtual void invalidate_tlb() = 0;
|
||||
virtual uint32_t reg(HVReg reg) = 0;
|
||||
virtual void reg(HVReg reg, uint32_t val) = 0;
|
||||
virtual exit_t enter() = 0;
|
||||
};
|
203
Mac/HVMac.cpp
Normal file
203
Mac/HVMac.cpp
Normal file
|
@ -0,0 +1,203 @@
|
|||
#include "Zookeeper.hpp"
|
||||
|
||||
HV::~HV() {} // This has to be defined, but there's no use in making a new cpp file.
|
||||
|
||||
#define cap2ctrl(cap, ctrl) ((ctrl) | ((cap) & 0xffffffff)) & ((cap) >> 32)
|
||||
#define VMCS_PRI_PROC_BASED_CTLS_HLT (1 << 7)
|
||||
#define VMCS_PRI_PROC_BASED_CTLS_CR8_LOAD (1 << 19)
|
||||
#define VMCS_PRI_PROC_BASED_CTLS_CR8_STORE (1 << 20)
|
||||
|
||||
HVMac::HVMac() {
|
||||
bailout(hv_vm_create(HV_VM_DEFAULT));
|
||||
bailout(hv_vcpu_create(&vcpu, HV_VCPU_DEFAULT));
|
||||
|
||||
uint64_t vmx_cap_pinbased, vmx_cap_procbased, vmx_cap_procbased2, vmx_cap_entry;
|
||||
bailout(hv_vmx_read_capability(HV_VMX_CAP_PINBASED, &vmx_cap_pinbased));
|
||||
bailout(hv_vmx_read_capability(HV_VMX_CAP_PROCBASED, &vmx_cap_procbased));
|
||||
bailout(hv_vmx_read_capability(HV_VMX_CAP_PROCBASED2, &vmx_cap_procbased2));
|
||||
bailout(hv_vmx_read_capability(HV_VMX_CAP_ENTRY, &vmx_cap_entry));
|
||||
|
||||
wvmcs(VMCS_CTRL_PIN_BASED, cap2ctrl(vmx_cap_pinbased, 0));
|
||||
wvmcs(VMCS_CTRL_CPU_BASED, cap2ctrl(
|
||||
vmx_cap_procbased,
|
||||
VMCS_PRI_PROC_BASED_CTLS_HLT |
|
||||
VMCS_PRI_PROC_BASED_CTLS_CR8_LOAD |
|
||||
VMCS_PRI_PROC_BASED_CTLS_CR8_STORE));
|
||||
wvmcs(VMCS_CTRL_CPU_BASED2, cap2ctrl(vmx_cap_procbased2, 0));
|
||||
wvmcs(VMCS_CTRL_VMENTRY_CONTROLS, cap2ctrl(vmx_cap_entry, 0));
|
||||
wvmcs(VMCS_CTRL_EXC_BITMAP, 0xffffffff);
|
||||
wvmcs(VMCS_CTRL_CR0_MASK, 0xffffffff);
|
||||
wvmcs(VMCS_CTRL_CR0_SHADOW, 0xffffffff);
|
||||
wvmcs(VMCS_CTRL_CR4_MASK, 0xffffffff);
|
||||
wvmcs(VMCS_CTRL_CR4_SHADOW, 0xffffffff);
|
||||
|
||||
wvmcs(VMCS_GUEST_CS, 1 << 3);
|
||||
wvmcs(VMCS_GUEST_CS_AR, 0xc093);
|
||||
wvmcs(VMCS_GUEST_CS_LIMIT, 0xffffffff);
|
||||
wvmcs(VMCS_GUEST_CS_BASE, 0x0);
|
||||
|
||||
wvmcs(VMCS_GUEST_DS, 2 << 3);
|
||||
wvmcs(VMCS_GUEST_DS_AR, 0xc093);
|
||||
wvmcs(VMCS_GUEST_DS_LIMIT, 0xffffffff);
|
||||
wvmcs(VMCS_GUEST_DS_BASE, 0);
|
||||
|
||||
wvmcs(VMCS_GUEST_ES, 2 << 3);
|
||||
wvmcs(VMCS_GUEST_ES_AR, 0xc093);
|
||||
wvmcs(VMCS_GUEST_ES_LIMIT, 0xffffffff);
|
||||
wvmcs(VMCS_GUEST_ES_BASE, 0);
|
||||
|
||||
wvmcs(VMCS_GUEST_FS, 2 << 3);
|
||||
wvmcs(VMCS_GUEST_FS_AR, 0xc093);
|
||||
wvmcs(VMCS_GUEST_FS_LIMIT, 0xffffffff);
|
||||
wvmcs(VMCS_GUEST_FS_BASE, 0);
|
||||
|
||||
wvmcs(VMCS_GUEST_GS, 2 << 3);
|
||||
wvmcs(VMCS_GUEST_GS_AR, 0xc093);
|
||||
wvmcs(VMCS_GUEST_GS_LIMIT, 0xffffffff);
|
||||
wvmcs(VMCS_GUEST_GS_BASE, 0);
|
||||
|
||||
wvmcs(VMCS_GUEST_SS, 2 << 3);
|
||||
wvmcs(VMCS_GUEST_SS_AR, 0xc093);
|
||||
wvmcs(VMCS_GUEST_SS_LIMIT, 0xffffffff);
|
||||
wvmcs(VMCS_GUEST_SS_BASE, 0);
|
||||
|
||||
wvmcs(VMCS_GUEST_LDTR, 0);
|
||||
wvmcs(VMCS_GUEST_LDTR_LIMIT, 0);
|
||||
wvmcs(VMCS_GUEST_LDTR_AR, 0x10000);
|
||||
wvmcs(VMCS_GUEST_LDTR_BASE, 0);
|
||||
|
||||
wvmcs(VMCS_GUEST_TR, 0);
|
||||
wvmcs(VMCS_GUEST_TR_LIMIT, 0);
|
||||
wvmcs(VMCS_GUEST_TR_AR, 0x83);
|
||||
wvmcs(VMCS_GUEST_TR_BASE, 0);
|
||||
}
|
||||
|
||||
HVMac::~HVMac() {
|
||||
bailout(hv_vcpu_destroy(vcpu));
|
||||
bailout(hv_vm_unmap(0, RAM_SIZE));
|
||||
bailout(hv_vm_destroy());
|
||||
}
|
||||
|
||||
void HVMac::map_phys(void *memory, uint32_t base, uint32_t size) {
|
||||
bailout(hv_vm_map(memory, base, size, HV_MEMORY_READ | HV_MEMORY_WRITE | HV_MEMORY_EXEC));
|
||||
}
|
||||
|
||||
void HVMac::invalidate_tlb() {
|
||||
hv_vcpu_invalidate_tlb(vcpu);
|
||||
}
|
||||
|
||||
#define REG_MAGIC() \
|
||||
REG(EIP, RIP) \
|
||||
REG(EFLAGS, RFLAGS) \
|
||||
REG(EAX, RAX) \
|
||||
REG(ECX, RCX) \
|
||||
REG(EDX, RDX) \
|
||||
REG(EBX, RBX) \
|
||||
REG(ESI, RSI) \
|
||||
REG(EDI, RDI) \
|
||||
REG(ESP, RSP) \
|
||||
REG(EBP, RBP) \
|
||||
REG1(CS) \
|
||||
REG1(SS) \
|
||||
REG1(DS) \
|
||||
REG1(ES) \
|
||||
REG1(FS) \
|
||||
REG1(GS) \
|
||||
REG1(IDT_BASE) \
|
||||
REG1(IDT_LIMIT) \
|
||||
REG1(GDT_BASE) \
|
||||
REG1(GDT_LIMIT) \
|
||||
REG1(LDTR) \
|
||||
REG1(LDT_BASE) \
|
||||
REG1(LDT_LIMIT) \
|
||||
REG1(LDT_AR) \
|
||||
REG1(TR) \
|
||||
REG1(TSS_BASE) \
|
||||
REG1(TSS_LIMIT) \
|
||||
REG1(TSS_AR) \
|
||||
REG1(CR0) \
|
||||
REG1(CR1) \
|
||||
REG1(CR2) \
|
||||
REG1(CR3) \
|
||||
REG1(CR4) \
|
||||
REG1(DR0) \
|
||||
REG1(DR1) \
|
||||
REG1(DR2) \
|
||||
REG1(DR3) \
|
||||
REG1(DR4) \
|
||||
REG1(DR5) \
|
||||
REG1(DR6) \
|
||||
REG1(DR7) \
|
||||
REG1(TPR) \
|
||||
REG1(XCR0)
|
||||
|
||||
uint32_t HVMac::reg(HVReg reg) {
|
||||
#define REG(a, b) case a: return rreg(HV_X86_##b);
|
||||
#define REG1(a) case a: return rreg(HV_X86_##a);
|
||||
switch(reg) {
|
||||
REG_MAGIC()
|
||||
}
|
||||
#undef REG
|
||||
#undef REG1
|
||||
}
|
||||
void HVMac::reg(HVReg reg, uint32_t val) {
|
||||
#define REG(a, b) case a: wreg(HV_X86_##b, val); break;
|
||||
#define REG1(a) case a: wreg(HV_X86_##a, val); break;
|
||||
switch(reg) {
|
||||
REG_MAGIC()
|
||||
}
|
||||
#undef REG
|
||||
#undef REG1
|
||||
}
|
||||
|
||||
exit_t HVMac::enter() {
|
||||
exit_t _exit;
|
||||
|
||||
bailout(hv_vcpu_run(vcpu));
|
||||
auto exit_reason = rvmcs(VMCS_RO_EXIT_REASON);
|
||||
if(exit_reason & 0x80000000) {
|
||||
_exit.reason = EntryFailed;
|
||||
return _exit;
|
||||
}
|
||||
|
||||
_exit.address = rvmcs(VMCS_RO_EXIT_QUALIFIC);
|
||||
|
||||
switch(exit_reason) {
|
||||
case VMX_REASON_EXC_NMI: {
|
||||
auto vec_val = rvmcs(VMCS_RO_VMEXIT_IRQ_INFO) & 0xFFFF;
|
||||
switch((vec_val >> 8) & 7) {
|
||||
case 6: {
|
||||
_exit.reason = Interrupt;
|
||||
_exit.interrupt_no = vec_val & 0xFF;
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
_exit.reason = Exception;
|
||||
_exit.interrupt_no = vec_val & 0xFF;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
cout << "Unknown NMI class. " << hex << vec_val << endl;
|
||||
_exit.reason = Ignore;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case VMX_REASON_VMCALL: {
|
||||
_exit.reason = VmCall;
|
||||
break;
|
||||
}
|
||||
case VMX_REASON_TRIPLE_FAULT: {
|
||||
_exit.reason = TripleFault;
|
||||
break;
|
||||
}
|
||||
case VMX_REASON_HLT: {
|
||||
_exit.reason = Hlt;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
_exit.reason = Ignore;
|
||||
}
|
||||
}
|
||||
return _exit;
|
||||
}
|
34
Mac/HVMac.hpp
Normal file
34
Mac/HVMac.hpp
Normal file
|
@ -0,0 +1,34 @@
|
|||
#include "Zookeeper.hpp"
|
||||
|
||||
class HVMac : public HV {
|
||||
public:
|
||||
HVMac();
|
||||
~HVMac();
|
||||
void map_phys(void *memory, uint32_t base, uint32_t size);
|
||||
void invalidate_tlb();
|
||||
uint32_t reg(HVReg reg);
|
||||
void reg(HVReg reg, uint32_t val);
|
||||
exit_t enter();
|
||||
private:
|
||||
uint32_t rreg(hv_x86_reg_t reg) {
|
||||
uint64_t v;
|
||||
bailout(hv_vcpu_read_register(vcpu, reg, &v));
|
||||
return (uint32_t) v;
|
||||
}
|
||||
void wreg(hv_x86_reg_t reg, uint32_t v) {
|
||||
bailout(hv_vcpu_write_register(vcpu, reg, (uint32_t) v));
|
||||
}
|
||||
|
||||
uint64_t rvmcs(uint32_t field) {
|
||||
uint64_t v;
|
||||
bailout(hv_vmx_vcpu_read_vmcs(vcpu, field, &v));
|
||||
return v;
|
||||
}
|
||||
void wvmcs(uint32_t field, uint64_t v) {
|
||||
bailout(hv_vmx_vcpu_write_vmcs(vcpu, field, v));
|
||||
}
|
||||
|
||||
hv_vcpuid_t vcpu;
|
||||
};
|
||||
|
||||
#define HVImpl HVMac
|
13
Makefile
13
Makefile
|
@ -1,6 +1,17 @@
|
|||
CPP_FILES := $(wildcard *.cpp)
|
||||
CC_FLAGS := -std=c++14 -I.
|
||||
|
||||
UNAME_S := $(shell uname -s)
|
||||
ifeq ($(UNAME_S),Linux)
|
||||
CC_FLAGS += -DLINUX
|
||||
CPP_FILES += $(wildcard Linux/*.cpp)
|
||||
endif
|
||||
ifeq ($(UNAME_S),Darwin)
|
||||
CC_FLAGS += -DMAC
|
||||
CPP_FILES += $(wildcard Mac/*.cpp)
|
||||
endif
|
||||
|
||||
OBJ_FILES := $(CPP_FILES:.cpp=.o)
|
||||
CC_FLAGS := -std=c++14
|
||||
|
||||
all: NightBeliever zookeeper
|
||||
|
||||
|
|
|
@ -58,16 +58,16 @@ uint32_t ThreadManager::current_thread() {
|
|||
}
|
||||
|
||||
#define REGMAGIC() do {\
|
||||
REG(RIP, eip); \
|
||||
REG(RFLAGS, eflags); \
|
||||
REG(RAX, eax); \
|
||||
REG(RCX, ecx); \
|
||||
REG(RDX, edx); \
|
||||
REG(RBX, ebx); \
|
||||
REG(RSI, esi); \
|
||||
REG(RDI, edi); \
|
||||
REG(RSP, esp); \
|
||||
REG(RBP, ebp); \
|
||||
REG(EIP, eip); \
|
||||
REG(EFLAGS, eflags); \
|
||||
REG(EAX, eax); \
|
||||
REG(ECX, ecx); \
|
||||
REG(EDX, edx); \
|
||||
REG(EBX, ebx); \
|
||||
REG(ESI, esi); \
|
||||
REG(EDI, edi); \
|
||||
REG(ESP, esp); \
|
||||
REG(EBP, ebp); \
|
||||
REG(CS, cs); \
|
||||
REG(SS, ss); \
|
||||
REG(DS, ds); \
|
||||
|
@ -77,7 +77,7 @@ uint32_t ThreadManager::current_thread() {
|
|||
} while(0)
|
||||
|
||||
void Thread::save() {
|
||||
#define REG(reg, name) (name = (uint32_t) box->cpu->rreg(HV_X86_##reg))
|
||||
#define REG(_reg, name) (name = box->cpu->hv->reg(_reg))
|
||||
REGMAGIC();
|
||||
#undef REG
|
||||
#ifdef THREADDEBUG
|
||||
|
@ -89,7 +89,7 @@ void Thread::save() {
|
|||
}
|
||||
|
||||
void Thread::restore() {
|
||||
#define REG(reg, name) (box->cpu->wreg(HV_X86_##reg, (uint64_t) name))
|
||||
#define REG(_reg, name) (box->cpu->hv->reg(_reg, name))
|
||||
REGMAGIC();
|
||||
#undef REG
|
||||
#ifdef THREADDEBUG
|
||||
|
|
|
@ -22,6 +22,11 @@ using namespace boost::algorithm;
|
|||
#define RAM_SIZE 128*1024*1024
|
||||
#define KRAM_SIZE 128*1024*1024
|
||||
|
||||
#include "HV.hpp"
|
||||
#ifdef MAC
|
||||
#include "Mac/HVMac.hpp"
|
||||
#endif
|
||||
|
||||
#include "Hypercall.hpp"
|
||||
#include "xbetypes.hpp"
|
||||
#include "Xbe.hpp"
|
||||
|
|
|
@ -73,7 +73,7 @@ for i, (name, args) in enumerate(calls.items()):
|
|||
print >>zhc, '\t\t\tauto sarg = box->cpu->read_memory<hypercall_%s_t>(addr);' % (name)
|
||||
print >>zhc, '\t\t\t%sbox->hypercall->%s(%s);' % (ret, name, ', '.join('sarg.' + arg for arg, _, _ in args))
|
||||
if rettype != 'void':
|
||||
print >>zhc, '\t\t\tbox->cpu->wreg(HV_X86_RAX, ret);'
|
||||
print >>zhc, '\t\t\tbox->cpu->hv->reg(EAX, ret);'
|
||||
|
||||
print >>zhl, '\t%s %s(%s);' % (typemap(rettype), name, ', '.join('%s %s' % (mapped, name) for name, _, mapped in args))
|
||||
|
||||
|
@ -89,7 +89,7 @@ for i, (name, args) in enumerate(calls.items()):
|
|||
elif len(args) == 1:
|
||||
print >>zhc, '\t\t\t%sbox->hypercall->%s(%saddr);' % (ret, name, cast('uint32_t', args[0][2]))
|
||||
if rettype != 'void':
|
||||
print >>zhc, '\t\t\tbox->cpu->wreg(HV_X86_RAX, ret);'
|
||||
print >>zhc, '\t\t\tbox->cpu->hv->reg(EAX, ret);'
|
||||
|
||||
print >>zhl, '\t%s %s(%s %s);' % (typemap(rettype), name, args[0][2], args[0][0])
|
||||
|
||||
|
@ -102,7 +102,7 @@ for i, (name, args) in enumerate(calls.items()):
|
|||
else:
|
||||
print >>zhc, '\t\t\t%sbox->hypercall->%s();' % (ret, name)
|
||||
if rettype != 'void':
|
||||
print >>zhc, '\t\t\tbox->cpu->wreg(HV_X86_RAX, ret);'
|
||||
print >>zhc, '\t\t\tbox->cpu->hv->reg(EAX, ret);'
|
||||
|
||||
print >>zhl, '\t%s %s();' % (typemap(rettype), name)
|
||||
|
||||
|
|
Loading…
Reference in a new issue