mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-30 16:13:54 +08:00
07031e14c1
This adds the profile=kvm boot option, which enables KVM to profile VM exits. Use: "readprofile -m ./System.map | sort -n" to see the resulting output: [...] 18246 serial_out 148.3415 18945 native_flush_tlb 378.9000 23618 serial_in 212.7748 29279 __spin_unlock_irq 622.9574 43447 native_apic_write 2068.9048 52702 enable_8259A_irq 742.2817 54250 vgacon_scroll 89.3740 67394 ide_inb 6126.7273 79514 copy_page_range 98.1654 84868 do_wp_page 86.6000 140266 pit_read 783.6089 151436 ide_outb 25239.3333 152668 native_io_delay 21809.7143 174783 mask_and_ack_8259A 783.7803 362404 native_set_pte_at 36240.4000 1688747 total 0.5009 Signed-off-by: Ingo Molnar <mingo@elte.hu> Acked-by: Avi Kivity <avi@qumranet.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
127 lines
2.6 KiB
C
127 lines
2.6 KiB
C
#ifndef _LINUX_PROFILE_H
|
|
#define _LINUX_PROFILE_H
|
|
|
|
#ifdef __KERNEL__
|
|
|
|
#include <linux/kernel.h>
|
|
#include <linux/init.h>
|
|
#include <linux/cpumask.h>
|
|
#include <linux/cache.h>
|
|
|
|
#include <asm/errno.h>
|
|
|
|
extern int prof_on __read_mostly;
|
|
|
|
#define CPU_PROFILING 1
|
|
#define SCHED_PROFILING 2
|
|
#define SLEEP_PROFILING 3
|
|
#define KVM_PROFILING 4
|
|
|
|
struct proc_dir_entry;
|
|
struct pt_regs;
|
|
struct notifier_block;
|
|
|
|
/* init basic kernel profiler */
|
|
void __init profile_init(void);
|
|
void profile_tick(int);
|
|
|
|
/*
|
|
* Add multiple profiler hits to a given address:
|
|
*/
|
|
void profile_hits(int, void *ip, unsigned int nr_hits);
|
|
|
|
/*
|
|
* Single profiler hit:
|
|
*/
|
|
static inline void profile_hit(int type, void *ip)
|
|
{
|
|
/*
|
|
* Speedup for the common (no profiling enabled) case:
|
|
*/
|
|
if (unlikely(prof_on == type))
|
|
profile_hits(type, ip, 1);
|
|
}
|
|
|
|
#ifdef CONFIG_PROC_FS
|
|
void create_prof_cpu_mask(struct proc_dir_entry *);
|
|
#else
|
|
#define create_prof_cpu_mask(x) do { (void)(x); } while (0)
|
|
#endif
|
|
|
|
enum profile_type {
|
|
PROFILE_TASK_EXIT,
|
|
PROFILE_MUNMAP
|
|
};
|
|
|
|
#ifdef CONFIG_PROFILING
|
|
|
|
struct task_struct;
|
|
struct mm_struct;
|
|
|
|
/* task is in do_exit() */
|
|
void profile_task_exit(struct task_struct * task);
|
|
|
|
/* task is dead, free task struct ? Returns 1 if
|
|
* the task was taken, 0 if the task should be freed.
|
|
*/
|
|
int profile_handoff_task(struct task_struct * task);
|
|
|
|
/* sys_munmap */
|
|
void profile_munmap(unsigned long addr);
|
|
|
|
int task_handoff_register(struct notifier_block * n);
|
|
int task_handoff_unregister(struct notifier_block * n);
|
|
|
|
int profile_event_register(enum profile_type, struct notifier_block * n);
|
|
int profile_event_unregister(enum profile_type, struct notifier_block * n);
|
|
|
|
int register_timer_hook(int (*hook)(struct pt_regs *));
|
|
void unregister_timer_hook(int (*hook)(struct pt_regs *));
|
|
|
|
/* Timer based profiling hook */
|
|
extern int (*timer_hook)(struct pt_regs *);
|
|
|
|
struct pt_regs;
|
|
|
|
#else
|
|
|
|
static inline int task_handoff_register(struct notifier_block * n)
|
|
{
|
|
return -ENOSYS;
|
|
}
|
|
|
|
static inline int task_handoff_unregister(struct notifier_block * n)
|
|
{
|
|
return -ENOSYS;
|
|
}
|
|
|
|
static inline int profile_event_register(enum profile_type t, struct notifier_block * n)
|
|
{
|
|
return -ENOSYS;
|
|
}
|
|
|
|
static inline int profile_event_unregister(enum profile_type t, struct notifier_block * n)
|
|
{
|
|
return -ENOSYS;
|
|
}
|
|
|
|
#define profile_task_exit(a) do { } while (0)
|
|
#define profile_handoff_task(a) (0)
|
|
#define profile_munmap(a) do { } while (0)
|
|
|
|
static inline int register_timer_hook(int (*hook)(struct pt_regs *))
|
|
{
|
|
return -ENOSYS;
|
|
}
|
|
|
|
static inline void unregister_timer_hook(int (*hook)(struct pt_regs *))
|
|
{
|
|
return;
|
|
}
|
|
|
|
#endif /* CONFIG_PROFILING */
|
|
|
|
#endif /* __KERNEL__ */
|
|
|
|
#endif /* _LINUX_PROFILE_H */
|