FreeBSD-5.3 SMP and qemu

March 16, 2013

TL; DR:

Рецепт FreeBSD-5.3 с поддержкой многопроцессорности на KVM (запоздал на 10 лет, но вдруг кому еще надо):

А теперь история сего элегантного решения :]

Давным-давно (году, эдак, в 2005-м :]) у нас появился потенциальный клиент. Ему нужен был наш продукт (написан на С++/pthreads) для FreeBSD-5.

Для этого быстро взяли железную машину и с матерщиной установили туда фрю. В 2006-2007 году я устроился на должность программиста, поддерживающего нашу прогу на зоопарке всяких linux/BSD.

FreeBSD-5 оказалась самой глючной системой из всех мне попадавшихся, но это тема отдельного застольного разговора :]

Гораздо позже (в 2009 году) можности тачек подросли и я решил перенести это хрупкое чудо на виртуальную машину (тогда остановился на Xen в качестве гипервизора).

Всё началось с того, что FreeBSD-5.3 ненавидит ACPI в любом его проявлении. При попытке загрузки ядро висло не доходя до старта /sbin/init. Не работали первых 2 пункта меню загрузки системы: default и without ACPI.

Но 3-й пункт меню (Safe mode) работал! Немного покопавшись конфигах загрузчика я нашел заветвый кусок кода:

dup bootsafekey @ = if
        s" arch-i386" environment? if
                s" acpi_load" unsetenv
                s" 1" s" hint.acpi.0.disabled" setenv
                s" 1" s" loader.acpi_disabled_by_user" setenv
                s" 1" s" hint.apic.0.disabled" setenv
        then
        s" 0" s" hw.ata.ata_dma" setenv
        s" 0" s" hw.ata.atapi_dma" setenv
        s" 0" s" hw.ata.wc" setenv
        s" 0" s" hw.eisa_slots" setenv
        0 boot
then

Из этого мне оказалась нужна единственная строка:

s" 1" s" hint.acpi.0.disabled" setenv

Что в переводе на /boot/loader.conf:

hint.apic.0.disabled="1"

Этот костыль полностью отключает ACPI и позволяет кое-как грузить тачку и собирать там продукты. Позже я устал от ядра Xen.

Это был упатченный linux-2.6.18, в котором было сломано почти всё, что я тогда пытался использовать:

Немного поюзав KVM на своей машине решил перевести и сервер виртуальных машин. Гостевых ОСей было 5:

Не завелась единственная система. Угадайте какая?

Правильно - FreeBSD-5 :] Но на этот раз в ядре linux. Немного порывшись в интернетах нашел решение, которое уже попало в git дерево проекта kvm. Оно исправляло эмуляцию какой-то 16-битной ring0 инструкции работы с сегментами. Обновившись до ядра из этой ветки я ненадолго успокоился.

Прошло несколько лет и мы обновили сервер сборки с двухголового AMD64-X2 до 8-голового Core i7. Горе в том, что при отключенном APIC система в принципе не видит больше одного процессора.

В результате на FreeBSD-5 продукты собирались в 2 раза медленнее, чем на на всех остальных виртуальных машинах вместе взятых.

По умолчанию ядро FreeBSD-5 вообще не поддерживает SMP системы, так как SMP-ядро работает чуть медленнее UP ядра на UP системе.

Я стал ёрзать и отважился впервые пересобрать ядро FreeBSD. У ребят прекрасный handbook, с помощью которого я сравнительно быстро нашел проблему в ACPI и собрал таки работающее ядро.

Результирующий конфиг:

# cd /usr/src
# cat sys/i386/conf/MYKERNEL
include GENERIC

options SMP
options NO_MIXED_MODE
# make buildkernel KERNCONF=MYKERNEL
# make installkernel KERNCONF=MYKERNEL
# /sbin/reboot

Время сборки продукта сократилось с 5 минут до 36 секунд:

bash-2.05b$ time gmake target=freebsd5 -j9
...
real    0m36.046s
user    4m13.069s
sys     0m24.774s
bash-2.05b$ uname -r
5.3-RELEASE

Такие дела :]