LINUX.ORG.RU

reserve_perfctr_nmi возвращает ошибку

 , ,


0

1

Блин, пока писал понял что нужно сделать echo 0 > /proc/sys/kernel/nmi_watchdog ибо «NMI watchdog: enabled on all CPUs, permanently consumes one hw-PMU counter.». Короче, проблема решена. Ну, не пропадать же написанному...

Пытаюсь портировать вот этот код на последнее ядро: http://castl.cs.columbia.edu/files/lprof-linux-2.6.32-1.3.diff (там про hardware performance counters и подсистему perf).

Вроде, всё спортировал нормально, но оно не работает. Конкретно валится на этой функции:

http://lxr.free-electrons.com/source/arch/x86/kernel/cpu/perfctr-watchdog.c?a...

Более точно: в строке 115 (test_and_set_bit) когда проверяется выставился ли нужный бит. Что это значит и что делать? :(? Я даже смысла кода не улавливаю. Как я вижу этот код: если этот event никем не используется то возвращаем ошибку. По-моему, это нелогично. Я проверил код в оригинальном ядре 2.6.32, эта функция не изменилась.

PS если это как-то поможет, я туда отладочных принтов накидал. Уже во время загрузки там такое (NMI_MAX_COUNTER_BITS и NMI_MAX_COUNTER_BITS это мой printk в соотв. местах reserve_perfctr_nmi):

[    0.074229] Performance Events: PEBS fmt1+, 16-deep LBR, IvyBridge events, full-width counters, Intel PMU driver.
[    0.074237] ... version:                3
[    0.074238] ... bit width:              48
[    0.074239] ... generic registers:      4
[    0.074241] ... value mask:             0000ffffffffffff
[    0.074242] ... max period:             0000ffffffffffff
[    0.074243] ... fixed-purpose events:   3
[    0.074244] ... event mask:             000000070000000f
[    0.090983] NMI_MAX_COUNTER_BITS
[    0.090986] CPU: 0 PID: 11 Comm: watchdog/0 Not tainted 3.13.0-1-custom #2
[    0.090988] Hardware name: ASUSTeK COMPUTER INC. UX32VD/UX32VD, BIOS UX32VD.214 01/29/2013
[    0.090990]  0000000000000000 ffff8802a015dd20 ffffffff81514c91 ffff8802a440e000
[    0.090993]  ffff8802a015dd30 ffffffff8103fd63 ffff8802a015dd70 ffffffff81029b55
[    0.090996]  ffff8802a00de520 ffffffff8181a820 ffff8802a440e000 0000000000000000
[    0.090999] Call Trace:
[    0.091007]  [<ffffffff81514c91>] dump_stack+0x4d/0x6f
[    0.091011]  [<ffffffff8103fd63>] reserve_perfctr_nmi+0xe3/0xf0
[    0.091014]  [<ffffffff81029b55>] x86_pmu_event_init+0x3b5/0x430
[    0.091018]  [<ffffffff8112f8ff>] perf_init_event+0xcf/0x110
[    0.091021]  [<ffffffff8112fcc0>] perf_event_alloc+0x380/0x430
[    0.091026]  [<ffffffff810f8100>] ? restart_watchdog_hrtimer+0x50/0x50
[    0.091029]  [<ffffffff8112fd96>] perf_event_create_kernel_counter+0x26/0xe0
[    0.091033]  [<ffffffff810f7e65>] watchdog_nmi_enable+0x75/0x140
[    0.091036]  [<ffffffff810f7f75>] watchdog_enable+0x45/0xa0
[    0.091039]  [<ffffffff8108b5e3>] smpboot_thread_fn+0xe3/0x270
[    0.091042]  [<ffffffff815177d9>] ? schedule+0x29/0x70
[    0.091045]  [<ffffffff8108b500>] ? SyS_setgroups+0x150/0x150
[    0.091047]  [<ffffffff81084632>] kthread+0xd2/0xf0
[    0.091051]  [<ffffffff81084560>] ? kthread_create_on_node+0x180/0x180
[    0.091054]  [<ffffffff8152303c>] ret_from_fork+0x7c/0xb0
[    0.091058]  [<ffffffff81084560>] ? kthread_create_on_node+0x180/0x180
[    0.091060] NMI_MAX_COUNTER_BITS
[    0.091061] CPU: 0 PID: 11 Comm: watchdog/0 Not tainted 3.13.0-1-custom #2
[    0.091063] Hardware name: ASUSTeK COMPUTER INC. UX32VD/UX32VD, BIOS UX32VD.214 01/29/2013
[    0.091064]  0000000000000001 ffff8802a015dd20 ffffffff81514c91 ffff8802a440e000
[    0.091067]  ffff8802a015dd30 ffffffff8103fd63 ffff8802a015dd70 ffffffff81029b55
[    0.091069]  ffff8802a00de520 ffffffff8181a820 ffff8802a440e000 0000000000000000
[    0.091072] Call Trace:
[    0.091075]  [<ffffffff81514c91>] dump_stack+0x4d/0x6f
[    0.091078]  [<ffffffff8103fd63>] reserve_perfctr_nmi+0xe3/0xf0
[    0.091081]  [<ffffffff81029b55>] x86_pmu_event_init+0x3b5/0x430
[    0.091084]  [<ffffffff8112f8ff>] perf_init_event+0xcf/0x110
[    0.091088]  [<ffffffff8112fcc0>] perf_event_alloc+0x380/0x430
[    0.091091]  [<ffffffff810f8100>] ? restart_watchdog_hrtimer+0x50/0x50
[    0.091094]  [<ffffffff8112fd96>] perf_event_create_kernel_counter+0x26/0xe0
[    0.091097]  [<ffffffff810f7e65>] watchdog_nmi_enable+0x75/0x140
[    0.091100]  [<ffffffff810f7f75>] watchdog_enable+0x45/0xa0
[    0.091104]  [<ffffffff8108b5e3>] smpboot_thread_fn+0xe3/0x270
[    0.091106]  [<ffffffff815177d9>] ? schedule+0x29/0x70
[    0.091109]  [<ffffffff8108b500>] ? SyS_setgroups+0x150/0x150
[    0.091111]  [<ffffffff81084632>] kthread+0xd2/0xf0
[    0.091115]  [<ffffffff81084560>] ? kthread_create_on_node+0x180/0x180
[    0.091118]  [<ffffffff8152303c>] ret_from_fork+0x7c/0xb0
[    0.091121]  [<ffffffff81084560>] ? kthread_create_on_node+0x180/0x180
[    0.091123] NMI_MAX_COUNTER_BITS
[    0.091124] CPU: 0 PID: 11 Comm: watchdog/0 Not tainted 3.13.0-1-custom #2
[    0.091126] Hardware name: ASUSTeK COMPUTER INC. UX32VD/UX32VD, BIOS UX32VD.214 01/29/2013
[    0.091127]  0000000000000002 ffff8802a015dd20 ffffffff81514c91 ffff8802a440e000
[    0.091129]  ffff8802a015dd30 ffffffff8103fd63 ffff8802a015dd70 ffffffff81029b55
[    0.091132]  ffff8802a00de520 ffffffff8181a820 ffff8802a440e000 0000000000000000
[    0.091135] Call Trace:
[    0.091138]  [<ffffffff81514c91>] dump_stack+0x4d/0x6f
[    0.091141]  [<ffffffff8103fd63>] reserve_perfctr_nmi+0xe3/0xf0
[    0.091143]  [<ffffffff81029b55>] x86_pmu_event_init+0x3b5/0x430
[    0.091147]  [<ffffffff8112f8ff>] perf_init_event+0xcf/0x110
[    0.091150]  [<ffffffff8112fcc0>] perf_event_alloc+0x380/0x430
[    0.091153]  [<ffffffff810f8100>] ? restart_watchdog_hrtimer+0x50/0x50
[    0.091157]  [<ffffffff8112fd96>] perf_event_create_kernel_counter+0x26/0xe0
[    0.091160]  [<ffffffff810f7e65>] watchdog_nmi_enable+0x75/0x140
[    0.091163]  [<ffffffff810f7f75>] watchdog_enable+0x45/0xa0
[    0.091166]  [<ffffffff8108b5e3>] smpboot_thread_fn+0xe3/0x270
[    0.091168]  [<ffffffff815177d9>] ? schedule+0x29/0x70
[    0.091172]  [<ffffffff8108b500>] ? SyS_setgroups+0x150/0x150
[    0.091174]  [<ffffffff81084632>] kthread+0xd2/0xf0
[    0.091177]  [<ffffffff81084560>] ? kthread_create_on_node+0x180/0x180
[    0.091180]  [<ffffffff8152303c>] ret_from_fork+0x7c/0xb0
[    0.091184]  [<ffffffff81084560>] ? kthread_create_on_node+0x180/0x180
[    0.091185] NMI_MAX_COUNTER_BITS
[    0.091186] CPU: 0 PID: 11 Comm: watchdog/0 Not tainted 3.13.0-1-custom #2
[    0.091188] Hardware name: ASUSTeK COMPUTER INC. UX32VD/UX32VD, BIOS UX32VD.214 01/29/2013
[    0.091189]  0000000000000003 ffff8802a015dd20 ffffffff81514c91 ffff8802a440e000
[    0.091191]  ffff8802a015dd30 ffffffff8103fd63 ffff8802a015dd70 ffffffff81029b55
[    0.091194]  ffff8802a00de520 ffffffff8181a820 ffff8802a440e000 0000000000000000
[    0.091197] Call Trace:
[    0.091200]  [<ffffffff81514c91>] dump_stack+0x4d/0x6f
[    0.091203]  [<ffffffff8103fd63>] reserve_perfctr_nmi+0xe3/0xf0
[    0.091205]  [<ffffffff81029b55>] x86_pmu_event_init+0x3b5/0x430
[    0.091209]  [<ffffffff8112f8ff>] perf_init_event+0xcf/0x110
[    0.091212]  [<ffffffff8112fcc0>] perf_event_alloc+0x380/0x430
[    0.091215]  [<ffffffff810f8100>] ? restart_watchdog_hrtimer+0x50/0x50
[    0.091219]  [<ffffffff8112fd96>] perf_event_create_kernel_counter+0x26/0xe0
[    0.091222]  [<ffffffff810f7e65>] watchdog_nmi_enable+0x75/0x140
[    0.091225]  [<ffffffff810f7f75>] watchdog_enable+0x45/0xa0
[    0.091228]  [<ffffffff8108b5e3>] smpboot_thread_fn+0xe3/0x270
[    0.091230]  [<ffffffff815177d9>] ? schedule+0x29/0x70
[    0.091233]  [<ffffffff8108b500>] ? SyS_setgroups+0x150/0x150
[    0.091236]  [<ffffffff81084632>] kthread+0xd2/0xf0
[    0.091239]  [<ffffffff81084560>] ? kthread_create_on_node+0x180/0x180
[    0.091242]  [<ffffffff8152303c>] ret_from_fork+0x7c/0xb0
[    0.091245]  [<ffffffff81084560>] ? kthread_create_on_node+0x180/0x180
[    0.097690] x86: Booting SMP configuration:
[    0.111414] NMI watchdog: enabled on all CPUs, permanently consumes one hw-PMU counter.
[    0.097692] .... node  #0, CPUs:      #1 #2 #3
[    0.152303] x86: Booted up 1 node, 4 CPUs

★★★★★

Последнее исправление: CYB3R (всего исправлений: 3)

2 tailgunner: насколько секурно выкладывать дампы регистров и dmesg? А вдруг там мои ssh-ключи или ещё какая важная байда...

true_admin ★★★★★
() автор топика
Ответ на: комментарий от true_admin

насколько секурно выкладывать дампы регистров и dmesg?

Теоретически возможно, что дамп содержит значения регистров кода, который возится с чем-то секретным прямо в ядре, но это точно не твой случай.

А для того, чтобы переносить нетривиальный код на 20 релизов вперед, нужно очень хорошо понимать, что он делает. Лично меня исходный дифф слегка пугает.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

Ты про эти критические секции и про функцию doLastModify? Вот есть описание из статьи. Увы, ссыкотный код который я очень плохо понимаю и, в случае чего, вряд ли поправлю :( На 90% я расчитываю на удачу что ядро в плане процессов по-прежнему работает так как оно работало двадцать релизов назад.

To detect whether or not an application is in the
middle of a counter read during a counter overflow we sim-
ply check the pattern of instructions before the process was
interrupted (pointed to by the process’ instruction pointer).
If a counter read is detected, the kernel zeros the process’
registers (%rax and %rdx in the x86 example) to match the
new (overflowed) contents of the performance counter. Once
resumed, the program will behave as if the interrupt, con-
text switch and overflow had occurred immediately prior to
the read of the performance counter.
true_admin ★★★★★
() автор топика
Ответ на: комментарий от true_admin

Ты про эти критические секции и про функцию doLastModify?

Я про set_in_cr4 и {wr,rd}msrl. А еще access_ok с игнорируемым кодом возврата. Если это магия, а не остатки старого кода, я отказываюсь иметь с этим дело %)

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

Я про set_in_cr4 и {wr,rd}msrl

set_in_cr4 даёт доступ из юзерспейса к performance counters. Ну, чтобы инструкцию rdpmc можно было вызывать обычным процессам. Ради этого всё и затевается. Весь остальной код это тупо сохранение/восстановление значений регистров при смене контекста и миграции процесса и обработка переполнений счётчиков т.к. они могут быть 48-битными O_O

rdmsrl/wrmsrl сохраняют/восстанавливают значение каунтеров при смене процессов. Это нужно для того чтобы вести независимую статистику для каждого из процессов.

А еще access_ok с игнорируемым кодом возврата

Нет там такого :)

true_admin ★★★★★
() автор топика
Ответ на: комментарий от true_admin

set_in_cr4 даёт [...] rdmsrl/wrmslr [...]

Я всё это понимаю. Только вот логика такого уровня мало кому нужна, так что тестируется мало и каким образом она сломается - ХЗ.

Нет там такого :)

Печать не в счет. Да и вообще мне не нравится использование access_ok - это либо излишне при copy_{to,from}_user, либо должно сопровождаться локингом (а локинга я не вижу вообще - автор либо полагается на внешний, который мог поплыть со времен 2.6.32, либо пишет всё очень аккуратно, либо просто забил).

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

Только вот логика такого уровня мало кому нужна

По-моему, это как раз тот случай. Суть проекта — дать доступ к регистрам из юзерспейса чтобы обойтись без ядра. Стандартный способ это вызвать perf_event_open и читать из полученного дескриптора. Но это, типа, долго.

либо пишет всё очень аккуратно, либо просто забил

Автор заявляет что он сделал «всё очень аккуратно». Проверить по коду не могу, скиллов не хватает.

true_admin ★★★★★
() автор топика
Ответ на: комментарий от true_admin

А как с этим бороться? Надо как-то на время запретить вытеснение ядра?

Она всё равно останется сломанной на SMP. Если я правильно понимаю, нужно лочить мютекс, закрывающий операции с mmap, но... за счет лока профайлер потеряет часть скорости. Подозреваю, что при нормальной дисциплине локинга он будет не быстрее обычного perf.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

lprof_switchto вызывается из kernel/sched/core.c:context_switch().

Неужели context_switch тоже может быть вытеснен? Это как-то... странно.

true_admin ★★★★★
() автор топика
Ответ на: комментарий от true_admin

Неужели context_switch тоже может быть вытеснен?

А с чего бы переключению контекста блокировать другие процессоры? Или ты полагаешь, что переключение контекста захватывает mmap_lock? Но тогда код полагается на внешний локинг. Этот локинг гарантирован?

tailgunner ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.