s390/extable: convert to relative table with data

Follow arm64, riscv, and x86 and change extable layout to common
"relative table with data". This allows to get rid of s390 specific
code in sorttable.c.

The main difference to before is that extable entries do not contain a
relative function pointer anymore. Instead data and type fields are
added.

The type field is used to indicate which exception handler needs to be
called, while the data field is currently unused.

Acked-by: Alexander Gordeev <agordeev@linux.ibm.com>
Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
This commit is contained in:
Heiko Carstens 2022-02-28 14:52:42 +01:00 committed by Vasily Gorbik
parent 46fee16f57
commit 3d66718cd6
5 changed files with 46 additions and 74 deletions

View File

@ -5,17 +5,22 @@
#include <linux/stringify.h>
#include <asm/asm-const.h>
#define __EX_TABLE(_section, _fault, _target) \
#define EX_TYPE_NONE 0
#define EX_TYPE_FIXUP 1
#define EX_TYPE_BPF 2
#define __EX_TABLE(_section, _fault, _target, _type) \
stringify_in_c(.section _section,"a";) \
stringify_in_c(.align 8;) \
stringify_in_c(.align 4;) \
stringify_in_c(.long (_fault) - .;) \
stringify_in_c(.long (_target) - .;) \
stringify_in_c(.quad 0;) \
stringify_in_c(.short (_type);) \
stringify_in_c(.short 0;) \
stringify_in_c(.previous)
#define EX_TABLE(_fault, _target) \
__EX_TABLE(__ex_table, _fault, _target)
__EX_TABLE(__ex_table, _fault, _target, EX_TYPE_FIXUP)
#define EX_TABLE_AMODE31(_fault, _target) \
__EX_TABLE(.amode31.ex_table, _fault, _target)
__EX_TABLE(.amode31.ex_table, _fault, _target, EX_TYPE_FIXUP)
#endif /* __ASM_EXTABLE_H */

View File

@ -25,7 +25,7 @@
struct exception_table_entry
{
int insn, fixup;
long handler;
short type, data;
};
extern struct exception_table_entry *__start_amode31_ex_table;
@ -38,17 +38,6 @@ static inline unsigned long extable_fixup(const struct exception_table_entry *x)
return (unsigned long)&x->fixup + x->fixup;
}
typedef bool (*ex_handler_t)(const struct exception_table_entry *,
struct pt_regs *);
static inline ex_handler_t
ex_fixup_handler(const struct exception_table_entry *x)
{
if (likely(!x->handler))
return NULL;
return (ex_handler_t)((unsigned long)&x->handler + x->handler);
}
#define ARCH_HAS_RELATIVE_EXTABLE
static inline void swap_ex_entry_fixup(struct exception_table_entry *a,
@ -58,15 +47,26 @@ static inline void swap_ex_entry_fixup(struct exception_table_entry *a,
{
a->fixup = b->fixup + delta;
b->fixup = tmp.fixup - delta;
a->handler = b->handler;
if (a->handler)
a->handler += delta;
b->handler = tmp.handler;
if (b->handler)
b->handler -= delta;
a->type = b->type;
b->type = tmp.type;
a->data = b->data;
b->data = tmp.data;
}
#define swap_ex_entry_fixup swap_ex_entry_fixup
#ifdef CONFIG_BPF_JIT
bool ex_handler_bpf(const struct exception_table_entry *ex, struct pt_regs *regs);
#else /* !CONFIG_BPF_JIT */
static inline bool ex_handler_bpf(const struct exception_table_entry *ex, struct pt_regs *regs)
{
return false;
}
#endif /* CONFIG_BPF_JIT */
bool fixup_exception(struct pt_regs *regs);
#endif

View File

@ -1,6 +1,8 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/extable.h>
#include <linux/panic.h>
#include <asm/asm-extable.h>
#include <asm/extable.h>
const struct exception_table_entry *s390_search_extables(unsigned long addr)
@ -15,17 +17,24 @@ const struct exception_table_entry *s390_search_extables(unsigned long addr)
return search_extable(__start_amode31_ex_table, num, addr);
}
static bool ex_handler_fixup(const struct exception_table_entry *ex, struct pt_regs *regs)
{
regs->psw.addr = extable_fixup(ex);
return true;
}
bool fixup_exception(struct pt_regs *regs)
{
const struct exception_table_entry *ex;
ex_handler_t handler;
ex = s390_search_extables(instruction_pointer(regs));
if (!ex)
return false;
handler = ex_fixup_handler(ex);
if (unlikely(handler))
return handler(ex, regs);
regs->psw.addr = extable_fixup(ex);
return true;
switch (ex->type) {
case EX_TYPE_FIXUP:
return ex_handler_fixup(ex, regs);
case EX_TYPE_BPF:
return ex_handler_bpf(ex, regs);
}
panic("invalid exception table entry");
}

View File

@ -622,8 +622,7 @@ static int get_probe_mem_regno(const u8 *insn)
return insn[1] >> 4;
}
static bool ex_handler_bpf(const struct exception_table_entry *x,
struct pt_regs *regs)
bool ex_handler_bpf(const struct exception_table_entry *x, struct pt_regs *regs)
{
int regno;
u8 *insn;
@ -678,7 +677,7 @@ static int bpf_jit_probe_mem(struct bpf_jit *jit, struct bpf_prog *fp,
/* JIT bug - landing pad and extable must be close. */
return -1;
ex->fixup = delta;
ex->handler = (u8 *)ex_handler_bpf - (u8 *)&ex->handler;
ex->type = EX_TYPE_BPF;
jit->excnt++;
}
return 0;

View File

@ -261,45 +261,6 @@ static void sort_relative_table_with_data(char *extab_image, int image_size)
}
}
static void s390_sort_relative_table(char *extab_image, int image_size)
{
int i;
for (i = 0; i < image_size; i += 16) {
char *loc = extab_image + i;
uint64_t handler;
w(r((uint32_t *)loc) + i, (uint32_t *)loc);
w(r((uint32_t *)(loc + 4)) + (i + 4), (uint32_t *)(loc + 4));
/*
* 0 is a special self-relative handler value, which means that
* handler should be ignored. It is safe, because it means that
* handler field points to itself, which should never happen.
* When creating extable-relative values, keep it as 0, since
* this should never occur either: it would mean that handler
* field points to the first extable entry.
*/
handler = r8((uint64_t *)(loc + 8));
if (handler)
handler += i + 8;
w8(handler, (uint64_t *)(loc + 8));
}
qsort(extab_image, image_size / 16, 16, compare_relative_table);
for (i = 0; i < image_size; i += 16) {
char *loc = extab_image + i;
uint64_t handler;
w(r((uint32_t *)loc) - i, (uint32_t *)loc);
w(r((uint32_t *)(loc + 4)) - (i + 4), (uint32_t *)(loc + 4));
handler = r8((uint64_t *)(loc + 8));
if (handler)
handler -= i + 8;
w8(handler, (uint64_t *)(loc + 8));
}
}
static int do_file(char const *const fname, void *addr)
{
int rc = -1;
@ -340,12 +301,10 @@ static int do_file(char const *const fname, void *addr)
case EM_386:
case EM_AARCH64:
case EM_RISCV:
case EM_S390:
case EM_X86_64:
custom_sort = sort_relative_table_with_data;
break;
case EM_S390:
custom_sort = s390_sort_relative_table;
break;
case EM_PARISC:
case EM_PPC:
case EM_PPC64: