OSDev

для всех
Текущее время: 24 июл 2019, 09:47

Часовой пояс: UTC + 3 часа




Начать новую тему Ответить на тему  [ Сообщений: 14 ]  На страницу 1, 2  След.
Автор Сообщение
 Заголовок сообщения: Вопрос про память
СообщениеДобавлено: 21 июн 2010, 14:17 

Зарегистрирован: 16 фев 2010, 22:03
Сообщения: 101
У меня такой вопрос. Во-первых, является ли память непрерывной. В смысле от адреса 0x100000 до конца физической памяти дыр вроде BIOS и памяти устройств не будет? И в длинном режиме тоже? Просто я почитал немного osdev wiki, конкретнее про io apic и увидел, что адрес регистров IO APIC есть 32-битное значение из MSR. Или в длинном режиме будет браться и старшая часть значения MSR? А ещё есть функция BIOS, которая возвращает т. н. карту памяти. Которая тоже предполагает, что могут быть "дыры". Ну так вот. Если "дыры" в адресном пространстве могут быть, то получается, что самым простым способом - перебором страниц, записью значения и проверкой его - не получиться подсчитывать память. А в той функции BIOS'а, которая возвращает карту памяти я не совсем понял. "Доступно для использования ОС" - в это понятие включается видео память и прочее или только оперативная память? Просто я сейчас не имею возможности проверить свои догадки, поэтому хочу спросить у людей, которые уже знают про это.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Вопрос про память
СообщениеДобавлено: 21 июн 2010, 15:49 

Зарегистрирован: 28 окт 2007, 18:33
Сообщения: 1382
Память может идти произвольными кусками, перемежаясь с регистрами и памятью устройств, с памятью БИОС и т.д. Поэтому нужно определять карту распределения памяти с помощью соответствующей функции БИОС (описано на осдевовской вике, наизусть не помню), относящейся к стандарту АЦПИ.

Видеопамять -- это память устройства (видюхи в данном случае), и никакого отношения к ОЗУ она не имеет. Функция же БИОС возвращает карту распределения именно ОЗУ, ничего другого она не возвращает (кстати, она не сообщает и о памяти ниже 1 Мбайта -- там действует способ определения имеющегося объёма, неизменный со времён самых первых ПК; считать, что доступны все 640 Кбайт ОЗУ, нельзя, поскольку некоторая часть верхних адресов занята переменными БИОСа, и их разрушение приведёт к непредсказуемым последствиям).

Часть реального ОЗУ занята таблицами АЦПИ и прочей белибердой, поэтому-то упомянутая функция, возвращая информацию об очередной порции памяти, снабжает её атрибутом, показывающим, как эту память можно использовать.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Вопрос про память
СообщениеДобавлено: 21 июн 2010, 19:16 

Зарегистрирован: 16 фев 2010, 22:03
Сообщения: 101
Спасибо. Сейчас буду переделавать функцию определения объёма памяти (вернее перемещю её в начальный загрузчик). Хорошо, что объём памяти возвращается с вычетом памяти ACPI - не хотелось бы разрушить таблицы которые мне в далёком будущем могут пригодиться (когда я буду делать поддержку ACPI). Кстати, можно вам известно где можно взять документацию (более полную, чем на вики) по IO APIC на русском языке?
P.S. Если размер буфера для карты памяти 3064 байт, то этого же хватит в любом случае? (Просто в начальном загрузчике удобно выделить именно этот размер)


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Вопрос про память
СообщениеДобавлено: 21 июн 2010, 21:16 

Зарегистрирован: 10 май 2007, 11:33
Сообщения: 1204
SII писал(а):
кстати, она не сообщает и о памяти ниже 1 Мбайта -- там действует способ определения имеющегося объёма
Сообщает, но можно отсечь этот блок и пользоваться по старинке int 12h.

KIV писал(а):
P.S. Если размер буфера для карты памяти 3064 байт, то этого же хватит в любом случае? (Просто в начальном загрузчике удобно выделить именно этот размер)
Ты можешь сохранять информацию о блоках памяти в более компактных структурах, причем сразу отбрасывать блоки неподходящего типа. Например, не сохранять тип, а сохранять только базу/размер. Моя система к примеру не работает с физ. адресами выше 4 гиг, поэтому я сохраняю только 32-разрядные значения. Ядро запускается в реальном режиме и по началу имеет такие же ограничения в памяти, что и начальный загрузчик; я структуры блоков вместе с др. параметрами сохраняю в стеке под адресом 0x8000, т.е. для их хранения доступно примерно 30 Кб (в начале физ адр. пространства не должны разрушаться IVT, BDA плюс еще один блок для передачи параметров переменной, но не очень большой длины). В добавок использую константу MAXMEMREGIONS (обычно устанавливается равной 40), определяющую максимальное количество блоков, информацию о которых можно сохранить, т.е. обычно массив структур занимает в стеке не более 8*40=320 байт.

Что касается основного вопроса топика, то обычно память после первого мега идет непрерывно. Фрагментация обычно присутствует под границей 4 гига (там иногда встречаются куски свободной памяти по несколько килобайт, конечно если у тебя изначально установлено не менее 3-4 гиг), на старых компьютерах иногда встречается разрыв под границей 16 мег. Я вообще придерживаюсь правила считать всю память выше первого мега фрагментированной, поэтому сначала формирую непрерывный участок вирт. адр. пространства, а потом уже что-то перемещаю/загружаю в него.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Вопрос про память
СообщениеДобавлено: 21 июн 2010, 22:21 

Зарегистрирован: 10 май 2007, 11:33
Сообщения: 1204
Для лучшего понимания того, о чем я говорил, привожу код.
Код:
; Получаем местоположение и количество доступной памяти выше 1-го мегабайта.
; Скорректированную информацию об отдельных областях памяти сохраняем в стеке
; в виде набора структур, состоящих из следующих полей:
; 1) dword - адрес первой страницы области минус 0x1000;
; 2) dword - адрес последней страницы области.

        align16
@@:
        xor ebx,ebx
        mov ecx,20
        mov es,bx
        mov di,.ARDesc

; Суммарное количество памяти будем подсчитывать в отдельной переменной.

        label .HighMemorySize dword at .BaseMemorySizeKB-4
        push ebx

.next:
        mov edx,"PAMS"
        mov eax,0E820h
        int 15h
        jc .nosmap
        sub eax,"PAMS"
        jnz .nosmap
        cmp ecx,20
        jne .nosmap

        cmp [di+ARDESC.Type],AR_MEMORY
        jne .loop

        mov edx,[di+ARDESC.BaseAddrLow]
        cmp edx,100000h
        jb .loop
        cmp [di+ARDESC.BaseAddrHigh],eax
        jne .loop
        mov ebp,edx
        dec ebp
        and bp,0F000h
        add edx,[di+ARDESC.LengthLow]
        jc @f
        cmp [di+ARDESC.LengthHigh],eax
        jne @f
        mov eax,edx
        and ax,0F000h
@@:
        sub eax,1000h
        cmp eax,ebp
        jbe .loop
        push eax
        push ebp
        sub eax,ebp
        add [.HighMemorySize],eax
        cmp sp,.HighMemorySize-8*MAXMEMREGIONS
        jbe @f
.loop:
        and ebx,ebx
        jnz .next
@@:


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Вопрос про память
СообщениеДобавлено: 22 июн 2010, 01:21 

Зарегистрирован: 28 окт 2007, 18:33
Сообщения: 1382
phantom-84 писал(а):
SII писал(а):
кстати, она не сообщает и о памяти ниже 1 Мбайта -- там действует способ определения имеющегося объёма
Сообщает, но можно отсечь этот блок и пользоваться по старинке int 12h.[quote]

У меня не сообщала (вроде на Тиановской Тигер Е7505), карта памяти от АЦПИ начиналась с 1 Мбайта.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Вопрос про память
СообщениеДобавлено: 22 июн 2010, 16:24 

Зарегистрирован: 16 фев 2010, 22:03
Сообщения: 101
Как я теперь определяю память: Начальных загрузчик вызывает функцию для получения карты памяти и помещает карту в блоке размером 3064 байта (это расстояние между начальным загрузчиком и загруженным ядром. просто ядро выравнил на границу страницы и осталось свободное место), а ещё записывает в определённую ячейку памяти размер карты, который вернул BIOS. Если функция не поддерживается, то вызывает более старые, а результат заносит в карту памяти как один свободный блок от 0x100000 размером со всю верхнюю память. Ядро когда стартует анализирует карту памяти. Все адреса меньше 1 МБ отбрасывает - весь первый мегабайт зарезервирован и память из него не будет выделяться по вызову alloc_phis_pages (там находятся таблицы страниц ядра, само ядро, временно храняться загруженные начальным загрузчиком модули, поэтому лучше туда не лезть, а от 640 КБ в системе не убудет). Если адрес больше 1 МБ и помечен как "доступный для использования" ОС, то его адрес и размер заноситься в служебные структуры данных, чтобы можно было выделять из него страницы. Я решил, что карту памяти лучше хранить всю - когда будет поддержка ACPI я по ней определю что ещё можно осовободить, когда таблицы ACPI будут прочитаны. Поскольку моя ОС работает в длинном режиме игнорирование блоков выше 4 ГБ мне не подходит. Однако проверить как работает настоящая функция получения карты памяти я не могу, потому что текущая версия BIOS Bochs её не поддерживает. Но её имитация на основе данных от старых функция как ни странно работает.

Кстати, насчёт стандартной памяти. Я читал в osdev wiki, что верхние 7 КБ могут использоваться BIOS. Могут ли данные из них мне пригодиться? Например, из области данных BIOS я могу узнать позицию курсора, свойства дисков и прочие данные, которые могут пригодиться драйверам. Дело в том, что после перехода в PM я разрушаю эти данные помещая туда таблицу страниц ядра (до перехода в PM у меня примонтирован только 1 МБ, а после уже я монтирую ядро). Стоит ли опустить таблицу страниц пониже, чем 0x9F000 или и так всё нормально.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Вопрос про память
СообщениеДобавлено: 22 июн 2010, 16:44 

Зарегистрирован: 28 окт 2007, 18:33
Сообщения: 1382
Плохо читали вику. Из младших 640 Кбайт используются не "верхние 7 Кбайт", а произвольный объём, который надо определять, вызвав стандартную функцию БИОС для определения объёма нижней памяти (ИНТ 12 вроде как, смотреть лениво). 7 Кбайт было занято на одной из проверенных мною плат -- Тиан Тигер Е7505. На других платах объёмы были иные (был и килобайт, и 3 килобайта, и ещё что-то). Использовать эту область нельзя ни в коем случае -- что там хранит БИОС, одному БИОСу известно (ну и Господу Богу -- по определению, но мы теологическими вопросами здесь не занимаемся).


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Вопрос про память
СообщениеДобавлено: 22 июн 2010, 17:40 

Зарегистрирован: 10 май 2007, 11:33
Сообщения: 1204
KIV писал(а):
Все адреса меньше 1 МБ отбрасывает - весь первый мегабайт зарезервирован и память из него не будет выделяться по вызову alloc_phis_pages (там находятся таблицы страниц ядра, само ядро, временно храняться загруженные начальным загрузчиком модули, поэтому лучше туда не лезть, а от 640 КБ в системе не убудет).
У меня образ ядра хранится в базовой памяти только на стадии загрузки. В процессе инициализации после включения пэйджинга я выбираю из образа основную секцию ядра и копирую ее (не отображаю, а именно копирую) на свое законное место, аналогично размещаю еще один дополнительный модуль, также изначально находящийся в базовой памяти. Память для таблиц страниц берется из основного пула (используется спец. версия функции GetPage, работающая с пулом без включенного пэйджинга). Короче на определенном этапе вся базовая память становится свободной, но я все-таки использую первую физическую страницу с IVT, BDA и спец. секцией, в которой передается часть параметров из RM, отображая ее в пространство ядра. Оставшаяся базовая память предназначена для драйверов, работающих с устаревшими устройствами.

SII все правильно сказал про вершину доступной базовой памяти - ее нужно определять - выше находится EBDA, которую разрушать крайне нежелательно. Раз уж ты собрался работать с ACPI, то содержимое этого участка тебе еще пригодится ;)


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Вопрос про память
СообщениеДобавлено: 22 июн 2010, 18:16 

Зарегистрирован: 16 фев 2010, 22:03
Сообщения: 101
Ясно. Значит нужно сохранить... Буду определять адрес с помощью int 0x12.

А у меня загрузчик делает большую часть подготовки за ядро: загружает самые важные модули (у меня микроядро. без дополнительных модулей вроде драйвера жёсткого диска система дальше загрузиться не сможет), монтирует жизненно важные для ядра страницы (код ядра, стек, таблица страниц ядра, чтобы ярдо могло примонтировать к временному адресу физические страницы для модификации), переключается в 64-битный режим и передаёт управление ядру. Поскольку не имеет смысла делать в загрузчике менеджер памяти я задаю адреса статически. Когда стартует ядро, то для всего прочего (таблицы прерываний, TSS и т. д.) память уже выделяется динамически. А ядро так и остаётся навсегда в 1 МБ (физически, разумеется, для приложений оно в верхних адресах).


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 14 ]  На страницу 1, 2  След.

Часовой пояс: UTC + 3 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  
cron
Создано на основе phpBB® Forum Software © phpBB Group
Русская поддержка phpBB