blob: 54598476cbd439cc9ab684b67cca156ad55a077a [file] [log] [blame]
// 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 <asm.h>
#include <arch/x86/vmx_state.h>
#include <zircon/errors.h>
.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)