diff -urP linux-2.5.59/include/linux/tlbhook.h linux-2.5.59_patched/include/linux/tlbhook.h --- linux-2.5.59/include/linux/tlbhook.h Thu Jan 1 01:00:00 1970 +++ linux-2.5.59_patched/include/linux/tlbhook.h Wed Jan 22 22:29:30 2003 @@ -0,0 +1,122 @@ +#ifndef _LINUX_TLBHOOK_H +#define _LINUX_TLBHOOK_H + +#include + +typedef struct tlb_hook_struct { + void (*flush_tlb)( void ); + void (*flush_tlb_all)( void ); + void (*flush_tlb_mm)( struct mm_struct *mm ); + void (*flush_tlb_page)( struct vm_area_struct *vma, + unsigned long addr ); + void (*flush_tlb_range)( struct vm_area_struct *vma, + unsigned long start, unsigned long end ); + void (*flush_tlb_kernel_range)( unsigned long start, + unsigned long end ); + void (*flush_tlb_pgtables)( struct mm_struct *mm, + unsigned long start, unsigned long end ); + + struct tlb_hook_struct *next; + struct tlb_hook_struct *last; +} tlb_hook_t; + +extern tlb_hook_t *tlb_hook_root; + +extern int register_tlb_hook( tlb_hook_t *hook ); +extern int unregister_tlb_hook( tlb_hook_t *hook ); + +static inline void flush_tlb_hook( void ) +{ + tlb_hook_t *hook = tlb_hook_root; + + while( hook ) + { + if( hook->flush_tlb ) + hook->flush_tlb( ); + hook = hook->next; + } +} + + +static inline void flush_tlb_all_hook( void ) +{ + tlb_hook_t *hook = tlb_hook_root; + + while( hook ) + { + if( hook->flush_tlb_all ) + hook->flush_tlb_all( ); + hook = hook->next; + } +} + + +static inline void flush_tlb_mm_hook( struct mm_struct *mm ) +{ + tlb_hook_t *hook = tlb_hook_root; + + while( hook ) + { + if( hook->flush_tlb_mm ) + hook->flush_tlb_mm( mm ); + hook = hook->next; + } +} + + +static inline void flush_tlb_page_hook( struct vm_area_struct *vma, + unsigned long addr ) +{ + tlb_hook_t *hook = tlb_hook_root; + + while( hook ) + { + if( hook->flush_tlb_page ) + hook->flush_tlb_page( vma, addr ); + hook = hook->next; + } +} + + +static inline void flush_tlb_range_hook( struct vm_area_struct *vma, + unsigned long start, unsigned long end ) +{ + tlb_hook_t *hook = tlb_hook_root; + + while( hook ) + { + if( hook->flush_tlb_range ) + hook->flush_tlb_range( vma, start, end ); + hook = hook->next; + } +} + + +static inline void flush_tlb_kernel_range_hook( unsigned long start, + unsigned long end ) +{ + tlb_hook_t *hook = tlb_hook_root; + + while( hook) + { + if( hook->flush_tlb_kernel_range ) + hook->flush_tlb_kernel_range( start, end ); + hook = hook->next; + } +} + + +static inline void flush_tlb_pgtables_hook( struct mm_struct *mm, + unsigned long start, unsigned long end ) +{ + tlb_hook_t *hook = tlb_hook_root; + + while( hook ) + { + if( hook->flush_tlb_pgtables ) + hook->flush_tlb_pgtables( mm, start, end ); + hook = hook->next; + } +} + +#endif /* _LINUX_TLBHOOK_H */ diff -urP linux-2.5.59/mm/Makefile linux-2.5.59_patched/mm/Makefile --- linux-2.5.59/mm/Makefile Fri Jan 17 03:22:20 2003 +++ linux-2.5.59_patched/mm/Makefile Wed Jan 22 22:34:06 2003 @@ -2,7 +2,8 @@ # Makefile for the linux memory manager. # -export-objs := shmem.o filemap.o mempool.o page_alloc.o page-writeback.o +export-objs := shmem.o filemap.o mempool.o page_alloc.o page-writeback.o \ + tlbhook.o mmu-y := nommu.o mmu-$(CONFIG_MMU) := fremap.o highmem.o madvise.o memory.o mincore.o \ @@ -11,6 +12,6 @@ obj-y := bootmem.o filemap.o mempool.o oom_kill.o \ page_alloc.o page-writeback.o pdflush.o readahead.o \ - slab.o swap.o truncate.o vcache.o vmscan.o $(mmu-y) + slab.o swap.o tlbhook.o truncate.o vcache.o vmscan.o $(mmu-y) obj-$(CONFIG_SWAP) += page_io.o swap_state.o swapfile.o diff -urP linux-2.5.59/mm/tlbhook.c linux-2.5.59_patched/mm/tlbhook.c --- linux-2.5.59/mm/tlbhook.c Thu Jan 1 01:00:00 1970 +++ linux-2.5.59_patched/mm/tlbhook.c Wed Jan 22 22:38:42 2003 @@ -0,0 +1,70 @@ +#include +#include + +static spinlock_t tlb_hook_lock = SPIN_LOCK_UNLOCKED; + +tlb_hook_t *tlb_hook_root = NULL; + + +/* register hooks for the flush_tlb* functions */ +int register_tlb_hook( tlb_hook_t *hook ) +{ + tlb_hook_t *last; + + if( !hook ) + return -EINVAL; + + hook->next = NULL; + + // lock the tlb_hook_struct to avoid race conditions + spin_lock( &tlb_hook_lock ); + + if( tlb_hook_root ) + { + last = tlb_hook_root->last; + tlb_hook_root->last = hook; + + hook->last = last; + last->next = hook; + } else { + hook->last = hook; + tlb_hook_root = hook; + } + + spin_unlock( &tlb_hook_lock ); + + return 0; +} + + +/* unregister hooks for the flush_tlb* functions */ +int unregister_tlb_hook( tlb_hook_t *hook ) +{ + if( !hook ) + return -EINVAL; + + // lock the tlb_hook_struct to avoid race conditions + spin_lock( &tlb_hook_lock ); + + if( hook == tlb_hook_root ) + { + tlb_hook_root = hook->next; + } else { + hook->last->next = hook->next; + } + + if( hook->next ) + { + hook->next->last = hook->last; + } else if( tlb_hook_root ) { + tlb_hook_root->last = hook->last; + } + + spin_unlock( &tlb_hook_lock ); + + return 0; +} + + +EXPORT_SYMBOL( register_tlb_hook ); +EXPORT_SYMBOL( unregister_tlb_hook );