Risc v linux 64 bit

Часть 4: Всё-таки запускаем Linux на RocketChip RISC-V

На картинке Linux kernel шлёт вам привет через GPIO.

В этой части истории с портированием RISC-V RocketChip на китайскую плату с Cyclone IV мы всё-таки запустим Linux, а также научимся сами конфигурировать IP Core контроллера памяти и чуть подредактируем dts-описание аппаратуры. Эта статья является продолжением третьей части, но, в отличие от изрядно разросшейся предыдущей, она будет довольно короткой.

… Поскольку setup_smp вызывается, только если ядро сконфигурировано с поддержкой SMP, можно попробовать отключить многоядерность. Будет неприятно, если мне нужно будет ещё и реализовывать в модуле памяти поддержку атомарности (мне казалось, с этим кеш возится самостоятельно), но в одноядерном случае оно нам помешать не должно.

Занятно, что после всей отладки я решил посмотреть, как должен выглядеть «референсный» вывод ядра, сказал make qemu , и увидел аналогичную ошибку.

Увы, следующий уровень (Linux kernel) сложнее: GDB, подключённый через JTAG к RocketChip, работает, по-видимому, с физическими адресами вне зависимости от того, как настроено MMU, а ядро в интересующий нас момент уже настроило отображение адресов, поэтому просто сказать display/10i $pc не получится — увидим лишь много unimp . Зато, если мы уже выяснили смещение (похоже, что 0x80200000 -> 0xffffffe000000000 ), то можно схитрить:

Брекпоинты проставляются аналогично:

Вот только их приходится вручную снимать, чтобы пойти дальше — для GDB это какой-то совершенно непонятный trap. Ах да, если вы случайно скажете s или n вместо si , gdb попытается вставить неявный брекпоинт, который по понятным причинам не выставится, но и отговорить GDB уже никак. Но не спешите перезагружать плату — по моим наблюдениям, достаточно перезапустить только gdb (учтите, что старые breakpoint-ы, возможно, не исчезнут).

Собственно, придётся разбираться с изначальной проблемой: расстановка отладочных printk в функцию of_find_node_by_type , используемую кодом поиска загрузочного процессорного ядра, показывает, что оно видит какой-то мусор вместо названий типов устройств. Например, оно откуда-то берёт строчку «Serial port», хотя такого явно нет в dtb в поле device_type . Поискав эти байты в образе ядра, я их нашёл, посмотрел на смещение, и понял очевидное: размер ядра в параметрах загрузки явно недооценён: ему выделено 8Mb, а занимает оно больше десяти. Выделил 16Mb, но странности не прекратились. После плясок с чтением FDT с разных адресов (штатно адрес передаётся ядру в регистре a1 ), я, наконец, решил трассировать, а что же сейчас там парсится. К счастью, вместо хождений с отладчиком (а мы помним, что есть нюансы с трансляцией адресов, которые ещё нужно так или иначе решить), можно просто и костыльно в файле drivers/of/fdt.c указать #define pr_debug printk . В итоге получилось:

(«Таймстемпнутыми» строчки выводит ядро, перед ними дерево выводит BBL) С одной стороны, FDT успешно читается, с другой — получается какая-то чепуха в распарсенном «объектном» дереве.

В процессе отладки я понял, что BBL не мог прочитать «двойной» адрес не потому, что в конфиге была ошибка, а просто потому, что у корневого узла был выставлен #address-cells = ; #size-cells = ; .

Расширив отладочный вывод, я увидел, что указатели на type и name «побились», причём довольно странным образом: у них обнулился первый (начиная с нуля) байт, что-то вроде 0xabcdef -> 0xab00ef . Пришлось воспользоваться знакомой тактикой: зная адреса, по которым находится повреждённая память, дописать в функцию printk печать этих данных. Ну и самих вызовов printk пораскидать, где их мало. Увы, сильно понятнее не стало. Тогда я стал, сверяясь с дизассемблированной objdump версией, вручную расставлять breakpoint-ы и по шагам проходить проблемный участок кода. И тут обнаружилось загадочное и неприятное: если сразу поставить точку останова куда-нибудь относительно далеко от known-good состояния, то, остановившись на ней, я увижу уже повреждённую память. Но если попытаться тихо подкрасться к ней по шагам, то ошибка успевает спрятаться! Дело пахнет битым контроллером памяти и кешом, скрывающим ошибку, если постоянно запрашивать нужное значение. А что если.

Читайте также:  Как можно загрузить windows

Заменяем память

Цепляясь за возможность решить проблему не на своей стороне, я предположил, что, может, мне просто пришла битая планка памяти. Тут я вспомнил, что нетбук десятилетней давности — это не только портативный компьютер, но и ценный источник DDR2 SO-DIMM. Бонусом, в него можно засунуть вынутую из платы память, и получить почти мгновенное зависание Memtest (Linux, кстати, при этом грузился почти до графической оболочки. Но лучше не повторяйте такой эксперимент, если вам дорога информация на подмонтированных дисках. ). С одной стороны, можно предположить, что просто память не подошла конкретно к этому нетбуку. С другой стороны, он же смог загрузиться! Появилась надежда, что просто память «битая», и проблема не в моей обёртке.

Значит, нужно попробовать временно запуститься с нетбучной памятью. К сожалению, Quartus 18 не умеет апгрейдить этот IP Core так, чтобы его можно было редактировать. Значит, всё-таки пришло время научиться создавать новые инстансы. Всё оказалось довольно просто: ищем в IP Catalog пункт DDR2 SDRAM Controller with ALTMEMPHY Intel FPGA IP и получаем блок с таким же интерфейсом, как и раньше. Единственная проблема — это выставить правильные настройки памяти.

Получаем параметры модуля памяти

Есть относительно очевидный способ настроить модуль: прочитать параметры из SPD. Действительно, если обычный компьютер вычитывает данные SPD и настраивает по ним контроллер, то давайте вычитаем эти данные на имеющемся нетбуке и вобьём их в табличку.

На Ubuntu это делается весьма нехитро: нужно поставить пакет i2c-tools , загрузить модули eeprom и i2c-i801 (не уверен, правда, что второй драйвер подойдёт везде), после чего запустить decode-dimms :

Проблема в том, что некоторых таймингов здесь не указано, поэтому пойдём по второму пути.

Что у нас написано на модулях:

В данном случае интереснее надпись на самих микросхемах памяти: K4T1G164QQ-HCF7. Забив эту строчку в Гугл, получаем datasheet на несколько десятков страниц со всеми необходимыми параметрами, которые можно аккуратно перебить в свойства IP Core. Только обращайте внимание на единицы измерения: где-то ns , где-то — ps , а иногда и вообще доли tCK . Учить вас, на что нужно обращать внимание, я не буду — сам многое настраивал методом тыка (не могу при этом гарантировать, что так нельзя «сжечь» память или ПЛИС). Обращу лишь внимание вот на что: я очень долго не мог заставить контроллер работать, и последним шагом было осознание, что нужно проверить ширину всех интерфейсов к памяти на соответствие сгенерированному коду на Verilog: ведь когда в MemIfBundle указан val mem_ba = IO(Output(UInt(2.W))) , а банков 8 (т.е. адрес шириной 3 бита), то всё, что у нас есть — висящий в воздухе output из контроллера памяти — проблема, но не критическая, поэтому всё синтезируется, но не работает.

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

Итак, после перемещения timebase-frequency в DTS с уровня конкретного CPU на уровень узла cpus (по вполне понятно сказанной просьбе ядра), получаем:

Читайте также:  Создать загрузочный раздел linux

После чего ничего видимого не происходит.

Теперь можно попробовать побороться с тремя проблемами:

… а также с прекращением вывода в консоль.

С двумя проблемами с частотами побороться совсем несложно: нужно добавить пункты clocks в поддеревья требуемых устройств, для удобства дав понятное имя метки для узла tlclk :

Добавив строчку #define pr_debug printk в начало файла init/initramfs.c , выводящего сообщение про мусор вместо initramfs получаем чуть более подробное сообщение:

То есть, возможно, мусор не вместо initramfs, а вместе.

Окей, что-то он нашёл, может, и этого достаточно. А куда делась консоль? Поиск даёт ссылку на issue на Гитхабе: linux failed to bringup on vc707 board — оказывается, один UART это, по мнению драйвера, даже не стоит разговоров. Но исправление датировано 11 июля 2018 года — год назад. Оказалось, этот коммит так и не попал в дерево, из которого у меня собирается ядро. Вручную применив этот патч, я получил работающий Линукс! Оказалось, с initramfs проблема была, действительно, не критичная.

Залогинившись как user=root, password=sifive, я смог без особых проблем (кроме того, чтобы понять, что у номера GPIO есть base, от которого всё считается, и который просто нужно прочитать из соответствующего псевдо-файла) через sysfs зажечь светодиод на плате.

Как и в прошлый раз, прикладываю текстовое видео запуска Linux. В момент переключения консоли с earlyprintk на штатную идёт какой-то мусор, похожий на вывод при неправильно выставленной скорости UART. Что интересно, плеер успешно отработал эту «кашу».

Источник

Risc v linux 64 bit

Build Fedora Gnome Desktop on RISC-V!!

The intent of this document is to share the hardware setup and source code build instructions to bring up Fedora 29 GNOME desktop on HiFive Unleased board. It is assumed that you know how to set up a RISC-V development environment. If not please follow the instructions below using the freedom-u-sdk.

Let’s get back to the problem at hand i.e. Setup Fedora 29 GNOME desktop on RISC-V! Here is the hardware used for our setup.

HiFive Unleashed (This is the only Linux capable RISC-V board)

Microsemi HiFive Unleashed Expansion board (available from Crowd Supply)

  • Again, this is the only expansion board available with multiple I/O Support
  • However, only PCIe, SATA, M.2 SSD connectors are enabled right now.

Radeon HD 6450 GPU card

  • Any Caicos-based card should be OK, but the kernel config instructs specific firmware to be used. It is recommended to use the above specific GPU as it is verified. In case you want to use any other GPU, load the appropriate firmware accordingly.
  • The GPU uses x16 PCI Express card connector.

PCIe to USB card (I have used this)

  • x1 PCI Express card connector can be used to provide USB ports for mouse/keyboard.

SATA Drive(HDD/SSD) or NVMe SSD. This is where the Fedora image will be copied. It is not recommended to use an image from a micro SD card.

FYI: NVMe SSD should be connected via the NVMe M.2 connector present at the bottom of the expansion card. The board layout is available here

The current upstream kernel (v4.19-rc2) boots in QEMU for RISC-V. However, it is still missing some of the HiFive Unleashed specific drivers. That’s why the Linux kernel source tree also has to be hosted out of mainline tree.

riscv-linux-conf:

It contains the required Linux config file for this project. This needs to be copied to freedom-u-sdk conf directory.

Читайте также:  Ccleaner для windows njhhtyn

N.B. The Linux config file will only work for HiFive Unleashed board with a GPU card. You can’t use this in a QEMU setup. Mainline kernel 4.19-rc2 should boot in QEMU without any issues.

riscv-linux:

It is based on 4.19-rc2 and contains all required drivers and a couple of kernel hacks. Here is the summary of out-of-tree commits:

riscv-pk:

This repository builds the BBL (Berkely Boot Loader) for RISC-V project. To use the Microsemi expansion board, the DT in HiFive Unleashed board has to be updated unless you have the latest firmware with updated DT. In that case, you don’t need this change.

patches:

All the above patches are copied here in separate directories according to the projects.

resources:

This contains the dmesg, lspci & devicetree output for verification purpose.

The build instructions are based on freedom-u-sdk setup only on Ubuntu 16.04. It may not work correctly if you are using your own toolchain.

If you are using your own toolchain build, you can just compile the riscv-pk and riscv-linux separately and use the bbl.bin image. You should directly apply these patches on top of your tree as well instead of checkout procedure explained below. Here is commit head on which patches should be applied.

  • Clone RISC-V-Linux project from github.
  • Checkout riscv-pk repo from the RISC-V-Linux project.

Now the new BBL will add Microsemi specific PCIe entry to the device tree. You can always verify the device tree entry by adding ‘—enable-print-device-tree’ option to the root Makefile in freedom-u-sdk as per below diff.

  • Checkout Linux repo from RISC-V-Linux project. This will bring all the out-of-tree kernel patches on top of 4.19-rc2 to your Linux repo.
  • Copy the Linux config from this repo to your freedom-u-sdk directory. The current config mounts the Fedora image to the first partition of the disk. The present config file has two options
    • SATA SSD (root=/dev/sda1)
    • NVME SSD (root=/dev/nvme0n1p1) Enable/disable correct CONFIG_CMDLINE config based on your setup.
  • Update freedom-u-sdk Makefile to use the just copied config. Apply the below diff
  • Recompile the kernel (from freedom-u-sdk repo).
  • copy the bbl file to the first partition of your microSD card (i.e. /dev/disk2s1 in this case ).
  • Download the latest Fedora Gnome Desktop stage4 image from this link.

The disk image (above) is partitioned, but usually we need an unpartitioned («naked») filesystem.

This creates a naked ext4 filesystem called *-sda1.raw . The naked ext4 filesystem can be copied to the first partition of your disk.

(The drive should be connected to your Desktop/Laptop. If it is recognized as something other than /dev/sda1, please change accordingly.)

  • Now connect the hard drive in appropriate slot on Expansion board.
  • Connect the power to the Expansion board only. It powers the unleashed board as well.
  • Turn on the Unleashed switch.
  • Turn on the Expansion board switch.
  • Connect to the serial terminal. If a display is connected, you should Fedora prompt in a while. Once you are done with the initial Fedora setup process in the screen, you may have to reboot the system.

Welcome to RISC-V Fedora Desktop!!

Acknowledgement:

[1] Fedora image instructions are available from this page.

(Responsible for Fedora builds and numerous help over irc)

Источник

Оцените статью