1/* 2 * Copyright 2019, Data61, CSIRO (ABN 41 687 119 230) 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#include <autoconf.h> 8#include <stdio.h> 9#include <stdlib.h> 10 11#include <sel4vm/guest_vm.h> 12#include <sel4vm/boot.h> 13#include "sel4vm/guest_memory.h" 14 15#include "vm.h" 16#include "mem_abort.h" 17#include "fault.h" 18#include "guest_memory.h" 19 20static int unhandled_memory_fault(vm_t *vm, vm_vcpu_t *vcpu, fault_t *fault) 21{ 22 uintptr_t addr = fault_get_address(fault); 23 size_t fault_size = fault_get_width_size(fault); 24 memory_fault_result_t fault_result = vm->mem.unhandled_mem_fault_handler(vm, vcpu, addr, fault_size, 25 vm->mem.unhandled_mem_fault_cookie); 26 switch (fault_result) { 27 case FAULT_HANDLED: 28 return 0; 29 case FAULT_RESTART: 30 restart_fault(fault); 31 return 0; 32 case FAULT_IGNORE: 33 return ignore_fault(fault); 34 case FAULT_ERROR: 35 print_fault(fault); 36 abandon_fault(fault); 37 return -1; 38 default: 39 break; 40 } 41 return -1; 42} 43 44int handle_page_fault(vm_t *vm, vm_vcpu_t *vcpu, fault_t *fault) 45{ 46 int err; 47 uintptr_t addr = fault_get_address(fault); 48 size_t fault_size = fault_get_width_size(fault); 49 50 memory_fault_result_t fault_result = vm_memory_handle_fault(vm, vcpu, addr, fault_size); 51 switch (fault_result) { 52 case FAULT_HANDLED: 53 return 0; 54 case FAULT_RESTART: 55 restart_fault(fault); 56 return 0; 57 case FAULT_IGNORE: 58 return ignore_fault(fault); 59 case FAULT_ERROR: 60 print_fault(fault); 61 abandon_fault(fault); 62 return -1; 63 case FAULT_UNHANDLED: 64 if (vm->mem.unhandled_mem_fault_handler) { 65 err = unhandled_memory_fault(vm, vcpu, fault); 66 if (err) { 67 return -1; 68 } 69 return 0; 70 } 71 default: 72 break; 73 /* We don't have a memory reservation for the faulting address 74 * We move onto the rest of the page fault handler */ 75 } 76 77 print_fault(fault); 78 abandon_fault(fault); 79 return -1; 80} 81 82int vm_guest_mem_abort_handler(vm_vcpu_t *vcpu) 83{ 84 int err; 85 fault_t *fault; 86 fault = vcpu->vcpu_arch.fault; 87 err = new_memory_fault(fault); 88 if (err) { 89 ZF_LOGE("Failed to initialise new fault"); 90 return -1; 91 } 92 err = handle_page_fault(vcpu->vm, vcpu, fault); 93 if (err) { 94 return VM_EXIT_HANDLE_ERROR; 95 } 96 return VM_EXIT_HANDLED; 97} 98