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 Sat Jan 25 10:33:51 2003 @@ -0,0 +1,151 @@ +#ifndef _LINUX_TLBHOOK_H +#define _LINUX_TLBHOOK_H + +#include + +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; + volatile int used; +}; + +extern struct tlb_hook_struct *tlb_hook_root; + +extern int register_tlb_hook(struct tlb_hook_struct *hook); +extern int unregister_tlb_hook(struct tlb_hook_struct *hook); + +static inline void flush_tlb_hook(void) +{ + struct tlb_hook_struct *hook = tlb_hook_root; + + while(hook) + { + if(hook->flush_tlb) + { + hook->used = 1; + hook->flush_tlb(); + hook->used = 0; + } + hook = hook->next; + } +} + + +static inline void flush_tlb_all_hook(void) +{ + struct tlb_hook_struct *hook = tlb_hook_root; + + while(hook) + { + if(hook->flush_tlb_all) + { + hook->used = 1; + hook->flush_tlb_all(); + hook->used = 0; + } + hook = hook->next; + } +} + + +static inline void flush_tlb_mm_hook(struct mm_struct *mm) +{ + struct tlb_hook_struct *hook = tlb_hook_root; + + while(hook) + { + if(hook->flush_tlb_mm) + { + hook->used = 1; + hook->flush_tlb_mm(mm); + hook->used = 0; + } + hook = hook->next; + } +} + + +static inline void flush_tlb_page_hook(struct vm_area_struct *vma, + unsigned long addr) +{ + struct tlb_hook_struct *hook = tlb_hook_root; + + while(hook) + { + if(hook->flush_tlb_page) + { + hook->used = 1; + hook->flush_tlb_page(vma, addr); + hook->used = 0; + } + hook = hook->next; + } +} + + +static inline void flush_tlb_range_hook(struct vm_area_struct *vma, + unsigned long start, unsigned long end) +{ + struct tlb_hook_struct *hook = tlb_hook_root; + + while(hook) + { + if(hook->flush_tlb_range) + { + hook->used = 1; + hook->flush_tlb_range(vma, start, end); + hook->used = 0; + } + hook = hook->next; + } +} + + +static inline void flush_tlb_kernel_range_hook(unsigned long start, + unsigned long end) +{ + struct tlb_hook_struct *hook = tlb_hook_root; + + while(hook) + { + if(hook->flush_tlb_kernel_range) + { + hook->used = 1; + hook->flush_tlb_kernel_range(start, end); + hook->used = 0; + } + hook = hook->next; + } +} + + +static inline void flush_tlb_pgtables_hook(struct mm_struct *mm, + unsigned long start, unsigned long end) +{ + struct tlb_hook_struct *hook = tlb_hook_root; + + while(hook) + { + if(hook->flush_tlb_pgtables) + { + hook->used = 1; + hook->flush_tlb_pgtables(mm, start, end); + hook->used = 0; + } + 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 Sat Jan 25 03:45:01 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 Sat Jan 25 10:43:33 2003 @@ -0,0 +1,68 @@ +#include +#include + +static spinlock_t tlb_hook_lock = SPIN_LOCK_UNLOCKED; + +struct tlb_hook_struct *tlb_hook_root = NULL; + + +/* register hooks for the flush_tlb* functions */ +int register_tlb_hook(struct tlb_hook_struct *hook) +{ + if(!hook) + return -EINVAL; + + hook->last = NULL; + hook->used = 0; + + // lock the tlb_hook_struct to avoid race conditions + spin_lock(&tlb_hook_lock); + + hook->next = tlb_hook_root; + if(tlb_hook_root) + { + tlb_hook_root->last = hook; + } + tlb_hook_root = hook; + + spin_unlock(&tlb_hook_lock); + + return 0; +} + + +/* unregister hooks for the flush_tlb* functions */ +int unregister_tlb_hook(struct tlb_hook_struct *hook) +{ + if(!hook) + return -EINVAL; + + // lock the tlb_hook_struct to avoid race conditions + spin_lock(&tlb_hook_lock); + + if(hook->last) + { + hook->last->next = hook->next; + } else { + tlb_hook_root = hook->next; + } + + if(hook->next) + { + hook->next->last = hook->last; + } + + spin_unlock(&tlb_hook_lock); + + // wait until hook is unused + while(hook->used) + { + cpu_relax(); + } + + return 0; +} + + +EXPORT_SYMBOL(register_tlb_hook); +EXPORT_SYMBOL(unregister_tlb_hook);