• 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 <ipc/notification.h>
13 #include <irq/irq.h>
14 #include <object/irq.h>
15 #include <common/errno.h>
16 #include <sched/context.h>
17 
18 
19 
20 struct irq_notification *irq_notifcs[MAX_IRQ_NUM];
user_handle_irq(int irq)21 int user_handle_irq(int irq)
22 {
23     struct irq_notification *irq_notic;
24 
25     irq_notic = irq_notifcs[irq];
26 
27     /*
28      * If the interrupt handler thread is not ready for handling a new
29      * interrupt, we ignore a nested interrupt.
30      */
31     if (!irq_notic || !irq_notic->user_handler_ready) {
32         kdebug("One interrupt (irq: %d) is ingored since the handler "
33                "thread is not ready.\n",
34                irq);
35         return 0;
36     }
37 
38     /*
39      * Disable the irq before passing the current irq to the
40      * user-level handler thread.
41      */
42     arch_disable_irqno(irq_notic->intr_vector);
43 
44     signal_irq_notific(irq_notic);
45     sched();
46     eret_to_thread(switch_context());
47     /* Never returns. */
48 
49     BUG_ON(1);
50     return 0;
51 }
52 
irq_deinit(void * irq_ptr)53 void irq_deinit(void *irq_ptr)
54 {
55     struct irq_notification *irq_notifc;
56     int irq;
57 
58     irq_notifc = (struct irq_notification *)irq_ptr;
59     irq = irq_notifc->intr_vector;
60     irq_handle_type[irq] = HANDLE_KERNEL;
61     smp_mb();
62     irq_notifcs[irq] = NULL;
63 }
64 
sys_irq_register(int irq)65 cap_t sys_irq_register(int irq)
66 {
67     struct irq_notification *irq_notifc = NULL;
68     cap_t irq_notifc_cap = 0;
69     int ret = 0;
70 
71     if (irq < 0 || irq >= MAX_IRQ_NUM)
72         return -EINVAL;
73 
74     irq_notifc = obj_alloc(TYPE_IRQ, sizeof(*irq_notifc));
75     if (!irq_notifc) {
76         ret = -ENOMEM;
77         goto out_fail;
78     }
79     irq_notifc->intr_vector = irq;
80     init_notific(&irq_notifc->notifc);
81     irq_notifc->user_handler_ready = 0;
82 
83     irq_notifc_cap = cap_alloc(current_cap_group, irq_notifc);
84     if (irq_notifc_cap < 0) {
85         ret = irq_notifc_cap;
86         goto out_free_obj;
87     }
88 
89     irq_notifcs[irq] = irq_notifc;
90     smp_mb();
91     irq_handle_type[irq] = HANDLE_USER;
92 
93     return irq_notifc_cap;
94 out_free_obj:
95     obj_free(irq_notifc);
96 out_fail:
97     return ret;
98 }
99 
sys_irq_stop(cap_t irq_cap)100 int sys_irq_stop(cap_t irq_cap)
101 {
102     struct irq_notification *irq_notifc = NULL;
103     int ret = 0;
104     irq_notifc = obj_get(current_thread->cap_group, irq_cap, TYPE_IRQ);
105     if (!irq_notifc) {
106         ret = -ECAPBILITY;
107         goto out;
108     }
109 
110     ret = stop_irq_notific(irq_notifc);
111 
112 out:
113     return ret;
114 }
115 
sys_irq_wait(cap_t irq_cap,bool is_block)116 int sys_irq_wait(cap_t irq_cap, bool is_block)
117 {
118     struct irq_notification *irq_notifc = NULL;
119     int ret = 0;
120     irq_notifc = obj_get(current_thread->cap_group, irq_cap, TYPE_IRQ);
121     if (!irq_notifc) {
122         ret = -ECAPBILITY;
123         goto out;
124     }
125 
126     /*
127      * When the interrupt handler thread calls this function,
128      * we enable the corresponding irq.
129      */
130     arch_enable_irqno(irq_notifc->intr_vector);
131     ret = wait_irq_notific(irq_notifc);
132     if (ret) {
133         goto out;
134     }
135 
136     /* Never returns */
137     BUG_ON(1);
138 
139 out:
140     return ret;
141 }
142 
sys_irq_ack(cap_t irq_cap)143 int sys_irq_ack(cap_t irq_cap)
144 {
145     struct irq_notification *irq_notifc = NULL;
146     int ret = 0;
147     irq_notifc = obj_get(current_thread->cap_group, irq_cap, TYPE_IRQ);
148     if (!irq_notifc) {
149         ret = -ECAPBILITY;
150         goto out;
151     }
152     plat_ack_irq(irq_notifc->intr_vector);
153     obj_put(irq_notifc);
154 out:
155     return ret;
156 }
157 
sys_disable_irqno(int irq)158 int sys_disable_irqno(int irq)
159 {
160     plat_disable_irqno(irq);
161     return 0;
162 }
163 
sys_enable_irqno(int irq)164 int sys_enable_irqno(int irq)
165 {
166     plat_enable_irqno(irq);
167     return 0;
168 }
169 
sys_irq_op(int irq,int op,long val)170 int sys_irq_op(int irq, int op, long val)
171 {
172     extern int gicv3_op(int irq, int op, long val);
173     return gicv3_op(irq, op, val);
174 }