diff --git a/Cargo.toml b/Cargo.toml index eeb02d4..395e01d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,12 +29,13 @@ run-args = [ "-display", "none", "-m", - "512M", + "256M", "-cpu", "host", "-enable-kvm", "-monitor", - "telnet:127.0.0.1:5555,server,nowait" + "telnet:127.0.0.1:5555,server,nowait", + "-s" ] test-args = [ "-device", diff --git a/src/vmm/asm.rs b/src/vmm/asm.rs index 180a10d..6935225 100644 --- a/src/vmm/asm.rs +++ b/src/vmm/asm.rs @@ -5,133 +5,120 @@ use super::{register::GuestRegisters, vcpu::VCpu}; #[allow(improper_ctypes)] extern "C" { pub fn asm_vm_entry(vcpu: *mut VCpu) -> u16; - pub fn asm_vm_entry_resume(vcpu: *mut VCpu) -> u16; - pub fn guest_entry() -> !; - pub fn vmexit_handler_asm() -> !; + pub fn asm_vmexit_handler() -> !; } -const GUEST_REGS_OFFSET: usize = offset_of!(VCpu, guest_registers); -const LAUNCH_DONE_OFFSET: usize = offset_of!(VCpu, launch_done); - -const RAX_OFFSET: usize = offset_of!(GuestRegisters, rax); -const RCX_OFFSET: usize = offset_of!(GuestRegisters, rcx); -const RDX_OFFSET: usize = offset_of!(GuestRegisters, rdx); -const RBX_OFFSET: usize = offset_of!(GuestRegisters, rbx); -const RSI_OFFSET: usize = offset_of!(GuestRegisters, rsi); -const RDI_OFFSET: usize = offset_of!(GuestRegisters, rdi); -const RBP_OFFSET: usize = offset_of!(GuestRegisters, rbp); -const R8_OFFSET: usize = offset_of!(GuestRegisters, r8); -const R9_OFFSET: usize = offset_of!(GuestRegisters, r9); -const R10_OFFSET: usize = offset_of!(GuestRegisters, r10); -const R11_OFFSET: usize = offset_of!(GuestRegisters, r11); -const R12_OFFSET: usize = offset_of!(GuestRegisters, r12); -const R13_OFFSET: usize = offset_of!(GuestRegisters, r13); -const R14_OFFSET: usize = offset_of!(GuestRegisters, r14); -const R15_OFFSET: usize = offset_of!(GuestRegisters, r15); -const XMM0_OFFSET: usize = offset_of!(GuestRegisters, xmm0); -const XMM1_OFFSET: usize = offset_of!(GuestRegisters, xmm1); -const XMM2_OFFSET: usize = offset_of!(GuestRegisters, xmm2); -const XMM3_OFFSET: usize = offset_of!(GuestRegisters, xmm3); -const XMM4_OFFSET: usize = offset_of!(GuestRegisters, xmm4); -const XMM5_OFFSET: usize = offset_of!(GuestRegisters, xmm5); -const XMM6_OFFSET: usize = offset_of!(GuestRegisters, xmm6); -const XMM7_OFFSET: usize = offset_of!(GuestRegisters, xmm7); - global_asm!( - ".global asm_vm_entry_resume", - ".type asm_vm_entry_resume, @function", - "asm_vm_entry_resume:", - "push rbp", - "push r15", - "push r14", - "push r13", - "push r12", - "push rbx", - "lea rbx, [rdi + {0}]", - "push rbx", - "push rdi", - "lea rdi, [rsp + 8]", - "call set_host_stack", - "pop rdi", - "mov rax, rdi", - "mov rcx, [rax+{2}]", - "mov rdx, [rax+{3}]", - "mov rbx, [rax+{4}]", - "mov rsi, [rax+{5}]", - "mov rdi, [rax+{6}]", - "mov rbp, [rax+{7}]", - "mov r8, [rax+{8}]", - "mov r9, [rax+{9}]", - "mov r10, [rax+{10}]", - "mov r11, [rax+{11}]", - "mov r12, [rax+{12}]", - "mov r13, [rax+{13}]", - "mov r14, [rax+{14}]", - "mov r15, [rax+{15}]", - "movaps xmm0, [rax+{17}]", - "movaps xmm1, [rax+{18}]", - "movaps xmm2, [rax+{19}]", - "movaps xmm3, [rax+{20}]", - "movaps xmm4, [rax+{21}]", - "movaps xmm5, [rax+{22}]", - "movaps xmm6, [rax+{23}]", - "movaps xmm7, [rax+{24}]", - "mov rax, [rax+{16}]", - "vmresume", - "mov ax, 1", - "add rsp, 8", - "pop rbx", - "pop r12", - "pop r13", - "pop r14", - "pop r15", - "pop rbp", - "ret", - ".size asm_vm_entry_resume, . - asm_vm_entry_resume", - ".global asm_vm_entry", ".type asm_vm_entry, @function", - "asm_vm_entry:", + "asm_vm_entry:", // rdi = *VCpu "push rbp", "push r15", "push r14", "push r13", "push r12", "push rbx", - "lea rbx, [rdi + {0}]", - "push rbx", - "push rdi", - "lea rdi, [rsp + 8]", +/* +stack: ++-----+ +| RBX | ++-----+ +| R12 | ++-----+ +| R13 | ++-----+ +| R14 | ++-----+ +| R15 | ++-----+ +| RBP | ++-----+ +| RIP | ++-----+ + +regs: +RDI = *VCpu +*/ + "lea rbx, [rdi + {guest_regs_offset}]", // rbx = *guest_regs + "push rbx", // push *guest_regs + "push rdi", // push *VCpu + "lea rdi, [rsp + 8]", // rdi = rsp + 8 = *guest_regs "call set_host_stack", - "pop rdi", - "test byte ptr [rdi + {1}], 1", - "mov rax, rdi", - "mov rcx, [rax+{2}]", - "mov rdx, [rax+{3}]", - "mov rbx, [rax+{4}]", - "mov rsi, [rax+{5}]", - "mov rdi, [rax+{6}]", - "mov rbp, [rax+{7}]", - "mov r8, [rax+{8}]", - "mov r9, [rax+{9}]", - "mov r10, [rax+{10}]", - "mov r11, [rax+{11}]", - "mov r12, [rax+{12}]", - "mov r13, [rax+{13}]", - "mov r14, [rax+{14}]", - "mov r15, [rax+{15}]", - "mov rax, [rax+{16}]", - "movaps xmm0, [rax+{17}]", - "movaps xmm1, [rax+{18}]", - "movaps xmm2, [rax+{19}]", - "movaps xmm3, [rax+{20}]", - "movaps xmm4, [rax+{21}]", - "movaps xmm5, [rax+{22}]", - "movaps xmm6, [rax+{23}]", - "movaps xmm7, [rax+{24}]", + "pop rdi", // rdi = *VCpu + "test byte ptr [rdi + {launch_done_offset}], 1", // flag = launch_done ? 1 : 0 +/* +stack: ++-------------+ +| *guest_regs | ++-------------+ +| RBX | ++-------------+ +| R12 | ++-------------+ +| R13 | ++-------------+ +| R14 | ++-------------+ +| R15 | ++-------------+ +| RBP | ++-------------+ +| RIP | ++-------------+ +regs: +RDI = *VCpu +RBX = *guest_regs +*/ + "mov rax, rbx", // rax = *guest_regs + "mov rcx, [rax+{reg_offset_rcx}]", // rcx = guest_regs.rcx + "mov rdx, [rax+{reg_offset_rdx}]", // rdx = guest_regs.rdx + "mov rbx, [rax+{reg_offset_rbx}]", // rbx = guest_regs.rbx + "mov rsi, [rax+{reg_offset_rsi}] ", // rsi = guest_regs.rsi + "mov rdi, [rax+{reg_offset_rdi}]", // rdi = guest_regs.rdi + "mov rbp, [rax+{reg_offset_rbp}]", // rbp = guest_regs.rbp + "mov r8, [rax+{reg_offset_r8}]", // r8 = guest_regs.r8 + "mov r9, [rax+{reg_offset_r9}]", // r9 = guest_regs.r9 + "mov r10, [rax+{reg_offset_r10}]", // r10 = guest_regs.r10 + "mov r11, [rax+{reg_offset_r11}]", // r11 = guest_regs.r11 + "mov r12, [rax+{reg_offset_r12}]", // r12 = guest_regs.r12 + "mov r13, [rax+{reg_offset_r13}]", // r13 = guest_regs.r13 + "mov r14, [rax+{reg_offset_r14}]", // r14 = guest_regs.r14 + "mov r15, [rax+{reg_offset_r15}]", // r15 = guest_regs.r15 + "movaps xmm0, [rax+{reg_offset_xmm0}]", // xmm0 = guest_regs.xmm0 + "movaps xmm1, [rax+{reg_offset_xmm1}]", // xmm1 = guest_regs.xmm1 + "movaps xmm2, [rax+{reg_offset_xmm2}]", // xmm2 = guest_regs.xmm2 + "movaps xmm3, [rax+{reg_offset_xmm3}]", // xmm3 = guest_regs.xmm3 + "movaps xmm4, [rax+{reg_offset_xmm4}]", // xmm4 = guest_regs.xmm4 + "movaps xmm5, [rax+{reg_offset_xmm5}]", // xmm5 = guest_regs.xmm5 + "movaps xmm6, [rax+{reg_offset_xmm6}]", // xmm6 = guest_regs.xmm6 + "movaps xmm7, [rax+{reg_offset_xmm7}]", // xmm7 = guest_regs.xmm7 + "mov rax, [rax+{reg_offset_rax}]", // rax = guest_regs.rax +/* +stack: ++-------------+ +| *guest_regs | ++-------------+ +| RBX | ++-------------+ +| R12 | ++-------------+ +| R13 | ++-------------+ +| R14 | ++-------------+ +| R15 | ++-------------+ +| RBP | ++-------------+ +| RIP | ++-------------+ +*/ + "jz 2f", + "vmresume", + "2:", "vmlaunch", "mov ax, 1", - "add rsp, 8", + "add rsp, 0x8", "pop rbx", "pop r12", "pop r13", @@ -139,70 +126,144 @@ global_asm!( "pop r15", "pop rbp", "ret", + ".size asm_vm_entry, . - asm_vm_entry", - ".global vmexit_handler_asm", - ".type vmexit_handler_asm, @function", - "vmexit_handler_asm:", + ".global asm_vmexit_handler", + ".type asm_vmexit_handler, @function", + "asm_vmexit_handler:", + "cli", +/* +stack: ++-------------+ +| *guest_regs | ++-------------+ +| RBX | ++-------------+ +| R12 | ++-------------+ +| R13 | ++-------------+ +| R14 | ++-------------+ +| R15 | ++-------------+ +| RBP | ++-------------+ +| RIP | ++-------------+ +regs: +RAX = guest CPU's rax +*/ "push rax", - "mov rax, [rsp+8]", - "pop [rax+{16}]", - "add rsp, 8", - "mov [rax+{2}], rcx", - "mov [rax+{3}], rdx", - "mov [rax+{4}], rbx", - "mov [rax+{5}], rsi", - "mov [rax+{6}], rdi", - "mov [rax+{7}], rbp", - "mov [rax+{8}], r8", - "mov [rax+{9}], r9", - "mov [rax+{10}], r10", - "mov [rax+{11}], r11", - "mov [rax+{12}], r12", - "mov [rax+{13}], r13", - "mov [rax+{14}], r14", - "mov [rax+{15}], r15", - "movaps [rax+{17}], xmm0", - "movaps [rax+{18}], xmm1", - "movaps [rax+{19}], xmm2", - "movaps [rax+{20}], xmm3", - "movaps [rax+{21}], xmm4", - "movaps [rax+{22}], xmm5", - "movaps [rax+{23}], xmm6", - "movaps [rax+{24}], xmm7", + "mov rax, qword ptr [rsp + 0x8]", // rax = *guest_regs +/* +stack: ++-------------+ +| guest RAX | ++-------------+ +| *guest_regs | ++-------------+ +| RBX | ++-------------+ +| R12 | ++-------------+ +| R13 | ++-------------+ +| R14 | ++-------------+ +| R15 | ++-------------+ +| RBP | ++-------------+ +| RIP | ++-------------+ +*/ + + "pop [rax + {reg_offset_rax}]", // guest_regs.rax = guest CPU's rax + "add rsp, 0x8", // discard *guest_regs +/* +stack: ++-------------+ +| RBX | ++-------------+ +| R12 | ++-------------+ +| R13 | ++-------------+ +| R14 | ++-------------+ +| R15 | ++-------------+ +| RBP | ++-------------+ +| RIP | ++-------------+ +*/ + + // save rcx, rdx, rbx, rsi, rdi, rbp, r8~15, xmm0~7 + "mov [rax + {reg_offset_rcx}], rcx", + "mov [rax + {reg_offset_rdx}], rdx", + "mov [rax + {reg_offset_rbx}], rbx", + "mov [rax + {reg_offset_rsi}], rsi", + "mov [rax + {reg_offset_rdi}], rdi", + "mov [rax + {reg_offset_rbp}], rbp", + "mov [rax + {reg_offset_r8}], r8", + "mov [rax + {reg_offset_r9}], r9", + "mov [rax + {reg_offset_r10}], r10", + "mov [rax + {reg_offset_r11}], r11", + "mov [rax + {reg_offset_r12}], r12", + "mov [rax + {reg_offset_r13}], r13", + "mov [rax + {reg_offset_r14}], r14", + "mov [rax + {reg_offset_r15}], r15", + "movaps [rax + {reg_offset_xmm0}], xmm0", + "movaps [rax + {reg_offset_xmm1}], xmm1", + "movaps [rax + {reg_offset_xmm2}], xmm2", + "movaps [rax + {reg_offset_xmm3}], xmm3", + "movaps [rax + {reg_offset_xmm4}], xmm4", + "movaps [rax + {reg_offset_xmm5}], xmm5", + "movaps [rax + {reg_offset_xmm6}], xmm6", + "movaps [rax + {reg_offset_xmm7}], xmm7", "pop rbx", "pop r12", "pop r13", "pop r14", "pop r15", "pop rbp", - "mov rax, 0", +/* +stack: ++-------------+ +| RIP | ++-------------+ +*/ + "mov rax, 0x0", "ret", - ".size vmexit_handler_asm, . - vmexit_handler_asm", - const GUEST_REGS_OFFSET, - const LAUNCH_DONE_OFFSET, - const RCX_OFFSET, - const RDX_OFFSET, - const RBX_OFFSET, - const RSI_OFFSET, - const RDI_OFFSET, - const RBP_OFFSET, - const R8_OFFSET, - const R9_OFFSET, - const R10_OFFSET, - const R11_OFFSET, - const R12_OFFSET, - const R13_OFFSET, - const R14_OFFSET, - const R15_OFFSET, - const RAX_OFFSET, - const XMM0_OFFSET, - const XMM1_OFFSET, - const XMM2_OFFSET, - const XMM3_OFFSET, - const XMM4_OFFSET, - const XMM5_OFFSET, - const XMM6_OFFSET, - const XMM7_OFFSET, + ".size asm_vmexit_handler, . - asm_vmexit_handler", + + guest_regs_offset = const offset_of!(VCpu, guest_registers), + launch_done_offset = const offset_of!(VCpu, launch_done), + reg_offset_rax = const offset_of!(GuestRegisters, rax), + reg_offset_rcx = const offset_of!(GuestRegisters, rcx), + reg_offset_rdx = const offset_of!(GuestRegisters, rdx), + reg_offset_rbx = const offset_of!(GuestRegisters, rbx), + reg_offset_rsi = const offset_of!(GuestRegisters, rsi), + reg_offset_rdi = const offset_of!(GuestRegisters, rdi), + reg_offset_rbp = const offset_of!(GuestRegisters, rbp), + reg_offset_r8 = const offset_of!(GuestRegisters, r8), + reg_offset_r9 = const offset_of!(GuestRegisters, r9), + reg_offset_r10 = const offset_of!(GuestRegisters, r10), + reg_offset_r11 = const offset_of!(GuestRegisters, r11), + reg_offset_r12 = const offset_of!(GuestRegisters, r12), + reg_offset_r13 = const offset_of!(GuestRegisters, r13), + reg_offset_r14 = const offset_of!(GuestRegisters, r14), + reg_offset_r15 = const offset_of!(GuestRegisters, r15), + reg_offset_xmm0 = const offset_of!(GuestRegisters, xmm0), + reg_offset_xmm1 = const offset_of!(GuestRegisters, xmm1), + reg_offset_xmm2 = const offset_of!(GuestRegisters, xmm2), + reg_offset_xmm3 = const offset_of!(GuestRegisters, xmm3), + reg_offset_xmm4 = const offset_of!(GuestRegisters, xmm4), + reg_offset_xmm5 = const offset_of!(GuestRegisters, xmm5), + reg_offset_xmm6 = const offset_of!(GuestRegisters, xmm6), + reg_offset_xmm7 = const offset_of!(GuestRegisters, xmm7), ); diff --git a/src/vmm/vcpu.rs b/src/vmm/vcpu.rs index 12837f0..2756654 100644 --- a/src/vmm/vcpu.rs +++ b/src/vmm/vcpu.rs @@ -29,11 +29,12 @@ use super::{ vmxon::Vmxon, }; +#[repr(C)] pub struct VCpu { + pub guest_registers: GuestRegisters, pub vmxon: Vmxon, pub vmcs: Vmcs, pub phys_mem_offset: u64, - pub guest_registers: GuestRegisters, pub launch_done: bool, pub ept: EPT, pub eptp: EPTP, @@ -301,7 +302,7 @@ impl VCpu { vmwrite(vmcs::host::CR3, cr3())?; vmwrite(vmcs::host::CR4, cr4().bits() as u64)?; - vmwrite(vmcs::host::RIP, crate::vmm::asm::vmexit_handler_asm as u64)?; + vmwrite(vmcs::host::RIP, crate::vmm::asm::asm_vmexit_handler as u64)?; vmwrite( vmcs::host::RSP, VirtAddr::from_ptr(&raw mut TEMP_STACK).as_u64() + TEMP_STACK_SIZE as u64, @@ -359,7 +360,10 @@ impl VCpu { vmwrite(vmcs::guest::CR3, cr3())?; vmwrite( vmcs::guest::CR4, - vmread(vmcs::guest::CR4)? | Cr4Flags::VIRTUAL_MACHINE_EXTENSIONS.bits(), + vmread(vmcs::guest::CR4)? + | 1 << 5 + | 1 << 7 + | Cr4Flags::VIRTUAL_MACHINE_EXTENSIONS.bits(), )?; vmwrite(vmcs::guest::CS_BASE, 0)?; @@ -512,17 +516,11 @@ impl VCpu { let success = { let result: u16; self.print_guest_regs(); - if !self.launch_done { - unsafe { - result = crate::vmm::asm::asm_vm_entry(self as *mut _); - }; - result == 0 - } else { - unsafe { - result = crate::vmm::asm::asm_vm_entry_resume(self as *mut _); - }; - result == 0 - } + + unsafe { + result = crate::vmm::asm::asm_vm_entry(self as *mut _); + }; + result == 0 }; if !self.launch_done && success {