Возможно, вы не хотите перепрограммировать счетчик внутри функции переключения контекста.
Проще всего было бы сделать системные вызовы из пространства пользователя для программирования PMU (для подсчета какого-либо события, возможно, установив его для подсчета в режиме ядра, но не пространство пользователя, просто счетчик реже переполняется).
Затем просто дважды используйте rdpmc
(чтобы получить счетчики запуска / остановки) в своем пользовательском коде ядра. Счетчик будет работать, и я думаю, что Perf-код ядра будет обрабатывать прерывания, когда он оборачивается. (Или когда его буфер PEBS заполнен.)
IDK, если возможно запрограммировать счетчик так, чтобы он просто переносился без прерывания, для таких случаев использования, как этот, когда вас не волнует итоговое или профильное профилирование, и вы просто хотите использовать rdpmc
. Если это так, сделайте это.
Старый ответ, касающийся вашего старого вопроса, основанного на глючной строке формата printf
, которая печатала ненулевой мусор, даже если вы ничего не учитывали в пользовательском пространстве.
Ваш встроенный ассемблер выглядит правильно, поэтому вопрос в том, что именно этот счетчик PMU запрограммирован для подсчета в режиме ядра в контексте, где работает ваш код.
perf
виртуализирует счетчики PMU при переключении контекста, создавая иллюзию perf stat
подсчета одного процесса, даже если он мигрирует между процессорами. Если вы не используете perf -a
для получения общесистемных подсчетов, PMU может не быть запрограммирован для подсчета чего-либо, поэтому все операции чтения дадут 0
, даже если в другое время он запрограммирован для подсчета быстро меняющегося события, такого как циклы или инструкции.
Вы уверены, что perf
настроен на подсчет событий пользователя + ядра, а не только событий в пространстве пользователя?
perf stat
покажет что-то вроде instructions:u
вместо instructions
, если оно ограничено пользовательским пространством. (Это значение по умолчанию для не-root, если вы не понизили sysctl kernel.perf_event_paranoid
до 0 или что-то из безопасного значения по умолчанию, которое не позволяет пользовательскому пространству узнать что-либо о ядре.)
Имеется поддержка HW для программирования счетчика для подсчета только когда CPL! = 0 (то есть не в кольце 0 / режиме ядра). Более высокие значения для kernel.perf_event_paranoid
ограничивают API-интерфейс perf, чтобы не разрешать программирование счетчиков считать в режиме ядра + пользователя, но даже с paranoid = -1
их можно запрограммировать таким образом. Если вы так запрограммировали счетчик, то это все объяснит.
Нам нужно увидеть ваш код, который программирует счетчики. Это не происходит автоматически.
Ядро не просто оставляет счетчики включенными все время, когда ни один процесс не использовал функцию PAPI для включения счетчика для процесса или общесистемного счетчика; это приведет к прерываниям, которые замедляют работу системы без какой-либо выгоды.