1/*
2 * Copyright 2019, Data61, CSIRO (ABN 41 687 119 230)
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#include <sel4vm/guest_vcpu_fault.h>
8
9#include <sel4vm/arch/vmcs_fields.h>
10
11#include "guest_state.h"
12#include "processor/decode.h"
13
14seL4_Word get_vcpu_fault_address(vm_vcpu_t *vcpu)
15{
16    return vm_guest_exit_get_physical(vcpu->vcpu_arch.guest_state);
17}
18
19seL4_Word get_vcpu_fault_ip(vm_vcpu_t *vcpu)
20{
21    return vm_guest_state_get_eip(vcpu->vcpu_arch.guest_state);
22}
23
24seL4_Word get_vcpu_fault_data(vm_vcpu_t *vcpu)
25{
26    int reg;
27    uint32_t imm;
28    int size;
29    vm_decode_ept_violation(vcpu, &reg, &imm, &size);
30    int vcpu_reg = vm_decoder_reg_mapw[reg];
31    unsigned int data;
32    vm_get_thread_context_reg(vcpu, vcpu_reg, &data);
33    return data;
34}
35
36size_t get_vcpu_fault_size(vm_vcpu_t *vcpu)
37{
38    int reg;
39    uint32_t imm;
40    int size;
41    vm_decode_ept_violation(vcpu, &reg, &imm, &size);
42    return size;
43}
44
45seL4_Word get_vcpu_fault_data_mask(vm_vcpu_t *vcpu)
46{
47    size_t size = get_vcpu_fault_size(vcpu);
48    seL4_Word addr = get_vcpu_fault_address(vcpu);
49    seL4_Word mask = 0;
50    switch (size) {
51    case sizeof(uint8_t):
52        mask = 0x000000ff;
53        break;
54    case sizeof(uint16_t):
55        mask = 0x0000ffff;
56        break;
57    case sizeof(uint32_t):
58        mask = 0xffffffff;
59        break;
60    default:
61        ZF_LOGE("Invalid fault size");
62        return 0;
63    }
64    mask <<= (addr & 0x3) * 8;
65    return mask;
66}
67
68bool is_vcpu_read_fault(vm_vcpu_t *vcpu)
69{
70    unsigned int qualification = vm_guest_exit_get_qualification(vcpu->vcpu_arch.guest_state);
71    return true ? qualification & BIT(0) : false;
72}
73
74int set_vcpu_fault_data(vm_vcpu_t *vcpu, seL4_Word data)
75{
76    int reg;
77    uint32_t imm;
78    int size;
79    vm_decode_ept_violation(vcpu, &reg, &imm, &size);
80    int vcpu_reg = vm_decoder_reg_mapw[reg];
81    return vm_set_thread_context_reg(vcpu, vcpu_reg, data);
82}
83
84void advance_vcpu_fault(vm_vcpu_t *vcpu)
85{
86    vm_guest_exit_next_instruction(vcpu->vcpu_arch.guest_state, vcpu->vcpu.cptr);
87}
88
89void restart_vcpu_fault(vm_vcpu_t *vcpu)
90{
91    return;
92}
93