2 * Copyright 2023 Linaro Ltd.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see http://www.gnu.org/copyleft/gpl.txt
19 #include "smatch_slist.h"
23 bool in_irq_context(void)
25 if (has_possible_state(my_id
, "irq_context", NULL
, &true_state
))
30 void clear_irq_context(void)
32 struct smatch_state
*state
;
34 state
= get_state(my_id
, "irq_context", NULL
);
37 set_state(my_id
, "irq_context", NULL
, &undefined
);
40 static int db_set_irq(void *_found
, int argc
, char **argv
, char **azColName
)
47 static bool is_irq_handler(void)
54 run_sql(db_set_irq
, &found
,
55 "select * from fn_data_link where file = 0x%llx and function = '%s' and static = %d and type = %d;",
56 (cur_func_sym
->ctype
.modifiers
& MOD_STATIC
) ? get_base_file_id() : 0,
57 cur_func_sym
->ident
->name
,
58 !!(cur_func_sym
->ctype
.modifiers
& MOD_STATIC
),
64 static void match_declaration(struct symbol
*sym
)
66 if (!is_irq_handler())
69 set_state(my_id
, "irq_context", NULL
, &true_state
);
72 static void match_request_irq(struct expression
*expr
, const char *name
, struct symbol
*sym
, void *data
)
74 struct expression
*handler
;
75 sval_t sval
= int_zero
;
77 while (expr
&& expr
->type
== EXPR_ASSIGNMENT
)
78 expr
= strip_expr(expr
->right
);
79 if (!expr
|| expr
->type
!= EXPR_CALL
)
82 handler
= get_argument_from_call_expr(expr
->args
, 1);
83 if (!get_implied_value(handler
, &sval
))
86 sql_insert_fn_data_link(handler
, IRQ_CONTEXT
, -1, "", "");
89 static void match_request_threaded_irq(struct expression
*expr
, const char *name
, struct symbol
*sym
, void *data
)
91 struct expression
*thread
;
93 while (expr
&& expr
->type
== EXPR_ASSIGNMENT
)
94 expr
= strip_expr(expr
->right
);
95 if (!expr
|| expr
->type
!= EXPR_CALL
)
98 thread
= get_argument_from_call_expr(expr
->args
, 2);
99 if (!expr_is_zero(thread
))
101 if (get_function() && strcmp(get_function(), "request_irq") == 0)
104 sm_warning("why call request_threaded_irq() with a NULL thread");
107 static void match_in_irq(struct expression
*expr
)
109 char *macro
= get_macro_name(expr
->pos
);
111 if (!macro
|| strcmp(macro
, "in_irq") != 0)
113 set_true_false_states(my_id
, "irq_context", NULL
, NULL
, &undefined
);
116 static bool is_ignored_fn(struct expression
*expr
)
121 fn
= get_fnptr_name(expr
->fn
);
125 if (strcmp(fn
, "bus_for_each_drv") == 0 ||
126 strcmp(fn
, "call_mmap") == 0 ||
127 strcmp(fn
, "(struct comedi_subdevice)->cancel") == 0 ||
128 strcmp(fn
, "(struct flexcop_device)->read_ibi_reg") == 0 ||
129 strcmp(fn
, "(struct irqaction)->handler") == 0 || /* called from __handle_irq_event_percpu() */
130 strcmp(fn
, "(struct spi_message)->complete") == 0 ||
131 strcmp(fn
, "(struct usb_gadget_driver)->setup") == 0 ||
132 strcmp(fn
, "(struct v4l2_subdev_core_ops)->interrupt_service_routine") == 0 ||
133 strcmp(fn
, "call_mmap") == 0)
140 static void match_call_info(struct expression
*expr
)
142 if (!in_irq_context())
145 if (is_ignored_fn(expr
))
148 sql_insert_caller_info(expr
, IRQ_CONTEXT
, -1, "", is_irq_handler() ? "<- IRQ handler" : "");
151 static void select_call_info(const char *name
, struct symbol
*sym
, char *key
, char *value
)
153 set_state(my_id
, "irq_context", NULL
, &true_state
);
156 void register_kernel_irq_context(int id
)
158 if (option_project
!= PROJ_KERNEL
)
163 add_function_param_key_hook("request_irq", &match_request_irq
, 1, "$", NULL
);
164 add_function_param_key_hook("request_threaded_irq", &match_request_threaded_irq
, 1, "$", NULL
);
165 add_hook(&match_in_irq
, CONDITION_HOOK
);
167 add_hook(&match_call_info
, FUNCTION_CALL_HOOK
);
168 select_caller_info_hook(&select_call_info
, IRQ_CONTEXT
);
169 add_hook(&match_declaration
, DECLARATION_HOOK
);