@@ -307,6 +307,42 @@ fn check_prerequisites() -> Result<()> {
307307 ) ;
308308 }
309309
310+ // Check for precise guest IP sampling support.
311+ //
312+ // Intel: Guest PEBS was introduced with Ice Lake. Without it,
313+ // `perf kvm` falls back to NMI-based sampling where the guest
314+ // RIP has significant skid, making function-level attribution
315+ // unreliable (see the module-level "Known issue" documentation).
316+ //
317+ // We read the PMU name from sysfs and check against the known
318+ // set of pre-Ice-Lake PMU names (a closed set that won't grow).
319+ // Unknown names are assumed to be newer and not warned about.
320+ //
321+ // TODO: AMD guest IBS (IBSVIRT, Zen 4+) has the same issue but
322+ // detection is not implemented yet — needs testing on AMD hardware.
323+ const PRE_ICELAKE_PMUS : & [ & str ] = & [
324+ "nehalem" ,
325+ "westmere" ,
326+ "sandybridge" ,
327+ "ivybridge" ,
328+ "haswell" ,
329+ "broadwell" ,
330+ "skylake" ,
331+ "knl" , // Knights Landing
332+ ] ;
333+ if let Ok ( pmu_name) = fs:: read_to_string (
334+ "/sys/bus/event_source/devices/cpu/caps/pmu_name" ,
335+ ) {
336+ let pmu = pmu_name. trim ( ) ;
337+ if PRE_ICELAKE_PMUS . contains ( & pmu) {
338+ eprintln ! (
339+ "Warning: CPU PMU is '{pmu}' (pre-Ice Lake). Guest PEBS is not \
340+ available — guest IP samples will have significant NMI skid, \
341+ making function-level attribution unreliable."
342+ ) ;
343+ }
344+ }
345+
310346 Ok ( ( ) )
311347 }
312348}
@@ -540,8 +576,10 @@ fn report_perf(args: &PerfArgs, kallsyms: &Path) -> Result<()> {
540576 args. output . as_os_str ( ) . to_owned ( ) ,
541577 "--stdio" . into ( ) ,
542578 "--no-children" . into ( ) ,
579+ "--sort" . into ( ) ,
580+ "overhead" . into ( ) ,
543581 "-F" . into ( ) ,
544- "overhead,sym" . into ( ) ,
582+ "overhead,dso, sym" . into ( ) ,
545583 ] ) ;
546584
547585 let mut child = Command :: new ( "perf" )
0 commit comments