Menyu
Microsoft Surface 2 da Linux

GPU, xotira va çastotalar

Teksturaga 8 ms dan 0,7 ms gaça, 792 MGs xotira va çastotasi haqida aldagan protsessor.

Bu material hozirça rus tilida.

Планшет запускал GNOME, но работал заметно медленнее, чем позволяет его железо. Причины оказались не в одном месте: в драйвере графики, в таблицах памяти и в настройках, которые UEFI оставляет при загрузке.

Текстуры: 80 % времени в memcpy

При перетаскивании окна профилировщик показал, что 80–87 % времени главного потока GNOME Şell уходит на memcpy из некешируемой памяти. Отрисовка одного окна 1045×400 занимала около 8 мс.

Дело в шаге строки. Аппаратный сэмплер GR3D требует для текстур размером не в степень двойки шаг 64 байта, а драйвер выделял их с шагом 32 байта, как для буфера рисования. Текстура не подходила, драйвер делал её упакованную копию, и делал это на каждую отрисовку.

Из описания патча:

The GR3D sampler has an implicit row stride (16 bytes for power-of-two
textures, 64 bytes for NPOT), but textures were allocated with the 32-byte
render-target pitch. Every NPOT texture whose row was not a multiple of 64
bytes (window textures, icons, glyph atlases, ...) therefore got a "packed"
shadow BO and was re-copied row by row, reading from uncached GEM memory,
on EVERY draw that sampled it.

Исправление простое: сразу выделять такие текстуры с шагом сэмплера, чтобы они читались на месте. Для импортированных буферов копия теперь обновляется только после записи в текстуру.

ПоказательДоПосле
Отрисовка окна 1045×4007,9 мс0,6–0,7 мс
Перетаскивание окна38–51 fps59 fps
Главный поток Şell66–92 %33–37 %
Открытие обзора0,65–1,1 с0,37–0,57 с

Рядом исправлены «призраки» на экране: аппаратура принимает не больше 4096 индексов за отрисовку, поэтому большие отрисовки теперь разбиваются на части.

Память: родные таблицы лежали в ACPI

Контроллер памяти EMC работал на 408 МГц при паспортных 792 МГц. Переключить частоту нельзя без таблицы таймингов, а она уникальна для каждой платы и типа памяти.

Таблица нашлась в самом планшете: \_SB.PEPD.DVF6 в SSDT-6, структура tegra11_emc_table ревизии 0x42, 10 частот. Запись на 408 МГц совпала с реальными регистрами, значит таблица настоящая.

Алгоритм переключения мы взяли из tegra11_emc.c в ядре NVIDIA. Модуль surface-emc никогда не меняет напряжение: он только проверяет, что VDD_CORE достаточно.

/*
 * Supported targets: 204000 (PLLP/2), 408000, 600000 (PLLC, reserved
 * exclusively), 792000 (PLLM reprogrammed to 792 MHz while EMC runs on PLLP).
 * VDD_CORE (Palmas SMPS457) must already be >= table min_mV; the module
 * never changes voltages.
 */
Тест408 МГц792 МГцПрирост
Задержка, нс294207−30 %
Запись, 4 потока, МБ/с49858192+64 %
memcpy, МБ/с17172434+42 %
Чтение, МБ/с16121988+23 %

Проверка: memtest на 792 МГц и 1680 переключений между частотами, 670 из них под нагрузкой, без единой ошибки.

Процессор: система врала о своей частоте

Сделав новое ядро, мы увидели странный результат: на части загрузок оно работало на 23 % медленнее. Конфигурация и компилятор были ни при чём. Счётчик тактов показал реальные 990 МГц при заявленных 1320.

UEFI передаёт управление с SUPER_CCLKG_DIVIDER = 0x40000203. Это аппаратный пропуск тактов с коэффициентом 3/4 и бит, отдающий управление блоку термозащиты. Драйвера этого блока для T114 нет, ядро отключает его как неиспользуемый, и троттлинг застывает навсегда.

/*
 * Firmware may leave SUPER_CDIV_USE_THERM_CONTROLS set, handing the
 * CPU-G clock skipper to SOC_THERM. There is no Tegra114 soctherm
 * driver and soc_therm gets gated as an unused clock, so a throttle
 * active at that moment stays frozen (e.g. 0x40000203: cclk_g at 3/4
 * while cpufreq reports the full rate). Like NVIDIA's downstream
 * tegra11_super_clk_init(), start with the skipper cleared.
 */
{
    u32 cdiv = readl(clk_base + SUPER_CCLKG_DIVIDER);

    if (cdiv)
        pr_info("tegra114: clearing SUPER_CCLKG_DIVIDER 0x%08x\n",
            cdiv);
    writel(0, clk_base + SUPER_CCLKG_DIVIDER);
}

Управление частотой и температурой

Модуль surface-cpufreq меняет частоту от 204 до 1320 МГц вместе с напряжением VDD_CPU:

Частота, МГцНапряжение, мВ
до 408900
612940
816990
10201030
12241090
13261120

Защита: с 85 °C частота снижается шагами, с 95 °C сразу падает до 612 МГц, а при 100 °C система штатно выключается. Под стрессом на 4 ядрах максимум составил около 80 °C.

Частота GPU поднята с 300 до 492 МГц без изменения напряжения, что сократило отрисовку смешанного слоя 1080p с 11,2 до 8,3 мс.

Видео

Аппаратный декодер H.264 работает на отдельном процессоре AVP и доступен как обычное устройство /dev/video60. Контрольные суммы всех кадров совпали с программным декодированием, а 1080p30 занимает около 61 % одного ядра. FFmpeg, GStreamer, mpv и VLC используют его через V4L2.

Чего не удалось добиться

Кодировщик MSENC запускается, но отклоняет каждый кадр с ошибкой e2640010, даже с оригинальной прошивкой и повторением команд. Это заняло больше всего экспериментов и осталось нерешённым. А GTK 4 на GPU невозможен в принципе: ему нужен GLES3, у GR3D только GLES2.