summary refs log tree commit diff
path: root/scripts/sorttable.c
diff options
context:
space:
mode:
authorIlya Leoshkevich <iii@linux.ibm.com>2020-06-30 20:52:03 +0200
committerHeiko Carstens <hca@linux.ibm.com>2020-07-20 10:55:50 +0200
commit05a68e892e89c97df6650cd8cc55058002657cbc (patch)
tree50da3706b76870f99a1acf549c9cbf4227388baf /scripts/sorttable.c
parent88aa8939c96781089e5ace3492d818074c5c6fe9 (diff)
downloadlinux-05a68e892e89c97df6650cd8cc55058002657cbc.tar.gz
s390/kernel: expand exception table logic to allow new handling options
This is a s390 port of commit 548acf19234d ("x86/mm: Expand the
exception table logic to allow new handling options"), which is needed
for implementing BPF_PROBE_MEM on s390.

The new handler field is made 64-bit in order to allow pointing from
dynamically allocated entries to handlers in kernel text. Unlike on x86,
NULL is used instead of ex_handler_default. This is because exception
tables are used by boot/text_dma.S, and it would be a pain to preserve
ex_handler_default.

The new infrastructure is ignored in early_pgm_check_handler, since
there is no pt_regs.

Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
Reviewed-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
Diffstat (limited to 'scripts/sorttable.c')
-rw-r--r--scripts/sorttable.c41
1 files changed, 41 insertions, 0 deletions
diff --git a/scripts/sorttable.c b/scripts/sorttable.c
index ec6b5e81eba1..0ef3abfc4a51 100644
--- a/scripts/sorttable.c
+++ b/scripts/sorttable.c
@@ -255,6 +255,45 @@ static void x86_sort_relative_table(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;
@@ -297,6 +336,8 @@ static int do_file(char const *const fname, void *addr)
 		custom_sort = x86_sort_relative_table;
 		break;
 	case EM_S390:
+		custom_sort = s390_sort_relative_table;
+		break;
 	case EM_AARCH64:
 	case EM_PARISC:
 	case EM_PPC: