Linux Audio

Check our new training course

Loading...
v4.17
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * linux/arch/sparc/mm/extable.c
  4 */
  5
  6#include <linux/module.h>
  7#include <linux/extable.h>
  8#include <linux/uaccess.h>
  9
 10void sort_extable(struct exception_table_entry *start,
 11		  struct exception_table_entry *finish)
 12{
 13}
 14
 15/* Caller knows they are in a range if ret->fixup == 0 */
 16const struct exception_table_entry *
 17search_extable(const struct exception_table_entry *base,
 18	       const size_t num,
 19	       unsigned long value)
 20{
 21	int i;
 22
 23	/* Single insn entries are encoded as:
 24	 *	word 1:	insn address
 25	 *	word 2:	fixup code address
 26	 *
 27	 * Range entries are encoded as:
 28	 *	word 1: first insn address
 29	 *	word 2: 0
 30	 *	word 3: last insn address + 4 bytes
 31	 *	word 4: fixup code address
 32	 *
 33	 * Deleted entries are encoded as:
 34	 *	word 1: unused
 35	 *	word 2: -1
 36	 *
 37	 * See asm/uaccess.h for more details.
 38	 */
 39
 40	/* 1. Try to find an exact match. */
 41	for (i = 0; i < num; i++) {
 42		if (base[i].fixup == 0) {
 43			/* A range entry, skip both parts. */
 44			i++;
 45			continue;
 46		}
 47
 48		/* A deleted entry; see trim_init_extable */
 49		if (base[i].fixup == -1)
 50			continue;
 51
 52		if (base[i].insn == value)
 53			return &base[i];
 54	}
 55
 56	/* 2. Try to find a range match. */
 57	for (i = 0; i < (num - 1); i++) {
 58		if (base[i].fixup)
 59			continue;
 60
 61		if (base[i].insn <= value && base[i + 1].insn > value)
 62			return &base[i];
 63
 64		i++;
 65	}
 66
 67        return NULL;
 68}
 69
 70#ifdef CONFIG_MODULES
 71/* We could memmove them around; easier to mark the trimmed ones. */
 72void trim_init_extable(struct module *m)
 73{
 74	unsigned int i;
 75	bool range;
 76
 77	for (i = 0; i < m->num_exentries; i += range ? 2 : 1) {
 78		range = m->extable[i].fixup == 0;
 79
 80		if (within_module_init(m->extable[i].insn, m)) {
 81			m->extable[i].fixup = -1;
 82			if (range)
 83				m->extable[i+1].fixup = -1;
 84		}
 85		if (range)
 86			i++;
 87	}
 88}
 89#endif /* CONFIG_MODULES */
 90
 91/* Special extable search, which handles ranges.  Returns fixup */
 92unsigned long search_extables_range(unsigned long addr, unsigned long *g2)
 93{
 94	const struct exception_table_entry *entry;
 95
 96	entry = search_exception_tables(addr);
 97	if (!entry)
 98		return 0;
 99
100	/* Inside range?  Fix g2 and return correct fixup */
101	if (!entry->fixup) {
102		*g2 = (addr - entry->insn) / 4;
103		return (entry + 1)->fixup;
104	}
105
106	return entry->fixup;
107}
v3.1
 
  1/*
  2 * linux/arch/sparc/mm/extable.c
  3 */
  4
  5#include <linux/module.h>
  6#include <asm/uaccess.h>
 
  7
  8void sort_extable(struct exception_table_entry *start,
  9		  struct exception_table_entry *finish)
 10{
 11}
 12
 13/* Caller knows they are in a range if ret->fixup == 0 */
 14const struct exception_table_entry *
 15search_extable(const struct exception_table_entry *start,
 16	       const struct exception_table_entry *last,
 17	       unsigned long value)
 18{
 19	const struct exception_table_entry *walk;
 20
 21	/* Single insn entries are encoded as:
 22	 *	word 1:	insn address
 23	 *	word 2:	fixup code address
 24	 *
 25	 * Range entries are encoded as:
 26	 *	word 1: first insn address
 27	 *	word 2: 0
 28	 *	word 3: last insn address + 4 bytes
 29	 *	word 4: fixup code address
 30	 *
 31	 * Deleted entries are encoded as:
 32	 *	word 1: unused
 33	 *	word 2: -1
 34	 *
 35	 * See asm/uaccess.h for more details.
 36	 */
 37
 38	/* 1. Try to find an exact match. */
 39	for (walk = start; walk <= last; walk++) {
 40		if (walk->fixup == 0) {
 41			/* A range entry, skip both parts. */
 42			walk++;
 43			continue;
 44		}
 45
 46		/* A deleted entry; see trim_init_extable */
 47		if (walk->fixup == -1)
 48			continue;
 49
 50		if (walk->insn == value)
 51			return walk;
 52	}
 53
 54	/* 2. Try to find a range match. */
 55	for (walk = start; walk <= (last - 1); walk++) {
 56		if (walk->fixup)
 57			continue;
 58
 59		if (walk[0].insn <= value && walk[1].insn > value)
 60			return walk;
 61
 62		walk++;
 63	}
 64
 65        return NULL;
 66}
 67
 68#ifdef CONFIG_MODULES
 69/* We could memmove them around; easier to mark the trimmed ones. */
 70void trim_init_extable(struct module *m)
 71{
 72	unsigned int i;
 73	bool range;
 74
 75	for (i = 0; i < m->num_exentries; i += range ? 2 : 1) {
 76		range = m->extable[i].fixup == 0;
 77
 78		if (within_module_init(m->extable[i].insn, m)) {
 79			m->extable[i].fixup = -1;
 80			if (range)
 81				m->extable[i+1].fixup = -1;
 82		}
 83		if (range)
 84			i++;
 85	}
 86}
 87#endif /* CONFIG_MODULES */
 88
 89/* Special extable search, which handles ranges.  Returns fixup */
 90unsigned long search_extables_range(unsigned long addr, unsigned long *g2)
 91{
 92	const struct exception_table_entry *entry;
 93
 94	entry = search_exception_tables(addr);
 95	if (!entry)
 96		return 0;
 97
 98	/* Inside range?  Fix g2 and return correct fixup */
 99	if (!entry->fixup) {
100		*g2 = (addr - entry->insn) / 4;
101		return (entry + 1)->fixup;
102	}
103
104	return entry->fixup;
105}