1/* 2 * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 * 4 * SPDX-License-Identifier: GPL-2.0-only 5 */ 6 7/*vm exits related with ept violations*/ 8 9#include <stdio.h> 10#include <stdlib.h> 11 12#include <sel4/sel4.h> 13 14#include <sel4vm/guest_memory.h> 15#include <sel4vm/arch/vmcs_fields.h> 16 17#include "vm.h" 18#include "guest_state.h" 19#include "vmcs.h" 20#include "debug.h" 21#include "processor/decode.h" 22#include "guest_memory.h" 23 24#define EPT_VIOL_READ(qual) ((qual) & BIT(0)) 25#define EPT_VIOL_WRITE(qual) ((qual) & BIT(1)) 26#define EPT_VIOL_FETCH(qual) ((qual) & BIT(2)) 27 28void print_ept_violation(vm_vcpu_t *vcpu) 29{ 30 /* Read linear address that guest is trying to access. */ 31 unsigned int linear_address; 32 vm_vmcs_read(vcpu->vcpu.cptr, VMX_DATA_GUEST_LINEAR_ADDRESS, &linear_address); 33 printf(COLOUR_R "!!!!!!!! ALERT :: GUEST OS PAGE FAULT !!!!!!!!\n"); 34 printf(" Guest OS VMExit due to EPT Violation:\n"); 35 printf(" Linear address 0x%x.\n", linear_address); 36 printf(" Guest-Physical address 0x%x.\n", vm_guest_exit_get_physical(vcpu->vcpu_arch.guest_state)); 37 printf(" Instruction pointer 0x%x.\n", vm_guest_state_get_eip(vcpu->vcpu_arch.guest_state)); 38 printf(" This is most likely due to a bug or misconfiguration.\n" COLOUR_RESET); 39} 40 41static int unhandled_memory_fault(vm_t *vm, vm_vcpu_t *vcpu, uint32_t guest_phys, size_t size) 42{ 43 memory_fault_result_t fault_result = vm->mem.unhandled_mem_fault_handler(vm, vcpu, guest_phys, size, 44 vm->mem.unhandled_mem_fault_cookie); 45 switch (fault_result) { 46 case FAULT_ERROR: 47 print_ept_violation(vcpu); 48 return -1; 49 case FAULT_HANDLED: 50 case FAULT_IGNORE: 51 vm_guest_exit_next_instruction(vcpu->vcpu_arch.guest_state, vcpu->vcpu.cptr); 52 return 0; 53 } 54 return -1; 55} 56 57/* Handling EPT violation VMExit Events. */ 58int vm_ept_violation_handler(vm_vcpu_t *vcpu) 59{ 60 int err; 61 uintptr_t guest_phys = vm_guest_exit_get_physical(vcpu->vcpu_arch.guest_state); 62 unsigned int qualification = vm_guest_exit_get_qualification(vcpu->vcpu_arch.guest_state); 63 64 int read = EPT_VIOL_READ(qualification); 65 int write = EPT_VIOL_WRITE(qualification); 66 int fetch = EPT_VIOL_FETCH(qualification); 67 if (read && write) { 68 /* Indicates a fault while walking EPT */ 69 return VM_EXIT_HANDLE_ERROR; 70 } 71 if (fetch) { 72 /* This is not MMIO */ 73 return VM_EXIT_HANDLE_ERROR; 74 } 75 76 int reg; 77 uint32_t imm; 78 int size; 79 vm_decode_ept_violation(vcpu, ®, &imm, &size); 80 memory_fault_result_t fault_result = vm_memory_handle_fault(vcpu->vm, vcpu, guest_phys, size); 81 switch (fault_result) { 82 case FAULT_ERROR: 83 print_ept_violation(vcpu); 84 return -1; 85 case FAULT_HANDLED: 86 return VM_EXIT_HANDLED; 87 case FAULT_IGNORE: 88 vm_guest_exit_next_instruction(vcpu->vcpu_arch.guest_state, vcpu->vcpu.cptr); 89 return VM_EXIT_HANDLED; 90 case FAULT_UNHANDLED: 91 if (vcpu->vm->mem.unhandled_mem_fault_handler) { 92 err = unhandled_memory_fault(vcpu->vm, vcpu, guest_phys, size); 93 if (err) { 94 return -1; 95 } 96 return 0; 97 } 98 } 99 ZF_LOGE("Failed to handle ept fault"); 100 print_ept_violation(vcpu); 101 return -1; 102} 103