Partea 4: În cele din urmă, lansăm Linux pe RocketChip RISC-V

Partea 4: În cele din urmă, lansăm Linux pe RocketChip RISC-V În imagine, kernelul Linux vă salută prin GPIO.

În această parte a istoriei portării RISC-V RocketChip pe o placă chinezescă cu Cyclone IV, în cele din urmă vom lansa Linux și vom învăța să configurăm noi IP Core-ul controlerului de memorie și să modificăm puțin descrierea hardware-ului dts. Acest articol este o continuare a treia parte, dar, spre deosebire de cea anterioară, care a devenit destul de lungă, aceasta va fi destul de scurtă.

… De vreme ce setup_smp este apelat doar dacă kernelul este configurat cu suport SMP, putem încerca să dezactivăm multicoartele. Ar fi neplăcut să trebuiască să implementez suportul atomic în modulul de memorie (mi s-a părut că acest lucru este gestionat de cache), dar în cazul unicore nu ar trebui să ne împiedice.

Tot nu a reușit...

[    0.000000] OF: fdt: Ignorând intervalul de memorie 0x80000000 - 0x80200000
[    0.000000] Versiunea Linux 4.19.0-sifive-1+ (trosinenko@trosinenko-pc) (gcc versiunea 8.3.0 (Buildroot 2019.02-07449-g4eddd28f99)) #1 Joi 4 Iul 2019 18:38:10 MSK
[    0.000000] bootconsole [early0] activat
[    0.000000] Ramdisk inițial la: 0x(____ptrval____) (16777216 bytes)
[    0.000000] Intervalele zonei:
[    0.000000]   DMA32    [mem 0x0000000080200000-0x00000000bfffffff]
[    0.000000]   Normal   [mem 0x00000000c0000000-0x00000bffffffffff]
[    0.000000] Zona mobilă începe pentru fiecare nod
[    0.000000] Intervalele de memorie timpurie ale nodurilor
[    0.000000]   nod   0: [mem 0x0000000080200000-0x00000000bfffffff]
[    0.000000] Configurarea memoriei inițiale pentru nod 0 [mem 0x0000000080200000-0x00000000bfffffff]
[    0.000000] softver IO TLB: mapat [mem 0xbb1fc000-0xbf1fc000] (64MB)
[    0.000000] Nu s-a putut găsi intrarea "cpu" în arborele dispozitivelor
[    0.000000] S-au construit 1 liste zonale, gruparea mobilității este activă.  Total pagini: 258055
[    0.000000] Linia de comandă a nucleului: debug console=ttySIF0,125200 root=\/dev\/mmcblk0p2 loglevel=7 rootwait
[    0.000000] Intrările tabelului hash pentru cache-ul dentry: 131072 (ordine: 8, 1048576 bytes)
[    0.000000] Intrările tabelului hash pentru cache-ul inode: 65536 (ordine: 7, 524288 bytes)
[    0.000000] Sortare __ex_table...
[    0.000000] BUG: Stare proastă a paginii în procesul swapper  pfn:80bf7
[    0.000000] pagină:ffffffe03f029e08 count:0 mapcount:-65280 mapping:0000000000000000 index:0x1
[    0.000000] flags: 0x0()
[    0.000000] raw: 0000000000000000 0000000000000100 0000000000000200 0000000000000000
[    0.000000] raw: 0000000000000001 0000000000000000 00000000ffff00ff
[    0.000000] pagina dumpată deoarece: mapcount nonzero
[    0.000000] Module legate în:
[    0.000000] CPU: 0 PID: 0 Comm: swapper Nu este contaminat 4.19.0-sifive-1+ #1
[    0.000000] Call Trace:
[    0.000000] [<ffffffe00002cfde>] walk_stackframe+0x0\/0xa0
[    0.000000] [<ffffffe00002d1da>] show_stack+0x2a\/0x34
[    0.000000] [<ffffffe00063c898>] chachachllachachachTradeonachachach_inachachipachachachachllachachachTradeonachachachdevachachachypachachachllachachachTradeona+0x20\/0x28
[    0.000000] [<ffffffe00009499c>] bad_page+0xe4\/0x102
[    0.000000] [<ffffffe0000949f2>] free_pages_check_bad+0x38\/0x7a
[    0.000000] [<ffffffe000094bb0>] free_pcppages_bulk+0x106\/0x36c
[    0.000000] [<ffffffe0000957be>] free_unref_page_commit.isra.23+0x86\/0x8e
[    0.000000] [<ffffffe0000960bc>] free_unref_page+0x44\/0x58
[    0.000000] [<ffffffe0000960de>] __free_pages.part.28+0xe\/0x22
[    0.000000] [<ffffffe0000056da>] __free_pages_bootmem+0x86\/0x90
[    0.000000] [<ffffffe000007c46>] free_all_bootmem+0x156\/0x1ba
[    0.000000] [<ffffffe0000023f8>] mem_init+0x36\/0x44
[    0.000000] [<ffffffe0000007a0>] start_kernel+0x1aa\/0x328
[    0.000000] [<ffffffe000000058>] _sinittext+0x58\/0x5c
[    0.000000] Dezactivarea depanării blocărilor din cauza contaminării nucleului
[    0.000000] BUG: Stare proastă a paginii în procesul swapper  pfn:80bf9
[    0.000000] pagină:ffffffe03f029e78 count:0 mapcount:-65280 mapping:0000000000000000 index:0x0
[    0.000000] flags: 0x0()
[    0.000000] raw: 0000000000000000 ffffffe03f020080 ffffffe03f020080 0000000000000000
[    0.000000] raw: 0000000000000000 0000000000000000 00000000ffff00ff
[    0.000000] pagina dumpată deoarece: mapcount nonzero
[    0.000000] Module legate în:
[    0.000000] CPU: 0 PID: 0 Comm: swapper Contaminat: G    B             4.19.0-sifive-1+ #1
[    0.000000] Call Trace:
[    0.000000] [<ffffffe00002cfde>] walk_stackframe+0x0\/0xa0
[    0.000000] [<ffffffe00002d1da>] show_stack+0x2a\/0x34
[    0.000000] [<ffffffe00063c898>] chachachllachachachTradeonachachach_inachachipachachachachllachachachTradeonachachachdevachachachypachachachllachachachTradeona+0x20\/0x28
[    0.000000] [<ffffffe00009499c>] bad_page+0xe4\/0x102
[    0.000000] [<ffffffe0000949f2>] free_pages_check_bad+0x38\/0x7a
[    0.000000] [<ffffffe0000955c6>] __free_pages_ok+0x3fe\/0x430
[    0.000000] [<ffffffe0000960ea>] __free_pages.part.28+0x1a\/0x22
[    0.000000] [<ffffffe0000056da>] __free_pages_bootmem+0x86\/0x90
[    0.000000] [<ffffffe000007c46>] free_all_bootmem+0x156\/0x1ba
[    0.000000] [<ffffffe0000023f8>] mem_init+0x36\/0x44
[    0.000000] [<ffffffe0000007a0>] start_kernel+0x1aa\/0x328
[    0.000000] [<ffffffe000000058>] _sinittext+0x58\/0x5c
[    0.000000] BUG: Stare proastă a paginii în procesul swapper  pfn:80bfa
[    0.000000] pagină:ffffffe03f029eb0 count:0 mapcount:-65280 mapping:0000000000000000 index:0x0
[    0.000000] flags: 0x0()
[    0.000000] raw: 0000000000000000 ffffffe03f0200b8 ffffffe03f0200b8 0000000000000000
[    0.000000] raw: 0000000000000000 0000000000000000 00000000ffff00ff
[    0.000000] pagina dumpată deoarece: mapcount nonzero
[    0.000000] Module legate în:
[    0.000000] CPU: 0 PID: 0 Comm: swapper Contaminat: G    B             4.19.0-sifive-1+ #1
[    0.000000] Call Trace:
[    0.000000] [<ffffffe00002cfde>] walk_stackframe+0x0\/0xa0
[    0.000000] [<ffffffe00002d1da>] show_stack+0x2a\/0x34
[    0.000000] [<ffffffe00063c898>] chachachllachachachTradeonachachach_inachachipachachachachllachachachTradeonachachachdevachachachypachachachllachachachTradeona+0x20\/0x28
[    0.000000] [<ffffffe00009499c>] bad_page+0xe4\/0x102
[    0.000000] [<ffffffe0000949f2>] free_pages_check_bad+0x38\/0x7a
[    0.000000] [<ffffffe0000955c6>] __free_pages_ok+0x3fe\/0x430
[    0.000000] [<ffffffe0000960ea>] __free_pages.part.28+0x1a\/0x22
[    0.000000] [<ffffffe0000056da>] __free_pages_bootmem+0x86\/0x90
[    0.000000] [<ffffffe000007c46>] free_all_bootmem+0x156\/0x1ba
[    0.000000] [<ffffffe0000023f8>] mem_init+0x36\/0x44
[    0.000000] [<ffffffe0000007a0>] start_kernel+0x1aa\/0x328
[    0.000000] [<ffffffe000000058>] _sinittext+0x58\/0x5c
[    0.000000] BUG: Stare proastă a paginii în procesul swapper  pfn:80bfb
[    0.000000] pagină:ffffffe03f029ee8 count:0 mapcount:-65280 mapping:0000000000000000 index:0x0
[    0.000000] flags: 0x0()
[    0.000000] raw: 0000000000000000 ffffffe03f0200f0 ffffffe03f0200f0 0000000000000000
[    0.000000] raw: 0000000000000000 0000000000000000 00000000ffff00ff
[    0.000000] pagina dumpată deoarece: mapcount nonzero
[    0.000000] Module legate în:
[    0.000000] CPU: 0 PID: 0 Comm: swapper Contaminat: G    B             4.19.0-sifive-1+ #1
[    0.000000] Call Trace:
[    0.000000] [<ffffffe00002cfde>] walk_stackframe+0x0\/0xa0
[    0.000000] [<ffffffe00002d1da>] show_stack+0x2a\/0x34
[    0.000000] [<ffffffe00063c898>] chachachllachachachTradeonachachach_inachachipachachachachllachachachTradeonachachachdevachachachypachachachllachachachTradeona+0x20\/0x28
[    0.000000] [<ffffffe00009499c>] bad_page+0xe4\/0x102
[    0.000000] [<ffffffe0000949f2>] free_pages_check_bad+0x38\/0x7a
[    0.000000] [<ffffffe0000955c6>] __free_pages_ok+0x3fe\/0x430
[    0.000000] [<ffffffe0000960ea>] __free_pages.part.28+0x1a\/0x22
[    0.000000] [<ffffffe0000056da>] __free_pages_bootmem+0x86\/0x90
[    0.000000] [<ffffffe000007c46>] free_all_bootmem+0x156\/0x1ba
[    0.000000] [<ffffffe0000023f8>] mem_init+0x36\/0x44
[    0.000000] [<ffffffe0000007a0>] start_kernel+0x1aa\/0x328
[    0.000000] [<ffffffe000000058>] _sinittext+0x58\/0x5c

Interesant, că după toată depanarea, am decis să văd cum ar trebui să arate ieșirea „de referință” a nucleului, a spus make qemu, și am văzut o eroare similară.

Din păcate, următorul nivel (nucleul Linux) este mai complicat: GDB, conectat prin JTAG la RocketChip, funcționează, aparent, cu adrese fizice, indiferent de cum este configurat MMU, iar nucleul la momentul de interes a configurat deja maparea adreselor, așa că pur și simplu să spunem display/10i $pc nu va funcționa — vom vedea doar multe unimp. Totuși, dacă deja am stabilit decalajul (se pare că 0x80200000 -> 0xffffffe000000000), putem fi ingenioși:

1: x/10i $pc
-> 0xffffffe000002436 :      unimp
   0xffffffe000002438 :    unimp
   0xffffffe00000243a :    unimp
   0xffffffe00000243c :    unimp
   0xffffffe00000243e :    unimp
   0xffffffe000002440 :   unimp
   0xffffffe000002442 :   unimp
   0xffffffe000002444 :   unimp
   0xffffffe000002446 :   unimp
   0xffffffe000002448 :   unimp
(gdb) undisplay 1
(gdb) display/10i ($pc - 0xffffffe000002436 + 0x80202436)
2: x/10i ($pc - 0xffffffe000002436 + 0x80202436)
   0x80202436:  addi    sp,sp,-96
   0x80202438:  sd      s0,80(sp)
   0x8020243a:  sd      s1,72(sp)
   0x8020243c:  sd      s2,64(sp)
   0x8020243e:  sd      s3,56(sp)
   0x80202440:  sd      s4,48(sp)
   0x80202442:  sd      s5,40(sp)
   0x80202444:  sd      s6,32(sp)
   0x80202446:  sd      s7,24(sp)
   0x80202448:  sd      s8,16(sp)

Punctele de întrerupere sunt stabilite similar:

(gdb) p setup_smp
$1 = {} 0xffffffe000002436 
(gdb) b *0x80202436
Breakpoint 1 at 0x80202436
(gdb) c
Continuing.

Program received signal SIGTRAP, Trace/breakpoint trap.
setup_smp () at /home/trosinenko/freedom-u-sdk/linux/arch/riscv/kernel/smpboot.c:58
58              while ((dn = of_find_node_by_type(dn, "cpu"))) {
(gdb) bt
#0  setup_smp () at /home/trosinenko/freedom-u-sdk/linux/arch/riscv/kernel/smpboot.c:58
#1  0xffffffe0000022a2 in setup_arch () at /home/trosinenko/freedom-u-sdk/linux/arch/riscv/kernel/setup.c:253
#2  0x0000000000000000 in ?? ()
Backtrace stopped: frame did not save the PC

Din păcate, trebuie să le elimin manual pentru a continua — pentru GDB, acesta este un tip de capcană complet incomprehensibil. Ah, da, dacă spuneți accidental s sau n în loc de si, gdb va încerca să insereze un punct de întrerupere implicit, care din motive evidente nu va fi setat, dar nu poate să descurajeze GDB. Dar nu vă grăbiți să reporniți placa — din observațiile mele, este suficient să reporniți doar gdb (rețineți că vechile puncte de întrerupere nu vor dispărea, poate).

Prin urmare, va trebui să mă ocup de problema inițială: plasarea punctelor de întrerupere printk în funcția of_find_node_by_type, folosit de codul de căutare al nucleului procesorului de încărcare, arată că observa un fel de zgomot în loc de numele tipurilor de dispozitive. De exemplu, preia dintr-o sursă linia «Serial port», deși nu există așa ceva în dtb în câmpul device_type. Căutând aceste octeți în imaginea nucleului, i-am găsit, am privit la deplasare și mi-am dat seama de evident: dimensiunea nucleului în parametrii de încărcare este evident subestimată: i s-au alocat 8Mb, dar ocupă mai mult de zece. Am alocat 16Mb, dar ciudățeniile nu s-au oprit. După multe încercări cu citirea FDT din diferite adrese (în mod obișnuit, adresa este transmisă nucleului în registrul a1), în cele din urmă am decis să fac o urmărire despre ce anume acum este acolo analizat. Din fericire, în loc de a umbla cu un debugger (iar noi ne amintim că există nuanțe în traducerea adreselor care trebuie să fie rezolvate), se poate pur și simplu și improvizat în fișierul drivers/of/fdt.c specifica #define pr_debug printk. În cele din urmă, a ieșit:

adăugarea unei ieșiri de depanare

diff --git a/arch/riscv/kernel/setup.c b/arch/riscv/kernel/setup.c
index 3db0d71d128b..fac47df9d1db 100644
--- a/arch/riscv/kernel/setup.c
+++ b/arch/riscv/kernel/setup.c
@@ -173,6 +173,7 @@ asmlinkage void __init setup_vm(void)

 void __init parse_dtb(unsigned int hartid, void *dtb)
 {
+       printk("HART = %u DTB = %lxn", hartid, dtb);
        early_init_dt_scan(__va(dtb));
 }

diff --git a/drivers/of/base.c b/drivers/of/base.c
index 74eaedd5b860..c019e4158e1d 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -940,10 +940,12 @@ struct device_node *of_find_node_by_type(struct device_node *from,
        unsigned long flags;

        raw_spin_lock_irqsave(&devtree_lock, flags);
-       for_each_of_allnodes_from(from, np)
+       for_each_of_allnodes_from(from, np) {
+               printk("%lx %lx [%s] | [%s]n", from, np, np->type, type);
                if (np->type && (of_node_cmp(np->type, type) == 0)
                    && of_node_get(np))
                        break;
+       }
        of_node_put(from);
        raw_spin_unlock_irqrestore(&devtree_lock, flags);
        return np;
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index 800ad252cf9c..2b45870ebada 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -31,6 +31,8 @@

 #include "of_private.h"

+#define pr_debug printk
+
 /*
  * of_fdt_limit_memory - limitează numărul de regiuni în nodul /memory
  * @limit: intrări maxime
@@ -1253,6 +1255,7 @@ bool __init early_init_dt_scan(void *params)
  * /
 void __init unflatten_device_tree(void)
 {
+       printk("INITIAL: %lxn", initial_boot_params);
        __unflatten_device_tree(initial_boot_params, NULL, &of_root,
                                early_init_dt_alloc_memory_arch, false);

Ieșire pe hardware

                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
 {
  #address-cells = ;
  #size-cells = ;
  compatible = "freechips,rocketchip-unknown-dev";
  model = "freechips,rocketchip-unknown";
  chosen {
    linux,initrd-start = ;
    riscv,kernel-end = ;
    riscv,kernel-start = ;
    #address-cells = ;
    #size-cells = ;
    bootargs = ;
  }
  firmware {
    sifive,uboot = "YYYY-MM-DD";
  }
  aliases {
    serial0 = ;
  }
  cpus {
    #address-cells = ;
    #size-cells = ;
    cpu@0 {
      device_type = "cpu";
      clock-frequency = ;
      compatible = "sifive,rocket0", "riscv";
      d-cache-block-size = ;
      d-cache-sets = ;
      d-cache-size = ;
      d-tlb-sets = ;
      d-tlb-size = ;
      i-cache-block-size = ;
      i-cache-sets = ;
      i-cache-size = ;
      i-tlb-sets = ;
      i-tlb-size = ;
      mmu-type = "riscv,sv39";
      next-level-cache = ;
      reg = ;
      riscv,isa = "rv64imafdc";
      status = "okay";
      timebase-frequency = ;
      tlb-split;
      interrupt-controller {
        #interrupt-cells = ;
        compatible = "riscv,cpu-intc";
        interrupt-controller;
        phandle = ;
      }
    }
  }
  ram@80000000 {
    device_type = "memory";
    reg = ;
    reg-names = "mem";
    phandle = ;
  }
  soc {
    #address-cells = ;
    #size-cells = ;
    compatible = "freechips,rocketchip-unknown-soc", "simple-bus";
    ranges;
    clint@2000000 {
      compatible = "riscv,clint0";
      interrupts-extended = ;
      reg = ;
      reg-names = "control";
    }
    debug-controller@0 {
      compatible = "sifive,debug-013", "riscv,debug-013";
      interrupts-extended = ;
      reg = ;
      reg-names = "control";
    }
    gpio@64002000 {
      #gpio-cells = ;
      #interrupt-cells = ;
      compatible = "sifive,gpio0";
      gpio-controller;
      interrupt-controller;
      interrupt-parent = ;
      interrupts = ;
      reg = ;
      reg-names = "control";
    }
    interrupt-controller@c000000 {
      #interrupt-cells = ;
      compatible = "riscv,plic0";
      interrupt-controller;
      interrupts-extended = ;
      reg = ;
      reg-names = "control";
      riscv,max-priority = ;
      riscv,ndev = ;
      phandle = ;
    }
    rom@10000 {
      compatible = "sifive,maskrom0";
      reg = ;
      reg-names = "mem";
    }
    serial@64000000 {
      compatible = "sifive,uart0";
      interrupt-parent = ;
      interrupts = ;
      reg = ;
      reg-names = "control";
    }
    spi@64001000 {
      #address-cells = ;
      #size-cells = ;
      compatible = "sifive,spi0";
      interrupt-parent = ;
      interrupts = ;
      reg = ;
      reg-names = "control";
      mmc@0 {
        compatible = "mmc-spi-slot";
        disable-wp;
        reg = ;
        spi-max-frequency = ;
        voltage-ranges = ;
      }
    }
    tlclk {
      #clock-cells = ;
      clock-frequency = ;
      clock-output-names = "tlclk";
      compatible = "fixed-clock";
    }
  }
}
[    0.000000] HART = 0 DTB = 81200000
[    0.000000] search "chosen", depth: 0, uname:
[    0.000000] search "chosen", depth: 1, uname: chosen
[    0.000000] Looking for initrd properties...
[    0.000000] Command line is: debug console=ttySIF0,125200 root=\/dev\/mmcblk0p2 loglevel=7 rootwait
[    0.000000] dt_root_size_cells = 1
[    0.000000] dt_root_addr_cells = 1
[    0.000000] memory scan node ram@80000000, reg size 8,
[    0.000000]  - 80000000 ,  40000000
[    0.000000] OF: fdt: Ignoring memory range 0x80000000 - 0x80200000
[    0.000000] Linux version 4.19.0-sifive-1+ (trosinenko@trosinenko-pc) (gcc version 8.3.0 (Buildroot 2019.02-07449-g4eddd28f99)) #1 SMP Sat Jul 6 12:14:41 MSK 2019
[    0.000000] bootconsole [early0] enabled
[    0.000000] initrd not found or empty - disabling initrd
[    0.000000] Zone ranges:
[    0.000000]   DMA32    [mem 0x0000000080200000-0x00000000bfffffff]
[    0.000000]   Normal   [mem 0x00000000c0000000-0x00000bffffffffff]
[    0.000000] Movable zone start for each node
[    0.000000] Early memory node ranges
[    0.000000]   node   0: [mem 0x0000000080200000-0x00000000bfffffff]
[    0.000000] Initmem setup node 0 [mem 0x0000000080200000-0x00000000bfffffff]
[    0.000000] INITIAL: ffffffe001000000
[    0.000000]  -> unflatten_device_tree()
[    0.000000] Unflattening device tree:
[    0.000000] magic: d00dfeed
[    0.000000] size: 00001000
[    0.000000] version: 00000011
[    0.000000]   size is 13512, allocating...
[    0.000000]   unflattening (____ptrval____)...
[    0.000000] fixed up name for  ->
[    0.000000] fixed up name for chosen -> chosen
[    0.000000] fixed up name for firmware -> firmware
[    0.000000] fixed up name for aliases -> aliases
[    0.000000] fixed up name for cpus -> cpus
[    0.000000] fixed up name for cpu@0 -> cpu
[    0.000000] fixed up name for interrupt-controller -> interrupt-controller
[    0.000000] fixed up name for ram@80000000 -> ram
[    0.000000] fixed up name for soc -> soc
[    0.000000] fixed up name for clint@2000000 -> clint
[    0.000000] fixed up name for debug-controller@0 -> debug-controller
[    0.000000] fixed up name for gpio@64002000 -> gpio
[    0.000000] fixed up name for interrupt-controller@c000000 -> interrupt-controller
[    0.000000] fixed up name for rom@10000 -> rom
[    0.000000] fixed up name for serial@64000000 -> serial
[    0.000000] fixed up name for spi@64001000 -> spi
[    0.000000] fixed up name for mmc@0 -> mmc
[    0.000000] fixed up name for tlclk -> tlclk
[    0.000000]  <- unflatten_device_tree()
[    0.000000] software IO TLB: mapped [mem 0xbb1fc000-0xbf1fc000] (64MB)
[    0.000000] 0 ffffffe03effcab0 [attach() failed for %s with error %d
[    0.000000] ] | [cpu]
[    0.000000] 0 ffffffe03eff0020 [(null)] | [cpu]

Ieşire în QEMU

                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
 {
  #address-cells = ;
  #size-cells = ;
  compatible = "riscv-virtio";
  model = "riscv-virtio,qemu";
  chosen {
    linux,initrd-start = ;
    linux,initrd-end = ;
    riscv,kernel-start = ;
    riscv,kernel-end = ;
    bootargs = "";
    stdout-path = ;
  }
  uart@10000000 {
    interrupts = ;
    interrupt-parent = ;
    clock-frequency = ;
    reg = ;
    compatible = "ns16550a";
  }
  test@100000 {
    reg = ;
    compatible = "sifive:test0";
  }
  virtio_mmio@10008000 {
    interrupts = ;
    interrupt-parent = ;
    reg = ;
    compatible = "virtio,mmio";
  }
  virtio_mmio@10007000 {
    interrupts = ;
    interrupt-parent = ;
    reg = ;
    compatible = "virtio,mmio";
  }
  virtio_mmio@10006000 {
    interrupts = ;
    interrupt-parent = ;
    reg = ;
    compatible = "virtio,mmio";
  }
  virtio_mmio@10005000 {
    interrupts = ;
    interrupt-parent = ;
    reg = ;
    compatible = "virtio,mmio";
  }
  virtio_mmio@10004000 {
    interrupts = ;
    interrupt-parent = ;
    reg = ;
    compatible = "virtio,mmio";
  }
  virtio_mmio@10003000 {
    interrupts = ;
    interrupt-parent = ;
    reg = ;
    compatible = "virtio,mmio";
  }
  virtio_mmio@10002000 {
    interrupts = ;
    interrupt-parent = ;
    reg = ;
    compatible = "virtio,mmio";
  }
  virtio_mmio@10001000 {
    interrupts = ;
    interrupt-parent = ;
    reg = ;
    compatible = "virtio,mmio";
  }
  cpus {
    #address-cells = ;
    #size-cells = ;
    timebase-frequency = ;
    cpu@0 {
      device_type = "cpu";
      reg = ;
      status = "okay";
      compatible = "riscv";
      riscv,isa = "rv64imafdcsu";
      mmu-type = "riscv,sv48";
      clock-frequency = ;
      interrupt-controller {
        #interrupt-cells = ;
        interrupt-controller;
        compatible = "riscv,cpu-intc";
        linux,phandle = ;
        phandle = ;
      }
    }
  }
  memory@80000000 {
    device_type = "memory";
    reg = ;
  }
  soc {
    #address-cells = ;
    #size-cells = ;
    compatible = "simple-bus";
    ranges;
    pci@30000000 {
      interrupt-map-mask = ;
      interrupt-map = ;
      ranges = ;
      reg = ;
      dma-coherent;
      bus-range = ;
      linux,pci-domain = ;
      device_type = "pci";
      compatible = "pci-host-ecam-generic";
      #size-cells = ;
      #interrupt-cells = ;
      #address-cells = ;
    }
    interrupt-controller@c000000 {
      linux,phandle = ;
      phandle = ;
      riscv,ndev = ;
      riscv,max-priority = ;
      reg-names = "control";
      reg = ;
      interrupts-extended = ;
      interrupt-controller;
      compatible = "riscv,plic0";
      #interrupt-cells = ;
      #address-cells = ;
    }
    clint@2000000 {
      interrupts-extended = ;
      reg = ;
      compatible = "riscv,clint0";
    }
  }
}
[    0.000000] HART = 0 DTB = 80e00000
[    0.000000] search "chosen", depth: 0, uname:
[    0.000000] search "chosen", depth: 1, uname: chosen
[    0.000000] Looking for initrd properties...
[    0.000000] initrd_start=0x88000000  initrd_end=0x88442b86
[    0.000000] Command line is: earlyprintk
[    0.000000] dt_root_size_cells = 2
[    0.000000] dt_root_addr_cells = 2
[    0.000000] memory scan node memory@80000000, reg size 16,
[    0.000000]  - 80000000 ,  40000000
[    0.000000] OF: fdt: Ignoring memory range 0x80000000 - 0x80200000
[    0.000000] Linux version 4.19.0-sifive-1+ (trosinenko@trosinenko-pc) (gcc version 8.3.0 (Buildroot 2019.02-07449-g4eddd28f99)) #1 SMP Sat Jul 6 12:14:41 MSK 2019
[    0.000000] bootconsole [early0] enabled
[    0.000000] Initial ramdisk at: 0x(____ptrval____) (4467590 bytes)
[    0.000000] Zone ranges:
[    0.000000]   DMA32    [mem 0x0000000080200000-0x00000000bfffffff]
[    0.000000]   Normal   [mem 0x00000000c0000000-0x00000bffffffffff]
[    0.000000] Movable zone start for each node
[    0.000000] Early memory node ranges
[    0.000000]   node   0: [mem 0x0000000080200000-0x00000000bfffffff]
[    0.000000] Initmem setup node 0 [mem 0x0000000080200000-0x00000000bfffffff]
[    0.000000] INITIAL: ffffffe000c00000
[    0.000000]  -> unflatten_device_tree()
[    0.000000] Unflattening device tree:
[    0.000000] magic: d00dfeed
[    0.000000] size: 00000d56
[    0.000000] version: 00000011
[    0.000000]   size is 14192, allocating...
[    0.000000]   unflattening (____ptrval____)...
[    0.000000] fixed up name for  ->
[    0.000000] fixed up name for chosen -> chosen
[    0.000000] fixed up name for uart@10000000 -> uart
[    0.000000] fixed up name for test@100000 -> test
[    0.000000] fixed up name for virtio_mmio@10008000 -> virtio_mmio
[    0.000000] fixed up name for virtio_mmio@10007000 -> virtio_mmio
[    0.000000] fixed up name for virtio_mmio@10006000 -> virtio_mmio
[    0.000000] fixed up name for virtio_mmio@10005000 -> virtio_mmio
[    0.000000] fixed up name for virtio_mmio@10004000 -> virtio_mmio
[    0.000000] fixed up name for virtio_mmio@10003000 -> virtio_mmio
[    0.000000] fixed up name for virtio_mmio@10002000 -> virtio_mmio
[    0.000000] fixed up name for virtio_mmio@10001000 -> virtio_mmio
[    0.000000] fixed up name for cpus -> cpus
[    0.000000] fixed up name for cpu@0 -> cpu
[    0.000000] fixed up name for interrupt-controller -> interrupt-controller
[    0.000000] fixed up name for memory@80000000 -> memory
[    0.000000] fixed up name for soc -> soc
[    0.000000] fixed up name for pci@30000000 -> pci
[    0.000000] fixed up name for interrupt-controller@c000000 -> interrupt-controller
[    0.000000] fixed up name for clint@2000000 -> clint
[    0.000000]  <- unflatten_device_tree()
[    0.000000] software IO TLB: mapped [mem 0xbb1fc000-0xbf1fc000] (64MB)
[    0.000000] 0 ffffffe03effc808 [<NULL>] | [cpu]
[    0.000000] 0 ffffffe03effca78 [<NULL>] | [cpu]
[    0.000000] 0 ffffffe03effcd98 [<NULL>] | [cpu]
[    0.000000] 0 ffffffe03effd068 [<NULL>] | [cpu]
[    0.000000] 0 ffffffe03effd230 [<NULL>] | [cpu]
[    0.000000] 0 ffffffe03effd4b8 [<NULL>] | [cpu]
[    0.000000] 0 ffffffe03effd740 [<NULL>] | [cpu]
[    0.000000] 0 ffffffe03effd9c8 [<NULL>] | [cpu]
[    0.000000] 0 ffffffe03effdc50 [<NULL>] | [cpu]
[    0.000000] 0 ffffffe03effded8 [<NULL>] | [cpu]
[    0.000000] 0 ffffffe03effe160 [<NULL>] | [cpu]
[    0.000000] 0 ffffffe03effe3e8 [<NULL>] | [cpu]
[    0.000000] 0 ffffffe03effe670 [<NULL>] | [cpu]
[    0.000000] 0 ffffffe03effe888 [cpu] | [cpu]
[    0.000000] ffffffe03effe888 ffffffe03effec00 [<NULL>] | [cpu]
[    0.000000] ffffffe03effe888 ffffffe03effeee8 [memory] | [cpu]
[    0.000000] ffffffe03effe888 ffffffe03efff0b0 [<NULL>] | [cpu]
[    0.000000] ffffffe03effe888 ffffffe03efff320 [pci] | [cpu]
[    0.000000] ffffffe03effe888 ffffffe03efff858 [<NULL>] | [cpu]
[    0.000000] ffffffe03effe888 ffffffe03efffd58 [<NULL>] | [cpu]
[    0.000000] 0 ffffffe03effc808 [<NULL>] | [cpu]
[    0.000000] 0 ffffffe03effca78 [<NULL>] | [cpu]
[    0.000000] 0 ffffffe03effcd98 [<NULL>] | [cpu]
[    0.000000] 0 ffffffe03effd068 [<NULL>] | [cpu]
[    0.000000] 0 ffffffe03effd230 [<NULL>] | [cpu]
[    0.000000] 0 ffffffe03effd4b8 [<NULL>] | [cpu]
[    0.000000] 0 ffffffe03effd740 [<NULL>] | [cpu]
[    0.000000] 0 ffffffe03effd9c8 [<NULL>] | [cpu]
[    0.000000] 0 ffffffe03effdc50 [<NULL>] | [cpu]
[    0.000000] 0 ffffffe03effded8 [<NULL>] | [cpu]
[    0.000000] 0 ffffffe03effe160 [<NULL>] | [cpu]
[    0.000000] 0 ffffffe03effe3e8 [<NULL>] | [cpu]
[    0.000000] 0 ffffffe03effe670 [<NULL>] | [cpu]
[    0.000000] 0 ffffffe03effe888 [cpu] | [cpu]
[    0.000000] elf_hwcap is 0x112d
[    0.000000] percpu: Embedded 17 pages/cpu @(____ptrval____) s29400 r8192 d32040 u69632
[    0.000000] Built 1 zonelists, mobility grouping on.  Total pages: 258055
[    0.000000] Kernel command line: earlyprintk
[    0.000000] Dentry cache hash table entries: 131072 (order: 8, 1048576 bytes)
[    0.000000] Inode-cache hash table entries: 65536 (order: 7, 524288 bytes)
[    0.000000] Sorting __ex_table...
[    0.000000] Memory: 949716K/1046528K available (6565K kernel code, 342K rwdata, 2564K rodata, 208K init, 832K bss, 96812K reserved, 0K cma-reserved)
[    0.000000] SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
[    0.000000] rcu: Hierarchical RCU implementation.
[    0.000000] rcu:     RCU event tracing is enabled.
[    0.000000] rcu:     RCU restricting CPUs from NR_CPUS=8 to nr_cpu_ids=1.
[    0.000000] rcu: Adjusting geometry for rcu_fanout_leaf=16, nr_cpu_ids=1
[    0.000000] NR_IRQS: 0, nr_irqs: 0, preallocated irqs: 0
[    0.000000] plic: mapped 53 interrupts to 2 (out of 2) handlers.
[    0.000000] clocksource: riscv_clocksource: mask: 0xffffffffffffffff max_cycles: 0x24e6a1710, max_idle_ns: 440795202120 ns
[    0.000000] Console: colour dummy device 80x25
[    0.000000] console [tty0] enabled
[    0.000000] bootconsole [early0] disabled
[    0.000000] Calibrating delay loop (skipped), value calculated using timer frequency.. 20.00 BogoMIPS (lpj=100000)
[    0.000000] pid_max: default: 32768 minimum: 301
[    0.000000] Mount-cache hash table entries: 2048 (order: 2, 16384 bytes)
[    0.000000] Mountpoint-cache hash table entries: 2048 (order: 2, 16384 bytes)
[    0.020000] rcu: Hierarchical SRCU implementation.
[    0.020000] smp: Bringing up secondary CPUs ...
[    0.020000] smp: Brought up 1 node, 1 CPU
[    0.050000] devtmpfs: initialized
[    0.050000] 0 ffffffe03effc808 [<NULL>] | [cpu]
[    0.050000] 0 ffffffe03effca78 [<NULL>] | [cpu]
[    0.050000] 0 ffffffe03effcd98 [<NULL>] | [cpu]
[    0.050000] 0 ffffffe03effd068 [<NULL>] | [cpu]
[    0.050000] 0 ffffffe03effd230 [<NULL>] | [cpu]
[    0.050000] 0 ffffffe03effd4b8 [<NULL>] | [cpu]
[    0.050000] 0 ffffffe03effd740 [<NULL>] | [cpu]
[    0.050000] 0 ffffffe03effd9c8 [<NULL>] | [cpu]
[    0.050000] 0 ffffffe03effdc50 [<NULL>] | [cpu]
[    0.050000] 0 ffffffe03effded8 [<NULL>] | [cpu]
[    0.050000] 0 ffffffe03effe160 [<NULL>] | [cpu]
[    0.050000] 0 ffffffe03effe3e8 [<NULL>] | [cpu]
[    0.050000] 0 ffffffe03effe670 [<NULL>] | [cpu]
[    0.050000] 0 ffffffe03effe888 [cpu] | [cpu]
[    0.050000] random: get_random_u32 called from bucket_table_alloc+0x76/0x17a with crng_init=0
[    0.050000] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604462750000 ns
[    0.050000] futex hash table entries: 256 (order: 2, 16384 bytes)
[    0.060000] NET: Registered protocol family 16
[    0.090000] vgaarb: loaded
[    0.090000] SCSI subsystem initialized
[    0.090000] usbcore: registered new interface driver usbfs
[    0.090000] usbcore: registered new interface driver hub
[    0.090000] usbcore: registered new device driver usb
[    0.090000] pps_core: LinuxPPS API ver. 1 registered
[    0.090000] pps_core: Software ver. 5.3.6 - Copyright 2005-2007 Rodolfo Giometti <giometti@linux.it>
[    0.090000] PTP clock support registered
[    0.100000] Advanced Linux Sound Architecture Driver Initialized.
[    0.100000] clocksource: Switched to clocksource riscv_clocksource
[    0.110000] NET: Registered protocol family 2
[    0.110000] tcp_listen_portaddr_hash hash table entries: 512 (order: 1, 8192 bytes)
[    0.110000] TCP established hash table entries: 8192 (order: 4, 65536 bytes)
[    0.110000] TCP bind hash table entries: 8192 (order: 5, 131072 bytes)
[    0.110000] TCP: Hash tables configured (established 8192 bind 8192)
[    0.110000] UDP hash table entries: 512 (order: 2, 16384 bytes)
[    0.110000] UDP-Lite hash table entries: 512 (order: 2, 16384 bytes)
[    0.110000] NET: Registered protocol family 1
[    0.120000] Unpacking initramfs...
[    0.590000] workingset: timestamp_bits=62 max_order=18 bucket_order=0
[    0.620000] Block layer SCSI generic (bsg) driver version 0.4 loaded (major 251)
[    0.620000] io scheduler noop registered
[    0.620000] io scheduler deadline registered
[    0.620000] io scheduler cfq registered (default)
[    0.620000] io scheduler mq-deadline registered
[    0.620000] io scheduler kyber registered
[    0.620000] shpchp: Standard Hot Plug PCI Controller Driver version: 0.4
[    0.690000] Serial: 8250/16550 driver, 4 ports, IRQ sharing disabled
[    0.690000] 10000000.uart: ttyS0 at MMIO 0x10000000 (irq = 10, base_baud = 230400) is a 16550A
[    0.720000] console [ttyS0] enabled
[    0.720000] [drm] radeon kernel modesetting enabled.
[    0.720000] [drm] amdgpu kernel modesetting enabled.
[    0.730000] loop: module loaded
[    0.730000] libphy: Fixed MDIO Bus: probed
[    0.740000] e1000e: Intel(R) PRO/1000 Network Driver - 3.2.6-k
[    0.740000] e1000e: Copyright(c) 1999 - 2015 Intel Corporation.
[    0.740000] ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
[    0.740000] ehci-pci: EHCI PCI platform driver
[    0.740000] ehci-platform: EHCI generic platform driver
[    0.740000] mousedev: PS/2 mouse device common for all mice
[    0.740000] usbcore: registered new interface driver usbhid
[    0.740000] usbhid: USB HID core driver
[    0.740000] usbcore: registered new interface driver snd-usb-audio
[    0.740000] NET: Registered protocol family 10
[    0.750000] Segment Routing with IPv6
[    0.750000] sit: IPv6, IPv4 and MPLS over IPv4 tunneling driver
[    0.750000] NET: Registered protocol family 17
[    0.750000] Key type dns_resolver registered
[    0.760000] ALSA device list:
[    0.760000]   No soundcards found.
[    0.770000] Freeing unused kernel memory: 208K
[    0.770000] This architecture does not have kernel memory protection.
[    0.770000] Run /init as init process

(«Timestamped» rows are output by the kernel, before them the tree outputs BBL) On one side, FDT is read successfully, on the other, it results in some nonsense in the parsed "object" tree.

During debugging, I realized that BBL could not read the "double" address not because there was an error in the config, but simply because the root node was set. #address-cells = <1>; #size-cells = <1>;.

By expanding the debug output, I saw that the pointers to type și name "crashed", and in a rather strange way: their first (starting from zero) byte was zeroed out, something like 0xabcdef -> 0xab00ef. I had to use a familiar tactic: knowing the addresses where the damaged memory is located, I wrote into the function printk to print this data. Well, and scattered the calls printk where they were few. Unfortunately, it didn't become significantly clearer. Then I began, comparing with the disassembled objdump version, to manually set breakpoints and step through the problematic section of code. And here a mysterious and unpleasant discovery was made: if I immediately set a breakpoint somewhere relative to a known-good state, then, stopping on it, I would see already damaged memory. But if I try to sneak up on it step by step, the error manages to hide! This smells like a faulty memory controller and a cache hiding the error if the required value is continuously requested. And what if...

Replacing memory

Clinging to the possibility of solving the problem not on my side, I assumed that maybe I just got a faulty stick of memory. Then I remembered that a decade-old netbook is not only a portable computer but also a valuable source of DDR2 SO-DIMM. As a bonus, you can insert the memory removed from the board, and get almost an instant hang from Memtest (Linux, by the way, was loading almost to the graphical shell at this point. But better not to repeat such an experiment if you value the information on mounted drives...). On one hand, it can be assumed that the memory simply did not fit this netbook. On the other hand, it managed to boot! There was hope that the memory was just "faulty", and the issue was not with my wrapper.

Așadar, trebuie să încercăm să ne pornim temporar cu memorie de netbook. Din păcate, Quartus 18 nu poate actualiza acest IP Core astfel încât să fie editabil. Aceasta înseamnă că a venit momentul să învățăm să creăm noi instanțe. S-a dovedit a fi destul de simplu: căutăm în IP Catalog elementul DDR2 SDRAM Controller with ALTMEMPHY Intel FPGA IP și obținem un bloc cu același interfață ca înainte. Singura problemă este să setăm corect configurațiile memoriei.

Obținem parametrii modulului de memorie

Există o modalitate relativ evidentă de a configura modulul: citind parametrii din SPD. De fapt, dacă un computer obișnuit citește datele SPD și configurează controlerul în funcție de acestea, atunci să citim aceste date pe netbookul disponibil și să le introducem într-un tabel.

Acest lucru se face pe Ubuntu destul de ușor: trebuie să instalăm pachetul i2c-tools, să încărcăm modulele eeprom și i2c-i801 (nu sunt sigur, totuși, că al doilea driver se potrivește peste tot), după care să rulăm decode-dimms:

Ieșirea decode-dimms

# decode-dimms version 6231 (2014-02-20 10:54:34 +0100)

Memory Serial Presence Detect Decoder
By Philip Edelbrock, Christian Zuckschwerdt, Burkart Lingner,
Jean Delvare, Trent Piepho and others

Decoding EEPROM: /sys/bus/i2c/drivers/eeprom/0-0050
Guessing DIMM is in                             bank 1

---=== SPD EEPROM Information ===---
EEPROM Checksum of bytes 0-62                   OK (0x00)
SPD Revision                                    Invalid
Fundamental Memory type                         Unknown (0x00)

---=== Manufacturing Information ===---
Manufacturer                                    Undefined
Part Number                                     Undefined

Decoding EEPROM: /sys/bus/i2c/drivers/eeprom/4-0050
Guessing DIMM is in                             bank 1

---=== SPD EEPROM Information ===---
EEPROM Checksum of bytes 0-62                   OK (0x00)
SPD Revision                                    Invalid
Fundamental Memory type                         Unknown (0x00)

---=== Manufacturing Information ===---
Manufacturer                                    Undefined
Part Number                                     Undefined

Decoding EEPROM: /sys/bus/i2c/drivers/eeprom/6-0050
Guessing DIMM is in                             bank 1

---=== SPD EEPROM Information ===---
EEPROM Checksum of bytes 0-62                   OK (0x76)
# of bytes written to SDRAM EEPROM              128
Total number of bytes in EEPROM                 256
Fundamental Memory type                         DDR2 SDRAM
SPD Revision                                    1.2

---=== Memory Characteristics ===---
Maximum module speed                            800 MHz (PC2-6400)
Size                                            1024 MB
Banks x Rows x Columns x Bits                   8 x 13 x 10 x 64
Ranks                                           2
SDRAM Device Width                              16 bits
Module Height                                   30.0 mm
Module Type                                     SO-DIMM (67.6 mm)
DRAM Package                                    Planar
Voltage Interface Level                         SSTL 1.8V
Module Configuration Type                       No Parity
Refresh Rate                                    Reduced (7.8 us) - Self Refresh
Supported Burst Lengths                         4, 8
tCL-tRCD-tRP-tRAS                               6-6-6-18
Supported CAS Latencies (tCL)                   6T, 5T, 4T
Minimum Cycle Time                              2.50 ns at CAS 6 (tCK min)
                                                3.00 ns at CAS 5
                                                3.75 ns at CAS 4
Maximum Access Time                             0.40 ns at CAS 6 (tAC)
                                                0.45 ns at CAS 5
                                                0.50 ns at CAS 4
Maximum Cycle Time (tCK max)                    8.00 ns

---=== Timing Parameters ===---
Address/Command Setup Time Before Clock (tIS)   0.17 ns
Address/Command Hold Time After Clock (tIH)     0.25 ns
Data Input Setup Time Before Strobe (tDS)       0.05 ns
Data Input Hold Time After Strobe (tDH)         0.12 ns
Minimum Row Precharge Delay (tRP)               15.00 ns
Minimum Row Active to Row Active Delay (tRRD)   10.00 ns
Minimum RAS# to CAS# Delay (tRCD)               15.00 ns
Minimum RAS# Pulse Width (tRAS)                 45.00 ns
Write Recovery Time (tWR)                       15.00 ns
Minimum Write to Read CMD Delay (tWTR)          7.50 ns
Minimum Read to Pre-charge CMD Delay (tRTP)     7.50 ns
Minimum Active to Auto-refresh Delay (tRC)      60.00 ns
Minimum Recovery Delay (tRFC)                   127.50 ns
Maximum DQS to DQ Skew (tDQSQ)                  0.20 ns
Maximum Read Data Hold Skew (tQHS)              0.30 ns

---=== Manufacturing Information ===---
Manufacturer                                    Samsung
Manufacturing Location Code                     0x02
Part Number                                     M4 70T2864QZ3-CF7
Revision Code                                   0x3351
Manufacturing Date                              2009-W34
Assembly Serial Number                          0x79C64E9A

Number of SDRAM DIMMs detected and decoded: 3

Problema este că unele timpi nu sunt specificați aici, așa că vom urma a doua cale.

Ce avem scris pe module:

Partea 4: În cele din urmă, lansăm Linux pe RocketChip RISC-VPartea 4: În cele din urmă, lansăm Linux pe RocketChip RISC-V

În acest caz, inscripția pe cipurile de memorie este mai interesantă: K4T1G164QQ-HCF7. Introducând această linie în Google, obținem un datasheet de câteva zeci de pagini cu toate parametrii necesari, pe care îi putem introduce cu atenție în proprietățile IP Core. Doar fiți atenți la unitățile de măsură: undeva ns, undeva — ps, iar uneori chiar fracțiuni tCK. Nu voi învăța ce trebuie să observi, deoarece am configurat multe prin încercări și erori (nu pot garanta că nu aș putea „arde” memoria sau FPGA-ul). Voi sublinia doar un aspect: am avut mari dificultăți în a face controlerul să funcționeze, iar ultimul pas a fost realizarea că trebuie să verific lățimea tuturor interfețelor de memorie în conformitate cu codul generat pe Verilog: în cazul în care în MemIfBundle este specificat val mem_ba = IO(Output(UInt(2.W))), iar băncile sunt 8 (adică, adresa are o lățime de 3 biți), tot ce avem — un output suspendat din controlerul de memorie — este o problemă, dar nu critică, așa că totul se sintetizează, dar nu funcționează.

Poate că totul ar fi funcționat și cu vechiul modul, dacă aș actualiza controlerul, dar acum mi-e lene să mă ocup de eventualele buguri plutesc: am destule de rezolvat.

Așadar, după mutarea timebase-frequency în DTS de la nivelul CPU-ului specific la nivelul nodului cpus (la o cerere exprimată destul de clar de nucleu), obținem:

Text ascuns

[    0.000000] OF: fdt: Ignorând intervalul de memorie 0x80000000 - 0x80200000
[    0.000000] Versiunea Linux 4.19.0-sifive-1+ (trosinenko@trosinenko-pc) (gcc versiunea 8.3.0 (Buildroot 2019.02-07449-g4eddd28f99)) #1 SMP Mar Jul 9 22:42:36 MSK 2019
[    0.000000] bootconsole [early0] activat
[    0.000000] Ramdisk-ul inițial este la: 0x(____ptrval____) (16777216 bytes)
[    0.000000] Intervalele de zonă:
[    0.000000]   DMA32    [mem 0x0000000080200000-0x00000000bfffffff]
[    0.000000]   Normal   [mem 0x00000000c0000000-0x00000bffffffffff]
[    0.000000] Începutul zonei mobile pentru fiecare nod
[    0.000000] Intervalele de memorie timpurie pentru noduri
[    0.000000]   nod   0: [mem 0x0000000080200000-0x00000000bfffffff]
[    0.000000] Configurarea memoriei inițiale a nodului 0 [mem 0x0000000080200000-0x00000000bfffffff]
[    0.000000] software IO TLB: mapat [mem 0xbb1fc000-0xbf1fc000] (64MB)
[    0.000000] elf_hwcap este 0x112d
[    0.000000] percpu: Memorat 17 pagini/cpu @(____ptrval____) s29400 r8192 d32040 u69632
[    0.000000] A fost construit 1 zonelist, gruparea mobilității activată.  Total pagini: 258055
[    0.000000] Linia de comandă a kernelului: debug console=ttySIF0,125200 root=\/dev\/mmcblk0p2 loglevel=7 rootwait
[    0.000000] Intrările în tabela de hash pentru cache-ul Dentry: 131072 (ordonare: 8, 1048576 bytes)
[    0.000000] Intrările în tabela de hash pentru cache-ul de inode: 65536 (ordonare: 7, 524288 bytes)
[    0.000000] Sortare __ex_table...
[    0.000000] Memorie: 937696K\/1046528K disponibile (6565K cod kernel, 343K rwdata, 2564K rodata, 208K inițializare, 832K bss, 108832K rezervat, 0K rezervat cma)
[    0.000000] SLUB: HWalign=64, Ordonare=0-3, MinObjects=0, CPUs=1, Noduri=1
[    0.000000] rcu: Implementare RCU ierarhică.
[    0.000000] rcu:     Urmărirea evenimentelor RCU este activată.
[    0.000000] rcu:     RCU restricționează CPUs de la NR_CPUS=8 la nr_cpu_ids=1.
[    0.000000] rcu: Ajustarea geometriei pentru rcu_fanout_leaf=16, nr_cpu_ids=1
[    0.000000] NR_IRQS: 0, nr_irqs: 0, irqs prealocate: 0
[    0.000000] plic: 8 întreruperi mapate la 1 (din 2) manipulatoare.
[    0.000000] clocksource: riscv_clocksource: masca: 0xffffffffffffffff max_cycles: 0x1d854df40, max_idle_ns: 3526361616960 ns
[    0.000000] Consola: dispozitiv dummy colorat 80x25
[    0.000000] Calibrarea buclei de întârziere (omisa), valoarea calculată folosind frecvența temporizatorului.. 2.00 BogoMIPS (lpj=10000)
[    0.020000] pid_max: implicit: 32768 minim: 301
[    0.030000] Intrările în tabela de hash pentru cache-ul montaj: 2048 (ordonare: 2, 16384 bytes)
[    0.040000] Intrările în tabela de hash pentru cache-ul punctului de montaj: 2048 (ordonare: 2, 16384 bytes)
[    0.140000] rcu: Implementare SRCU ierarhică.
[    0.190000] smp: Pornind procesoarele secundare ...
[    0.190000] smp: A fost inițializat 1 nod, 1 CPU
[    0.220000] devtmpfs: inițializat
[    0.300000] random: get_random_u32 apelat din bucket_table_alloc+0x76\/0x17a cu crng_init=0
[    0.330000] clocksource: jiffies: masca: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604462750000 ns
[    0.340000] intrările în tabela de hash futex: 256 (ordonare: 2, 16384 bytes)
[    0.380000] NET: Înregistrat protocolul familia 16
[    1.850000] vgaarb: încărcat
[    1.870000] subsistemul SCSI inițializat
[    1.900000] usbcore: înregistrat un nou driver de interfață usbfs
[    1.910000] usbcore: înregistrat un nou driver de interfață hub
[    1.920000] usbcore: înregistrat un nou driver de dispozitiv usb
[    1.930000] pps_core: API LinuxPPS ver. 1 înregistrat
[    1.940000] pps_core: Software ver. 5.3.6 - Copyright 2005-2007 Rodolfo Giometti 
[    1.950000] Suport pentru ceas PTP înregistrat
[    1.970000] Driver-ul Avansat de Arhitectură a Sunetului Linux a fost inițializat.
[    2.010000] clocksource: Trecut la clocksource riscv_clocksource
[    2.600000] NET: Înregistrat protocolul familia 2
[    2.640000] tcp_listen_portaddr_hash intrările în tabela de hash: 512 (ordonare: 1, 8192 bytes)
[    2.650000] TCP intrările în tabela de hash stabilite: 8192 (ordonare: 4, 65536 bytes)
[    2.670000] TCP intrările în tabela de hash pentru legături: 8192 (ordonare: 5, 131072 bytes)
[    2.700000] TCP: Tabelele de hash configurate (stabilite 8192 legat 8192)
[    2.720000] UDP intrările în tabela de hash: 512 (ordonare: 2, 16384 bytes)
[    2.730000] UDP-Lite intrările în tabela de hash: 512 (ordonare: 2, 16384 bytes)
[    2.750000] NET: Înregistrat protocolul familia 1
[    2.770000] Despachetat initramfs...
[   23.980000] Despachetarea initramfs a eșuat: gunoi în arhiva comprimată
[   24.030000] workingset: timestamp_bits=62 max_order=18 bucket_order=0
[   25.020000] Driver-ul de tip Block layer SCSI generic (bsg) versiunea 0.4 încărcat (major 251)
[   25.030000] scheduler-ul de io noop înregistrat
[   25.040000] scheduler-ul de io deadline înregistrat
[   25.050000] scheduler-ul de io cfq înregistrat (implicit)
[   25.060000] scheduler-ul de io mq-deadline înregistrat
[   25.060000] scheduler-ul de io kyber înregistrat
[   25.120000] sifive_gpio 64002000.gpio: Chip-ul GPIO SiFive a fost înregistrat 6 GPIOs
[   25.150000] shpchp: Driver-ul Standard pentru Controlerul Hot Plug PCI versiunea: 0.4
[   28.870000] Serial: driver 8250/16550, 4 porturi, partajarea IRQ dezactivată
[   28.940000] sifive-serial 64000000.serial: nu a fost posibilă găsirea ceasului controlerului
[   28.950000] sifive-serial: probe of 64000000.serial a eșuat cu eroarea -2
[   28.980000] [drm] radeon suport pentru moduri kernel activate.
[   28.990000] [drm] amdgpu suport pentru moduri kernel activate.
[   29.500000] loop: modul încărcat
[   29.610000] sifive_spi 64001000.spi: Nu s-a putut găsi ceasul de bus
[   29.620000] sifive_spi: probe of 64001000.spi a eșuat cu eroarea -2
[   29.640000] libphy: Bus MDIO fix: probat
[   29.680000] e1000e: Driver-ul Intel(R) PRO/1000 Network - 3.2.6-k
[   29.690000] e1000e: Copyright(c) 1999 - 2015 Intel Corporation.
[   29.700000] ehci_hcd: Controllerul principal USB 2.0 'Enhanced' (EHCI) Driver
[   29.710000] ehci-pci: driver-ul EHCI PCI platform
[   29.720000] ehci-platform: driver-ul EHCI generic platform
[   29.750000] mousedev: dispozitivul mouse PS/2 comun pentru toate mouse-urile
[   29.790000] usbcore: înregistrat un nou driver de interfață usbhid
[   29.800000] usbhid: driver-ul de bază USB HID
[   29.820000] usbcore: înregistrat un nou driver de interfață snd-usb-audio
[   29.900000] NET: Înregistrat protocolul familia 10
[   29.960000] Rutarea segmentată cu IPv6
[   29.960000] sit: driver-ul de tunelare IPv6, IPv4 și MPLS peste IPv4
[   30.020000] NET: Înregistrat protocolul familia 17
[   30.020000] Tip de cheie dns_resolver înregistrat
[   30.070000] bootconsole [early0] folosește memoria inițială și trebuie dezactivat chiar înainte ca cea reală să fie gata
[   30.080000] bootconsole [early0] dezactivat

După care nu se întâmplă nimic vizibil.

Acum se poate încerca să se rezolve trei probleme:

[   23.980000] Initramfs unpacking failed: junk in compressed archive
...
[   28.940000] sifive-serial 64000000.serial: unable to find controller clock
...
[   29.610000] sifive_spi 64001000.spi: Unable to find bus clock

… și cu oprirea ieșirii în consolă.

A rezolva două probleme legate de frecvențe nu este deloc complicat: trebuie adăugat punctele clocks în subarborele dispozitivelor necesare, pentru comoditate având un nume explicativ pentru eticheta nodului tlclk:

diff --git a/arch/riscv/dts/zeowaa-1gb.dts b/arch/riscv/dts/zeowaa-1gb.dts
index 4b2cebc..1347e76 100644
--- a/arch/riscv/dts/zeowaa-1gb.dts
+++ b/arch/riscv/dts/zeowaa-1gb.dts
@@ -96,6 +97,7 @@
                 L8: serial@64000000 {
                         compatible = "sifive,uart0";
                         interrupt-parent = <&L0>;
+                        clocks = <&tlclk>;
                         interrupts = <>;
                         reg = <0x64000000 0x1000>;
                         reg-names = "control";
@@ -107,6 +109,7 @@
                         interrupt-parent = <&L0>;
                         interrupts = <>;
                         reg = <0x64001000 0x1000>;
+                        clocks = <&tlclk>;
                         reg-names = "control";
                         L12: mmc@0 {
                                 compatible = "mmc-spi-slot";
@@ -116,7 +119,7 @@
                                 voltage-ranges = <>;
                         };
                 };
-                L11: tlclk {
+                tlclk: tlclk {
                         #clock-cells = <>;
                         clock-frequency = <>;
                         clock-output-names = "tlclk";

Adăugând linia #define pr_debug printk în începutul fișierului init/initramfs.c, mesajul despre gunoi în loc de initramfs devine puțin mai detaliat:

[    2.760000] Unpacking initramfs...
[    2.770000] Detected gzip compressed data
[   23.940000] Detected (null) compressed data
[   23.970000] Initramfs unpacking failed: junk in compressed archive

Deci, poate, gunoiul nu este în loc de initramfs, ci împreună.

Ok, a găsit ceva, poate că e suficient. Dar unde a dispărut consola? Căutarea oferă un link către un issue pe GitHub: linux failed to bringup on vc707 board — se pare că un UART nu merită discuția, conform driver-ului. Dar un fix data de 11 iulie 2018 — cu un an în urmă. Se pare că acest commit nu a ajuns în arborele din care am compilat kernelul. Aplicând manual acest patch, am obținut un Linux funcțional! Se pare că problema cu initramfs era, într-adevăr, nu critică.

Autentificându-mă ca user=root, password=sifive, am reușit fără probleme (cu excepția de a înțelege că fiecare număr GPIO are un base, de la care totul este calculat, și care trebuie citit din fișierul pseudo corespunzător) prin sysfs să aprind LED-ul de pe placă.

La fel ca data trecută, vă anexez textul videoului de pornire Linux. În momentul schimbării consolei de la earlyprintk la cea standard, apare o anumită interferență, asemănătoare cu ieșirea într-o configurare greșită a vitezei UART. Ce este interesant, playerul a reușit să gestioneze această "mâncare".

Partea 4: În cele din urmă, lansăm Linux pe RocketChip RISC-V

Sursa: habr.com

Cumpără un hosting fiabil pentru site-uri cu protecție DDoS, servere VPS VDS 🔥 Cumpără un hosting fiabil pentru site-uri cu protecție DDoS, servere VPS VDS | ProHoster