\section{Распределение ресурсов между доменами Xen}

\subsection{Процессор}
Виртуальные процессоры (VCPU) виртуальных машин автоматически распределяются
планировщиком между доступными физическими процессорами.
Назначать соответствие виртуального процесса реальному вручную не нужно.
Однако, при возникновении такой необходимости, 
можно указать на каком процессоре будет выполняться виртуальный процессор.
Это делается с помощью команды \textbf{xm vcpu-pin}.

Каждый домен характеризуется двумя числами — \textit{весом} (weight) и \textit{лимитом} (cap).

Домен с весом 512 получает на том же хосте в два раза больше 
процессорного времени чем домен с весом 256.
Вес может изменяться в диапазоне от 1 до 65535, 
и он равен по умолчанию 256.

Значение лимита (cap) может использоваться для того чтобы указать максимальную величину
процессорного времени, который может получить домен, даже в случае, если хост-система
простаивает. Значение выражается в процентах: 100 это 1 физический процессор, 50 это половина процессора, 400 — 4 процессора и т.д.
Значение по умолчанию равно 0, что означает, что верхнее ограничение отсутствует.

Значения лимита и веса можно просматривать и модифицировать с помощью команд:

\begin{itemize}
\item  \textbf{xm sched-credit -d domain} — показать значение вес (weight) и верх (cap) для домена;
\item  \textbf{xm sched-credit -d domain -w weight} — установить вес равным \textbf{weight};
\item  \textbf{xm sched-credit -d domain -c cap} — установить верх равным \textbf{cap}.
\end{itemize}

Для того чтобы эти значения сохранялись и после перезапуска домена,
их нужно указать в конфигурационном файле
с помощью параметров:
\begin{itemize}
\item  \texttt{cpu\_cap} — верх (по умолчанию 0)
\item  \texttt{cpu\_weight} — вес (по умолчанию 256)
\end{itemize}

\subsection{Оперативная память}
Объём памяти, выделяемой домену 0, задаётся как параметр \textbf{dom0\_mem} гипервизора Xen.
В этом случае подразумевается, что объём памяти 
указан в килобайтах.

Пример секции конфигурационного файла \texttt{menu.lst} загрузчика GRUB:

\begin{verbatim}
title       Xen 3.2-1-i386 / Debian GNU/Linux, kernel 2.6.18-4-xen
root        (hd0,0)
kernel      /boot/xen-3.2-1-i386.gz dom0_mem=1200000
module      /boot/vmlinuz-2.6.18-4-xen-686 root=/dev/sda1 ro console=tty0
module      /boot/initrd.img-2.6.18-4-xen-686
savedefault
\end{verbatim}

В этом примере домен 0 при старте будет в объёме оперативной
памяти до 1.2G.

По умолчанию (то есть, если параметр \texttt{dom0\_mem} не указан),
домен 0 сначала получает весь доступный объём оперативной памяти,
а потом, по мере необходимости, при старте других доменов, его начинают снижать.
Это делает специально предназначенный для такой работы balloon-драйвер.

Снижение будет производиться до величины \texttt{dom0-min-mem}, 
заданной в конфигурационном файле \texttt{/etc/xen/xend-config.sxp}.
Здесь величина памяти указывается в мегабайтах.
Если в качестве значения указан 0, 
уменьшение памяти домена 0 выполняться не будет.

Пример настройки:

\begin{verbatim}
(dom0-min-mem 0)
\end{verbatim}

Объём памяти, выделяемой остальным доменам (то есть, виртуальным машинам),
задаётся в их конфигурационных файлах с помощью параметра \texttt{memory}.
Параметр может быть указан с суффиксом B, K, M или G, что означает байты, килобайты, мегабайты или гигабайты соответственно.
По умолчанию подразумевается, что в конфигурационном файле домена объём памяти указан в мегабайтах.

Впоследствии этот размер можно изменить прямо для работающего
домена при помощи команды:

\begin{verbatim}
xm mem-set <domain-id> <mem>
\end{verbatim}

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

Более правильный способ — использовать параметр конфигурационного файла домена \texttt{maxmem},
и передавать ядру гостевой системы (при условии что это Linux) параметр \texttt{mem}:

\begin{verbatim}
$ grep mem /etc/xen/dhcp 
memory = 128
maxmem = 512
extra = "mem=512M"
\end{verbatim}

Система при старте получает 128 MB ОЗУ, 
но она сможет корректно отработать увеличение
памяти до 512 MB.

\begin{verbatim}
$ sudo xm create dhcp
Using config file "/etc/xen/dhcp".
Started domain dhcp

$ sudo xm list 
Name                                        ID   Mem VCPUs      State   Time(s)
Domain-0                                     0  1171     1     r-----   5274.5
dhcp                                         8   128     1     -b----      2.8
\end{verbatim}

Гостевая операционная система видит 128MB:

\begin{verbatim}
$ sudo xm console dhcp
Debian GNU/Linux lenny/sid dhcp tty1

dhcp login: root
Password: 

dhcp:~# free
             total       used       free     shared    buffers     cached
Mem:        131220      33132      98088          0       1524      12204
-/+ buffers/cache:      19404     111816
Swap:            0          0          0
\end{verbatim}

Увеличиваем объём доступной домену оперативной памяти:

\begin{verbatim}
%$ sudo xm mem-set dhcp 256
%$ sudo xm list
Name                                        ID   Mem VCPUs      State   Time(s)
Domain-0                                     0  1171     1     r-----   5329.8
dhcp                                         8   256     1     -b----      2.9
\end{verbatim}

Гостевая операционная система теперь видит 256MB:

\begin{verbatim}
$ sudo xm console dhcp

dhcp:~# 
dhcp:~# 
dhcp:~# free
             total       used       free     shared    buffers     cached
Mem:        262144      33336     228808          0       1620      12228
-/+ buffers/cache:      19488     242656
Swap:            0          0          0
\end{verbatim}

В настоящий момент изменение памяти на лету \textit{НЕ} поддерживает 
ядро Linux, работающее через \textit{pv-ops}.
Это означает, в частности, что паравиртуальные ядра 2.6.24 и 2.6.25
не смогут увидеть изменение памяти в домене.

\subsection{Распределение устройств}
В режиме нормальной работы Xen-инсталляции все устройства (дисковая подсистема, сетевые адаптеры и проч.)
видны напрямую только домену 0. 
Гостевые домены могут пользоваться этими устройствами, 
но не напрямую, а только опосредованно, 
при помощи механизмов, предоставляемых доменом 0.

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

Для проброса PCI-устройств необходимо чтобы:
\begin{itemize}
\item  в ядре привилегированного домена (домена 0) присутствовала поддержка PCI backend;
\item  в ядрах, которые будут запускаться в пользовательских доменах и которые собираются использовать PCI-устройства, присутствовала поддержка PCI frontend. 
\end{itemize}
В XenLinux PCI backend включается в конфигурационной секции Xen, 
а PCI frontend включается в зависимой от архитектуры секции \dq{}Bus Options\dq{}. 
Можно вкомпилировать вместе в одно ядро поддержку backend\rq{}а и поддержку frontend\rq{}а. Они друг другу не мешают.
Обычно в ядрах, которые входят в состав распространённых дистрибутивов,
поддержка есть по умолчанию.

PCI-устройство, которое передаётся непривилегированному домену, 
должно быть скрыто от backend-домена (обычно домена 0) — 
не должно так получиться, что домен 0 загрузит случайно драйвер устройства,
и тот начнём работать с этим устройством.

Для этого нужно указать PCI backend, какое устройство он должен скрыть.
Он привязывает себя как драйвер к устройству
и тем самым гарантирует, что никакие другие драйверы устройств к нему не привяжутся.
То есть, в действительности, устройства не скрываются от домена 0, просто они никак им не используются.

Информация о том, какое устройство должно скрываться, 
передаётся как параметр ядра \texttt{pciback.hide}
в его командной строке, задающейся через загрузчик.
PCI-устройства идентифицируются шестнадцатеричными числами слот/функция (slot/function), 
в Linux эти номера можно определить с помощью программы \textbf{lspci}.
Их можно указывать с информацией о номере домена или без неё:

\begin{verbatim}
           (bus:slot.func) например (02:1d.3)
    (domain:bus:slot.func) например (0000:02:1d.3)
\end{verbatim}

Пример параметров ядра Linux, скрывающих два PCI-устройства:

\begin{verbatim}
root=/dev/sda4 ro console=tty0 pciback.hide=(02:01.f)(0000:04:1d.0)
\end{verbatim}

Устройство можно отобрать у драйвера и скрыть его
и без перезагрузки:

\begin{verbatim}
# echo -n 0000:05:02.0 > /sys/bus/pci/drivers/3c905/unbind
# echo -n 0000:05:02.0 > /sys/bus/pci/drivers/pciback/new_slot
# echo -n 0000:05:02.0 > /sys/bus/pci/drivers/pciback/bind
\end{verbatim}

Сначала устройство отвязывается от драйвера,
который его держит.
Затем оно привязывается к PCI backend.

Просмотреть к какому устройству привязан какой драйвер
можно командой:

\begin{verbatim}
%# ls -l /sys/bus/pci/devices/*/driver
\end{verbatim}

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

\begin{verbatim}
pci=['05:02.0']
\end{verbatim}

Когда гостевой домен будет запущен,
проверить видит ли он проброшенное внутрь устройство,
можно командой:

\begin{verbatim}
%# lspci
\end{verbatim}

\subsection{Дополнительная информация}
\begin{itemize}
\item \htmladdnormallinkfoot{Распределение ресурсов между доменами Xen}{http://xgu.ru/wiki/xen/resources} (рус.)
\end{itemize}

