Указание архитектуры процессора в конфиге ядра шаблонами

Ведение

Эта статья покажет вам как легко шаблонами настроить ядро на работу с CPU с максимальной производительностью.
Мимоходом будет упомянуто о создании локальных шаблонов.
Тем, кто хочет потренироваться в создании шаблонов, это может быть полезно.

Итак…
Порою возникает необходимость в конфиге ядра указать архитектуру процессора, под которую необходимо это самое ядро собирать.@
@
Конкретно у меня такая необходимость возникла при настройке кофемолки компьютера на Intel Atom в качестве рутера. Шутка ли? это подняло пропускную способность сервера в качестве рутера с едениц мегабайт до порога провайдера.

Тот самый Atom, и первый велосипед чтоб ему работалось лучше

В этом конкретном случае, поскольку работа была разовой, и не предполагала сопровождение, я установил CSS с включенным автообновлением
явно отключил ключ minimal у ядра:

echo 'sys-kernel/calculate-sources -minimal' >>/etc/portage/package.use/custom

дабы исключить установку ядра из пакаджей

На скорую руку создал шаблон задающий архитектуру в конфиге ядра:
Для начала создал структуру для локальных шаблонов…

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

## тут я создал ветвь в директории локальных шаблов в соответствии со структурой calculate-шаблонов
mkdir -pv /var/calculate/templates/3.1/6_ac_install_patch/sys-kernel/calculate-sources

## а тут просто копировал файлы определяющие структуру шаблонов calculate в локальные шаблоны
for d in $(find /var/calculate/templates/3.1 -maxdepth 3 -type d ); do 
    cp -va /var/lib/layman/calculate/profiles${d#/var/calculate}/{.calculate_directory,README-{rus,eng}.txt} $d/
done
## .calculate_directory - файлы определяющие смысл того как и в каких ситуациях трактовать содержимое текущей директории
## README-rus.txt и README-eng.txt - просто описание, никакой функции не несут. Но тому, кто может захочет после меня там покопаться, с ними будет проще.

!!![](ВАЖНО)!! если вы захотите на этом примере создать свой локальный оверлей, сначала постарайтесь понять что они делают. почитайте документацию. приведенные выше команды врядли что-то поломают, но гарантировать этого я не буду
и собственно сам шаблон:

cat << EOF >/var/calculate/templates/3.1/6_ac_install_patch/sys-kernel/calculate-sources/atom.config
 # Calculate format=openrc name=.config

CONFIG_M686=n
CONFIG_MATOM=y
EOF

## запускаю пересборку ядра
emerge -avt1 calculate-sources 

## и иду чай пить... часов на четыре-пять...
## Да, компиляция ядра - не самая сильная сторона Atom-а
## хорошо, что был вечер, и на месте я толко установил систему. Настраивал ее я уже издому.

Как видите, получилось довольно просто.
make oldconfig выполнемый при сборке ядра после настройки шаблонами, сам изменит все необходимые параметры (я проверял. для Atmom-а он так же включил параметры CONFIG_X86_INTERNODE_CACHE_SHIFT=6 и CONFIG_X86_L1_CACHE_SHIFT=6)

Поиск универсального решения

Такое простое решение сподвигло меня на создание шаблона упрощающего настройку этого параметра ядра.
Пораскинув мозгами, я обозначил для себя следующие пункты:
# Постановка задачи по созданию шаблонов для архитектур x86 и x86_64

## Задаваемое семейство процессора может не соответствовать семейству машины, на которой происходит сборка. Это позволит собирать ядра на других, более мощных компьютерах.

## название переменной, задащей семейство, должно быть интуитивно понятно

## Если семейство не указано, либо не соответствует предлагаемым в menuconfig - использовать дефолтное (M686 для i686 и GENERIC_CPU для x86_64)

## Желательно сохранять ядро для архитектуры по умолчанию. Во всяком случае, если оно установлено - оно не должно быть перезаписано.
# Реализация задач.

Постановка задачи

Сборка ядра для семейства отличного от машины где происходит сборка.

Возможна ситуация, когда сборка будет проводиться на мощном железе, с отличным CPU Family. А значит, автоматическое определение архитектуры при сборке неприемлемо.
Гораздо правильнее (да и легче) было-бы использовать шаблоны, определяеме в ini.env. Так я и сделал.

Название переменной

Тут все просто.
Поскольку для своих шаблонов я уже использую переменные в разделе [kernel] в ini.env:

[kernel]
os_kernel_highmem = 64G
os_broadcom-sta = on
os_classic_netname = on
mavriq_fixes = on

просто создам в нем еще одну переменную.
Я решил назовать ее kernel.family

Значения по умолчанию

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

Сохранение дефолтного ядра.

Первое, что пришло ко мне в голову - было прописать ARCH+FAMILY в параметр ядра CONFIG_LOCALVERSION. Но, к сожалению, опыт показал, что без изменения ebuild-а это приведет к ряду неприятностей, вроде отсутствующих /lib/modules/<release> в initramfs. Это можно, конечно, было пофиксить, но я пока решил это отложить.
Тем более, что дальше будет предложено более элегантное решение.

Реализация

Попытка номер один (неудачная)

Поскольку я, как и любой админ - человек ленивый, я решил, что пусть шаблоны все делают за меня.
Я создал два шаблона: i686.config и x86_64.config
Тут приведу лишь второй (он короче)

calculate cpu_family # cat x86_64.config 
 # Calculate format=openrc name=.config ini(kernel.family)!= os_arch_machine==x86_64 in(kernel.family,GENERIC_CPU,MATOM,MCORE2,MPSC,MK8)!=

CONFIG_MK8=n
CONFIG_MPSC=n
CONFIG_MCORE2=n
CONFIG_MATOM=n
CONFIG_GENERIC_CPU=n
CONFIG_#-ini(kernel.family)-#=y

Т.е., если архитектура соответствующая, параметр kernel.family определен, и соответствует одному из возможных для данной архитектуры значений, мы сначала выключаем все варианты CPU Family, и потом включаем нужный. В ручном режиме данный метод проверку прошел. make oldconfig прекрасно понимал что от него хотят.
Скажу сразу - так не получилось. Оказывается in(key, valuelist) не работает с переменными определяемыми в ini.env. (разработчики уже в курсе, и обещали попробовать что-нибудь придумать)
Ладно. подойдем с другой стороны

Попытка номер два (рабочая)

Раз не получается сделать красиво - нагенерим три десятка шаблонов для каждого случая.
Общий принцип такой:

  • В шапке определяем архитектуру и kernel.family при которых этот шаблон отработает.
    В теле - отключаем ненужные параметры. Включаем нужные.
  • Для дефолтных шаблонов логика чуть-чуть другая. В шапке проверяем архитектуру и НЕсоответствие kernel.family всем остальным вариантам для данной архитектуры.

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

<code class="sh">
fam_template_gen() {
    local f ff ARCH=$1; shift
    local DEFAULT=$1 FAMILY=("$@")
    for f in ${FAMILY[@]}; do
    {
        echo -n "# Calculate format=openrc name=.config os_arch_machine==${ARCH}"
        if [[ "$f" != "$DEFAULT" ]]; then
            echo -e " ini(kernel.family)==$f\n\n# CONFIG_LOCALVERSION=\".${ARCH}.$f\""
        else
            for ff in ${FAMILY[@]}; do
                [[ "$ff" != "$DEFAULT" ]] && echo -n " ini(kernel.family)!=$ff"
            done
            echo -e "\n"
        fi
        for ff in ${FAMILY[@]}; do
            echo -n "CONFIG_$ff="; [[ "$f" == "$ff" ]] && echo y || echo n
        done
    } >${ARCH}.$f.config
    done 
}

fam_template_gen i686 M686 M486 M586 M586TSC M586MMX MPENTIUMII MPENTIUMIII MPENTIUMM MPENTIUM4 MK6 MK7 MK8 MCRUSOE MEFFICEON MWINCHIPC6 MWINCHIP3D MELAN MGEODEGX1 MGEODE_LX MCYRIXIII MVIAC3_2 MVIAC7 MCORE2 MATOM
fam_template_gen x86_64 GENERIC_CPU MK8 MPSC MCORE2 MATOM
</code>

Все! результат достигнут.
Этот скрипт не претендует на право быть эталоном кода. главное что он решает поставленную одноразовую задачу.

Результат работы скрипта вы можете увидеть в моем оверлее

Там же есть генератор шаблонов и нерабочие шаблоны i686.config и x86_64.config с шапкой скорректированной для того, чтоб они не мешали нормальной работе шаблонов.

Исключение пакетов модулей из списка устанавливаемых из пакаджей

К сожалению, тут мне похвастать нечем.
Попытка через /etc/portage/env и /etc/portage/package.env прописать для выбраных пакетов FEATURES=-getbinpkg и PORTAGE_BINHOST=/dev/null ничего не дала.
Если у кого-то появятся мысли как эту задачу решить не забивая в make.conf кучу параметров EMERGE_DEFAULT_OPTS="--usepkg-exclude <PKGNAME>" - буду рад если поделитесь.


Скоро допишу и дооформлю свои мысли о том, в какую сторону двигаться, чтоб решить оставшиеся задачи

Отличная статья, ссылка на лень - отговорка…
Поскольку в целом, все это очень трудоемко.
Ждем продолжения данной статьи.

ссылка на лень - отговорка…

Лень - двигатель прогресса. Когда мне лень сто раз делать что-то однотипное - я автоматзирую.
Так что тут я был искренен

В продолжении я хотел не только высказать свое мнение куда дальше двигаться, но и частично реализолвать это в шаблонах. Пока не получилось (или я что-то не так делаю, или заявленный функционал шаблонов не до конца соответствует реализованному. пока склоняюсь к первому)

Когда найду время перепроверю свои шаблоны и в любом случае распишу то что обещал