In Er is een meer of minder werkende geheugencontroller gerealiseerd, of beter gezegd — een wrapper bovenop de IP Core uit Quartus, die als een overgang fungeert naar TileLink. Vandaag in de rubriek 'We porteren RocketChip naar een onbekende Chinese plaat met een Cyclone' zie je een werkende console. Het proces heeft iets langer geduurd: ik dacht dat ik Linux snel zou kunnen opstarten en dan verder zou gaan, maar zo ging het niet. In dit deel stel ik voor om naar het opstartproces van U-Boot, BBL, en de aarzelende pogingen van de Linux-kernel om te initialiseren te kijken. Maar er is een console — de U-Boot-console, en behoorlijk geavanceerd, met veel van wat je van een volwaardige console zou verwachten.
In de hardwaresectie zal er een SD-kaart worden toegevoegd, aangesloten via de SPI-interface, evenals UART. In de softwaresectie zal de BootROM worden vervangen door xip en een werkende opdracht krijgen. sdboot en bovendien worden de volgende opstartfasen toegevoegd (op de SD-kaart).
Fijnslijpen van de hardwaresector
Dus de taak is: we moeten overstappen op de 'grote' kern en de UART (van Raspberry) en SD-adapter aansluiten (er werd een of andere printplaat van Catalex gebruikt met zes pinnen: GND, VCC, MISO, MOSI, SCK, CS).
In principe was alles vrij eenvoudig. Maar voordat ik dat besefte, werd ik een beetje van de hak op de tak gestuurd: na de vorige keer besloot ik dat ik gewoon weer een beetje moest mengen in Systeem iets als HasPeripheryUART (en in de implementatie overeenkomstig), hetzelfde voor de SD-kaart — en alles zou klaar zijn. Toen besloot ik te kijken, hoe het in een 'serieus' ontwerp is geïmplementeerd. Dus, wat hebben we hier van iets serieus? Arty is vermoedelijk niet geschikt — de monster unleahshed.DevKitConfigs. En plots ontdekte ik dat er overal overlays zijn die worden toegevoegd via parameters door middel van sleutels. Ik vermoed dat dit waarschijnlijk heel flexibel en configureerbaar is, maar ik zou in ieder geval iets willen opstarten... Hebben jullie niets vergelijkbaars, maar dan eenvoudiger en minder gecompliceerd? Hier stuitte ik op vera.iofpga.FPGAChip voor Microsemi FPGA en meteen uit elkaar gehaald op citaten probeerde een eigen implementatie te maken naar analogie, gelukkig staat hier meer dan genoeg de 'bedrading van de systeemkaart' in één bestand.
Het bleek inderdaad simpelweg nodig om in System.scala de regels toe te voegen
class System(implicit p: Parameters) extends RocketSubsystem
...
with HasPeripherySPI
with HasPeripheryUART
...
{
val tlclock = new FixedClockResource("tlclk", p(DevKitFPGAFrequencyKey))
...
}
class SystemModule[+L <: System](_outer: L)
extends RocketSubsystemModuleImp(_outer)
...
with HasPeripheryUARTModuleImp
with HasPeripheryGPIOModuleImp
...De regel in de body van de klasse Systeem voegt informatie toe over de frequentie waarop dit deel van onze SoC werkt in het dts-bestand. Zover ik begrijp, is DTS/DTB een statisch equivalent van plug-and-play technologie voor ingebedde apparaten: de dts-beschrijving wordt gecompileerd naar een binaire dtb-bestand en doorgegeven aan de bootloader van de kernel, zodat deze de hardware correct kan configureren. Interessant genoeg, zonder de regel met tlclock synthese verloopt perfect, maar het BootROM compileren (ter herinnering, dit zal nu al) sdboot) is niet mogelijk — tijdens het compileren parseert het dts-bestand en genereert een header met de macro TL_CLK, waardoor het in staat zal zijn om de frequentiedelers voor externe interfaces correct in te stellen.
Bovendien moet de "lay-out" een beetje worden aangepast:
Platform.scala:
class PlatformIO(implicit val p: Parameters) extends Bundle {
...
// UART
io.uart_tx := sys.uart(0).txd
sys.uart(0).rxd := RegNext(RegNext(io.uart_rx))
// SD kaart
io.sd_cs := sys.spi(0).cs(0)
io.sd_sck := sys.spi(0).sck
io.sd_mosi := sys.spi(0).dq(0).o
sys.spi(0).dq(0).i := false.B
sys.spi(0).dq(1).i := RegNext(RegNext(io.sd_miso))
sys.spi(0).dq(2).i := false.B
sys.spi(0).dq(3).i := false.B
}Registerketens zijn eerlijk gezegd simpelweg toegevoegd ter analogie met enkele andere plekken uit de oorspronkelijke code. Waarschijnlijk moeten ze beschermen tegen . Misschien hebben sommige modules al hun eigen bescherming, maar in eerste instantie wil ik in ieder geval "op een kwalitatief niveau" draaien. Een interessanter voor mij vragen is waarom MISO en MOSI aan verschillende dq Fysiek heb ik de ontwerppinnen toegewezen aan vrije contacten op de connector en de spanningsselectieschakelaar verplaatst naar 3.3V.? Ответа я пока так и не нашёл, но, похоже, остальной код рассчитывает именно на такое подключение.
SD-adapter
Bovenaanzicht:
Onderzicht:

Debugging van de softwarecomponent: tools

Laten we beginnen met de beschikbare debugtools en hun beperkingen.
Minicom
Ten eerste moeten we de output van de bootloader en de kernel kunnen lezen. Hiervoor hebben we op Linux (in dit geval op de Raspberry Pi) het programma Minicom nodig. In principe is elke programma die met een seriële poort werkt geschikt.
Let op dat je bij het starten de apparaatsnaam van de poort moet opgeven als
-D /dev/ttyS0 — na de optie . En de belangrijkste informatie: gebruik om af te sluiten -DCtrl-A, X . Ik had trouwens een geval waarin deze combinatie niet werkte — dan kun je gewoon vanuit een andere SSH-sessie zeggenkillall -KILL minicom killall -KILL minicom.
Er is nog een ander kenmerk. Specifiek voor Raspberry Pi zijn er twee UART's en beide poorten kunnen al voor iets worden gebruikt: één voor Bluetooth, en via de andere wordt standaard de kernconsole weergegeven. Gelukkig kan dit gedrag worden opnieuw ingesteld. .
Het herschrijven van geheugen.
Tijdens het debuggen moest ik om mijn hypothese te controleren soms de bootloader laden (sorry) in het RAM rechtstreeks vanaf de host. Misschien kan dit direct vanuit GDB, maar ik koos uiteindelijk de simpele weg: ik kopieerde het benodigde bestand naar de Raspberry, tunneelde ook poort 4444 (telnet van OpenOCD) via SSH en gebruikte het commando load_image.Wanneer je dit uitvoert, lijkt alles vast te lopen, maar in werkelijkheid «slaapt het niet, het knippert gewoon langzaam»: het laadt het bestand, maar doet dit met een snelheid van een paar kilobyte per seconde.
Kenmerken van het instellen van breakpoints.
Waarschijnlijk hebben velen hier niet over nagedacht tijdens het debuggen van gewone programma's, maar breakpoints worden niet altijd hardwarematig ingesteld. Soms bestaat het instellen van een breakpoint eruit om tijdelijk een speciale instructie op de juiste plek direct in de machinecode. Bijvoorbeeld, zo functioneerde de standaardopdracht b in GDB. Dit is wat daaruit voortkomt:
- je kunt geen breakpoint binnen de BootROM plaatsen, omdat ROM
- je kunt een breakpoint plaatsen op de code die naar het RAM is geladen vanaf de SD-kaart, maar je moet wachten tot deze is geladen. Anders herschrijven wij een stukje code, en herschrijft de bootloader onze breakpoint.
Ik ben er zeker van dat je expliciet kunt vragen om hardware breakpoints te gebruiken, maar in ieder geval is hun aantal beperkt.
Snelle vervanging van BootROM.
In de vroege fase van het debuggen ontstaat vaak de wens om de BootROM aan te passen en het nog eens te proberen. Maar er is een probleem: de BootROM maakt deel uit van het ontwerp dat in de FPGA wordt geladen, en de synthese ervan duurt enkele minuten (en dat is nog na de bijna directe compilatie van de BootROM afbeelding uit C en Assembler…). Gelukkig is het in werkelijkheid veel sneller: de reeks handelingen is als volgt:
- genereer bootrom.mif opnieuw (ik ben overgestapt op MIF in plaats van HEX, omdat ik voortdurend problemen had met HEX, en MIF is het native Altera-formaat)
- in Quartus zeg
Processing -> Update Memory Initialization File - bij de Assembleeroptie (in de linker kolom Taken) beveel je Start opnieuw aan.
Voor alles samen — een paar tientallen seconden.
Voorbereiding van de SD-kaart.
Hier is alles relatief eenvoudig, maar je moet geduld hebben en ongeveer 14 Gb schijfruimte reserveren:
git clone https://github.com/sifive/freedom-u-sdk
git submodule update --recursive --init
makeVervolgens moet je een schone, of beter gezegd, een lege SD-kaart invoegen en uitvoeren
sudo make DISK=/dev/sdX format-boot-loader… waar sdX — het apparaat is toegewezen aan de kaart. LET OP: alle gegevens op de kaart worden gewist, overschreven en, over het algemeen! Het lijkt me niet handig om de hele build vanuit sudote doen, omdat dan alle build-artefacten aan roottoebehoren, en je moet de build vanuit sudo doen.
Uiteindelijk krijg je een kaart die is ingedeeld in GPT met vier partities, waarvan er één FAT heeft met uEnv.txt en een opstartafbeelding in FIT-formaat (die bevat meerdere subafbeeldingen, elk met zijn eigen laadadres), de andere partitie is leeg en is bedoeld om als Ext4 voor Linux te formatteren. De laatste twee partities zijn mysterieuze: op één daarvan leeft U-Boot (de offset daarvan is, voor zover ik begrijp, ingebakken in de BootROM), op de andere lijken zijn omgevingsvariabelen te leven, maar die gebruik ik voorlopig nog niet.
Niveau één, BootROM
Volkswijsheid zegt: "Als er dansen met een trommel zijn in programmeren, dan is er in elektronica ook nog dansen met een brandblusser". Het gaat er niet eens om dat ik een keer bijna de printplaat verbrandde, omdat ik dacht: "Nou, GND is toch hetzelfde als een laag niveau" (waarschijnlijk zou een weerstand toch wel helpen...) Het gaat eerder om het feit dat als je handen niet daar vandaan komen, elektronica je niet stopt met verrassen: terwijl ik de connector op de printplaat soldeerde, lukte het me niet om de contacten goed te solderen — op video laten ze zien hoe het lood zich vanzelf over de hele verbinding verspreidt, alleen de soldeerbout erbij houden, maar bij mij 'stippelde' het gewoon overal. Misschien was het lood niet geschikt voor de temperatuur van de soldeerbout, misschien nog iets anders... Kortom, toen ik zag dat ik al een tiental contacten had, gooide ik het op en begon ik met debuggen. En toen begon het mysterieuze: ik sloot RX/TX van de UART aan, laad de firmware — en het zegt
INIT
CMD0
ERRORNou, dat is logisch — de SD-kaartmodule had ik niet aangesloten. We herstellen de situatie, laden de firmware... En stilte... Wat ik ook niet heb gedacht, maar het deurje was gewoon te openen: één van de pinnen van de module moest op VCC worden aangesloten. In mijn geval ondersteunde de module 5V voor voeding, dus ik plugde de draad die van de module kwam aan de andere kant van de printplaat. Uiteindelijk sloeg de scheef gesoldeerde connector scheef, ik ben gewoon het UART-contact kwijtgeraakt. facepalm.jpg In het algemeen, "een dom hoofd geeft de voeten geen rust", en kromme handen — het hoofd…
Uiteindelijk zag ik in Minicom het langverwachte
INIT
CMD0
CMD8
ACMD41
CMD58
CMD16
CMD18
LOADING /Bovendien draait de groene laadindicator. Het doet me denken aan de schooltijd en de langzame opstart van MinuetOS vanaf een floppy. Behalve dat de diskdrive niet krast.
Het probleem is dat er na het BOOT-bericht niets meer gebeurt. Dat betekent dat het tijd is om via OpenOCD op de Raspberry aan te sluiten, GDB op de host, en te kijken wat er aan de hand is.
Ten eerste toonde de verbinding met GDB onmiddellijk aan dat $pc (program counter, adres van de huidige instructie) verdwijnt in 0x0 — waarschijnlijk gebeurt dit na een meerdere fout. Daarom, direct na het verzenden van het bericht BOOT voegen we een oneindige lus toe. Dit zal hem even tegenhouden…
diff --git a/bootrom/sdboot/sd.c b/bootrom/sdboot/sd.c
index c6b5ede..bca1b7f 100644
--- a/bootrom/sdboot/sd.c
+++ b/bootrom/sdboot/sd.c
@@ -224,6 +224,8 @@ int main(void)
kputs("BOOT");
+ while(*(volatile char *)0x10000){}
+
__asm__ __volatile__ ("fence.i" : : : "memory");
return 0;
}Zo'n slimme code wordt gebruikt "voor betrouwbaarheid": ik heb ergens gehoord dat, als het goed is, een oneindige lus — dat is Undefined Behavior, en hier zal de compiler waarschijnlijk niet raden (ter herinnering, dat 0x10000 is BootROM).

Het zou vanzelfsprekend moeten zijn — zware embedded, welke bronbestanden zijn hier te verwachten. Maar dat de auteur debugde C-code… Kreks-feks-peks:
(gdb) file builds/zeowaa-e115/sdboot.elf
Een programma wordt al gedebugd.
Weet je zeker dat je het bestand wilt veranderen? (y of n) y
Symbolen worden ingelezen van builds/zeowaa-e115/sdboot.elf...klaar.
Je moet niet het MIF-bestand en niet de bin laden, maar de originele versie in ELF-formaat.
Nu kun je met de n-de poging het adres raden waar de uitvoering verdergaat (dit is nog een reden waarom de compiler niet had moeten raden dat de lus — oneindig was). Het commando
set variable $pc=0xADDRstaat je toe om de waarde van het register on-the-fly te veranderen (in dit geval — het adres van de huidige instructie). Hiermee kun je ook waarden veranderen die in het geheugen zijn opgeslagen (en memory-mapped registers).
Uiteindelijk kwam ik tot de conclusie (waarvan ik niet zeker weet of het correct is), dat we "de sd-kaart afbeelding van dat systeem" hebben, en dat we niet naar het begin van de geladen gegevens moeten gaan, maar naar 0x89800 een byte verder:
diff --git a/bootrom/sdboot/head.S b/bootrom/sdboot/head.S
index 14fa740..2a6c944 100644
--- a/bootrom/sdboot/head.S
+++ b/bootrom/sdboot/head.S
@@ -13,7 +13,7 @@ _prog_start:
smp_resume(s1, s2)
csrr a0, mhartid
la a1, dtb
- li s1, PAYLOAD_DEST
+ li s1, (PAYLOAD_DEST + 0x89800)
jr s1
.section .rodataMisschien heeft het ook te maken met het feit dat ik, zonder een ongewenste kaart van 4Gb bij de hand te hebben, een 2Gb kaart heb genomen en door middel van trial-and-error heb ik het in de Makefile vervangen. DEMO_END=11718750 en een werkende opdracht krijgen. DEMO_END=3078900 (zoek geen betekenis in de specifieke waarde — die is er niet, het beeld past gewoon nu op de kaart).
Niveau twee, U-Boot
Nu ‘vallen’ we nog steeds, maar zijn we inmiddels al op het juiste adres. 0x0000000080089a84. Hier moet ik toegeven: in werkelijkheid gaat de uiteenzetting niet ‘met alle stops’, maar wordt deze gedeeltelijk al ‘achteraf’ geschreven, dus hier heb ik al de juiste dtb-bestand van onze SoC toegevoegd en de instellingen aangepast. HiFive_U-Boot variabele CONFIG_SYS_TEXT_BASE=0x80089800 (in plaats van 0x08000000), zodat het laadadres overeenkomt met het werkelijke. We laden nu de kaart van het volgende niveau met een ander beeld:
(gdb) file ..\/freedom-u-sdk\/work\/HiFive_U-Boot\/u-boot
(gdb) tui enEn we zien:
│304
/* │
│305 * trap entry │
│306 */ │
│307 trap_entry: │
│308 addi sp, sp, -32*REGBYTES │
>│309 SREG x1, 1*REGBYTES(sp) │
│310 SREG x2, 2*REGBYTES(sp) │
│311 SREG x3, 3*REGBYTES(sp) │Trouwens, we springen tussen de regels 308 en 309. En dat is niet verwonderlijk, aangezien er in $sp de waarde ligt 0xfffffffe31cdc0a0. Helaas, het ‘vlucht’ nog steeds constant weg door regel 307. Dus laten we proberen een breakpoint te plaatsen op trap_entry, en daarna weer terug te gaan naar 0x80089800 (de ingangspunt U-Boot), en laten we hopen dat het geen juiste instelling van registers vereist voor de overgang… Het lijkt te werken:
(gdb) b trap_entry
Breakpoint 1 bij 0x80089a80: bestand \/hdd\/trosinenko\/fpga\/freedom-u-sdk\/HiFive_U-Boot\/arch\/riscv\/cpu\/HiFive\/start.S, regel 308.
(gdb) set variable $pc=0x80089800
(gdb) c
Voortzetten.
Breakpoint 1, trap_entry () bij \/hdd\/trosinenko\/fpga\/freedom-u-sdk\/HiFive_U-Boot\/arch\/riscv\/cpu\/HiFive\/start.S:308
(gdb) p\/x $sp
$4 = 0x81cf950Niet echt een goede stack pointer, om eerlijk te zijn: wijst volledig weg van het RAM-geheugen (tenzij we nog geen adrestranslatie hebben, maar laten we hopen op de eenvoudige optie).
Laten we de pointer vervangen door 0x881cf950. Uiteindelijk komen we tot het punt dat handle_trap wordt aangeroepen en opnieuw wordt aangeroepen, terwijl we in _exit_trap met het argument epc=2148315240 (in decimale vorm):
(gdb) x/10i 2148315240
0x800cb068 : lbu a4,0(a5)
0x800cb06c : bnez a4,0x800cb078
0x800cb070 : sub a0,a5,a0
0x800cb074 : ret
0x800cb078 : addi a5,a5,1
0x800cb07c : j 0x800cb064
0x800cb080 : addi sp,sp,-32
0x800cb084 : sd s0,16(sp)
0x800cb088 : sd ra,24(sp)
0x800cb08c : li s0,0We zetten een breakpoint op strnlen, we gaan verder en zien:
(gdb) bt
#0 strnlen (s=s@entry=0x10060000 "", count=18446744073709551615) at lib/string.c:283
#1 0x00000000800cc14c in string (buf=buf@entry=0x881cbd4c "", end=end@entry=0x881cc15c "", s=0x10060000 "", field_width=, precision=, flags=) at lib/vsprintf.c:265
#2 0x00000000800cc63c in vsnprintf_internal (buf=buf@entry=0x881cbd38 "exception code: 5 , ", size=size@entry=1060, fmt=0x800d446e "s , epc x , ra lxn", fmt@entry=0x800d4458 "exception code: %d , %s , epc x , ra lxn", args=0x881cc1a0,
args@entry=0x881cc188) at lib/vsprintf.c:619
#3 0x00000000800cca54 in vsnprintf (buf=buf@entry=0x881cbd38 "exception code: 5 , ", size=size@entry=1060, fmt=fmt@entry=0x800d4458 "exception code: %d , %s , epc x , ra lxn", args=args@entry=0x881cc188) at lib/vsprintf.c:710
#4 0x00000000800cca68 in vscnprintf (buf=buf@entry=0x881cbd38 "exception code: 5 , ", size=size@entry=1060, fmt=fmt@entry=0x800d4458 "exception code: %d , %s , epc x , ra lxn", args=args@entry=0x881cc188) at lib/vsprintf.c:717
#5 0x00000000800ccb50 in printf (fmt=fmt@entry=0x800d4458 "exception code: %d , %s , epc x , ra lxn") at lib/vsprintf.c:792
#6 0x000000008008a9f0 in _exit_trap (regs=, epc=2148315240, code=) at arch/riscv/lib/interrupts.c:92
#7 handle_trap (mcause=, epc=, regs=) at arch/riscv/lib/interrupts.c:55
#8 0x0000000080089b10 in trap_entry () at /hdd/trosinenko/fpga/freedom-u-sdk/HiFive_U-Boot/arch/riscv/cpu/HiFive/start.S:343
Backtrace stopped: frame did not save the PCHet lijkt erop dat _exit_trap het debug-informatie over de opgetreden uitzondering wil geven, maar het niet lukt. Dus krijgen we de bronbestanden weer niet weergegeven. set directories ../freedom-u-sdk/HiFive_U-Boot/ Oh! Nu zijn ze zichtbaar!
Laten we nogmaals starten en de oorzaak van het oorspronkelijke probleem in de stacktrace zien, die de eerste fout heeft veroorzaakt (mcause == 5). Als ik het goed begreep van wat er staat op pagina 37, betekent deze uitzondering Load access fault. De reden is blijkbaar dat hier
arch/riscv/cpu/HiFive/start.S:
call_board_init_f:
li t0, -16
li t1, CONFIG_SYS_INIT_SP_ADDR
and sp, t1, t0 /* forceren 16 byte alignering */
#ifdef CONFIG_DEBUG_UART
jal debug_uart_init
#endif
call_board_init_f_0:
mv a0, sp
jal board_init_f_alloc_reserve
mv sp, a0
jal board_init_f_init_reserve
mv a0, zero /* a0 <— boot_flags = 0 */
la t5, board_init_f
jr t5 /* springen naar board_init_f() */
$sp de onjuiste waarde bevat, en binnen board_init_f_init_reserve de fout optreedt. Het lijkt erop dat dit de schuldige is: een variabele met een duidelijke naam CONFIG_SYS_INIT_SP_ADDR. Het is gedefinieerd in het bestand HiFive_U-Boot/include/configs/HiFive-U540.h. Op een gegeven moment dacht ik zelfs, misschien is het makkelijker om de processor een beetje aan te passen dan de bootloader voor de processor te perfectioneren? Maar toen zag ik dat dit meer leek op een artifact van niet helemaal goed ingestelde configuraties voor een andere geheugentype, en dat we het zo konden proberen:#if 0-de instellingen voor de andere configuratie aan te passen, en we kunnen het zo proberen:
diff --git a/include/configs/HiFive-U540.h b/include/configs/HiFive-U540.h
index ca89383..245542c 100644
--- a/include/configs/HiFive-U540.h
+++ b/include/configs/HiFive-U540.h
@@ -65,12 +65,9 @@
#define CONFIG_SYS_SDRAM_BASE PHYS_SDRAM_0
#endif
#if 1
-
#define CONFIG_NR_DRAM_BANKS 1
+#define CONFIG_NR_DRAM_BANKS 1
#define PHYS_SDRAM_0 0x80000000 /* SDRAM Bank #1 */
-#define PHYS_SDRAM_1
- (PHYS_SDRAM_0 + PHYS_SDRAM_0_SIZE) /* SDRAM Bank #2 */
-#define PHYS_SDRAM_0_SIZE 0x80000000 /* 2 GB */
-#define PHYS_SDRAM_1_SIZE 0x10000000 /* 256 MB */
+#define PHYS_SDRAM_0_SIZE 0x40000000 /* 1 GB */
#define CONFIG_SYS_SDRAM_BASE PHYS_SDRAM_0
#endif
/*
@@ -81,7 +78,7 @@
#define CONSOLE_ARG "console=ttyS0,115200 "
/* Init Stack Pointer */
-#define CONFIG_SYS_INIT_SP_ADDR (0x08000000 + 0x001D0000 -
+#define CONFIG_SYS_INIT_SP_ADDR (0x80000000 + 0x001D0000 -
GENERATED_GBL_DATA_SIZE)
#define CONFIG_SYS_LOAD_ADDR 0xa0000000 /* gedeeltelijk in SDRAM */Op een gegeven moment bereikte het aantal noodoplossingen een kritieke drempel. Na enige tijd worstelen realiseerde ik me dat ik een correcte poort naar mijn bord moest maken. Om dit te doen moet ik een aantal bestanden kopiëren en aanpassen voor onze configuratie.
Nou, ongeveer, hier is een beetje
trosinenko@trosinenko-pc:/hdd/trosinenko/fpga/freedom-u-sdk/HiFive_U-Boot$ git show --name-status
commit 39cd67d59c16ac87b46b51ac1fb58f16f1eb1048 (HEAD -> zeowaa-1gb)
Author: Anatoly Trosinenko
Date: Tue Jul 2 17:13:16 2019 +0300
Eerste ondersteuning voor het Zeowaa A-E115FB bord
M arch/riscv/Kconfig
A arch/riscv/cpu/zeowaa-1gb/Makefile
A arch/riscv/cpu/zeowaa-1gb/cpu.c
A arch/riscv/cpu/zeowaa-1gb/start.S
A arch/riscv/cpu/zeowaa-1gb/timer.c
A arch/riscv/cpu/zeowaa-1gb/u-boot.lds
M arch/riscv/dts/Makefile
A arch/riscv/dts/zeowaa-1gb.dts
A board/Zeowaa/zeowaa-1gb/Kconfig
A board/Zeowaa/zeowaa-1gb/MAINTAINERS
A board/Zeowaa/zeowaa-1gb/Makefile
A board/Zeowaa/zeowaa-1gb/Zeowaa-A-E115FB.c
A configs/zeowaa-1gb_defconfig
A include/configs/zeowaa-1gb.hDetails kunnen worden bekeken in .
Blijkbaar hebben de registers van sommige apparaten op dit SiFive-bord andere adressen. Het bleek ook dat U-Boot wordt geconfigureerd met het reeds bekende Kconfig-mechanisme van de Linux-kernel — bijvoorbeeld, je kunt het commando geven maak menuconfig, en er verschijnt een handige tekstinterface met beschrijvingen van de parameters. ? En dit soort dingen. Kortom, door uit de beschrijvingen van twee kaarten de beschrijving van een derde samen te stellen en allerlei pompeuze PLL-instellingen te negeren (waarschijnlijk is dit gerelateerd aan de besturing vanaf de hostcomputer via PCIe, maar dat is niet zeker), kreeg ik een bepaalde firmware die, bij goed weer op Mars, via UART een bericht gaf over welke commit-hash het was samengesteld en over hoeveel DRAM ik had (maar die informatie had ik zelf in de header aangegeven).
Het is jammer dat de kaart meestal stopt met reageren via de processor JTAG, en opstarten vanaf een SD-kaart is - helaas - in mijn configuratie niet snel. Aan de andere kant gaf BootROM soms het bericht dat FOUT, opstarten niet gelukt was, en het U-Boot kwam onmiddellijk tevoorschijn. Toen realiseerde ik me: blijkbaar wordt na het opnieuw opstarten de bitstream in de FPGA het geheugen niet overschreven, het wordt niet 'gereset', enzovoorts. Kortom, je kunt gewoon aansluiten met een debugger zodra je het bericht ziet LOADING / en vervolgens de volgende opdracht geven set variable $pc=0x80089800, en daarmee deze lange opstarttijd omzeilen (natuurlijk uitgaande van de veronderstelling dat het vorige keer vroeg genoeg is afgebroken zodat er niet iets bovenop de originele code is geladen).
Trouwens, is het eigenlijk normaal dat de processor volledig vastloopt en dat de JTAG-debugger geen verbinding kan maken met berichten
Error: unable to halt hart 0
Error: dmcontrol=0x80000001
Error: dmstatus =0x00030c82Wacht even! Dit heb ik al eerder gezien! Iets dergelijks gebeurt bij een deadlock van TileLink, en de auteur van de geheugencontroller vertrouw ik niet echt - hij heeft het zelf geschreven... Plotseling, na de eerste succesvolle recompilatie van de processor na het bewerken van de controller, zag ik:
INIT
CMD0
CMD8
ACMD41
CMD58
CMD16
CMD18
LOADING
BOOT
U-Boot 2018.09-g39cd67d-dirty (3 jul 2019 - 13:50:33 +0300)
DRAM: 1 GiB
MMC:
BEFORE LOAD ENVBEFORE FDTCONTROLADDRBEFORE LOADADDRIn: serial
Out: serial
Err: serial
Druk op een toets om autoboot te stoppen: 3Op deze vreemde regel voor In: serial Let op — dit was ik die probeerde uit te vogelen of het goed werkt met de environment op een vastgelopen processor. Wat betekent het: "Het hangt nu al tien minuten"? Is het tenminste gelukt om te relozeren en naar het opstartmenu te gaan? Een kleine zijsprong: hoewel U-Boot laadt in de eerste 2^24 bytes van de SD-kaart, kopieert het zichzelf zodra het opstart naar een andere locatie, ofwel naar het adres dat in de configuratie-header staat geschreven, of simpelweg naar hogere adressen in het RAM, voert het de relocatie van ELF-symbolen uit en geeft het de controle daarover. Dus, het lijkt erop dat dit niveau is gehaald en als bonus kregen we een processor die na deze stap niet vastloopt.
Dus waarom werkt de timer niet? Het lijkt erop dat de klok om de een of andere reden überhaupt niet loopt…
(gdb) x/x 0x0200bff8
0x200bff8: 0x00000000En wat als we de wijzers handmatig draait?
(gdb) set variable *0x0200bff8=310000000
(gdb) cDan:
Druk op een toets om het autobootproces te stoppen: 0
MMC_SPI: 0 bij 0:1 hz 20000000 modus 0Conclusie: de klok loopt niet. Waarschijnlijk werkt de invoer van het toetsenbord ook om deze reden niet:
HiFive_U-Boot/cmd/bootmenu.c:
static void bootmenu_loop(struct bootmenu_data *menu,
enum bootmenu_key *key, int *esc)
{
int c;
while (!tstc()) {
WATCHDOG_RESET();
mdelay(10);
}
c = getc();
switch (*esc) {
case 0:
/* Eerste teken van ANSI escape-sequentie 'e' */
if (c == 'e') {
*esc = 1;
*key = KEY_NONE;
}
break;
case 1:
/* Tweede teken van ANSI '[' */
if (c == '[') {
...Het probleem was dat ik een beetje te ver ging: ik heb de sleutel toegevoegd in de processorconfiguratie:
case DTSTimebase => BigInt(0)… uitgaande van de opmerking: "Als je het niet weet, laat dan 0 staan". En zelfs WithNBigCores werd het een waarde van 1MHz, zoals trouwens ook stond aangegeven in de U-Boot-configuratie. Maar ik wilde het perfect en nauwkeurig doen: hier weet ik het niet, daar 25MHz! Uiteindelijk werkt er niets meer. Ik heb mijn "verbeteringen" verwijderd en…
Druk op een toets om het autobootproces te stoppen: 0
MMC_SPI: 0 bij 0:1 hz 20000000 modus 0
## Onbekend partition table type 0
libfdt fdt_path_offset() gaf FDT_ERR_NOTFOUND terug
** Geen partition table - mmc 0 **
## Info: invoergrootte = 34 = 0x22
uEnv.txt boot2 wordt uitgevoerd...
## Fout: "boot2" niet gedefinieerd
HiFive-Unleashed #Je kunt zelfs opdrachten invoeren! Bijvoorbeeld, na wat geknoei, kun je eindelijk raden om in te voeren mmc_spi 1 10000000 0; mmc part, door de SPI-frequentie te verlagen van 20 MHz naar 10 MHz. Waarom? Nou, in de configuratie stond de maximale frequentie van 20 MHz, en die staat er nu nog steeds. Maar, voor zover ik begrijp, werken de interfaces, althans hier, zo: de code deelt de frequentie van het hardwareblok (bij mij overal 25 MHz) door de doelwaarde en stelt de verkregen waarde in als deler in het bijbehorende controle register. Het probleem is dat als voor de 115200 Hz UART het ongeveer is wat nodig is, als je 25000000 door 20000000 deelt, krijg je 1, dat wil zeggen dat het op 25 MHz zal werken. Misschien is dat normaal, maar als beperkingen worden ingesteld, betekent dat dat het iemand nodig heeft (maar dat is niet zeker)... Kortom, het is makkelijker om het in te stellen en verder te gaan — ver weg en, helaas, voor lange tijd. 25 MHz is niet hetzelfde als een Core i9.
Console-uitvoer
HiFive-Unleashed # env edit mmcsetup
edit: mmc_spi 1 10000000 0; mmc part
HiFive-Unleashed # boot
MMC_SPI: 1 op 0:1 hz 10000000 modus 0
Partitiet Map voor MMC apparaat 0 -- Partitiet Type: EFI
Part Start LBA End LBA Naam
Attributen
Type GUID
Partitiet GUID
1 0x00000800 0x0000ffde "Vfat Boot"
attrs: 0x0000000000000000
type: ebd0a0a2-b9e5-4433-87c0-68b6b72699c7
type: gegevens
guid: 76bd71fd-1694-4ff3-8197-bfa81699c2fb
2 0x00040800 0x002efaf4 "root"
attrs: 0x0000000000000000
type: 0fc63daf-8483-4772-8e79-3d69d8477de4
type: linux
guid: 9f3adcc5-440c-4772-b7b7-283124f38bf3
3 0x0000044c 0x000007e4 "uboot"
attrs: 0x0000000000000000
type: 5b193300-fc78-40cd-8002-e86c45580b47
guid: bb349257-0694-4e0f-9932-c801b4d76fa3
4 0x00000400 0x0000044b "uboot-env"
attrs: 0x0000000000000000
type: a09354ac-cd63-11e8-9aff-70b3d592f0fa
guid: 4db442d0-2109-435f-b858-be69629e7dbf
libfdt fdt_path_offset() retourneerde FDT_ERR_NOTFOUND
2376 bytes gelezen in 0 ms
Running uEnv.txt boot2...
15332118 bytes gelezen in 0 ms
## Kernel laden van FIT Beeld op 90000000 ...
Gebruik 'config-1' configuratie
Poging tot 'bbl' kernel subafbeelding
Beschrijving: BBL/SBI/riscv-pk
Type: Kernel Afbeelding
Compressie: ongecomprimeerd
Gegevens Start: 0x900000d4
Gegevensgrootte: 74266 Bytes = 72.5 KiB
Architectuur: RISC-V
OS: Linux
Laadadres: 0x80000000
Instapunt: 0x80000000
Hash algo: sha256
Hash waarde: 28972571467c4ad0cf08a81d9cf92b9dffc5a7cb2e0cd12fdbb3216cf1f19cbd
Verifieren Hash Integriteit ... sha256+ OK
## Laden fdt van FIT Beeld op 90000000 ...
Gebruik 'config-1' configuratie
Poging tot 'fdt' fdt subafbeelding
Beschrijving: niet beschikbaar
Type: Flat Device Boom
Compressie: ongecomprimeerd
Gegevens Start: 0x90e9d31c
Gegevensgrootte: 6911 Bytes = 6.7 KiB
Architectuur: RISC-V
Laadadres: 0x81f00000
Hash algo: sha256
Hash waarde: 10b0244a5a9205357772ea1c4e135a4f882409262176d8c7191238cff65bb3a8
Verifieren Hash Integriteit ... sha256+ OK
Laden fdt van 0x90e9d31c naar 0x81f00000
Booten met behulp van de fdt blob op 0x81f00000
## Laden laadbare bestanden van FIT Beeld op 90000000 ...
Poging tot 'kernel' laadbare subafbeelding
Beschrijving: Linux kernel
Type: Kernel Afbeelding
Compressie: ongecomprimeerd
Gegevens Start: 0x900123e8
Gegevensgrootte: 10781356 Bytes = 10.3 MiB
Architectuur: RISC-V
OS: Linux
Laadadres: 0x80200000
Instapunt: niet beschikbaar
Hash algo: sha256
Hash waarde: 72a9847164f4efb2ac9bae736f86efe7e3772ab1f01ae275e427e2a5389c84f0
Verifieren Hash Integriteit ... sha256+ OK
Laden laadbare bestanden van 0x900123e8 naar 0x80200000
## Laden laadbare bestanden van FIT Beeld op 90000000 ...
Poging tot 'ramdisk' laadbare subafbeelding
Beschrijving: buildroot initramfs
Type: RAMDisk Afbeelding
Compressie: gzip gecomprimeerd
Gegevens Start: 0x90a5a780
Gegevensgrootte: 4467411 Bytes = 4.3 MiB
Architectuur: RISC-V
OS: Linux
Laadadres: 0x82000000
Instapunt: niet beschikbaar
Hash algo: sha256
Hash waarde: 883dfd33ca047e3ac10d5667ffdef7b8005cac58b95055c2c2beda44bec49bd0
Verifieren Hash Integriteit ... sha256+ OK
Laden laadbare bestanden van 0x90a5a780 naar 0x82000000Oké, we zijn naar een nieuw niveau gegaan, maar het hangt nog steeds vast. En soms komen er ook uitzonderingen. Je kunt mcause zien door de code op het opgegeven adres af te wachten. $pc en na si terechtkomen op trap_entry. De U-Boot handler kan alleen uitvoeren voor mcause = 0..4, dus bereid je voor op een eindeloze lus door een onjuiste boot. Hier heb ik in de configuratie gekeken, wat ik hebt gewijzigd, en ik herinnerde me: daar in conf/rvboot-fit.txt Het bedrijf Finservice is actief sinds 2012 en is een toonaangevende onafhankelijke financiële broker op het gebied van POS-financiering op de Russische markt. Op dit moment maakt Finservice deel uit van een grote multifunctionele holding, heeft meer dan 200 werknemers en is actief aan het uitbreiden in alle regio's van Rusland.
fitfile=image.fit
# hieronder moet veel overeenkomen met wat in FIT staat (ugha)Laten we alle bestanden in overeenstemming brengen, vervangen we de kernel commandoregel ongeveer zo, omdat er vermoedens zijn dat SIF0 — dit is een uitvoer ergens via PCIe:
-bootargs=console=ttySIF0,921600 debug
+bootargs=console=ttyS0,125200 debugEn we zullen ook het hashing-algoritme veranderen van SHA-256 naar MD5: cryptografische veiligheid heb ik niet nodig (vooral tijdens het debuggen), het is schandalig traag, en voor het opsporen van integriteitsfouten tijdens het booten is MD5 meer dan genoeg. Wat hebben we uiteindelijk? We gingen merkbaar sneller door het vorige niveau (door de eenvoudigere hashing), en het volgende niveau werd geopend:
...
Verifiëren van Hash-integriteit ... md5+ OK
Laden van uitvoerbare bestanden van 0x90a5a758 naar 0x82000000
libfdt fdt_check_header(): FDT_ERR_BADMAGIC
gekozen {
linux,initrd-end = ;
linux,initrd-start = ;
riscv,kernel-end = ;
riscv,kernel-start = ;
bootargs = "debug console=tty0 console=ttyS0,125200 root=/dev/mmcblk0p2 rootwait";
};
libfdt fdt_path_offset() retourneerde FDT_ERR_NOTFOUND
gekozen {
linux,initrd-end = ;
linux,initrd-start = ;
riscv,kernel-end = ;
riscv,kernel-start = ;
bootargs = "debug console=tty0 console=ttyS0,125200 root=/dev/mmcblk0p2 rootwait";
};
Laden van Kernel Image ... OK
Kernel wordt opgestart in
3Maar de klok tikt niet...
(gdb) x/x 0x0200bff8
0x200bff8: 0x00000000Oeps, het lijkt erop dat het corrigeren van de tijd een placebo was, hoewel het me toen leek te helpen. Nee, het moet natuurlijk gerepareerd worden, maar laten we eerst handmatig aan de wijzers draaien en kijken wat er gebeurt:
0x00000000bff6dbb0 in ?? ()
(gdb) set variable *0x0200bff8=1000000
(gdb) c
Voortzetten.
^C
Programma ontving signaal SIGINT, Onderbreking.
0x00000000bff6dbb0 in ?? ()
(gdb) set variable *0x0200bff8=2000000
(gdb) c
Voortzetten.
^C
Programma ontving signaal SIGINT, Onderbreking.
0x00000000bff6dbb0 in ?? ()
(gdb) set variable *0x0200bff8=3000000
(gdb) c
Voortzetten.Ondertussen...
Laden van Kernel Image ... OK
Kernel wordt opgestart in
3
2
1
0
## Toepassing wordt gestart op 0x80000000 ...Nee, ik ga de klok automatiseren — anders kan hij denken dat hij de timer moet kalibreren!
En het adres van de huidige instructie wijst ondertussen ergens naar
0000000080001c20 :
80001c20: 1141 addi sp,sp,-16
80001c22: e022 sd s0,0(sp)
80001c24: 842a mv s0,a0
80001c26: 00005517 auipc a0,0x5
80001c2a: 0ca50513 addi a0,a0,202 # 80006cf0
80001c2e: e406 sd ra,8(sp)
80001c30: f7fff0ef jal ra,80001bae
80001c34: 8522 mv a0,s0
80001c36: 267000ef jal ra,8000269c
80001c3a: 00010797 auipc a5,0x10
80001c3e: 41e78793 addi a5,a5,1054 # 80012058
80001c42: 639c ld a5,0(a5)
80001c44: c399 beqz a5,80001c4a
80001c46: 72c000ef jal ra,80002372
80001c4a: 45a1 li a1,8
80001c4c: 4501 li a0,0
80001c4e: dc7ff0ef jal ra,80001a14
80001c52: 10500073 wfi
80001c56: bff5 j 80001c52binnen de opgestarte Berkeley Boot Loader. Persoonlijk maakt het vermelden hiervan me onzeker htif — hostinterface, gebruikt voor het tethered starten van de kernel (d.w.z. in samenwerking met de host-ARM), ik dacht dat het standalone was. Als je echter deze functie in de broncode vindt, blijkt het niet zo slecht te zijn:
void poweroff(uint16_t code)
{
printm("Power offrn");
finisher_exit(code);
if (htif) {
htif_poweroff();
} else {
send_ipi_many(0, IPI_HALT);
while (1) { asm volatile ("wfin"); }
}
}Quest: start de klok
De zoektocht naar registers in CLINT leidt ons naar
val io = IO(new Bundle {
val rtcTick = Bool(INPUT)
})
val time = RegInit(UInt(0, width = timeWidth))
when (io.rtcTick) { time := time + UInt(1) }Die is aangesloten op de RTC, of op het mysterieuze MockAON, waarvan ik aanvankelijk dacht: "Wat hebben we hier? Onbekend? Uitschakelen!" Omdat ik nog steeds niet begrijp welke klokmagie daar gebeurt, ga ik deze logica opnieuw implementeren in System.scala:
val rtcDivider = RegInit(0.asUInt(16.W)) // ter ondersteuning tot 16 GHz, ik ben optimistisch :)
val mhzInt = p(DevKitFPGAFrequencyKey).toInt
// Laten we aannemen dat de frequentie gelijk is aan een heel getal in megahertz
rtcDivider := Mux(rtcDivider === (mhzInt - 1).U, 0.U, rtcDivider + 1.U)
outer.clintOpt.foreach { clint =>
clint.module.io.rtcTick := rtcDivider === 0.U
}Op weg naar de Linux kernel
Het verhaal is al lang en enigszins eentonig geworden, dus ik zal het kort samenvatten:
BBL ging ervan uit dat er een FDT op het adres zat 0xF0000000, dat had ik al gecorrigeerd! Nou, laten we verder zoeken… Ik vond het in HiFive_U-Boot/arch/riscv/lib/boot.c, vervangen door 0x81F00000, zoals opgegeven in de U-Boot opstartconfiguratie.
Toen klaagde BBL dat er geen geheugen was. Mijn pad leidde naar de functie mem_prop, die in riscv-pk/machine/fdt.c: daar vernam ik dat ik de fdt ram-knoop moet markeren als device_type = "memory" — misschien moet ik later de processor generator aanpassen, maar voorlopig schrijf ik het gewoon met de hand in — ik heb dit bestand tenslotte handmatig overgebracht.
Nu heb ik een bericht ontvangen (weergegeven in opgemaakte vorm, met terugloop):
Dit is bbl's dummy_payload. Om een echte kernel op te starten, configureer bbl opnieuw
met de vlag --with-payload=PATH, en bouw bbl opnieuw. Als alternatief kan
bbl worden gebruikt in firmware-only modus door device-tree knooppunten
voor een externe payload toe te voegen en de -bios en -kernel opties van QEMU te gebruiken.Het lijkt erop dat de opties correct worden opgegeven riscv,kernel-start en riscv,kernel-end in de DTB, maar de nullen worden niet goed geparsed. Debugging query_chosen toonde aan dat BBL probeert een 32-bits adres te parseren, terwijl hij een paar tegenkomt <0x0 0xADDR>, en de eerste waarde lijkt de lagere bits te zijn. Heb het toegevoegd in de sectie chosen
chosen {
#address-cells = ;
#size-cells = ;
...
}en heb de generatie van waarden aangepast: niet toevoegen 0x0 als het eerste element.
Deze 100500 eenvoudige stappen laten je gemakkelijk en simpel zien hoe de pingwin valt:
Verborgen tekst
Controle van de integriteit van de hash ... md5+ OK
Laadbare bestanden laden van 0x90a5a758 tot 0x82000000
libfdt fdt_check_header(): FDT_ERR_BADMAGIC
gekozen {
linux,initrd-end = ;
linux,initrd-start = ;
riscv,kernel-end = ;
riscv,kernel-start = ;
#address-cells = ;
#size-cells = ;
bootargs = "debug console=tty0 console=ttyS0,125200 root=/dev/mmcblk0p2 rootwait";
stdout-path = "uart0:38400n8";
};
libfdt fdt_path_offset() gaf FDT_ERR_NOTFOUND terug
gekozen {
linux,initrd-end = ;
linux,initrd-start = ;
riscv,kernel-end = ;
riscv,kernel-start = ;
#address-cells = ;
#size-cells = ;
bootargs = "debug console=tty0 console=ttyS0,125200 root=/dev/mmcblk0p2 rootwait";
stdout-path = "uart0:38400n8";
};
Het laden van de kernelafbeelding ... OK
Kernel opstarten in
3
2
1
0
## Starten van de applicatie op 0x80000000 ...
bbl loader
SIFIVE, INC.
5555555555555555555555555
5555 5555
5555 5555
5555 5555
5555 5555555555555555555555
5555 555555555555555555555555
5555 5555
5555 5555
5555 5555
5555555555555555555555555555 55555
55555 555555555 55555
55555 55555 55555
55555 5 55555
55555 55555
55555 55555
55555 55555
55555 55555
55555 55555
555555555
55555
5
SiFive RISC-V Core IP
[ 0.000000] OF: fdt: Negeert geheugengebied 0x80000000 - 0x80200000
[ 0.000000] Linux versie 4.19.0-sifive-1+ (trosinenko@trosinenko-pc) (gcc versie 8.3.0 (Buildroot 2019.02-07449-g4eddd28f99)) #1 SMP Wo 3 jul 21:29:21 MSK 2019
[ 0.000000] bootconsole [early0] ingeschakeld
[ 0.000000] Initieel ramdisk op: 0x(____ptrval____) (16777216 bytes)
[ 0.000000] Zone bereiken:
[ 0.000000] DMA32 [mem 0x0000000080200000-0x00000000bfffffff]
[ 0.000000] Normaal [mem 0x00000000c0000000-0x00000bffffffffff]
[ 0.000000] Movable zone start voor elke node
[ 0.000000] Vroeg geheugennode bereiken
[ 0.000000] node 0: [mem 0x0000000080200000-0x00000000bfffffff]
[ 0.000000] Initmem instellen node 0 [mem 0x0000000080200000-0x00000000bfffffff]
[ 0.000000] Op node 0 totaalpagina's: 261632
[ 0.000000] DMA32 zone: 3577 pagina's gebruikt voor memmap
[ 0.000000] DMA32 zone: 0 pagina's gereserveerd
[ 0.000000] DMA32 zone: 261632 pagina's, LIFO batch:63
[ 0.000000] software IO TLB: gemapt [mem 0xbb1fc000-0xbf1fc000] (64MB)(De embleem wordt weergegeven door BBL, en wat met de tijdstempels is - de kernel).
Gelukkig weet ik niet hoe het overal is, maar op RocketChip kun je bij het aansluiten van de debugger via JTAG traps uit de doos vangen - de debugger stopt precies op dat punt.
Programma ontving signaal SIGTRAP, Trace/breakpoint trap.
0xffffffe0000024ca in ?? ()
(gdb) bt
#0 0xffffffe0000024ca in ?? ()
Backtrace gestopt: vorige frame is identiek aan dit frame (corrupt stack?)
(gdb) bestand work/linux/vmlinux
Een programma wordt al gedebugd.
Weet je zeker dat je het bestand wilt wijzigen? (y of n) y
Symbolen lezen van work/linux/vmlinux...klaar.
(gdb) bt
#0 0xffffffe0000024ca in setup_smp () bij /hdd/trosinenko/fpga/freedom-u-sdk/linux/arch/riscv/kernel/smpboot.c:75
#1 0x0000000000000000 in ?? ()
Backtrace gestopt: frame heeft de PC niet opgeslagenfreedom-u-sdk/linux/arch/riscv/kernel/smpboot.c:
void __init setup_smp(void)
{
struct device_node *dn = NULL;
int hart;
bool found_boot_cpu = false;
int cpuid = 1;
while ((dn = of_find_node_by_type(dn, "cpu"))) {
hart = riscv_of_processor_hartid(dn);
if (hart < 0)
continue;
if (hart == cpuid_to_hartid_map(0)) {
BUG_ON(found_boot_cpu);
found_boot_cpu = 1;
continue;
}
cpuid_to_hartid_map(cpuid) = hart;
set_cpu_possible(cpuid, true);
set_cpu_present(cpuid, true);
cpuid++;
}
BUG_ON(!found_boot_cpu); // < U BENT HIER
}Zoals in de oude grap werd gezegd, CPU niet gevonden, draaiende software-emulatie. Nou ja, of niet draaiende. Verdwaald in de enige processor-kern.
/* The lucky hart to first increment this variable will boot the other cores */
atomic_t hart_lottery;
unsigned long boot_cpu_hartid;Een goede opmerking in linux/arch/riscv/kernel/setup.c — zo'n verfbeurt van een hekje op Tom Sawyer-manier. Kortom, vandaag zijn er om de een of andere reden geen winnaars, de prijs wordt naar de volgende trekking overgebracht…
Hiermee stel ik voor om te eindigen met het al te lange artikel.
Vervolg volgt. Daarin komt de strijd met een slimme fout die zich weet te verstoppen als je er langzaam met singlestep naar toe sluipt.
Tekstuele screencast van de opstart (externe link):
Bron: habr.com
