• 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 <irq/irq.h>
13 #include <common/types.h>
14 #include <common/kprint.h>
15 #include <common/util.h>
16 #include <sched/sched.h>
17 #include <sched/fpu.h>
18 #include <arch/machine/smp.h>
19 #include <arch/machine/esr.h>
20 #include <arch/trustzone/smc.h>
21 #include "irq_entry.h"
22 
23 u8 irq_handle_type[MAX_IRQ_NUM];
24 
arch_enable_irqno(int irq)25 void arch_enable_irqno(int irq)
26 {
27     plat_enable_irqno(irq);
28 }
29 
arch_disable_irqno(int irq)30 void arch_disable_irqno(int irq)
31 {
32     plat_disable_irqno(irq);
33 }
34 
arch_interrupt_init_per_cpu(void)35 void arch_interrupt_init_per_cpu(void)
36 {
37     disable_irq();
38 
39     /* platform dependent init */
40     set_exception_vector();
41     plat_interrupt_init();
42 }
43 
arch_interrupt_init(void)44 void arch_interrupt_init(void)
45 {
46     arch_interrupt_init_per_cpu();
47     memset(irq_handle_type, HANDLE_KERNEL, MAX_IRQ_NUM);
48 }
49 
handle_entry_c(int type,u64 esr,u64 address)50 u64 handle_entry_c(int type, u64 esr, u64 address)
51 {
52     /* ec: exception class */
53     u32 esr_ec = GET_ESR_EL1_EC(esr);
54 
55     kdebug("Exception type: %d, ESR: 0x%lx, Fault address: 0x%lx, "
56            "EC 0b%b\n",
57            type,
58            esr,
59            address,
60            esr_ec);
61 
62     /* Currently, ChCore only handles a part of IRQs */
63     if (type < SYNC_EL0_64) {
64         if (esr_ec != ESR_EL1_EC_DABT_CEL) {
65             kinfo("%s: irq type is %d\n", __func__, type);
66             BUG_ON(1);
67         }
68     }
69 
70     u64 fix_addr = 0;
71     /* Dispatch exception according to EC */
72     switch (esr_ec) {
73     case ESR_EL1_EC_UNKNOWN:
74         kdebug("Unknown\n");
75         break;
76     case ESR_EL1_EC_WFI_WFE:
77         kdebug("Trapped WFI or WFE instruction execution\n");
78         return address;
79     case ESR_EL1_EC_ENFP:
80 #if FPU_SAVING_MODE == LAZY_FPU_MODE
81         /*
82          * Disable FPU in EL1: IRQ type is SYNC_EL1h (4).
83          * Disable FPU in EL0: IRQ type is SYNC_EL0_64 (8).
84          */
85         change_fpu_owner();
86         return address;
87 #else
88         kdebug(
89             "Access to SVE, Advanced SIMD, or floating-point functionality\n");
90         break;
91 #endif
92     case ESR_EL1_EC_ILLEGAL_EXEC:
93         kdebug("Illegal Execution state\n");
94         break;
95     case ESR_EL1_EC_SVC_32:
96         kdebug("SVC instruction execution in AArch32 state\n");
97         break;
98     case ESR_EL1_EC_SVC_64:
99         kdebug("SVC instruction execution in AArch64 state\n");
100         break;
101     case ESR_EL1_EC_MRS_MSR_64:
102         kdebug("Using MSR or MRS from a lower Exception level\n");
103         break;
104     case ESR_EL1_EC_IABT_LEL:
105         kdebug("Instruction Abort from a lower Exception level\n");
106         /* Page fault handler here:
107          * dynamic loading can trigger faults here.
108          */
109         do_page_fault(esr, address, type, &fix_addr);
110         return address;
111     case ESR_EL1_EC_IABT_CEL:
112         kinfo("Instruction Abort from current Exception level\n");
113         break;
114     case ESR_EL1_EC_PC_ALIGN:
115         kdebug("PC alignment fault exception\n");
116         break;
117     case ESR_EL1_EC_DABT_LEL:
118         kdebug("Data Abort from a lower Exception level\n");
119         /* Handle faults caused by data access.
120          * We only consider page faults for now.
121          */
122         do_page_fault(esr, address, type, &fix_addr);
123         return address;
124     case ESR_EL1_EC_DABT_CEL:
125         kdebug("Data Abort from a current Exception level\n");
126         do_page_fault(esr, address, type, &fix_addr);
127 
128         if (fix_addr)
129             return fix_addr;
130         else
131             return address;
132     case ESR_EL1_EC_SP_ALIGN:
133         kdebug("SP alignment fault exception\n");
134         break;
135     case ESR_EL1_EC_FP_32:
136         kdebug("Trapped floating-point exception taken from AArch32 state\n");
137         break;
138     case ESR_EL1_EC_FP_64:
139         kdebug("Trapped floating-point exception taken from AArch64 state\n");
140         break;
141     case ESR_EL1_EC_SError:
142         kdebug("SERROR\n");
143         break;
144     default:
145         kdebug("Unsupported Exception ESR %lx\n", esr);
146         break;
147     }
148 
149     kinfo("Exception type: %d, ESR: 0x%lx, Fault address: 0x%lx, "
150           "EC 0b%b\n",
151           type,
152           esr,
153           address,
154           esr_ec);
155 
156     BUG_ON(1);
157 }
158 
159 /* Interrupt handler for interrupts happening when in EL0. */
handle_irq(void)160 void handle_irq(void)
161 {
162     plat_handle_irq();
163     sched();
164     eret_to_thread(switch_context());
165 }
166 
167 /* Interrupt handler for interrupts happening when in EL1 (idle thread). */
handle_irq_el1(u64 elr_el1)168 void handle_irq_el1(u64 elr_el1)
169 {
170     /* Just reuse the same interrupt handler for EL0. */
171     handle_irq();
172 }
173 
unexpected_handler(void)174 void unexpected_handler(void)
175 {
176     kinfo("[fatal error] %s is invoked\n", __func__);
177     BUG_ON(1);
178 }
179 
handle_fiq(void)180 void handle_fiq(void)
181 {
182     save_and_release_fpu_owner();
183     smc_call(SMC_STD_RESPONSE, SMC_EXIT_PREEMPTED);
184 }
185