xref: /openbmc/linux/kernel/extable.c (revision 505f2b970b2269ce4cb669b3ff4f6479d379cec2)
11da177e4SLinus Torvalds /* Rewritten by Rusty Russell, on the backs of many others...
21da177e4SLinus Torvalds    Copyright (C) 2001 Rusty Russell, 2002 Rusty Russell IBM.
31da177e4SLinus Torvalds 
41da177e4SLinus Torvalds     This program is free software; you can redistribute it and/or modify
51da177e4SLinus Torvalds     it under the terms of the GNU General Public License as published by
61da177e4SLinus Torvalds     the Free Software Foundation; either version 2 of the License, or
71da177e4SLinus Torvalds     (at your option) any later version.
81da177e4SLinus Torvalds 
91da177e4SLinus Torvalds     This program is distributed in the hope that it will be useful,
101da177e4SLinus Torvalds     but WITHOUT ANY WARRANTY; without even the implied warranty of
111da177e4SLinus Torvalds     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
121da177e4SLinus Torvalds     GNU General Public License for more details.
131da177e4SLinus Torvalds 
141da177e4SLinus Torvalds     You should have received a copy of the GNU General Public License
151da177e4SLinus Torvalds     along with this program; if not, write to the Free Software
161da177e4SLinus Torvalds     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
171da177e4SLinus Torvalds */
188b96f011SFrederic Weisbecker #include <linux/ftrace.h>
19*505f2b97SIngo Molnar #include <linux/module.h>
20*505f2b97SIngo Molnar #include <linux/mutex.h>
21*505f2b97SIngo Molnar #include <linux/init.h>
22*505f2b97SIngo Molnar 
231da177e4SLinus Torvalds #include <asm/sections.h>
24*505f2b97SIngo Molnar #include <asm/uaccess.h>
25*505f2b97SIngo Molnar 
26*505f2b97SIngo Molnar /*
27*505f2b97SIngo Molnar  * mutex protecting text section modification (dynamic code patching).
28*505f2b97SIngo Molnar  * some users need to sleep (allocating memory...) while they hold this lock.
29*505f2b97SIngo Molnar  *
30*505f2b97SIngo Molnar  * NOT exported to modules - patching kernel text is a really delicate matter.
31*505f2b97SIngo Molnar  */
32*505f2b97SIngo Molnar DEFINE_MUTEX(text_mutex);
331da177e4SLinus Torvalds 
341da177e4SLinus Torvalds extern struct exception_table_entry __start___ex_table[];
351da177e4SLinus Torvalds extern struct exception_table_entry __stop___ex_table[];
361da177e4SLinus Torvalds 
371da177e4SLinus Torvalds /* Sort the kernel's built-in exception table */
381da177e4SLinus Torvalds void __init sort_main_extable(void)
391da177e4SLinus Torvalds {
401da177e4SLinus Torvalds 	sort_extable(__start___ex_table, __stop___ex_table);
411da177e4SLinus Torvalds }
421da177e4SLinus Torvalds 
431da177e4SLinus Torvalds /* Given an address, look for it in the exception tables. */
441da177e4SLinus Torvalds const struct exception_table_entry *search_exception_tables(unsigned long addr)
451da177e4SLinus Torvalds {
461da177e4SLinus Torvalds 	const struct exception_table_entry *e;
471da177e4SLinus Torvalds 
481da177e4SLinus Torvalds 	e = search_extable(__start___ex_table, __stop___ex_table-1, addr);
491da177e4SLinus Torvalds 	if (!e)
501da177e4SLinus Torvalds 		e = search_module_extables(addr);
511da177e4SLinus Torvalds 	return e;
521da177e4SLinus Torvalds }
531da177e4SLinus Torvalds 
543861a17bSFrederic Weisbecker int core_kernel_text(unsigned long addr)
551da177e4SLinus Torvalds {
561da177e4SLinus Torvalds 	if (addr >= (unsigned long)_stext &&
571da177e4SLinus Torvalds 	    addr <= (unsigned long)_etext)
581da177e4SLinus Torvalds 		return 1;
591da177e4SLinus Torvalds 
60a2da4052SRusty Russell 	if (system_state == SYSTEM_BOOTING &&
61a2da4052SRusty Russell 	    addr >= (unsigned long)_sinittext &&
621da177e4SLinus Torvalds 	    addr <= (unsigned long)_einittext)
631da177e4SLinus Torvalds 		return 1;
641da177e4SLinus Torvalds 	return 0;
651da177e4SLinus Torvalds }
661da177e4SLinus Torvalds 
673861a17bSFrederic Weisbecker int __kernel_text_address(unsigned long addr)
681da177e4SLinus Torvalds {
691da177e4SLinus Torvalds 	if (core_kernel_text(addr))
701da177e4SLinus Torvalds 		return 1;
711da177e4SLinus Torvalds 	return __module_text_address(addr) != NULL;
721da177e4SLinus Torvalds }
731da177e4SLinus Torvalds 
741da177e4SLinus Torvalds int kernel_text_address(unsigned long addr)
751da177e4SLinus Torvalds {
761da177e4SLinus Torvalds 	if (core_kernel_text(addr))
771da177e4SLinus Torvalds 		return 1;
781da177e4SLinus Torvalds 	return module_text_address(addr) != NULL;
791da177e4SLinus Torvalds }
80ab7476cfSArjan van de Ven 
81ab7476cfSArjan van de Ven /*
82ab7476cfSArjan van de Ven  * On some architectures (PPC64, IA64) function pointers
83ab7476cfSArjan van de Ven  * are actually only tokens to some data that then holds the
84ab7476cfSArjan van de Ven  * real function address. As a result, to find if a function
85ab7476cfSArjan van de Ven  * pointer is part of the kernel text, we need to do some
86ab7476cfSArjan van de Ven  * special dereferencing first.
87ab7476cfSArjan van de Ven  */
88ab7476cfSArjan van de Ven int func_ptr_is_kernel_text(void *ptr)
89ab7476cfSArjan van de Ven {
90ab7476cfSArjan van de Ven 	unsigned long addr;
91ab7476cfSArjan van de Ven 	addr = (unsigned long) dereference_function_descriptor(ptr);
92ab7476cfSArjan van de Ven 	if (core_kernel_text(addr))
93ab7476cfSArjan van de Ven 		return 1;
94ab7476cfSArjan van de Ven 	return module_text_address(addr) != NULL;
95ab7476cfSArjan van de Ven }
96