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 
Arch_handleFaultReply(tcb_t * receiver,tcb_t * sender,word_t faultType)14 bool_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 
Arch_setMRs_fault(tcb_t * sender,tcb_t * receiver,word_t * receiveIPCBuffer,word_t faultType)33 word_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