diff mbox

[RFC,07/11] kprobes: introduces macros for allocing early kprobe resources.

Message ID 1420616151-43023-1-git-send-email-wangnan0@huawei.com (mailing list archive)
State New, archived
Headers show

Commit Message

Wang Nan Jan. 7, 2015, 7:35 a.m. UTC
Introduces macros to genearte common early kprobe related resource
allocator.

All early kprobe related resources are statically allocated during
linking for each early kprobe slot. For each type of resource, a bitmap
is used to track allocation. __DEFINE_EKPROBE_ALLOC_OPS defines alloc
and free handler for them. The range of the resource and the bitmap
should be provided for allocaing and freeing. DEFINE_EKPROBE_ALLOC_OPS
defines bitmap and the array used by it.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
---
 include/linux/kprobes.h | 69 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 69 insertions(+)

Comments

Wang Nan Jan. 7, 2015, 10:45 a.m. UTC | #1
On 2015/1/7 15:35, Wang Nan wrote:
> Introduces macros to genearte common early kprobe related resource
> allocator.
> 
> All early kprobe related resources are statically allocated during
> linking for each early kprobe slot. For each type of resource, a bitmap
> is used to track allocation. __DEFINE_EKPROBE_ALLOC_OPS defines alloc
> and free handler for them. The range of the resource and the bitmap
> should be provided for allocaing and freeing. DEFINE_EKPROBE_ALLOC_OPS
> defines bitmap and the array used by it.
> 
> Signed-off-by: Wang Nan <wangnan0@huawei.com>
> ---
>  include/linux/kprobes.h | 69 +++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 69 insertions(+)
> 
> diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
> index b0265f9..9a18188 100644
> --- a/include/linux/kprobes.h
> +++ b/include/linux/kprobes.h
> @@ -270,6 +270,75 @@ extern void show_registers(struct pt_regs *regs);
>  extern void kprobes_inc_nmissed_count(struct kprobe *p);
>  extern bool arch_within_kprobe_blacklist(unsigned long addr);
>  
> +#ifdef CONFIG_EARLY_KPROBES
> +
> +#define NR_EARLY_KPROBES_SLOTS	CONFIG_NR_EARLY_KPROBES_SLOTS
> +#define ALIGN_UP(v, a)	(((v) + ((a) - 1)) & ~((a) - 1))
> +#define EARLY_KPROBES_BITMAP_SZ	ALIGN_UP(NR_EARLY_KPROBES_SLOTS, BITS_PER_LONG)
> +
> +#define __ek_in_range(v, s, e)	(((v) >= (s)) && ((v) < (e)))
> +#define __ek_buf_sz(s, e)	((void *)(e) - (void *)(s))
> +#define __ek_elem_sz_b(s, e)	(__ek_buf_sz(s, e) / NR_EARLY_KPROBES_SLOTS)
> +#define __ek_elem_sz(s, e)	(__ek_elem_sz_b(s, e) / sizeof(s[0]))
> +#define __ek_elem_idx(v, s, e)	(__ek_buf_sz(s, v) / __ek_elem_sz_b(s, e))
> +#define __ek_get_elem(i, s, e)	(&((s)[__ek_elem_sz(s, e) * (i)]))
> +#define __DEFINE_EKPROBE_ALLOC_OPS(__t, __name)				\
> +static inline __t *__ek_alloc_##__name(__t *__s, __t *__e, unsigned long *__b)\
> +{									\
> +	int __i = find_next_zero_bit(__b, NR_EARLY_KPROBES_SLOTS, 0);	\
> +	if (__i >= NR_EARLY_KPROBES_SLOTS)				\
> +		return NULL;						\
> +	set_bit(__i, __b);						\
> +	return __ek_get_elem(__i, __s, __e);				\
> +}									\
> +static inline int __ek_free_##__name(__t *__v, __t *__s, __t *__e, unsigned long *__b)	\
> +{									\
> +	if (!__ek_in_range(__v, __s, __e))				\
> +		return 0;						\
> +	clear_bit(__ek_elem_idx(__v, __s, __e), __b);			\
> +	return 1;							\
> +}
> +
> +#define DEFINE_EKPROBE_ALLOC_OPS(__t, __name, __static)			\
> +__static __t __ek_##__name##_slots[NR_EARLY_KPROBES_SLOTS];		\
> +__static unsigned long __ek_##__name##_bitmap[EARLY_KPROBES_BITMAP_SZ];	\
> +__DEFINE_EKPROBE_ALLOC_OPS(__t, __name)					\
> +static inline __t *ek_alloc_##__name(void)				\
> +{									\
> +	return __ek_alloc_##__name(&((__ek_##__name##_slots)[0]),	\
> +			&((__ek_##__name##_slots)[NR_EARLY_KPROBES_SLOTS]),\
> +			(__ek_##__name##_bitmap));			\
> +}									\
> +static inline int ek_free_##__name(__t *__s)				\
> +{									\
> +	return __ek_free_##__name(__s, &((__ek_##__name##_slots)[0]),	\
> +			&((__ek_##__name##_slots)[NR_EARLY_KPROBES_SLOTS]),\
> +			(__ek_##__name##_bitmap));			\
> +}
> +
> +
> +#else
> +#define __DEFINE_EKPROBE_ALLOC_OPS(__t, __name)				\
> +static inline __t *__ek_alloc_##__name(__t *__s, __t *__e, unsigned long *__b)\
> +{									\
> +	return NULL;							\
> +}									\
> +static inline int __ek_free_##__name(__t *__v, __t *__s, __t *__e, unsigned long *__b)\
> +{									\
> +	return 0;							\
> +}
> +
> +#define DEFINE_EKPROBE_ALLOC_OPS(__t, __name, __static)			\
> +static inline __t *ek_alloc_##__name(void)				\
> +{									\
> +	return NULL;							\
> +}									\
> +static inline void ek_free_##__name(__t *__s)				\
> +{									\
> +}
> +

Sorry, here is a small problem. Should be:
static inline int ek_free_##__name(__t *__s)				\
{									\
	return 0;							\
}

> +#endif
> +
>  struct kprobe_insn_cache {
>  	struct mutex mutex;
>  	void *(*alloc)(void);	/* allocate insn page */
>
diff mbox

Patch

diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index b0265f9..9a18188 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -270,6 +270,75 @@  extern void show_registers(struct pt_regs *regs);
 extern void kprobes_inc_nmissed_count(struct kprobe *p);
 extern bool arch_within_kprobe_blacklist(unsigned long addr);
 
+#ifdef CONFIG_EARLY_KPROBES
+
+#define NR_EARLY_KPROBES_SLOTS	CONFIG_NR_EARLY_KPROBES_SLOTS
+#define ALIGN_UP(v, a)	(((v) + ((a) - 1)) & ~((a) - 1))
+#define EARLY_KPROBES_BITMAP_SZ	ALIGN_UP(NR_EARLY_KPROBES_SLOTS, BITS_PER_LONG)
+
+#define __ek_in_range(v, s, e)	(((v) >= (s)) && ((v) < (e)))
+#define __ek_buf_sz(s, e)	((void *)(e) - (void *)(s))
+#define __ek_elem_sz_b(s, e)	(__ek_buf_sz(s, e) / NR_EARLY_KPROBES_SLOTS)
+#define __ek_elem_sz(s, e)	(__ek_elem_sz_b(s, e) / sizeof(s[0]))
+#define __ek_elem_idx(v, s, e)	(__ek_buf_sz(s, v) / __ek_elem_sz_b(s, e))
+#define __ek_get_elem(i, s, e)	(&((s)[__ek_elem_sz(s, e) * (i)]))
+#define __DEFINE_EKPROBE_ALLOC_OPS(__t, __name)				\
+static inline __t *__ek_alloc_##__name(__t *__s, __t *__e, unsigned long *__b)\
+{									\
+	int __i = find_next_zero_bit(__b, NR_EARLY_KPROBES_SLOTS, 0);	\
+	if (__i >= NR_EARLY_KPROBES_SLOTS)				\
+		return NULL;						\
+	set_bit(__i, __b);						\
+	return __ek_get_elem(__i, __s, __e);				\
+}									\
+static inline int __ek_free_##__name(__t *__v, __t *__s, __t *__e, unsigned long *__b)	\
+{									\
+	if (!__ek_in_range(__v, __s, __e))				\
+		return 0;						\
+	clear_bit(__ek_elem_idx(__v, __s, __e), __b);			\
+	return 1;							\
+}
+
+#define DEFINE_EKPROBE_ALLOC_OPS(__t, __name, __static)			\
+__static __t __ek_##__name##_slots[NR_EARLY_KPROBES_SLOTS];		\
+__static unsigned long __ek_##__name##_bitmap[EARLY_KPROBES_BITMAP_SZ];	\
+__DEFINE_EKPROBE_ALLOC_OPS(__t, __name)					\
+static inline __t *ek_alloc_##__name(void)				\
+{									\
+	return __ek_alloc_##__name(&((__ek_##__name##_slots)[0]),	\
+			&((__ek_##__name##_slots)[NR_EARLY_KPROBES_SLOTS]),\
+			(__ek_##__name##_bitmap));			\
+}									\
+static inline int ek_free_##__name(__t *__s)				\
+{									\
+	return __ek_free_##__name(__s, &((__ek_##__name##_slots)[0]),	\
+			&((__ek_##__name##_slots)[NR_EARLY_KPROBES_SLOTS]),\
+			(__ek_##__name##_bitmap));			\
+}
+
+
+#else
+#define __DEFINE_EKPROBE_ALLOC_OPS(__t, __name)				\
+static inline __t *__ek_alloc_##__name(__t *__s, __t *__e, unsigned long *__b)\
+{									\
+	return NULL;							\
+}									\
+static inline int __ek_free_##__name(__t *__v, __t *__s, __t *__e, unsigned long *__b)\
+{									\
+	return 0;							\
+}
+
+#define DEFINE_EKPROBE_ALLOC_OPS(__t, __name, __static)			\
+static inline __t *ek_alloc_##__name(void)				\
+{									\
+	return NULL;							\
+}									\
+static inline void ek_free_##__name(__t *__s)				\
+{									\
+}
+
+#endif
+
 struct kprobe_insn_cache {
 	struct mutex mutex;
 	void *(*alloc)(void);	/* allocate insn page */