1/*
2 * Copyright 2020, Data61, CSIRO (ABN 41 687 119 230)
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 */
6
7#include <config.h>
8#include <types.h>
9#include <object.h>
10#include <kernel/vspace.h>
11#include <api/faults.h>
12#include <api/syscall.h>
13
14bool_t Arch_handleFaultReply(tcb_t *receiver, tcb_t *sender, word_t faultType)
15{
16    switch (faultType) {
17    case seL4_Fault_VMFault:
18        return true;
19
20#ifdef CONFIG_ARM_HYPERVISOR_SUPPORT
21    case seL4_Fault_VGICMaintenance:
22        return true;
23    case seL4_Fault_VCPUFault:
24        return true;
25    case seL4_Fault_VPPIEvent:
26        return true;
27#endif
28    default:
29        fail("Invalid fault");
30    }
31}
32
33word_t Arch_setMRs_fault(tcb_t *sender, tcb_t *receiver, word_t *receiveIPCBuffer, word_t faultType)
34{
35    switch (faultType) {
36    case seL4_Fault_VMFault: {
37        if (config_set(CONFIG_ARM_HYPERVISOR_SUPPORT)) {
38            word_t ipa, va;
39            va = getRestartPC(sender);
40            ipa = (addressTranslateS1CPR(va) & ~MASK(PAGE_BITS)) | (va & MASK(PAGE_BITS));
41            setMR(receiver, receiveIPCBuffer, seL4_VMFault_IP, ipa);
42        } else {
43            setMR(receiver, receiveIPCBuffer, seL4_VMFault_IP, getRestartPC(sender));
44        }
45        setMR(receiver, receiveIPCBuffer, seL4_VMFault_Addr,
46              seL4_Fault_VMFault_get_address(sender->tcbFault));
47        setMR(receiver, receiveIPCBuffer, seL4_VMFault_PrefetchFault,
48              seL4_Fault_VMFault_get_instructionFault(sender->tcbFault));
49        return setMR(receiver, receiveIPCBuffer, seL4_VMFault_FSR,
50                     seL4_Fault_VMFault_get_FSR(sender->tcbFault));
51    }
52
53#ifdef CONFIG_ARM_HYPERVISOR_SUPPORT
54    case seL4_Fault_VGICMaintenance:
55        if (seL4_Fault_VGICMaintenance_get_idxValid(sender->tcbFault)) {
56            return setMR(receiver, receiveIPCBuffer, seL4_VGICMaintenance_IDX,
57                         seL4_Fault_VGICMaintenance_get_idx(sender->tcbFault));
58        } else {
59            return setMR(receiver, receiveIPCBuffer, seL4_VGICMaintenance_IDX, -1);
60        }
61    case seL4_Fault_VCPUFault:
62        return setMR(receiver, receiveIPCBuffer, seL4_VCPUFault_HSR, seL4_Fault_VCPUFault_get_hsr(sender->tcbFault));
63    case seL4_Fault_VPPIEvent:
64        return setMR(receiver, receiveIPCBuffer, seL4_VPPIEvent_IRQ, seL4_Fault_VPPIEvent_get_irq_w(sender->tcbFault));
65#endif
66
67    default:
68        fail("Invalid fault");
69    }
70}
71