Skip to content

Latest commit

 

History

History
15 lines (10 loc) · 4.82 KB

step3.md

File metadata and controls

15 lines (10 loc) · 4.82 KB

Physical memory mapping

После включение paging'а, ядру нужен доступ к физической памяти. Текущая реализация HeLL OS маппит первые 4 мегабайта физической памяти в верхние адреса ядра (higher-half kernel), начиная с адреса 0x80000000. Чтобы не усложнять вещи, мы будем работать в предположении, что вы можете выделить ядерные виртуальные адреса для всей доступной оперативной памяти. Однако в реальности это не так, поэтому в Linux используется следующий трюк: память разбивается на low и high, lowmem маппится полностью в пространство ядра — это адреса, к которым ядро часто обращается (например, DMA). Доступ к верхним адресам требует постоянных изменений page directory/page table, то есть вы сначала подмапливаете страницу, изменяете данные на ней, а затем отдаёте обратно ядру её виртуальный адрес для переиспользования. Почитать можно тут: раз, два, три, четыре и пять.

Цель: всё, что вам нужно сделать — это расширить диапазон адресов с 4 Мб до максимально доступного адреса оперативной памяти и добавить его в аллокатор. Его можно получить из инфорации, передаваемой Multiboot-загрузчиком. Парсинг этой информации у вас должен был быть реализован на прошлом шаге. Hint: используйте страницы размером 4 Мб — они позволят писать меньше кода, и будут работать быстрее, потому что будет меньше TLB misses.

Memory manager

В HeLL OS реализован простейший аллокатор фреймов, основнный на списке свободных страниц. kalloc выделяет фрейм и возвращает его вирутальный адрес, а затем с помощью map_continuous выделяется виртуальный адрес. Однако, аллокатор обладает рядом недостатков. Во-первых, он не умеет освобождать память. Во-вторых, ядру иногда нужно будет выделять не одну страницу, а сразу несколько (например, под стек ядра или для mmap). Во-третьих, в следствии фрагментации физической памяти не всегда возможно выделить последовательные физические адреса заданного размера.

Цель: вам нужно будет чуть улучшить kalloc так, чтобы он умел выделять (и освобождать) свободный диапазон виртуальных адресов заданного размера в текущем адресном пространстве и мапить его в нужное количество фреймов. Учтите, что в будущем потребуется выделять пользовательские и ядерные адреса в разных половинах адресного пространства.

Hint: как вариант, вы можете реализовать следующий интерфейс:

  • void* kalloc(size_t size, int flags), а flags будет принимать флаги ALLOC_USER | ALLOC_KERNEL | ALLOC_WRITABLE.
  • void kfree(void*, size_t size)

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