diff -r 3de4393f5649 -r 3d08ce800ba0 SConstruct --- a/SConstruct Tue Oct 15 13:26:34 2013 +0200 +++ b/SConstruct Tue Oct 15 13:44:55 2013 +0200 @@ -792,12 +792,35 @@ context.Result(ret) return ret +# Add a custom Check function to test for structure members. +def CheckMember(context, include, decl, member, include_quotes="<>"): + context.Message("Checking for member %s in %s..." % + (member, decl)) + text = """ +#include %(header)s +int main(){ + %(decl)s test; + (void)test.%(member)s; + return 0; +}; +""" % { "header" : include_quotes[0] + include + include_quotes[1], + "decl" : decl, + "member" : member, + } + + ret = context.TryCompile(text, extension=".cc") + context.Result(ret) + return ret + # Platform-specific configuration. Note again that we assume that all # builds under a given build root run on the same host platform. conf = Configure(main, conf_dir = joinpath(build_root, '.scons_config'), log_file = joinpath(build_root, 'scons_config.log'), - custom_tests = { 'CheckLeading' : CheckLeading }) + custom_tests = { + 'CheckLeading' : CheckLeading, + 'CheckMember' : CheckMember, + }) # Check for leading underscores. Don't really need to worry either # way so don't need to check the return code. @@ -962,6 +985,12 @@ return host_isa in isa_comp_table.get(isa, []) +# Check if the exclude_host attribute is available. We want this to +# get accurate instruction counts in KVM. +main['HAVE_PERF_ATTR_EXCLUDE_HOST'] = conf.CheckMember( + 'linux/perf_event.h', 'struct perf_event_attr', 'exclude_host') + + ###################################################################### # # Finish the configuration @@ -1063,7 +1092,8 @@ # These variables get exported to #defines in config/*.hh (see src/SConscript). export_vars += ['USE_FENV', 'SS_COMPATIBLE_FP', 'TARGET_ISA', 'CP_ANNOTATE', - 'USE_POSIX_CLOCK', 'PROTOCOL', 'HAVE_PROTOBUF'] + 'USE_POSIX_CLOCK', 'PROTOCOL', 'HAVE_PROTOBUF', + 'HAVE_PERF_ATTR_EXCLUDE_HOST'] ################################################### # @@ -1241,6 +1271,13 @@ "target ISA combination" env['USE_KVM'] = False + # Warn about missing optional functionality + if env['USE_KVM']: + if not main['HAVE_PERF_ATTR_EXCLUDE_HOST']: + print "Warning: perf_event headers lack support for the " \ + "exclude_host attribute. KVM instruction counts will " \ + "be inaccurate." + # Save sticky variable settings back to current variables file sticky_vars.Save(current_vars_file, env) diff -r 3de4393f5649 -r 3d08ce800ba0 src/cpu/kvm/base.cc --- a/src/cpu/kvm/base.cc Tue Oct 15 13:26:34 2013 +0200 +++ b/src/cpu/kvm/base.cc Tue Oct 15 13:44:55 2013 +0200 @@ -1133,6 +1133,12 @@ cfgCycles.disabled(true) .pinned(true); + // Try to exclude the host. We set both exclude_hv and + // exclude_host since different architectures use slightly + // different APIs in the kernel. + cfgCycles.exclude_hv(true) + .exclude_host(true); + if (perfControlledByTimer) { // We need to configure the cycles counter to send overflows // since we are going to use it to trigger timer signals that @@ -1206,6 +1212,12 @@ PerfKvmCounterConfig cfgInstructions(PERF_TYPE_HARDWARE, PERF_COUNT_HW_INSTRUCTIONS); + // Try to exclude the host. We set both exclude_hv and + // exclude_host since different architectures use slightly + // different APIs in the kernel. + cfgInstructions.exclude_hv(true) + .exclude_host(true); + if (period) { // Setup a sampling counter if that has been requested. cfgInstructions.wakeupEvents(1) diff -r 3de4393f5649 -r 3d08ce800ba0 src/cpu/kvm/perfevent.hh --- a/src/cpu/kvm/perfevent.hh Tue Oct 15 13:26:34 2013 +0200 +++ b/src/cpu/kvm/perfevent.hh Tue Oct 15 13:44:55 2013 +0200 @@ -45,6 +45,8 @@ #include +#include "config/have_perf_attr_exclude_host.hh" + /** * PerfEvent counter configuration. */ @@ -125,6 +127,39 @@ return *this; } + /** + * Exclude the events from the host (i.e., only include events + * from the guest system). + * + * Intel CPUs seem to support this attribute from Linux 3.2 and + * onwards. Non-x86 architectures currently ignore this attribute + * (Linux 3.12-rc5). + * + * @warn This attribute is ignored if it isn't present in the + * kernel headers or if the kernel doesn't support it. + * + * @param val true to exclude host events + */ + PerfKvmCounterConfig &exclude_host(bool val) { +#if HAVE_PERF_ATTR_EXCLUDE_HOST == 1 + attr.exclude_host = val; +#endif + return *this; + } + + /** + * Exclude the hyper visor (i.e., only include events from the + * guest system). + * + * @warn This is attribute only seems to be ignored on Intel. + * + * @param val true to exclude host events + */ + PerfKvmCounterConfig &exclude_hv(bool val) { + attr.exclude_hv = val; + return *this; + } + /** Underlying perf_event_attr structure describing the counter */ struct perf_event_attr attr; };