Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 100510
b: refs/heads/master
c: 8606978
h: refs/heads/master
v: v3
  • Loading branch information
Pekka Paalanen authored and Thomas Gleixner committed May 23, 2008
1 parent 1bfbcb7 commit 4d57ae4
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 8f0f996e80b980fba07d11961d96a5fefb60976a
refs/heads/master: 86069782d62e731b4835a0cf8eb7d1d0e17cf306
8 changes: 8 additions & 0 deletions trunk/arch/x86/Kconfig.debug
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,14 @@ config IOMMU_LEAK
Add a simple leak tracer to the IOMMU code. This is useful when you
are debugging a buggy device driver that leaks IOMMU mappings.

config PAGE_FAULT_HANDLERS
bool "Custom page fault handlers"
depends on DEBUG_KERNEL
help
Allow the use of custom page fault handlers. A kernel module may
register a function that is called on every page fault. Custom
handlers are used by some debugging and reverse engineering tools.

#
# IO delay types:
#
Expand Down
56 changes: 56 additions & 0 deletions trunk/arch/x86/mm/fault.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,60 @@
#define PF_RSVD (1<<3)
#define PF_INSTR (1<<4)

#ifdef CONFIG_PAGE_FAULT_HANDLERS
static HLIST_HEAD(pf_handlers); /* protected by RCU */
static DEFINE_SPINLOCK(pf_handlers_writer);

void register_page_fault_handler(struct pf_handler *new_pfh)
{
unsigned long flags;
spin_lock_irqsave(&pf_handlers_writer, flags);
hlist_add_head_rcu(&new_pfh->hlist, &pf_handlers);
spin_unlock_irqrestore(&pf_handlers_writer, flags);
}
EXPORT_SYMBOL_GPL(register_page_fault_handler);

/**
* unregister_page_fault_handler:
* The caller must ensure @old_pfh is not in use anymore before freeing it.
* This function does not guarantee it. The list of handlers is protected by
* RCU, so you can do this by e.g. calling synchronize_rcu().
*/
void unregister_page_fault_handler(struct pf_handler *old_pfh)
{
unsigned long flags;
spin_lock_irqsave(&pf_handlers_writer, flags);
hlist_del_rcu(&old_pfh->hlist);
spin_unlock_irqrestore(&pf_handlers_writer, flags);
}
EXPORT_SYMBOL_GPL(unregister_page_fault_handler);
#endif

/* returns non-zero if do_page_fault() should return */
static int handle_custom_pf(struct pt_regs *regs, unsigned long error_code,
unsigned long address)
{
#ifdef CONFIG_PAGE_FAULT_HANDLERS
int ret = 0;
struct pf_handler *cur;
struct hlist_node *ncur;

if (hlist_empty(&pf_handlers))
return 0;

rcu_read_lock();
hlist_for_each_entry_rcu(cur, ncur, &pf_handlers, hlist) {
ret = cur->handler(regs, error_code, address);
if (ret)
break;
}
rcu_read_unlock();
return ret;
#else
return 0;
#endif
}

static inline int notify_page_fault(struct pt_regs *regs)
{
#ifdef CONFIG_KPROBES
Expand Down Expand Up @@ -601,6 +655,8 @@ void __kprobes do_page_fault(struct pt_regs *regs, unsigned long error_code)

if (notify_page_fault(regs))
return;
if (handle_custom_pf(regs, error_code, address))
return;

/*
* We fault-in kernel-space virtual memory on-demand. The
Expand Down
9 changes: 9 additions & 0 deletions trunk/include/asm-x86/kdebug.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,13 @@ extern void show_regs(struct pt_regs *regs);
extern unsigned long oops_begin(void);
extern void oops_end(unsigned long, struct pt_regs *, int signr);

struct pf_handler {
struct hlist_node hlist;
int (*handler)(struct pt_regs *regs, unsigned long error_code,
unsigned long address);
};

extern void register_page_fault_handler(struct pf_handler *new_pfh);
extern void unregister_page_fault_handler(struct pf_handler *old_pfh);

#endif

0 comments on commit 4d57ae4

Please sign in to comment.