--- include/linux/ipipe_base.h | 6 ++++ include/linux/ipipe_trace.h | 7 ++++- include/linux/kernel.h | 8 ++++- include/linux/preempt.h | 59 +++++++++++++++++--------------------------- include/linux/smp.h | 14 ++++++++-- kernel/ipipe/Kconfig.debug | 9 ++++++ kernel/ipipe/core.c | 25 ++++++++++++++++++ 7 files changed, 88 insertions(+), 40 deletions(-) Index: linux-2.6.20/include/linux/ipipe_base.h =================================================================== --- linux-2.6.20.orig/include/linux/ipipe_base.h +++ linux-2.6.20/include/linux/ipipe_base.h @@ -75,6 +75,12 @@ void __ipipe_unstall_root(void); void __ipipe_restore_root(unsigned long x); +#ifdef CONFIG_IPIPE_DEBUG_CONTEXT +void ipipe_check_context(struct ipipe_domain *border_ipd); +#else /* !CONFIG_IPIPE_DEBUG_CONTEXT */ +static inline void ipipe_check_context(struct ipipe_domain *border_ipd) { } +#endif /* !CONFIG_IPIPE_DEBUG_CONTEXT */ + #endif /* CONFIG_IPIPE */ #endif /* !__LINUX_IPIPE_BASE_H */ Index: linux-2.6.20/include/linux/kernel.h =================================================================== --- linux-2.6.20.orig/include/linux/kernel.h +++ linux-2.6.20/include/linux/kernel.h @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -72,9 +73,12 @@ struct user; */ #ifdef CONFIG_PREEMPT_VOLUNTARY extern int cond_resched(void); -# define might_resched() cond_resched() +# define might_resched() do { \ + ipipe_check_context(ipipe_root_domain); \ + cond_resched(); \ + } while (0) #else -# define might_resched() do { } while (0) +# define might_resched() ipipe_check_context(ipipe_root_domain) #endif #ifdef CONFIG_DEBUG_SPINLOCK_SLEEP Index: linux-2.6.20/include/linux/preempt.h =================================================================== --- linux-2.6.20.orig/include/linux/preempt.h +++ linux-2.6.20/include/linux/preempt.h @@ -8,6 +8,7 @@ #include #include +#include #ifdef CONFIG_DEBUG_PREEMPT extern void fastcall add_preempt_count(int val); @@ -26,52 +27,40 @@ asmlinkage void preempt_schedule(void); -#ifdef CONFIG_IPIPE -#include -DECLARE_PER_CPU(struct ipipe_domain *, ipipe_percpu_domain); -extern struct ipipe_domain ipipe_root; -#define ipipe_preempt_guard() (per_cpu(ipipe_percpu_domain, ipipe_processor_id()) == &ipipe_root) -#else /* !CONFIG_IPIPE */ -#define ipipe_preempt_guard() 1 -#endif /* CONFIG_IPIPE */ - -#define preempt_disable() \ -do { \ - if (ipipe_preempt_guard()) { \ - inc_preempt_count(); \ - barrier(); \ - } \ +#define preempt_disable() \ +do { \ + ipipe_check_context(ipipe_root_domain); \ + inc_preempt_count(); \ + barrier(); \ } while (0) -#define preempt_enable_no_resched() \ -do { \ - if (ipipe_preempt_guard()) { \ - barrier(); \ - dec_preempt_count(); \ - } \ +#define preempt_enable_no_resched() \ +do { \ + ipipe_check_context(ipipe_root_domain); \ + barrier(); \ + dec_preempt_count(); \ } while (0) -#define preempt_check_resched() \ -do { \ - if (ipipe_preempt_guard()) { \ - if (unlikely(test_thread_flag(TIF_NEED_RESCHED))) \ - preempt_schedule(); \ - } \ +#define preempt_check_resched() \ +do { \ + ipipe_check_context(ipipe_root_domain); \ + if (unlikely(test_thread_flag(TIF_NEED_RESCHED))) \ + preempt_schedule(); \ } while (0) -#define preempt_enable() \ -do { \ - preempt_enable_no_resched(); \ +#define preempt_enable() \ +do { \ + preempt_enable_no_resched(); \ barrier(); \ - preempt_check_resched(); \ + preempt_check_resched(); \ } while (0) #else -#define preempt_disable() do { } while (0) -#define preempt_enable_no_resched() do { } while (0) -#define preempt_enable() do { } while (0) -#define preempt_check_resched() do { } while (0) +#define preempt_disable() ipipe_check_context(ipipe_root_domain) +#define preempt_enable_no_resched() ipipe_check_context(ipipe_root_domain) +#define preempt_enable() ipipe_check_context(ipipe_root_domain) +#define preempt_check_resched() ipipe_check_context(ipipe_root_domain) #endif Index: linux-2.6.20/kernel/ipipe/Kconfig.debug =================================================================== --- linux-2.6.20.orig/kernel/ipipe/Kconfig.debug +++ linux-2.6.20/kernel/ipipe/Kconfig.debug @@ -2,6 +2,15 @@ config IPIPE_DEBUG bool "I-pipe debugging" depends on IPIPE +config IPIPE_DEBUG_CONTEXT + bool "Check for illicit cross-domain calls" + depends on IPIPE_DEBUG + ---help--- + Enable this feature to arm checkpoints in the kernel that + verify the correct invocation context. On entry of critical + Linux services a warning is issued if the caller is not + running over the root domain. + config IPIPE_TRACE bool "Latency tracing" depends on IPIPE_DEBUG Index: linux-2.6.20/kernel/ipipe/core.c =================================================================== --- linux-2.6.20.orig/kernel/ipipe/core.c +++ linux-2.6.20/kernel/ipipe/core.c @@ -33,6 +33,7 @@ #include #include #endif /* CONFIG_PROC_FS */ +#include static int __ipipe_ptd_key_count; @@ -1383,6 +1384,30 @@ void __init ipipe_init_proc(void) #endif /* CONFIG_PROC_FS */ +#ifdef CONFIG_IPIPE_DEBUG_CONTEXT +void ipipe_check_context(struct ipipe_domain *border_ipd) +{ + static int check_hit; + + if (likely(ipipe_current_domain->priority <= border_ipd->priority) || + check_hit) + return; + + check_hit = 1; + + ipipe_trace_panic_freeze(); + ipipe_set_printk_sync(ipipe_current_domain); + printk(KERN_ERR "I-pipe: Detected illicit call from domain '%s'\n" + KERN_ERR " into a service reserved for domain '%s' and " + "below.\n", + ipipe_current_domain->name, border_ipd->name); + show_stack(NULL, NULL); + ipipe_trace_panic_dump(); +} + +EXPORT_SYMBOL(ipipe_check_context); +#endif /* CONFIG_IPIPE_DEBUG_CONTEXT */ + EXPORT_SYMBOL(ipipe_virtualize_irq); EXPORT_SYMBOL(ipipe_control_irq); EXPORT_SYMBOL(ipipe_suspend_domain); Index: linux-2.6.20/include/linux/smp.h =================================================================== --- linux-2.6.20.orig/include/linux/smp.h +++ linux-2.6.20/include/linux/smp.h @@ -109,6 +109,8 @@ static inline int smp_call_function_sing #endif /* !SMP */ +#include + /* * smp_processor_id(): get the current CPU ID. * @@ -126,9 +128,17 @@ static inline int smp_call_function_sing */ #ifdef CONFIG_DEBUG_PREEMPT extern unsigned int debug_smp_processor_id(void); -# define smp_processor_id() debug_smp_processor_id() +# define smp_processor_id() \ + ({ \ + ipipe_check_context(ipipe_root_domain); \ + debug_smp_processor_id(); \ + }) #else -# define smp_processor_id() raw_smp_processor_id() +# define smp_processor_id() \ + ({ \ + ipipe_check_context(ipipe_root_domain); \ + raw_smp_processor_id(); \ + }) #endif #define get_cpu() ({ preempt_disable(); smp_processor_id(); }) Index: linux-2.6.20/include/linux/ipipe_trace.h =================================================================== --- linux-2.6.20.orig/include/linux/ipipe_trace.h +++ linux-2.6.20/include/linux/ipipe_trace.h @@ -39,6 +39,11 @@ int ipipe_trace_frozen_reset(void); void ipipe_trace_panic_freeze(void); void ipipe_trace_panic_dump(void); -#endif /* CONFIG_IPIPE_TRACE */ +#else /* !CONFIG_IPIPE_TRACE */ + +static inline void ipipe_trace_panic_freeze(void) { } +static inline void ipipe_trace_panic_dump(void) { } + +#endif /* !CONFIG_IPIPE_TRACE */ #endif /* !__LINUX_IPIPE_H */