1/*
2 * Copyright 2017, Data61
3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO)
4 * ABN 41 687 119 230.
5 *
6 * This software may be distributed and modified according to the terms of
7 * the GNU General Public License version 2. Note that NO WARRANTY is provided.
8 * See "LICENSE_GPLv2.txt" for details.
9 *
10 * @TAG(DATA61_GPL)
11 */
12
13#include <config.h>
14#include <types.h>
15#include <object.h>
16#include <kernel/vspace.h>
17#include <api/faults.h>
18#include <api/syscall.h>
19
20bool_t
21Arch_handleFaultReply(tcb_t *receiver, tcb_t *sender, word_t faultType)
22{
23    switch (faultType) {
24    case seL4_Fault_VMFault:
25        return true;
26
27#ifdef CONFIG_ARM_HYPERVISOR_SUPPORT
28    case seL4_Fault_VGICMaintenance:
29        return true;
30    case seL4_Fault_VCPUFault:
31        return true;
32#endif
33    default:
34        fail("Invalid fault");
35    }
36}
37
38word_t
39Arch_setMRs_fault(tcb_t *sender, tcb_t* receiver, word_t *receiveIPCBuffer, word_t faultType)
40{
41    switch (faultType) {
42    case seL4_Fault_VMFault: {
43        if (config_set(CONFIG_ARM_HYPERVISOR_SUPPORT)) {
44            word_t ipa, va;
45            va = getRestartPC(sender);
46            ipa = (addressTranslateS1CPR(va) & ~MASK(PAGE_BITS)) | (va & MASK(PAGE_BITS));
47            setMR(receiver, receiveIPCBuffer, seL4_VMFault_IP, ipa);
48        } else {
49            setMR(receiver, receiveIPCBuffer, seL4_VMFault_IP, getRestartPC(sender));
50        }
51        setMR(receiver, receiveIPCBuffer, seL4_VMFault_Addr,
52              seL4_Fault_VMFault_get_address(sender->tcbFault));
53        setMR(receiver, receiveIPCBuffer, seL4_VMFault_PrefetchFault,
54              seL4_Fault_VMFault_get_instructionFault(sender->tcbFault));
55        return setMR(receiver, receiveIPCBuffer, seL4_VMFault_FSR,
56                     seL4_Fault_VMFault_get_FSR(sender->tcbFault));
57    }
58
59#ifdef CONFIG_ARM_HYPERVISOR_SUPPORT
60    case seL4_Fault_VGICMaintenance:
61        if (seL4_Fault_VGICMaintenance_get_idxValid(sender->tcbFault)) {
62            return setMR(receiver, receiveIPCBuffer, seL4_VGICMaintenance_IDX,
63                         seL4_Fault_VGICMaintenance_get_idx(sender->tcbFault));
64        } else {
65            return setMR(receiver, receiveIPCBuffer, seL4_VGICMaintenance_IDX, -1);
66        }
67    case seL4_Fault_VCPUFault:
68        return setMR(receiver, receiveIPCBuffer, seL4_VCPUFault_HSR, seL4_Fault_VCPUFault_get_hsr(sender->tcbFault));
69#endif
70
71    default:
72        fail("Invalid fault");
73    }
74}
75