mirror of
				https://github.com/torvalds/linux.git
				synced 2025-10-31 08:38:45 +02:00 
			
		
		
		
	s390/kprobes: Remove custom insn slot allocator
Since commit c98d2ecae0 ("s390/mm: Uncouple physical vs virtual address
spaces") the kernel image and module area are within the same 4GB area.
This eliminates the need of a custom insn slot allocator for kprobes within
the kernel image, since standard module_alloc() allocated pages are
sufficient for PC relative instructions with a signed 32 bit offset.
Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
			
			
This commit is contained in:
		
							parent
							
								
									e7dec0b792
								
							
						
					
					
						commit
						d890e6af50
					
				
					 4 changed files with 10 additions and 89 deletions
				
			
		|  | @ -59,7 +59,6 @@ obj-$(CONFIG_COMPAT)		+= compat_linux.o compat_signal.o | ||||||
| obj-$(CONFIG_COMPAT)		+= $(compat-obj-y) | obj-$(CONFIG_COMPAT)		+= $(compat-obj-y) | ||||||
| obj-$(CONFIG_EARLY_PRINTK)	+= early_printk.o | obj-$(CONFIG_EARLY_PRINTK)	+= early_printk.o | ||||||
| obj-$(CONFIG_KPROBES)		+= kprobes.o | obj-$(CONFIG_KPROBES)		+= kprobes.o | ||||||
| obj-$(CONFIG_KPROBES)		+= kprobes_insn_page.o |  | ||||||
| obj-$(CONFIG_KPROBES)		+= mcount.o | obj-$(CONFIG_KPROBES)		+= mcount.o | ||||||
| obj-$(CONFIG_RETHOOK)		+= rethook.o | obj-$(CONFIG_RETHOOK)		+= rethook.o | ||||||
| obj-$(CONFIG_FUNCTION_TRACER)	+= ftrace.o | obj-$(CONFIG_FUNCTION_TRACER)	+= ftrace.o | ||||||
|  |  | ||||||
|  | @ -24,7 +24,6 @@ | ||||||
| #include <asm/set_memory.h> | #include <asm/set_memory.h> | ||||||
| #include <asm/sections.h> | #include <asm/sections.h> | ||||||
| #include <asm/dis.h> | #include <asm/dis.h> | ||||||
| #include "kprobes.h" |  | ||||||
| #include "entry.h" | #include "entry.h" | ||||||
| 
 | 
 | ||||||
| DEFINE_PER_CPU(struct kprobe *, current_kprobe); | DEFINE_PER_CPU(struct kprobe *, current_kprobe); | ||||||
|  | @ -32,8 +31,6 @@ DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); | ||||||
| 
 | 
 | ||||||
| struct kretprobe_blackpoint kretprobe_blacklist[] = { }; | struct kretprobe_blackpoint kretprobe_blacklist[] = { }; | ||||||
| 
 | 
 | ||||||
| static int insn_page_in_use; |  | ||||||
| 
 |  | ||||||
| void *alloc_insn_page(void) | void *alloc_insn_page(void) | ||||||
| { | { | ||||||
| 	void *page; | 	void *page; | ||||||
|  | @ -45,26 +42,6 @@ void *alloc_insn_page(void) | ||||||
| 	return page; | 	return page; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void *alloc_s390_insn_page(void) |  | ||||||
| { |  | ||||||
| 	if (xchg(&insn_page_in_use, 1) == 1) |  | ||||||
| 		return NULL; |  | ||||||
| 	return &kprobes_insn_page; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void free_s390_insn_page(void *page) |  | ||||||
| { |  | ||||||
| 	xchg(&insn_page_in_use, 0); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| struct kprobe_insn_cache kprobe_s390_insn_slots = { |  | ||||||
| 	.mutex = __MUTEX_INITIALIZER(kprobe_s390_insn_slots.mutex), |  | ||||||
| 	.alloc = alloc_s390_insn_page, |  | ||||||
| 	.free = free_s390_insn_page, |  | ||||||
| 	.pages = LIST_HEAD_INIT(kprobe_s390_insn_slots.pages), |  | ||||||
| 	.insn_size = MAX_INSN_SIZE, |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| static void copy_instruction(struct kprobe *p) | static void copy_instruction(struct kprobe *p) | ||||||
| { | { | ||||||
| 	kprobe_opcode_t insn[MAX_INSN_SIZE]; | 	kprobe_opcode_t insn[MAX_INSN_SIZE]; | ||||||
|  | @ -78,10 +55,10 @@ static void copy_instruction(struct kprobe *p) | ||||||
| 	if (probe_is_insn_relative_long(&insn[0])) { | 	if (probe_is_insn_relative_long(&insn[0])) { | ||||||
| 		/*
 | 		/*
 | ||||||
| 		 * For pc-relative instructions in RIL-b or RIL-c format patch | 		 * For pc-relative instructions in RIL-b or RIL-c format patch | ||||||
| 		 * the RI2 displacement field. We have already made sure that | 		 * the RI2 displacement field. The insn slot for the to be | ||||||
| 		 * the insn slot for the patched instruction is within the same | 		 * patched instruction is within the same 4GB area like the | ||||||
| 		 * 2GB area as the original instruction (either kernel image or | 		 * original instruction. Therefore the new displacement will | ||||||
| 		 * module area). Therefore the new displacement will always fit. | 		 * always fit. | ||||||
| 		 */ | 		 */ | ||||||
| 		disp = *(s32 *)&insn[1]; | 		disp = *(s32 *)&insn[1]; | ||||||
| 		addr = (u64)(unsigned long)p->addr; | 		addr = (u64)(unsigned long)p->addr; | ||||||
|  | @ -93,34 +70,6 @@ static void copy_instruction(struct kprobe *p) | ||||||
| } | } | ||||||
| NOKPROBE_SYMBOL(copy_instruction); | NOKPROBE_SYMBOL(copy_instruction); | ||||||
| 
 | 
 | ||||||
| static int s390_get_insn_slot(struct kprobe *p) |  | ||||||
| { |  | ||||||
| 	/*
 |  | ||||||
| 	 * Get an insn slot that is within the same 2GB area like the original |  | ||||||
| 	 * instruction. That way instructions with a 32bit signed displacement |  | ||||||
| 	 * field can be patched and executed within the insn slot. |  | ||||||
| 	 */ |  | ||||||
| 	p->ainsn.insn = NULL; |  | ||||||
| 	if (is_kernel((unsigned long)p->addr)) |  | ||||||
| 		p->ainsn.insn = get_s390_insn_slot(); |  | ||||||
| 	else if (is_module_addr(p->addr)) |  | ||||||
| 		p->ainsn.insn = get_insn_slot(); |  | ||||||
| 	return p->ainsn.insn ? 0 : -ENOMEM; |  | ||||||
| } |  | ||||||
| NOKPROBE_SYMBOL(s390_get_insn_slot); |  | ||||||
| 
 |  | ||||||
| static void s390_free_insn_slot(struct kprobe *p) |  | ||||||
| { |  | ||||||
| 	if (!p->ainsn.insn) |  | ||||||
| 		return; |  | ||||||
| 	if (is_kernel((unsigned long)p->addr)) |  | ||||||
| 		free_s390_insn_slot(p->ainsn.insn, 0); |  | ||||||
| 	else |  | ||||||
| 		free_insn_slot(p->ainsn.insn, 0); |  | ||||||
| 	p->ainsn.insn = NULL; |  | ||||||
| } |  | ||||||
| NOKPROBE_SYMBOL(s390_free_insn_slot); |  | ||||||
| 
 |  | ||||||
| /* Check if paddr is at an instruction boundary */ | /* Check if paddr is at an instruction boundary */ | ||||||
| static bool can_probe(unsigned long paddr) | static bool can_probe(unsigned long paddr) | ||||||
| { | { | ||||||
|  | @ -174,7 +123,8 @@ int arch_prepare_kprobe(struct kprobe *p) | ||||||
| 	/* Make sure the probe isn't going on a difficult instruction */ | 	/* Make sure the probe isn't going on a difficult instruction */ | ||||||
| 	if (probe_is_prohibited_opcode(p->addr)) | 	if (probe_is_prohibited_opcode(p->addr)) | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
| 	if (s390_get_insn_slot(p)) | 	p->ainsn.insn = get_insn_slot(); | ||||||
|  | 	if (!p->ainsn.insn) | ||||||
| 		return -ENOMEM; | 		return -ENOMEM; | ||||||
| 	copy_instruction(p); | 	copy_instruction(p); | ||||||
| 	return 0; | 	return 0; | ||||||
|  | @ -216,7 +166,10 @@ NOKPROBE_SYMBOL(arch_disarm_kprobe); | ||||||
| 
 | 
 | ||||||
| void arch_remove_kprobe(struct kprobe *p) | void arch_remove_kprobe(struct kprobe *p) | ||||||
| { | { | ||||||
| 	s390_free_insn_slot(p); | 	if (!p->ainsn.insn) | ||||||
|  | 		return; | ||||||
|  | 	free_insn_slot(p->ainsn.insn, 0); | ||||||
|  | 	p->ainsn.insn = NULL; | ||||||
| } | } | ||||||
| NOKPROBE_SYMBOL(arch_remove_kprobe); | NOKPROBE_SYMBOL(arch_remove_kprobe); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,9 +0,0 @@ | ||||||
| /* SPDX-License-Identifier: GPL-2.0+ */ |  | ||||||
| #ifndef _ARCH_S390_KPROBES_H |  | ||||||
| #define _ARCH_S390_KPROBES_H |  | ||||||
| 
 |  | ||||||
| #include <linux/kprobes.h> |  | ||||||
| 
 |  | ||||||
| DEFINE_INSN_CACHE_OPS(s390_insn); |  | ||||||
| 
 |  | ||||||
| #endif |  | ||||||
|  | @ -1,22 +0,0 @@ | ||||||
| /* SPDX-License-Identifier: GPL-2.0 */ |  | ||||||
| 
 |  | ||||||
| #include <linux/linkage.h> |  | ||||||
| 
 |  | ||||||
| /* |  | ||||||
|  * insn_page is a special 4k aligned dummy function for kprobes. |  | ||||||
|  * It will contain all kprobed instructions that are out-of-line executed. |  | ||||||
|  * The page must be within the kernel image to guarantee that the |  | ||||||
|  * out-of-line instructions are within 2GB distance of their original |  | ||||||
|  * location. Using a dummy function ensures that the insn_page is within |  | ||||||
|  * the text section of the kernel and mapped read-only/executable from |  | ||||||
|  * the beginning on, thus avoiding to split large mappings if the page |  | ||||||
|  * would be in the data section instead. |  | ||||||
|  */ |  | ||||||
| 	.section .kprobes.text, "ax" |  | ||||||
| 	.balign 4096
 |  | ||||||
| SYM_CODE_START(kprobes_insn_page) |  | ||||||
| 	.rept 2048
 |  | ||||||
| 	.word 0x07fe
 |  | ||||||
| 	.endr |  | ||||||
| SYM_CODE_END(kprobes_insn_page) |  | ||||||
| 	.previous |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Heiko Carstens
						Heiko Carstens