• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 Institute of Parallel And Distributed Systems (IPADS), Shanghai Jiao Tong University (SJTU)
3  * Licensed under the Mulan PSL v2.
4  * You can use this software according to the terms and conditions of the Mulan PSL v2.
5  * You may obtain a copy of Mulan PSL v2 at:
6  *     http://license.coscl.org.cn/MulanPSL2
7  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
8  * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
9  * PURPOSE.
10  * See the Mulan PSL v2 for more details.
11  */
12 #include <arch/machine/esr.h>
13 #include <arch/mmu.h>
14 #include <common/types.h>
15 #include <mm/extable.h>
16 #include <mm/page_fault.h>
17 #include <mm/vmspace.h>
18 #include <object/recycle.h>
19 #include <object/thread.h>
20 
21 #include "irq_entry.h"
22 
get_fault_addr(void)23 static inline vaddr_t get_fault_addr(void)
24 {
25     vaddr_t addr;
26     asm volatile("mrs %0, far_el1\n\t" : "=r"(addr));
27     return addr;
28 }
29 
__do_kernel_fault(u64 esr,u64 fault_ins_addr,u64 * fix_addr)30 static void __do_kernel_fault(u64 esr, u64 fault_ins_addr, u64 *fix_addr)
31 {
32     kdebug("kernel_fault triggered\n");
33     if (fixup_exception(fault_ins_addr, fix_addr)) {
34         return;
35     }
36 
37     BUG_ON(1);
38 
39     sys_exit_group(-1);
40 }
41 
42 // EC: Instruction Abort or Data Abort
do_page_fault(u64 esr,u64 fault_ins_addr,int type,u64 * fix_addr)43 void do_page_fault(u64 esr, u64 fault_ins_addr, int type, u64 *fix_addr)
44 {
45     vaddr_t fault_addr;
46     int fsc; // fault status code
47     int wnr;
48     int ret;
49 
50     fault_addr = get_fault_addr();
51     fsc = GET_ESR_EL1_FSC(esr);
52     switch (fsc) {
53     case DFSC_TRANS_FAULT_L0:
54     case DFSC_TRANS_FAULT_L1:
55     case DFSC_TRANS_FAULT_L2:
56     case DFSC_TRANS_FAULT_L3: {
57         ret = handle_trans_fault(current_thread->vmspace, fault_addr);
58         if (ret != 0) {
59             /* The trap happens in the kernel */
60             if (type < SYNC_EL0_64) {
61                 goto no_context;
62             }
63 
64             kinfo("do_page_fault: faulting ip is 0x%lx (real IP),"
65                   "faulting address is 0x%lx,"
66                   "fsc is trans_fault (0b%b),"
67                   "type is %d\n",
68                   fault_ins_addr,
69                   fault_addr,
70                   fsc,
71                   type);
72             kprint_vmr(current_thread->vmspace);
73 
74             kinfo("current_cap_group is %s\n",
75                   current_cap_group->cap_group_name);
76 
77             sys_exit_group(-1);
78         }
79         break;
80     }
81     case DFSC_PERM_FAULT_L1:
82     case DFSC_PERM_FAULT_L2:
83     case DFSC_PERM_FAULT_L3:
84         wnr = GET_ESR_EL1_WnR(esr);
85         if (wnr) {
86             ret = handle_perm_fault(
87                 current_thread->vmspace, fault_addr, VMR_WRITE);
88         } else {
89             ret = handle_perm_fault(
90                 current_thread->vmspace, fault_addr, VMR_READ);
91         }
92 
93         if (ret != 0) {
94             /* The trap happens in the kernel */
95             if (type < SYNC_EL0_64) {
96                 goto no_context;
97             }
98             sys_exit_group(-1);
99         }
100         break;
101     case DFSC_ACCESS_FAULT_L1:
102     case DFSC_ACCESS_FAULT_L2:
103     case DFSC_ACCESS_FAULT_L3:
104         kinfo("do_page_fault: fsc is access_fault (0b%b)\n", fsc);
105         BUG_ON(1);
106         break;
107     default:
108         kinfo("do_page_fault: faulting ip is 0x%lx (real IP),"
109               "faulting address is 0x%lx,"
110               "fsc is unsupported now (0b%b)\n",
111               fault_ins_addr,
112               fault_addr,
113               fsc);
114         kprint_vmr(current_thread->vmspace);
115 
116         kinfo("current_cap_group is %s\n", current_cap_group->cap_group_name);
117 
118         BUG_ON(1);
119         break;
120     }
121 
122     return;
123 
124 no_context:
125     kinfo("kernel_fault: faulting ip is 0x%lx (real IP),"
126           "faulting address is 0x%lx,"
127           "fsc is 0b%b\n",
128           fault_ins_addr,
129           fault_addr,
130           fsc);
131     __do_kernel_fault(esr, fault_ins_addr, fix_addr);
132 }
133