// Copyright 2017 The Fuchsia Authors // // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file or at // https://opensource.org/licenses/MIT #include #include #include .text /* zx_status_t vmx_enter(VmxState* vmx_state) */ FUNCTION(vmx_enter) // Store the return address. // We do this first to adjust the RSP we store. popq HS_RIP(%rdi) // Store the callee save registers. mov %rbx, HS_RBX(%rdi) mov %rsp, HS_RSP(%rdi) mov %rbp, HS_RBP(%rdi) mov %r12, HS_R12(%rdi) mov %r13, HS_R13(%rdi) mov %r14, HS_R14(%rdi) mov %r15, HS_R15(%rdi) // Store the processor flags. pushfq popq HS_RFLAGS(%rdi) // We are going to trample RDI, so move it to RSP. This also conveniently // mirrors the exit code. mov %rdi, %rsp // Load the guest CR2. mov GS_CR2(%rsp), %rax mov %rax, %cr2 // Load the guest registers not covered by the VMCS. mov GS_RAX(%rsp), %rax mov GS_RCX(%rsp), %rcx mov GS_RDX(%rsp), %rdx mov GS_RBX(%rsp), %rbx mov GS_RBP(%rsp), %rbp mov GS_RSI(%rsp), %rsi mov GS_RDI(%rsp), %rdi mov GS_R8(%rsp), %r8 mov GS_R9(%rsp), %r9 mov GS_R10(%rsp), %r10 mov GS_R11(%rsp), %r11 mov GS_R12(%rsp), %r12 mov GS_R13(%rsp), %r13 mov GS_R14(%rsp), %r14 mov GS_R15(%rsp), %r15 // If we are resuming, jump to resume. testb $1, VS_RESUME(%rsp) jnz resume // Launch the guest. vmlaunch jmp failure resume: // Resume the guest. vmresume failure: // We will only be here if vmlaunch or vmresume failed. // Restore host RDI and RSP. mov %rsp, %rdi mov HS_RSP(%rdi), %rsp // Set up the return address. pushq HS_RIP(%rdi) // Return ZX_ERR_INTERNAL. mov $ZX_ERR_INTERNAL, %eax ret END_FUNCTION(vmx_enter) /* This is effectively the second-half of vmx_enter. When we return from a * VM exit, vmx_state argument is stored in RSP. We use this to restore the * stack and registers to the state they were in when vmx_enter was called. */ FUNCTION(vmx_exit_entry) // Store the guest registers not covered by the VMCS. At this point, // vmx_state is in RSP. mov %rax, GS_RAX(%rsp) mov %rcx, GS_RCX(%rsp) mov %rdx, GS_RDX(%rsp) mov %rbx, GS_RBX(%rsp) mov %rbp, GS_RBP(%rsp) mov %rsi, GS_RSI(%rsp) mov %rdi, GS_RDI(%rsp) mov %r8, GS_R8(%rsp) mov %r9, GS_R9(%rsp) mov %r10, GS_R10(%rsp) mov %r11, GS_R11(%rsp) mov %r12, GS_R12(%rsp) mov %r13, GS_R13(%rsp) mov %r14, GS_R14(%rsp) mov %r15, GS_R15(%rsp) // Store the guest CR2. mov %cr2, %rax mov %rax, GS_CR2(%rsp) // Load vmx_state from RSP into RDI. mov %rsp, %rdi // Load the host callee save registers. mov HS_RBX(%rdi), %rbx mov HS_RSP(%rdi), %rsp mov HS_RBP(%rdi), %rbp mov HS_R12(%rdi), %r12 mov HS_R13(%rdi), %r13 mov HS_R14(%rdi), %r14 mov HS_R15(%rdi), %r15 // Load the host processor flags. pushq HS_RFLAGS(%rdi) popfq // Set up the return address. pushq HS_RIP(%rdi) // Call vmx_exit(vmx_state). sub $8, %rsp call vmx_exit add $8, %rsp // Return ZX_OK, using the return address of vmx_enter pushed above. mov $ZX_OK, %eax ret END_FUNCTION(vmx_exit_entry)