До этого момента обсуждение подбиралось к моменту, когда система Intel становится готовой к настройке страниц. По мере нашего продвижения по коду head. S мы увидели,как происходит инициализация и как Linux использует х86-защищенный режим системы страниц. Это последний код, выполняемый перед стартом main. с ядра. За полной информацией о множестве доступных режимов и установок, связанных с инициализацией памяти и процессоров Intel, см. Intel Architecture Software Developer Manual, (Т. 3).
* Установка сегмента в известное значение. */ eld
Igdt boot_gdt_descr - PAGE_OFFSET
movl $( BOOT_DS),%eax
movl %eax,%ds
movl %eax,%es
movl %eax,%fs
movl %eax,%gs
/*
* Инициализация таблиц страниц. Создает PDE и настраивает таблицы
* страниц, расположенные сразу за _end. Переменная
* init_pg_tables_end устанавливается указывающей на первую
* "безопасную" позицию. Отображения создаются в виртуальном
* адресе 0 (тождественное отображение)и PAGE_OFFSET до
* _end+sizeof(page tables)+INIT_MAP_BEYOND_END.
* ВНИМАНИЕ! He используйте %esi или стек в этом коде. Однако %esp
* может быть использован как GPR, если вам это необходимо ... */
page_pde_offset = ( PAGE_OFFSET » 20);
movl $(pgO - PAGE_OFFSET), %edi
movl $(swapper_pg_dir - PAGE_OFFSET), %edx
movl $0x007, %eax /* 0x007 = PRESENT+RW+USER */
10:
leal 0x007(%edi),%ecx /* Создание элемента PDE */
movl %ecx,(%edx) /* Сохранение единичного элемента PDE */
movl %ecx,page_pde_offset(%edx) /* Сохранение элемента PDE ядра*/ addl $4,%edx movl $1024, %ecx 11: stosl
addl $0x1000,%eax loop lib
106 /* Конечное состояние: мы должны выполнить отображение до /* INIT_MAP_BEYOND_END включительно */
107 /* и до конца наших таблиц страниц; +0x007 - бит атрибутов */
108 leal (INIT_MAP_BEYOND_END+0x007)(%edi),%ebp
109 cmpl %ebp,%eax
110 jb 10b
111 movl %edi,(init_pg_tables_end - PAGE_OFFSET)
112
113 #ifdef CONFIG_SMP
156 3:
157 #endif /* CONFIG_SMP */ 158
159 /*
160 * Включение подкачки
161 */
162 movl $swapper_pg_dir- PAGE_OFFSET,%eax
163 movl %eax,%cr3 /* настройка указателя таблицы страниц.. */
164 movl %cr0,%eax
165 orl $0x80000000,%eax
166 movl %eax,%cr0 /* ..установка бита страницы (PG) */
167 ljmp $ BOOT_CS,$lf /* Очистка выборки и нормализация %eip */
168 1:
169 /* Настройка указателя стека */
170 lss stack_start,%esp
177 pushl $0
178 popfl 179
180 #ifdef CONFIG_SMP
181 andl %ebx,%ebx
182 jz If /* Начальная очистка BSS */
183 jmp checkCPUtype
184 1:
185 #endif /* CONFIG_SMP */ 186
187 /*
188 * Настройка 32-битового запуска системы. Нам нужно переделать
189 * кое-что, что было выполнено в "реальном" 16-битовом режиме.
190 */
191 call setup_idt
192
193 /*
194 * Копирование загрузочных параметров.
195 * ПРИМЕЧАНИЕ. %esi до сих пор указывает на данные реального режима.
196 */
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215
279 280
movl $boot_params,%edi
movl $(PARAM_SIZE/4),%ecx
eld
rep
movsl
movl boot_params+NEW_CL_POINTER,%esi andl %esi,%esi
jnz 2f # Протокол новой командной строки
cmpw $(OLD_CL_MAGIC),OLD_CL_MAGIC_ADDR jne If
movzwl OLD_CL_OFFSET,%esi addl $(OLD_CL_BASE_ADDR),%esi 2:
movl $saved_command_line,%edi movl $(COMMAND_LINE_SIZE/4),%ecx rep movsl 1:
checkCPUtype:
lgdt cpu_gdt_descr lidt idtdescr
адресами загрузочного GDT. Загрузка GDT представляет собой то же самое, что и GDT, используемая в setup. S (4 Гб кода и данных начиная с адреса 0x00000000), и применяется только для загрузки кода.
Строки 64-68
Инициализация оставшихся сегментов регистров с BOOT_DS начиная с 24 (см.
/include/asm-i386/segment.h). Это значение указывает на селектор 24h (начиная с 0) в финальном GDT, устанавливаемом далее в этом коде.
Строки 91-111
Создание записи директории страниц (PDE) в swapper_pg_dir, которая относится к таблице страниц (рдО) с записями, начинающимися с виртуального адреса 0 (тождественные), и с записями-копиями PAGE_OFFSET (память ядра).
Строки 113-157
Этот блок кода инициализирует дополнительные (незагрузочные) процессоры в таблице страниц. Для нашего обсуждения мы сфокусируемся на загрузочном процессоре.
Строки 162-164
Регистр сгЗ является точкой вхождения для аппаратных страниц х86. Этот регистр инициализируется в точке на основе Директории страниц (Page Directory), находящейся в нашем случае в swapper_pg_dir.
Строки 165-168
Установка бита PG (страниц) в сгО загрузочного процессора. Бит PG включает механизм страниц х86. Инструкция перехода (в строке 167) необходима при смене бита PG для понимания, что все инструкции в процессоре сериализируются в момент вхождения или выхода из режима страниц.
Строка 170
Инициализация стека в начале сегмента данных (см. также строки 401-403). Строки 177-178
Регистр eflags является системным регистром чтения-записи, содержащим состояния прерываний, моделей и разрешений. Регистры очищаются нулем в стеке и прямо извлекаются в регистры с помощью инструкции popf 1.
Строки 180-185
Регистр общего назначения ebx используется в качестве флага для обозначения того, загрузочный ли процессор выполняет этот код. Так как мы прослеживаем этот код, выполняющийся как на загрузочном процессоре, ebx очищается (0) и мы переходим к вызову setup_idt.
Строка 191
Функция setup_idt инициализирует таблицу описателей прерываний (IDT), в которой каждой точке вхождения соответствует обработчик-иусотышка. ГОТ обсуждается в гл. 7, «Планировщик и синхронизация ядра», и представляет собой таблицу функций (или обработчиков), вызываемых, когда процессору нужно выполнить критический по времени код.
Строки 197-214
Во время загрузки пользователь может передать Linux несколько параметров. Они сохраняются здесь и могут быть использованы позже.
Строки 215-303
Код, приведенный в этих строках, выполняет основную необходимую работу по проверке версии х86 процессора и некоторую дополнительную инициализацию.
С помощью инструкции cupid (или ее отсутствия) некоторые биты устанавливаются в регистрах ef lags и сгО. Одна из важных настроек, тип расширения (ЕТ), содержится в бите 4 сгО. Этот бит означает поддержку инструкций математического сопроцессора на старых, х86-процессорах. Наиболее важными строками в этом блоке являются строки 279-280. Именно здесь ШТ GDT загружаются (с помощью инструкций lidt и Igdt) в регистры idtr и gdtr. И наконец, в строке 303 мы переходим в функцию start_kernel ().
С кодом из head. S система может теперь отображать логические адреса в линейные адреса, а затем и в физические адреса (рис. 8.10). Начиная с логических адресов селектор (в регистрах CS, DS, ES и т. д.) ссылается на описатели в GDT. Отступ является искомым нами плоским адресом. Информация из описателя и отступа комбинируется для формирования логических адресов.
В этой прогулке по коду мы увидели, как создаются директория страниц (swapper_pg_dir) и таблица страниц (рдО) и как сг 3 инициализируется в точке директории страниц. Как обсуждалось ранее, процессор становится внимательным к просмотру компонентов страниц в соответствии с настройками сгЗ и настройками сгО (6HTPG) ДЛЯ того, чтобы процессор был проинформирован об их использовании. В логических адресах биты 22:31 означают элемент директории страниц (PDE), биты 12:21 означают элемент таблицы страниц (РТЕ) и биты 0:11 означают отступ (в данном примере 4 Кб) в физической странице.
Теперь у системы есть 8 Мб отображенной памяти для использования временной системы страниц. Следующим шагом является вызов функции start_kernel () в init/ main. с.