* [PATCH 2/4] perf ui browser: Use libslang to read keys
From: Arnaldo Carvalho de Melo @ 2011-10-23 19:12 UTC (permalink / raw)
To: Ingo Molnar
Cc: linux-kernel, Arnaldo Carvalho de Melo, David Ahern,
Frederic Weisbecker, Mike Galbraith, Paul Mackerras,
Peter Zijlstra, Stephane Eranian
In-Reply-To: <1319397143-20301-1-git-send-email-acme@infradead.org>
From: Arnaldo Carvalho de Melo <acme@redhat.com>
Just another step in stopping the use of libnewt in perf.
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-uy6s534uqxq8tenh6s3k8ocj@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/Makefile | 1 +
tools/perf/builtin-annotate.c | 8 ++--
tools/perf/util/hist.h | 9 +--
tools/perf/util/ui/browser.c | 79 +++++++++++++++++++++----------
tools/perf/util/ui/browsers/annotate.c | 19 +++----
tools/perf/util/ui/browsers/hists.c | 33 ++++++-------
tools/perf/util/ui/keysyms.h | 25 ++++++++++
tools/perf/util/ui/libslang.h | 2 +
tools/perf/util/ui/setup.c | 13 +++++
9 files changed, 125 insertions(+), 64 deletions(-)
create mode 100644 tools/perf/util/ui/keysyms.h
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 37fe930..b98e307 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -472,6 +472,7 @@ else
LIB_H += util/ui/browser.h
LIB_H += util/ui/browsers/map.h
LIB_H += util/ui/helpline.h
+ LIB_H += util/ui/keysyms.h
LIB_H += util/ui/libslang.h
LIB_H += util/ui/progress.h
LIB_H += util/ui/util.h
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 3ea764a..46b4c24 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -118,7 +118,7 @@ static void hists__find_annotations(struct hists *self, int evidx,
int nr_events)
{
struct rb_node *nd = rb_first(&self->entries), *next;
- int key = KEY_RIGHT;
+ int key = K_RIGHT;
while (nd) {
struct hist_entry *he = rb_entry(nd, struct hist_entry, rb_node);
@@ -130,7 +130,7 @@ static void hists__find_annotations(struct hists *self, int evidx,
notes = symbol__annotation(he->ms.sym);
if (notes->src == NULL) {
find_next:
- if (key == KEY_LEFT)
+ if (key == K_LEFT)
nd = rb_prev(nd);
else
nd = rb_next(nd);
@@ -141,10 +141,10 @@ find_next:
key = hist_entry__tui_annotate(he, evidx, nr_events,
NULL, NULL, 0);
switch (key) {
- case KEY_RIGHT:
+ case K_RIGHT:
next = rb_next(nd);
break;
- case KEY_LEFT:
+ case K_LEFT:
next = rb_prev(nd);
break;
default:
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 575bcbc..ff93ddc 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -125,16 +125,13 @@ static inline int hist_entry__tui_annotate(struct hist_entry *self __used,
{
return 0;
}
-#define KEY_LEFT -1
-#define KEY_RIGHT -2
+#define K_LEFT -1
+#define K_RIGHT -2
#else
-#include <newt.h>
+#include "ui/keysyms.h"
int hist_entry__tui_annotate(struct hist_entry *he, int evidx, int nr_events,
void(*timer)(void *arg), void *arg, int delay_secs);
-#define KEY_LEFT NEWT_KEY_LEFT
-#define KEY_RIGHT NEWT_KEY_RIGHT
-
int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help,
void(*timer)(void *arg), void *arg,
int refresh);
diff --git a/tools/perf/util/ui/browser.c b/tools/perf/util/ui/browser.c
index 06fc9eb..5359f37 100644
--- a/tools/perf/util/ui/browser.c
+++ b/tools/perf/util/ui/browser.c
@@ -11,10 +11,9 @@
#include <sys/ttydefaults.h>
#include "browser.h"
#include "helpline.h"
+#include "keysyms.h"
#include "../color.h"
-int newtGetKey(void);
-
static int ui_browser__percent_color(struct ui_browser *browser,
double percent, bool current)
{
@@ -292,16 +291,55 @@ void ui_browser__update_nr_entries(struct ui_browser *browser, u32 nr_entries)
browser->seek(browser, browser->top_idx, SEEK_SET);
}
+static int ui__getch(int delay_secs)
+{
+ struct timeval timeout, *ptimeout = delay_secs ? &timeout : NULL;
+ fd_set read_set;
+ int err, key;
+
+ FD_ZERO(&read_set);
+ FD_SET(0, &read_set);
+
+ if (delay_secs) {
+ timeout.tv_sec = delay_secs;
+ timeout.tv_usec = 0;
+ }
+
+ err = select(1, &read_set, NULL, NULL, ptimeout);
+
+ if (err == 0)
+ return K_TIMER;
+
+ if (err == -1) {
+ if (errno == EINTR)
+ return K_RESIZE;
+ return K_ERROR;
+ }
+
+ key = SLang_getkey();
+ if (key != K_ESC)
+ return key;
+
+ FD_ZERO(&read_set);
+ FD_SET(0, &read_set);
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 20;
+ err = select(1, &read_set, NULL, NULL, &timeout);
+ if (err == 0)
+ return K_ESC;
+
+ SLang_ungetkey(key);
+ return SLkp_getkey();
+}
+
int ui_browser__run(struct ui_browser *self, int delay_secs)
{
int err, key;
- struct timeval timeout, *ptimeout = delay_secs ? &timeout : NULL;
pthread__unblock_sigwinch();
while (1) {
off_t offset;
- fd_set read_set;
pthread_mutex_lock(&ui__lock);
err = __ui_browser__refresh(self);
@@ -310,20 +348,9 @@ int ui_browser__run(struct ui_browser *self, int delay_secs)
if (err < 0)
break;
- FD_ZERO(&read_set);
- FD_SET(0, &read_set);
+ key = ui__getch(delay_secs);
- if (delay_secs) {
- timeout.tv_sec = delay_secs;
- timeout.tv_usec = 0;
- }
-
- err = select(1, &read_set, NULL, NULL, ptimeout);
- if (err > 0 && FD_ISSET(0, &read_set))
- key = newtGetKey();
- else if (err == 0)
- break;
- else {
+ if (key == K_RESIZE) {
pthread_mutex_lock(&ui__lock);
SLtt_get_screen_size();
SLsmg_reinit_smg();
@@ -335,9 +362,9 @@ int ui_browser__run(struct ui_browser *self, int delay_secs)
}
if (self->use_navkeypressed && !self->navkeypressed) {
- if (key == NEWT_KEY_DOWN || key == NEWT_KEY_UP ||
- key == NEWT_KEY_PGDN || key == NEWT_KEY_PGUP ||
- key == NEWT_KEY_HOME || key == NEWT_KEY_END ||
+ if (key == K_DOWN || key == K_UP ||
+ key == K_PGDN || key == K_PGUP ||
+ key == K_HOME || key == K_END ||
key == ' ') {
self->navkeypressed = true;
continue;
@@ -346,7 +373,7 @@ int ui_browser__run(struct ui_browser *self, int delay_secs)
}
switch (key) {
- case NEWT_KEY_DOWN:
+ case K_DOWN:
if (self->index == self->nr_entries - 1)
break;
++self->index;
@@ -355,7 +382,7 @@ int ui_browser__run(struct ui_browser *self, int delay_secs)
self->seek(self, +1, SEEK_CUR);
}
break;
- case NEWT_KEY_UP:
+ case K_UP:
if (self->index == 0)
break;
--self->index;
@@ -364,7 +391,7 @@ int ui_browser__run(struct ui_browser *self, int delay_secs)
self->seek(self, -1, SEEK_CUR);
}
break;
- case NEWT_KEY_PGDN:
+ case K_PGDN:
case ' ':
if (self->top_idx + self->height > self->nr_entries - 1)
break;
@@ -376,7 +403,7 @@ int ui_browser__run(struct ui_browser *self, int delay_secs)
self->top_idx += offset;
self->seek(self, +offset, SEEK_CUR);
break;
- case NEWT_KEY_PGUP:
+ case K_PGUP:
if (self->top_idx == 0)
break;
@@ -389,10 +416,10 @@ int ui_browser__run(struct ui_browser *self, int delay_secs)
self->top_idx -= offset;
self->seek(self, -offset, SEEK_CUR);
break;
- case NEWT_KEY_HOME:
+ case K_HOME:
ui_browser__reset_index(self);
break;
- case NEWT_KEY_END:
+ case K_END:
offset = self->height - 1;
if (offset >= self->nr_entries)
offset = self->nr_entries - 1;
diff --git a/tools/perf/util/ui/browsers/annotate.c b/tools/perf/util/ui/browsers/annotate.c
index 1a12d8f..4e0cb7f 100644
--- a/tools/perf/util/ui/browsers/annotate.c
+++ b/tools/perf/util/ui/browsers/annotate.c
@@ -6,6 +6,7 @@
#include "../../sort.h"
#include "../../symbol.h"
#include <pthread.h>
+#include <newt.h>
static void ui__error_window(const char *fmt, ...)
{
@@ -265,18 +266,14 @@ static int annotate_browser__run(struct annotate_browser *self, int evidx,
}
switch (key) {
- case -1:
- /*
- * FIXME we need to check if it was
- * es.reason == NEWT_EXIT_TIMER
- */
+ case K_TIMER:
if (timer != NULL)
timer(arg);
if (delay_secs != 0)
symbol__annotate_decay_histogram(sym, evidx);
continue;
- case NEWT_KEY_TAB:
+ case K_TAB:
if (nd != NULL) {
nd = rb_prev(nd);
if (nd == NULL)
@@ -284,7 +281,7 @@ static int annotate_browser__run(struct annotate_browser *self, int evidx,
} else
nd = self->curr_hot;
break;
- case NEWT_KEY_UNTAB:
+ case K_UNTAB:
if (nd != NULL)
nd = rb_next(nd);
if (nd == NULL)
@@ -299,8 +296,8 @@ static int annotate_browser__run(struct annotate_browser *self, int evidx,
if (annotate_browser__toggle_source(self))
ui_helpline__puts(help);
continue;
- case NEWT_KEY_ENTER:
- case NEWT_KEY_RIGHT:
+ case K_ENTER:
+ case K_RIGHT:
if (self->selection == NULL) {
ui_helpline__puts("Huh? No selection. Report to linux-kernel@vger.kernel.org");
continue;
@@ -350,8 +347,8 @@ static int annotate_browser__run(struct annotate_browser *self, int evidx,
timer, arg, delay_secs);
}
continue;
- case NEWT_KEY_LEFT:
- case NEWT_KEY_ESCAPE:
+ case K_LEFT:
+ case K_ESC:
case 'q':
case CTRL('c'):
goto out;
diff --git a/tools/perf/util/ui/browsers/hists.c b/tools/perf/util/ui/browsers/hists.c
index a06e7d9..af12e6f 100644
--- a/tools/perf/util/ui/browsers/hists.c
+++ b/tools/perf/util/ui/browsers/hists.c
@@ -344,7 +344,7 @@ static int hist_browser__run(struct hist_browser *self, const char *ev_name,
/* Expand the whole world. */
hist_browser__set_folding(self, true);
break;
- case NEWT_KEY_ENTER:
+ case K_ENTER:
if (hist_browser__toggle_fold(self))
break;
/* fall thru */
@@ -872,8 +872,8 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
}
switch (key) {
- case NEWT_KEY_TAB:
- case NEWT_KEY_UNTAB:
+ case K_TAB:
+ case K_UNTAB:
if (nr_events == 1)
continue;
/*
@@ -891,7 +891,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
goto zoom_dso;
case 't':
goto zoom_thread;
- case NEWT_KEY_F1:
+ case K_F1:
case 'h':
case '?':
ui__help_window("h/?/F1 Show this window\n"
@@ -909,11 +909,11 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
"d Zoom into current DSO\n"
"t Zoom into current Thread\n");
continue;
- case NEWT_KEY_ENTER:
- case NEWT_KEY_RIGHT:
+ case K_ENTER:
+ case K_RIGHT:
/* menu */
break;
- case NEWT_KEY_LEFT: {
+ case K_LEFT: {
const void *top;
if (pstack__empty(fstack)) {
@@ -931,7 +931,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
goto zoom_out_thread;
continue;
}
- case NEWT_KEY_ESCAPE:
+ case K_ESC:
if (!left_exits &&
!ui__dialog_yesno("Do you really want to exit?"))
continue;
@@ -1091,12 +1091,11 @@ static int perf_evsel_menu__run(struct perf_evsel_menu *menu,
key = ui_browser__run(&menu->b, delay_secs);
switch (key) {
- case -1:
- /* FIXME we need to check if it was es.reason == NEWT_EXIT_TIMER */
+ case K_TIMER:
timer(arg);
continue;
- case NEWT_KEY_RIGHT:
- case NEWT_KEY_ENTER:
+ case K_RIGHT:
+ case K_ENTER:
if (!menu->selection)
continue;
pos = menu->selection;
@@ -1114,19 +1113,19 @@ browse_hists:
arg, delay_secs);
ui_browser__show_title(&menu->b, title);
switch (key) {
- case NEWT_KEY_TAB:
+ case K_TAB:
if (pos->node.next == &evlist->entries)
pos = list_entry(evlist->entries.next, struct perf_evsel, node);
else
pos = list_entry(pos->node.next, struct perf_evsel, node);
goto browse_hists;
- case NEWT_KEY_UNTAB:
+ case K_UNTAB:
if (pos->node.prev == &evlist->entries)
pos = list_entry(evlist->entries.prev, struct perf_evsel, node);
else
pos = list_entry(pos->node.prev, struct perf_evsel, node);
goto browse_hists;
- case NEWT_KEY_ESCAPE:
+ case K_ESC:
if (!ui__dialog_yesno("Do you really want to exit?"))
continue;
/* Fall thru */
@@ -1136,9 +1135,9 @@ browse_hists:
default:
continue;
}
- case NEWT_KEY_LEFT:
+ case K_LEFT:
continue;
- case NEWT_KEY_ESCAPE:
+ case K_ESC:
if (!ui__dialog_yesno("Do you really want to exit?"))
continue;
/* Fall thru */
diff --git a/tools/perf/util/ui/keysyms.h b/tools/perf/util/ui/keysyms.h
new file mode 100644
index 0000000..3458b19
--- /dev/null
+++ b/tools/perf/util/ui/keysyms.h
@@ -0,0 +1,25 @@
+#ifndef _PERF_KEYSYMS_H_
+#define _PERF_KEYSYMS_H_ 1
+
+#include "libslang.h"
+
+#define K_DOWN SL_KEY_DOWN
+#define K_END SL_KEY_END
+#define K_ENTER '\r'
+#define K_ESC 033
+#define K_F1 SL_KEY_F(1)
+#define K_HOME SL_KEY_HOME
+#define K_LEFT SL_KEY_LEFT
+#define K_PGDN SL_KEY_NPAGE
+#define K_PGUP SL_KEY_PPAGE
+#define K_RIGHT SL_KEY_RIGHT
+#define K_TAB '\t'
+#define K_UNTAB SL_KEY_UNTAB
+#define K_UP SL_KEY_UP
+
+/* Not really keys */
+#define K_TIMER -1
+#define K_ERROR -2
+#define K_RESIZE -3
+
+#endif /* _PERF_KEYSYMS_H_ */
diff --git a/tools/perf/util/ui/libslang.h b/tools/perf/util/ui/libslang.h
index 2b63e1c..4d54b64 100644
--- a/tools/perf/util/ui/libslang.h
+++ b/tools/perf/util/ui/libslang.h
@@ -24,4 +24,6 @@
#define sltt_set_color SLtt_set_color
#endif
+#define SL_KEY_UNTAB 0x1000
+
#endif /* _PERF_UI_SLANG_H_ */
diff --git a/tools/perf/util/ui/setup.c b/tools/perf/util/ui/setup.c
index 5111f1a..1e6ba06 100644
--- a/tools/perf/util/ui/setup.c
+++ b/tools/perf/util/ui/setup.c
@@ -18,6 +18,18 @@ static void newt_suspend(void *d __used)
newtResume();
}
+static int ui__init(void)
+{
+ int err = SLkp_init();
+
+ if (err < 0)
+ goto out;
+
+ SLkp_define_keysym((char *)"^(kB)", SL_KEY_UNTAB);
+out:
+ return err;
+}
+
static void ui__exit(void)
{
SLtt_set_cursor_visibility(1);
@@ -44,6 +56,7 @@ void setup_browser(bool fallback_to_pager)
use_browser = 1;
newtInit();
+ ui__init();
newtSetSuspendCallback(newt_suspend, NULL);
ui_helpline__init();
ui_browser__init();
--
1.6.2.5
^ permalink raw reply related
* [PATCH 1/4] perf tools: Fix tracing info recording
From: Arnaldo Carvalho de Melo @ 2011-10-23 19:12 UTC (permalink / raw)
To: Ingo Molnar
Cc: linux-kernel, Jiri Olsa, Eric Dumazet, Ingo Molnar, Neil Horman,
Paul Mackerras, Peter Zijlstra, Steven Rostedt,
Arnaldo Carvalho de Melo
In-Reply-To: <1319397143-20301-1-git-send-email-acme@infradead.org>
From: Jiri Olsa <jolsa@redhat.com>
Fixing the way the tracing information is stored within record command.
The current implementation is causing issues for pipe output.
Following commands fail currently:
perf script syscall-counts ls
perf record -e syscalls:sys_exit_read ls | ./perf report -i -
The tracing information is part of the perf data file. It contains
several files from within the tracing debugfs and procs directories.
Beside some static header files, for each tracing event the format
file is added. The /proc/kallsyms file is also added.
The tracing data are stored with preceeding size. This is causing some
dificulties for pipe output, since there's no way to tell debugfs/proc
file size before reading it. So, for pipe output, all the debugfs files
were read twice. Once to get the overall size and once to store the
content itself. This can cause problem in case any of these file
changed, within the storage time.
To fix this behaviour and ensure the integrity of the tracing data, we:
- read debugfs/proc file into the temp file
- get temp file size and dump it to the pipe
- dump the temp file contents to the pipe
Cc: Eric Dumazet <eric.dumazet@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Neil Horman <nhorman@tuxdriver.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Steven Rostedt <rostedt@goodmis.org>
Link: http://lkml.kernel.org/r/20111020135943.GD2092@jolsa.brq.redhat.com
Signed-off-by: Jiri Olsa <jolsa@redhat.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
| 27 +++++++-
tools/perf/util/trace-event-info.c | 112 ++++++++++++++++++++++++++++--------
tools/perf/util/trace-event.h | 13 ++++-
3 files changed, 123 insertions(+), 29 deletions(-)
--git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 6a9c041..76c0b2c 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -2218,15 +2218,29 @@ int perf_event__synthesize_tracing_data(int fd, struct perf_evlist *evlist,
struct perf_session *session __unused)
{
union perf_event ev;
+ struct tracing_data *tdata;
ssize_t size = 0, aligned_size = 0, padding;
int err __used = 0;
+ /*
+ * We are going to store the size of the data followed
+ * by the data contents. Since the fd descriptor is a pipe,
+ * we cannot seek back to store the size of the data once
+ * we know it. Instead we:
+ *
+ * - write the tracing data to the temp file
+ * - get/write the data size to pipe
+ * - write the tracing data from the temp file
+ * to the pipe
+ */
+ tdata = tracing_data_get(&evlist->entries, fd, true);
+ if (!tdata)
+ return -1;
+
memset(&ev, 0, sizeof(ev));
ev.tracing_data.header.type = PERF_RECORD_HEADER_TRACING_DATA;
- size = read_tracing_data_size(fd, &evlist->entries);
- if (size <= 0)
- return size;
+ size = tdata->size;
aligned_size = ALIGN(size, sizeof(u64));
padding = aligned_size - size;
ev.tracing_data.header.size = sizeof(ev.tracing_data);
@@ -2234,7 +2248,12 @@ int perf_event__synthesize_tracing_data(int fd, struct perf_evlist *evlist,
process(&ev, NULL, session);
- err = read_tracing_data(fd, &evlist->entries);
+ /*
+ * The put function will copy all the tracing data
+ * stored in temp file to the pipe.
+ */
+ tracing_data_put(tdata);
+
write_padded(fd, NULL, 0, padding);
return aligned_size;
diff --git a/tools/perf/util/trace-event-info.c b/tools/perf/util/trace-event-info.c
index 3403f81..2d530cf 100644
--- a/tools/perf/util/trace-event-info.c
+++ b/tools/perf/util/trace-event-info.c
@@ -196,7 +196,8 @@ static void record_file(const char *file, size_t hdr_sz)
die("Can't read '%s'", file);
/* put in zeros for file size, then fill true size later */
- write_or_die(&size, hdr_sz);
+ if (hdr_sz)
+ write_or_die(&size, hdr_sz);
do {
r = read(fd, buf, BUFSIZ);
@@ -212,7 +213,7 @@ static void record_file(const char *file, size_t hdr_sz)
if (bigendian())
sizep += sizeof(u64) - hdr_sz;
- if (pwrite(output_fd, sizep, hdr_sz, hdr_pos) < 0)
+ if (hdr_sz && pwrite(output_fd, sizep, hdr_sz, hdr_pos) < 0)
die("writing to %s", output_file);
}
@@ -428,6 +429,19 @@ get_tracepoints_path(struct list_head *pattrs)
return nr_tracepoints > 0 ? path.next : NULL;
}
+static void
+put_tracepoints_path(struct tracepoint_path *tps)
+{
+ while (tps) {
+ struct tracepoint_path *t = tps;
+
+ tps = tps->next;
+ free(t->name);
+ free(t->system);
+ free(t);
+ }
+}
+
bool have_tracepoints(struct list_head *pattrs)
{
struct perf_evsel *pos;
@@ -439,19 +453,11 @@ bool have_tracepoints(struct list_head *pattrs)
return false;
}
-int read_tracing_data(int fd, struct list_head *pattrs)
+static void tracing_data_header(void)
{
- char buf[BUFSIZ];
- struct tracepoint_path *tps = get_tracepoints_path(pattrs);
-
- /*
- * What? No tracepoints? No sense writing anything here, bail out.
- */
- if (tps == NULL)
- return -1;
-
- output_fd = fd;
+ char buf[20];
+ /* just guessing this is someone's birthday.. ;) */
buf[0] = 23;
buf[1] = 8;
buf[2] = 68;
@@ -476,28 +482,86 @@ int read_tracing_data(int fd, struct list_head *pattrs)
/* save page_size */
page_size = sysconf(_SC_PAGESIZE);
write_or_die(&page_size, 4);
+}
+
+struct tracing_data *tracing_data_get(struct list_head *pattrs,
+ int fd, bool temp)
+{
+ struct tracepoint_path *tps;
+ struct tracing_data *tdata;
+
+ output_fd = fd;
+
+ tps = get_tracepoints_path(pattrs);
+ if (!tps)
+ return NULL;
+ tdata = malloc_or_die(sizeof(*tdata));
+ tdata->temp = temp;
+ tdata->size = 0;
+
+ if (temp) {
+ int temp_fd;
+
+ snprintf(tdata->temp_file, sizeof(tdata->temp_file),
+ "/tmp/perf-XXXXXX");
+ if (!mkstemp(tdata->temp_file))
+ die("Can't make temp file");
+
+ temp_fd = open(tdata->temp_file, O_RDWR);
+ if (temp_fd < 0)
+ die("Can't read '%s'", tdata->temp_file);
+
+ /*
+ * Set the temp file the default output, so all the
+ * tracing data are stored into it.
+ */
+ output_fd = temp_fd;
+ }
+
+ tracing_data_header();
read_header_files();
read_ftrace_files(tps);
read_event_files(tps);
read_proc_kallsyms();
read_ftrace_printk();
- return 0;
+ /*
+ * All tracing data are stored by now, we can restore
+ * the default output file in case we used temp file.
+ */
+ if (temp) {
+ tdata->size = lseek(output_fd, 0, SEEK_CUR);
+ close(output_fd);
+ output_fd = fd;
+ }
+
+ put_tracepoints_path(tps);
+ return tdata;
}
-ssize_t read_tracing_data_size(int fd, struct list_head *pattrs)
+void tracing_data_put(struct tracing_data *tdata)
{
- ssize_t size;
- int err = 0;
+ if (tdata->temp) {
+ record_file(tdata->temp_file, 0);
+ unlink(tdata->temp_file);
+ }
- calc_data_size = 1;
- err = read_tracing_data(fd, pattrs);
- size = calc_data_size - 1;
- calc_data_size = 0;
+ free(tdata);
+}
- if (err < 0)
- return err;
+int read_tracing_data(int fd, struct list_head *pattrs)
+{
+ struct tracing_data *tdata;
- return size;
+ /*
+ * We work over the real file, so we can write data
+ * directly, no temp file is needed.
+ */
+ tdata = tracing_data_get(pattrs, fd, false);
+ if (!tdata)
+ return -ENOMEM;
+
+ tracing_data_put(tdata);
+ return 0;
}
diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h
index f674dda..a841008 100644
--- a/tools/perf/util/trace-event.h
+++ b/tools/perf/util/trace-event.h
@@ -263,7 +263,18 @@ void *raw_field_ptr(struct event *event, const char *name, void *data);
unsigned long long eval_flag(const char *flag);
int read_tracing_data(int fd, struct list_head *pattrs);
-ssize_t read_tracing_data_size(int fd, struct list_head *pattrs);
+
+struct tracing_data {
+ /* size is only valid if temp is 'true' */
+ ssize_t size;
+ bool temp;
+ char temp_file[50];
+};
+
+struct tracing_data *tracing_data_get(struct list_head *pattrs,
+ int fd, bool temp);
+void tracing_data_put(struct tracing_data *tdata);
+
/* taken from kernel/trace/trace.h */
enum trace_flag_type {
--
1.6.2.5
^ permalink raw reply related
* [GIT PULL 0/4] perf/core fixes and improvements
From: Arnaldo Carvalho de Melo @ 2011-10-23 19:12 UTC (permalink / raw)
To: Ingo Molnar
Cc: linux-kernel, Arnaldo Carvalho de Melo, Anton Blanchard,
David Ahern, Eric Dumazet, Frederic Weisbecker, Ingo Molnar,
Jiri Olsa, Mike Galbraith, Neil Horman, Paul Mackerras,
Pekka Enberg, Peter Zijlstra, Ricardo Ribalda Delgado,
Stephane Eranian, Steven Rostedt, arnaldo.melo
Hi Ingo,
Please consider pulling from:
git://github.com/acmel/linux.git perf/core
Regards,
- Arnaldo
Arnaldo Carvalho de Melo (2):
perf ui browser: Use libslang to read keys
perf hists browser: Refuse 'a' hotkey on non symbolic views
Jiri Olsa (1):
perf tools: Fix tracing info recording
Ricardo Ribalda Delgado (1):
perf symbols: Increase symbol KSYM_NAME_LEN size
tools/perf/Makefile | 1 +
tools/perf/builtin-annotate.c | 8 +-
tools/perf/util/header.c | 27 +++++++-
tools/perf/util/hist.h | 9 +--
tools/perf/util/symbol.c | 2 +-
tools/perf/util/trace-event-info.c | 112 +++++++++++++++++++++++++-------
tools/perf/util/trace-event.h | 13 ++++-
tools/perf/util/ui/browser.c | 79 +++++++++++++++-------
tools/perf/util/ui/browsers/annotate.c | 19 ++---
tools/perf/util/ui/browsers/hists.c | 40 +++++++-----
tools/perf/util/ui/keysyms.h | 25 +++++++
tools/perf/util/ui/libslang.h | 2 +
tools/perf/util/ui/setup.c | 13 ++++
13 files changed, 256 insertions(+), 94 deletions(-)
create mode 100644 tools/perf/util/ui/keysyms.h
^ permalink raw reply
* [PATCH 4/4] perf symbols: Increase symbol KSYM_NAME_LEN size
From: Arnaldo Carvalho de Melo @ 2011-10-23 19:12 UTC (permalink / raw)
To: Ingo Molnar
Cc: linux-kernel, Ricardo Ribalda Delgado, Anton Blanchard,
David Ahern, Ingo Molnar, Paul Mackerras, Pekka Enberg,
Peter Zijlstra, Arnaldo Carvalho de Melo
In-Reply-To: <1319397143-20301-1-git-send-email-acme@infradead.org>
From: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com>
Fglrx propietary driver has symbol names over 128 chars (:S). This
breaks the function kallsyms__parse.
This fix increases the size of KSYM_NAME_LEN, so kallsyms__parse can
work on such kernels.
The only counterparty, is that such function requires 128 more bytes to
work.
Acked-by: Pekka Enberg <penberg@kernel.org>
Cc: Anton Blanchard <anton@samba.org>
Cc: David Ahern <daahern@cisco.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Pekka Enberg <penberg@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1319096606-11568-1-git-send-email-ricardo.ribalda@gmail.com
Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/util/symbol.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 3f09a23..632b50c 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -24,7 +24,7 @@
#include <sys/utsname.h>
#ifndef KSYM_NAME_LEN
-#define KSYM_NAME_LEN 128
+#define KSYM_NAME_LEN 256
#endif
#ifndef NT_GNU_BUILD_ID
--
1.6.2.5
^ permalink raw reply related
* [PATCH 3/4] perf hists browser: Refuse 'a' hotkey on non symbolic views
From: Arnaldo Carvalho de Melo @ 2011-10-23 19:12 UTC (permalink / raw)
To: Ingo Molnar
Cc: linux-kernel, Arnaldo Carvalho de Melo, David Ahern,
Frederic Weisbecker, Mike Galbraith, Paul Mackerras,
Peter Zijlstra, Stephane Eranian
In-Reply-To: <1319397143-20301-1-git-send-email-acme@infradead.org>
From: Arnaldo Carvalho de Melo <acme@redhat.com>
We don't allocate the histogram data structures for --sort lists without
"sym", so, just like was done for the menu, don't try to annotate when
'a' is pressed, just warn the user about it.
Reported-by: David Ahern <dsahern@gmail.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-27mjg02s2mbw8lfxqv7jpzec@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/util/ui/browsers/hists.c | 7 +++++++
1 files changed, 7 insertions(+), 0 deletions(-)
diff --git a/tools/perf/util/ui/browsers/hists.c b/tools/perf/util/ui/browsers/hists.c
index af12e6f..4663dcb 100644
--- a/tools/perf/util/ui/browsers/hists.c
+++ b/tools/perf/util/ui/browsers/hists.c
@@ -882,6 +882,13 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
*/
goto out_free_stack;
case 'a':
+ if (!browser->has_symbols) {
+ ui__warning(
+ "Annotation is only available for symbolic views, "
+ "include \"sym\" in --sort to use it.");
+ continue;
+ }
+
if (browser->selection == NULL ||
browser->selection->sym == NULL ||
browser->selection->map->dso->annotate_warned)
--
1.6.2.5
^ permalink raw reply related
* Re: cifs and win2k8
From: Pavel Shilovsky @ 2011-10-23 19:10 UTC (permalink / raw)
To: Jeff Layton
Cc: sean finney, Terrence Shipclark,
linux-cifs-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20111023065534.566a0aad-4QP7MXygkU+dMjc06nkz3ljfA9RmPOcC@public.gmane.org>
2011/10/23 Jeff Layton <jlayton-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>:
> On Sun, 23 Oct 2011 12:30:03 +0200
> sean finney <seanius-ADwgVSpYHhHR7s880joybQ@public.gmane.org> wrote:
>
>> Hello Terrence,
>>
>> On Fri, Oct 21, 2011 at 07:18:20AM -0400, Terrence Shipclark wrote:
>> > I have been attempting to get the cifs kernel modules to mount the
>> > win2k8 dfs at my workplace. I did finally manage to get
>> > the dfs to mount after modifying the kernel module with this small patch
>>
>> I believe this should already be fixed (in a more correct fashion) in >= 3.0.
>>
>> > Within the dfs tree there is a referral to //server/share$/folder.
>> > My user has access to //server/share$/folder, however do not have
>> > access to
>> > //server/$share. While following the referral the cifs module does a
>> > QUERY_PATH_INFO on \\server\share$\folder, and then is followed up
>> > by a QUERY_PATH_INFO on \\server\share$\ which rightfully returns a
>> > STATUS_ACCESS_DENIED from the server.
>>
>> I've also noticed that the mounting process seems to query more than
>> it should, but I've taken the easy way out and asked the local windows
>> admin to add "traverse filesystem" and "read attributes" permissions on
>> the parent folders, which should be enough. I suspect that there is a
>> "real fix" to avoid this, but haven't looked too hard myself.
>>
>>
>
> I believe this is a known bug...
>
> 3.0 got a patchset to allow superblocks to be shared, but that
> regressed the above use case (mounting a directory that you have access
> to but not the stuff below it).
>
> Pavel had some patches that he was going to propose to fix it, but
> discussion of them sort of fell off. Pavel, did you ever come up with
> something that worked here?
>
We had the discussion in "[PATCH] CIFS: Fix NT_STATUS_ACCESS_DENIED
for mounts with prefixpath option" thread in this list where I
proposed a patch that fixes it. Later I found two bugs in it but
didn't send another (right) version because we decided to fix the
permission problem another way.
After that I didn't have time to work on it. So, I am going to give it
more time when we finished with merging lock patchset and SMB2 patches
for 3.2.
Also, if you are interested, I can send you the right version of the
patch I've already posted.
--
Best regards,
Pavel Shilovsky.
^ permalink raw reply
* [PATCH RFC V2 5/5] kvm guest : pv-ticketlocks support for linux guests running on KVM hypervisor
From: Raghavendra K T @ 2011-10-23 19:07 UTC (permalink / raw)
To: Greg Kroah-Hartman, H. Peter Anvin, Gleb Natapov, Virtualization,
Jeremy Fitzhardinge, x86, KVM, Dave Jiang, Thomas Gleixner,
Stefano Stabellini, Yinghai Lu, Sedat Dilek, Ingo Molnar,
Marcelo Tosatti, Xen, Avi Kivity, Rik van Riel,
Konrad Rzeszutek Wilk, LKML
Cc: Suzuki Poulose, Srivatsa Vaddagiri, Peter Zijlstra,
Raghavendra K T
In-Reply-To: <20111023190307.16364.35381.sendpatchset@oc5400248562.ibm.com>
This patch extends Linux guests running on KVM hypervisor to support
pv-ticketlocks. Very early during bootup, paravirtualied KVM guest detects if
the hypervisor has required feature (KVM_FEATURE_WAIT_FOR_KICK) to support
pv-ticketlocks. If so, support for pv-ticketlocks is registered via pv_lock_ops.
Signed-off-by: Srivatsa Vaddagiri <vatsa@linux.vnet.ibm.com>
Signed-off-by: Suzuki Poulose <suzuki@in.ibm.com>
Signed-off-by: Raghavendra K T <raghavendra.kt@linux.vnet.ibm.com>
---
diff --git a/arch/x86/include/asm/kvm_para.h b/arch/x86/include/asm/kvm_para.h
index 2874c19..c7f34b7 100644
--- a/arch/x86/include/asm/kvm_para.h
+++ b/arch/x86/include/asm/kvm_para.h
@@ -195,10 +195,18 @@ void kvm_async_pf_task_wait(u32 token);
void kvm_async_pf_task_wake(u32 token);
u32 kvm_read_and_reset_pf_reason(void);
extern void kvm_disable_steal_time(void);
-#else
+
+#ifdef CONFIG_PARAVIRT_SPINLOCKS
+void __init kvm_guest_early_init(void);
+#else /* CONFIG_PARAVIRT_SPINLOCKS */
+#define kvm_guest_early_init() do { } while (0)
+#endif /* CONFIG_PARAVIRT_SPINLOCKS */
+
+#else /* CONFIG_KVM_GUEST */
#define kvm_guest_init() do { } while (0)
#define kvm_async_pf_task_wait(T) do {} while(0)
#define kvm_async_pf_task_wake(T) do {} while(0)
+#define kvm_guest_early_init() do { } while (0)
static inline u32 kvm_read_and_reset_pf_reason(void)
{
return 0;
diff --git a/arch/x86/kernel/head32.c b/arch/x86/kernel/head32.c
index 3bb0850..fb25bca 100644
--- a/arch/x86/kernel/head32.c
+++ b/arch/x86/kernel/head32.c
@@ -9,6 +9,7 @@
#include <linux/start_kernel.h>
#include <linux/mm.h>
#include <linux/memblock.h>
+#include <linux/kvm_para.h>
#include <asm/setup.h>
#include <asm/sections.h>
@@ -59,6 +60,8 @@ void __init i386_start_kernel(void)
break;
}
+ kvm_guest_early_init();
+
/*
* At this point everything still needed from the boot loader
* or BIOS or kernel text should be early reserved or marked not
diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c
index 5655c22..cabf8ec 100644
--- a/arch/x86/kernel/head64.c
+++ b/arch/x86/kernel/head64.c
@@ -13,6 +13,7 @@
#include <linux/start_kernel.h>
#include <linux/io.h>
#include <linux/memblock.h>
+#include <linux/kvm_para.h>
#include <asm/processor.h>
#include <asm/proto.h>
@@ -115,6 +116,8 @@ void __init x86_64_start_reservations(char *real_mode_data)
reserve_ebda_region();
+ kvm_guest_early_init();
+
/*
* At this point everything still needed from the boot loader
* or BIOS or kernel text should be early reserved or marked not
diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c
index a9c2116..f4f341f 100644
--- a/arch/x86/kernel/kvm.c
+++ b/arch/x86/kernel/kvm.c
@@ -39,6 +39,16 @@
#include <asm/desc.h>
#include <asm/tlbflush.h>
+#ifdef CONFIG_PARAVIRT_SPINLOCKS
+
+#ifdef CONFIG_KVM_DEBUG_FS
+
+#include <linux/debugfs.h>
+
+#endif /* CONFIG_KVM_DEBUG_FS */
+
+#endif /* CONFIG_PARAVIRT_SPINLOCKS */
+
#define MMU_QUEUE_SIZE 1024
static int kvmapf = 1;
@@ -627,3 +637,240 @@ static __init int activate_jump_labels(void)
return 0;
}
arch_initcall(activate_jump_labels);
+
+#ifdef CONFIG_PARAVIRT_SPINLOCKS
+
+#ifdef CONFIG_KVM_DEBUG_FS
+
+static struct kvm_spinlock_stats
+{
+ u32 taken_slow;
+ u32 taken_slow_pickup;
+
+ u32 released_slow;
+ u32 released_slow_kicked;
+
+#define HISTO_BUCKETS 30
+ u32 histo_spin_blocked[HISTO_BUCKETS+1];
+
+ u64 time_blocked;
+} spinlock_stats;
+
+static u8 zero_stats;
+
+static inline void check_zero(void)
+{
+ if (unlikely(zero_stats)) {
+ memset(&spinlock_stats, 0, sizeof(spinlock_stats));
+ zero_stats = 0;
+ }
+}
+
+#define ADD_STATS(elem, val) \
+ do { check_zero(); spinlock_stats.elem += (val); } while (0)
+
+static inline u64 spin_time_start(void)
+{
+ return sched_clock();
+}
+
+static void __spin_time_accum(u64 delta, u32 *array)
+{
+ unsigned index = ilog2(delta);
+
+ check_zero();
+
+ if (index < HISTO_BUCKETS)
+ array[index]++;
+ else
+ array[HISTO_BUCKETS]++;
+}
+
+static inline void spin_time_accum_blocked(u64 start)
+{
+ u32 delta = sched_clock() - start;
+
+ __spin_time_accum(delta, spinlock_stats.histo_spin_blocked);
+ spinlock_stats.time_blocked += delta;
+}
+
+static struct dentry *d_spin_debug;
+static struct dentry *d_kvm_debug;
+
+struct dentry *kvm_init_debugfs(void)
+{
+ d_kvm_debug = debugfs_create_dir("kvm", NULL);
+ if (!d_kvm_debug)
+ printk(KERN_WARNING "Could not create 'kvm' debugfs directory\n");
+
+ return d_kvm_debug;
+}
+
+static int __init kvm_spinlock_debugfs(void)
+{
+ struct dentry *d_kvm = kvm_init_debugfs();
+
+ if (d_kvm == NULL)
+ return -ENOMEM;
+
+ d_spin_debug = debugfs_create_dir("spinlocks", d_kvm);
+
+ debugfs_create_u8("zero_stats", 0644, d_spin_debug, &zero_stats);
+
+ debugfs_create_u32("taken_slow", 0444, d_spin_debug,
+ &spinlock_stats.taken_slow);
+ debugfs_create_u32("taken_slow_pickup", 0444, d_spin_debug,
+ &spinlock_stats.taken_slow_pickup);
+
+ debugfs_create_u32("released_slow", 0444, d_spin_debug,
+ &spinlock_stats.released_slow);
+ debugfs_create_u32("released_slow_kicked", 0444, d_spin_debug,
+ &spinlock_stats.released_slow_kicked);
+
+ debugfs_create_u64("time_blocked", 0444, d_spin_debug,
+ &spinlock_stats.time_blocked);
+
+ debugfs_create_u32_array("histo_blocked", 0444, d_spin_debug,
+ spinlock_stats.histo_spin_blocked, HISTO_BUCKETS + 1);
+
+ return 0;
+}
+fs_initcall(kvm_spinlock_debugfs);
+#else /* !CONFIG_KVM_DEBUG_FS */
+#define TIMEOUT (1 << 10)
+#define ADD_STATS(elem, val) do { (void)(val); } while (0)
+
+static inline u64 spin_time_start(void)
+{
+ return 0;
+}
+
+static inline void spin_time_accum_blocked(u64 start)
+{
+}
+#endif /* CONFIG_KVM_DEBUG_FS */
+
+struct kvm_lock_waiting {
+ struct arch_spinlock *lock;
+ __ticket_t want;
+};
+
+/* cpus 'waiting' on a spinlock to become available */
+static cpumask_t waiting_cpus;
+
+/* Track spinlock on which a cpu is waiting */
+static DEFINE_PER_CPU(struct kvm_lock_waiting, lock_waiting);
+
+static inline void kvm_wait_for_kick(void)
+{
+ kvm_hypercall0(KVM_HC_WAIT_FOR_KICK);
+}
+
+static void kvm_lock_spinning(struct arch_spinlock *lock, __ticket_t want)
+{
+ struct kvm_lock_waiting *w = &__get_cpu_var(lock_waiting);
+ int cpu = smp_processor_id();
+ u64 start;
+ unsigned long flags;
+
+ start = spin_time_start();
+
+ /*
+ * Make sure an interrupt handler can't upset things in a
+ * partially setup state.
+ */
+ local_irq_save(flags);
+
+ /*
+ * The ordering protocol on this is that the "lock" pointer
+ * may only be set non-NULL if the "want" ticket is correct.
+ * If we're updating "want", we must first clear "lock".
+ */
+ w->lock = NULL;
+ smp_wmb();
+ w->want = want;
+ smp_wmb();
+ w->lock = lock;
+
+ ADD_STATS(taken_slow, 1);
+
+ /*
+ * This uses set_bit, which is atomic but we should not rely on its
+ * reordering gurantees. So barrier is needed after this call.
+ */
+ cpumask_set_cpu(cpu, &waiting_cpus);
+
+ barrier();
+
+ /*
+ * Mark entry to slowpath before doing the pickup test to make
+ * sure we don't deadlock with an unlocker.
+ */
+ __ticket_enter_slowpath(lock);
+
+ /*
+ * check again make sure it didn't become free while
+ * we weren't looking.
+ */
+ if (ACCESS_ONCE(lock->tickets.head) == want) {
+ ADD_STATS(taken_slow_pickup, 1);
+ goto out;
+ }
+
+ /* Allow interrupts while blocked */
+ local_irq_restore(flags);
+
+ kvm_wait_for_kick();
+
+ local_irq_save(flags);
+out:
+ cpumask_clear_cpu(cpu, &waiting_cpus);
+ w->lock = NULL;
+ local_irq_restore(flags);
+ spin_time_accum_blocked(start);
+}
+PV_CALLEE_SAVE_REGS_THUNK(kvm_lock_spinning);
+
+/* Kick a cpu */
+static inline void kvm_kick_cpu(int cpu)
+{
+ kvm_hypercall1(KVM_HC_KICK_CPU, cpu);
+}
+
+/* Kick vcpu waiting on @lock->head to reach value @ticket */
+static void kvm_unlock_kick(struct arch_spinlock *lock, __ticket_t ticket)
+{
+ int cpu;
+
+ ADD_STATS(released_slow, 1);
+
+ for_each_cpu(cpu, &waiting_cpus) {
+ const struct kvm_lock_waiting *w = &per_cpu(lock_waiting, cpu);
+ if (ACCESS_ONCE(w->lock) == lock &&
+ ACCESS_ONCE(w->want) == ticket) {
+ ADD_STATS(released_slow_kicked, 1);
+ kvm_kick_cpu(cpu);
+ break;
+ }
+ }
+}
+
+/*
+ * Setup pv_lock_ops to exploit KVM_FEATURE_WAIT_FOR_KICK if present.
+ * This needs to be setup really early in boot, before the first call to
+ * spinlock is issued!
+ */
+void __init kvm_guest_early_init(void)
+{
+ if (!kvm_para_available())
+ return;
+ /* Does host kernel support KVM_FEATURE_WAIT_FOR_KICK? */
+ if (!kvm_para_has_feature(KVM_FEATURE_WAIT_FOR_KICK))
+ return;
+
+ jump_label_inc(¶virt_ticketlocks_enabled);
+
+ pv_lock_ops.lock_spinning = PV_CALLEE_SAVE(kvm_lock_spinning);
+ pv_lock_ops.unlock_kick = kvm_unlock_kick;
+}
+#endif /* CONFIG_PARAVIRT_SPINLOCKS */
^ permalink raw reply related
* [PATCH RFC V2 5/5] kvm guest : pv-ticketlocks support for linux guests running on KVM hypervisor
From: Raghavendra K T @ 2011-10-23 19:07 UTC (permalink / raw)
To: Greg Kroah-Hartman, H. Peter Anvin, Gleb Natapov, Virtualization,
Jeremy
Cc: Suzuki Poulose, Srivatsa Vaddagiri, Peter Zijlstra,
Raghavendra K T
In-Reply-To: <20111023190307.16364.35381.sendpatchset@oc5400248562.ibm.com>
This patch extends Linux guests running on KVM hypervisor to support
pv-ticketlocks. Very early during bootup, paravirtualied KVM guest detects if
the hypervisor has required feature (KVM_FEATURE_WAIT_FOR_KICK) to support
pv-ticketlocks. If so, support for pv-ticketlocks is registered via pv_lock_ops.
Signed-off-by: Srivatsa Vaddagiri <vatsa@linux.vnet.ibm.com>
Signed-off-by: Suzuki Poulose <suzuki@in.ibm.com>
Signed-off-by: Raghavendra K T <raghavendra.kt@linux.vnet.ibm.com>
---
diff --git a/arch/x86/include/asm/kvm_para.h b/arch/x86/include/asm/kvm_para.h
index 2874c19..c7f34b7 100644
--- a/arch/x86/include/asm/kvm_para.h
+++ b/arch/x86/include/asm/kvm_para.h
@@ -195,10 +195,18 @@ void kvm_async_pf_task_wait(u32 token);
void kvm_async_pf_task_wake(u32 token);
u32 kvm_read_and_reset_pf_reason(void);
extern void kvm_disable_steal_time(void);
-#else
+
+#ifdef CONFIG_PARAVIRT_SPINLOCKS
+void __init kvm_guest_early_init(void);
+#else /* CONFIG_PARAVIRT_SPINLOCKS */
+#define kvm_guest_early_init() do { } while (0)
+#endif /* CONFIG_PARAVIRT_SPINLOCKS */
+
+#else /* CONFIG_KVM_GUEST */
#define kvm_guest_init() do { } while (0)
#define kvm_async_pf_task_wait(T) do {} while(0)
#define kvm_async_pf_task_wake(T) do {} while(0)
+#define kvm_guest_early_init() do { } while (0)
static inline u32 kvm_read_and_reset_pf_reason(void)
{
return 0;
diff --git a/arch/x86/kernel/head32.c b/arch/x86/kernel/head32.c
index 3bb0850..fb25bca 100644
--- a/arch/x86/kernel/head32.c
+++ b/arch/x86/kernel/head32.c
@@ -9,6 +9,7 @@
#include <linux/start_kernel.h>
#include <linux/mm.h>
#include <linux/memblock.h>
+#include <linux/kvm_para.h>
#include <asm/setup.h>
#include <asm/sections.h>
@@ -59,6 +60,8 @@ void __init i386_start_kernel(void)
break;
}
+ kvm_guest_early_init();
+
/*
* At this point everything still needed from the boot loader
* or BIOS or kernel text should be early reserved or marked not
diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c
index 5655c22..cabf8ec 100644
--- a/arch/x86/kernel/head64.c
+++ b/arch/x86/kernel/head64.c
@@ -13,6 +13,7 @@
#include <linux/start_kernel.h>
#include <linux/io.h>
#include <linux/memblock.h>
+#include <linux/kvm_para.h>
#include <asm/processor.h>
#include <asm/proto.h>
@@ -115,6 +116,8 @@ void __init x86_64_start_reservations(char *real_mode_data)
reserve_ebda_region();
+ kvm_guest_early_init();
+
/*
* At this point everything still needed from the boot loader
* or BIOS or kernel text should be early reserved or marked not
diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c
index a9c2116..f4f341f 100644
--- a/arch/x86/kernel/kvm.c
+++ b/arch/x86/kernel/kvm.c
@@ -39,6 +39,16 @@
#include <asm/desc.h>
#include <asm/tlbflush.h>
+#ifdef CONFIG_PARAVIRT_SPINLOCKS
+
+#ifdef CONFIG_KVM_DEBUG_FS
+
+#include <linux/debugfs.h>
+
+#endif /* CONFIG_KVM_DEBUG_FS */
+
+#endif /* CONFIG_PARAVIRT_SPINLOCKS */
+
#define MMU_QUEUE_SIZE 1024
static int kvmapf = 1;
@@ -627,3 +637,240 @@ static __init int activate_jump_labels(void)
return 0;
}
arch_initcall(activate_jump_labels);
+
+#ifdef CONFIG_PARAVIRT_SPINLOCKS
+
+#ifdef CONFIG_KVM_DEBUG_FS
+
+static struct kvm_spinlock_stats
+{
+ u32 taken_slow;
+ u32 taken_slow_pickup;
+
+ u32 released_slow;
+ u32 released_slow_kicked;
+
+#define HISTO_BUCKETS 30
+ u32 histo_spin_blocked[HISTO_BUCKETS+1];
+
+ u64 time_blocked;
+} spinlock_stats;
+
+static u8 zero_stats;
+
+static inline void check_zero(void)
+{
+ if (unlikely(zero_stats)) {
+ memset(&spinlock_stats, 0, sizeof(spinlock_stats));
+ zero_stats = 0;
+ }
+}
+
+#define ADD_STATS(elem, val) \
+ do { check_zero(); spinlock_stats.elem += (val); } while (0)
+
+static inline u64 spin_time_start(void)
+{
+ return sched_clock();
+}
+
+static void __spin_time_accum(u64 delta, u32 *array)
+{
+ unsigned index = ilog2(delta);
+
+ check_zero();
+
+ if (index < HISTO_BUCKETS)
+ array[index]++;
+ else
+ array[HISTO_BUCKETS]++;
+}
+
+static inline void spin_time_accum_blocked(u64 start)
+{
+ u32 delta = sched_clock() - start;
+
+ __spin_time_accum(delta, spinlock_stats.histo_spin_blocked);
+ spinlock_stats.time_blocked += delta;
+}
+
+static struct dentry *d_spin_debug;
+static struct dentry *d_kvm_debug;
+
+struct dentry *kvm_init_debugfs(void)
+{
+ d_kvm_debug = debugfs_create_dir("kvm", NULL);
+ if (!d_kvm_debug)
+ printk(KERN_WARNING "Could not create 'kvm' debugfs directory\n");
+
+ return d_kvm_debug;
+}
+
+static int __init kvm_spinlock_debugfs(void)
+{
+ struct dentry *d_kvm = kvm_init_debugfs();
+
+ if (d_kvm == NULL)
+ return -ENOMEM;
+
+ d_spin_debug = debugfs_create_dir("spinlocks", d_kvm);
+
+ debugfs_create_u8("zero_stats", 0644, d_spin_debug, &zero_stats);
+
+ debugfs_create_u32("taken_slow", 0444, d_spin_debug,
+ &spinlock_stats.taken_slow);
+ debugfs_create_u32("taken_slow_pickup", 0444, d_spin_debug,
+ &spinlock_stats.taken_slow_pickup);
+
+ debugfs_create_u32("released_slow", 0444, d_spin_debug,
+ &spinlock_stats.released_slow);
+ debugfs_create_u32("released_slow_kicked", 0444, d_spin_debug,
+ &spinlock_stats.released_slow_kicked);
+
+ debugfs_create_u64("time_blocked", 0444, d_spin_debug,
+ &spinlock_stats.time_blocked);
+
+ debugfs_create_u32_array("histo_blocked", 0444, d_spin_debug,
+ spinlock_stats.histo_spin_blocked, HISTO_BUCKETS + 1);
+
+ return 0;
+}
+fs_initcall(kvm_spinlock_debugfs);
+#else /* !CONFIG_KVM_DEBUG_FS */
+#define TIMEOUT (1 << 10)
+#define ADD_STATS(elem, val) do { (void)(val); } while (0)
+
+static inline u64 spin_time_start(void)
+{
+ return 0;
+}
+
+static inline void spin_time_accum_blocked(u64 start)
+{
+}
+#endif /* CONFIG_KVM_DEBUG_FS */
+
+struct kvm_lock_waiting {
+ struct arch_spinlock *lock;
+ __ticket_t want;
+};
+
+/* cpus 'waiting' on a spinlock to become available */
+static cpumask_t waiting_cpus;
+
+/* Track spinlock on which a cpu is waiting */
+static DEFINE_PER_CPU(struct kvm_lock_waiting, lock_waiting);
+
+static inline void kvm_wait_for_kick(void)
+{
+ kvm_hypercall0(KVM_HC_WAIT_FOR_KICK);
+}
+
+static void kvm_lock_spinning(struct arch_spinlock *lock, __ticket_t want)
+{
+ struct kvm_lock_waiting *w = &__get_cpu_var(lock_waiting);
+ int cpu = smp_processor_id();
+ u64 start;
+ unsigned long flags;
+
+ start = spin_time_start();
+
+ /*
+ * Make sure an interrupt handler can't upset things in a
+ * partially setup state.
+ */
+ local_irq_save(flags);
+
+ /*
+ * The ordering protocol on this is that the "lock" pointer
+ * may only be set non-NULL if the "want" ticket is correct.
+ * If we're updating "want", we must first clear "lock".
+ */
+ w->lock = NULL;
+ smp_wmb();
+ w->want = want;
+ smp_wmb();
+ w->lock = lock;
+
+ ADD_STATS(taken_slow, 1);
+
+ /*
+ * This uses set_bit, which is atomic but we should not rely on its
+ * reordering gurantees. So barrier is needed after this call.
+ */
+ cpumask_set_cpu(cpu, &waiting_cpus);
+
+ barrier();
+
+ /*
+ * Mark entry to slowpath before doing the pickup test to make
+ * sure we don't deadlock with an unlocker.
+ */
+ __ticket_enter_slowpath(lock);
+
+ /*
+ * check again make sure it didn't become free while
+ * we weren't looking.
+ */
+ if (ACCESS_ONCE(lock->tickets.head) == want) {
+ ADD_STATS(taken_slow_pickup, 1);
+ goto out;
+ }
+
+ /* Allow interrupts while blocked */
+ local_irq_restore(flags);
+
+ kvm_wait_for_kick();
+
+ local_irq_save(flags);
+out:
+ cpumask_clear_cpu(cpu, &waiting_cpus);
+ w->lock = NULL;
+ local_irq_restore(flags);
+ spin_time_accum_blocked(start);
+}
+PV_CALLEE_SAVE_REGS_THUNK(kvm_lock_spinning);
+
+/* Kick a cpu */
+static inline void kvm_kick_cpu(int cpu)
+{
+ kvm_hypercall1(KVM_HC_KICK_CPU, cpu);
+}
+
+/* Kick vcpu waiting on @lock->head to reach value @ticket */
+static void kvm_unlock_kick(struct arch_spinlock *lock, __ticket_t ticket)
+{
+ int cpu;
+
+ ADD_STATS(released_slow, 1);
+
+ for_each_cpu(cpu, &waiting_cpus) {
+ const struct kvm_lock_waiting *w = &per_cpu(lock_waiting, cpu);
+ if (ACCESS_ONCE(w->lock) == lock &&
+ ACCESS_ONCE(w->want) == ticket) {
+ ADD_STATS(released_slow_kicked, 1);
+ kvm_kick_cpu(cpu);
+ break;
+ }
+ }
+}
+
+/*
+ * Setup pv_lock_ops to exploit KVM_FEATURE_WAIT_FOR_KICK if present.
+ * This needs to be setup really early in boot, before the first call to
+ * spinlock is issued!
+ */
+void __init kvm_guest_early_init(void)
+{
+ if (!kvm_para_available())
+ return;
+ /* Does host kernel support KVM_FEATURE_WAIT_FOR_KICK? */
+ if (!kvm_para_has_feature(KVM_FEATURE_WAIT_FOR_KICK))
+ return;
+
+ jump_label_inc(¶virt_ticketlocks_enabled);
+
+ pv_lock_ops.lock_spinning = PV_CALLEE_SAVE(kvm_lock_spinning);
+ pv_lock_ops.unlock_kick = kvm_unlock_kick;
+}
+#endif /* CONFIG_PARAVIRT_SPINLOCKS */
^ permalink raw reply related
* [PATCH RFC V2 5/5] kvm guest : pv-ticketlocks support for linux guests running on KVM hypervisor
From: Raghavendra K T @ 2011-10-23 19:07 UTC (permalink / raw)
To: Greg Kroah-Hartman, H. Peter Anvin, Gleb Natapov, Virtualization,
Jeremy
Cc: Peter Zijlstra, Suzuki Poulose, Raghavendra K T,
Srivatsa Vaddagiri
In-Reply-To: <20111023190307.16364.35381.sendpatchset@oc5400248562.ibm.com>
This patch extends Linux guests running on KVM hypervisor to support
pv-ticketlocks. Very early during bootup, paravirtualied KVM guest detects if
the hypervisor has required feature (KVM_FEATURE_WAIT_FOR_KICK) to support
pv-ticketlocks. If so, support for pv-ticketlocks is registered via pv_lock_ops.
Signed-off-by: Srivatsa Vaddagiri <vatsa@linux.vnet.ibm.com>
Signed-off-by: Suzuki Poulose <suzuki@in.ibm.com>
Signed-off-by: Raghavendra K T <raghavendra.kt@linux.vnet.ibm.com>
---
diff --git a/arch/x86/include/asm/kvm_para.h b/arch/x86/include/asm/kvm_para.h
index 2874c19..c7f34b7 100644
--- a/arch/x86/include/asm/kvm_para.h
+++ b/arch/x86/include/asm/kvm_para.h
@@ -195,10 +195,18 @@ void kvm_async_pf_task_wait(u32 token);
void kvm_async_pf_task_wake(u32 token);
u32 kvm_read_and_reset_pf_reason(void);
extern void kvm_disable_steal_time(void);
-#else
+
+#ifdef CONFIG_PARAVIRT_SPINLOCKS
+void __init kvm_guest_early_init(void);
+#else /* CONFIG_PARAVIRT_SPINLOCKS */
+#define kvm_guest_early_init() do { } while (0)
+#endif /* CONFIG_PARAVIRT_SPINLOCKS */
+
+#else /* CONFIG_KVM_GUEST */
#define kvm_guest_init() do { } while (0)
#define kvm_async_pf_task_wait(T) do {} while(0)
#define kvm_async_pf_task_wake(T) do {} while(0)
+#define kvm_guest_early_init() do { } while (0)
static inline u32 kvm_read_and_reset_pf_reason(void)
{
return 0;
diff --git a/arch/x86/kernel/head32.c b/arch/x86/kernel/head32.c
index 3bb0850..fb25bca 100644
--- a/arch/x86/kernel/head32.c
+++ b/arch/x86/kernel/head32.c
@@ -9,6 +9,7 @@
#include <linux/start_kernel.h>
#include <linux/mm.h>
#include <linux/memblock.h>
+#include <linux/kvm_para.h>
#include <asm/setup.h>
#include <asm/sections.h>
@@ -59,6 +60,8 @@ void __init i386_start_kernel(void)
break;
}
+ kvm_guest_early_init();
+
/*
* At this point everything still needed from the boot loader
* or BIOS or kernel text should be early reserved or marked not
diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c
index 5655c22..cabf8ec 100644
--- a/arch/x86/kernel/head64.c
+++ b/arch/x86/kernel/head64.c
@@ -13,6 +13,7 @@
#include <linux/start_kernel.h>
#include <linux/io.h>
#include <linux/memblock.h>
+#include <linux/kvm_para.h>
#include <asm/processor.h>
#include <asm/proto.h>
@@ -115,6 +116,8 @@ void __init x86_64_start_reservations(char *real_mode_data)
reserve_ebda_region();
+ kvm_guest_early_init();
+
/*
* At this point everything still needed from the boot loader
* or BIOS or kernel text should be early reserved or marked not
diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c
index a9c2116..f4f341f 100644
--- a/arch/x86/kernel/kvm.c
+++ b/arch/x86/kernel/kvm.c
@@ -39,6 +39,16 @@
#include <asm/desc.h>
#include <asm/tlbflush.h>
+#ifdef CONFIG_PARAVIRT_SPINLOCKS
+
+#ifdef CONFIG_KVM_DEBUG_FS
+
+#include <linux/debugfs.h>
+
+#endif /* CONFIG_KVM_DEBUG_FS */
+
+#endif /* CONFIG_PARAVIRT_SPINLOCKS */
+
#define MMU_QUEUE_SIZE 1024
static int kvmapf = 1;
@@ -627,3 +637,240 @@ static __init int activate_jump_labels(void)
return 0;
}
arch_initcall(activate_jump_labels);
+
+#ifdef CONFIG_PARAVIRT_SPINLOCKS
+
+#ifdef CONFIG_KVM_DEBUG_FS
+
+static struct kvm_spinlock_stats
+{
+ u32 taken_slow;
+ u32 taken_slow_pickup;
+
+ u32 released_slow;
+ u32 released_slow_kicked;
+
+#define HISTO_BUCKETS 30
+ u32 histo_spin_blocked[HISTO_BUCKETS+1];
+
+ u64 time_blocked;
+} spinlock_stats;
+
+static u8 zero_stats;
+
+static inline void check_zero(void)
+{
+ if (unlikely(zero_stats)) {
+ memset(&spinlock_stats, 0, sizeof(spinlock_stats));
+ zero_stats = 0;
+ }
+}
+
+#define ADD_STATS(elem, val) \
+ do { check_zero(); spinlock_stats.elem += (val); } while (0)
+
+static inline u64 spin_time_start(void)
+{
+ return sched_clock();
+}
+
+static void __spin_time_accum(u64 delta, u32 *array)
+{
+ unsigned index = ilog2(delta);
+
+ check_zero();
+
+ if (index < HISTO_BUCKETS)
+ array[index]++;
+ else
+ array[HISTO_BUCKETS]++;
+}
+
+static inline void spin_time_accum_blocked(u64 start)
+{
+ u32 delta = sched_clock() - start;
+
+ __spin_time_accum(delta, spinlock_stats.histo_spin_blocked);
+ spinlock_stats.time_blocked += delta;
+}
+
+static struct dentry *d_spin_debug;
+static struct dentry *d_kvm_debug;
+
+struct dentry *kvm_init_debugfs(void)
+{
+ d_kvm_debug = debugfs_create_dir("kvm", NULL);
+ if (!d_kvm_debug)
+ printk(KERN_WARNING "Could not create 'kvm' debugfs directory\n");
+
+ return d_kvm_debug;
+}
+
+static int __init kvm_spinlock_debugfs(void)
+{
+ struct dentry *d_kvm = kvm_init_debugfs();
+
+ if (d_kvm == NULL)
+ return -ENOMEM;
+
+ d_spin_debug = debugfs_create_dir("spinlocks", d_kvm);
+
+ debugfs_create_u8("zero_stats", 0644, d_spin_debug, &zero_stats);
+
+ debugfs_create_u32("taken_slow", 0444, d_spin_debug,
+ &spinlock_stats.taken_slow);
+ debugfs_create_u32("taken_slow_pickup", 0444, d_spin_debug,
+ &spinlock_stats.taken_slow_pickup);
+
+ debugfs_create_u32("released_slow", 0444, d_spin_debug,
+ &spinlock_stats.released_slow);
+ debugfs_create_u32("released_slow_kicked", 0444, d_spin_debug,
+ &spinlock_stats.released_slow_kicked);
+
+ debugfs_create_u64("time_blocked", 0444, d_spin_debug,
+ &spinlock_stats.time_blocked);
+
+ debugfs_create_u32_array("histo_blocked", 0444, d_spin_debug,
+ spinlock_stats.histo_spin_blocked, HISTO_BUCKETS + 1);
+
+ return 0;
+}
+fs_initcall(kvm_spinlock_debugfs);
+#else /* !CONFIG_KVM_DEBUG_FS */
+#define TIMEOUT (1 << 10)
+#define ADD_STATS(elem, val) do { (void)(val); } while (0)
+
+static inline u64 spin_time_start(void)
+{
+ return 0;
+}
+
+static inline void spin_time_accum_blocked(u64 start)
+{
+}
+#endif /* CONFIG_KVM_DEBUG_FS */
+
+struct kvm_lock_waiting {
+ struct arch_spinlock *lock;
+ __ticket_t want;
+};
+
+/* cpus 'waiting' on a spinlock to become available */
+static cpumask_t waiting_cpus;
+
+/* Track spinlock on which a cpu is waiting */
+static DEFINE_PER_CPU(struct kvm_lock_waiting, lock_waiting);
+
+static inline void kvm_wait_for_kick(void)
+{
+ kvm_hypercall0(KVM_HC_WAIT_FOR_KICK);
+}
+
+static void kvm_lock_spinning(struct arch_spinlock *lock, __ticket_t want)
+{
+ struct kvm_lock_waiting *w = &__get_cpu_var(lock_waiting);
+ int cpu = smp_processor_id();
+ u64 start;
+ unsigned long flags;
+
+ start = spin_time_start();
+
+ /*
+ * Make sure an interrupt handler can't upset things in a
+ * partially setup state.
+ */
+ local_irq_save(flags);
+
+ /*
+ * The ordering protocol on this is that the "lock" pointer
+ * may only be set non-NULL if the "want" ticket is correct.
+ * If we're updating "want", we must first clear "lock".
+ */
+ w->lock = NULL;
+ smp_wmb();
+ w->want = want;
+ smp_wmb();
+ w->lock = lock;
+
+ ADD_STATS(taken_slow, 1);
+
+ /*
+ * This uses set_bit, which is atomic but we should not rely on its
+ * reordering gurantees. So barrier is needed after this call.
+ */
+ cpumask_set_cpu(cpu, &waiting_cpus);
+
+ barrier();
+
+ /*
+ * Mark entry to slowpath before doing the pickup test to make
+ * sure we don't deadlock with an unlocker.
+ */
+ __ticket_enter_slowpath(lock);
+
+ /*
+ * check again make sure it didn't become free while
+ * we weren't looking.
+ */
+ if (ACCESS_ONCE(lock->tickets.head) == want) {
+ ADD_STATS(taken_slow_pickup, 1);
+ goto out;
+ }
+
+ /* Allow interrupts while blocked */
+ local_irq_restore(flags);
+
+ kvm_wait_for_kick();
+
+ local_irq_save(flags);
+out:
+ cpumask_clear_cpu(cpu, &waiting_cpus);
+ w->lock = NULL;
+ local_irq_restore(flags);
+ spin_time_accum_blocked(start);
+}
+PV_CALLEE_SAVE_REGS_THUNK(kvm_lock_spinning);
+
+/* Kick a cpu */
+static inline void kvm_kick_cpu(int cpu)
+{
+ kvm_hypercall1(KVM_HC_KICK_CPU, cpu);
+}
+
+/* Kick vcpu waiting on @lock->head to reach value @ticket */
+static void kvm_unlock_kick(struct arch_spinlock *lock, __ticket_t ticket)
+{
+ int cpu;
+
+ ADD_STATS(released_slow, 1);
+
+ for_each_cpu(cpu, &waiting_cpus) {
+ const struct kvm_lock_waiting *w = &per_cpu(lock_waiting, cpu);
+ if (ACCESS_ONCE(w->lock) == lock &&
+ ACCESS_ONCE(w->want) == ticket) {
+ ADD_STATS(released_slow_kicked, 1);
+ kvm_kick_cpu(cpu);
+ break;
+ }
+ }
+}
+
+/*
+ * Setup pv_lock_ops to exploit KVM_FEATURE_WAIT_FOR_KICK if present.
+ * This needs to be setup really early in boot, before the first call to
+ * spinlock is issued!
+ */
+void __init kvm_guest_early_init(void)
+{
+ if (!kvm_para_available())
+ return;
+ /* Does host kernel support KVM_FEATURE_WAIT_FOR_KICK? */
+ if (!kvm_para_has_feature(KVM_FEATURE_WAIT_FOR_KICK))
+ return;
+
+ jump_label_inc(¶virt_ticketlocks_enabled);
+
+ pv_lock_ops.lock_spinning = PV_CALLEE_SAVE(kvm_lock_spinning);
+ pv_lock_ops.unlock_kick = kvm_unlock_kick;
+}
+#endif /* CONFIG_PARAVIRT_SPINLOCKS */
^ permalink raw reply related
* [PATCH RFC V2 4/5] kvm guest : Added configuration support to enable debug information for KVM Guests
From: Raghavendra K T @ 2011-10-23 19:07 UTC (permalink / raw)
To: Greg Kroah-Hartman, KVM, Sedat Dilek, Ingo Molnar, Virtualization,
Jeremy Fitzhardinge, x86, H. Peter Anvin, Dave Jiang,
Thomas Gleixner, Stefano Stabellini, Gleb Natapov, Yinghai Lu,
Marcelo Tosatti, Xen, Avi Kivity, Rik van Riel,
Konrad Rzeszutek Wilk, LKML
Cc: Suzuki Poulose, Srivatsa Vaddagiri, Peter Zijlstra,
Raghavendra K T
In-Reply-To: <20111023190307.16364.35381.sendpatchset@oc5400248562.ibm.com>
Added configuration support to enable debug information
for KVM Guests in debugfs
Signed-off-by: Srivatsa Vaddagiri <vatsa@linux.vnet.ibm.com>
Signed-off-by: Suzuki Poulose <suzuki@in.ibm.com>
Signed-off-by: Raghavendra K T <raghavendra.kt@linux.vnet.ibm.com>
---
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 1f03f82..ed34269 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -562,6 +562,15 @@ config KVM_GUEST
This option enables various optimizations for running under the KVM
hypervisor.
+config KVM_DEBUG_FS
+ bool "Enable debug information for KVM Guests in debugfs"
+ depends on KVM_GUEST
+ default n
+ ---help---
+ This option enables collection of various statistics for KVM guest.
+ Statistics are displayed in debugfs filesystem. Enabling this option
+ may incur significant overhead.
+
source "arch/x86/lguest/Kconfig"
config PARAVIRT
^ permalink raw reply related
* [PATCH RFC V2 4/5] kvm guest : Added configuration support to enable debug information for KVM Guests
From: Raghavendra K T @ 2011-10-23 19:07 UTC (permalink / raw)
To: Greg Kroah-Hartman, KVM, Sedat Dilek, Ingo Molnar, Virtualization
Cc: Peter Zijlstra, Suzuki Poulose, Raghavendra K T,
Srivatsa Vaddagiri
In-Reply-To: <20111023190307.16364.35381.sendpatchset@oc5400248562.ibm.com>
Added configuration support to enable debug information
for KVM Guests in debugfs
Signed-off-by: Srivatsa Vaddagiri <vatsa@linux.vnet.ibm.com>
Signed-off-by: Suzuki Poulose <suzuki@in.ibm.com>
Signed-off-by: Raghavendra K T <raghavendra.kt@linux.vnet.ibm.com>
---
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 1f03f82..ed34269 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -562,6 +562,15 @@ config KVM_GUEST
This option enables various optimizations for running under the KVM
hypervisor.
+config KVM_DEBUG_FS
+ bool "Enable debug information for KVM Guests in debugfs"
+ depends on KVM_GUEST
+ default n
+ ---help---
+ This option enables collection of various statistics for KVM guest.
+ Statistics are displayed in debugfs filesystem. Enabling this option
+ may incur significant overhead.
+
source "arch/x86/lguest/Kconfig"
config PARAVIRT
^ permalink raw reply related
* [PATCH RFC V2 4/5] kvm guest : Added configuration support to enable debug information for KVM Guests
From: Raghavendra K T @ 2011-10-23 19:07 UTC (permalink / raw)
To: Greg Kroah-Hartman, KVM, Sedat Dilek, Ingo Molnar, Virtualization
Cc: Suzuki Poulose, Srivatsa Vaddagiri, Peter Zijlstra,
Raghavendra K T
In-Reply-To: <20111023190307.16364.35381.sendpatchset@oc5400248562.ibm.com>
Added configuration support to enable debug information
for KVM Guests in debugfs
Signed-off-by: Srivatsa Vaddagiri <vatsa@linux.vnet.ibm.com>
Signed-off-by: Suzuki Poulose <suzuki@in.ibm.com>
Signed-off-by: Raghavendra K T <raghavendra.kt@linux.vnet.ibm.com>
---
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 1f03f82..ed34269 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -562,6 +562,15 @@ config KVM_GUEST
This option enables various optimizations for running under the KVM
hypervisor.
+config KVM_DEBUG_FS
+ bool "Enable debug information for KVM Guests in debugfs"
+ depends on KVM_GUEST
+ default n
+ ---help---
+ This option enables collection of various statistics for KVM guest.
+ Statistics are displayed in debugfs filesystem. Enabling this option
+ may incur significant overhead.
+
source "arch/x86/lguest/Kconfig"
config PARAVIRT
^ permalink raw reply related
* [PATCH RFC V2 3/5] kvm hypervisor : Add two hypercalls to support pv-ticketlock
From: Raghavendra K T @ 2011-10-23 19:05 UTC (permalink / raw)
To: Greg Kroah-Hartman, H. Peter Anvin, Gleb Natapov, Virtualization,
Jeremy Fitzhardinge, x86, KVM, Dave Jiang, Thomas Gleixner,
Stefano Stabellini, Xen, Sedat Dilek, Yinghai Lu, Marcelo Tosatti,
Ingo Molnar, Avi Kivity, Rik van Riel, Konrad Rzeszutek Wilk,
LKML
Cc: Suzuki Poulose, Srivatsa Vaddagiri, Peter Zijlstra,
Raghavendra K T
In-Reply-To: <20111023190307.16364.35381.sendpatchset@oc5400248562.ibm.com>
Add two hypercalls to KVM hypervisor to support pv-ticketlocks.
KVM_HC_WAIT_FOR_KICK blocks the calling vcpu until another vcpu kicks it or it
is woken up because of an event like interrupt.
KVM_HC_KICK_CPU allows the calling vcpu to kick another vcpu.
The presence of these hypercalls is indicated to guest via
KVM_FEATURE_WAIT_FOR_KICK/KVM_CAP_WAIT_FOR_KICK.
Qemu needs a corresponding patch to pass up the presence of this feature to
guest via cpuid. Patch to qemu will be sent separately.
There is no Xen/KVM hypercall interface to await kick from.
Signed-off-by: Srivatsa Vaddagiri <vatsa@linux.vnet.ibm.com>
Signed-off-by: Suzuki Poulose <suzuki@in.ibm.com>
Signed-off-by: Raghavendra K T <raghavendra.kt@linux.vnet.ibm.com>
---
diff --git a/arch/x86/include/asm/kvm_para.h b/arch/x86/include/asm/kvm_para.h
index 734c376..2874c19 100644
--- a/arch/x86/include/asm/kvm_para.h
+++ b/arch/x86/include/asm/kvm_para.h
@@ -16,12 +16,14 @@
#define KVM_FEATURE_CLOCKSOURCE 0
#define KVM_FEATURE_NOP_IO_DELAY 1
#define KVM_FEATURE_MMU_OP 2
+
/* This indicates that the new set of kvmclock msrs
* are available. The use of 0x11 and 0x12 is deprecated
*/
#define KVM_FEATURE_CLOCKSOURCE2 3
#define KVM_FEATURE_ASYNC_PF 4
#define KVM_FEATURE_STEAL_TIME 5
+#define KVM_FEATURE_WAIT_FOR_KICK 6
/* The last 8 bits are used to indicate how to interpret the flags field
* in pvclock structure. If no bits are set, all flags are ignored.
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 84a28ea..b43fd18 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -2077,6 +2077,7 @@ int kvm_dev_ioctl_check_extension(long ext)
case KVM_CAP_XSAVE:
case KVM_CAP_ASYNC_PF:
case KVM_CAP_GET_TSC_KHZ:
+ case KVM_CAP_WAIT_FOR_KICK:
r = 1;
break;
case KVM_CAP_COALESCED_MMIO:
@@ -2548,7 +2549,8 @@ static void do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
(1 << KVM_FEATURE_NOP_IO_DELAY) |
(1 << KVM_FEATURE_CLOCKSOURCE2) |
(1 << KVM_FEATURE_ASYNC_PF) |
- (1 << KVM_FEATURE_CLOCKSOURCE_STABLE_BIT);
+ (1 << KVM_FEATURE_CLOCKSOURCE_STABLE_BIT) |
+ (1 << KVM_FEATURE_WAIT_FOR_KICK);
if (sched_info_on())
entry->eax |= (1 << KVM_FEATURE_STEAL_TIME);
@@ -5231,6 +5233,61 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu)
return 1;
}
+/*
+ * kvm_pv_wait_for_kick_op : Block until kicked by either a KVM_HC_KICK_CPU
+ * hypercall or a event like interrupt.
+ *
+ * @vcpu : vcpu which is blocking.
+ */
+static void kvm_pv_wait_for_kick_op(struct kvm_vcpu *vcpu)
+{
+ DEFINE_WAIT(wait);
+
+ /*
+ * Blocking on vcpu->wq allows us to wake up sooner if required to
+ * service pending events (like interrupts).
+ *
+ * Also set state to TASK_INTERRUPTIBLE before checking vcpu->kicked to
+ * avoid racing with kvm_pv_kick_cpu_op().
+ */
+ prepare_to_wait(&vcpu->wq, &wait, TASK_INTERRUPTIBLE);
+
+ /*
+ * Somebody has already tried kicking us. Acknowledge that
+ * and terminate the wait.
+ */
+ if (vcpu->kicked) {
+ vcpu->kicked = 0;
+ goto end_wait;
+ }
+
+ /* Let's wait for either KVM_HC_KICK_CPU or someother event
+ * to wake us up.
+ */
+
+ srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx);
+ schedule();
+ vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
+
+end_wait:
+ finish_wait(&vcpu->wq, &wait);
+}
+
+/*
+ * kvm_pv_kick_cpu_op: Kick a vcpu.
+ *
+ * @cpu - vcpu to be kicked.
+ */
+static void kvm_pv_kick_cpu_op(struct kvm *kvm, int cpu)
+{
+ struct kvm_vcpu *vcpu = kvm_get_vcpu(kvm, cpu);
+
+ if (vcpu) {
+ vcpu->kicked = 1;
+ wake_up_interruptible(&vcpu->wq);
+ }
+}
+
int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
{
unsigned long nr, a0, a1, a2, a3, ret;
@@ -5267,6 +5324,14 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
case KVM_HC_MMU_OP:
r = kvm_pv_mmu_op(vcpu, a0, hc_gpa(vcpu, a1, a2), &ret);
break;
+ case KVM_HC_WAIT_FOR_KICK:
+ kvm_pv_wait_for_kick_op(vcpu);
+ ret = 0;
+ break;
+ case KVM_HC_KICK_CPU:
+ kvm_pv_kick_cpu_op(vcpu->kvm, a0);
+ ret = 0;
+ break;
default:
ret = -KVM_ENOSYS;
break;
diff --git a/include/linux/kvm.h b/include/linux/kvm.h
index aace6b8..736acc0 100644
--- a/include/linux/kvm.h
+++ b/include/linux/kvm.h
@@ -553,6 +553,7 @@ struct kvm_ppc_pvinfo {
#define KVM_CAP_SPAPR_TCE 63
#define KVM_CAP_PPC_SMT 64
#define KVM_CAP_PPC_RMA 65
+#define KVM_CAP_WAIT_FOR_KICK 66
#define KVM_CAP_S390_GMAP 71
#ifdef KVM_CAP_IRQ_ROUTING
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index eabb21a..2946563 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -152,6 +152,11 @@ struct kvm_vcpu {
#endif
struct kvm_vcpu_arch arch;
+
+ /*
+ * blocked vcpu wakes up by checking this flag set by unlocker
+ */
+ int kicked;
};
static inline int kvm_vcpu_exiting_guest_mode(struct kvm_vcpu *vcpu)
diff --git a/include/linux/kvm_para.h b/include/linux/kvm_para.h
index 47a070b..4efee4d 100644
--- a/include/linux/kvm_para.h
+++ b/include/linux/kvm_para.h
@@ -19,6 +19,8 @@
#define KVM_HC_MMU_OP 2
#define KVM_HC_FEATURES 3
#define KVM_HC_PPC_MAP_MAGIC_PAGE 4
+#define KVM_HC_WAIT_FOR_KICK 5
+#define KVM_HC_KICK_CPU 6
/*
* hypercalls use architecture specific
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index aefdda3..d09982d 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -224,6 +224,7 @@ int kvm_vcpu_init(struct kvm_vcpu *vcpu, struct kvm *kvm, unsigned id)
vcpu->kvm = kvm;
vcpu->vcpu_id = id;
vcpu->pid = NULL;
+ vcpu->kicked = 0;
init_waitqueue_head(&vcpu->wq);
kvm_async_pf_vcpu_init(vcpu);
^ permalink raw reply related
* [PATCH RFC V2 3/5] kvm hypervisor : Add two hypercalls to support pv-ticketlock
From: Raghavendra K T @ 2011-10-23 19:05 UTC (permalink / raw)
To: Greg Kroah-Hartman, H. Peter Anvin, Gleb Natapov, Virtualization,
Jeremy
Cc: Suzuki Poulose, Srivatsa Vaddagiri, Peter Zijlstra,
Raghavendra K T
In-Reply-To: <20111023190307.16364.35381.sendpatchset@oc5400248562.ibm.com>
Add two hypercalls to KVM hypervisor to support pv-ticketlocks.
KVM_HC_WAIT_FOR_KICK blocks the calling vcpu until another vcpu kicks it or it
is woken up because of an event like interrupt.
KVM_HC_KICK_CPU allows the calling vcpu to kick another vcpu.
The presence of these hypercalls is indicated to guest via
KVM_FEATURE_WAIT_FOR_KICK/KVM_CAP_WAIT_FOR_KICK.
Qemu needs a corresponding patch to pass up the presence of this feature to
guest via cpuid. Patch to qemu will be sent separately.
There is no Xen/KVM hypercall interface to await kick from.
Signed-off-by: Srivatsa Vaddagiri <vatsa@linux.vnet.ibm.com>
Signed-off-by: Suzuki Poulose <suzuki@in.ibm.com>
Signed-off-by: Raghavendra K T <raghavendra.kt@linux.vnet.ibm.com>
---
diff --git a/arch/x86/include/asm/kvm_para.h b/arch/x86/include/asm/kvm_para.h
index 734c376..2874c19 100644
--- a/arch/x86/include/asm/kvm_para.h
+++ b/arch/x86/include/asm/kvm_para.h
@@ -16,12 +16,14 @@
#define KVM_FEATURE_CLOCKSOURCE 0
#define KVM_FEATURE_NOP_IO_DELAY 1
#define KVM_FEATURE_MMU_OP 2
+
/* This indicates that the new set of kvmclock msrs
* are available. The use of 0x11 and 0x12 is deprecated
*/
#define KVM_FEATURE_CLOCKSOURCE2 3
#define KVM_FEATURE_ASYNC_PF 4
#define KVM_FEATURE_STEAL_TIME 5
+#define KVM_FEATURE_WAIT_FOR_KICK 6
/* The last 8 bits are used to indicate how to interpret the flags field
* in pvclock structure. If no bits are set, all flags are ignored.
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 84a28ea..b43fd18 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -2077,6 +2077,7 @@ int kvm_dev_ioctl_check_extension(long ext)
case KVM_CAP_XSAVE:
case KVM_CAP_ASYNC_PF:
case KVM_CAP_GET_TSC_KHZ:
+ case KVM_CAP_WAIT_FOR_KICK:
r = 1;
break;
case KVM_CAP_COALESCED_MMIO:
@@ -2548,7 +2549,8 @@ static void do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
(1 << KVM_FEATURE_NOP_IO_DELAY) |
(1 << KVM_FEATURE_CLOCKSOURCE2) |
(1 << KVM_FEATURE_ASYNC_PF) |
- (1 << KVM_FEATURE_CLOCKSOURCE_STABLE_BIT);
+ (1 << KVM_FEATURE_CLOCKSOURCE_STABLE_BIT) |
+ (1 << KVM_FEATURE_WAIT_FOR_KICK);
if (sched_info_on())
entry->eax |= (1 << KVM_FEATURE_STEAL_TIME);
@@ -5231,6 +5233,61 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu)
return 1;
}
+/*
+ * kvm_pv_wait_for_kick_op : Block until kicked by either a KVM_HC_KICK_CPU
+ * hypercall or a event like interrupt.
+ *
+ * @vcpu : vcpu which is blocking.
+ */
+static void kvm_pv_wait_for_kick_op(struct kvm_vcpu *vcpu)
+{
+ DEFINE_WAIT(wait);
+
+ /*
+ * Blocking on vcpu->wq allows us to wake up sooner if required to
+ * service pending events (like interrupts).
+ *
+ * Also set state to TASK_INTERRUPTIBLE before checking vcpu->kicked to
+ * avoid racing with kvm_pv_kick_cpu_op().
+ */
+ prepare_to_wait(&vcpu->wq, &wait, TASK_INTERRUPTIBLE);
+
+ /*
+ * Somebody has already tried kicking us. Acknowledge that
+ * and terminate the wait.
+ */
+ if (vcpu->kicked) {
+ vcpu->kicked = 0;
+ goto end_wait;
+ }
+
+ /* Let's wait for either KVM_HC_KICK_CPU or someother event
+ * to wake us up.
+ */
+
+ srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx);
+ schedule();
+ vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
+
+end_wait:
+ finish_wait(&vcpu->wq, &wait);
+}
+
+/*
+ * kvm_pv_kick_cpu_op: Kick a vcpu.
+ *
+ * @cpu - vcpu to be kicked.
+ */
+static void kvm_pv_kick_cpu_op(struct kvm *kvm, int cpu)
+{
+ struct kvm_vcpu *vcpu = kvm_get_vcpu(kvm, cpu);
+
+ if (vcpu) {
+ vcpu->kicked = 1;
+ wake_up_interruptible(&vcpu->wq);
+ }
+}
+
int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
{
unsigned long nr, a0, a1, a2, a3, ret;
@@ -5267,6 +5324,14 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
case KVM_HC_MMU_OP:
r = kvm_pv_mmu_op(vcpu, a0, hc_gpa(vcpu, a1, a2), &ret);
break;
+ case KVM_HC_WAIT_FOR_KICK:
+ kvm_pv_wait_for_kick_op(vcpu);
+ ret = 0;
+ break;
+ case KVM_HC_KICK_CPU:
+ kvm_pv_kick_cpu_op(vcpu->kvm, a0);
+ ret = 0;
+ break;
default:
ret = -KVM_ENOSYS;
break;
diff --git a/include/linux/kvm.h b/include/linux/kvm.h
index aace6b8..736acc0 100644
--- a/include/linux/kvm.h
+++ b/include/linux/kvm.h
@@ -553,6 +553,7 @@ struct kvm_ppc_pvinfo {
#define KVM_CAP_SPAPR_TCE 63
#define KVM_CAP_PPC_SMT 64
#define KVM_CAP_PPC_RMA 65
+#define KVM_CAP_WAIT_FOR_KICK 66
#define KVM_CAP_S390_GMAP 71
#ifdef KVM_CAP_IRQ_ROUTING
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index eabb21a..2946563 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -152,6 +152,11 @@ struct kvm_vcpu {
#endif
struct kvm_vcpu_arch arch;
+
+ /*
+ * blocked vcpu wakes up by checking this flag set by unlocker
+ */
+ int kicked;
};
static inline int kvm_vcpu_exiting_guest_mode(struct kvm_vcpu *vcpu)
diff --git a/include/linux/kvm_para.h b/include/linux/kvm_para.h
index 47a070b..4efee4d 100644
--- a/include/linux/kvm_para.h
+++ b/include/linux/kvm_para.h
@@ -19,6 +19,8 @@
#define KVM_HC_MMU_OP 2
#define KVM_HC_FEATURES 3
#define KVM_HC_PPC_MAP_MAGIC_PAGE 4
+#define KVM_HC_WAIT_FOR_KICK 5
+#define KVM_HC_KICK_CPU 6
/*
* hypercalls use architecture specific
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index aefdda3..d09982d 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -224,6 +224,7 @@ int kvm_vcpu_init(struct kvm_vcpu *vcpu, struct kvm *kvm, unsigned id)
vcpu->kvm = kvm;
vcpu->vcpu_id = id;
vcpu->pid = NULL;
+ vcpu->kicked = 0;
init_waitqueue_head(&vcpu->wq);
kvm_async_pf_vcpu_init(vcpu);
^ permalink raw reply related
* [PATCH RFC V2 3/5] kvm hypervisor : Add two hypercalls to support pv-ticketlock
From: Raghavendra K T @ 2011-10-23 19:05 UTC (permalink / raw)
To: Greg Kroah-Hartman, H. Peter Anvin, Gleb Natapov, Virtualization,
Jeremy
Cc: Peter Zijlstra, Suzuki Poulose, Raghavendra K T,
Srivatsa Vaddagiri
In-Reply-To: <20111023190307.16364.35381.sendpatchset@oc5400248562.ibm.com>
Add two hypercalls to KVM hypervisor to support pv-ticketlocks.
KVM_HC_WAIT_FOR_KICK blocks the calling vcpu until another vcpu kicks it or it
is woken up because of an event like interrupt.
KVM_HC_KICK_CPU allows the calling vcpu to kick another vcpu.
The presence of these hypercalls is indicated to guest via
KVM_FEATURE_WAIT_FOR_KICK/KVM_CAP_WAIT_FOR_KICK.
Qemu needs a corresponding patch to pass up the presence of this feature to
guest via cpuid. Patch to qemu will be sent separately.
There is no Xen/KVM hypercall interface to await kick from.
Signed-off-by: Srivatsa Vaddagiri <vatsa@linux.vnet.ibm.com>
Signed-off-by: Suzuki Poulose <suzuki@in.ibm.com>
Signed-off-by: Raghavendra K T <raghavendra.kt@linux.vnet.ibm.com>
---
diff --git a/arch/x86/include/asm/kvm_para.h b/arch/x86/include/asm/kvm_para.h
index 734c376..2874c19 100644
--- a/arch/x86/include/asm/kvm_para.h
+++ b/arch/x86/include/asm/kvm_para.h
@@ -16,12 +16,14 @@
#define KVM_FEATURE_CLOCKSOURCE 0
#define KVM_FEATURE_NOP_IO_DELAY 1
#define KVM_FEATURE_MMU_OP 2
+
/* This indicates that the new set of kvmclock msrs
* are available. The use of 0x11 and 0x12 is deprecated
*/
#define KVM_FEATURE_CLOCKSOURCE2 3
#define KVM_FEATURE_ASYNC_PF 4
#define KVM_FEATURE_STEAL_TIME 5
+#define KVM_FEATURE_WAIT_FOR_KICK 6
/* The last 8 bits are used to indicate how to interpret the flags field
* in pvclock structure. If no bits are set, all flags are ignored.
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 84a28ea..b43fd18 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -2077,6 +2077,7 @@ int kvm_dev_ioctl_check_extension(long ext)
case KVM_CAP_XSAVE:
case KVM_CAP_ASYNC_PF:
case KVM_CAP_GET_TSC_KHZ:
+ case KVM_CAP_WAIT_FOR_KICK:
r = 1;
break;
case KVM_CAP_COALESCED_MMIO:
@@ -2548,7 +2549,8 @@ static void do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
(1 << KVM_FEATURE_NOP_IO_DELAY) |
(1 << KVM_FEATURE_CLOCKSOURCE2) |
(1 << KVM_FEATURE_ASYNC_PF) |
- (1 << KVM_FEATURE_CLOCKSOURCE_STABLE_BIT);
+ (1 << KVM_FEATURE_CLOCKSOURCE_STABLE_BIT) |
+ (1 << KVM_FEATURE_WAIT_FOR_KICK);
if (sched_info_on())
entry->eax |= (1 << KVM_FEATURE_STEAL_TIME);
@@ -5231,6 +5233,61 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu)
return 1;
}
+/*
+ * kvm_pv_wait_for_kick_op : Block until kicked by either a KVM_HC_KICK_CPU
+ * hypercall or a event like interrupt.
+ *
+ * @vcpu : vcpu which is blocking.
+ */
+static void kvm_pv_wait_for_kick_op(struct kvm_vcpu *vcpu)
+{
+ DEFINE_WAIT(wait);
+
+ /*
+ * Blocking on vcpu->wq allows us to wake up sooner if required to
+ * service pending events (like interrupts).
+ *
+ * Also set state to TASK_INTERRUPTIBLE before checking vcpu->kicked to
+ * avoid racing with kvm_pv_kick_cpu_op().
+ */
+ prepare_to_wait(&vcpu->wq, &wait, TASK_INTERRUPTIBLE);
+
+ /*
+ * Somebody has already tried kicking us. Acknowledge that
+ * and terminate the wait.
+ */
+ if (vcpu->kicked) {
+ vcpu->kicked = 0;
+ goto end_wait;
+ }
+
+ /* Let's wait for either KVM_HC_KICK_CPU or someother event
+ * to wake us up.
+ */
+
+ srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx);
+ schedule();
+ vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
+
+end_wait:
+ finish_wait(&vcpu->wq, &wait);
+}
+
+/*
+ * kvm_pv_kick_cpu_op: Kick a vcpu.
+ *
+ * @cpu - vcpu to be kicked.
+ */
+static void kvm_pv_kick_cpu_op(struct kvm *kvm, int cpu)
+{
+ struct kvm_vcpu *vcpu = kvm_get_vcpu(kvm, cpu);
+
+ if (vcpu) {
+ vcpu->kicked = 1;
+ wake_up_interruptible(&vcpu->wq);
+ }
+}
+
int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
{
unsigned long nr, a0, a1, a2, a3, ret;
@@ -5267,6 +5324,14 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
case KVM_HC_MMU_OP:
r = kvm_pv_mmu_op(vcpu, a0, hc_gpa(vcpu, a1, a2), &ret);
break;
+ case KVM_HC_WAIT_FOR_KICK:
+ kvm_pv_wait_for_kick_op(vcpu);
+ ret = 0;
+ break;
+ case KVM_HC_KICK_CPU:
+ kvm_pv_kick_cpu_op(vcpu->kvm, a0);
+ ret = 0;
+ break;
default:
ret = -KVM_ENOSYS;
break;
diff --git a/include/linux/kvm.h b/include/linux/kvm.h
index aace6b8..736acc0 100644
--- a/include/linux/kvm.h
+++ b/include/linux/kvm.h
@@ -553,6 +553,7 @@ struct kvm_ppc_pvinfo {
#define KVM_CAP_SPAPR_TCE 63
#define KVM_CAP_PPC_SMT 64
#define KVM_CAP_PPC_RMA 65
+#define KVM_CAP_WAIT_FOR_KICK 66
#define KVM_CAP_S390_GMAP 71
#ifdef KVM_CAP_IRQ_ROUTING
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index eabb21a..2946563 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -152,6 +152,11 @@ struct kvm_vcpu {
#endif
struct kvm_vcpu_arch arch;
+
+ /*
+ * blocked vcpu wakes up by checking this flag set by unlocker
+ */
+ int kicked;
};
static inline int kvm_vcpu_exiting_guest_mode(struct kvm_vcpu *vcpu)
diff --git a/include/linux/kvm_para.h b/include/linux/kvm_para.h
index 47a070b..4efee4d 100644
--- a/include/linux/kvm_para.h
+++ b/include/linux/kvm_para.h
@@ -19,6 +19,8 @@
#define KVM_HC_MMU_OP 2
#define KVM_HC_FEATURES 3
#define KVM_HC_PPC_MAP_MAGIC_PAGE 4
+#define KVM_HC_WAIT_FOR_KICK 5
+#define KVM_HC_KICK_CPU 6
/*
* hypercalls use architecture specific
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index aefdda3..d09982d 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -224,6 +224,7 @@ int kvm_vcpu_init(struct kvm_vcpu *vcpu, struct kvm *kvm, unsigned id)
vcpu->kvm = kvm;
vcpu->vcpu_id = id;
vcpu->pid = NULL;
+ vcpu->kicked = 0;
init_waitqueue_head(&vcpu->wq);
kvm_async_pf_vcpu_init(vcpu);
^ permalink raw reply related
* [PATCH RFC V2 1/5] debugfs: Add support to print u32 array in debugfs
From: Raghavendra K T @ 2011-10-23 19:04 UTC (permalink / raw)
To: Greg Kroah-Hartman, Virtualization, Gleb Natapov, H. Peter Anvin,
Jeremy Fitzhardinge, x86, KVM, Dave Jiang, Thomas Gleixner,
Stefano Stabellini, LKML, Sedat Dilek, Yinghai Lu,
Marcelo Tosatti, Ingo Molnar, Avi Kivity, Rik van Riel, Xen,
Konrad Rzeszutek Wilk
Cc: Suzuki Poulose, Srivatsa Vaddagiri, Peter Zijlstra,
Raghavendra K T
In-Reply-To: <20111023190307.16364.35381.sendpatchset@oc5400248562.ibm.com>
Add debugfs support to print u32-arrays in debugfs. Move the code from Xen to debugfs
to make the code common for other users as well.
Signed-off-by: Srivatsa Vaddagiri <vatsa@linux.vnet.ibm.com>
Signed-off-by: Suzuki Poulose <suzuki@in.ibm.com>
Signed-off-by: Raghavendra K T <raghavendra.kt@linux.vnet.ibm.com>
---
diff --git a/arch/x86/xen/debugfs.c b/arch/x86/xen/debugfs.c
index 7c0fedd..c8377fb 100644
--- a/arch/x86/xen/debugfs.c
+++ b/arch/x86/xen/debugfs.c
@@ -19,107 +19,3 @@ struct dentry * __init xen_init_debugfs(void)
return d_xen_debug;
}
-struct array_data
-{
- void *array;
- unsigned elements;
-};
-
-static int u32_array_open(struct inode *inode, struct file *file)
-{
- file->private_data = NULL;
- return nonseekable_open(inode, file);
-}
-
-static size_t format_array(char *buf, size_t bufsize, const char *fmt,
- u32 *array, unsigned array_size)
-{
- size_t ret = 0;
- unsigned i;
-
- for(i = 0; i < array_size; i++) {
- size_t len;
-
- len = snprintf(buf, bufsize, fmt, array[i]);
- len++; /* ' ' or '\n' */
- ret += len;
-
- if (buf) {
- buf += len;
- bufsize -= len;
- buf[-1] = (i == array_size-1) ? '\n' : ' ';
- }
- }
-
- ret++; /* \0 */
- if (buf)
- *buf = '\0';
-
- return ret;
-}
-
-static char *format_array_alloc(const char *fmt, u32 *array, unsigned array_size)
-{
- size_t len = format_array(NULL, 0, fmt, array, array_size);
- char *ret;
-
- ret = kmalloc(len, GFP_KERNEL);
- if (ret == NULL)
- return NULL;
-
- format_array(ret, len, fmt, array, array_size);
- return ret;
-}
-
-static ssize_t u32_array_read(struct file *file, char __user *buf, size_t len,
- loff_t *ppos)
-{
- struct inode *inode = file->f_path.dentry->d_inode;
- struct array_data *data = inode->i_private;
- size_t size;
-
- if (*ppos == 0) {
- if (file->private_data) {
- kfree(file->private_data);
- file->private_data = NULL;
- }
-
- file->private_data = format_array_alloc("%u", data->array, data->elements);
- }
-
- size = 0;
- if (file->private_data)
- size = strlen(file->private_data);
-
- return simple_read_from_buffer(buf, len, ppos, file->private_data, size);
-}
-
-static int xen_array_release(struct inode *inode, struct file *file)
-{
- kfree(file->private_data);
-
- return 0;
-}
-
-static const struct file_operations u32_array_fops = {
- .owner = THIS_MODULE,
- .open = u32_array_open,
- .release= xen_array_release,
- .read = u32_array_read,
- .llseek = no_llseek,
-};
-
-struct dentry *xen_debugfs_create_u32_array(const char *name, mode_t mode,
- struct dentry *parent,
- u32 *array, unsigned elements)
-{
- struct array_data *data = kmalloc(sizeof(*data), GFP_KERNEL);
-
- if (data == NULL)
- return NULL;
-
- data->array = array;
- data->elements = elements;
-
- return debugfs_create_file(name, mode, parent, data, &u32_array_fops);
-}
diff --git a/arch/x86/xen/debugfs.h b/arch/x86/xen/debugfs.h
index e281320..12ebf33 100644
--- a/arch/x86/xen/debugfs.h
+++ b/arch/x86/xen/debugfs.h
@@ -3,8 +3,4 @@
struct dentry * __init xen_init_debugfs(void);
-struct dentry *xen_debugfs_create_u32_array(const char *name, mode_t mode,
- struct dentry *parent,
- u32 *array, unsigned elements);
-
#endif /* _XEN_DEBUGFS_H */
diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c
index 90f7657..9aa12e3 100644
--- a/fs/debugfs/file.c
+++ b/fs/debugfs/file.c
@@ -18,6 +18,7 @@
#include <linux/pagemap.h>
#include <linux/namei.h>
#include <linux/debugfs.h>
+#include <linux/slab.h>
static ssize_t default_read_file(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
@@ -525,3 +526,110 @@ struct dentry *debugfs_create_blob(const char *name, mode_t mode,
return debugfs_create_file(name, mode, parent, blob, &fops_blob);
}
EXPORT_SYMBOL_GPL(debugfs_create_blob);
+
+struct array_data {
+ void *array;
+ unsigned elements;
+};
+
+static int u32_array_open(struct inode *inode, struct file *file)
+{
+ file->private_data = NULL;
+ return nonseekable_open(inode, file);
+}
+
+static size_t format_array(char *buf, size_t bufsize, const char *fmt,
+ u32 *array, unsigned array_size)
+{
+ size_t ret = 0;
+ unsigned i;
+
+ for (i = 0; i < array_size; i++) {
+ size_t len;
+
+ len = snprintf(buf, bufsize, fmt, array[i]);
+ len++; /* ' ' or '\n' */
+ ret += len;
+
+ if (buf) {
+ buf += len;
+ bufsize -= len;
+ buf[-1] = (i == array_size-1) ? '\n' : ' ';
+ }
+ }
+
+ ret++; /* \0 */
+ if (buf)
+ *buf = '\0';
+
+ return ret;
+}
+
+static char *format_array_alloc(const char *fmt, u32 *array,
+ unsigned array_size)
+{
+ size_t len = format_array(NULL, 0, fmt, array, array_size);
+ char *ret;
+
+ ret = kmalloc(len, GFP_KERNEL);
+ if (ret == NULL)
+ return NULL;
+
+ format_array(ret, len, fmt, array, array_size);
+ return ret;
+}
+
+static ssize_t u32_array_read(struct file *file, char __user *buf, size_t len,
+ loff_t *ppos)
+{
+ struct inode *inode = file->f_path.dentry->d_inode;
+ struct array_data *data = inode->i_private;
+ size_t size;
+
+ if (*ppos == 0) {
+ if (file->private_data) {
+ kfree(file->private_data);
+ file->private_data = NULL;
+ }
+
+ file->private_data = format_array_alloc("%u", data->array,
+ data->elements);
+ }
+
+ size = 0;
+ if (file->private_data)
+ size = strlen(file->private_data);
+
+ return simple_read_from_buffer(buf, len, ppos,
+ file->private_data, size);
+}
+
+static int xen_array_release(struct inode *inode, struct file *file)
+{
+ kfree(file->private_data);
+
+ return 0;
+}
+
+static const struct file_operations u32_array_fops = {
+ .owner = THIS_MODULE,
+ .open = u32_array_open,
+ .release = xen_array_release,
+ .read = u32_array_read,
+ .llseek = no_llseek,
+};
+
+struct dentry *xen_debugfs_create_u32_array(const char *name, mode_t mode,
+ struct dentry *parent,
+ u32 *array, unsigned elements)
+{
+ struct array_data *data = kmalloc(sizeof(*data), GFP_KERNEL);
+
+ if (data == NULL)
+ return NULL;
+
+ data->array = array;
+ data->elements = elements;
+
+ return debugfs_create_file(name, mode, parent, data, &u32_array_fops);
+}
diff --git a/include/linux/debugfs.h b/include/linux/debugfs.h
index e7d9b20..8c08636 100644
--- a/include/linux/debugfs.h
+++ b/include/linux/debugfs.h
@@ -74,6 +74,10 @@ struct dentry *debugfs_create_blob(const char *name, mode_t mode,
struct dentry *parent,
struct debugfs_blob_wrapper *blob);
+struct dentry *xen_debugfs_create_u32_array(const char *name, mode_t mode,
+ struct dentry *parent,
+ u32 *array, unsigned elements);
+
bool debugfs_initialized(void);
#else
@@ -193,6 +197,13 @@ static inline bool debugfs_initialized(void)
return false;
}
+struct dentry *xen_debugfs_create_u32_array(const char *name, mode_t mode,
+ struct dentry *parent,
+ u32 *array, unsigned elements)
+{
+ return ERR_PTR(-ENODEV);
+}
+
#endif
#endif
^ permalink raw reply related
* [PATCH RFC V2 1/5] debugfs: Add support to print u32 array in debugfs
From: Raghavendra K T @ 2011-10-23 19:04 UTC (permalink / raw)
To: Greg Kroah-Hartman, Virtualization, Gleb Natapov, H. Peter Anvin,
Jeremy
Cc: Suzuki Poulose, Srivatsa Vaddagiri, Peter Zijlstra,
Raghavendra K T
In-Reply-To: <20111023190307.16364.35381.sendpatchset@oc5400248562.ibm.com>
Add debugfs support to print u32-arrays in debugfs. Move the code from Xen to debugfs
to make the code common for other users as well.
Signed-off-by: Srivatsa Vaddagiri <vatsa@linux.vnet.ibm.com>
Signed-off-by: Suzuki Poulose <suzuki@in.ibm.com>
Signed-off-by: Raghavendra K T <raghavendra.kt@linux.vnet.ibm.com>
---
diff --git a/arch/x86/xen/debugfs.c b/arch/x86/xen/debugfs.c
index 7c0fedd..c8377fb 100644
--- a/arch/x86/xen/debugfs.c
+++ b/arch/x86/xen/debugfs.c
@@ -19,107 +19,3 @@ struct dentry * __init xen_init_debugfs(void)
return d_xen_debug;
}
-struct array_data
-{
- void *array;
- unsigned elements;
-};
-
-static int u32_array_open(struct inode *inode, struct file *file)
-{
- file->private_data = NULL;
- return nonseekable_open(inode, file);
-}
-
-static size_t format_array(char *buf, size_t bufsize, const char *fmt,
- u32 *array, unsigned array_size)
-{
- size_t ret = 0;
- unsigned i;
-
- for(i = 0; i < array_size; i++) {
- size_t len;
-
- len = snprintf(buf, bufsize, fmt, array[i]);
- len++; /* ' ' or '\n' */
- ret += len;
-
- if (buf) {
- buf += len;
- bufsize -= len;
- buf[-1] = (i == array_size-1) ? '\n' : ' ';
- }
- }
-
- ret++; /* \0 */
- if (buf)
- *buf = '\0';
-
- return ret;
-}
-
-static char *format_array_alloc(const char *fmt, u32 *array, unsigned array_size)
-{
- size_t len = format_array(NULL, 0, fmt, array, array_size);
- char *ret;
-
- ret = kmalloc(len, GFP_KERNEL);
- if (ret == NULL)
- return NULL;
-
- format_array(ret, len, fmt, array, array_size);
- return ret;
-}
-
-static ssize_t u32_array_read(struct file *file, char __user *buf, size_t len,
- loff_t *ppos)
-{
- struct inode *inode = file->f_path.dentry->d_inode;
- struct array_data *data = inode->i_private;
- size_t size;
-
- if (*ppos == 0) {
- if (file->private_data) {
- kfree(file->private_data);
- file->private_data = NULL;
- }
-
- file->private_data = format_array_alloc("%u", data->array, data->elements);
- }
-
- size = 0;
- if (file->private_data)
- size = strlen(file->private_data);
-
- return simple_read_from_buffer(buf, len, ppos, file->private_data, size);
-}
-
-static int xen_array_release(struct inode *inode, struct file *file)
-{
- kfree(file->private_data);
-
- return 0;
-}
-
-static const struct file_operations u32_array_fops = {
- .owner = THIS_MODULE,
- .open = u32_array_open,
- .release= xen_array_release,
- .read = u32_array_read,
- .llseek = no_llseek,
-};
-
-struct dentry *xen_debugfs_create_u32_array(const char *name, mode_t mode,
- struct dentry *parent,
- u32 *array, unsigned elements)
-{
- struct array_data *data = kmalloc(sizeof(*data), GFP_KERNEL);
-
- if (data == NULL)
- return NULL;
-
- data->array = array;
- data->elements = elements;
-
- return debugfs_create_file(name, mode, parent, data, &u32_array_fops);
-}
diff --git a/arch/x86/xen/debugfs.h b/arch/x86/xen/debugfs.h
index e281320..12ebf33 100644
--- a/arch/x86/xen/debugfs.h
+++ b/arch/x86/xen/debugfs.h
@@ -3,8 +3,4 @@
struct dentry * __init xen_init_debugfs(void);
-struct dentry *xen_debugfs_create_u32_array(const char *name, mode_t mode,
- struct dentry *parent,
- u32 *array, unsigned elements);
-
#endif /* _XEN_DEBUGFS_H */
diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c
index 90f7657..9aa12e3 100644
--- a/fs/debugfs/file.c
+++ b/fs/debugfs/file.c
@@ -18,6 +18,7 @@
#include <linux/pagemap.h>
#include <linux/namei.h>
#include <linux/debugfs.h>
+#include <linux/slab.h>
static ssize_t default_read_file(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
@@ -525,3 +526,110 @@ struct dentry *debugfs_create_blob(const char *name, mode_t mode,
return debugfs_create_file(name, mode, parent, blob, &fops_blob);
}
EXPORT_SYMBOL_GPL(debugfs_create_blob);
+
+struct array_data {
+ void *array;
+ unsigned elements;
+};
+
+static int u32_array_open(struct inode *inode, struct file *file)
+{
+ file->private_data = NULL;
+ return nonseekable_open(inode, file);
+}
+
+static size_t format_array(char *buf, size_t bufsize, const char *fmt,
+ u32 *array, unsigned array_size)
+{
+ size_t ret = 0;
+ unsigned i;
+
+ for (i = 0; i < array_size; i++) {
+ size_t len;
+
+ len = snprintf(buf, bufsize, fmt, array[i]);
+ len++; /* ' ' or '\n' */
+ ret += len;
+
+ if (buf) {
+ buf += len;
+ bufsize -= len;
+ buf[-1] = (i == array_size-1) ? '\n' : ' ';
+ }
+ }
+
+ ret++; /* \0 */
+ if (buf)
+ *buf = '\0';
+
+ return ret;
+}
+
+static char *format_array_alloc(const char *fmt, u32 *array,
+ unsigned array_size)
+{
+ size_t len = format_array(NULL, 0, fmt, array, array_size);
+ char *ret;
+
+ ret = kmalloc(len, GFP_KERNEL);
+ if (ret == NULL)
+ return NULL;
+
+ format_array(ret, len, fmt, array, array_size);
+ return ret;
+}
+
+static ssize_t u32_array_read(struct file *file, char __user *buf, size_t len,
+ loff_t *ppos)
+{
+ struct inode *inode = file->f_path.dentry->d_inode;
+ struct array_data *data = inode->i_private;
+ size_t size;
+
+ if (*ppos == 0) {
+ if (file->private_data) {
+ kfree(file->private_data);
+ file->private_data = NULL;
+ }
+
+ file->private_data = format_array_alloc("%u", data->array,
+ data->elements);
+ }
+
+ size = 0;
+ if (file->private_data)
+ size = strlen(file->private_data);
+
+ return simple_read_from_buffer(buf, len, ppos,
+ file->private_data, size);
+}
+
+static int xen_array_release(struct inode *inode, struct file *file)
+{
+ kfree(file->private_data);
+
+ return 0;
+}
+
+static const struct file_operations u32_array_fops = {
+ .owner = THIS_MODULE,
+ .open = u32_array_open,
+ .release = xen_array_release,
+ .read = u32_array_read,
+ .llseek = no_llseek,
+};
+
+struct dentry *xen_debugfs_create_u32_array(const char *name, mode_t mode,
+ struct dentry *parent,
+ u32 *array, unsigned elements)
+{
+ struct array_data *data = kmalloc(sizeof(*data), GFP_KERNEL);
+
+ if (data == NULL)
+ return NULL;
+
+ data->array = array;
+ data->elements = elements;
+
+ return debugfs_create_file(name, mode, parent, data, &u32_array_fops);
+}
diff --git a/include/linux/debugfs.h b/include/linux/debugfs.h
index e7d9b20..8c08636 100644
--- a/include/linux/debugfs.h
+++ b/include/linux/debugfs.h
@@ -74,6 +74,10 @@ struct dentry *debugfs_create_blob(const char *name, mode_t mode,
struct dentry *parent,
struct debugfs_blob_wrapper *blob);
+struct dentry *xen_debugfs_create_u32_array(const char *name, mode_t mode,
+ struct dentry *parent,
+ u32 *array, unsigned elements);
+
bool debugfs_initialized(void);
#else
@@ -193,6 +197,13 @@ static inline bool debugfs_initialized(void)
return false;
}
+struct dentry *xen_debugfs_create_u32_array(const char *name, mode_t mode,
+ struct dentry *parent,
+ u32 *array, unsigned elements)
+{
+ return ERR_PTR(-ENODEV);
+}
+
#endif
#endif
^ permalink raw reply related
* [PATCH RFC V2 2/5] debugfs: Renaming of xen functions and change unsigned to u32
From: Raghavendra K T @ 2011-10-23 19:04 UTC (permalink / raw)
To: Greg Kroah-Hartman, KVM, Konrad Rzeszutek Wilk, Sedat Dilek,
Virtualization, Jeremy Fitzhardinge, x86, H. Peter Anvin,
Dave Jiang, Thomas Gleixner, Stefano Stabellini, Gleb Natapov,
Yinghai Lu, Marcelo Tosatti, Ingo Molnar, Avi Kivity,
Rik van Riel, Xen, LKML
Cc: Suzuki Poulose, Srivatsa Vaddagiri, Peter Zijlstra,
Raghavendra K T
In-Reply-To: <20111023190307.16364.35381.sendpatchset@oc5400248562.ibm.com>
Renaming of xen functions and change unsigned to u32.
Signed-off-by: Srivatsa Vaddagiri <vatsa@linux.vnet.ibm.com>
Signed-off-by: Suzuki Poulose <suzuki@in.ibm.com>
Signed-off-by: Raghavendra K T <raghavendra.kt@linux.vnet.ibm.com>
---
diff --git a/arch/x86/xen/spinlock.c b/arch/x86/xen/spinlock.c
index fc506e6..14a8961 100644
--- a/arch/x86/xen/spinlock.c
+++ b/arch/x86/xen/spinlock.c
@@ -286,7 +286,7 @@ static int __init xen_spinlock_debugfs(void)
debugfs_create_u64("time_blocked", 0444, d_spin_debug,
&spinlock_stats.time_blocked);
- xen_debugfs_create_u32_array("histo_blocked", 0444, d_spin_debug,
+ debugfs_create_u32_array("histo_blocked", 0444, d_spin_debug,
spinlock_stats.histo_spin_blocked, HISTO_BUCKETS + 1);
return 0;
diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c
index 9aa12e3..68af40d 100644
--- a/fs/debugfs/file.c
+++ b/fs/debugfs/file.c
@@ -529,7 +529,7 @@ EXPORT_SYMBOL_GPL(debugfs_create_blob);
struct array_data {
void *array;
- unsigned elements;
+ u32 elements;
};
static int u32_array_open(struct inode *inode, struct file *file)
@@ -539,10 +539,10 @@ static int u32_array_open(struct inode *inode, struct file *file)
}
static size_t format_array(char *buf, size_t bufsize, const char *fmt,
- u32 *array, unsigned array_size)
+ u32 *array, u32 array_size)
{
size_t ret = 0;
- unsigned i;
+ u32 i;
for (i = 0; i < array_size; i++) {
size_t len;
@@ -566,7 +566,7 @@ static size_t format_array(char *buf, size_t bufsize, const char *fmt,
}
static char *format_array_alloc(const char *fmt, u32 *array,
- unsigned array_size)
+ u32 array_size)
{
size_t len = format_array(NULL, 0, fmt, array, array_size);
char *ret;
@@ -604,7 +604,7 @@ static ssize_t u32_array_read(struct file *file, char __user *buf, size_t len,
file->private_data, size);
}
-static int xen_array_release(struct inode *inode, struct file *file)
+static int u32_array_release(struct inode *inode, struct file *file)
{
kfree(file->private_data);
@@ -614,14 +614,14 @@ static int xen_array_release(struct inode *inode, struct file *file)
static const struct file_operations u32_array_fops = {
.owner = THIS_MODULE,
.open = u32_array_open,
- .release = xen_array_release,
+ .release = u32_array_release,
.read = u32_array_read,
.llseek = no_llseek,
};
-struct dentry *xen_debugfs_create_u32_array(const char *name, mode_t mode,
+struct dentry *debugfs_create_u32_array(const char *name, mode_t mode,
struct dentry *parent,
- u32 *array, unsigned elements)
+ u32 *array, u32 elements)
{
struct array_data *data = kmalloc(sizeof(*data), GFP_KERNEL);
diff --git a/include/linux/debugfs.h b/include/linux/debugfs.h
index 8c08636..253e2fb 100644
--- a/include/linux/debugfs.h
+++ b/include/linux/debugfs.h
@@ -74,9 +74,9 @@ struct dentry *debugfs_create_blob(const char *name, mode_t mode,
struct dentry *parent,
struct debugfs_blob_wrapper *blob);
-struct dentry *xen_debugfs_create_u32_array(const char *name, mode_t mode,
- struct dentry *parent,
- u32 *array, unsigned elements);
+struct dentry *debugfs_create_u32_array(const char *name, mode_t mode,
+ struct dentry *parent,
+ u32 *array, u32 elements);
bool debugfs_initialized(void);
@@ -197,9 +197,9 @@ static inline bool debugfs_initialized(void)
return false;
}
-struct dentry *xen_debugfs_create_u32_array(const char *name, mode_t mode,
- struct dentry *parent,
- u32 *array, unsigned elements)
+struct dentry *debugfs_create_u32_array(const char *name, mode_t mode,
+ struct dentry *parent,
+ u32 *array, u32 elements)
{
return ERR_PTR(-ENODEV);
}
^ permalink raw reply related
* [PATCH RFC V2 2/5] debugfs: Renaming of xen functions and change unsigned to u32
From: Raghavendra K T @ 2011-10-23 19:04 UTC (permalink / raw)
To: Greg Kroah-Hartman, KVM, Konrad Rzeszutek Wilk, Sedat Dilek,
Virtualization
Cc: Peter Zijlstra, Suzuki Poulose, Raghavendra K T,
Srivatsa Vaddagiri
In-Reply-To: <20111023190307.16364.35381.sendpatchset@oc5400248562.ibm.com>
Renaming of xen functions and change unsigned to u32.
Signed-off-by: Srivatsa Vaddagiri <vatsa@linux.vnet.ibm.com>
Signed-off-by: Suzuki Poulose <suzuki@in.ibm.com>
Signed-off-by: Raghavendra K T <raghavendra.kt@linux.vnet.ibm.com>
---
diff --git a/arch/x86/xen/spinlock.c b/arch/x86/xen/spinlock.c
index fc506e6..14a8961 100644
--- a/arch/x86/xen/spinlock.c
+++ b/arch/x86/xen/spinlock.c
@@ -286,7 +286,7 @@ static int __init xen_spinlock_debugfs(void)
debugfs_create_u64("time_blocked", 0444, d_spin_debug,
&spinlock_stats.time_blocked);
- xen_debugfs_create_u32_array("histo_blocked", 0444, d_spin_debug,
+ debugfs_create_u32_array("histo_blocked", 0444, d_spin_debug,
spinlock_stats.histo_spin_blocked, HISTO_BUCKETS + 1);
return 0;
diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c
index 9aa12e3..68af40d 100644
--- a/fs/debugfs/file.c
+++ b/fs/debugfs/file.c
@@ -529,7 +529,7 @@ EXPORT_SYMBOL_GPL(debugfs_create_blob);
struct array_data {
void *array;
- unsigned elements;
+ u32 elements;
};
static int u32_array_open(struct inode *inode, struct file *file)
@@ -539,10 +539,10 @@ static int u32_array_open(struct inode *inode, struct file *file)
}
static size_t format_array(char *buf, size_t bufsize, const char *fmt,
- u32 *array, unsigned array_size)
+ u32 *array, u32 array_size)
{
size_t ret = 0;
- unsigned i;
+ u32 i;
for (i = 0; i < array_size; i++) {
size_t len;
@@ -566,7 +566,7 @@ static size_t format_array(char *buf, size_t bufsize, const char *fmt,
}
static char *format_array_alloc(const char *fmt, u32 *array,
- unsigned array_size)
+ u32 array_size)
{
size_t len = format_array(NULL, 0, fmt, array, array_size);
char *ret;
@@ -604,7 +604,7 @@ static ssize_t u32_array_read(struct file *file, char __user *buf, size_t len,
file->private_data, size);
}
-static int xen_array_release(struct inode *inode, struct file *file)
+static int u32_array_release(struct inode *inode, struct file *file)
{
kfree(file->private_data);
@@ -614,14 +614,14 @@ static int xen_array_release(struct inode *inode, struct file *file)
static const struct file_operations u32_array_fops = {
.owner = THIS_MODULE,
.open = u32_array_open,
- .release = xen_array_release,
+ .release = u32_array_release,
.read = u32_array_read,
.llseek = no_llseek,
};
-struct dentry *xen_debugfs_create_u32_array(const char *name, mode_t mode,
+struct dentry *debugfs_create_u32_array(const char *name, mode_t mode,
struct dentry *parent,
- u32 *array, unsigned elements)
+ u32 *array, u32 elements)
{
struct array_data *data = kmalloc(sizeof(*data), GFP_KERNEL);
diff --git a/include/linux/debugfs.h b/include/linux/debugfs.h
index 8c08636..253e2fb 100644
--- a/include/linux/debugfs.h
+++ b/include/linux/debugfs.h
@@ -74,9 +74,9 @@ struct dentry *debugfs_create_blob(const char *name, mode_t mode,
struct dentry *parent,
struct debugfs_blob_wrapper *blob);
-struct dentry *xen_debugfs_create_u32_array(const char *name, mode_t mode,
- struct dentry *parent,
- u32 *array, unsigned elements);
+struct dentry *debugfs_create_u32_array(const char *name, mode_t mode,
+ struct dentry *parent,
+ u32 *array, u32 elements);
bool debugfs_initialized(void);
@@ -197,9 +197,9 @@ static inline bool debugfs_initialized(void)
return false;
}
-struct dentry *xen_debugfs_create_u32_array(const char *name, mode_t mode,
- struct dentry *parent,
- u32 *array, unsigned elements)
+struct dentry *debugfs_create_u32_array(const char *name, mode_t mode,
+ struct dentry *parent,
+ u32 *array, u32 elements)
{
return ERR_PTR(-ENODEV);
}
^ permalink raw reply related
* [PATCH RFC V2 2/5] debugfs: Renaming of xen functions and change unsigned to u32
From: Raghavendra K T @ 2011-10-23 19:04 UTC (permalink / raw)
To: Greg Kroah-Hartman, KVM, Konrad Rzeszutek Wilk, Sedat Dilek,
Virtualization
Cc: Suzuki Poulose, Srivatsa Vaddagiri, Peter Zijlstra,
Raghavendra K T
In-Reply-To: <20111023190307.16364.35381.sendpatchset@oc5400248562.ibm.com>
Renaming of xen functions and change unsigned to u32.
Signed-off-by: Srivatsa Vaddagiri <vatsa@linux.vnet.ibm.com>
Signed-off-by: Suzuki Poulose <suzuki@in.ibm.com>
Signed-off-by: Raghavendra K T <raghavendra.kt@linux.vnet.ibm.com>
---
diff --git a/arch/x86/xen/spinlock.c b/arch/x86/xen/spinlock.c
index fc506e6..14a8961 100644
--- a/arch/x86/xen/spinlock.c
+++ b/arch/x86/xen/spinlock.c
@@ -286,7 +286,7 @@ static int __init xen_spinlock_debugfs(void)
debugfs_create_u64("time_blocked", 0444, d_spin_debug,
&spinlock_stats.time_blocked);
- xen_debugfs_create_u32_array("histo_blocked", 0444, d_spin_debug,
+ debugfs_create_u32_array("histo_blocked", 0444, d_spin_debug,
spinlock_stats.histo_spin_blocked, HISTO_BUCKETS + 1);
return 0;
diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c
index 9aa12e3..68af40d 100644
--- a/fs/debugfs/file.c
+++ b/fs/debugfs/file.c
@@ -529,7 +529,7 @@ EXPORT_SYMBOL_GPL(debugfs_create_blob);
struct array_data {
void *array;
- unsigned elements;
+ u32 elements;
};
static int u32_array_open(struct inode *inode, struct file *file)
@@ -539,10 +539,10 @@ static int u32_array_open(struct inode *inode, struct file *file)
}
static size_t format_array(char *buf, size_t bufsize, const char *fmt,
- u32 *array, unsigned array_size)
+ u32 *array, u32 array_size)
{
size_t ret = 0;
- unsigned i;
+ u32 i;
for (i = 0; i < array_size; i++) {
size_t len;
@@ -566,7 +566,7 @@ static size_t format_array(char *buf, size_t bufsize, const char *fmt,
}
static char *format_array_alloc(const char *fmt, u32 *array,
- unsigned array_size)
+ u32 array_size)
{
size_t len = format_array(NULL, 0, fmt, array, array_size);
char *ret;
@@ -604,7 +604,7 @@ static ssize_t u32_array_read(struct file *file, char __user *buf, size_t len,
file->private_data, size);
}
-static int xen_array_release(struct inode *inode, struct file *file)
+static int u32_array_release(struct inode *inode, struct file *file)
{
kfree(file->private_data);
@@ -614,14 +614,14 @@ static int xen_array_release(struct inode *inode, struct file *file)
static const struct file_operations u32_array_fops = {
.owner = THIS_MODULE,
.open = u32_array_open,
- .release = xen_array_release,
+ .release = u32_array_release,
.read = u32_array_read,
.llseek = no_llseek,
};
-struct dentry *xen_debugfs_create_u32_array(const char *name, mode_t mode,
+struct dentry *debugfs_create_u32_array(const char *name, mode_t mode,
struct dentry *parent,
- u32 *array, unsigned elements)
+ u32 *array, u32 elements)
{
struct array_data *data = kmalloc(sizeof(*data), GFP_KERNEL);
diff --git a/include/linux/debugfs.h b/include/linux/debugfs.h
index 8c08636..253e2fb 100644
--- a/include/linux/debugfs.h
+++ b/include/linux/debugfs.h
@@ -74,9 +74,9 @@ struct dentry *debugfs_create_blob(const char *name, mode_t mode,
struct dentry *parent,
struct debugfs_blob_wrapper *blob);
-struct dentry *xen_debugfs_create_u32_array(const char *name, mode_t mode,
- struct dentry *parent,
- u32 *array, unsigned elements);
+struct dentry *debugfs_create_u32_array(const char *name, mode_t mode,
+ struct dentry *parent,
+ u32 *array, u32 elements);
bool debugfs_initialized(void);
@@ -197,9 +197,9 @@ static inline bool debugfs_initialized(void)
return false;
}
-struct dentry *xen_debugfs_create_u32_array(const char *name, mode_t mode,
- struct dentry *parent,
- u32 *array, unsigned elements)
+struct dentry *debugfs_create_u32_array(const char *name, mode_t mode,
+ struct dentry *parent,
+ u32 *array, u32 elements)
{
return ERR_PTR(-ENODEV);
}
^ permalink raw reply related
* [PATCH] TTY: tty flip buffer change reserve memory strategy.
From: Ilya Zykov @ 2011-10-23 19:04 UTC (permalink / raw)
To: Greg Kroah-Hartman; +Cc: linux-kernel, Alan Cox
Currently, free flip buffer (tty->buf->free) reserve memory for further
used,
only if driver send to ldisc less 257 bytes in one time.
If driver send more, flip buffer reserve(kmalloc()) and then
free(kfree()) every chunk more 256 bytes every time,
even we have in free buffer enough space, because we can't
pass through chunk boundary in free buffer. Also we can't limit reserve
memory size. In worse case we will have in free buffer:
(256 * 256 byte chunk) = (256 * 552 ) = 141312 byte unused memory.
This patch allow reserve more than 256 bytes in one time. And have
self-regulation chunk size ability(very useful for pty).
Also we can limit reserve memory size, but then,
we will be use kmalloc()-kree() calls on intensive stream from driver.
diff -uprN last-orig/drivers/tty/tty_buffer.c
tty_buffer.patched/drivers/tty/tty_buffer.c
--- last-orig/drivers/tty/tty_buffer.c 2011-10-18 13:57:32.000000000
+0400
+++ tty_buffer.patched/drivers/tty/tty_buffer.c 2011-10-22
09:45:09.000000000 +0400
@@ -58,7 +58,7 @@ static struct tty_buffer *tty_buffer_all
{
struct tty_buffer *p;
- if (tty->buf.memory_used + size > 65536)
+ if (tty->buf.memory_used + size > TTY_BUFFER_MAX)
return NULL;
p = kmalloc(sizeof(struct tty_buffer) + 2 * size, GFP_ATOMIC);
if (p == NULL)
@@ -91,10 +91,21 @@ static void tty_buffer_free(struct tty_s
tty->buf.memory_used -= b->size;
WARN_ON(tty->buf.memory_used < 0);
- if (b->size >= 512)
- kfree(b);
- else {
- b->next = tty->buf.free;
+ tty->buf.memory_reserve += b->size;
+ b->next = NULL;
+ if (tty->buf.free != NULL) {
+ struct tty_buffer *p = tty->buf.free;
+ while (p->next != NULL)
+ p = p->next;
+ p->next = b;
+ while (tty->buf.memory_reserve > TTY_BUFFER_RESERVE ) {
+ p = tty->buf.free;
+ tty->buf.free = p->next;
+ tty->buf.memory_reserve -= p->size;
+ WARN_ON(tty->buf.memory_reserve < 0);
+ kfree(p);
+ }
+ } else {
tty->buf.free = b;
}
}
@@ -175,6 +186,8 @@ static struct tty_buffer *tty_buffer_fin
t->commit = 0;
t->read = 0;
tty->buf.memory_used += t->size;
+ tty->buf.memory_reserve -= t->size;
+ WARN_ON(tty->buf.memory_reserve < 0);
return t;
}
tbh = &((*tbh)->next);
@@ -517,6 +530,7 @@ void tty_buffer_init(struct tty_struct *
tty->buf.tail = NULL;
tty->buf.free = NULL;
tty->buf.memory_used = 0;
+ tty->buf.memory_reserve = 0;
INIT_WORK(&tty->buf.work, flush_to_ldisc);
}
diff -uprN last-orig/include/linux/tty.h
tty_buffer.patched/include/linux/tty.h
--- last-orig/include/linux/tty.h 2011-05-19 08:06:34.000000000 +0400
+++ tty_buffer.patched/include/linux/tty.h 2011-10-22
13:48:46.000000000 +0400
@@ -79,7 +79,8 @@ struct tty_buffer {
*/
#define TTY_BUFFER_PAGE (((PAGE_SIZE - sizeof(struct tty_buffer)) /
2) & ~0xFF)
-
+#define TTY_BUFFER_MAX 65536
+#define TTY_BUFFER_RESERVE TTY_BUFFER_MAX
struct tty_bufhead {
struct work_struct work;
@@ -87,8 +88,8 @@ struct tty_bufhead {
struct tty_buffer *head; /* Queue head */
struct tty_buffer *tail; /* Active buffer */
struct tty_buffer *free; /* Free queue head */
- int memory_used; /* Buffer space used excluding
- free queue */
+ int memory_used; /* Buffer space used excluding free queue */
+ int memory_reserve; /* Free queue space */
};
/*
* When a break, frame error, or parity error happens, these codes are
^ permalink raw reply
* [PATCH RFC V2 1/5] debugfs: Add support to print u32 array in debugfs
From: Raghavendra K T @ 2011-10-23 19:04 UTC (permalink / raw)
To: Greg Kroah-Hartman, Virtualization, Gleb Natapov, H. Peter Anvin,
Jeremy
Cc: Peter Zijlstra, Suzuki Poulose, Raghavendra K T,
Srivatsa Vaddagiri
In-Reply-To: <20111023190307.16364.35381.sendpatchset@oc5400248562.ibm.com>
Add debugfs support to print u32-arrays in debugfs. Move the code from Xen to debugfs
to make the code common for other users as well.
Signed-off-by: Srivatsa Vaddagiri <vatsa@linux.vnet.ibm.com>
Signed-off-by: Suzuki Poulose <suzuki@in.ibm.com>
Signed-off-by: Raghavendra K T <raghavendra.kt@linux.vnet.ibm.com>
---
diff --git a/arch/x86/xen/debugfs.c b/arch/x86/xen/debugfs.c
index 7c0fedd..c8377fb 100644
--- a/arch/x86/xen/debugfs.c
+++ b/arch/x86/xen/debugfs.c
@@ -19,107 +19,3 @@ struct dentry * __init xen_init_debugfs(void)
return d_xen_debug;
}
-struct array_data
-{
- void *array;
- unsigned elements;
-};
-
-static int u32_array_open(struct inode *inode, struct file *file)
-{
- file->private_data = NULL;
- return nonseekable_open(inode, file);
-}
-
-static size_t format_array(char *buf, size_t bufsize, const char *fmt,
- u32 *array, unsigned array_size)
-{
- size_t ret = 0;
- unsigned i;
-
- for(i = 0; i < array_size; i++) {
- size_t len;
-
- len = snprintf(buf, bufsize, fmt, array[i]);
- len++; /* ' ' or '\n' */
- ret += len;
-
- if (buf) {
- buf += len;
- bufsize -= len;
- buf[-1] = (i == array_size-1) ? '\n' : ' ';
- }
- }
-
- ret++; /* \0 */
- if (buf)
- *buf = '\0';
-
- return ret;
-}
-
-static char *format_array_alloc(const char *fmt, u32 *array, unsigned array_size)
-{
- size_t len = format_array(NULL, 0, fmt, array, array_size);
- char *ret;
-
- ret = kmalloc(len, GFP_KERNEL);
- if (ret == NULL)
- return NULL;
-
- format_array(ret, len, fmt, array, array_size);
- return ret;
-}
-
-static ssize_t u32_array_read(struct file *file, char __user *buf, size_t len,
- loff_t *ppos)
-{
- struct inode *inode = file->f_path.dentry->d_inode;
- struct array_data *data = inode->i_private;
- size_t size;
-
- if (*ppos == 0) {
- if (file->private_data) {
- kfree(file->private_data);
- file->private_data = NULL;
- }
-
- file->private_data = format_array_alloc("%u", data->array, data->elements);
- }
-
- size = 0;
- if (file->private_data)
- size = strlen(file->private_data);
-
- return simple_read_from_buffer(buf, len, ppos, file->private_data, size);
-}
-
-static int xen_array_release(struct inode *inode, struct file *file)
-{
- kfree(file->private_data);
-
- return 0;
-}
-
-static const struct file_operations u32_array_fops = {
- .owner = THIS_MODULE,
- .open = u32_array_open,
- .release= xen_array_release,
- .read = u32_array_read,
- .llseek = no_llseek,
-};
-
-struct dentry *xen_debugfs_create_u32_array(const char *name, mode_t mode,
- struct dentry *parent,
- u32 *array, unsigned elements)
-{
- struct array_data *data = kmalloc(sizeof(*data), GFP_KERNEL);
-
- if (data == NULL)
- return NULL;
-
- data->array = array;
- data->elements = elements;
-
- return debugfs_create_file(name, mode, parent, data, &u32_array_fops);
-}
diff --git a/arch/x86/xen/debugfs.h b/arch/x86/xen/debugfs.h
index e281320..12ebf33 100644
--- a/arch/x86/xen/debugfs.h
+++ b/arch/x86/xen/debugfs.h
@@ -3,8 +3,4 @@
struct dentry * __init xen_init_debugfs(void);
-struct dentry *xen_debugfs_create_u32_array(const char *name, mode_t mode,
- struct dentry *parent,
- u32 *array, unsigned elements);
-
#endif /* _XEN_DEBUGFS_H */
diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c
index 90f7657..9aa12e3 100644
--- a/fs/debugfs/file.c
+++ b/fs/debugfs/file.c
@@ -18,6 +18,7 @@
#include <linux/pagemap.h>
#include <linux/namei.h>
#include <linux/debugfs.h>
+#include <linux/slab.h>
static ssize_t default_read_file(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
@@ -525,3 +526,110 @@ struct dentry *debugfs_create_blob(const char *name, mode_t mode,
return debugfs_create_file(name, mode, parent, blob, &fops_blob);
}
EXPORT_SYMBOL_GPL(debugfs_create_blob);
+
+struct array_data {
+ void *array;
+ unsigned elements;
+};
+
+static int u32_array_open(struct inode *inode, struct file *file)
+{
+ file->private_data = NULL;
+ return nonseekable_open(inode, file);
+}
+
+static size_t format_array(char *buf, size_t bufsize, const char *fmt,
+ u32 *array, unsigned array_size)
+{
+ size_t ret = 0;
+ unsigned i;
+
+ for (i = 0; i < array_size; i++) {
+ size_t len;
+
+ len = snprintf(buf, bufsize, fmt, array[i]);
+ len++; /* ' ' or '\n' */
+ ret += len;
+
+ if (buf) {
+ buf += len;
+ bufsize -= len;
+ buf[-1] = (i == array_size-1) ? '\n' : ' ';
+ }
+ }
+
+ ret++; /* \0 */
+ if (buf)
+ *buf = '\0';
+
+ return ret;
+}
+
+static char *format_array_alloc(const char *fmt, u32 *array,
+ unsigned array_size)
+{
+ size_t len = format_array(NULL, 0, fmt, array, array_size);
+ char *ret;
+
+ ret = kmalloc(len, GFP_KERNEL);
+ if (ret == NULL)
+ return NULL;
+
+ format_array(ret, len, fmt, array, array_size);
+ return ret;
+}
+
+static ssize_t u32_array_read(struct file *file, char __user *buf, size_t len,
+ loff_t *ppos)
+{
+ struct inode *inode = file->f_path.dentry->d_inode;
+ struct array_data *data = inode->i_private;
+ size_t size;
+
+ if (*ppos == 0) {
+ if (file->private_data) {
+ kfree(file->private_data);
+ file->private_data = NULL;
+ }
+
+ file->private_data = format_array_alloc("%u", data->array,
+ data->elements);
+ }
+
+ size = 0;
+ if (file->private_data)
+ size = strlen(file->private_data);
+
+ return simple_read_from_buffer(buf, len, ppos,
+ file->private_data, size);
+}
+
+static int xen_array_release(struct inode *inode, struct file *file)
+{
+ kfree(file->private_data);
+
+ return 0;
+}
+
+static const struct file_operations u32_array_fops = {
+ .owner = THIS_MODULE,
+ .open = u32_array_open,
+ .release = xen_array_release,
+ .read = u32_array_read,
+ .llseek = no_llseek,
+};
+
+struct dentry *xen_debugfs_create_u32_array(const char *name, mode_t mode,
+ struct dentry *parent,
+ u32 *array, unsigned elements)
+{
+ struct array_data *data = kmalloc(sizeof(*data), GFP_KERNEL);
+
+ if (data == NULL)
+ return NULL;
+
+ data->array = array;
+ data->elements = elements;
+
+ return debugfs_create_file(name, mode, parent, data, &u32_array_fops);
+}
diff --git a/include/linux/debugfs.h b/include/linux/debugfs.h
index e7d9b20..8c08636 100644
--- a/include/linux/debugfs.h
+++ b/include/linux/debugfs.h
@@ -74,6 +74,10 @@ struct dentry *debugfs_create_blob(const char *name, mode_t mode,
struct dentry *parent,
struct debugfs_blob_wrapper *blob);
+struct dentry *xen_debugfs_create_u32_array(const char *name, mode_t mode,
+ struct dentry *parent,
+ u32 *array, unsigned elements);
+
bool debugfs_initialized(void);
#else
@@ -193,6 +197,13 @@ static inline bool debugfs_initialized(void)
return false;
}
+struct dentry *xen_debugfs_create_u32_array(const char *name, mode_t mode,
+ struct dentry *parent,
+ u32 *array, unsigned elements)
+{
+ return ERR_PTR(-ENODEV);
+}
+
#endif
#endif
^ permalink raw reply related
* [PATCH RFC V2 0/5] kvm : Paravirt-spinlock support for KVM guests
From: Raghavendra K T @ 2011-10-23 19:03 UTC (permalink / raw)
To: Greg Kroah-Hartman, Sedat Dilek, Stefano Stabellini, KVM,
Jeremy Fitzhardinge, x86, H. Peter Anvin, Dave Jiang,
Thomas Gleixner, Marcelo Tosatti, Yinghai Lu, Gleb Natapov,
Ingo Molnar, Avi Kivity, Xen, Virtualization, Rik van Riel,
Konrad Rzeszutek Wilk, LKML
Cc: Suzuki Poulose, Srivatsa Vaddagiri, Peter Zijlstra,
Raghavendra K T
The 5-patch series to follow this email extends KVM-hypervisor and Linux guest
running on KVM-hypervisor to support pv-ticket spinlocks, based heavily on Xen's implementation.
Two hypercalls are being introduced in KVM hypervisor, one that allows a
vcpu (spinning on a lock) to block and another that allows a vcpu to kick
another out of blocking state.
This is discussed in : (posted by Srivatsa V).
https://lkml.org/lkml/2010/7/26/24
https://lkml.org/lkml/2011/1/19/212
The BASE patch is tip rc9 + Jeremy's following patches.
compare exchange (https://lkml.org/lkml/2011/8/29/321),
xadd (https://lkml.org/lkml/2011/10/4/328)
x86/ticketlocklock (https://lkml.org/lkml/2011/10/12/496).
Changes since last posting:
- rebased patchesto -rc9
- synchronization related changes based on Jeremy's changes (Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>) pointed by
Stephan Diestelhorst <stephan.diestelhorst@amd.com>
- enabling 32 bit guests
- splitted patches into two more chunks
Results:
set up :
Kernel for host/guest : 3.1-rc9 + Jeremys ticketlock cleanup, xadd, pv spinlock patches as BASE
3 guests with 8VCPU, 4GB RAM, 1 used for kernbench (kernbench -f -H -M -o 20) other for cpuhog (shell script while
true with an instruction)
scenario A: unpinned
scenario B: each vcpu pinned to corresponding cpu
1x: no hogs
2x: 8hogs in one guest
3x: 8hogs each in two guest
Result for Non PLE machine :
Machine : IBM xSeries with Intel(R) Xeon(R) x5570 2.93GHz CPU with 8 core , 64GB RAM
BASE BASE+patch %improvement
mean (sd) mean (sd)
Scenario A:
case 1x: 157.495 (15.2924) 148.355 (7.35479) 5.80336
case 2x: 761.955 (581.384) 247.306 (64.4707) 67.5432
case 3x: 2804.36 (2613.57) 261.522 (85.0856) 90.6744
Scenario B
case 1x: 1241.86 (812.155) 313.805 (140.99) 74.731
case 2x: 1277.32 (771.316) 308.325 (124.808) 75.8616
case 3x: 1239.45 (860.012) 307.535 (124.243) 75.1878
Result for PLE machine:
Machine : IBM xSeries with Intel(R) Xeon(R) X7560 2.27GHz CPU with 32/64 core, with 8
online cores and 4*64GB RAM
BASE BASE+patch %improvement
mean (sd) mean (sd)
Scenario A:
case 1x: 72.7133 (43.7109) 70.0734 (37.7866) 3.63056
case 2x: 124.138 (79.9515) 119.28 (81.3597) 3.91339
case 3x: 174.561 (132.209) 159.283 (116.232) 8.75224
Scenario B
case 1x: 166.101 (119.313) 160.056 (117.446) 3.63935
case 2x: 167.421 (120.767) 158.133 (115.022) 5.54769
case 3x: 169.317 (122.088) 159.353 (116.737) 5.88482
Srivatsa Vaddagiri, Suzuki Poulose, Raghavendra K T (5):
Add debugfs support to print u32-arrays in debugfs
Renaming of xen functions and change unsigned to u32
Add two hypercalls to KVM hypervisor to support pv-ticketlocks
Added configuration support to enable debug information for KVM Guests
pv-ticketlocks support for linux guests running on KVM hypervisor
arch/x86/Kconfig | 9 ++
arch/x86/include/asm/kvm_para.h | 12 ++-
arch/x86/kernel/head32.c | 3 +
arch/x86/kernel/head64.c | 3 +
arch/x86/kernel/kvm.c | 247 +++++++++++++++++++++++++++++++++++++++
arch/x86/kvm/x86.c | 67 +++++++++++-
arch/x86/xen/debugfs.c | 104 ----------------
arch/x86/xen/debugfs.h | 4 -
arch/x86/xen/spinlock.c | 2 +-
fs/debugfs/file.c | 108 +++++++++++++++++
include/linux/debugfs.h | 11 ++
include/linux/kvm.h | 1 +
include/linux/kvm_host.h | 5 +
include/linux/kvm_para.h | 2 +
virt/kvm/kvm_main.c | 1 +
15 files changed, 468 insertions(+), 111 deletions(-)
---
^ permalink raw reply
* [PATCH RFC V2 0/5] kvm : Paravirt-spinlock support for KVM guests
From: Raghavendra K T @ 2011-10-23 19:03 UTC (permalink / raw)
To: Greg Kroah-Hartman, Sedat Dilek, Stefano Stabellini, KVM,
Jeremy Fitzhardinge <jerem>
Cc: Peter Zijlstra, Suzuki Poulose, Raghavendra K T,
Srivatsa Vaddagiri
The 5-patch series to follow this email extends KVM-hypervisor and Linux guest
running on KVM-hypervisor to support pv-ticket spinlocks, based heavily on Xen's implementation.
Two hypercalls are being introduced in KVM hypervisor, one that allows a
vcpu (spinning on a lock) to block and another that allows a vcpu to kick
another out of blocking state.
This is discussed in : (posted by Srivatsa V).
https://lkml.org/lkml/2010/7/26/24
https://lkml.org/lkml/2011/1/19/212
The BASE patch is tip rc9 + Jeremy's following patches.
compare exchange (https://lkml.org/lkml/2011/8/29/321),
xadd (https://lkml.org/lkml/2011/10/4/328)
x86/ticketlocklock (https://lkml.org/lkml/2011/10/12/496).
Changes since last posting:
- rebased patchesto -rc9
- synchronization related changes based on Jeremy's changes (Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>) pointed by
Stephan Diestelhorst <stephan.diestelhorst@amd.com>
- enabling 32 bit guests
- splitted patches into two more chunks
Results:
set up :
Kernel for host/guest : 3.1-rc9 + Jeremys ticketlock cleanup, xadd, pv spinlock patches as BASE
3 guests with 8VCPU, 4GB RAM, 1 used for kernbench (kernbench -f -H -M -o 20) other for cpuhog (shell script while
true with an instruction)
scenario A: unpinned
scenario B: each vcpu pinned to corresponding cpu
1x: no hogs
2x: 8hogs in one guest
3x: 8hogs each in two guest
Result for Non PLE machine :
Machine : IBM xSeries with Intel(R) Xeon(R) x5570 2.93GHz CPU with 8 core , 64GB RAM
BASE BASE+patch %improvement
mean (sd) mean (sd)
Scenario A:
case 1x: 157.495 (15.2924) 148.355 (7.35479) 5.80336
case 2x: 761.955 (581.384) 247.306 (64.4707) 67.5432
case 3x: 2804.36 (2613.57) 261.522 (85.0856) 90.6744
Scenario B
case 1x: 1241.86 (812.155) 313.805 (140.99) 74.731
case 2x: 1277.32 (771.316) 308.325 (124.808) 75.8616
case 3x: 1239.45 (860.012) 307.535 (124.243) 75.1878
Result for PLE machine:
Machine : IBM xSeries with Intel(R) Xeon(R) X7560 2.27GHz CPU with 32/64 core, with 8
online cores and 4*64GB RAM
BASE BASE+patch %improvement
mean (sd) mean (sd)
Scenario A:
case 1x: 72.7133 (43.7109) 70.0734 (37.7866) 3.63056
case 2x: 124.138 (79.9515) 119.28 (81.3597) 3.91339
case 3x: 174.561 (132.209) 159.283 (116.232) 8.75224
Scenario B
case 1x: 166.101 (119.313) 160.056 (117.446) 3.63935
case 2x: 167.421 (120.767) 158.133 (115.022) 5.54769
case 3x: 169.317 (122.088) 159.353 (116.737) 5.88482
Srivatsa Vaddagiri, Suzuki Poulose, Raghavendra K T (5):
Add debugfs support to print u32-arrays in debugfs
Renaming of xen functions and change unsigned to u32
Add two hypercalls to KVM hypervisor to support pv-ticketlocks
Added configuration support to enable debug information for KVM Guests
pv-ticketlocks support for linux guests running on KVM hypervisor
arch/x86/Kconfig | 9 ++
arch/x86/include/asm/kvm_para.h | 12 ++-
arch/x86/kernel/head32.c | 3 +
arch/x86/kernel/head64.c | 3 +
arch/x86/kernel/kvm.c | 247 +++++++++++++++++++++++++++++++++++++++
arch/x86/kvm/x86.c | 67 +++++++++++-
arch/x86/xen/debugfs.c | 104 ----------------
arch/x86/xen/debugfs.h | 4 -
arch/x86/xen/spinlock.c | 2 +-
fs/debugfs/file.c | 108 +++++++++++++++++
include/linux/debugfs.h | 11 ++
include/linux/kvm.h | 1 +
include/linux/kvm_host.h | 5 +
include/linux/kvm_para.h | 2 +
virt/kvm/kvm_main.c | 1 +
15 files changed, 468 insertions(+), 111 deletions(-)
---
^ permalink raw reply
* [PATCH RFC V2 0/5] kvm : Paravirt-spinlock support for KVM guests
From: Raghavendra K T @ 2011-10-23 19:03 UTC (permalink / raw)
To: Greg Kroah-Hartman, Sedat Dilek, Stefano Stabellini, KVM,
Jeremy Fitzhardinge <jerem
Cc: Suzuki Poulose, Srivatsa Vaddagiri, Peter Zijlstra,
Raghavendra K T
The 5-patch series to follow this email extends KVM-hypervisor and Linux guest
running on KVM-hypervisor to support pv-ticket spinlocks, based heavily on Xen's implementation.
Two hypercalls are being introduced in KVM hypervisor, one that allows a
vcpu (spinning on a lock) to block and another that allows a vcpu to kick
another out of blocking state.
This is discussed in : (posted by Srivatsa V).
https://lkml.org/lkml/2010/7/26/24
https://lkml.org/lkml/2011/1/19/212
The BASE patch is tip rc9 + Jeremy's following patches.
compare exchange (https://lkml.org/lkml/2011/8/29/321),
xadd (https://lkml.org/lkml/2011/10/4/328)
x86/ticketlocklock (https://lkml.org/lkml/2011/10/12/496).
Changes since last posting:
- rebased patchesto -rc9
- synchronization related changes based on Jeremy's changes (Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>) pointed by
Stephan Diestelhorst <stephan.diestelhorst@amd.com>
- enabling 32 bit guests
- splitted patches into two more chunks
Results:
set up :
Kernel for host/guest : 3.1-rc9 + Jeremys ticketlock cleanup, xadd, pv spinlock patches as BASE
3 guests with 8VCPU, 4GB RAM, 1 used for kernbench (kernbench -f -H -M -o 20) other for cpuhog (shell script while
true with an instruction)
scenario A: unpinned
scenario B: each vcpu pinned to corresponding cpu
1x: no hogs
2x: 8hogs in one guest
3x: 8hogs each in two guest
Result for Non PLE machine :
Machine : IBM xSeries with Intel(R) Xeon(R) x5570 2.93GHz CPU with 8 core , 64GB RAM
BASE BASE+patch %improvement
mean (sd) mean (sd)
Scenario A:
case 1x: 157.495 (15.2924) 148.355 (7.35479) 5.80336
case 2x: 761.955 (581.384) 247.306 (64.4707) 67.5432
case 3x: 2804.36 (2613.57) 261.522 (85.0856) 90.6744
Scenario B
case 1x: 1241.86 (812.155) 313.805 (140.99) 74.731
case 2x: 1277.32 (771.316) 308.325 (124.808) 75.8616
case 3x: 1239.45 (860.012) 307.535 (124.243) 75.1878
Result for PLE machine:
Machine : IBM xSeries with Intel(R) Xeon(R) X7560 2.27GHz CPU with 32/64 core, with 8
online cores and 4*64GB RAM
BASE BASE+patch %improvement
mean (sd) mean (sd)
Scenario A:
case 1x: 72.7133 (43.7109) 70.0734 (37.7866) 3.63056
case 2x: 124.138 (79.9515) 119.28 (81.3597) 3.91339
case 3x: 174.561 (132.209) 159.283 (116.232) 8.75224
Scenario B
case 1x: 166.101 (119.313) 160.056 (117.446) 3.63935
case 2x: 167.421 (120.767) 158.133 (115.022) 5.54769
case 3x: 169.317 (122.088) 159.353 (116.737) 5.88482
Srivatsa Vaddagiri, Suzuki Poulose, Raghavendra K T (5):
Add debugfs support to print u32-arrays in debugfs
Renaming of xen functions and change unsigned to u32
Add two hypercalls to KVM hypervisor to support pv-ticketlocks
Added configuration support to enable debug information for KVM Guests
pv-ticketlocks support for linux guests running on KVM hypervisor
arch/x86/Kconfig | 9 ++
arch/x86/include/asm/kvm_para.h | 12 ++-
arch/x86/kernel/head32.c | 3 +
arch/x86/kernel/head64.c | 3 +
arch/x86/kernel/kvm.c | 247 +++++++++++++++++++++++++++++++++++++++
arch/x86/kvm/x86.c | 67 +++++++++++-
arch/x86/xen/debugfs.c | 104 ----------------
arch/x86/xen/debugfs.h | 4 -
arch/x86/xen/spinlock.c | 2 +-
fs/debugfs/file.c | 108 +++++++++++++++++
include/linux/debugfs.h | 11 ++
include/linux/kvm.h | 1 +
include/linux/kvm_host.h | 5 +
include/linux/kvm_para.h | 2 +
virt/kvm/kvm_main.c | 1 +
15 files changed, 468 insertions(+), 111 deletions(-)
---
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.