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