Conditional Calls
Subsystems (14)
cover Conditional Calls
Hi,
Following Andi Kleen's advice, I splitted the jump-over-call into a speparate piece of infrastructure so it can be used more widely.
It also use a hash table to permit cond_call enable/disable both when the cond_call is armed and when a module containing an armed cond_call is loaded.
Please add at the end of the 2.6.22-mm1 series,
conditional-calls-architecture-independent-code.patch conditional-calls-hash-table.patch conditional-calls-non-optimized-architectures.patch conditional-calls-kconfig-menus.patch conditional-calls-i386-optimization.patch conditional-calls-powerpc-optimization.patch conditional-calls-documentation.patch
#
f00f-bug-use-cond-calls.patch profiling-use-cond-calls.patch
Mathieu
Signature · 3 lines
Mathieu Desnoyers Computer Engineering Ph.D. Student, Ecole Polytechnique de Montreal OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68
PATCH 1/9 Conditional Calls - Architecture Independent Code
Conditional calls are used to compile in code that is meant to be dynamically enabled at runtime. When code is disabled, it has a very small footprint.
It has a generic cond_call version and optimized per architecture cond_calls. The optimized cond_call uses a load immediate to remove a data cache hit.
It adds a new rodata section "__cond_call" to place the pointers to the enable value.
cond_call activation functions sits in module.c.
--- include/asm-generic/vmlinux.lds.h | 16 +- include/linux/condcall.h | 91 +++++++++++++ include/linux/module.h | 4 kernel/module.c | 248 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 356 insertions(+), 3 deletions(-)
include/linux/condcall.h new file +91 -0
@@ -0,0 +1,91 @@ +#ifndef _LINUX_CONDCALL_H +#define _LINUX_CONDCALL_H + +/* +* Conditional function calls. Cheap when disabled, enabled at runtime. +* +* (C) Copyright 2007 Mathieu Desnoyers <[email protected]> +* +* This file is released under the GPLv2. +* See the file COPYING for more details. +*/ + +#ifdef __KERNEL__ + +struct __cond_call_struct { +const char *name; +void *enable; +int flags; +} __attribute__((packed)); + + +/* Cond call flags : selects the mechanism used to enable the conditional calls +* and prescribe what can be executed within their function. This is primarily +* used at reentrancy-unfriendly sites. */ +#define CF_OPTIMIZED (1 << 0)/* Use optimized cond_call */ +#define CF_LOCKDEP (1 << 1)/* Can call lockdep */ +#define CF_PRINTK (1 << 2)/* Probe can call vprintk */ +#define CF_STATIC_ENABLE (1 << 3)/* Enable cond_call statically */ +#define _CF_NR 4 + +#ifdef CONFIG_COND_CALL + +/* Generic cond_call flavor always available. +* Note : the empty asm volatile with read constraint is used here instead of a +* "used" attribute to fix a gcc 4.1.x bug. */ +#define cond_call_generic (flags, name, func) \ + ({ \ + static const char __cstrtab_name_##name[] \ + __attribute__((section("__cond_call_strings"))) = #name; \ + static char __cond_call_enable_##name = \ + (flags) & CF_STATIC_ENABLE; \ + static const struct __cond_call_struct __cond_call_##name \ + __attribute__((section("__cond_call"))) = \ + { __cstrtab_name_##name, \ + &__cond_call_enable_##name, \ + (flags) & ~CF_OPTIMIZED } ; \ + asm volatile ( "" : : "i" (&__cond_call_##name)); \ + (unlikely(__cond_call_enable_##name)) ? \ + (func) : \ + (__typeof__(func))0; \ + }) + +#define COND_CALL_GENERIC_ENABLE_IMMEDIATE_OFFSET 0 +#define COND_CALL_GENERIC_ENABLE_TYPE unsigned char +/* Dereference enable as lvalue from a pointer to its instruction */ +#define COND_CALL_GENERIC_ENABLE (a) \ + *(COND_CALL_GENERIC_ENABLE_TYPE*) \ + ((char*)a+COND_CALL_GENERIC_ENABLE_IMMEDIATE_OFFSET) + +static inline int cond_call_generic_set_enable (void *address,char enable) +{ +COND_CALL_GENERIC_ENABLE (address) = enable; +return 0 ; +} + +#else /* !CONFIG_COND_CALL */ +#define cond_call_generic (flags, name, func) \ + ({ \ + ((flags) & CF_STATIC_ENABLE) ? \ + (func) : \ + (__typeof__(func))0; \ + }) +#endif /* CONFIG_COND_CALL */ + +#ifdef CONFIG_COND_CALL_ENABLE_OPTIMIZATION +#include <asm/condcall.h> /* optimized cond_call flavor */ +#else +#include <asm-generic/condcall.h> /* fallback on generic cond_call */ +#endif + +#define COND_CALL_MAX_FORMAT_LEN 1024 + +extern int cond_call_arm (const char *name); +extern int cond_call_disarm (const char *name); + +/* cond_call_query : Returns 1 if enabled, 0 if disabled or not present */ +extern int cond_call_query (const char *name); +extern int cond_call_list (const char *name); + +#endif /* __KERNEL__ */ +#endif
include/asm-generic/vmlinux.lds.h +13 -3
@@ -116,11 +116,22 @@ *(__kcrctab_gpl_future ) \ VMLINUX_SYMBOL(__stop___kcrctab_gpl_future) = .; \ } \ - \ +/* Conditional calls: pointers */ \ + __cond_call : AT(ADDR(__cond_call) - LOAD_OFFSET) { \ + VMLINUX_SYMBOL(__start___cond_call) = .; \ + *(__cond_call ) \ + VMLINUX_SYMBOL(__stop___cond_call) = .; \ + } \/* Kernel symbol table: strings */ \ __ksymtab_strings : AT(ADDR(__ksymtab_strings) - LOAD_OFFSET) { \ *(__ksymtab_strings) \ - } \ + } \ +/* Conditional calls: strings */ \ + __cond_call_strings : AT(ADDR(__cond_call_strings) - LOAD_OFFSET) { \ + *(__cond_call_strings) \ + } \ + __end_rodata = .; \ + . = ALIGN(4096); \ \/* Built-in module parameters. */ \ __param : AT(ADDR(__param) - LOAD_OFFSET) { \
@@ -228,4 +239,3 @@ *(.initcall6s.init) \ *(.initcall7.init) \ *(.initcall7s.init) -
include/linux/module.h +4 -0
@@ -16,6 +16,7 @@#include <linux/stringify.h> #include <linux/kobject.h> #include <linux/moduleparam.h> +#include <linux/condcall.h> #include <asm/local.h> #include <asm/module.h>
@@ -356,6 +357,9 @@/* The command line arguments (may be mangled). People like keeping pointers to this stuff */ char *args; + +const struct __cond_call_struct *cond_calls; +unsigned int num_cond_calls; };#ifndef MODULE_ARCH_INIT #define MODULE_ARCH_INIT {}
kernel/module.c +248 -0
290 lines not on this page · raw message
Signature · 3 lines
Mathieu Desnoyers Computer Engineering Ph.D. Student, Ecole Polytechnique de Montreal OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68
PATCH 2/9 Conditional Calls - Hash Table
In reply to Mathieu DesnoyersReimplementation of the cond calls which uses a hash table to hold the active cond_calls. It permits to first arm a cond_call and then load supplementary modules that contain this cond_call.
Without this, the order of loading a module containing a cond_call and arming a cond_call matters and there is no symbol dependency to check this.
At module load time, each cond_call checks if it is enabled in the hash table and is set accordingly.
--- include/linux/condcall.h | 2 kernel/module.c | 205 +++++++++++++++++++++++++++++------------------ 2 files changed, 129 insertions(+), 78 deletions(-)
kernel/module.c +128 -77
@@ -33,6 +33,8 @@#include <linux/moduleparam.h> #include <linux/errno.h> #include <linux/condcall.h> +#include <linux/jhash.h> +#include <linux/list.h> #include <linux/err.h> #include <linux/vermagic.h> #include <linux/notifier.h>
@@ -71,6 +73,20 @@static BLOCKING_NOTIFIER_HEAD (module_notify_list); +#ifdef CONFIG_COND_CALL +/* Conditional call hash table, containing the active cond_calls. +* Protected by module_mutex. */ +#define COND_CALL_HASH_BITS 6 +#define COND_CALL_TABLE_SIZE (1 << COND_CALL_HASH_BITS) + +struct cond_call_entry { +struct hlist_node hlist; +char name[0 ]; +}; + +static struct hlist_head cond_call_table[COND_CALL_TABLE_SIZE ]; +#endif //CONFIG_COND_CALL +int register_module_notifier (struct notifier_block * nb) {return blocking_notifier_chain_register (&module_notify_list, nb);
@@ -305,6 +321,68 @@ }#ifdef CONFIG_COND_CALL +/* Check if the cond_call is present in the hash table. +* Returns 1 if present, 0 if not. */ +static int hash_check_cond_call (const char *name) +{ +struct hlist_head *head; +struct hlist_node *node; +struct cond_call_entry *e; +size_t len =strlen (name); +u32 hash =jhash (name, len,0 ); + + head = &cond_call_table[hash & ((1 <<COND_CALL_HASH_BITS )-1 )]; +hlist_for_each_entry (e, node, head, hlist) +if (!strcmp (name, e->name)) +return 1 ; +return 0 ; +} + +/* Add the cond_call to the hash table. Must be called with mutex_lock held. */ +static int hash_add_cond_call (const char *name) +{ +struct hlist_head *head; +struct hlist_node *node; +struct cond_call_entry *e; +size_t len =strlen (name); +u32 hash =jhash (name, len,0 ); + + head = &cond_call_table[hash & ((1 <<COND_CALL_HASH_BITS )-1 )]; +hlist_for_each_entry (e, node, head, hlist) +if (!strcmp (name, e->name)) +return 0 ;/* Already there */ +/* Using kmalloc here to allocate a variable length element. Could +* cause some memory fragmentation if overused. */ + e =kmalloc (sizeof (struct cond_call_entry ) + len +1 ,GFP_KERNEL ); +if (!e) +return -ENOMEM ; +memcpy (&e->name[0 ], name, len +1 ); +hlist_add_head (&e->hlist, head); +return 0 ; +} + +/* Remove the cond_call from the hash table. Must be called with mutex_lock +* held. */ +static void hash_remove_cond_call (const char *name) +{ +struct hlist_head *head; +struct hlist_node *node; +struct cond_call_entry *e; +int found =0 ; +size_t len =strlen (name); +u32 hash =jhash (name, len,0 ); + + head = &cond_call_table[hash & ((1 <<COND_CALL_HASH_BITS )-1 )]; +hlist_for_each_entry (e, node, head, hlist) +if (!strcmp (name, e->name)) { + found =1 ; +break ; + } +if (found) { +hlist_del (&e->hlist); +kfree (e); + } +}/* Set the enable bit of the cond_call, choosing the generic or architecture * specific functions depending on the cond_call's flags.
@@ -317,59 +395,53 @@return cond_call_generic_set_enable (address, enable); } -/* Query the state of a cond_calls range. */ -static int _cond_call_query_range (const char *name, -const struct __cond_call_struct *begin, -const struct __cond_call_struct *end) +static int cond_call_get_enable (void *address,int flags) +{ +if (flags &CF_OPTIMIZED ) +return COND_CALL_OPTIMIZED_ENABLE (address); +else +return COND_CALL_GENERIC_ENABLE (address); +} + +/* Setup the cond_call according to the data present in the cond_call hash +* upon module load. */ +void module_cond_call_setup (struct module *mod) {const struct __cond_call_struct *iter; -int ret =0 ; +int enable; -for (iter = begin; iter < end; iter++) { -if (strcmp (name, iter->name) !=0 ) -continue ; -if (iter->flags &CF_OPTIMIZED ) - ret =COND_CALL_OPTIMIZED_ENABLE (iter->enable); -else - ret =COND_CALL_GENERIC_ENABLE (iter->enable); -if (ret) -break ; +for (iter = mod->cond_calls; + iter < mod->cond_calls+mod->num_cond_calls; iter++) { + enable =hash_check_cond_call (iter->name); +if (enable !=cond_call_get_enable (iter->enable, iter->flags)) +cond_call_set_enable (iter->enable, enable, iter->flags); } -return ret; }/* Sets a range of cond_calls to a enabled state : set the enable bit. */ -static int _cond_call_arm_range (const char *name, +static void _cond_call_arm_range (const char *name,const struct __cond_call_struct *begin,const struct __cond_call_struct *end) {const struct __cond_call_struct *iter; -int found =0 ;for (iter = begin; iter < end; iter++) { -if (strcmp (name, iter->name) !=0 ) -continue ; -cond_call_set_enable (iter->enable,1 , iter->flags); - found++; +if (!strcmp (name, iter->name)) +cond_call_set_enable (iter->enable,1 , iter->flags); } -return found; }/* Sets a range of cond_calls to a disabled state : unset the enable bit. */ -static int _cond_call_disarm_range (const char *name, +static void _cond_call_disarm_range (const char *name,const struct __cond_call_struct *begin,const struct __cond_call_struct *end) {const struct __cond_call_struct *iter; -int found =0 ;for (iter = begin; iter < end; iter++) { -if (strcmp (name, iter->name) !=0 ) -continue ; -cond_call_set_enable (iter->enable,0 , iter->flags); - found++; +if (!strcmp (name, iter->name)) +cond_call_set_enable (iter->enable,0 , iter->flags); } -return found; }/* Provides a listing of the cond_calls present in the kernel with their type
@@ -397,105 +469,79 @@return found; } -/* Calls _cond_call_query_range for the core cond_calls and modules cond_calls. -*/ -static int _cond_call_query (const char *name) -{ -struct module *mod; -int ret =0 ; - -/* Core kernel cond_calls */ - ret =_cond_call_query_range (name, - __start___cond_call, __stop___cond_call); -if (ret) -return ret; -/* Cond_calls in modules. */ -list_for_each_entry (mod, &modules, list) { -if (mod->taints) -continue ; - ret =_cond_call_query_range (name, - mod->cond_calls, mod->cond_calls+mod->num_cond_calls); -if (ret) -break ; - } -return ret; -} -/* Cond_call enabling/disabling use the module_mutex to synchronize. -* Returns 1 if enabled, 0 if disabled or not present. */ +* Returns 1 if enabled, 0 if disabled. */ int cond_call_query (const char *name) { -int ret =0 ; +int ret;mutex_lock (&module_mutex); - ret =_cond_call_query (name); + ret =hash_check_cond_call (name);mutex_unlock (&module_mutex);return ret; }EXPORT_SYMBOL_GPL (cond_call_query); -/* Calls _cond_call_arm_range for the core cond_calls and modules cond_calls. -* FIXME : cond_call will not be active on modules loaded later than the -* cond_call_arm. */ +/* Calls _cond_call_arm_range for the core cond_calls and modules cond_calls. */ static int _cond_call_arm (const char *name) {struct module *mod; -int found =0 ; +int ret; + + ret =hash_add_cond_call (name); +if (ret) +return ret;/* Core kernel cond_calls */ - found +=_cond_call_arm_range (name, +_cond_call_arm_range (name, __start___cond_call, __stop___cond_call);/* Cond_calls in modules. */ list_for_each_entry (mod, &modules, list) {if (mod->taints)continue ; - found +=_cond_call_arm_range (name, +_cond_call_arm_range (name, mod->cond_calls, mod->cond_calls+mod->num_cond_calls); } -return found; +return ret; }/* Cond_call enabling/disabling use the module_mutex to synchronize. */ int cond_call_arm (const char *name) { -int found =0 ; +int ret;mutex_lock (&module_mutex); - found =_cond_call_arm (name); + ret =_cond_call_arm (name);mutex_unlock (&module_mutex); -return found; +return ret; }EXPORT_SYMBOL_GPL (cond_call_arm);/* Calls _cond_call_disarm_range for the core cond_calls and modules cond_calls. */ -static int _cond_call_disarm (const char *name) +static void _cond_call_disarm (const char *name) {struct module *mod; -int found =0 ;/* Core kernel cond_calls */ - found +=_cond_call_disarm_range (name, +_cond_call_disarm_range (name, __start___cond_call, __stop___cond_call);/* Cond_calls in modules. */ list_for_each_entry (mod, &modules, list) {if (mod->taints)continue ; - found +=_cond_call_disarm_range (name, +_cond_call_disarm_range (name, mod->cond_calls, mod->cond_calls+mod->num_cond_calls); } -return found; +hash_remove_cond_call (name); }/* Cond_call enabling/disabling use the module_mutex to synchronize. */ -int cond_call_disarm (const char *name) +void cond_call_disarm (const char *name) { -int found =0 ; -mutex_lock (&module_mutex); - found =_cond_call_disarm (name); +_cond_call_disarm (name);mutex_unlock (&module_mutex); -return found; }EXPORT_SYMBOL_GPL (cond_call_disarm);
@@ -525,7 +571,10 @@ return found; }EXPORT_SYMBOL_GPL (cond_call_list); - +#else +static void module_cond_call_setup (struct module *mod) +{ +}#endif #ifdef CONFIG_SMP
@@ -2211,6 +2260,8 @@add_kallsyms (mod, sechdrs, symindex, strindex, secstrings); +module_cond_call_setup (mod); + err =module_finalize (hdr, sechdrs, mod);if (err <0 ) goto cleanup;
include/linux/condcall.h +1 -1
@@ -81,7 +81,7 @@#define COND_CALL_MAX_FORMAT_LEN 1024extern int cond_call_arm (const char *name); -extern int cond_call_disarm (const char *name); +extern void cond_call_disarm (const char *name);/* cond_call_query : Returns 1 if enabled, 0 if disabled or not present */ extern int cond_call_query (const char *name);
Signature · 3 lines
Mathieu Desnoyers Computer Engineering Ph.D. Student, Ecole Polytechnique de Montreal OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68
PATCH 3/9 Conditional Calls - Non Optimized Architectures
In reply to Mathieu DesnoyersArchitecture agnostic, generic, version of the cond_calls.
--- include/asm-alpha/condcall.h | 1 + include/asm-arm/condcall.h | 1 + include/asm-arm26/condcall.h | 1 + include/asm-cris/condcall.h | 1 + include/asm-frv/condcall.h | 1 + include/asm-generic/condcall.h | 25 +++++++++++++++++++++++++ include/asm-h8300/condcall.h | 1 + include/asm-i386/condcall.h | 1 + include/asm-ia64/condcall.h | 1 + include/asm-m32r/condcall.h | 1 + include/asm-m68k/condcall.h | 1 + include/asm-m68knommu/condcall.h | 1 + include/asm-mips/condcall.h | 1 + include/asm-parisc/condcall.h | 1 + include/asm-powerpc/condcall.h | 1 + include/asm-ppc/condcall.h | 1 + include/asm-s390/condcall.h | 1 + include/asm-sh/condcall.h | 1 + include/asm-sh64/condcall.h | 1 + include/asm-sparc/condcall.h | 1 + include/asm-sparc64/condcall.h | 1 + include/asm-um/condcall.h | 1 + include/asm-v850/condcall.h | 1 + include/asm-x86_64/condcall.h | 1 + include/asm-xtensa/condcall.h | 1 + 25 files changed, 49 insertions(+)
include/asm-generic/condcall.h new file +25 -0
@@ -0,0 +1,25 @@ +#ifndef _ASM_GENERIC_CONDCALL_H +#define _ASM_GENERIC_CONDCALL_H + +/* Default flags, used by _cond_call() */ +#define CF_DEFAULT 0 + +/* Fallback on the generic cond_call, since no optimized version is available */ +#define cond_call_optimized cond_call_generic +#define _cond_call (flags, name, func) cond_call_generic(flags, name, func) + +/* cond_call with default behavior */ +#define cond_call (name, func) _cond_call(CF_DEFAULT, name, func) + +/* Architecture dependant cond_call information, used internally for cond_call +* activation. */ + +#define COND_CALL_OPTIMIZED_ENABLE_IMMEDIATE_OFFSET \ + COND_CALL_GENERIC_ENABLE_IMMEDIATE_OFFSET +#define COND_CALL_OPTIMIZED_ENABLE_TYPE COND_CALL_GENERIC_ENABLE_TYPE +/* Dereference enable as lvalue from a pointer to its instruction */ +#define COND_CALL_OPTIMIZED_ENABLE COND_CALL_GENERIC_ENABLE + +#define cond_call_optimized_set_enable cond_call_generic_set_enable + +#endif /* _ASM_GENERIC_MARKER_H */
include/asm-alpha/condcall.h new file +1 -0
@@ -0,0 +1 @@ +#include <asm-generic/condcall.h>
include/asm-arm/condcall.h new file +1 -0
@@ -0,0 +1 @@ +#include <asm-generic/condcall.h>
include/asm-arm26/condcall.h new file +1 -0
@@ -0,0 +1 @@ +#include <asm-generic/condcall.h>
include/asm-cris/condcall.h new file +1 -0
@@ -0,0 +1 @@ +#include <asm-generic/condcall.h>
include/asm-frv/condcall.h new file +1 -0
@@ -0,0 +1 @@ +#include <asm-generic/condcall.h>
include/asm-h8300/condcall.h new file +1 -0
@@ -0,0 +1 @@ +#include <asm-generic/condcall.h>
include/asm-ia64/condcall.h new file +1 -0
@@ -0,0 +1 @@ +#include <asm-generic/condcall.h>
include/asm-m32r/condcall.h new file +1 -0
@@ -0,0 +1 @@ +#include <asm-generic/condcall.h>
include/asm-m68k/condcall.h new file +1 -0
@@ -0,0 +1 @@ +#include <asm-generic/condcall.h>
include/asm-m68knommu/condcall.h new file +1 -0
@@ -0,0 +1 @@ +#include <asm-generic/condcall.h>
include/asm-mips/condcall.h new file +1 -0
@@ -0,0 +1 @@ +#include <asm-generic/condcall.h>
include/asm-parisc/condcall.h new file +1 -0
@@ -0,0 +1 @@ +#include <asm-generic/condcall.h>
include/asm-ppc/condcall.h new file +1 -0
@@ -0,0 +1 @@ +#include <asm-generic/condcall.h>
include/asm-s390/condcall.h new file +1 -0
@@ -0,0 +1 @@ +#include <asm-generic/condcall.h>
include/asm-sh/condcall.h new file +1 -0
@@ -0,0 +1 @@ +#include <asm-generic/condcall.h>
include/asm-sh64/condcall.h new file +1 -0
@@ -0,0 +1 @@ +#include <asm-generic/condcall.h>
include/asm-sparc/condcall.h new file +1 -0
@@ -0,0 +1 @@ +#include <asm-generic/condcall.h>
include/asm-sparc64/condcall.h new file +1 -0
@@ -0,0 +1 @@ +#include <asm-generic/condcall.h>
include/asm-um/condcall.h new file +1 -0
@@ -0,0 +1 @@ +#include <asm-generic/condcall.h>
include/asm-v850/condcall.h new file +1 -0
@@ -0,0 +1 @@ +#include <asm-generic/condcall.h>
include/asm-x86_64/condcall.h new file +1 -0
@@ -0,0 +1 @@ +#include <asm-generic/condcall.h>
include/asm-xtensa/condcall.h new file +1 -0
@@ -0,0 +1 @@ +#include <asm-generic/condcall.h>
include/asm-i386/condcall.h new file +1 -0
@@ -0,0 +1 @@ +#include <asm-generic/condcall.h>
include/asm-powerpc/condcall.h new file +1 -0
@@ -0,0 +1 @@ +#include <asm-generic/condcall.h>
Signature · 3 lines
Mathieu Desnoyers Computer Engineering Ph.D. Student, Ecole Polytechnique de Montreal OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68
PATCH 4/9 Conditional Calls - Add kconfig menus
In reply to Mathieu DesnoyersConditional calls provide a way to compile in kernels features that can be enabled dynamically, with a very small footprint when disabled.
This patch:
Add Kconfig menus for the marker code.
---
arch/alpha/Kconfig | 6 ++++++ arch/arm/Kconfig | 6 ++++++ arch/arm26/Kconfig | 6 ++++++ arch/avr32/Kconfig.debug | 7 +++++++ arch/cris/Kconfig | 6 ++++++ arch/frv/Kconfig | 6 ++++++ arch/h8300/Kconfig | 6 ++++++ arch/i386/Kconfig | 3 +++ arch/ia64/Kconfig | 3 +++ arch/m32r/Kconfig | 6 ++++++ arch/m68k/Kconfig | 6 ++++++ arch/m68knommu/Kconfig | 6 ++++++ arch/mips/Kconfig | 6 ++++++ arch/parisc/Kconfig | 6 ++++++ arch/powerpc/Kconfig | 3 +++ arch/ppc/Kconfig | 6 ++++++ arch/s390/Kconfig | 2 ++ arch/sh/Kconfig | 6 ++++++ arch/sh64/Kconfig | 6 ++++++ arch/sparc/Kconfig | 2 ++ arch/sparc64/Kconfig | 3 +++ arch/um/Kconfig | 6 ++++++ arch/v850/Kconfig | 6 ++++++ arch/x86_64/Kconfig | 3 +++ arch/xtensa/Kconfig | 6 ++++++ kernel/Kconfig.condcall | 20 ++++++++++++++++++++ 26 files changed, 148 insertions(+)
arch/alpha/Kconfig +6 -0
@@ -642,6 +642,12 @@ source "arch/alpha/oprofile/Kconfig" +menu "Instrumentation Support" + +source "kernel/Kconfig.condcall" + +endmenu + source "arch/alpha/Kconfig.debug" source "security/Kconfig"
arch/arm/Kconfig +6 -0
@@ -1025,6 +1025,12 @@ source "arch/arm/oprofile/Kconfig" +menu "Instrumentation Support" + +source "kernel/Kconfig.condcall" + +endmenu + source "arch/arm/Kconfig.debug" source "security/Kconfig"
arch/arm26/Kconfig +6 -0
@@ -241,6 +241,12 @@ source "drivers/usb/Kconfig" +menu "Instrumentation Support" + +source "kernel/Kconfig.condcall" + +endmenu + source "arch/arm26/Kconfig.debug" source "security/Kconfig"
arch/cris/Kconfig +6 -0
@@ -198,6 +198,12 @@ source "drivers/usb/Kconfig" +menu "Instrumentation Support" + +source "kernel/Kconfig.condcall" + +endmenu + source "arch/cris/Kconfig.debug" source "security/Kconfig"
arch/frv/Kconfig +6 -0
@@ -385,6 +385,12 @@ source "fs/Kconfig" +menu "Instrumentation Support" + +source "kernel/Kconfig.condcall" + +endmenu + source "arch/frv/Kconfig.debug" source "security/Kconfig"
arch/h8300/Kconfig +6 -0
@@ -220,6 +220,12 @@ source "fs/Kconfig" +menu "Instrumentation Support" + +source "kernel/Kconfig.condcall" + +endmenu + source "arch/h8300/Kconfig.debug" source "security/Kconfig"
arch/i386/Kconfig +3 -0
@@ -1229,6 +1229,9 @@ a probepoint and specifies the callback. Kprobes is useful for kernel debugging, non-intrusive instrumentation and testing. If in doubt, say "N". + +source "kernel/Kconfig.condcall" + endmenu source "arch/i386/Kconfig.debug"
arch/ia64/Kconfig +3 -0
@@ -591,6 +591,9 @@ a probepoint and specifies the callback. Kprobes is useful for kernel debugging, non-intrusive instrumentation and testing. If in doubt, say "N". + +source "kernel/Kconfig.condcall" + endmenu source "arch/ia64/Kconfig.debug"
arch/m32r/Kconfig +6 -0
@@ -401,6 +401,12 @@ source "arch/m32r/oprofile/Kconfig" +menu "Instrumentation Support" + +source "kernel/Kconfig.condcall" + +endmenu + source "arch/m32r/Kconfig.debug" source "security/Kconfig"
arch/m68k/Kconfig +6 -0
@@ -670,6 +670,12 @@ source "fs/Kconfig" +menu "Instrumentation Support" + +source "kernel/Kconfig.condcall" + +endmenu + source "arch/m68k/Kconfig.debug" source "security/Kconfig"
arch/m68knommu/Kconfig +6 -0
@@ -676,6 +676,12 @@ source "fs/Kconfig" +menu "Instrumentation Support" + +source "kernel/Kconfig.condcall" + +endmenu + source "arch/m68knommu/Kconfig.debug" source "security/Kconfig"
arch/mips/Kconfig +6 -0
@@ -2150,6 +2150,12 @@ source "arch/mips/oprofile/Kconfig" +menu "Instrumentation Support" + +source "kernel/Kconfig.condcall" + +endmenu + source "arch/mips/Kconfig.debug" source "security/Kconfig"
arch/parisc/Kconfig +6 -0
@@ -269,6 +269,12 @@ source "arch/parisc/oprofile/Kconfig" +menu "Instrumentation Support" + +source "kernel/Kconfig.condcall" + +endmenu + source "arch/parisc/Kconfig.debug" source "security/Kconfig"
arch/powerpc/Kconfig +3 -0
@@ -902,6 +902,9 @@ a probepoint and specifies the callback. Kprobes is useful for kernel debugging, non-intrusive instrumentation and testing. If in doubt, say "N". + +source "kernel/Kconfig.condcall" + endmenu source "arch/powerpc/Kconfig.debug"
arch/ppc/Kconfig +6 -0
@@ -1453,8 +1453,14 @@ source "lib/Kconfig" +menu "Instrumentation Support" + source "arch/powerpc/oprofile/Kconfig" +source "kernel/Kconfig.condcall" + +endmenu + source "arch/ppc/Kconfig.debug" source "security/Kconfig"
arch/s390/Kconfig +2 -0
@@ -569,6 +569,8 @@ source "lib/Kconfig.statistic" +source "kernel/Kconfig.condcall" + endmenu source "arch/s390/Kconfig.debug"
arch/sh/Kconfig +6 -0
@@ -738,6 +738,12 @@ source "arch/sh/oprofile/Kconfig" +menu "Instrumentation Support" + +source "kernel/Kconfig.condcall" + +endmenu + source "arch/sh/Kconfig.debug" source "security/Kconfig"
arch/sh64/Kconfig +6 -0
@@ -281,6 +281,12 @@ source "arch/sh64/oprofile/Kconfig" +menu "Instrumentation Support" + +source "kernel/Kconfig.condcall" + +endmenu + source "arch/sh64/Kconfig.debug" source "security/Kconfig"
arch/sparc/Kconfig +2 -0
@@ -306,6 +306,8 @@ source "arch/sparc/oprofile/Kconfig" +source "kernel/Kconfig.condcall" + endmenu source "arch/sparc/Kconfig.debug"
arch/sparc64/Kconfig +3 -0
@@ -444,6 +444,9 @@ a probepoint and specifies the callback. Kprobes is useful for kernel debugging, non-intrusive instrumentation and testing. If in doubt, say "N". + +source "kernel/Kconfig.condcall" + endmenu source "arch/sparc64/Kconfig.debug"
arch/um/Kconfig +6 -0
@@ -333,4 +333,10 @@ bool default n +menu "Instrumentation Support" + +source "kernel/Kconfig.condcall" + +endmenu + source "arch/um/Kconfig.debug"
arch/v850/Kconfig +6 -0
@@ -339,6 +339,12 @@ source "drivers/usb/Kconfig" +menu "Instrumentation Support" + +source "kernel/Kconfig.condcall" + +endmenu + source "arch/v850/Kconfig.debug" source "security/Kconfig"
arch/x86_64/Kconfig +3 -0
@@ -790,6 +790,9 @@ a probepoint and specifies the callback. Kprobes is useful for kernel debugging, non-intrusive instrumentation and testing. If in doubt, say "N". + +source "kernel/Kconfig.condcall" + endmenu source "arch/x86_64/Kconfig.debug"
arch/xtensa/Kconfig +6 -0
@@ -251,6 +251,12 @@ provide one yourself. endmenu +menu "Instrumentation Support" + +source "kernel/Kconfig.condcall" + +endmenu + source "arch/xtensa/Kconfig.debug" source "security/Kconfig"
kernel/Kconfig.condcall new file +20 -0
@@ -0,0 +1,20 @@ +# Code markers configuration + +config COND_CALL + bool "Activate conditional calls" + depends on MODULES + help + Provides a way to dynamically enable kernel features while having a + very small footprint when disabled. + +config COND_CALL_DISABLE_OPTIMIZATION + bool "Disable conditional calls optimization" + depends on COND_CALL && EMBEDDED + default n + help + Disable code replacement jump optimisations. Especially useful if your + code is in a read-only rom/flash. + +config COND_CALL_ENABLE_OPTIMIZATION + def_bool y + depends on COND_CALL && !COND_CALL_DISABLE_OPTIMIZATION
arch/avr32/Kconfig.debug +7 -0
@@ -6,6 +6,9 @@ source "lib/Kconfig.debug" +menu "Instrumentation Support" + depends on EXPERIMENTAL + config KPROBES bool "Kprobes" depends on DEBUG_KERNEL
@@ -17,4 +20,8 @@ for kernel debugging, non-intrusive instrumentation and testing. If in doubt, say "N". +source "kernel/Kconfig.condcall" + +endmenu + endmenu
Signature · 3 lines
Mathieu Desnoyers Computer Engineering Ph.D. Student, Ecole Polytechnique de Montreal OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68
PATCH 5/9 Conditional Calls - i386 Optimization
In reply to Mathieu Desnoyersi386 optimization of the cond_calls which uses a movb with code patching to set/unset the value used to populate the register used for the branch test.
--- arch/i386/kernel/Makefile | 1 arch/i386/kernel/condcall.c | 140 ++++++++++++++++++++++++++++++++++++++++++++ include/asm-i386/condcall.h | 69 +++++++++++++++++++++ 3 files changed, 209 insertions(+), 1 deletion(-)
include/asm-i386/condcall.h +68 -1
@@ -1 +1,68 @@ -#include <asm-generic/condcall.h> +#ifndef _ASM_I386_CONDCALL_H +#define _ASM_I386_CONDCALL_H + +/* +* Conditional function calls. i386 architecture optimizations. +* +* (C) Copyright 2006 Mathieu Desnoyers <[email protected]> +* +* This file is released under the GPLv2. +* See the file COPYING for more details. +*/ + + +#ifdef CONFIG_COND_CALL + +#define CF_DEFAULT (CF_OPTIMIZED | CF_LOCKDEP | CF_PRINTK) + +/* Optimized version of the cond_call. Passing the flags as a pointer to +* the inline assembly to trick it into putting the flags value as third +* parameter in the structure. */ +#define cond_call_optimized (flags, name, func) \ + ({ \ + static const char __cstrtab_name_##name[] \ + __attribute__((section("__cond_call_strings"))) = #name; \ + char condition; \ + asm ( ".section __cond_call, \"a\", @progbits;\n\t" \ + ".long %1, 0f, %2;\n\t" \ + ".previous;\n\t" \ + ".align 2\n\t" \ + "0:\n\t" \ + "movb %3,%0;\n\t" \ + : "=r" (condition) \ + : "m" (*__cstrtab_name_##name), \ + "m" (*(char*)flags), \ + "i" ((flags) & CF_STATIC_ENABLE)); \ + (likely(!condition)) ? \ + (__typeof__(func))0 : \ + (func); \ + }) + +/* cond_call macro selecting the generic or optimized version of cond_call, +* depending on the flags specified. */ +#define _cond_call (flags, name, func) \ +({ \ + (((flags) & CF_LOCKDEP) && ((flags) & CF_OPTIMIZED)) ? \ + cond_call_optimized(flags, name, func) : \ + cond_call_generic(flags, name, func); \ +}) + +/* cond_call with default behavior */ +#define cond_call (name, func) _cond_call(CF_DEFAULT, name, func) + +/* Architecture dependant cond_call information, used internally for cond_call +* activation. */ + +/* Offset of the immediate value from the start of the movb instruction, in +* bytes. */ +#define COND_CALL_OPTIMIZED_ENABLE_IMMEDIATE_OFFSET 1 +#define COND_CALL_OPTIMIZED_ENABLE_TYPE unsigned char +/* Dereference enable as lvalue from a pointer to its instruction */ +#define COND_CALL_OPTIMIZED_ENABLE (a) \ + *(COND_CALL_OPTIMIZED_ENABLE_TYPE*) \ + ((char*)a+COND_CALL_OPTIMIZED_ENABLE_IMMEDIATE_OFFSET) + +extern int cond_call_optimized_set_enable (void *address,char enable); + +#endif +#endif //_ASM_I386_CONDCALL_H
arch/i386/kernel/Makefile +1 -0
@@ -33,6 +33,7 @@ obj-y += sysenter.o vsyscall.o obj-$(CONFIG_ACPI_SRAT) += srat.o obj-$(CONFIG_EFI) += efi.o efi_stub.o +obj-$(CONFIG_COND_CALL_ENABLE_OPTIMIZATION) += condcall.o obj-$(CONFIG_DOUBLEFAULT) += doublefault.o obj-$(CONFIG_SERIAL_8250) += legacy_serial.o obj-$(CONFIG_VM86) += vm86.o
arch/i386/kernel/condcall.c new file +140 -0
140 lines not on this page · raw message
Signature · 3 lines
Mathieu Desnoyers Computer Engineering Ph.D. Student, Ecole Polytechnique de Montreal OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68
PATCH 6/9 Conditional Calls - PowerPC Optimization
In reply to Mathieu DesnoyersPowerPC optimization of the cond_calls which uses a li instruction, patched with an immediate value 0 or 1 to enable/disable the cond_call.
--- include/asm-powerpc/condcall.h | 68 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 67 insertions(+), 1 deletion(-)
include/asm-powerpc/condcall.h +67 -1
@@ -1 +1,67 @@ -#include <asm-generic/condcall.h> +#ifndef _ASM_POWERPC_CONDCALL_H +#define _ASM_POWERPC_CONDCALL_H + +/* +* Conditional function calls. PowerPC architecture optimizations. +* +* (C) Copyright 2006 Mathieu Desnoyers <[email protected]> +* +* This file is released under the GPLv2. +* See the file COPYING for more details. +*/ + +#include <asm/asm-compat.h> + +#ifdef CONFIG_COND_CALL + +#define CF_DEFAULT (CF_OPTIMIZED | CF_LOCKDEP | CF_PRINTK) + +/* Optimized version of the cond_call */ +#define cond_call_optimized (flags, name, func) \ + ({ \ + static const char __cstrtab_name_##name[] \ + __attribute__((section("__cond_call_strings"))) = #name; \ + char condition; \ + asm ( ".section __cond_call, \"a\", @progbits;\n\t" \ + PPC_LONG "%1, 0f, %2;\n\t" \ + ".previous;\n\t" \ + ".align 4\n\t" \ + "0:\n\t" \ + "li %0,%3;\n\t" \ + : "=r" (condition) \ + : "i" (__cstrtab_name_##name), \ + "i" (flags), \ + "i" ((flags) & CF_STATIC_ENABLE)); \ + (unlikely(condition)) ? \ + (func) : \ + (__typeof__(func))0; \ + }) + +/* cond_call macro selecting the generic or optimized version of cond_call, +* depending on the flags specified. */ +#define _cond_call (flags, name, func) \ +({ \ + ((flags) & CF_OPTIMIZED) ? \ + cond_call_optimized(flags, name, func) : \ + cond_call_generic(flags, name, func); \ +}) + +/* cond_call with default behavior */ +#define cond_call (name, func) _cond_call(CF_DEFAULT, name, func) + +/* Architecture dependant cond_call information, used internally for cond_call +* activation. */ + +/* Offset of the immediate value from the start of the addi instruction (result +* of the li mnemonic), in bytes. */ +#define COND_CALL_OPTIMIZED_ENABLE_IMMEDIATE_OFFSET 2 +#define COND_CALL_OPTIMIZED_ENABLE_TYPE unsigned short +/* Dereference enable as lvalue from a pointer to its instruction */ +#define COND_CALL_OPTIMIZED_ENABLE (a) \ + *(COND_CALL_OPTIMIZED_ENABLE_TYPE*) \ + ((char*)a+COND_CALL_OPTIMIZED_ENABLE_IMMEDIATE_OFFSET) + +extern int cond_call_optimized_set_enable (void *address,char enable); + +#endif +#endif //_ASM_POWERPC_CONDCALL_H
Signature · 3 lines
Mathieu Desnoyers Computer Engineering Ph.D. Student, Ecole Polytechnique de Montreal OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68
PATCH 7/9 Conditional Calls - Documentation
In reply to Mathieu Desnoyers--- Documentation/condcall.txt | 60 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+)
Documentation/condcall.txt new file +60 -0
@@ -0,0 +1,60 @@ + Using the Conditional Calls + + Mathieu Desnoyers + + +This document introduces Conditional Calls and their use. + +* Purpose of conditional calls + +A conditional call is used to compile into the kernel a function call that is +disabled at compile-time. Then, at runtime, it can be enabled dynamically. As +explained below, the opposite can also be done. + + +* Usage + +In order to use the macro cond_call, you should include linux/condcall.h. + +#include <linux/condcall.h> + +Add, in your code : + +ret = cond_call(examplecondcall, myfunc(a, b)); + +Where : +- examplecondcall is the conditional call identifier +- myfunc(a, b) is a call to myfunc with valid parameters. +- "ret" is, optionally, the variable in which the return value of myfunc() must + be put. If the conditional call is disabled, ret will be set to 0 casted to + the type of the return value of myfunc(). + +Use cond_call_arm("examplecondcall") to activate the conditional call. + +Use cond_call_disarm("examplecondcall") to deactivate the conditional call. + +Use cond_call_query("examplecondcall") to query the conditional call state. + +The cond_call mechanism supports inserting multiple instances of the same +cond_call. Conditional calls can be put in inline functions, inlined static +functions, and unrolled loops. + + +* Optimization for a given architecture + +One can implement optimized conditional calls for a given architecture by +replacing asm-$ARCH/condcall.h. + +The CF_* flags can be used to control the type of conditional call. See the +include/linux/condcall.h header for the list of flags. They can be specified as +the first parameter of the _cond_call() macro, as in the following example, +which declares a cond_call enabled statically (which can be disabled/reenabled +dynamically) + +ret = _cond_call(CF_DEFAULT | CF_STATIC_ENABLE, examplecondcall, myfunc(a, b)); + +Another example of flag usage is to declare a cond_call that always uses the +generic version of the cond_calls. It can be useful to use this when cond_calls +are placed in kernel code presenting particular reentrancy challenges. + +ret = _cond_call(CF_DEFAULT & ~CF_OPTIMIZED, examplecondcall, myfunc(a, b));
Signature · 3 lines
Mathieu Desnoyers Computer Engineering Ph.D. Student, Ecole Polytechnique de Montreal OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68
PATCH 8/9 F00F bug fixup for i386 - use conditional calls
In reply to Mathieu DesnoyersUse the faster conditional calls for F00F bug handling in do_page_fault.
--- arch/i386/Kconfig.cpu | 1 + arch/i386/kernel/traps.c | 2 ++ arch/i386/mm/fault.c | 35 ++++++++++++++++++++++------------- 3 files changed, 25 insertions(+), 13 deletions(-)
arch/i386/kernel/traps.c +2 -0
@@ -31,6 +31,7 @@#include <linux/uaccess.h> #include <linux/nmi.h> #include <linux/bug.h> +#include <linux/condcall.h> #ifdef CONFIG_EISA #include <linux/ioport.h>
@@ -1084,6 +1085,7 @@*/ idt_descr.address =fix_to_virt (FIX_F00F_IDT );load_idt (&idt_descr); + BUG_ON(cond_call_arm("fix_f00f")); }#endif
arch/i386/mm/fault.c +22 -13
@@ -25,6 +25,7 @@#include <linux/kprobes.h> #include <linux/uaccess.h> #include <linux/kdebug.h> +#include <linux/condcall.h> #include <asm/system.h> #include <asm/desc.h>
@@ -221,6 +222,25 @@ fastcall void do_invalid_op(struct pt_regs *, unsigned long); +#ifdef CONFIG_X86_F00F_BUG +/* +* Pentium F0 0F C7 C8 bug workaround. +*/ +static inline int do_f00f_workaround (struct pt_regs *regs, +unsigned long address) +{ +unsigned long nr; + + nr = (address - idt_descr.address) >>3 ; + +if (nr ==6 ) { +do_invalid_op (regs,0 ); +return 1 ; + } +return 0 ; +} +#endif +static inline pmd_t *vmalloc_sync_one (pgd_t *pgd,unsigned long address) {unsigned index =pgd_index (address);
@@ -474,19 +494,8 @@ }#ifdef CONFIG_X86_F00F_BUG -/* -* Pentium F0 0F C7 C8 bug workaround. -*/ -if (boot_cpu_data.f00f_bug) { -unsigned long nr; - - nr = (address - idt_descr.address) >>3 ; - -if (nr ==6 ) { -do_invalid_op (regs,0 ); -return ; - } - } +if (cond_call (fix_f00f,do_f00f_workaround (regs, address))) +return ;#endif no_context:
arch/i386/Kconfig.cpu +1 -0
@@ -275,6 +275,7 @@ config X86_F00F_BUG bool depends on M586MMX || M586TSC || M586 || M486 || M386 + select COND_CALL default y config X86_WP_WORKS_OK
Signature · 3 lines
Mathieu Desnoyers Computer Engineering Ph.D. Student, Ecole Polytechnique de Montreal OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68
PATCH 9/9 Scheduler profiling - Use conditional calls
In reply to Mathieu DesnoyersUse conditional calls with lower d-cache hit in optimized version as a condition for scheduler profiling call.
--- kernel/profile.c | 4 ++++ kernel/sched.c | 32 +++++++++++++++++++------------- 2 files changed, 23 insertions(+), 13 deletions(-)
kernel/profile.c +4 -0
@@ -23,6 +23,7 @@#include <linux/profile.h> #include <linux/highmem.h> #include <linux/mutex.h> +#include <linux/condcall.h> #include <asm/sections.h> #include <asm/semaphore.h> #include <asm/irq_regs.h>
@@ -91,6 +92,8 @@printk (KERN_INFO "kernel profiling enabled (shift: %ld)\n" , prof_shift); } +if (prof_on) +BUG_ON (cond_call_arm ("profile_on" ));return 1 ; }__setup ("profile=" , profile_setup);
@@ -555,6 +558,7 @@return 0 ; out_cleanup: prof_on =0 ; +cond_call_disarm ("profile_on" );smp_mb ();on_each_cpu (profile_nop,NULL ,0 ,1 );for_each_online_cpu (cpu) {
kernel/sched.c +19 -13
@@ -54,6 +54,7 @@#include <linux/kprobes.h> #include <linux/delayacct.h> #include <linux/reciprocal_div.h> +#include <linux/condcall.h> #include <asm/tlb.h> #include <asm/unistd.h>
@@ -972,6 +973,21 @@ }/* +* Sleep time is in units of nanosecs, so shift by 20 to get a +* milliseconds-range estimation of the amount of time that the task +* spent sleeping: +*/ +static inline void activate_task_prof (struct task_struct *p, +unsigned long long now) +{ +if (unlikely (prof_on ==SLEEP_PROFILING )) { +if (p->state ==TASK_UNINTERRUPTIBLE ) +profile_hits (SLEEP_PROFILING , (void *)get_wchan (p), + (now - p->timestamp) >>20 ); + } +} + +/* * activate_task - move a task to the runqueue and do priority recalculation * * Update all the scheduling statistics stuff. (sleep average
@@ -993,18 +1009,7 @@ + rq->most_recent_timestamp; }#endif - -/* -* Sleep time is in units of nanosecs, so shift by 20 to get a -* milliseconds-range estimation of the amount of time that the task -* spent sleeping: -*/ -if (unlikely (prof_on ==SLEEP_PROFILING )) { -if (p->state ==TASK_UNINTERRUPTIBLE ) -profile_hits (SLEEP_PROFILING , (void *)get_wchan (p), - (now - p->timestamp) >>20 ); - } - +cond_call (profile_on,activate_task_prof (p, now)); p->prio =recalc_task_prio (p, now);/*
@@ -3534,7 +3539,8 @@print_irqtrace_events (current);dump_stack (); } -profile_hit (SCHED_PROFILING ,__builtin_return_address (0 )); +cond_call (profile_on, +profile_hit (SCHED_PROFILING ,__builtin_return_address (0 ))); need_resched:preempt_disable ();
Signature · 3 lines
Mathieu Desnoyers Computer Engineering Ph.D. Student, Ecole Polytechnique de Montreal OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68
It seems I was still working on 2.6.21-mm2. A new patch for 2.6.22-mm1 will be posted in a jiffy.
Mathieu
Quoted 33 lines · * Mathieu Desnoyers ([email protected]) wrote:
Hi,
Following Andi Kleen's advice, I splitted the jump-over-call into a speparate piece of infrastructure so it can be used more widely.
It also use a hash table to permit
cond_callenable/disable both when thecond_callis armed and when a module containing an armedcond_callis loaded.Please add at the end of the 2.6.22-mm1 series,
conditional-calls-architecture-independent-code.patch conditional-calls-hash-table.patch conditional-calls-non-optimized-architectures.patch conditional-calls-kconfig-menus.patch conditional-calls-i386-optimization.patch conditional-calls-powerpc-optimization.patch conditional-calls-documentation.patch
#
f00f-bug-use-cond-calls.patch profiling-use-cond-calls.patchMathieu
Signature · 8 lines
Mathieu Desnoyers Computer Engineering Ph.D. Student, Ecole Polytechnique de Montreal OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68 - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Signature · 3 lines
Mathieu Desnoyers Computer Engineering Ph.D. Student, Ecole Polytechnique de Montreal OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68