Запуск обычной версии под RPi

Только технические вопросы по ЯОС и MINOS. Терминология и прочее - в других форумах.
Ответить

БудДен
Сообщения: 2839
Зарегистрирован: 07.10.18 14:01

Re: Запуск обычной версии под RPi

Сообщение БудДен » 27.03.22 15:48

Читаем конфигурацию Zynq, видим модули:
ARM { ARM.FPE64.Mod ARM.Builtins.Mod }
RPI и COOP { RPI.CPU.Mod }
ZYNQ и COOP { Zynq.CPU.Mod }
ARM и ~COOP { ARM.Initializer.Mod }
ZYNQ и ~COOP { Zynq.ARM.Platform.Mod }
ARM и ~COOP { ARM.BootConfig.Mod }
RPI и COOP { RPI.Processors.Mod RPI.Timer.Mod }
ZYNQ и COOP { Zynq.Processors.Mod Zynq.Timer.Mod }
COOP { Queues.Mod BaseTypes.Mod Activities.Mod ExclusiveBlocks.Mod Interrupts.Mod Runtime.Mod }
NATIVE и COOP { HeapManager.Mod }
BIOS и COOP { BIOS.Environment.Mod }
RPI и COOP { RPI.Environment.Mod }
ZYNQ и COOP { Zynq.Environment.Mod }
UNIX и COOP { Unix.Environment.Mod }
ZYNQ и ~COOP { Zynq.PsUartMin.Mod Zynq.TraceDevice.Mod Zynq.PrivateWatchdog.Mod ARM.Machine.Mod }
~COOP { Heaps.Mod }
Modules.Mod
ARM и ~COOP { ARM.Objects.Mod ARM.Kernel.Mod }
Здесь я оставил большинство модулей для COOP.

БудДен
Сообщения: 2839
Зарегистрирован: 07.10.18 14:01

Re: Запуск обычной версии под RPi

Сообщение БудДен » 27.03.22 15:51

Модуль ARM.Initializer содержит проц {INITIAL,NOPAF} Init;

https://tvoygit.ru/budden/ja-o-s/src/br ... -версии.md

Видимо, сопоставлять его надо с RPI.Environment.Mod/KernelBegin

Наверное, надо скопировать каждый файл от Zynq, к-рый будет меняться.

БудДен
Сообщения: 2839
Зарегистрирован: 07.10.18 14:01

Re: Запуск обычной версии под RPi

Сообщение БудДен » 29.04.22 22:10

Код: Выделить всё

System.DoCommands
	FSTools.DeleteFiles -i ЯОС:NewRPI2/* ~
	Release.Build -b --path="ЯОС:NewRPi2/" RPi2 ~
	Linker.Link --fileName=ЯОС:NewRPI2/kernel7.img --displacement=8000H -a 
	   --path="ЯОС:NewRPi2/" Initializer Platform FPE64 ПримитивыСредыВыполнения 
	   Ю32 ПереводыЭлементовКода Trace BootConfig PsUartMin TraceDevice PrivateWatchdog 
	   Ю16 Ю16_2 Machine Heaps Modules Objects Kernel ЛогЯдра Plugins Streams Pipes 
	   Commands Reals Clock Dates Strings Files Disks DiskCaches Reflection TrapWriters 
	   Traps Locks Options ~
	FSTools.CopyFiles -o ЯОС:NewRPI2/kernel7.img => C:/vb_share/a2/2/kernel7.img ~
	FSTools.CopyFiles -o ЯОС:NewRPI2/kernel7.log => C:/vb_share/a2/2/kernel7.log ~~

БудДен
Сообщения: 2839
Зарегистрирован: 07.10.18 14:01

Re: Запуск обычной версии под RPi

Сообщение БудДен » 29.04.22 22:58

https://zen.yandex.ru/video/watch/62a79 ... 692a14250c - видео о том, как собрать и запустить в эмуляторе ядро, в т.ч. под отладчиком. До того момента, когда оно падает.
Последний раз редактировалось БудДен 03.09.22 17:56, всего редактировалось 1 раз.

БудДен
Сообщения: 2839
Зарегистрирован: 07.10.18 14:01

Re: Запуск обычной версии под RPi

Сообщение БудДен » 01.07.22 23:38

Падает на проверке

утв(memStackStop <= memIOStart);

участвующие в проверке величины назначаются в ARM.Machine.Mod:

Код: Выделить всё

		memConfigStop := Platform.DDRStart + СтрВЦел32(i, value);
		ДайЗначениеКлючаКонфигурацииЯОС("ConfigSize", value);
		i := 0;
		memConfigStart := memConfigStop - СтрВЦел32(i, value);

		memStackStart := memHeapStop;
		memStackStop := memConfigStart;

		memIOStart := Platform.IOStart;
		memIOStop := memIOStart + Platform.IOSize;

БудДен
Сообщения: 2839
Зарегистрирован: 07.10.18 14:01

Re: Запуск обычной версии под RPi

Сообщение БудДен » 02.07.22 20:10

Теперь нам надо, похоже, запустить кооп. версию и в ней понять, чему равно memTag.size (можно с помощью TRACE, т.к. трассировка уже поднята).

БудДен
Сообщения: 2839
Зарегистрирован: 07.10.18 14:01

Re: Запуск обычной версии под RPi

Сообщение БудДен » 02.07.22 22:41

Код: Выделить всё

memTag^.size = 1006632960
RPI.Environment.Mod@5628 Environment.InitMemory:memTag^.start= 00000000H; 
RPI.Environment.Mod@5654 Environment.InitMemory: операцияАдресОт KernelEnd= 00065EA0H; 
Последний раз редактировалось БудДен 03.07.22 11:30, всего редактировалось 1 раз.

БудДен
Сообщения: 2839
Зарегистрирован: 07.10.18 14:01

Re: Запуск обычной версии под RPi

Сообщение БудДен » 02.07.22 22:42

теперь надо понять, что дальше происходит с этой памятью. Мы выяснили, что она мапится 1*1 в виртуальную память (если я всё правильно понял). Но дальше, очевидно, часть должна резервироваться под вектора прерываний, часть - это порты, а остальное должно инициализироваться с помощью менеджера памяти. Т.е. нужно дальше читать загрузку RPiC.

Может помочь картинка:
периферия-bcm2835.png
периферия-bcm2835.png (151.69 КБ) 727 просмотров
источник
Последний раз редактировалось БудДен 03.07.22 12:24, всего редактировалось 1 раз.

БудДен
Сообщения: 2839
Зарегистрирован: 07.10.18 14:01

Re: Запуск обычной версии под RPi

Сообщение БудДен » 03.07.22 11:38

Вызывают интерес следующие строчки в кооперативной версии. Похоже, что всё, что за ядром, выкладывается в один непрерывный диапазон адресов. Остаётся вопрос, что с периферией? На картинке упоминается iobase. Такое слово в исходниках есть, но пока смысл не раскопал.

Код: Выделить всё

	
	HeapManager.Initialize (heap, begin := операцияАдресОт KernelEnd, end := memTag.start + memTag.size);
	memory := memTag.start + memTag.size - операцияАдресОт KernelEnd;

БудДен
Сообщения: 2839
Зарегистрирован: 07.10.18 14:01

Re: Запуск обычной версии под RPi

Сообщение БудДен » 03.07.22 12:43

Как же работает трассировка? А вот как:

В RPI.CPU.Mod написано:

Код: Выделить всё

конст UART_CR* = 03F201030H
- это 1059065904

А MemTag.size = 1006632960 = 3C000000, т.е. порты находятся ЗА пределами диапазона.
Видимо, неявным образом iobase = 3C000000 или что-то в этом роде. Уточним.
В примере c:\ob\RaspberryPi-baremetal\002-hello-lo-lo-lo\uart.S
видим:

Код: Выделить всё

#define PERIPHERAL_BASE 0x3F000000 // Raspberry Pi 2 Peripheral Base Address

БудДен
Сообщения: 2839
Зарегистрирован: 07.10.18 14:01

Re: Запуск обычной версии под RPi

Сообщение БудДен » 03.07.22 18:09

В файле для Zynq написано:

Код: Выделить всё

 * Interrupt Vector. Located at 0FFFFFFF0H
При том есть переменная sysVectorStart, которая равна FFFF0000, и которая нигде не используется. Странно это всё.

БудДен
Сообщения: 2839
Зарегистрирован: 07.10.18 14:01

Re: Запуск обычной версии под RPi

Сообщение БудДен » 03.07.22 23:57

Теперь пытаемся понять, что такое sysFirstLvlPtStart и sysSecondLvlPtStart.
Это явно два каких-то куска.

GetSecondLevelEntry - испольузется в:

* ExtendStack
* GetStack
* AllocatePage/DeallocatePage
* TranslateVirtual
* ValidStack
* EnableDCacheRange/DisableDCacheRange (DCache - это кеш данных)


GetFirstLevelEntry - используется в:
* EnableDCacheRange/DisableDCacheRange
* TranslateVirtual
* AllocateHeap

Причём в EnableDCacheRange выглядит так, как будто FirstLevel главнее.

Теперь смотрим сюда:

БудДен
Сообщения: 2839
Зарегистрирован: 07.10.18 14:01

Re: Запуск обычной версии под RPi

Сообщение БудДен » 04.07.22 00:01

https://programmersought.com/article/24173413930/

There are two cores of CORE0 and CORE1 in zynq. The two cores have independent L1 DCache and share the same L2 DCache.

Пазл складывается. Похоже, что FirstLevel/SecondLevel как-то относится к кешу и всё это - специфика Zynq. Для RPi - неактуально.

БудДен
Сообщения: 2839
Зарегистрирован: 07.10.18 14:01

Re: Запуск обычной версии под RPi

Сообщение БудДен » 28.08.22 23:08

Вроде выяснил, что TLB-это аппаратный кеш для трансляции страниц. Его нужно обновлять при изменении таблиц вирт. памяти. Т.е. в ЭВМ.AllocatePage понятен вызов InvalidateTLBEntry, осталось выяснить, есть ли аналогичное в RPi.

Что касается SecondLevelEntry, то вот кусок кода возле определения sysSecondLvlPtStart:

Код: Выделить всё

	(* System Parameters *)
        (* ... *)
	(* First Level Page Table: size of 16 * k to map 4GB with 1MB pages. *)
	sysFirstLvlPtStart,
	sysFirstLvlPtStop,
	(*
	 * Second Level Page Table:
	 *		- 2 * 256 entries for the system area (first and last MB of VMem)
	 *		- 256 entries for each MB of virtual stack space
	 * 256 entries take 1kB memory space.
	 *)
	sysSecondLvlPtStart,
	sysSecondLvlPtStop,

БудДен
Сообщения: 2839
Зарегистрирован: 07.10.18 14:01

Re: Запуск обычной версии под RPi

Сообщение БудДен » 28.08.22 23:35

Видимо, ARM.Machine.Mod/InvalidateDCache ~= RPI.CPU.Mod/Invalidate.

Также в RPI.CPU.Mod нашлась переменная:

Код: Выделить всё

перем pageTable {выровнять (4000H)}: запись entry: массив 4096 из размерМЗ кон;

БудДен
Сообщения: 2839
Зарегистрирован: 07.10.18 14:01

Re: Запуск обычной версии под RPi

Сообщение БудДен » 28.08.22 23:48

Название RPI.CPU/IdentityMapMemory намекает на примитивность управления памятью в RPi.
Наверное, можно не расширять стек, а вот как насчёт выделения памяти? Пока неясно. Поскольку
мы хотим сузить интерфейс, придётся пересмотреть все использования вирт. памяти в Zynq
и понять, сможем ли мы их отобразить и как.

БудДен
Сообщения: 2839
Зарегистрирован: 07.10.18 14:01

Re: Запуск обычной версии под RPi

Сообщение БудДен » 30.08.22 17:58

Перебираем всех, кто обращается к выделению страниц.

ExtendStack - в обычной версии,
Activities.ExpandStack - в кооперативной. Максимальный стек в 1000 раз больше изначального. Вероятно, у нас будут затруднения обойтись без расширения стека. Поэтому придётся разобраться, как работает ExpandStack во всех версиях и сможем ли мы его расширять при условии, что мы отображаем обычную память в виртуальную как 1 в 1.

BIOS.I386.Machine.Mod/ExtendStack - пользуется вирт. памятью (MapPage)
ARM обычный - то же.
Activities.Mod/ExpandStack - я ничего не понял, но похоже, что стек состоит из сегментов (записей). Загадочно то, что с одной стороны, стек вроде расширяется путём создания новой записи и на неё сохраняется ссылка. С другой, предпоследняя запись при создании последней явно удаляется.
Во всяком случае, не видно, чтобы тут работало отображение страниц.

Однако кооп. версия нам не нужна. Возможно всё же нужно перенести управление памятью (с вирт. памятью) из Zynq, перенастроив его. Попробуем концептуально понять это из https://habr.com/ru/post/422385/ и потом поискать примеры для RPi с конкретикой.

https://s-matyukevich.github.io/raspber ... pi-os.html

БудДен
Сообщения: 2839
Зарегистрирован: 07.10.18 14:01

Re: Запуск обычной версии под RPi

Сообщение БудДен » 01.09.22 00:13

В общем, похоже, что надо более агрессивно запихивать Zynq версию на RPi , со всеми прибамбасами, кроме отсутствующих. Для этого надо:
* прочитать, что уже сделано (сравнить главную ветку и RPI2-3)
* составить табличку всех параметров (чисел), участвующих в конфигурации ОС, с двумя колонками, Zybo и RPi
* найти эти параметры в коде
* подменить

БудДен
Сообщения: 2839
Зарегистрирован: 07.10.18 14:01

Re: Запуск обычной версии под RPi

Сообщение БудДен » 03.09.22 13:13

Возвращаемся к вопросу про периферию. Судя по изучению упомянутого c:\ob\RaspberryPi-baremetal\002-hello-lo-lo-lo\uart.S , адрес периферии прибит гвоздями к модели RPi. Поскольку он у нас находится за пределами памяти (адрес больше 1гб), то и волноваться о его пересечении с обычной памятью у нас нет причин. Если нам тут о чём-то и стоит волноваться, так это про то, чтобы в Zynq эта периферия не оказалась где-то внутри адресного пространства и появились бы спец.костыли для её исключения. Попробуем это увидеть.

БудДен
Сообщения: 2839
Зарегистрирован: 07.10.18 14:01

Re: Запуск обычной версии под RPi

Сообщение БудДен » 03.09.22 17:49

Нашёл в Zynq.ARM.Platform.Mod

Код: Выделить всё

UartBase* = [адресВПамяти(0E0000000H),адресВПамяти(0E0001000H)]; (* base address for all UART controllers present in the system *)

БудДен
Сообщения: 2839
Зарегистрирован: 07.10.18 14:01

Re: Запуск обычной версии под RPi

Сообщение БудДен » 03.09.22 19:02

sysSecondLvlPtStart не влез куда надо, видимо, по той причине, что его пытались запихнуть в OCM, размером 192кб.
А это - специальная микросхема памяти, которая есть в Zynq, и, видимо, занимает адреса от 0 (Platform.OCMStart = 0).
Теперь всё же придётся разобраться, куда можно поместить таблицу страниц в RPi.

Имеем:
Для управления системой(в т.ч. блоком MMU) в архитектуре ARM предназначен специальный сопроцессор CP15. К управлению памятью относятся полтора десятка его регистов. Нас интересуют несколько из них — Control, TTBR0/1, TTBCR, ContextID.
P15 в ЯОС - как-то соотносится с CP15 (ищем в коде EnterCoprocessor(CP15, "P15");

Далее, имеем такой код (RPI.CPU.Mod/EnableMemoryManagementUnit)

Код: Выделить всё

проц EnableMemoryManagementUnit-;
машКод
load:
	LDR	R0, [PC, #page-$-8]
	MCR	P15, 0, R0, C2, C0, 0
	B	grant
page:
	d32 pageTable
grant:
	MOV	R0, #0b11
	MCR	P15, 0, R0, C3, C0, 0
enable:
	MRC	P15, 0, R0, C1, C0, 0
	ORR	R0, R0, #0b1	; memory protection
	ORR	R0, R0, #0b100	; data and unified cache
	ORR	R0, R0, #0b100000000000	; branch prediction
	ORR	R0, R0, #0b1000000000000	; instruction cache
	MCR	P15, 0, R0, C1, C0, 0
кон EnableMemoryManagementUnit;
Здесь pageTable - это просто статическая переменная с каким-то (каким попало) адресом:

Код: Выделить всё

перем pageTable {выровнять (4000H)}: запись entry: массив 4096 из размерМЗ кон;
Хаа, такая же нашлась и в ARM.Machine.Mod, но она содержит адреса:

Код: Выделить всё

	pageTable: запись virtual, memory: адресВПамяти кон;
при этом ожидаемо (ARM.Machine.Mod):

Код: Выделить всё

		pageTable.virtual := sysFirstLvlPtStart;
		pageTable.memory := sysFirstLvlPtStart;
Значит, раз в RPI нет какого-то особого (ускоряющего) места для этой таблицы, то нам нужно создать две переменных для таблиц
первого и второго уровня и передать их адреса. А переменные sysFirstLvlPt* упразднить.

БудДен
Сообщения: 2839
Зарегистрирован: 07.10.18 14:01

Re: Запуск обычной версии под RPi

Сообщение БудДен » 03.09.22 21:37

Теперь нам нужно узнать размеры таблиц для RPi, одна из них есть, а вторая? В Zynq она где-то лежит и имеет какой-то размер (0x390400, хотя кто знает, что это означает).

RPI.Environment.Mod/Allocate -> HeapManager.Allocate -> а дальше как-то не попадается ничего, похожего на таблицу 2-го уровня.

Тогда план будет такой: таблица первого уровня пусть имеет размер 0x1000, второго - 0x390400 (хз, что это, но пусть будет так пока что), memSysLowStart и memSysLowStop выкидываем, а под таблицы заводим две статических переменных (только надо понять, в чём измеряется размер).

БудДен
Сообщения: 2839
Зарегистрирован: 07.10.18 14:01

Re: Запуск обычной версии под RPi

Сообщение БудДен » 04.09.22 01:22

поменял размер начальной системной области (поставил 1мб с запасом, как раз хватило до адреса загрузки ядра),
размер кучи (уменьшил)
размер стека (128мб, а не отсчитываю от конфига, который где-то далеко в небе)

Загрузка прошла чуть дальше.

БудДен
Сообщения: 2839
Зарегистрирован: 07.10.18 14:01

Re: Запуск обычной версии под RPi

Сообщение БудДен » 04.09.22 12:02

Пытаемся изжить memSysHighStart/Stop, но внутри них находятся:

(* High system memory region. Within the last MB, contains: interrupt vector and reference counts
* for caching. *)

Это опять же кусок адресного пространства, к-рый в Zynq отвечает за OCM - on-chip memory, которой в RPi (наверное) нет.

Нужно выяснить, где в RPi вектор прерываний и что делать с "счётчиками ссылок для кеширования"

Вектор прерываний живёт по адресам около 0, а у нас в новой версии что там? Туда попал Config - его надо разместить получше (или вообще выкинуть,
ведь у нас есть константа для конфига). А в Zynq есть sysVectorStart и sysVectorsStop и он - где-то в верхних адресах. Посмотрим, где он используется. А нигде, кроме проверок.

ARM.Machine.Mod (ЭВМ для Zynq) InterruptVector == sysVectorStart, но совпадение не проверяется и называется почему-то по-другому. И написано так:

Код: Выделить всё

	(* Interrupt Vector base. Valid only after MMU is enabled *)
	InterruptVector = 0FFFF0000H;
Поскольку у нас он будет в начале и мы мапим начало 1:1, то нет причины, почему он не является корректным в любое время (кроме времени, когда MMU включено, а отображение 1:1 ещё не сделано).

Ставим sysVectorStart = 1. Размер его равен PS (4кб, одна страница) - надесь, это нас не сломает, если мы поставим его в начале. Опробуем, но перед этим посмотрим, где используется InterruptVector. На беглый взгляд ничего страшного, но чую, что всё рухнет эпически.
Последний раз редактировалось БудДен 04.09.22 13:03, всего редактировалось 4 раза.

БудДен
Сообщения: 2839
Зарегистрирован: 07.10.18 14:01

Re: Запуск обычной версии под RPi

Сообщение БудДен » 04.09.22 12:06

Хм, оказывается в RPi тоже есть SDRAM, видимо, это аналог OCM (см. картинку в начале темы), и она ещё как-то может делиться на 2 части. Но пока мы это игнорируем.

БудДен
Сообщения: 2839
Зарегистрирован: 07.10.18 14:01

Re: Запуск обычной версии под RPi

Сообщение БудДен » 04.09.22 14:21

Надеемся, что счётчики для кеширования - это просто память, а не что-то аппаратное. Если окажется иначе, будем думать. sysCacheRefStart - ищем, как используется. Используется для переменной ARM.Machine.Mod/cacheRefs, она частная и в ассемблере не используется. Значение прибито гвоздями и равно 0FFFF1000H - это подозрительно. Запросы "zynq ffff1000 cache" и "zynq 0xffff1000 cache" ничего не показывают. Будем считать, что это просто число, а не особая железка в zynq. Также ищем во всех файлах исходников, ничего не находим.

БудДен
Сообщения: 2839
Зарегистрирован: 07.10.18 14:01

Re: Запуск обычной версии под RPi

Сообщение БудДен » 04.09.22 14:56

memConfigStart/memConfigStop - странно, но я не нашёл, где бы они использовались. В старой версии нашёл такой кусок кода:

ARM.BootConfig.Mod (версия Zynq):

Код: Выделить всё

	
проц Init *;
	нач
		НИЗКОУР.копируйПамять(Initializer.configBase, 1FFFF000H, Initializer.configSize);
		Initializer.configBase := 1FFFF000H;
		config := Initializer.configBase;
		size := Initializer.configSize;
		если size >= ConfigSize то size := ConfigSize-1; всё;
		config[size] := CR;
	кон Init;

Скорее всего, он как-то вычисляется статически из размера памяти, но я не нашёл такого значения в *. Значит, мы их выпилим, а инициализация у нас уже по-другому устроена (конфигурация у нас не берётся с платы, а впечатана в коде ядра):

ARM.BootConfig.Mod (версия RPi2):

Код: Выделить всё

	проц Init *;
	нач
		(* НИЗКОУР.копируйПамять(Initializer.configBase, 1FFFF000H, Initializer.configSize);
		Initializer.configBase := 1FFFF000H;
		config := Initializer.configBase;
		size := Initializer.configSize;
		если size >= ConfigSize то size := ConfigSize-1; всё;
		config[size] := CR; *)
	cfg := "CpuClockHz=666666666
UartInputClockHz=50000000
KernelOutputUart=1
...

БудДен
Сообщения: 2839
Зарегистрирован: 07.10.18 14:01

Re: Запуск обычной версии под RPi

Сообщение БудДен » 04.09.22 15:20

Раскладка памяти выглядит так:

Код: Выделить всё

System Start(memSysLowStart):              00000000
System Stop(memSysLowStop):                00100000
System Size:                               00100000
Interrupt Vector Start(sysVectorStart):    00000000
Interrupt Vector Stop(sysVectorStop):      00001000
Interrupt Vector Size:                     00001000
Interrupt Stack Start(sysIntStackStart):   00001000
Interrupt Stack Stop(sysIntStackStop):     00008000
Interrupt Stack Size:                      00007000
Cache References Start(sysCacheRefStart):  00008000
Cache References Stop(sysCacheRefStop):    00010104
Cache References Size:                     00008104
Cache References Stack Offset(sysCacheStackOfs):    00000100
Second Page Table Start(sysSecondLvlPtStart):  000DB800
Second Page Table Stop(sysSecondLvlPtStop):    000FC000
Second Page Table Size:                        00020800
First Page Table Start(sysFirstLvlPtStart):000FC000
First Page Table Stop(sysFirstLvlPtStop):  00100000
First Page Table Size:                     00004000
Heap Start(memHeapStart):                  00100000
Heap Stop(memHeapStop):                    10100000
Heap Size:                                 10000000
Stack Start(memStackStart):                10100000
Stack Stop(memStackStop):                  18100000
Stack Size:                                08000000
I/O Start(memIOStart):                     40000000
I/O Stop(memIOStop):                       FE000000
I/O Size:                                  BE000000
SysHigh Start(memSysHighStart):            FFF00000
SysHigh Stop(memSysHighStop - 1):          FFFFFFFE
InitMemory падает только на последней строчке.
Из очевидного - нужно выкинуть SysHigh (или уточнить границы), а также поправить I/O Start/Stop (он явно другой в RPi)

БудДен
Сообщения: 2839
Зарегистрирован: 07.10.18 14:01

Re: Запуск обычной версии под RPi

Сообщение БудДен » 05.09.22 22:43

Удалось создать согласованную раскладку памяти. Теперь пришли к той неприятности, что ядро в RPi загружается с адреса 8000H, а в Zynq - со 100000H, соответственно, при нашей раскладке памяти ядро будет затёрто. Ядро у нас - размером более 1 Мб, поэтому, если там где-то и есть быстрая память, то она вся будет занята ядром. Ну ок, для нашей задачи (просто работать) это некритично. Главное, чтобы вообще хоть как-то заработало.

БудДен
Сообщения: 2839
Зарегистрирован: 07.10.18 14:01

Re: Запуск обычной версии под RPi

Сообщение БудДен » 28.09.22 13:52

Начинаем кучу от 4Мб и тянем её до 256Мб + 4Мб (или просто до 256Мб). То, что раньше жило до мегабайта, ставим между 3Мб и 4Мб.

БудДен
Сообщения: 2839
Зарегистрирован: 07.10.18 14:01

Re: Запуск обычной версии под RPi

Сообщение БудДен » 28.09.22 22:23

Код: Выделить всё

ARM.Machine.Mod@88007 ЭВМ.SetFirstLevelEntry:virtual= 17F00000H; 
ARM.Machine.Mod@88059 ЭВМ.SetFirstLevelEntry:physical= 003FB400H; 
Выяснить, почему так.

БудДен
Сообщения: 2839
Зарегистрирован: 07.10.18 14:01

Re: Запуск обычной версии под RPi

Сообщение БудДен » 01.10.22 23:56

* ARM paging - https://wiki.osdev.org/ARM_Paging - там описаны виды страниц.
* inner and outer shareable - см. https://community.arm.com/support-forum ... r-in-armv7
* isb - instruction synchronization barrier
* sy - то же, системного уровня

пытаемся сопоставить процедуры инвалидации кеша (требуется перед чтением из памяти, изменённой устройством) и его сброса (требуется перед тем, как устройство прочитает память). В RPI это делается цепочкой команд

Код: Выделить всё

проц (* RPI.CPU.Mod *) Invalidate- (address: адресВПамяти);
машКод
	LDR	R0, [FP, #address]
	BIC	R0, R0, #(CacheLineSize - 1)
	MCR	P15, 0, R0, C7, C6, 1
кон Invalidate;
И годится только для одного адреса.

В Zybo - по-другому (а может это и не одно и то же вообще)

Код: Выделить всё

проц (* ARM.Machine.Mod *) DisableDCacheRange * (adr: адресВПамяти; len: размерМЗ);
	InvalidateTLBEntry(adr);
		MCR p15, 0, R0, c8, c3, 1	; invalidate address
	FlushDCachePhysRange(adr - adr остОтДеленияНа M, M, range, 1);
		если ~enableCaching и (len # 0) то
			если len остОтДеленияНа cacheline # 0 то увел(len, cacheline - len остОтДеленияНа cacheline) всё;
			(* Select cache L0 Data cache in CSSR *)
			машКод
				mov	r0, #0
				mcr	p15, 2, r0,  c0,  c0, 0	(*		mtcp(XREG_CP15_CACHE_SIZE_SEL, 0);*)
			кон;

			(* Flush all cache lines in the memory region *)
			нцДля r := 0 до numRanges - 1 делай
				cur := ranges[r].адр;
				end := cur + ranges[r].разм;
				нцПока (cur < end)  делай
					(* Flush L1 Data cache line with virtual address *)
					машКод
						ldr r3, [fp, #adr]    (* load*)
						mcr	p15, 0, r3,  c7, c14, 1;				MCR XREG_CP15_CLEAN_INVAL_DC_LINE_MVA_POC :: "r" (adr));
					кон;
					(* Flush L2 cache line with physical address *)
					НИЗКОУР.запишиОбъектПоАдресу(L2CCOffset, cur);
					cur := cur + cacheline;
					adr := adr + cacheline
				кц
			кц
		всё;
		(* Wait for L1 and L2 flush to complete *)
		машКод
			DSB
		кон;

		НИЗКОУР.запиши32битаПоАдресу(L2CCCacheSync, 1);
		нцДо кцПри НИЗКОУР.прочти32битаПоАдресу(L2CCCacheSync) = 0;

БудДен
Сообщения: 2839
Зарегистрирован: 07.10.18 14:01

Re: Запуск обычной версии под RPi

Сообщение БудДен » 02.10.22 00:10

А это вообще одно и то же или разное? (ARM.Machine.Mod/)ИнвалидируйКешДанныхДляДиапазона используется в SD, т.е реально нужен. В RPI он не видно, чтобы был реализован, в Coop.arm.machine.mod, и в Coop.Machine.Mod он пустой.

А где используется RPI-шный Invalidate? В неработающем (или непостижимом для меня) RPI.DisplayLinear.Mod:

Код: Выделить всё

		FOR address := ADDRESS OF buffer.size TO ADDRESS OF buffer.padding BY CPU.CacheLineSize DO CPU.Invalidate (address) EN
Код кратно проще, и может быть, прямо вот из него можно состряпать реализацию инвалидации кеша данных для диапазона?

БудДен
Сообщения: 2839
Зарегистрирован: 07.10.18 14:01

Re: Запуск обычной версии под RPi

Сообщение БудДен » 02.10.22 00:19

Чтобы закончить с упрощением, нужно попытаться выкинуть мелкие страницы и обойтись крупными, как в RPI. Мелкие страницы, как я понял, нужны только для кеша.

БудДен
Сообщения: 2839
Зарегистрирован: 07.10.18 14:01

Re: Запуск обычной версии под RPi

Сообщение БудДен » 04.10.22 16:04

С повреждениями, но MMU инициализировался. Теперь падаем на инициализации таймера. Однако, т.к. мы упразднили второй уровень таблиц вирт. памяти, у нас теперь не работает

AllocatePage <- NewStack <- NewProcess <- ARM.Objects.Mod/CreateProcess

При этом, NewStack сам находит свободную страницу, поэтому можно не волноваться. Нужно волноваться лишь о:
* том, чтобы начало стека было выровнено под 1Мб
* предельный размер стека равен maxUserStackSize = 2Мб
*

Код: Выделить всё

InitStackSize = размерМаленькойСтраницы;
StackGuardSize = размерМаленькойСтраницы;
здесь заменить на большую страницу. Выделять в AllocatePage большую, а не маленькую страницу.
Поменять порядок подсчёта во freeStack и т.п.

БудДен
Сообщения: 2839
Зарегистрирован: 07.10.18 14:01

Re: Запуск обычной версии под RPi

Сообщение БудДен » 04.10.22 16:16

Пока стек отложим и разберёмся с таймером. GlobalTimerCounterRegister и иже с ним, используются в
ARM.Machine.Mod/ДайКвоТактовПроцессораСМоментаПерезапуска, а также в Zynq.Timer.Mod, параллельный которому в RPI называется RPI.Timer.Mod и там уже есть нужный код. Короче, наверное, тут ясно, что и как поправить, и на этом мы поставим точку с запятой.

БудДен
Сообщения: 2839
Зарегистрирован: 07.10.18 14:01

Re: Запуск обычной версии под RPi

Сообщение БудДен » 05.10.22 01:45

Дошёл до инициализации модуля Modules. В Init есть загадочные строчки о том, что что-то инициализируется компоновщиком и мы падаем до входа в тело модуля. Наверное, что-то там пошло не так - надо изучать код линкера. Как вариант, код, подмешанный линкером, выделяет динамическую память и это его губит.

БудДен
Сообщения: 2839
Зарегистрирован: 07.10.18 14:01

Re: Запуск обычной версии под RPi

Сообщение БудДен » 06.10.22 21:11

Ну вот, мы доехали до ситуации, когда оказалось, что ядро должно было быть внутри кучи. А мы разместили всяческие "убежища" выше ядра, но ниже кучи. Теперь нужно их перемещать и возникает снова две системных области - нижняя и верхняя. А мы уже это выпилили. Что ж, придётся обратно впилить.

БудДен
Сообщения: 2839
Зарегистрирован: 07.10.18 14:01

Re: Запуск обычной версии под RPi

Сообщение БудДен » 07.10.22 01:59

ндя, чем больше я всё это курочу, тем крепче убеждение, что придётся в какой-то момент всё начать заново.

БудДен
Сообщения: 2839
Зарегистрирован: 07.10.18 14:01

Re: Запуск обычной версии под RPi

Сообщение БудДен » 12.10.22 00:51

Дошёл до InitProcessors - стек вроде удалось выделить. Посоветовали такой источник знаний:

https://arm-software.github.io/CMSIS_5/ ... index.html

БудДен
Сообщения: 2839
Зарегистрирован: 07.10.18 14:01

Re: Запуск обычной версии под RPi

Сообщение БудДен » 12.10.22 11:38

Дмитрий Фролов накидал ссылок:

https://forums.raspberrypi.com/viewtopic.php?t=268543

https://github.com/s-matyukevich/raspbe ... /rpi-os.md

Вот тут загрузчик, может там есть что-то что нужно https://github.com/ultibohub/Core/blob/ ... otrpi2.pas

БудДен
Сообщения: 2839
Зарегистрирован: 07.10.18 14:01

Re: Запуск обычной версии под RPi

Сообщение БудДен » 12.10.22 13:44

Докатился до таймера. Таймер - это прерывание номер 27. В Zynq есть переменная - массив обработчиков, иииии тут нахожу, что тело процедуры InitInterrupts полностью пропущено, поставлен возврат в самом начале. А упёрся я в "distribution control register", который является частью какого-то там mpcore, о котором в кооп версии не написано ничего. Теперь нужно выяснить, есть ли такое вообще в RPi. Вспоминаю, что я уже начинал это делать, но решил отложить на потом. И вот, потом наступило.

https://www.macs.hw.ac.uk/~hwloidl/Cour ... p5_trm.pdf

БудДен
Сообщения: 2839
Зарегистрирован: 07.10.18 14:01

Re: Запуск обычной версии под RPi

Сообщение БудДен » 13.10.22 21:53

Ну вот, пропала прекрасная запись. В ultibo нашёл:

* TInitTimer - может быть полезной
* BCM2836 в RPi2, но модуль в ultibo сделан на базе BCM2835, т.к. информации по 2836 не было (и, видимо, нету по сей день)
* В модуле BCM2836 написано:

Код: Выделить всё

BCM2836_SYSTEM_TIMER_REGS_BASE = BCM2836_PERIPHERALS_BASE + $3000;
Это похоже на то, что в A2/ЯОС называется "таймером" (модуль RPI.Timer.Mod и далее
RPI.CPU.Mod:

Код: Выделить всё

конст STCLO* = 03F003004H; STCHI* = 03F003008H;
Согласно пункту 14.1, именно этот таймер работает с фиксированной частотой, значит он-то нам и нужен. Конечно, есть ещё другие таймеры, работающие с системной частотой процессора, но будем надяеться, что нам пока нужен только один таймер. Будем верить это, пока не столкнёмся с обратным.

БудДен
Сообщения: 2839
Зарегистрирован: 07.10.18 14:01

Re: Запуск обычной версии под RPi

Сообщение БудДен » 14.10.22 13:25

В Ultibo нашёл файл BootRPI2, может быть, его чтение чем-то поможет.

А также в mrvn есть пример 7 именно про "тот" таймер и его прерывание.

https://github.com/mrvn/RaspberryPi-bar ... d-to-chill

БудДен
Сообщения: 2839
Зарегистрирован: 07.10.18 14:01

Re: Запуск обычной версии под RPi

Сообщение БудДен » 16.10.22 21:49

Философский вопрос: какой из таймеров отвечает за переключение задач?

ARM.Objects.Mod/InstallHandler при каких-то обстоятельствах назначает обработчик с помощью
ARM.Machine.Mod/InstallHandler, передавая ему обработчик, называемый FieldIRQ. Этот обработчик
вызывает Enter, содержит переменную preempt, а также вызывает Select. Т.е. гипотеза, что переключение
происходит по прерыванию таймера, вроде подтверждается. Но похоже, что не только таймер может приводить к переключению,
а и другие обработчики тоже. Но условие с FieldIRQ выглядит мутным и слёту кажется, что оно вообще не должно выполняться никогда.

Поищем, кто ещё вызывает Select и Enter...

ARM.Objects.Mod/Timeslice - "preempt the current process". Кто вызывает Timeslice? Прежде всего,
одноимённое поле Timeslice типа Handler (а Handler - процедура, принимающая состояние процессора, что бы это ни значило), и рядышком с ним - поле timer: EventHandler - оба, как написано, для вытесняющей многозадачности.

БудДен
Сообщения: 2839
Зарегистрирован: 07.10.18 14:01

Re: Запуск обычной версии под RPi

Сообщение БудДен » 16.10.22 22:13

Код: Выделить всё


ARM.Objects.Mod/Timeslice
  HandleMPTimer 
    Не используется
  HandleUPTimer
    InstallHandler(HandleUPTimer, PrivateTimerIRQ);
  инициализация ARM.Kernel.Mod - присваивается ЭВМ.Timeslice := Objects.Timeslice;
 
ARM.Objects.Mod/timer
  HandleMPTimer
  HandleUPTimer
  InstallEventHandler (присваивает переменной timer)
    
Видимо UP - это как раз Private timer.

Итак, теперь нам нужно в ARMv9 понять, что такое Private Timer, и по возможности найти такой же в BCM2836 (и в QEMU).
Последний раз редактировалось БудДен 16.10.22 22:38, всего редактировалось 1 раз.

БудДен
Сообщения: 2839
Зарегистрирован: 07.10.18 14:01

Re: Запуск обычной версии под RPi

Сообщение БудДен » 16.10.22 22:32

Или хоть какой-нибудь таймер... https://forums.raspberrypi.com/viewtopi ... 3#p1315584 - тут пишут обнадёживающе:
Looking at the QEMU source it seems it still does not support he System Timer device in the Raspberry Pi emulation.

However the -M raspi2 and -M raspi3 emulations do include the ARM generic timer device (per processor core) and it does appear to have the interrupts connected so you should be able to use that one instead.

See the appropriate ARM Architecture Reference Manual for details of programming the generic timer.
Осталось лишь, чтобы и наша QEMU это поддерживала.

О, и даже ссылки на примеры, это очень хорошо:

https://github.com/eggman/raspberrypi/t ... i2/timer01

Правда примеры работают только в QEMU, но не на железке, это уже хуже.

БудДен
Сообщения: 2839
Зарегистрирован: 07.10.18 14:01

Re: Запуск обычной версии под RPi

Сообщение БудДен » 23.10.22 14:17

Поскольку есть аж два системных таймера и прерывания от них работают, можно отправить 2 ядра в простой, и сделать 2-ядерную ОС.

БудДен
Сообщения: 2839
Зарегистрирован: 07.10.18 14:01

Re: Запуск обычной версии под RPi

Сообщение БудДен » 23.10.22 22:41

https://forums.raspberrypi.com/viewtopi ... 1&p=922616 - вот тут вроде бы решение, хотя это ещё надо посмотреть.

БудДен
Сообщения: 2839
Зарегистрирован: 07.10.18 14:01

Re: Запуск обычной версии под RPi

Сообщение БудДен » 25.10.22 01:06

Дошёл до несуществующей инструкции cpsie i

Ответить