diff options
author | Ingo Molnar <mingo@kernel.org> | 2012-03-30 02:47:19 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2012-03-30 02:50:06 -0400 |
commit | 186e54cbe1145f4d11e32fe10e7e20a11f1b27dd (patch) | |
tree | 9b6cf3667a3ea90e0cec0ea7119688ba76c55a71 /tools | |
parent | 99dd5497e5be4fe4194cad181d45fd6569a930db (diff) | |
parent | 4bde23f8751f388867766b0a62ed1ef8b7e01561 (diff) |
Merge branch 'linus' into x86/urgent
Merge reason: Needed for include file dependencies.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'tools')
30 files changed, 1805 insertions, 136 deletions
diff --git a/tools/perf/util/include/linux/bitops.h b/tools/perf/util/include/linux/bitops.h index 62cdee78db7b..f1584833bd22 100644 --- a/tools/perf/util/include/linux/bitops.h +++ b/tools/perf/util/include/linux/bitops.h | |||
@@ -15,7 +15,7 @@ | |||
15 | (bit) = find_next_bit((addr), (size), (bit) + 1)) | 15 | (bit) = find_next_bit((addr), (size), (bit) + 1)) |
16 | 16 | ||
17 | /* same as for_each_set_bit() but use bit as value to start with */ | 17 | /* same as for_each_set_bit() but use bit as value to start with */ |
18 | #define for_each_set_bit_cont(bit, addr, size) \ | 18 | #define for_each_set_bit_from(bit, addr, size) \ |
19 | for ((bit) = find_next_bit((addr), (size), (bit)); \ | 19 | for ((bit) = find_next_bit((addr), (size), (bit)); \ |
20 | (bit) < (size); \ | 20 | (bit) < (size); \ |
21 | (bit) = find_next_bit((addr), (size), (bit) + 1)) | 21 | (bit) = find_next_bit((addr), (size), (bit) + 1)) |
diff --git a/tools/power/cpupower/Makefile b/tools/power/cpupower/Makefile index e8a03aceceb1..a93e06cfcc2a 100644 --- a/tools/power/cpupower/Makefile +++ b/tools/power/cpupower/Makefile | |||
@@ -19,6 +19,16 @@ | |||
19 | # along with this program; if not, write to the Free Software | 19 | # along with this program; if not, write to the Free Software |
20 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 20 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
21 | # | 21 | # |
22 | OUTPUT=./ | ||
23 | ifeq ("$(origin O)", "command line") | ||
24 | OUTPUT := $(O)/ | ||
25 | endif | ||
26 | |||
27 | ifneq ($(OUTPUT),) | ||
28 | # check that the output directory actually exists | ||
29 | OUTDIR := $(shell cd $(OUTPUT) && /bin/pwd) | ||
30 | $(if $(OUTDIR),, $(error output directory "$(OUTPUT)" does not exist)) | ||
31 | endif | ||
22 | 32 | ||
23 | # --- CONFIGURATION BEGIN --- | 33 | # --- CONFIGURATION BEGIN --- |
24 | 34 | ||
@@ -87,6 +97,7 @@ AR = $(CROSS)ar | |||
87 | STRIP = $(CROSS)strip | 97 | STRIP = $(CROSS)strip |
88 | RANLIB = $(CROSS)ranlib | 98 | RANLIB = $(CROSS)ranlib |
89 | HOSTCC = gcc | 99 | HOSTCC = gcc |
100 | MKDIR = mkdir | ||
90 | 101 | ||
91 | 102 | ||
92 | # Now we set up the build system | 103 | # Now we set up the build system |
@@ -95,7 +106,7 @@ HOSTCC = gcc | |||
95 | # set up PWD so that older versions of make will work with our build. | 106 | # set up PWD so that older versions of make will work with our build. |
96 | PWD = $(shell pwd) | 107 | PWD = $(shell pwd) |
97 | 108 | ||
98 | GMO_FILES = ${shell for HLANG in ${LANGUAGES}; do echo po/$$HLANG.gmo; done;} | 109 | GMO_FILES = ${shell for HLANG in ${LANGUAGES}; do echo $(OUTPUT)po/$$HLANG.gmo; done;} |
99 | 110 | ||
100 | export CROSS CC AR STRIP RANLIB CFLAGS LDFLAGS LIB_OBJS | 111 | export CROSS CC AR STRIP RANLIB CFLAGS LDFLAGS LIB_OBJS |
101 | 112 | ||
@@ -122,15 +133,18 @@ UTIL_OBJS = utils/helpers/amd.o utils/helpers/topology.o utils/helpers/msr.o \ | |||
122 | utils/cpupower.o utils/cpufreq-info.o utils/cpufreq-set.o \ | 133 | utils/cpupower.o utils/cpufreq-info.o utils/cpufreq-set.o \ |
123 | utils/cpupower-set.o utils/cpupower-info.o utils/cpuidle-info.o | 134 | utils/cpupower-set.o utils/cpupower-info.o utils/cpuidle-info.o |
124 | 135 | ||
136 | UTIL_SRC := $(UTIL_OBJS:.o=.c) | ||
137 | |||
138 | UTIL_OBJS := $(addprefix $(OUTPUT),$(UTIL_OBJS)) | ||
139 | |||
125 | UTIL_HEADERS = utils/helpers/helpers.h utils/idle_monitor/cpupower-monitor.h \ | 140 | UTIL_HEADERS = utils/helpers/helpers.h utils/idle_monitor/cpupower-monitor.h \ |
126 | utils/helpers/bitmask.h \ | 141 | utils/helpers/bitmask.h \ |
127 | utils/idle_monitor/idle_monitors.h utils/idle_monitor/idle_monitors.def | 142 | utils/idle_monitor/idle_monitors.h utils/idle_monitor/idle_monitors.def |
128 | 143 | ||
129 | UTIL_SRC := $(UTIL_OBJS:.o=.c) | ||
130 | |||
131 | LIB_HEADERS = lib/cpufreq.h lib/sysfs.h | 144 | LIB_HEADERS = lib/cpufreq.h lib/sysfs.h |
132 | LIB_SRC = lib/cpufreq.c lib/sysfs.c | 145 | LIB_SRC = lib/cpufreq.c lib/sysfs.c |
133 | LIB_OBJS = lib/cpufreq.o lib/sysfs.o | 146 | LIB_OBJS = lib/cpufreq.o lib/sysfs.o |
147 | LIB_OBJS := $(addprefix $(OUTPUT),$(LIB_OBJS)) | ||
134 | 148 | ||
135 | CFLAGS += -pipe | 149 | CFLAGS += -pipe |
136 | 150 | ||
@@ -168,83 +182,90 @@ endif | |||
168 | 182 | ||
169 | # the actual make rules | 183 | # the actual make rules |
170 | 184 | ||
171 | all: libcpupower cpupower $(COMPILE_NLS) $(COMPILE_BENCH) | 185 | all: libcpupower $(OUTPUT)cpupower $(COMPILE_NLS) $(COMPILE_BENCH) |
172 | 186 | ||
173 | lib/%.o: $(LIB_SRC) $(LIB_HEADERS) | 187 | $(OUTPUT)lib/%.o: $(LIB_SRC) $(LIB_HEADERS) |
174 | $(ECHO) " CC " $@ | 188 | $(ECHO) " CC " $@ |
175 | $(QUIET) $(CC) $(CFLAGS) -fPIC -o $@ -c lib/$*.c | 189 | $(QUIET) $(CC) $(CFLAGS) -fPIC -o $@ -c lib/$*.c |
176 | 190 | ||
177 | libcpupower.so.$(LIB_MAJ): $(LIB_OBJS) | 191 | $(OUTPUT)libcpupower.so.$(LIB_MAJ): $(LIB_OBJS) |
178 | $(ECHO) " LD " $@ | 192 | $(ECHO) " LD " $@ |
179 | $(QUIET) $(CC) -shared $(CFLAGS) $(LDFLAGS) -o $@ \ | 193 | $(QUIET) $(CC) -shared $(CFLAGS) $(LDFLAGS) -o $@ \ |
180 | -Wl,-soname,libcpupower.so.$(LIB_MIN) $(LIB_OBJS) | 194 | -Wl,-soname,libcpupower.so.$(LIB_MIN) $(LIB_OBJS) |
181 | @ln -sf $@ libcpupower.so | 195 | @ln -sf $(@F) $(OUTPUT)libcpupower.so |
182 | @ln -sf $@ libcpupower.so.$(LIB_MIN) | 196 | @ln -sf $(@F) $(OUTPUT)libcpupower.so.$(LIB_MIN) |
183 | 197 | ||
184 | libcpupower: libcpupower.so.$(LIB_MAJ) | 198 | libcpupower: $(OUTPUT)libcpupower.so.$(LIB_MAJ) |
185 | 199 | ||
186 | # Let all .o files depend on its .c file and all headers | 200 | # Let all .o files depend on its .c file and all headers |
187 | # Might be worth to put this into utils/Makefile at some point of time | 201 | # Might be worth to put this into utils/Makefile at some point of time |
188 | $(UTIL_OBJS): $(UTIL_HEADERS) | 202 | $(UTIL_OBJS): $(UTIL_HEADERS) |
189 | 203 | ||
190 | .c.o: | 204 | $(OUTPUT)%.o: %.c |
191 | $(ECHO) " CC " $@ | 205 | $(ECHO) " CC " $@ |
192 | $(QUIET) $(CC) $(CFLAGS) -I./lib -I ./utils -o $@ -c $*.c | 206 | $(QUIET) $(CC) $(CFLAGS) -I./lib -I ./utils -o $@ -c $*.c |
193 | 207 | ||
194 | cpupower: $(UTIL_OBJS) libcpupower.so.$(LIB_MAJ) | 208 | $(OUTPUT)cpupower: $(UTIL_OBJS) $(OUTPUT)libcpupower.so.$(LIB_MAJ) |
195 | $(ECHO) " CC " $@ | 209 | $(ECHO) " CC " $@ |
196 | $(QUIET) $(CC) $(CFLAGS) $(LDFLAGS) -lcpupower -lrt -lpci -L. -o $@ $(UTIL_OBJS) | 210 | $(QUIET) $(CC) $(CFLAGS) $(LDFLAGS) $(UTIL_OBJS) -lcpupower -lrt -lpci -L$(OUTPUT) -o $@ |
197 | $(QUIET) $(STRIPCMD) $@ | 211 | $(QUIET) $(STRIPCMD) $@ |
198 | 212 | ||
199 | po/$(PACKAGE).pot: $(UTIL_SRC) | 213 | $(OUTPUT)po/$(PACKAGE).pot: $(UTIL_SRC) |
200 | $(ECHO) " GETTEXT " $@ | 214 | $(ECHO) " GETTEXT " $@ |
201 | $(QUIET) xgettext --default-domain=$(PACKAGE) --add-comments \ | 215 | $(QUIET) xgettext --default-domain=$(PACKAGE) --add-comments \ |
202 | --keyword=_ --keyword=N_ $(UTIL_SRC) && \ | 216 | --keyword=_ --keyword=N_ $(UTIL_SRC) -p $(@D) -o $(@F) |
203 | test -f $(PACKAGE).po && \ | ||
204 | mv -f $(PACKAGE).po po/$(PACKAGE).pot | ||
205 | 217 | ||
206 | po/%.gmo: po/%.po | 218 | $(OUTPUT)po/%.gmo: po/%.po |
207 | $(ECHO) " MSGFMT " $@ | 219 | $(ECHO) " MSGFMT " $@ |
208 | $(QUIET) msgfmt -o $@ po/$*.po | 220 | $(QUIET) msgfmt -o $@ po/$*.po |
209 | 221 | ||
210 | create-gmo: ${GMO_FILES} | 222 | create-gmo: ${GMO_FILES} |
211 | 223 | ||
212 | update-po: po/$(PACKAGE).pot | 224 | update-po: $(OUTPUT)po/$(PACKAGE).pot |
213 | $(ECHO) " MSGMRG " $@ | 225 | $(ECHO) " MSGMRG " $@ |
214 | $(QUIET) @for HLANG in $(LANGUAGES); do \ | 226 | $(QUIET) @for HLANG in $(LANGUAGES); do \ |
215 | echo -n "Updating $$HLANG "; \ | 227 | echo -n "Updating $$HLANG "; \ |
216 | if msgmerge po/$$HLANG.po po/$(PACKAGE).pot -o \ | 228 | if msgmerge po/$$HLANG.po $< -o \ |
217 | po/$$HLANG.new.po; then \ | 229 | $(OUTPUT)po/$$HLANG.new.po; then \ |
218 | mv -f po/$$HLANG.new.po po/$$HLANG.po; \ | 230 | mv -f $(OUTPUT)po/$$HLANG.new.po $(OUTPUT)po/$$HLANG.po; \ |
219 | else \ | 231 | else \ |
220 | echo "msgmerge for $$HLANG failed!"; \ | 232 | echo "msgmerge for $$HLANG failed!"; \ |
221 | rm -f po/$$HLANG.new.po; \ | 233 | rm -f $(OUTPUT)po/$$HLANG.new.po; \ |
222 | fi; \ | 234 | fi; \ |
223 | done; | 235 | done; |
224 | 236 | ||
225 | compile-bench: libcpupower.so.$(LIB_MAJ) | 237 | compile-bench: $(OUTPUT)libcpupower.so.$(LIB_MAJ) |
226 | @V=$(V) confdir=$(confdir) $(MAKE) -C bench | 238 | @V=$(V) confdir=$(confdir) $(MAKE) -C bench O=$(OUTPUT) |
239 | |||
240 | # we compile into subdirectories. if the target directory is not the | ||
241 | # source directory, they might not exists. So we depend the various | ||
242 | # files onto their directories. | ||
243 | DIRECTORY_DEPS = $(LIB_OBJS) $(UTIL_OBJS) $(GMO_FILES) | ||
244 | $(DIRECTORY_DEPS): | $(sort $(dir $(DIRECTORY_DEPS))) | ||
245 | |||
246 | # In the second step, we make a rule to actually create these directories | ||
247 | $(sort $(dir $(DIRECTORY_DEPS))): | ||
248 | $(ECHO) " MKDIR " $@ | ||
249 | $(QUIET) $(MKDIR) -p $@ 2>/dev/null | ||
227 | 250 | ||
228 | clean: | 251 | clean: |
229 | -find . \( -not -type d \) -and \( -name '*~' -o -name '*.[oas]' \) -type f -print \ | 252 | -find $(OUTPUT) \( -not -type d \) -and \( -name '*~' -o -name '*.[oas]' \) -type f -print \ |
230 | | xargs rm -f | 253 | | xargs rm -f |
231 | -rm -f $(UTIL_BINS) | 254 | -rm -f $(OUTPUT)cpupower |
232 | -rm -f $(IDLE_OBJS) | 255 | -rm -f $(OUTPUT)libcpupower.so* |
233 | -rm -f cpupower | 256 | -rm -rf $(OUTPUT)po/*.{gmo,pot} |
234 | -rm -f libcpupower.so* | 257 | $(MAKE) -C bench O=$(OUTPUT) clean |
235 | -rm -rf po/*.gmo po/*.pot | ||
236 | $(MAKE) -C bench clean | ||
237 | 258 | ||
238 | 259 | ||
239 | install-lib: | 260 | install-lib: |
240 | $(INSTALL) -d $(DESTDIR)${libdir} | 261 | $(INSTALL) -d $(DESTDIR)${libdir} |
241 | $(CP) libcpupower.so* $(DESTDIR)${libdir}/ | 262 | $(CP) $(OUTPUT)libcpupower.so* $(DESTDIR)${libdir}/ |
242 | $(INSTALL) -d $(DESTDIR)${includedir} | 263 | $(INSTALL) -d $(DESTDIR)${includedir} |
243 | $(INSTALL_DATA) lib/cpufreq.h $(DESTDIR)${includedir}/cpufreq.h | 264 | $(INSTALL_DATA) lib/cpufreq.h $(DESTDIR)${includedir}/cpufreq.h |
244 | 265 | ||
245 | install-tools: | 266 | install-tools: |
246 | $(INSTALL) -d $(DESTDIR)${bindir} | 267 | $(INSTALL) -d $(DESTDIR)${bindir} |
247 | $(INSTALL_PROGRAM) cpupower $(DESTDIR)${bindir} | 268 | $(INSTALL_PROGRAM) $(OUTPUT)cpupower $(DESTDIR)${bindir} |
248 | 269 | ||
249 | install-man: | 270 | install-man: |
250 | $(INSTALL_DATA) -D man/cpupower.1 $(DESTDIR)${mandir}/man1/cpupower.1 | 271 | $(INSTALL_DATA) -D man/cpupower.1 $(DESTDIR)${mandir}/man1/cpupower.1 |
@@ -257,13 +278,13 @@ install-man: | |||
257 | install-gmo: | 278 | install-gmo: |
258 | $(INSTALL) -d $(DESTDIR)${localedir} | 279 | $(INSTALL) -d $(DESTDIR)${localedir} |
259 | for HLANG in $(LANGUAGES); do \ | 280 | for HLANG in $(LANGUAGES); do \ |
260 | echo '$(INSTALL_DATA) -D po/$$HLANG.gmo $(DESTDIR)${localedir}/$$HLANG/LC_MESSAGES/cpupower.mo'; \ | 281 | echo '$(INSTALL_DATA) -D $(OUTPUT)po/$$HLANG.gmo $(DESTDIR)${localedir}/$$HLANG/LC_MESSAGES/cpupower.mo'; \ |
261 | $(INSTALL_DATA) -D po/$$HLANG.gmo $(DESTDIR)${localedir}/$$HLANG/LC_MESSAGES/cpupower.mo; \ | 282 | $(INSTALL_DATA) -D $(OUTPUT)po/$$HLANG.gmo $(DESTDIR)${localedir}/$$HLANG/LC_MESSAGES/cpupower.mo; \ |
262 | done; | 283 | done; |
263 | 284 | ||
264 | install-bench: | 285 | install-bench: |
265 | @#DESTDIR must be set from outside to survive | 286 | @#DESTDIR must be set from outside to survive |
266 | @sbindir=$(sbindir) bindir=$(bindir) docdir=$(docdir) confdir=$(confdir) $(MAKE) -C bench install | 287 | @sbindir=$(sbindir) bindir=$(bindir) docdir=$(docdir) confdir=$(confdir) $(MAKE) -C bench O=$(OUTPUT) install |
267 | 288 | ||
268 | install: all install-lib install-tools install-man $(INSTALL_NLS) $(INSTALL_BENCH) | 289 | install: all install-lib install-tools install-man $(INSTALL_NLS) $(INSTALL_BENCH) |
269 | 290 | ||
diff --git a/tools/power/cpupower/bench/Makefile b/tools/power/cpupower/bench/Makefile index 2b67606fc3e3..7ec7021a29cd 100644 --- a/tools/power/cpupower/bench/Makefile +++ b/tools/power/cpupower/bench/Makefile | |||
@@ -1,29 +1,36 @@ | |||
1 | LIBS = -L../ -lm -lcpupower | 1 | OUTPUT := ./ |
2 | ifeq ("$(origin O)", "command line") | ||
3 | ifneq ($(O),) | ||
4 | OUTPUT := $(O)/ | ||
5 | endif | ||
6 | endif | ||
2 | 7 | ||
3 | OBJS = main.o parse.o system.o benchmark.o | 8 | LIBS = -L../ -L$(OUTPUT) -lm -lcpupower |
9 | |||
10 | OBJS = $(OUTPUT)main.o $(OUTPUT)parse.o $(OUTPUT)system.o $(OUTPUT)benchmark.o | ||
4 | CFLAGS += -D_GNU_SOURCE -I../lib -DDEFAULT_CONFIG_FILE=\"$(confdir)/cpufreq-bench.conf\" | 11 | CFLAGS += -D_GNU_SOURCE -I../lib -DDEFAULT_CONFIG_FILE=\"$(confdir)/cpufreq-bench.conf\" |
5 | 12 | ||
6 | %.o : %.c | 13 | $(OUTPUT)%.o : %.c |
7 | $(ECHO) " CC " $@ | 14 | $(ECHO) " CC " $@ |
8 | $(QUIET) $(CC) -c $(CFLAGS) $< -o $@ | 15 | $(QUIET) $(CC) -c $(CFLAGS) $< -o $@ |
9 | 16 | ||
10 | cpufreq-bench: $(OBJS) | 17 | $(OUTPUT)cpufreq-bench: $(OBJS) |
11 | $(ECHO) " CC " $@ | 18 | $(ECHO) " CC " $@ |
12 | $(QUIET) $(CC) -o $@ $(CFLAGS) $(OBJS) $(LIBS) | 19 | $(QUIET) $(CC) -o $@ $(CFLAGS) $(OBJS) $(LIBS) |
13 | 20 | ||
14 | all: cpufreq-bench | 21 | all: $(OUTPUT)cpufreq-bench |
15 | 22 | ||
16 | install: | 23 | install: |
17 | mkdir -p $(DESTDIR)/$(sbindir) | 24 | mkdir -p $(DESTDIR)/$(sbindir) |
18 | mkdir -p $(DESTDIR)/$(bindir) | 25 | mkdir -p $(DESTDIR)/$(bindir) |
19 | mkdir -p $(DESTDIR)/$(docdir) | 26 | mkdir -p $(DESTDIR)/$(docdir) |
20 | mkdir -p $(DESTDIR)/$(confdir) | 27 | mkdir -p $(DESTDIR)/$(confdir) |
21 | install -m 755 cpufreq-bench $(DESTDIR)/$(sbindir)/cpufreq-bench | 28 | install -m 755 $(OUTPUT)cpufreq-bench $(DESTDIR)/$(sbindir)/cpufreq-bench |
22 | install -m 755 cpufreq-bench_plot.sh $(DESTDIR)/$(bindir)/cpufreq-bench_plot.sh | 29 | install -m 755 cpufreq-bench_plot.sh $(DESTDIR)/$(bindir)/cpufreq-bench_plot.sh |
23 | install -m 644 README-BENCH $(DESTDIR)/$(docdir)/README-BENCH | 30 | install -m 644 README-BENCH $(DESTDIR)/$(docdir)/README-BENCH |
24 | install -m 755 cpufreq-bench_script.sh $(DESTDIR)/$(docdir)/cpufreq-bench_script.sh | 31 | install -m 755 cpufreq-bench_script.sh $(DESTDIR)/$(docdir)/cpufreq-bench_script.sh |
25 | install -m 644 example.cfg $(DESTDIR)/$(confdir)/cpufreq-bench.conf | 32 | install -m 644 example.cfg $(DESTDIR)/$(confdir)/cpufreq-bench.conf |
26 | 33 | ||
27 | clean: | 34 | clean: |
28 | rm -f *.o | 35 | rm -f $(OUTPUT)*.o |
29 | rm -f cpufreq-bench | 36 | rm -f $(OUTPUT)cpufreq-bench |
diff --git a/tools/power/cpupower/debug/i386/Makefile b/tools/power/cpupower/debug/i386/Makefile index d08cc1ead9bc..3ba158f0e287 100644 --- a/tools/power/cpupower/debug/i386/Makefile +++ b/tools/power/cpupower/debug/i386/Makefile | |||
@@ -1,20 +1,38 @@ | |||
1 | OUTPUT=./ | ||
2 | ifeq ("$(origin O)", "command line") | ||
3 | OUTPUT := $(O)/ | ||
4 | endif | ||
5 | |||
6 | DESTDIR = | ||
7 | bindir = /usr/bin | ||
8 | |||
9 | INSTALL = /usr/bin/install | ||
10 | |||
11 | |||
1 | default: all | 12 | default: all |
2 | 13 | ||
3 | centrino-decode: centrino-decode.c | 14 | $(OUTPUT)centrino-decode: centrino-decode.c |
4 | $(CC) $(CFLAGS) -o centrino-decode centrino-decode.c | 15 | $(CC) $(CFLAGS) -o $@ centrino-decode.c |
5 | 16 | ||
6 | dump_psb: dump_psb.c | 17 | $(OUTPUT)dump_psb: dump_psb.c |
7 | $(CC) $(CFLAGS) -o dump_psb dump_psb.c | 18 | $(CC) $(CFLAGS) -o $@ dump_psb.c |
8 | 19 | ||
9 | intel_gsic: intel_gsic.c | 20 | $(OUTPUT)intel_gsic: intel_gsic.c |
10 | $(CC) $(CFLAGS) -o intel_gsic -llrmi intel_gsic.c | 21 | $(CC) $(CFLAGS) -o $@ -llrmi intel_gsic.c |
11 | 22 | ||
12 | powernow-k8-decode: powernow-k8-decode.c | 23 | $(OUTPUT)powernow-k8-decode: powernow-k8-decode.c |
13 | $(CC) $(CFLAGS) -o powernow-k8-decode powernow-k8-decode.c | 24 | $(CC) $(CFLAGS) -o $@ powernow-k8-decode.c |
14 | 25 | ||
15 | all: centrino-decode dump_psb intel_gsic powernow-k8-decode | 26 | all: $(OUTPUT)centrino-decode $(OUTPUT)dump_psb $(OUTPUT)intel_gsic $(OUTPUT)powernow-k8-decode |
16 | 27 | ||
17 | clean: | 28 | clean: |
18 | rm -rf centrino-decode dump_psb intel_gsic powernow-k8-decode | 29 | rm -rf $(OUTPUT){centrino-decode,dump_psb,intel_gsic,powernow-k8-decode} |
30 | |||
31 | install: | ||
32 | $(INSTALL) -d $(DESTDIR)${bindir} | ||
33 | $(INSTALL) $(OUTPUT)centrino-decode $(DESTDIR)${bindir} | ||
34 | $(INSTALL) $(OUTPUT)powernow-k8-decode $(DESTDIR)${bindir} | ||
35 | $(INSTALL) $(OUTPUT)dump_psb $(DESTDIR)${bindir} | ||
36 | $(INSTALL) $(OUTPUT)intel_gsic $(DESTDIR)${bindir} | ||
19 | 37 | ||
20 | .PHONY: all default clean | 38 | .PHONY: all default clean install |
diff --git a/tools/power/cpupower/debug/x86_64/Makefile b/tools/power/cpupower/debug/x86_64/Makefile index 3326217dd311..1c5214526716 100644 --- a/tools/power/cpupower/debug/x86_64/Makefile +++ b/tools/power/cpupower/debug/x86_64/Makefile | |||
@@ -1,14 +1,30 @@ | |||
1 | OUTPUT=./ | ||
2 | ifeq ("$(origin O)", "command line") | ||
3 | OUTPUT := $(O)/ | ||
4 | endif | ||
5 | |||
6 | DESTDIR = | ||
7 | bindir = /usr/bin | ||
8 | |||
9 | INSTALL = /usr/bin/install | ||
10 | |||
11 | |||
1 | default: all | 12 | default: all |
2 | 13 | ||
3 | centrino-decode: ../i386/centrino-decode.c | 14 | $(OUTPUT)centrino-decode: ../i386/centrino-decode.c |
4 | $(CC) $(CFLAGS) -o $@ $< | 15 | $(CC) $(CFLAGS) -o $@ $< |
5 | 16 | ||
6 | powernow-k8-decode: ../i386/powernow-k8-decode.c | 17 | $(OUTPUT)powernow-k8-decode: ../i386/powernow-k8-decode.c |
7 | $(CC) $(CFLAGS) -o $@ $< | 18 | $(CC) $(CFLAGS) -o $@ $< |
8 | 19 | ||
9 | all: centrino-decode powernow-k8-decode | 20 | all: $(OUTPUT)centrino-decode $(OUTPUT)powernow-k8-decode |
10 | 21 | ||
11 | clean: | 22 | clean: |
12 | rm -rf centrino-decode powernow-k8-decode | 23 | rm -rf $(OUTPUT)centrino-decode $(OUTPUT)powernow-k8-decode |
24 | |||
25 | install: | ||
26 | $(INSTALL) -d $(DESTDIR)${bindir} | ||
27 | $(INSTALL) $(OUTPUT)centrino-decode $(DESTDIR)${bindir} | ||
28 | $(INSTALL) $(OUTPUT)powernow-k8-decode $(DESTDIR)${bindir} | ||
13 | 29 | ||
14 | .PHONY: all default clean | 30 | .PHONY: all default clean install |
diff --git a/tools/power/cpupower/man/cpupower-frequency-info.1 b/tools/power/cpupower/man/cpupower-frequency-info.1 index bb60a8d1e45a..4a1918ea8f9c 100644 --- a/tools/power/cpupower/man/cpupower-frequency-info.1 +++ b/tools/power/cpupower/man/cpupower-frequency-info.1 | |||
@@ -1,4 +1,4 @@ | |||
1 | .TH "cpupower-frequency-info" "1" "0.1" "Mattia Dongili" "" | 1 | .TH "CPUPOWER\-FREQUENCY\-INFO" "1" "0.1" "" "cpupower Manual" |
2 | .SH "NAME" | 2 | .SH "NAME" |
3 | .LP | 3 | .LP |
4 | cpupower frequency\-info \- Utility to retrieve cpufreq kernel information | 4 | cpupower frequency\-info \- Utility to retrieve cpufreq kernel information |
@@ -50,8 +50,6 @@ Prints out information like provided by the /proc/cpufreq interface in 2.4. and | |||
50 | \fB\-m\fR \fB\-\-human\fR | 50 | \fB\-m\fR \fB\-\-human\fR |
51 | human\-readable output for the \-f, \-w, \-s and \-y parameters. | 51 | human\-readable output for the \-f, \-w, \-s and \-y parameters. |
52 | .TP | 52 | .TP |
53 | \fB\-h\fR \fB\-\-help\fR | ||
54 | Prints out the help screen. | ||
55 | .SH "REMARKS" | 53 | .SH "REMARKS" |
56 | .LP | 54 | .LP |
57 | By default only values of core zero are displayed. How to display settings of | 55 | By default only values of core zero are displayed. How to display settings of |
diff --git a/tools/power/cpupower/man/cpupower-frequency-set.1 b/tools/power/cpupower/man/cpupower-frequency-set.1 index 685f469093ad..3eacc8d03d1a 100644 --- a/tools/power/cpupower/man/cpupower-frequency-set.1 +++ b/tools/power/cpupower/man/cpupower-frequency-set.1 | |||
@@ -1,4 +1,4 @@ | |||
1 | .TH "cpupower-freqency-set" "1" "0.1" "Mattia Dongili" "" | 1 | .TH "CPUPOWER\-FREQUENCY\-SET" "1" "0.1" "" "cpupower Manual" |
2 | .SH "NAME" | 2 | .SH "NAME" |
3 | .LP | 3 | .LP |
4 | cpupower frequency\-set \- A small tool which allows to modify cpufreq settings. | 4 | cpupower frequency\-set \- A small tool which allows to modify cpufreq settings. |
@@ -26,8 +26,6 @@ specific frequency to be set. Requires userspace governor to be available and lo | |||
26 | \fB\-r\fR \fB\-\-related\fR | 26 | \fB\-r\fR \fB\-\-related\fR |
27 | modify all hardware-related CPUs at the same time | 27 | modify all hardware-related CPUs at the same time |
28 | .TP | 28 | .TP |
29 | \fB\-h\fR \fB\-\-help\fR | ||
30 | Prints out the help screen. | ||
31 | .SH "REMARKS" | 29 | .SH "REMARKS" |
32 | .LP | 30 | .LP |
33 | By default values are applied on all cores. How to modify single core | 31 | By default values are applied on all cores. How to modify single core |
diff --git a/tools/power/cpupower/man/cpupower-idle-info.1 b/tools/power/cpupower/man/cpupower-idle-info.1 new file mode 100644 index 000000000000..4178effd9e99 --- /dev/null +++ b/tools/power/cpupower/man/cpupower-idle-info.1 | |||
@@ -0,0 +1,90 @@ | |||
1 | .TH "CPUPOWER-IDLE-INFO" "1" "0.1" "" "cpupower Manual" | ||
2 | .SH "NAME" | ||
3 | .LP | ||
4 | cpupower idle\-info \- Utility to retrieve cpu idle kernel information | ||
5 | .SH "SYNTAX" | ||
6 | .LP | ||
7 | cpupower [ \-c cpulist ] idle\-info [\fIoptions\fP] | ||
8 | .SH "DESCRIPTION" | ||
9 | .LP | ||
10 | A tool which prints out per cpu idle information helpful to developers and interested users. | ||
11 | .SH "OPTIONS" | ||
12 | .LP | ||
13 | .TP | ||
14 | \fB\-f\fR \fB\-\-silent\fR | ||
15 | Only print a summary of all available C-states in the system. | ||
16 | .TP | ||
17 | \fB\-e\fR \fB\-\-proc\fR | ||
18 | deprecated. | ||
19 | Prints out idle information in old /proc/acpi/processor/*/power format. This | ||
20 | interface has been removed from the kernel for quite some time, do not let | ||
21 | further code depend on this option, best do not use it. | ||
22 | |||
23 | .SH IDLE\-INFO DESCRIPTIONS | ||
24 | CPU sleep state statistics and descriptions are retrieved from sysfs files, | ||
25 | exported by the cpuidle kernel subsystem. The kernel only updates these | ||
26 | statistics when it enters or leaves an idle state, therefore on a very idle or | ||
27 | a very busy system, these statistics may not be accurate. They still provide a | ||
28 | good overview about the usage and availability of processor sleep states on | ||
29 | the platform. | ||
30 | |||
31 | Be aware that the sleep states as exported by the hardware or BIOS and used by | ||
32 | the Linux kernel may not exactly reflect the capabilities of the | ||
33 | processor. This often is the case on the X86 architecture when the acpi_idle | ||
34 | driver is used. It is also possible that the hardware overrules the kernel | ||
35 | requests, due to internal activity monitors or other reasons. | ||
36 | On recent X86 platforms it is often possible to read out hardware registers | ||
37 | which monitor the duration of sleep states the processor resided in. The | ||
38 | cpupower monitor tool (cpupower\-monitor(1)) can be used to show real sleep | ||
39 | state residencies. Please refer to the architecture specific description | ||
40 | section below. | ||
41 | |||
42 | .SH IDLE\-INFO ARCHITECTURE SPECIFIC DESCRIPTIONS | ||
43 | .SS "X86" | ||
44 | POLL idle state | ||
45 | |||
46 | If cpuidle is active, X86 platforms have one special idle state. | ||
47 | The POLL idle state is not a real idle state, it does not save any | ||
48 | power. Instead, a busy\-loop is executed doing nothing for a short period of | ||
49 | time. This state is used if the kernel knows that work has to be processed | ||
50 | very soon and entering any real hardware idle state may result in a slight | ||
51 | performance penalty. | ||
52 | |||
53 | There exist two different cpuidle drivers on the X86 architecture platform: | ||
54 | |||
55 | "acpi_idle" cpuidle driver | ||
56 | |||
57 | The acpi_idle cpuidle driver retrieves available sleep states (C\-states) from | ||
58 | the ACPI BIOS tables (from the _CST ACPI function on recent platforms or from | ||
59 | the FADT BIOS table on older ones). | ||
60 | The C1 state is not retrieved from ACPI tables. If the C1 state is entered, | ||
61 | the kernel will call the hlt instruction (or mwait on Intel). | ||
62 | |||
63 | "intel_idle" cpuidle driver | ||
64 | |||
65 | In kernel 2.6.36 the intel_idle driver was introduced. | ||
66 | It only serves recent Intel CPUs (Nehalem, Westmere, Sandybridge, Atoms or | ||
67 | newer). On older Intel CPUs the acpi_idle driver is still used (if the BIOS | ||
68 | provides C\-state ACPI tables). | ||
69 | The intel_idle driver knows the sleep state capabilities of the processor and | ||
70 | ignores ACPI BIOS exported processor sleep states tables. | ||
71 | |||
72 | .SH "REMARKS" | ||
73 | .LP | ||
74 | By default only values of core zero are displayed. How to display settings of | ||
75 | other cores is described in the cpupower(1) manpage in the \-\-cpu option | ||
76 | section. | ||
77 | .SH REFERENCES | ||
78 | http://www.acpi.info/spec.htm | ||
79 | .SH "FILES" | ||
80 | .nf | ||
81 | \fI/sys/devices/system/cpu/cpu*/cpuidle/state*\fP | ||
82 | \fI/sys/devices/system/cpu/cpuidle/*\fP | ||
83 | .fi | ||
84 | .SH "AUTHORS" | ||
85 | .nf | ||
86 | Thomas Renninger <trenn@suse.de> | ||
87 | .fi | ||
88 | .SH "SEE ALSO" | ||
89 | .LP | ||
90 | cpupower(1), cpupower\-monitor(1), cpupower\-info(1), cpupower\-set(1) | ||
diff --git a/tools/power/cpupower/man/cpupower-monitor.1 b/tools/power/cpupower/man/cpupower-monitor.1 index d5cfa265c3d3..1141c2073719 100644 --- a/tools/power/cpupower/man/cpupower-monitor.1 +++ b/tools/power/cpupower/man/cpupower-monitor.1 | |||
@@ -107,7 +107,7 @@ Deepest package sleep states may in reality show up as machine/platform wide | |||
107 | sleep states and can only be entered if all cores are idle. Look up Intel | 107 | sleep states and can only be entered if all cores are idle. Look up Intel |
108 | manuals (some are provided in the References section) for further details. | 108 | manuals (some are provided in the References section) for further details. |
109 | 109 | ||
110 | .SS "Ontario" "Liano" | 110 | .SS "Fam_12h" "Fam_14h" |
111 | AMD laptop and desktop processor (family 12h and 14h) sleep state counters. | 111 | AMD laptop and desktop processor (family 12h and 14h) sleep state counters. |
112 | The registers are accessed via PCI and therefore can still be read out while | 112 | The registers are accessed via PCI and therefore can still be read out while |
113 | cores have been offlined. | 113 | cores have been offlined. |
diff --git a/tools/power/cpupower/utils/cpuidle-info.c b/tools/power/cpupower/utils/cpuidle-info.c index b028267c1376..8145af5f93a6 100644 --- a/tools/power/cpupower/utils/cpuidle-info.c +++ b/tools/power/cpupower/utils/cpuidle-info.c | |||
@@ -35,17 +35,9 @@ static void cpuidle_cpu_output(unsigned int cpu, int verbose) | |||
35 | printf(_("CPU %u: Can't read idle state info\n"), cpu); | 35 | printf(_("CPU %u: Can't read idle state info\n"), cpu); |
36 | return; | 36 | return; |
37 | } | 37 | } |
38 | tmp = sysfs_get_idlestate_name(cpu, idlestates - 1); | ||
39 | if (!tmp) { | ||
40 | printf(_("Could not determine max idle state %u\n"), | ||
41 | idlestates - 1); | ||
42 | return; | ||
43 | } | ||
44 | |||
45 | printf(_("Number of idle states: %d\n"), idlestates); | 38 | printf(_("Number of idle states: %d\n"), idlestates); |
46 | |||
47 | printf(_("Available idle states:")); | 39 | printf(_("Available idle states:")); |
48 | for (idlestate = 1; idlestate < idlestates; idlestate++) { | 40 | for (idlestate = 0; idlestate < idlestates; idlestate++) { |
49 | tmp = sysfs_get_idlestate_name(cpu, idlestate); | 41 | tmp = sysfs_get_idlestate_name(cpu, idlestate); |
50 | if (!tmp) | 42 | if (!tmp) |
51 | continue; | 43 | continue; |
@@ -57,7 +49,7 @@ static void cpuidle_cpu_output(unsigned int cpu, int verbose) | |||
57 | if (!verbose) | 49 | if (!verbose) |
58 | return; | 50 | return; |
59 | 51 | ||
60 | for (idlestate = 1; idlestate < idlestates; idlestate++) { | 52 | for (idlestate = 0; idlestate < idlestates; idlestate++) { |
61 | tmp = sysfs_get_idlestate_name(cpu, idlestate); | 53 | tmp = sysfs_get_idlestate_name(cpu, idlestate); |
62 | if (!tmp) | 54 | if (!tmp) |
63 | continue; | 55 | continue; |
diff --git a/tools/power/cpupower/utils/helpers/amd.c b/tools/power/cpupower/utils/helpers/amd.c index 87d5605bdda8..6437ef39aeea 100644 --- a/tools/power/cpupower/utils/helpers/amd.c +++ b/tools/power/cpupower/utils/helpers/amd.c | |||
@@ -112,14 +112,12 @@ int decode_pstates(unsigned int cpu, unsigned int cpu_family, | |||
112 | int amd_pci_get_num_boost_states(int *active, int *states) | 112 | int amd_pci_get_num_boost_states(int *active, int *states) |
113 | { | 113 | { |
114 | struct pci_access *pci_acc; | 114 | struct pci_access *pci_acc; |
115 | int vendor_id = 0x1022; | ||
116 | int boost_dev_ids[4] = {0x1204, 0x1604, 0x1704, 0}; | ||
117 | struct pci_dev *device; | 115 | struct pci_dev *device; |
118 | uint8_t val = 0; | 116 | uint8_t val = 0; |
119 | 117 | ||
120 | *active = *states = 0; | 118 | *active = *states = 0; |
121 | 119 | ||
122 | device = pci_acc_init(&pci_acc, vendor_id, boost_dev_ids); | 120 | device = pci_slot_func_init(&pci_acc, 0x18, 4); |
123 | 121 | ||
124 | if (device == NULL) | 122 | if (device == NULL) |
125 | return -ENODEV; | 123 | return -ENODEV; |
diff --git a/tools/power/cpupower/utils/helpers/helpers.h b/tools/power/cpupower/utils/helpers/helpers.h index 2747e738efb0..2eb584cf2f55 100644 --- a/tools/power/cpupower/utils/helpers/helpers.h +++ b/tools/power/cpupower/utils/helpers/helpers.h | |||
@@ -66,8 +66,8 @@ enum cpupower_cpu_vendor {X86_VENDOR_UNKNOWN = 0, X86_VENDOR_INTEL, | |||
66 | #define CPUPOWER_CAP_AMD_CBP 0x00000004 | 66 | #define CPUPOWER_CAP_AMD_CBP 0x00000004 |
67 | #define CPUPOWER_CAP_PERF_BIAS 0x00000008 | 67 | #define CPUPOWER_CAP_PERF_BIAS 0x00000008 |
68 | #define CPUPOWER_CAP_HAS_TURBO_RATIO 0x00000010 | 68 | #define CPUPOWER_CAP_HAS_TURBO_RATIO 0x00000010 |
69 | #define CPUPOWER_CAP_IS_SNB 0x00000011 | 69 | #define CPUPOWER_CAP_IS_SNB 0x00000020 |
70 | #define CPUPOWER_CAP_INTEL_IDA 0x00000012 | 70 | #define CPUPOWER_CAP_INTEL_IDA 0x00000040 |
71 | 71 | ||
72 | #define MAX_HW_PSTATES 10 | 72 | #define MAX_HW_PSTATES 10 |
73 | 73 | ||
@@ -132,8 +132,11 @@ extern unsigned long long msr_intel_get_turbo_ratio(unsigned int cpu); | |||
132 | 132 | ||
133 | /* PCI stuff ****************************/ | 133 | /* PCI stuff ****************************/ |
134 | extern int amd_pci_get_num_boost_states(int *active, int *states); | 134 | extern int amd_pci_get_num_boost_states(int *active, int *states); |
135 | extern struct pci_dev *pci_acc_init(struct pci_access **pacc, int vendor_id, | 135 | extern struct pci_dev *pci_acc_init(struct pci_access **pacc, int domain, |
136 | int *dev_ids); | 136 | int bus, int slot, int func, int vendor, |
137 | int dev); | ||
138 | extern struct pci_dev *pci_slot_func_init(struct pci_access **pacc, | ||
139 | int slot, int func); | ||
137 | 140 | ||
138 | /* PCI stuff ****************************/ | 141 | /* PCI stuff ****************************/ |
139 | 142 | ||
diff --git a/tools/power/cpupower/utils/helpers/pci.c b/tools/power/cpupower/utils/helpers/pci.c index cd2eb6fe41c4..9690798e6446 100644 --- a/tools/power/cpupower/utils/helpers/pci.c +++ b/tools/power/cpupower/utils/helpers/pci.c | |||
@@ -10,19 +10,24 @@ | |||
10 | * **pacc : if a valid pci_dev is returned | 10 | * **pacc : if a valid pci_dev is returned |
11 | * *pacc must be passed to pci_acc_cleanup to free it | 11 | * *pacc must be passed to pci_acc_cleanup to free it |
12 | * | 12 | * |
13 | * vendor_id : the pci vendor id matching the pci device to access | 13 | * domain: domain |
14 | * dev_ids : device ids matching the pci device to access | 14 | * bus: bus |
15 | * slot: slot | ||
16 | * func: func | ||
17 | * vendor: vendor | ||
18 | * device: device | ||
19 | * Pass -1 for one of the six above to match any | ||
15 | * | 20 | * |
16 | * Returns : | 21 | * Returns : |
17 | * struct pci_dev which can be used with pci_{read,write}_* functions | 22 | * struct pci_dev which can be used with pci_{read,write}_* functions |
18 | * to access the PCI config space of matching pci devices | 23 | * to access the PCI config space of matching pci devices |
19 | */ | 24 | */ |
20 | struct pci_dev *pci_acc_init(struct pci_access **pacc, int vendor_id, | 25 | struct pci_dev *pci_acc_init(struct pci_access **pacc, int domain, int bus, |
21 | int *dev_ids) | 26 | int slot, int func, int vendor, int dev) |
22 | { | 27 | { |
23 | struct pci_filter filter_nb_link = { -1, -1, -1, -1, vendor_id, 0}; | 28 | struct pci_filter filter_nb_link = { domain, bus, slot, func, |
29 | vendor, dev }; | ||
24 | struct pci_dev *device; | 30 | struct pci_dev *device; |
25 | unsigned int i; | ||
26 | 31 | ||
27 | *pacc = pci_alloc(); | 32 | *pacc = pci_alloc(); |
28 | if (*pacc == NULL) | 33 | if (*pacc == NULL) |
@@ -31,14 +36,20 @@ struct pci_dev *pci_acc_init(struct pci_access **pacc, int vendor_id, | |||
31 | pci_init(*pacc); | 36 | pci_init(*pacc); |
32 | pci_scan_bus(*pacc); | 37 | pci_scan_bus(*pacc); |
33 | 38 | ||
34 | for (i = 0; dev_ids[i] != 0; i++) { | 39 | for (device = (*pacc)->devices; device; device = device->next) { |
35 | filter_nb_link.device = dev_ids[i]; | 40 | if (pci_filter_match(&filter_nb_link, device)) |
36 | for (device = (*pacc)->devices; device; device = device->next) { | 41 | return device; |
37 | if (pci_filter_match(&filter_nb_link, device)) | ||
38 | return device; | ||
39 | } | ||
40 | } | 42 | } |
41 | pci_cleanup(*pacc); | 43 | pci_cleanup(*pacc); |
42 | return NULL; | 44 | return NULL; |
43 | } | 45 | } |
46 | |||
47 | /* Typically one wants to get a specific slot(device)/func of the root domain | ||
48 | and bus */ | ||
49 | struct pci_dev *pci_slot_func_init(struct pci_access **pacc, int slot, | ||
50 | int func) | ||
51 | { | ||
52 | return pci_acc_init(pacc, 0, 0, slot, func, -1, -1); | ||
53 | } | ||
54 | |||
44 | #endif /* defined(__i386__) || defined(__x86_64__) */ | 55 | #endif /* defined(__i386__) || defined(__x86_64__) */ |
diff --git a/tools/power/cpupower/utils/idle_monitor/amd_fam14h_idle.c b/tools/power/cpupower/utils/idle_monitor/amd_fam14h_idle.c index 202e555988be..2116df9ad832 100644 --- a/tools/power/cpupower/utils/idle_monitor/amd_fam14h_idle.c +++ b/tools/power/cpupower/utils/idle_monitor/amd_fam14h_idle.c | |||
@@ -20,8 +20,6 @@ | |||
20 | #include "idle_monitor/cpupower-monitor.h" | 20 | #include "idle_monitor/cpupower-monitor.h" |
21 | #include "helpers/helpers.h" | 21 | #include "helpers/helpers.h" |
22 | 22 | ||
23 | /******** PCI parts could go into own file and get shared ***************/ | ||
24 | |||
25 | #define PCI_NON_PC0_OFFSET 0xb0 | 23 | #define PCI_NON_PC0_OFFSET 0xb0 |
26 | #define PCI_PC1_OFFSET 0xb4 | 24 | #define PCI_PC1_OFFSET 0xb4 |
27 | #define PCI_PC6_OFFSET 0xb8 | 25 | #define PCI_PC6_OFFSET 0xb8 |
@@ -82,10 +80,7 @@ static cstate_t amd_fam14h_cstates[AMD_FAM14H_STATE_NUM] = { | |||
82 | }; | 80 | }; |
83 | 81 | ||
84 | static struct pci_access *pci_acc; | 82 | static struct pci_access *pci_acc; |
85 | static int pci_vendor_id = 0x1022; | ||
86 | static int pci_dev_ids[2] = {0x1716, 0}; | ||
87 | static struct pci_dev *amd_fam14h_pci_dev; | 83 | static struct pci_dev *amd_fam14h_pci_dev; |
88 | |||
89 | static int nbp1_entered; | 84 | static int nbp1_entered; |
90 | 85 | ||
91 | struct timespec start_time; | 86 | struct timespec start_time; |
@@ -286,13 +281,13 @@ struct cpuidle_monitor *amd_fam14h_register(void) | |||
286 | if (cpupower_cpu_info.vendor != X86_VENDOR_AMD) | 281 | if (cpupower_cpu_info.vendor != X86_VENDOR_AMD) |
287 | return NULL; | 282 | return NULL; |
288 | 283 | ||
289 | if (cpupower_cpu_info.family == 0x14) { | 284 | if (cpupower_cpu_info.family == 0x14) |
290 | if (cpu_count <= 0 || cpu_count > 2) { | 285 | strncpy(amd_fam14h_monitor.name, "Fam_14h", |
291 | fprintf(stderr, "AMD fam14h: Invalid cpu count: %d\n", | 286 | MONITOR_NAME_LEN - 1); |
292 | cpu_count); | 287 | else if (cpupower_cpu_info.family == 0x12) |
293 | return NULL; | 288 | strncpy(amd_fam14h_monitor.name, "Fam_12h", |
294 | } | 289 | MONITOR_NAME_LEN - 1); |
295 | } else | 290 | else |
296 | return NULL; | 291 | return NULL; |
297 | 292 | ||
298 | /* We do not alloc for nbp1 machine wide counter */ | 293 | /* We do not alloc for nbp1 machine wide counter */ |
@@ -303,7 +298,9 @@ struct cpuidle_monitor *amd_fam14h_register(void) | |||
303 | sizeof(unsigned long long)); | 298 | sizeof(unsigned long long)); |
304 | } | 299 | } |
305 | 300 | ||
306 | amd_fam14h_pci_dev = pci_acc_init(&pci_acc, pci_vendor_id, pci_dev_ids); | 301 | /* We need PCI device: Slot 18, Func 6, compare with BKDG |
302 | for fam 12h/14h */ | ||
303 | amd_fam14h_pci_dev = pci_slot_func_init(&pci_acc, 0x18, 6); | ||
307 | if (amd_fam14h_pci_dev == NULL || pci_acc == NULL) | 304 | if (amd_fam14h_pci_dev == NULL || pci_acc == NULL) |
308 | return NULL; | 305 | return NULL; |
309 | 306 | ||
@@ -325,7 +322,7 @@ static void amd_fam14h_unregister(void) | |||
325 | } | 322 | } |
326 | 323 | ||
327 | struct cpuidle_monitor amd_fam14h_monitor = { | 324 | struct cpuidle_monitor amd_fam14h_monitor = { |
328 | .name = "Ontario", | 325 | .name = "", |
329 | .hw_states = amd_fam14h_cstates, | 326 | .hw_states = amd_fam14h_cstates, |
330 | .hw_states_num = AMD_FAM14H_STATE_NUM, | 327 | .hw_states_num = AMD_FAM14H_STATE_NUM, |
331 | .start = amd_fam14h_start, | 328 | .start = amd_fam14h_start, |
diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index 758ec2a08c40..95d6a6f7c33a 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl | |||
@@ -46,6 +46,7 @@ my %default = ( | |||
46 | "DIE_ON_FAILURE" => 1, | 46 | "DIE_ON_FAILURE" => 1, |
47 | "SSH_EXEC" => "ssh \$SSH_USER\@\$MACHINE \$SSH_COMMAND", | 47 | "SSH_EXEC" => "ssh \$SSH_USER\@\$MACHINE \$SSH_COMMAND", |
48 | "SCP_TO_TARGET" => "scp \$SRC_FILE \$SSH_USER\@\$MACHINE:\$DST_FILE", | 48 | "SCP_TO_TARGET" => "scp \$SRC_FILE \$SSH_USER\@\$MACHINE:\$DST_FILE", |
49 | "SCP_TO_TARGET_INSTALL" => "\${SCP_TO_TARGET}", | ||
49 | "REBOOT" => "ssh \$SSH_USER\@\$MACHINE reboot", | 50 | "REBOOT" => "ssh \$SSH_USER\@\$MACHINE reboot", |
50 | "STOP_AFTER_SUCCESS" => 10, | 51 | "STOP_AFTER_SUCCESS" => 10, |
51 | "STOP_AFTER_FAILURE" => 60, | 52 | "STOP_AFTER_FAILURE" => 60, |
@@ -86,11 +87,13 @@ my $reboot_on_error; | |||
86 | my $switch_to_good; | 87 | my $switch_to_good; |
87 | my $switch_to_test; | 88 | my $switch_to_test; |
88 | my $poweroff_on_error; | 89 | my $poweroff_on_error; |
90 | my $reboot_on_success; | ||
89 | my $die_on_failure; | 91 | my $die_on_failure; |
90 | my $powercycle_after_reboot; | 92 | my $powercycle_after_reboot; |
91 | my $poweroff_after_halt; | 93 | my $poweroff_after_halt; |
92 | my $ssh_exec; | 94 | my $ssh_exec; |
93 | my $scp_to_target; | 95 | my $scp_to_target; |
96 | my $scp_to_target_install; | ||
94 | my $power_off; | 97 | my $power_off; |
95 | my $grub_menu; | 98 | my $grub_menu; |
96 | my $grub_number; | 99 | my $grub_number; |
@@ -211,6 +214,7 @@ my %option_map = ( | |||
211 | "SWITCH_TO_GOOD" => \$switch_to_good, | 214 | "SWITCH_TO_GOOD" => \$switch_to_good, |
212 | "SWITCH_TO_TEST" => \$switch_to_test, | 215 | "SWITCH_TO_TEST" => \$switch_to_test, |
213 | "POWEROFF_ON_ERROR" => \$poweroff_on_error, | 216 | "POWEROFF_ON_ERROR" => \$poweroff_on_error, |
217 | "REBOOT_ON_SUCCESS" => \$reboot_on_success, | ||
214 | "DIE_ON_FAILURE" => \$die_on_failure, | 218 | "DIE_ON_FAILURE" => \$die_on_failure, |
215 | "POWER_OFF" => \$power_off, | 219 | "POWER_OFF" => \$power_off, |
216 | "POWERCYCLE_AFTER_REBOOT" => \$powercycle_after_reboot, | 220 | "POWERCYCLE_AFTER_REBOOT" => \$powercycle_after_reboot, |
@@ -243,6 +247,7 @@ my %option_map = ( | |||
243 | "BUILD_TARGET" => \$build_target, | 247 | "BUILD_TARGET" => \$build_target, |
244 | "SSH_EXEC" => \$ssh_exec, | 248 | "SSH_EXEC" => \$ssh_exec, |
245 | "SCP_TO_TARGET" => \$scp_to_target, | 249 | "SCP_TO_TARGET" => \$scp_to_target, |
250 | "SCP_TO_TARGET_INSTALL" => \$scp_to_target_install, | ||
246 | "CHECKOUT" => \$checkout, | 251 | "CHECKOUT" => \$checkout, |
247 | "TARGET_IMAGE" => \$target_image, | 252 | "TARGET_IMAGE" => \$target_image, |
248 | "LOCALVERSION" => \$localversion, | 253 | "LOCALVERSION" => \$localversion, |
@@ -1113,7 +1118,6 @@ sub reboot_to_good { | |||
1113 | 1118 | ||
1114 | if (defined($switch_to_good)) { | 1119 | if (defined($switch_to_good)) { |
1115 | run_command $switch_to_good; | 1120 | run_command $switch_to_good; |
1116 | return; | ||
1117 | } | 1121 | } |
1118 | 1122 | ||
1119 | reboot $time; | 1123 | reboot $time; |
@@ -1349,8 +1353,7 @@ sub run_ssh { | |||
1349 | } | 1353 | } |
1350 | 1354 | ||
1351 | sub run_scp { | 1355 | sub run_scp { |
1352 | my ($src, $dst) = @_; | 1356 | my ($src, $dst, $cp_scp) = @_; |
1353 | my $cp_scp = $scp_to_target; | ||
1354 | 1357 | ||
1355 | $cp_scp =~ s/\$SRC_FILE/$src/g; | 1358 | $cp_scp =~ s/\$SRC_FILE/$src/g; |
1356 | $cp_scp =~ s/\$DST_FILE/$dst/g; | 1359 | $cp_scp =~ s/\$DST_FILE/$dst/g; |
@@ -1358,6 +1361,22 @@ sub run_scp { | |||
1358 | return run_command "$cp_scp"; | 1361 | return run_command "$cp_scp"; |
1359 | } | 1362 | } |
1360 | 1363 | ||
1364 | sub run_scp_install { | ||
1365 | my ($src, $dst) = @_; | ||
1366 | |||
1367 | my $cp_scp = $scp_to_target_install; | ||
1368 | |||
1369 | return run_scp($src, $dst, $cp_scp); | ||
1370 | } | ||
1371 | |||
1372 | sub run_scp_mod { | ||
1373 | my ($src, $dst) = @_; | ||
1374 | |||
1375 | my $cp_scp = $scp_to_target; | ||
1376 | |||
1377 | return run_scp($src, $dst, $cp_scp); | ||
1378 | } | ||
1379 | |||
1361 | sub get_grub_index { | 1380 | sub get_grub_index { |
1362 | 1381 | ||
1363 | if ($reboot_type ne "grub") { | 1382 | if ($reboot_type ne "grub") { |
@@ -1460,6 +1479,7 @@ sub get_sha1 { | |||
1460 | sub monitor { | 1479 | sub monitor { |
1461 | my $booted = 0; | 1480 | my $booted = 0; |
1462 | my $bug = 0; | 1481 | my $bug = 0; |
1482 | my $bug_ignored = 0; | ||
1463 | my $skip_call_trace = 0; | 1483 | my $skip_call_trace = 0; |
1464 | my $loops; | 1484 | my $loops; |
1465 | 1485 | ||
@@ -1531,9 +1551,13 @@ sub monitor { | |||
1531 | } | 1551 | } |
1532 | 1552 | ||
1533 | if ($full_line =~ /call trace:/i) { | 1553 | if ($full_line =~ /call trace:/i) { |
1534 | if (!$ignore_errors && !$bug && !$skip_call_trace) { | 1554 | if (!$bug && !$skip_call_trace) { |
1535 | $bug = 1; | 1555 | if ($ignore_errors) { |
1536 | $failure_start = time; | 1556 | $bug_ignored = 1; |
1557 | } else { | ||
1558 | $bug = 1; | ||
1559 | $failure_start = time; | ||
1560 | } | ||
1537 | } | 1561 | } |
1538 | } | 1562 | } |
1539 | 1563 | ||
@@ -1595,6 +1619,10 @@ sub monitor { | |||
1595 | fail "failed - never got a boot prompt." and return 0; | 1619 | fail "failed - never got a boot prompt." and return 0; |
1596 | } | 1620 | } |
1597 | 1621 | ||
1622 | if ($bug_ignored) { | ||
1623 | doprint "WARNING: Call Trace detected but ignored due to IGNORE_ERRORS=1\n"; | ||
1624 | } | ||
1625 | |||
1598 | return 1; | 1626 | return 1; |
1599 | } | 1627 | } |
1600 | 1628 | ||
@@ -1621,7 +1649,7 @@ sub install { | |||
1621 | 1649 | ||
1622 | my $cp_target = eval_kernel_version $target_image; | 1650 | my $cp_target = eval_kernel_version $target_image; |
1623 | 1651 | ||
1624 | run_scp "$outputdir/$build_target", "$cp_target" or | 1652 | run_scp_install "$outputdir/$build_target", "$cp_target" or |
1625 | dodie "failed to copy image"; | 1653 | dodie "failed to copy image"; |
1626 | 1654 | ||
1627 | my $install_mods = 0; | 1655 | my $install_mods = 0; |
@@ -1643,7 +1671,7 @@ sub install { | |||
1643 | return; | 1671 | return; |
1644 | } | 1672 | } |
1645 | 1673 | ||
1646 | run_command "$make INSTALL_MOD_PATH=$tmpdir modules_install" or | 1674 | run_command "$make INSTALL_MOD_STRIP=1 INSTALL_MOD_PATH=$tmpdir modules_install" or |
1647 | dodie "Failed to install modules"; | 1675 | dodie "Failed to install modules"; |
1648 | 1676 | ||
1649 | my $modlib = "/lib/modules/$version"; | 1677 | my $modlib = "/lib/modules/$version"; |
@@ -1656,7 +1684,7 @@ sub install { | |||
1656 | run_command "cd $tmpdir && tar -cjf $modtar lib/modules/$version" or | 1684 | run_command "cd $tmpdir && tar -cjf $modtar lib/modules/$version" or |
1657 | dodie "making tarball"; | 1685 | dodie "making tarball"; |
1658 | 1686 | ||
1659 | run_scp "$tmpdir/$modtar", "/tmp" or | 1687 | run_scp_mod "$tmpdir/$modtar", "/tmp" or |
1660 | dodie "failed to copy modules"; | 1688 | dodie "failed to copy modules"; |
1661 | 1689 | ||
1662 | unlink "$tmpdir/$modtar"; | 1690 | unlink "$tmpdir/$modtar"; |
@@ -3526,8 +3554,10 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { | |||
3526 | die "failed to checkout $checkout"; | 3554 | die "failed to checkout $checkout"; |
3527 | } | 3555 | } |
3528 | 3556 | ||
3529 | $no_reboot = 0; | 3557 | # A test may opt to not reboot the box |
3530 | 3558 | if ($reboot_on_success) { | |
3559 | $no_reboot = 0; | ||
3560 | } | ||
3531 | 3561 | ||
3532 | if ($test_type eq "bisect") { | 3562 | if ($test_type eq "bisect") { |
3533 | bisect $i; | 3563 | bisect $i; |
@@ -3572,8 +3602,12 @@ if ($opt{"POWEROFF_ON_SUCCESS"}) { | |||
3572 | halt; | 3602 | halt; |
3573 | } elsif ($opt{"REBOOT_ON_SUCCESS"} && !do_not_reboot) { | 3603 | } elsif ($opt{"REBOOT_ON_SUCCESS"} && !do_not_reboot) { |
3574 | reboot_to_good; | 3604 | reboot_to_good; |
3605 | } elsif (defined($switch_to_good)) { | ||
3606 | # still need to get to the good kernel | ||
3607 | run_command $switch_to_good; | ||
3575 | } | 3608 | } |
3576 | 3609 | ||
3610 | |||
3577 | doprint "\n $successes of $opt{NUM_TESTS} tests were successful\n\n"; | 3611 | doprint "\n $successes of $opt{NUM_TESTS} tests were successful\n\n"; |
3578 | 3612 | ||
3579 | exit 0; | 3613 | exit 0; |
diff --git a/tools/testing/ktest/sample.conf b/tools/testing/ktest/sample.conf index 5ea04c6a71bf..b682456afda8 100644 --- a/tools/testing/ktest/sample.conf +++ b/tools/testing/ktest/sample.conf | |||
@@ -710,10 +710,18 @@ | |||
710 | # The variables SSH_USER, MACHINE and SSH_COMMAND are defined | 710 | # The variables SSH_USER, MACHINE and SSH_COMMAND are defined |
711 | #SSH_EXEC = ssh $SSH_USER@$MACHINE $SSH_COMMAND"; | 711 | #SSH_EXEC = ssh $SSH_USER@$MACHINE $SSH_COMMAND"; |
712 | 712 | ||
713 | # The way to copy a file to the target | 713 | # The way to copy a file to the target (install and modules) |
714 | # (default scp $SRC_FILE $SSH_USER@$MACHINE:$DST_FILE) | 714 | # (default scp $SRC_FILE $SSH_USER@$MACHINE:$DST_FILE) |
715 | # The variables SSH_USER, MACHINE, SRC_FILE and DST_FILE are defined. | 715 | # The variables SSH_USER, MACHINE are defined by the config |
716 | #SCP_TO_TARGET = scp $SRC_FILE $SSH_USER@$MACHINE:$DST_FILE | 716 | # SRC_FILE and DST_FILE are ktest internal variables and |
717 | # should only have '$' and not the '${}' notation. | ||
718 | # (default scp $SRC_FILE ${SSH_USER}@${MACHINE}:$DST_FILE) | ||
719 | #SCP_TO_TARGET = echo skip scp for $SRC_FILE $DST_FILE | ||
720 | |||
721 | # If install needs to be different than modules, then this | ||
722 | # option will override the SCP_TO_TARGET for installation. | ||
723 | # (default ${SCP_TO_TARGET} ) | ||
724 | #SCP_TO_TARGET_INSTALL = scp $SRC_FILE tftp@tftpserver:$DST_FILE | ||
717 | 725 | ||
718 | # The nice way to reboot the target | 726 | # The nice way to reboot the target |
719 | # (default ssh $SSH_USER@$MACHINE reboot) | 727 | # (default ssh $SSH_USER@$MACHINE reboot) |
diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile index 4ec84018cc13..28bc57ee757c 100644 --- a/tools/testing/selftests/Makefile +++ b/tools/testing/selftests/Makefile | |||
@@ -1,10 +1,15 @@ | |||
1 | TARGETS = breakpoints | 1 | TARGETS = breakpoints vm |
2 | 2 | ||
3 | all: | 3 | all: |
4 | for TARGET in $(TARGETS); do \ | 4 | for TARGET in $(TARGETS); do \ |
5 | make -C $$TARGET; \ | 5 | make -C $$TARGET; \ |
6 | done; | 6 | done; |
7 | 7 | ||
8 | run_tests: all | ||
9 | for TARGET in $(TARGETS); do \ | ||
10 | make -C $$TARGET run_tests; \ | ||
11 | done; | ||
12 | |||
8 | clean: | 13 | clean: |
9 | for TARGET in $(TARGETS); do \ | 14 | for TARGET in $(TARGETS); do \ |
10 | make -C $$TARGET clean; \ | 15 | make -C $$TARGET clean; \ |
diff --git a/tools/testing/selftests/breakpoints/Makefile b/tools/testing/selftests/breakpoints/Makefile index f362722cdce7..931278035f5c 100644 --- a/tools/testing/selftests/breakpoints/Makefile +++ b/tools/testing/selftests/breakpoints/Makefile | |||
@@ -11,10 +11,13 @@ endif | |||
11 | 11 | ||
12 | all: | 12 | all: |
13 | ifeq ($(ARCH),x86) | 13 | ifeq ($(ARCH),x86) |
14 | gcc breakpoint_test.c -o run_test | 14 | gcc breakpoint_test.c -o breakpoint_test |
15 | else | 15 | else |
16 | echo "Not an x86 target, can't build breakpoints selftests" | 16 | echo "Not an x86 target, can't build breakpoints selftests" |
17 | endif | 17 | endif |
18 | 18 | ||
19 | run_tests: | ||
20 | ./breakpoint_test | ||
21 | |||
19 | clean: | 22 | clean: |
20 | rm -fr run_test | 23 | rm -fr breakpoint_test |
diff --git a/tools/testing/selftests/run_tests b/tools/testing/selftests/run_tests deleted file mode 100644 index 320718a4e6bf..000000000000 --- a/tools/testing/selftests/run_tests +++ /dev/null | |||
@@ -1,8 +0,0 @@ | |||
1 | #!/bin/bash | ||
2 | |||
3 | TARGETS=breakpoints | ||
4 | |||
5 | for TARGET in $TARGETS | ||
6 | do | ||
7 | $TARGET/run_test | ||
8 | done | ||
diff --git a/tools/testing/selftests/vm/Makefile b/tools/testing/selftests/vm/Makefile new file mode 100644 index 000000000000..b336b24aa6c0 --- /dev/null +++ b/tools/testing/selftests/vm/Makefile | |||
@@ -0,0 +1,14 @@ | |||
1 | # Makefile for vm selftests | ||
2 | |||
3 | CC = $(CROSS_COMPILE)gcc | ||
4 | CFLAGS = -Wall -Wextra | ||
5 | |||
6 | all: hugepage-mmap hugepage-shm map_hugetlb | ||
7 | %: %.c | ||
8 | $(CC) $(CFLAGS) -o $@ $^ | ||
9 | |||
10 | run_tests: all | ||
11 | /bin/sh ./run_vmtests | ||
12 | |||
13 | clean: | ||
14 | $(RM) hugepage-mmap hugepage-shm map_hugetlb | ||
diff --git a/tools/testing/selftests/vm/hugepage-mmap.c b/tools/testing/selftests/vm/hugepage-mmap.c new file mode 100644 index 000000000000..a10f310d2362 --- /dev/null +++ b/tools/testing/selftests/vm/hugepage-mmap.c | |||
@@ -0,0 +1,92 @@ | |||
1 | /* | ||
2 | * hugepage-mmap: | ||
3 | * | ||
4 | * Example of using huge page memory in a user application using the mmap | ||
5 | * system call. Before running this application, make sure that the | ||
6 | * administrator has mounted the hugetlbfs filesystem (on some directory | ||
7 | * like /mnt) using the command mount -t hugetlbfs nodev /mnt. In this | ||
8 | * example, the app is requesting memory of size 256MB that is backed by | ||
9 | * huge pages. | ||
10 | * | ||
11 | * For the ia64 architecture, the Linux kernel reserves Region number 4 for | ||
12 | * huge pages. That means that if one requires a fixed address, a huge page | ||
13 | * aligned address starting with 0x800000... will be required. If a fixed | ||
14 | * address is not required, the kernel will select an address in the proper | ||
15 | * range. | ||
16 | * Other architectures, such as ppc64, i386 or x86_64 are not so constrained. | ||
17 | */ | ||
18 | |||
19 | #include <stdlib.h> | ||
20 | #include <stdio.h> | ||
21 | #include <unistd.h> | ||
22 | #include <sys/mman.h> | ||
23 | #include <fcntl.h> | ||
24 | |||
25 | #define FILE_NAME "huge/hugepagefile" | ||
26 | #define LENGTH (256UL*1024*1024) | ||
27 | #define PROTECTION (PROT_READ | PROT_WRITE) | ||
28 | |||
29 | /* Only ia64 requires this */ | ||
30 | #ifdef __ia64__ | ||
31 | #define ADDR (void *)(0x8000000000000000UL) | ||
32 | #define FLAGS (MAP_SHARED | MAP_FIXED) | ||
33 | #else | ||
34 | #define ADDR (void *)(0x0UL) | ||
35 | #define FLAGS (MAP_SHARED) | ||
36 | #endif | ||
37 | |||
38 | static void check_bytes(char *addr) | ||
39 | { | ||
40 | printf("First hex is %x\n", *((unsigned int *)addr)); | ||
41 | } | ||
42 | |||
43 | static void write_bytes(char *addr) | ||
44 | { | ||
45 | unsigned long i; | ||
46 | |||
47 | for (i = 0; i < LENGTH; i++) | ||
48 | *(addr + i) = (char)i; | ||
49 | } | ||
50 | |||
51 | static int read_bytes(char *addr) | ||
52 | { | ||
53 | unsigned long i; | ||
54 | |||
55 | check_bytes(addr); | ||
56 | for (i = 0; i < LENGTH; i++) | ||
57 | if (*(addr + i) != (char)i) { | ||
58 | printf("Mismatch at %lu\n", i); | ||
59 | return 1; | ||
60 | } | ||
61 | return 0; | ||
62 | } | ||
63 | |||
64 | int main(void) | ||
65 | { | ||
66 | void *addr; | ||
67 | int fd, ret; | ||
68 | |||
69 | fd = open(FILE_NAME, O_CREAT | O_RDWR, 0755); | ||
70 | if (fd < 0) { | ||
71 | perror("Open failed"); | ||
72 | exit(1); | ||
73 | } | ||
74 | |||
75 | addr = mmap(ADDR, LENGTH, PROTECTION, FLAGS, fd, 0); | ||
76 | if (addr == MAP_FAILED) { | ||
77 | perror("mmap"); | ||
78 | unlink(FILE_NAME); | ||
79 | exit(1); | ||
80 | } | ||
81 | |||
82 | printf("Returned address is %p\n", addr); | ||
83 | check_bytes(addr); | ||
84 | write_bytes(addr); | ||
85 | ret = read_bytes(addr); | ||
86 | |||
87 | munmap(addr, LENGTH); | ||
88 | close(fd); | ||
89 | unlink(FILE_NAME); | ||
90 | |||
91 | return ret; | ||
92 | } | ||
diff --git a/tools/testing/selftests/vm/hugepage-shm.c b/tools/testing/selftests/vm/hugepage-shm.c new file mode 100644 index 000000000000..0d0ef4fc0c04 --- /dev/null +++ b/tools/testing/selftests/vm/hugepage-shm.c | |||
@@ -0,0 +1,100 @@ | |||
1 | /* | ||
2 | * hugepage-shm: | ||
3 | * | ||
4 | * Example of using huge page memory in a user application using Sys V shared | ||
5 | * memory system calls. In this example the app is requesting 256MB of | ||
6 | * memory that is backed by huge pages. The application uses the flag | ||
7 | * SHM_HUGETLB in the shmget system call to inform the kernel that it is | ||
8 | * requesting huge pages. | ||
9 | * | ||
10 | * For the ia64 architecture, the Linux kernel reserves Region number 4 for | ||
11 | * huge pages. That means that if one requires a fixed address, a huge page | ||
12 | * aligned address starting with 0x800000... will be required. If a fixed | ||
13 | * address is not required, the kernel will select an address in the proper | ||
14 | * range. | ||
15 | * Other architectures, such as ppc64, i386 or x86_64 are not so constrained. | ||
16 | * | ||
17 | * Note: The default shared memory limit is quite low on many kernels, | ||
18 | * you may need to increase it via: | ||
19 | * | ||
20 | * echo 268435456 > /proc/sys/kernel/shmmax | ||
21 | * | ||
22 | * This will increase the maximum size per shared memory segment to 256MB. | ||
23 | * The other limit that you will hit eventually is shmall which is the | ||
24 | * total amount of shared memory in pages. To set it to 16GB on a system | ||
25 | * with a 4kB pagesize do: | ||
26 | * | ||
27 | * echo 4194304 > /proc/sys/kernel/shmall | ||
28 | */ | ||
29 | |||
30 | #include <stdlib.h> | ||
31 | #include <stdio.h> | ||
32 | #include <sys/types.h> | ||
33 | #include <sys/ipc.h> | ||
34 | #include <sys/shm.h> | ||
35 | #include <sys/mman.h> | ||
36 | |||
37 | #ifndef SHM_HUGETLB | ||
38 | #define SHM_HUGETLB 04000 | ||
39 | #endif | ||
40 | |||
41 | #define LENGTH (256UL*1024*1024) | ||
42 | |||
43 | #define dprintf(x) printf(x) | ||
44 | |||
45 | /* Only ia64 requires this */ | ||
46 | #ifdef __ia64__ | ||
47 | #define ADDR (void *)(0x8000000000000000UL) | ||
48 | #define SHMAT_FLAGS (SHM_RND) | ||
49 | #else | ||
50 | #define ADDR (void *)(0x0UL) | ||
51 | #define SHMAT_FLAGS (0) | ||
52 | #endif | ||
53 | |||
54 | int main(void) | ||
55 | { | ||
56 | int shmid; | ||
57 | unsigned long i; | ||
58 | char *shmaddr; | ||
59 | |||
60 | shmid = shmget(2, LENGTH, SHM_HUGETLB | IPC_CREAT | SHM_R | SHM_W); | ||
61 | if (shmid < 0) { | ||
62 | perror("shmget"); | ||
63 | exit(1); | ||
64 | } | ||
65 | printf("shmid: 0x%x\n", shmid); | ||
66 | |||
67 | shmaddr = shmat(shmid, ADDR, SHMAT_FLAGS); | ||
68 | if (shmaddr == (char *)-1) { | ||
69 | perror("Shared memory attach failure"); | ||
70 | shmctl(shmid, IPC_RMID, NULL); | ||
71 | exit(2); | ||
72 | } | ||
73 | printf("shmaddr: %p\n", shmaddr); | ||
74 | |||
75 | dprintf("Starting the writes:\n"); | ||
76 | for (i = 0; i < LENGTH; i++) { | ||
77 | shmaddr[i] = (char)(i); | ||
78 | if (!(i % (1024 * 1024))) | ||
79 | dprintf("."); | ||
80 | } | ||
81 | dprintf("\n"); | ||
82 | |||
83 | dprintf("Starting the Check..."); | ||
84 | for (i = 0; i < LENGTH; i++) | ||
85 | if (shmaddr[i] != (char)i) { | ||
86 | printf("\nIndex %lu mismatched\n", i); | ||
87 | exit(3); | ||
88 | } | ||
89 | dprintf("Done.\n"); | ||
90 | |||
91 | if (shmdt((const void *)shmaddr) != 0) { | ||
92 | perror("Detach failure"); | ||
93 | shmctl(shmid, IPC_RMID, NULL); | ||
94 | exit(4); | ||
95 | } | ||
96 | |||
97 | shmctl(shmid, IPC_RMID, NULL); | ||
98 | |||
99 | return 0; | ||
100 | } | ||
diff --git a/tools/testing/selftests/vm/map_hugetlb.c b/tools/testing/selftests/vm/map_hugetlb.c new file mode 100644 index 000000000000..ac56639dd4a9 --- /dev/null +++ b/tools/testing/selftests/vm/map_hugetlb.c | |||
@@ -0,0 +1,79 @@ | |||
1 | /* | ||
2 | * Example of using hugepage memory in a user application using the mmap | ||
3 | * system call with MAP_HUGETLB flag. Before running this program make | ||
4 | * sure the administrator has allocated enough default sized huge pages | ||
5 | * to cover the 256 MB allocation. | ||
6 | * | ||
7 | * For ia64 architecture, Linux kernel reserves Region number 4 for hugepages. | ||
8 | * That means the addresses starting with 0x800000... will need to be | ||
9 | * specified. Specifying a fixed address is not required on ppc64, i386 | ||
10 | * or x86_64. | ||
11 | */ | ||
12 | #include <stdlib.h> | ||
13 | #include <stdio.h> | ||
14 | #include <unistd.h> | ||
15 | #include <sys/mman.h> | ||
16 | #include <fcntl.h> | ||
17 | |||
18 | #define LENGTH (256UL*1024*1024) | ||
19 | #define PROTECTION (PROT_READ | PROT_WRITE) | ||
20 | |||
21 | #ifndef MAP_HUGETLB | ||
22 | #define MAP_HUGETLB 0x40000 /* arch specific */ | ||
23 | #endif | ||
24 | |||
25 | /* Only ia64 requires this */ | ||
26 | #ifdef __ia64__ | ||
27 | #define ADDR (void *)(0x8000000000000000UL) | ||
28 | #define FLAGS (MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB | MAP_FIXED) | ||
29 | #else | ||
30 | #define ADDR (void *)(0x0UL) | ||
31 | #define FLAGS (MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB) | ||
32 | #endif | ||
33 | |||
34 | static void check_bytes(char *addr) | ||
35 | { | ||
36 | printf("First hex is %x\n", *((unsigned int *)addr)); | ||
37 | } | ||
38 | |||
39 | static void write_bytes(char *addr) | ||
40 | { | ||
41 | unsigned long i; | ||
42 | |||
43 | for (i = 0; i < LENGTH; i++) | ||
44 | *(addr + i) = (char)i; | ||
45 | } | ||
46 | |||
47 | static int read_bytes(char *addr) | ||
48 | { | ||
49 | unsigned long i; | ||
50 | |||
51 | check_bytes(addr); | ||
52 | for (i = 0; i < LENGTH; i++) | ||
53 | if (*(addr + i) != (char)i) { | ||
54 | printf("Mismatch at %lu\n", i); | ||
55 | return 1; | ||
56 | } | ||
57 | return 0; | ||
58 | } | ||
59 | |||
60 | int main(void) | ||
61 | { | ||
62 | void *addr; | ||
63 | int ret; | ||
64 | |||
65 | addr = mmap(ADDR, LENGTH, PROTECTION, FLAGS, 0, 0); | ||
66 | if (addr == MAP_FAILED) { | ||
67 | perror("mmap"); | ||
68 | exit(1); | ||
69 | } | ||
70 | |||
71 | printf("Returned address is %p\n", addr); | ||
72 | check_bytes(addr); | ||
73 | write_bytes(addr); | ||
74 | ret = read_bytes(addr); | ||
75 | |||
76 | munmap(addr, LENGTH); | ||
77 | |||
78 | return ret; | ||
79 | } | ||
diff --git a/tools/testing/selftests/vm/run_vmtests b/tools/testing/selftests/vm/run_vmtests new file mode 100644 index 000000000000..8b40bd5e5cc2 --- /dev/null +++ b/tools/testing/selftests/vm/run_vmtests | |||
@@ -0,0 +1,77 @@ | |||
1 | #!/bin/bash | ||
2 | #please run as root | ||
3 | |||
4 | #we need 256M, below is the size in kB | ||
5 | needmem=262144 | ||
6 | mnt=./huge | ||
7 | |||
8 | #get pagesize and freepages from /proc/meminfo | ||
9 | while read name size unit; do | ||
10 | if [ "$name" = "HugePages_Free:" ]; then | ||
11 | freepgs=$size | ||
12 | fi | ||
13 | if [ "$name" = "Hugepagesize:" ]; then | ||
14 | pgsize=$size | ||
15 | fi | ||
16 | done < /proc/meminfo | ||
17 | |||
18 | #set proper nr_hugepages | ||
19 | if [ -n "$freepgs" ] && [ -n "$pgsize" ]; then | ||
20 | nr_hugepgs=`cat /proc/sys/vm/nr_hugepages` | ||
21 | needpgs=`expr $needmem / $pgsize` | ||
22 | if [ $freepgs -lt $needpgs ]; then | ||
23 | lackpgs=$(( $needpgs - $freepgs )) | ||
24 | echo $(( $lackpgs + $nr_hugepgs )) > /proc/sys/vm/nr_hugepages | ||
25 | if [ $? -ne 0 ]; then | ||
26 | echo "Please run this test as root" | ||
27 | exit 1 | ||
28 | fi | ||
29 | fi | ||
30 | else | ||
31 | echo "no hugetlbfs support in kernel?" | ||
32 | exit 1 | ||
33 | fi | ||
34 | |||
35 | mkdir $mnt | ||
36 | mount -t hugetlbfs none $mnt | ||
37 | |||
38 | echo "--------------------" | ||
39 | echo "runing hugepage-mmap" | ||
40 | echo "--------------------" | ||
41 | ./hugepage-mmap | ||
42 | if [ $? -ne 0 ]; then | ||
43 | echo "[FAIL]" | ||
44 | else | ||
45 | echo "[PASS]" | ||
46 | fi | ||
47 | |||
48 | shmmax=`cat /proc/sys/kernel/shmmax` | ||
49 | shmall=`cat /proc/sys/kernel/shmall` | ||
50 | echo 268435456 > /proc/sys/kernel/shmmax | ||
51 | echo 4194304 > /proc/sys/kernel/shmall | ||
52 | echo "--------------------" | ||
53 | echo "runing hugepage-shm" | ||
54 | echo "--------------------" | ||
55 | ./hugepage-shm | ||
56 | if [ $? -ne 0 ]; then | ||
57 | echo "[FAIL]" | ||
58 | else | ||
59 | echo "[PASS]" | ||
60 | fi | ||
61 | echo $shmmax > /proc/sys/kernel/shmmax | ||
62 | echo $shmall > /proc/sys/kernel/shmall | ||
63 | |||
64 | echo "--------------------" | ||
65 | echo "runing map_hugetlb" | ||
66 | echo "--------------------" | ||
67 | ./map_hugetlb | ||
68 | if [ $? -ne 0 ]; then | ||
69 | echo "[FAIL]" | ||
70 | else | ||
71 | echo "[PASS]" | ||
72 | fi | ||
73 | |||
74 | #cleanup | ||
75 | umount $mnt | ||
76 | rm -rf $mnt | ||
77 | echo $nr_hugepgs > /proc/sys/vm/nr_hugepages | ||
diff --git a/tools/virtio/linux/hrtimer.h b/tools/virtio/linux/hrtimer.h new file mode 100644 index 000000000000..e69de29bb2d1 --- /dev/null +++ b/tools/virtio/linux/hrtimer.h | |||
diff --git a/tools/virtio/linux/module.h b/tools/virtio/linux/module.h new file mode 100644 index 000000000000..e69de29bb2d1 --- /dev/null +++ b/tools/virtio/linux/module.h | |||
diff --git a/tools/virtio/linux/virtio.h b/tools/virtio/linux/virtio.h index b4fbc91c41b4..7579f19e61e0 100644 --- a/tools/virtio/linux/virtio.h +++ b/tools/virtio/linux/virtio.h | |||
@@ -181,6 +181,9 @@ struct virtqueue { | |||
181 | #define smp_mb() mb() | 181 | #define smp_mb() mb() |
182 | # define smp_rmb() barrier() | 182 | # define smp_rmb() barrier() |
183 | # define smp_wmb() barrier() | 183 | # define smp_wmb() barrier() |
184 | /* Weak barriers should be used. If not - it's a bug */ | ||
185 | # define rmb() abort() | ||
186 | # define wmb() abort() | ||
184 | #else | 187 | #else |
185 | #error Please fill in barrier macros | 188 | #error Please fill in barrier macros |
186 | #endif | 189 | #endif |
diff --git a/tools/vm/Makefile b/tools/vm/Makefile new file mode 100644 index 000000000000..8e30e5c40f8a --- /dev/null +++ b/tools/vm/Makefile | |||
@@ -0,0 +1,11 @@ | |||
1 | # Makefile for vm tools | ||
2 | |||
3 | CC = $(CROSS_COMPILE)gcc | ||
4 | CFLAGS = -Wall -Wextra | ||
5 | |||
6 | all: page-types slabinfo | ||
7 | %: %.c | ||
8 | $(CC) $(CFLAGS) -o $@ $^ | ||
9 | |||
10 | clean: | ||
11 | $(RM) page-types slabinfo | ||
diff --git a/tools/vm/page-types.c b/tools/vm/page-types.c new file mode 100644 index 000000000000..7dab7b25b5c6 --- /dev/null +++ b/tools/vm/page-types.c | |||
@@ -0,0 +1,1102 @@ | |||
1 | /* | ||
2 | * page-types: Tool for querying page flags | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | ||
5 | * under the terms of the GNU General Public License as published by the Free | ||
6 | * Software Foundation; version 2. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
11 | * more details. | ||
12 | * | ||
13 | * You should find a copy of v2 of the GNU General Public License somewhere on | ||
14 | * your Linux system; if not, write to the Free Software Foundation, Inc., 59 | ||
15 | * Temple Place, Suite 330, Boston, MA 02111-1307 USA. | ||
16 | * | ||
17 | * Copyright (C) 2009 Intel corporation | ||
18 | * | ||
19 | * Authors: Wu Fengguang <fengguang.wu@intel.com> | ||
20 | */ | ||
21 | |||
22 | #define _LARGEFILE64_SOURCE | ||
23 | #include <stdio.h> | ||
24 | #include <stdlib.h> | ||
25 | #include <unistd.h> | ||
26 | #include <stdint.h> | ||
27 | #include <stdarg.h> | ||
28 | #include <string.h> | ||
29 | #include <getopt.h> | ||
30 | #include <limits.h> | ||
31 | #include <assert.h> | ||
32 | #include <sys/types.h> | ||
33 | #include <sys/errno.h> | ||
34 | #include <sys/fcntl.h> | ||
35 | #include <sys/mount.h> | ||
36 | #include <sys/statfs.h> | ||
37 | #include "../../include/linux/magic.h" | ||
38 | |||
39 | |||
40 | #ifndef MAX_PATH | ||
41 | # define MAX_PATH 256 | ||
42 | #endif | ||
43 | |||
44 | #ifndef STR | ||
45 | # define _STR(x) #x | ||
46 | # define STR(x) _STR(x) | ||
47 | #endif | ||
48 | |||
49 | /* | ||
50 | * pagemap kernel ABI bits | ||
51 | */ | ||
52 | |||
53 | #define PM_ENTRY_BYTES sizeof(uint64_t) | ||
54 | #define PM_STATUS_BITS 3 | ||
55 | #define PM_STATUS_OFFSET (64 - PM_STATUS_BITS) | ||
56 | #define PM_STATUS_MASK (((1LL << PM_STATUS_BITS) - 1) << PM_STATUS_OFFSET) | ||
57 | #define PM_STATUS(nr) (((nr) << PM_STATUS_OFFSET) & PM_STATUS_MASK) | ||
58 | #define PM_PSHIFT_BITS 6 | ||
59 | #define PM_PSHIFT_OFFSET (PM_STATUS_OFFSET - PM_PSHIFT_BITS) | ||
60 | #define PM_PSHIFT_MASK (((1LL << PM_PSHIFT_BITS) - 1) << PM_PSHIFT_OFFSET) | ||
61 | #define PM_PSHIFT(x) (((u64) (x) << PM_PSHIFT_OFFSET) & PM_PSHIFT_MASK) | ||
62 | #define PM_PFRAME_MASK ((1LL << PM_PSHIFT_OFFSET) - 1) | ||
63 | #define PM_PFRAME(x) ((x) & PM_PFRAME_MASK) | ||
64 | |||
65 | #define PM_PRESENT PM_STATUS(4LL) | ||
66 | #define PM_SWAP PM_STATUS(2LL) | ||
67 | |||
68 | |||
69 | /* | ||
70 | * kernel page flags | ||
71 | */ | ||
72 | |||
73 | #define KPF_BYTES 8 | ||
74 | #define PROC_KPAGEFLAGS "/proc/kpageflags" | ||
75 | |||
76 | /* copied from kpageflags_read() */ | ||
77 | #define KPF_LOCKED 0 | ||
78 | #define KPF_ERROR 1 | ||
79 | #define KPF_REFERENCED 2 | ||
80 | #define KPF_UPTODATE 3 | ||
81 | #define KPF_DIRTY 4 | ||
82 | #define KPF_LRU 5 | ||
83 | #define KPF_ACTIVE 6 | ||
84 | #define KPF_SLAB 7 | ||
85 | #define KPF_WRITEBACK 8 | ||
86 | #define KPF_RECLAIM 9 | ||
87 | #define KPF_BUDDY 10 | ||
88 | |||
89 | /* [11-20] new additions in 2.6.31 */ | ||
90 | #define KPF_MMAP 11 | ||
91 | #define KPF_ANON 12 | ||
92 | #define KPF_SWAPCACHE 13 | ||
93 | #define KPF_SWAPBACKED 14 | ||
94 | #define KPF_COMPOUND_HEAD 15 | ||
95 | #define KPF_COMPOUND_TAIL 16 | ||
96 | #define KPF_HUGE 17 | ||
97 | #define KPF_UNEVICTABLE 18 | ||
98 | #define KPF_HWPOISON 19 | ||
99 | #define KPF_NOPAGE 20 | ||
100 | #define KPF_KSM 21 | ||
101 | #define KPF_THP 22 | ||
102 | |||
103 | /* [32-] kernel hacking assistances */ | ||
104 | #define KPF_RESERVED 32 | ||
105 | #define KPF_MLOCKED 33 | ||
106 | #define KPF_MAPPEDTODISK 34 | ||
107 | #define KPF_PRIVATE 35 | ||
108 | #define KPF_PRIVATE_2 36 | ||
109 | #define KPF_OWNER_PRIVATE 37 | ||
110 | #define KPF_ARCH 38 | ||
111 | #define KPF_UNCACHED 39 | ||
112 | |||
113 | /* [48-] take some arbitrary free slots for expanding overloaded flags | ||
114 | * not part of kernel API | ||
115 | */ | ||
116 | #define KPF_READAHEAD 48 | ||
117 | #define KPF_SLOB_FREE 49 | ||
118 | #define KPF_SLUB_FROZEN 50 | ||
119 | #define KPF_SLUB_DEBUG 51 | ||
120 | |||
121 | #define KPF_ALL_BITS ((uint64_t)~0ULL) | ||
122 | #define KPF_HACKERS_BITS (0xffffULL << 32) | ||
123 | #define KPF_OVERLOADED_BITS (0xffffULL << 48) | ||
124 | #define BIT(name) (1ULL << KPF_##name) | ||
125 | #define BITS_COMPOUND (BIT(COMPOUND_HEAD) | BIT(COMPOUND_TAIL)) | ||
126 | |||
127 | static const char * const page_flag_names[] = { | ||
128 | [KPF_LOCKED] = "L:locked", | ||
129 | [KPF_ERROR] = "E:error", | ||
130 | [KPF_REFERENCED] = "R:referenced", | ||
131 | [KPF_UPTODATE] = "U:uptodate", | ||
132 | [KPF_DIRTY] = "D:dirty", | ||
133 | [KPF_LRU] = "l:lru", | ||
134 | [KPF_ACTIVE] = "A:active", | ||
135 | [KPF_SLAB] = "S:slab", | ||
136 | [KPF_WRITEBACK] = "W:writeback", | ||
137 | [KPF_RECLAIM] = "I:reclaim", | ||
138 | [KPF_BUDDY] = "B:buddy", | ||
139 | |||
140 | [KPF_MMAP] = "M:mmap", | ||
141 | [KPF_ANON] = "a:anonymous", | ||
142 | [KPF_SWAPCACHE] = "s:swapcache", | ||
143 | [KPF_SWAPBACKED] = "b:swapbacked", | ||
144 | [KPF_COMPOUND_HEAD] = "H:compound_head", | ||
145 | [KPF_COMPOUND_TAIL] = "T:compound_tail", | ||
146 | [KPF_HUGE] = "G:huge", | ||
147 | [KPF_UNEVICTABLE] = "u:unevictable", | ||
148 | [KPF_HWPOISON] = "X:hwpoison", | ||
149 | [KPF_NOPAGE] = "n:nopage", | ||
150 | [KPF_KSM] = "x:ksm", | ||
151 | [KPF_THP] = "t:thp", | ||
152 | |||
153 | [KPF_RESERVED] = "r:reserved", | ||
154 | [KPF_MLOCKED] = "m:mlocked", | ||
155 | [KPF_MAPPEDTODISK] = "d:mappedtodisk", | ||
156 | [KPF_PRIVATE] = "P:private", | ||
157 | [KPF_PRIVATE_2] = "p:private_2", | ||
158 | [KPF_OWNER_PRIVATE] = "O:owner_private", | ||
159 | [KPF_ARCH] = "h:arch", | ||
160 | [KPF_UNCACHED] = "c:uncached", | ||
161 | |||
162 | [KPF_READAHEAD] = "I:readahead", | ||
163 | [KPF_SLOB_FREE] = "P:slob_free", | ||
164 | [KPF_SLUB_FROZEN] = "A:slub_frozen", | ||
165 | [KPF_SLUB_DEBUG] = "E:slub_debug", | ||
166 | }; | ||
167 | |||
168 | |||
169 | static const char * const debugfs_known_mountpoints[] = { | ||
170 | "/sys/kernel/debug", | ||
171 | "/debug", | ||
172 | 0, | ||
173 | }; | ||
174 | |||
175 | /* | ||
176 | * data structures | ||
177 | */ | ||
178 | |||
179 | static int opt_raw; /* for kernel developers */ | ||
180 | static int opt_list; /* list pages (in ranges) */ | ||
181 | static int opt_no_summary; /* don't show summary */ | ||
182 | static pid_t opt_pid; /* process to walk */ | ||
183 | |||
184 | #define MAX_ADDR_RANGES 1024 | ||
185 | static int nr_addr_ranges; | ||
186 | static unsigned long opt_offset[MAX_ADDR_RANGES]; | ||
187 | static unsigned long opt_size[MAX_ADDR_RANGES]; | ||
188 | |||
189 | #define MAX_VMAS 10240 | ||
190 | static int nr_vmas; | ||
191 | static unsigned long pg_start[MAX_VMAS]; | ||
192 | static unsigned long pg_end[MAX_VMAS]; | ||
193 | |||
194 | #define MAX_BIT_FILTERS 64 | ||
195 | static int nr_bit_filters; | ||
196 | static uint64_t opt_mask[MAX_BIT_FILTERS]; | ||
197 | static uint64_t opt_bits[MAX_BIT_FILTERS]; | ||
198 | |||
199 | static int page_size; | ||
200 | |||
201 | static int pagemap_fd; | ||
202 | static int kpageflags_fd; | ||
203 | |||
204 | static int opt_hwpoison; | ||
205 | static int opt_unpoison; | ||
206 | |||
207 | static char hwpoison_debug_fs[MAX_PATH+1]; | ||
208 | static int hwpoison_inject_fd; | ||
209 | static int hwpoison_forget_fd; | ||
210 | |||
211 | #define HASH_SHIFT 13 | ||
212 | #define HASH_SIZE (1 << HASH_SHIFT) | ||
213 | #define HASH_MASK (HASH_SIZE - 1) | ||
214 | #define HASH_KEY(flags) (flags & HASH_MASK) | ||
215 | |||
216 | static unsigned long total_pages; | ||
217 | static unsigned long nr_pages[HASH_SIZE]; | ||
218 | static uint64_t page_flags[HASH_SIZE]; | ||
219 | |||
220 | |||
221 | /* | ||
222 | * helper functions | ||
223 | */ | ||
224 | |||
225 | #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) | ||
226 | |||
227 | #define min_t(type, x, y) ({ \ | ||
228 | type __min1 = (x); \ | ||
229 | type __min2 = (y); \ | ||
230 | __min1 < __min2 ? __min1 : __min2; }) | ||
231 | |||
232 | #define max_t(type, x, y) ({ \ | ||
233 | type __max1 = (x); \ | ||
234 | type __max2 = (y); \ | ||
235 | __max1 > __max2 ? __max1 : __max2; }) | ||
236 | |||
237 | static unsigned long pages2mb(unsigned long pages) | ||
238 | { | ||
239 | return (pages * page_size) >> 20; | ||
240 | } | ||
241 | |||
242 | static void fatal(const char *x, ...) | ||
243 | { | ||
244 | va_list ap; | ||
245 | |||
246 | va_start(ap, x); | ||
247 | vfprintf(stderr, x, ap); | ||
248 | va_end(ap); | ||
249 | exit(EXIT_FAILURE); | ||
250 | } | ||
251 | |||
252 | static int checked_open(const char *pathname, int flags) | ||
253 | { | ||
254 | int fd = open(pathname, flags); | ||
255 | |||
256 | if (fd < 0) { | ||
257 | perror(pathname); | ||
258 | exit(EXIT_FAILURE); | ||
259 | } | ||
260 | |||
261 | return fd; | ||
262 | } | ||
263 | |||
264 | /* | ||
265 | * pagemap/kpageflags routines | ||
266 | */ | ||
267 | |||
268 | static unsigned long do_u64_read(int fd, char *name, | ||
269 | uint64_t *buf, | ||
270 | unsigned long index, | ||
271 | unsigned long count) | ||
272 | { | ||
273 | long bytes; | ||
274 | |||
275 | if (index > ULONG_MAX / 8) | ||
276 | fatal("index overflow: %lu\n", index); | ||
277 | |||
278 | if (lseek(fd, index * 8, SEEK_SET) < 0) { | ||
279 | perror(name); | ||
280 | exit(EXIT_FAILURE); | ||
281 | } | ||
282 | |||
283 | bytes = read(fd, buf, count * 8); | ||
284 | if (bytes < 0) { | ||
285 | perror(name); | ||
286 | exit(EXIT_FAILURE); | ||
287 | } | ||
288 | if (bytes % 8) | ||
289 | fatal("partial read: %lu bytes\n", bytes); | ||
290 | |||
291 | return bytes / 8; | ||
292 | } | ||
293 | |||
294 | static unsigned long kpageflags_read(uint64_t *buf, | ||
295 | unsigned long index, | ||
296 | unsigned long pages) | ||
297 | { | ||
298 | return do_u64_read(kpageflags_fd, PROC_KPAGEFLAGS, buf, index, pages); | ||
299 | } | ||
300 | |||
301 | static unsigned long pagemap_read(uint64_t *buf, | ||
302 | unsigned long index, | ||
303 | unsigned long pages) | ||
304 | { | ||
305 | return do_u64_read(pagemap_fd, "/proc/pid/pagemap", buf, index, pages); | ||
306 | } | ||
307 | |||
308 | static unsigned long pagemap_pfn(uint64_t val) | ||
309 | { | ||
310 | unsigned long pfn; | ||
311 | |||
312 | if (val & PM_PRESENT) | ||
313 | pfn = PM_PFRAME(val); | ||
314 | else | ||
315 | pfn = 0; | ||
316 | |||
317 | return pfn; | ||
318 | } | ||
319 | |||
320 | |||
321 | /* | ||
322 | * page flag names | ||
323 | */ | ||
324 | |||
325 | static char *page_flag_name(uint64_t flags) | ||
326 | { | ||
327 | static char buf[65]; | ||
328 | int present; | ||
329 | int i, j; | ||
330 | |||
331 | for (i = 0, j = 0; i < ARRAY_SIZE(page_flag_names); i++) { | ||
332 | present = (flags >> i) & 1; | ||
333 | if (!page_flag_names[i]) { | ||
334 | if (present) | ||
335 | fatal("unknown flag bit %d\n", i); | ||
336 | continue; | ||
337 | } | ||
338 | buf[j++] = present ? page_flag_names[i][0] : '_'; | ||
339 | } | ||
340 | |||
341 | return buf; | ||
342 | } | ||
343 | |||
344 | static char *page_flag_longname(uint64_t flags) | ||
345 | { | ||
346 | static char buf[1024]; | ||
347 | int i, n; | ||
348 | |||
349 | for (i = 0, n = 0; i < ARRAY_SIZE(page_flag_names); i++) { | ||
350 | if (!page_flag_names[i]) | ||
351 | continue; | ||
352 | if ((flags >> i) & 1) | ||
353 | n += snprintf(buf + n, sizeof(buf) - n, "%s,", | ||
354 | page_flag_names[i] + 2); | ||
355 | } | ||
356 | if (n) | ||
357 | n--; | ||
358 | buf[n] = '\0'; | ||
359 | |||
360 | return buf; | ||
361 | } | ||
362 | |||
363 | |||
364 | /* | ||
365 | * page list and summary | ||
366 | */ | ||
367 | |||
368 | static void show_page_range(unsigned long voffset, | ||
369 | unsigned long offset, uint64_t flags) | ||
370 | { | ||
371 | static uint64_t flags0; | ||
372 | static unsigned long voff; | ||
373 | static unsigned long index; | ||
374 | static unsigned long count; | ||
375 | |||
376 | if (flags == flags0 && offset == index + count && | ||
377 | (!opt_pid || voffset == voff + count)) { | ||
378 | count++; | ||
379 | return; | ||
380 | } | ||
381 | |||
382 | if (count) { | ||
383 | if (opt_pid) | ||
384 | printf("%lx\t", voff); | ||
385 | printf("%lx\t%lx\t%s\n", | ||
386 | index, count, page_flag_name(flags0)); | ||
387 | } | ||
388 | |||
389 | flags0 = flags; | ||
390 | index = offset; | ||
391 | voff = voffset; | ||
392 | count = 1; | ||
393 | } | ||
394 | |||
395 | static void show_page(unsigned long voffset, | ||
396 | unsigned long offset, uint64_t flags) | ||
397 | { | ||
398 | if (opt_pid) | ||
399 | printf("%lx\t", voffset); | ||
400 | printf("%lx\t%s\n", offset, page_flag_name(flags)); | ||
401 | } | ||
402 | |||
403 | static void show_summary(void) | ||
404 | { | ||
405 | int i; | ||
406 | |||
407 | printf(" flags\tpage-count MB" | ||
408 | " symbolic-flags\t\t\tlong-symbolic-flags\n"); | ||
409 | |||
410 | for (i = 0; i < ARRAY_SIZE(nr_pages); i++) { | ||
411 | if (nr_pages[i]) | ||
412 | printf("0x%016llx\t%10lu %8lu %s\t%s\n", | ||
413 | (unsigned long long)page_flags[i], | ||
414 | nr_pages[i], | ||
415 | pages2mb(nr_pages[i]), | ||
416 | page_flag_name(page_flags[i]), | ||
417 | page_flag_longname(page_flags[i])); | ||
418 | } | ||
419 | |||
420 | printf(" total\t%10lu %8lu\n", | ||
421 | total_pages, pages2mb(total_pages)); | ||
422 | } | ||
423 | |||
424 | |||
425 | /* | ||
426 | * page flag filters | ||
427 | */ | ||
428 | |||
429 | static int bit_mask_ok(uint64_t flags) | ||
430 | { | ||
431 | int i; | ||
432 | |||
433 | for (i = 0; i < nr_bit_filters; i++) { | ||
434 | if (opt_bits[i] == KPF_ALL_BITS) { | ||
435 | if ((flags & opt_mask[i]) == 0) | ||
436 | return 0; | ||
437 | } else { | ||
438 | if ((flags & opt_mask[i]) != opt_bits[i]) | ||
439 | return 0; | ||
440 | } | ||
441 | } | ||
442 | |||
443 | return 1; | ||
444 | } | ||
445 | |||
446 | static uint64_t expand_overloaded_flags(uint64_t flags) | ||
447 | { | ||
448 | /* SLOB/SLUB overload several page flags */ | ||
449 | if (flags & BIT(SLAB)) { | ||
450 | if (flags & BIT(PRIVATE)) | ||
451 | flags ^= BIT(PRIVATE) | BIT(SLOB_FREE); | ||
452 | if (flags & BIT(ACTIVE)) | ||
453 | flags ^= BIT(ACTIVE) | BIT(SLUB_FROZEN); | ||
454 | if (flags & BIT(ERROR)) | ||
455 | flags ^= BIT(ERROR) | BIT(SLUB_DEBUG); | ||
456 | } | ||
457 | |||
458 | /* PG_reclaim is overloaded as PG_readahead in the read path */ | ||
459 | if ((flags & (BIT(RECLAIM) | BIT(WRITEBACK))) == BIT(RECLAIM)) | ||
460 | flags ^= BIT(RECLAIM) | BIT(READAHEAD); | ||
461 | |||
462 | return flags; | ||
463 | } | ||
464 | |||
465 | static uint64_t well_known_flags(uint64_t flags) | ||
466 | { | ||
467 | /* hide flags intended only for kernel hacker */ | ||
468 | flags &= ~KPF_HACKERS_BITS; | ||
469 | |||
470 | /* hide non-hugeTLB compound pages */ | ||
471 | if ((flags & BITS_COMPOUND) && !(flags & BIT(HUGE))) | ||
472 | flags &= ~BITS_COMPOUND; | ||
473 | |||
474 | return flags; | ||
475 | } | ||
476 | |||
477 | static uint64_t kpageflags_flags(uint64_t flags) | ||
478 | { | ||
479 | flags = expand_overloaded_flags(flags); | ||
480 | |||
481 | if (!opt_raw) | ||
482 | flags = well_known_flags(flags); | ||
483 | |||
484 | return flags; | ||
485 | } | ||
486 | |||
487 | /* verify that a mountpoint is actually a debugfs instance */ | ||
488 | static int debugfs_valid_mountpoint(const char *debugfs) | ||
489 | { | ||
490 | struct statfs st_fs; | ||
491 | |||
492 | if (statfs(debugfs, &st_fs) < 0) | ||
493 | return -ENOENT; | ||
494 | else if (st_fs.f_type != (long) DEBUGFS_MAGIC) | ||
495 | return -ENOENT; | ||
496 | |||
497 | return 0; | ||
498 | } | ||
499 | |||
500 | /* find the path to the mounted debugfs */ | ||
501 | static const char *debugfs_find_mountpoint(void) | ||
502 | { | ||
503 | const char **ptr; | ||
504 | char type[100]; | ||
505 | FILE *fp; | ||
506 | |||
507 | ptr = debugfs_known_mountpoints; | ||
508 | while (*ptr) { | ||
509 | if (debugfs_valid_mountpoint(*ptr) == 0) { | ||
510 | strcpy(hwpoison_debug_fs, *ptr); | ||
511 | return hwpoison_debug_fs; | ||
512 | } | ||
513 | ptr++; | ||
514 | } | ||
515 | |||
516 | /* give up and parse /proc/mounts */ | ||
517 | fp = fopen("/proc/mounts", "r"); | ||
518 | if (fp == NULL) | ||
519 | perror("Can't open /proc/mounts for read"); | ||
520 | |||
521 | while (fscanf(fp, "%*s %" | ||
522 | STR(MAX_PATH) | ||
523 | "s %99s %*s %*d %*d\n", | ||
524 | hwpoison_debug_fs, type) == 2) { | ||
525 | if (strcmp(type, "debugfs") == 0) | ||
526 | break; | ||
527 | } | ||
528 | fclose(fp); | ||
529 | |||
530 | if (strcmp(type, "debugfs") != 0) | ||
531 | return NULL; | ||
532 | |||
533 | return hwpoison_debug_fs; | ||
534 | } | ||
535 | |||
536 | /* mount the debugfs somewhere if it's not mounted */ | ||
537 | |||
538 | static void debugfs_mount(void) | ||
539 | { | ||
540 | const char **ptr; | ||
541 | |||
542 | /* see if it's already mounted */ | ||
543 | if (debugfs_find_mountpoint()) | ||
544 | return; | ||
545 | |||
546 | ptr = debugfs_known_mountpoints; | ||
547 | while (*ptr) { | ||
548 | if (mount(NULL, *ptr, "debugfs", 0, NULL) == 0) { | ||
549 | /* save the mountpoint */ | ||
550 | strcpy(hwpoison_debug_fs, *ptr); | ||
551 | break; | ||
552 | } | ||
553 | ptr++; | ||
554 | } | ||
555 | |||
556 | if (*ptr == NULL) { | ||
557 | perror("mount debugfs"); | ||
558 | exit(EXIT_FAILURE); | ||
559 | } | ||
560 | } | ||
561 | |||
562 | /* | ||
563 | * page actions | ||
564 | */ | ||
565 | |||
566 | static void prepare_hwpoison_fd(void) | ||
567 | { | ||
568 | char buf[MAX_PATH + 1]; | ||
569 | |||
570 | debugfs_mount(); | ||
571 | |||
572 | if (opt_hwpoison && !hwpoison_inject_fd) { | ||
573 | snprintf(buf, MAX_PATH, "%s/hwpoison/corrupt-pfn", | ||
574 | hwpoison_debug_fs); | ||
575 | hwpoison_inject_fd = checked_open(buf, O_WRONLY); | ||
576 | } | ||
577 | |||
578 | if (opt_unpoison && !hwpoison_forget_fd) { | ||
579 | snprintf(buf, MAX_PATH, "%s/hwpoison/unpoison-pfn", | ||
580 | hwpoison_debug_fs); | ||
581 | hwpoison_forget_fd = checked_open(buf, O_WRONLY); | ||
582 | } | ||
583 | } | ||
584 | |||
585 | static int hwpoison_page(unsigned long offset) | ||
586 | { | ||
587 | char buf[100]; | ||
588 | int len; | ||
589 | |||
590 | len = sprintf(buf, "0x%lx\n", offset); | ||
591 | len = write(hwpoison_inject_fd, buf, len); | ||
592 | if (len < 0) { | ||
593 | perror("hwpoison inject"); | ||
594 | return len; | ||
595 | } | ||
596 | return 0; | ||
597 | } | ||
598 | |||
599 | static int unpoison_page(unsigned long offset) | ||
600 | { | ||
601 | char buf[100]; | ||
602 | int len; | ||
603 | |||
604 | len = sprintf(buf, "0x%lx\n", offset); | ||
605 | len = write(hwpoison_forget_fd, buf, len); | ||
606 | if (len < 0) { | ||
607 | perror("hwpoison forget"); | ||
608 | return len; | ||
609 | } | ||
610 | return 0; | ||
611 | } | ||
612 | |||
613 | /* | ||
614 | * page frame walker | ||
615 | */ | ||
616 | |||
617 | static int hash_slot(uint64_t flags) | ||
618 | { | ||
619 | int k = HASH_KEY(flags); | ||
620 | int i; | ||
621 | |||
622 | /* Explicitly reserve slot 0 for flags 0: the following logic | ||
623 | * cannot distinguish an unoccupied slot from slot (flags==0). | ||
624 | */ | ||
625 | if (flags == 0) | ||
626 | return 0; | ||
627 | |||
628 | /* search through the remaining (HASH_SIZE-1) slots */ | ||
629 | for (i = 1; i < ARRAY_SIZE(page_flags); i++, k++) { | ||
630 | if (!k || k >= ARRAY_SIZE(page_flags)) | ||
631 | k = 1; | ||
632 | if (page_flags[k] == 0) { | ||
633 | page_flags[k] = flags; | ||
634 | return k; | ||
635 | } | ||
636 | if (page_flags[k] == flags) | ||
637 | return k; | ||
638 | } | ||
639 | |||
640 | fatal("hash table full: bump up HASH_SHIFT?\n"); | ||
641 | exit(EXIT_FAILURE); | ||
642 | } | ||
643 | |||
644 | static void add_page(unsigned long voffset, | ||
645 | unsigned long offset, uint64_t flags) | ||
646 | { | ||
647 | flags = kpageflags_flags(flags); | ||
648 | |||
649 | if (!bit_mask_ok(flags)) | ||
650 | return; | ||
651 | |||
652 | if (opt_hwpoison) | ||
653 | hwpoison_page(offset); | ||
654 | if (opt_unpoison) | ||
655 | unpoison_page(offset); | ||
656 | |||
657 | if (opt_list == 1) | ||
658 | show_page_range(voffset, offset, flags); | ||
659 | else if (opt_list == 2) | ||
660 | show_page(voffset, offset, flags); | ||
661 | |||
662 | nr_pages[hash_slot(flags)]++; | ||
663 | total_pages++; | ||
664 | } | ||
665 | |||
666 | #define KPAGEFLAGS_BATCH (64 << 10) /* 64k pages */ | ||
667 | static void walk_pfn(unsigned long voffset, | ||
668 | unsigned long index, | ||
669 | unsigned long count) | ||
670 | { | ||
671 | uint64_t buf[KPAGEFLAGS_BATCH]; | ||
672 | unsigned long batch; | ||
673 | long pages; | ||
674 | unsigned long i; | ||
675 | |||
676 | while (count) { | ||
677 | batch = min_t(unsigned long, count, KPAGEFLAGS_BATCH); | ||
678 | pages = kpageflags_read(buf, index, batch); | ||
679 | if (pages == 0) | ||
680 | break; | ||
681 | |||
682 | for (i = 0; i < pages; i++) | ||
683 | add_page(voffset + i, index + i, buf[i]); | ||
684 | |||
685 | index += pages; | ||
686 | count -= pages; | ||
687 | } | ||
688 | } | ||
689 | |||
690 | #define PAGEMAP_BATCH (64 << 10) | ||
691 | static void walk_vma(unsigned long index, unsigned long count) | ||
692 | { | ||
693 | uint64_t buf[PAGEMAP_BATCH]; | ||
694 | unsigned long batch; | ||
695 | unsigned long pages; | ||
696 | unsigned long pfn; | ||
697 | unsigned long i; | ||
698 | |||
699 | while (count) { | ||
700 | batch = min_t(unsigned long, count, PAGEMAP_BATCH); | ||
701 | pages = pagemap_read(buf, index, batch); | ||
702 | if (pages == 0) | ||
703 | break; | ||
704 | |||
705 | for (i = 0; i < pages; i++) { | ||
706 | pfn = pagemap_pfn(buf[i]); | ||
707 | if (pfn) | ||
708 | walk_pfn(index + i, pfn, 1); | ||
709 | } | ||
710 | |||
711 | index += pages; | ||
712 | count -= pages; | ||
713 | } | ||
714 | } | ||
715 | |||
716 | static void walk_task(unsigned long index, unsigned long count) | ||
717 | { | ||
718 | const unsigned long end = index + count; | ||
719 | unsigned long start; | ||
720 | int i = 0; | ||
721 | |||
722 | while (index < end) { | ||
723 | |||
724 | while (pg_end[i] <= index) | ||
725 | if (++i >= nr_vmas) | ||
726 | return; | ||
727 | if (pg_start[i] >= end) | ||
728 | return; | ||
729 | |||
730 | start = max_t(unsigned long, pg_start[i], index); | ||
731 | index = min_t(unsigned long, pg_end[i], end); | ||
732 | |||
733 | assert(start < index); | ||
734 | walk_vma(start, index - start); | ||
735 | } | ||
736 | } | ||
737 | |||
738 | static void add_addr_range(unsigned long offset, unsigned long size) | ||
739 | { | ||
740 | if (nr_addr_ranges >= MAX_ADDR_RANGES) | ||
741 | fatal("too many addr ranges\n"); | ||
742 | |||
743 | opt_offset[nr_addr_ranges] = offset; | ||
744 | opt_size[nr_addr_ranges] = min_t(unsigned long, size, ULONG_MAX-offset); | ||
745 | nr_addr_ranges++; | ||
746 | } | ||
747 | |||
748 | static void walk_addr_ranges(void) | ||
749 | { | ||
750 | int i; | ||
751 | |||
752 | kpageflags_fd = checked_open(PROC_KPAGEFLAGS, O_RDONLY); | ||
753 | |||
754 | if (!nr_addr_ranges) | ||
755 | add_addr_range(0, ULONG_MAX); | ||
756 | |||
757 | for (i = 0; i < nr_addr_ranges; i++) | ||
758 | if (!opt_pid) | ||
759 | walk_pfn(0, opt_offset[i], opt_size[i]); | ||
760 | else | ||
761 | walk_task(opt_offset[i], opt_size[i]); | ||
762 | |||
763 | close(kpageflags_fd); | ||
764 | } | ||
765 | |||
766 | |||
767 | /* | ||
768 | * user interface | ||
769 | */ | ||
770 | |||
771 | static const char *page_flag_type(uint64_t flag) | ||
772 | { | ||
773 | if (flag & KPF_HACKERS_BITS) | ||
774 | return "(r)"; | ||
775 | if (flag & KPF_OVERLOADED_BITS) | ||
776 | return "(o)"; | ||
777 | return " "; | ||
778 | } | ||
779 | |||
780 | static void usage(void) | ||
781 | { | ||
782 | int i, j; | ||
783 | |||
784 | printf( | ||
785 | "page-types [options]\n" | ||
786 | " -r|--raw Raw mode, for kernel developers\n" | ||
787 | " -d|--describe flags Describe flags\n" | ||
788 | " -a|--addr addr-spec Walk a range of pages\n" | ||
789 | " -b|--bits bits-spec Walk pages with specified bits\n" | ||
790 | " -p|--pid pid Walk process address space\n" | ||
791 | #if 0 /* planned features */ | ||
792 | " -f|--file filename Walk file address space\n" | ||
793 | #endif | ||
794 | " -l|--list Show page details in ranges\n" | ||
795 | " -L|--list-each Show page details one by one\n" | ||
796 | " -N|--no-summary Don't show summary info\n" | ||
797 | " -X|--hwpoison hwpoison pages\n" | ||
798 | " -x|--unpoison unpoison pages\n" | ||
799 | " -h|--help Show this usage message\n" | ||
800 | "flags:\n" | ||
801 | " 0x10 bitfield format, e.g.\n" | ||
802 | " anon bit-name, e.g.\n" | ||
803 | " 0x10,anon comma-separated list, e.g.\n" | ||
804 | "addr-spec:\n" | ||
805 | " N one page at offset N (unit: pages)\n" | ||
806 | " N+M pages range from N to N+M-1\n" | ||
807 | " N,M pages range from N to M-1\n" | ||
808 | " N, pages range from N to end\n" | ||
809 | " ,M pages range from 0 to M-1\n" | ||
810 | "bits-spec:\n" | ||
811 | " bit1,bit2 (flags & (bit1|bit2)) != 0\n" | ||
812 | " bit1,bit2=bit1 (flags & (bit1|bit2)) == bit1\n" | ||
813 | " bit1,~bit2 (flags & (bit1|bit2)) == bit1\n" | ||
814 | " =bit1,bit2 flags == (bit1|bit2)\n" | ||
815 | "bit-names:\n" | ||
816 | ); | ||
817 | |||
818 | for (i = 0, j = 0; i < ARRAY_SIZE(page_flag_names); i++) { | ||
819 | if (!page_flag_names[i]) | ||
820 | continue; | ||
821 | printf("%16s%s", page_flag_names[i] + 2, | ||
822 | page_flag_type(1ULL << i)); | ||
823 | if (++j > 3) { | ||
824 | j = 0; | ||
825 | putchar('\n'); | ||
826 | } | ||
827 | } | ||
828 | printf("\n " | ||
829 | "(r) raw mode bits (o) overloaded bits\n"); | ||
830 | } | ||
831 | |||
832 | static unsigned long long parse_number(const char *str) | ||
833 | { | ||
834 | unsigned long long n; | ||
835 | |||
836 | n = strtoll(str, NULL, 0); | ||
837 | |||
838 | if (n == 0 && str[0] != '0') | ||
839 | fatal("invalid name or number: %s\n", str); | ||
840 | |||
841 | return n; | ||
842 | } | ||
843 | |||
844 | static void parse_pid(const char *str) | ||
845 | { | ||
846 | FILE *file; | ||
847 | char buf[5000]; | ||
848 | |||
849 | opt_pid = parse_number(str); | ||
850 | |||
851 | sprintf(buf, "/proc/%d/pagemap", opt_pid); | ||
852 | pagemap_fd = checked_open(buf, O_RDONLY); | ||
853 | |||
854 | sprintf(buf, "/proc/%d/maps", opt_pid); | ||
855 | file = fopen(buf, "r"); | ||
856 | if (!file) { | ||
857 | perror(buf); | ||
858 | exit(EXIT_FAILURE); | ||
859 | } | ||
860 | |||
861 | while (fgets(buf, sizeof(buf), file) != NULL) { | ||
862 | unsigned long vm_start; | ||
863 | unsigned long vm_end; | ||
864 | unsigned long long pgoff; | ||
865 | int major, minor; | ||
866 | char r, w, x, s; | ||
867 | unsigned long ino; | ||
868 | int n; | ||
869 | |||
870 | n = sscanf(buf, "%lx-%lx %c%c%c%c %llx %x:%x %lu", | ||
871 | &vm_start, | ||
872 | &vm_end, | ||
873 | &r, &w, &x, &s, | ||
874 | &pgoff, | ||
875 | &major, &minor, | ||
876 | &ino); | ||
877 | if (n < 10) { | ||
878 | fprintf(stderr, "unexpected line: %s\n", buf); | ||
879 | continue; | ||
880 | } | ||
881 | pg_start[nr_vmas] = vm_start / page_size; | ||
882 | pg_end[nr_vmas] = vm_end / page_size; | ||
883 | if (++nr_vmas >= MAX_VMAS) { | ||
884 | fprintf(stderr, "too many VMAs\n"); | ||
885 | break; | ||
886 | } | ||
887 | } | ||
888 | fclose(file); | ||
889 | } | ||
890 | |||
891 | static void parse_file(const char *name) | ||
892 | { | ||
893 | } | ||
894 | |||
895 | static void parse_addr_range(const char *optarg) | ||
896 | { | ||
897 | unsigned long offset; | ||
898 | unsigned long size; | ||
899 | char *p; | ||
900 | |||
901 | p = strchr(optarg, ','); | ||
902 | if (!p) | ||
903 | p = strchr(optarg, '+'); | ||
904 | |||
905 | if (p == optarg) { | ||
906 | offset = 0; | ||
907 | size = parse_number(p + 1); | ||
908 | } else if (p) { | ||
909 | offset = parse_number(optarg); | ||
910 | if (p[1] == '\0') | ||
911 | size = ULONG_MAX; | ||
912 | else { | ||
913 | size = parse_number(p + 1); | ||
914 | if (*p == ',') { | ||
915 | if (size < offset) | ||
916 | fatal("invalid range: %lu,%lu\n", | ||
917 | offset, size); | ||
918 | size -= offset; | ||
919 | } | ||
920 | } | ||
921 | } else { | ||
922 | offset = parse_number(optarg); | ||
923 | size = 1; | ||
924 | } | ||
925 | |||
926 | add_addr_range(offset, size); | ||
927 | } | ||
928 | |||
929 | static void add_bits_filter(uint64_t mask, uint64_t bits) | ||
930 | { | ||
931 | if (nr_bit_filters >= MAX_BIT_FILTERS) | ||
932 | fatal("too much bit filters\n"); | ||
933 | |||
934 | opt_mask[nr_bit_filters] = mask; | ||
935 | opt_bits[nr_bit_filters] = bits; | ||
936 | nr_bit_filters++; | ||
937 | } | ||
938 | |||
939 | static uint64_t parse_flag_name(const char *str, int len) | ||
940 | { | ||
941 | int i; | ||
942 | |||
943 | if (!*str || !len) | ||
944 | return 0; | ||
945 | |||
946 | if (len <= 8 && !strncmp(str, "compound", len)) | ||
947 | return BITS_COMPOUND; | ||
948 | |||
949 | for (i = 0; i < ARRAY_SIZE(page_flag_names); i++) { | ||
950 | if (!page_flag_names[i]) | ||
951 | continue; | ||
952 | if (!strncmp(str, page_flag_names[i] + 2, len)) | ||
953 | return 1ULL << i; | ||
954 | } | ||
955 | |||
956 | return parse_number(str); | ||
957 | } | ||
958 | |||
959 | static uint64_t parse_flag_names(const char *str, int all) | ||
960 | { | ||
961 | const char *p = str; | ||
962 | uint64_t flags = 0; | ||
963 | |||
964 | while (1) { | ||
965 | if (*p == ',' || *p == '=' || *p == '\0') { | ||
966 | if ((*str != '~') || (*str == '~' && all && *++str)) | ||
967 | flags |= parse_flag_name(str, p - str); | ||
968 | if (*p != ',') | ||
969 | break; | ||
970 | str = p + 1; | ||
971 | } | ||
972 | p++; | ||
973 | } | ||
974 | |||
975 | return flags; | ||
976 | } | ||
977 | |||
978 | static void parse_bits_mask(const char *optarg) | ||
979 | { | ||
980 | uint64_t mask; | ||
981 | uint64_t bits; | ||
982 | const char *p; | ||
983 | |||
984 | p = strchr(optarg, '='); | ||
985 | if (p == optarg) { | ||
986 | mask = KPF_ALL_BITS; | ||
987 | bits = parse_flag_names(p + 1, 0); | ||
988 | } else if (p) { | ||
989 | mask = parse_flag_names(optarg, 0); | ||
990 | bits = parse_flag_names(p + 1, 0); | ||
991 | } else if (strchr(optarg, '~')) { | ||
992 | mask = parse_flag_names(optarg, 1); | ||
993 | bits = parse_flag_names(optarg, 0); | ||
994 | } else { | ||
995 | mask = parse_flag_names(optarg, 0); | ||
996 | bits = KPF_ALL_BITS; | ||
997 | } | ||
998 | |||
999 | add_bits_filter(mask, bits); | ||
1000 | } | ||
1001 | |||
1002 | static void describe_flags(const char *optarg) | ||
1003 | { | ||
1004 | uint64_t flags = parse_flag_names(optarg, 0); | ||
1005 | |||
1006 | printf("0x%016llx\t%s\t%s\n", | ||
1007 | (unsigned long long)flags, | ||
1008 | page_flag_name(flags), | ||
1009 | page_flag_longname(flags)); | ||
1010 | } | ||
1011 | |||
1012 | static const struct option opts[] = { | ||
1013 | { "raw" , 0, NULL, 'r' }, | ||
1014 | { "pid" , 1, NULL, 'p' }, | ||
1015 | { "file" , 1, NULL, 'f' }, | ||
1016 | { "addr" , 1, NULL, 'a' }, | ||
1017 | { "bits" , 1, NULL, 'b' }, | ||
1018 | { "describe" , 1, NULL, 'd' }, | ||
1019 | { "list" , 0, NULL, 'l' }, | ||
1020 | { "list-each" , 0, NULL, 'L' }, | ||
1021 | { "no-summary", 0, NULL, 'N' }, | ||
1022 | { "hwpoison" , 0, NULL, 'X' }, | ||
1023 | { "unpoison" , 0, NULL, 'x' }, | ||
1024 | { "help" , 0, NULL, 'h' }, | ||
1025 | { NULL , 0, NULL, 0 } | ||
1026 | }; | ||
1027 | |||
1028 | int main(int argc, char *argv[]) | ||
1029 | { | ||
1030 | int c; | ||
1031 | |||
1032 | page_size = getpagesize(); | ||
1033 | |||
1034 | while ((c = getopt_long(argc, argv, | ||
1035 | "rp:f:a:b:d:lLNXxh", opts, NULL)) != -1) { | ||
1036 | switch (c) { | ||
1037 | case 'r': | ||
1038 | opt_raw = 1; | ||
1039 | break; | ||
1040 | case 'p': | ||
1041 | parse_pid(optarg); | ||
1042 | break; | ||
1043 | case 'f': | ||
1044 | parse_file(optarg); | ||
1045 | break; | ||
1046 | case 'a': | ||
1047 | parse_addr_range(optarg); | ||
1048 | break; | ||
1049 | case 'b': | ||
1050 | parse_bits_mask(optarg); | ||
1051 | break; | ||
1052 | case 'd': | ||
1053 | describe_flags(optarg); | ||
1054 | exit(0); | ||
1055 | case 'l': | ||
1056 | opt_list = 1; | ||
1057 | break; | ||
1058 | case 'L': | ||
1059 | opt_list = 2; | ||
1060 | break; | ||
1061 | case 'N': | ||
1062 | opt_no_summary = 1; | ||
1063 | break; | ||
1064 | case 'X': | ||
1065 | opt_hwpoison = 1; | ||
1066 | prepare_hwpoison_fd(); | ||
1067 | break; | ||
1068 | case 'x': | ||
1069 | opt_unpoison = 1; | ||
1070 | prepare_hwpoison_fd(); | ||
1071 | break; | ||
1072 | case 'h': | ||
1073 | usage(); | ||
1074 | exit(0); | ||
1075 | default: | ||
1076 | usage(); | ||
1077 | exit(1); | ||
1078 | } | ||
1079 | } | ||
1080 | |||
1081 | if (opt_list && opt_pid) | ||
1082 | printf("voffset\t"); | ||
1083 | if (opt_list == 1) | ||
1084 | printf("offset\tlen\tflags\n"); | ||
1085 | if (opt_list == 2) | ||
1086 | printf("offset\tflags\n"); | ||
1087 | |||
1088 | walk_addr_ranges(); | ||
1089 | |||
1090 | if (opt_list == 1) | ||
1091 | show_page_range(0, 0, 0); /* drain the buffer */ | ||
1092 | |||
1093 | if (opt_no_summary) | ||
1094 | return 0; | ||
1095 | |||
1096 | if (opt_list) | ||
1097 | printf("\n\n"); | ||
1098 | |||
1099 | show_summary(); | ||
1100 | |||
1101 | return 0; | ||
1102 | } | ||
diff --git a/tools/slub/slabinfo.c b/tools/vm/slabinfo.c index 164cbcf61106..164cbcf61106 100644 --- a/tools/slub/slabinfo.c +++ b/tools/vm/slabinfo.c | |||