KVM: MMU: invalidate and flush on spte small->large page size change
[safe/jmp/linux-2.6] / tools / perf / builtin-top.c
index 5f3ac9f..a66f427 100644 (file)
@@ -57,7 +57,7 @@
 
 static int                     *fd[MAX_NR_CPUS][MAX_COUNTERS];
 
-static int                     system_wide                     =      0;
+static bool                    system_wide                     =  false;
 
 static int                     default_interval                =      0;
 
@@ -68,18 +68,18 @@ static int                  target_pid                      =     -1;
 static int                     target_tid                      =     -1;
 static pid_t                   *all_tids                       =      NULL;
 static int                     thread_num                      =      0;
-static int                     inherit                         =      0;
+static bool                    inherit                         =  false;
 static int                     profile_cpu                     =     -1;
 static int                     nr_cpus                         =      0;
-static unsigned int            realtime_prio                   =      0;
-static int                     group                           =      0;
+static int                     realtime_prio                   =      0;
+static bool                    group                           =  false;
 static unsigned int            page_size;
 static unsigned int            mmap_pages                      =     16;
 static int                     freq                            =   1000; /* 1 KHz */
 
 static int                     delay_secs                      =      2;
-static int                     zero                            =      0;
-static int                     dump_symtab                     =      0;
+static bool                    zero                            =  false;
+static bool                    dump_symtab                     =  false;
 
 static bool                    hide_kernel_symbols             =  false;
 static bool                    hide_user_symbols               =  false;
@@ -96,7 +96,7 @@ struct source_line {
        struct source_line      *next;
 };
 
-static char                    *sym_filter                     =   NULL;
+static const char              *sym_filter                     =   NULL;
 struct sym_entry               *sym_filter_entry               =   NULL;
 struct sym_entry               *sym_filter_entry_sched         =   NULL;
 static int                     sym_pcnt_filter                 =      5;
@@ -420,8 +420,9 @@ static double sym_weight(const struct sym_entry *sym)
 }
 
 static long                    samples;
-static long                    userspace_samples;
+static long                    kernel_samples, us_samples;
 static long                    exact_samples;
+static long                    guest_us_samples, guest_kernel_samples;
 static const char              CONSOLE_CLEAR[] = "\e[H\e[2J";
 
 static void __list_insert_active_sym(struct sym_entry *syme)
@@ -461,7 +462,10 @@ static void print_sym_table(void)
        int printed = 0, j;
        int counter, snap = !display_weighted ? sym_counter : 0;
        float samples_per_sec = samples/delay_secs;
-       float ksamples_per_sec = (samples-userspace_samples)/delay_secs;
+       float ksamples_per_sec = kernel_samples/delay_secs;
+       float us_samples_per_sec = (us_samples)/delay_secs;
+       float guest_kernel_samples_per_sec = (guest_kernel_samples)/delay_secs;
+       float guest_us_samples_per_sec = (guest_us_samples)/delay_secs;
        float esamples_percent = (100.0*exact_samples)/samples;
        float sum_ksamples = 0.0;
        struct sym_entry *syme, *n;
@@ -470,7 +474,8 @@ static void print_sym_table(void)
        int sym_width = 0, dso_width = 0, dso_short_width = 0;
        const int win_width = winsize.ws_col - 1;
 
-       samples = userspace_samples = exact_samples = 0;
+       samples = us_samples = kernel_samples = exact_samples = 0;
+       guest_kernel_samples = guest_us_samples = 0;
 
        /* Sort the active symbols */
        pthread_mutex_lock(&active_symbols_lock);
@@ -501,10 +506,30 @@ static void print_sym_table(void)
        puts(CONSOLE_CLEAR);
 
        printf("%-*.*s\n", win_width, win_width, graph_dotted_line);
-       printf( "   PerfTop:%8.0f irqs/sec  kernel:%4.1f%%  exact: %4.1f%% [",
-               samples_per_sec,
-               100.0 - (100.0*((samples_per_sec-ksamples_per_sec)/samples_per_sec)),
-               esamples_percent);
+       if (!perf_guest) {
+               printf("   PerfTop:%8.0f irqs/sec  kernel:%4.1f%%"
+                       "  exact: %4.1f%% [",
+                       samples_per_sec,
+                       100.0 - (100.0 * ((samples_per_sec - ksamples_per_sec) /
+                                        samples_per_sec)),
+                       esamples_percent);
+       } else {
+               printf("   PerfTop:%8.0f irqs/sec  kernel:%4.1f%% us:%4.1f%%"
+                       " guest kernel:%4.1f%% guest us:%4.1f%%"
+                       " exact: %4.1f%% [",
+                       samples_per_sec,
+                       100.0 - (100.0 * ((samples_per_sec-ksamples_per_sec) /
+                                         samples_per_sec)),
+                       100.0 - (100.0 * ((samples_per_sec-us_samples_per_sec) /
+                                         samples_per_sec)),
+                       100.0 - (100.0 * ((samples_per_sec -
+                                               guest_kernel_samples_per_sec) /
+                                         samples_per_sec)),
+                       100.0 - (100.0 * ((samples_per_sec -
+                                          guest_us_samples_per_sec) /
+                                         samples_per_sec)),
+                       esamples_percent);
+       }
 
        if (nr_counters == 1 || !display_weighted) {
                printf("%Ld", (u64)attrs[0].sample_period);
@@ -597,7 +622,6 @@ static void print_sym_table(void)
 
                syme = rb_entry(nd, struct sym_entry, rb_node);
                sym = sym_entry__symbol(syme);
-
                if (++printed > print_entries || (int)syme->snap_count < count_filter)
                        continue;
 
@@ -761,7 +785,7 @@ static int key_mapped(int c)
        return 0;
 }
 
-static void handle_keypress(int c)
+static void handle_keypress(struct perf_session *session, int c)
 {
        if (!key_mapped(c)) {
                struct pollfd stdin_poll = { .fd = 0, .events = POLLIN };
@@ -830,7 +854,7 @@ static void handle_keypress(int c)
                case 'Q':
                        printf("exiting.\n");
                        if (dump_symtab)
-                               dsos__fprintf(stderr);
+                               perf_session__fprintf_dsos(session, stderr);
                        exit(0);
                case 's':
                        prompt_symbol(&sym_filter_entry, "Enter details symbol");
@@ -854,7 +878,7 @@ static void handle_keypress(int c)
                        display_weighted = ~display_weighted;
                        break;
                case 'z':
-                       zero = ~zero;
+                       zero = !zero;
                        break;
                default:
                        break;
@@ -866,6 +890,7 @@ static void *display_thread(void *arg __used)
        struct pollfd stdin_poll = { .fd = 0, .events = POLLIN };
        struct termios tc, save;
        int delay_msecs, c;
+       struct perf_session *session = (struct perf_session *) arg;
 
        tcgetattr(0, &save);
        tc = save;
@@ -886,7 +911,7 @@ repeat:
        c = getc(stdin);
        tcsetattr(0, TCSAFLUSH, &save);
 
-       handle_keypress(c);
+       handle_keypress(session, c);
        goto repeat;
 
        return NULL;
@@ -957,25 +982,46 @@ static void event__process_sample(const event_t *self,
        u64 ip = self->ip.ip;
        struct sym_entry *syme;
        struct addr_location al;
+       struct machine *machine;
        u8 origin = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
 
        ++samples;
 
        switch (origin) {
        case PERF_RECORD_MISC_USER:
-               ++userspace_samples;
+               ++us_samples;
                if (hide_user_symbols)
                        return;
+               machine = perf_session__find_host_machine(session);
                break;
        case PERF_RECORD_MISC_KERNEL:
+               ++kernel_samples;
                if (hide_kernel_symbols)
                        return;
+               machine = perf_session__find_host_machine(session);
                break;
+       case PERF_RECORD_MISC_GUEST_KERNEL:
+               ++guest_kernel_samples;
+               machine = perf_session__find_machine(session, self->ip.pid);
+               break;
+       case PERF_RECORD_MISC_GUEST_USER:
+               ++guest_us_samples;
+               /*
+                * TODO: we don't process guest user from host side
+                * except simple counting.
+                */
+               return;
        default:
                return;
        }
 
-       if (self->header.misc & PERF_RECORD_MISC_EXACT)
+       if (!machine && perf_guest) {
+               pr_err("Can't find guest [%d]'s kernel information\n",
+                       self->ip.pid);
+               return;
+       }
+
+       if (self->header.misc & PERF_RECORD_MISC_EXACT_IP)
                exact_samples++;
 
        if (event__preprocess_sample(self, session, &al, symbol_filter) < 0 ||
@@ -994,7 +1040,7 @@ static void event__process_sample(const event_t *self,
                 * --hide-kernel-symbols, even if the user specifies an
                 * invalid --vmlinux ;-)
                 */
-               if (al.map == session->vmlinux_maps[MAP__FUNCTION] &&
+               if (al.map == machine->vmlinux_maps[MAP__FUNCTION] &&
                    RB_EMPTY_ROOT(&al.map->dso->symbols[MAP__FUNCTION])) {
                        pr_err("The %s file can't be used\n",
                               symbol_conf.vmlinux_name);
@@ -1014,7 +1060,7 @@ static void event__process_sample(const event_t *self,
                        pr_err("Can't annotate %s", sym->name);
                        if (sym_filter_entry->map->dso->origin == DSO__ORIG_KERNEL) {
                                pr_err(": No vmlinux file was found in the path:\n");
-                               vmlinux_path__fprintf(stderr);
+                               machine__fprintf_vmlinux_path(machine, stderr);
                        } else
                                pr_err(".\n");
                        exit(1);
@@ -1241,7 +1287,7 @@ static int __cmd_top(void)
         * FIXME: perf_session__new should allow passing a O_MMAP, so that all this
         * mmap reading, etc is encapsulated in it. Use O_WRONLY for now.
         */
-       struct perf_session *session = perf_session__new(NULL, O_WRONLY, false);
+       struct perf_session *session = perf_session__new(NULL, O_WRONLY, false, false);
        if (session == NULL)
                return -ENOMEM;
 
@@ -1261,7 +1307,7 @@ static int __cmd_top(void)
 
        perf_session__mmap_read(session);
 
-       if (pthread_create(&thread, NULL, display_thread, NULL)) {
+       if (pthread_create(&thread, NULL, display_thread, session)) {
                printf("Could not create display thread.\n");
                exit(-1);
        }
@@ -1311,8 +1357,7 @@ static const struct option options[] = {
                   "file", "vmlinux pathname"),
        OPT_BOOLEAN('K', "hide_kernel_symbols", &hide_kernel_symbols,
                    "hide kernel symbols"),
-       OPT_INTEGER('m', "mmap-pages", &mmap_pages,
-                   "number of mmap data pages"),
+       OPT_UINTEGER('m', "mmap-pages", &mmap_pages, "number of mmap data pages"),
        OPT_INTEGER('r', "realtime", &realtime_prio,
                    "collect data with this RT SCHED_FIFO priority"),
        OPT_INTEGER('d', "delay", &delay_secs,
@@ -1335,7 +1380,7 @@ static const struct option options[] = {
                    "display this many functions"),
        OPT_BOOLEAN('U', "hide_user_symbols", &hide_user_symbols,
                    "hide user symbols"),
-       OPT_BOOLEAN('v', "verbose", &verbose,
+       OPT_INCR('v', "verbose", &verbose,
                    "be more verbose (show counter open errors, etc)"),
        OPT_END()
 };
@@ -1371,7 +1416,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
        for (i = 0; i < MAX_NR_CPUS; i++) {
                for (j = 0; j < MAX_COUNTERS; j++) {
                        fd[i][j] = malloc(sizeof(int)*thread_num);
-                       mmap_array[i][j] = malloc(
+                       mmap_array[i][j] = zalloc(
                                sizeof(struct mmap_data)*thread_num);
                        if (!fd[i][j] || !mmap_array[i][j])
                                return -ENOMEM;